Import 2.3.16
[davej-history.git] / drivers / isdn / icn / icn.c
blob26ac3502df0500de2fc4ad67e0652911a75b0d84
1 /* $Id: icn.c,v 1.59 1999/08/28 22:10:55 keil Exp $
3 * ISDN low-level module for the ICN active ISDN-Card.
5 * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * $Log: icn.c,v $
22 * Revision 1.59 1999/08/28 22:10:55 keil
23 * __setup function should be static
25 * Revision 1.58 1999/08/25 16:44:17 keil
26 * Support for new __setup function
28 * Revision 1.57 1999/07/06 16:15:30 detabc
29 * remove unused messages
31 * Revision 1.56 1999/04/12 13:15:07 fritz
32 * Fixed a cast.
34 * Revision 1.55 1999/04/12 12:34:02 fritz
35 * Changes from 2.0 tree.
37 * Revision 1.54 1999/01/05 18:29:39 he
38 * merged remaining schedule_timeout() changes from 2.1.127
40 * Revision 1.53 1998/06/17 19:51:28 he
41 * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
42 * brute force fix to avoid Ugh's in isdn_tty_write()
43 * cleaned up some dead code
45 * Revision 1.52 1998/05/20 19:29:58 tsbogend
46 * fixed bug introduced by changes for new BSENT callback
48 * Revision 1.51 1998/03/07 22:29:55 fritz
49 * Adapted Detlef's chenges for 2.1.
51 * Revision 1.49 1998/02/13 11:14:15 keil
52 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
54 * Revision 1.48 1997/10/10 15:56:14 fritz
55 * New HL<->LL interface:
56 * New BSENT callback with nr. of bytes included.
57 * Sending without ACK.
59 * Revision 1.47 1997/10/01 09:21:51 fritz
60 * Removed old compatibility stuff for 2.0.X kernels.
61 * From now on, this code is for 2.1.X ONLY!
62 * Old stuff is still in the separate branch.
64 * Revision 1.46 1997/08/21 22:38:33 fritz
65 * Fixed a typo.
67 * Revision 1.45 1997/06/21 10:42:06 fritz
68 * Added availability to select leased mode on only one channel.
70 * Revision 1.44 1997/03/30 16:51:26 calle
71 * changed calls to copy_from_user/copy_to_user and removed verify_area
72 * were possible.
74 * Revision 1.43 1997/03/21 18:27:04 fritz
75 * Corrected parsing of incoming setup.
77 * Revision 1.42 1997/03/05 21:13:18 fritz
78 * Bugfix: sndcount was not reset on hangup.
80 * Revision 1.41 1997/02/24 23:34:29 fritz
81 * Bugfix in Layer1 error-recovery.
83 * Revision 1.40 1997/02/23 23:34:45 fritz
84 * Minor bugfixes in debugging code.
86 * Revision 1.39 1997/02/23 16:21:56 fritz
87 * Bugfix: Check for NULL pointer in icn_parse_status().
89 * Revision 1.38 1997/02/11 18:29:31 fritz
90 * Bugfix in D64S initialization.
92 * Revision 1.37 1997/02/10 22:43:20 fritz
93 * Added plan and screen elements on ISDN_STAT_ICALL
95 * Revision 1.36 1997/02/10 21:31:20 fritz
96 * Changed setup-interface (incoming and outgoing).
98 * Revision 1.35 1997/02/10 10:10:28 fritz
99 * Changes for Kernel 2.1.X compatibility.
100 * Enhanced initialization, can recover from
101 * misconfiguration by other autoprobing drivers.
103 * Revision 1.34 1997/01/29 22:34:44 fritz
104 * Cleanup, Corrected D64S setup of 2nd channel.
106 * Revision 1.33 1996/12/05 20:31:48 tsbogend
107 * added handling of L2: DATA LINK LOST messages
109 * Revision 1.32 1996/11/14 23:49:18 fritz
110 * Bugfix: copy_to_user/copy_from_user mismatch in debugging-ioctl.
112 * Revision 1.31 1996/11/13 02:36:25 fritz
113 * Fixed a race condition in writecmd.
114 * Some optimizations and cleanup.
116 * Revision 1.30 1996/10/22 23:14:09 fritz
117 * Changes for compatibility to 2.0.X and 2.1.X kernels.
119 * Revision 1.29 1996/08/29 20:34:54 fritz
120 * Bugfix in send queue management:
121 * sndcount was not updated correctly.
122 * Minor Bugfixes.
124 * Revision 1.28 1996/06/28 17:02:53 fritz
125 * replaced memcpy_fromfs_toio.
127 * Revision 1.27 1996/06/25 18:38:59 fritz
128 * Fixed function name in error message.
130 * Revision 1.26 1996/06/24 17:20:35 fritz
131 * Bugfixes in pollbchan_send():
132 * - Using lock field of skbuff breaks networking.
133 * - Added channel locking
134 * - changed dequeuing scheme.
135 * Eliminated misc. compiler warnings.
137 * Revision 1.25 1996/06/11 22:53:35 tsbogend
138 * fixed problem with large array on stack
139 * made the driver working on Linux/alpha
141 * Revision 1.24 1996/06/06 13:58:33 fritz
142 * Changed code to be architecture independent
144 * Revision 1.23 1996/06/03 19:59:00 fritz
145 * Fixed typos.
147 * Revision 1.22 1996/05/17 15:46:41 fritz
148 * Removed own queue management.
149 * Changed queue management to use sk_buffs.
151 * Revision 1.21 1996/05/02 04:01:20 fritz
152 * Bugfix:
153 * - icn_addcard() evaluated wrong driverId.
155 * Revision 1.20 1996/05/02 00:40:27 fritz
156 * Major rewrite to support more than one card
157 * with a single module.
158 * Support for new firmware.
160 * Revision 1.19 1996/04/21 17:43:32 fritz
161 * Changes for Support of new Firmware BRV3.02
163 * Revision 1.18 1996/04/20 16:50:26 fritz
164 * Fixed status-buffer overrun.
165 * Misc. typos
167 * Revision 1.17 1996/02/11 02:39:04 fritz
168 * Increased Buffer for status-messages.
169 * Removed conditionals for HDLC-firmware.
171 * Revision 1.16 1996/01/22 05:01:55 fritz
172 * Revert to GPL.
174 * Revision 1.15 1996/01/10 20:57:39 fritz
175 * Bugfix: Loading firmware twice caused the device stop working.
177 * Revision 1.14 1995/12/18 18:23:37 fritz
178 * Support for ICN-2B Cards.
179 * Change for supporting user-settable service-octet.
181 * Revision 1.13 1995/10/29 21:41:07 fritz
182 * Added support for DriverId's, added Jan's patches for Kernel versions.
184 * Revision 1.12 1995/04/29 13:07:35 fritz
185 * Added support for new Euro-ISDN-firmware
187 * Revision 1.11 1995/04/23 13:40:45 fritz
188 * Added support for SPV's.
189 * Changed Dial-Command to support MSN's on DSS1-Lines.
191 * Revision 1.10 1995/03/25 23:23:24 fritz
192 * Changed configurable Ports, to allow settings for DIP-Switch Cardversions.
194 * Revision 1.9 1995/03/25 23:17:30 fritz
195 * Fixed race-condition in pollbchan_send
197 * Revision 1.8 1995/03/15 12:49:44 fritz
198 * Added support for SPV's
199 * Split pollbchan_work for calling send-routine directly
201 * Revision 1.7 1995/02/20 03:48:03 fritz
202 * Added support of new request_region-function.
203 * Minor bugfixes.
205 * Revision 1.6 1995/01/31 15:48:45 fritz
206 * Added Cause-Messages to be signaled to upper layers.
207 * Added Revision-Info on load.
209 * Revision 1.5 1995/01/29 23:34:59 fritz
210 * Added stopdriver() and appropriate calls.
211 * Changed printk-statements to support loglevels.
213 * Revision 1.4 1995/01/09 07:40:46 fritz
214 * Added GPL-Notice
216 * Revision 1.3 1995/01/04 05:15:18 fritz
217 * Added undocumented "bootload-finished"-command in download-code
218 * to satisfy some brain-damaged icn card-versions.
220 * Revision 1.2 1995/01/02 02:14:45 fritz
221 * Misc Bugfixes
223 * Revision 1.1 1994/12/14 17:56:06 fritz
224 * Initial revision
228 #include "icn.h"
231 * Verbose bootcode- and protocol-downloading.
233 #undef BOOT_DEBUG
236 * Verbose Shmem-Mapping.
238 #undef MAP_DEBUG
240 static char
241 *revision = "$Revision: 1.59 $";
243 static int icn_addcard(int, char *, char *);
246 * Free send-queue completely.
247 * Parameter:
248 * card = pointer to card struct
249 * channel = channel number
251 static void
252 icn_free_queue(icn_card * card, int channel)
254 struct sk_buff_head *queue = &card->spqueue[channel];
255 struct sk_buff *skb;
256 unsigned long flags;
258 while ((skb = skb_dequeue(queue)))
259 dev_kfree_skb(skb);
260 save_flags(flags);
261 cli();
262 card->xlen[channel] = 0;
263 card->sndcount[channel] = 0;
264 if ((skb = card->xskb[channel])) {
265 card->xskb[channel] = NULL;
266 restore_flags(flags);
267 dev_kfree_skb(skb);
268 } else
269 restore_flags(flags);
272 /* Put a value into a shift-register, highest bit first.
273 * Parameters:
274 * port = port for output (bit 0 is significant)
275 * val = value to be output
276 * firstbit = Bit-Number of highest bit
277 * bitcount = Number of bits to output
279 static inline void
280 icn_shiftout(unsigned short port,
281 unsigned long val,
282 int firstbit,
283 int bitcount)
286 register u_char s;
287 register u_char c;
289 for (s = firstbit, c = bitcount; c > 0; s--, c--)
290 OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port);
294 * disable a cards shared memory
296 static inline void
297 icn_disable_ram(icn_card * card)
299 OUTB_P(0, ICN_MAPRAM);
303 * enable a cards shared memory
305 static inline void
306 icn_enable_ram(icn_card * card)
308 OUTB_P(0xff, ICN_MAPRAM);
312 * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12)
314 static inline void
315 icn_map_channel(icn_card * card, int channel)
317 #ifdef MAP_DEBUG
318 printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel);
319 #endif
320 if ((channel == dev.channel) && (card == dev.mcard))
321 return;
322 if (dev.mcard)
323 icn_disable_ram(dev.mcard);
324 icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4); /* Select Bank */
325 icn_enable_ram(card);
326 dev.mcard = card;
327 dev.channel = channel;
328 #ifdef MAP_DEBUG
329 printk(KERN_DEBUG "icn_map_channel done\n");
330 #endif
334 * Lock a cards channel.
335 * Return 0 if requested card/channel is unmapped (failure).
336 * Return 1 on success.
338 static inline int
339 icn_lock_channel(icn_card * card, int channel)
341 register int retval;
342 ulong flags;
344 #ifdef MAP_DEBUG
345 printk(KERN_DEBUG "icn_lock_channel %d\n", channel);
346 #endif
347 save_flags(flags);
348 cli();
349 if ((dev.channel == channel) && (card == dev.mcard)) {
350 dev.chanlock++;
351 retval = 1;
352 #ifdef MAP_DEBUG
353 printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel);
354 #endif
355 } else {
356 retval = 0;
357 #ifdef MAP_DEBUG
358 printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel);
359 #endif
361 restore_flags(flags);
362 return retval;
366 * Release current card/channel lock
368 static inline void
369 icn_release_channel(void)
371 ulong flags;
373 #ifdef MAP_DEBUG
374 printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock);
375 #endif
376 save_flags(flags);
377 cli();
378 if (dev.chanlock > 0)
379 dev.chanlock--;
380 restore_flags(flags);
384 * Try to map and lock a cards channel.
385 * Return 1 on success, 0 on failure.
387 static inline int
388 icn_trymaplock_channel(icn_card * card, int channel)
390 ulong flags;
392 #ifdef MAP_DEBUG
393 printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel,
394 dev.chanlock);
395 #endif
396 save_flags(flags);
397 cli();
398 if ((!dev.chanlock) ||
399 ((dev.channel == channel) && (dev.mcard == card))) {
400 dev.chanlock++;
401 icn_map_channel(card, channel);
402 restore_flags(flags);
403 #ifdef MAP_DEBUG
404 printk(KERN_DEBUG "trymaplock %d OK\n", channel);
405 #endif
406 return 1;
408 restore_flags(flags);
409 #ifdef MAP_DEBUG
410 printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);
411 #endif
412 return 0;
416 * Release current card/channel lock,
417 * then map same or other channel without locking.
419 static inline void
420 icn_maprelease_channel(icn_card * card, int channel)
422 ulong flags;
424 #ifdef MAP_DEBUG
425 printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);
426 #endif
427 save_flags(flags);
428 cli();
429 if (dev.chanlock > 0)
430 dev.chanlock--;
431 if (!dev.chanlock)
432 icn_map_channel(card, channel);
433 restore_flags(flags);
436 /* Get Data from the B-Channel, assemble fragmented packets and put them
437 * into receive-queue. Wake up any B-Channel-reading processes.
438 * This routine is called via timer-callback from icn_pollbchan().
441 static void
442 icn_pollbchan_receive(int channel, icn_card * card)
444 int mch = channel + ((card->secondhalf) ? 2 : 0);
445 int eflag;
446 int cnt;
447 struct sk_buff *skb;
449 if (icn_trymaplock_channel(card, mch)) {
450 while (rbavl) {
451 cnt = readb(&rbuf_l);
452 if ((card->rcvidx[channel] + cnt) > 4000) {
453 printk(KERN_WARNING
454 "icn: (%s) bogus packet on ch%d, dropping.\n",
455 CID,
456 channel + 1);
457 card->rcvidx[channel] = 0;
458 eflag = 0;
459 } else {
460 memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]],
461 &rbuf_d, cnt);
462 card->rcvidx[channel] += cnt;
463 eflag = readb(&rbuf_f);
465 rbnext;
466 icn_maprelease_channel(card, mch & 2);
467 if (!eflag) {
468 if ((cnt = card->rcvidx[channel])) {
469 if (!(skb = dev_alloc_skb(cnt))) {
470 printk(KERN_WARNING "ïcn: receive out of memory\n");
471 break;
473 memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt);
474 card->rcvidx[channel] = 0;
475 card->interface.rcvcallb_skb(card->myid, channel, skb);
478 if (!icn_trymaplock_channel(card, mch))
479 break;
481 icn_maprelease_channel(card, mch & 2);
485 /* Send data-packet to B-Channel, split it up into fragments of
486 * ICN_FRAGSIZE length. If last fragment is sent out, signal
487 * success to upper layers via statcallb with ISDN_STAT_BSENT argument.
488 * This routine is called via timer-callback from icn_pollbchan() or
489 * directly from icn_sendbuf().
492 static void
493 icn_pollbchan_send(int channel, icn_card * card)
495 int mch = channel + ((card->secondhalf) ? 2 : 0);
496 int cnt;
497 unsigned long flags;
498 struct sk_buff *skb;
499 isdn_ctrl cmd;
501 if (!(card->sndcount[channel] || card->xskb[channel] ||
502 skb_queue_len(&card->spqueue[channel])))
503 return;
504 if (icn_trymaplock_channel(card, mch)) {
505 while (sbfree &&
506 (card->sndcount[channel] ||
507 skb_queue_len(&card->spqueue[channel]) ||
508 card->xskb[channel])) {
509 save_flags(flags);
510 cli();
511 if (card->xmit_lock[channel]) {
512 restore_flags(flags);
513 break;
515 card->xmit_lock[channel]++;
516 restore_flags(flags);
517 skb = card->xskb[channel];
518 if (!skb) {
519 skb = skb_dequeue(&card->spqueue[channel]);
520 if (skb) {
521 /* Pop ACK-flag off skb.
522 * Store length to xlen.
524 if (*(skb_pull(skb,1)))
525 card->xlen[channel] = skb->len;
526 else
527 card->xlen[channel] = 0;
530 if (!skb)
531 break;
532 if (skb->len > ICN_FRAGSIZE) {
533 writeb(0xff, &sbuf_f);
534 cnt = ICN_FRAGSIZE;
535 } else {
536 writeb(0x0, &sbuf_f);
537 cnt = skb->len;
539 writeb(cnt, &sbuf_l);
540 memcpy_toio(&sbuf_d, skb->data, cnt);
541 skb_pull(skb, cnt);
542 card->sndcount[channel] -= cnt;
543 sbnext; /* switch to next buffer */
544 icn_maprelease_channel(card, mch & 2);
545 if (!skb->len) {
546 save_flags(flags);
547 cli();
548 if (card->xskb[channel]) {
549 card->xskb[channel] = NULL;
550 restore_flags(flags);
551 dev_kfree_skb(skb);
552 } else
553 restore_flags(flags);
554 if (card->xlen[channel]) {
555 cmd.command = ISDN_STAT_BSENT;
556 cmd.driver = card->myid;
557 cmd.arg = channel;
558 cmd.parm.length = card->xlen[channel];
559 card->interface.statcallb(&cmd);
561 } else {
562 save_flags(flags);
563 cli();
564 card->xskb[channel] = skb;
565 restore_flags(flags);
567 card->xmit_lock[channel] = 0;
568 if (!icn_trymaplock_channel(card, mch))
569 break;
571 icn_maprelease_channel(card, mch & 2);
575 /* Send/Receive Data to/from the B-Channel.
576 * This routine is called via timer-callback.
577 * It schedules itself while any B-Channel is open.
580 static void
581 icn_pollbchan(unsigned long data)
583 icn_card *card = (icn_card *) data;
584 unsigned long flags;
586 if (card->flags & ICN_FLAGS_B1ACTIVE) {
587 icn_pollbchan_receive(0, card);
588 icn_pollbchan_send(0, card);
590 if (card->flags & ICN_FLAGS_B2ACTIVE) {
591 icn_pollbchan_receive(1, card);
592 icn_pollbchan_send(1, card);
594 if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
595 /* schedule b-channel polling again */
596 save_flags(flags);
597 cli();
598 del_timer(&card->rb_timer);
599 card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
600 add_timer(&card->rb_timer);
601 card->flags |= ICN_FLAGS_RBTIMER;
602 restore_flags(flags);
603 } else
604 card->flags &= ~ICN_FLAGS_RBTIMER;
607 typedef struct icn_stat {
608 char *statstr;
609 int command;
610 int action;
611 } icn_stat;
612 /* *INDENT-OFF* */
613 static icn_stat icn_stat_table[] =
615 {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */
616 {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */
618 ** add d-channel connect and disconnect support to link-level
620 {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */
621 {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */
622 {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */
623 {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */
624 {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */
625 {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */
626 {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */
627 {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */
628 {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */
629 {"NO D-CHAN", ISDN_STAT_NODCH, 0}, /* No D-channel available */
630 {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
631 {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */
632 {"E_L1: ACTIVATION FAILED",
633 ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
634 {NULL, 0, -1}
636 /* *INDENT-ON* */
640 * Check Statusqueue-Pointer from isdn-cards.
641 * If there are new status-replies from the interface, check
642 * them against B-Channel-connects/disconnects and set flags accordingly.
643 * Wake-Up any processes, who are reading the status-device.
644 * If there are B-Channels open, initiate a timer-callback to
645 * icn_pollbchan().
646 * This routine is called periodically via timer.
649 static void
650 icn_parse_status(u_char * status, int channel, icn_card * card)
652 icn_stat *s = icn_stat_table;
653 int action = -1;
654 unsigned long flags;
655 isdn_ctrl cmd;
657 while (s->statstr) {
658 if (!strncmp(status, s->statstr, strlen(s->statstr))) {
659 cmd.command = s->command;
660 action = s->action;
661 break;
663 s++;
665 if (action == -1)
666 return;
667 cmd.driver = card->myid;
668 cmd.arg = channel;
669 switch (action) {
670 case 11:
671 save_flags(flags);
672 cli();
673 icn_free_queue(card,channel);
674 card->rcvidx[channel] = 0;
676 if (card->flags &
677 ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {
679 isdn_ctrl ncmd;
681 card->flags &= ~((channel)?
682 ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);
684 memset(&ncmd, 0, sizeof(ncmd));
686 ncmd.driver = card->myid;
687 ncmd.arg = channel;
688 ncmd.command = ISDN_STAT_BHUP;
689 restore_flags(flags);
690 card->interface.statcallb(&cmd);
691 } else
692 restore_flags(flags);
694 break;
695 case 1:
696 icn_free_queue(card,channel);
697 card->flags |= (channel) ?
698 ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
699 break;
700 case 2:
701 card->flags &= ~((channel) ?
702 ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);
703 icn_free_queue(card, channel);
704 save_flags(flags);
705 cli();
706 card->rcvidx[channel] = 0;
707 restore_flags(flags);
708 break;
709 case 3:
711 char *t = status + 6;
712 char *s = strpbrk(t, ",");
714 *s++ = '\0';
715 strncpy(cmd.parm.setup.phone, t,
716 sizeof(cmd.parm.setup.phone));
717 s = strpbrk(t = s, ",");
718 *s++ = '\0';
719 if (!strlen(t))
720 cmd.parm.setup.si1 = 0;
721 else
722 cmd.parm.setup.si1 =
723 simple_strtoul(t, NULL, 10);
724 s = strpbrk(t = s, ",");
725 *s++ = '\0';
726 if (!strlen(t))
727 cmd.parm.setup.si2 = 0;
728 else
729 cmd.parm.setup.si2 =
730 simple_strtoul(t, NULL, 10);
731 strncpy(cmd.parm.setup.eazmsn, s,
732 sizeof(cmd.parm.setup.eazmsn));
734 cmd.parm.setup.plan = 0;
735 cmd.parm.setup.screen = 0;
736 break;
737 case 4:
738 sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
739 sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
740 cmd.parm.setup.si1 = 7;
741 cmd.parm.setup.si2 = 0;
742 cmd.parm.setup.plan = 0;
743 cmd.parm.setup.screen = 0;
744 break;
745 case 5:
746 strncpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num) - 1);
747 break;
748 case 6:
749 sprintf(cmd.parm.num, "%d",
750 (int) simple_strtoul(status + 7, NULL, 16));
751 break;
752 case 7:
753 status += 3;
754 if (strlen(status) == 4)
755 sprintf(cmd.parm.num, "%s%c%c",
756 status + 2, *status, *(status + 1));
757 else
758 strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1);
759 break;
760 case 8:
761 card->flags &= ~ICN_FLAGS_B1ACTIVE;
762 icn_free_queue(card, 0);
763 save_flags(flags);
764 cli();
765 card->rcvidx[0] = 0;
766 restore_flags(flags);
767 cmd.arg = 0;
768 cmd.driver = card->myid;
769 card->interface.statcallb(&cmd);
770 cmd.command = ISDN_STAT_DHUP;
771 cmd.arg = 0;
772 cmd.driver = card->myid;
773 card->interface.statcallb(&cmd);
774 cmd.command = ISDN_STAT_BHUP;
775 card->flags &= ~ICN_FLAGS_B2ACTIVE;
776 icn_free_queue(card, 1);
777 save_flags(flags);
778 cli();
779 card->rcvidx[1] = 0;
780 restore_flags(flags);
781 cmd.arg = 1;
782 cmd.driver = card->myid;
783 card->interface.statcallb(&cmd);
784 cmd.command = ISDN_STAT_DHUP;
785 cmd.arg = 1;
786 cmd.driver = card->myid;
787 break;
789 card->interface.statcallb(&cmd);
790 return;
793 static void
794 icn_putmsg(icn_card * card, unsigned char c)
796 ulong flags;
798 save_flags(flags);
799 cli();
800 *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
801 if (card->msg_buf_write == card->msg_buf_read) {
802 if (++card->msg_buf_read > card->msg_buf_end)
803 card->msg_buf_read = card->msg_buf;
805 if (card->msg_buf_write > card->msg_buf_end)
806 card->msg_buf_write = card->msg_buf;
807 restore_flags(flags);
810 static void
811 icn_polldchan(unsigned long data)
813 icn_card *card = (icn_card *) data;
814 int mch = card->secondhalf ? 2 : 0;
815 int avail = 0;
816 int left;
817 u_char c;
818 int ch;
819 int flags;
820 int i;
821 u_char *p;
822 isdn_ctrl cmd;
824 if (icn_trymaplock_channel(card, mch)) {
825 avail = msg_avail;
826 for (left = avail, i = readb(&msg_o); left > 0; i++, left--) {
827 c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]);
828 icn_putmsg(card, c);
829 if (c == 0xff) {
830 card->imsg[card->iptr] = 0;
831 card->iptr = 0;
832 if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
833 card->imsg[1] <= '2' && card->imsg[2] == ';') {
834 ch = (card->imsg[1] - '0') - 1;
835 p = &card->imsg[3];
836 icn_parse_status(p, ch, card);
837 } else {
838 p = card->imsg;
839 if (!strncmp(p, "DRV1.", 5)) {
840 u_char vstr[10];
841 u_char *q = vstr;
843 printk(KERN_INFO "icn: (%s) %s\n", CID, p);
844 if (!strncmp(p + 7, "TC", 2)) {
845 card->ptype = ISDN_PTYPE_1TR6;
846 card->interface.features |= ISDN_FEATURE_P_1TR6;
847 printk(KERN_INFO
848 "icn: (%s) 1TR6-Protocol loaded and running\n", CID);
850 if (!strncmp(p + 7, "EC", 2)) {
851 card->ptype = ISDN_PTYPE_EURO;
852 card->interface.features |= ISDN_FEATURE_P_EURO;
853 printk(KERN_INFO
854 "icn: (%s) Euro-Protocol loaded and running\n", CID);
856 p = strstr(card->imsg, "BRV") + 3;
857 while (*p) {
858 if (*p >= '0' && *p <= '9')
859 *q++ = *p;
860 p++;
862 *q = '\0';
863 strcat(vstr, "000");
864 vstr[3] = '\0';
865 card->fw_rev = (int) simple_strtoul(vstr, NULL, 10);
866 continue;
870 } else {
871 card->imsg[card->iptr] = c;
872 if (card->iptr < 59)
873 card->iptr++;
876 writeb((readb(&msg_o) + avail) & 0xff, &msg_o);
877 icn_release_channel();
879 if (avail) {
880 cmd.command = ISDN_STAT_STAVAIL;
881 cmd.driver = card->myid;
882 cmd.arg = avail;
883 card->interface.statcallb(&cmd);
885 if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
886 if (!(card->flags & ICN_FLAGS_RBTIMER)) {
887 /* schedule b-channel polling */
888 card->flags |= ICN_FLAGS_RBTIMER;
889 save_flags(flags);
890 cli();
891 del_timer(&card->rb_timer);
892 card->rb_timer.function = icn_pollbchan;
893 card->rb_timer.data = (unsigned long) card;
894 card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
895 add_timer(&card->rb_timer);
896 restore_flags(flags);
898 /* schedule again */
899 save_flags(flags);
900 cli();
901 del_timer(&card->st_timer);
902 card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
903 add_timer(&card->st_timer);
904 restore_flags(flags);
907 /* Append a packet to the transmit buffer-queue.
908 * Parameters:
909 * channel = Number of B-channel
910 * skb = pointer to sk_buff
911 * card = pointer to card-struct
912 * Return:
913 * Number of bytes transferred, -E??? on error
916 static int
917 icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card)
919 int len = skb->len;
920 unsigned long flags;
921 struct sk_buff *nskb;
923 if (len > 4000) {
924 printk(KERN_WARNING
925 "icn: Send packet too large\n");
926 return -EINVAL;
928 if (len) {
929 if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE))
930 return 0;
931 if (card->sndcount[channel] > ICN_MAX_SQUEUE)
932 return 0;
933 save_flags(flags);
934 cli();
935 nskb = skb_clone(skb, GFP_ATOMIC);
936 if (nskb) {
937 /* Push ACK flag as one
938 * byte in front of data.
940 *(skb_push(nskb, 1)) = ack?1:0;
941 skb_queue_tail(&card->spqueue[channel], nskb);
942 dev_kfree_skb(skb);
943 } else
944 len = 0;
945 card->sndcount[channel] += len;
946 restore_flags(flags);
948 return len;
952 * Check card's status after starting the bootstrap loader.
953 * On entry, the card's shared memory has already to be mapped.
954 * Return:
955 * 0 on success (Boot loader ready)
956 * -EIO on failure (timeout)
958 static int
959 icn_check_loader(int cardnumber)
961 int timer = 0;
963 while (1) {
964 #ifdef BOOT_DEBUG
965 printk(KERN_DEBUG "Loader %d ?\n", cardnumber);
966 #endif
967 if (readb(&dev.shmem->data_control.scns) ||
968 readb(&dev.shmem->data_control.scnr)) {
969 if (timer++ > 5) {
970 printk(KERN_WARNING
971 "icn: Boot-Loader %d timed out.\n",
972 cardnumber);
973 icn_release_channel();
974 return -EIO;
976 #ifdef BOOT_DEBUG
977 printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);
978 #endif
979 current->state = TASK_INTERRUPTIBLE;
980 schedule_timeout(ICN_BOOT_TIMEOUT1);
981 } else {
982 #ifdef BOOT_DEBUG
983 printk(KERN_DEBUG "Loader %d OK\n", cardnumber);
984 #endif
985 icn_release_channel();
986 return 0;
991 /* Load the boot-code into the interface-card's memory and start it.
992 * Always called from user-process.
994 * Parameters:
995 * buffer = pointer to packet
996 * Return:
997 * 0 if successfully loaded
1000 #ifdef BOOT_DEBUG
1001 #define SLEEP(sec) { \
1002 int slsec = sec; \
1003 printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \
1004 while (slsec) { \
1005 current->state = TASK_INTERRUPTIBLE; \
1006 schedule_timeout(HZ); \
1007 slsec--; \
1010 #else
1011 #define SLEEP(sec)
1012 #endif
1014 static int
1015 icn_loadboot(u_char * buffer, icn_card * card)
1017 int ret;
1018 ulong flags;
1019 u_char *codebuf;
1021 #ifdef BOOT_DEBUG
1022 printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
1023 #endif
1024 if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) {
1025 printk(KERN_WARNING "icn: Could not allocate code buffer\n");
1026 return -ENOMEM;
1028 if ((ret = copy_from_user(codebuf, buffer, ICN_CODE_STAGE1))) {
1029 kfree(codebuf);
1030 return ret;
1032 save_flags(flags);
1033 cli();
1034 if (!card->rvalid) {
1035 if (check_region(card->port, ICN_PORTLEN)) {
1036 printk(KERN_WARNING
1037 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1038 CID,
1039 card->port,
1040 card->port + ICN_PORTLEN);
1041 restore_flags(flags);
1042 kfree(codebuf);
1043 return -EBUSY;
1045 request_region(card->port, ICN_PORTLEN, card->regname);
1046 card->rvalid = 1;
1047 if (card->doubleS0)
1048 card->other->rvalid = 1;
1050 if (!dev.mvalid) {
1051 if (check_shmem((ulong) dev.shmem, 0x4000)) {
1052 printk(KERN_WARNING
1053 "icn: memory at 0x%08lx in use.\n",
1054 (ulong) dev.shmem);
1055 restore_flags(flags);
1056 return -EBUSY;
1058 request_shmem((ulong) dev.shmem, 0x4000, "icn");
1059 dev.mvalid = 1;
1061 restore_flags(flags);
1062 OUTB_P(0, ICN_RUN); /* Reset Controller */
1063 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
1064 icn_shiftout(ICN_CFG, 0x0f, 3, 4); /* Windowsize= 16k */
1065 icn_shiftout(ICN_CFG, (unsigned long) dev.shmem, 23, 10); /* Set RAM-Addr. */
1066 #ifdef BOOT_DEBUG
1067 printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev.shmem);
1068 #endif
1069 SLEEP(1);
1070 #ifdef BOOT_DEBUG
1071 printk(KERN_DEBUG "Map Bank 0\n");
1072 #endif
1073 save_flags(flags);
1074 cli();
1075 icn_map_channel(card, 0); /* Select Bank 0 */
1076 icn_lock_channel(card, 0); /* Lock Bank 0 */
1077 restore_flags(flags);
1078 SLEEP(1);
1079 memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
1080 #ifdef BOOT_DEBUG
1081 printk(KERN_DEBUG "Bootloader transfered\n");
1082 #endif
1083 if (card->doubleS0) {
1084 SLEEP(1);
1085 #ifdef BOOT_DEBUG
1086 printk(KERN_DEBUG "Map Bank 8\n");
1087 #endif
1088 save_flags(flags);
1089 cli();
1090 icn_release_channel();
1091 icn_map_channel(card, 2); /* Select Bank 8 */
1092 icn_lock_channel(card, 2); /* Lock Bank 8 */
1093 restore_flags(flags);
1094 SLEEP(1);
1095 memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
1096 #ifdef BOOT_DEBUG
1097 printk(KERN_DEBUG "Bootloader transfered\n");
1098 #endif
1100 kfree(codebuf);
1101 SLEEP(1);
1102 OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */
1103 if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1)))
1104 return ret;
1105 if (!card->doubleS0)
1106 return 0;
1107 /* reached only, if we have a Double-S0-Card */
1108 #ifdef BOOT_DEBUG
1109 printk(KERN_DEBUG "Map Bank 0\n");
1110 #endif
1111 save_flags(flags);
1112 cli();
1113 icn_map_channel(card, 0); /* Select Bank 0 */
1114 icn_lock_channel(card, 0); /* Lock Bank 0 */
1115 restore_flags(flags);
1116 SLEEP(1);
1117 return (icn_check_loader(1));
1120 static int
1121 icn_loadproto(u_char * buffer, icn_card * card)
1123 register u_char *p = buffer;
1124 u_char codebuf[256];
1125 uint left = ICN_CODE_STAGE2;
1126 uint cnt;
1127 int timer;
1128 int ret;
1129 unsigned long flags;
1131 #ifdef BOOT_DEBUG
1132 printk(KERN_DEBUG "icn_loadproto called\n");
1133 #endif
1134 if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2)))
1135 return ret;
1136 timer = 0;
1137 save_flags(flags);
1138 cli();
1139 if (card->secondhalf) {
1140 icn_map_channel(card, 2);
1141 icn_lock_channel(card, 2);
1142 } else {
1143 icn_map_channel(card, 0);
1144 icn_lock_channel(card, 0);
1146 restore_flags(flags);
1147 while (left) {
1148 if (sbfree) { /* If there is a free buffer... */
1149 cnt = MIN(256, left);
1150 if (copy_from_user(codebuf, p, cnt)) {
1151 icn_maprelease_channel(card, 0);
1152 return -EFAULT;
1154 memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */
1155 sbnext; /* switch to next buffer */
1156 p += cnt;
1157 left -= cnt;
1158 timer = 0;
1159 } else {
1160 #ifdef BOOT_DEBUG
1161 printk(KERN_DEBUG "boot 2 !sbfree\n");
1162 #endif
1163 if (timer++ > 5) {
1164 icn_maprelease_channel(card, 0);
1165 return -EIO;
1167 current->state = TASK_INTERRUPTIBLE;
1168 schedule_timeout(10);
1171 writeb(0x20, &sbuf_n);
1172 timer = 0;
1173 while (1) {
1174 if (readb(&cmd_o) || readb(&cmd_i)) {
1175 #ifdef BOOT_DEBUG
1176 printk(KERN_DEBUG "Proto?\n");
1177 #endif
1178 if (timer++ > 5) {
1179 printk(KERN_WARNING
1180 "icn: (%s) Protocol timed out.\n",
1181 CID);
1182 #ifdef BOOT_DEBUG
1183 printk(KERN_DEBUG "Proto TO!\n");
1184 #endif
1185 icn_maprelease_channel(card, 0);
1186 return -EIO;
1188 #ifdef BOOT_DEBUG
1189 printk(KERN_DEBUG "Proto TO?\n");
1190 #endif
1191 current->state = TASK_INTERRUPTIBLE;
1192 schedule_timeout(ICN_BOOT_TIMEOUT1);
1193 } else {
1194 if ((card->secondhalf) || (!card->doubleS0)) {
1195 #ifdef BOOT_DEBUG
1196 printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
1197 card->secondhalf);
1198 #endif
1199 save_flags(flags);
1200 cli();
1201 init_timer(&card->st_timer);
1202 card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
1203 card->st_timer.function = icn_polldchan;
1204 card->st_timer.data = (unsigned long) card;
1205 add_timer(&card->st_timer);
1206 card->flags |= ICN_FLAGS_RUNNING;
1207 if (card->doubleS0) {
1208 init_timer(&card->other->st_timer);
1209 card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
1210 card->other->st_timer.function = icn_polldchan;
1211 card->other->st_timer.data = (unsigned long) card->other;
1212 add_timer(&card->other->st_timer);
1213 card->other->flags |= ICN_FLAGS_RUNNING;
1215 restore_flags(flags);
1217 icn_maprelease_channel(card, 0);
1218 return 0;
1223 /* Read the Status-replies from the Interface */
1224 static int
1225 icn_readstatus(u_char * buf, int len, int user, icn_card * card)
1227 int count;
1228 u_char *p;
1230 for (p = buf, count = 0; count < len; p++, count++) {
1231 if (card->msg_buf_read == card->msg_buf_write)
1232 return count;
1233 if (user)
1234 put_user(*card->msg_buf_read++, p);
1235 else
1236 *p = *card->msg_buf_read++;
1237 if (card->msg_buf_read > card->msg_buf_end)
1238 card->msg_buf_read = card->msg_buf;
1240 return count;
1243 /* Put command-strings into the command-queue of the Interface */
1244 static int
1245 icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
1247 int mch = card->secondhalf ? 2 : 0;
1248 int avail;
1249 int pp;
1250 int i;
1251 int count;
1252 int xcount;
1253 int ocount;
1254 int loop;
1255 unsigned long flags;
1256 int lastmap_channel;
1257 struct icn_card *lastmap_card;
1258 u_char *p;
1259 isdn_ctrl cmd;
1260 u_char msg[0x100];
1262 ocount = 1;
1263 xcount = loop = 0;
1264 while (len) {
1265 save_flags(flags);
1266 cli();
1267 lastmap_card = dev.mcard;
1268 lastmap_channel = dev.channel;
1269 icn_map_channel(card, mch);
1271 avail = cmd_free;
1272 count = MIN(avail, len);
1273 if (user)
1274 copy_from_user(msg, buf, count);
1275 else
1276 memcpy(msg, buf, count);
1277 icn_putmsg(card, '>');
1278 for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
1279 ++) {
1280 writeb((*p == '\n') ? 0xff : *p,
1281 &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);
1282 len--;
1283 xcount++;
1284 icn_putmsg(card, *p);
1285 if ((*p == '\n') && (i > 1)) {
1286 icn_putmsg(card, '>');
1287 ocount++;
1289 ocount++;
1291 writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
1292 if (lastmap_card)
1293 icn_map_channel(lastmap_card, lastmap_channel);
1294 restore_flags(flags);
1295 if (len) {
1296 mdelay(1);
1297 if (loop++ > 20)
1298 break;
1299 } else
1300 break;
1302 if (len && (!user))
1303 printk(KERN_WARNING "icn: writemsg incomplete!\n");
1304 cmd.command = ISDN_STAT_STAVAIL;
1305 cmd.driver = card->myid;
1306 cmd.arg = ocount;
1307 card->interface.statcallb(&cmd);
1308 return xcount;
1312 * Delete card's pending timers, send STOP to linklevel
1314 static void
1315 icn_stopcard(icn_card * card)
1317 unsigned long flags;
1318 isdn_ctrl cmd;
1320 save_flags(flags);
1321 cli();
1322 if (card->flags & ICN_FLAGS_RUNNING) {
1323 card->flags &= ~ICN_FLAGS_RUNNING;
1324 del_timer(&card->st_timer);
1325 del_timer(&card->rb_timer);
1326 cmd.command = ISDN_STAT_STOP;
1327 cmd.driver = card->myid;
1328 card->interface.statcallb(&cmd);
1329 if (card->doubleS0)
1330 icn_stopcard(card->other);
1332 restore_flags(flags);
1335 static void
1336 icn_stopallcards(void)
1338 icn_card *p = cards;
1340 while (p) {
1341 icn_stopcard(p);
1342 p = p->next;
1347 * Unmap all cards, because some of them may be mapped accidetly during
1348 * autoprobing of some network drivers (SMC-driver?)
1350 static void
1351 icn_disable_cards(void)
1353 icn_card *card = cards;
1354 unsigned long flags;
1356 save_flags(flags);
1357 cli();
1358 while (card) {
1359 if (check_region(card->port, ICN_PORTLEN)) {
1360 printk(KERN_WARNING
1361 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1362 CID,
1363 card->port,
1364 card->port + ICN_PORTLEN);
1365 cli();
1366 } else {
1367 OUTB_P(0, ICN_RUN); /* Reset Controller */
1368 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
1370 card = card->next;
1372 restore_flags(flags);
1375 static int
1376 icn_command(isdn_ctrl * c, icn_card * card)
1378 ulong a;
1379 ulong flags;
1380 int i;
1381 char cbuf[60];
1382 isdn_ctrl cmd;
1383 icn_cdef cdef;
1385 switch (c->command) {
1386 case ISDN_CMD_IOCTL:
1387 memcpy(&a, c->parm.num, sizeof(ulong));
1388 switch (c->arg) {
1389 case ICN_IOCTL_SETMMIO:
1390 if ((unsigned long) dev.shmem != (a & 0x0ffc000)) {
1391 if (check_shmem((ulong) (a & 0x0ffc000), 0x4000)) {
1392 printk(KERN_WARNING
1393 "icn: memory at 0x%08lx in use.\n",
1394 (ulong) (a & 0x0ffc000));
1395 return -EINVAL;
1397 icn_stopallcards();
1398 save_flags(flags);
1399 cli();
1400 if (dev.mvalid)
1401 release_shmem((ulong) dev.shmem, 0x4000);
1402 dev.mvalid = 0;
1403 dev.shmem = (icn_shmem *) (a & 0x0ffc000);
1404 restore_flags(flags);
1405 printk(KERN_INFO
1406 "icn: (%s) mmio set to 0x%08lx\n",
1407 CID,
1408 (unsigned long) dev.shmem);
1410 break;
1411 case ICN_IOCTL_GETMMIO:
1412 return (long) dev.shmem;
1413 case ICN_IOCTL_SETPORT:
1414 if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
1415 || a == 0x340 || a == 0x350 || a == 0x360 ||
1416 a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338
1417 || a == 0x348 || a == 0x358 || a == 0x368) {
1418 if (card->port != (unsigned short) a) {
1419 if (check_region((unsigned short) a, ICN_PORTLEN)) {
1420 printk(KERN_WARNING
1421 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1422 CID, (int) a, (int) a + ICN_PORTLEN);
1423 return -EINVAL;
1425 icn_stopcard(card);
1426 save_flags(flags);
1427 cli();
1428 if (card->rvalid)
1429 release_region(card->port, ICN_PORTLEN);
1430 card->port = (unsigned short) a;
1431 card->rvalid = 0;
1432 if (card->doubleS0) {
1433 card->other->port = (unsigned short) a;
1434 card->other->rvalid = 0;
1436 restore_flags(flags);
1437 printk(KERN_INFO
1438 "icn: (%s) port set to 0x%03x\n",
1439 CID, card->port);
1441 } else
1442 return -EINVAL;
1443 break;
1444 case ICN_IOCTL_GETPORT:
1445 return (int) card->port;
1446 case ICN_IOCTL_GETDOUBLE:
1447 return (int) card->doubleS0;
1448 case ICN_IOCTL_DEBUGVAR:
1449 if ((i = copy_to_user((char *) a,
1450 (char *) &card, sizeof(ulong))))
1451 return i;
1452 a += sizeof(ulong);
1454 ulong l = (ulong) & dev;
1455 if ((i = copy_to_user((char *) a,
1456 (char *) &l, sizeof(ulong))))
1457 return i;
1459 return 0;
1460 case ICN_IOCTL_LOADBOOT:
1461 if (dev.firstload) {
1462 icn_disable_cards();
1463 dev.firstload = 0;
1465 icn_stopcard(card);
1466 return (icn_loadboot((u_char *) a, card));
1467 case ICN_IOCTL_LOADPROTO:
1468 icn_stopcard(card);
1469 if ((i = (icn_loadproto((u_char *) a, card))))
1470 return i;
1471 if (card->doubleS0)
1472 i = icn_loadproto((u_char *) (a + ICN_CODE_STAGE2), card->other);
1473 return i;
1474 break;
1475 case ICN_IOCTL_ADDCARD:
1476 if (!dev.firstload)
1477 return -EBUSY;
1478 if ((i = copy_from_user((char *) &cdef, (char *) a, sizeof(cdef))))
1479 return i;
1480 return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
1481 break;
1482 case ICN_IOCTL_LEASEDCFG:
1483 if (a) {
1484 if (!card->leased) {
1485 card->leased = 1;
1486 while (card->ptype == ISDN_PTYPE_UNKNOWN) {
1487 schedule_timeout(ICN_BOOT_TIMEOUT1);
1489 schedule_timeout(ICN_BOOT_TIMEOUT1);
1490 sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",
1491 (a & 1)?'1':'C', (a & 2)?'2':'C');
1492 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1493 printk(KERN_INFO
1494 "icn: (%s) Leased-line mode enabled\n",
1495 CID);
1496 cmd.command = ISDN_STAT_RUN;
1497 cmd.driver = card->myid;
1498 cmd.arg = 0;
1499 card->interface.statcallb(&cmd);
1501 } else {
1502 if (card->leased) {
1503 card->leased = 0;
1504 sprintf(cbuf, "00;FV2OFF\n");
1505 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1506 printk(KERN_INFO
1507 "icn: (%s) Leased-line mode disabled\n",
1508 CID);
1509 cmd.command = ISDN_STAT_RUN;
1510 cmd.driver = card->myid;
1511 cmd.arg = 0;
1512 card->interface.statcallb(&cmd);
1515 return 0;
1516 default:
1517 return -EINVAL;
1519 break;
1520 case ISDN_CMD_DIAL:
1521 if (!card->flags & ICN_FLAGS_RUNNING)
1522 return -ENODEV;
1523 if (card->leased)
1524 break;
1525 if ((c->arg & 255) < ICN_BCH) {
1526 char *p;
1527 char dial[50];
1528 char dcode[4];
1530 a = c->arg;
1531 p = c->parm.setup.phone;
1532 if (*p == 's' || *p == 'S') {
1533 /* Dial for SPV */
1534 p++;
1535 strcpy(dcode, "SCA");
1536 } else
1537 /* Normal Dial */
1538 strcpy(dcode, "CAL");
1539 strcpy(dial, p);
1540 sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
1541 dcode, dial, c->parm.setup.si1,
1542 c->parm.setup.si2, c->parm.setup.eazmsn);
1543 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1545 break;
1546 case ISDN_CMD_ACCEPTD:
1547 if (!card->flags & ICN_FLAGS_RUNNING)
1548 return -ENODEV;
1549 if (c->arg < ICN_BCH) {
1550 a = c->arg + 1;
1551 if (card->fw_rev >= 300) {
1552 switch (card->l2_proto[a - 1]) {
1553 case ISDN_PROTO_L2_X75I:
1554 sprintf(cbuf, "%02d;BX75\n", (int) a);
1555 break;
1556 case ISDN_PROTO_L2_HDLC:
1557 sprintf(cbuf, "%02d;BTRA\n", (int) a);
1558 break;
1560 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1562 sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1563 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1565 break;
1566 case ISDN_CMD_ACCEPTB:
1567 if (!card->flags & ICN_FLAGS_RUNNING)
1568 return -ENODEV;
1569 if (c->arg < ICN_BCH) {
1570 a = c->arg + 1;
1571 if (card->fw_rev >= 300)
1572 switch (card->l2_proto[a - 1]) {
1573 case ISDN_PROTO_L2_X75I:
1574 sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
1575 break;
1576 case ISDN_PROTO_L2_HDLC:
1577 sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
1578 break;
1579 } else
1580 sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1581 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1583 break;
1584 case ISDN_CMD_HANGUP:
1585 if (!card->flags & ICN_FLAGS_RUNNING)
1586 return -ENODEV;
1587 if (c->arg < ICN_BCH) {
1588 a = c->arg + 1;
1589 sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1590 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1592 break;
1593 case ISDN_CMD_SETEAZ:
1594 if (!card->flags & ICN_FLAGS_RUNNING)
1595 return -ENODEV;
1596 if (card->leased)
1597 break;
1598 if (c->arg < ICN_BCH) {
1599 a = c->arg + 1;
1600 if (card->ptype == ISDN_PTYPE_EURO) {
1601 sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
1602 c->parm.num[0] ? "N" : "ALL", c->parm.num);
1603 } else
1604 sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
1605 c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
1606 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1608 break;
1609 case ISDN_CMD_CLREAZ:
1610 if (!card->flags & ICN_FLAGS_RUNNING)
1611 return -ENODEV;
1612 if (card->leased)
1613 break;
1614 if (c->arg < ICN_BCH) {
1615 a = c->arg + 1;
1616 if (card->ptype == ISDN_PTYPE_EURO)
1617 sprintf(cbuf, "%02d;MSNC\n", (int) a);
1618 else
1619 sprintf(cbuf, "%02d;EAZC\n", (int) a);
1620 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1622 break;
1623 case ISDN_CMD_SETL2:
1624 if (!card->flags & ICN_FLAGS_RUNNING)
1625 return -ENODEV;
1626 if ((c->arg & 255) < ICN_BCH) {
1627 a = c->arg;
1628 switch (a >> 8) {
1629 case ISDN_PROTO_L2_X75I:
1630 sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1631 break;
1632 case ISDN_PROTO_L2_HDLC:
1633 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1634 break;
1635 default:
1636 return -EINVAL;
1638 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1639 card->l2_proto[a & 255] = (a >> 8);
1641 break;
1642 case ISDN_CMD_GETL2:
1643 if (!card->flags & ICN_FLAGS_RUNNING)
1644 return -ENODEV;
1645 if ((c->arg & 255) < ICN_BCH)
1646 return card->l2_proto[c->arg & 255];
1647 else
1648 return -ENODEV;
1649 case ISDN_CMD_SETL3:
1650 if (!card->flags & ICN_FLAGS_RUNNING)
1651 return -ENODEV;
1652 return 0;
1653 case ISDN_CMD_GETL3:
1654 if (!card->flags & ICN_FLAGS_RUNNING)
1655 return -ENODEV;
1656 if ((c->arg & 255) < ICN_BCH)
1657 return ISDN_PROTO_L3_TRANS;
1658 else
1659 return -ENODEV;
1660 case ISDN_CMD_GETEAZ:
1661 if (!card->flags & ICN_FLAGS_RUNNING)
1662 return -ENODEV;
1663 break;
1664 case ISDN_CMD_SETSIL:
1665 if (!card->flags & ICN_FLAGS_RUNNING)
1666 return -ENODEV;
1667 break;
1668 case ISDN_CMD_GETSIL:
1669 if (!card->flags & ICN_FLAGS_RUNNING)
1670 return -ENODEV;
1671 break;
1672 case ISDN_CMD_LOCK:
1673 MOD_INC_USE_COUNT;
1674 break;
1675 case ISDN_CMD_UNLOCK:
1676 MOD_DEC_USE_COUNT;
1677 break;
1678 default:
1679 return -EINVAL;
1681 return 0;
1685 * Find card with given driverId
1687 static inline icn_card *
1688 icn_findcard(int driverid)
1690 icn_card *p = cards;
1692 while (p) {
1693 if (p->myid == driverid)
1694 return p;
1695 p = p->next;
1697 return (icn_card *) 0;
1701 * Wrapper functions for interface to linklevel
1703 static int
1704 if_command(isdn_ctrl * c)
1706 icn_card *card = icn_findcard(c->driver);
1708 if (card)
1709 return (icn_command(c, card));
1710 printk(KERN_ERR
1711 "icn: if_command %d called with invalid driverId %d!\n",
1712 c->command, c->driver);
1713 return -ENODEV;
1716 static int
1717 if_writecmd(const u_char * buf, int len, int user, int id, int channel)
1719 icn_card *card = icn_findcard(id);
1721 if (card) {
1722 if (!card->flags & ICN_FLAGS_RUNNING)
1723 return -ENODEV;
1724 return (icn_writecmd(buf, len, user, card));
1726 printk(KERN_ERR
1727 "icn: if_writecmd called with invalid driverId!\n");
1728 return -ENODEV;
1731 static int
1732 if_readstatus(u_char * buf, int len, int user, int id, int channel)
1734 icn_card *card = icn_findcard(id);
1736 if (card) {
1737 if (!card->flags & ICN_FLAGS_RUNNING)
1738 return -ENODEV;
1739 return (icn_readstatus(buf, len, user, card));
1741 printk(KERN_ERR
1742 "icn: if_readstatus called with invalid driverId!\n");
1743 return -ENODEV;
1746 static int
1747 if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
1749 icn_card *card = icn_findcard(id);
1751 if (card) {
1752 if (!card->flags & ICN_FLAGS_RUNNING)
1753 return -ENODEV;
1754 return (icn_sendbuf(channel, ack, skb, card));
1756 printk(KERN_ERR
1757 "icn: if_sendbuf called with invalid driverId!\n");
1758 return -ENODEV;
1762 * Allocate a new card-struct, initialize it
1763 * link it into cards-list and register it at linklevel.
1765 static icn_card *
1766 icn_initcard(int port, char *id)
1768 icn_card *card;
1769 int i;
1771 if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) {
1772 printk(KERN_WARNING
1773 "icn: (%s) Could not allocate card-struct.\n", id);
1774 return (icn_card *) 0;
1776 memset((char *) card, 0, sizeof(icn_card));
1777 card->port = port;
1778 card->interface.hl_hdrlen = 1;
1779 card->interface.channels = ICN_BCH;
1780 card->interface.maxbufsize = 4000;
1781 card->interface.command = if_command;
1782 card->interface.writebuf_skb = if_sendbuf;
1783 card->interface.writecmd = if_writecmd;
1784 card->interface.readstat = if_readstatus;
1785 card->interface.features = ISDN_FEATURE_L2_X75I |
1786 ISDN_FEATURE_L2_HDLC |
1787 ISDN_FEATURE_L3_TRANS |
1788 ISDN_FEATURE_P_UNKNOWN;
1789 card->ptype = ISDN_PTYPE_UNKNOWN;
1790 strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
1791 card->msg_buf_write = card->msg_buf;
1792 card->msg_buf_read = card->msg_buf;
1793 card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
1794 for (i = 0; i < ICN_BCH; i++) {
1795 card->l2_proto[i] = ISDN_PROTO_L2_X75I;
1796 skb_queue_head_init(&card->spqueue[i]);
1798 card->next = cards;
1799 cards = card;
1800 if (!register_isdn(&card->interface)) {
1801 cards = cards->next;
1802 printk(KERN_WARNING
1803 "icn: Unable to register %s\n", id);
1804 kfree(card);
1805 return (icn_card *) 0;
1807 card->myid = card->interface.channels;
1808 sprintf(card->regname, "icn-isdn (%s)", card->interface.id);
1809 return card;
1812 static int
1813 icn_addcard(int port, char *id1, char *id2)
1815 ulong flags;
1816 icn_card *card;
1817 icn_card *card2;
1819 save_flags(flags);
1820 cli();
1821 if (!(card = icn_initcard(port, id1))) {
1822 restore_flags(flags);
1823 return -EIO;
1825 if (!strlen(id2)) {
1826 restore_flags(flags);
1827 printk(KERN_INFO
1828 "icn: (%s) ICN-2B, port 0x%x added\n",
1829 card->interface.id, port);
1830 return 0;
1832 if (!(card2 = icn_initcard(port, id2))) {
1833 restore_flags(flags);
1834 printk(KERN_INFO
1835 "icn: (%s) half ICN-4B, port 0x%x added\n",
1836 card2->interface.id, port);
1837 return 0;
1839 card->doubleS0 = 1;
1840 card->secondhalf = 0;
1841 card->other = card2;
1842 card2->doubleS0 = 1;
1843 card2->secondhalf = 1;
1844 card2->other = card;
1845 restore_flags(flags);
1846 printk(KERN_INFO
1847 "icn: (%s and %s) ICN-4B, port 0x%x added\n",
1848 card->interface.id, card2->interface.id, port);
1849 return 0;
1852 #ifdef MODULE
1853 #define icn_init init_module
1854 #else
1855 #ifdef COMPAT_HAS_NEW_SETUP
1856 #include <linux/init.h>
1857 static int __init
1858 icn_setup(char *line)
1860 char *p, *str;
1861 int ints[3];
1862 static char sid[20];
1863 static char sid2[20];
1865 str = get_options(line, 2, ints);
1866 #else
1867 void
1868 icn_setup(char *str, int *ints)
1870 char *p;
1871 static char sid[20];
1872 static char sid2[20];
1873 #endif
1874 if (ints[0])
1875 portbase = ints[1];
1876 if (ints[0] > 1)
1877 membase = ints[2];
1878 if (strlen(str)) {
1879 strcpy(sid, str);
1880 icn_id = sid;
1881 if ((p = strchr(sid, ','))) {
1882 *p++ = 0;
1883 strcpy(sid2, p);
1884 icn_id2 = sid2;
1887 #ifdef COMPAT_HAS_NEW_SETUP
1888 return(1);
1890 __setup("icn=", icn_setup);
1891 #else
1893 #endif
1894 #endif /* MODULES */
1897 icn_init(void)
1899 char *p;
1900 char rev[10];
1902 memset(&dev, 0, sizeof(icn_dev));
1903 dev.shmem = (icn_shmem *) ((unsigned long) membase & 0x0ffc000);
1904 dev.channel = -1;
1905 dev.mcard = NULL;
1906 dev.firstload = 1;
1908 /* No symbols to export, hide all symbols */
1909 EXPORT_NO_SYMBOLS;
1911 if ((p = strchr(revision, ':'))) {
1912 strcpy(rev, p + 1);
1913 p = strchr(rev, '$');
1914 *p = 0;
1915 } else
1916 strcpy(rev, " ??? ");
1917 printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
1918 (ulong) dev.shmem);
1919 return (icn_addcard(portbase, icn_id, icn_id2));
1922 #ifdef MODULE
1923 void
1924 cleanup_module(void)
1926 isdn_ctrl cmd;
1927 icn_card *card = cards;
1928 icn_card *last;
1929 int i;
1931 icn_stopallcards();
1932 while (card) {
1933 cmd.command = ISDN_STAT_UNLOAD;
1934 cmd.driver = card->myid;
1935 card->interface.statcallb(&cmd);
1936 if (card->rvalid) {
1937 OUTB_P(0, ICN_RUN); /* Reset Controller */
1938 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
1939 if (card->secondhalf || (!card->doubleS0)) {
1940 release_region(card->port, ICN_PORTLEN);
1941 card->rvalid = 0;
1943 for (i = 0; i < ICN_BCH; i++)
1944 icn_free_queue(card, i);
1946 card = card->next;
1948 card = cards;
1949 while (card) {
1950 last = card;
1951 card = card->next;
1952 kfree(last);
1954 if (dev.mvalid)
1955 release_shmem((ulong) dev.shmem, 0x4000);
1956 printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n");
1958 #endif