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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [icn/] [icn.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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