File: /usr/src/linux/drivers/isdn/icn/icn.c
1 /* $Id: icn.c,v 1.65.6.7 2001/08/17 12:34:27 kai Exp $
2
3 * ISDN low-level module for the ICN active ISDN-Card.
4 *
5 * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
6 *
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.
11 *
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.
16 *
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.
20 *
21 */
22
23 #include "icn.h"
24 #include <linux/init.h>
25
26 /*
27 * Verbose bootcode- and protocol-downloading.
28 */
29 #undef BOOT_DEBUG
30
31 /*
32 * Verbose Shmem-Mapping.
33 */
34 #undef MAP_DEBUG
35
36 static char
37 *revision = "$Revision: 1.65.6.7 $";
38
39 static int icn_addcard(int, char *, char *);
40
41 /*
42 * Free send-queue completely.
43 * Parameter:
44 * card = pointer to card struct
45 * channel = channel number
46 */
47 static void
48 icn_free_queue(icn_card * card, int channel)
49 {
50 struct sk_buff_head *queue = &card->spqueue[channel];
51 struct sk_buff *skb;
52 unsigned long flags;
53
54 skb_queue_purge(queue);
55 save_flags(flags);
56 cli();
57 card->xlen[channel] = 0;
58 card->sndcount[channel] = 0;
59 if ((skb = card->xskb[channel])) {
60 card->xskb[channel] = NULL;
61 restore_flags(flags);
62 dev_kfree_skb(skb);
63 } else
64 restore_flags(flags);
65 }
66
67 /* Put a value into a shift-register, highest bit first.
68 * Parameters:
69 * port = port for output (bit 0 is significant)
70 * val = value to be output
71 * firstbit = Bit-Number of highest bit
72 * bitcount = Number of bits to output
73 */
74 static inline void
75 icn_shiftout(unsigned short port,
76 unsigned long val,
77 int firstbit,
78 int bitcount)
79 {
80
81 register u_char s;
82 register u_char c;
83
84 for (s = firstbit, c = bitcount; c > 0; s--, c--)
85 OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port);
86 }
87
88 /*
89 * disable a cards shared memory
90 */
91 static inline void
92 icn_disable_ram(icn_card * card)
93 {
94 OUTB_P(0, ICN_MAPRAM);
95 }
96
97 /*
98 * enable a cards shared memory
99 */
100 static inline void
101 icn_enable_ram(icn_card * card)
102 {
103 OUTB_P(0xff, ICN_MAPRAM);
104 }
105
106 /*
107 * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12)
108 */
109 static inline void
110 icn_map_channel(icn_card * card, int channel)
111 {
112 #ifdef MAP_DEBUG
113 printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel);
114 #endif
115 if ((channel == dev.channel) && (card == dev.mcard))
116 return;
117 if (dev.mcard)
118 icn_disable_ram(dev.mcard);
119 icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4); /* Select Bank */
120 icn_enable_ram(card);
121 dev.mcard = card;
122 dev.channel = channel;
123 #ifdef MAP_DEBUG
124 printk(KERN_DEBUG "icn_map_channel done\n");
125 #endif
126 }
127
128 /*
129 * Lock a cards channel.
130 * Return 0 if requested card/channel is unmapped (failure).
131 * Return 1 on success.
132 */
133 static inline int
134 icn_lock_channel(icn_card * card, int channel)
135 {
136 register int retval;
137 ulong flags;
138
139 #ifdef MAP_DEBUG
140 printk(KERN_DEBUG "icn_lock_channel %d\n", channel);
141 #endif
142 save_flags(flags);
143 cli();
144 if ((dev.channel == channel) && (card == dev.mcard)) {
145 dev.chanlock++;
146 retval = 1;
147 #ifdef MAP_DEBUG
148 printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel);
149 #endif
150 } else {
151 retval = 0;
152 #ifdef MAP_DEBUG
153 printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel);
154 #endif
155 }
156 restore_flags(flags);
157 return retval;
158 }
159
160 /*
161 * Release current card/channel lock
162 */
163 static inline void
164 icn_release_channel(void)
165 {
166 ulong flags;
167
168 #ifdef MAP_DEBUG
169 printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock);
170 #endif
171 save_flags(flags);
172 cli();
173 if (dev.chanlock > 0)
174 dev.chanlock--;
175 restore_flags(flags);
176 }
177
178 /*
179 * Try to map and lock a cards channel.
180 * Return 1 on success, 0 on failure.
181 */
182 static inline int
183 icn_trymaplock_channel(icn_card * card, int channel)
184 {
185 ulong flags;
186
187 #ifdef MAP_DEBUG
188 printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel,
189 dev.chanlock);
190 #endif
191 save_flags(flags);
192 cli();
193 if ((!dev.chanlock) ||
194 ((dev.channel == channel) && (dev.mcard == card))) {
195 dev.chanlock++;
196 icn_map_channel(card, channel);
197 restore_flags(flags);
198 #ifdef MAP_DEBUG
199 printk(KERN_DEBUG "trymaplock %d OK\n", channel);
200 #endif
201 return 1;
202 }
203 restore_flags(flags);
204 #ifdef MAP_DEBUG
205 printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);
206 #endif
207 return 0;
208 }
209
210 /*
211 * Release current card/channel lock,
212 * then map same or other channel without locking.
213 */
214 static inline void
215 icn_maprelease_channel(icn_card * card, int channel)
216 {
217 ulong flags;
218
219 #ifdef MAP_DEBUG
220 printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);
221 #endif
222 save_flags(flags);
223 cli();
224 if (dev.chanlock > 0)
225 dev.chanlock--;
226 if (!dev.chanlock)
227 icn_map_channel(card, channel);
228 restore_flags(flags);
229 }
230
231 /* Get Data from the B-Channel, assemble fragmented packets and put them
232 * into receive-queue. Wake up any B-Channel-reading processes.
233 * This routine is called via timer-callback from icn_pollbchan().
234 */
235
236 static void
237 icn_pollbchan_receive(int channel, icn_card * card)
238 {
239 int mch = channel + ((card->secondhalf) ? 2 : 0);
240 int eflag;
241 int cnt;
242 struct sk_buff *skb;
243
244 if (icn_trymaplock_channel(card, mch)) {
245 while (rbavl) {
246 cnt = readb(&rbuf_l);
247 if ((card->rcvidx[channel] + cnt) > 4000) {
248 printk(KERN_WARNING
249 "icn: (%s) bogus packet on ch%d, dropping.\n",
250 CID,
251 channel + 1);
252 card->rcvidx[channel] = 0;
253 eflag = 0;
254 } else {
255 memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]],
256 &rbuf_d, cnt);
257 card->rcvidx[channel] += cnt;
258 eflag = readb(&rbuf_f);
259 }
260 rbnext;
261 icn_maprelease_channel(card, mch & 2);
262 if (!eflag) {
263 if ((cnt = card->rcvidx[channel])) {
264 if (!(skb = dev_alloc_skb(cnt))) {
265 printk(KERN_WARNING "icn: receive out of memory\n");
266 break;
267 }
268 memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt);
269 card->rcvidx[channel] = 0;
270 card->interface.rcvcallb_skb(card->myid, channel, skb);
271 }
272 }
273 if (!icn_trymaplock_channel(card, mch))
274 break;
275 }
276 icn_maprelease_channel(card, mch & 2);
277 }
278 }
279
280 /* Send data-packet to B-Channel, split it up into fragments of
281 * ICN_FRAGSIZE length. If last fragment is sent out, signal
282 * success to upper layers via statcallb with ISDN_STAT_BSENT argument.
283 * This routine is called via timer-callback from icn_pollbchan() or
284 * directly from icn_sendbuf().
285 */
286
287 static void
288 icn_pollbchan_send(int channel, icn_card * card)
289 {
290 int mch = channel + ((card->secondhalf) ? 2 : 0);
291 int cnt;
292 unsigned long flags;
293 struct sk_buff *skb;
294 isdn_ctrl cmd;
295
296 if (!(card->sndcount[channel] || card->xskb[channel] ||
297 skb_queue_len(&card->spqueue[channel])))
298 return;
299 if (icn_trymaplock_channel(card, mch)) {
300 while (sbfree &&
301 (card->sndcount[channel] ||
302 skb_queue_len(&card->spqueue[channel]) ||
303 card->xskb[channel])) {
304 save_flags(flags);
305 cli();
306 if (card->xmit_lock[channel]) {
307 restore_flags(flags);
308 break;
309 }
310 card->xmit_lock[channel]++;
311 restore_flags(flags);
312 skb = card->xskb[channel];
313 if (!skb) {
314 skb = skb_dequeue(&card->spqueue[channel]);
315 if (skb) {
316 /* Pop ACK-flag off skb.
317 * Store length to xlen.
318 */
319 if (*(skb_pull(skb,1)))
320 card->xlen[channel] = skb->len;
321 else
322 card->xlen[channel] = 0;
323 }
324 }
325 if (!skb)
326 break;
327 if (skb->len > ICN_FRAGSIZE) {
328 writeb(0xff, &sbuf_f);
329 cnt = ICN_FRAGSIZE;
330 } else {
331 writeb(0x0, &sbuf_f);
332 cnt = skb->len;
333 }
334 writeb(cnt, &sbuf_l);
335 memcpy_toio(&sbuf_d, skb->data, cnt);
336 skb_pull(skb, cnt);
337 card->sndcount[channel] -= cnt;
338 sbnext; /* switch to next buffer */
339 icn_maprelease_channel(card, mch & 2);
340 if (!skb->len) {
341 save_flags(flags);
342 cli();
343 if (card->xskb[channel])
344 card->xskb[channel] = NULL;
345 restore_flags(flags);
346 dev_kfree_skb(skb);
347 if (card->xlen[channel]) {
348 cmd.command = ISDN_STAT_BSENT;
349 cmd.driver = card->myid;
350 cmd.arg = channel;
351 cmd.parm.length = card->xlen[channel];
352 card->interface.statcallb(&cmd);
353 }
354 } else {
355 save_flags(flags);
356 cli();
357 card->xskb[channel] = skb;
358 restore_flags(flags);
359 }
360 card->xmit_lock[channel] = 0;
361 if (!icn_trymaplock_channel(card, mch))
362 break;
363 }
364 icn_maprelease_channel(card, mch & 2);
365 }
366 }
367
368 /* Send/Receive Data to/from the B-Channel.
369 * This routine is called via timer-callback.
370 * It schedules itself while any B-Channel is open.
371 */
372
373 static void
374 icn_pollbchan(unsigned long data)
375 {
376 icn_card *card = (icn_card *) data;
377 unsigned long flags;
378
379 if (card->flags & ICN_FLAGS_B1ACTIVE) {
380 icn_pollbchan_receive(0, card);
381 icn_pollbchan_send(0, card);
382 }
383 if (card->flags & ICN_FLAGS_B2ACTIVE) {
384 icn_pollbchan_receive(1, card);
385 icn_pollbchan_send(1, card);
386 }
387 if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
388 /* schedule b-channel polling again */
389 save_flags(flags);
390 cli();
391 mod_timer(&card->rb_timer, jiffies+ICN_TIMER_BCREAD);
392 card->flags |= ICN_FLAGS_RBTIMER;
393 restore_flags(flags);
394 } else
395 card->flags &= ~ICN_FLAGS_RBTIMER;
396 }
397
398 typedef struct icn_stat {
399 char *statstr;
400 int command;
401 int action;
402 } icn_stat;
403 /* *INDENT-OFF* */
404 static icn_stat icn_stat_table[] =
405 {
406 {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */
407 {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */
408 /*
409 ** add d-channel connect and disconnect support to link-level
410 */
411 {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */
412 {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */
413 {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */
414 {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */
415 {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */
416 {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */
417 {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */
418 {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */
419 {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */
420 {"NO D-CHAN", ISDN_STAT_NODCH, 0}, /* No D-channel available */
421 {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
422 {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */
423 {"E_L1: ACTIVATION FAILED",
424 ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
425 {NULL, 0, -1}
426 };
427 /* *INDENT-ON* */
428
429
430 /*
431 * Check Statusqueue-Pointer from isdn-cards.
432 * If there are new status-replies from the interface, check
433 * them against B-Channel-connects/disconnects and set flags accordingly.
434 * Wake-Up any processes, who are reading the status-device.
435 * If there are B-Channels open, initiate a timer-callback to
436 * icn_pollbchan().
437 * This routine is called periodically via timer.
438 */
439
440 static void
441 icn_parse_status(u_char * status, int channel, icn_card * card)
442 {
443 icn_stat *s = icn_stat_table;
444 int action = -1;
445 unsigned long flags;
446 isdn_ctrl cmd;
447
448 while (s->statstr) {
449 if (!strncmp(status, s->statstr, strlen(s->statstr))) {
450 cmd.command = s->command;
451 action = s->action;
452 break;
453 }
454 s++;
455 }
456 if (action == -1)
457 return;
458 cmd.driver = card->myid;
459 cmd.arg = channel;
460 switch (action) {
461 case 11:
462 save_flags(flags);
463 cli();
464 icn_free_queue(card,channel);
465 card->rcvidx[channel] = 0;
466
467 if (card->flags &
468 ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {
469
470 isdn_ctrl ncmd;
471
472 card->flags &= ~((channel)?
473 ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);
474
475 memset(&ncmd, 0, sizeof(ncmd));
476
477 ncmd.driver = card->myid;
478 ncmd.arg = channel;
479 ncmd.command = ISDN_STAT_BHUP;
480 restore_flags(flags);
481 card->interface.statcallb(&cmd);
482 } else
483 restore_flags(flags);
484
485 break;
486 case 1:
487 icn_free_queue(card,channel);
488 card->flags |= (channel) ?
489 ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
490 break;
491 case 2:
492 card->flags &= ~((channel) ?
493 ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);
494 icn_free_queue(card, channel);
495 save_flags(flags);
496 cli();
497 card->rcvidx[channel] = 0;
498 restore_flags(flags);
499 break;
500 case 3:
501 {
502 char *t = status + 6;
503 char *s = strpbrk(t, ",");
504
505 *s++ = '\0';
506 strncpy(cmd.parm.setup.phone, t,
507 sizeof(cmd.parm.setup.phone));
508 s = strpbrk(t = s, ",");
509 *s++ = '\0';
510 if (!strlen(t))
511 cmd.parm.setup.si1 = 0;
512 else
513 cmd.parm.setup.si1 =
514 simple_strtoul(t, NULL, 10);
515 s = strpbrk(t = s, ",");
516 *s++ = '\0';
517 if (!strlen(t))
518 cmd.parm.setup.si2 = 0;
519 else
520 cmd.parm.setup.si2 =
521 simple_strtoul(t, NULL, 10);
522 strncpy(cmd.parm.setup.eazmsn, s,
523 sizeof(cmd.parm.setup.eazmsn));
524 }
525 cmd.parm.setup.plan = 0;
526 cmd.parm.setup.screen = 0;
527 break;
528 case 4:
529 sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
530 sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
531 cmd.parm.setup.si1 = 7;
532 cmd.parm.setup.si2 = 0;
533 cmd.parm.setup.plan = 0;
534 cmd.parm.setup.screen = 0;
535 break;
536 case 5:
537 strncpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num) - 1);
538 break;
539 case 6:
540 sprintf(cmd.parm.num, "%d",
541 (int) simple_strtoul(status + 7, NULL, 16));
542 break;
543 case 7:
544 status += 3;
545 if (strlen(status) == 4)
546 sprintf(cmd.parm.num, "%s%c%c",
547 status + 2, *status, *(status + 1));
548 else
549 strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1);
550 break;
551 case 8:
552 card->flags &= ~ICN_FLAGS_B1ACTIVE;
553 icn_free_queue(card, 0);
554 save_flags(flags);
555 cli();
556 card->rcvidx[0] = 0;
557 restore_flags(flags);
558 cmd.arg = 0;
559 cmd.driver = card->myid;
560 card->interface.statcallb(&cmd);
561 cmd.command = ISDN_STAT_DHUP;
562 cmd.arg = 0;
563 cmd.driver = card->myid;
564 card->interface.statcallb(&cmd);
565 cmd.command = ISDN_STAT_BHUP;
566 card->flags &= ~ICN_FLAGS_B2ACTIVE;
567 icn_free_queue(card, 1);
568 save_flags(flags);
569 cli();
570 card->rcvidx[1] = 0;
571 restore_flags(flags);
572 cmd.arg = 1;
573 cmd.driver = card->myid;
574 card->interface.statcallb(&cmd);
575 cmd.command = ISDN_STAT_DHUP;
576 cmd.arg = 1;
577 cmd.driver = card->myid;
578 break;
579 }
580 card->interface.statcallb(&cmd);
581 return;
582 }
583
584 static void
585 icn_putmsg(icn_card * card, unsigned char c)
586 {
587 ulong flags;
588
589 save_flags(flags);
590 cli();
591 *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
592 if (card->msg_buf_write == card->msg_buf_read) {
593 if (++card->msg_buf_read > card->msg_buf_end)
594 card->msg_buf_read = card->msg_buf;
595 }
596 if (card->msg_buf_write > card->msg_buf_end)
597 card->msg_buf_write = card->msg_buf;
598 restore_flags(flags);
599 }
600
601 static void
602 icn_polldchan(unsigned long data)
603 {
604 icn_card *card = (icn_card *) data;
605 int mch = card->secondhalf ? 2 : 0;
606 int avail = 0;
607 int left;
608 u_char c;
609 int ch;
610 long flags;
611 int i;
612 u_char *p;
613 isdn_ctrl cmd;
614
615 if (icn_trymaplock_channel(card, mch)) {
616 avail = msg_avail;
617 for (left = avail, i = readb(&msg_o); left > 0; i++, left--) {
618 c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]);
619 icn_putmsg(card, c);
620 if (c == 0xff) {
621 card->imsg[card->iptr] = 0;
622 card->iptr = 0;
623 if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
624 card->imsg[1] <= '2' && card->imsg[2] == ';') {
625 ch = (card->imsg[1] - '0') - 1;
626 p = &card->imsg[3];
627 icn_parse_status(p, ch, card);
628 } else {
629 p = card->imsg;
630 if (!strncmp(p, "DRV1.", 5)) {
631 u_char vstr[10];
632 u_char *q = vstr;
633
634 printk(KERN_INFO "icn: (%s) %s\n", CID, p);
635 if (!strncmp(p + 7, "TC", 2)) {
636 card->ptype = ISDN_PTYPE_1TR6;
637 card->interface.features |= ISDN_FEATURE_P_1TR6;
638 printk(KERN_INFO
639 "icn: (%s) 1TR6-Protocol loaded and running\n", CID);
640 }
641 if (!strncmp(p + 7, "EC", 2)) {
642 card->ptype = ISDN_PTYPE_EURO;
643 card->interface.features |= ISDN_FEATURE_P_EURO;
644 printk(KERN_INFO
645 "icn: (%s) Euro-Protocol loaded and running\n", CID);
646 }
647 p = strstr(card->imsg, "BRV") + 3;
648 while (*p) {
649 if (*p >= '0' && *p <= '9')
650 *q++ = *p;
651 p++;
652 }
653 *q = '\0';
654 strcat(vstr, "000");
655 vstr[3] = '\0';
656 card->fw_rev = (int) simple_strtoul(vstr, NULL, 10);
657 continue;
658
659 }
660 }
661 } else {
662 card->imsg[card->iptr] = c;
663 if (card->iptr < 59)
664 card->iptr++;
665 }
666 }
667 writeb((readb(&msg_o) + avail) & 0xff, &msg_o);
668 icn_release_channel();
669 }
670 if (avail) {
671 cmd.command = ISDN_STAT_STAVAIL;
672 cmd.driver = card->myid;
673 cmd.arg = avail;
674 card->interface.statcallb(&cmd);
675 }
676 if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
677 if (!(card->flags & ICN_FLAGS_RBTIMER)) {
678 /* schedule b-channel polling */
679 card->flags |= ICN_FLAGS_RBTIMER;
680 save_flags(flags);
681 cli();
682 del_timer(&card->rb_timer);
683 card->rb_timer.function = icn_pollbchan;
684 card->rb_timer.data = (unsigned long) card;
685 card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
686 add_timer(&card->rb_timer);
687 restore_flags(flags);
688 }
689 /* schedule again */
690 save_flags(flags);
691 cli();
692 mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD);
693 restore_flags(flags);
694 }
695
696 /* Append a packet to the transmit buffer-queue.
697 * Parameters:
698 * channel = Number of B-channel
699 * skb = pointer to sk_buff
700 * card = pointer to card-struct
701 * Return:
702 * Number of bytes transferred, -E??? on error
703 */
704
705 static int
706 icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card)
707 {
708 int len = skb->len;
709 unsigned long flags;
710 struct sk_buff *nskb;
711
712 if (len > 4000) {
713 printk(KERN_WARNING
714 "icn: Send packet too large\n");
715 return -EINVAL;
716 }
717 if (len) {
718 if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE))
719 return 0;
720 if (card->sndcount[channel] > ICN_MAX_SQUEUE)
721 return 0;
722 save_flags(flags);
723 cli();
724 nskb = skb_clone(skb, GFP_ATOMIC);
725 if (nskb) {
726 /* Push ACK flag as one
727 * byte in front of data.
728 */
729 *(skb_push(nskb, 1)) = ack?1:0;
730 skb_queue_tail(&card->spqueue[channel], nskb);
731 dev_kfree_skb(skb);
732 } else
733 len = 0;
734 card->sndcount[channel] += len;
735 restore_flags(flags);
736 }
737 return len;
738 }
739
740 /*
741 * Check card's status after starting the bootstrap loader.
742 * On entry, the card's shared memory has already to be mapped.
743 * Return:
744 * 0 on success (Boot loader ready)
745 * -EIO on failure (timeout)
746 */
747 static int
748 icn_check_loader(int cardnumber)
749 {
750 int timer = 0;
751
752 while (1) {
753 #ifdef BOOT_DEBUG
754 printk(KERN_DEBUG "Loader %d ?\n", cardnumber);
755 #endif
756 if (readb(&dev.shmem->data_control.scns) ||
757 readb(&dev.shmem->data_control.scnr)) {
758 if (timer++ > 5) {
759 printk(KERN_WARNING
760 "icn: Boot-Loader %d timed out.\n",
761 cardnumber);
762 icn_release_channel();
763 return -EIO;
764 }
765 #ifdef BOOT_DEBUG
766 printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);
767 #endif
768 current->state = TASK_INTERRUPTIBLE;
769 schedule_timeout(ICN_BOOT_TIMEOUT1);
770 } else {
771 #ifdef BOOT_DEBUG
772 printk(KERN_DEBUG "Loader %d OK\n", cardnumber);
773 #endif
774 icn_release_channel();
775 return 0;
776 }
777 }
778 }
779
780 /* Load the boot-code into the interface-card's memory and start it.
781 * Always called from user-process.
782 *
783 * Parameters:
784 * buffer = pointer to packet
785 * Return:
786 * 0 if successfully loaded
787 */
788
789 #ifdef BOOT_DEBUG
790 #define SLEEP(sec) { \
791 int slsec = sec; \
792 printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \
793 while (slsec) { \
794 current->state = TASK_INTERRUPTIBLE; \
795 schedule_timeout(HZ); \
796 slsec--; \
797 } \
798 }
799 #else
800 #define SLEEP(sec)
801 #endif
802
803 static int
804 icn_loadboot(u_char * buffer, icn_card * card)
805 {
806 int ret;
807 u_char *codebuf;
808 unsigned long flags;
809
810 #ifdef BOOT_DEBUG
811 printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
812 #endif
813 if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) {
814 printk(KERN_WARNING "icn: Could not allocate code buffer\n");
815 return -ENOMEM;
816 }
817 if ((ret = copy_from_user(codebuf, buffer, ICN_CODE_STAGE1))) {
818 kfree(codebuf);
819 return ret;
820 }
821 if (!card->rvalid) {
822 if (check_region(card->port, ICN_PORTLEN)) {
823 printk(KERN_WARNING
824 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
825 CID,
826 card->port,
827 card->port + ICN_PORTLEN);
828 kfree(codebuf);
829 return -EBUSY;
830 }
831 request_region(card->port, ICN_PORTLEN, card->regname);
832 card->rvalid = 1;
833 if (card->doubleS0)
834 card->other->rvalid = 1;
835 }
836 if (!dev.mvalid) {
837 if (check_mem_region(dev.memaddr, 0x4000)) {
838 printk(KERN_WARNING
839 "icn: memory at 0x%08lx in use.\n", dev.memaddr);
840 return -EBUSY;
841 }
842 request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)");
843 dev.shmem = ioremap(dev.memaddr, 0x4000);
844 dev.mvalid = 1;
845 }
846 OUTB_P(0, ICN_RUN); /* Reset Controller */
847 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
848 icn_shiftout(ICN_CFG, 0x0f, 3, 4); /* Windowsize= 16k */
849 icn_shiftout(ICN_CFG, dev.memaddr, 23, 10); /* Set RAM-Addr. */
850 #ifdef BOOT_DEBUG
851 printk(KERN_DEBUG "shmem=%08lx\n", dev.memaddr);
852 #endif
853 SLEEP(1);
854 #ifdef BOOT_DEBUG
855 printk(KERN_DEBUG "Map Bank 0\n");
856 #endif
857 save_flags(flags);
858 cli();
859 icn_map_channel(card, 0); /* Select Bank 0 */
860 icn_lock_channel(card, 0); /* Lock Bank 0 */
861 restore_flags(flags);
862 SLEEP(1);
863 memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
864 #ifdef BOOT_DEBUG
865 printk(KERN_DEBUG "Bootloader transferred\n");
866 #endif
867 if (card->doubleS0) {
868 SLEEP(1);
869 #ifdef BOOT_DEBUG
870 printk(KERN_DEBUG "Map Bank 8\n");
871 #endif
872 save_flags(flags);
873 cli();
874 icn_release_channel();
875 icn_map_channel(card, 2); /* Select Bank 8 */
876 icn_lock_channel(card, 2); /* Lock Bank 8 */
877 restore_flags(flags);
878 SLEEP(1);
879 memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
880 #ifdef BOOT_DEBUG
881 printk(KERN_DEBUG "Bootloader transferred\n");
882 #endif
883 }
884 kfree(codebuf);
885 SLEEP(1);
886 OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */
887 if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1)))
888 return ret;
889 if (!card->doubleS0)
890 return 0;
891 /* reached only, if we have a Double-S0-Card */
892 #ifdef BOOT_DEBUG
893 printk(KERN_DEBUG "Map Bank 0\n");
894 #endif
895 save_flags(flags);
896 cli();
897 icn_map_channel(card, 0); /* Select Bank 0 */
898 icn_lock_channel(card, 0); /* Lock Bank 0 */
899 restore_flags(flags);
900 SLEEP(1);
901 return (icn_check_loader(1));
902 }
903
904 static int
905 icn_loadproto(u_char * buffer, icn_card * card)
906 {
907 register u_char *p = buffer;
908 u_char codebuf[256];
909 uint left = ICN_CODE_STAGE2;
910 uint cnt;
911 int timer;
912 int ret;
913 unsigned long flags;
914
915 #ifdef BOOT_DEBUG
916 printk(KERN_DEBUG "icn_loadproto called\n");
917 #endif
918 if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2)))
919 return ret;
920 timer = 0;
921 save_flags(flags);
922 cli();
923 if (card->secondhalf) {
924 icn_map_channel(card, 2);
925 icn_lock_channel(card, 2);
926 } else {
927 icn_map_channel(card, 0);
928 icn_lock_channel(card, 0);
929 }
930 restore_flags(flags);
931 while (left) {
932 if (sbfree) { /* If there is a free buffer... */
933 cnt = left;
934 if (cnt > 256)
935 cnt = 256;
936 if (copy_from_user(codebuf, p, cnt)) {
937 icn_maprelease_channel(card, 0);
938 return -EFAULT;
939 }
940 memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */
941 sbnext; /* switch to next buffer */
942 p += cnt;
943 left -= cnt;
944 timer = 0;
945 } else {
946 #ifdef BOOT_DEBUG
947 printk(KERN_DEBUG "boot 2 !sbfree\n");
948 #endif
949 if (timer++ > 5) {
950 icn_maprelease_channel(card, 0);
951 return -EIO;
952 }
953 current->state = TASK_INTERRUPTIBLE;
954 schedule_timeout(10);
955 }
956 }
957 writeb(0x20, &sbuf_n);
958 timer = 0;
959 while (1) {
960 if (readb(&cmd_o) || readb(&cmd_i)) {
961 #ifdef BOOT_DEBUG
962 printk(KERN_DEBUG "Proto?\n");
963 #endif
964 if (timer++ > 5) {
965 printk(KERN_WARNING
966 "icn: (%s) Protocol timed out.\n",
967 CID);
968 #ifdef BOOT_DEBUG
969 printk(KERN_DEBUG "Proto TO!\n");
970 #endif
971 icn_maprelease_channel(card, 0);
972 return -EIO;
973 }
974 #ifdef BOOT_DEBUG
975 printk(KERN_DEBUG "Proto TO?\n");
976 #endif
977 current->state = TASK_INTERRUPTIBLE;
978 schedule_timeout(ICN_BOOT_TIMEOUT1);
979 } else {
980 if ((card->secondhalf) || (!card->doubleS0)) {
981 #ifdef BOOT_DEBUG
982 printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
983 card->secondhalf);
984 #endif
985 save_flags(flags);
986 cli();
987 init_timer(&card->st_timer);
988 card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
989 card->st_timer.function = icn_polldchan;
990 card->st_timer.data = (unsigned long) card;
991 add_timer(&card->st_timer);
992 card->flags |= ICN_FLAGS_RUNNING;
993 if (card->doubleS0) {
994 init_timer(&card->other->st_timer);
995 card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
996 card->other->st_timer.function = icn_polldchan;
997 card->other->st_timer.data = (unsigned long) card->other;
998 add_timer(&card->other->st_timer);
999 card->other->flags |= ICN_FLAGS_RUNNING;
1000 }
1001 restore_flags(flags);
1002 }
1003 icn_maprelease_channel(card, 0);
1004 return 0;
1005 }
1006 }
1007 }
1008
1009 /* Read the Status-replies from the Interface */
1010 static int
1011 icn_readstatus(u_char * buf, int len, int user, icn_card * card)
1012 {
1013 int count;
1014 u_char *p;
1015
1016 for (p = buf, count = 0; count < len; p++, count++) {
1017 if (card->msg_buf_read == card->msg_buf_write)
1018 return count;
1019 if (user)
1020 put_user(*card->msg_buf_read++, p);
1021 else
1022 *p = *card->msg_buf_read++;
1023 if (card->msg_buf_read > card->msg_buf_end)
1024 card->msg_buf_read = card->msg_buf;
1025 }
1026 return count;
1027 }
1028
1029 /* Put command-strings into the command-queue of the Interface */
1030 static int
1031 icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
1032 {
1033 int mch = card->secondhalf ? 2 : 0;
1034 int pp;
1035 int i;
1036 int count;
1037 int xcount;
1038 int ocount;
1039 int loop;
1040 unsigned long flags;
1041 int lastmap_channel;
1042 struct icn_card *lastmap_card;
1043 u_char *p;
1044 isdn_ctrl cmd;
1045 u_char msg[0x100];
1046
1047 ocount = 1;
1048 xcount = loop = 0;
1049 while (len) {
1050 count = cmd_free;
1051 if (count > len)
1052 count = len;
1053 if (user)
1054 copy_from_user(msg, buf, count);
1055 else
1056 memcpy(msg, buf, count);
1057
1058 save_flags(flags);
1059 cli();
1060 lastmap_card = dev.mcard;
1061 lastmap_channel = dev.channel;
1062 icn_map_channel(card, mch);
1063
1064 icn_putmsg(card, '>');
1065 for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
1066 ++) {
1067 writeb((*p == '\n') ? 0xff : *p,
1068 &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);
1069 len--;
1070 xcount++;
1071 icn_putmsg(card, *p);
1072 if ((*p == '\n') && (i > 1)) {
1073 icn_putmsg(card, '>');
1074 ocount++;
1075 }
1076 ocount++;
1077 }
1078 writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
1079 if (lastmap_card)
1080 icn_map_channel(lastmap_card, lastmap_channel);
1081 restore_flags(flags);
1082 if (len) {
1083 mdelay(1);
1084 if (loop++ > 20)
1085 break;
1086 } else
1087 break;
1088 }
1089 if (len && (!user))
1090 printk(KERN_WARNING "icn: writemsg incomplete!\n");
1091 cmd.command = ISDN_STAT_STAVAIL;
1092 cmd.driver = card->myid;
1093 cmd.arg = ocount;
1094 card->interface.statcallb(&cmd);
1095 return xcount;
1096 }
1097
1098 /*
1099 * Delete card's pending timers, send STOP to linklevel
1100 */
1101 static void
1102 icn_stopcard(icn_card * card)
1103 {
1104 unsigned long flags;
1105 isdn_ctrl cmd;
1106
1107 save_flags(flags);
1108 cli();
1109 if (card->flags & ICN_FLAGS_RUNNING) {
1110 card->flags &= ~ICN_FLAGS_RUNNING;
1111 del_timer(&card->st_timer);
1112 del_timer(&card->rb_timer);
1113 cmd.command = ISDN_STAT_STOP;
1114 cmd.driver = card->myid;
1115 card->interface.statcallb(&cmd);
1116 if (card->doubleS0)
1117 icn_stopcard(card->other);
1118 }
1119 restore_flags(flags);
1120 }
1121
1122 static void
1123 icn_stopallcards(void)
1124 {
1125 icn_card *p = cards;
1126
1127 while (p) {
1128 icn_stopcard(p);
1129 p = p->next;
1130 }
1131 }
1132
1133 /*
1134 * Unmap all cards, because some of them may be mapped accidetly during
1135 * autoprobing of some network drivers (SMC-driver?)
1136 */
1137 static void
1138 icn_disable_cards(void)
1139 {
1140 icn_card *card = cards;
1141
1142 while (card) {
1143 if (check_region(card->port, ICN_PORTLEN)) {
1144 printk(KERN_WARNING
1145 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1146 CID,
1147 card->port,
1148 card->port + ICN_PORTLEN);
1149 } else {
1150 OUTB_P(0, ICN_RUN); /* Reset Controller */
1151 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
1152 }
1153 card = card->next;
1154 }
1155 }
1156
1157 static int
1158 icn_command(isdn_ctrl * c, icn_card * card)
1159 {
1160 ulong a;
1161 ulong flags;
1162 int i;
1163 char cbuf[60];
1164 isdn_ctrl cmd;
1165 icn_cdef cdef;
1166
1167 switch (c->command) {
1168 case ISDN_CMD_IOCTL:
1169 memcpy(&a, c->parm.num, sizeof(ulong));
1170 switch (c->arg) {
1171 case ICN_IOCTL_SETMMIO:
1172 if (dev.memaddr != (a & 0x0ffc000)) {
1173 if (check_mem_region(a & 0x0ffc000, 0x4000)) {
1174 printk(KERN_WARNING
1175 "icn: memory at 0x%08lx in use.\n",
1176 a & 0x0ffc000);
1177 return -EINVAL;
1178 }
1179 icn_stopallcards();
1180 save_flags(flags);
1181 cli();
1182 if (dev.mvalid) {
1183 iounmap(dev.shmem);
1184 release_mem_region(dev.memaddr, 0x4000);
1185 }
1186 dev.mvalid = 0;
1187 dev.memaddr = a & 0x0ffc000;
1188 restore_flags(flags);
1189 printk(KERN_INFO
1190 "icn: (%s) mmio set to 0x%08lx\n",
1191 CID,
1192 dev.memaddr);
1193 }
1194 break;
1195 case ICN_IOCTL_GETMMIO:
1196 return (long) dev.memaddr;
1197 case ICN_IOCTL_SETPORT:
1198 if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
1199 || a == 0x340 || a == 0x350 || a == 0x360 ||
1200 a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338
1201 || a == 0x348 || a == 0x358 || a == 0x368) {
1202 if (card->port != (unsigned short) a) {
1203 if (check_region((unsigned short) a, ICN_PORTLEN)) {
1204 printk(KERN_WARNING
1205 "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1206 CID, (int) a, (int) a + ICN_PORTLEN);
1207 return -EINVAL;
1208 }
1209 icn_stopcard(card);
1210 save_flags(flags);
1211 cli();
1212 if (card->rvalid)
1213 release_region(card->port, ICN_PORTLEN);
1214 card->port = (unsigned short) a;
1215 card->rvalid = 0;
1216 if (card->doubleS0) {
1217 card->other->port = (unsigned short) a;
1218 card->other->rvalid = 0;
1219 }
1220 restore_flags(flags);
1221 printk(KERN_INFO
1222 "icn: (%s) port set to 0x%03x\n",
1223 CID, card->port);
1224 }
1225 } else
1226 return -EINVAL;
1227 break;
1228 case ICN_IOCTL_GETPORT:
1229 return (int) card->port;
1230 case ICN_IOCTL_GETDOUBLE:
1231 return (int) card->doubleS0;
1232 case ICN_IOCTL_DEBUGVAR:
1233 if ((i = copy_to_user((char *) a,
1234 (char *) &card, sizeof(ulong))))
1235 return i;
1236 a += sizeof(ulong);
1237 {
1238 ulong l = (ulong) & dev;
1239 if ((i = copy_to_user((char *) a,
1240 (char *) &l, sizeof(ulong))))
1241 return i;
1242 }
1243 return 0;
1244 case ICN_IOCTL_LOADBOOT:
1245 if (dev.firstload) {
1246 icn_disable_cards();
1247 dev.firstload = 0;
1248 }
1249 icn_stopcard(card);
1250 return (icn_loadboot((u_char *) a, card));
1251 case ICN_IOCTL_LOADPROTO:
1252 icn_stopcard(card);
1253 if ((i = (icn_loadproto((u_char *) a, card))))
1254 return i;
1255 if (card->doubleS0)
1256 i = icn_loadproto((u_char *) (a + ICN_CODE_STAGE2), card->other);
1257 return i;
1258 break;
1259 case ICN_IOCTL_ADDCARD:
1260 if (!dev.firstload)
1261 return -EBUSY;
1262 if ((i = copy_from_user((char *) &cdef, (char *) a, sizeof(cdef))))
1263 return i;
1264 return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
1265 break;
1266 case ICN_IOCTL_LEASEDCFG:
1267 if (a) {
1268 if (!card->leased) {
1269 card->leased = 1;
1270 while (card->ptype == ISDN_PTYPE_UNKNOWN) {
1271 schedule_timeout(ICN_BOOT_TIMEOUT1);
1272 }
1273 schedule_timeout(ICN_BOOT_TIMEOUT1);
1274 sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",
1275 (a & 1)?'1':'C', (a & 2)?'2':'C');
1276 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1277 printk(KERN_INFO
1278 "icn: (%s) Leased-line mode enabled\n",
1279 CID);
1280 cmd.command = ISDN_STAT_RUN;
1281 cmd.driver = card->myid;
1282 cmd.arg = 0;
1283 card->interface.statcallb(&cmd);
1284 }
1285 } else {
1286 if (card->leased) {
1287 card->leased = 0;
1288 sprintf(cbuf, "00;FV2OFF\n");
1289 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1290 printk(KERN_INFO
1291 "icn: (%s) Leased-line mode disabled\n",
1292 CID);
1293 cmd.command = ISDN_STAT_RUN;
1294 cmd.driver = card->myid;
1295 cmd.arg = 0;
1296 card->interface.statcallb(&cmd);
1297 }
1298 }
1299 return 0;
1300 default:
1301 return -EINVAL;
1302 }
1303 break;
1304 case ISDN_CMD_DIAL:
1305 if (!card->flags & ICN_FLAGS_RUNNING)
1306 return -ENODEV;
1307 if (card->leased)
1308 break;
1309 if ((c->arg & 255) < ICN_BCH) {
1310 char *p;
1311 char dial[50];
1312 char dcode[4];
1313
1314 a = c->arg;
1315 p = c->parm.setup.phone;
1316 if (*p == 's' || *p == 'S') {
1317 /* Dial for SPV */
1318 p++;
1319 strcpy(dcode, "SCA");
1320 } else
1321 /* Normal Dial */
1322 strcpy(dcode, "CAL");
1323 strcpy(dial, p);
1324 sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
1325 dcode, dial, c->parm.setup.si1,
1326 c->parm.setup.si2, c->parm.setup.eazmsn);
1327 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1328 }
1329 break;
1330 case ISDN_CMD_ACCEPTD:
1331 if (!card->flags & ICN_FLAGS_RUNNING)
1332 return -ENODEV;
1333 if (c->arg < ICN_BCH) {
1334 a = c->arg + 1;
1335 if (card->fw_rev >= 300) {
1336 switch (card->l2_proto[a - 1]) {
1337 case ISDN_PROTO_L2_X75I:
1338 sprintf(cbuf, "%02d;BX75\n", (int) a);
1339 break;
1340 case ISDN_PROTO_L2_HDLC:
1341 sprintf(cbuf, "%02d;BTRA\n", (int) a);
1342 break;
1343 }
1344 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1345 }
1346 sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1347 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1348 }
1349 break;
1350 case ISDN_CMD_ACCEPTB:
1351 if (!card->flags & ICN_FLAGS_RUNNING)
1352 return -ENODEV;
1353 if (c->arg < ICN_BCH) {
1354 a = c->arg + 1;
1355 if (card->fw_rev >= 300)
1356 switch (card->l2_proto[a - 1]) {
1357 case ISDN_PROTO_L2_X75I:
1358 sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
1359 break;
1360 case ISDN_PROTO_L2_HDLC:
1361 sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
1362 break;
1363 } else
1364 sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1365 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1366 }
1367 break;
1368 case ISDN_CMD_HANGUP:
1369 if (!card->flags & ICN_FLAGS_RUNNING)
1370 return -ENODEV;
1371 if (c->arg < ICN_BCH) {
1372 a = c->arg + 1;
1373 sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1374 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1375 }
1376 break;
1377 case ISDN_CMD_SETEAZ:
1378 if (!card->flags & ICN_FLAGS_RUNNING)
1379 return -ENODEV;
1380 if (card->leased)
1381 break;
1382 if (c->arg < ICN_BCH) {
1383 a = c->arg + 1;
1384 if (card->ptype == ISDN_PTYPE_EURO) {
1385 sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
1386 c->parm.num[0] ? "N" : "ALL", c->parm.num);
1387 } else
1388 sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
1389 c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
1390 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1391 }
1392 break;
1393 case ISDN_CMD_CLREAZ:
1394 if (!card->flags & ICN_FLAGS_RUNNING)
1395 return -ENODEV;
1396 if (card->leased)
1397 break;
1398 if (c->arg < ICN_BCH) {
1399 a = c->arg + 1;
1400 if (card->ptype == ISDN_PTYPE_EURO)
1401 sprintf(cbuf, "%02d;MSNC\n", (int) a);
1402 else
1403 sprintf(cbuf, "%02d;EAZC\n", (int) a);
1404 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1405 }
1406 break;
1407 case ISDN_CMD_SETL2:
1408 if (!card->flags & ICN_FLAGS_RUNNING)
1409 return -ENODEV;
1410 if ((c->arg & 255) < ICN_BCH) {
1411 a = c->arg;
1412 switch (a >> 8) {
1413 case ISDN_PROTO_L2_X75I:
1414 sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1415 break;
1416 case ISDN_PROTO_L2_HDLC:
1417 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1418 break;
1419 default:
1420 return -EINVAL;
1421 }
1422 i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1423 card->l2_proto[a & 255] = (a >> 8);
1424 }
1425 break;
1426 case ISDN_CMD_GETL2:
1427 if (!card->flags & ICN_FLAGS_RUNNING)
1428 return -ENODEV;
1429 if ((c->arg & 255) < ICN_BCH)
1430 return card->l2_proto[c->arg & 255];
1431 else
1432 return -ENODEV;
1433 case ISDN_CMD_SETL3:
1434 if (!card->flags & ICN_FLAGS_RUNNING)
1435 return -ENODEV;
1436 return 0;
1437 case ISDN_CMD_GETL3:
1438 if (!card->flags & ICN_FLAGS_RUNNING)
1439 return -ENODEV;
1440 if ((c->arg & 255) < ICN_BCH)
1441 return ISDN_PROTO_L3_TRANS;
1442 else
1443 return -ENODEV;
1444 case ISDN_CMD_GETEAZ:
1445 if (!card->flags & ICN_FLAGS_RUNNING)
1446 return -ENODEV;
1447 break;
1448 case ISDN_CMD_SETSIL:
1449 if (!card->flags & ICN_FLAGS_RUNNING)
1450 return -ENODEV;
1451 break;
1452 case ISDN_CMD_GETSIL:
1453 if (!card->flags & ICN_FLAGS_RUNNING)
1454 return -ENODEV;
1455 break;
1456 case ISDN_CMD_LOCK:
1457 MOD_INC_USE_COUNT;
1458 break;
1459 case ISDN_CMD_UNLOCK:
1460 MOD_DEC_USE_COUNT;
1461 break;
1462 default:
1463 return -EINVAL;
1464 }
1465 return 0;
1466 }
1467
1468 /*
1469 * Find card with given driverId
1470 */
1471 static inline icn_card *
1472 icn_findcard(int driverid)
1473 {
1474 icn_card *p = cards;
1475
1476 while (p) {
1477 if (p->myid == driverid)
1478 return p;
1479 p = p->next;
1480 }
1481 return (icn_card *) 0;
1482 }
1483
1484 /*
1485 * Wrapper functions for interface to linklevel
1486 */
1487 static int
1488 if_command(isdn_ctrl * c)
1489 {
1490 icn_card *card = icn_findcard(c->driver);
1491
1492 if (card)
1493 return (icn_command(c, card));
1494 printk(KERN_ERR
1495 "icn: if_command %d called with invalid driverId %d!\n",
1496 c->command, c->driver);
1497 return -ENODEV;
1498 }
1499
1500 static int
1501 if_writecmd(const u_char * buf, int len, int user, int id, int channel)
1502 {
1503 icn_card *card = icn_findcard(id);
1504
1505 if (card) {
1506 if (!card->flags & ICN_FLAGS_RUNNING)
1507 return -ENODEV;
1508 return (icn_writecmd(buf, len, user, card));
1509 }
1510 printk(KERN_ERR
1511 "icn: if_writecmd called with invalid driverId!\n");
1512 return -ENODEV;
1513 }
1514
1515 static int
1516 if_readstatus(u_char * buf, int len, int user, int id, int channel)
1517 {
1518 icn_card *card = icn_findcard(id);
1519
1520 if (card) {
1521 if (!card->flags & ICN_FLAGS_RUNNING)
1522 return -ENODEV;
1523 return (icn_readstatus(buf, len, user, card));
1524 }
1525 printk(KERN_ERR
1526 "icn: if_readstatus called with invalid driverId!\n");
1527 return -ENODEV;
1528 }
1529
1530 static int
1531 if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
1532 {
1533 icn_card *card = icn_findcard(id);
1534
1535 if (card) {
1536 if (!card->flags & ICN_FLAGS_RUNNING)
1537 return -ENODEV;
1538 return (icn_sendbuf(channel, ack, skb, card));
1539 }
1540 printk(KERN_ERR
1541 "icn: if_sendbuf called with invalid driverId!\n");
1542 return -ENODEV;
1543 }
1544
1545 /*
1546 * Allocate a new card-struct, initialize it
1547 * link it into cards-list and register it at linklevel.
1548 */
1549 static icn_card *
1550 icn_initcard(int port, char *id)
1551 {
1552 icn_card *card;
1553 int i;
1554
1555 if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) {
1556 printk(KERN_WARNING
1557 "icn: (%s) Could not allocate card-struct.\n", id);
1558 return (icn_card *) 0;
1559 }
1560 memset((char *) card, 0, sizeof(icn_card));
1561 card->port = port;
1562 card->interface.hl_hdrlen = 1;
1563 card->interface.channels = ICN_BCH;
1564 card->interface.maxbufsize = 4000;
1565 card->interface.command = if_command;
1566 card->interface.writebuf_skb = if_sendbuf;
1567 card->interface.writecmd = if_writecmd;
1568 card->interface.readstat = if_readstatus;
1569 card->interface.features = ISDN_FEATURE_L2_X75I |
1570 ISDN_FEATURE_L2_HDLC |
1571 ISDN_FEATURE_L3_TRANS |
1572 ISDN_FEATURE_P_UNKNOWN;
1573 card->ptype = ISDN_PTYPE_UNKNOWN;
1574 strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
1575 card->msg_buf_write = card->msg_buf;
1576 card->msg_buf_read = card->msg_buf;
1577 card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
1578 for (i = 0; i < ICN_BCH; i++) {
1579 card->l2_proto[i] = ISDN_PROTO_L2_X75I;
1580 skb_queue_head_init(&card->spqueue[i]);
1581 }
1582 card->next = cards;
1583 cards = card;
1584 if (!register_isdn(&card->interface)) {
1585 cards = cards->next;
1586 printk(KERN_WARNING
1587 "icn: Unable to register %s\n", id);
1588 kfree(card);
1589 return (icn_card *) 0;
1590 }
1591 card->myid = card->interface.channels;
1592 sprintf(card->regname, "icn-isdn (%s)", card->interface.id);
1593 return card;
1594 }
1595
1596 static int
1597 icn_addcard(int port, char *id1, char *id2)
1598 {
1599 icn_card *card;
1600 icn_card *card2;
1601
1602 if (!(card = icn_initcard(port, id1))) {
1603 return -EIO;
1604 }
1605 if (!strlen(id2)) {
1606 printk(KERN_INFO
1607 "icn: (%s) ICN-2B, port 0x%x added\n",
1608 card->interface.id, port);
1609 return 0;
1610 }
1611 if (!(card2 = icn_initcard(port, id2))) {
1612 printk(KERN_INFO
1613 "icn: (%s) half ICN-4B, port 0x%x added\n",
1614 card2->interface.id, port);
1615 return 0;
1616 }
1617 card->doubleS0 = 1;
1618 card->secondhalf = 0;
1619 card->other = card2;
1620 card2->doubleS0 = 1;
1621 card2->secondhalf = 1;
1622 card2->other = card;
1623 printk(KERN_INFO
1624 "icn: (%s and %s) ICN-4B, port 0x%x added\n",
1625 card->interface.id, card2->interface.id, port);
1626 return 0;
1627 }
1628
1629 #ifndef MODULE
1630 static int __init
1631 icn_setup(char *line)
1632 {
1633 char *p, *str;
1634 int ints[3];
1635 static char sid[20];
1636 static char sid2[20];
1637
1638 str = get_options(line, 2, ints);
1639 if (ints[0])
1640 portbase = ints[1];
1641 if (ints[0] > 1)
1642 membase = (unsigned long)ints[2];
1643 if (str && *str) {
1644 strcpy(sid, str);
1645 icn_id = sid;
1646 if ((p = strchr(sid, ','))) {
1647 *p++ = 0;
1648 strcpy(sid2, p);
1649 icn_id2 = sid2;
1650 }
1651 }
1652 return(1);
1653 }
1654 __setup("icn=", icn_setup);
1655 #endif /* MODULE */
1656
1657 static int __init icn_init(void)
1658 {
1659 char *p;
1660 char rev[10];
1661
1662 memset(&dev, 0, sizeof(icn_dev));
1663 dev.memaddr = (membase & 0x0ffc000);
1664 dev.channel = -1;
1665 dev.mcard = NULL;
1666 dev.firstload = 1;
1667
1668 if ((p = strchr(revision, ':'))) {
1669 strcpy(rev, p + 1);
1670 p = strchr(rev, '$');
1671 *p = 0;
1672 } else
1673 strcpy(rev, " ??? ");
1674 printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
1675 dev.memaddr);
1676 return (icn_addcard(portbase, icn_id, icn_id2));
1677 }
1678
1679 static void __exit icn_exit(void)
1680 {
1681 isdn_ctrl cmd;
1682 icn_card *card = cards;
1683 icn_card *last;
1684 int i;
1685
1686 icn_stopallcards();
1687 while (card) {
1688 cmd.command = ISDN_STAT_UNLOAD;
1689 cmd.driver = card->myid;
1690 card->interface.statcallb(&cmd);
1691 if (card->rvalid) {
1692 OUTB_P(0, ICN_RUN); /* Reset Controller */
1693 OUTB_P(0, ICN_MAPRAM); /* Disable RAM */
1694 if (card->secondhalf || (!card->doubleS0)) {
1695 release_region(card->port, ICN_PORTLEN);
1696 card->rvalid = 0;
1697 }
1698 for (i = 0; i < ICN_BCH; i++)
1699 icn_free_queue(card, i);
1700 }
1701 card = card->next;
1702 }
1703 card = cards;
1704 while (card) {
1705 last = card;
1706 card = card->next;
1707 kfree(last);
1708 }
1709 if (dev.mvalid) {
1710 iounmap(dev.shmem);
1711 release_mem_region(dev.memaddr, 0x4000);
1712 }
1713 printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n");
1714 }
1715
1716 module_init(icn_init);
1717 module_exit(icn_exit);
1718