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