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