blob: f8658686439df9bf0aded55b944c9cd76452b90d [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/ptrace.h>
39#include <linux/slab.h>
40#include <linux/string.h>
41#include <linux/timer.h>
42#include <linux/serial_core.h>
Petr Vandrovec30bac7a2006-02-10 02:04:00 -080043#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#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
Russell King1fbbac42006-09-16 21:09:41 +010082struct serial_quirk {
Russell Kinga8244b52006-09-16 21:26:16 +010083 unsigned int manfid;
84 unsigned int prodid;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 int multi; /* 1 = multifunction, > 1 = # ports */
Russell Kingefd92df2006-09-16 23:00:54 +010086 void (*config)(struct pcmcia_device *);
Russell Kingf3d10682006-09-16 23:07:46 +010087 void (*setup)(struct pcmcia_device *, struct uart_port *);
Russell King7ef057f2006-09-16 22:45:41 +010088 void (*wakeup)(struct pcmcia_device *);
Russell Kingeee3a882006-09-16 21:34:11 +010089 int (*post)(struct pcmcia_device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090};
91
Russell Kingeee3a882006-09-16 21:34:11 +010092struct serial_info {
93 struct pcmcia_device *p_dev;
94 int ndev;
95 int multi;
96 int slave;
97 int manfid;
98 int prodid;
99 int c950ctrl;
100 dev_node_t node[4];
101 int line[4];
102 const struct serial_quirk *quirk;
103};
104
105struct serial_cfg_mem {
106 tuple_t tuple;
107 cisparse_t parse;
108 u_char buf[256];
109};
110
Russell Kingf3d10682006-09-16 23:07:46 +0100111/*
112 * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6"
113 * manfid 0x0160, 0x0104
114 * This card appears to have a 14.7456MHz clock.
115 */
116static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
117{
118 port->uartclk = 14745600;
119}
120
Russell Kingeee3a882006-09-16 21:34:11 +0100121static int quirk_post_ibm(struct pcmcia_device *link)
122{
123 conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
124 int last_ret, last_fn;
125
126 last_ret = pcmcia_access_configuration_register(link, &reg);
127 if (last_ret) {
128 last_fn = AccessConfigurationRegister;
129 goto cs_failed;
130 }
131 reg.Action = CS_WRITE;
132 reg.Value = reg.Value | 1;
133 last_ret = pcmcia_access_configuration_register(link, &reg);
134 if (last_ret) {
135 last_fn = AccessConfigurationRegister;
136 goto cs_failed;
137 }
138 return 0;
139
140 cs_failed:
141 cs_error(link, last_fn, last_ret);
142 return -ENODEV;
143}
144
Russell King20f13042006-09-16 23:04:37 +0100145/*
146 * Nokia cards are not really multiport cards. Shouldn't this
147 * be handled by setting the quirk entry .multi = 0 | 1 ?
148 */
149static void quirk_config_nokia(struct pcmcia_device *link)
150{
151 struct serial_info *info = link->priv;
152
153 if (info->multi > 1)
154 info->multi = 1;
155}
156
Russell King7ef057f2006-09-16 22:45:41 +0100157static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
158{
159 struct serial_info *info = link->priv;
160
161 outb(12, info->c950ctrl + 1);
162}
163
164/* request_region? oxsemi branch does no request_region too... */
165/*
166 * This sequence is needed to properly initialize MC45 attached to OXCF950.
167 * I tried decreasing these msleep()s, but it worked properly (survived
168 * 1000 stop/start operations) with these timeouts (or bigger).
169 */
170static void quirk_wakeup_possio_gcc(struct pcmcia_device *link)
171{
172 struct serial_info *info = link->priv;
173 unsigned int ctrl = info->c950ctrl;
174
175 outb(0xA, ctrl + 1);
176 msleep(100);
177 outb(0xE, ctrl + 1);
178 msleep(300);
179 outb(0xC, ctrl + 1);
180 msleep(100);
181 outb(0xE, ctrl + 1);
182 msleep(200);
183 outb(0xF, ctrl + 1);
184 msleep(100);
185 outb(0xE, ctrl + 1);
186 msleep(100);
187 outb(0xC, ctrl + 1);
188}
189
Russell Kingefd92df2006-09-16 23:00:54 +0100190/*
191 * Socket Dual IO: this enables irq's for second port
192 */
193static void quirk_config_socket(struct pcmcia_device *link)
194{
195 struct serial_info *info = link->priv;
196
197 if (info->multi) {
198 link->conf.Present |= PRESENT_EXT_STATUS;
199 link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
200 }
201}
202
Russell King1fbbac42006-09-16 21:09:41 +0100203static const struct serial_quirk quirks[] = {
204 {
Russell Kingf3d10682006-09-16 23:07:46 +0100205 .manfid = 0x0160,
206 .prodid = 0x0104,
207 .multi = -1,
208 .setup = quirk_setup_brainboxes_0104,
209 }, {
Russell Kingeee3a882006-09-16 21:34:11 +0100210 .manfid = MANFID_IBM,
211 .prodid = ~0,
212 .multi = -1,
213 .post = quirk_post_ibm,
214 }, {
Russell King7ef057f2006-09-16 22:45:41 +0100215 .manfid = MANFID_INTEL,
216 .prodid = PRODID_INTEL_DUAL_RS232,
217 .multi = 2,
218 }, {
219 .manfid = MANFID_NATINST,
220 .prodid = PRODID_NATINST_QUAD_RS232,
221 .multi = 4,
222 }, {
Russell King20f13042006-09-16 23:04:37 +0100223 .manfid = MANFID_NOKIA,
224 .prodid = ~0,
225 .multi = -1,
226 .config = quirk_config_nokia,
227 }, {
Russell King1fbbac42006-09-16 21:09:41 +0100228 .manfid = MANFID_OMEGA,
229 .prodid = PRODID_OMEGA_QSP_100,
230 .multi = 4,
231 }, {
Russell King7ef057f2006-09-16 22:45:41 +0100232 .manfid = MANFID_OXSEMI,
233 .prodid = ~0,
234 .multi = -1,
235 .wakeup = quirk_wakeup_oxsemi,
236 }, {
237 .manfid = MANFID_POSSIO,
238 .prodid = PRODID_POSSIO_GCC,
239 .multi = -1,
240 .wakeup = quirk_wakeup_possio_gcc,
241 }, {
Russell King1fbbac42006-09-16 21:09:41 +0100242 .manfid = MANFID_QUATECH,
243 .prodid = PRODID_QUATECH_DUAL_RS232,
244 .multi = 2,
245 }, {
246 .manfid = MANFID_QUATECH,
247 .prodid = PRODID_QUATECH_DUAL_RS232_D1,
248 .multi = 2,
249 }, {
250 .manfid = MANFID_QUATECH,
Sergei Organovbb289bc2007-02-02 20:43:12 +0300251 .prodid = PRODID_QUATECH_DUAL_RS232_G,
252 .multi = 2,
253 }, {
254 .manfid = MANFID_QUATECH,
Russell King1fbbac42006-09-16 21:09:41 +0100255 .prodid = PRODID_QUATECH_QUAD_RS232,
256 .multi = 4,
257 }, {
258 .manfid = MANFID_SOCKET,
259 .prodid = PRODID_SOCKET_DUAL_RS232,
260 .multi = 2,
Russell Kingefd92df2006-09-16 23:00:54 +0100261 .config = quirk_config_socket,
262 }, {
263 .manfid = MANFID_SOCKET,
264 .prodid = ~0,
265 .multi = -1,
266 .config = quirk_config_socket,
Russell King1fbbac42006-09-16 21:09:41 +0100267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Yum Rayan16f31112005-05-01 08:59:14 -0700270
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200271static int serial_config(struct pcmcia_device * link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274/*======================================================================
275
276 After a card is removed, serial_remove() will unregister
277 the serial device(s), and release the PCMCIA configuration.
278
279======================================================================*/
280
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200281static void serial_remove(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{
283 struct serial_info *info = link->priv;
284 int i;
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 DEBUG(0, "serial_release(0x%p)\n", link);
287
288 /*
289 * Recheck to see if the device is still configured.
290 */
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100291 for (i = 0; i < info->ndev; i++)
292 serial8250_unregister_port(info->line[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100294 info->p_dev->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100296 if (!info->slave)
297 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298}
299
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200300static int serial_suspend(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100302 struct serial_info *info = link->priv;
303 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100305 for (i = 0; i < info->ndev; i++)
306 serial8250_suspend_port(info->line[i]);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100307
308 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309}
310
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200311static int serial_resume(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312{
Russell Kingfe59d532006-10-01 17:14:07 +0100313 struct serial_info *info = link->priv;
314 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Russell Kingfe59d532006-10-01 17:14:07 +0100316 for (i = 0; i < info->ndev; i++)
317 serial8250_resume_port(info->line[i]);
Russell King7ef057f2006-09-16 22:45:41 +0100318
Russell Kingfe59d532006-10-01 17:14:07 +0100319 if (info->quirk && info->quirk->wakeup)
320 info->quirk->wakeup(link);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100321
322 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323}
324
325/*======================================================================
326
327 serial_attach() creates an "instance" of the driver, allocating
328 local data structures for one device. The device is registered
329 with Card Services.
330
331======================================================================*/
332
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200333static int serial_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
335 struct serial_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 DEBUG(0, "serial_attach()\n");
338
339 /* Create new serial device */
Burman Yan8f31bb32007-02-14 00:33:07 -0800340 info = kzalloc(sizeof (*info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 if (!info)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100342 return -ENOMEM;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200343 info->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 link->priv = info;
345
346 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
347 link->io.NumPorts1 = 8;
Komuro5e7bf8c2007-10-28 11:26:17 +0900348 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
350 link->conf.Attributes = CONF_ENABLE_IRQ;
351 if (do_sound) {
352 link->conf.Attributes |= CONF_ENABLE_SPKR;
353 link->conf.Status = CCSR_AUDIO_ENA;
354 }
355 link->conf.IntType = INT_MEMORY_AND_IO;
356
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200357 return serial_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
360/*======================================================================
361
362 This deletes a driver "instance". The device is de-registered
363 with Card Services. If it has been released, all local data
364 structures are freed. Otherwise, the structures will be freed
365 when the device is released.
366
367======================================================================*/
368
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200369static void serial_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370{
371 struct serial_info *info = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373 DEBUG(0, "serial_detach(0x%p)\n", link);
374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 /*
376 * Ensure any outstanding scheduled tasks are completed.
377 */
378 flush_scheduled_work();
379
380 /*
381 * Ensure that the ports have been released.
382 */
383 serial_remove(link);
384
Dominik Brodowskib4635812005-11-14 21:25:35 +0100385 /* free bits */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 kfree(info);
387}
388
389/*====================================================================*/
390
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200391static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
Olof Johansson906da802008-02-04 22:27:35 -0800392 unsigned int iobase, int irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
394 struct uart_port port;
395 int line;
396
397 memset(&port, 0, sizeof (struct uart_port));
398 port.iobase = iobase;
399 port.irq = irq;
400 port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
401 port.uartclk = 1843200;
402 port.dev = &handle_to_dev(handle);
403 if (buggy_uart)
404 port.flags |= UPF_BUGGY_UART;
Russell Kingf3d10682006-09-16 23:07:46 +0100405
406 if (info->quirk && info->quirk->setup)
407 info->quirk->setup(handle, &port);
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 line = serial8250_register_port(&port);
410 if (line < 0) {
411 printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
412 "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
413 return -EINVAL;
414 }
415
416 info->line[info->ndev] = line;
417 sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
418 info->node[info->ndev].major = TTY_MAJOR;
419 info->node[info->ndev].minor = 0x40 + line;
420 if (info->ndev > 0)
421 info->node[info->ndev - 1].next = &info->node[info->ndev];
422 info->ndev++;
423
424 return 0;
425}
426
427/*====================================================================*/
428
429static int
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200430first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
432 int i;
433 i = pcmcia_get_first_tuple(handle, tuple);
434 if (i != CS_SUCCESS)
435 return CS_NO_MORE_ITEMS;
436 i = pcmcia_get_tuple_data(handle, tuple);
437 if (i != CS_SUCCESS)
438 return i;
439 return pcmcia_parse_tuple(handle, tuple, parse);
440}
441
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200442/*====================================================================*/
443
444static int simple_config_check(struct pcmcia_device *p_dev,
445 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200446 cistpl_cftable_entry_t *dflt,
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200447 void *priv_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448{
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200449 static const int size_table[2] = { 8, 16 };
450 int *try = priv_data;
451
452 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
453 p_dev->conf.Vpp =
454 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
455
456 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
457 && (cf->io.win[0].base != 0)) {
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200458 p_dev->io.BasePort1 = cf->io.win[0].base;
459 p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
460 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
461 if (!pcmcia_request_io(p_dev, &p_dev->io))
462 return 0;
463 }
464 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465}
466
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200467static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
468 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200469 cistpl_cftable_entry_t *dflt,
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200470 void *priv_data)
471{
472 static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
473 int j;
474
475 if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200476 for (j = 0; j < 5; j++) {
477 p_dev->io.BasePort1 = base[j];
478 p_dev->io.IOAddrLines = base[j] ? 16 : 3;
479 if (!pcmcia_request_io(p_dev, &p_dev->io))
480 return 0;
481 }
482 }
483 return -ENODEV;
484}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200486static int simple_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 struct serial_info *info = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 config_info_t config;
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200490 int i, try;
Yum Rayan16f31112005-05-01 08:59:14 -0700491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 /* If the card is already configured, look up the port and irq */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200493 i = pcmcia_get_configuration_info(link, &config);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
Olof Johansson906da802008-02-04 22:27:35 -0800495 unsigned int port = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
497 port = config.BasePort2;
498 info->slave = 1;
499 } else if ((info->manfid == MANFID_OSITECH) &&
500 (config.NumPorts1 == 0x40)) {
501 port = config.BasePort1 + 0x28;
502 info->slave = 1;
503 }
Yum Rayan16f31112005-05-01 08:59:14 -0700504 if (info->slave) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200505 return setup_serial(link, info, port, config.AssignedIRQ);
Yum Rayan16f31112005-05-01 08:59:14 -0700506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200509 /* First pass: look for a config entry that looks normal.
510 * Two tries: without IO aliases, then with aliases */
511 for (try = 0; try < 4; try++)
512 if (!pcmcia_loop_config(link, simple_config_check, &try))
513 goto found_port;
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 /* Second pass: try to find an entry that isn't picky about
516 its base address, then try to grab any standard serial port
517 address, and finally try to get any free port. */
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200518 if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
519 goto found_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200521 printk(KERN_NOTICE
522 "serial_cs: no usable port range found, giving up\n");
523 cs_error(link, RequestIO, i);
524 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200526found_port:
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200527 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200529 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 link->irq.AssignedIRQ = 0;
531 }
532 if (info->multi && (info->manfid == MANFID_3COM))
533 link->conf.ConfigIndex &= ~(0x08);
Russell Kingefd92df2006-09-16 23:00:54 +0100534
535 /*
536 * Apply any configuration quirks.
537 */
538 if (info->quirk && info->quirk->config)
539 info->quirk->config(link);
540
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200541 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200543 cs_error(link, RequestConfiguration, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return -1;
545 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200546 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547}
548
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200549static int multi_config_check(struct pcmcia_device *p_dev,
550 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200551 cistpl_cftable_entry_t *dflt,
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200552 void *priv_data)
553{
554 int *base2 = priv_data;
555
556 /* The quad port cards have bad CIS's, so just look for a
557 window larger than 8 ports and assume it will be right */
558 if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200559 p_dev->io.BasePort1 = cf->io.win[0].base;
560 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
561 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
562 *base2 = p_dev->io.BasePort1 + 8;
563 return 0;
564 }
565 }
566 return -ENODEV;
567}
568
569static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
570 cistpl_cftable_entry_t *cf,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200571 cistpl_cftable_entry_t *dflt,
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200572 void *priv_data)
573{
574 int *base2 = priv_data;
575
576 if (cf->io.nwin == 2) {
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200577 p_dev->io.BasePort1 = cf->io.win[0].base;
578 p_dev->io.BasePort2 = cf->io.win[1].base;
579 p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
580 if (!pcmcia_request_io(p_dev, &p_dev->io)) {
581 *base2 = p_dev->io.BasePort2;
582 return 0;
583 }
584 }
585 return -ENODEV;
586}
587
588static int multi_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 struct serial_info *info = link->priv;
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200591 int i, base2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 /* First, look for a generic full-sized window */
594 link->io.NumPorts1 = info->multi * 8;
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200595 if (pcmcia_loop_config(link, multi_config_check, &base2)) {
596 /* If that didn't work, look for two windows */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 link->io.NumPorts1 = link->io.NumPorts2 = 8;
598 info->multi = 2;
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200599 if (pcmcia_loop_config(link, multi_config_check_notpicky,
600 &base2)) {
601 printk(KERN_NOTICE "serial_cs: no usable port range"
602 "found, giving up\n");
603 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
605 }
606
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200607 i = pcmcia_request_irq(link, &link->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 if (i != CS_SUCCESS) {
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200609 /* FIXME: comment does not fit, error handling does not fit */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 printk(KERN_NOTICE
611 "serial_cs: no usable port range found, giving up\n");
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200612 cs_error(link, RequestIRQ, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 link->irq.AssignedIRQ = 0;
614 }
Russell Kingefd92df2006-09-16 23:00:54 +0100615
616 /*
617 * Apply any configuration quirks.
618 */
619 if (info->quirk && info->quirk->config)
620 info->quirk->config(link);
621
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200622 i = pcmcia_request_configuration(link, &link->conf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200624 cs_error(link, RequestConfiguration, i);
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200625 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 }
627
628 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800629 * 8 registers are for the UART, the others are extra registers.
630 * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
631 */
632 if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
633 info->prodid == PRODID_POSSIO_GCC)) {
634 int err;
635
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200636 if (link->conf.ConfigIndex == 1 ||
637 link->conf.ConfigIndex == 3) {
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800638 err = setup_serial(link, info, base2,
639 link->irq.AssignedIRQ);
640 base2 = link->io.BasePort1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 } else {
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800642 err = setup_serial(link, info, link->io.BasePort1,
643 link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 }
Petr Vandrovec30bac7a2006-02-10 02:04:00 -0800645 info->c950ctrl = base2;
Russell King7ef057f2006-09-16 22:45:41 +0100646
647 /*
648 * FIXME: We really should wake up the port prior to
649 * handing it over to the serial layer.
650 */
651 if (info->quirk && info->quirk->wakeup)
652 info->quirk->wakeup(link);
653
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200654 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 }
656
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200657 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 for (i = 0; i < info->multi - 1; i++)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200659 setup_serial(link, info, base2 + (8 * i),
Yum Rayan16f31112005-05-01 08:59:14 -0700660 link->irq.AssignedIRQ);
Dominik Brodowski84e2d342008-07-29 08:38:55 +0200661 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662}
663
664/*======================================================================
665
666 serial_config() is scheduled to run after a CARD_INSERTION event
667 is received, to configure the PCMCIA socket, and to make the
668 serial device available to the system.
669
670======================================================================*/
671
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200672static int serial_config(struct pcmcia_device * link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 struct serial_info *info = link->priv;
Yum Rayan16f31112005-05-01 08:59:14 -0700675 struct serial_cfg_mem *cfg_mem;
676 tuple_t *tuple;
677 u_char *buf;
678 cisparse_t *parse;
679 cistpl_cftable_entry_t *cf;
Dominik Brodowskiaf2b3b52006-10-25 21:49:27 -0400680 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682 DEBUG(0, "serial_config(0x%p)\n", link);
683
Yum Rayan16f31112005-05-01 08:59:14 -0700684 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
685 if (!cfg_mem)
686 goto failed;
687
688 tuple = &cfg_mem->tuple;
689 parse = &cfg_mem->parse;
690 cf = &parse->cftable_entry;
691 buf = cfg_mem->buf;
692
693 tuple->TupleData = (cisdata_t *) buf;
694 tuple->TupleOffset = 0;
695 tuple->TupleDataMax = 255;
696 tuple->Attributes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 /* Is this a compliant multifunction card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700699 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
700 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200701 info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
703 /* Is this a multiport card? */
Yum Rayan16f31112005-05-01 08:59:14 -0700704 tuple->DesiredTuple = CISTPL_MANFID;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400705 info->manfid = link->manf_id;
706 info->prodid = link->card_id;
Russell Kinga8244b52006-09-16 21:26:16 +0100707
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400708 for (i = 0; i < ARRAY_SIZE(quirks); i++)
709 if ((quirks[i].manfid == ~0 ||
710 quirks[i].manfid == info->manfid) &&
711 (quirks[i].prodid == ~0 ||
712 quirks[i].prodid == info->prodid)) {
713 info->quirk = &quirks[i];
714 break;
715 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 /* Another check for dual-serial cards: look for either serial or
718 multifunction cards that ask for appropriate IO port ranges */
Yum Rayan16f31112005-05-01 08:59:14 -0700719 tuple->DesiredTuple = CISTPL_FUNCID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 if ((info->multi == 0) &&
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400721 (link->has_func_id) &&
722 ((link->func_id == CISTPL_FUNCID_MULTI) ||
723 (link->func_id == CISTPL_FUNCID_SERIAL))) {
Yum Rayan16f31112005-05-01 08:59:14 -0700724 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200725 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
727 info->multi = cf->io.win[0].len >> 3;
728 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
729 (cf->io.win[1].len == 8))
730 info->multi = 2;
731 }
732 }
733
Russell King1fbbac42006-09-16 21:09:41 +0100734 /*
735 * Apply any multi-port quirk.
736 */
737 if (info->quirk && info->quirk->multi != -1)
738 info->multi = info->quirk->multi;
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 if (info->multi > 1)
741 multi_config(link);
742 else
743 simple_config(link);
744
745 if (info->ndev == 0)
746 goto failed;
747
Russell Kingeee3a882006-09-16 21:34:11 +0100748 /*
749 * Apply any post-init quirk. FIXME: This should really happen
750 * before we register the port, since it might already be in use.
751 */
752 if (info->quirk && info->quirk->post)
753 if (info->quirk->post(link))
754 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Dominik Brodowskifd238232006-03-05 10:45:09 +0100756 link->dev_node = &info->node[0];
Yum Rayan16f31112005-05-01 08:59:14 -0700757 kfree(cfg_mem);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200758 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 failed:
761 serial_remove(link);
Yum Rayan16f31112005-05-01 08:59:14 -0700762 kfree(cfg_mem);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200763 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764}
765
Dominik Brodowski325aa292005-06-27 16:28:18 -0700766static struct pcmcia_device_id serial_ids[] = {
767 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
768 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
769 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
770 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
771 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
772 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
773 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
774 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
775 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
776 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
777 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
778 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
Jun Komurof4d75102005-06-27 16:28:44 -0700779 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
780 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700781 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
782 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
783 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
784 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
785 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
786 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
787 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
788 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
789 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
Komurod277ad02005-07-28 01:07:24 -0700790 PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700791 PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
792 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
793 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
794 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
795 PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
796 PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
Komuro40738f32007-05-27 08:57:58 +0900797 PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
798 PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
Komurod277ad02005-07-28 01:07:24 -0700799 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
800 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700801 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
802 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
803 PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
Komurod277ad02005-07-28 01:07:24 -0700804 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
Komuro40738f32007-05-27 08:57:58 +0900805 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
806 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700807 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
808 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
809 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
810 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
811 PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
812 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
813 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
814 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
815 PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
816 PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
817 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100818 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700819 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
820 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
821 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
822 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
823 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
824 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
825 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
826 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
827 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
828 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
829 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
830 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
831 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
832 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
833 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
834 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
835 PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
836 PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
Domen Puncer1de9ced2006-03-06 10:25:53 +0100837 PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700838 PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
839 PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
840 PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
841 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
842 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
843 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
844 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
845 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
Komurod277ad02005-07-28 01:07:24 -0700846 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700847 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
848 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
849 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
850 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
851 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
852 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
853 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
Sergei Organovbb289bc2007-02-02 20:43:12 +0300854 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700855 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
856 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
857 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
858 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
859 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
860 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
861 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
862 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"),
863 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
864 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
865 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
Eric Leblond64da82e2007-10-16 01:23:54 -0700866 PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
Dominik Brodowskia42f0dc2005-09-24 23:12:44 -0700867 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 +0100868 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
869 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 -0700870 PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
871 PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
872 PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
873 PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
Dominik Brodowskifec21882006-04-26 19:57:32 +0200874 PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
Tony Olech44e5e332006-11-29 08:54:51 +0000875 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b),
876 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83),
877 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490),
878 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235),
879 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3),
880 PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442),
881 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190),
882 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262),
883 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d),
884 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa),
885 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903),
886 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676),
887 PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767),
888 PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
889 PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
890 PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
891 PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
892 PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
893 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7),
894 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41),
895 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029),
896 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
897 PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
898 PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4),
Attila Kinali9d9b7ad2007-10-07 00:24:38 -0700899 PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b),
Dominik Brodowski325aa292005-06-27 16:28:18 -0700900 /* too generic */
901 /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
902 /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
903 PCMCIA_DEVICE_FUNC_ID(2),
904 PCMCIA_DEVICE_NULL,
905};
906MODULE_DEVICE_TABLE(pcmcia, serial_ids);
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908static struct pcmcia_driver serial_cs_driver = {
909 .owner = THIS_MODULE,
910 .drv = {
911 .name = "serial_cs",
912 },
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100913 .probe = serial_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100914 .remove = serial_detach,
Dominik Brodowski325aa292005-06-27 16:28:18 -0700915 .id_table = serial_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100916 .suspend = serial_suspend,
917 .resume = serial_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918};
919
920static int __init init_serial_cs(void)
921{
922 return pcmcia_register_driver(&serial_cs_driver);
923}
924
925static void __exit exit_serial_cs(void)
926{
927 pcmcia_unregister_driver(&serial_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928}
929
930module_init(init_serial_cs);
931module_exit(exit_serial_cs);
932
933MODULE_LICENSE("GPL");