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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [avmb1/] [b1capi.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * $Id: b1capi.c,v 1.1 2005-12-20 10:16:58 jcastillo Exp $
3
 *
4
 * CAPI 2.0 Module for AVM B1-card.
5
 *
6
 * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
7
 *
8
 * $Log: not supported by cvs2svn $
9
 * Revision 1.1.1.1  2001/09/10 07:44:18  simons
10
 * Initial import
11
 *
12
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
13
 * Initial revision
14
 *
15
 * Revision 1.4.2.19  1998/10/25 14:36:14  fritz
16
 * Backported from MIPS (Cobalt).
17
 *
18
 * Revision 1.4.2.18  1998/03/20 20:34:37  calle
19
 * port valid check now only for T1, because of the PCI and PCMCIA cards.
20
 *
21
 * Revision 1.4.2.17  1998/03/20 14:38:17  calle
22
 * capidrv: prepared state machines for suspend/resume/hold
23
 * capidrv: fix bug in state machine if B1/T1 is out of nccis
24
 * b1capi: changed some errno returns.
25
 * b1capi: detect if you try to add same T1 to different io address.
26
 * b1capi: change number of nccis depending on number of channels.
27
 * b1lli: cosmetics
28
 *
29
 * Revision 1.4.2.16  1998/03/20 09:01:08  calle
30
 * Changes capi_register handling to get full support for 30 bchannels.
31
 *
32
 * Revision 1.4.2.15  1998/03/18 17:43:26  calle
33
 * T1 with fastlink, bugfix for multicontroller support in capidrv.c
34
 *
35
 * Revision 1.4.2.14  1998/03/04 17:33:47  calle
36
 * Changes for T1.
37
 *
38
 * Revision 1.4.2.13  1998/02/27 15:40:41  calle
39
 * T1 running with slow link. bugfix in capi_release.
40
 *
41
 * Revision 1.4.2.12  1998/02/24 17:58:25  calle
42
 * changes for T1.
43
 *
44
 * Revision 1.4.2.11  1998/01/27 16:12:49  calle
45
 * Support for PCMCIA B1/M1/M2 ready.
46
 *
47
 * Revision 1.4.2.10  1998/01/26 14:53:30  calle
48
 * interface change for pcmcia cards
49
 *
50
 * Revision 1.4.2.9  1998/01/23 16:49:27  calle
51
 * added functions for pcmcia cards,
52
 * avmb1_addcard returns now the controller number.
53
 *
54
 * Revision 1.4.2.8  1998/01/16 14:04:15  calle
55
 * Decoding of manufacturer part of capi_profile, now show linetype and
56
 * protocol if possible.
57
 *
58
 * Revision 1.4.2.7  1998/01/15 15:33:34  calle
59
 * print cardtype, d2 protocol and linetype after load.
60
 *
61
 * Revision 1.4.2.6  1997/12/08 06:58:41  calle
62
 * correct typo.
63
 *
64
 * Revision 1.4.2.5  1997/12/07 19:59:54  calle
65
 * more changes for M1/T1/B1 + config
66
 *
67
 * Revision 1.4.2.4  1997/11/26 16:57:20  calle
68
 * more changes for B1/M1/T1.
69
 *
70
 * Revision 1.4.2.3  1997/11/26 10:46:52  calle
71
 * prepared for M1 (Mobile) and T1 (PMX) cards.
72
 * prepared to set configuration after load to support other D-channel
73
 * protocols, point-to-point and leased lines.
74
 *
75
 * Revision 1.4.2.2  1997/10/19 14:44:36  calle
76
 * fixed capi_get_version.
77
 *
78
 * Revision 1.4.2.1  1997/07/12 08:18:59  calle
79
 * Correct bug in CARD_NR macro, so now more than one card will work.
80
 * Allow card reset, even if card is in running state.
81
 *
82
 * Revision 1.4  1997/05/27 15:17:45  fritz
83
 * Added changes for recent 2.1.x kernels:
84
 *   changed return type of isdn_close
85
 *   queue_task_* -> queue_task
86
 *   clear/set_bit -> test_and_... where apropriate.
87
 *   changed type of hard_header_cache parameter.
88
 *
89
 * Revision 1.3  1997/05/18 09:24:09  calle
90
 * added verbose disconnect reason reporting to avmb1.
91
 * some fixes in capi20 interface.
92
 * changed info messages for B1-PCI
93
 *
94
 * Revision 1.2  1997/03/05 21:20:41  fritz
95
 * Removed include of config.h (mkdep stated this is unneded).
96
 *
97
 * Revision 1.1  1997/03/04 21:50:27  calle
98
 * Frirst version in isdn4linux
99
 *
100
 * Revision 2.2  1997/02/12 09:31:39  calle
101
 * new version
102
 *
103
 * Revision 1.1  1997/01/31 10:32:20  calle
104
 * Initial revision
105
 *
106
 *
107
 */
108
 
109
#include <linux/module.h>
110
#include <linux/kernel.h>
111
#include <linux/mm.h>
112
#include <linux/interrupt.h>
113
#include <linux/ioport.h>
114
#include <asm/segment.h>
115
#include <linux/skbuff.h>
116
#include <linux/tqueue.h>
117
#include <linux/capi.h>
118
#include <linux/b1lli.h>
119
#include <linux/kernelcapi.h>
120
#include "compat.h"
121
#include "capicmd.h"
122
#include "capiutil.h"
123
 
124
static char *revision = "$Revision: 1.1 $";
125
 
126
/* ------------------------------------------------------------- */
127
 
128
int showcapimsgs = 0;            /* used in lli.c */
129
int loaddebug = 0;
130
 
131
#ifdef HAS_NEW_SYMTAB
132
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
133
MODULE_PARM(showcapimsgs, "0-5i");
134
MODULE_PARM(loaddebug, "0-1i");
135
#endif
136
 
137
/* ------------------------------------------------------------- */
138
 
139
struct msgidqueue {
140
        struct msgidqueue *next;
141
        __u16 msgid;
142
};
143
 
144
typedef struct avmb1_ncci {
145
        struct avmb1_ncci *next;
146
        __u16 applid;
147
        __u32 ncci;
148
        __u32 winsize;
149
        struct msgidqueue *msgidqueue;
150
        struct msgidqueue *msgidlast;
151
        struct msgidqueue *msgidfree;
152
        struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
153
} avmb1_ncci;
154
 
155
typedef struct avmb1_appl {
156
        __u16 applid;
157
        capi_register_params rparam;
158
        int releasing;
159
        __u32 param;
160
        void (*signal) (__u16 applid, __u32 param);
161
        struct sk_buff_head recv_queue;
162
        struct avmb1_ncci *nccilist;
163
} avmb1_appl;
164
 
165
/* ------------------------------------------------------------- */
166
 
167
static struct capi_version driver_version = {2, 0, 1, 1<<4};
168
static char driver_serial[CAPI_SERIAL_LEN] = "4711";
169
static char capi_manufakturer[64] = "AVM Berlin";
170
 
171
#define APPL(a)            (&applications[(a)-1])
172
#define VALID_APPLID(a)    ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
173
#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
174
#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
175
#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
176
 
177
#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
178
 
179
#define VALID_CARD(c)      ((c) > 0 && (c) <= CAPI_MAXCONTR)
180
#define CARD(c)            (&cards[(c)-1])
181
#define CARDNR(cp)         (((cp)-cards)+1)
182
 
183
static avmb1_appl applications[CAPI_MAXAPPL];
184
static avmb1_card cards[CAPI_MAXCONTR];
185
static int ncards = 0;
186
static struct sk_buff_head recv_queue;
187
static struct capi_interface_user *capi_users = 0;
188
static long notify_up_set = 0;
189
static long notify_down_set = 0;
190
 
191
static struct tq_struct tq_state_notify;
192
static struct tq_struct tq_recv_notify;
193
 
194
/* -------- util functions ------------------------------------ */
195
 
196
static char *cardtype2str(int cardtype)
197
{
198
        switch (cardtype) {
199
                default:
200
                case AVM_CARDTYPE_B1: return "B1";
201
                case AVM_CARDTYPE_M1: return "M1";
202
                case AVM_CARDTYPE_M2: return "M2";
203
                case AVM_CARDTYPE_T1: return "T1";
204
        }
205
}
206
 
207
static inline int capi_cmd_valid(__u8 cmd)
208
{
209
        switch (cmd) {
210
        case CAPI_ALERT:
211
        case CAPI_CONNECT:
212
        case CAPI_CONNECT_ACTIVE:
213
        case CAPI_CONNECT_B3_ACTIVE:
214
        case CAPI_CONNECT_B3:
215
        case CAPI_CONNECT_B3_T90_ACTIVE:
216
        case CAPI_DATA_B3:
217
        case CAPI_DISCONNECT_B3:
218
        case CAPI_DISCONNECT:
219
        case CAPI_FACILITY:
220
        case CAPI_INFO:
221
        case CAPI_LISTEN:
222
        case CAPI_MANUFACTURER:
223
        case CAPI_RESET_B3:
224
        case CAPI_SELECT_B_PROTOCOL:
225
                return 1;
226
        }
227
        return 0;
228
}
229
 
230
static inline int capi_subcmd_valid(__u8 subcmd)
231
{
232
        switch (subcmd) {
233
        case CAPI_REQ:
234
        case CAPI_CONF:
235
        case CAPI_IND:
236
        case CAPI_RESP:
237
                return 1;
238
        }
239
        return 0;
240
}
241
 
242
/* -------- NCCI Handling ------------------------------------- */
243
 
244
static inline void mq_init(avmb1_ncci * np)
245
{
246
        int i;
247
        np->msgidqueue = 0;
248
        np->msgidlast = 0;
249
        memset(np->msgidpool, 0, sizeof(np->msgidpool));
250
        np->msgidfree = &np->msgidpool[0];
251
        for (i = 1; i < np->winsize; i++) {
252
                np->msgidpool[i].next = np->msgidfree;
253
                np->msgidfree = &np->msgidpool[i];
254
        }
255
}
256
 
257
static inline int mq_enqueue(avmb1_ncci * np, __u16 msgid)
258
{
259
        struct msgidqueue *mq;
260
        if ((mq = np->msgidfree) == 0)
261
                return 0;
262
        np->msgidfree = mq->next;
263
        mq->msgid = msgid;
264
        mq->next = 0;
265
        if (np->msgidlast)
266
                np->msgidlast->next = mq;
267
        np->msgidlast = mq;
268
        if (!np->msgidqueue)
269
                np->msgidqueue = mq;
270
        return 1;
271
}
272
 
273
static inline int mq_dequeue(avmb1_ncci * np, __u16 msgid)
274
{
275
        struct msgidqueue **pp;
276
        for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
277
                if ((*pp)->msgid == msgid) {
278
                        struct msgidqueue *mq = *pp;
279
                        *pp = mq->next;
280
                        if (mq == np->msgidlast)
281
                                np->msgidlast = 0;
282
                        mq->next = np->msgidfree;
283
                        np->msgidfree = mq;
284
                        return 1;
285
                }
286
        }
287
        return 0;
288
}
289
 
290
void avmb1_handle_new_ncci(avmb1_card * card,
291
                           __u16 appl, __u32 ncci, __u32 winsize)
292
{
293
        avmb1_ncci *np;
294
        if (!VALID_APPLID(appl)) {
295
                printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
296
                return;
297
        }
298
        if ((np = (avmb1_ncci *) kmalloc(sizeof(avmb1_ncci), GFP_ATOMIC)) == 0) {
299
                printk(KERN_ERR "avmb1_handle_new_ncci: alloc failed ncci 0x%x\n", ncci);
300
                return;
301
        }
302
        if (winsize > CAPI_MAXDATAWINDOW) {
303
                printk(KERN_ERR "avmb1_handle_new_ncci: winsize %d too big, set to %d\n",
304
                       winsize, CAPI_MAXDATAWINDOW);
305
                winsize = CAPI_MAXDATAWINDOW;
306
        }
307
        np->applid = appl;
308
        np->ncci = ncci;
309
        np->winsize = winsize;
310
        mq_init(np);
311
        np->next = APPL(appl)->nccilist;
312
        APPL(appl)->nccilist = np;
313
        printk(KERN_INFO "b1capi: appl %d ncci 0x%x up\n", appl, ncci);
314
 
315
}
316
 
317
void avmb1_handle_free_ncci(avmb1_card * card,
318
                            __u16 appl, __u32 ncci)
