📄 parport_pc.c
字号:
static int __devinit parport_ECPEPP_supported(struct parport *pb){ struct parport_pc_private *priv = pb->private_data; int result; unsigned char oecr; if (!priv->ecr) { return 0; } oecr = inb (ECONTROL (pb)); /* Search for SMC style EPP+ECP mode */ ECR_WRITE (pb, 0x80); outb (0x04, CONTROL (pb)); result = parport_EPP_supported(pb); ECR_WRITE (pb, oecr); if (result) { /* Set up access functions to use ECP+EPP hardware. */ pb->ops->epp_read_data = parport_pc_ecpepp_read_data; pb->ops->epp_write_data = parport_pc_ecpepp_write_data; pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr; pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr; } return result;}#else /* No IEEE 1284 support *//* Don't bother probing for modes we know we won't use. */static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }#ifdef CONFIG_PARPORT_PC_FIFOstatic int __devinit parport_ECP_supported(struct parport *pb) { return 0; }#endifstatic int __devinit parport_EPP_supported(struct parport *pb) { return 0; }static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}#endif /* No IEEE 1284 support *//* --- IRQ detection -------------------------------------- *//* Only if supports ECP mode */static int __devinit programmable_irq_support(struct parport *pb){ int irq, intrLine; unsigned char oecr = inb (ECONTROL (pb)); static const int lookup[8] = { PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5 }; ECR_WRITE (pb, ECR_CNF << 5); /* Configuration MODE */ intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07; irq = lookup[intrLine]; ECR_WRITE (pb, oecr); return irq;}static int __devinit irq_probe_ECP(struct parport *pb){ int i; unsigned long irqs; sti(); irqs = probe_irq_on(); ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ ECR_WRITE (pb, (ECR_TST << 5) | 0x04); ECR_WRITE (pb, ECR_TST << 5); /* If Full FIFO sure that writeIntrThreshold is generated */ for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) outb (0xaa, FIFO (pb)); pb->irq = probe_irq_off(irqs); ECR_WRITE (pb, ECR_SPP << 5); if (pb->irq <= 0) pb->irq = PARPORT_IRQ_NONE; return pb->irq;}/* * This detection seems that only works in National Semiconductors * This doesn't work in SMC, LGS, and Winbond */static int __devinit irq_probe_EPP(struct parport *pb){#ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE;#else int irqs; unsigned char oecr; if (pb->modes & PARPORT_MODE_PCECR) oecr = inb (ECONTROL (pb)); sti(); irqs = probe_irq_on(); if (pb->modes & PARPORT_MODE_PCECR) frob_econtrol (pb, 0x10, 0x10); clear_epp_timeout(pb); parport_pc_frob_control (pb, 0x20, 0x20); parport_pc_frob_control (pb, 0x10, 0x10); clear_epp_timeout(pb); /* Device isn't expecting an EPP read * and generates an IRQ. */ parport_pc_read_epp(pb); udelay(20); pb->irq = probe_irq_off (irqs); if (pb->modes & PARPORT_MODE_PCECR) ECR_WRITE (pb, oecr); parport_pc_write_control(pb, 0xc); if (pb->irq <= 0) pb->irq = PARPORT_IRQ_NONE; return pb->irq;#endif /* Advanced detection */}static int __devinit irq_probe_SPP(struct parport *pb){ /* Don't even try to do this. */ return PARPORT_IRQ_NONE;}/* We will attempt to share interrupt requests since other devices * such as sound cards and network cards seem to like using the * printer IRQs. * * When ECP is available we can autoprobe for IRQs. * NOTE: If we can autoprobe it, we can register the IRQ. */static int __devinit parport_irq_probe(struct parport *pb){ struct parport_pc_private *priv = pb->private_data; priv->ctr_writable |= 0x10; if (priv->ecr) { pb->irq = programmable_irq_support(pb); if (pb->irq == PARPORT_IRQ_NONE) pb->irq = irq_probe_ECP(pb); } if ((pb->irq == PARPORT_IRQ_NONE) && priv->ecr && (pb->modes & PARPORT_MODE_EPP)) pb->irq = irq_probe_EPP(pb); clear_epp_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP)) pb->irq = irq_probe_EPP(pb); clear_epp_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE) pb->irq = irq_probe_SPP(pb); if (pb->irq == PARPORT_IRQ_NONE) pb->irq = get_superio_irq(pb); if (pb->irq == PARPORT_IRQ_NONE) priv->ctr_writable &= ~0x10; return pb->irq;}/* --- DMA detection -------------------------------------- *//* Only if chipset conforms to ECP ISA Interface Standard */static int __devinit programmable_dma_support (struct parport *p){ unsigned char oecr = inb (ECONTROL (p)); int dma; frob_set_mode (p, ECR_CNF); dma = inb (CONFIGB(p)) & 0x07; /* 000: Indicates jumpered 8-bit DMA if read-only. 100: Indicates jumpered 16-bit DMA if read-only. */ if ((dma & 0x03) == 0) dma = PARPORT_DMA_NONE; ECR_WRITE (p, oecr); return dma;}static int __devinit parport_dma_probe (struct parport *p){ const struct parport_pc_private *priv = p->private_data; if (priv->ecr) p->dma = programmable_dma_support(p); /* ask ECP chipset first */ if (p->dma == PARPORT_DMA_NONE) { /* ask known Super-IO chips proper, although these claim ECP compatible, some don't report their DMA conforming to ECP standards */ p->dma = get_superio_dma(p); } return p->dma;}/* --- Initialisation code -------------------------------- */struct parport *parport_pc_probe_port (unsigned long int base, unsigned long int base_hi, int irq, int dma, struct pci_dev *dev){ struct parport_pc_private *priv; struct parport_operations *ops; struct parport tmp; struct parport *p = &tmp; int probedirq = PARPORT_IRQ_NONE; if (check_region(base, 3)) return NULL; priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); if (!priv) { printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); return NULL; } ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); if (!ops) { printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", base); kfree (priv); return NULL; } memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations)); priv->ctr = 0xc; priv->ctr_writable = ~0x10; priv->ecr = 0; priv->fifo_depth = 0; priv->dma_buf = 0; priv->dma_handle = 0; priv->dev = dev; p->base = base; p->base_hi = base_hi; p->irq = irq; p->dma = dma; p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; p->ops = ops; p->private_data = priv; p->physport = p; if (base_hi && !check_region(base_hi,3)) parport_ECR_present(p); if (base != 0x3bc) { if (!check_region(base+0x3, 5)) { if (!parport_EPP_supported(p)) parport_ECPEPP_supported(p); } } if (!parport_SPP_supported (p)) { /* No port. */ kfree (priv); kfree (ops); return NULL; } if (priv->ecr) parport_ECPPS2_supported(p); else parport_PS2_supported (p); if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops))) { kfree (priv); kfree (ops); return NULL; } p->base_hi = base_hi; p->modes = tmp.modes; p->size = (p->modes & PARPORT_MODE_EPP)?8:3; p->private_data = priv; printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); if (p->base_hi && priv->ecr) printk(" (0x%lx)", p->base_hi); p->irq = irq; p->dma = dma; if (p->irq == PARPORT_IRQ_AUTO) { p->irq = PARPORT_IRQ_NONE; parport_irq_probe(p); } else if (p->irq == PARPORT_IRQ_PROBEONLY) { p->irq = PARPORT_IRQ_NONE; parport_irq_probe(p); probedirq = p->irq; p->irq = PARPORT_IRQ_NONE; } if (p->irq != PARPORT_IRQ_NONE) { printk(", irq %d", p->irq); if (p->dma == PARPORT_DMA_AUTO) { p->dma = PARPORT_DMA_NONE; parport_dma_probe(p); } } if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq is mandatory (see above) */ p->dma = PARPORT_DMA_NONE;#ifdef CONFIG_PARPORT_PC_FIFO if (parport_ECP_supported(p) && p->dma != PARPORT_DMA_NOFIFO && priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) { p->modes |= PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; p->ops->compat_write_data = parport_pc_compat_write_block_pio;#ifdef CONFIG_PARPORT_1284 p->ops->ecp_write_data = parport_pc_ecp_write_block_pio; /* currently broken, but working on it.. (FB) */ /* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */#endif /* IEEE 1284 support */ if (p->dma != PARPORT_DMA_NONE) { printk(", dma %d", p->dma); p->modes |= PARPORT_MODE_DMA; } else printk(", using FIFO"); } else /* We can't use the DMA channel after all. */ p->dma = PARPORT_DMA_NONE;#endif /* Allowed to use FIFO/DMA */ printk(" [");#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}} { int f = 0; printmode(PCSPP); printmode(TRISTATE); printmode(COMPAT) printmode(EPP); printmode(ECP); printmode(DMA); }#undef printmode#ifndef CONFIG_PARPORT_1284 printk ("(,...)");#endif /* CONFIG_PARPORT_1284 */ printk("]\n"); if (probedirq != PARPORT_IRQ_NONE) printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); parport_proc_register(p); request_region (p->base, 3, p->name); if (p->size > 3) request_region (p->base + 3, p->size - 3, p->name); if (p->modes & PARPORT_MODE_ECP) request_region (p->base_hi, 3, p->name); if (p->irq != PARPORT_IRQ_NONE) { if (request_irq (p->irq, parport_pc_interrupt, 0, p->name, p)) { printk (KERN_WARNING "%s: irq %d in use, " "resorting to polled operation\n", p->name, p->irq); p->irq = PARPORT_IRQ_NONE; p->dma = PARPORT_DMA_NONE; }#ifdef CONFIG_PARPORT_PC_FIFO if (p->dma != PARPORT_DMA_NONE) { if (request_dma (p->dma, p->name)) { printk (KERN_WARNING "%s: dma %d in use, " "resorting to PIO operation\n", p->name, p->dma); p->dma = PARPORT_DMA_NONE; } else { priv->dma_buf = pci_alloc_consistent(priv->dev, PAGE_SIZE, &priv->dma_handle); if (! priv->dma_buf) { printk (KERN_WARNING "%s: " "cannot get buffer for DMA, " "resorting to PIO operation\n", p->name); free_dma(p->dma); p->dma = PARPORT_DMA_NONE; } } }#endif /* CONFIG_PARPORT_PC_FIFO */ } /* Done probing. Now put the port into a sensible start-up state. */ if (priv->ecr) /* * Put the ECP detected port in PS2 mode. * Do this also for ports that have ECR but don't do ECP. */ ECR_WRITE (p, 0x34); parport_pc_write_data(p, 0); parport_pc_data_forward (p); /* Now that we've told the sharing engine about the port, and found out its characteristics, let the high-level drivers know about it. */ parport_announce_port (p); return p;}void parport_pc_unregister_port (struct parport *p){ struct parport_pc_private *priv = p->private_data; struct parport_operations *ops = p->ops; if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) free_irq(p->irq, p); release_region(p->base, 3); if (p->size > 3) release_region(p->base + 3, p->size - 3); if (p->modes & PARPORT_MODE_ECP) release_region(p->base_hi, 3); parport_proc_unregister(p); if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, priv->dma_buf, priv->dma_handle); kfree (p->private_data); parport_unregister_port(p); kfree (ops); /* hope no-one cached it */}#ifdef CONFIG_PCI/* ITE support maintained by Rich Liu <richliu@poorman.org> */static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, int autodma){ short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 }; u32 ite8872set; u32 ite8872_lpt, ite8872_lpthi; u8 ite8872_irq, type; int irq; int i; DPRINTK (KERN_DEBUG "sio_ite_8872_probe()\n"); // make sure which one chip for(i = 0; i < 5; i++) { if (check_region (inta_addr[i], 0x8) >= 0) { int test; pci_write_config_dword (pdev, 0x60, 0xe7000000 | inta_addr[i]); pci_write_config_dword (pdev, 0x78, 0x00000000 | inta_addr[i]); test = inb (inta_addr[i]); if (test != 0xff) break; } } if(i >= 5) { printk (KERN_INFO "parport_pc: cannot find ITE8872 INTA\n"); return 0; } type = inb (inta_addr[i] + 0x18); type &= 0x0f; switch (type) { case 0x2: printk (KERN_INFO "parport_pc: ITE8871 found (1P)\n"); ite8872set = 0x64200000; break; case 0xa: printk (KERN_INFO "parport_pc: ITE8875 found (1P)\n"); ite8872set = 0x64200000; break; case 0xe: printk (KERN_INFO "parport_pc: ITE8872 found (2S1P)\n"); ite8872set = 0x64e00000; break; case 0x6: printk (KERN_INFO "parport_pc: ITE8873 found (1S)\n"); return 0; case 0x8: DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n"); return 0; default: printk (KERN_INFO "parport_pc: unkn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -