Import 2.3.16
[davej-history.git] / drivers / isdn / eicon / eicon_mod.c
blob587b763b6694bf7e76aef83960965a9927c44d4d
1 /* $Id: eicon_mod.c,v 1.11 1999/08/29 17:23:45 armin Exp $
3 * ISDN lowlevel-module for Eicon.Diehl active cards.
4 *
5 * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
6 * Copyright 1998,99 by Armin Schindler (mac@melware.de)
7 * Copyright 1999 Cytronics & Melware (info@melware.de)
8 *
9 * Thanks to Eicon Technology Diehl GmbH & Co. oHG for
10 * documents, informations and hardware.
12 * Deutsche Telekom AG for S2M support.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * $Log: eicon_mod.c,v $
29 * Revision 1.11 1999/08/29 17:23:45 armin
30 * New setup compat.
31 * Bugfix if compile as not module.
33 * Revision 1.10 1999/08/28 21:32:53 armin
34 * Prepared for fax related functions.
35 * Now compilable without errors/warnings.
37 * Revision 1.9 1999/08/18 20:17:02 armin
38 * Added XLOG function for all cards.
39 * Bugfix of alloc_skb NULL pointer.
41 * Revision 1.8 1999/07/25 15:12:08 armin
42 * fix of some debug logs.
43 * enabled ISA-cards option.
45 * Revision 1.7 1999/07/11 17:16:27 armin
46 * Bugfixes in queue handling.
47 * Added DSP-DTMF decoder functions.
48 * Reorganized ack_handler.
50 * Revision 1.6 1999/06/09 19:31:26 armin
51 * Wrong PLX size for request_region() corrected.
52 * Added first MCA code from Erik Weber.
54 * Revision 1.5 1999/04/01 12:48:35 armin
55 * Changed some log outputs.
57 * Revision 1.4 1999/03/29 11:19:47 armin
58 * I/O stuff now in seperate file (eicon_io.c)
59 * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
61 * Revision 1.3 1999/03/02 12:37:47 armin
62 * Added some important checks.
63 * Analog Modem with DSP.
64 * Channels will be added to Link-Level after loading firmware.
66 * Revision 1.2 1999/01/24 20:14:21 armin
67 * Changed and added debug stuff.
68 * Better data sending. (still problems with tty's flip buffer)
70 * Revision 1.1 1999/01/01 18:09:44 armin
71 * First checkin of new eicon driver.
72 * DIVA-Server BRI/PCI and PRI/PCI are supported.
73 * Old diehl code is obsolete.
78 #define DRIVERPATCH ""
80 #include <linux/config.h>
81 #include <linux/module.h>
82 #include <linux/init.h>
83 #ifdef CONFIG_MCA
84 #include <linux/mca.h>
85 #endif
87 #include "eicon.h"
89 #define INCLUDE_INLINE_FUNCS
91 static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
92 start of card-list */
94 static char *eicon_revision = "$Revision: 1.11 $";
96 extern char *eicon_pci_revision;
97 extern char *eicon_isa_revision;
98 extern char *eicon_idi_revision;
100 #ifdef MODULE
101 #define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
102 #endif
104 #define EICON_CTRL_VERSION 2
106 ulong DebugVar;
108 /* Parameters to be set by insmod */
109 #ifdef CONFIG_ISDN_DRV_EICON_ISA
110 static int membase = -1;
111 static int irq = -1;
112 #endif
113 static char *id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
115 MODULE_DESCRIPTION( "Driver for Eicon.Diehl active ISDN cards");
116 MODULE_AUTHOR( "Armin Schindler");
117 MODULE_SUPPORTED_DEVICE( "ISDN subsystem");
118 MODULE_PARM_DESC(id, "ID-String of first card");
119 MODULE_PARM(id, "s");
120 #ifdef CONFIG_ISDN_DRV_EICON_ISA
121 MODULE_PARM_DESC(membase, "Base address of first ISA card");
122 MODULE_PARM_DESC(irq, "IRQ of first card");
123 MODULE_PARM(membase, "i");
124 MODULE_PARM(irq, "i");
125 #endif
127 char *eicon_ctype_name[] = {
128 "ISDN-S",
129 "ISDN-SX",
130 "ISDN-SCOM",
131 "ISDN-QUADRO",
132 "ISDN-S2M",
133 "DIVA Server BRI/PCI",
134 "DIVA Server 4BRI/PCI",
135 "DIVA Server 4BRI/PCI",
136 "DIVA Server PRI/PCI"
139 static int
140 getrel(char *p)
142 int v = 0;
143 char *tmp = 0;
145 if ((tmp = strchr(p, '.')))
146 p = tmp + 1;
147 while (p[0] >= '0' && p[0] <= '9') {
148 v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0');
149 p++;
151 return v;
156 static char *
157 eicon_getrev(const char *revision)
159 char *rev;
160 char *p;
161 if ((p = strchr(revision, ':'))) {
162 rev = p + 2;
163 p = strchr(rev, '$');
164 *--p = 0;
165 } else rev = "?.??";
166 return rev;
170 static eicon_chan *
171 find_channel(eicon_card *card, int channel)
173 if ((channel >= 0) && (channel < card->nchannels))
174 return &(card->bch[channel]);
175 if (DebugVar & 1)
176 printk(KERN_WARNING "eicon: Invalid channel %d\n", channel);
177 return NULL;
181 * Free MSN list
183 static void
184 eicon_clear_msn(eicon_card *card)
186 struct msn_entry *p = card->msn_list;
187 struct msn_entry *q;
188 unsigned long flags;
190 save_flags(flags);
191 cli();
192 card->msn_list = NULL;
193 restore_flags(flags);
194 while (p) {
195 q = p->next;
196 kfree(p);
197 p = q;
202 * Find an MSN entry in the list.
203 * If ia5 != 0, return IA5-encoded EAZ, else
204 * return a bitmask with corresponding bit set.
206 static __u16
207 eicon_find_msn(eicon_card *card, char *msn, int ia5)
209 struct msn_entry *p = card->msn_list;
210 __u8 eaz = '0';
212 while (p) {
213 if (!strcmp(p->msn, msn)) {
214 eaz = p->eaz;
215 break;
217 p = p->next;
219 if (!ia5)
220 return (1 << (eaz - '0'));
221 else
222 return eaz;
226 * Find an EAZ entry in the list.
227 * return a string with corresponding msn.
229 char *
230 eicon_find_eaz(eicon_card *card, char eaz)
232 struct msn_entry *p = card->msn_list;
234 while (p) {
235 if (p->eaz == eaz)
236 return(p->msn);
237 p = p->next;
239 return("\0");
242 #if 0
244 * Add or delete an MSN to the MSN list
246 * First character of msneaz is EAZ, rest is MSN.
247 * If length of eazmsn is 1, delete that entry.
249 static int
250 eicon_set_msn(eicon_card *card, char *eazmsn)
252 struct msn_entry *p = card->msn_list;
253 struct msn_entry *q = NULL;
254 unsigned long flags;
255 int i;
257 if (!strlen(eazmsn))
258 return 0;
259 if (strlen(eazmsn) > 16)
260 return -EINVAL;
261 for (i = 0; i < strlen(eazmsn); i++)
262 if (!isdigit(eazmsn[i]))
263 return -EINVAL;
264 if (strlen(eazmsn) == 1) {
265 /* Delete a single MSN */
266 while (p) {
267 if (p->eaz == eazmsn[0]) {
268 save_flags(flags);
269 cli();
270 if (q)
271 q->next = p->next;
272 else
273 card->msn_list = p->next;
274 restore_flags(flags);
275 kfree(p);
276 if (DebugVar & 8)
277 printk(KERN_DEBUG
278 "Mapping for EAZ %c deleted\n",
279 eazmsn[0]);
280 return 0;
282 q = p;
283 p = p->next;
285 return 0;
287 /* Add a single MSN */
288 while (p) {
289 /* Found in list, replace MSN */
290 if (p->eaz == eazmsn[0]) {
291 save_flags(flags);
292 cli();
293 strcpy(p->msn, &eazmsn[1]);
294 restore_flags(flags);
295 if (DebugVar & 8)
296 printk(KERN_DEBUG
297 "Mapping for EAZ %c changed to %s\n",
298 eazmsn[0],
299 &eazmsn[1]);
300 return 0;
302 p = p->next;
304 /* Not found in list, add new entry */
305 p = kmalloc(sizeof(msn_entry), GFP_KERNEL);
306 if (!p)
307 return -ENOMEM;
308 p->eaz = eazmsn[0];
309 strcpy(p->msn, &eazmsn[1]);
310 p->next = card->msn_list;
311 save_flags(flags);
312 cli();
313 card->msn_list = p;
314 restore_flags(flags);
315 if (DebugVar & 8)
316 printk(KERN_DEBUG
317 "Mapping %c -> %s added\n",
318 eazmsn[0],
319 &eazmsn[1]);
320 return 0;
322 #endif
324 static void
325 eicon_rcv_dispatch(struct eicon_card *card)
327 switch (card->bus) {
328 case EICON_BUS_ISA:
329 case EICON_BUS_MCA:
330 case EICON_BUS_PCI:
331 eicon_io_rcv_dispatch(card);
332 break;
333 default:
334 if (DebugVar & 1)
335 printk(KERN_WARNING
336 "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
340 static void
341 eicon_ack_dispatch(struct eicon_card *card)
343 switch (card->bus) {
344 case EICON_BUS_ISA:
345 case EICON_BUS_MCA:
346 case EICON_BUS_PCI:
347 eicon_io_ack_dispatch(card);
348 break;
349 default:
350 if (DebugVar & 1)
351 printk(KERN_WARNING
352 "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
356 static void
357 eicon_transmit(struct eicon_card *card)
359 switch (card->bus) {
360 case EICON_BUS_ISA:
361 case EICON_BUS_MCA:
362 case EICON_BUS_PCI:
363 eicon_io_transmit(card);
364 break;
365 default:
366 if (DebugVar & 1)
367 printk(KERN_WARNING
368 "eicon_transmit: Illegal bustype %d\n", card->bus);
372 static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
374 xlogreq_t *xlr;
375 int ret_val;
377 if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
378 if (DebugVar & 1)
379 printk(KERN_WARNING "idi_err: alloc_xlogreq_t failed\n");
380 return -ENOMEM;
382 if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
383 kfree(xlr);
384 return -EFAULT;
387 ret_val = eicon_get_xlog(card, xlr);
389 if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) {
390 kfree(xlr);
391 return -EFAULT;
393 kfree(xlr);
395 return ret_val;
398 static int
399 eicon_command(eicon_card * card, isdn_ctrl * c)
401 ulong a;
402 eicon_chan *chan;
403 eicon_cdef cdef;
404 isdn_ctrl cmd;
405 char tmp[17];
406 int ret = 0;
407 unsigned long flags;
409 if (DebugVar & 16)
410 printk(KERN_WARNING "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
411 c->command, c->arg, (ulong) *c->parm.num);
413 switch (c->command) {
414 case ISDN_CMD_IOCTL:
415 memcpy(&a, c->parm.num, sizeof(ulong));
416 switch (c->arg) {
417 case EICON_IOCTL_GETVER:
418 return(EICON_CTRL_VERSION);
419 case EICON_IOCTL_GETTYPE:
420 return(card->type);
421 case EICON_IOCTL_GETMMIO:
422 switch (card->bus) {
423 case EICON_BUS_ISA:
424 case EICON_BUS_MCA:
425 return (int)card->hwif.isa.shmem;
426 #if CONFIG_PCI
427 case EICON_BUS_PCI:
428 return card->hwif.pci.PCIram;
429 #endif
430 default:
431 if (DebugVar & 1)
432 printk(KERN_WARNING
433 "eicon: Illegal BUS type %d\n",
434 card->bus);
435 ret = -ENODEV;
437 #ifdef CONFIG_ISDN_DRV_EICON_ISA
438 case EICON_IOCTL_SETMMIO:
439 if (card->flags & EICON_FLAGS_LOADED)
440 return -EBUSY;
441 switch (card->bus) {
442 case EICON_BUS_ISA:
443 case EICON_BUS_MCA:
444 if (eicon_isa_find_card(a,
445 card->hwif.isa.irq,
446 card->regname) < 0)
447 return -EFAULT;
448 card->hwif.isa.shmem = (eicon_isa_shmem *)a;
449 return 0;
450 default:
451 if (DebugVar & 1)
452 printk(KERN_WARNING
453 "eicon: Illegal BUS type %d\n",
454 card->bus);
455 ret = -ENODEV;
457 #endif
458 case EICON_IOCTL_GETIRQ:
459 switch (card->bus) {
460 case EICON_BUS_ISA:
461 case EICON_BUS_MCA:
462 return card->hwif.isa.irq;
463 #if CONFIG_PCI
464 case EICON_BUS_PCI:
465 return card->hwif.pci.irq;
466 #endif
467 default:
468 if (DebugVar & 1)
469 printk(KERN_WARNING
470 "eicon: Illegal BUS type %d\n",
471 card->bus);
472 ret = -ENODEV;
474 case EICON_IOCTL_SETIRQ:
475 if (card->flags & EICON_FLAGS_LOADED)
476 return -EBUSY;
477 if ((a < 2) || (a > 15))
478 return -EFAULT;
479 switch (card->bus) {
480 case EICON_BUS_ISA:
481 case EICON_BUS_MCA:
482 card->hwif.isa.irq = a;
483 return 0;
484 default:
485 if (DebugVar & 1)
486 printk(KERN_WARNING
487 "eicon: Illegal BUS type %d\n",
488 card->bus);
489 ret = -ENODEV;
491 #ifdef CONFIG_ISDN_DRV_EICON_ISA
492 case EICON_IOCTL_LOADBOOT:
493 if (card->flags & EICON_FLAGS_RUNNING)
494 return -EBUSY;
495 switch (card->bus) {
496 case EICON_BUS_ISA:
497 case EICON_BUS_MCA:
498 ret = eicon_isa_bootload(
499 &(card->hwif.isa),
500 &(((eicon_codebuf *)a)->isa));
501 break;
502 default:
503 if (DebugVar & 1)
504 printk(KERN_WARNING
505 "eicon: Illegal BUS type %d\n",
506 card->bus);
507 ret = -ENODEV;
509 return ret;
510 #endif
511 #ifdef CONFIG_ISDN_DRV_EICON_ISA
512 case EICON_IOCTL_LOADISA:
513 if (card->flags & EICON_FLAGS_RUNNING)
514 return -EBUSY;
515 switch (card->bus) {
516 case EICON_BUS_ISA:
517 case EICON_BUS_MCA:
518 ret = eicon_isa_load(
519 &(card->hwif.isa),
520 &(((eicon_codebuf *)a)->isa));
521 if (!ret) {
522 card->flags |= EICON_FLAGS_LOADED;
523 card->flags |= EICON_FLAGS_RUNNING;
524 if (card->hwif.isa.channels > 1) {
525 cmd.command = ISDN_STAT_ADDCH;
526 cmd.driver = card->myid;
527 cmd.arg = card->hwif.isa.channels - 1;
528 card->interface.statcallb(&cmd);
530 cmd.command = ISDN_STAT_RUN;
531 cmd.driver = card->myid;
532 cmd.arg = 0;
533 card->interface.statcallb(&cmd);
535 break;
536 default:
537 if (DebugVar & 1)
538 printk(KERN_WARNING
539 "eicon: Illegal BUS type %d\n",
540 card->bus);
541 ret = -ENODEV;
543 return ret;
544 #endif
545 case EICON_IOCTL_MANIF:
546 if (!card->flags & EICON_FLAGS_RUNNING)
547 return -ENODEV;
548 if (!card->Feature & PROTCAP_MANIF)
549 return -ENODEV;
550 ret = eicon_idi_manage(
551 card,
552 (eicon_manifbuf *)a);
553 return ret;
555 case EICON_IOCTL_GETXLOG:
556 if (!card->flags & EICON_FLAGS_RUNNING)
557 return XLOG_ERR_CARD_STATE;
558 ret = eicon_xlog(card, (xlogreq_t *)a);
559 return ret;
560 #if CONFIG_PCI
561 case EICON_IOCTL_LOADPCI:
562 if (card->flags & EICON_FLAGS_RUNNING)
563 return -EBUSY;
564 if (card->bus == EICON_BUS_PCI) {
565 switch(card->type) {
566 case EICON_CTYPE_MAESTRA:
567 ret = eicon_pci_load_bri(
568 &(card->hwif.pci),
569 &(((eicon_codebuf *)a)->pci));
570 break;
572 case EICON_CTYPE_MAESTRAP:
573 ret = eicon_pci_load_pri(
574 &(card->hwif.pci),
575 &(((eicon_codebuf *)a)->pci));
576 break;
578 if (!ret) {
579 card->flags |= EICON_FLAGS_LOADED;
580 card->flags |= EICON_FLAGS_RUNNING;
581 if (card->hwif.pci.channels > 1) {
582 cmd.command = ISDN_STAT_ADDCH;
583 cmd.driver = card->myid;
584 cmd.arg = card->hwif.pci.channels - 1;
585 card->interface.statcallb(&cmd);
587 cmd.command = ISDN_STAT_RUN;
588 cmd.driver = card->myid;
589 cmd.arg = 0;
590 card->interface.statcallb(&cmd);
592 return ret;
593 } else return -ENODEV;
594 #endif
595 #if 0
596 case EICON_IOCTL_SETMSN:
597 if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp))))
598 return -EFAULT;
599 if ((ret = eicon_set_msn(card, tmp)))
600 return ret;
601 #if 0
602 if (card->flags & EICON_FLAGS_RUNNING)
603 return(eicon_capi_manufacturer_req_msn(card));
604 #endif
605 return 0;
606 #endif
607 case EICON_IOCTL_ADDCARD:
608 if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
609 return -EFAULT;
610 if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id)))
611 return -EIO;
612 return 0;
613 case EICON_IOCTL_DEBUGVAR:
614 DebugVar = a;
615 printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar);
616 return 0;
617 #ifdef MODULE
618 case EICON_IOCTL_FREEIT:
619 while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
620 MOD_INC_USE_COUNT;
621 return 0;
622 #endif
623 default:
624 return -EINVAL;
626 break;
627 case ISDN_CMD_DIAL:
628 if (!card->flags & EICON_FLAGS_RUNNING)
629 return -ENODEV;
630 if (!(chan = find_channel(card, c->arg & 0x1f)))
631 break;
632 save_flags(flags);
633 cli();
634 if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
635 restore_flags(flags);
636 if (DebugVar & 1)
637 printk(KERN_WARNING "Dial on channel %d with state %d\n",
638 chan->No, chan->fsm_state);
639 return -EBUSY;
641 if (card->ptype == ISDN_PTYPE_EURO)
642 tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1);
643 else
644 tmp[0] = c->parm.setup.eazmsn[0];
645 chan->fsm_state = EICON_STATE_OCALL;
646 chan->callref = 0xffff;
647 restore_flags(flags);
649 ret = idi_connect_req(card, chan, c->parm.setup.phone,
650 c->parm.setup.eazmsn,
651 c->parm.setup.si1,
652 c->parm.setup.si2);
653 if (ret) {
654 cmd.driver = card->myid;
655 cmd.command = ISDN_STAT_DHUP;
656 cmd.arg &= 0x1f;
657 card->interface.statcallb(&cmd);
659 return ret;
660 case ISDN_CMD_ACCEPTD:
661 if (!card->flags & EICON_FLAGS_RUNNING)
662 return -ENODEV;
663 if (!(chan = find_channel(card, c->arg & 0x1f)))
664 break;
665 if (chan->fsm_state == EICON_STATE_ICALL) {
666 idi_connect_res(card, chan);
668 return 0;
669 case ISDN_CMD_ACCEPTB:
670 if (!card->flags & EICON_FLAGS_RUNNING)
671 return -ENODEV;
672 return 0;
673 case ISDN_CMD_HANGUP:
674 if (!card->flags & EICON_FLAGS_RUNNING)
675 return -ENODEV;
676 if (!(chan = find_channel(card, c->arg & 0x1f)))
677 break;
678 idi_hangup(card, chan);
679 return 0;
680 case ISDN_CMD_SETEAZ:
681 if (!card->flags & EICON_FLAGS_RUNNING)
682 return -ENODEV;
683 if (!(chan = find_channel(card, c->arg & 0x1f)))
684 break;
685 if (strlen(c->parm.num)) {
686 if (card->ptype == ISDN_PTYPE_EURO) {
687 chan->eazmask = eicon_find_msn(card, c->parm.num, 0);
689 if (card->ptype == ISDN_PTYPE_1TR6) {
690 int i;
691 chan->eazmask = 0;
692 for (i = 0; i < strlen(c->parm.num); i++)
693 if (isdigit(c->parm.num[i]))
694 chan->eazmask |= (1 << (c->parm.num[i] - '0'));
696 } else
697 chan->eazmask = 0x3ff;
698 eicon_idi_listen_req(card, chan);
699 return 0;
700 case ISDN_CMD_CLREAZ:
701 if (!card->flags & EICON_FLAGS_RUNNING)
702 return -ENODEV;
703 if (!(chan = find_channel(card, c->arg & 0x1f)))
704 break;
705 chan->eazmask = 0;
706 eicon_idi_listen_req(card, chan);
707 return 0;
708 case ISDN_CMD_SETL2:
709 if (!card->flags & EICON_FLAGS_RUNNING)
710 return -ENODEV;
711 if (!(chan = find_channel(card, c->arg & 0x1f)))
712 break;
713 chan->l2prot = (c->arg >> 8);
714 return 0;
715 case ISDN_CMD_GETL2:
716 if (!card->flags & EICON_FLAGS_RUNNING)
717 return -ENODEV;
718 if (!(chan = find_channel(card, c->arg & 0x1f)))
719 break;
720 return chan->l2prot;
721 case ISDN_CMD_SETL3:
722 if (!card->flags & EICON_FLAGS_RUNNING)
723 return -ENODEV;
724 if (!(chan = find_channel(card, c->arg & 0x1f)))
725 break;
726 chan->l3prot = (c->arg >> 8);
727 #ifdef CONFIG_ISDN_TTY_FAX
728 if (chan->l3prot == ISDN_PROTO_L3_FAX)
729 chan->fax = c->parm.fax;
730 #endif
731 return 0;
732 case ISDN_CMD_GETL3:
733 if (!card->flags & EICON_FLAGS_RUNNING)
734 return -ENODEV;
735 if (!(chan = find_channel(card, c->arg & 0x1f)))
736 break;
737 return chan->l3prot;
738 case ISDN_CMD_GETEAZ:
739 if (!card->flags & EICON_FLAGS_RUNNING)
740 return -ENODEV;
741 if (DebugVar & 1)
742 printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n");
743 return 0;
744 case ISDN_CMD_SETSIL:
745 if (!card->flags & EICON_FLAGS_RUNNING)
746 return -ENODEV;
747 if (DebugVar & 1)
748 printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n");
749 return 0;
750 case ISDN_CMD_GETSIL:
751 if (!card->flags & EICON_FLAGS_RUNNING)
752 return -ENODEV;
753 if (DebugVar & 1)
754 printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n");
755 return 0;
756 case ISDN_CMD_LOCK:
757 MOD_INC_USE_COUNT;
758 return 0;
759 case ISDN_CMD_UNLOCK:
760 MOD_DEC_USE_COUNT;
761 return 0;
762 #ifdef CONFIG_ISDN_TTY_FAX
763 case ISDN_CMD_FAXCMD:
764 if (!card->flags & EICON_FLAGS_RUNNING)
765 return -ENODEV;
766 if (!(chan = find_channel(card, c->arg & 0x1f)))
767 break;
768 if (!chan->fax)
769 break;
770 idi_fax_cmd(card, chan);
771 return 0;
772 #endif
773 case ISDN_CMD_AUDIO:
774 if (!card->flags & EICON_FLAGS_RUNNING)
775 return -ENODEV;
776 if (!(chan = find_channel(card, c->arg & 0x1f)))
777 break;
778 idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
779 return 0;
782 return -EINVAL;
786 * Find card with given driverId
788 static inline eicon_card *
789 eicon_findcard(int driverid)
791 eicon_card *p = cards;
793 while (p) {
794 if (p->myid == driverid)
795 return p;
796 p = p->next;
798 return (eicon_card *) 0;
802 * Wrapper functions for interface to linklevel
804 static int
805 if_command(isdn_ctrl * c)
807 eicon_card *card = eicon_findcard(c->driver);
809 if (card)
810 return (eicon_command(card, c));
811 printk(KERN_ERR
812 "eicon: if_command %d called with invalid driverId %d!\n",
813 c->command, c->driver);
814 return -ENODEV;
817 static int
818 if_writecmd(const u_char * buf, int len, int user, int id, int channel)
820 #if 0
821 /* Not yet used */
822 eicon_card *card = eicon_findcard(id);
824 if (card) {
825 if (!card->flags & EICON_FLAGS_RUNNING)
826 return (len);
827 return (len);
829 printk(KERN_ERR
830 "eicon: if_writecmd called with invalid driverId!\n");
831 #endif
832 return (len);
835 static int
836 if_readstatus(u_char * buf, int len, int user, int id, int channel)
838 #if 0
839 /* Not yet used */
840 eicon_card *card = eicon_findcard(id);
842 if (card) {
843 if (!card->flags & EICON_FLAGS_RUNNING)
844 return -ENODEV;
845 return (eicon_readstatus(buf, len, user, card));
847 printk(KERN_ERR
848 "eicon: if_readstatus called with invalid driverId!\n");
849 #endif
850 return 0;
853 static int
854 if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
856 eicon_card *card = eicon_findcard(id);
857 eicon_chan *chan;
858 int ret = 0;
859 int len;
861 len = skb->len;
863 if (card) {
864 if (!card->flags & EICON_FLAGS_RUNNING) {
865 dev_kfree_skb(skb);
866 return -ENODEV;
868 if (!(chan = find_channel(card, channel))) {
869 dev_kfree_skb(skb);
870 return -ENODEV;
872 if (chan->fsm_state == EICON_STATE_ACTIVE) {
873 #ifdef CONFIG_ISDN_TTY_FAX
874 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
875 if ((ret = idi_faxdata_send(card, chan, skb)) > 0)
876 ret = len;
878 else
879 #endif
880 ret = idi_send_data(card, chan, ack, skb, 1);
881 return (ret);
882 } else {
883 dev_kfree_skb(skb);
884 return -ENODEV;
887 printk(KERN_ERR
888 "eicon: if_sendbuf called with invalid driverId!\n");
889 dev_kfree_skb(skb);
890 return -ENODEV;
895 * Allocate a new card-struct, initialize it
896 * link it into cards-list.
898 static void
899 eicon_alloccard(int Type, int membase, int irq, char *id)
901 int i;
902 int j;
903 int qloop;
904 #ifdef CONFIG_ISDN_DRV_EICON_ISA
905 char qid[5];
906 #endif
907 eicon_card *card;
908 #if CONFIG_PCI
909 eicon_pci_card *pcic;
910 #endif
912 qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
913 for (i = 0; i <= qloop; i++) {
914 if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) {
915 printk(KERN_WARNING
916 "eicon: (%s) Could not allocate card-struct.\n", id);
917 return;
919 memset((char *) card, 0, sizeof(eicon_card));
920 skb_queue_head_init(&card->sndq);
921 skb_queue_head_init(&card->rcvq);
922 skb_queue_head_init(&card->rackq);
923 skb_queue_head_init(&card->sackq);
924 card->snd_tq.routine = (void *) (void *) eicon_transmit;
925 card->snd_tq.data = card;
926 card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch;
927 card->rcv_tq.data = card;
928 card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch;
929 card->ack_tq.data = card;
930 card->interface.maxbufsize = 4000;
931 card->interface.command = if_command;
932 card->interface.writebuf_skb = if_sendbuf;
933 card->interface.writecmd = if_writecmd;
934 card->interface.readstat = if_readstatus;
935 card->interface.features =
936 ISDN_FEATURE_L2_X75I |
937 ISDN_FEATURE_L2_HDLC |
938 ISDN_FEATURE_L2_TRANS |
939 ISDN_FEATURE_L3_TRANS |
940 ISDN_FEATURE_P_UNKNOWN;
941 card->interface.hl_hdrlen = 20;
942 card->ptype = ISDN_PTYPE_UNKNOWN;
943 strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
944 card->myid = -1;
945 card->type = Type;
946 switch (Type) {
947 #ifdef CONFIG_ISDN_DRV_EICON_ISA
948 #if CONFIG_MCA /* only needed for MCA */
949 case EICON_CTYPE_S:
950 case EICON_CTYPE_SX:
951 case EICON_CTYPE_SCOM:
952 if (membase == -1)
953 membase = EICON_ISA_MEMBASE;
954 if (irq == -1)
955 irq = EICON_ISA_IRQ;
956 card->bus = EICON_BUS_MCA;
957 card->hwif.isa.card = (void *)card;
958 card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
959 card->hwif.isa.master = 1;
961 card->hwif.isa.irq = irq;
962 card->hwif.isa.type = Type;
963 card->nchannels = 2;
964 card->interface.channels = 1;
965 break;
966 #endif /* CONFIG_MCA */
967 case EICON_CTYPE_QUADRO:
968 if (membase == -1)
969 membase = EICON_ISA_MEMBASE;
970 if (irq == -1)
971 irq = EICON_ISA_IRQ;
972 card->bus = EICON_BUS_ISA;
973 card->hwif.isa.card = (void *)card;
974 card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET);
975 card->hwif.isa.master = 0;
976 strcpy(card->interface.id, id);
977 if (id[strlen(id) - 1] == 'a') {
978 card->interface.id[strlen(id) - 1] = 'a' + i + 1;
979 } else {
980 sprintf(qid, "_%c",'2' + i);
981 strcat(card->interface.id, qid);
983 printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n",
984 card->interface.id);
985 if (i == 0) {
986 eicon_card *p = cards;
987 while(p) {
988 if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) {
989 p->qnext = card;
990 break;
992 p = p->next;
994 if (!p) {
995 printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n");
996 kfree(card);
997 return;
999 } else {
1000 cards->qnext = card;
1002 card->hwif.isa.irq = irq;
1003 card->hwif.isa.type = Type;
1004 card->nchannels = 2;
1005 card->interface.channels = 1;
1006 break;
1007 #endif
1008 #if CONFIG_PCI
1009 case EICON_CTYPE_MAESTRA:
1010 (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
1011 card->bus = EICON_BUS_PCI;
1012 card->interface.features |=
1013 ISDN_FEATURE_L2_V11096 |
1014 ISDN_FEATURE_L2_V11019 |
1015 ISDN_FEATURE_L2_V11038 |
1016 ISDN_FEATURE_L2_MODEM |
1017 /* ISDN_FEATURE_L2_FAX | */
1018 ISDN_FEATURE_L3_TRANSDSP |
1019 ISDN_FEATURE_L3_FAX;
1020 card->hwif.pci.card = (void *)card;
1021 card->hwif.pci.PCIreg = pcic->PCIreg;
1022 card->hwif.pci.PCIcfg = pcic->PCIcfg;
1023 card->hwif.pci.master = 1;
1024 card->hwif.pci.mvalid = pcic->mvalid;
1025 card->hwif.pci.ivalid = 0;
1026 card->hwif.pci.irq = irq;
1027 card->hwif.pci.type = Type;
1028 card->flags = 0;
1029 card->nchannels = 2;
1030 card->interface.channels = 1;
1031 break;
1033 case EICON_CTYPE_MAESTRAP:
1034 (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
1035 card->bus = EICON_BUS_PCI;
1036 card->interface.features |=
1037 ISDN_FEATURE_L2_V11096 |
1038 ISDN_FEATURE_L2_V11019 |
1039 ISDN_FEATURE_L2_V11038 |
1040 ISDN_FEATURE_L2_MODEM |
1041 /* ISDN_FEATURE_L2_FAX | */
1042 ISDN_FEATURE_L3_TRANSDSP |
1043 ISDN_FEATURE_L3_FAX;
1044 card->hwif.pci.card = (void *)card;
1045 card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
1046 card->hwif.pci.PCIreg = pcic->PCIreg;
1047 card->hwif.pci.PCIram = pcic->PCIram;
1048 card->hwif.pci.PCIcfg = pcic->PCIcfg;
1049 card->hwif.pci.master = 1;
1050 card->hwif.pci.mvalid = pcic->mvalid;
1051 card->hwif.pci.ivalid = 0;
1052 card->hwif.pci.irq = irq;
1053 card->hwif.pci.type = Type;
1054 card->flags = 0;
1055 card->nchannels = 30;
1056 card->interface.channels = 1;
1057 break;
1058 #endif
1059 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1060 case EICON_CTYPE_ISABRI:
1061 if (membase == -1)
1062 membase = EICON_ISA_MEMBASE;
1063 if (irq == -1)
1064 irq = EICON_ISA_IRQ;
1065 card->bus = EICON_BUS_ISA;
1066 card->hwif.isa.card = (void *)card;
1067 card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
1068 card->hwif.isa.master = 1;
1069 card->hwif.isa.irq = irq;
1070 card->hwif.isa.type = Type;
1071 card->nchannels = 2;
1072 card->interface.channels = 1;
1073 break;
1074 case EICON_CTYPE_ISAPRI:
1075 if (membase == -1)
1076 membase = EICON_ISA_MEMBASE;
1077 if (irq == -1)
1078 irq = EICON_ISA_IRQ;
1079 card->bus = EICON_BUS_ISA;
1080 card->hwif.isa.card = (void *)card;
1081 card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
1082 card->hwif.isa.master = 1;
1083 card->hwif.isa.irq = irq;
1084 card->hwif.isa.type = Type;
1085 card->nchannels = 30;
1086 card->interface.channels = 1;
1087 break;
1088 #endif
1089 default:
1090 printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type);
1091 kfree(card);
1092 return;
1094 if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1)
1095 , GFP_KERNEL))) {
1096 printk(KERN_WARNING
1097 "eicon: (%s) Could not allocate bch-struct.\n", id);
1098 kfree(card);
1099 return;
1101 for (j=0; j< (card->nchannels + 1); j++) {
1102 memset((char *)&card->bch[j], 0, sizeof(eicon_chan));
1103 card->bch[j].plci = 0x8000;
1104 card->bch[j].ncci = 0x8000;
1105 card->bch[j].l2prot = ISDN_PROTO_L2_X75I;
1106 card->bch[j].l3prot = ISDN_PROTO_L3_TRANS;
1107 card->bch[j].e.D3Id = 0;
1108 card->bch[j].e.B2Id = 0;
1109 card->bch[j].e.Req = 0;
1110 card->bch[j].No = j;
1111 skb_queue_head_init(&card->bch[j].e.X);
1112 skb_queue_head_init(&card->bch[j].e.R);
1114 card->next = cards;
1115 cards = card;
1120 * register card at linklevel
1122 static int
1123 eicon_registercard(eicon_card * card)
1125 switch (card->bus) {
1126 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1127 case EICON_BUS_ISA:
1128 /* TODO something to print */
1129 break;
1130 #ifdef CONFIG_MCA
1131 case EICON_BUS_MCA:
1132 eicon_isa_printpar(&card->hwif.isa);
1133 break;
1134 #endif
1135 #endif
1136 case EICON_BUS_PCI:
1137 #if CONFIG_PCI
1138 eicon_pci_printpar(&card->hwif.pci);
1139 break;
1140 #endif
1141 default:
1142 if (DebugVar & 1)
1143 printk(KERN_WARNING
1144 "eicon_registercard: Illegal BUS type %d\n",
1145 card->bus);
1146 return -1;
1148 if (!register_isdn(&card->interface)) {
1149 printk(KERN_WARNING
1150 "eicon_registercard: Unable to register %s\n",
1151 card->interface.id);
1152 return -1;
1154 card->myid = card->interface.channels;
1155 sprintf(card->regname, "%s", card->interface.id);
1156 return 0;
1159 #ifdef MODULE
1160 static void
1161 unregister_card(eicon_card * card)
1163 isdn_ctrl cmd;
1165 cmd.command = ISDN_STAT_UNLOAD;
1166 cmd.driver = card->myid;
1167 card->interface.statcallb(&cmd);
1168 switch (card->bus) {
1169 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1170 case EICON_BUS_ISA:
1171 #ifdef CONFIG_MCA
1172 case EICON_BUS_MCA:
1173 #endif
1174 eicon_isa_release(&card->hwif.isa);
1175 break;
1176 #endif
1177 case EICON_BUS_PCI:
1178 #if CONFIG_PCI
1179 eicon_pci_release(&card->hwif.pci);
1180 break;
1181 #endif
1182 default:
1183 if (DebugVar & 1)
1184 printk(KERN_WARNING
1185 "eicon: Invalid BUS type %d\n",
1186 card->bus);
1187 break;
1190 #endif /* MODULE */
1192 static void
1193 eicon_freecard(eicon_card *card) {
1194 eicon_clear_msn(card);
1195 kfree(card->bch);
1196 kfree(card);
1200 eicon_addcard(int Type, int membase, int irq, char *id)
1202 eicon_card *p;
1203 eicon_card *q = NULL;
1204 int registered;
1205 int added = 0;
1206 int failed = 0;
1208 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1209 if (!Type) /* ISA */
1210 if ((Type = eicon_isa_find_card(membase, irq, id)) < 0)
1211 return 0;
1212 #endif
1213 eicon_alloccard(Type, membase, irq, id);
1214 p = cards;
1215 while (p) {
1216 registered = 0;
1217 if (!p->interface.statcallb) {
1218 /* Not yet registered.
1219 * Try to register and activate it.
1221 added++;
1222 switch (p->bus) {
1223 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1224 case EICON_BUS_ISA:
1225 case EICON_BUS_MCA:
1226 if (eicon_registercard(p))
1227 break;
1228 registered = 1;
1229 break;
1230 #endif
1231 case EICON_BUS_PCI:
1232 #if CONFIG_PCI
1233 if (eicon_registercard(p))
1234 break;
1235 registered = 1;
1236 break;
1237 #endif
1238 default:
1239 if (DebugVar & 1)
1240 printk(KERN_WARNING
1241 "eicon: addcard: Invalid BUS type %d\n",
1242 p->bus);
1244 } else
1245 /* Card already registered */
1246 registered = 1;
1247 if (registered) {
1248 /* Init OK, next card ... */
1249 q = p;
1250 p = p->next;
1251 } else {
1252 /* registering failed, remove card from list, free memory */
1253 printk(KERN_WARNING
1254 "eicon: Initialization of %s failed\n",
1255 p->interface.id);
1256 if (q) {
1257 q->next = p->next;
1258 eicon_freecard(p);
1259 p = q->next;
1260 } else {
1261 cards = p->next;
1262 eicon_freecard(p);
1263 p = cards;
1265 failed++;
1268 return (added - failed);
1271 #define DRIVERNAME "Eicon active ISDN driver"
1272 #define DRIVERRELEASE "1"
1274 #ifdef MODULE
1275 #define eicon_init init_module
1276 #endif
1278 __initfunc(int
1279 eicon_init(void))
1281 int card_count = 0;
1282 int release = 0;
1283 char tmprev[50];
1285 DebugVar = 1;
1287 printk(KERN_INFO "%s Rev: ", DRIVERNAME);
1288 strcpy(tmprev, eicon_revision);
1289 printk("%s/", eicon_getrev(tmprev));
1290 release += getrel(tmprev);
1291 strcpy(tmprev, eicon_pci_revision);
1292 #if CONFIG_PCI
1293 printk("%s/", eicon_getrev(tmprev));
1294 #else
1295 printk("---/");
1296 #endif
1297 release += getrel(tmprev);
1298 strcpy(tmprev, eicon_isa_revision);
1299 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1300 printk("%s/", eicon_getrev(tmprev));
1301 #else
1302 printk("---/");
1303 #endif
1304 release += getrel(tmprev);
1305 strcpy(tmprev, eicon_idi_revision);
1306 printk("%s\n", eicon_getrev(tmprev));
1307 release += getrel(tmprev);
1308 sprintf(tmprev,"%d", release);
1309 printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME,
1310 DRIVERRELEASE, tmprev, DRIVERPATCH);
1312 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1313 #ifdef CONFIG_MCA
1314 /* Check if we have MCA-bus */
1315 if (!MCA_bus)
1317 printk(KERN_INFO
1318 "eicon: No MCA bus, ISDN-interfaces not probed.\n");
1319 } else {
1320 if (DebugVar & 8)
1321 printk(KERN_DEBUG
1322 "eicon_mca_find_card, irq=%d.\n",
1323 irq);
1324 if (!eicon_mca_find_card(0, membase, irq, id))
1325 card_count++;
1327 #else
1328 card_count = eicon_addcard(0, membase, irq, id);
1329 #endif /* CONFIG_MCA */
1330 #endif /* CONFIG_ISDN_DRV_EICON_ISA */
1332 #if CONFIG_PCI
1333 card_count += eicon_pci_find_card(id);
1334 #endif
1335 if (!cards) {
1336 #ifdef MODULE
1337 #ifndef CONFIG_PCI
1338 #ifndef CONFIG_ISDN_DRV_EICON_ISA
1339 printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
1340 #else
1341 printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
1342 #endif
1343 #else
1344 printk(KERN_INFO "Eicon: No PCI-cards found, driver not loaded !\n");
1345 #endif
1346 #endif /* MODULE */
1347 return -ENODEV;
1349 } else
1350 printk(KERN_INFO "Eicon: %d card%s added\n", card_count,
1351 (card_count>1)?"s":"");
1352 /* No symbols to export, hide all symbols */
1353 EXPORT_NO_SYMBOLS;
1354 return 0;
1357 #ifdef MODULE
1358 void
1359 cleanup_module(void)
1361 eicon_card *card = cards;
1362 eicon_card *last;
1363 while (card) {
1364 #ifdef CONFIG_MCA
1365 if (MCA_bus)
1367 mca_mark_as_unused (card->mca_slot);
1368 mca_set_adapter_procfn(card->mca_slot, NULL, NULL);
1370 #endif
1371 unregister_card(card);
1372 card = card->next;
1374 card = cards;
1375 while (card) {
1376 last = card;
1377 card = card->next;
1378 eicon_freecard(last);
1380 printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
1383 #else /* no module */
1385 #ifdef COMPAT_HAS_NEW_SETUP
1386 static int __init
1387 eicon_setup(char *line)
1389 int i, argc;
1390 int ints[5];
1391 char *str;
1393 str = get_options(line, 4, ints);
1394 #else
1395 __initfunc(void
1396 eicon_setup(char *str, int *ints))
1398 int i, argc;
1399 #endif
1401 argc = ints[0];
1402 i = 1;
1403 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1404 if (argc) {
1405 membase = irq = -1;
1406 if (argc) {
1407 membase = ints[i];
1408 i++;
1409 argc--;
1411 if (argc) {
1412 irq = ints[i];
1413 i++;
1414 argc--;
1416 if (strlen(str)) {
1417 strcpy(id, str);
1418 } else {
1419 strcpy(id, "eicon");
1421 printk(KERN_INFO "Eicon ISDN active driver setup (id=%s membase=0x%x irq=%d)\n",
1422 id, membase, irq);
1424 #else
1425 printk(KERN_INFO "Eicon ISDN active driver setup\n");
1426 #endif
1427 #ifdef COMPAT_HAS_NEW_SETUP
1428 return(1);
1430 __setup("eicon=", eicon_setup);
1431 #else
1433 #endif
1435 #endif /* MODULE */
1437 #ifdef CONFIG_ISDN_DRV_EICON_ISA
1438 #ifdef CONFIG_MCA
1440 struct eicon_mca_adapters_struct {
1441 char * name;
1442 int adf_id;
1444 /* possible MCA-brands of eicon cards */
1445 struct eicon_mca_adapters_struct eicon_mca_adapters[] = {
1446 { "ISDN-P/2 Adapter", 0x6abb },
1447 { "ISDN-[S|SX|SCOM]/2 Adapter", 0x6a93 },
1448 { "DIVA /MCA", 0x6336 },
1449 { NULL, 0 },
1452 int eicon_mca_find_card(int type, /* type-idx of eicon-card */
1453 int membase,
1454 int irq,
1455 char * id) /* name of eicon-isdn-dev */
1457 int j, curr_slot = 0;
1459 if (DebugVar & 8)
1460 printk(KERN_DEBUG
1461 "eicon_mca_find_card type: %d, membase: %#x, irq %d \n",
1462 type, membase, irq);
1463 /* find a no-driver-assigned eicon card */
1464 for (j=0; eicon_mca_adapters[j].adf_id != 0; j++)
1466 for ( curr_slot=0; curr_slot<=MCA_MAX_SLOT_NR; curr_slot++)
1468 curr_slot = mca_find_unused_adapter(
1469 eicon_mca_adapters[j].adf_id, curr_slot);
1470 if (curr_slot != MCA_NOTFOUND)
1472 /* check if pre-set parameters match
1473 these of the card, check cards memory */
1474 if (!(int) eicon_mca_probe(curr_slot,
1476 membase,
1477 irq,
1478 id))
1480 return 0;
1481 /* means: adapter parms did match */
1484 break;
1485 /* MCA_NOTFOUND-branch: no matching adapter of
1486 THIS flavor found, next flavor */
1490 /* all adapter flavors checked without match, finito with: */
1491 return ENODEV;
1495 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1496 * stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999
1498 int eicon_info(char * buf, int slot, void *d)
1500 int len = 0;
1501 struct eicon_card *dev;
1503 dev = (struct eicon_card *) d;
1505 if (dev == NULL)
1506 return len;
1507 len += sprintf(buf+len, "eicon ISDN adapter, type %d.\n",dev->type);
1508 len += sprintf(buf+len, "IRQ: %d\n", dev->hwif.isa.irq);
1509 len += sprintf(buf+len, "MEMBASE: %#lx\n", (unsigned long)dev->hwif.isa.shmem);
1511 return len;
1514 int eicon_mca_probe(int slot, /* slot-nr where the card was detected */
1515 int a_idx, /* idx-nr of probed card in eicon_mca_adapters */
1516 int membase,
1517 int irq,
1518 char * id) /* name of eicon-isdn-dev */
1520 unsigned char adf_pos0;
1521 int cards_irq, cards_membase, cards_io;
1522 int type = EICON_CTYPE_S;
1523 int irq_array[]={0,3,4,2};
1524 int irq_array1[]={3,4,0,0,2,10,11,12};
1526 adf_pos0 = mca_read_stored_pos(slot,2);
1527 if (DebugVar & 8)
1528 printk(KERN_DEBUG
1529 "eicon_mca_probe irq=%d, membase=%d\n",
1530 irq,
1531 membase);
1532 switch (a_idx) {
1533 case 0: /* P/2-Adapter (== PRI/S2M ? ) */
1534 cards_membase= 0xC0000+((adf_pos0>>4)*0x4000);
1535 if (membase == -1) {
1536 membase = cards_membase;
1537 } else {
1538 if (membase != cards_membase)
1539 return ENODEV;
1541 cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
1542 if (irq == -1) {
1543 irq = cards_irq;
1544 } else {
1545 if (irq != irq)
1546 return ENODEV;
1548 cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
1549 type = EICON_CTYPE_ISAPRI;
1550 break;
1552 case 1: /* [S|SX|SCOM]/2 */
1553 cards_membase= 0xC0000+((adf_pos0>>4)*0x2000);
1554 if (membase == -1) {
1555 membase = cards_membase;
1556 } else {
1557 if (membase != cards_membase)
1558 return ENODEV;
1560 cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
1561 if (irq == -1) {
1562 irq = cards_irq;
1563 } else {
1564 if (irq != cards_irq)
1565 return ENODEV;
1568 cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
1569 type = EICON_CTYPE_SCOM;
1570 break;
1572 case 2: /* DIVA/MCA */
1573 cards_io = 0x200+ ((adf_pos0>>4)* 0x20);
1574 cards_irq = irq_array1[(adf_pos0 & 0x7)];
1575 if (irq == -1) {
1576 irq = cards_irq;
1577 } else {
1578 if (irq != irq)
1579 return ENODEV;
1581 type = 0;
1582 break;
1583 default:
1584 return ENODEV;
1586 /* Uebereinstimmung vorgegebener membase & irq */
1587 if ( 1 == eicon_addcard(type, membase, irq, id)) {
1588 mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name);
1589 mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards);
1591 mca_mark_as_used(slot);
1592 cards->mca_slot = slot;
1593 /* card->io noch setzen oder ?? */
1594 if (DebugVar & 8)
1595 printk("eicon_addcard: erfolgreich fuer slot: %d.\n",
1596 cards->mca_slot+1);
1597 return 0 ; /* eicon_addcard hat eine Karte zugefuegt */
1598 } else {
1599 return ENODEV;
1602 #endif /* CONFIG_MCA */
1603 #endif /* CONFIG_ISDN_DRV_EICON_ISA */