319
{
320
        if (!VALID_APPLID(appl)) {
321
                printk(KERN_ERR "avmb1_handle_free_ncci: illegal appl %d\n", appl);
322
                return;
323
        }
324
        if (ncci != 0xffffffff) {
325
                avmb1_ncci **pp;
326
                for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
327
                        if ((*pp)->ncci == ncci) {
328
                                avmb1_ncci *np = *pp;
329
                                *pp = np->next;
330
                                kfree(np);
331
                                printk(KERN_INFO "b1capi: appl %d ncci 0x%x down\n", appl, ncci);
332
                                return;
333
                        }
334
                }
335
                printk(KERN_ERR "avmb1_handle_free_ncci: ncci 0x%x not found\n", ncci);
336
        } else {
337
                avmb1_ncci **pp, **nextpp;
338
                for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
339
                        if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
340
                                avmb1_ncci *np = *pp;
341
                                *pp = np->next;
342
                                printk(KERN_INFO "b1capi: appl %d ncci 0x%x down!\n", appl, np->ncci);
343
                                kfree(np);
344
                                nextpp = pp;
345
                        } else {
346
                                nextpp = &(*pp)->next;
347
                        }
348
                }
349
                APPL(appl)->releasing--;
350
                if (APPL(appl)->releasing <= 0) {
351
                        APPL(appl)->signal = 0;
352
                        APPL_MARK_FREE(appl);
353
                        printk(KERN_INFO "b1capi: appl %d down\n", appl);
354
                }
355
        }
356
}
357
 
358
static avmb1_ncci *find_ncci(avmb1_appl * app, __u32 ncci)
359
{
360
        avmb1_ncci *np;
361
        for (np = app->nccilist; np; np = np->next) {
362
                if (np->ncci == ncci)
363
                        return np;
364
        }
365
        return 0;
366
}
367
 
368
 
369
 
370
/* -------- Receiver ------------------------------------------ */
371
 
372
 
373
static void recv_handler(void *dummy)
374
{
375
        struct sk_buff *skb;
376
 
377
        while ((skb = skb_dequeue(&recv_queue)) != 0) {
378
                __u16 appl = CAPIMSG_APPID(skb->data);
379
                struct avmb1_ncci *np;
380
                if (!VALID_APPLID(appl)) {
381
                        printk(KERN_ERR "b1capi: recv_handler: applid %d ? (%s)\n",
382
                               appl, capi_message2str(skb->data));
383
                        kfree_skb(skb, FREE_READ);
384
                        continue;
385
                }
386
                if (APPL(appl)->signal == 0) {
387
                        printk(KERN_ERR "b1capi: recv_handler: applid %d has no signal function\n",
388
                               appl);
389
                        kfree_skb(skb, FREE_READ);
390
                        continue;
391
                }
392
                if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
393
                    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
394
                    && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
395
                    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
396
                        printk(KERN_ERR "b1capi: msgid %hu ncci 0x%x not on queue\n",
397
                                CAPIMSG_MSGID(skb->data), np->ncci);
398
                }
399
                skb_queue_tail(&APPL(appl)->recv_queue, skb);
400
                (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
401
        }
402
}
403
 
404
 
405
void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb)
406
{
407
        if (card->cardstate != CARD_RUNNING) {
408
                printk(KERN_INFO "b1capi: controller %d not active, got: %s",
409
                       card->cnr, capi_message2str(skb->data));
410
                goto error;
411
                return;
412
        }
413
        skb_queue_tail(&recv_queue, skb);
414
        queue_task(&tq_recv_notify, &tq_immediate);
415
        mark_bh(IMMEDIATE_BH);
416
        return;
417
 
418
      error:
419
        kfree_skb(skb, FREE_READ);
420
}
421
 
422
void avmb1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
423
{
424
        avmb1_card *card;
425
 
426
        card = (avmb1_card *) devptr;
427
 
428
        if (!card) {
429
                printk(KERN_WARNING "avmb1_interrupt: wrong device\n");
430
                return;
431
        }
432
        if (card->interrupt) {
433
                printk(KERN_ERR "avmb1_interrupt: reentering interrupt hander\n");
434
                return;
435
        }
436
 
437
        card->interrupt = 1;
438
 
439
        B1_handle_interrupt(card);
440
 
441
        card->interrupt = 0;
442
}
443
 
444
/* -------- Notifier ------------------------------------------ */
445
 
446
static void notify_up(__u16 contr)
447
{
448
        struct capi_interface_user *p;
449
 
450
        printk(KERN_NOTICE "b1capi: notify up contr %d\n", contr);
451
        for (p = capi_users; p; p = p->next) {
452
                if (p->callback)
453
                        (*p->callback) (KCI_CONTRUP, contr,
454
                                (capi_profile *)
455
                                        CARD(contr)->version[VER_PROFILE]);
456
        }
457
}
458
 
459
static void notify_down(__u16 contr)
460
{
461
        struct capi_interface_user *p;
462
        printk(KERN_NOTICE "b1capi: notify down contr %d\n", contr);
463
        for (p = capi_users; p; p = p->next) {
464
                if (p->callback)
465
                        (*p->callback) (KCI_CONTRDOWN, contr, 0);
466
        }
467
}
468
 
