📄 parport_pc.c
字号:
{ 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){ if (verbose_probing) printk(KERN_DEBUG "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){ if (verbose_probing) printk(KERN_DEBUG "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_INFO "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); r = parport_pc_read_data (pb); if (r == w) { w = 0x55; parport_pc_write_data (pb, w); r = parport_pc_read_data (pb); if (r == w) return PARPORT_MODE_PCSPP; } if (user_specified) { /* Didn't work, but the user is convinced this is the * place. */ printk (KERN_INFO "parport 0x%lx (WARNING): DATA: " "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); printk (KERN_INFO "parport 0x%lx: You gave this address, " "but there is probably no parallel port there!\n", pb->base); } /* It's possible that we can't read the control register or * the data register. In that case just believe the user. */ if (user_specified) return PARPORT_MODE_PCSPP; return 0;}/* Check for ECR * * Old style XT ports alias io ports every 0x400, hence accessing ECR * on these cards actually accesses the CTR. * * Modern cards don't do this but reading from ECR will return 0xff * regardless of what is written here if the card does NOT support * ECP. * * We first check to see if ECR is the same as CTR. If not, the low * two bits of ECR aren't writable, so we check by writing ECR and * reading it back to see if it's what we expect. */static int __devinit parport_ECR_present(struct parport *pb){ struct parport_pc_private *priv = pb->private_data; unsigned char r = 0xc; outb (r, CONTROL (pb)); if ((inb (ECONTROL (pb)) & 0x3) == (r & 0x3)) { outb (r ^ 0x2, CONTROL (pb)); /* Toggle bit 1 */ r = inb (CONTROL (pb)); if ((inb (ECONTROL (pb)) & 0x2) == (r & 0x2)) goto no_reg; /* Sure that no ECR register exists */ } if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1) goto no_reg; ECR_WRITE (pb, 0x34); if (inb (ECONTROL (pb)) != 0x35) goto no_reg; priv->ecr = 1; outb (0xc, CONTROL (pb)); /* Go to mode 000 */ frob_set_mode (pb, ECR_SPP); return 1; no_reg: outb (0xc, CONTROL (pb)); return 0; }#ifdef CONFIG_PARPORT_1284/* Detect PS/2 support. * * Bit 5 (0x20) sets the PS/2 data direction; setting this high * allows us to read data from the data lines. In theory we would get back * 0xff but any peripheral attached to the port may drag some or all of the * lines down to zero. So if we get back anything that isn't the contents * of the data register we deem PS/2 support to be present. * * Some SPP ports have "half PS/2" ability - you can't turn off the line * drivers, but an external peripheral with sufficiently beefy drivers of * its own can overpower them and assert its own levels onto the bus, from * where they can then be read back as normal. Ports with this property * and the right type of device attached are likely to fail the SPP test, * (as they will appear to have stuck bits) and so the fact that they might * be misdetected here is rather academic. */static int __devinit parport_PS2_supported(struct parport *pb){ int ok = 0; clear_epp_timeout(pb); /* try to tri-state the buffer */ parport_pc_data_reverse (pb); parport_pc_write_data(pb, 0x55); if (parport_pc_read_data(pb) != 0x55) ok++; parport_pc_write_data(pb, 0xaa); if (parport_pc_read_data(pb) != 0xaa) ok++; /* cancel input mode */ parport_pc_data_forward (pb); if (ok) { pb->modes |= PARPORT_MODE_TRISTATE; } else { struct parport_pc_private *priv = pb->private_data; priv->ctr_writable &= ~0x20; } return ok;}#ifdef CONFIG_PARPORT_PC_FIFOstatic int __devinit parport_ECP_supported(struct parport *pb){ int i; int config, configb; int pword; struct parport_pc_private *priv = pb->private_data; /* Translate ECP intrLine to ISA irq value */ static const int intrline[]= { 0, 7, 9, 10, 11, 14, 15, 5 }; /* If there is no ECR, we have no hope of supporting ECP. */ if (!priv->ecr) return 0; /* Find out FIFO depth */ ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ ECR_WRITE (pb, ECR_TST << 5); /* TEST FIFO */ for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++) outb (0xaa, FIFO (pb)); /* * Using LGS chipset it uses ECR register, but * it doesn't support ECP or FIFO MODE */ if (i == 1024) { ECR_WRITE (pb, ECR_SPP << 5); return 0; } priv->fifo_depth = i; if (verbose_probing) printk (KERN_DEBUG "0x%lx: FIFO is %d bytes\n", pb->base, i); /* Find out writeIntrThreshold */ frob_econtrol (pb, 1<<2, 1<<2); frob_econtrol (pb, 1<<2, 0); for (i = 1; i <= priv->fifo_depth; i++) { inb (FIFO (pb)); udelay (50); if (inb (ECONTROL (pb)) & (1<<2)) break; } if (i <= priv->fifo_depth) { if (verbose_probing) printk (KERN_DEBUG "0x%lx: writeIntrThreshold is %d\n", pb->base, i); } else /* Number of bytes we know we can write if we get an interrupt. */ i = 0; priv->writeIntrThreshold = i; /* Find out readIntrThreshold */ frob_set_mode (pb, ECR_PS2); /* Reset FIFO and enable PS2 */ parport_pc_data_reverse (pb); /* Must be in PS2 mode */ frob_set_mode (pb, ECR_TST); /* Test FIFO */ frob_econtrol (pb, 1<<2, 1<<2); frob_econtrol (pb, 1<<2, 0); for (i = 1; i <= priv->fifo_depth; i++) { outb (0xaa, FIFO (pb)); if (inb (ECONTROL (pb)) & (1<<2)) break; } if (i <= priv->fifo_depth) { if (verbose_probing) printk (KERN_INFO "0x%lx: readIntrThreshold is %d\n", pb->base, i); } else /* Number of bytes we can read if we get an interrupt. */ i = 0; priv->readIntrThreshold = i; ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ ECR_WRITE (pb, 0xf4); /* Configuration mode */ config = inb (CONFIGA (pb)); pword = (config >> 4) & 0x7; switch (pword) { case 0: pword = 2; printk (KERN_WARNING "0x%lx: Unsupported pword size!\n", pb->base); break; case 2: pword = 4; printk (KERN_WARNING "0x%lx: Unsupported pword size!\n", pb->base); break; default: printk (KERN_WARNING "0x%lx: Unknown implementation ID\n", pb->base); /* Assume 1 */ case 1: pword = 1; } priv->pword = pword; if (verbose_probing) { printk (KERN_DEBUG "0x%lx: PWord is %d bits\n", pb->base, 8 * pword); printk (KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base, config & 0x80 ? "Level" : "Pulses"); configb = inb (CONFIGB (pb)); printk (KERN_DEBUG "0x%lx: ECP port cfgA=0x%02x cfgB=0x%02x\n", pb->base, config, configb); printk (KERN_DEBUG "0x%lx: ECP settings irq=", pb->base); if ((configb >>3) & 0x07) printk("%d",intrline[(configb >>3) & 0x07]); else printk("<none or set by other means>"); printk (" dma="); if( (configb & 0x03 ) == 0x00) printk("<none or set by other means>\n"); else printk("%d\n",configb & 0x07); } /* Go back to mode 000 */ frob_set_mode (pb, ECR_SPP); return 1;}#endifstatic int __devinit parport_ECPPS2_supported(struct parport *pb){ const struct parport_pc_private *priv = pb->private_data; int result; unsigned char oecr; if (!priv->ecr) return 0; oecr = inb (ECONTROL (pb)); ECR_WRITE (pb, ECR_PS2 << 5); result = parport_PS2_supported(pb); ECR_WRITE (pb, oecr); return result;}/* EPP mode detection */static int __devinit parport_EPP_supported(struct parport *pb){ const struct parport_pc_private *priv = pb->private_data; /* * Theory: * Bit 0 of STR is the EPP timeout bit, this bit is 0 * when EPP is possible and is set high when an EPP timeout * occurs (EPP uses the HALT line to stop the CPU while it does * the byte transfer, an EPP timeout occurs if the attached * device fails to respond after 10 micro seconds). * * This bit is cleared by either reading it (National Semi) * or writing a 1 to the bit (SMC, UMC, WinBond), others ??? * This bit is always high in non EPP modes. */ /* If EPP timeout bit clear then EPP available */ if (!clear_epp_timeout(pb)) { return 0; /* No way to clear timeout */ } /* Check for Intel bug. */ if (priv->ecr) { unsigned char i; for (i = 0x00; i < 0x80; i += 0x20) { ECR_WRITE (pb, i); if (clear_epp_timeout (pb)) { /* Phony EPP in ECP. */ return 0; } } } pb->modes |= PARPORT_MODE_EPP; /* Set up access functions to use EPP hardware. */ pb->ops->epp_read_data = parport_pc_epp_read_data; pb->ops->epp_write_data = parport_pc_epp_write_data; pb->ops->epp_read_addr = parport_pc_epp_read_addr; pb->ops->epp_write_addr = parport_pc_epp_write_addr; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -