kcapi.c (ef69bb2ec6036945da1d3d3f07b75253f484f693) kcapi.c (0ca3a017a7373a4545dd7b345a8a0cecc16bc7e2)
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

--- 47 unchanged lines hidden (view full) ---

56static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
57static char capi_manufakturer[64] = "AVM Berlin";
58
59#define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
60
61LIST_HEAD(capi_drivers);
62DEFINE_MUTEX(capi_drivers_lock);
63
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

--- 47 unchanged lines hidden (view full) ---

56static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
57static char capi_manufakturer[64] = "AVM Berlin";
58
59#define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
60
61LIST_HEAD(capi_drivers);
62DEFINE_MUTEX(capi_drivers_lock);
63
64struct capi_ctr *capi_controller[CAPI_MAXCONTR];
65DEFINE_MUTEX(capi_controller_lock);
66
64static DEFINE_RWLOCK(application_lock);
67static DEFINE_RWLOCK(application_lock);
65static DEFINE_MUTEX(controller_mutex);
66
67struct capi20_appl *capi_applications[CAPI_MAXAPPL];
68
69struct capi20_appl *capi_applications[CAPI_MAXAPPL];
68struct capi_ctr *capi_controller[CAPI_MAXCONTR];
69
70static int ncontrollers;
71
72static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);
73
74/* -------- controller ref counting -------------------------------------- */
75
76static inline struct capi_ctr *

--- 89 unchanged lines hidden (view full) ---

166}
167
168static void notify_up(u32 contr)
169{
170 struct capi20_appl *ap;
171 struct capi_ctr *ctr;
172 u16 applid;
173
70
71static int ncontrollers;
72
73static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);
74
75/* -------- controller ref counting -------------------------------------- */
76
77static inline struct capi_ctr *

--- 89 unchanged lines hidden (view full) ---