469
static void notify_handler(void *dummy)
470
{
471
        __u16 contr;
472
 
473
        for (contr=1; VALID_CARD(contr); contr++)
474
                 if (test_and_clear_bit(contr, &notify_up_set))
475
                         notify_up(contr);
476
        for (contr=1; VALID_CARD(contr); contr++)
477
                 if (test_and_clear_bit(contr, &notify_down_set))
478
                         notify_down(contr);
479
}
480
 
481
/* -------- card ready callback ------------------------------- */
482
 
483
 
484
void avmb1_card_ready(avmb1_card * card)
485
{
486
        struct capi_profile *profp =
487
                        (struct capi_profile *)card->version[VER_PROFILE];
488
        char *dversion = card->version[VER_DRIVER];
489
        __u16 appl;
490
        char *cardname, cname[20];
491
        __u32 flag;
492
        int nbchan = profp->nbchannel;
493
 
494
        card->cversion.majorversion = 2;
495
        card->cversion.minorversion = 0;
496
        card->cversion.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
497
        card->cversion.majormanuversion |= ((dversion[2] - '0') & 0xf);
498
        card->cversion.minormanuversion = (dversion[3] - '0') << 4;
499
        card->cversion.minormanuversion |=
500
                (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
501
        card->cardstate = CARD_RUNNING;
502
 
503
        for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
504
                if (VALID_APPLID(appl) && !APPL(appl)->releasing) {
505
                        int nconn, want = APPL(appl)->rparam.level3cnt;
506
 
507
                        if (want > 0) nconn = want;
508
                        else nconn = nbchan * -want;
509
                        if (nconn == 0) nconn = nbchan;
510
 
511
                        B1_send_register(card->port, appl,
512
                                1024 * (nconn+1), nconn,
513
                                APPL(appl)->rparam.datablkcnt,
514
                                APPL(appl)->rparam.datablklen);
515
                }
516
        }
517
 
518
        set_bit(CARDNR(card), &notify_up_set);
519
        queue_task(&tq_state_notify, &tq_scheduler);
520
 
521
        flag = ((__u8 *)(profp->manu))[1];
522
        switch (flag) {
523
        case 0: cardname = cardtype2str(card->cardtype); break;
524
        case 3: cardname = "PCMCIA B"; break;
525
        case 4: cardname = "PCMCIA M1"; break;
526
        case 5: cardname = "PCMCIA M2"; break;
527
        case 6: cardname = "B1 V3.0"; break;
528
        case 7: cardname = "B1 PCI"; break;
529
        default: cardname = cname; break;
530
                 sprintf(cname, "AVM?%u", (unsigned int)flag);
531
                 break;
532
        }
533
        printk(KERN_NOTICE "b1capi: card %d \"%s\" ready.\n",
534
                CARDNR(card), cardname);
535
        flag = ((__u8 *)(profp->manu))[3];
536
        if (flag)
537
                printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
538
                        CARDNR(card),
539
                        (flag & 0x01) ? " DSS1" : "",
540
                        (flag & 0x02) ? " CT1" : "",
541
                        (flag & 0x04) ? " VN3" : "",
542
                        (flag & 0x08) ? " NI1" : "",
543
                        (flag & 0x10) ? " AUSTEL" : "",
544
                        (flag & 0x20) ? " ESS" : "",
545
                        (flag & 0x40) ? " 1TR6" : ""
546
                        );
547
        flag = ((__u8 *)(profp->manu))[5];
548
        if (flag)
549
                printk(KERN_NOTICE "b1capi: card %d Linetype:%s%s%s%s\n",
550
                        CARDNR(card),
551
                        (flag & 0x01) ? " point to point" : "",
552
                        (flag & 0x02) ? " point to multipoint" : "",
553
                        (flag & 0x08) ? " leased line without D-channel" : "",
554
                        (flag & 0x04) ? " leased line with D-channel" : ""
555
                        );
556
}
557
 
558
static void avmb1_card_down(avmb1_card * card, int notify)
559
{
560
        __u16 appl;
561
 
562
        card->cardstate = CARD_DETECTED;
563
 
564
        for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
565
                avmb1_ncci **pp, **nextpp;
566
                for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
567
                        if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
568
                                avmb1_ncci *np = *pp;
569
                                *pp = np->next;
570
                                printk(KERN_INFO "b1capi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
571
                                kfree(np);
572
                                nextpp = pp;
573
                        } else {
574
                                nextpp = &(*pp)->next;
575
                        }
576
                }
577
        }
578
        set_bit(CARDNR(card), &notify_down_set);
579
        queue_task(&tq_state_notify, &tq_scheduler);
580
        printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card));
581
}
582
 
583
/* ------------------------------------------------------------- */
584
 
585
 
586
int avmb1_registercard(int port, int irq, int cardtype, int allocio)
587
{
588
        struct avmb1_card *card;
589
        int irqval,i;
590
 
591
 
592
        for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
593
 
594
        if (i == CAPI_MAXCONTR) {
595
                printk(KERN_ERR "b1capi: out of controller slots\n");
596
                return -ENFILE;
597
        }
598
 
599
        card = &cards[i];
600
        memset(card, 0, sizeof(avmb1_card));
601
        sprintf(card->name, "avmb1-%d", CARDNR(card));
602
 
603
        if (allocio)
604
                request_region(port, AVMB1_PORTLEN, card->name);
605
 
606
        if ((irqval = request_irq(irq, avmb1_interrupt,
607
                                 SA_SHIRQ, card->name, card)) != 0) {
608
                printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n",
609
                       irq, irqval);
610
                release_region(port, AVMB1_PORTLEN);
611
                return -EBUSY;
612
        }
613
 
614
        card->cardstate = CARD_DETECTED;
615
        ncards++;
616
        card->cnr = CARDNR(card);
617
        card->port = port;
618
        card->irq = irq;
619
        card->cardtype = cardtype;
