[Linux-parport] [PATCH] ite887x driver for 2.6.2

Ted.Wen at ite.com.tw Ted.Wen at ite.com.tw
Wed Mar 31 13:39:12 BST 2004


> patch two files , parport_pc.c and parport_serial.c
>=20
> --- parport_pc-2.6.2.c	2004-03-31 07:31:57.000000000 +0800
> +++ parport_pc-ite887x.c	2004-03-31 07:32:39.000000000 +0800
> @@ -2457,111 +2457,6 @@
> =20
>  #ifdef CONFIG_PCI
> =20
> -/* ITE support maintained by Rich Liu <richliu at poorman.org> */
> -static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int =
autoirq,
> -					 int autodma)
> -{
> -	short inta_addr[6] =3D { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
> -	struct resource *base_res;
> -	u32 ite8872set;
> -	u32 ite8872_lpt, ite8872_lpthi;
> -	u8 ite8872_irq, type;
> -	char *fake_name =3D "parport probe";
> -	int irq;
> -	int i;
> -
> -	DPRINTK (KERN_DEBUG "sio_ite_8872_probe()\n");
> -=09
> -	// make sure which one chip
> -	for(i =3D 0; i < 5; i++) {
> -		base_res =3D request_region(inta_addr[i], 0x8, fake_name);
> -		if (base_res) {
> -			int test;
> -			pci_write_config_dword (pdev, 0x60,
> -						0xe7000000 | inta_addr[i]);
> -			pci_write_config_dword (pdev, 0x78,
> -						0x00000000 | inta_addr[i]);
> -			test =3D inb (inta_addr[i]);
> -			if (test !=3D 0xff) break;
> -			release_region(inta_addr[i], 0x8);
> -		}
> -	}
> -	if(i >=3D 5) {
> -		printk (KERN_INFO "parport_pc: cannot find ITE8872 INTA\n");
> -		return 0;
> -	}
> -
> -	type =3D inb (inta_addr[i] + 0x18);
> -	type &=3D 0x0f;
> -
> -	switch (type) {
> -	case 0x2:
> -		printk (KERN_INFO "parport_pc: ITE8871 found (1P)\n");
> -		ite8872set =3D 0x64200000;
> -		break;
> -	case 0xa:
> -		printk (KERN_INFO "parport_pc: ITE8875 found (1P)\n");
> -		ite8872set =3D 0x64200000;
> -		break;
> -	case 0xe:
> -		printk (KERN_INFO "parport_pc: ITE8872 found (2S1P)\n");
> -		ite8872set =3D 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 at ite.com.tw\n");
> -		return 0;
> -	}
> -
> -	pci_read_config_byte (pdev, 0x3c, &ite8872_irq);
> -	pci_read_config_dword (pdev, 0x1c, &ite8872_lpt);
> -	ite8872_lpt &=3D 0x0000ff00;
> -	pci_read_config_dword (pdev, 0x20, &ite8872_lpthi);
> -	ite8872_lpthi &=3D 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 =3D ite8872_irq;
> -	if (autoirq !=3D PARPORT_IRQ_AUTO)
> -		irq =3D PARPORT_IRQ_NONE;
> -
> -	/*
> -	 * Release the resource so that parport_pc_probe_port can get it.
> -	 */
> -	release_resource(base_res);
> -	if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi,
> -				   irq, PARPORT_DMA_NONE, NULL)) {
> -		printk (KERN_INFO
> -			"parport_pc: ITE 8872 parallel port: io=3D0x%X",
> -			ite8872_lpt);
> -		if (irq !=3D PARPORT_IRQ_NONE)
> -			printk (", irq=3D%d", irq);
> -		printk ("\n");
> -		return 1;
> -	}
> -
> -	return 0;
> -}
> -
>  /* Via support maintained by Jeff Garzik <jgarzik at pobox.com> */
>  static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int =
autoirq,
>  					 int autodma)
> @@ -2672,7 +2567,6 @@
> =20
>  enum parport_pc_sio_types {
>  	sio_via_686a =3D 0,	/* Via VT82C686A motherboard Super I/O */
> -	sio_ite_8872,
>  	last_sio
>  };
> =20
> @@ -2681,7 +2575,6 @@
>  	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma);
>  } parport_pc_superio_info[] __devinitdata =3D > {
>  	{ sio_via_686a_probe, },
> -	{ sio_ite_8872_probe, },
>  };
> =20
> =20
> @@ -2832,8 +2725,6 @@
>  static struct pci_device_id parport_pc_pci_tbl[] =3D {
>  	/* 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 },
> =20
>  	/* PCI cards */
>  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
>=20
>=20
>=20
>=20
>=20
>=20
>=20
>=20
>=20
>=20
> --- parport_serial-2.6.2.c	2004-03-31 07:32:01.000000000 +0800
> +++ parport_serial-ite887x.c	2004-03-31 07:32:39.000000000 +0800
> @@ -30,6 +30,11 @@
> =20
>  #include <asm/serial.h>
> =20
> +/* ITE 887x  */
> +static int pci_ite887x_fn(struct pci_dev *dev, int autoirq, int =
autodma);
> +static void ite887x_remove(struct pci_dev *dev);
> +
> +
>  enum parport_pc_pci_cards {
>  	titan_110l =3D 0,
>  	titan_210l,
> @@ -47,6 +52,7 @@
>  	siig_2p1s_20x,
>  	siig_1s1p_20x,
>  	siig_2s1p_20x,
> +	ite_887x,
>  };
> =20
> =20
> @@ -64,6 +70,7 @@
>  	 * If it returns non-zero, no probing will take place and the
>  	 * ports will not be used. */
>  	int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int =
autodma);
> +	void (*remove_hook) (struct pci_dev *pdev);
> =20
>  	/* If set, this is called after probing for ports.  If 'failed'
>  	 * is non-zero we couldn't use any of the ports. */
> @@ -85,6 +92,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, NULL, =
ite887x_remove },
>  };
> =20
>  static struct pci_device_id parport_serial_pci_tbl[] =3D {
> @@ -133,6 +141,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},
> =20
>  	{ 0, } /* terminate list */
>  };
> @@ -186,6 +196,12 @@
>  /* 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 ite_priv {
> +	u32 inta;
> +	u32 intc;
>  };
> =20
>  struct parport_serial_private {
> @@ -194,8 +210,188 @@
>  	struct pci_board_no_ids ser;
>  	int num_par;
>  	struct parport *port[PARPORT_MAX];
> +	int tbl_index;
> +	void *hw_priv;
>  };
> =20
> +
> +/* Integrated Technology Express, Inc. IT887x Device Driver  */
> +
> +static void ite887x_remove(struct pci_dev *dev)
> +{
> +	struct parport_serial_private *priv =3D pci_get_drvdata(dev);
> +	struct ite_priv *ite_priv =3D priv->hw_priv;
> +
> +	free_irq(dev->irq, dev);
> +	release_region(ite_priv->inta, 0x8);
> +	kfree(ite_priv);
> +}
> +
> +static void ite887x_interrupt(int irq, void *dev_id, struct pt_regs =
*regs)
> +{
> +	struct pci_dev *dev =3D dev_id;
> +	struct parport_serial_private *priv =3D pci_get_drvdata(dev);
> +	struct ite_priv *ite_priv =3D priv->hw_priv;
> +
> +	u8 itmp;
> +	/* clear ITE887x interrupt  */
> +	itmp =3D inb(ite_priv->intc + 2);
> +	if (itmp & 0xf)=20
> +		outb(itmp, ite_priv->intc + 2);
> +}
> +
> +static int __devinit pci_ite887x_fn(struct pci_dev *dev, int autoirq, =
int autodma)
> +{
> +	struct parport_serial_private *priv =3D pci_get_drvdata(dev);
> +	int result, ite887xcomnum =3D 0, ite887xparportnum =3D 0;
> +	short INTA_Addr[8] =3D { 0x2a0, 0x2c0, 0x220, 0x240, 0x1E0, 0x200, =
0x280 };
> +	u32 j, u32Tmp, itmp, ITE887x_COM1, ITE887x_COM2, ITE887xSET =3D =
0x64E00000;
> +	u32 set60, set78, ite887x_lpt, ite887x_lpthi;
> +	struct ite_priv *ite_priv;
> +
> +	ite_priv =3D kmalloc(sizeof *ite_priv, GFP_KERNEL);
> +	if (!ite_priv)
> +		return -ENOMEM;
> +
> +	priv->hw_priv =3D ite_priv;
> +	pci_read_config_dword(dev, 0x60, &set60);>=20
> +	pci_read_config_dword(dev, 0x78, &set78);
> +
> +	for (j =3D 0; j < 7; j++)
> +		if (check_region(INTA_Addr[j], 0x8) >=3D 0) {
> +			pci_write_config_dword(dev, 0x60, 0xE7000000 | INTA_Addr[j]);
> +			pci_write_config_dword(dev, 0x78, INTA_Addr[j]);
> +			itmp =3D inb(INTA_Addr[j]);
> +			if (itmp !=3D 0xFF)
> +				break;
> +		}
> +
> +	if (j >=3D 7) {
> +		printk(KERN_INFO "ITE887x INTA cannot find.\n");
> +		result -ENODEV;=09
> +		goto out_free;
> +	}
> +
> +	/* Detect the type of 887x */
> +	ite_priv->inta =3D INTA_Addr[j];
> +	itmp =3D INTA_Addr[j];
> +	u32Tmp =3D inb(itmp + 0x18);
> +	u32Tmp &=3D 0x0F;
> +
> +	result =3D -EBUSY;
> +	switch (u32Tmp) {
> +	case 0x2:
> +		printk(KERN_INFO "ITE887x: ITE8871 found , Parallel*1 \n");
> +		ITE887xSET =3D 0x64200000;
> +		ite887xcomnum =3D 0;
> +		ite887xparportnum =3D 1;
> +		if (!request_region(INTA_Addr[j], 0x8, "ite8871"))
> +			goto out_free;
> +		break;
> +	case 0xA:
> +		printk(KERN_INFO "ITE887x: ITE8875 found , Parallel*1 \n");
> +		ITE887xSET =3D 0x64200000;
> +		ite887xcomnum =3D 0;
> +		ite887xparportnum =3D 1;
> +		if (!request_region(INTA_Addr[j], 0x8, "ite8875"))
> +			goto out_free;
> +		break;
> +	case 0xE:
> +		printk(KERN_INFO
> +		       "ITE887x: ITE8872 found , Serial *2 , Parallel*1 \n");
> +		ite887xcomnum =3D 2;
> +		ite887xparportnum =3D 1;
> +		ITE887xSET =3D 0x64E00000;
> +		if (!request_region(INTA_Addr[j], 0x8, "ite8872"))
> +			goto out_free;
> +		break;
> +	case 0x6:
> +		printk(KERN_INFO "ITE887x: ITE8873 found , Serial *1 \n");
> +		ite887xcomnum =3D 1;
> +		ite887xparportnum =3D 0;
> +		ITE887xSET =3D 0x64800000;
> +		if (!request_region(INTA_Addr[j], 0x8, "ite8873"))
> +			goto out_free;
> +		break;
> +	case 0x8:
> +		printk(KERN_INFO "ITE887x: ITE8874 found , Serial *2 \n");
> +		ite887xcomnum =3D 2;
> +		ite887xparportnum =3D 0;
> +		ITE887xSET =3D 0x64C00000;
> +		if (!request_region(INTA_Addr[j], 0x8, "ite8874"))
> +			goto out_free;
> +		break;
> +	default:
> +		ite887xcomnum =3D 0;
> +		ite887xparportnum =3D 0;
> +		printk(KERN_INFO "ITE887x: unknown ITE887x \n");
> +		printk(KERN_INFO
> +		       "ITE887x: please mail lspci -nvv output to =
ted.wen at ite.com.tw\n");
> +		pci_write_config_dword(dev, 0x60, set60);
> +		pci_write_config_dword(dev, 0x78, set78);
> +		result =3D -ENODEV;
> +		goto out_free;
> +	}
> +
> +	cards[priv->tbl_index].numports =3D ite887xparportnum;
> +	pci_boards[priv->tbl_index].num_ports =3D ite887xcomnum;
> +	printk(KERN_DEBUG "ITE887X_IRQ : %d \n", dev->irq);
> +	result =3D request_irq(dev->irq, ite887x_interrupt, SA_SHIRQ, =
"ite887x", dev);
> +	if (result) {
> +		printk(KERN_INFO "ITE887x: cannot assign irq :%x \n", dev->irq);
> +		goto out_free_region;
> +	}
> +
> +	/* INTC */
> +	pci_read_config_dword(dev, 0x10, &ite_priv->intc);
> +	ite_priv->intc &=3D 0x0000FF00;
> +	pci_write_config_dword(dev, 0x60, 0xE5000000 | ite_priv->intc);
> +	pci_write_config_dword(dev, 0x78, ite_priv->intc);
> +
> +	if (ite887xcomnum >=3D 1) {
> +		/* COM1 */
> +		pci_read_config_dword(dev, 0x14, &ITE887x_COM1);
> +		ITE887x_COM1 &=3D 0x0000FF00;
> +		pci_write_config_dword(dev, 0x64, 0xE3000000 | ITE887x_COM1);
> +
> +		/* COM2 */
> +		if (ite887xcomnum =3D=3D 2) {
> +			pci_read_config_dword(dev, 0x18, &ITE887x_COM2);
> +			ITE887x_COM2 &=3D 0x0000FF00;
> +			pci_write_config_dword(dev, 0x68, 0xE3000000 | ITE887x_COM2);
> +		} else
> +			ITE887x_COM2 =3D 0;
> +
> +		pci_write_config_dword(dev, 0x7C, (ITE887x_COM2 << 16) | =
(ITE887x_COM1));
> +	}
> +
> +	/* Parport */
> +	if (ite887xparportnum >=3D 1) {
> +		pci_read_config_dword(dev, 0x1c, &ite887x_lpt);
> +		ite887x_lpt &=3D 0x0000ff00;
> +		pci_read_config_dword(dev, 0x20, &ite887x_lpthi);
> +		ite887x_lpthi &=3D 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 * =
dev->irq));
> +	/* Add next interface */
> +	pci_set_drvdata(dev, priv);
> +	return 0;
> +
> +out_free_region:
> +	release_region(INTA_Addr[j], 0x8);
> +out_free:
> +	kfree(ite_priv);
> +	return result;
> +}
> +
>  static int __devinit get_pci_port (struct pci_dev *dev,
>  				   struct pci_board_no_ids *board,
>  				   struct serial_struct *req,
> @@ -276,6 +472,8 @@
>  	if (!base_baud)
>  		base_baud =3D BASE_BAUD;
>  	memset (&serial_req, 0, sizeof (serial_req));
> +	if (board->num_ports =3D=3D 0)
> +		success =3D 1;
> =20
>  	for (k =3D 0; k < board->num_ports; k++) {
>  		int line;
> @@ -309,6 +507,9 @@
>  	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
>  		return -ENODEV;
> =20
> +	if (cards[i].numports =3D=3D 0)
> +		success =3D 1;
> +
>  	for (n =3D 0; n < cards[i].numports; n++) {
>  		struct parport *port;
>  		int lo =3D cards[i].addr[n].lo;
> @@ -325,8 +526,7 @@
>  		/* 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 =3D parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
>  					      PARPORT_DMA_NONE, dev);
>  		if (port) {
> @@ -360,6 +560,8 @@
>  		return err;
>  	}
> =20
> +	priv->tbl_index =3D id->driver_data;
> +
>  	if (parport_register (dev, id)) {
>  		pci_set_drvdata (dev, NULL);
>  		kfree (priv);
> @@ -383,6 +585,10 @@
>  	struct parport_serial_private *priv =3D pci_get_drvdata (dev);
>  	int i;
> =20
> +	if (cards[priv->tbl_index].remove_hook)
> +		cards[priv->tbl_index].remove_hook(dev);
> +
> +
>  	// Serial ports
>  	for (i =3D 0; i < priv->num_ser; i++) {
>  		unregister_serial (priv->line[i]);



More information about the Linux-parport mailing list