167}
168
169static void notify_up(u32 contr)
170{
171 struct capi20_appl *ap;
172 struct capi_ctr *ctr;
173 u16 applid;
174
175 mutex_lock(&capi_controller_lock);
176
174 if (showcapimsgs & 1)
175 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
176
177 ctr = get_capi_ctr_by_nr(contr);
178 if (ctr) {
179 if (ctr->state == CAPI_CTR_RUNNING)
177 if (showcapimsgs & 1)
178 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
179
180 ctr = get_capi_ctr_by_nr(contr);
181 if (ctr) {
182 if (ctr->state == CAPI_CTR_RUNNING)
180 return;
183 goto unlock_out;
181
182 ctr->state = CAPI_CTR_RUNNING;
183
184 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
185 ap = get_capi_appl_by_nr(applid);
186 if (!ap || ap->release_in_progress)
187 continue;
188 register_appl(ctr, applid, &ap->rparam);
189 }
184
185 ctr->state = CAPI_CTR_RUNNING;
186
187 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
188 ap = get_capi_appl_by_nr(applid);
189 if (!ap || ap->release_in_progress)
190 continue;
191 register_appl(ctr, applid, &ap->rparam);
192 }
193
194 wake_up_interruptible_all(&ctr->state_wait_queue);
190 } else
191 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
195 } else
196 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
197
198unlock_out:
199 mutex_unlock(&capi_controller_lock);
192}
193
200}
201
194static void ctr_down(struct capi_ctr *ctr)
202static void ctr_down(struct capi_ctr *ctr, int new_state)
195{
196 struct capi20_appl *ap;
197 u16 applid;
198
203{
204 struct capi20_appl *ap;
205 u16 applid;
206
199 if (ctr->state == CAPI_CTR_DETECTED)
207 if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED)
200 return;
201
208 return;
209
202 ctr->state = CAPI_CTR_DETECTED;
210 ctr->state = new_state;
203
204 memset(ctr->manu, 0, sizeof(ctr->manu));
205 memset(&ctr->version, 0, sizeof(ctr->version));
206 memset(&ctr->profile, 0, sizeof(ctr->profile));
207 memset(ctr->serial, 0, sizeof(ctr->serial));
208
209 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
210 ap = get_capi_appl_by_nr(applid);
211 if (ap && !ap->release_in_progress)
212 capi_ctr_put(ctr);
213 }
211
212 memset(ctr->manu, 0, sizeof(ctr->manu));
213 memset(&ctr->version, 0, sizeof(ctr->version));
214 memset(&ctr->profile, 0, sizeof(ctr->profile));
215 memset(ctr->serial, 0, sizeof(ctr->serial));
216
217 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
218 ap = get_capi_appl_by_nr(applid);
219 if (ap && !ap->release_in_progress)
220 capi_ctr_put(ctr);
221 }
222
223 wake_up_interruptible_all(&ctr->state_wait_queue);
214}
215
216static void notify_down(u32 contr)
217{
218 struct capi_ctr *ctr;
219
224}
225
226static void notify_down(u32 contr)
227{
228 struct capi_ctr *ctr;
229
230 mutex_lock(&capi_controller_lock);
231
220 if (showcapimsgs & 1)
221 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
222
223 ctr = get_capi_ctr_by_nr(contr);
224 if (ctr)
232 if (showcapimsgs & 1)
233 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
234
235 ctr = get_capi_ctr_by_nr(contr);
236 if (ctr)
225 ctr_down(ctr);
237 ctr_down(ctr, CAPI_CTR_DETECTED);
226 else
227 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
238 else
239 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
240
241 mutex_unlock(&capi_controller_lock);
228}
229
230static int
231notify_handler(struct notifier_block *nb, unsigned long val, void *v)
232{
233 u32 contr = (long)v;
234
235 switch (val) {

--- 195 unchanged lines hidden (view full) ---

431
432EXPORT_SYMBOL(capi_ctr_down);
433
434/**
435 * capi_ctr_suspend_output() - suspend controller
436 * @ctr: controller descriptor structure.
437 *
438 * Called by hardware driver to stop data flow.
242}
243
244static int
245notify_handler(struct notifier_block *nb, unsigned long val, void *v)
246{
247 u32 contr = (long)v;
248
249 switch (val) {

--- 195 unchanged lines hidden (view full) ---

445
446EXPORT_SYMBOL(capi_ctr_down);
447
448/**
449 * capi_ctr_suspend_output() - suspend controller
450 * @ctr: controller descriptor structure.
451 *
452 * Called by hardware driver to stop data flow.
453 *
454 * Note: The caller is responsible for synchronizing concurrent state changes
455 * as well as invocations of capi_ctr_handle_message.
439 */
440
441void capi_ctr_suspend_output(struct capi_ctr *ctr)
442{
443 if (!ctr->blocked) {
444 printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n",
445 ctr->cnr);
446 ctr->blocked = 1;
447 }
448}
449
450EXPORT_SYMBOL(capi_ctr_suspend_output);
451
452/**
453 * capi_ctr_resume_output() - resume controller
454 * @ctr: controller descriptor structure.
455 *
456 * Called by hardware driver to resume data flow.
456 */
457
458void capi_ctr_suspend_output(struct capi_ctr *ctr)
459{
460 if (!ctr->blocked) {
461 printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n",
462 ctr->cnr);
463 ctr->blocked = 1;
464 }
465}
466
467EXPORT_SYMBOL(capi_ctr_suspend_output);
468
469/**
470 * capi_ctr_resume_output() - resume controller
471 * @ctr: controller descriptor structure.
472 *
473 * Called by hardware driver to resume data flow.
474 *
475 * Note: The caller is responsible for synchronizing concurrent state changes
476 * as well as invocations of capi_ctr_handle_message.
457 */
458
459void capi_ctr_resume_output(struct capi_ctr *ctr)
460{
461 if (ctr->blocked) {
462 printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n",
463 ctr->cnr);
464 ctr->blocked = 0;

--- 11 unchanged lines hidden (view full) ---

476 * Called by hardware driver to register a controller with the CAPI subsystem.
477 * Return value: 0 on success, error code < 0 on error
478 */
479
480int attach_capi_ctr(struct capi_ctr *ctr)
481{
482 int i;
483
477 */
478
479void capi_ctr_resume_output(struct capi_ctr *ctr)
480{
481 if (ctr->blocked) {
482 printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n",
483 ctr->cnr);
484 ctr->blocked = 0;

--- 11 unchanged lines hidden (view full) ---

496 * Called by hardware driver to register a controller with the CAPI subsystem.
497 * Return value: 0 on success, error code < 0 on error
498 */
499
500int attach_capi_ctr(struct capi_ctr *ctr)
501{
502 int i;
503
484 mutex_lock(&controller_mutex);
504 mutex_lock(&capi_controller_lock);
485
486 for (i = 0; i < CAPI_MAXCONTR; i++) {
487 if (!capi_controller[i])
488 break;
489 }
490 if (i == CAPI_MAXCONTR) {
505
506 for (i = 0; i < CAPI_MAXCONTR; i++) {
507 if (!capi_controller[i])
508 break;
509 }
510 if (i == CAPI_MAXCONTR) {
491 mutex_unlock(&controller_mutex);
511 mutex_unlock(&capi_controller_lock);
492 printk(KERN_ERR "kcapi: out of controller slots\n");
493 return -EBUSY;
494 }
495 capi_controller[i] = ctr;
496
512 printk(KERN_ERR "kcapi: out of controller slots\n");
513 return -EBUSY;
514 }
515 capi_controller[i] = ctr;
516
497 mutex_unlock(&controller_mutex);
498
499 ctr->nrecvctlpkt = 0;
500 ctr->nrecvdatapkt = 0;
501 ctr->nsentctlpkt = 0;
502 ctr->nsentdatapkt = 0;
503 ctr->cnr = i + 1;
504 ctr->state = CAPI_CTR_DETECTED;
505 ctr->blocked = 0;
506 ctr->traceflag = showcapimsgs;
517 ctr->nrecvctlpkt = 0;
518 ctr->nrecvdatapkt = 0;
519 ctr->nsentctlpkt = 0;
520 ctr->nsentdatapkt = 0;
521 ctr->cnr = i + 1;
522 ctr->state = CAPI_CTR_DETECTED;
523 ctr->blocked = 0;
524 ctr->traceflag = showcapimsgs;
525 init_waitqueue_head(&ctr->state_wait_queue);
507
508 sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
509 ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr);
510
511 ncontrollers++;
526
527 sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
528 ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr);
529
530 ncontrollers++;
531
532 mutex_unlock(&capi_controller_lock);
533
512 printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
513 ctr->cnr, ctr->name);
514 return 0;
515}
516
517EXPORT_SYMBOL(attach_capi_ctr);
518
519/**
520 * detach_capi_ctr() - unregister CAPI controller
521 * @ctr: controller descriptor structure.
522 *
523 * Called by hardware driver to remove the registration of a controller
524 * with the CAPI subsystem.
525 * Return value: 0 on success, error code < 0 on error
526 */
527
528int detach_capi_ctr(struct capi_ctr *ctr)
529{
534 printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
535 ctr->cnr, ctr->name);
536 return 0;
537}
538
539EXPORT_SYMBOL(attach_capi_ctr);
540
541/**
542 * detach_capi_ctr() - unregister CAPI controller
543 * @ctr: controller descriptor structure.
544 *
545 * Called by hardware driver to remove the registration of a controller
546 * with the CAPI subsystem.
547 * Return value: 0 on success, error code < 0 on error
548 */
549
550int detach_capi_ctr(struct capi_ctr *ctr)
551{
530 ctr_down(ctr);
552 int err = 0;
531
553
532 ncontrollers--;
554 mutex_lock(&capi_controller_lock);
533
555
534 if (ctr->procent) {
535 remove_proc_entry(ctr->procfn, NULL);
536 ctr->procent = NULL;
556 ctr_down(ctr, CAPI_CTR_DETACHED);
557
558 if (capi_controller[ctr->cnr - 1] != ctr) {
559 err = -EINVAL;
560 goto unlock_out;
537 }
538 capi_controller[ctr->cnr - 1] = NULL;
561 }
562 capi_controller[ctr->cnr - 1] = NULL;
563 ncontrollers--;
564
565 if (ctr->procent)
566 remove_proc_entry(ctr->procfn, NULL);
567
539 printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
540 ctr->cnr, ctr->name);
541
568 printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
569 ctr->cnr, ctr->name);
570
542 return 0;
571unlock_out:
572 mutex_unlock(&capi_controller_lock);
573
574 return err;
543}
544
545EXPORT_SYMBOL(detach_capi_ctr);
546
547/**
548 * register_capi_driver() - register CAPI driver
549 * @driver: driver descriptor structure.
550 *

--- 33 unchanged lines hidden (view full) ---

584 * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED
585 *
586 * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller
587 * is ready for use, CAPI_REGNOTINSTALLED otherwise)
588 */
589
590u16 capi20_isinstalled(void)
591{
575}
576
577EXPORT_SYMBOL(detach_capi_ctr);
578
579/**
580 * register_capi_driver() - register CAPI driver
581 * @driver: driver descriptor structure.
582 *

--- 33 unchanged lines hidden (view full) ---

616 * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED
617 *
618 * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller
619 * is ready for use, CAPI_REGNOTINSTALLED otherwise)
620 */
621
622u16 capi20_isinstalled(void)
623{
624 u16 ret = CAPI_REGNOTINSTALLED;
592 int i;
625 int i;
593 for (i = 0; i < CAPI_MAXCONTR; i++) {
626
627 mutex_lock(&capi_controller_lock);
628
629 for (i = 0; i < CAPI_MAXCONTR; i++)
594 if (capi_controller[i] &&
630 if (capi_controller[i] &&
595 capi_controller[i]->state == CAPI_CTR_RUNNING)
596 return CAPI_NOERROR;
597 }
598 return CAPI_REGNOTINSTALLED;
631 capi_controller[i]->state == CAPI_CTR_RUNNING) {
632 ret = CAPI_NOERROR;
633 break;
634 }
635
636 mutex_unlock(&capi_controller_lock);
637
638 return ret;
599}
600
601EXPORT_SYMBOL(capi20_isinstalled);
602
603/**
604 * capi20_register() - CAPI 2.0 operation CAPI_REGISTER
605 * @ap: CAPI application descriptor structure.
606 *

--- 36 unchanged lines hidden (view full) ---

643 ap->nsentdatapkt = 0;
644 mutex_init(&ap->recv_mtx);
645 skb_queue_head_init(&ap->recv_queue);
646 INIT_WORK(&ap->recv_work, recv_handler);
647 ap->release_in_progress = 0;
648
649 write_unlock_irqrestore(&application_lock, flags);
650
639}
640
641EXPORT_SYMBOL(capi20_isinstalled);
642
643/**
644 * capi20_register() - CAPI 2.0 operation CAPI_REGISTER
645 * @ap: CAPI application descriptor structure.
646 *

--- 36 unchanged lines hidden (view full) ---

683 ap->nsentdatapkt = 0;
684 mutex_init(&ap->recv_mtx);
685 skb_queue_head_init(&ap->recv_queue);
686 INIT_WORK(&ap->recv_work, recv_handler);
687 ap->release_in_progress = 0;
688
689 write_unlock_irqrestore(&application_lock, flags);
690
651 mutex_lock(&controller_mutex);
691 mutex_lock(&capi_controller_lock);
692
652 for (i = 0; i < CAPI_MAXCONTR; i++) {
653 if (!capi_controller[i] ||
654 capi_controller[i]->state != CAPI_CTR_RUNNING)
655 continue;
656 register_appl(capi_controller[i], applid, &ap->rparam);
657 }
693 for (i = 0; i < CAPI_MAXCONTR; i++) {
694 if (!capi_controller[i] ||
695 capi_controller[i]->state != CAPI_CTR_RUNNING)
696 continue;
697 register_appl(capi_controller[i], applid, &ap->rparam);
698 }
658 mutex_unlock(&controller_mutex);
659
699
700 mutex_unlock(&capi_controller_lock);
701
660 if (showcapimsgs & 1) {
661 printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
662 }
663
664 return CAPI_NOERROR;
665}
666
667EXPORT_SYMBOL(capi20_register);

--- 15 unchanged lines hidden (view full) ---

683
684 DBG("applid %#x", ap->applid);
685
686 write_lock_irqsave(&application_lock, flags);
687 ap->release_in_progress = 1;
688 capi_applications[ap->applid - 1] = NULL;
689 write_unlock_irqrestore(&application_lock, flags);
690
702 if (showcapimsgs & 1) {
703 printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
704 }
705
706 return CAPI_NOERROR;
707}
708
709EXPORT_SYMBOL(capi20_register);

--- 15 unchanged lines hidden (view full) ---

725
726 DBG("applid %#x", ap->applid);
727
728 write_lock_irqsave(&application_lock, flags);
729 ap->release_in_progress = 1;
730 capi_applications[ap->applid - 1] = NULL;
731 write_unlock_irqrestore(&application_lock, flags);
732
691 mutex_lock(&controller_mutex);
733 mutex_lock(&capi_controller_lock);
734
692 for (i = 0; i < CAPI_MAXCONTR; i++) {
693 if (!capi_controller[i] ||
694 capi_controller[i]->state != CAPI_CTR_RUNNING)
695 continue;
696 release_appl(capi_controller[i], ap->applid);
697 }
735 for (i = 0; i < CAPI_MAXCONTR; i++) {
736 if (!capi_controller[i] ||
737 capi_controller[i]->state != CAPI_CTR_RUNNING)
738 continue;
739 release_appl(capi_controller[i], ap->applid);
740 }
698 mutex_unlock(&controller_mutex);
699
741
742 mutex_unlock(&capi_controller_lock);
743
700 flush_scheduled_work();
701 skb_queue_purge(&ap->recv_queue);
702
703 if (showcapimsgs & 1) {
704 printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
705 }
706
707 return CAPI_NOERROR;

--- 21 unchanged lines hidden (view full) ---

729 if (ncontrollers == 0)
730 return CAPI_REGNOTINSTALLED;
731 if ((ap->applid == 0) || ap->release_in_progress)
732 return CAPI_ILLAPPNR;
733 if (skb->len < 12
734 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
735 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
736 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
744 flush_scheduled_work();
745 skb_queue_purge(&ap->recv_queue);
746
747 if (showcapimsgs & 1) {
748 printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
749 }
750
751 return CAPI_NOERROR;

--- 21 unchanged lines hidden (view full) ---

773 if (ncontrollers == 0)
774 return CAPI_REGNOTINSTALLED;
775 if ((ap->applid == 0) || ap->release_in_progress)
776 return CAPI_ILLAPPNR;
777 if (skb->len < 12
778 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
779 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
780 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
781
782 /*
783 * The controller reference is protected by the existence of the
784 * application passed to us. We assume that the caller properly
785 * synchronizes this service with capi20_release.
786 */
737 ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
738 if (!ctr || ctr->state != CAPI_CTR_RUNNING) {
739 ctr = get_capi_ctr_by_nr(1); /* XXX why? */
740 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
741 return CAPI_REGNOTINSTALLED;
742 }
743 if (ctr->blocked)
744 return CAPI_SENDQUEUEFULL;