620
        return card->cnr;
621
}
622
 
623
int avmb1_addcard(int port, int irq, int cardtype)
624
{
625
        return avmb1_registercard(port, irq, cardtype, 1);
626
}
627
 
628
int avmb1_detectcard(int port, int irq, int cardtype)
629
{
630
        int rc;
631
 
632
        if (!B1_valid_irq(irq, cardtype)) {
633
                printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n",
634
                                irq, cardtype2str(cardtype));
635
                return -EINVAL;
636
        }
637
        if (!B1_valid_port(port, cardtype)) {
638
                printk(KERN_WARNING "b1capi: port 0x%x not valid for %s-card.\n",
639
                                port, cardtype2str(cardtype));
640
                return -EINVAL;
641
        }
642
        B1_reset(port);
643
        if ((rc = B1_detect(port, cardtype)) != 0) {
644
                printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n",
645
                                          cardtype2str(cardtype), port, rc);
646
                return -EIO;
647
        }
648
        B1_reset(port);
649
        switch (cardtype) {
650
                default:
651
                case AVM_CARDTYPE_M1:
652
                case AVM_CARDTYPE_M2:
653
                case AVM_CARDTYPE_B1:
654
                        printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port);
655
                        break;
656
                case AVM_CARDTYPE_T1:
657
                        break;
658
        }
659
 
660
        return 0;
661
}
662
 
663
int avmb1_probecard(int port, int irq, int cardtype)
664
{
665
        if (check_region(port, AVMB1_PORTLEN)) {
666
                printk(KERN_WARNING
667
                       "b1capi: ports 0x%03x-0x%03x in use.\n",
668
                       port, port + AVMB1_PORTLEN);
669
                return -EBUSY;
670
        }
671
        return avmb1_detectcard(port, irq, cardtype);
672
}
673
 
674
int avmb1_unregistercard(int cnr, int freeio)
675
{
676
        avmb1_card * card;
677
        if (!VALID_CARD(cnr))
678
                return -ESRCH;
679
        card = CARD(cnr);
680
 
681
        if (card->cardstate == CARD_FREE)
682
                return -ESRCH;
683
        if (card->cardstate == CARD_RUNNING)
684
                avmb1_card_down(card, freeio);
685
 
686
        if (card->cardstate != CARD_FREE)
687
                if (card->cardtype == AVM_CARDTYPE_T1)
688
                        T1_reset(card->port);
689
 
690
        free_irq(card->irq, card);
691
        if (freeio)
692
                release_region(card->port, AVMB1_PORTLEN);
693
        card->cardstate = CARD_FREE;
694
        return 0;
695
}
696
 
697
int avmb1_resetcard(int cnr)
698
{
699
        avmb1_card * card;
700
 
701
        if (!VALID_CARD(cnr))
702
                return -ESRCH;
703
        card = CARD(cnr);
704
        if (card->cardstate == CARD_FREE)
705
                return -ESRCH;
706
 
707
        if (card->cardstate == CARD_RUNNING)
708
                avmb1_card_down(card, 0);
709
 
710
        B1_reset(card->port);
711
        B1_reset(card->port);
712
 
713
        card->cardstate = CARD_DETECTED;
714
 
715
        return 0;
716
}
717
 
718
/* ------------------------------------------------------------- */
719
/* -------- CAPI2.0 Interface ---------------------------------- */
720
/* ------------------------------------------------------------- */
721
 
722
static int capi_installed(void)
723
{
724
        int i;
725
        for (i = 0; i < CAPI_MAXCONTR; i++) {
726
                if (cards[i].cardstate == CARD_RUNNING)
727
                        return 1;
728
        }
729
        return 0;
730
}
731
 
732
static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
733
{
734
        int nconn, want = rparam->level3cnt;
735
        int i;
736
        int appl;
737
 
738
        if (rparam->datablklen < 128)
739
                return CAPI_LOGBLKSIZETOSMALL;
740
 
741
        for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
742
                if (APPL_IS_FREE(appl))
743
                        break;
744
        }
745
        if (appl > CAPI_MAXAPPL)
746
                return CAPI_TOOMANYAPPLS;
747
 
748
        APPL_MARK_USED(appl);
749
        skb_queue_head_init(&APPL(appl)->recv_queue);
750
 
751
        memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
752
 
753
        for (i = 0; i < CAPI_MAXCONTR; i++) {
754
                struct capi_profile *profp =
755
                        (struct capi_profile *)cards[i].version[VER_PROFILE];
756
 
757
                if (cards[i].cardstate != CARD_RUNNING)
758
                        continue;
759
 
760
                if (want > 0) nconn = want;
761
                else nconn = profp->nbchannel * -want;
762
                if (nconn == 0) nconn = profp->nbchannel;
763
 
764
                B1_send_register(cards[i].port, appl,
765
                        1024 * (nconn+1), nconn,
766
                        APPL(appl)->rparam.datablkcnt,
767
                        APPL(appl)->rparam.datablklen);
768
        }
769
        *applidp = appl;
770
        printk(KERN_INFO "b1capi: appl %d up\n", appl);
771
 
772
        return CAPI_NOERROR;
773
}
774
 
775
static __u16 capi_release(__u16 applid)
776
{
777
        struct sk_buff *skb;
778
        int i;
779
 
780
        if (!VALID_APPLID(applid) || APPL(applid)->releasing)
781
                return CAPI_ILLAPPNR;
782
        while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
783
                kfree_skb(skb, FREE_READ);
784
        for (i = 0; i < CAPI_MAXCONTR; i++) {
785
                if (cards[i].cardstate != CARD_RUNNING) {
786
                        continue;
787
                }
788
                APPL(applid)->releasing++;
789
                B1_send_release(cards[i].port, applid);
790
        }
791
        if (APPL(applid)->releasing <= 0) {
792
                APPL(applid)->signal = 0;
793
                APPL_MARK_FREE(applid);
794
                printk(KERN_INFO "b1capi: appl %d down\n", applid);
795
        }
796
        return CAPI_NOERROR;
797
}
798
 
