1fecae16eSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0+
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Support for common PCI multi-I/O cards (which is most of them)
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Multi-function PCI cards are supposed to present separate logical
81da177e4SLinus Torvalds  * devices on the bus.  A common thing to do seems to be to just use
91da177e4SLinus Torvalds  * one logical device with lots of base address registers for both
101da177e4SLinus Torvalds  * parallel ports and serial ports.  This driver is for dealing with
111da177e4SLinus Torvalds  * that.
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds 
1451dcdfecSAlan Cox #include <linux/interrupt.h>
154af5781aSAndy Shevchenko #include <linux/module.h>
161da177e4SLinus Torvalds #include <linux/parport.h>
171da177e4SLinus Torvalds #include <linux/parport_pc.h>
184af5781aSAndy Shevchenko #include <linux/pci.h>
194af5781aSAndy Shevchenko #include <linux/slab.h>
204af5781aSAndy Shevchenko #include <linux/types.h>
214af5781aSAndy Shevchenko 
221da177e4SLinus Torvalds #include <linux/8250_pci.h>
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds enum parport_pc_pci_cards {
251da177e4SLinus Torvalds 	titan_110l = 0,
261da177e4SLinus Torvalds 	titan_210l,
271da177e4SLinus Torvalds 	netmos_9xx5_combo,
2844e58a6aSMartin Schitter 	netmos_9855,
2950db9d8eSPhilippe De Muyter 	netmos_9855_2p,
307808edcdSNicos Gollan 	netmos_9900,
317808edcdSNicos Gollan 	netmos_9900_2p,
327808edcdSNicos Gollan 	netmos_99xx_1p,
331da177e4SLinus Torvalds 	avlab_1s1p,
341da177e4SLinus Torvalds 	avlab_1s2p,
351da177e4SLinus Torvalds 	avlab_2s1p,
361da177e4SLinus Torvalds 	siig_1s1p_10x,
371da177e4SLinus Torvalds 	siig_2s1p_10x,
381da177e4SLinus Torvalds 	siig_2p1s_20x,
391da177e4SLinus Torvalds 	siig_1s1p_20x,
401da177e4SLinus Torvalds 	siig_2s1p_20x,
41b9b24558SFrédéric Brière 	timedia_4078a,
42b9b24558SFrédéric Brière 	timedia_4079h,
43b9b24558SFrédéric Brière 	timedia_4085h,
44b9b24558SFrédéric Brière 	timedia_4088a,
45b9b24558SFrédéric Brière 	timedia_4089a,
46b9b24558SFrédéric Brière 	timedia_4095a,
47b9b24558SFrédéric Brière 	timedia_4096a,
48b9b24558SFrédéric Brière 	timedia_4078u,
49b9b24558SFrédéric Brière 	timedia_4079a,
50b9b24558SFrédéric Brière 	timedia_4085u,
51b9b24558SFrédéric Brière 	timedia_4079r,
52b9b24558SFrédéric Brière 	timedia_4079s,
53b9b24558SFrédéric Brière 	timedia_4079d,
54b9b24558SFrédéric Brière 	timedia_4079e,
55b9b24558SFrédéric Brière 	timedia_4079f,
56b9b24558SFrédéric Brière 	timedia_9079a,
57b9b24558SFrédéric Brière 	timedia_9079b,
58b9b24558SFrédéric Brière 	timedia_9079c,
59feb58142SEzequiel Garcia 	wch_ch353_1s1p,
606971c635SGuainluca Anzolin 	wch_ch353_2s1p,
61c9a104e2SColin Ian King 	wch_ch382_0s1p,
622fdd8c8cSSergej Pupykin 	wch_ch382_2s1p,
63ec8e3893SAndy Shevchenko 	brainboxes_5s1p,
64c6c94eecSKai-Heng Feng 	sunix_4008a,
65c6c94eecSKai-Heng Feng 	sunix_5069a,
66c6c94eecSKai-Heng Feng 	sunix_5079a,
67c6c94eecSKai-Heng Feng 	sunix_5099a,
6803427e7fSCameron Williams 	brainboxes_uc257,
6903427e7fSCameron Williams 	brainboxes_is300,
7003427e7fSCameron Williams 	brainboxes_uc414,
7103427e7fSCameron Williams 	brainboxes_px263,
721da177e4SLinus Torvalds };
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds /* each element directly indexed from enum list, above */
751da177e4SLinus Torvalds struct parport_pc_pci {
761da177e4SLinus Torvalds 	int numports;
771da177e4SLinus Torvalds 	struct { /* BAR (base address registers) numbers in the config
781da177e4SLinus Torvalds                     space header */
791da177e4SLinus Torvalds 		int lo;
801da177e4SLinus Torvalds 		int hi; /* -1 if not there, >6 for offset-method (max
811da177e4SLinus Torvalds                            BAR is 6) */
821da177e4SLinus Torvalds 	} addr[4];
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	/* If set, this is called immediately after pci_enable_device.
851da177e4SLinus Torvalds 	 * If it returns non-zero, no probing will take place and the
861da177e4SLinus Torvalds 	 * ports will not be used. */
871da177e4SLinus Torvalds 	int (*preinit_hook) (struct pci_dev *pdev, struct parport_pc_pci *card,
881da177e4SLinus Torvalds 				int autoirq, int autodma);
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	/* If set, this is called after probing for ports.  If 'failed'
911da177e4SLinus Torvalds 	 * is non-zero we couldn't use any of the ports. */
921da177e4SLinus Torvalds 	void (*postinit_hook) (struct pci_dev *pdev,
931da177e4SLinus Torvalds 				struct parport_pc_pci *card, int failed);
941da177e4SLinus Torvalds };
951da177e4SLinus Torvalds 
netmos_parallel_init(struct pci_dev * dev,struct parport_pc_pci * par,int autoirq,int autodma)96312facafSGreg Kroah-Hartman static int netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par,
97312facafSGreg Kroah-Hartman 				int autoirq, int autodma)
981da177e4SLinus Torvalds {
993abdbf90SJiri Slaby 	/* the rule described below doesn't hold for this device */
1003abdbf90SJiri Slaby 	if (dev->device == PCI_DEVICE_ID_NETMOS_9835 &&
1013abdbf90SJiri Slaby 			dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
1023abdbf90SJiri Slaby 			dev->subsystem_device == 0x0299)
1033abdbf90SJiri Slaby 		return -ENODEV;
1047808edcdSNicos Gollan 
1057808edcdSNicos Gollan 	if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
1067808edcdSNicos Gollan 		par->numports = 1;
1077808edcdSNicos Gollan 	} else {
1081da177e4SLinus Torvalds 		/*
1091da177e4SLinus Torvalds 		 * Netmos uses the subdevice ID to indicate the number of parallel
1101da177e4SLinus Torvalds 		 * and serial ports.  The form is 0x00PS, where <P> is the number of
1111da177e4SLinus Torvalds 		 * parallel ports and <S> is the number of serial ports.
1121da177e4SLinus Torvalds 		 */
11350db9d8eSPhilippe De Muyter 		par->numports = (dev->subsystem_device & 0xf0) >> 4;
11450db9d8eSPhilippe De Muyter 		if (par->numports > ARRAY_SIZE(par->addr))
11550db9d8eSPhilippe De Muyter 			par->numports = ARRAY_SIZE(par->addr);
1167808edcdSNicos Gollan 	}
1177808edcdSNicos Gollan 
1181da177e4SLinus Torvalds 	return 0;
1191da177e4SLinus Torvalds }
1201da177e4SLinus Torvalds 
121312facafSGreg Kroah-Hartman static struct parport_pc_pci cards[] = {
1221da177e4SLinus Torvalds 	/* titan_110l */		{ 1, { { 3, -1 }, } },
1231da177e4SLinus Torvalds 	/* titan_210l */		{ 1, { { 3, -1 }, } },
1241da177e4SLinus Torvalds 	/* netmos_9xx5_combo */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
12550db9d8eSPhilippe De Muyter 	/* netmos_9855 */		{ 1, { { 0, -1 }, }, netmos_parallel_init },
12650db9d8eSPhilippe De Muyter 	/* netmos_9855_2p */		{ 2, { { 0, -1 }, { 2, -1 }, } },
1277808edcdSNicos Gollan 	/* netmos_9900 */		{1, { { 3, 4 }, }, netmos_parallel_init },
1287808edcdSNicos Gollan 	/* netmos_9900_2p */		{2, { { 0, 1 }, { 3, 4 }, } },
1297808edcdSNicos Gollan 	/* netmos_99xx_1p */		{1, { { 0, 1 }, } },
1301da177e4SLinus Torvalds 	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
1311da177e4SLinus Torvalds 	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
1321da177e4SLinus Torvalds 	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
1331da177e4SLinus Torvalds 	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
1341da177e4SLinus Torvalds 	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
1351da177e4SLinus Torvalds 	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
1361da177e4SLinus Torvalds 	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
1371da177e4SLinus Torvalds 	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
138b9b24558SFrédéric Brière 	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
139b9b24558SFrédéric Brière 	/* timedia_4079h */             { 1, { { 2, 3 }, } },
140b9b24558SFrédéric Brière 	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
141b9b24558SFrédéric Brière 	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
142b9b24558SFrédéric Brière 	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
143b9b24558SFrédéric Brière 	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
144b9b24558SFrédéric Brière 	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
145b9b24558SFrédéric Brière 	/* timedia_4078u */             { 1, { { 2, -1 }, } },
146b9b24558SFrédéric Brière 	/* timedia_4079a */             { 1, { { 2, 3 }, } },
147b9b24558SFrédéric Brière 	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
148b9b24558SFrédéric Brière 	/* timedia_4079r */             { 1, { { 2, 3 }, } },
149b9b24558SFrédéric Brière 	/* timedia_4079s */             { 1, { { 2, 3 }, } },
150b9b24558SFrédéric Brière 	/* timedia_4079d */             { 1, { { 2, 3 }, } },
151b9b24558SFrédéric Brière 	/* timedia_4079e */             { 1, { { 2, 3 }, } },
152b9b24558SFrédéric Brière 	/* timedia_4079f */             { 1, { { 2, 3 }, } },
153b9b24558SFrédéric Brière 	/* timedia_9079a */             { 1, { { 2, 3 }, } },
154b9b24558SFrédéric Brière 	/* timedia_9079b */             { 1, { { 2, 3 }, } },
155b9b24558SFrédéric Brière 	/* timedia_9079c */             { 1, { { 2, 3 }, } },
156feb58142SEzequiel Garcia 	/* wch_ch353_1s1p*/             { 1, { { 1, -1}, } },
1576971c635SGuainluca Anzolin 	/* wch_ch353_2s1p*/             { 1, { { 2, -1}, } },
158c9a104e2SColin Ian King 	/* wch_ch382_0s1p*/		{ 1, { { 2, -1}, } },
1592fdd8c8cSSergej Pupykin 	/* wch_ch382_2s1p*/             { 1, { { 2, -1}, } },
160ec8e3893SAndy Shevchenko 	/* brainboxes_5s1p */           { 1, { { 3, -1 }, } },
161c6c94eecSKai-Heng Feng 	/* sunix_4008a */		{ 1, { { 1, 2 }, } },
162c6c94eecSKai-Heng Feng 	/* sunix_5069a */		{ 1, { { 1, 2 }, } },
163c6c94eecSKai-Heng Feng 	/* sunix_5079a */		{ 1, { { 1, 2 }, } },
164c6c94eecSKai-Heng Feng 	/* sunix_5099a */		{ 1, { { 1, 2 }, } },
16503427e7fSCameron Williams 	/* brainboxes_uc257 */	{ 1, { { 3, -1 }, } },
16603427e7fSCameron Williams 	/* brainboxes_is300 */	{ 1, { { 3, -1 }, } },
16703427e7fSCameron Williams 	/* brainboxes_uc414 */  { 1, { { 3, -1 }, } },
16803427e7fSCameron Williams 	/* brainboxes_px263 */	{ 1, { { 3, -1 }, } },
1691da177e4SLinus Torvalds };
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds static struct pci_device_id parport_serial_pci_tbl[] = {
1721da177e4SLinus Torvalds 	/* PCI cards */
1731da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
1741da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
1751da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
1761da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
1771da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
1781da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
1791da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9745,
1801da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
1811da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
1821da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
1831da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
1841da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
1851da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
18650db9d8eSPhilippe De Muyter 	  0x1000, 0x0020, 0, 0, netmos_9855_2p },
18750db9d8eSPhilippe De Muyter 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
18850db9d8eSPhilippe De Muyter 	  0x1000, 0x0022, 0, 0, netmos_9855_2p },
18950db9d8eSPhilippe De Muyter 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
19044e58a6aSMartin Schitter 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
1917808edcdSNicos Gollan 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
1927808edcdSNicos Gollan 	  0xA000, 0x3011, 0, 0, netmos_9900 },
1937808edcdSNicos Gollan 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
1947808edcdSNicos Gollan 	  0xA000, 0x3012, 0, 0, netmos_9900 },
1957808edcdSNicos Gollan 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
1967808edcdSNicos Gollan 	  0xA000, 0x3020, 0, 0, netmos_9900_2p },
1977808edcdSNicos Gollan 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
1987808edcdSNicos Gollan 	  0xA000, 0x2000, 0, 0, netmos_99xx_1p },
1991da177e4SLinus Torvalds 	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
20091bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
20191bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
20291bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2111,
20391bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
20491bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2112,
20591bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
20691bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2140,
20791bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
20891bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2141,
20991bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
21091bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2142,
21191bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
21291bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2160,
21391bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
21491bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2161,
21591bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
21691bca4b3SRussell King 	{ PCI_VENDOR_ID_AFAVLAB, 0x2162,
21791bca4b3SRussell King 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
2181da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
2191da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
2201da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
2211da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
2221da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
2231da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
2241da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
2251da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
2261da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
2271da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
2281da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
2291da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
2301da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
2311da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
2321da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
2331da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
2341da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
2351da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
2361da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
2371da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
2381da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
2391da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
2401da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
2411da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
2421da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
2431da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
2441da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
2451da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
2461da177e4SLinus Torvalds 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
2471da177e4SLinus Torvalds 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
248b9b24558SFrédéric Brière 	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
249b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
250b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
251b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
252b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
253b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
254b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
255b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
256b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
257b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
258b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
259b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
260b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
261b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
262b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
263b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
264b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
265b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
266b9b24558SFrédéric Brière 	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
267abd7bacaSStephen Chivers 
2686971c635SGuainluca Anzolin 	/* WCH CARDS */
269feb58142SEzequiel Garcia 	{ 0x4348, 0x5053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, wch_ch353_1s1p},
2706971c635SGuainluca Anzolin 	{ 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
271c9a104e2SColin Ian King 	{ 0x1c00, 0x3050, 0x1c00, 0x3050, 0, 0, wch_ch382_0s1p},
2722fdd8c8cSSergej Pupykin 	{ 0x1c00, 0x3250, 0x1c00, 0x3250, 0, 0, wch_ch382_2s1p},
273abd7bacaSStephen Chivers 
274ec8e3893SAndy Shevchenko 	/* BrainBoxes PX272/PX306 MIO card */
275ec8e3893SAndy Shevchenko 	{ PCI_VENDOR_ID_INTASHIELD, 0x4100,
276ec8e3893SAndy Shevchenko 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_5s1p },
277ec8e3893SAndy Shevchenko 
278c6c94eecSKai-Heng Feng 	/* Sunix boards */
279abd7bacaSStephen Chivers 	{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
280c6c94eecSKai-Heng Feng 	  0x0100, 0, 0, sunix_4008a },
281c6c94eecSKai-Heng Feng 	{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
282c6c94eecSKai-Heng Feng 	  0x0101, 0, 0, sunix_5069a },
283c6c94eecSKai-Heng Feng 	{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
284c6c94eecSKai-Heng Feng 	  0x0102, 0, 0, sunix_5079a },
285c6c94eecSKai-Heng Feng 	{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
286c6c94eecSKai-Heng Feng 	  0x0104, 0, 0, sunix_5099a },
287abd7bacaSStephen Chivers 
288*12786872SCameron Williams 	/* Brainboxes UC-203 */
289*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0bc1,
290*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
291*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0bc2,
292*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
293*12786872SCameron Williams 
294*12786872SCameron Williams 	/* Brainboxes UC-257 */
295*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0861,
296*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
297*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0862,
298*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
299*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0863,
300*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
301*12786872SCameron Williams 
302*12786872SCameron Williams 	/* Brainboxes UC-414 */
303*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0e61,
304*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc414 },
305*12786872SCameron Williams 
306*12786872SCameron Williams 	/* Brainboxes UC-475 */
307*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0981,
308*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
309*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0982,
310*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
311*12786872SCameron Williams 
312*12786872SCameron Williams 	/* Brainboxes IS-300/IS-500 */
313*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x0da0,
314*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_is300 },
315*12786872SCameron Williams 
316*12786872SCameron Williams 	/* Brainboxes PX-263/PX-295 */
317*12786872SCameron Williams 	{ PCI_VENDOR_ID_INTASHIELD, 0x402c,
318*12786872SCameron Williams 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_px263 },
319*12786872SCameron Williams 
3201da177e4SLinus Torvalds 	{ 0, } /* terminate list */
3211da177e4SLinus Torvalds };
3221da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds /*
32505caac58SRussell King  * This table describes the serial "geometry" of these boards.  Any
32605caac58SRussell King  * quirks for these can be found in drivers/serial/8250_pci.c
32705caac58SRussell King  *
32805caac58SRussell King  * Cards not tested are marked n/t
32905caac58SRussell King  * If you have one of these cards and it works for you, please tell me..
3301da177e4SLinus Torvalds  */
331312facafSGreg Kroah-Hartman static struct pciserial_board pci_parport_serial_boards[] = {
33205caac58SRussell King 	[titan_110l] = {
33305caac58SRussell King 		.flags		= FL_BASE1 | FL_BASE_BARS,
33405caac58SRussell King 		.num_ports	= 1,
33505caac58SRussell King 		.base_baud	= 921600,
33605caac58SRussell King 		.uart_offset	= 8,
33705caac58SRussell King 	},
33805caac58SRussell King 	[titan_210l] = {
33905caac58SRussell King 		.flags		= FL_BASE1 | FL_BASE_BARS,
34005caac58SRussell King 		.num_ports	= 2,
34105caac58SRussell King 		.base_baud	= 921600,
34205caac58SRussell King 		.uart_offset	= 8,
34305caac58SRussell King 	},
34405caac58SRussell King 	[netmos_9xx5_combo] = {
34505caac58SRussell King 		.flags		= FL_BASE0 | FL_BASE_BARS,
34605caac58SRussell King 		.num_ports	= 1,
34705caac58SRussell King 		.base_baud	= 115200,
34805caac58SRussell King 		.uart_offset	= 8,
34905caac58SRussell King 	},
35005caac58SRussell King 	[netmos_9855] = {
35150db9d8eSPhilippe De Muyter 		.flags		= FL_BASE2 | FL_BASE_BARS,
35250db9d8eSPhilippe De Muyter 		.num_ports	= 1,
35350db9d8eSPhilippe De Muyter 		.base_baud	= 115200,
35450db9d8eSPhilippe De Muyter 		.uart_offset	= 8,
35550db9d8eSPhilippe De Muyter 	},
35650db9d8eSPhilippe De Muyter 	[netmos_9855_2p] = {
357c01106e5SChristian Pellegrin 		.flags		= FL_BASE4 | FL_BASE_BARS,
35805caac58SRussell King 		.num_ports	= 1,
35905caac58SRussell King 		.base_baud	= 115200,
36005caac58SRussell King 		.uart_offset	= 8,
36105caac58SRussell King 	},
3627808edcdSNicos Gollan 	[netmos_9900] = { /* n/t */
3637808edcdSNicos Gollan 		.flags		= FL_BASE0 | FL_BASE_BARS,
3647808edcdSNicos Gollan 		.num_ports	= 1,
3657808edcdSNicos Gollan 		.base_baud	= 115200,
3667808edcdSNicos Gollan 		.uart_offset	= 8,
3677808edcdSNicos Gollan 	},
3687808edcdSNicos Gollan 	[netmos_9900_2p] = { /* parallel only */ /* n/t */
3697808edcdSNicos Gollan 		.flags		= FL_BASE0,
3707808edcdSNicos Gollan 		.num_ports	= 0,
3717808edcdSNicos Gollan 		.base_baud	= 115200,
3727808edcdSNicos Gollan 		.uart_offset	= 8,
3737808edcdSNicos Gollan 	},
3747808edcdSNicos Gollan 	[netmos_99xx_1p] = { /* parallel only */ /* n/t */
3757808edcdSNicos Gollan 		.flags		= FL_BASE0,
3767808edcdSNicos Gollan 		.num_ports	= 0,
3777808edcdSNicos Gollan 		.base_baud	= 115200,
3787808edcdSNicos Gollan 		.uart_offset	= 8,
3797808edcdSNicos Gollan 	},
38005caac58SRussell King 	[avlab_1s1p] = { /* n/t */
38105caac58SRussell King 		.flags		= FL_BASE0 | FL_BASE_BARS,
38205caac58SRussell King 		.num_ports	= 1,
38305caac58SRussell King 		.base_baud	= 115200,
38405caac58SRussell King 		.uart_offset	= 8,
38505caac58SRussell King 	},
38605caac58SRussell King 	[avlab_1s2p] = { /* n/t */
38705caac58SRussell King 		.flags		= FL_BASE0 | FL_BASE_BARS,
38805caac58SRussell King 		.num_ports	= 1,
38905caac58SRussell King 		.base_baud	= 115200,
39005caac58SRussell King 		.uart_offset	= 8,
39105caac58SRussell King 	},
39205caac58SRussell King 	[avlab_2s1p] = { /* n/t */
39305caac58SRussell King 		.flags		= FL_BASE0 | FL_BASE_BARS,
39405caac58SRussell King 		.num_ports	= 2,
39505caac58SRussell King 		.base_baud	= 115200,
39605caac58SRussell King 		.uart_offset	= 8,
39705caac58SRussell King 	},
39805caac58SRussell King 	[siig_1s1p_10x] = {
39905caac58SRussell King 		.flags		= FL_BASE2,
40005caac58SRussell King 		.num_ports	= 1,
40105caac58SRussell King 		.base_baud	= 460800,
40205caac58SRussell King 		.uart_offset	= 8,
40305caac58SRussell King 	},
40405caac58SRussell King 	[siig_2s1p_10x] = {
40505caac58SRussell King 		.flags		= FL_BASE2,
40605caac58SRussell King 		.num_ports	= 1,
40705caac58SRussell King 		.base_baud	= 921600,
40805caac58SRussell King 		.uart_offset	= 8,
40905caac58SRussell King 	},
41005caac58SRussell King 	[siig_2p1s_20x] = {
41105caac58SRussell King 		.flags		= FL_BASE0,
41205caac58SRussell King 		.num_ports	= 1,
41305caac58SRussell King 		.base_baud	= 921600,
41405caac58SRussell King 		.uart_offset	= 8,
41505caac58SRussell King 	},
41605caac58SRussell King 	[siig_1s1p_20x] = {
41705caac58SRussell King 		.flags		= FL_BASE0,
41805caac58SRussell King 		.num_ports	= 1,
41905caac58SRussell King 		.base_baud	= 921600,
42005caac58SRussell King 		.uart_offset	= 8,
42105caac58SRussell King 	},
42205caac58SRussell King 	[siig_2s1p_20x] = {
42305caac58SRussell King 		.flags		= FL_BASE0,
42405caac58SRussell King 		.num_ports	= 1,
42505caac58SRussell King 		.base_baud	= 921600,
42605caac58SRussell King 		.uart_offset	= 8,
42705caac58SRussell King 	},
428b9b24558SFrédéric Brière 	[timedia_4078a] = {
429b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
430b9b24558SFrédéric Brière 		.num_ports	= 1,
431b9b24558SFrédéric Brière 		.base_baud	= 921600,
432b9b24558SFrédéric Brière 		.uart_offset	= 8,
433b9b24558SFrédéric Brière 	},
434b9b24558SFrédéric Brière 	[timedia_4079h] = {
435b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
436b9b24558SFrédéric Brière 		.num_ports	= 1,
437b9b24558SFrédéric Brière 		.base_baud	= 921600,
438b9b24558SFrédéric Brière 		.uart_offset	= 8,
439b9b24558SFrédéric Brière 	},
440b9b24558SFrédéric Brière 	[timedia_4085h] = {
441b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
442b9b24558SFrédéric Brière 		.num_ports	= 1,
443b9b24558SFrédéric Brière 		.base_baud	= 921600,
444b9b24558SFrédéric Brière 		.uart_offset	= 8,
445b9b24558SFrédéric Brière 	},
446b9b24558SFrédéric Brière 	[timedia_4088a] = {
447b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
448b9b24558SFrédéric Brière 		.num_ports	= 1,
449b9b24558SFrédéric Brière 		.base_baud	= 921600,
450b9b24558SFrédéric Brière 		.uart_offset	= 8,
451b9b24558SFrédéric Brière 	},
452b9b24558SFrédéric Brière 	[timedia_4089a] = {
453b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
454b9b24558SFrédéric Brière 		.num_ports	= 1,
455b9b24558SFrédéric Brière 		.base_baud	= 921600,
456b9b24558SFrédéric Brière 		.uart_offset	= 8,
457b9b24558SFrédéric Brière 	},
458b9b24558SFrédéric Brière 	[timedia_4095a] = {
459b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
460b9b24558SFrédéric Brière 		.num_ports	= 1,
461b9b24558SFrédéric Brière 		.base_baud	= 921600,
462b9b24558SFrédéric Brière 		.uart_offset	= 8,
463b9b24558SFrédéric Brière 	},
464b9b24558SFrédéric Brière 	[timedia_4096a] = {
465b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
466b9b24558SFrédéric Brière 		.num_ports	= 1,
467b9b24558SFrédéric Brière 		.base_baud	= 921600,
468b9b24558SFrédéric Brière 		.uart_offset	= 8,
469b9b24558SFrédéric Brière 	},
470b9b24558SFrédéric Brière 	[timedia_4078u] = {
471b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
472b9b24558SFrédéric Brière 		.num_ports	= 1,
473b9b24558SFrédéric Brière 		.base_baud	= 921600,
474b9b24558SFrédéric Brière 		.uart_offset	= 8,
475b9b24558SFrédéric Brière 	},
476b9b24558SFrédéric Brière 	[timedia_4079a] = {
477b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
478b9b24558SFrédéric Brière 		.num_ports	= 1,
479b9b24558SFrédéric Brière 		.base_baud	= 921600,
480b9b24558SFrédéric Brière 		.uart_offset	= 8,
481b9b24558SFrédéric Brière 	},
482b9b24558SFrédéric Brière 	[timedia_4085u] = {
483b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
484b9b24558SFrédéric Brière 		.num_ports	= 1,
485b9b24558SFrédéric Brière 		.base_baud	= 921600,
486b9b24558SFrédéric Brière 		.uart_offset	= 8,
487b9b24558SFrédéric Brière 	},
488b9b24558SFrédéric Brière 	[timedia_4079r] = {
489b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
490b9b24558SFrédéric Brière 		.num_ports	= 1,
491b9b24558SFrédéric Brière 		.base_baud	= 921600,
492b9b24558SFrédéric Brière 		.uart_offset	= 8,
493b9b24558SFrédéric Brière 	},
494b9b24558SFrédéric Brière 	[timedia_4079s] = {
495b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
496b9b24558SFrédéric Brière 		.num_ports	= 1,
497b9b24558SFrédéric Brière 		.base_baud	= 921600,
498b9b24558SFrédéric Brière 		.uart_offset	= 8,
499b9b24558SFrédéric Brière 	},
500b9b24558SFrédéric Brière 	[timedia_4079d] = {
501b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
502b9b24558SFrédéric Brière 		.num_ports	= 1,
503b9b24558SFrédéric Brière 		.base_baud	= 921600,
504b9b24558SFrédéric Brière 		.uart_offset	= 8,
505b9b24558SFrédéric Brière 	},
506b9b24558SFrédéric Brière 	[timedia_4079e] = {
507b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
508b9b24558SFrédéric Brière 		.num_ports	= 1,
509b9b24558SFrédéric Brière 		.base_baud	= 921600,
510b9b24558SFrédéric Brière 		.uart_offset	= 8,
511b9b24558SFrédéric Brière 	},
512b9b24558SFrédéric Brière 	[timedia_4079f] = {
513b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
514b9b24558SFrédéric Brière 		.num_ports	= 1,
515b9b24558SFrédéric Brière 		.base_baud	= 921600,
516b9b24558SFrédéric Brière 		.uart_offset	= 8,
517b9b24558SFrédéric Brière 	},
518b9b24558SFrédéric Brière 	[timedia_9079a] = {
519b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
520b9b24558SFrédéric Brière 		.num_ports	= 1,
521b9b24558SFrédéric Brière 		.base_baud	= 921600,
522b9b24558SFrédéric Brière 		.uart_offset	= 8,
523b9b24558SFrédéric Brière 	},
524b9b24558SFrédéric Brière 	[timedia_9079b] = {
525b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
526b9b24558SFrédéric Brière 		.num_ports	= 1,
527b9b24558SFrédéric Brière 		.base_baud	= 921600,
528b9b24558SFrédéric Brière 		.uart_offset	= 8,
529b9b24558SFrédéric Brière 	},
530b9b24558SFrédéric Brière 	[timedia_9079c] = {
531b9b24558SFrédéric Brière 		.flags		= FL_BASE0|FL_BASE_BARS,
532b9b24558SFrédéric Brière 		.num_ports	= 1,
533b9b24558SFrédéric Brière 		.base_baud	= 921600,
534b9b24558SFrédéric Brière 		.uart_offset	= 8,
535b9b24558SFrédéric Brière 	},
536feb58142SEzequiel Garcia 	[wch_ch353_1s1p] = {
537feb58142SEzequiel Garcia 		.flags          = FL_BASE0|FL_BASE_BARS,
538feb58142SEzequiel Garcia 		.num_ports      = 1,
539feb58142SEzequiel Garcia 		.base_baud      = 115200,
540feb58142SEzequiel Garcia 		.uart_offset    = 8,
541feb58142SEzequiel Garcia 	},
5426971c635SGuainluca Anzolin 	[wch_ch353_2s1p] = {
5436971c635SGuainluca Anzolin 		.flags          = FL_BASE0|FL_BASE_BARS,
5446971c635SGuainluca Anzolin 		.num_ports      = 2,
5456971c635SGuainluca Anzolin 		.base_baud      = 115200,
5466971c635SGuainluca Anzolin 		.uart_offset    = 8,
5476971c635SGuainluca Anzolin 	},
548c9a104e2SColin Ian King 	[wch_ch382_0s1p] = {
549c9a104e2SColin Ian King 		.flags          = FL_BASE0,
550c9a104e2SColin Ian King 		.num_ports      = 0,
551c9a104e2SColin Ian King 		.base_baud      = 115200,
552c9a104e2SColin Ian King 		.uart_offset    = 8,
553c9a104e2SColin Ian King 	},
5542fdd8c8cSSergej Pupykin 	[wch_ch382_2s1p] = {
5552fdd8c8cSSergej Pupykin 		.flags          = FL_BASE0,
5562fdd8c8cSSergej Pupykin 		.num_ports      = 2,
5572fdd8c8cSSergej Pupykin 		.base_baud      = 115200,
5582fdd8c8cSSergej Pupykin 		.uart_offset    = 8,
5592fdd8c8cSSergej Pupykin 		.first_offset   = 0xC0,
5602fdd8c8cSSergej Pupykin 	},
561ec8e3893SAndy Shevchenko 	[brainboxes_5s1p] = {
562ec8e3893SAndy Shevchenko 		.flags		= FL_BASE2,
563ec8e3893SAndy Shevchenko 		.num_ports	= 5,
564ec8e3893SAndy Shevchenko 		.base_baud	= 921600,
565ec8e3893SAndy Shevchenko 		.uart_offset	= 8,
566ec8e3893SAndy Shevchenko 	},
567c6c94eecSKai-Heng Feng 	[sunix_4008a] = {
568c6c94eecSKai-Heng Feng 		.num_ports	= 0,
569c6c94eecSKai-Heng Feng 	},
570c6c94eecSKai-Heng Feng 	[sunix_5069a] = {
571c6c94eecSKai-Heng Feng 		.num_ports	= 1,
572c6c94eecSKai-Heng Feng 		.base_baud      = 921600,
573c6c94eecSKai-Heng Feng 		.uart_offset	= 0x8,
574c6c94eecSKai-Heng Feng 	},
575c6c94eecSKai-Heng Feng 	[sunix_5079a] = {
576abd7bacaSStephen Chivers 		.num_ports	= 2,
577abd7bacaSStephen Chivers 		.base_baud      = 921600,
578c6c94eecSKai-Heng Feng 		.uart_offset	= 0x8,
579c6c94eecSKai-Heng Feng 	},
580c6c94eecSKai-Heng Feng 	[sunix_5099a] = {
581c6c94eecSKai-Heng Feng 		.num_ports	= 4,
582c6c94eecSKai-Heng Feng 		.base_baud      = 921600,
583c6c94eecSKai-Heng Feng 		.uart_offset	= 0x8,
584abd7bacaSStephen Chivers 	},
585*12786872SCameron Williams 	[brainboxes_uc257] = {
586*12786872SCameron Williams 		.flags		= FL_BASE2,
587*12786872SCameron Williams 		.num_ports	= 2,
588*12786872SCameron Williams 		.base_baud	= 115200,
589*12786872SCameron Williams 		.uart_offset	= 8,
590*12786872SCameron Williams 	},
591*12786872SCameron Williams 	[brainboxes_is300] = {
592*12786872SCameron Williams 		.flags		= FL_BASE2,
593*12786872SCameron Williams 		.num_ports	= 1,
594*12786872SCameron Williams 		.base_baud	= 115200,
595*12786872SCameron Williams 		.uart_offset	= 8,
596*12786872SCameron Williams 	},
597*12786872SCameron Williams 	[brainboxes_uc414] = {
598*12786872SCameron Williams 		.flags		= FL_BASE2,
599*12786872SCameron Williams 		.num_ports	= 4,
600*12786872SCameron Williams 		.base_baud	= 115200,
601*12786872SCameron Williams 		.uart_offset	= 8,
602*12786872SCameron Williams 	},
603*12786872SCameron Williams 	[brainboxes_px263] = {
604*12786872SCameron Williams 		.flags		= FL_BASE2,
605*12786872SCameron Williams 		.num_ports	= 4,
606*12786872SCameron Williams 		.base_baud	= 921600,
607*12786872SCameron Williams 		.uart_offset	= 8,
608*12786872SCameron Williams 	},
6091da177e4SLinus Torvalds };
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds struct parport_serial_private {
61205caac58SRussell King 	struct serial_private	*serial;
6131da177e4SLinus Torvalds 	int num_par;
6141da177e4SLinus Torvalds 	struct parport *port[PARPORT_MAX];
6151da177e4SLinus Torvalds 	struct parport_pc_pci par;
6161da177e4SLinus Torvalds };
6171da177e4SLinus Torvalds 
6181da177e4SLinus Torvalds /* Register the serial port(s) of a PCI card. */
serial_register(struct pci_dev * dev,const struct pci_device_id * id)619312facafSGreg Kroah-Hartman static int serial_register(struct pci_dev *dev, const struct pci_device_id *id)
6201da177e4SLinus Torvalds {
6211da177e4SLinus Torvalds 	struct parport_serial_private *priv = pci_get_drvdata (dev);
62205caac58SRussell King 	struct pciserial_board *board;
62305caac58SRussell King 	struct serial_private *serial;
6241da177e4SLinus Torvalds 
62505caac58SRussell King 	board = &pci_parport_serial_boards[id->driver_data];
6267808edcdSNicos Gollan 	if (board->num_ports == 0)
6277808edcdSNicos Gollan 		return 0;
6287808edcdSNicos Gollan 
62905caac58SRussell King 	serial = pciserial_init_ports(dev, board);
63005caac58SRussell King 	if (IS_ERR(serial))
63105caac58SRussell King 		return PTR_ERR(serial);
6321da177e4SLinus Torvalds 
63305caac58SRussell King 	priv->serial = serial;
63405caac58SRussell King 	return 0;
6351da177e4SLinus Torvalds }
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds /* Register the parallel port(s) of a PCI card. */
parport_register(struct pci_dev * dev,const struct pci_device_id * id)638312facafSGreg Kroah-Hartman static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
6391da177e4SLinus Torvalds {
6401da177e4SLinus Torvalds 	struct parport_pc_pci *card;
6411da177e4SLinus Torvalds 	struct parport_serial_private *priv = pci_get_drvdata (dev);
6427a171cdcSRussell King 	int n, success = 0;
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds 	priv->par = cards[id->driver_data];
6451da177e4SLinus Torvalds 	card = &priv->par;
6461da177e4SLinus Torvalds 	if (card->preinit_hook &&
6471da177e4SLinus Torvalds 	    card->preinit_hook (dev, card, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
6481da177e4SLinus Torvalds 		return -ENODEV;
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	for (n = 0; n < card->numports; n++) {
6511da177e4SLinus Torvalds 		struct parport *port;
6521da177e4SLinus Torvalds 		int lo = card->addr[n].lo;
6531da177e4SLinus Torvalds 		int hi = card->addr[n].hi;
6541da177e4SLinus Torvalds 		unsigned long io_lo, io_hi;
65551dcdfecSAlan Cox 		int irq;
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 		if (priv->num_par == ARRAY_SIZE (priv->port)) {
65882dfabf1SAndy Shevchenko 			dev_warn(&dev->dev,
65982dfabf1SAndy Shevchenko 				 "only %zu parallel ports supported (%d reported)\n",
6601da177e4SLinus Torvalds 				 ARRAY_SIZE(priv->port), card->numports);
6611da177e4SLinus Torvalds 			break;
6621da177e4SLinus Torvalds 		}
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds 		io_lo = pci_resource_start (dev, lo);
6651da177e4SLinus Torvalds 		io_hi = 0;
6661da177e4SLinus Torvalds 		if ((hi >= 0) && (hi <= 6))
6671da177e4SLinus Torvalds 			io_hi = pci_resource_start (dev, hi);
6681da177e4SLinus Torvalds 		else if (hi > 6)
6691da177e4SLinus Torvalds 			io_lo += hi; /* Reinterpret the meaning of
6701da177e4SLinus Torvalds                                         "hi" as an offset (see SYBA
6711da177e4SLinus Torvalds                                         def.) */
6721da177e4SLinus Torvalds 		/* TODO: test if sharing interrupts works */
673fa11c81cSAndy Shevchenko 		irq = pci_irq_vector(dev, 0);
674fa11c81cSAndy Shevchenko 		if (irq < 0)
675fa11c81cSAndy Shevchenko 			return irq;
67609b18f2fSAndy Shevchenko 		if (irq == 0)
67709b18f2fSAndy Shevchenko 			irq = PARPORT_IRQ_NONE;
67809b18f2fSAndy Shevchenko 		if (irq == PARPORT_IRQ_NONE) {
67951dcdfecSAlan Cox 			dev_dbg(&dev->dev,
68051dcdfecSAlan Cox 				"PCI parallel port detected: I/O at %#lx(%#lx)\n",
68151dcdfecSAlan Cox 				io_lo, io_hi);
68251dcdfecSAlan Cox 		} else {
68351dcdfecSAlan Cox 			dev_dbg(&dev->dev,
68451dcdfecSAlan Cox 				"PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
68551dcdfecSAlan Cox 				io_lo, io_hi, irq);
68651dcdfecSAlan Cox 		}
68751dcdfecSAlan Cox 		port = parport_pc_probe_port (io_lo, io_hi, irq,
68851dcdfecSAlan Cox 			      PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED);
6891da177e4SLinus Torvalds 		if (port) {
6901da177e4SLinus Torvalds 			priv->port[priv->num_par++] = port;
6911da177e4SLinus Torvalds 			success = 1;
6921da177e4SLinus Torvalds 		}
6931da177e4SLinus Torvalds 	}
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds 	if (card->postinit_hook)
6961da177e4SLinus Torvalds 		card->postinit_hook (dev, card, !success);
6971da177e4SLinus Torvalds 
6987a171cdcSRussell King 	return 0;
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds 
parport_serial_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)701312facafSGreg Kroah-Hartman static int parport_serial_pci_probe(struct pci_dev *dev,
7021da177e4SLinus Torvalds 				    const struct pci_device_id *id)
7031da177e4SLinus Torvalds {
7041da177e4SLinus Torvalds 	struct parport_serial_private *priv;
7051da177e4SLinus Torvalds 	int err;
7061da177e4SLinus Torvalds 
707ad8ce834SAndy Shevchenko 	priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
7081da177e4SLinus Torvalds 	if (!priv)
7091da177e4SLinus Torvalds 		return -ENOMEM;
710ad8ce834SAndy Shevchenko 
7111da177e4SLinus Torvalds 	pci_set_drvdata (dev, priv);
7121da177e4SLinus Torvalds 
713ad8ce834SAndy Shevchenko 	err = pcim_enable_device(dev);
714ad8ce834SAndy Shevchenko 	if (err)
7151da177e4SLinus Torvalds 		return err;
7161da177e4SLinus Torvalds 
71796edf537SAndy Shevchenko 	err = parport_register(dev, id);
71896edf537SAndy Shevchenko 	if (err)
71996edf537SAndy Shevchenko 		return err;
7201da177e4SLinus Torvalds 
72196edf537SAndy Shevchenko 	err = serial_register(dev, id);
72296edf537SAndy Shevchenko 	if (err) {
7231da177e4SLinus Torvalds 		int i;
7241da177e4SLinus Torvalds 		for (i = 0; i < priv->num_par; i++)
7251da177e4SLinus Torvalds 			parport_pc_unregister_port (priv->port[i]);
72696edf537SAndy Shevchenko 		return err;
7271da177e4SLinus Torvalds 	}
7281da177e4SLinus Torvalds 
7291da177e4SLinus Torvalds 	return 0;
7301da177e4SLinus Torvalds }
7311da177e4SLinus Torvalds 
parport_serial_pci_remove(struct pci_dev * dev)732312facafSGreg Kroah-Hartman static void parport_serial_pci_remove(struct pci_dev *dev)
7331da177e4SLinus Torvalds {
7341da177e4SLinus Torvalds 	struct parport_serial_private *priv = pci_get_drvdata (dev);
7351da177e4SLinus Torvalds 	int i;
7361da177e4SLinus Torvalds 
73705caac58SRussell King 	// Serial ports
73805caac58SRussell King 	if (priv->serial)
73905caac58SRussell King 		pciserial_remove_ports(priv->serial);
74005caac58SRussell King 
7411da177e4SLinus Torvalds 	// Parallel ports
7421da177e4SLinus Torvalds 	for (i = 0; i < priv->num_par; i++)
7431da177e4SLinus Torvalds 		parport_pc_unregister_port (priv->port[i]);
7441da177e4SLinus Torvalds 
7451da177e4SLinus Torvalds 	return;
7461da177e4SLinus Torvalds }
7471da177e4SLinus Torvalds 
parport_serial_pci_suspend(struct device * dev)7481089c911SAndy Shevchenko static int __maybe_unused parport_serial_pci_suspend(struct device *dev)
74905caac58SRussell King {
7509e18a80cSChuhong Yuan 	struct parport_serial_private *priv = dev_get_drvdata(dev);
75105caac58SRussell King 
75205caac58SRussell King 	if (priv->serial)
75305caac58SRussell King 		pciserial_suspend_ports(priv->serial);
75405caac58SRussell King 
75505caac58SRussell King 	/* FIXME: What about parport? */
75605caac58SRussell King 	return 0;
75705caac58SRussell King }
75805caac58SRussell King 
parport_serial_pci_resume(struct device * dev)7591089c911SAndy Shevchenko static int __maybe_unused parport_serial_pci_resume(struct device *dev)
76005caac58SRussell King {
7619e18a80cSChuhong Yuan 	struct parport_serial_private *priv = dev_get_drvdata(dev);
76205caac58SRussell King 
76305caac58SRussell King 	if (priv->serial)
76405caac58SRussell King 		pciserial_resume_ports(priv->serial);
76505caac58SRussell King 
76605caac58SRussell King 	/* FIXME: What about parport? */
76705caac58SRussell King 	return 0;
76805caac58SRussell King }
7691089c911SAndy Shevchenko 
7701089c911SAndy Shevchenko static SIMPLE_DEV_PM_OPS(parport_serial_pm_ops,
7711089c911SAndy Shevchenko 			 parport_serial_pci_suspend, parport_serial_pci_resume);
77205caac58SRussell King 
7731da177e4SLinus Torvalds static struct pci_driver parport_serial_pci_driver = {
7741da177e4SLinus Torvalds 	.name		= "parport_serial",
7751da177e4SLinus Torvalds 	.id_table	= parport_serial_pci_tbl,
7761da177e4SLinus Torvalds 	.probe		= parport_serial_pci_probe,
777312facafSGreg Kroah-Hartman 	.remove		= parport_serial_pci_remove,
7781089c911SAndy Shevchenko 	.driver         = {
7791089c911SAndy Shevchenko 		.pm     = &parport_serial_pm_ops,
7801089c911SAndy Shevchenko 	},
7811da177e4SLinus Torvalds };
782b0b0a643SAndy Shevchenko module_pci_driver(parport_serial_pci_driver);
7831da177e4SLinus Torvalds 
7841da177e4SLinus Torvalds MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
7851da177e4SLinus Torvalds MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
7861da177e4SLinus Torvalds MODULE_LICENSE("GPL");
787