Blame view

drivers/parport/parport_serial.c 19 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /*
   * Support for common PCI multi-I/O cards (which is most of them)
   *
   * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   *
   *
   * Multi-function PCI cards are supposed to present separate logical
   * devices on the bus.  A common thing to do seems to be to just use
   * one logical device with lots of base address registers for both
   * parallel ports and serial ports.  This driver is for dealing with
   * that.
   *
   */
  
  #include <linux/types.h>
  #include <linux/module.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  #include <linux/pci.h>
51dcdfec6   Alan Cox   parport: Use the ...
25
  #include <linux/interrupt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  #include <linux/parport.h>
  #include <linux/parport_pc.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/8250_pci.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  enum parport_pc_pci_cards {
  	titan_110l = 0,
  	titan_210l,
  	netmos_9xx5_combo,
44e58a6a0   Martin Schitter   [PATCH] parport: ...
33
  	netmos_9855,
50db9d8e4   Philippe De Muyter   parport: netmos 9...
34
  	netmos_9855_2p,
7808edcd3   Nicos Gollan   Basic support for...
35
36
37
  	netmos_9900,
  	netmos_9900_2p,
  	netmos_99xx_1p,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  	avlab_1s1p,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  	avlab_1s2p,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	avlab_2s1p,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
  	siig_1s1p_10x,
  	siig_2s1p_10x,
  	siig_2p1s_20x,
  	siig_1s1p_20x,
  	siig_2s1p_20x,
b9b24558f   Frédéric Brière   parport/serial: a...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  	timedia_4078a,
  	timedia_4079h,
  	timedia_4085h,
  	timedia_4088a,
  	timedia_4089a,
  	timedia_4095a,
  	timedia_4096a,
  	timedia_4078u,
  	timedia_4079a,
  	timedia_4085u,
  	timedia_4079r,
  	timedia_4079s,
  	timedia_4079d,
  	timedia_4079e,
  	timedia_4079f,
  	timedia_9079a,
  	timedia_9079b,
  	timedia_9079c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  };
  
  /* each element directly indexed from enum list, above */
  struct parport_pc_pci {
  	int numports;
  	struct { /* BAR (base address registers) numbers in the config
                      space header */
  		int lo;
  		int hi; /* -1 if not there, >6 for offset-method (max
                             BAR is 6) */
  	} addr[4];
  
  	/* If set, this is called immediately after pci_enable_device.
  	 * If it returns non-zero, no probing will take place and the
  	 * ports will not be used. */
  	int (*preinit_hook) (struct pci_dev *pdev, struct parport_pc_pci *card,
  				int autoirq, int autodma);
  
  	/* If set, this is called after probing for ports.  If 'failed'
  	 * is non-zero we couldn't use any of the ports. */
  	void (*postinit_hook) (struct pci_dev *pdev,
  				struct parport_pc_pci *card, int failed);
  };
50db9d8e4   Philippe De Muyter   parport: netmos 9...
87
  static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par, int autoirq, int autodma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  {
3abdbf90a   Jiri Slaby   parport: parport_...
89
90
91
92
93
  	/* the rule described below doesn't hold for this device */
  	if (dev->device == PCI_DEVICE_ID_NETMOS_9835 &&
  			dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
  			dev->subsystem_device == 0x0299)
  		return -ENODEV;
7808edcd3   Nicos Gollan   Basic support for...
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  	if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
  		par->numports = 1;
  	} else {
  		/*
  		 * Netmos uses the subdevice ID to indicate the number of parallel
  		 * and serial ports.  The form is 0x00PS, where <P> is the number of
  		 * parallel ports and <S> is the number of serial ports.
  		 */
  		par->numports = (dev->subsystem_device & 0xf0) >> 4;
  		if (par->numports > ARRAY_SIZE(par->addr))
  			par->numports = ARRAY_SIZE(par->addr);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
  	return 0;
  }
  
  static struct parport_pc_pci cards[] __devinitdata = {
  	/* titan_110l */		{ 1, { { 3, -1 }, } },
  	/* titan_210l */		{ 1, { { 3, -1 }, } },
  	/* netmos_9xx5_combo */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
50db9d8e4   Philippe De Muyter   parport: netmos 9...
114
115
  	/* netmos_9855 */		{ 1, { { 0, -1 }, }, netmos_parallel_init },
  	/* netmos_9855_2p */		{ 2, { { 0, -1 }, { 2, -1 }, } },
7808edcd3   Nicos Gollan   Basic support for...
116
117
118
  	/* netmos_9900 */		{1, { { 3, 4 }, }, netmos_parallel_init },
  	/* netmos_9900_2p */		{2, { { 0, 1 }, { 3, 4 }, } },
  	/* netmos_99xx_1p */		{1, { { 0, 1 }, } },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
  	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
  	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
  	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
  	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
  	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
b9b24558f   Frédéric Brière   parport/serial: a...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
  	/* timedia_4079h */             { 1, { { 2, 3 }, } },
  	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
  	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
  	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
  	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
  	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
  	/* timedia_4078u */             { 1, { { 2, -1 }, } },
  	/* timedia_4079a */             { 1, { { 2, 3 }, } },
  	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
  	/* timedia_4079r */             { 1, { { 2, 3 }, } },
  	/* timedia_4079s */             { 1, { { 2, 3 }, } },
  	/* timedia_4079d */             { 1, { { 2, 3 }, } },
  	/* timedia_4079e */             { 1, { { 2, 3 }, } },
  	/* timedia_4079f */             { 1, { { 2, 3 }, } },
  	/* timedia_9079a */             { 1, { { 2, 3 }, } },
  	/* timedia_9079b */             { 1, { { 2, 3 }, } },
  	/* timedia_9079c */             { 1, { { 2, 3 }, } },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
152
153
154
155
156
157
  };
  
  static struct pci_device_id parport_serial_pci_tbl[] = {
  	/* PCI cards */
  	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
  	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9745,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
50db9d8e4   Philippe De Muyter   parport: netmos 9...
162
163
164
165
  	  0x1000, 0x0020, 0, 0, netmos_9855_2p },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
  	  0x1000, 0x0022, 0, 0, netmos_9855_2p },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