799
static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
800
{
801
        avmb1_ncci *np;
802
        int contr;
803
        if (ncards == 0)
804
                return CAPI_REGNOTINSTALLED;
805
        if (!VALID_APPLID(applid))
806
                return CAPI_ILLAPPNR;
807
        if (skb->len < 12
808
            || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
809
            || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
810
                return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
811
        contr = CAPIMSG_CONTROLLER(skb->data);
812
        if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
813
                contr = 1;
814
                if (CARD(contr)->cardstate != CARD_RUNNING)
815
                        return CAPI_REGNOTINSTALLED;
816
        }
817
        if (CARD(contr)->blocked)
818
                return CAPI_SENDQUEUEFULL;
819
 
820
        if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
821
            && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ
822
            && (np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
823
            && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
824
                return CAPI_SENDQUEUEFULL;
825
 
826
        B1_send_message(CARD(contr)->port, skb);
827
        return CAPI_NOERROR;
828
}
829
 
830
static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
831
{
832
        struct sk_buff *skb;
833
 
834
        if (!VALID_APPLID(applid))
835
                return CAPI_ILLAPPNR;
836
        if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
837
                return CAPI_RECEIVEQUEUEEMPTY;
838
        *msgp = skb;
839
        return CAPI_NOERROR;
840
}
841
 
842
static __u16 capi_set_signal(__u16 applid,
843
                             void (*signal) (__u16 applid, __u32 param),
844
                             __u32 param)
845
{
846
        if (!VALID_APPLID(applid))
847
                return CAPI_ILLAPPNR;
848
        APPL(applid)->signal = signal;
849
        APPL(applid)->param = param;
850
        return CAPI_NOERROR;
851
}
852
 
853
static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
854
{
855
        if (contr == 0) {
856
                strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
857
                return CAPI_NOERROR;
858
        }
859
        if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
860
                return 0x2002;
861
 
862
        strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
863
        return CAPI_NOERROR;
864
}
865
 
866
static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
867
{
868
        if (contr == 0) {
869
                *verp = driver_version;
870
                return CAPI_NOERROR;
871
        }
872
        if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
873
                return 0x2002;
874
 
875
        memcpy((void *) verp, &CARD(contr)->cversion,
876
               sizeof(capi_version));
877
        return CAPI_NOERROR;
878
}
879
 
880
static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
881
{
882
        if (contr == 0) {
883
                strncpy(serial, driver_serial, 8);
884
                return CAPI_NOERROR;
885
        }
886
        if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
887
                return 0x2002;
888
 
889
        memcpy((void *) serial, CARD(contr)->version[VER_SERIAL],
890
               CAPI_SERIAL_LEN);
891
        serial[CAPI_SERIAL_LEN - 1] = 0;
892
        return CAPI_NOERROR;
893
}
894
 
895
static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
896
{
897
        if (contr == 0) {
898
                profp->ncontroller = ncards;
899
                return CAPI_NOERROR;
900
        }
901
        if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
902
                return 0x2002;
903
 
904
        memcpy((void *) profp, CARD(contr)->version[VER_PROFILE],
905
               sizeof(struct capi_profile));
906
        return CAPI_NOERROR;
907
}
908
 
909
static int capi_manufacturer(unsigned int cmd, void *data)
910
{
911
        unsigned long flags;
912
        avmb1_loadandconfigdef ldef;
913
        avmb1_extcarddef cdef;
914
        avmb1_resetdef rdef;
915
        avmb1_getdef gdef;
916
        avmb1_card *card;
917
        int rc;
918
 
919
        switch (cmd) {
920
        case AVMB1_ADDCARD:
921
        case AVMB1_ADDCARD_WITH_TYPE:
922
                if (cmd == AVMB1_ADDCARD) {
923
                   if ((rc = copy_from_user((void *) &cdef, data,
924
                                            sizeof(avmb1_carddef))))
925
                           return rc;
926
                   cdef.cardtype = AVM_CARDTYPE_B1;
927
                } else {
928
                   if ((rc = copy_from_user((void *) &cdef, data,
929
                                            sizeof(avmb1_extcarddef))))
930
                           return rc;
931
                }
932
 
933
                if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0)
934
                        return rc;
935
 
936
                if (cdef.cardtype == AVM_CARDTYPE_T1) {
937
                        int i;
938
                        for (i=0; i < CAPI_MAXCONTR; i++) {
939
                                if (   cards[i].cardstate != CARD_FREE
940
                                    && cards[i].cardtype == AVM_CARDTYPE_T1
941
                                    && cards[i].cardnr == cdef.cardnr) {
942
                                        printk(KERN_ERR
943
                                                "b1capi: T1-HEMA-card-%d already at 0x%x\n",
944
                                                cdef.cardnr, cards[i].port);
945
                                        return -EBUSY;
946
                                }
947
                        }
948
                        rc = T1_detectandinit(cdef.port,cdef.irq,cdef.cardnr);
949
                        if (rc) {
950
                                printk(KERN_NOTICE "b1capi: NO T1-HEMA-card-%d at 0x%x (%d)\n",
951
                                          cdef.cardnr, cdef.port, rc);
952
                                return -EIO;
953
                        }
954
                        printk(KERN_NOTICE "b1capi: T1-HEMA-card-%d at 0x%x\n",
955
                                  cdef.cardnr, cdef.port);
956
                }
957
 
958
                rc = avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
959
                if (rc < 0)
960
                        return rc;
961
                /* don't want to change interface t
962
                   addcard/probecard/registercard */
963
                if (cdef.cardtype == AVM_CARDTYPE_T1) {
964
                        int i;
965
                        for (i=0; i < CAPI_MAXCONTR; i++) {
966
                                if (cards[i].cnr == rc) {
967
                                        cards[i].cardnr = cdef.cardnr;
968
                                        break;
969
                                }
970
                        }
971
                }
972
                return rc;
973
 
974
        case AVMB1_LOAD:
975
        case AVMB1_LOAD_AND_CONFIG:
976
 
977
                if (cmd == AVMB1_LOAD) {
978
                        if ((rc = copy_from_user((void *) &ldef, data,
979
                                                sizeof(avmb1_loaddef))))
980
                                return rc;
981
                        ldef.t4config.len = 0;
982
                        ldef.t4config.data = 0;
983
                } else {
984
                        if ((rc = copy_from_user((void *) &ldef, data,
985
                                                sizeof(avmb1_loadandconfigdef))))
986
                                return rc;
987
                }
988
                if (!VALID_CARD(ldef.contr))
989
                        return -ESRCH;
990
 
991
                if (ldef.t4file.len <= 0) {
992
                        printk(KERN_DEBUG "b1capi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
993
                        return -EINVAL;
994
                }
995
 
996
                card = CARD(ldef.contr);
997
                save_flags(flags);
998
                cli();
999
                if (card->cardstate != CARD_DETECTED) {
1000
                        restore_flags(flags);
1001
                        if (loaddebug)
1002
                                printk(KERN_DEBUG "b1capi: load: contr=%d not in detect state\n", ldef.contr);
1003
                        return -EBUSY;
1004
                }
1005
                card->cardstate = CARD_LOADING;
1006
                restore_flags(flags);
1007
 
1008
                if (loaddebug) {
1009
                        printk(KERN_DEBUG "b1capi: load: reseting contr %d\n",
1010
                                ldef.contr);
1011
                }
1012
 
1013
                B1_reset(card->port);
1014
 
1015
                if (loaddebug) {
1016
                        printk(KERN_DEBUG "b1capi: loading contr %d\n",
1017
                                ldef.contr);
1018
                }
1019
 
1020
                if ((rc = B1_load_t4file(card->port, &ldef.t4file))) {
1021
                        B1_reset(card->port);
1022
                        printk(KERN_ERR "b1capi: failed to load t4file!!\n");
1023
                        card->cardstate = CARD_DETECTED;
1024
                        return rc;
1025
                }
1026
 
1027
                B1_disable_irq(card->port);
1028
 
1029
                if (ldef.t4config.len > 0) { /* load config */
1030
                        if (loaddebug) {
1031
                                printk(KERN_DEBUG "b1capi: loading config to contr %d\n",
1032
                                                        ldef.contr);
1033
                        }
1034
                        if ((rc = B1_load_config(card->port, &ldef.t4config))) {
1035
                                B1_reset(card->port);
1036
                                printk(KERN_ERR "b1capi: failed to load config!!\n");
1037
                                card->cardstate = CARD_DETECTED;
1038
                                return rc;
1039
                        }
1040
                }
1041
 
1042
                if (loaddebug) {
1043
                        printk(KERN_DEBUG "b1capi: load: ready contr %d: checking\n",
1044
                                ldef.contr);
1045
                }
1046
 
1047
                if (!B1_loaded(card->port)) {
1048
                        card->cardstate = CARD_DETECTED;
1049
                        printk(KERN_ERR "b1capi: failed to load t4file.\n");
1050
                        return -EIO;
1051
                }
1052
                /*
1053
                 * enable interrupt
1054
                 */
1055
 
1056
                card->cardstate = CARD_INITSTATE;
1057
                save_flags(flags);
1058
                cli();
1059
                B1_setinterrupt(card->port, card->irq, card->cardtype);
1060
                restore_flags(flags);
1061
 
1062
                if (loaddebug) {
1063
                        printk(KERN_DEBUG "b1capi: load: irq enabled contr %d\n",
1064
                                ldef.contr);
1065
                }
1066
 
1067
                /*
1068
                 * init card
1069
                 */
1070
                if (card->cardtype == AVM_CARDTYPE_T1)
1071
                   B1_send_init(card->port, AVM_NAPPS,
1072
                                            AVM_NNCCI_PER_CHANNEL*30,
1073
                                            card->cnr - 1);
1074
                else
1075
                   B1_send_init(card->port, AVM_NAPPS,
1076
                                            AVM_NNCCI_PER_CHANNEL*2,
1077
                                            card->cnr - 1);
1078
 
1079
                if (loaddebug) {
1080
                        printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n",
1081
                                ldef.contr);
1082
                }
1083
 
1084
                while (card->cardstate != CARD_RUNNING) {
1085
 
1086
                        current->timeout = jiffies + HZ / 10;   /* 0.1 sec */
1087
                        current->state = TASK_INTERRUPTIBLE;
1088
                        schedule();
1089
 
1090
                        if (current->signal & ~current->blocked)
1091
                                return -EINTR;
1092
                }
1093
                return 0;
1094
 
1095
        case AVMB1_RESETCARD:
1096
                if ((rc = copy_from_user((void *) &rdef, data,
1097
                                         sizeof(avmb1_resetdef))))
1098
                        return rc;
1099
 
1100
                return avmb1_resetcard(rdef.contr);
1101
 
1102
        case AVMB1_GET_CARDINFO:
1103
                if ((rc = copy_from_user((void *) &gdef, data,
1104
                                         sizeof(avmb1_getdef))))
1105
                        return rc;
1106
 
1107
                if (!VALID_CARD(gdef.contr))
1108
                        return -ESRCH;
1109
 
1110
                card = CARD(gdef.contr);
1111
 
1112
                gdef.cardstate = card->cardstate;
1113
                gdef.cardtype = card->cardtype;
1114
 
1115
                if ((rc = copy_to_user(data, (void *) &gdef,
1116
                                         sizeof(avmb1_getdef))))
1117
                        return rc;
1118
 
1119
                return 0;
1120
        case AVMB1_REMOVECARD:
1121
                if ((rc = copy_from_user((void *) &rdef, data,
1122
                                         sizeof(avmb1_resetdef))))
1123
                        return rc;
1124
                if (!VALID_CARD(rdef.contr))
1125
                        return -ESRCH;
1126
 
1127
                card = CARD(rdef.contr);
1128
 
1129
                if (card->cardstate != CARD_DETECTED)
1130
                        return -EBUSY;
1131
 
1132
                return avmb1_unregistercard(rdef.contr, 1);
1133
        }
1134
        return -EINVAL;
1135
}
1136
 
