]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/serial/serial_cs.c
[SERIAL] serial_cs: Use clean up multiport card detection
[net-next-2.6.git] / drivers / serial / serial_cs.c
CommitLineData
1da177e4
LT
1/*======================================================================
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>
30bac7aa 44#include <linux/delay.h>
1da177e4
LT
45#include <linux/major.h>
46#include <asm/io.h>
47#include <asm/system.h>
48
1da177e4
LT
49#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
cb3592be 89static const struct multi_id multi_id[] = {
1da177e4
LT
90 { 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};
1da177e4
LT
98
99struct serial_info {
fd238232 100 struct pcmcia_device *p_dev;
1da177e4
LT
101 int ndev;
102 int multi;
103 int slave;
104 int manfid;
30bac7aa
PV
105 int prodid;
106 int c950ctrl;
1da177e4
LT
107 dev_node_t node[4];
108 int line[4];
109};
110
16f31113
YR
111struct serial_cfg_mem {
112 tuple_t tuple;
113 cisparse_t parse;
114 u_char buf[256];
115};
116
117
15b99ac1 118static int serial_config(struct pcmcia_device * link);
1da177e4 119
1da177e4 120
30bac7aa
PV
121static void wakeup_card(struct serial_info *info)
122{
123 int ctrl = info->c950ctrl;
124
125 if (info->manfid == MANFID_OXSEMI) {
126 outb(12, ctrl + 1);
127 } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
128 /* request_region? oxsemi branch does no request_region too... */
129 /* This sequence is needed to properly initialize MC45 attached to OXCF950.
130 * I tried decreasing these msleep()s, but it worked properly (survived
131 * 1000 stop/start operations) with these timeouts (or bigger). */
132 outb(0xA, ctrl + 1);
133 msleep(100);
134 outb(0xE, ctrl + 1);
135 msleep(300);
136 outb(0xC, ctrl + 1);
137 msleep(100);
138 outb(0xE, ctrl + 1);
139 msleep(200);
140 outb(0xF, ctrl + 1);
141 msleep(100);
142 outb(0xE, ctrl + 1);
143 msleep(100);
144 outb(0xC, ctrl + 1);
145 }
146}
147
1da177e4
LT
148/*======================================================================
149
150 After a card is removed, serial_remove() will unregister
151 the serial device(s), and release the PCMCIA configuration.
152
153======================================================================*/
154
fba395ee 155static void serial_remove(struct pcmcia_device *link)
1da177e4
LT
156{
157 struct serial_info *info = link->priv;
158 int i;
159
1da177e4
LT
160 DEBUG(0, "serial_release(0x%p)\n", link);
161
162 /*
163 * Recheck to see if the device is still configured.
164 */
e2d40963
DB
165 for (i = 0; i < info->ndev; i++)
166 serial8250_unregister_port(info->line[i]);
1da177e4 167
e2d40963 168 info->p_dev->dev_node = NULL;
1da177e4 169
e2d40963
DB
170 if (!info->slave)
171 pcmcia_disable_device(link);
1da177e4
LT
172}
173
fba395ee 174static int serial_suspend(struct pcmcia_device *link)
1da177e4 175{
e2d40963
DB
176 struct serial_info *info = link->priv;
177 int i;
1da177e4 178
e2d40963
DB
179 for (i = 0; i < info->ndev; i++)
180 serial8250_suspend_port(info->line[i]);
98e4c28b
DB
181
182 return 0;
1da177e4
LT
183}
184
fba395ee 185static int serial_resume(struct pcmcia_device *link)
1da177e4 186{
9940ec36 187 if (pcmcia_dev_present(link)) {
1da177e4
LT
188 struct serial_info *info = link->priv;
189 int i;
190
1da177e4
LT
191 for (i = 0; i < info->ndev; i++)
192 serial8250_resume_port(info->line[i]);
30bac7aa 193 wakeup_card(info);
1da177e4 194 }
98e4c28b
DB
195
196 return 0;
1da177e4
LT
197}
198
199/*======================================================================
200
201 serial_attach() creates an "instance" of the driver, allocating
202 local data structures for one device. The device is registered
203 with Card Services.
204
205======================================================================*/
206
fba395ee 207static int serial_probe(struct pcmcia_device *link)
1da177e4
LT
208{
209 struct serial_info *info;
1da177e4
LT
210
211 DEBUG(0, "serial_attach()\n");
212
213 /* Create new serial device */
214 info = kmalloc(sizeof (*info), GFP_KERNEL);
215 if (!info)
f8cfa618 216 return -ENOMEM;
1da177e4 217 memset(info, 0, sizeof (*info));
fba395ee 218 info->p_dev = link;
1da177e4
LT
219 link->priv = info;
220
221 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
222 link->io.NumPorts1 = 8;
223 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
224 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
225 link->conf.Attributes = CONF_ENABLE_IRQ;
226 if (do_sound) {
227 link->conf.Attributes |= CONF_ENABLE_SPKR;
228 link->conf.Status = CCSR_AUDIO_ENA;
229 }
230 link->conf.IntType = INT_MEMORY_AND_IO;
231
15b99ac1 232 return serial_config(link);
1da177e4
LT
233}
234
235/*======================================================================
236
237 This deletes a driver "instance". The device is de-registered
238 with Card Services. If it has been released, all local data
239 structures are freed. Otherwise, the structures will be freed
240 when the device is released.
241
242======================================================================*/
243
fba395ee 244static void serial_detach(struct pcmcia_device *link)
1da177e4
LT
245{
246 struct serial_info *info = link->priv;
1da177e4
LT
247
248 DEBUG(0, "serial_detach(0x%p)\n", link);
249
1da177e4
LT
250 /*
251 * Ensure any outstanding scheduled tasks are completed.
252 */
253 flush_scheduled_work();
254
255 /*
256 * Ensure that the ports have been released.
257 */
258 serial_remove(link);
259
b4635811 260 /* free bits */
1da177e4
LT
261 kfree(info);
262}
263
264/*====================================================================*/
265
fba395ee 266static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
1da177e4
LT
267 kio_addr_t iobase, int irq)
268{
269 struct uart_port port;
270 int line;
271
272 memset(&port, 0, sizeof (struct uart_port));
273 port.iobase = iobase;
274 port.irq = irq;
275 port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
276 port.uartclk = 1843200;
277 port.dev = &handle_to_dev(handle);
278 if (buggy_uart)
279 port.flags |= UPF_BUGGY_UART;
280 line = serial8250_register_port(&port);
281 if (line < 0) {
282 printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
283 "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
284 return -EINVAL;
285 }
286
287 info->line[info->ndev] = line;
288 sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
289 info->node[info->ndev].major = TTY_MAJOR;
290 info->node[info->ndev].minor = 0x40 + line;
291 if (info->ndev > 0)
292 info->node[info->ndev - 1].next = &info->node[info->ndev];
293 info->ndev++;
294
295 return 0;
296}
297
298/*====================================================================*/
299
300static int
fba395ee 301first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
1da177e4
LT
302{
303 int i;
304 i = pcmcia_get_first_tuple(handle, tuple);
305 if (i != CS_SUCCESS)
306 return CS_NO_MORE_ITEMS;
307 i = pcmcia_get_tuple_data(handle, tuple);
308 if (i != CS_SUCCESS)
309 return i;
310 return pcmcia_parse_tuple(handle, tuple, parse);
311}
312
313static int
fba395ee 314next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
1da177e4
LT
315{
316 int i;
317 i = pcmcia_get_next_tuple(handle, tuple);
318 if (i != CS_SUCCESS)
319 return CS_NO_MORE_ITEMS;
320 i = pcmcia_get_tuple_data(handle, tuple);
321 if (i != CS_SUCCESS)
322 return i;
323 return pcmcia_parse_tuple(handle, tuple, parse);
324}
325
326/*====================================================================*/
327
fba395ee 328static int simple_config(struct pcmcia_device *link)
1da177e4 329{
cb3592be
AV
330 static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
331 static const int size_table[2] = { 8, 16 };
1da177e4 332 struct serial_info *info = link->priv;
16f31113
YR
333 struct serial_cfg_mem *cfg_mem;
334 tuple_t *tuple;
335 u_char *buf;
336 cisparse_t *parse;
337 cistpl_cftable_entry_t *cf;
1da177e4
LT
338 config_info_t config;
339 int i, j, try;
340 int s;
341
16f31113
YR
342 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
343 if (!cfg_mem)
344 return -1;
345
346 tuple = &cfg_mem->tuple;
347 parse = &cfg_mem->parse;
348 cf = &parse->cftable_entry;
349 buf = cfg_mem->buf;
350
1da177e4 351 /* If the card is already configured, look up the port and irq */
fba395ee 352 i = pcmcia_get_configuration_info(link, &config);
1da177e4
LT
353 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
354 kio_addr_t port = 0;
355 if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
356 port = config.BasePort2;
357 info->slave = 1;
358 } else if ((info->manfid == MANFID_OSITECH) &&
359 (config.NumPorts1 == 0x40)) {
360 port = config.BasePort1 + 0x28;
361 info->slave = 1;
362 }
16f31113
YR
363 if (info->slave) {
364 kfree(cfg_mem);
fba395ee 365 return setup_serial(link, info, port, config.AssignedIRQ);
16f31113 366 }
1da177e4 367 }
1da177e4
LT
368
369 /* First pass: look for a config entry that looks normal. */
16f31113
YR
370 tuple->TupleData = (cisdata_t *) buf;
371 tuple->TupleOffset = 0;
372 tuple->TupleDataMax = 255;
373 tuple->Attributes = 0;
374 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
1da177e4
LT
375 /* Two tries: without IO aliases, then with aliases */
376 for (s = 0; s < 2; s++) {
377 for (try = 0; try < 2; try++) {
fba395ee 378 i = first_tuple(link, tuple, parse);
1da177e4
LT
379 while (i != CS_NO_MORE_ITEMS) {
380 if (i != CS_SUCCESS)
381 goto next_entry;
382 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
70294b46 383 link->conf.Vpp =
1da177e4
LT
384 cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
385 if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
386 (cf->io.win[0].base != 0)) {
387 link->conf.ConfigIndex = cf->index;
388 link->io.BasePort1 = cf->io.win[0].base;
389 link->io.IOAddrLines = (try == 0) ?
390 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
fba395ee 391 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
392 if (i == CS_SUCCESS)
393 goto found_port;
394 }
395next_entry:
fba395ee 396 i = next_tuple(link, tuple, parse);
1da177e4
LT
397 }
398 }
399 }
400 /* Second pass: try to find an entry that isn't picky about
401 its base address, then try to grab any standard serial port
402 address, and finally try to get any free port. */
fba395ee 403 i = first_tuple(link, tuple, parse);
1da177e4
LT
404 while (i != CS_NO_MORE_ITEMS) {
405 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
406 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
407 link->conf.ConfigIndex = cf->index;
408 for (j = 0; j < 5; j++) {
409 link->io.BasePort1 = base[j];
410 link->io.IOAddrLines = base[j] ? 16 : 3;
fba395ee 411 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
412 if (i == CS_SUCCESS)
413 goto found_port;
414 }
415 }
fba395ee 416 i = next_tuple(link, tuple, parse);
1da177e4
LT
417 }
418
419 found_port:
420 if (i != CS_SUCCESS) {
421 printk(KERN_NOTICE
422 "serial_cs: no usable port range found, giving up\n");
fba395ee 423 cs_error(link, RequestIO, i);
16f31113 424 kfree(cfg_mem);
1da177e4
LT
425 return -1;
426 }
427
fba395ee 428 i = pcmcia_request_irq(link, &link->irq);
1da177e4 429 if (i != CS_SUCCESS) {
fba395ee 430 cs_error(link, RequestIRQ, i);
1da177e4
LT
431 link->irq.AssignedIRQ = 0;
432 }
433 if (info->multi && (info->manfid == MANFID_3COM))
434 link->conf.ConfigIndex &= ~(0x08);
fba395ee 435 i = pcmcia_request_configuration(link, &link->conf);
1da177e4 436 if (i != CS_SUCCESS) {
fba395ee 437 cs_error(link, RequestConfiguration, i);
16f31113 438 kfree(cfg_mem);
1da177e4
LT
439 return -1;
440 }
16f31113 441 kfree(cfg_mem);
fba395ee 442 return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
1da177e4
LT
443}
444
fba395ee 445static int multi_config(struct pcmcia_device * link)
1da177e4 446{
1da177e4 447 struct serial_info *info = link->priv;
16f31113
YR
448 struct serial_cfg_mem *cfg_mem;
449 tuple_t *tuple;
450 u_char *buf;
451 cisparse_t *parse;
452 cistpl_cftable_entry_t *cf;
16f31113
YR
453 int i, rc, base2 = 0;
454
455 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
456 if (!cfg_mem)
457 return -1;
458 tuple = &cfg_mem->tuple;
459 parse = &cfg_mem->parse;
460 cf = &parse->cftable_entry;
461 buf = cfg_mem->buf;
1da177e4 462
16f31113
YR
463 tuple->TupleData = (cisdata_t *) buf;
464 tuple->TupleOffset = 0;
465 tuple->TupleDataMax = 255;
466 tuple->Attributes = 0;
467 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
1da177e4
LT
468
469 /* First, look for a generic full-sized window */
470 link->io.NumPorts1 = info->multi * 8;
fba395ee 471 i = first_tuple(link, tuple, parse);
1da177e4
LT
472 while (i != CS_NO_MORE_ITEMS) {
473 /* The quad port cards have bad CIS's, so just look for a
474 window larger than 8 ports and assume it will be right */
475 if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
476 (cf->io.win[0].len > 8)) {
477 link->conf.ConfigIndex = cf->index;
478 link->io.BasePort1 = cf->io.win[0].base;
479 link->io.IOAddrLines =
480 cf->io.flags & CISTPL_IO_LINES_MASK;
fba395ee 481 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
482 base2 = link->io.BasePort1 + 8;
483 if (i == CS_SUCCESS)
484 break;
485 }
fba395ee 486 i = next_tuple(link, tuple, parse);
1da177e4
LT
487 }
488
489 /* If that didn't work, look for two windows */
490 if (i != CS_SUCCESS) {
491 link->io.NumPorts1 = link->io.NumPorts2 = 8;
492 info->multi = 2;
fba395ee 493 i = first_tuple(link, tuple, parse);
1da177e4
LT
494 while (i != CS_NO_MORE_ITEMS) {
495 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
496 link->conf.ConfigIndex = cf->index;
497 link->io.BasePort1 = cf->io.win[0].base;
498 link->io.BasePort2 = cf->io.win[1].base;
499 link->io.IOAddrLines =
500 cf->io.flags & CISTPL_IO_LINES_MASK;
fba395ee 501 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
502 base2 = link->io.BasePort2;
503 if (i == CS_SUCCESS)
504 break;
505 }
fba395ee 506 i = next_tuple(link, tuple, parse);
1da177e4
LT
507 }
508 }
509
510 if (i != CS_SUCCESS) {
fba395ee 511 cs_error(link, RequestIO, i);
16f31113
YR
512 rc = -1;
513 goto free_cfg_mem;
1da177e4
LT
514 }
515
fba395ee 516 i = pcmcia_request_irq(link, &link->irq);
1da177e4
LT
517 if (i != CS_SUCCESS) {
518 printk(KERN_NOTICE
519 "serial_cs: no usable port range found, giving up\n");
fba395ee 520 cs_error(link, RequestIRQ, i);
1da177e4
LT
521 link->irq.AssignedIRQ = 0;
522 }
523 /* Socket Dual IO: this enables irq's for second port */
524 if (info->multi && (info->manfid == MANFID_SOCKET)) {
525 link->conf.Present |= PRESENT_EXT_STATUS;
526 link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
527 }
fba395ee 528 i = pcmcia_request_configuration(link, &link->conf);
1da177e4 529 if (i != CS_SUCCESS) {
fba395ee 530 cs_error(link, RequestConfiguration, i);
16f31113
YR
531 rc = -1;
532 goto free_cfg_mem;
1da177e4
LT
533 }
534
535 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
30bac7aa
PV
536 * 8 registers are for the UART, the others are extra registers.
537 * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
538 */
539 if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
540 info->prodid == PRODID_POSSIO_GCC)) {
541 int err;
542
1da177e4 543 if (cf->index == 1 || cf->index == 3) {
30bac7aa
PV
544 err = setup_serial(link, info, base2,
545 link->irq.AssignedIRQ);
546 base2 = link->io.BasePort1;
1da177e4 547 } else {
30bac7aa
PV
548 err = setup_serial(link, info, link->io.BasePort1,
549 link->irq.AssignedIRQ);
1da177e4 550 }
30bac7aa
PV
551 info->c950ctrl = base2;
552 wakeup_card(info);
16f31113
YR
553 rc = 0;
554 goto free_cfg_mem;
1da177e4
LT
555 }
556
fba395ee 557 setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
1da177e4 558 /* The Nokia cards are not really multiport cards */
16f31113
YR
559 if (info->manfid == MANFID_NOKIA) {
560 rc = 0;
561 goto free_cfg_mem;
562 }
1da177e4 563 for (i = 0; i < info->multi - 1; i++)
fba395ee 564 setup_serial(link, info, base2 + (8 * i),
16f31113
YR
565 link->irq.AssignedIRQ);
566 rc = 0;
567free_cfg_mem:
568 kfree(cfg_mem);
569 return rc;
1da177e4
LT
570}
571
572/*======================================================================
573
574 serial_config() is scheduled to run after a CARD_INSERTION event
575 is received, to configure the PCMCIA socket, and to make the
576 serial device available to the system.
577
578======================================================================*/
579
15b99ac1 580static int serial_config(struct pcmcia_device * link)
1da177e4 581{
1da177e4 582 struct serial_info *info = link->priv;
16f31113
YR
583 struct serial_cfg_mem *cfg_mem;
584 tuple_t *tuple;
585 u_char *buf;
586 cisparse_t *parse;
587 cistpl_cftable_entry_t *cf;
1da177e4
LT
588 int i, last_ret, last_fn;
589
590 DEBUG(0, "serial_config(0x%p)\n", link);
591
16f31113
YR
592 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
593 if (!cfg_mem)
594 goto failed;
595
596 tuple = &cfg_mem->tuple;
597 parse = &cfg_mem->parse;
598 cf = &parse->cftable_entry;
599 buf = cfg_mem->buf;
600
601 tuple->TupleData = (cisdata_t *) buf;
602 tuple->TupleOffset = 0;
603 tuple->TupleDataMax = 255;
604 tuple->Attributes = 0;
1da177e4 605 /* Get configuration register information */
16f31113 606 tuple->DesiredTuple = CISTPL_CONFIG;
fba395ee 607 last_ret = first_tuple(link, tuple, parse);
1da177e4
LT
608 if (last_ret != CS_SUCCESS) {
609 last_fn = ParseTuple;
610 goto cs_failed;
611 }
16f31113
YR
612 link->conf.ConfigBase = parse->config.base;
613 link->conf.Present = parse->config.rmask[0];
1da177e4 614
1da177e4 615 /* Is this a compliant multifunction card? */
16f31113
YR
616 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
617 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
fba395ee 618 info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
1da177e4
LT
619
620 /* Is this a multiport card? */
16f31113 621 tuple->DesiredTuple = CISTPL_MANFID;
fba395ee 622 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
f1fc3990 623 info->manfid = parse->manfid.manf;
43549ad7
RK
624 info->prodid = parse->manfid.card;
625 for (i = 0; i < ARRAY_SIZE(multi_id); i++)
1da177e4 626 if ((info->manfid == multi_id[i].manfid) &&
43549ad7
RK
627 (info->prodid == multi_id[i].prodid)) {
628 info->multi = multi_id[i].multi;
1da177e4 629 break;
43549ad7 630 }
1da177e4
LT
631 }
632
633 /* Another check for dual-serial cards: look for either serial or
634 multifunction cards that ask for appropriate IO port ranges */
16f31113 635 tuple->DesiredTuple = CISTPL_FUNCID;
1da177e4 636 if ((info->multi == 0) &&
fba395ee 637 ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
16f31113
YR
638 (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
639 (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
640 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
fba395ee 641 if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
1da177e4
LT
642 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
643 info->multi = cf->io.win[0].len >> 3;
644 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
645 (cf->io.win[1].len == 8))
646 info->multi = 2;
647 }
648 }
649
650 if (info->multi > 1)
651 multi_config(link);
652 else
653 simple_config(link);
654
655 if (info->ndev == 0)
656 goto failed;
657
658 if (info->manfid == MANFID_IBM) {
659 conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
fba395ee 660 last_ret = pcmcia_access_configuration_register(link, &reg);
1da177e4
LT
661 if (last_ret) {
662 last_fn = AccessConfigurationRegister;
663 goto cs_failed;
664 }
665 reg.Action = CS_WRITE;
666 reg.Value = reg.Value | 1;
fba395ee 667 last_ret = pcmcia_access_configuration_register(link, &reg);
1da177e4
LT
668 if (last_ret) {
669 last_fn = AccessConfigurationRegister;
670 goto cs_failed;
671 }
672 }
673
fd238232 674 link->dev_node = &info->node[0];
16f31113 675 kfree(cfg_mem);
15b99ac1 676 return 0;
1da177e4
LT
677
678 cs_failed:
fba395ee 679 cs_error(link, last_fn, last_ret);
1da177e4
LT
680 failed:
681 serial_remove(link);
16f31113 682 kfree(cfg_mem);
15b99ac1 683 return -ENODEV;
1da177e4
LT
684}
685
325aa29f
DB
686static struct pcmcia_device_id serial_ids[] = {
687 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
688 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
689 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
690 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
691 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
692 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
693 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a),
694 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341),
695 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab),
696 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
697 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
698 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
f4d7510d
JK
699 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
700 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
325aa29f
DB
701 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
702 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
703 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
704 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
705 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
706 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
707 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
708 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
709 PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
d277ad0e 710 PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
325aa29f
DB
711 PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
712 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
713 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
714 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
715 PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
716 PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
d277ad0e
K
717 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
718 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
325aa29f
DB
719 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
720 PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
721 PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
d277ad0e 722 PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
325aa29f
DB
723 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
724 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
725 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
726 PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020),
727 PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
728 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
729 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
730 PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
731 PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
732 PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
733 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
1de9cedf 734 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
325aa29f
DB
735 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
736 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
737 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
738 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
739 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
740 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
741 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
742 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
743 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
744 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
745 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
746 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
747 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
748 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
749 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
750 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
751 PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
752 PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
1de9cedf 753 PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
325aa29f
DB
754 PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
755 PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
756 PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
757 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76),
758 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
759 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
760 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
761 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
d277ad0e 762 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
325aa29f
DB
763 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
764 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
765 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
766 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
767 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
768 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
769 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
770 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
771 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
772 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
773 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
774 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
775 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
776 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
777 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"),
778 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
779 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
780 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
a42f0dc4 781 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
f542ff6d
DB
782 PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
783 PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
325aa29f
DB
784 PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
785 PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
786 PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
787 PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
fec21889 788 PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
325aa29f
DB
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
1da177e4
LT
797static struct pcmcia_driver serial_cs_driver = {
798 .owner = THIS_MODULE,
799 .drv = {
800 .name = "serial_cs",
801 },
f8cfa618 802 .probe = serial_probe,
cc3b4866 803 .remove = serial_detach,
325aa29f 804 .id_table = serial_ids,
98e4c28b
DB
805 .suspend = serial_suspend,
806 .resume = serial_resume,
1da177e4
LT
807};
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);
1da177e4
LT
817}
818
819module_init(init_serial_cs);
820module_exit(exit_serial_cs);
821
822MODULE_LICENSE("GPL");