* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / isdn / avmb1 / b1capi.c
blobea4aeb369ebf6c9d11ca8bcdf5ea8bf3486c0faf
1 /*
2 * $Id: b1capi.c,v 1.14 1999/04/15 19:49:29 calle 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: b1capi.c,v $
9 * Revision 1.14 1999/04/15 19:49:29 calle
10 * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
12 * Revision 1.13 1999/01/05 18:29:31 he
13 * merged remaining schedule_timeout() changes from 2.1.127
15 * Revision 1.12 1998/10/25 14:38:58 fritz
16 * Backported from MIPS (Cobalt).
18 * Revision 1.11 1998/03/29 16:05:58 calle
19 * changes from 2.0 tree merged.
21 * Revision 1.4.2.18 1998/03/20 20:34:37 calle
22 * port valid check now only for T1, because of the PCI and PCMCIA cards.
24 * Revision 1.4.2.17 1998/03/20 14:38:17 calle
25 * capidrv: prepared state machines for suspend/resume/hold
26 * capidrv: fix bug in state machine if B1/T1 is out of nccis
27 * b1capi: changed some errno returns.
28 * b1capi: detect if you try to add same T1 to different io address.
29 * b1capi: change number of nccis depending on number of channels.
30 * b1lli: cosmetics
32 * Revision 1.4.2.16 1998/03/20 09:01:08 calle
33 * Changes capi_register handling to get full support for 30 bchannels.
35 * Revision 1.4.2.15 1998/03/18 17:43:26 calle
36 * T1 with fastlink, bugfix for multicontroller support in capidrv.c
38 * Revision 1.4.2.14 1998/03/04 17:33:47 calle
39 * Changes for T1.
41 * Revision 1.4.2.13 1998/02/27 15:40:41 calle
42 * T1 running with slow link. bugfix in capi_release.
44 * Revision 1.4.2.12 1998/02/24 17:58:25 calle
45 * changes for T1.
47 * Revision 1.10 1998/02/13 07:09:10 calle
48 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
50 * Revision 1.9 1998/01/31 11:14:39 calle
51 * merged changes to 2.0 tree, prepare 2.1.82 to work.
53 * Revision 1.8 1997/12/10 20:00:46 calle
54 * get changes from 2.0 version
56 * Revision 1.4.2.5 1997/12/07 19:59:54 calle
57 * more changes for M1/T1/B1 + config
59 * Revision 1.4.2.4 1997/11/26 16:57:20 calle
60 * more changes for B1/M1/T1.
62 * Revision 1.7 1997/10/19 14:45:40 calle
63 * fixed capi_get_version.
65 * Revision 1.6 1997/10/01 09:21:09 fritz
66 * Removed old compatibility stuff for 2.0.X kernels.
67 * From now on, this code is for 2.1.X ONLY!
68 * Old stuff is still in the separate branch.
70 * Revision 1.5 1997/07/12 08:22:26 calle
71 * Correct bug in CARD_NR macro, so now more than one card will work.
72 * Allow card reset, even if card is in running state.
75 * Revision 1.4 1997/05/27 15:17:45 fritz
76 * Added changes for recent 2.1.x kernels:
77 * changed return type of isdn_close
78 * queue_task_* -> queue_task
79 * clear/set_bit -> test_and_... where apropriate.
80 * changed type of hard_header_cache parameter.
82 * Revision 1.3 1997/05/18 09:24:09 calle
83 * added verbose disconnect reason reporting to avmb1.
84 * some fixes in capi20 interface.
85 * changed info messages for B1-PCI
87 * Revision 1.2 1997/03/05 21:20:41 fritz
88 * Removed include of config.h (mkdep stated this is unneded).
90 * Revision 1.1 1997/03/04 21:50:27 calle
91 * Frirst version in isdn4linux
93 * Revision 2.2 1997/02/12 09:31:39 calle
94 * new version
96 * Revision 1.1 1997/01/31 10:32:20 calle
97 * Initial revision
102 #include <linux/module.h>
103 #include <linux/kernel.h>
104 #include <linux/mm.h>
105 #include <linux/interrupt.h>
106 #include <linux/ioport.h>
107 #include <asm/segment.h>
108 #include <linux/skbuff.h>
109 #include <linux/tqueue.h>
110 #include <linux/capi.h>
111 #include <linux/b1lli.h>
112 #include <linux/kernelcapi.h>
113 #include "compat.h"
114 #include "capicmd.h"
115 #include "capiutil.h"
117 static char *revision = "$Revision: 1.14 $";
119 /* ------------------------------------------------------------- */
121 int showcapimsgs = 0; /* used in lli.c */
122 int loaddebug = 0;
124 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
125 MODULE_PARM(showcapimsgs, "0-5i");
126 MODULE_PARM(loaddebug, "0-1i");
128 /* ------------------------------------------------------------- */
130 struct msgidqueue {
131 struct msgidqueue *next;
132 __u16 msgid;
135 typedef struct avmb1_ncci {
136 struct avmb1_ncci *next;
137 __u16 applid;
138 __u32 ncci;
139 __u32 winsize;
140 struct msgidqueue *msgidqueue;
141 struct msgidqueue *msgidlast;
142 struct msgidqueue *msgidfree;
143 struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
144 } avmb1_ncci;
146 typedef struct avmb1_appl {
147 __u16 applid;
148 capi_register_params rparam;
149 int releasing;
150 __u32 param;
151 void (*signal) (__u16 applid, __u32 param);
152 struct sk_buff_head recv_queue;
153 struct avmb1_ncci *nccilist;
154 } avmb1_appl;
156 /* ------------------------------------------------------------- */
158 static struct capi_version driver_version = {2, 0, 1, 1<<4};
159 static char driver_serial[CAPI_SERIAL_LEN] = "4711";
160 static char capi_manufakturer[64] = "AVM Berlin";
162 #define APPL(a) (&applications[(a)-1])
163 #define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
164 #define APPL_IS_FREE(a) (APPL(a)->applid == 0)
165 #define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
166 #define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
168 #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
170 #define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR)
171 #define CARD(c) (&cards[(c)-1])
172 #define CARDNR(cp) (((cp)-cards)+1)
174 static avmb1_appl applications[CAPI_MAXAPPL];
175 static avmb1_card cards[CAPI_MAXCONTR];
176 static int ncards = 0;
177 static struct sk_buff_head recv_queue;
178 static struct capi_interface_user *capi_users = 0;
179 static long notify_up_set = 0;
180 static long notify_down_set = 0;
182 static struct tq_struct tq_state_notify;
183 static struct tq_struct tq_recv_notify;
185 /* -------- util functions ------------------------------------ */
187 static char *cardtype2str(int cardtype)
189 switch (cardtype) {
190 default:
191 case AVM_CARDTYPE_B1: return "B1-ISA";
192 case AVM_CARDTYPE_B1PCI: return "B1-PCI";
193 case AVM_CARDTYPE_M1: return "M1";
194 case AVM_CARDTYPE_M2: return "M2";
195 case AVM_CARDTYPE_T1: return "T1";
199 static inline int capi_cmd_valid(__u8 cmd)
201 switch (cmd) {
202 case CAPI_ALERT:
203 case CAPI_CONNECT:
204 case CAPI_CONNECT_ACTIVE:
205 case CAPI_CONNECT_B3_ACTIVE:
206 case CAPI_CONNECT_B3:
207 case CAPI_CONNECT_B3_T90_ACTIVE:
208 case CAPI_DATA_B3:
209 case CAPI_DISCONNECT_B3:
210 case CAPI_DISCONNECT:
211 case CAPI_FACILITY:
212 case CAPI_INFO:
213 case CAPI_LISTEN:
214 case CAPI_MANUFACTURER:
215 case CAPI_RESET_B3:
216 case CAPI_SELECT_B_PROTOCOL:
217 return 1;
219 return 0;
222 static inline int capi_subcmd_valid(__u8 subcmd)
224 switch (subcmd) {
225 case CAPI_REQ:
226 case CAPI_CONF:
227 case CAPI_IND:
228 case CAPI_RESP:
229 return 1;
231 return 0;
234 /* -------- NCCI Handling ------------------------------------- */
236 static inline void mq_init(avmb1_ncci * np)
238 int i;
239 np->msgidqueue = 0;
240 np->msgidlast = 0;
241 memset(np->msgidpool, 0, sizeof(np->msgidpool));
242 np->msgidfree = &np->msgidpool[0];
243 for (i = 1; i < np->winsize; i++) {
244 np->msgidpool[i].next = np->msgidfree;
245 np->msgidfree = &np->msgidpool[i];
249 static inline int mq_enqueue(avmb1_ncci * np, __u16 msgid)
251 struct msgidqueue *mq;
252 if ((mq = np->msgidfree) == 0)
253 return 0;
254 np->msgidfree = mq->next;
255 mq->msgid = msgid;
256 mq->next = 0;
257 if (np->msgidlast)
258 np->msgidlast->next = mq;
259 np->msgidlast = mq;
260 if (!np->msgidqueue)
261 np->msgidqueue = mq;
262 return 1;
265 static inline int mq_dequeue(avmb1_ncci * np, __u16 msgid)
267 struct msgidqueue **pp;
268 for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
269 if ((*pp)->msgid == msgid) {
270 struct msgidqueue *mq = *pp;
271 *pp = mq->next;
272 if (mq == np->msgidlast)
273 np->msgidlast = 0;
274 mq->next = np->msgidfree;
275 np->msgidfree = mq;
276 return 1;
279 return 0;
282 void avmb1_handle_new_ncci(avmb1_card * card,
283 __u16 appl, __u32 ncci, __u32 winsize)
285 avmb1_ncci *np;
286 if (!VALID_APPLID(appl)) {
287 printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
288 return;
290 if ((np = (avmb1_ncci *) kmalloc(sizeof(avmb1_ncci), GFP_ATOMIC)) == 0) {
291 printk(KERN_ERR "avmb1_handle_new_ncci: alloc failed ncci 0x%x\n", ncci);
292 return;
294 if (winsize > CAPI_MAXDATAWINDOW) {
295 printk(KERN_ERR "avmb1_handle_new_ncci: winsize %d too big, set to %d\n",
296 winsize, CAPI_MAXDATAWINDOW);
297 winsize = CAPI_MAXDATAWINDOW;
299 np->applid = appl;
300 np->ncci = ncci;
301 np->winsize = winsize;
302 mq_init(np);
303 np->next = APPL(appl)->nccilist;
304 APPL(appl)->nccilist = np;
305 printk(KERN_INFO "b1capi: appl %d ncci 0x%x up\n", appl, ncci);
309 void avmb1_handle_free_ncci(avmb1_card * card,
310 __u16 appl, __u32 ncci)
312 if (!VALID_APPLID(appl)) {
313 printk(KERN_ERR "avmb1_handle_free_ncci: illegal appl %d\n", appl);
314 return;
316 if (ncci != 0xffffffff) {
317 avmb1_ncci **pp;
318 for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
319 if ((*pp)->ncci == ncci) {
320 avmb1_ncci *np = *pp;
321 *pp = np->next;
322 kfree(np);
323 printk(KERN_INFO "b1capi: appl %d ncci 0x%x down\n", appl, ncci);
324 return;
327 printk(KERN_ERR "avmb1_handle_free_ncci: ncci 0x%x not found\n", ncci);
328 } else {
329 avmb1_ncci **pp, **nextpp;
330 for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
331 if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
332 avmb1_ncci *np = *pp;
333 *pp = np->next;
334 printk(KERN_INFO "b1capi: appl %d ncci 0x%x down!\n", appl, np->ncci);
335 kfree(np);
336 nextpp = pp;
337 } else {
338 nextpp = &(*pp)->next;
341 APPL(appl)->releasing--;
342 if (APPL(appl)->releasing <= 0) {
343 APPL(appl)->signal = 0;
344 APPL_MARK_FREE(appl);
345 printk(KERN_INFO "b1capi: appl %d down\n", appl);
350 static avmb1_ncci *find_ncci(avmb1_appl * app, __u32 ncci)
352 avmb1_ncci *np;
353 for (np = app->nccilist; np; np = np->next) {
354 if (np->ncci == ncci)
355 return np;
357 return 0;
362 /* -------- Receiver ------------------------------------------ */
365 static void recv_handler(void *dummy)
367 struct sk_buff *skb;
369 while ((skb = skb_dequeue(&recv_queue)) != 0) {
370 __u16 appl = CAPIMSG_APPID(skb->data);
371 struct avmb1_ncci *np;
372 if (!VALID_APPLID(appl)) {
373 printk(KERN_ERR "b1capi: recv_handler: applid %d ? (%s)\n",
374 appl, capi_message2str(skb->data));
375 kfree_skb(skb);
376 continue;
378 if (APPL(appl)->signal == 0) {
379 printk(KERN_ERR "b1capi: recv_handler: applid %d has no signal function\n",
380 appl);
381 kfree_skb(skb);
382 continue;
384 if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
385 && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
386 && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
387 && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
388 printk(KERN_ERR "b1capi: msgid %hu ncci 0x%x not on queue\n",
389 CAPIMSG_MSGID(skb->data), np->ncci);
391 skb_queue_tail(&APPL(appl)->recv_queue, skb);
392 (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
397 void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb)
399 if (card->cardstate != CARD_RUNNING) {
400 printk(KERN_INFO "b1capi: controller %d not active, got: %s",
401 card->cnr, capi_message2str(skb->data));
402 goto error;
403 return;
405 skb_queue_tail(&recv_queue, skb);
406 queue_task(&tq_recv_notify, &tq_immediate);
407 mark_bh(IMMEDIATE_BH);
408 return;
410 error:
411 kfree_skb(skb);
414 void avmb1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
416 avmb1_card *card;
418 card = (avmb1_card *) devptr;
420 if (!card) {
421 printk(KERN_WARNING "avmb1_interrupt: wrong device\n");
422 return;
424 if (card->interrupt) {
425 printk(KERN_ERR "avmb1_interrupt: reentering interrupt hander\n");
426 return;
429 card->interrupt = 1;
431 B1_handle_interrupt(card);
433 card->interrupt = 0;
436 /* -------- Notifier ------------------------------------------ */
438 static void notify_up(__u16 contr)
440 struct capi_interface_user *p;
442 printk(KERN_NOTICE "b1capi: notify up contr %d\n", contr);
443 for (p = capi_users; p; p = p->next) {
444 if (p->callback)
445 (*p->callback) (KCI_CONTRUP, contr,
446 (capi_profile *)
447 CARD(contr)->version[VER_PROFILE]);
451 static void notify_down(__u16 contr)
453 struct capi_interface_user *p;
454 printk(KERN_NOTICE "b1capi: notify down contr %d\n", contr);
455 for (p = capi_users; p; p = p->next) {
456 if (p->callback)
457 (*p->callback) (KCI_CONTRDOWN, contr, 0);
461 static void notify_handler(void *dummy)
463 __u16 contr;
465 for (contr=1; VALID_CARD(contr); contr++)
466 if (test_and_clear_bit(contr, &notify_up_set))
467 notify_up(contr);
468 for (contr=1; VALID_CARD(contr); contr++)
469 if (test_and_clear_bit(contr, &notify_down_set))
470 notify_down(contr);
473 /* -------- card ready callback ------------------------------- */
476 void avmb1_card_ready(avmb1_card * card)
478 struct capi_profile *profp =
479 (struct capi_profile *)card->version[VER_PROFILE];
480 char *dversion = card->version[VER_DRIVER];
481 __u16 appl;
482 char *cardname, cname[20];
483 __u32 flag;
484 int nbchan = profp->nbchannel;
486 card->cversion.majorversion = 2;
487 card->cversion.minorversion = 0;
488 card->cversion.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
489 card->cversion.majormanuversion |= ((dversion[2] - '0') & 0xf);
490 card->cversion.minormanuversion = (dversion[3] - '0') << 4;
491 card->cversion.minormanuversion |=
492 (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
493 card->cardstate = CARD_RUNNING;
495 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
496 if (VALID_APPLID(appl) && !APPL(appl)->releasing) {
497 int nconn, want = APPL(appl)->rparam.level3cnt;
499 if (want > 0) nconn = want;
500 else nconn = nbchan * -want;
501 if (nconn == 0) nconn = nbchan;
503 B1_send_register(card->port, appl,
504 1024 * (nconn+1), nconn,
505 APPL(appl)->rparam.datablkcnt,
506 APPL(appl)->rparam.datablklen);
510 set_bit(CARDNR(card), &notify_up_set);
511 queue_task(&tq_state_notify, &tq_scheduler);
513 flag = ((__u8 *)(profp->manu))[1];
514 switch (flag) {
515 case 0: cardname = cardtype2str(card->cardtype); break;
516 case 3: cardname = "PCMCIA B"; break;
517 case 4: cardname = "PCMCIA M1"; break;
518 case 5: cardname = "PCMCIA M2"; break;
519 case 6: cardname = "B1 V3.0"; break;
520 case 7: cardname = "B1 PCI"; break;
521 default: cardname = cname; break;
522 sprintf(cname, "AVM?%u", (unsigned int)flag);
523 break;
525 printk(KERN_NOTICE "b1capi: card %d \"%s\" ready.\n",
526 CARDNR(card), cardname);
527 flag = ((__u8 *)(profp->manu))[3];
528 if (flag)
529 printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
530 CARDNR(card),
531 (flag & 0x01) ? " DSS1" : "",
532 (flag & 0x02) ? " CT1" : "",
533 (flag & 0x04) ? " VN3" : "",
534 (flag & 0x08) ? " NI1" : "",
535 (flag & 0x10) ? " AUSTEL" : "",
536 (flag & 0x20) ? " ESS" : "",
537 (flag & 0x40) ? " 1TR6" : ""
539 flag = ((__u8 *)(profp->manu))[5];
540 if (flag)
541 printk(KERN_NOTICE "b1capi: card %d Linetype:%s%s%s%s\n",
542 CARDNR(card),
543 (flag & 0x01) ? " point to point" : "",
544 (flag & 0x02) ? " point to multipoint" : "",
545 (flag & 0x08) ? " leased line without D-channel" : "",
546 (flag & 0x04) ? " leased line with D-channel" : ""
550 static void avmb1_card_down(avmb1_card * card, int notify)
552 __u16 appl;
554 card->cardstate = CARD_DETECTED;
556 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
557 avmb1_ncci **pp, **nextpp;
558 for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
559 if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
560 avmb1_ncci *np = *pp;
561 *pp = np->next;
562 printk(KERN_INFO "b1capi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
563 kfree(np);
564 nextpp = pp;
565 } else {
566 nextpp = &(*pp)->next;
570 set_bit(CARDNR(card), &notify_down_set);
571 queue_task(&tq_state_notify, &tq_scheduler);
572 printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card));
575 /* ------------------------------------------------------------- */
578 int avmb1_registercard(int port, int irq, int cardtype, int allocio)
580 struct avmb1_card *card;
581 int irqval,i;
584 for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
586 if (i == CAPI_MAXCONTR) {
587 printk(KERN_ERR "b1capi: out of controller slots\n");
588 return -ENFILE;
591 card = &cards[i];
592 memset(card, 0, sizeof(avmb1_card));
593 sprintf(card->name, "avmb1-%d", CARDNR(card));
595 if (allocio)
596 request_region(port, AVMB1_PORTLEN, card->name);
598 if ((irqval = request_irq(irq, avmb1_interrupt,
599 SA_SHIRQ, card->name, card)) != 0) {
600 printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n",
601 irq, irqval);
602 release_region(port, AVMB1_PORTLEN);
603 return -EBUSY;
606 card->cardstate = CARD_DETECTED;
607 ncards++;
608 card->cnr = CARDNR(card);
609 card->port = port;
610 card->irq = irq;
611 card->cardtype = cardtype;
612 return card->cnr;
615 int avmb1_addcard(int port, int irq, int cardtype)
617 return avmb1_registercard(port, irq, cardtype, 1);
620 int avmb1_detectcard(int port, int irq, int cardtype)
622 int rc;
624 if (!B1_valid_irq(irq, cardtype)) {
625 printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n",
626 irq, cardtype2str(cardtype));
627 return -EINVAL;
629 if (!B1_valid_port(port, cardtype)) {
630 printk(KERN_WARNING "b1capi: port 0x%x not valid for %s-card.\n",
631 port, cardtype2str(cardtype));
632 return -EINVAL;
634 B1_reset(port);
635 if ((rc = B1_detect(port, cardtype)) != 0) {
636 printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n",
637 cardtype2str(cardtype), port, rc);
638 return -EIO;
640 B1_reset(port);
641 switch (cardtype) {
642 default:
643 case AVM_CARDTYPE_M1:
644 case AVM_CARDTYPE_M2:
645 case AVM_CARDTYPE_B1:
646 case AVM_CARDTYPE_B1PCI:
647 printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port);
648 break;
649 case AVM_CARDTYPE_T1:
650 break;
653 return 0;
656 int avmb1_probecard(int port, int irq, int cardtype)
658 if (check_region(port, AVMB1_PORTLEN)) {
659 printk(KERN_WARNING
660 "b1capi: ports 0x%03x-0x%03x in use.\n",
661 port, port + AVMB1_PORTLEN);
662 return -EBUSY;
664 return avmb1_detectcard(port, irq, cardtype);
667 int avmb1_unregistercard(int cnr, int freeio)
669 avmb1_card * card;
670 if (!VALID_CARD(cnr))
671 return -ESRCH;
672 card = CARD(cnr);
674 if (card->cardstate == CARD_FREE)
675 return -ESRCH;
676 if (card->cardstate == CARD_RUNNING)
677 avmb1_card_down(card, freeio);
679 if (card->cardstate != CARD_FREE)
680 if (card->cardtype == AVM_CARDTYPE_T1)
681 T1_reset(card->port);
683 free_irq(card->irq, card);
684 if (freeio)
685 release_region(card->port, AVMB1_PORTLEN);
686 card->cardstate = CARD_FREE;
687 return 0;
690 int avmb1_resetcard(int cnr)
692 avmb1_card * card;
694 if (!VALID_CARD(cnr))
695 return -ESRCH;
696 card = CARD(cnr);
697 if (card->cardstate == CARD_FREE)
698 return -ESRCH;
700 if (card->cardstate == CARD_RUNNING)
701 avmb1_card_down(card, 0);
703 B1_reset(card->port);
704 B1_reset(card->port);
706 card->cardstate = CARD_DETECTED;
708 return 0;
711 /* ------------------------------------------------------------- */
712 /* -------- CAPI2.0 Interface ---------------------------------- */
713 /* ------------------------------------------------------------- */
715 static int capi_installed(void)
717 int i;
718 for (i = 0; i < CAPI_MAXCONTR; i++) {
719 if (cards[i].cardstate == CARD_RUNNING)
720 return 1;
722 return 0;
725 static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
727 int nconn, want = rparam->level3cnt;
728 int i;
729 int appl;
731 if (rparam->datablklen < 128)
732 return CAPI_LOGBLKSIZETOSMALL;
734 for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
735 if (APPL_IS_FREE(appl))
736 break;
738 if (appl > CAPI_MAXAPPL)
739 return CAPI_TOOMANYAPPLS;
741 APPL_MARK_USED(appl);
742 skb_queue_head_init(&APPL(appl)->recv_queue);
744 memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
746 for (i = 0; i < CAPI_MAXCONTR; i++) {
747 struct capi_profile *profp =
748 (struct capi_profile *)cards[i].version[VER_PROFILE];
750 if (cards[i].cardstate != CARD_RUNNING)
751 continue;
753 if (want > 0) nconn = want;
754 else nconn = profp->nbchannel * -want;
755 if (nconn == 0) nconn = profp->nbchannel;
757 B1_send_register(cards[i].port, appl,
758 1024 * (nconn+1), nconn,
759 APPL(appl)->rparam.datablkcnt,
760 APPL(appl)->rparam.datablklen);
762 *applidp = appl;
763 printk(KERN_INFO "b1capi: appl %d up\n", appl);
765 return CAPI_NOERROR;
768 static __u16 capi_release(__u16 applid)
770 struct sk_buff *skb;
771 int i;
773 if (!VALID_APPLID(applid) || APPL(applid)->releasing)
774 return CAPI_ILLAPPNR;
775 while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
776 kfree_skb(skb);
777 for (i = 0; i < CAPI_MAXCONTR; i++) {
778 if (cards[i].cardstate != CARD_RUNNING) {
779 continue;
781 APPL(applid)->releasing++;
782 B1_send_release(cards[i].port, applid);
784 if (APPL(applid)->releasing <= 0) {
785 APPL(applid)->signal = 0;
786 APPL_MARK_FREE(applid);
787 printk(KERN_INFO "b1capi: appl %d down\n", applid);
789 return CAPI_NOERROR;
792 static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
794 avmb1_ncci *np;
795 int contr;
796 if (ncards == 0)
797 return CAPI_REGNOTINSTALLED;
798 if (!VALID_APPLID(applid))
799 return CAPI_ILLAPPNR;
800 if (skb->len < 12
801 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
802 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
803 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
804 contr = CAPIMSG_CONTROLLER(skb->data);
805 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
806 contr = 1;
807 if (CARD(contr)->cardstate != CARD_RUNNING)
808 return CAPI_REGNOTINSTALLED;
810 if (CARD(contr)->blocked)
811 return CAPI_SENDQUEUEFULL;
813 if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
814 && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ
815 && (np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
816 && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
817 return CAPI_SENDQUEUEFULL;
819 B1_send_message(CARD(contr)->port, skb);
820 return CAPI_NOERROR;
823 static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
825 struct sk_buff *skb;
827 if (!VALID_APPLID(applid))
828 return CAPI_ILLAPPNR;
829 if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
830 return CAPI_RECEIVEQUEUEEMPTY;
831 *msgp = skb;
832 return CAPI_NOERROR;
835 static __u16 capi_set_signal(__u16 applid,
836 void (*signal) (__u16 applid, __u32 param),
837 __u32 param)
839 if (!VALID_APPLID(applid))
840 return CAPI_ILLAPPNR;
841 APPL(applid)->signal = signal;
842 APPL(applid)->param = param;
843 return CAPI_NOERROR;
846 static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
848 if (contr == 0) {
849 strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
850 return CAPI_NOERROR;
852 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
853 return 0x2002;
855 strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
856 return CAPI_NOERROR;
859 static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
861 if (contr == 0) {
862 *verp = driver_version;
863 return CAPI_NOERROR;
865 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
866 return 0x2002;
868 memcpy((void *) verp, &CARD(contr)->cversion,
869 sizeof(capi_version));
870 return CAPI_NOERROR;
873 static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
875 if (contr == 0) {
876 strncpy(serial, driver_serial, 8);
877 return CAPI_NOERROR;
879 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
880 return 0x2002;
882 memcpy((void *) serial, CARD(contr)->version[VER_SERIAL],
883 CAPI_SERIAL_LEN);
884 serial[CAPI_SERIAL_LEN - 1] = 0;
885 return CAPI_NOERROR;
888 static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
890 if (contr == 0) {
891 profp->ncontroller = ncards;
892 return CAPI_NOERROR;
894 if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
895 return 0x2002;
897 memcpy((void *) profp, CARD(contr)->version[VER_PROFILE],
898 sizeof(struct capi_profile));
899 return CAPI_NOERROR;
902 static int capi_manufacturer(unsigned int cmd, void *data)
904 unsigned long flags;
905 avmb1_loadandconfigdef ldef;
906 avmb1_extcarddef cdef;
907 avmb1_resetdef rdef;
908 avmb1_getdef gdef;
909 avmb1_card *card;
910 int rc;
912 switch (cmd) {
913 case AVMB1_ADDCARD:
914 case AVMB1_ADDCARD_WITH_TYPE:
915 if (cmd == AVMB1_ADDCARD) {
916 if ((rc = copy_from_user((void *) &cdef, data,
917 sizeof(avmb1_carddef))))
918 return rc;
919 cdef.cardtype = AVM_CARDTYPE_B1;
920 } else {
921 if ((rc = copy_from_user((void *) &cdef, data,
922 sizeof(avmb1_extcarddef))))
923 return rc;
926 if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0)
927 return rc;
929 if (cdef.cardtype == AVM_CARDTYPE_T1) {
930 int i;
931 for (i=0; i < CAPI_MAXCONTR; i++) {
932 if ( cards[i].cardstate != CARD_FREE
933 && cards[i].cardtype == AVM_CARDTYPE_T1
934 && cards[i].cardnr == cdef.cardnr) {
935 printk(KERN_ERR
936 "b1capi: T1-HEMA-card-%d already at 0x%x\n",
937 cdef.cardnr, cards[i].port);
938 return -EBUSY;
941 rc = T1_detectandinit(cdef.port,cdef.irq,cdef.cardnr);
942 if (rc) {
943 printk(KERN_NOTICE "b1capi: NO T1-HEMA-card-%d at 0x%x (%d)\n",
944 cdef.cardnr, cdef.port, rc);
945 return -EIO;
947 printk(KERN_NOTICE "b1capi: T1-HEMA-card-%d at 0x%x\n",
948 cdef.cardnr, cdef.port);
951 rc = avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
952 if (rc < 0)
953 return rc;
954 /* don't want to change interface t
955 addcard/probecard/registercard */
956 if (cdef.cardtype == AVM_CARDTYPE_T1) {
957 int i;
958 for (i=0; i < CAPI_MAXCONTR; i++) {
959 if (cards[i].cnr == rc) {
960 cards[i].cardnr = cdef.cardnr;
961 break;
965 return rc;
967 case AVMB1_LOAD:
968 case AVMB1_LOAD_AND_CONFIG:
970 if (cmd == AVMB1_LOAD) {
971 if ((rc = copy_from_user((void *) &ldef, data,
972 sizeof(avmb1_loaddef))))
973 return rc;
974 ldef.t4config.len = 0;
975 ldef.t4config.data = 0;
976 } else {
977 if ((rc = copy_from_user((void *) &ldef, data,
978 sizeof(avmb1_loadandconfigdef))))
979 return rc;
981 if (!VALID_CARD(ldef.contr))
982 return -ESRCH;
984 if (ldef.t4file.len <= 0) {
985 printk(KERN_DEBUG "b1capi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
986 return -EINVAL;
989 card = CARD(ldef.contr);
990 save_flags(flags);
991 cli();
992 if (card->cardstate != CARD_DETECTED) {
993 restore_flags(flags);
994 if (loaddebug)
995 printk(KERN_DEBUG "b1capi: load: contr=%d not in detect state\n", ldef.contr);
996 return -EBUSY;
998 card->cardstate = CARD_LOADING;
999 restore_flags(flags);
1001 if (loaddebug) {
1002 printk(KERN_DEBUG "b1capi: load: reseting contr %d\n",
1003 ldef.contr);
1006 B1_reset(card->port);
1008 if (loaddebug) {
1009 printk(KERN_DEBUG "b1capi: loading contr %d\n",
1010 ldef.contr);
1013 if ((rc = B1_load_t4file(card->port, &ldef.t4file))) {
1014 B1_reset(card->port);
1015 printk(KERN_ERR "b1capi: failed to load t4file!!\n");
1016 card->cardstate = CARD_DETECTED;
1017 return rc;
1020 B1_disable_irq(card->port);
1022 if (ldef.t4config.len > 0) { /* load config */
1023 if (loaddebug) {
1024 printk(KERN_DEBUG "b1capi: loading config to contr %d\n",
1025 ldef.contr);
1027 if ((rc = B1_load_config(card->port, &ldef.t4config))) {
1028 B1_reset(card->port);
1029 printk(KERN_ERR "b1capi: failed to load config!!\n");
1030 card->cardstate = CARD_DETECTED;
1031 return rc;
1035 if (loaddebug) {
1036 printk(KERN_DEBUG "b1capi: load: ready contr %d: checking\n",
1037 ldef.contr);
1040 if (!B1_loaded(card->port)) {
1041 card->cardstate = CARD_DETECTED;
1042 printk(KERN_ERR "b1capi: failed to load t4file.\n");
1043 return -EIO;
1046 * enable interrupt
1049 card->cardstate = CARD_INITSTATE;
1050 save_flags(flags);
1051 cli();
1052 B1_setinterrupt(card->port, card->irq, card->cardtype);
1053 restore_flags(flags);
1055 if (loaddebug) {
1056 printk(KERN_DEBUG "b1capi: load: irq enabled contr %d\n",
1057 ldef.contr);
1061 * init card
1063 if (card->cardtype == AVM_CARDTYPE_T1)
1064 B1_send_init(card->port, AVM_NAPPS,
1065 AVM_NNCCI_PER_CHANNEL*30,
1066 card->cnr - 1);
1067 else
1068 B1_send_init(card->port, AVM_NAPPS,
1069 AVM_NNCCI_PER_CHANNEL*2,
1070 card->cnr - 1);
1072 if (loaddebug) {
1073 printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n",
1074 ldef.contr);
1077 while (card->cardstate != CARD_RUNNING) {
1079 current->state = TASK_INTERRUPTIBLE;
1080 schedule_timeout(HZ/10); /* 0.1 sec */
1082 if (signal_pending(current))
1083 return -EINTR;
1085 return 0;
1087 case AVMB1_RESETCARD:
1088 if ((rc = copy_from_user((void *) &rdef, data,
1089 sizeof(avmb1_resetdef))))
1090 return rc;
1092 return avmb1_resetcard(rdef.contr);
1094 case AVMB1_GET_CARDINFO:
1095 if ((rc = copy_from_user((void *) &gdef, data,
1096 sizeof(avmb1_getdef))))
1097 return rc;
1099 if (!VALID_CARD(gdef.contr))
1100 return -ESRCH;
1102 card = CARD(gdef.contr);
1104 gdef.cardstate = card->cardstate;
1105 gdef.cardtype = card->cardtype;
1107 if ((rc = copy_to_user(data, (void *) &gdef,
1108 sizeof(avmb1_getdef))))
1109 return rc;
1111 return 0;
1112 case AVMB1_REMOVECARD:
1113 if ((rc = copy_from_user((void *) &rdef, data,
1114 sizeof(avmb1_resetdef))))
1115 return rc;
1116 if (!VALID_CARD(rdef.contr))
1117 return -ESRCH;
1119 card = CARD(rdef.contr);
1121 if (card->cardstate != CARD_DETECTED)
1122 return -EBUSY;
1124 return avmb1_unregistercard(rdef.contr, 1);
1126 return -EINVAL;
1129 struct capi_interface avmb1_interface =
1131 capi_installed,
1132 capi_register,
1133 capi_release,
1134 capi_put_message,
1135 capi_get_message,
1136 capi_set_signal,
1137 capi_get_manufacturer,
1138 capi_get_version,
1139 capi_get_serial,
1140 capi_get_profile,
1141 capi_manufacturer
1144 /* ------------------------------------------------------------- */
1145 /* -------- Exported Functions --------------------------------- */
1146 /* ------------------------------------------------------------- */
1148 struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
1150 struct capi_interface_user *p;
1152 for (p = capi_users; p; p = p->next) {
1153 if (p == userp) {
1154 printk(KERN_ERR "b1capi: double attach from %s\n",
1155 userp->name);
1156 return 0;
1159 userp->next = capi_users;
1160 capi_users = userp;
1161 MOD_INC_USE_COUNT;
1162 printk(KERN_NOTICE "b1capi: %s attached\n", userp->name);
1164 return &avmb1_interface;
1167 int detach_capi_interface(struct capi_interface_user *userp)
1169 struct capi_interface_user **pp;
1171 for (pp = &capi_users; *pp; pp = &(*pp)->next) {
1172 if (*pp == userp) {
1173 *pp = userp->next;
1174 userp->next = 0;
1175 MOD_DEC_USE_COUNT;
1176 printk(KERN_NOTICE "b1capi: %s detached\n", userp->name);
1177 return 0;
1180 printk(KERN_ERR "b1capi: double detach from %s\n", userp->name);
1181 return -1;
1184 /* ------------------------------------------------------------- */
1185 /* -------- Init & Cleanup ------------------------------------- */
1186 /* ------------------------------------------------------------- */
1188 EXPORT_SYMBOL(attach_capi_interface);
1189 EXPORT_SYMBOL(detach_capi_interface);
1190 EXPORT_SYMBOL(avmb1_addcard);
1191 EXPORT_SYMBOL(avmb1_probecard);
1192 EXPORT_SYMBOL(avmb1_registercard);
1193 EXPORT_SYMBOL(avmb1_unregistercard);
1194 EXPORT_SYMBOL(avmb1_resetcard);
1195 EXPORT_SYMBOL(avmb1_detectcard);
1199 * init / exit functions
1202 #ifdef MODULE
1203 #define avmb1_init init_module
1204 #endif
1206 int avmb1_init(void)
1208 char *p;
1209 char rev[10];
1211 skb_queue_head_init(&recv_queue);
1212 /* init_bh(CAPI_BH, do_capi_bh); */
1214 tq_state_notify.routine = notify_handler;
1215 tq_state_notify.data = 0;
1217 tq_recv_notify.routine = recv_handler;
1218 tq_recv_notify.data = 0;
1221 if ((p = strchr(revision, ':'))) {
1222 strcpy(rev, p + 1);
1223 p = strchr(rev, '$');
1224 *p = 0;
1225 } else
1226 strcpy(rev, " ??? ");
1228 #ifdef MODULE
1229 printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: loaded\n", rev);
1230 #else
1231 printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: started\n", rev);
1232 #endif
1233 return 0;
1236 #ifdef MODULE
1237 void cleanup_module(void)
1239 char rev[10];
1240 char *p;
1241 int i;
1243 if ((p = strchr(revision, ':'))) {
1244 strcpy(rev, p + 1);
1245 p = strchr(rev, '$');
1246 *p = 0;
1247 } else {
1248 strcpy(rev, " ??? ");
1251 for (i = 0; i < CAPI_MAXCONTR; i++) {
1252 if (cards[i].cardstate != CARD_FREE) {
1254 * disable card
1256 B1_disable_irq(cards[i].port);
1257 avmb1_resetcard(i+1);
1259 * free kernel resources
1261 avmb1_unregistercard(i+1, 1);
1264 schedule(); /* execute queued tasks .... */
1265 printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: unloaded\n", rev);
1267 #endif