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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [avmb1/] [b1capi.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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