blob: 1fe8cafebe38e7de8386eaf5dce2f369fb7f5532 [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>
44#include <linux/major.h>
45#include <asm/io.h>
46#include <asm/system.h>
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <pcmcia/cs_types.h>
49#include <pcmcia/cs.h>
50#include <pcmcia/cistpl.h>
51#include <pcmcia/ciscode.h>
52#include <pcmcia/ds.h>
53#include <pcmcia/cisreg.h>
54
55#include "8250.h"
56
57#ifdef PCMCIA_DEBUG
58static int pc_debug = PCMCIA_DEBUG;
59module_param(pc_debug, int, 0644);
60#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)";
62#else
63#define DEBUG(n, args...)
64#endif
65
66/*====================================================================*/
67
68/* Parameters that can be set with 'insmod' */
69
70/* Enable the speaker? */
71static int do_sound = 1;
72/* Skip strict UART tests? */
73static int buggy_uart;
74
75module_param(do_sound, int, 0444);
76module_param(buggy_uart, int, 0444);
77
78/*====================================================================*/
79
80/* Table of multi-port card ID's */
81
82struct multi_id {
83 u_short manfid;
84 u_short prodid;
85 int multi; /* 1 = multifunction, > 1 = # ports */
86};
87
Arjan van de Vencb3592b2005-11-28 21:04:11 +000088static const struct multi_id multi_id[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 },
90 { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
91 { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
92 { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 },
93 { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 },
94 { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 },
95 { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 }
96};
97#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
98
99struct serial_info {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100100 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 int ndev;
102 int multi;
103 int slave;
104 int manfid;
105 dev_node_t node[4];
106 int line[4];
107};
108
Yum Rayan16f31112005-05-01 08:59:14 -0700109struct serial_cfg_mem {
110 tuple_t tuple;
111 cisparse_t parse;
112 u_char buf[256];
113};
114
115
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200116static void serial_config(struct pcmcia_device * link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119/*======================================================================
120
121 After a card is removed, serial_remove() will unregister
122 the serial device(s), and release the PCMCIA configuration.
123
124======================================================================*/
125
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200126static void serial_remove(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
128 struct serial_info *info = link->priv;
129 int i;
130
131 link->state &= ~DEV_PRESENT;
132
133 DEBUG(0, "serial_release(0x%p)\n", link);
134
135 /*
136 * Recheck to see if the device is still configured.
137 */
Dominik Brodowskifd238232006-03-05 10:45:09 +0100138 if (info->p_dev->state & DEV_CONFIG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 for (i = 0; i < info->ndev; i++)
140 serial8250_unregister_port(info->line[i]);
141
Dominik Brodowskifd238232006-03-05 10:45:09 +0100142 info->p_dev->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +0100144 if (!info->slave)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200145 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Dominik Brodowskifd238232006-03-05 10:45:09 +0100147 info->p_dev->state &= ~DEV_CONFIG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 }
149}
150
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200151static int serial_suspend(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 if (link->state & DEV_CONFIG) {
154 struct serial_info *info = link->priv;
155 int i;
156
157 for (i = 0; i < info->ndev; i++)
158 serial8250_suspend_port(info->line[i]);
159
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100160 if (info->slave)
161 link->state &= DEV_SUSPEND_NORELEASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100163
164 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200167static int serial_resume(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 if (DEV_OK(link)) {
170 struct serial_info *info = link->priv;
171 int i;
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 for (i = 0; i < info->ndev; i++)
174 serial8250_resume_port(info->line[i]);
175 }
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100176
177 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178}
179
180/*======================================================================
181
182 serial_attach() creates an "instance" of the driver, allocating
183 local data structures for one device. The device is registered
184 with Card Services.
185
186======================================================================*/
187
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200188static int serial_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189{
190 struct serial_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192 DEBUG(0, "serial_attach()\n");
193
194 /* Create new serial device */
195 info = kmalloc(sizeof (*info), GFP_KERNEL);
196 if (!info)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100197 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 memset(info, 0, sizeof (*info));
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200199 info->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 link->priv = info;
201
202 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
203 link->io.NumPorts1 = 8;
204 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
205 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
206 link->conf.Attributes = CONF_ENABLE_IRQ;
207 if (do_sound) {
208 link->conf.Attributes |= CONF_ENABLE_SPKR;
209 link->conf.Status = CCSR_AUDIO_ENA;
210 }
211 link->conf.IntType = INT_MEMORY_AND_IO;
212
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100213 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
214 serial_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100216 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217}
218
219/*======================================================================
220
221 This deletes a driver "instance". The device is de-registered
222 with Card Services. If it has been released, all local data
223 structures are freed. Otherwise, the structures will be freed
224 when the device is released.
225
226======================================================================*/
227
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200228static void serial_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229{
230 struct serial_info *info = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232 DEBUG(0, "serial_detach(0x%p)\n", link);
233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 /*
235 * Ensure any outstanding scheduled tasks are completed.
236 */
237 flush_scheduled_work();
238
239 /*
240 * Ensure that the ports have been released.
241 */
242 serial_remove(link);
243
Dominik Brodowskib4635812005-11-14 21:25:35 +0100244 /* free bits */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 kfree(info);
246}
247
248/*====================================================================*/
249
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200250static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 kio_addr_t iobase, int irq)
252{
253 struct uart_port port;
254 int line;
255
256 memset(&port, 0, sizeof (struct uart_port));
257 port.iobase = iobase;
258 port.irq = irq;
259 port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
260 port.uartclk = 1843200;
261 port.dev = &handle_to_dev(handle);
262 if (buggy_uart)
263 port.flags |= UPF_BUGGY_UART;
264 line = serial8250_register_port(&port);
265 if (line < 0) {
266 printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
267 "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
268 return -EINVAL;
269 }
270
271 info->line[info->ndev] = line;
272 sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
273 info->node[info->ndev].major = TTY_MAJOR;
274 info->node[info->ndev].minor = 0x40 + line;
275 if (info->ndev > 0)
276 info->node[info->ndev - 1].next = &info->node[info->ndev];
277 info->ndev++;
278
279 return 0;
280}
281
282/*====================================================================*/
283
284static int
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200285first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
287 int i;
288 i = pcmcia_get_first_tuple(handle, tuple);
289 if (i != CS_SUCCESS)
290 return CS_NO_MORE_ITEMS;
291 i = pcmcia_get_tuple_data(handle, tuple);
292 if (i != CS_SUCCESS)
293 return i;
294 return pcmcia_parse_tuple(handle, tuple, parse);
295}
296
297static int
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200298next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
300 int i;
301 i = pcmcia_get_next_tuple(handle, tuple);
302 if (i != CS_SUCCESS)
303 return CS_NO_MORE_ITEMS;
304 i = pcmcia_get_tuple_data(handle, tuple);
305 if (i != CS_SUCCESS)
306 return i;
307 return pcmcia_parse_tuple(handle, tuple, parse);
308}
309
310/*====================================================================*/
311
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200312static int simple_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313{
Arjan van de Vencb3592b2005-11-28 21:04:11 +0000314 static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
315 static const int size_table[2] = { 8, 16 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700317 struct serial_cfg_mem *cfg_mem;
318 tuple_t *tuple;
319 u_char *buf;
320 cisparse_t *parse;
321 cistpl_cftable_entry_t *cf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 config_info_t config;
323 int i, j, try;
324 int s;
325
Yum Rayan16f31112005-05-01 08:59:14 -0700326 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
327 if (!cfg_mem)
328 return -1;
329
330 tuple = &cfg_mem->tuple;
331 parse = &cfg_mem->parse;
332 cf = &parse->cftable_entry;
333 buf = cfg_mem->buf;
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 /* If the card is already configured, look up the port and irq */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200336 i = pcmcia_get_configuration_info(link, &config);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
338 kio_addr_t port = 0;
339 if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
340 port = config.BasePort2;
341 info->slave = 1;
342 } else if ((info->manfid == MANFID_OSITECH) &&
343 (config.NumPorts1 == 0x40)) {
344 port = config.BasePort1 + 0x28;
345 info->slave = 1;
346 }
Yum Rayan16f31112005-05-01 08:59:14 -0700347 if (info->slave) {
348 kfree(cfg_mem);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200349 return setup_serial(link, info, port, config.AssignedIRQ);
Yum Rayan16f31112005-05-01 08:59:14 -0700350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 /* First pass: look for a config entry that looks normal. */
Yum Rayan16f31112005-05-01 08:59:14 -0700354 tuple->TupleData = (cisdata_t *) buf;
355 tuple->TupleOffset = 0;
356 tuple->TupleDataMax = 255;
357 tuple->Attributes = 0;
358 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /* Two tries: without IO aliases, then with aliases */
360 for (s = 0; s < 2; s++) {
361 for (try = 0; try < 2; try++) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200362 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 while (i != CS_NO_MORE_ITEMS) {
364 if (i != CS_SUCCESS)
365 goto next_entry;
366 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
Dominik Brodowski70294b42006-01-15 12:43:16 +0100367 link->conf.Vpp =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
369 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
370 (cf->io.win[0].base != 0)) {
371 link->conf.ConfigIndex = cf->index;
372 link->io.BasePort1 = cf->io.win[0].base;
373 link->io.IOAddrLines = (try == 0) ?
374 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200375 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (i == CS_SUCCESS)
377 goto found_port;
378 }
379next_entry:
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200380 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 }
382 }
383 }
384 /* Second pass: try to find an entry that isn't picky about
385 its base address, then try to grab any standard serial port
386 address, and finally try to get any free port. */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200387 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 while (i != CS_NO_MORE_ITEMS) {
389 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
390 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
391 link->conf.ConfigIndex = cf->index;
392 for (j = 0; j < 5; j++) {
393 link->io.BasePort1 = base[j];
394 link->io.IOAddrLines = base[j] ? 16 : 3;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200395 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if (i == CS_SUCCESS)
397 goto found_port;
398 }
399 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200400 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402
403 found_port:
404 if (i != CS_SUCCESS) {
405 printk(KERN_NOTICE
406 "serial_cs: no usable port range found, giving up\n");
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200407 cs_error(link, RequestIO, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700408 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 return -1;
410 }
411
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200412 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200414 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 link->irq.AssignedIRQ = 0;
416 }
417 if (info->multi && (info->manfid == MANFID_3COM))
418 link->conf.ConfigIndex &= ~(0x08);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200419 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200421 cs_error(link, RequestConfiguration, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700422 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return -1;
424 }
Yum Rayan16f31112005-05-01 08:59:14 -0700425 kfree(cfg_mem);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200426 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427}
428
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200429static int multi_config(struct pcmcia_device * link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700432 struct serial_cfg_mem *cfg_mem;
433 tuple_t *tuple;
434 u_char *buf;
435 cisparse_t *parse;
436 cistpl_cftable_entry_t *cf;
Yum Rayan16f31112005-05-01 08:59:14 -0700437 int i, rc, base2 = 0;
438
439 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
440 if (!cfg_mem)
441 return -1;
442 tuple = &cfg_mem->tuple;
443 parse = &cfg_mem->parse;
444 cf = &parse->cftable_entry;
445 buf = cfg_mem->buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Yum Rayan16f31112005-05-01 08:59:14 -0700447 tuple->TupleData = (cisdata_t *) buf;
448 tuple->TupleOffset = 0;
449 tuple->TupleDataMax = 255;
450 tuple->Attributes = 0;
451 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 /* First, look for a generic full-sized window */
454 link->io.NumPorts1 = info->multi * 8;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200455 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 while (i != CS_NO_MORE_ITEMS) {
457 /* The quad port cards have bad CIS's, so just look for a
458 window larger than 8 ports and assume it will be right */
459 if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
460 (cf->io.win[0].len > 8)) {
461 link->conf.ConfigIndex = cf->index;
462 link->io.BasePort1 = cf->io.win[0].base;
463 link->io.IOAddrLines =
464 cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200465 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 base2 = link->io.BasePort1 + 8;
467 if (i == CS_SUCCESS)
468 break;
469 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200470 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 }
472
473 /* If that didn't work, look for two windows */
474 if (i != CS_SUCCESS) {
475 link->io.NumPorts1 = link->io.NumPorts2 = 8;
476 info->multi = 2;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200477 i = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 while (i != CS_NO_MORE_ITEMS) {
479 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
480 link->conf.ConfigIndex = cf->index;
481 link->io.BasePort1 = cf->io.win[0].base;
482 link->io.BasePort2 = cf->io.win[1].base;
483 link->io.IOAddrLines =
484 cf->io.flags & CISTPL_IO_LINES_MASK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200485 i = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 base2 = link->io.BasePort2;
487 if (i == CS_SUCCESS)
488 break;
489 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200490 i = next_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492 }
493
494 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200495 cs_error(link, RequestIO, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700496 rc = -1;
497 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200500 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 if (i != CS_SUCCESS) {
502 printk(KERN_NOTICE
503 "serial_cs: no usable port range found, giving up\n");
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200504 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 link->irq.AssignedIRQ = 0;
506 }
507 /* Socket Dual IO: this enables irq's for second port */
508 if (info->multi && (info->manfid == MANFID_SOCKET)) {
509 link->conf.Present |= PRESENT_EXT_STATUS;
510 link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
511 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200512 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200514 cs_error(link, RequestConfiguration, i);
Yum Rayan16f31112005-05-01 08:59:14 -0700515 rc = -1;
516 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 }
518
519 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
520 8 registers are for the UART, the others are extra registers */
521 if (info->manfid == MANFID_OXSEMI) {
522 if (cf->index == 1 || cf->index == 3) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200523 setup_serial(link, info, base2, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 outb(12, link->io.BasePort1 + 1);
525 } else {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200526 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 outb(12, base2 + 1);
528 }
Yum Rayan16f31112005-05-01 08:59:14 -0700529 rc = 0;
530 goto free_cfg_mem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 }
532
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200533 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 /* The Nokia cards are not really multiport cards */
Yum Rayan16f31112005-05-01 08:59:14 -0700535 if (info->manfid == MANFID_NOKIA) {
536 rc = 0;
537 goto free_cfg_mem;
538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 for (i = 0; i < info->multi - 1; i++)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200540 setup_serial(link, info, base2 + (8 * i),
Yum Rayan16f31112005-05-01 08:59:14 -0700541 link->irq.AssignedIRQ);
542 rc = 0;
543free_cfg_mem:
544 kfree(cfg_mem);
545 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546}
547
548/*======================================================================
549
550 serial_config() is scheduled to run after a CARD_INSERTION event
551 is received, to configure the PCMCIA socket, and to make the
552 serial device available to the system.
553
554======================================================================*/
555
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200556void serial_config(struct pcmcia_device * link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700559 struct serial_cfg_mem *cfg_mem;
560 tuple_t *tuple;
561 u_char *buf;
562 cisparse_t *parse;
563 cistpl_cftable_entry_t *cf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 int i, last_ret, last_fn;
565
566 DEBUG(0, "serial_config(0x%p)\n", link);
567
Yum Rayan16f31112005-05-01 08:59:14 -0700568 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
569 if (!cfg_mem)
570 goto failed;
571
572 tuple = &cfg_mem->tuple;
573 parse = &cfg_mem->parse;
574 cf = &parse->cftable_entry;
575 buf = cfg_mem->buf;
576
577 tuple->TupleData = (cisdata_t *) buf;
578 tuple->TupleOffset = 0;
579 tuple->TupleDataMax = 255;
580 tuple->Attributes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 /* Get configuration register information */
Yum Rayan16f31112005-05-01 08:59:14 -0700582 tuple->DesiredTuple = CISTPL_CONFIG;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200583 last_ret = first_tuple(link, tuple, parse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 if (last_ret != CS_SUCCESS) {
585 last_fn = ParseTuple;
586 goto cs_failed;
587 }
Yum Rayan16f31112005-05-01 08:59:14 -0700588 link->conf.ConfigBase = parse->config.base;
589 link->conf.Present = parse->config.rmask[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 /* Configure card */
592 link->state |= DEV_CONFIG;
593
594 /* Is this a compliant multifunction card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700595 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
596 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200597 info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599 /* Is this a multiport card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700600 tuple->DesiredTuple = CISTPL_MANFID;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200601 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
Petr Vandrovecf1fc3992005-05-16 21:53:44 -0700602 info->manfid = parse->manfid.manf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 for (i = 0; i < MULTI_COUNT; i++)
604 if ((info->manfid == multi_id[i].manfid) &&
Petr Vandrovecf1fc3992005-05-16 21:53:44 -0700605 (parse->manfid.card == multi_id[i].prodid))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 break;
607 if (i < MULTI_COUNT)
608 info->multi = multi_id[i].multi;
609 }
610
611 /* Another check for dual-serial cards: look for either serial or
612 multifunction cards that ask for appropriate IO port ranges */
Yum Rayan16f31112005-05-01 08:59:14 -0700613 tuple->DesiredTuple = CISTPL_FUNCID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 if ((info->multi == 0) &&
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200615 ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
Yum Rayan16f31112005-05-01 08:59:14 -0700616 (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
617 (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
618 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200619 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
621 info->multi = cf->io.win[0].len >> 3;
622 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
623 (cf->io.win[1].len == 8))
624 info->multi = 2;
625 }
626 }
627
628 if (info->multi > 1)
629 multi_config(link);
630 else
631 simple_config(link);
632
633 if (info->ndev == 0)
634 goto failed;
635
636 if (info->manfid == MANFID_IBM) {
637 conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200638 last_ret = pcmcia_access_configuration_register(link, &reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (last_ret) {
640 last_fn = AccessConfigurationRegister;
641 goto cs_failed;
642 }
643 reg.Action = CS_WRITE;
644 reg.Value = reg.Value | 1;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200645 last_ret = pcmcia_access_configuration_register(link, &reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 if (last_ret) {
647 last_fn = AccessConfigurationRegister;
648 goto cs_failed;
649 }
650 }
651
Dominik Brodowskifd238232006-03-05 10:45:09 +0100652 link->dev_node = &info->node[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 link->state &= ~DEV_CONFIG_PENDING;
Yum Rayan16f31112005-05-01 08:59:14 -0700654 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 return;
656
657 cs_failed:
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200658 cs_error(link, last_fn, last_ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 failed:
660 serial_remove(link);
661 link->state &= ~DEV_CONFIG_PENDING;
Yum Rayan16f31112005-05-01 08:59:14 -0700662 kfree(cfg_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663}
664
Dominik Brodowski325aa292005-06-27 16:28:18 -0700665static struct pcmcia_device_id serial_ids[] = {
666 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
667 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
668 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
669 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
670 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
671 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
672 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
673 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
674 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
675 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
676 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
677 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
Jun Komurof4d75102005-06-27 16:28:44 -0700678 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
679 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700680 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
681 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
682 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
683 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
684 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
685 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
686 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
687 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
688 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
Komurod277ad02005-07-28 01:07:24 -0700689 PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700690 PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
691 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
692 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
693 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
694 PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
695 PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
Komurod277ad02005-07-28 01:07:24 -0700696 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
697 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700698 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
699 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
700 PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
Komurod277ad02005-07-28 01:07:24 -0700701 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700702 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
703 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
704 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
705 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
706 PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
707 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
708 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
709 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
710 PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
711 PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
712 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100713 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700714 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
715 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
716 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
717 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
718 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
719 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
720 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
721 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
722 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
723 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
724 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
725 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
726 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
727 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
728 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
729 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
730 PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
731 PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100732 PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700733 PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
734 PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
735 PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
736 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
737 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
738 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
739 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
740 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
Komurod277ad02005-07-28 01:07:24 -0700741 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700742 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
743 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
744 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
745 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
746 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
747 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
748 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
749 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
750 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
751 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
752 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
753 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
754 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
755 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
756 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"),
757 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
758 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
759 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
Dominik Brodowskia42f0dc2005-09-24 23:12:44 -0700760 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 +0100761 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
762 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 -0700763 PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
764 PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
765 PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
766 PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
767 /* too generic */
768 /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
769 /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
770 PCMCIA_DEVICE_FUNC_ID(2),
771 PCMCIA_DEVICE_NULL,
772};
773MODULE_DEVICE_TABLE(pcmcia, serial_ids);
774
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775static struct pcmcia_driver serial_cs_driver = {
776 .owner = THIS_MODULE,
777 .drv = {
778 .name = "serial_cs",
779 },
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100780 .probe = serial_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100781 .remove = serial_detach,
Dominik Brodowski325aa292005-06-27 16:28:18 -0700782 .id_table = serial_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100783 .suspend = serial_suspend,
784 .resume = serial_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785};
786
787static int __init init_serial_cs(void)
788{
789 return pcmcia_register_driver(&serial_cs_driver);
790}
791
792static void __exit exit_serial_cs(void)
793{
794 pcmcia_unregister_driver(&serial_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795}
796
797module_init(init_serial_cs);
798module_exit(exit_serial_cs);
799
800MODULE_LICENSE("GPL");