📄 parport_pc.c
字号:
if (ecrval & 0x02) { /* FIFO is full. */ insb (fifo, bufp, fifo_depth); bufp += fifo_depth; left -= fifo_depth; continue; } *bufp++ = inb (fifo); left--; } port->ieee1284.phase = IEEE1284_PH_REV_IDLE; /* Go to forward idle mode to shut the peripheral up. */ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) printk (KERN_DEBUG "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n", port->name, r); port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; /* Finish up. */ { int lost = get_fifo_residue (port); if (lost) /* Shouldn't happen with compliant peripherals. */ printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name, lost); } return length - left;}#endif /* IEEE 1284 support */#endif /* Allowed to use FIFO/DMA */void parport_pc_inc_use_count(void){#ifdef MODULE MOD_INC_USE_COUNT;#endif}void parport_pc_dec_use_count(void){#ifdef MODULE MOD_DEC_USE_COUNT;#endif}struct parport_operations parport_pc_ops = { parport_pc_write_data, parport_pc_read_data, parport_pc_write_control, parport_pc_read_control, parport_pc_frob_control, parport_pc_read_status, parport_pc_enable_irq, parport_pc_disable_irq, parport_pc_data_forward, parport_pc_data_reverse, parport_pc_init_state, parport_pc_save_state, parport_pc_restore_state, parport_pc_inc_use_count, parport_pc_dec_use_count, parport_ieee1284_epp_write_data, parport_ieee1284_epp_read_data, parport_ieee1284_epp_write_addr, parport_ieee1284_epp_read_addr, parport_ieee1284_ecp_write_data, parport_ieee1284_ecp_read_data, parport_ieee1284_ecp_write_addr, parport_ieee1284_write_compat, parport_ieee1284_read_nibble, parport_ieee1284_read_byte,};#ifdef CONFIG_PARPORT_PC_SUPERIO/* Super-IO chipset detection, Winbond, SMSC */static void __devinit show_parconfig_smsc37c669(int io, int key){ int cr1,cr4,cra,cr23,cr26,cr27,i=0; char *modes[]={ "SPP and Bidirectional (PS/2)", "EPP and SPP", "ECP", "ECP and EPP"}; outb(key,io); outb(key,io); outb(1,io); cr1=inb(io+1); outb(4,io); cr4=inb(io+1); outb(0x0a,io); cra=inb(io+1); outb(0x23,io); cr23=inb(io+1); outb(0x26,io); cr26=inb(io+1); outb(0x27,io); cr27=inb(io+1); outb(0xaa,io); printk ("SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, " "A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n", cr1,cr4,cra,cr23,cr26,cr27); /* The documentation calls DMA and IRQ-Lines by letters, so the board maker can/will wire them appropriately/randomly... G=reserved H=IDE-irq, */ printk ("SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, " "fifo threshold=%d\n", cr23*4, (cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-', (cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f); printk("SMSC LPT Config: enabled=%s power=%s\n", (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no"); printk("SMSC LPT Config: Port mode=%s, EPP version =%s\n", (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], (cr4 & 0x40) ? "1.7" : "1.9"); /* Heuristics ! BIOS setup for this mainboard device limits the choices to standard settings, i.e. io-address and IRQ are related, however DMA can be 1 or 3, assume DMA_A=DMA1, DMA_C=DMA3 (this is true e.g. for TYAN 1564D Tomcat IV) */ if(cr23*4 >=0x100) { /* if active */ while((superios[i].io!= 0) && (i<NR_SUPERIOS)) i++; if(i==NR_SUPERIOS) printk("Super-IO: too many chips!\n"); else { int d; switch (cr23*4) { case 0x3bc: superios[i].io = 0x3bc; superios[i].irq = 7; break; case 0x378: superios[i].io = 0x378; superios[i].irq = 7; break; case 0x278: superios[i].io = 0x278; superios[i].irq = 5; } d=(cr26 &0x0f); if((d==1) || (d==3)) superios[i].dma= d; else superios[i].dma= PARPORT_DMA_NONE; } }}static void __devinit show_parconfig_winbond(int io, int key){ int cr30,cr60,cr61,cr70,cr74,crf0,i=0; char *modes[]={ "Standard (SPP) and Bidirectional(PS/2)", /* 0 */ "EPP-1.9 and SPP", "ECP", "ECP and EPP-1.9", "Standard (SPP)", "EPP-1.7 and SPP", /* 5 */ "undefined!", "ECP and EPP-1.7"}; char *irqtypes[]={"pulsed low, high-Z", "follows nACK"}; /* The registers are called compatible-PnP because the register layout is modelled after ISA-PnP, the access method is just another ... */ outb(key,io); outb(key,io); outb(0x07,io); /* Register 7: Select Logical Device */ outb(0x01,io+1); /* LD1 is Parallel Port */ outb(0x30,io); cr30=inb(io+1); outb(0x60,io); cr60=inb(io+1); outb(0x61,io); cr61=inb(io+1); outb(0x70,io); cr70=inb(io+1); outb(0x74,io); cr74=inb(io+1); outb(0xf0,io); crf0=inb(io+1); outb(0xaa,io); printk("Winbond LPT Config: cr_30=%02x 60,61=%02x%02x " "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0); printk("Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f ); if ((cr74 & 0x07) > 3) printk("dma=none\n"); else printk("dma=%d\n",cr74 & 0x07); printk("Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", irqtypes[crf0>>7], (crf0>>3)&0x0f); printk("Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]); if(cr30 & 0x01) { /* the settings can be interrogated later ... */ while((superios[i].io!= 0) && (i<NR_SUPERIOS)) i++; if(i==NR_SUPERIOS) printk("Super-IO: too many chips!\n"); else { superios[i].io = (cr60<<8)|cr61; superios[i].irq = cr70&0x0f; superios[i].dma = (((cr74 & 0x07) > 3) ? PARPORT_DMA_NONE : (cr74 & 0x07)); } }}static void __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid){ char *type=NULL; int id,progif=2; if (devid == devrev) /* simple heuristics, we happened to read some non-winbond register */ return; printk("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x " "oldid=%02x\n", efer,key,devid,devrev,oldid); id=(devid<<8) | devrev; /* Values are from public data sheets pdf files, I can just confirm 83977TF is correct :-) */ if (id == 0x9771) type="83977F/AF"; else if (id == 0x9773) type="83977TF / SMSC 97w33x/97w34x"; else if (id == 0x9774) type="83977ATF"; else if ((id & ~0x0f) == 0x5270) type="83977CTF / SMSC 97w36x"; else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97w35x"; else if ((id & ~0x0f) == 0x5210) type="83627"; else if ((id & ~0x0f) == 0x6010) type="83697HF"; else if ((oldid &0x0f ) == 0x0a) { type="83877F"; progif=1;} else if ((oldid &0x0f ) == 0x0b) { type="83877AF"; progif=1;} else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;} else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;} else progif=0; if(type==NULL) printk("Winbond unknown chip type\n"); else printk("Winbond chip type %s\n",type); if(progif==2) show_parconfig_winbond(efer,key); return;}static void __devinit decode_smsc(int efer, int key, int devid, int devrev){ char *type=NULL; void (*func)(int io, int key); int id; if (devid == devrev) /* simple heuristics, we happened to read some non-smsc register */ return; func=NULL; printk("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n", efer,key,devid,devrev); id=(devid<<8) | devrev; if (id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;} else if (id==0x6582) type="37c665IR"; else if (devid==0x65) type="37c665GT"; else if (devid==0x66) type="37c666GT"; if(type==NULL) printk("SMSC unknown chip type\n"); else printk("SMSC chip type %s\n",type); if(func) (func)(efer,key); return;}static void __devinit winbond_check(int io, int key){ int devid,devrev,oldid,x_devid,x_devrev,x_oldid; /* First probe without key */ outb(0x20,io); x_devid=inb(io+1); outb(0x21,io); x_devrev=inb(io+1); outb(0x09,io); x_oldid=inb(io+1); outb(key,io); outb(key,io); /* Write Magic Sequence to EFER, extended funtion enable register */ outb(0x20,io); /* Write EFIR, extended function index register */ devid=inb(io+1); /* Read EFDR, extended function data register */ outb(0x21,io); devrev=inb(io+1); outb(0x09,io); oldid=inb(io+1); outb(0xaa,io); /* Magic Seal */ if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) return; /* protection against false positives */ decode_winbond(io,key,devid,devrev,oldid);}static void __devinit winbond_check2(int io,int key){ int devid,devrev,oldid,x_devid,x_devrev,x_oldid; /* First probe without the key */ outb(0x20,io+2); x_devid=inb(io+2); outb(0x21,io+1); x_devrev=inb(io+2); outb(0x09,io+1); x_oldid=inb(io+2); outb(key,io); /* Write Magic Byte to EFER, extended funtion enable register */ outb(0x20,io+2); /* Write EFIR, extended function index register */ devid=inb(io+2); /* Read EFDR, extended function data register */ outb(0x21,io+1); devrev=inb(io+2); outb(0x09,io+1); oldid=inb(io+2); outb(0xaa,io); /* Magic Seal */ if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) return; /* protection against false positives */ decode_winbond(io,key,devid,devrev,oldid);}static void __devinit smsc_check(int io, int key){ int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev; /* First probe without the key */ outb(0x0d,io); x_oldid=inb(io+1); outb(0x0e,io); x_oldrev=inb(io+1); outb(0x20,io); x_id=inb(io+1); outb(0x21,io); x_rev=inb(io+1); outb(key,io); outb(key,io); /* Write Magic Sequence to EFER, extended funtion enable register */ outb(0x0d,io); /* Write EFIR, extended function index register */ oldid=inb(io+1); /* Read EFDR, extended function data register */ outb(0x0e,io); oldrev=inb(io+1); outb(0x20,io); id=inb(io+1); outb(0x21,io); rev=inb(io+1); outb(0xaa,io); /* Magic Seal */ if ((x_id == id) && (x_oldrev == oldrev) && (x_oldid == oldid) && (x_rev == rev)) return; /* protection against false positives */ decode_smsc(io,key,oldid,oldrev);}static void __devinit detect_and_report_winbond (void){ printk("Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n"); winbond_check(0x3f0,0x87); winbond_check(0x370,0x87); winbond_check(0x2e ,0x87); winbond_check(0x4e ,0x87); winbond_check(0x3f0,0x86); winbond_check2(0x250,0x88); winbond_check2(0x250,0x89);}static void __devinit detect_and_report_smsc (void){ printk("SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n"); smsc_check(0x3f0,0x55); smsc_check(0x370,0x55); smsc_check(0x3f0,0x44); smsc_check(0x370,0x44);}#endif /* CONFIG_PARPORT_PC_SUPERIO */static int __devinit get_superio_dma (struct parport *p){ int i=0; while( (superios[i].io != p->base) && (i<NR_SUPERIOS)) i++; if (i!=NR_SUPERIOS) return superios[i].dma; return PARPORT_DMA_NONE;}static int __devinit get_superio_irq (struct parport *p){ int i=0; while( (superios[i].io != p->base) && (i<NR_SUPERIOS)) i++; if (i!=NR_SUPERIOS) return superios[i].irq; return PARPORT_IRQ_NONE;} /* --- Mode detection ------------------------------------- *//* * Checks for port existence, all ports support SPP MODE * Returns: * 0 : No parallel port at this adress * PARPORT_MODE_PCSPP : SPP port detected * (if the user specified an ioport himself, * this shall always be the case!) * */static int __devinit parport_SPP_supported(struct parport *pb){ unsigned char r, w; /* * first clear an eventually pending EPP timeout * I (sailer@ife.ee.ethz.ch) have an SMSC chipset * that does not even respond to SPP cycles if an EPP * timeout is pending */ clear_epp_timeout(pb); /* Do a simple read-write test to make sure the port exists. */ w = 0xc; outb (w, CONTROL (pb)); /* Is there a control register that we can read from? Some * ports don't allow reads, so read_control just returns a * software copy. Some ports _do_ allow reads, so bypass the * software copy here. In addition, some bits aren't * writable. */ r = inb (CONTROL (pb)); if ((r & 0xf) == w) { w = 0xe; outb (w, CONTROL (pb)); r = inb (CONTROL (pb)); outb (0xc, CONTROL (pb)); if ((r & 0xf) == w) return PARPORT_MODE_PCSPP; } if (user_specified) /* That didn't work, but the user thinks there's a * port here. */ printk (KERN_DEBUG "parport 0x%lx (WARNING): CTR: " "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); /* Try the data register. The data lines aren't tri-stated at * this stage, so we expect back what we wrote. */ w = 0xaa; parport_pc_write_data (pb, w);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -