blob: 2c70773543e052b94f98931557e967c9eb13a9eb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2
3 A driver for PCMCIA serial devices
4
5 serial_cs.c 1.134 2002/05/04 05:48:53
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/kernel.h>
37#include <linux/init.h>
38#include <linux/sched.h>
39#include <linux/ptrace.h>
40#include <linux/slab.h>
41#include <linux/string.h>
42#include <linux/timer.h>
43#include <linux/serial_core.h>
Petr Vandrovec30bac7a2006-02-10 02:04:00 -080044#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/major.h>
46#include <asm/io.h>
47#include <asm/system.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <pcmcia/cs_types.h>
50#include <pcmcia/cs.h>
51#include <pcmcia/cistpl.h>
52#include <pcmcia/ciscode.h>
53#include <pcmcia/ds.h>
54#include <pcmcia/cisreg.h>
55
56#include "8250.h"
57
58#ifdef PCMCIA_DEBUG
59static int pc_debug = PCMCIA_DEBUG;
60module_param(pc_debug, int, 0644);
61#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
62static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)";
63#else
64#define DEBUG(n, args...)
65#endif
66
67/*====================================================================*/
68
69/* Parameters that can be set with 'insmod' */
70
71/* Enable the speaker? */
72static int do_sound = 1;
73/* Skip strict UART tests? */
74static int buggy_uart;
75
76module_param(do_sound, int, 0444);
77module_param(buggy_uart, int, 0444);
78
79/*====================================================================*/
80
81/* Table of multi-port card ID's */
82
83struct multi_id {
84 u_short manfid;
85 u_short prodid;
86 int multi; /* 1 = multifunction, > 1 = # ports */
87};
88
Arjan van de Vencb3592b2005-11-28 21:04:11 +000089static const struct multi_id multi_id[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 },
91 { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
92 { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
93 { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 },
94 { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 },
95 { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 },
96 { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 }
97};
98#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
99
100struct serial_info {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100101 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 int ndev;
103 int multi;
104 int slave;
105 int manfid;
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800106 int prodid;
107 int c950ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 dev_node_t node[4];
109 int line[4];
110};
111
Yum Rayan16f31112005-05-01 08:59:14 -0700112struct serial_cfg_mem {
113 tuple_t tuple;
114 cisparse_t parse;
115 u_char buf[256];
116};
117
118
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200119static int serial_config(struct pcmcia_device * link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800122static void wakeup_card(struct serial_info *info)
123{
124 int ctrl = info->c950ctrl;
125
126 if (info->manfid == MANFID_OXSEMI) {
127 outb(12, ctrl + 1);
128 } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
129 /* request_region? oxsemi branch does no request_region too... */
130 /* This sequence is needed to properly initialize MC45 attached to OXCF950.
131 * I tried decreasing these msleep()s, but it worked properly (survived
132 * 1000 stop/start operations) with these timeouts (or bigger). */
133 outb(0xA, ctrl + 1);
134 msleep(100);
135 outb(0xE, ctrl + 1);
136 msleep(300);
137 outb(0xC, ctrl + 1);
138 msleep(100);
139 outb(0xE, ctrl + 1);
140 msleep(200);
141 outb(0xF, ctrl + 1);
142 msleep(100);
143 outb(0xE, ctrl + 1);
144 msleep(100);
145 outb(0xC, ctrl + 1);
146 }
147}
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149/*======================================================================
150
151 After a card is removed, serial_remove() will unregister
152 the serial device(s), and release the PCMCIA configuration.
153
154======================================================================*/
155
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200156static void serial_remove(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157{
158 struct serial_info *info = link->priv;
159 int i;
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 DEBUG(0, "serial_release(0x%p)\n", link);
162
163 /*
164 * Recheck to see if the device is still configured.
165 */
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100166 for (i = 0; i < info->ndev; i++)
167 serial8250_unregister_port(info->line[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100169 info->p_dev->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100171 if (!info->slave)
172 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173}
174
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200175static int serial_suspend(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100177 struct serial_info *info = link->priv;
178 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100180 for (i = 0; i < info->ndev; i++)
181 serial8250_suspend_port(info->line[i]);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100182
183 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184}
185
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200186static int serial_resume(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187{
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100188 if (pcmcia_dev_present(link)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 struct serial_info *info = link->priv;
190 int i;
191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 for (i = 0; i < info->ndev; i++)
193 serial8250_resume_port(info->line[i]);
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800194 wakeup_card(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 }
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100196
197 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198}
199
200/*======================================================================
201
202 serial_attach() creates an "instance" of the driver, allocating
203 local data structures for one device. The device is registered
204 with Card Services.
205
206======================================================================*/
207
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200208static int serial_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209{
210 struct serial_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
212 DEBUG(0, "serial_attach()\n");
213
214 /* Create new serial device */
215 info = kmalloc(sizeof (*info), GFP_KERNEL);
216 if (!info)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100217 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 memset(info, 0, sizeof (*info));
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200219 info->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 link->priv = info;
221
222 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
223 link->io.NumPorts1 = 8;
224 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
225 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
226 link->conf.Attributes = CONF_ENABLE_IRQ;
227 if (do_sound) {
228 link->conf.Attributes |= CONF_ENABLE_SPKR;
229 link->conf.Status = CCSR_AUDIO_ENA;
230 }
231 link->conf.IntType = INT_MEMORY_AND_IO;
232
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200233 return serial_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
236/*======================================================================
237
238 This deletes a driver "instance". The device is de-registered
239 with Card Services. If it has been released, all local data
240 structures are freed. Otherwise, the structures will be freed
241 when the device is released.
242
243======================================================================*/
244
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200245static void serial_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
247 struct serial_info *info = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 DEBUG(0, "serial_detach(0x%p)\n", link);
250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 /*
252 * Ensure any outstanding scheduled tasks are completed.
253 */
254 flush_scheduled_work();
255
256 /*
257 * Ensure that the ports have been released.
258 */
259 serial_remove(link);
260
Dominik Brodowskib4635812005-11-14 21:25:35 +0100261 /* free bits */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 kfree(info);
263}
264
265/*====================================================================*/
266
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200267static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 kio_addr_t iobase, int irq)
269{
270 struct uart_port port;
271 int line;
272
273 memset(&port, 0, sizeof (struct uart_port));
274 port.iobase = iobase;
275 port.irq = irq;
276 port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
277 port.uartclk = 1843200;
278 port.dev = &handle_to_dev(handle);
279 if (buggy_uart)
280 port.flags |= UPF_BUGGY_UART;
281 line = serial8250_register_port(&port);
282 if (line < 0) {
283 printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
284 "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
285 return -EINVAL;
286 }
287
288 info->line[info->ndev] = line;
289 sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
290 info->node[info->ndev].major = TTY_MAJOR;
291 info->node[info->ndev].minor = 0x40 + line;
292 if (info->ndev > 0)
293 info->node[info->ndev - 1].next = &info->node[info->ndev];
294 info->ndev++;
295
296 return 0;
297}
298
299/*====================================================================*/
300
301static int
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200302first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
304 int i;
305 i = pcmcia_get_first_tuple(handle, tuple);
306 if (i != CS_SUCCESS)
307 return CS_NO_MORE_ITEMS;
308 i = pcmcia_get_tuple_data(handle, tuple);
309 if (i != CS_SUCCESS)
310 return i;
311 return pcmcia_parse_tuple(handle, tuple, parse);
312}
313
314static int
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200315next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
317 int i;
318 i = pcmcia_get_next_tuple(handle, tuple);
319 if (i != CS_SUCCESS)
320 return CS_NO_MORE_ITEMS;
321 i = pcmcia_get_tuple_data(handle, tuple);
322 if (i != CS_SUCCESS)
323 return i;
324 return pcmcia_parse_tuple(handle, tuple, parse);
325}
326
327/*====================================================================*/
328
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200329static int simple_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
Arjan van de Vencb3592b2005-11-28 21:04:11 +0000331 static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
332 static const int size_table[2] = { 8, 16 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700334 struct serial_cfg_mem *cfg_mem;
335 tuple_t *tuple;
336 u_char *buf;
337 cisparse_t *parse;
338 cistpl_cftable_entry_t *cf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 config_info_t config;
340 int i, j, try;
341 int s;
342
Yum Rayan16f31112005-05-01 08:59:14 -0700343 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
344 if (!cfg_mem)
345 return -1;
346
347 tuple = &cfg_mem->tuple;
348 parse = &cfg_mem->parse;
349 cf = &parse->cftable_entry;
350 buf = cfg_mem->buf;
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 /* If the card is already configured, look up the port and irq */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200353 i = pcmcia_get_configuration_info(link, &config);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
355 kio_addr_t port = 0;
356 if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
357 port = config.BasePort2;
358 info->slave = 1;
359 } else if ((info->manfid == MANFID_OSITECH) &&
360 (config.NumPorts1 == 0x40)) {
361 port = config.BasePort1 + 0x28;
362 info->slave = 1;
363 }
Yum Rayan16f31112005-05-01 08:59:14 -0700364 if (info->slave) {
365 kfree(cfg_mem);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200366 return setup_serial(link, info, port, config.AssignedIRQ);
Yum Rayan16f31112005-05-01 08:59:14 -0700367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
370 /* First pass: look for a config entry that looks normal. */
Yum Rayan16f31112005-05-01 08:59:14 -0700371 tuple->TupleData = (cisdata_t *) buf;
372 tuple->TupleOffset = 0;
373 tuple->TupleDataMax = 255;
374 tuple->Attributes = 0;
375 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 /* Two tries: without IO aliases, then with aliases */
377 for (s = 0; s < 2; s++) {
378 for (try = 0; try < 2; try++) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200379 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 while (i != CS_NO_MORE_ITEMS) {
381 if (i != CS_SUCCESS)
382 goto next_entry;
383 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
Dominik Brodowski70294b42006-01-15 12:43:16 +0100384 link->conf.Vpp =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
386 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
387 (cf->io.win[0].base != 0)) {
388 link->conf.ConfigIndex = cf->index;
389 link->io.BasePort1 = cf->io.win[0].base;
390 link->io.IOAddrLines = (try == 0) ?
391 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200392 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 if (i == CS_SUCCESS)
394 goto found_port;
395 }
396next_entry:
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200397 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 }
399 }
400 }
401 /* Second pass: try to find an entry that isn't picky about
402 its base address, then try to grab any standard serial port
403 address, and finally try to get any free port. */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200404 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 while (i != CS_NO_MORE_ITEMS) {
406 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
407 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
408 link->conf.ConfigIndex = cf->index;
409 for (j = 0; j < 5; j++) {
410 link->io.BasePort1 = base[j];
411 link->io.IOAddrLines = base[j] ? 16 : 3;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200412 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (i == CS_SUCCESS)
414 goto found_port;
415 }
416 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200417 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 }
419
420 found_port:
421 if (i != CS_SUCCESS) {
422 printk(KERN_NOTICE
423 "serial_cs: no usable port range found, giving up\n");
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200424 cs_error(link, RequestIO, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700425 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 return -1;
427 }
428
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200429 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200431 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 link->irq.AssignedIRQ = 0;
433 }
434 if (info->multi && (info->manfid == MANFID_3COM))
435 link->conf.ConfigIndex &= ~(0x08);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200436 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200438 cs_error(link, RequestConfiguration, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700439 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 return -1;
441 }
Yum Rayan16f31112005-05-01 08:59:14 -0700442 kfree(cfg_mem);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200443 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444}
445
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200446static int multi_config(struct pcmcia_device * link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700449 struct serial_cfg_mem *cfg_mem;
450 tuple_t *tuple;
451 u_char *buf;
452 cisparse_t *parse;
453 cistpl_cftable_entry_t *cf;
Yum Rayan16f31112005-05-01 08:59:14 -0700454 int i, rc, base2 = 0;
455
456 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
457 if (!cfg_mem)
458 return -1;
459 tuple = &cfg_mem->tuple;
460 parse = &cfg_mem->parse;
461 cf = &parse->cftable_entry;
462 buf = cfg_mem->buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Yum Rayan16f31112005-05-01 08:59:14 -0700464 tuple->TupleData = (cisdata_t *) buf;
465 tuple->TupleOffset = 0;
466 tuple->TupleDataMax = 255;
467 tuple->Attributes = 0;
468 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /* First, look for a generic full-sized window */
471 link->io.NumPorts1 = info->multi * 8;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200472 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 while (i != CS_NO_MORE_ITEMS) {
474 /* The quad port cards have bad CIS's, so just look for a
475 window larger than 8 ports and assume it will be right */
476 if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
477 (cf->io.win[0].len > 8)) {
478 link->conf.ConfigIndex = cf->index;
479 link->io.BasePort1 = cf->io.win[0].base;
480 link->io.IOAddrLines =
481 cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200482 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 base2 = link->io.BasePort1 + 8;
484 if (i == CS_SUCCESS)
485 break;
486 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200487 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 }
489
490 /* If that didn't work, look for two windows */
491 if (i != CS_SUCCESS) {
492 link->io.NumPorts1 = link->io.NumPorts2 = 8;
493 info->multi = 2;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200494 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 while (i != CS_NO_MORE_ITEMS) {
496 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
497 link->conf.ConfigIndex = cf->index;
498 link->io.BasePort1 = cf->io.win[0].base;
499 link->io.BasePort2 = cf->io.win[1].base;
500 link->io.IOAddrLines =
501 cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200502 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 base2 = link->io.BasePort2;
504 if (i == CS_SUCCESS)
505 break;
506 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200507 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509 }
510
511 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200512 cs_error(link, RequestIO, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700513 rc = -1;
514 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 }
516
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200517 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (i != CS_SUCCESS) {
519 printk(KERN_NOTICE
520 "serial_cs: no usable port range found, giving up\n");
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200521 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 link->irq.AssignedIRQ = 0;
523 }
524 /* Socket Dual IO: this enables irq's for second port */
525 if (info->multi && (info->manfid == MANFID_SOCKET)) {
526 link->conf.Present |= PRESENT_EXT_STATUS;
527 link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
528 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200529 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200531 cs_error(link, RequestConfiguration, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700532 rc = -1;
533 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 }
535
536 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800537 * 8 registers are for the UART, the others are extra registers.
538 * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
539 */
540 if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
541 info->prodid == PRODID_POSSIO_GCC)) {
542 int err;
543
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 if (cf->index == 1 || cf->index == 3) {
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800545 err = setup_serial(link, info, base2,
546 link->irq.AssignedIRQ);
547 base2 = link->io.BasePort1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 } else {
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800549 err = setup_serial(link, info, link->io.BasePort1,
550 link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800552 info->c950ctrl = base2;
553 wakeup_card(info);
Yum Rayan16f31112005-05-01 08:59:14 -0700554 rc = 0;
555 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 }
557
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200558 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 /* The Nokia cards are not really multiport cards */
Yum Rayan16f31112005-05-01 08:59:14 -0700560 if (info->manfid == MANFID_NOKIA) {
561 rc = 0;
562 goto free_cfg_mem;
563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 for (i = 0; i < info->multi - 1; i++)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200565 setup_serial(link, info, base2 + (8 * i),
Yum Rayan16f31112005-05-01 08:59:14 -0700566 link->irq.AssignedIRQ);
567 rc = 0;
568free_cfg_mem:
569 kfree(cfg_mem);
570 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571}
572
573/*======================================================================
574
575 serial_config() is scheduled to run after a CARD_INSERTION event
576 is received, to configure the PCMCIA socket, and to make the
577 serial device available to the system.
578
579======================================================================*/
580
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200581static int serial_config(struct pcmcia_device * link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700584 struct serial_cfg_mem *cfg_mem;
585 tuple_t *tuple;
586 u_char *buf;
587 cisparse_t *parse;
588 cistpl_cftable_entry_t *cf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 int i, last_ret, last_fn;
590
591 DEBUG(0, "serial_config(0x%p)\n", link);
592
Yum Rayan16f31112005-05-01 08:59:14 -0700593 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
594 if (!cfg_mem)
595 goto failed;
596
597 tuple = &cfg_mem->tuple;
598 parse = &cfg_mem->parse;
599 cf = &parse->cftable_entry;
600 buf = cfg_mem->buf;
601
602 tuple->TupleData = (cisdata_t *) buf;
603 tuple->TupleOffset = 0;
604 tuple->TupleDataMax = 255;
605 tuple->Attributes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 /* Get configuration register information */
Yum Rayan16f31112005-05-01 08:59:14 -0700607 tuple->DesiredTuple = CISTPL_CONFIG;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200608 last_ret = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 if (last_ret != CS_SUCCESS) {
610 last_fn = ParseTuple;
611 goto cs_failed;
612 }
Yum Rayan16f31112005-05-01 08:59:14 -0700613 link->conf.ConfigBase = parse->config.base;
614 link->conf.Present = parse->config.rmask[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 /* Is this a compliant multifunction card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700617 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
618 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200619 info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 /* Is this a multiport card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700622 tuple->DesiredTuple = CISTPL_MANFID;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200623 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
Petr Vandrovecf1fc3992005-05-16 21:53:44 -0700624 info->manfid = parse->manfid.manf;
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800625 info->prodid = le16_to_cpu(buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 for (i = 0; i < MULTI_COUNT; i++)
627 if ((info->manfid == multi_id[i].manfid) &&
Petr Vandrovecf1fc3992005-05-16 21:53:44 -0700628 (parse->manfid.card == multi_id[i].prodid))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 break;
630 if (i < MULTI_COUNT)
631 info->multi = multi_id[i].multi;
632 }
633
634 /* Another check for dual-serial cards: look for either serial or
635 multifunction cards that ask for appropriate IO port ranges */
Yum Rayan16f31112005-05-01 08:59:14 -0700636 tuple->DesiredTuple = CISTPL_FUNCID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if ((info->multi == 0) &&
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200638 ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
Yum Rayan16f31112005-05-01 08:59:14 -0700639 (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
640 (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
641 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200642 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
644 info->multi = cf->io.win[0].len >> 3;
645 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
646 (cf->io.win[1].len == 8))
647 info->multi = 2;
648 }
649 }
650
651 if (info->multi > 1)
652 multi_config(link);
653 else
654 simple_config(link);
655
656 if (info->ndev == 0)
657 goto failed;
658
659 if (info->manfid == MANFID_IBM) {
660 conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200661 last_ret = pcmcia_access_configuration_register(link, &reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (last_ret) {
663 last_fn = AccessConfigurationRegister;
664 goto cs_failed;
665 }
666 reg.Action = CS_WRITE;
667 reg.Value = reg.Value | 1;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200668 last_ret = pcmcia_access_configuration_register(link, &reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 if (last_ret) {
670 last_fn = AccessConfigurationRegister;
671 goto cs_failed;
672 }
673 }
674
Dominik Brodowskifd238232006-03-05 10:45:09 +0100675 link->dev_node = &info->node[0];
Yum Rayan16f31112005-05-01 08:59:14 -0700676 kfree(cfg_mem);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200677 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679 cs_failed:
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200680 cs_error(link, last_fn, last_ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 failed:
682 serial_remove(link);
Yum Rayan16f31112005-05-01 08:59:14 -0700683 kfree(cfg_mem);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200684 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685}
686
Dominik Brodowski325aa292005-06-27 16:28:18 -0700687static struct pcmcia_device_id serial_ids[] = {
688 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
689 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
690 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
691 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
692 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
693 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
694 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
695 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
696 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
697 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
698 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
699 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
Jun Komurof4d75102005-06-27 16:28:44 -0700700 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
701 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700702 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
703 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
704 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
705 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
706 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
707 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
708 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
709 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
710 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
Komurod277ad02005-07-28 01:07:24 -0700711 PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700712 PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
713 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
714 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
715 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
716 PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
717 PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
Komurod277ad02005-07-28 01:07:24 -0700718 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
719 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700720 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
721 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
722 PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
Komurod277ad02005-07-28 01:07:24 -0700723 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700724 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
725 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
726 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
727 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
728 PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
729 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
730 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
731 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
732 PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
733 PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
734 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100735 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700736 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
737 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
738 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
739 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
740 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
741 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
742 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
743 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
744 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
745 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
746 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
747 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
748 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
749 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
750 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
751 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
752 PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
753 PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100754 PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700755 PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
756 PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
757 PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
758 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
759 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
760 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
761 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
762 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
Komurod277ad02005-07-28 01:07:24 -0700763 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700764 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
765 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
766 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
767 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
768 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
769 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
770 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
771 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
772 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
773 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
774 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
775 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
776 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
777 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
778 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"),
779 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
780 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
781 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
Dominik Brodowskia42f0dc2005-09-24 23:12:44 -0700782 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
Dominik Brodowskif542ff62006-01-10 19:06:33 +0100783 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
784 PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
Dominik Brodowski325aa292005-06-27 16:28:18 -0700785 PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
786 PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
787 PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
788 PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
789 /* too generic */
790 /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
791 /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
792 PCMCIA_DEVICE_FUNC_ID(2),
793 PCMCIA_DEVICE_NULL,
794};
795MODULE_DEVICE_TABLE(pcmcia, serial_ids);
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797static struct pcmcia_driver serial_cs_driver = {
798 .owner = THIS_MODULE,
799 .drv = {
800 .name = "serial_cs",
801 },
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100802 .probe = serial_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100803 .remove = serial_detach,
Dominik Brodowski325aa292005-06-27 16:28:18 -0700804 .id_table = serial_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100805 .suspend = serial_suspend,
806 .resume = serial_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807};
808
809static int __init init_serial_cs(void)
810{
811 return pcmcia_register_driver(&serial_cs_driver);
812}
813
814static void __exit exit_serial_cs(void)
815{
816 pcmcia_unregister_driver(&serial_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817}
818
819module_init(init_serial_cs);
820module_exit(exit_serial_cs);
821
822MODULE_LICENSE("GPL");