OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [icn/] [icn.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.