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