1137
struct capi_interface avmb1_interface =
1138
{
1139
        capi_installed,
1140
        capi_register,
1141
        capi_release,
1142
        capi_put_message,
1143
        capi_get_message,
1144
        capi_set_signal,
1145
        capi_get_manufacturer,
1146
        capi_get_version,
1147
        capi_get_serial,
1148
        capi_get_profile,
1149
        capi_manufacturer
1150
};
1151
 
1152
/* ------------------------------------------------------------- */
1153
/* -------- Exported Functions --------------------------------- */
1154
/* ------------------------------------------------------------- */
1155
 
1156
struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
1157
{
1158
        struct capi_interface_user *p;
1159
 
1160
        for (p = capi_users; p; p = p->next) {
1161
                if (p == userp) {
1162
                        printk(KERN_ERR "b1capi: double attach from %s\n",
1163
                               userp->name);
1164
                        return 0;
1165
                }
1166
        }
1167
        userp->next = capi_users;
1168
        capi_users = userp;
1169
        MOD_INC_USE_COUNT;
1170
        printk(KERN_NOTICE "b1capi: %s attached\n", userp->name);
1171
 
1172
        return &avmb1_interface;
1173
}
1174
 
1175
int detach_capi_interface(struct capi_interface_user *userp)
1176
{
1177
        struct capi_interface_user **pp;
1178
 
1179
        for (pp = &capi_users; *pp; pp = &(*pp)->next) {
1180
                if (*pp == userp) {
1181
                        *pp = userp->next;
1182
                        userp->next = 0;
1183
                        MOD_DEC_USE_COUNT;
1184
                        printk(KERN_NOTICE "b1capi: %s detached\n", userp->name);
1185
                        return 0;
1186
                }
1187
        }
1188
        printk(KERN_ERR "b1capi: double detach from %s\n", userp->name);
1189
        return -1;
1190
}
1191
 