44e58a6a0   Martin Schitter   [PATCH] parport: ...
166
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
7808edcd3   Nicos Gollan   Basic support for...
167
168
169
170
171
172
173
174
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
  	  0xA000, 0x3011, 0, 0, netmos_9900 },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
  	  0xA000, 0x3012, 0, 0, netmos_9900 },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
  	  0xA000, 0x3020, 0, 0, netmos_9900_2p },
  	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
  	  0xA000, 0x2000, 0, 0, netmos_99xx_1p },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
91bca4b3e   Russell King   [SERIAL] Merge av...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2111,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2112,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2140,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2141,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2142,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2160,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2161,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
  	{ PCI_VENDOR_ID_AFAVLAB, 0x2162,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
  	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
  	  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 },
b9b24558f   Frédéric Brière   parport/serial: a...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
  	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
  	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
  	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
  	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
  	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
  	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
  	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
  	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
  	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
  	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
  	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
  	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
  	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
  	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
  	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
  	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
  	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
  	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
  
  	{ 0, } /* terminate list */
  };
  MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
05caac585   Russell King   [SERIAL] Convert ...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  /*
   * This table describes the serial "geometry" of these boards.  Any
   * quirks for these can be found in drivers/serial/8250_pci.c
   *
   * Cards not tested are marked n/t
   * If you have one of these cards and it works for you, please tell me..
   */
  static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
  	[titan_110l] = {
  		.flags		= FL_BASE1 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[titan_210l] = {
  		.flags		= FL_BASE1 | FL_BASE_BARS,
  		.num_ports	= 2,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[netmos_9xx5_combo] = {
  		.flags		= FL_BASE0 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
  	[netmos_9855] = {
50db9d8e4   Philippe De Muyter   parport: netmos 9...
274
275
276
277
278
279
  		.flags		= FL_BASE2 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
  	[netmos_9855_2p] = {
c01106e57   Christian Pellegrin   parport_serial: n...
280
  		.flags		= FL_BASE4 | FL_BASE_BARS,
05caac585   Russell King   [SERIAL] Convert ...
281
282
283
284
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
7808edcd3   Nicos Gollan   Basic support for...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  	[netmos_9900] = { /* n/t */
  		.flags		= FL_BASE0 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
  	[netmos_9900_2p] = { /* parallel only */ /* n/t */
  		.flags		= FL_BASE0,
  		.num_ports	= 0,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
  	[netmos_99xx_1p] = { /* parallel only */ /* n/t */
  		.flags		= FL_BASE0,
  		.num_ports	= 0,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
05caac585   Russell King   [SERIAL] Convert ...
303
304
305
306
307
308
  	[avlab_1s1p] = { /* n/t */
  		.flags		= FL_BASE0 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
05caac585   Russell King   [SERIAL] Convert ...
309
310
311
312
313
314
  	[avlab_1s2p] = { /* n/t */
  		.flags		= FL_BASE0 | FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
05caac585   Russell King   [SERIAL] Convert ...
315
316
317
318
319
320
  	[avlab_2s1p] = { /* n/t */
  		.flags		= FL_BASE0 | FL_BASE_BARS,
  		.num_ports	= 2,
  		.base_baud	= 115200,
  		.uart_offset	= 8,
  	},
05caac585   Russell King   [SERIAL] Convert ...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  	[siig_1s1p_10x] = {
  		.flags		= FL_BASE2,
  		.num_ports	= 1,
  		.base_baud	= 460800,
  		.uart_offset	= 8,
  	},
  	[siig_2s1p_10x] = {
  		.flags		= FL_BASE2,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[siig_2p1s_20x] = {
  		.flags		= FL_BASE0,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[siig_1s1p_20x] = {
  		.flags		= FL_BASE0,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[siig_2s1p_20x] = {
  		.flags		= FL_BASE0,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
b9b24558f   Frédéric Brière   parport/serial: a...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  	[timedia_4078a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079h] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4085h] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4088a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4089a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4095a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4096a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4078u] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4085u] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079r] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079s] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079d] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079e] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_4079f] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_9079a] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_9079b] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
  	[timedia_9079c] = {
  		.flags		= FL_BASE0|FL_BASE_BARS,
  		.num_ports	= 1,
  		.base_baud	= 921600,
  		.uart_offset	= 8,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
  };
  
  struct parport_serial_private {
05caac585   Russell King   [SERIAL] Convert ...
462
  	struct serial_private	*serial;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
  	int num_par;
  	struct parport *port[PARPORT_MAX];
  	struct parport_pc_pci par;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
  /* Register the serial port(s) of a PCI card. */
  static int __devinit serial_register (struct pci_dev *dev,
  				      const struct pci_device_id *id)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
  	struct parport_serial_private *priv = pci_get_drvdata (dev);
05caac585   Russell King   [SERIAL] Convert ...
472
473
  	struct pciserial_board *board;
  	struct serial_private *serial;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

05caac585   Russell King   [SERIAL] Convert ...
475
  	board = &pci_parport_serial_boards[id->driver_data];
7808edcd3   Nicos Gollan   Basic support for...
476
477
478
  
  	if (board->num_ports == 0)
  		return 0;
05caac585   Russell King   [SERIAL] Convert ...
479
  	serial = pciserial_init_ports(dev, board);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480

05caac585   Russell King   [SERIAL] Convert ...
481
482
  	if (IS_ERR(serial))
  		return PTR_ERR(serial);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483

05caac585   Russell King   [SERIAL] Convert ...
484
485
  	priv->serial = serial;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
491
492
493
  }
  
  /* Register the parallel port(s) of a PCI card. */
  static int __devinit parport_register (struct pci_dev *dev,
  				       const struct pci_device_id *id)
  {
  	struct parport_pc_pci *card;
  	struct parport_serial_private *priv = pci_get_drvdata (dev);
7a171cdcb   Russell King   [SERIAL] Fix two ...
494
  	int n, success = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
499
500
501
502
503
504
505
506
  
  	priv->par = cards[id->driver_data];
  	card = &priv->par;
  	if (card->preinit_hook &&
  	    card->preinit_hook (dev, card, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
  		return -ENODEV;
  
  	for (n = 0; n < card->numports; n++) {
  		struct parport *port;
  		int lo = card->addr[n].lo;
  		int hi = card->addr[n].hi;
  		unsigned long io_lo, io_hi;
51dcdfec6   Alan Cox   parport: Use the ...
507
  		int irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
  
  		if (priv->num_par == ARRAY_SIZE (priv->port)) {
  			printk (KERN_WARNING
f4f64e9de   Andrew Morton   [PATCH] parport_s...
511
  				"parport_serial: %s: only %zu parallel ports "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
  				"supported (%d reported)
  ", pci_name (dev),
f4f64e9de   Andrew Morton   [PATCH] parport_s...
514
  				ARRAY_SIZE(priv->port), card->numports);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
521
522
523
524
525
526
  			break;
  		}
  
  		io_lo = pci_resource_start (dev, lo);
  		io_hi = 0;
  		if ((hi >= 0) && (hi <= 6))
  			io_hi = pci_resource_start (dev, hi);
  		else if (hi > 6)
  			io_lo += hi; /* Reinterpret the meaning of
                                          "hi" as an offset (see SYBA
                                          def.) */
  		/* TODO: test if sharing interrupts works */
51dcdfec6   Alan Cox   parport: Use the ...
527
528
529
530
531
532
533
534
535
536
537
538
  		irq = dev->irq;
  		if (irq == IRQ_NONE) {
  			dev_dbg(&dev->dev,
  			"PCI parallel port detected: I/O at %#lx(%#lx)
  ",
  				io_lo, io_hi);
  			irq = PARPORT_IRQ_NONE;
  		} else {
  			dev_dbg(&dev->dev,
  		"PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d
  ",
  				io_lo, io_hi, irq);
51dcdfec6   Alan Cox   parport: Use the ...
539
540
541
  		}
  		port = parport_pc_probe_port (io_lo, io_hi, irq,
  			      PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
544
545
546
547
548
549
  		if (port) {
  			priv->port[priv->num_par++] = port;
  			success = 1;
  		}
  	}
  
  	if (card->postinit_hook)
  		card->postinit_hook (dev, card, !success);
7a171cdcb   Russell King   [SERIAL] Fix two ...
550
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
555
556
557
  }
  
  static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
  					       const struct pci_device_id *id)
  {
  	struct parport_serial_private *priv;
  	int err;
dd00cc486   Yoann Padioleau   some kmalloc/mems...
558
  	priv = kzalloc (sizeof *priv, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
  	if (!priv)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  	pci_set_drvdata (dev, priv);
  
  	err = pci_enable_device (dev);
  	if (err) {
  		pci_set_drvdata (dev, NULL);
  		kfree (priv);
  		return err;
  	}
  
  	if (parport_register (dev, id)) {
  		pci_set_drvdata (dev, NULL);
  		kfree (priv);
  		return -ENODEV;
  	}
  
  	if (serial_register (dev, id)) {
  		int i;
  		for (i = 0; i < priv->num_par; i++)
  			parport_pc_unregister_port (priv->port[i]);
  		pci_set_drvdata (dev, NULL);
  		kfree (priv);
  		return -ENODEV;
  	}
  
  	return 0;
  }
  
  static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
  {
  	struct parport_serial_private *priv = pci_get_drvdata (dev);
  	int i;
05caac585   Russell King   [SERIAL] Convert ...
592
  	pci_set_drvdata(dev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  	// Serial ports
05caac585   Russell King   [SERIAL] Convert ...
594
595
  	if (priv->serial)
  		pciserial_remove_ports(priv->serial);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
601
602
603
  	// Parallel ports
  	for (i = 0; i < priv->num_par; i++)
  		parport_pc_unregister_port (priv->port[i]);
  
  	kfree (priv);
  	return;
  }
7dd7d6912   Alexey Dobriyan   [PATCH] CONFIG_PM...
604
  #ifdef CONFIG_PM
05caac585   Russell King   [SERIAL] Convert ...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
  {
  	struct parport_serial_private *priv = pci_get_drvdata(dev);
  
  	if (priv->serial)
  		pciserial_suspend_ports(priv->serial);
  
  	/* FIXME: What about parport? */
  
  	pci_save_state(dev);
  	pci_set_power_state(dev, pci_choose_state(dev, state));
  	return 0;
  }
  
  static int parport_serial_pci_resume(struct pci_dev *dev)
  {
  	struct parport_serial_private *priv = pci_get_drvdata(dev);
10f8a5981   Randy Dunlap   parport_serial: f...
622
  	int err;
05caac585   Russell King   [SERIAL] Convert ...
623
624
625
626
627
628
629
  
  	pci_set_power_state(dev, PCI_D0);
  	pci_restore_state(dev);
  
  	/*
  	 * The device may have been disabled.  Re-enable it.
  	 */
10f8a5981   Randy Dunlap   parport_serial: f...
630
631
632
633
634
635
636
  	err = pci_enable_device(dev);
  	if (err) {
  		printk(KERN_ERR "parport_serial: %s: error enabling "
  			"device for resume (%d)
  ", pci_name(dev), err);
  		return err;
  	}
05caac585   Russell King   [SERIAL] Convert ...
637
638
639
640
641
642
643
644
  
  	if (priv->serial)
  		pciserial_resume_ports(priv->serial);
  
  	/* FIXME: What about parport? */
  
  	return 0;
  }
7dd7d6912   Alexey Dobriyan   [PATCH] CONFIG_PM...
645
  #endif
05caac585   Russell King   [SERIAL] Convert ...
646

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
650
651
  static struct pci_driver parport_serial_pci_driver = {
  	.name		= "parport_serial",
  	.id_table	= parport_serial_pci_tbl,
  	.probe		= parport_serial_pci_probe,
  	.remove		= __devexit_p(parport_serial_pci_remove),
7dd7d6912   Alexey Dobriyan   [PATCH] CONFIG_PM...
652
  #ifdef CONFIG_PM
05caac585   Russell King   [SERIAL] Convert ...
653
654
  	.suspend	= parport_serial_pci_suspend,
  	.resume		= parport_serial_pci_resume,
7dd7d6912   Alexey Dobriyan   [PATCH] CONFIG_PM...
655
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
  };
  
  
  static int __init parport_serial_init (void)
  {
93b47684f   Richard Knutsson   [PATCH] drivers/*...
661
  	return pci_register_driver (&parport_serial_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  }
  
  static void __exit parport_serial_exit (void)
  {
  	pci_unregister_driver (&parport_serial_pci_driver);
  	return;
  }
  
  MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
  MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
  MODULE_LICENSE("GPL");
  
  module_init(parport_serial_init);
  module_exit(parport_serial_exit);