linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ITE887x parport_serial driver
@ 2003-06-11  3:49 Ted.Wen
  2003-06-11  4:09 ` Zwane Mwaikambo
  0 siblings, 1 reply; 2+ messages in thread
From: Ted.Wen @ 2003-06-11  3:49 UTC (permalink / raw)
  To: linux-kernel

I patched the 887x driver last month , but with something not well..I patch it again.
 I is very kind of  Zwane Mwaikambo to give me a big help .
The patch with two files , remove parport setting from parport_pc.c and 
   add parport and serial setting to parport_serial.c.
ITE887x is a pci card with parport and serial , five types:
8871: 1 parport
8872: 1 parport , 2 serial .
8873: 1 serial.
8874: 2 serial.
8875: 1 parport.
All of their dendor and device id is 1283 : 8872 ,
but we can recognize the type by other way after initialize the card .

In parport_serial , I request a irq and request region to initialize 887x ,
so I must run a additional ite887x_removecheck function to check it.
Some type of 887x  only with serial or only with parport , so that 
sometimes the port num would be 0 .
 I want the driver can proceed with runing even the card with no parport , or with on serial.
( the original driver return -ENODEV while fail in parport_register or serial_register )
 I set success = 1 while the port num =0 in the tables , to avoid fail from parport register or serial register.

I also fix a bug while printk the parport information.
The original driver printk parport_serial_pci_tb[i].vendor , 
  the index "i" is be used to cards[i].....but parport_serial_pci_tbl and cards are not match.
The bug will show wrong message wile printk parport information,
 so I fix it to be dev->vendor , to show the correct message.





--- parport_pc.c	2002-11-29 07:53:14.000000000 +0800
+++ /parport_pc_ite887x.c	2003-05-27 14:32:37.000000000 +0800
@@ -2436,103 +2436,6 @@
 
 #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: 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)
@@ -2643,7 +2546,6 @@
 
 enum parport_pc_sio_types {
 	sio_via_686a = 0,	/* Via VT82C686A motherboard Super I/O */
-	sio_ite_8872,
 	last_sio
 };
 
@@ -2652,7 +2554,6 @@
 	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma);
 } parport_pc_superio_info[] __devinitdata = {
 	{ sio_via_686a_probe, },
-	{ sio_ite_8872_probe, },
 };
 
 
@@ -2773,8 +2674,6 @@
 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_1P_10x,
















--- parport_serial.c	2003-06-11 10:57:11.000000000 +0800
+++ parport_serial_ite887x.c	2003-06-11 10:56:25.000000000 +0800
@@ -29,6 +29,15 @@
 
 #include <asm/serial.h>
 
+/*
+ * ITE 887x 
+ */
+int ITEBOARDNUMBER = 0, ite887x_index, rm_ite = 0;
+u32 ITE887x_INTC[8];
+u16 ITE887x_INTA[8];
+u8 ITE887x_IRQ[8];
+int __devinit pci_ite887x_fn(struct pci_dev *dev, int autoirq, int autodma);
+
 enum parport_pc_pci_cards {
 	titan_110l = 0,
 	titan_210l,
@@ -46,6 +55,7 @@
 	siig_2p1s_20x,
 	siig_1s1p_20x,
 	siig_2s1p_20x,
+	ite_887x,
 };
 
 
@@ -84,6 +94,7 @@
 	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
 	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
 	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
+	/* ite_887x      */  		{ 0, { { 3, 4 }, }, pci_ite887x_fn }, 
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
@@ -132,6 +143,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ite_887x},
 
 	{ 0, } /* terminate list */
 };
@@ -185,6 +198,7 @@
 /* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
 /* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
 /* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* ite_887x 	 */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 0, 115200 },
 };
 
 struct parport_serial_private {
@@ -195,6 +209,165 @@
 	struct parport *port[PARPORT_MAX];
 };
 
+/*
+ * Integrated Technology Express, Inc. IT887x Device Driver 
+ */
+
+ite887x_removecheck(struct pci_dev *dev)
+{
+	if (dev->vendor == PCI_VENDOR_ID_ITE
+	    && dev->device == PCI_DEVICE_ID_ITE_8872) {
+		free_irq(dev->irq, dev);
+		release_region(ITE887x_INTA[rm_ite++], 0x8);
+	}
+}
+
+void ite887x_requestirq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u8 itmp;
+	int i = 0;
+	/* measure which INTC went to control  */
+	for (i = 0; i < 8; i++)
+		if (irq == ITE887x_IRQ[i]) {
+			/* clean ITE887x interrupt  */
+			itmp = inb(ITE887x_INTC[i] + 2);
+			if (itmp && 0xf) {
+				outb(itmp, ITE887x_INTC[i] + 2);
+				break;
+			}
+		}
+}
+
+int __devinit pci_ite887x_fn(struct pci_dev *dev, int autoirq, int autodma)
+{
+	int result, ite887xcomnum = 0, ite887xparportnum = 0;
+	short INTA_Addr[8] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1E0, 0x200, 0x280 };
+	u32 j, u32Tmp, itmp, ITE887x_COM1, ITE887x_COM2, ITE887xSET = 0x64E00000, set60, set78, ite887x_lpt, ite887x_lpthi;
+
+	pci_read_config_dword(dev, 0x60, &set60);
+	pci_read_config_dword(dev, 0x78, &set78);
+
+	for (j = 0; j < 7; j++)
+		if (check_region(INTA_Addr[j], 0x8) >= 0) {
+			pci_write_config_dword(dev, 0x60, 0xE7000000 | INTA_Addr[j]);
+			pci_write_config_dword(dev, 0x78, 0x00000000 | INTA_Addr[j]);
+			itmp = inb(INTA_Addr[j]);
+			if (itmp != 0xFF)
+				break;
+		}
+
+	if (j >= 7) {
+		printk(KERN_INFO "ITE887x INTA cannot find.\n");
+		return 0;
+	}
+	/* Detect the type of 887x */
+	ITE887x_INTA[ITEBOARDNUMBER] = INTA_Addr[j];
+	itmp = INTA_Addr[j];
+	u32Tmp = inb(itmp + 0x18);
+	u32Tmp &= 0x0F;
+	switch (u32Tmp) {
+	case 0x2:
+		printk(KERN_INFO "ITE887x: ITE8871 found , Parallel*1 \n");
+		ITE887xSET = 0x64200000;
+		ite887xcomnum = 0;
+		ite887xparportnum = 1;
+		request_region(INTA_Addr[j], 0x8, "ite8871");
+		break;
+	case 0xA:
+		printk(KERN_INFO "ITE887x: ITE8875 found , Parallel*1 \n");
+		ITE887xSET = 0x64200000;
+		ite887xcomnum = 0;
+		ite887xparportnum = 1;
+		request_region(INTA_Addr[j], 0x8, "ite8875");
+		break;
+	case 0xE:
+		printk(KERN_INFO
+		       "ITE887x: ITE8872 found , Serial *2 , Parallel*1 \n");
+		ite887xcomnum = 2;
+		ite887xparportnum = 1;
+		ITE887xSET = 0x64E00000;
+		request_region(INTA_Addr[j], 0x8, "ite8872");
+		break;
+	case 0x6:
+		printk(KERN_INFO "ITE887x: ITE8873 found , Serial *1 \n");
+		ite887xcomnum = 1;
+		ite887xparportnum = 0;
+		ITE887xSET = 0x64800000;
+		request_region(INTA_Addr[j], 0x8, "ite8873");
+		break;
+	case 0x8:
+		printk(KERN_INFO "ITE887x: ITE8874 found , Serial *2 \n");
+		ite887xcomnum = 2;
+		ite887xparportnum = 0;
+		ITE887xSET = 0x64C00000;
+		request_region(INTA_Addr[j], 0x8, "ite8874");
+		break;
+	default:
+		ite887xcomnum = 0;
+		ite887xparportnum = 0;
+		printk(KERN_INFO "ITE887x: unknow ITE887x \n");
+		printk(KERN_INFO
+		       "ITE887x: please mail lspci -nvv output to ted.wen@ite.com.tw\n");
+		pci_write_config_dword(dev, 0x60, set60);
+		pci_write_config_dword(dev, 0x78, set78);
+		return 0;
+		break;
+	}
+	cards[ite887x_index].numports = ite887xparportnum;
+	pci_boards[ite887x_index].num_ports = ite887xcomnum;
+	ITE887x_IRQ[ITEBOARDNUMBER] = dev->irq;
+	printk(KERN_INFO "ITE887X_IRQ : %d \n", ITE887x_IRQ[ITEBOARDNUMBER]);
+	result = request_irq(ITE887x_IRQ[ITEBOARDNUMBER], ite887x_requestirq, SA_SHIRQ, "ite887x", dev);
+	if (result) {
+		printk(KERN_INFO "ITE887x: can't get assign irq :%x \n",
+		       ITE887x_IRQ[ITEBOARDNUMBER]);
+		return 0;
+	}
+
+	/* INTC */
+	pci_read_config_dword(dev, 0x10, &ITE887x_INTC[ITEBOARDNUMBER]);
+	ITE887x_INTC[ITEBOARDNUMBER] &= 0x0000FF00;
+	pci_write_config_dword(dev, 0x60, 0xE5000000 | ITE887x_INTC[ITEBOARDNUMBER]);
+	pci_write_config_dword(dev, 0x78, ITE887x_INTC[ITEBOARDNUMBER]);
+
+	if (ite887xcomnum >= 1) {
+		/* COM1 */
+		pci_read_config_dword(dev, 0x14, &ITE887x_COM1);
+		ITE887x_COM1 &= 0x0000FF00;
+		pci_write_config_dword(dev, 0x64, 0xE3000000 | ITE887x_COM1);
+
+		/* COM2 */
+		if (ite887xcomnum == 2) {
+			pci_read_config_dword(dev, 0x18, &ITE887x_COM2);
+			ITE887x_COM2 &= 0x0000FF00;
+			pci_write_config_dword(dev, 0x68, 0xE3000000 | ITE887x_COM2);
+		} else
+			ITE887x_COM2 = 0;
+
+		pci_write_config_dword(dev, 0x7C, (ITE887x_COM2 << 16) | (ITE887x_COM1));
+	}
+
+	/* Parport */
+	if (ite887xparportnum >= 1) {
+		pci_read_config_dword(dev, 0x1c, &ite887x_lpt);
+		ite887x_lpt &= 0x0000ff00;
+		pci_read_config_dword(dev, 0x20, &ite887x_lpthi);
+		ite887x_lpthi &= 0x0000ff00;
+		pci_write_config_dword(dev, 0x6c, 0xe3000000 | ite887x_lpt);
+		pci_write_config_dword(dev, 0x70, 0xe3000000 | ite887x_lpthi);
+		pci_write_config_dword(dev, 0x80, (ite887x_lpthi << 16) | ite887x_lpt);
+		printk(KERN_INFO "ITE887x: The PARALLEL I/O port is 0x%x.\n",
+		       ite887x_lpt);
+		printk(KERN_INFO "ITE887x: The PARALLEL I/O porthi is 0x%x.\n",
+		       ite887x_lpthi);
+	}
+	/* 9C write enable UART , IRQ Function */
+	pci_write_config_dword(dev, 0x9c, ITE887xSET | (0x11111 * ITE887x_IRQ[ITEBOARDNUMBER]));
+	/* Add next interface */
+	ITEBOARDNUMBER++;
+	return 0;
+}
+
 static int __devinit get_pci_port (struct pci_dev *dev,
 				   struct pci_board_no_ids *board,
 				   struct serial_struct *req,
@@ -276,6 +449,8 @@
 		base_baud = BASE_BAUD;
 	memset (&serial_req, 0, sizeof (serial_req));
 
+	if (board->num_ports == 0)
+		success = 1;
 	for (k = 0; k < board->num_ports; k++) {
 		int line;
 		serial_req.irq = dev->irq;
@@ -308,6 +483,8 @@
 	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
 		return -ENODEV;
 
+	if (cards[i].numports == 0)
+		success = 1;
 	for (n = 0; n < cards[i].numports; n++) {
 		struct parport *port;
 		int lo = cards[i].addr[n].lo;
@@ -324,8 +501,8 @@
 		/* TODO: test if sharing interrupts works */
 		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
 			"I/O at %#lx(%#lx)\n",
-			parport_serial_pci_tbl[i].vendor,
-			parport_serial_pci_tbl[i].device, io_lo, io_hi);
+			dev->vendor,
+			dev->device, io_lo, io_hi);
 		port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
 					      PARPORT_DMA_NONE, dev);
 		if (port) {
@@ -359,6 +536,7 @@
 		return err;
 	}
 
+	ite887x_index = id->driver_data;
 	if (parport_register (dev, id)) {
 		pci_set_drvdata (dev, NULL);
 		kfree (priv);
@@ -395,6 +573,7 @@
 	for (i = 0; i < priv->num_par; i++)
 		parport_pc_unregister_port (priv->port[i]);
 
+	ite887x_removecheck(dev);
 	kfree (priv);
 	return;
 }

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-06-11  4:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-11  3:49 [PATCH] ITE887x parport_serial driver Ted.Wen
2003-06-11  4:09 ` Zwane Mwaikambo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).