patch-2.4.14 linux/drivers/parport/parport_pc.c

Next file: linux/drivers/pci/compat.c
Previous file: linux/drivers/parport/ieee1284_ops.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.13/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
@@ -798,6 +798,8 @@
 {
 	size_t written;
 	int r;
+	long int expire;
+	const struct parport_pc_private *priv = port->physport->private_data;
 
 	/* Special case: a timeout of zero means we cannot call schedule(). */
 	if (!port->physport->cad->timeout)
@@ -819,9 +821,19 @@
 		written = parport_pc_fifo_write_block_pio (port, buf, length);
 
 	/* Finish up. */
-	if (change_mode (port, ECR_PS2) == -EBUSY) {
-		const struct parport_pc_private *priv = 
-			port->physport->private_data;
+	/* For some hardware we don't want to touch the mode until
+	 * the FIFO is empty, so allow 4 seconds for each position
+	 * in the fifo.
+	 */
+        expire = jiffies + (priv->fifo_depth * HZ * 4);
+	do {
+		/* Wait for the FIFO to empty */
+		r = change_mode (port, ECR_PS2);
+		if (r != -EBUSY) {
+			break;
+		}
+	} while (time_before (jiffies, expire));
+	if (r == -EBUSY) {
 
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
@@ -862,6 +874,8 @@
 {
 	size_t written;
 	int r;
+	long int expire;
+	const struct parport_pc_private *priv = port->physport->private_data;
 
 	/* Special case: a timeout of zero means we cannot call schedule(). */
 	if (!port->physport->cad->timeout)
@@ -904,9 +918,19 @@
 		written = parport_pc_fifo_write_block_pio (port, buf, length);
 
 	/* Finish up. */
-	if (change_mode (port, ECR_PS2) == -EBUSY) {
-		const struct parport_pc_private *priv =
-			port->physport->private_data;
+	/* For some hardware we don't want to touch the mode until
+	 * the FIFO is empty, so allow 4 seconds for each position
+	 * in the fifo.
+	 */
+	expire = jiffies + (priv->fifo_depth * (HZ * 4));
+	do {
+		/* Wait for the FIFO to empty */
+		r = change_mode (port, ECR_PS2);
+		if (r != -EBUSY) {
+			break;
+		}
+	} while (time_before (jiffies, expire));
+	if (r == -EBUSY) {
 
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
@@ -2095,10 +2119,9 @@
 
 	if (priv->ecr) {
 		pb->irq = programmable_irq_support(pb);
-	}
 
-	if (pb->modes & PARPORT_MODE_ECP) {
-		pb->irq = irq_probe_ECP(pb);
+		if (pb->irq == PARPORT_IRQ_NONE)
+			pb->irq = irq_probe_ECP(pb);
 	}
 
 	if ((pb->irq == PARPORT_IRQ_NONE) && priv->ecr &&
@@ -2231,7 +2254,7 @@
 	p->private_data = priv;
 
 	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
-	if (p->base_hi && (p->modes & PARPORT_MODE_ECP))
+	if (p->base_hi && priv->ecr)
 		printk(" (0x%lx)", p->base_hi);
 	p->irq = irq;
 	p->dma = dma;
@@ -2382,6 +2405,105 @@
 }
 
 #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 (1S1P)\n");
+		ite8872set = 0x64a00000;
+		break;
+	case 0x8:
+		DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n");
+		return 0;
+	default:
+		printk (KERN_INFO "parport_pc: unknown ITE887x\n");
+		printk (KERN_INFO "parport_pc: please mail 'lspci -nvv' "
+			"output to Rich.Liu@ite.com.tw\n");
+		return 0;
+	}
+
+	pci_read_config_byte (pdev, 0x3c, &ite8872_irq);
+	pci_read_config_dword (pdev, 0x1c, &ite8872_lpt);
+	ite8872_lpt &= 0x0000ff00;
+	pci_read_config_dword (pdev, 0x20, &ite8872_lpthi);
+	ite8872_lpthi &= 0x0000ff00;
+	pci_write_config_dword (pdev, 0x6c, 0xe3000000 | ite8872_lpt);
+	pci_write_config_dword (pdev, 0x70, 0xe3000000 | ite8872_lpthi);
+	pci_write_config_dword (pdev, 0x80, (ite8872_lpthi<<16) | ite8872_lpt);
+	// SET SPP&EPP , Parallel Port NO DMA , Enable All Function
+	// SET Parallel IRQ
+	pci_write_config_dword (pdev, 0x9c,
+				ite8872set | (ite8872_irq * 0x11111));
+
+	DPRINTK (KERN_DEBUG "ITE887x: The IRQ is %d.\n", ite8872_irq);
+	DPRINTK (KERN_DEBUG "ITE887x: The PARALLEL I/O port is 0x%x.\n",
+		 ite8872_lpt);
+	DPRINTK (KERN_DEBUG "ITE887x: The PARALLEL I/O porthi is 0x%x.\n",
+		 ite8872_lpthi);
+
+	/* Let the user (or defaults) steer us away from interrupts */
+	irq = ite8872_irq;
+	if (autoirq != PARPORT_IRQ_AUTO)
+		irq = PARPORT_IRQ_NONE;
+
+	if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi,
+				   irq, PARPORT_DMA_NONE, NULL)) {
+		printk (KERN_INFO
+			"parport_pc: ITE 8872 parallel port: io=0x%X",
+			ite8872_lpt);
+		if (irq != PARPORT_IRQ_NONE)
+			printk (", irq=%d", irq);
+		printk ("\n");
+		return 1;
+	}
+
+	return 0;
+}
+
 /* Via support maintained by Jeff Garzik <jgarzik@mandrakesoft.com> */
 static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq,
 					 int autodma)
@@ -2492,6 +2614,7 @@
 
 enum parport_pc_sio_types {
 	sio_via_686a = 0,	/* Via VT82C686A motherboard Super I/O */
+	sio_ite_8872,
 	last_sio
 };
 
@@ -2500,6 +2623,7 @@
 	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma);
 } parport_pc_superio_info[] __devinitdata = {
 	{ sio_via_686a_probe, },
+	{ sio_ite_8872_probe, },
 };
 
 
@@ -2559,6 +2683,7 @@
 	avlab_2p,
 	oxsemi_954,
 	oxsemi_840,
+	aks_0100,
 };
 
 
@@ -2632,11 +2757,14 @@
 	 * and 840 locks up if you write 1 to bit 2! */
 	/* oxsemi_954 */		{ 1, { { 0, -1 }, } },
 	/* oxsemi_840 */		{ 1, { { 0, -1 }, } },
+	/* aks_0100 */			{ 1, { { 0, 1 }, } },
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
 	/* Super-IO onboard chips */
 	{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
+	{ PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_ite_8872 },
 
 	/* PCI cards */
 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
@@ -2725,6 +2853,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_954 },
 	{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_12PCI840,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_840 },
+	{ PCI_VENDOR_ID_AKS, PCI_DEVICE_ID_AKS_ALADDINCARD,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, aks_0100 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)