1192
/* ------------------------------------------------------------- */
1193
/* -------- Init & Cleanup ------------------------------------- */
1194
/* ------------------------------------------------------------- */
1195
 
1196
#ifdef HAS_NEW_SYMTAB
1197
EXPORT_SYMBOL(attach_capi_interface);
1198
EXPORT_SYMBOL(detach_capi_interface);
1199
EXPORT_SYMBOL(avmb1_addcard);
1200
EXPORT_SYMBOL(avmb1_probecard);
1201
EXPORT_SYMBOL(avmb1_registercard);
1202
EXPORT_SYMBOL(avmb1_unregistercard);
1203
EXPORT_SYMBOL(avmb1_resetcard);
1204
EXPORT_SYMBOL(avmb1_detectcard);
1205
#else
1206
static struct symbol_table capidev_syms =
1207
{
1208
#include <linux/symtab_begin.h>
1209
        X(attach_capi_interface),
1210
        X(detach_capi_interface),
1211
        X(avmb1_addcard),
1212
        X(avmb1_probecard),
1213
        X(avmb1_registercard),
1214
        X(avmb1_unregistercard),
1215
        X(avmb1_resetcard),
1216
        X(avmb1_detectcard),
1217
#include <linux/symtab_end.h>
1218
};
1219
#endif
1220
 
1221
 
1222
/*
1223
 * init / exit functions
1224
 */
1225
 
1226
#ifdef MODULE
1227
#define avmb1_init init_module
1228
#endif
1229
 
1230
int avmb1_init(void)
1231
{
1232
        char *p;
1233
        char rev[10];
1234
 
1235
#ifndef HAS_NEW_SYMTAB
1236
        /* No symbols to export, hide all symbols */
1237
        register_symtab(&capidev_syms);
1238
#endif
1239
        skb_queue_head_init(&recv_queue);
1240
        /* init_bh(CAPI_BH, do_capi_bh); */
1241
 
1242
        tq_state_notify.routine = notify_handler;
1243
        tq_state_notify.data = 0;
1244
 
1245
        tq_recv_notify.routine = recv_handler;
1246
        tq_recv_notify.data = 0;
1247
 
1248
 
1249
        if ((p = strchr(revision, ':'))) {
1250
                strcpy(rev, p + 1);
1251
                p = strchr(rev, '$');
1252
                *p = 0;
1253
        } else
1254
                strcpy(rev, " ??? ");
1255
 
1256
#ifdef MODULE
1257
        printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: loaded\n", rev);
1258
#else
1259
        printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: started\n", rev);
1260
#endif
1261
        return 0;
1262
}
1263
 
1264
#ifdef MODULE
1265
void cleanup_module(void)
1266
{
1267
        char rev[10];
1268
        char *p;
1269
        int i;
1270
 
1271
        if ((p = strchr(revision, ':'))) {
1272
                strcpy(rev, p + 1);
1273
                p = strchr(rev, '$');
1274
                *p = 0;
1275
        } else {
1276
                strcpy(rev, " ??? ");
1277
        }
1278
 
1279
        for (i = 0; i < CAPI_MAXCONTR; i++) {
1280
                if (cards[i].cardstate != CARD_FREE) {
1281
                        /*
1282
                         * disable card
1283
                         */
1284
                        B1_disable_irq(cards[i].port);
1285
                        avmb1_resetcard(i+1);
1286
                        /*
1287
                         * free kernel resources
1288
                         */
1289
                        avmb1_unregistercard(i+1, 1);
1290
                }
1291
        }
1292
        schedule(); /* execute queued tasks .... */
1293
        printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: unloaded\n", rev);
1294
}
1295
#endif

powered by: WebSVN 2.1.0

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