[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