* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / isdn / avmb1 / kcapi.c
blobfc58f12415cb0e3e3915c02f55c78fec3ddf43da
1 /*
2 * $Id: kcapi.c,v 1.6 1999/07/20 06:41:49 calle Exp $
3 *
4 * Kernel CAPI 2.0 Module
5 *
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
7 *
8 * $Log: kcapi.c,v $
9 * Revision 1.6 1999/07/20 06:41:49 calle
10 * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
11 * compile, if not selected as modules.
13 * Revision 1.5 1999/07/09 15:05:48 keil
14 * compat.h is now isdn_compat.h
16 * Revision 1.4 1999/07/08 14:15:17 calle
17 * Forgot to count down ncards in drivercb_detach_ctr.
19 * Revision 1.3 1999/07/06 07:42:02 calle
20 * - changes in /proc interface
21 * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
23 * Revision 1.2 1999/07/05 15:09:52 calle
24 * - renamed "appl_release" to "appl_released".
25 * - version und profile data now cleared on controller reset
26 * - extended /proc interface, to allow driver and controller specific
27 * informations to include by driver hackers.
29 * Revision 1.1 1999/07/01 15:26:42 calle
30 * complete new version (I love it):
31 * + new hardware independed "capi_driver" interface that will make it easy to:
32 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
33 * - write a CAPI-2.0 for the passive cards
34 * - support serial link CAPI-2.0 boxes.
35 * + wrote "capi_driver" for all supported cards.
36 * + "capi_driver" (supported cards) now have to be configured with
37 * make menuconfig, in the past all supported cards where included
38 * at once.
39 * + new and better informations in /proc/capi/
40 * + new ioctl to switch trace of capi messages per controller
41 * using "avmcapictrl trace [contr] on|off|...."
42 * + complete testcircle with all supported cards and also the
43 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
46 #define CONFIG_AVMB1_COMPAT
48 #include <linux/config.h>
49 #include <linux/module.h>
50 #include <linux/kernel.h>
51 #include <linux/mm.h>
52 #include <linux/interrupt.h>
53 #include <linux/ioport.h>
54 #include <asm/segment.h>
55 #include <linux/proc_fs.h>
56 #include <linux/skbuff.h>
57 #include <linux/tqueue.h>
58 #include <linux/capi.h>
59 #include <linux/kernelcapi.h>
60 #include <linux/isdn_compat.h>
61 #include "capicmd.h"
62 #include "capiutil.h"
63 #include "capilli.h"
64 #ifdef CONFIG_AVMB1_COMPAT
65 #include <linux/b1lli.h>
66 #endif
68 static char *revision = "$Revision: 1.6 $";
70 /* ------------------------------------------------------------- */
72 #define CARD_FREE 0
73 #define CARD_DETECTED 1
74 #define CARD_LOADING 2
75 #define CARD_RUNNING 3
77 /* ------------------------------------------------------------- */
79 int showcapimsgs = 0;
81 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
82 MODULE_PARM(showcapimsgs, "0-4i");
84 /* ------------------------------------------------------------- */
86 struct msgidqueue {
87 struct msgidqueue *next;
88 __u16 msgid;
91 struct capi_ncci {
92 struct capi_ncci *next;
93 __u16 applid;
94 __u32 ncci;
95 __u32 winsize;
96 int nmsg;
97 struct msgidqueue *msgidqueue;
98 struct msgidqueue *msgidlast;
99 struct msgidqueue *msgidfree;
100 struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
103 struct capi_appl {
104 __u16 applid;
105 capi_register_params rparam;
106 int releasing;
107 __u32 param;
108 void (*signal) (__u16 applid, __u32 param);
109 struct sk_buff_head recv_queue;
110 int nncci;
111 struct capi_ncci *nccilist;
113 unsigned long nrecvctlpkt;
114 unsigned long nrecvdatapkt;
115 unsigned long nsentctlpkt;
116 unsigned long nsentdatapkt;
119 /* ------------------------------------------------------------- */
121 static struct capi_version driver_version = {2, 0, 1, 1<<4};
122 static char driver_serial[CAPI_SERIAL_LEN] = "4711";
123 static char capi_manufakturer[64] = "AVM Berlin";
125 #define APPL(a) (&applications[(a)-1])
126 #define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
127 #define APPL_IS_FREE(a) (APPL(a)->applid == 0)
128 #define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
129 #define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
131 #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
133 #define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR)
134 #define CARD(c) (&cards[(c)-1])
135 #define CARDNR(cp) (((cp)-cards)+1)
137 static struct capi_appl applications[CAPI_MAXAPPL];
138 static struct capi_ctr cards[CAPI_MAXCONTR];
139 static int ncards = 0;
140 static struct sk_buff_head recv_queue;
141 static struct capi_interface_user *capi_users = 0;
142 static struct capi_driver *drivers;
143 #ifdef CONFIG_AVMB1_COMPAT
144 static struct capi_driver *b1isa_driver;
145 static struct capi_driver *t1isa_driver;
146 #endif
147 static long notify_up_set = 0;
148 static long notify_down_set = 0;
150 static struct tq_struct tq_state_notify;
151 static struct tq_struct tq_recv_notify;
153 /* -------- util functions ------------------------------------ */
155 static char *cardstate2str(unsigned short cardstate)
157 switch (cardstate) {
158 default:
159 case CARD_FREE: return "free";
160 case CARD_DETECTED: return "detected";
161 case CARD_LOADING: return "loading";
162 case CARD_RUNNING: return "running";
166 static inline int capi_cmd_valid(__u8 cmd)
168 switch (cmd) {
169 case CAPI_ALERT:
170 case CAPI_CONNECT:
171 case CAPI_CONNECT_ACTIVE:
172 case CAPI_CONNECT_B3_ACTIVE:
173 case CAPI_CONNECT_B3:
174 case CAPI_CONNECT_B3_T90_ACTIVE:
175 case CAPI_DATA_B3:
176 case CAPI_DISCONNECT_B3:
177 case CAPI_DISCONNECT:
178 case CAPI_FACILITY:
179 case CAPI_INFO:
180 case CAPI_LISTEN:
181 case CAPI_MANUFACTURER:
182 case CAPI_RESET_B3:
183 case CAPI_SELECT_B_PROTOCOL:
184 return 1;
186 return 0;
189 static inline int capi_subcmd_valid(__u8 subcmd)
191 switch (subcmd) {
192 case CAPI_REQ:
193 case CAPI_CONF:
194 case CAPI_IND:
195 case CAPI_RESP:
196 return 1;
198 return 0;
201 /* -------- /proc functions ----------------------------------- */
203 * /proc/capi/applications:
204 * applid l3cnt dblkcnt dblklen #ncci recvqueuelen
206 static int proc_applications_read_proc(char *page, char **start, off_t off,
207 int count, int *eof, void *data)
209 struct capi_appl *ap;
210 int i;
211 int len = 0;
212 off_t begin = 0;
214 for (i=0; i < CAPI_MAXAPPL; i++) {
215 ap = &applications[i];
216 if (ap->applid == 0) continue;
217 len += sprintf(page+len, "%u %d %d %d %d %d\n",
218 ap->applid,
219 ap->rparam.level3cnt,
220 ap->rparam.datablkcnt,
221 ap->rparam.datablklen,
222 ap->nncci,
223 skb_queue_len(&ap->recv_queue));
224 if (len+begin > off+count)
225 goto endloop;
226 if (len+begin < off) {
227 begin += len;
228 len = 0;
231 endloop:
232 if (i >= CAPI_MAXAPPL)
233 *eof = 1;
234 if (off >= len+begin)
235 return 0;
236 *start = page + (begin-off);
237 return ((count < begin+len-off) ? count : begin+len-off);
241 * /proc/capi/ncci:
242 * applid ncci winsize nblk
244 static int proc_ncci_read_proc(char *page, char **start, off_t off,
245 int count, int *eof, void *data)
247 struct capi_appl *ap;
248 struct capi_ncci *np;
249 int i;
250 int len = 0;
251 off_t begin = 0;
253 for (i=0; i < CAPI_MAXAPPL; i++) {
254 ap = &applications[i];
255 if (ap->applid == 0) continue;
256 for (np = ap->nccilist; np; np = np->next) {
257 len += sprintf(page+len, "%d 0x%x %d %d\n",
258 np->applid,
259 np->ncci,
260 np->winsize,
261 np->nmsg);
262 if (len+begin > off+count)
263 goto endloop;
264 if (len+begin < off) {
265 begin += len;
266 len = 0;
270 endloop:
271 if (i >= CAPI_MAXAPPL)
272 *eof = 1;
273 if (off >= len+begin)
274 return 0;
275 *start = page + (begin-off);
276 return ((count < begin+len-off) ? count : begin+len-off);
280 * /proc/capi/driver:
281 * driver ncontroller
283 static int proc_driver_read_proc(char *page, char **start, off_t off,
284 int count, int *eof, void *data)
286 struct capi_driver *driver;
287 int len = 0;
288 off_t begin = 0;
290 for (driver = drivers; driver; driver = driver->next) {
291 len += sprintf(page+len, "%-32s %d %s\n",
292 driver->name,
293 driver->ncontroller,
294 driver->revision);
295 if (len+begin > off+count)
296 goto endloop;
297 if (len+begin < off) {
298 begin += len;
299 len = 0;
302 endloop:
303 if (!driver)
304 *eof = 1;
305 if (off >= len+begin)
306 return 0;
307 *start = page + (begin-off);
308 return ((count < begin+len-off) ? count : begin+len-off);
312 * /proc/capi/users:
313 * name
315 static int proc_users_read_proc(char *page, char **start, off_t off,
316 int count, int *eof, void *data)
318 struct capi_interface_user *cp;
319 int len = 0;
320 off_t begin = 0;
322 for (cp = capi_users; cp ; cp = cp->next) {
323 len += sprintf(page+len, "%s\n", cp->name);
324 if (len+begin > off+count)
325 goto endloop;
326 if (len+begin < off) {
327 begin += len;
328 len = 0;
331 endloop:
332 if (cp == 0)
333 *eof = 1;
334 if (off >= len+begin)
335 return 0;
336 *start = page + (begin-off);
337 return ((count < begin+len-off) ? count : begin+len-off);
341 * /proc/capi/controller:
342 * cnr driver cardstate name driverinfo
344 static int proc_controller_read_proc(char *page, char **start, off_t off,
345 int count, int *eof, void *data)
347 struct capi_ctr *cp;
348 int i;
349 int len = 0;
350 off_t begin = 0;
352 for (i=0; i < CAPI_MAXCONTR; i++) {
353 cp = &cards[i];
354 if (cp->cardstate == CARD_FREE) continue;
355 len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n",
356 cp->cnr, cp->driver->name,
357 cardstate2str(cp->cardstate),
358 cp->name,
359 cp->driver->procinfo ? cp->driver->procinfo(cp) : ""
361 if (len+begin > off+count)
362 goto endloop;
363 if (len+begin < off) {
364 begin += len;
365 len = 0;
368 endloop:
369 if (i >= CAPI_MAXCONTR)
370 *eof = 1;
371 if (off >= len+begin)
372 return 0;
373 *start = page + (begin-off);
374 return ((count < begin+len-off) ? count : begin+len-off);
378 * /proc/capi/applstats:
379 * applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
381 static int proc_applstats_read_proc(char *page, char **start, off_t off,
382 int count, int *eof, void *data)
384 struct capi_appl *ap;
385 int i;
386 int len = 0;
387 off_t begin = 0;
389 for (i=0; i < CAPI_MAXAPPL; i++) {
390 ap = &applications[i];
391 if (ap->applid == 0) continue;
392 len += sprintf(page+len, "%u %lu %lu %lu %lu\n",
393 ap->applid,
394 ap->nrecvctlpkt,
395 ap->nrecvdatapkt,
396 ap->nsentctlpkt,
397 ap->nsentdatapkt);
398 if (len+begin > off+count)
399 goto endloop;
400 if (len+begin < off) {
401 begin += len;
402 len = 0;
405 endloop:
406 if (i >= CAPI_MAXAPPL)
407 *eof = 1;
408 if (off >= len+begin)
409 return 0;
410 *start = page + (begin-off);
411 return ((count < begin+len-off) ? count : begin+len-off);
415 * /proc/capi/contrstats:
416 * cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
418 static int proc_contrstats_read_proc(char *page, char **start, off_t off,
419 int count, int *eof, void *data)
421 struct capi_ctr *cp;
422 int i;
423 int len = 0;
424 off_t begin = 0;
426 for (i=0; i < CAPI_MAXCONTR; i++) {
427 cp = &cards[i];
428 if (cp->cardstate == CARD_FREE) continue;
429 len += sprintf(page+len, "%d %lu %lu %lu %lu\n",
430 cp->cnr,
431 cp->nrecvctlpkt,
432 cp->nrecvdatapkt,
433 cp->nsentctlpkt,
434 cp->nsentdatapkt);
435 if (len+begin > off+count)
436 goto endloop;
437 if (len+begin < off) {
438 begin += len;
439 len = 0;
442 endloop:
443 if (i >= CAPI_MAXCONTR)
444 *eof = 1;
445 if (off >= len+begin)
446 return 0;
447 *start = page + (begin-off);
448 return ((count < begin+len-off) ? count : begin+len-off);
451 static struct procfsentries {
452 char *name;
453 mode_t mode;
454 int (*read_proc)(char *page, char **start, off_t off,
455 int count, int *eof, void *data);
456 struct proc_dir_entry *procent;
457 } procfsentries[] = {
458 { "capi", S_IFDIR, 0 },
459 { "capi/applications", 0 , proc_applications_read_proc },
460 { "capi/ncci", 0 , proc_ncci_read_proc },
461 { "capi/driver", 0 , proc_driver_read_proc },
462 { "capi/users", 0 , proc_users_read_proc },
463 { "capi/controller", 0 , proc_controller_read_proc },
464 { "capi/applstats", 0 , proc_applstats_read_proc },
465 { "capi/contrstats", 0 , proc_contrstats_read_proc },
466 { "capi/drivers", S_IFDIR, 0 },
467 { "capi/controllers", S_IFDIR, 0 },
470 static void proc_capi_init(void)
472 int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
473 int i;
475 for (i=0; i < nelem; i++) {
476 struct procfsentries *p = procfsentries + i;
477 p->procent = create_proc_entry(p->name, p->mode, 0);
478 if (p->procent) p->procent->read_proc = p->read_proc;
482 static void proc_capi_exit(void)
484 int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
485 int i;
487 for (i=nelem-1; i >= 0; i--) {
488 struct procfsentries *p = procfsentries + i;
489 if (p->procent) {
490 remove_proc_entry(p->name, 0);
491 p->procent = 0;
496 /* -------- NCCI Handling ------------------------------------- */
498 static inline void mq_init(struct capi_ncci * np)
500 int i;
501 np->msgidqueue = 0;
502 np->msgidlast = 0;
503 np->nmsg = 0;
504 memset(np->msgidpool, 0, sizeof(np->msgidpool));
505 np->msgidfree = &np->msgidpool[0];
506 for (i = 1; i < np->winsize; i++) {
507 np->msgidpool[i].next = np->msgidfree;
508 np->msgidfree = &np->msgidpool[i];
512 static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid)
514 struct msgidqueue *mq;
515 if ((mq = np->msgidfree) == 0)
516 return 0;
517 np->msgidfree = mq->next;
518 mq->msgid = msgid;
519 mq->next = 0;
520 if (np->msgidlast)
521 np->msgidlast->next = mq;
522 np->msgidlast = mq;
523 if (!np->msgidqueue)
524 np->msgidqueue = mq;
525 np->nmsg++;
526 return 1;
529 static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid)
531 struct msgidqueue **pp;
532 for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
533 if ((*pp)->msgid == msgid) {
534 struct msgidqueue *mq = *pp;
535 *pp = mq->next;
536 if (mq == np->msgidlast)
537 np->msgidlast = 0;
538 mq->next = np->msgidfree;
539 np->msgidfree = mq;
540 np->nmsg--;
541 return 1;
544 return 0;
547 static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl)
551 static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
553 struct capi_ncci **pp, **nextpp;
554 for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
555 if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
556 struct capi_ncci *np = *pp;
557 *pp = np->next;
558 printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci);
559 kfree(np);
560 APPL(appl)->nncci--;
561 nextpp = pp;
562 } else {
563 nextpp = &(*pp)->next;
566 APPL(appl)->releasing--;
567 if (APPL(appl)->releasing <= 0) {
568 APPL(appl)->signal = 0;
569 APPL_MARK_FREE(appl);
570 printk(KERN_INFO "kcapi: appl %d down\n", appl);
574 * ncci managment
577 static void controllercb_new_ncci(struct capi_ctr * card,
578 __u16 appl, __u32 ncci, __u32 winsize)
580 struct capi_ncci *np;
581 if (!VALID_APPLID(appl)) {
582 printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
583 return;
585 if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {
586 printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci);
587 return;
589 if (winsize > CAPI_MAXDATAWINDOW) {
590 printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",
591 winsize, CAPI_MAXDATAWINDOW);
592 winsize = CAPI_MAXDATAWINDOW;
594 np->applid = appl;
595 np->ncci = ncci;
596 np->winsize = winsize;
597 mq_init(np);
598 np->next = APPL(appl)->nccilist;
599 APPL(appl)->nccilist = np;
600 APPL(appl)->nncci++;
601 printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
605 static void controllercb_free_ncci(struct capi_ctr * card,
606 __u16 appl, __u32 ncci)
608 struct capi_ncci **pp;
609 if (!VALID_APPLID(appl)) {
610 printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);
611 return;
613 for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
614 if ((*pp)->ncci == ncci) {
615 struct capi_ncci *np = *pp;
616 *pp = np->next;
617 kfree(np);
618 APPL(appl)->nncci--;
619 printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
620 return;
623 printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci);
627 static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci)
629 struct capi_ncci *np;
630 for (np = app->nccilist; np; np = np->next) {
631 if (np->ncci == ncci)
632 return np;
634 return 0;
637 /* -------- Receiver ------------------------------------------ */
639 static void recv_handler(void *dummy)
641 struct sk_buff *skb;
643 while ((skb = skb_dequeue(&recv_queue)) != 0) {
644 __u16 appl = CAPIMSG_APPID(skb->data);
645 struct capi_ncci *np;
646 if (!VALID_APPLID(appl)) {
647 printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n",
648 appl, capi_message2str(skb->data));
649 kfree_skb(skb);
650 continue;
652 if (APPL(appl)->signal == 0) {
653 printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n",
654 appl);
655 kfree_skb(skb);
656 continue;
658 if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
659 && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
660 && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
661 && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
662 printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
663 CAPIMSG_MSGID(skb->data), np->ncci);
665 if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
666 && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
667 APPL(appl)->nrecvdatapkt++;
668 } else {
669 APPL(appl)->nrecvctlpkt++;
671 skb_queue_tail(&APPL(appl)->recv_queue, skb);
672 (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
676 static void controllercb_handle_capimsg(struct capi_ctr * card,
677 __u16 appl, struct sk_buff *skb)
679 int showctl = 0;
680 __u8 cmd, subcmd;
682 if (card->cardstate != CARD_RUNNING) {
683 printk(KERN_INFO "kcapi: controller %d not active, got: %s",
684 card->cnr, capi_message2str(skb->data));
685 goto error;
687 cmd = CAPIMSG_COMMAND(skb->data);
688 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
689 if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
690 card->nrecvdatapkt++;
691 if (card->traceflag > 2) showctl |= 2;
692 if (card->traceflag) showctl |= 2;
693 } else {
694 card->nrecvctlpkt++;
696 showctl |= (card->traceflag & 1);
697 if (showctl & 2) {
698 if (showctl & 1) {
699 printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",
700 (unsigned long) card->cnr,
701 CAPIMSG_APPID(skb->data),
702 capi_cmd2str(cmd, subcmd),
703 CAPIMSG_LEN(skb->data));
704 } else {
705 printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",
706 (unsigned long) card->cnr,
707 capi_message2str(skb->data));
711 skb_queue_tail(&recv_queue, skb);
712 queue_task(&tq_recv_notify, &tq_immediate);
713 mark_bh(IMMEDIATE_BH);
714 return;
716 error:
717 kfree_skb(skb);
720 /* -------- Notifier ------------------------------------------ */
722 static void notify_up(__u16 contr)
724 struct capi_interface_user *p;
726 printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
727 for (p = capi_users; p; p = p->next) {
728 if (!p->callback) continue;
729 (*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
733 static void notify_down(__u16 contr)
735 struct capi_interface_user *p;
736 printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
737 for (p = capi_users; p; p = p->next) {
738 if (!p->callback) continue;
739 (*p->callback) (KCI_CONTRDOWN, contr, 0);
743 static void notify_handler(void *dummy)
745 __u16 contr;
747 for (contr=1; VALID_CARD(contr); contr++)
748 if (test_and_clear_bit(contr, &notify_up_set))
749 notify_up(contr);
750 for (contr=1; VALID_CARD(contr); contr++)
751 if (test_and_clear_bit(contr, &notify_down_set))
752 notify_down(contr);
756 static void controllercb_ready(struct capi_ctr * card)
758 __u16 appl;
760 card->cardstate = CARD_RUNNING;
762 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
763 if (!VALID_APPLID(appl)) continue;
764 if (APPL(appl)->releasing) continue;
765 card->driver->register_appl(card, appl, &APPL(appl)->rparam);
768 set_bit(CARDNR(card), &notify_up_set);
769 queue_task(&tq_state_notify, &tq_scheduler);
771 printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
772 CARDNR(card), card->name);
775 static void controllercb_reseted(struct capi_ctr * card)
777 __u16 appl;
779 if (card->cardstate == CARD_FREE)
780 return;
781 if (card->cardstate == CARD_DETECTED)
782 return;
784 card->cardstate = CARD_DETECTED;
786 memset(card->manu, 0, sizeof(card->manu));
787 memset(&card->version, 0, sizeof(card->version));
788 memset(&card->profile, 0, sizeof(card->profile));
789 memset(card->serial, 0, sizeof(card->serial));
791 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
792 struct capi_ncci **pp, **nextpp;
793 for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
794 if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
795 struct capi_ncci *np = *pp;
796 *pp = np->next;
797 printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
798 kfree(np);
799 nextpp = pp;
800 } else {
801 nextpp = &(*pp)->next;
805 set_bit(CARDNR(card), &notify_down_set);
806 queue_task(&tq_state_notify, &tq_scheduler);
807 printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card));
810 static void controllercb_suspend_output(struct capi_ctr *card)
812 if (!card->blocked) {
813 printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card));
814 card->blocked = 1;
818 static void controllercb_resume_output(struct capi_ctr *card)
820 if (card->blocked) {
821 printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card));
822 card->blocked = 0;
826 /* ------------------------------------------------------------- */
829 struct capi_ctr *
830 drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata)
832 struct capi_ctr *card, **pp;
833 int i;
835 for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
837 if (i == CAPI_MAXCONTR) {
838 printk(KERN_ERR "kcapi: out of controller slots\n");
839 return 0;
841 card = &cards[i];
842 memset(card, 0, sizeof(struct capi_ctr));
843 card->driver = driver;
844 card->cnr = CARDNR(card);
845 strncpy(card->name, name, sizeof(card->name));
846 card->cardstate = CARD_DETECTED;
847 card->blocked = 0;
848 card->driverdata = driverdata;
849 card->traceflag = showcapimsgs;
851 card->ready = controllercb_ready;
852 card->reseted = controllercb_reseted;
853 card->suspend_output = controllercb_suspend_output;
854 card->resume_output = controllercb_resume_output;
855 card->handle_capimsg = controllercb_handle_capimsg;
856 card->appl_registered = controllercb_appl_registered;
857 card->appl_released = controllercb_appl_released;
858 card->new_ncci = controllercb_new_ncci;
859 card->free_ncci = controllercb_free_ncci;
861 for (pp = &driver->controller; *pp; pp = &(*pp)->next) ;
862 card->next = 0;
863 *pp = card;
864 driver->ncontroller++;
865 sprintf(card->procfn, "capi/controllers/%d", card->cnr);
866 card->procent = create_proc_entry(card->procfn, 0, 0);
867 if (card->procent) {
868 card->procent->read_proc =
869 (int (*)(char *,char **,off_t,int,int *,void *))
870 driver->ctr_read_proc;
871 card->procent->data = card;
874 ncards++;
875 printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",
876 card->cnr, card->name);
877 return card;
880 static int drivercb_detach_ctr(struct capi_ctr *card)
882 struct capi_driver *driver = card->driver;
883 struct capi_ctr **pp;
885 if (card->cardstate == CARD_FREE)
886 return 0;
887 if (card->cardstate != CARD_DETECTED)
888 controllercb_reseted(card);
889 for (pp = &driver->controller; *pp ; pp = &(*pp)->next) {
890 if (*pp == card) {
891 *pp = card->next;
892 driver->ncontroller--;
893 ncards--;
894 break;
897 if (card->procent) {
898 remove_proc_entry(card->procfn, 0);
899 card->procent = 0;
901 card->cardstate = CARD_FREE;
902 printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",
903 card->cnr, card->name);
904 return 0;
907 /* ------------------------------------------------------------- */
909 /* fallback if no driver read_proc function defined by driver */
911 static int driver_read_proc(char *page, char **start, off_t off,
912 int count, int *eof, void *data)
914 struct capi_driver *driver = (struct capi_driver *)data;
915 int len = 0;
917 len += sprintf(page+len, "%-16s %s\n", "name", driver->name);
918 len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision);
920 if (len < off)
921 return 0;
922 *eof = 1;
923 *start = page - off;
924 return ((count < len-off) ? count : len-off);
927 /* ------------------------------------------------------------- */
929 static struct capi_driver_interface di = {
930 drivercb_attach_ctr,
931 drivercb_detach_ctr,
934 struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
936 struct capi_driver **pp;
938 for (pp = &drivers; *pp; pp = &(*pp)->next) ;
939 driver->next = 0;
940 *pp = driver;
941 printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
942 #ifdef CONFIG_AVMB1_COMPAT
943 if (strcmp(driver->name, "b1isa") == 0 && driver->add_card)
944 b1isa_driver = driver;
945 if (strcmp(driver->name, "t1isa") == 0 && driver->add_card)
946 t1isa_driver = driver;
947 #endif
948 sprintf(driver->procfn, "capi/drivers/%s", driver->name);
949 driver->procent = create_proc_entry(driver->procfn, 0, 0);
950 if (driver->procent) {
951 if (driver->driver_read_proc) {
952 driver->procent->read_proc =
953 (int (*)(char *,char **,off_t,int,int *,void *))
954 driver->driver_read_proc;
955 } else {
956 driver->procent->read_proc = driver_read_proc;
958 driver->procent->data = driver;
960 return &di;
963 void detach_capi_driver(struct capi_driver *driver)
965 struct capi_driver **pp;
966 for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
967 if (*pp) {
968 *pp = (*pp)->next;
969 #ifdef CONFIG_AVMB1_COMPAT
970 if (driver == b1isa_driver) b1isa_driver = 0;
971 if (driver == t1isa_driver) t1isa_driver = 0;
972 #endif
973 printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);
974 } else {
975 printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
977 if (driver->procent) {
978 remove_proc_entry(driver->procfn, 0);
979 driver->procent = 0;
983 /* ------------------------------------------------------------- */
984 /* -------- CAPI2.0 Interface ---------------------------------- */
985 /* ------------------------------------------------------------- */
987 static int capi_installed(void)
989 int i;
990 for (i = 0; i < CAPI_MAXCONTR; i++) {
991 if (cards[i].cardstate == CARD_RUNNING)
992 return 1;
994 return 0;
997 static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
999 int appl;
1000 int i;
1002 if (rparam->datablklen < 128)
1003 return CAPI_LOGBLKSIZETOSMALL;
1005 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
1006 if (APPL_IS_FREE(appl))
1007 break;
1009 if (appl > CAPI_MAXAPPL)
1010 return CAPI_TOOMANYAPPLS;
1012 APPL_MARK_USED(appl);
1013 skb_queue_head_init(&APPL(appl)->recv_queue);
1014 APPL(appl)->nncci = 0;
1016 memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
1018 for (i = 0; i < CAPI_MAXCONTR; i++) {
1019 if (cards[i].cardstate != CARD_RUNNING)
1020 continue;
1021 cards[i].driver->register_appl(&cards[i], appl,
1022 &APPL(appl)->rparam);
1024 *applidp = appl;
1025 printk(KERN_INFO "kcapi: appl %d up\n", appl);
1027 return CAPI_NOERROR;
1030 static __u16 capi_release(__u16 applid)
1032 struct sk_buff *skb;
1033 int i;
1035 if (!VALID_APPLID(applid) || APPL(applid)->releasing)
1036 return CAPI_ILLAPPNR;
1037 while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
1038 kfree_skb(skb);
1039 for (i = 0; i < CAPI_MAXCONTR; i++) {
1040 if (cards[i].cardstate != CARD_RUNNING)
1041 continue;
1042 APPL(applid)->releasing++;
1043 cards[i].driver->release_appl(&cards[i], applid);
1045 if (APPL(applid)->releasing <= 0) {
1046 APPL(applid)->signal = 0;
1047 APPL_MARK_FREE(applid);
1048 printk(KERN_INFO "kcapi: appl %d down\n", applid);
1050 return CAPI_NOERROR;
1053 static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
1055 struct capi_ncci *np;
1056 int contr;
1057 int showctl = 0;
1058 __u8 cmd, subcmd;
1060 if (ncards == 0)
1061 return CAPI_REGNOTINSTALLED;
1062 if (!VALID_APPLID(applid))
1063 return CAPI_ILLAPPNR;
1064 if (skb->len < 12
1065 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
1066 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
1067 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
1068 contr = CAPIMSG_CONTROLLER(skb->data);
1069 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
1070 contr = 1;
1071 if (CARD(contr)->cardstate != CARD_RUNNING)
1072 return CAPI_REGNOTINSTALLED;
1074 if (CARD(contr)->blocked)
1075 return CAPI_SENDQUEUEFULL;
1077 cmd = CAPIMSG_COMMAND(skb->data);
1078 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
1080 if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
1081 if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
1082 && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
1083 return CAPI_SENDQUEUEFULL;
1084 CARD(contr)->nsentdatapkt++;
1085 APPL(applid)->nsentdatapkt++;
1086 if (CARD(contr)->traceflag > 2) showctl |= 2;
1087 } else {
1088 CARD(contr)->nsentctlpkt++;
1089 APPL(applid)->nsentctlpkt++;
1090 if (CARD(contr)->traceflag) showctl |= 2;
1092 showctl |= (CARD(contr)->traceflag & 1);
1093 if (showctl & 2) {
1094 if (showctl & 1) {
1095 printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n",
1096 (unsigned long) contr,
1097 CAPIMSG_APPID(skb->data),
1098 capi_cmd2str(cmd, subcmd),
1099 CAPIMSG_LEN(skb->data));
1100 } else {
1101 printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n",
1102 (unsigned long) contr,
1103 capi_message2str(skb->data));
1107 CARD(contr)->driver->send_message(CARD(contr), skb);
1108 return CAPI_NOERROR;
1111 static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
1113 struct sk_buff *skb;
1115 if (!VALID_APPLID(applid))
1116 return CAPI_ILLAPPNR;
1117 if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
1118 return CAPI_RECEIVEQUEUEEMPTY;
1119 *msgp = skb;
1120 return CAPI_NOERROR;
1123 static __u16 capi_set_signal(__u16 applid,
1124 void (*signal) (__u16 applid, __u32 param),
1125 __u32 param)
1127 if (!VALID_APPLID(applid))
1128 return CAPI_ILLAPPNR;
1129 APPL(applid)->signal = signal;
1130 APPL(applid)->param = param;
1131 return CAPI_NOERROR;
1134 static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
1136 if (contr == 0) {
1137 strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
1138 return CAPI_NOERROR;
1140 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
1141 return 0x2002;
1143 strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN);
1144 return CAPI_NOERROR;
1147 static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
1149 if (contr == 0) {
1150 *verp = driver_version;
1151 return CAPI_NOERROR;
1153 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
1154 return 0x2002;
1156 memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version));
1157 return CAPI_NOERROR;
1160 static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
1162 if (contr == 0) {
1163 strncpy(serial, driver_serial, CAPI_SERIAL_LEN);
1164 return CAPI_NOERROR;
1166 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
1167 return 0x2002;
1169 strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN);
1170 return CAPI_NOERROR;
1173 static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
1175 if (contr == 0) {
1176 profp->ncontroller = ncards;
1177 return CAPI_NOERROR;
1179 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
1180 return 0x2002;
1182 memcpy((void *) profp, &CARD(contr)->profile,
1183 sizeof(struct capi_profile));
1184 return CAPI_NOERROR;
1187 #ifdef CONFIG_AVMB1_COMPAT
1188 static int old_capi_manufacturer(unsigned int cmd, void *data)
1190 avmb1_loadandconfigdef ldef;
1191 avmb1_extcarddef cdef;
1192 avmb1_resetdef rdef;
1193 avmb1_getdef gdef;
1194 struct capi_driver *driver;
1195 struct capi_ctr *card;
1196 capicardparams cparams;
1197 capiloaddata ldata;
1198 int retval;
1200 switch (cmd) {
1201 case AVMB1_ADDCARD:
1202 case AVMB1_ADDCARD_WITH_TYPE:
1203 if (cmd == AVMB1_ADDCARD) {
1204 if ((retval = copy_from_user((void *) &cdef, data,
1205 sizeof(avmb1_carddef))))
1206 return retval;
1207 cdef.cardtype = AVM_CARDTYPE_B1;
1208 } else {
1209 if ((retval = copy_from_user((void *) &cdef, data,
1210 sizeof(avmb1_extcarddef))))
1211 return retval;
1213 cparams.port = cdef.port;
1214 cparams.irq = cdef.irq;
1215 cparams.cardnr = cdef.cardnr;
1217 switch (cdef.cardtype) {
1218 case AVM_CARDTYPE_B1: driver = b1isa_driver; break;
1219 case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
1220 default: driver = 0;
1222 if (!driver || !driver->add_card) {
1223 return -EIO;
1226 return driver->add_card(driver, &cparams);
1228 case AVMB1_LOAD:
1229 case AVMB1_LOAD_AND_CONFIG:
1231 if (cmd == AVMB1_LOAD) {
1232 if ((retval = copy_from_user((void *) &ldef, data,
1233 sizeof(avmb1_loaddef))))
1234 return retval;
1235 ldef.t4config.len = 0;
1236 ldef.t4config.data = 0;
1237 } else {
1238 if ((retval = copy_from_user((void *) &ldef, data,
1239 sizeof(avmb1_loadandconfigdef))))
1240 return retval;
1242 if (!VALID_CARD(ldef.contr))
1243 return -ESRCH;
1245 card = CARD(ldef.contr);
1246 if (card->cardstate == CARD_FREE)
1247 return -ESRCH;
1249 if (ldef.t4file.len <= 0) {
1250 printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
1251 return -EINVAL;
1253 if (ldef.t4file.data == 0) {
1254 printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
1255 return -EINVAL;
1258 ldata.firmware.user = 1;
1259 ldata.firmware.data = ldef.t4file.data;
1260 ldata.firmware.len = ldef.t4file.len;
1261 ldata.configuration.user = 1;
1262 ldata.configuration.data = ldef.t4config.data;
1263 ldata.configuration.len = ldef.t4config.len;
1265 if (card->cardstate != CARD_DETECTED) {
1266 printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
1267 return -EBUSY;
1269 card->cardstate = CARD_LOADING;
1271 retval = card->driver->load_firmware(card, &ldata);
1273 if (retval) {
1274 card->cardstate = CARD_DETECTED;
1275 return retval;
1278 while (card->cardstate != CARD_RUNNING) {
1280 current->state = TASK_INTERRUPTIBLE;
1281 schedule_timeout(HZ/10); /* 0.1 sec */
1283 if (signal_pending(current))
1284 return -EINTR;
1286 return 0;
1288 case AVMB1_RESETCARD:
1289 if ((retval = copy_from_user((void *) &rdef, data,
1290 sizeof(avmb1_resetdef))))
1291 return retval;
1292 if (!VALID_CARD(rdef.contr))
1293 return -ESRCH;
1294 card = CARD(rdef.contr);
1296 if (card->cardstate == CARD_FREE)
1297 return -ESRCH;
1298 if (card->cardstate == CARD_DETECTED)
1299 return 0;
1301 card->driver->reset_ctr(card);
1303 while (card->cardstate > CARD_DETECTED) {
1305 current->state = TASK_INTERRUPTIBLE;
1306 schedule_timeout(HZ/10); /* 0.1 sec */
1308 if (signal_pending(current))
1309 return -EINTR;
1311 return 0;
1313 case AVMB1_GET_CARDINFO:
1314 if ((retval = copy_from_user((void *) &gdef, data,
1315 sizeof(avmb1_getdef))))
1316 return retval;
1318 if (!VALID_CARD(gdef.contr))
1319 return -ESRCH;
1321 card = CARD(gdef.contr);
1323 if (card->cardstate == CARD_FREE)
1324 return -ESRCH;
1326 gdef.cardstate = card->cardstate;
1327 if (card->driver == b1isa_driver)
1328 gdef.cardtype = AVM_CARDTYPE_B1;
1329 else if (card->driver == t1isa_driver)
1330 gdef.cardtype = AVM_CARDTYPE_T1;
1331 else gdef.cardtype = AVM_CARDTYPE_B1;
1333 if ((retval = copy_to_user(data, (void *) &gdef,
1334 sizeof(avmb1_getdef))))
1335 return retval;
1337 return 0;
1339 case AVMB1_REMOVECARD:
1340 if ((retval = copy_from_user((void *) &rdef, data,
1341 sizeof(avmb1_resetdef))))
1342 return retval;
1344 if (!VALID_CARD(rdef.contr))
1345 return -ESRCH;
1346 card = CARD(rdef.contr);
1348 if (card->cardstate == CARD_FREE)
1349 return -ESRCH;
1351 if (card->cardstate != CARD_DETECTED)
1352 return -EBUSY;
1354 card->driver->remove_ctr(card);
1356 while (card->cardstate != CARD_FREE) {
1358 current->state = TASK_INTERRUPTIBLE;
1359 schedule_timeout(HZ/10); /* 0.1 sec */
1361 if (signal_pending(current))
1362 return -EINTR;
1364 return 0;
1366 return -EINVAL;
1368 #endif
1370 static int capi_manufacturer(unsigned int cmd, void *data)
1372 struct capi_ctr *card;
1373 kcapi_flagdef fdef;
1374 int retval;
1376 switch (cmd) {
1377 #ifdef CONFIG_AVMB1_COMPAT
1378 case AVMB1_ADDCARD:
1379 case AVMB1_ADDCARD_WITH_TYPE:
1380 case AVMB1_LOAD:
1381 case AVMB1_LOAD_AND_CONFIG:
1382 case AVMB1_RESETCARD:
1383 case AVMB1_GET_CARDINFO:
1384 case AVMB1_REMOVECARD:
1385 return old_capi_manufacturer(cmd, data);
1386 #endif
1387 case KCAPI_CMD_TRACE:
1388 if ((retval = copy_from_user((void *) &fdef, data,
1389 sizeof(kcapi_flagdef))))
1390 return retval;
1392 if (!VALID_CARD(fdef.contr))
1393 return -ESRCH;
1394 card = CARD(fdef.contr);
1395 if (card->cardstate == CARD_FREE)
1396 return -ESRCH;
1397 card->traceflag = fdef.flag;
1398 printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
1399 card->cnr, card->traceflag);
1400 return 0;
1402 return -EINVAL;
1405 struct capi_interface avmb1_interface =
1407 capi_installed,
1408 capi_register,
1409 capi_release,
1410 capi_put_message,
1411 capi_get_message,
1412 capi_set_signal,
1413 capi_get_manufacturer,
1414 capi_get_version,
1415 capi_get_serial,
1416 capi_get_profile,
1417 capi_manufacturer
1420 /* ------------------------------------------------------------- */
1421 /* -------- Exported Functions --------------------------------- */
1422 /* ------------------------------------------------------------- */
1424 struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
1426 struct capi_interface_user *p;
1428 for (p = capi_users; p; p = p->next) {
1429 if (p == userp) {
1430 printk(KERN_ERR "kcapi: double attach from %s\n",
1431 userp->name);
1432 return 0;
1435 userp->next = capi_users;
1436 capi_users = userp;
1437 MOD_INC_USE_COUNT;
1438 printk(KERN_NOTICE "kcapi: %s attached\n", userp->name);
1440 return &avmb1_interface;
1443 int detach_capi_interface(struct capi_interface_user *userp)
1445 struct capi_interface_user **pp;
1447 for (pp = &capi_users; *pp; pp = &(*pp)->next) {
1448 if (*pp == userp) {
1449 *pp = userp->next;
1450 userp->next = 0;
1451 MOD_DEC_USE_COUNT;
1452 printk(KERN_NOTICE "kcapi: %s detached\n", userp->name);
1453 return 0;
1456 printk(KERN_ERR "kcapi: double detach from %s\n", userp->name);
1457 return -1;
1460 /* ------------------------------------------------------------- */
1461 /* -------- Init & Cleanup ------------------------------------- */
1462 /* ------------------------------------------------------------- */
1464 EXPORT_SYMBOL(attach_capi_interface);
1465 EXPORT_SYMBOL(detach_capi_interface);
1466 EXPORT_SYMBOL(attach_capi_driver);
1467 EXPORT_SYMBOL(detach_capi_driver);
1469 #ifndef MODULE
1470 #ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
1471 extern int b1isa_init(void);
1472 #endif
1473 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
1474 extern int b1pci_init(void);
1475 #endif
1476 #ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
1477 extern int t1isa_init(void);
1478 #endif
1479 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
1480 extern int b1pcmcia_init(void);
1481 #endif
1482 #endif
1485 * init / exit functions
1488 #ifdef MODULE
1489 #define kcapi_init init_module
1490 #endif
1492 int kcapi_init(void)
1494 char *p;
1495 char rev[10];
1497 skb_queue_head_init(&recv_queue);
1498 /* init_bh(CAPI_BH, do_capi_bh); */
1500 tq_state_notify.routine = notify_handler;
1501 tq_state_notify.data = 0;
1503 tq_recv_notify.routine = recv_handler;
1504 tq_recv_notify.data = 0;
1506 proc_capi_init();
1508 if ((p = strchr(revision, ':'))) {
1509 strcpy(rev, p + 1);
1510 p = strchr(rev, '$');
1511 *p = 0;
1512 } else
1513 strcpy(rev, "1.0");
1515 #ifdef MODULE
1516 printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
1517 #else
1518 printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev);
1519 #ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
1520 (void)b1isa_init();
1521 #endif
1522 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
1523 (void)b1pci_init();
1524 #endif
1525 #ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
1526 (void)t1isa_init();
1527 #endif
1528 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
1529 (void)b1pcmcia_init();
1530 #endif
1531 #endif
1532 return 0;
1535 #ifdef MODULE
1536 void cleanup_module(void)
1538 char rev[10];
1539 char *p;
1541 if ((p = strchr(revision, ':'))) {
1542 strcpy(rev, p + 1);
1543 p = strchr(rev, '$');
1544 *p = 0;
1545 } else {
1546 strcpy(rev, "1.0");
1549 schedule(); /* execute queued tasks .... */
1550 proc_capi_exit();
1551 printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
1553 #endif