.. | .. |
---|
10 | 10 | * |
---|
11 | 11 | */ |
---|
12 | 12 | |
---|
13 | | -#define AVMB1_COMPAT |
---|
14 | | - |
---|
15 | 13 | #include "kcapi.h" |
---|
16 | 14 | #include <linux/module.h> |
---|
17 | 15 | #include <linux/mm.h> |
---|
.. | .. |
---|
31 | 29 | #include <linux/uaccess.h> |
---|
32 | 30 | #include <linux/isdn/capicmd.h> |
---|
33 | 31 | #include <linux/isdn/capiutil.h> |
---|
34 | | -#ifdef AVMB1_COMPAT |
---|
35 | | -#include <linux/b1lli.h> |
---|
36 | | -#endif |
---|
37 | 32 | #include <linux/mutex.h> |
---|
38 | 33 | #include <linux/rcupdate.h> |
---|
39 | 34 | |
---|
40 | 35 | static int showcapimsgs = 0; |
---|
41 | 36 | static struct workqueue_struct *kcapi_wq; |
---|
42 | 37 | |
---|
43 | | -MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); |
---|
44 | | -MODULE_AUTHOR("Carsten Paeth"); |
---|
45 | | -MODULE_LICENSE("GPL"); |
---|
46 | 38 | module_param(showcapimsgs, uint, 0); |
---|
47 | 39 | |
---|
48 | 40 | /* ------------------------------------------------------------- */ |
---|
.. | .. |
---|
61 | 53 | |
---|
62 | 54 | #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) |
---|
63 | 55 | |
---|
64 | | -LIST_HEAD(capi_drivers); |
---|
65 | | -DEFINE_MUTEX(capi_drivers_lock); |
---|
66 | | - |
---|
67 | 56 | struct capi_ctr *capi_controller[CAPI_MAXCONTR]; |
---|
68 | 57 | DEFINE_MUTEX(capi_controller_lock); |
---|
69 | 58 | |
---|
70 | 59 | struct capi20_appl *capi_applications[CAPI_MAXAPPL]; |
---|
71 | 60 | |
---|
72 | 61 | static int ncontrollers; |
---|
73 | | - |
---|
74 | | -static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); |
---|
75 | 62 | |
---|
76 | 63 | /* -------- controller ref counting -------------------------------------- */ |
---|
77 | 64 | |
---|
.. | .. |
---|
200 | 187 | if (ap) |
---|
201 | 188 | register_appl(ctr, applid, &ap->rparam); |
---|
202 | 189 | } |
---|
203 | | - |
---|
204 | | - wake_up_interruptible_all(&ctr->state_wait_queue); |
---|
205 | 190 | } else |
---|
206 | 191 | printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); |
---|
207 | 192 | |
---|
.. | .. |
---|
229 | 214 | if (ap) |
---|
230 | 215 | capi_ctr_put(ctr); |
---|
231 | 216 | } |
---|
232 | | - |
---|
233 | | - wake_up_interruptible_all(&ctr->state_wait_queue); |
---|
234 | 217 | } |
---|
235 | 218 | |
---|
236 | 219 | static void notify_down(u32 contr) |
---|
.. | .. |
---|
251 | 234 | mutex_unlock(&capi_controller_lock); |
---|
252 | 235 | } |
---|
253 | 236 | |
---|
254 | | -static int |
---|
255 | | -notify_handler(struct notifier_block *nb, unsigned long val, void *v) |
---|
256 | | -{ |
---|
257 | | - u32 contr = (long)v; |
---|
258 | | - |
---|
259 | | - switch (val) { |
---|
260 | | - case CAPICTR_UP: |
---|
261 | | - notify_up(contr); |
---|
262 | | - break; |
---|
263 | | - case CAPICTR_DOWN: |
---|
264 | | - notify_down(contr); |
---|
265 | | - break; |
---|
266 | | - } |
---|
267 | | - return NOTIFY_OK; |
---|
268 | | -} |
---|
269 | | - |
---|
270 | 237 | static void do_notify_work(struct work_struct *work) |
---|
271 | 238 | { |
---|
272 | 239 | struct capictr_event *event = |
---|
273 | 240 | container_of(work, struct capictr_event, work); |
---|
274 | 241 | |
---|
275 | | - blocking_notifier_call_chain(&ctr_notifier_list, event->type, |
---|
276 | | - (void *)(long)event->controller); |
---|
| 242 | + switch (event->type) { |
---|
| 243 | + case CAPICTR_UP: |
---|
| 244 | + notify_up(event->controller); |
---|
| 245 | + break; |
---|
| 246 | + case CAPICTR_DOWN: |
---|
| 247 | + notify_down(event->controller); |
---|
| 248 | + break; |
---|
| 249 | + } |
---|
| 250 | + |
---|
277 | 251 | kfree(event); |
---|
278 | 252 | } |
---|
279 | 253 | |
---|
280 | | -/* |
---|
281 | | - * The notifier will result in adding/deleteing of devices. Devices can |
---|
282 | | - * only removed in user process, not in bh. |
---|
283 | | - */ |
---|
284 | 254 | static int notify_push(unsigned int event_type, u32 controller) |
---|
285 | 255 | { |
---|
286 | 256 | struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); |
---|
.. | .. |
---|
295 | 265 | queue_work(kcapi_wq, &event->work); |
---|
296 | 266 | return 0; |
---|
297 | 267 | } |
---|
298 | | - |
---|
299 | | -int register_capictr_notifier(struct notifier_block *nb) |
---|
300 | | -{ |
---|
301 | | - return blocking_notifier_chain_register(&ctr_notifier_list, nb); |
---|
302 | | -} |
---|
303 | | -EXPORT_SYMBOL_GPL(register_capictr_notifier); |
---|
304 | | - |
---|
305 | | -int unregister_capictr_notifier(struct notifier_block *nb) |
---|
306 | | -{ |
---|
307 | | - return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); |
---|
308 | | -} |
---|
309 | | -EXPORT_SYMBOL_GPL(unregister_capictr_notifier); |
---|
310 | 268 | |
---|
311 | 269 | /* -------- Receiver ------------------------------------------ */ |
---|
312 | 270 | |
---|
.. | .. |
---|
454 | 412 | |
---|
455 | 413 | EXPORT_SYMBOL(capi_ctr_down); |
---|
456 | 414 | |
---|
457 | | -/** |
---|
458 | | - * capi_ctr_suspend_output() - suspend controller |
---|
459 | | - * @ctr: controller descriptor structure. |
---|
460 | | - * |
---|
461 | | - * Called by hardware driver to stop data flow. |
---|
462 | | - * |
---|
463 | | - * Note: The caller is responsible for synchronizing concurrent state changes |
---|
464 | | - * as well as invocations of capi_ctr_handle_message. |
---|
465 | | - */ |
---|
466 | | - |
---|
467 | | -void capi_ctr_suspend_output(struct capi_ctr *ctr) |
---|
468 | | -{ |
---|
469 | | - if (!ctr->blocked) { |
---|
470 | | - printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", |
---|
471 | | - ctr->cnr); |
---|
472 | | - ctr->blocked = 1; |
---|
473 | | - } |
---|
474 | | -} |
---|
475 | | - |
---|
476 | | -EXPORT_SYMBOL(capi_ctr_suspend_output); |
---|
477 | | - |
---|
478 | | -/** |
---|
479 | | - * capi_ctr_resume_output() - resume controller |
---|
480 | | - * @ctr: controller descriptor structure. |
---|
481 | | - * |
---|
482 | | - * Called by hardware driver to resume data flow. |
---|
483 | | - * |
---|
484 | | - * Note: The caller is responsible for synchronizing concurrent state changes |
---|
485 | | - * as well as invocations of capi_ctr_handle_message. |
---|
486 | | - */ |
---|
487 | | - |
---|
488 | | -void capi_ctr_resume_output(struct capi_ctr *ctr) |
---|
489 | | -{ |
---|
490 | | - if (ctr->blocked) { |
---|
491 | | - printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", |
---|
492 | | - ctr->cnr); |
---|
493 | | - ctr->blocked = 0; |
---|
494 | | - } |
---|
495 | | -} |
---|
496 | | - |
---|
497 | | -EXPORT_SYMBOL(capi_ctr_resume_output); |
---|
498 | | - |
---|
499 | 415 | /* ------------------------------------------------------------- */ |
---|
500 | 416 | |
---|
501 | 417 | /** |
---|
.. | .. |
---|
531 | 447 | ctr->state = CAPI_CTR_DETECTED; |
---|
532 | 448 | ctr->blocked = 0; |
---|
533 | 449 | ctr->traceflag = showcapimsgs; |
---|
534 | | - init_waitqueue_head(&ctr->state_wait_queue); |
---|
535 | 450 | |
---|
536 | 451 | sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); |
---|
537 | 452 | ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL, |
---|
.. | .. |
---|
591 | 506 | |
---|
592 | 507 | EXPORT_SYMBOL(detach_capi_ctr); |
---|
593 | 508 | |
---|
594 | | -/** |
---|
595 | | - * register_capi_driver() - register CAPI driver |
---|
596 | | - * @driver: driver descriptor structure. |
---|
597 | | - * |
---|
598 | | - * Called by hardware driver to register itself with the CAPI subsystem. |
---|
599 | | - */ |
---|
600 | | - |
---|
601 | | -void register_capi_driver(struct capi_driver *driver) |
---|
602 | | -{ |
---|
603 | | - mutex_lock(&capi_drivers_lock); |
---|
604 | | - list_add_tail(&driver->list, &capi_drivers); |
---|
605 | | - mutex_unlock(&capi_drivers_lock); |
---|
606 | | -} |
---|
607 | | - |
---|
608 | | -EXPORT_SYMBOL(register_capi_driver); |
---|
609 | | - |
---|
610 | | -/** |
---|
611 | | - * unregister_capi_driver() - unregister CAPI driver |
---|
612 | | - * @driver: driver descriptor structure. |
---|
613 | | - * |
---|
614 | | - * Called by hardware driver to unregister itself from the CAPI subsystem. |
---|
615 | | - */ |
---|
616 | | - |
---|
617 | | -void unregister_capi_driver(struct capi_driver *driver) |
---|
618 | | -{ |
---|
619 | | - mutex_lock(&capi_drivers_lock); |
---|
620 | | - list_del(&driver->list); |
---|
621 | | - mutex_unlock(&capi_drivers_lock); |
---|
622 | | -} |
---|
623 | | - |
---|
624 | | -EXPORT_SYMBOL(unregister_capi_driver); |
---|
625 | | - |
---|
626 | 509 | /* ------------------------------------------------------------- */ |
---|
627 | 510 | /* -------- CAPI2.0 Interface ---------------------------------- */ |
---|
628 | 511 | /* ------------------------------------------------------------- */ |
---|
.. | .. |
---|
652 | 535 | |
---|
653 | 536 | return ret; |
---|
654 | 537 | } |
---|
655 | | - |
---|
656 | | -EXPORT_SYMBOL(capi20_isinstalled); |
---|
657 | 538 | |
---|
658 | 539 | /** |
---|
659 | 540 | * capi20_register() - CAPI 2.0 operation CAPI_REGISTER |
---|
.. | .. |
---|
716 | 597 | return CAPI_NOERROR; |
---|
717 | 598 | } |
---|
718 | 599 | |
---|
719 | | -EXPORT_SYMBOL(capi20_register); |
---|
720 | | - |
---|
721 | 600 | /** |
---|
722 | 601 | * capi20_release() - CAPI 2.0 operation CAPI_RELEASE |
---|
723 | 602 | * @ap: CAPI application descriptor structure. |
---|
.. | .. |
---|
759 | 638 | |
---|
760 | 639 | return CAPI_NOERROR; |
---|
761 | 640 | } |
---|
762 | | - |
---|
763 | | -EXPORT_SYMBOL(capi20_release); |
---|
764 | 641 | |
---|
765 | 642 | /** |
---|
766 | 643 | * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE |
---|
.. | .. |
---|
839 | 716 | return ctr->send_message(ctr, skb); |
---|
840 | 717 | } |
---|
841 | 718 | |
---|
842 | | -EXPORT_SYMBOL(capi20_put_message); |
---|
843 | | - |
---|
844 | 719 | /** |
---|
845 | 720 | * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER |
---|
846 | 721 | * @contr: controller number. |
---|
.. | .. |
---|
873 | 748 | mutex_unlock(&capi_controller_lock); |
---|
874 | 749 | return ret; |
---|
875 | 750 | } |
---|
876 | | - |
---|
877 | | -EXPORT_SYMBOL(capi20_get_manufacturer); |
---|
878 | 751 | |
---|
879 | 752 | /** |
---|
880 | 753 | * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION |
---|
.. | .. |
---|
909 | 782 | return ret; |
---|
910 | 783 | } |
---|
911 | 784 | |
---|
912 | | -EXPORT_SYMBOL(capi20_get_version); |
---|
913 | | - |
---|
914 | 785 | /** |
---|
915 | 786 | * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER |
---|
916 | 787 | * @contr: controller number. |
---|
.. | .. |
---|
943 | 814 | mutex_unlock(&capi_controller_lock); |
---|
944 | 815 | return ret; |
---|
945 | 816 | } |
---|
946 | | - |
---|
947 | | -EXPORT_SYMBOL(capi20_get_serial); |
---|
948 | 817 | |
---|
949 | 818 | /** |
---|
950 | 819 | * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE |
---|
.. | .. |
---|
979 | 848 | return ret; |
---|
980 | 849 | } |
---|
981 | 850 | |
---|
982 | | -EXPORT_SYMBOL(capi20_get_profile); |
---|
983 | | - |
---|
984 | | -/* Must be called with capi_controller_lock held. */ |
---|
985 | | -static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) |
---|
986 | | -{ |
---|
987 | | - DEFINE_WAIT(wait); |
---|
988 | | - int retval = 0; |
---|
989 | | - |
---|
990 | | - ctr = capi_ctr_get(ctr); |
---|
991 | | - if (!ctr) |
---|
992 | | - return -ESRCH; |
---|
993 | | - |
---|
994 | | - for (;;) { |
---|
995 | | - prepare_to_wait(&ctr->state_wait_queue, &wait, |
---|
996 | | - TASK_INTERRUPTIBLE); |
---|
997 | | - |
---|
998 | | - if (ctr->state == state) |
---|
999 | | - break; |
---|
1000 | | - if (ctr->state == CAPI_CTR_DETACHED) { |
---|
1001 | | - retval = -ESRCH; |
---|
1002 | | - break; |
---|
1003 | | - } |
---|
1004 | | - if (signal_pending(current)) { |
---|
1005 | | - retval = -EINTR; |
---|
1006 | | - break; |
---|
1007 | | - } |
---|
1008 | | - |
---|
1009 | | - mutex_unlock(&capi_controller_lock); |
---|
1010 | | - schedule(); |
---|
1011 | | - mutex_lock(&capi_controller_lock); |
---|
1012 | | - } |
---|
1013 | | - finish_wait(&ctr->state_wait_queue, &wait); |
---|
1014 | | - |
---|
1015 | | - capi_ctr_put(ctr); |
---|
1016 | | - |
---|
1017 | | - return retval; |
---|
1018 | | -} |
---|
1019 | | - |
---|
1020 | | -#ifdef AVMB1_COMPAT |
---|
1021 | | -static int old_capi_manufacturer(unsigned int cmd, void __user *data) |
---|
1022 | | -{ |
---|
1023 | | - avmb1_loadandconfigdef ldef; |
---|
1024 | | - avmb1_extcarddef cdef; |
---|
1025 | | - avmb1_resetdef rdef; |
---|
1026 | | - capicardparams cparams; |
---|
1027 | | - struct capi_ctr *ctr; |
---|
1028 | | - struct capi_driver *driver = NULL; |
---|
1029 | | - capiloaddata ldata; |
---|
1030 | | - struct list_head *l; |
---|
1031 | | - int retval; |
---|
1032 | | - |
---|
1033 | | - switch (cmd) { |
---|
1034 | | - case AVMB1_ADDCARD: |
---|
1035 | | - case AVMB1_ADDCARD_WITH_TYPE: |
---|
1036 | | - if (cmd == AVMB1_ADDCARD) { |
---|
1037 | | - if ((retval = copy_from_user(&cdef, data, |
---|
1038 | | - sizeof(avmb1_carddef)))) |
---|
1039 | | - return -EFAULT; |
---|
1040 | | - cdef.cardtype = AVM_CARDTYPE_B1; |
---|
1041 | | - cdef.cardnr = 0; |
---|
1042 | | - } else { |
---|
1043 | | - if ((retval = copy_from_user(&cdef, data, |
---|
1044 | | - sizeof(avmb1_extcarddef)))) |
---|
1045 | | - return -EFAULT; |
---|
1046 | | - } |
---|
1047 | | - cparams.port = cdef.port; |
---|
1048 | | - cparams.irq = cdef.irq; |
---|
1049 | | - cparams.cardnr = cdef.cardnr; |
---|
1050 | | - |
---|
1051 | | - mutex_lock(&capi_drivers_lock); |
---|
1052 | | - |
---|
1053 | | - switch (cdef.cardtype) { |
---|
1054 | | - case AVM_CARDTYPE_B1: |
---|
1055 | | - list_for_each(l, &capi_drivers) { |
---|
1056 | | - driver = list_entry(l, struct capi_driver, list); |
---|
1057 | | - if (strcmp(driver->name, "b1isa") == 0) |
---|
1058 | | - break; |
---|
1059 | | - } |
---|
1060 | | - break; |
---|
1061 | | - case AVM_CARDTYPE_T1: |
---|
1062 | | - list_for_each(l, &capi_drivers) { |
---|
1063 | | - driver = list_entry(l, struct capi_driver, list); |
---|
1064 | | - if (strcmp(driver->name, "t1isa") == 0) |
---|
1065 | | - break; |
---|
1066 | | - } |
---|
1067 | | - break; |
---|
1068 | | - default: |
---|
1069 | | - driver = NULL; |
---|
1070 | | - break; |
---|
1071 | | - } |
---|
1072 | | - if (!driver) { |
---|
1073 | | - printk(KERN_ERR "kcapi: driver not loaded.\n"); |
---|
1074 | | - retval = -EIO; |
---|
1075 | | - } else if (!driver->add_card) { |
---|
1076 | | - printk(KERN_ERR "kcapi: driver has no add card function.\n"); |
---|
1077 | | - retval = -EIO; |
---|
1078 | | - } else |
---|
1079 | | - retval = driver->add_card(driver, &cparams); |
---|
1080 | | - |
---|
1081 | | - mutex_unlock(&capi_drivers_lock); |
---|
1082 | | - return retval; |
---|
1083 | | - |
---|
1084 | | - case AVMB1_LOAD: |
---|
1085 | | - case AVMB1_LOAD_AND_CONFIG: |
---|
1086 | | - |
---|
1087 | | - if (cmd == AVMB1_LOAD) { |
---|
1088 | | - if (copy_from_user(&ldef, data, |
---|
1089 | | - sizeof(avmb1_loaddef))) |
---|
1090 | | - return -EFAULT; |
---|
1091 | | - ldef.t4config.len = 0; |
---|
1092 | | - ldef.t4config.data = NULL; |
---|
1093 | | - } else { |
---|
1094 | | - if (copy_from_user(&ldef, data, |
---|
1095 | | - sizeof(avmb1_loadandconfigdef))) |
---|
1096 | | - return -EFAULT; |
---|
1097 | | - } |
---|
1098 | | - |
---|
1099 | | - mutex_lock(&capi_controller_lock); |
---|
1100 | | - |
---|
1101 | | - ctr = get_capi_ctr_by_nr(ldef.contr); |
---|
1102 | | - if (!ctr) { |
---|
1103 | | - retval = -EINVAL; |
---|
1104 | | - goto load_unlock_out; |
---|
1105 | | - } |
---|
1106 | | - |
---|
1107 | | - if (ctr->load_firmware == NULL) { |
---|
1108 | | - printk(KERN_DEBUG "kcapi: load: no load function\n"); |
---|
1109 | | - retval = -ESRCH; |
---|
1110 | | - goto load_unlock_out; |
---|
1111 | | - } |
---|
1112 | | - |
---|
1113 | | - if (ldef.t4file.len <= 0) { |
---|
1114 | | - printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); |
---|
1115 | | - retval = -EINVAL; |
---|
1116 | | - goto load_unlock_out; |
---|
1117 | | - } |
---|
1118 | | - if (ldef.t4file.data == NULL) { |
---|
1119 | | - printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); |
---|
1120 | | - retval = -EINVAL; |
---|
1121 | | - goto load_unlock_out; |
---|
1122 | | - } |
---|
1123 | | - |
---|
1124 | | - ldata.firmware.user = 1; |
---|
1125 | | - ldata.firmware.data = ldef.t4file.data; |
---|
1126 | | - ldata.firmware.len = ldef.t4file.len; |
---|
1127 | | - ldata.configuration.user = 1; |
---|
1128 | | - ldata.configuration.data = ldef.t4config.data; |
---|
1129 | | - ldata.configuration.len = ldef.t4config.len; |
---|
1130 | | - |
---|
1131 | | - if (ctr->state != CAPI_CTR_DETECTED) { |
---|
1132 | | - printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); |
---|
1133 | | - retval = -EBUSY; |
---|
1134 | | - goto load_unlock_out; |
---|
1135 | | - } |
---|
1136 | | - ctr->state = CAPI_CTR_LOADING; |
---|
1137 | | - |
---|
1138 | | - retval = ctr->load_firmware(ctr, &ldata); |
---|
1139 | | - if (retval) { |
---|
1140 | | - ctr->state = CAPI_CTR_DETECTED; |
---|
1141 | | - goto load_unlock_out; |
---|
1142 | | - } |
---|
1143 | | - |
---|
1144 | | - retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); |
---|
1145 | | - |
---|
1146 | | - load_unlock_out: |
---|
1147 | | - mutex_unlock(&capi_controller_lock); |
---|
1148 | | - return retval; |
---|
1149 | | - |
---|
1150 | | - case AVMB1_RESETCARD: |
---|
1151 | | - if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) |
---|
1152 | | - return -EFAULT; |
---|
1153 | | - |
---|
1154 | | - retval = 0; |
---|
1155 | | - |
---|
1156 | | - mutex_lock(&capi_controller_lock); |
---|
1157 | | - |
---|
1158 | | - ctr = get_capi_ctr_by_nr(rdef.contr); |
---|
1159 | | - if (!ctr) { |
---|
1160 | | - retval = -ESRCH; |
---|
1161 | | - goto reset_unlock_out; |
---|
1162 | | - } |
---|
1163 | | - |
---|
1164 | | - if (ctr->state == CAPI_CTR_DETECTED) |
---|
1165 | | - goto reset_unlock_out; |
---|
1166 | | - |
---|
1167 | | - if (ctr->reset_ctr == NULL) { |
---|
1168 | | - printk(KERN_DEBUG "kcapi: reset: no reset function\n"); |
---|
1169 | | - retval = -ESRCH; |
---|
1170 | | - goto reset_unlock_out; |
---|
1171 | | - } |
---|
1172 | | - |
---|
1173 | | - ctr->reset_ctr(ctr); |
---|
1174 | | - |
---|
1175 | | - retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); |
---|
1176 | | - |
---|
1177 | | - reset_unlock_out: |
---|
1178 | | - mutex_unlock(&capi_controller_lock); |
---|
1179 | | - return retval; |
---|
1180 | | - } |
---|
1181 | | - return -EINVAL; |
---|
1182 | | -} |
---|
1183 | | -#endif |
---|
1184 | | - |
---|
1185 | 851 | /** |
---|
1186 | 852 | * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER |
---|
1187 | 853 | * @cmd: command. |
---|
.. | .. |
---|
1197 | 863 | int retval; |
---|
1198 | 864 | |
---|
1199 | 865 | switch (cmd) { |
---|
1200 | | -#ifdef AVMB1_COMPAT |
---|
1201 | | - case AVMB1_LOAD: |
---|
1202 | | - case AVMB1_LOAD_AND_CONFIG: |
---|
1203 | | - case AVMB1_RESETCARD: |
---|
1204 | | - case AVMB1_GET_CARDINFO: |
---|
1205 | | - case AVMB1_REMOVECARD: |
---|
1206 | | - return old_capi_manufacturer(cmd, data); |
---|
1207 | | -#endif |
---|
1208 | 866 | case KCAPI_CMD_TRACE: |
---|
1209 | 867 | { |
---|
1210 | 868 | kcapi_flagdef fdef; |
---|
.. | .. |
---|
1227 | 885 | |
---|
1228 | 886 | return retval; |
---|
1229 | 887 | } |
---|
1230 | | - case KCAPI_CMD_ADDCARD: |
---|
1231 | | - { |
---|
1232 | | - struct list_head *l; |
---|
1233 | | - struct capi_driver *driver = NULL; |
---|
1234 | | - capicardparams cparams; |
---|
1235 | | - kcapi_carddef cdef; |
---|
1236 | | - |
---|
1237 | | - if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) |
---|
1238 | | - return -EFAULT; |
---|
1239 | | - |
---|
1240 | | - cparams.port = cdef.port; |
---|
1241 | | - cparams.irq = cdef.irq; |
---|
1242 | | - cparams.membase = cdef.membase; |
---|
1243 | | - cparams.cardnr = cdef.cardnr; |
---|
1244 | | - cparams.cardtype = 0; |
---|
1245 | | - cdef.driver[sizeof(cdef.driver) - 1] = 0; |
---|
1246 | | - |
---|
1247 | | - mutex_lock(&capi_drivers_lock); |
---|
1248 | | - |
---|
1249 | | - list_for_each(l, &capi_drivers) { |
---|
1250 | | - driver = list_entry(l, struct capi_driver, list); |
---|
1251 | | - if (strcmp(driver->name, cdef.driver) == 0) |
---|
1252 | | - break; |
---|
1253 | | - } |
---|
1254 | | - if (driver == NULL) { |
---|
1255 | | - printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", |
---|
1256 | | - cdef.driver); |
---|
1257 | | - retval = -ESRCH; |
---|
1258 | | - } else if (!driver->add_card) { |
---|
1259 | | - printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); |
---|
1260 | | - retval = -EIO; |
---|
1261 | | - } else |
---|
1262 | | - retval = driver->add_card(driver, &cparams); |
---|
1263 | | - |
---|
1264 | | - mutex_unlock(&capi_drivers_lock); |
---|
1265 | | - return retval; |
---|
1266 | | - } |
---|
1267 | 888 | |
---|
1268 | 889 | default: |
---|
1269 | 890 | printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n", |
---|
.. | .. |
---|
1274 | 895 | return -EINVAL; |
---|
1275 | 896 | } |
---|
1276 | 897 | |
---|
1277 | | -EXPORT_SYMBOL(capi20_manufacturer); |
---|
1278 | | - |
---|
1279 | 898 | /* ------------------------------------------------------------- */ |
---|
1280 | 899 | /* -------- Init & Cleanup ------------------------------------- */ |
---|
1281 | 900 | /* ------------------------------------------------------------- */ |
---|
.. | .. |
---|
1284 | 903 | * init / exit functions |
---|
1285 | 904 | */ |
---|
1286 | 905 | |
---|
1287 | | -static struct notifier_block capictr_nb = { |
---|
1288 | | - .notifier_call = notify_handler, |
---|
1289 | | - .priority = INT_MAX, |
---|
1290 | | -}; |
---|
1291 | | - |
---|
1292 | | -static int __init kcapi_init(void) |
---|
| 906 | +int __init kcapi_init(void) |
---|
1293 | 907 | { |
---|
1294 | 908 | int err; |
---|
1295 | 909 | |
---|
.. | .. |
---|
1297 | 911 | if (!kcapi_wq) |
---|
1298 | 912 | return -ENOMEM; |
---|
1299 | 913 | |
---|
1300 | | - register_capictr_notifier(&capictr_nb); |
---|
1301 | | - |
---|
1302 | 914 | err = cdebug_init(); |
---|
1303 | 915 | if (err) { |
---|
1304 | | - unregister_capictr_notifier(&capictr_nb); |
---|
1305 | 916 | destroy_workqueue(kcapi_wq); |
---|
1306 | 917 | return err; |
---|
1307 | 918 | } |
---|
.. | .. |
---|
1310 | 921 | return 0; |
---|
1311 | 922 | } |
---|
1312 | 923 | |
---|
1313 | | -static void __exit kcapi_exit(void) |
---|
| 924 | +void kcapi_exit(void) |
---|
1314 | 925 | { |
---|
1315 | 926 | kcapi_proc_exit(); |
---|
1316 | 927 | |
---|
1317 | | - unregister_capictr_notifier(&capictr_nb); |
---|
1318 | 928 | cdebug_exit(); |
---|
1319 | 929 | destroy_workqueue(kcapi_wq); |
---|
1320 | 930 | } |
---|
1321 | | - |
---|
1322 | | -module_init(kcapi_init); |
---|
1323 | | -module_exit(kcapi_exit); |
---|