--- 48 unchanged lines hidden (view full) ---

793 * Retrieve information about the manufacturer of the specified ISDN controller
794 * or (for @contr == 0) the driver itself.
795 * Return value: CAPI result code
796 */
797
798u16 capi20_get_manufacturer(u32 contr, u8 *buf)
799{
800 struct capi_ctr *ctr;
787 ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
788 if (!ctr || ctr->state != CAPI_CTR_RUNNING) {
789 ctr = get_capi_ctr_by_nr(1); /* XXX why? */
790 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
791 return CAPI_REGNOTINSTALLED;
792 }
793 if (ctr->blocked)
794 return CAPI_SENDQUEUEFULL;

--- 48 unchanged lines hidden (view full) ---

843 * Retrieve information about the manufacturer of the specified ISDN controller
844 * or (for @contr == 0) the driver itself.
845 * Return value: CAPI result code
846 */
847
848u16 capi20_get_manufacturer(u32 contr, u8 *buf)
849{
850 struct capi_ctr *ctr;
851 u16 ret;
801
802 if (contr == 0) {
803 strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
804 return CAPI_NOERROR;
805 }
852
853 if (contr == 0) {
854 strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
855 return CAPI_NOERROR;
856 }
857
858 mutex_lock(&capi_controller_lock);
859
806 ctr = get_capi_ctr_by_nr(contr);
860 ctr = get_capi_ctr_by_nr(contr);
807 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
808 return CAPI_REGNOTINSTALLED;
809 strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
810 return CAPI_NOERROR;
861 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
862 strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
863 ret = CAPI_NOERROR;
864 } else
865 ret = CAPI_REGNOTINSTALLED;
866
867 mutex_unlock(&capi_controller_lock);
868 return ret;
811}
812
813EXPORT_SYMBOL(capi20_get_manufacturer);
814
815/**
816 * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION
817 * @contr: controller number.
818 * @verp: result structure.
819 *
820 * Retrieve version information for the specified ISDN controller
821 * or (for @contr == 0) the driver itself.
822 * Return value: CAPI result code
823 */
824
825u16 capi20_get_version(u32 contr, struct capi_version *verp)
826{
827 struct capi_ctr *ctr;
869}
870
871EXPORT_SYMBOL(capi20_get_manufacturer);
872
873/**
874 * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION
875 * @contr: controller number.
876 * @verp: result structure.
877 *
878 * Retrieve version information for the specified ISDN controller
879 * or (for @contr == 0) the driver itself.
880 * Return value: CAPI result code
881 */
882
883u16 capi20_get_version(u32 contr, struct capi_version *verp)
884{
885 struct capi_ctr *ctr;
886 u16 ret;
828
829 if (contr == 0) {
830 *verp = driver_version;
831 return CAPI_NOERROR;
832 }
887
888 if (contr == 0) {
889 *verp = driver_version;
890 return CAPI_NOERROR;
891 }
892
893 mutex_lock(&capi_controller_lock);
894
833 ctr = get_capi_ctr_by_nr(contr);
895 ctr = get_capi_ctr_by_nr(contr);
834 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
835 return CAPI_REGNOTINSTALLED;
896 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
897 memcpy(verp, &ctr->version, sizeof(capi_version));
898 ret = CAPI_NOERROR;
899 } else
900 ret = CAPI_REGNOTINSTALLED;
836
901
837 memcpy(verp, &ctr->version, sizeof(capi_version));
838 return CAPI_NOERROR;
902 mutex_unlock(&capi_controller_lock);
903 return ret;
839}
840
841EXPORT_SYMBOL(capi20_get_version);
842
843/**
844 * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER
845 * @contr: controller number.
846 * @serial: result buffer (8 bytes).
847 *
848 * Retrieve the serial number of the specified ISDN controller
849 * or (for @contr == 0) the driver itself.
850 * Return value: CAPI result code
851 */
852
853u16 capi20_get_serial(u32 contr, u8 *serial)
854{
855 struct capi_ctr *ctr;
904}
905
906EXPORT_SYMBOL(capi20_get_version);
907
908/**
909 * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER
910 * @contr: controller number.
911 * @serial: result buffer (8 bytes).
912 *
913 * Retrieve the serial number of the specified ISDN controller
914 * or (for @contr == 0) the driver itself.
915 * Return value: CAPI result code
916 */
917
918u16 capi20_get_serial(u32 contr, u8 *serial)
919{
920 struct capi_ctr *ctr;
921 u16 ret;
856
857 if (contr == 0) {
858 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
859 return CAPI_NOERROR;
860 }
922
923 if (contr == 0) {
924 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
925 return CAPI_NOERROR;
926 }
927
928 mutex_lock(&capi_controller_lock);
929
861 ctr = get_capi_ctr_by_nr(contr);
930 ctr = get_capi_ctr_by_nr(contr);
862 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
863 return CAPI_REGNOTINSTALLED;
931 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
932 strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
933 ret = CAPI_NOERROR;
934 } else
935 ret = CAPI_REGNOTINSTALLED;
864
936
865 strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
866 return CAPI_NOERROR;
937 mutex_unlock(&capi_controller_lock);
938 return ret;
867}
868
869EXPORT_SYMBOL(capi20_get_serial);
870
871/**
872 * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE
873 * @contr: controller number.
874 * @profp: result structure.
875 *
876 * Retrieve capability information for the specified ISDN controller
877 * or (for @contr == 0) the number of installed controllers.
878 * Return value: CAPI result code
879 */
880
881u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
882{
883 struct capi_ctr *ctr;
939}
940
941EXPORT_SYMBOL(capi20_get_serial);
942
943/**
944 * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE
945 * @contr: controller number.
946 * @profp: result structure.
947 *
948 * Retrieve capability information for the specified ISDN controller
949 * or (for @contr == 0) the number of installed controllers.
950 * Return value: CAPI result code
951 */
952
953u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
954{
955 struct capi_ctr *ctr;
956 u16 ret;
884
885 if (contr == 0) {
886 profp->ncontroller = ncontrollers;
887 return CAPI_NOERROR;
888 }
957
958 if (contr == 0) {
959 profp->ncontroller = ncontrollers;
960 return CAPI_NOERROR;
961 }
962
963 mutex_lock(&capi_controller_lock);
964
889 ctr = get_capi_ctr_by_nr(contr);
965 ctr = get_capi_ctr_by_nr(contr);
890 if (!ctr || ctr->state != CAPI_CTR_RUNNING)
891 return CAPI_REGNOTINSTALLED;
966 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
967 memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
968 ret = CAPI_NOERROR;
969 } else
970 ret = CAPI_REGNOTINSTALLED;
892
971
893 memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
894 return CAPI_NOERROR;
972 mutex_unlock(&capi_controller_lock);
973 return ret;
895}
896
897EXPORT_SYMBOL(capi20_get_profile);
898
974}
975
976EXPORT_SYMBOL(capi20_get_profile);
977
978/* Must be called with capi_controller_lock held. */
979static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state)
980{
981 DEFINE_WAIT(wait);
982 int retval = 0;
983
984 ctr = capi_ctr_get(ctr);
985 if (!ctr)
986 return -ESRCH;
987
988 for (;;) {
989 prepare_to_wait(&ctr->state_wait_queue, &wait,
990 TASK_INTERRUPTIBLE);
991
992 if (ctr->state == state)
993 break;
994 if (ctr->state == CAPI_CTR_DETACHED) {
995 retval = -ESRCH;
996 break;
997 }
998 if (signal_pending(current)) {
999 retval = -EINTR;
1000 break;
1001 }
1002
1003 mutex_unlock(&capi_controller_lock);
1004 schedule();
1005 mutex_lock(&capi_controller_lock);
1006 }
1007 finish_wait(&ctr->state_wait_queue, &wait);
1008
1009 capi_ctr_put(ctr);
1010
1011 return retval;
1012}
1013
899#ifdef AVMB1_COMPAT
900static int old_capi_manufacturer(unsigned int cmd, void __user *data)
901{
902 avmb1_loadandconfigdef ldef;
903 avmb1_extcarddef cdef;
904 avmb1_resetdef rdef;
905 capicardparams cparams;
906 struct capi_ctr *ctr;

--- 61 unchanged lines hidden (view full) ---

968 return -EFAULT;
969 ldef.t4config.len = 0;
970 ldef.t4config.data = NULL;
971 } else {
972 if (copy_from_user(&ldef, data,
973 sizeof(avmb1_loadandconfigdef)))
974 return -EFAULT;
975 }
1014#ifdef AVMB1_COMPAT
1015static int old_capi_manufacturer(unsigned int cmd, void __user *data)
1016{
1017 avmb1_loadandconfigdef ldef;
1018 avmb1_extcarddef cdef;
1019 avmb1_resetdef rdef;
1020 capicardparams cparams;
1021 struct capi_ctr *ctr;

--- 61 unchanged lines hidden (view full) ---

1083 return -EFAULT;
1084 ldef.t4config.len = 0;
1085 ldef.t4config.data = NULL;
1086 } else {
1087 if (copy_from_user(&ldef, data,
1088 sizeof(avmb1_loadandconfigdef)))
1089 return -EFAULT;
1090 }
1091
1092 mutex_lock(&capi_controller_lock);
1093
976 ctr = get_capi_ctr_by_nr(ldef.contr);
1094 ctr = get_capi_ctr_by_nr(ldef.contr);
977 if (!ctr)
978 return -EINVAL;
979 ctr = capi_ctr_get(ctr);
980 if (!ctr)
981 return -ESRCH;
1095 if (!ctr) {
1096 retval = -EINVAL;
1097 goto load_unlock_out;
1098 }
1099
982 if (ctr->load_firmware == NULL) {
983 printk(KERN_DEBUG "kcapi: load: no load function\n");
1100 if (ctr->load_firmware == NULL) {
1101 printk(KERN_DEBUG "kcapi: load: no load function\n");
984 capi_ctr_put(ctr);
985 return -ESRCH;
1102 retval = -ESRCH;
1103 goto load_unlock_out;
986 }
987
988 if (ldef.t4file.len <= 0) {
989 printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
1104 }
1105
1106 if (ldef.t4file.len <= 0) {
1107 printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
990 capi_ctr_put(ctr);
991 return -EINVAL;
1108 retval = -EINVAL;
1109 goto load_unlock_out;
992 }
993 if (ldef.t4file.data == NULL) {
994 printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
1110 }
1111 if (ldef.t4file.data == NULL) {
1112 printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
995 capi_ctr_put(ctr);
996 return -EINVAL;
1113 retval = -EINVAL;
1114 goto load_unlock_out;
997 }
998
999 ldata.firmware.user = 1;
1000 ldata.firmware.data = ldef.t4file.data;
1001 ldata.firmware.len = ldef.t4file.len;
1002 ldata.configuration.user = 1;
1003 ldata.configuration.data = ldef.t4config.data;
1004 ldata.configuration.len = ldef.t4config.len;
1005
1006 if (ctr->state != CAPI_CTR_DETECTED) {
1007 printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
1115 }
1116
1117 ldata.firmware.user = 1;
1118 ldata.firmware.data = ldef.t4file.data;
1119 ldata.firmware.len = ldef.t4file.len;
1120 ldata.configuration.user = 1;
1121 ldata.configuration.data = ldef.t4config.data;
1122 ldata.configuration.len = ldef.t4config.len;
1123
1124 if (ctr->state != CAPI_CTR_DETECTED) {
1125 printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
1008 capi_ctr_put(ctr);
1009 return -EBUSY;
1126 retval = -EBUSY;
1127 goto load_unlock_out;
1010 }
1011 ctr->state = CAPI_CTR_LOADING;
1012
1013 retval = ctr->load_firmware(ctr, &ldata);
1128 }
1129 ctr->state = CAPI_CTR_LOADING;
1130
1131 retval = ctr->load_firmware(ctr, &ldata);
1014
1015 if (retval) {
1016 ctr->state = CAPI_CTR_DETECTED;
1132 if (retval) {
1133 ctr->state = CAPI_CTR_DETECTED;
1017 capi_ctr_put(ctr);
1018 return retval;
1134 goto load_unlock_out;
1019 }
1020
1135 }
1136
1021 while (ctr->state != CAPI_CTR_RUNNING) {
1137 retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING);
1022
1138
1023 msleep_interruptible(100); /* 0.1 sec */
1139load_unlock_out:
1140 mutex_unlock(&capi_controller_lock);
1141 return retval;
1024
1142
1025 if (signal_pending(current)) {
1026 capi_ctr_put(ctr);
1027 return -EINTR;
1028 }
1029 }
1030 capi_ctr_put(ctr);
1031 return 0;
1032
1033 case AVMB1_RESETCARD:
1034 if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
1035 return -EFAULT;
1143 case AVMB1_RESETCARD:
1144 if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
1145 return -EFAULT;
1146
1147 retval = 0;
1148
1149 mutex_lock(&capi_controller_lock);
1150
1036 ctr = get_capi_ctr_by_nr(rdef.contr);
1151 ctr = get_capi_ctr_by_nr(rdef.contr);
1037 if (!ctr)
1038 return -ESRCH;
1152 if (!ctr) {
1153 retval = -ESRCH;
1154 goto reset_unlock_out;
1155 }
1039
1040 if (ctr->state == CAPI_CTR_DETECTED)
1156
1157 if (ctr->state == CAPI_CTR_DETECTED)
1041 return 0;
1158 goto reset_unlock_out;
1042
1043 ctr->reset_ctr(ctr);
1044
1159
1160 ctr->reset_ctr(ctr);
1161
1045 while (ctr->state > CAPI_CTR_DETECTED) {
1162 retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
1046
1163
1047 msleep_interruptible(100); /* 0.1 sec */
1048
1049 if (signal_pending(current))
1050 return -EINTR;
1051 }
1052 return 0;
1053
1164reset_unlock_out:
1165 mutex_unlock(&capi_controller_lock);
1166 return retval;
1054 }
1055 return -EINVAL;
1056}
1057#endif
1058
1059/**
1060 * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER
1061 * @cmd: command.
1062 * @data: parameter.
1063 *
1064 * Perform manufacturer specific command.
1065 * Return value: CAPI result code
1066 */
1067
1068int capi20_manufacturer(unsigned int cmd, void __user *data)
1069{
1070 struct capi_ctr *ctr;
1167 }
1168 return -EINVAL;
1169}
1170#endif
1171
1172/**
1173 * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER
1174 * @cmd: command.
1175 * @data: parameter.
1176 *
1177 * Perform manufacturer specific command.
1178 * Return value: CAPI result code
1179 */
1180
1181int capi20_manufacturer(unsigned int cmd, void __user *data)
1182{
1183 struct capi_ctr *ctr;
1184 int retval;
1071
1072 switch (cmd) {
1073#ifdef AVMB1_COMPAT
1074 case AVMB1_LOAD:
1075 case AVMB1_LOAD_AND_CONFIG:
1076 case AVMB1_RESETCARD:
1077 case AVMB1_GET_CARDINFO:
1078 case AVMB1_REMOVECARD:
1079 return old_capi_manufacturer(cmd, data);
1080#endif
1081 case KCAPI_CMD_TRACE:
1082 {
1083 kcapi_flagdef fdef;
1084
1085 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
1086 return -EFAULT;
1087
1185
1186 switch (cmd) {
1187#ifdef AVMB1_COMPAT
1188 case AVMB1_LOAD:
1189 case AVMB1_LOAD_AND_CONFIG:
1190 case AVMB1_RESETCARD:
1191 case AVMB1_GET_CARDINFO:
1192 case AVMB1_REMOVECARD:
1193 return old_capi_manufacturer(cmd, data);
1194#endif
1195 case KCAPI_CMD_TRACE:
1196 {
1197 kcapi_flagdef fdef;
1198
1199 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
1200 return -EFAULT;
1201
1202 mutex_lock(&capi_controller_lock);
1203
1088 ctr = get_capi_ctr_by_nr(fdef.contr);
1204 ctr = get_capi_ctr_by_nr(fdef.contr);
1089 if (!ctr)
1090 return -ESRCH;
1205 if (ctr) {
1206 ctr->traceflag = fdef.flag;
1207 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
1208 ctr->cnr, ctr->traceflag);
1209 retval = 0;
1210 } else
1211 retval = -ESRCH;
1091
1212
1092 ctr->traceflag = fdef.flag;
1093 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
1094 ctr->cnr, ctr->traceflag);
1095 return 0;
1213 mutex_unlock(&capi_controller_lock);
1214
1215 return retval;
1096 }
1097 case KCAPI_CMD_ADDCARD:
1098 {
1099 struct list_head *l;
1100 struct capi_driver *driver = NULL;
1101 capicardparams cparams;
1102 kcapi_carddef cdef;
1216 }
1217 case KCAPI_CMD_ADDCARD:
1218 {
1219 struct list_head *l;
1220 struct capi_driver *driver = NULL;
1221 capicardparams cparams;
1222 kcapi_carddef cdef;
1103 int retval;
1104
1105 if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
1106 return retval;
1107
1108 cparams.port = cdef.port;
1109 cparams.irq = cdef.irq;
1110 cparams.membase = cdef.membase;
1111 cparams.cardnr = cdef.cardnr;

--- 71 unchanged lines hidden ---
1223
1224 if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
1225 return retval;
1226
1227 cparams.port = cdef.port;
1228 cparams.irq = cdef.irq;
1229 cparams.membase = cdef.membase;
1230 cparams.cardnr = cdef.cardnr;

--- 71 unchanged lines hidden ---