📄 parport_pc.c
字号:
"%s: BUSY timeout (%d) in ecp_write_block_pio\n", port->name, r); port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written;}size_t parport_pc_ecp_read_block_pio (struct parport *port, void *buf, size_t length, int flags){ size_t left = length; size_t fifofull; int r; const int fifo = FIFO(port); const struct parport_pc_private *priv = port->physport->private_data; const int fifo_depth = priv->fifo_depth; char *bufp = buf; port = port->physport;DPRINTK (KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n");dump_parport_state ("enter fcn", port); /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->cad->timeout) return parport_ieee1284_ecp_read_data (port, buf, length, flags); if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE) { /* If the peripheral is allowed to send RLE compressed * data, it is possible for a byte to expand to 128 * bytes in the FIFO. */ fifofull = 128; } else { fifofull = fifo_depth; } /* If the caller wants less than a full FIFO's worth of data, * go through software emulation. Otherwise we may have to throw * away data. */ if (length < fifofull) return parport_ieee1284_ecp_read_data (port, buf, length, flags); if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) { /* change to reverse-idle phase (must be in forward-idle) */ /* Event 38: Set nAutoFd low (also make sure nStrobe is high) */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE, PARPORT_CONTROL_AUTOFD); parport_pc_data_reverse (port); /* Must be in PS2 mode */ udelay (5); /* Event 39: Set nInit low to initiate bus reversal */ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); /* Event 40: Wait for nAckReverse (PError) to go low */ r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); if (r) { printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) " "in ecp_read_block_pio\n", port->name, r); return 0; } } /* 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; long int expire = jiffies + port->cad->timeout; unsigned char ecrval = inb (ECONTROL (port)); if (current->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 (current->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 * ****************************************** */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; 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; } 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; 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; 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){ const char *type = "unknown"; int id,progif=2; if (devid == devrev) /* simple heuristics, we happened to read some non-winbond register */ return; 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) show_parconfig_winbond(efer,key);}static void __devinit decode_smsc(int efer, int key, int devid, int devrev){ const char *type = "unknown"; void (*func)(int io, int key); int id; if (devid == devrev) /* simple heuristics, we happened to read some non-smsc register */ return; 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) func(efer,key);}static void __devinit winbond_check(int io, int key)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -