parport_pc.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,460 行 · 第 1/5 页
C
2,460 行
/* Set up ECP FIFO mode.*//* parport_pc_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); */ r = change_mode (port, ECR_ECP); /* ECP FIFO */ if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); port->ieee1284.phase = IEEE1284_PH_REV_DATA; /* the first byte must be collected manually */dump_parport_state ("pre 43", port); /* Event 43: Wait for nAck to go low */ r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0); if (r) { /* timed out while reading -- no data */ printk (KERN_DEBUG "PIO read timed out (initial byte)\n"); goto out_no_data; } /* read byte */ *bufp++ = inb (DATA (port)); left--;dump_parport_state ("43-44", port); /* Event 44: nAutoFd (HostAck) goes high to acknowledge */ parport_pc_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);dump_parport_state ("pre 45", port); /* Event 45: Wait for nAck to go high *//* r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); */dump_parport_state ("post 45", port);r = 0; if (r) { /* timed out while waiting for peripheral to respond to ack */ printk (KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n"); /* keep hold of the byte we've got already */ goto out_no_data; } /* Event 46: nAutoFd (HostAck) goes low to accept more data */ parport_pc_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD);dump_parport_state ("rev idle", port); /* Do the transfer. */ while (left > fifofull) { int ret; unsigned long expire = jiffies + port->cad->timeout; unsigned char ecrval = inb (ECONTROL (port)); if (need_resched() && time_before (jiffies, expire)) /* Can't yield the port. */ schedule (); /* At this point, the FIFO may already be full. In * that case ECP is already holding back the * peripheral (assuming proper design) with a delayed * handshake. Work fast to avoid a peripheral * timeout. */ if (ecrval & 0x01) { /* FIFO is empty. Wait for interrupt. */dump_parport_state ("FIFO empty", port); /* Anyone else waiting for the port? */ if (port->waithead) { printk (KERN_DEBUG "Somebody wants the port\n"); break; } /* Clear serviceIntr */ ECR_WRITE (port, ecrval & ~(1<<2)); false_alarm:dump_parport_state ("waiting", port); ret = parport_wait_event (port, HZ);DPRINTK (KERN_DEBUG "parport_wait_event returned %d\n", ret); if (ret < 0) break; ret = 0; if (!time_before (jiffies, expire)) { /* Timed out. */dump_parport_state ("timeout", port); printk (KERN_DEBUG "PIO read timed out\n"); break; } ecrval = inb (ECONTROL (port)); if (!(ecrval & (1<<2))) { if (need_resched() && time_before (jiffies, expire)) { schedule (); } goto false_alarm; } /* Depending on how the FIFO threshold was * set, how long interrupt service took, and * how fast the peripheral is, we might be * lucky and have a just filled FIFO. */ continue; } if (ecrval & 0x02) { /* FIFO is full. */dump_parport_state ("FIFO full", port); insb (fifo, bufp, fifo_depth); bufp += fifo_depth; left -= fifo_depth; continue; }DPRINTK (KERN_DEBUG "*** ecp_read_block_pio: reading one byte from the FIFO\n"); /* FIFO not filled. We will cycle this loop for a while * and either the peripheral will fill it faster, * tripping a fast empty with insb, or we empty it. */ *bufp++ = inb (fifo); left--; } /* scoop up anything left in the FIFO */ while (left && !(inb (ECONTROL (port) & 0x01))) { *bufp++ = inb (fifo); left--; } port->ieee1284.phase = IEEE1284_PH_REV_IDLE;dump_parport_state ("rev idle2", port);out_no_data: /* Go to forward idle mode to shut the peripheral up (event 47). */ parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); /* event 49: PError goes high */ 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); }dump_parport_state ("fwd idle", port); return length - left;}#endif /* IEEE 1284 support */#endif /* Allowed to use FIFO/DMA *//* * ****************************************** * INITIALISATION AND MODULE STUFF BELOW HERE * ****************************************** *//* GCC is not inlining extern inline function later overwriten to non-inline, so we use outlined_ variants here. */struct parport_operations parport_pc_ops = { .write_data = parport_pc_write_data, .read_data = parport_pc_read_data, .write_control = parport_pc_write_control, .read_control = parport_pc_read_control, .frob_control = parport_pc_frob_control, .read_status = parport_pc_read_status, .enable_irq = parport_pc_enable_irq, .disable_irq = parport_pc_disable_irq, .data_forward = parport_pc_data_forward, .data_reverse = parport_pc_data_reverse, .init_state = parport_pc_init_state, .save_state = parport_pc_save_state, .restore_state = parport_pc_restore_state, .epp_write_data = parport_ieee1284_epp_write_data, .epp_read_data = parport_ieee1284_epp_read_data, .epp_write_addr = parport_ieee1284_epp_write_addr, .epp_read_addr = parport_ieee1284_epp_read_addr, .ecp_write_data = parport_ieee1284_ecp_write_data, .ecp_read_data = parport_ieee1284_ecp_read_data, .ecp_write_addr = parport_ieee1284_ecp_write_addr, .compat_write_data = parport_ieee1284_write_compat, .nibble_read_data = parport_ieee1284_read_nibble, .byte_read_data = parport_ieee1284_read_byte, .owner = THIS_MODULE,};#ifdef CONFIG_PARPORT_PC_SUPERIO/* Super-IO chipset detection, Winbond, SMSC */static int __devinit show_parconfig_smsc37c669(int io, int key){ int cr1,cr4,cra,cr23,cr26,cr27,i=0; static const 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); if (verbose_probing) { printk (KERN_INFO "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 (KERN_INFO "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(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n", (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no"); printk(KERN_INFO "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(KERN_INFO "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; } if (io != superios[i].io) { /* how many bytes? */ if (!request_region(superios[i].io, 3, "smsc parport")) { superios[i].io = 0; return 0; } } d=(cr26 &0x0f); if((d==1) || (d==3)) superios[i].dma= d; else superios[i].dma= PARPORT_DMA_NONE; return 1; } } return 0;}static int __devinit show_parconfig_winbond(int io, int key){ int cr30,cr60,cr61,cr70,cr74,crf0,i=0; static const 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" }; static 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); if (verbose_probing) { printk(KERN_INFO "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x " "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0); printk(KERN_INFO "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(KERN_INFO "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", irqtypes[crf0>>7], (crf0>>3)&0x0f); printk(KERN_INFO "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(KERN_INFO "Super-IO: too many chips!\n"); else { superios[i].io = (cr60<<8)|cr61; if (io != superios[i].io) { /* how many bytes? */ if (!request_region(superios[i].io, 3, "winbond parport")) { superios[i].io = 0; return 0; } } superios[i].irq = cr70&0x0f; superios[i].dma = (((cr74 & 0x07) > 3) ? PARPORT_DMA_NONE : (cr74 & 0x07)); return 1; } } return 0;}static int __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid){ const char *type = "unknown"; int id,progif=2; if (devid == devrev) /* simple heuristics, we happened to read some non-winbond register */ return 0; 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 (verbose_probing) printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x " "devid=%02x devrev=%02x oldid=%02x type=%s\n", efer, key, devid, devrev, oldid, type); if (progif == 2) return show_parconfig_winbond(efer,key); return 0;}static int __devinit decode_smsc(int efer, int key, int devid, int devrev){ const char *type = "unknown"; int (*func)(int io, int key); int id; if (devid == devrev) /* simple heuristics, we happened to read some non-smsc register */ return 0; func=NULL; 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 (verbose_probing) printk(KERN_INFO "SMSC chip at EFER=0x%x " "key=0x%02x devid=%02x devrev=%02x type=%s\n", efer, key, devid, devrev, type); if (func) return func(efer,key); return 0;}static void __devinit winbond_check(int io, int key){ int devid,devrev,oldid,x_devid,x_devrev,x_oldid; if (!request_region(io, 3, __FUNCTION__)) return; /* 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)) goto out; /* protection against false positives */ if (decode_winbond(io,key,devid,devrev,oldid)); return;out: release_region(io, 3);}static void __devinit winbond_check2(int io,int key){ int devid,devrev,oldid,x_devid,x_devrev,x_oldid; if (!request_region(io, 3, __FUNCTION__)) return; /* 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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?