Linux-2.6.12-rc2
[linux-2.6] / drivers / isdn / capi / kcapi.c
1 /* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
2  * 
3  * Kernel CAPI 2.0 Module
4  * 
5  * Copyright 1999 by Carsten Paeth <calle@calle.de>
6  * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
7  * 
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  */
12
13 #define CONFIG_AVMB1_COMPAT
14
15 #include "kcapi.h"
16 #include <linux/module.h>
17 #include <linux/mm.h>
18 #include <linux/interrupt.h>
19 #include <linux/ioport.h>
20 #include <linux/proc_fs.h>
21 #include <linux/seq_file.h>
22 #include <linux/skbuff.h>
23 #include <linux/workqueue.h>
24 #include <linux/capi.h>
25 #include <linux/kernelcapi.h>
26 #include <linux/init.h>
27 #include <linux/moduleparam.h>
28 #include <linux/delay.h>
29 #include <asm/uaccess.h>
30 #include <linux/isdn/capicmd.h>
31 #include <linux/isdn/capiutil.h>
32 #ifdef CONFIG_AVMB1_COMPAT
33 #include <linux/b1lli.h>
34 #endif
35
36 static char *revision = "$Revision: 1.1.2.8 $";
37
38 /* ------------------------------------------------------------- */
39
40 static int showcapimsgs = 0;
41
42 MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
43 MODULE_AUTHOR("Carsten Paeth");
44 MODULE_LICENSE("GPL");
45 module_param(showcapimsgs, uint, 0);
46
47 /* ------------------------------------------------------------- */
48
49 struct capi_notifier {
50         struct work_struct work;
51         unsigned int cmd;
52         u32 controller;
53         u16 applid;
54         u32 ncci;
55 };
56
57 /* ------------------------------------------------------------- */
58
59 static struct capi_version driver_version = {2, 0, 1, 1<<4};
60 static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
61 static char capi_manufakturer[64] = "AVM Berlin";
62
63 #define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
64
65 LIST_HEAD(capi_drivers);
66 DEFINE_RWLOCK(capi_drivers_list_lock);
67
68 static DEFINE_RWLOCK(application_lock);
69 static DECLARE_MUTEX(controller_sem);
70
71 struct capi20_appl *capi_applications[CAPI_MAXAPPL];
72 struct capi_ctr *capi_cards[CAPI_MAXCONTR];
73
74 static int ncards;
75
76 /* -------- controller ref counting -------------------------------------- */
77
78 static inline struct capi_ctr *
79 capi_ctr_get(struct capi_ctr *card)
80 {
81         if (!try_module_get(card->owner))
82                 return NULL;
83         return card;
84 }
85
86 static inline void
87 capi_ctr_put(struct capi_ctr *card)
88 {
89         module_put(card->owner);
90 }
91
92 /* ------------------------------------------------------------- */
93
94 static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
95 {
96         if (contr - 1 >= CAPI_MAXCONTR)
97                 return NULL;
98
99         return capi_cards[contr - 1];
100 }
101
102 static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
103 {
104         if (applid - 1 >= CAPI_MAXAPPL)
105                 return NULL;
106
107         return capi_applications[applid - 1];
108 }
109
110 /* -------- util functions ------------------------------------ */
111
112 static inline int capi_cmd_valid(u8 cmd)
113 {
114         switch (cmd) {
115         case CAPI_ALERT:
116         case CAPI_CONNECT:
117         case CAPI_CONNECT_ACTIVE:
118         case CAPI_CONNECT_B3_ACTIVE:
119         case CAPI_CONNECT_B3:
120         case CAPI_CONNECT_B3_T90_ACTIVE:
121         case CAPI_DATA_B3:
122         case CAPI_DISCONNECT_B3:
123         case CAPI_DISCONNECT:
124         case CAPI_FACILITY:
125         case CAPI_INFO:
126         case CAPI_LISTEN:
127         case CAPI_MANUFACTURER:
128         case CAPI_RESET_B3:
129         case CAPI_SELECT_B_PROTOCOL:
130                 return 1;
131         }
132         return 0;
133 }
134
135 static inline int capi_subcmd_valid(u8 subcmd)
136 {
137         switch (subcmd) {
138         case CAPI_REQ:
139         case CAPI_CONF:
140         case CAPI_IND:
141         case CAPI_RESP:
142                 return 1;
143         }
144         return 0;
145 }
146
147 /* ------------------------------------------------------------ */
148
149 static void register_appl(struct capi_ctr *card, u16 applid, capi_register_params *rparam)
150 {
151         card = capi_ctr_get(card);
152
153         if (card)
154                 card->register_appl(card, applid, rparam);
155         else
156                 printk(KERN_WARNING "%s: cannot get card resources\n", __FUNCTION__);
157 }
158
159
160 static void release_appl(struct capi_ctr *card, u16 applid)
161 {
162         DBG("applid %#x", applid);
163         
164         card->release_appl(card, applid);
165         capi_ctr_put(card);
166 }
167
168 /* -------- KCI_CONTRUP --------------------------------------- */
169
170 static void notify_up(u32 contr)
171 {
172         struct capi_ctr *card = get_capi_ctr_by_nr(contr);
173         struct capi20_appl *ap;
174         u16 applid;
175
176         if (showcapimsgs & 1) {
177                 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
178         }
179         if (!card) {
180                 printk(KERN_WARNING "%s: invalid contr %d\n", __FUNCTION__, contr);
181                 return;
182         }
183         for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
184                 ap = get_capi_appl_by_nr(applid);
185                 if (!ap || ap->release_in_progress) continue;
186                 register_appl(card, applid, &ap->rparam);
187                 if (ap->callback && !ap->release_in_progress)
188                         ap->callback(KCI_CONTRUP, contr, &card->profile);
189         }
190 }
191
192 /* -------- KCI_CONTRDOWN ------------------------------------- */
193
194 static void notify_down(u32 contr)
195 {
196         struct capi20_appl *ap;
197         u16 applid;
198
199         if (showcapimsgs & 1) {
200                 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
201         }
202
203         for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
204                 ap = get_capi_appl_by_nr(applid);
205                 if (ap && ap->callback && !ap->release_in_progress)
206                         ap->callback(KCI_CONTRDOWN, contr, NULL);
207         }
208 }
209
210 static void notify_handler(void *data)
211 {
212         struct capi_notifier *np = data;
213
214         switch (np->cmd) {
215         case KCI_CONTRUP:
216                 notify_up(np->controller);
217                 break;
218         case KCI_CONTRDOWN:
219                 notify_down(np->controller);
220                 break;
221         }
222
223         kfree(np);
224 }
225
226 /*
227  * The notifier will result in adding/deleteing of devices. Devices can
228  * only removed in user process, not in bh.
229  */
230 static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci)
231 {
232         struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC);
233
234         if (!np)
235                 return -ENOMEM;
236
237         INIT_WORK(&np->work, notify_handler, np);
238         np->cmd = cmd;
239         np->controller = controller;
240         np->applid = applid;
241         np->ncci = ncci;
242
243         schedule_work(&np->work);
244         return 0;
245 }
246
247         
248 /* -------- Receiver ------------------------------------------ */
249
250 static void recv_handler(void *_ap)
251 {
252         struct sk_buff *skb;
253         struct capi20_appl *ap = (struct capi20_appl *) _ap;
254
255         if ((!ap) || (ap->release_in_progress))
256                 return;
257
258         down(&ap->recv_sem);
259         while ((skb = skb_dequeue(&ap->recv_queue))) {
260                 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
261                         ap->nrecvdatapkt++;
262                 else
263                         ap->nrecvctlpkt++;
264
265                 ap->recv_message(ap, skb);
266         }
267         up(&ap->recv_sem);
268 }
269
270 void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb)
271 {
272         struct capi20_appl *ap;
273         int showctl = 0;
274         u8 cmd, subcmd;
275         unsigned long flags;
276
277         if (card->cardstate != CARD_RUNNING) {
278                 printk(KERN_INFO "kcapi: controller %d not active, got: %s",
279                        card->cnr, capi_message2str(skb->data));
280                 goto error;
281         }
282
283         cmd = CAPIMSG_COMMAND(skb->data);
284         subcmd = CAPIMSG_SUBCOMMAND(skb->data);
285         if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
286                 card->nrecvdatapkt++;
287                 if (card->traceflag > 2) showctl |= 2;
288         } else {
289                 card->nrecvctlpkt++;
290                 if (card->traceflag) showctl |= 2;
291         }
292         showctl |= (card->traceflag & 1);
293         if (showctl & 2) {
294                 if (showctl & 1) {
295                         printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",
296                                (unsigned long) card->cnr,
297                                CAPIMSG_APPID(skb->data),
298                                capi_cmd2str(cmd, subcmd),
299                                CAPIMSG_LEN(skb->data));
300                 } else {
301                         printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",
302                                         (unsigned long) card->cnr,
303                                         capi_message2str(skb->data));
304                 }
305
306         }
307
308         read_lock_irqsave(&application_lock, flags);
309         ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
310         if ((!ap) || (ap->release_in_progress)) {
311                 read_unlock_irqrestore(&application_lock, flags);
312                 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
313                         CAPIMSG_APPID(skb->data), capi_message2str(skb->data));
314                 goto error;
315         }
316         skb_queue_tail(&ap->recv_queue, skb);
317         schedule_work(&ap->recv_work);
318         read_unlock_irqrestore(&application_lock, flags);
319
320         return;
321
322 error:
323         kfree_skb(skb);
324 }
325
326 EXPORT_SYMBOL(capi_ctr_handle_message);
327
328 void capi_ctr_ready(struct capi_ctr * card)
329 {
330         card->cardstate = CARD_RUNNING;
331
332         printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
333                card->cnr, card->name);
334
335         notify_push(KCI_CONTRUP, card->cnr, 0, 0);
336 }
337
338 EXPORT_SYMBOL(capi_ctr_ready);
339
340 void capi_ctr_reseted(struct capi_ctr * card)
341 {
342         u16 appl;
343
344         DBG("");
345
346         if (card->cardstate == CARD_DETECTED)
347                 return;
348
349         card->cardstate = CARD_DETECTED;
350
351         memset(card->manu, 0, sizeof(card->manu));
352         memset(&card->version, 0, sizeof(card->version));
353         memset(&card->profile, 0, sizeof(card->profile));
354         memset(card->serial, 0, sizeof(card->serial));
355
356         for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
357                 struct capi20_appl *ap = get_capi_appl_by_nr(appl);
358                 if (!ap || ap->release_in_progress)
359                         continue;
360
361                 capi_ctr_put(card);
362         }
363
364         printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr);
365
366         notify_push(KCI_CONTRDOWN, card->cnr, 0, 0);
367 }
368
369 EXPORT_SYMBOL(capi_ctr_reseted);
370
371 void capi_ctr_suspend_output(struct capi_ctr *card)
372 {
373         if (!card->blocked) {
374                 printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr);
375                 card->blocked = 1;
376         }
377 }
378
379 EXPORT_SYMBOL(capi_ctr_suspend_output);
380
381 void capi_ctr_resume_output(struct capi_ctr *card)
382 {
383         if (card->blocked) {
384                 printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr);
385                 card->blocked = 0;
386         }
387 }
388
389 EXPORT_SYMBOL(capi_ctr_resume_output);
390
391 /* ------------------------------------------------------------- */
392
393 int
394 attach_capi_ctr(struct capi_ctr *card)
395 {
396         int i;
397
398         down(&controller_sem);
399
400         for (i = 0; i < CAPI_MAXCONTR; i++) {
401                 if (capi_cards[i] == NULL)
402                         break;
403         }
404         if (i == CAPI_MAXCONTR) {
405                 up(&controller_sem);
406                 printk(KERN_ERR "kcapi: out of controller slots\n");
407                 return -EBUSY;
408         }
409         capi_cards[i] = card;
410
411         up(&controller_sem);
412
413         card->nrecvctlpkt = 0;
414         card->nrecvdatapkt = 0;
415         card->nsentctlpkt = 0;
416         card->nsentdatapkt = 0;
417         card->cnr = i + 1;
418         card->cardstate = CARD_DETECTED;
419         card->blocked = 0;
420         card->traceflag = showcapimsgs;
421
422         sprintf(card->procfn, "capi/controllers/%d", card->cnr);
423         card->procent = create_proc_entry(card->procfn, 0, NULL);
424         if (card->procent) {
425            card->procent->read_proc = 
426                 (int (*)(char *,char **,off_t,int,int *,void *))
427                         card->ctr_read_proc;
428            card->procent->data = card;
429         }
430
431         ncards++;
432         printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",
433                         card->cnr, card->name);
434         return 0;
435 }
436
437 EXPORT_SYMBOL(attach_capi_ctr);
438
439 int detach_capi_ctr(struct capi_ctr *card)
440 {
441         if (card->cardstate != CARD_DETECTED)
442                 capi_ctr_reseted(card);
443
444         ncards--;
445
446         if (card->procent) {
447            remove_proc_entry(card->procfn, NULL);
448            card->procent = NULL;
449         }
450         capi_cards[card->cnr - 1] = NULL;
451         printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",
452                         card->cnr, card->name);
453
454         return 0;
455 }
456
457 EXPORT_SYMBOL(detach_capi_ctr);
458
459 void register_capi_driver(struct capi_driver *driver)
460 {
461         unsigned long flags;
462
463         write_lock_irqsave(&capi_drivers_list_lock, flags);
464         list_add_tail(&driver->list, &capi_drivers);
465         write_unlock_irqrestore(&capi_drivers_list_lock, flags);
466 }
467
468 EXPORT_SYMBOL(register_capi_driver);
469
470 void unregister_capi_driver(struct capi_driver *driver)
471 {
472         unsigned long flags;
473
474         write_lock_irqsave(&capi_drivers_list_lock, flags);
475         list_del(&driver->list);
476         write_unlock_irqrestore(&capi_drivers_list_lock, flags);
477 }
478
479 EXPORT_SYMBOL(unregister_capi_driver);
480
481 /* ------------------------------------------------------------- */
482 /* -------- CAPI2.0 Interface ---------------------------------- */
483 /* ------------------------------------------------------------- */
484
485 u16 capi20_isinstalled(void)
486 {
487         int i;
488         for (i = 0; i < CAPI_MAXCONTR; i++) {
489                 if (capi_cards[i] && capi_cards[i]->cardstate == CARD_RUNNING)
490                         return CAPI_NOERROR;
491         }
492         return CAPI_REGNOTINSTALLED;
493 }
494
495 EXPORT_SYMBOL(capi20_isinstalled);
496
497 u16 capi20_register(struct capi20_appl *ap)
498 {
499         int i;
500         u16 applid;
501         unsigned long flags;
502
503         DBG("");
504
505         if (ap->rparam.datablklen < 128)
506                 return CAPI_LOGBLKSIZETOSMALL;
507
508         write_lock_irqsave(&application_lock, flags);
509
510         for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
511                 if (capi_applications[applid - 1] == NULL)
512                         break;
513         }
514         if (applid > CAPI_MAXAPPL) {
515                 write_unlock_irqrestore(&application_lock, flags);
516                 return CAPI_TOOMANYAPPLS;
517         }
518
519         ap->applid = applid;
520         capi_applications[applid - 1] = ap;
521
522         ap->nrecvctlpkt = 0;
523         ap->nrecvdatapkt = 0;
524         ap->nsentctlpkt = 0;
525         ap->nsentdatapkt = 0;
526         ap->callback = NULL;
527         init_MUTEX(&ap->recv_sem);
528         skb_queue_head_init(&ap->recv_queue);
529         INIT_WORK(&ap->recv_work, recv_handler, (void *)ap);
530         ap->release_in_progress = 0;
531
532         write_unlock_irqrestore(&application_lock, flags);
533         
534         down(&controller_sem);
535         for (i = 0; i < CAPI_MAXCONTR; i++) {
536                 if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING)
537                         continue;
538                 register_appl(capi_cards[i], applid, &ap->rparam);
539         }
540         up(&controller_sem);
541
542         if (showcapimsgs & 1) {
543                 printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
544         }
545
546         return CAPI_NOERROR;
547 }
548
549 EXPORT_SYMBOL(capi20_register);
550
551 u16 capi20_release(struct capi20_appl *ap)
552 {
553         int i;
554         unsigned long flags;
555
556         DBG("applid %#x", ap->applid);
557
558         write_lock_irqsave(&application_lock, flags);
559         ap->release_in_progress = 1;
560         capi_applications[ap->applid - 1] = NULL;
561         write_unlock_irqrestore(&application_lock, flags);
562
563         down(&controller_sem);
564         for (i = 0; i < CAPI_MAXCONTR; i++) {
565                 if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING)
566                         continue;
567                 release_appl(capi_cards[i], ap->applid);
568         }
569         up(&controller_sem);
570
571         flush_scheduled_work();
572         skb_queue_purge(&ap->recv_queue);
573
574         if (showcapimsgs & 1) {
575                 printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
576         }
577
578         return CAPI_NOERROR;
579 }
580
581 EXPORT_SYMBOL(capi20_release);
582
583 u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
584 {
585         struct capi_ctr *card;
586         int showctl = 0;
587         u8 cmd, subcmd;
588
589         DBG("applid %#x", ap->applid);
590  
591         if (ncards == 0)
592                 return CAPI_REGNOTINSTALLED;
593         if ((ap->applid == 0) || ap->release_in_progress)
594                 return CAPI_ILLAPPNR;
595         if (skb->len < 12
596             || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
597             || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
598                 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
599         card = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
600         if (!card || card->cardstate != CARD_RUNNING) {
601                 card = get_capi_ctr_by_nr(1); // XXX why?
602                 if (!card || card->cardstate != CARD_RUNNING) 
603                         return CAPI_REGNOTINSTALLED;
604         }
605         if (card->blocked)
606                 return CAPI_SENDQUEUEFULL;
607
608         cmd = CAPIMSG_COMMAND(skb->data);
609         subcmd = CAPIMSG_SUBCOMMAND(skb->data);
610
611         if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
612                 card->nsentdatapkt++;
613                 ap->nsentdatapkt++;
614                 if (card->traceflag > 2) showctl |= 2;
615         } else {
616                 card->nsentctlpkt++;
617                 ap->nsentctlpkt++;
618                 if (card->traceflag) showctl |= 2;
619         }
620         showctl |= (card->traceflag & 1);
621         if (showctl & 2) {
622                 if (showctl & 1) {
623                         printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n",
624                                CAPIMSG_CONTROLLER(skb->data),
625                                CAPIMSG_APPID(skb->data),
626                                capi_cmd2str(cmd, subcmd),
627                                CAPIMSG_LEN(skb->data));
628                 } else {
629                         printk(KERN_DEBUG "kcapi: put [%#x] %s\n",
630                                CAPIMSG_CONTROLLER(skb->data),
631                                capi_message2str(skb->data));
632                 }
633
634         }
635         return card->send_message(card, skb);
636 }
637
638 EXPORT_SYMBOL(capi20_put_message);
639
640 u16 capi20_get_manufacturer(u32 contr, u8 *buf)
641 {
642         struct capi_ctr *card;
643
644         if (contr == 0) {
645                 strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
646                 return CAPI_NOERROR;
647         }
648         card = get_capi_ctr_by_nr(contr);
649         if (!card || card->cardstate != CARD_RUNNING) 
650                 return CAPI_REGNOTINSTALLED;
651         strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN);
652         return CAPI_NOERROR;
653 }
654
655 EXPORT_SYMBOL(capi20_get_manufacturer);
656
657 u16 capi20_get_version(u32 contr, struct capi_version *verp)
658 {
659         struct capi_ctr *card;
660
661         if (contr == 0) {
662                 *verp = driver_version;
663                 return CAPI_NOERROR;
664         }
665         card = get_capi_ctr_by_nr(contr);
666         if (!card || card->cardstate != CARD_RUNNING) 
667                 return CAPI_REGNOTINSTALLED;
668
669         memcpy((void *) verp, &card->version, sizeof(capi_version));
670         return CAPI_NOERROR;
671 }
672
673 EXPORT_SYMBOL(capi20_get_version);
674
675 u16 capi20_get_serial(u32 contr, u8 *serial)
676 {
677         struct capi_ctr *card;
678
679         if (contr == 0) {
680                 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
681                 return CAPI_NOERROR;
682         }
683         card = get_capi_ctr_by_nr(contr);
684         if (!card || card->cardstate != CARD_RUNNING) 
685                 return CAPI_REGNOTINSTALLED;
686
687         strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN);
688         return CAPI_NOERROR;
689 }
690
691 EXPORT_SYMBOL(capi20_get_serial);
692
693 u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
694 {
695         struct capi_ctr *card;
696
697         if (contr == 0) {
698                 profp->ncontroller = ncards;
699                 return CAPI_NOERROR;
700         }
701         card = get_capi_ctr_by_nr(contr);
702         if (!card || card->cardstate != CARD_RUNNING) 
703                 return CAPI_REGNOTINSTALLED;
704
705         memcpy((void *) profp, &card->profile,
706                         sizeof(struct capi_profile));
707         return CAPI_NOERROR;
708 }
709
710 EXPORT_SYMBOL(capi20_get_profile);
711
712 #ifdef CONFIG_AVMB1_COMPAT
713 static int old_capi_manufacturer(unsigned int cmd, void __user *data)
714 {
715         avmb1_loadandconfigdef ldef;
716         avmb1_extcarddef cdef;
717         avmb1_resetdef rdef;
718         capicardparams cparams;
719         struct capi_ctr *card;
720         struct capi_driver *driver = NULL;
721         capiloaddata ldata;
722         struct list_head *l;
723         unsigned long flags;
724         int retval;
725
726         switch (cmd) {
727         case AVMB1_ADDCARD:
728         case AVMB1_ADDCARD_WITH_TYPE:
729                 if (cmd == AVMB1_ADDCARD) {
730                    if ((retval = copy_from_user(&cdef, data,
731                                             sizeof(avmb1_carddef))))
732                            return retval;
733                    cdef.cardtype = AVM_CARDTYPE_B1;
734                 } else {
735                    if ((retval = copy_from_user(&cdef, data,
736                                             sizeof(avmb1_extcarddef))))
737                            return retval;
738                 }
739                 cparams.port = cdef.port;
740                 cparams.irq = cdef.irq;
741                 cparams.cardnr = cdef.cardnr;
742
743                 read_lock_irqsave(&capi_drivers_list_lock, flags);
744                 switch (cdef.cardtype) {
745                         case AVM_CARDTYPE_B1:
746                                 list_for_each(l, &capi_drivers) {
747                                         driver = list_entry(l, struct capi_driver, list);
748                                         if (strcmp(driver->name, "b1isa") == 0)
749                                                 break;
750                                 }
751                                 break;
752                         case AVM_CARDTYPE_T1:
753                                 list_for_each(l, &capi_drivers) {
754                                         driver = list_entry(l, struct capi_driver, list);
755                                         if (strcmp(driver->name, "t1isa") == 0)
756                                                 break;
757                                 }
758                                 break;
759                         default:
760                                 driver = NULL;
761                                 break;
762                 }
763                 if (!driver) {
764                         read_unlock_irqrestore(&capi_drivers_list_lock, flags);
765                         printk(KERN_ERR "kcapi: driver not loaded.\n");
766                         return -EIO;
767                 }
768                 if (!driver->add_card) {
769                         read_unlock_irqrestore(&capi_drivers_list_lock, flags);
770                         printk(KERN_ERR "kcapi: driver has no add card function.\n");
771                         return -EIO;
772                 }
773
774                 retval = driver->add_card(driver, &cparams);
775                 read_unlock_irqrestore(&capi_drivers_list_lock, flags);
776                 return retval;
777
778         case AVMB1_LOAD:
779         case AVMB1_LOAD_AND_CONFIG:
780
781                 if (cmd == AVMB1_LOAD) {
782                         if (copy_from_user(&ldef, data,
783                                            sizeof(avmb1_loaddef)))
784                                 return -EFAULT;
785                         ldef.t4config.len = 0;
786                         ldef.t4config.data = NULL;
787                 } else {
788                         if (copy_from_user(&ldef, data,
789                                            sizeof(avmb1_loadandconfigdef)))
790                                 return -EFAULT;
791                 }
792                 card = get_capi_ctr_by_nr(ldef.contr);
793                 card = capi_ctr_get(card);
794                 if (!card)
795                         return -ESRCH;
796                 if (card->load_firmware == 0) {
797                         printk(KERN_DEBUG "kcapi: load: no load function\n");
798                         return -ESRCH;
799                 }
800
801                 if (ldef.t4file.len <= 0) {
802                         printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
803                         return -EINVAL;
804                 }
805                 if (ldef.t4file.data == 0) {
806                         printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
807                         return -EINVAL;
808                 }
809
810                 ldata.firmware.user = 1;
811                 ldata.firmware.data = ldef.t4file.data;
812                 ldata.firmware.len = ldef.t4file.len;
813                 ldata.configuration.user = 1;
814                 ldata.configuration.data = ldef.t4config.data;
815                 ldata.configuration.len = ldef.t4config.len;
816
817                 if (card->cardstate != CARD_DETECTED) {
818                         printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
819                         return -EBUSY;
820                 }
821                 card->cardstate = CARD_LOADING;
822
823                 retval = card->load_firmware(card, &ldata);
824
825                 if (retval) {
826                         card->cardstate = CARD_DETECTED;
827                         capi_ctr_put(card);
828                         return retval;
829                 }
830
831                 while (card->cardstate != CARD_RUNNING) {
832
833                         msleep_interruptible(100);      /* 0.1 sec */
834
835                         if (signal_pending(current)) {
836                                 capi_ctr_put(card);
837                                 return -EINTR;
838                         }
839                 }
840                 capi_ctr_put(card);
841                 return 0;
842
843         case AVMB1_RESETCARD:
844                 if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
845                         return -EFAULT;
846                 card = get_capi_ctr_by_nr(rdef.contr);
847                 if (!card)
848                         return -ESRCH;
849
850                 if (card->cardstate == CARD_DETECTED)
851                         return 0;
852
853                 card->reset_ctr(card);
854
855                 while (card->cardstate > CARD_DETECTED) {
856
857                         msleep_interruptible(100);      /* 0.1 sec */
858
859                         if (signal_pending(current))
860                                 return -EINTR;
861                 }
862                 return 0;
863
864         }
865         return -EINVAL;
866 }
867 #endif
868
869 int capi20_manufacturer(unsigned int cmd, void __user *data)
870 {
871         struct capi_ctr *card;
872
873         switch (cmd) {
874 #ifdef CONFIG_AVMB1_COMPAT
875         case AVMB1_LOAD:
876         case AVMB1_LOAD_AND_CONFIG:
877         case AVMB1_RESETCARD:
878         case AVMB1_GET_CARDINFO:
879         case AVMB1_REMOVECARD:
880                 return old_capi_manufacturer(cmd, data);
881 #endif
882         case KCAPI_CMD_TRACE:
883         {
884                 kcapi_flagdef fdef;
885
886                 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
887                         return -EFAULT;
888
889                 card = get_capi_ctr_by_nr(fdef.contr);
890                 if (!card)
891                         return -ESRCH;
892
893                 card->traceflag = fdef.flag;
894                 printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
895                         card->cnr, card->traceflag);
896                 return 0;
897         }
898         case KCAPI_CMD_ADDCARD:
899         {
900                 struct list_head *l;
901                 struct capi_driver *driver = NULL;
902                 capicardparams cparams;
903                 kcapi_carddef cdef;
904                 int retval;
905
906                 if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
907                         return retval;
908
909                 cparams.port = cdef.port;
910                 cparams.irq = cdef.irq;
911                 cparams.membase = cdef.membase;
912                 cparams.cardnr = cdef.cardnr;
913                 cparams.cardtype = 0;
914                 cdef.driver[sizeof(cdef.driver)-1] = 0;
915
916                 list_for_each(l, &capi_drivers) {
917                         driver = list_entry(l, struct capi_driver, list);
918                         if (strcmp(driver->name, cdef.driver) == 0)
919                                 break;
920                 }
921                 if (driver == 0) {
922                         printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
923                                         cdef.driver);
924                         return -ESRCH;
925                 }
926
927                 if (!driver->add_card) {
928                         printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
929                         return -EIO;
930                 }
931
932                 return driver->add_card(driver, &cparams);
933         }
934
935         default:
936                 printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
937                                         cmd);
938                 break;
939
940         }
941         return -EINVAL;
942 }
943
944 EXPORT_SYMBOL(capi20_manufacturer);
945
946 /* temporary hack */
947 void capi20_set_callback(struct capi20_appl *ap,
948                          void (*callback) (unsigned int cmd, __u32 contr, void *data))
949 {
950         ap->callback = callback;
951 }
952
953 EXPORT_SYMBOL(capi20_set_callback);
954
955 /* ------------------------------------------------------------- */
956 /* -------- Init & Cleanup ------------------------------------- */
957 /* ------------------------------------------------------------- */
958
959 /*
960  * init / exit functions
961  */
962
963 static int __init kcapi_init(void)
964 {
965         char *p;
966         char rev[32];
967
968         kcapi_proc_init();
969
970         if ((p = strchr(revision, ':')) != 0 && p[1]) {
971                 strlcpy(rev, p + 2, sizeof(rev));
972                 if ((p = strchr(rev, '$')) != 0 && p > rev)
973                    *(p-1) = 0;
974         } else
975                 strcpy(rev, "1.0");
976
977         printk(KERN_NOTICE "CAPI Subsystem Rev %s\n", rev);
978
979         return 0;
980 }
981
982 static void __exit kcapi_exit(void)
983 {
984         kcapi_proc_exit();
985
986         /* make sure all notifiers are finished */
987         flush_scheduled_work();
988 }
989
990 module_init(kcapi_init);
991 module_exit(kcapi_exit);