📄 b1capi.c
字号:
static __u16 capi_get_version(__u16 contr, struct capi_version *verp){ if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return 0x2002; memcpy((void *) verp, &CARD(contr)->cversion, sizeof(capi_version)); return CAPI_NOERROR;}static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN]){ if (contr == 0) { strncpy(serial, driver_serial, 8); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return 0x2002; memcpy((void *) serial, CARD(contr)->version[VER_SERIAL], CAPI_SERIAL_LEN); serial[CAPI_SERIAL_LEN - 1] = 0; return CAPI_NOERROR;}static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp){ if (contr == 0) { profp->ncontroller = ncards; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return 0x2002; memcpy((void *) profp, CARD(contr)->version[VER_PROFILE], sizeof(struct capi_profile)); return CAPI_NOERROR;}static int capi_manufacturer(unsigned int cmd, void *data){ unsigned long flags; avmb1_loadandconfigdef ldef; avmb1_extcarddef cdef; avmb1_resetdef rdef; avmb1_getdef gdef; avmb1_card *card; int rc; switch (cmd) { case AVMB1_ADDCARD: case AVMB1_ADDCARD_WITH_TYPE: if (cmd == AVMB1_ADDCARD) { if ((rc = copy_from_user((void *) &cdef, data, sizeof(avmb1_carddef)))) return rc; cdef.cardtype = AVM_CARDTYPE_B1; } else { if ((rc = copy_from_user((void *) &cdef, data, sizeof(avmb1_extcarddef)))) return rc; } if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0) return rc; if (cdef.cardtype == AVM_CARDTYPE_T1) { int i; for (i=0; i < CAPI_MAXCONTR; i++) { if ( cards[i].cardstate != CARD_FREE && cards[i].cardtype == AVM_CARDTYPE_T1 && cards[i].cardnr == cdef.cardnr) { printk(KERN_ERR "b1capi: T1-HEMA-card-%d already at 0x%x\n", cdef.cardnr, cards[i].port); return -EBUSY; } } rc = T1_detectandinit(cdef.port,cdef.irq,cdef.cardnr); if (rc) { printk(KERN_NOTICE "b1capi: NO T1-HEMA-card-%d at 0x%x (%d)\n", cdef.cardnr, cdef.port, rc); return -EIO; } printk(KERN_NOTICE "b1capi: T1-HEMA-card-%d at 0x%x\n", cdef.cardnr, cdef.port); } rc = avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype); if (rc < 0) return rc; /* don't want to change interface t addcard/probecard/registercard */ if (cdef.cardtype == AVM_CARDTYPE_T1) { int i; for (i=0; i < CAPI_MAXCONTR; i++) { if (cards[i].cnr == rc) { cards[i].cardnr = cdef.cardnr; break; } } } return rc; case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: if (cmd == AVMB1_LOAD) { if ((rc = copy_from_user((void *) &ldef, data, sizeof(avmb1_loaddef)))) return rc; ldef.t4config.len = 0; ldef.t4config.data = 0; } else { if ((rc = copy_from_user((void *) &ldef, data, sizeof(avmb1_loadandconfigdef)))) return rc; } if (!VALID_CARD(ldef.contr)) return -ESRCH; if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "b1capi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); return -EINVAL; } card = CARD(ldef.contr); save_flags(flags); cli(); if (card->cardstate != CARD_DETECTED) { restore_flags(flags); if (loaddebug) printk(KERN_DEBUG "b1capi: load: contr=%d not in detect state\n", ldef.contr); return -EBUSY; } card->cardstate = CARD_LOADING; restore_flags(flags); if (loaddebug) { printk(KERN_DEBUG "b1capi: load: reseting contr %d\n", ldef.contr); } B1_reset(card->port); if (loaddebug) { printk(KERN_DEBUG "b1capi: loading contr %d\n", ldef.contr); } if ((rc = B1_load_t4file(card->port, &ldef.t4file))) { B1_reset(card->port); printk(KERN_ERR "b1capi: failed to load t4file!!\n"); card->cardstate = CARD_DETECTED; return rc; } B1_disable_irq(card->port); if (ldef.t4config.len > 0) { /* load config */ if (loaddebug) { printk(KERN_DEBUG "b1capi: loading config to contr %d\n", ldef.contr); } if ((rc = B1_load_config(card->port, &ldef.t4config))) { B1_reset(card->port); printk(KERN_ERR "b1capi: failed to load config!!\n"); card->cardstate = CARD_DETECTED; return rc; } } if (loaddebug) { printk(KERN_DEBUG "b1capi: load: ready contr %d: checking\n", ldef.contr); } if (!B1_loaded(card->port)) { card->cardstate = CARD_DETECTED; printk(KERN_ERR "b1capi: failed to load t4file.\n"); return -EIO; } /* * enable interrupt */ card->cardstate = CARD_INITSTATE; save_flags(flags); cli(); B1_setinterrupt(card->port, card->irq, card->cardtype); restore_flags(flags); if (loaddebug) { printk(KERN_DEBUG "b1capi: load: irq enabled contr %d\n", ldef.contr); } /* * init card */ if (card->cardtype == AVM_CARDTYPE_T1) B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI_PER_CHANNEL*30, card->cnr - 1); else B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI_PER_CHANNEL*2, card->cnr - 1); if (loaddebug) { printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n", ldef.contr); } while (card->cardstate != CARD_RUNNING) { current->timeout = jiffies + HZ / 10; /* 0.1 sec */ current->state = TASK_INTERRUPTIBLE; schedule(); if (current->signal & ~current->blocked) return -EINTR; } return 0; case AVMB1_RESETCARD: if ((rc = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return rc; return avmb1_resetcard(rdef.contr); case AVMB1_GET_CARDINFO: if ((rc = copy_from_user((void *) &gdef, data, sizeof(avmb1_getdef)))) return rc; if (!VALID_CARD(gdef.contr)) return -ESRCH; card = CARD(gdef.contr); gdef.cardstate = card->cardstate; gdef.cardtype = card->cardtype; if ((rc = copy_to_user(data, (void *) &gdef, sizeof(avmb1_getdef)))) return rc; return 0; case AVMB1_REMOVECARD: if ((rc = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return rc; if (!VALID_CARD(rdef.contr)) return -ESRCH; card = CARD(rdef.contr); if (card->cardstate != CARD_DETECTED) return -EBUSY; return avmb1_unregistercard(rdef.contr, 1); } return -EINVAL;}struct capi_interface avmb1_interface ={ capi_installed, capi_register, capi_release, capi_put_message, capi_get_message, capi_set_signal, capi_get_manufacturer, capi_get_version, capi_get_serial, capi_get_profile, capi_manufacturer};/* ------------------------------------------------------------- *//* -------- Exported Functions --------------------------------- *//* ------------------------------------------------------------- */struct capi_interface *attach_capi_interface(struct capi_interface_user *userp){ struct capi_interface_user *p; for (p = capi_users; p; p = p->next) { if (p == userp) { printk(KERN_ERR "b1capi: double attach from %s\n", userp->name); return 0; } } userp->next = capi_users; capi_users = userp; MOD_INC_USE_COUNT; printk(KERN_NOTICE "b1capi: %s attached\n", userp->name); return &avmb1_interface;}int detach_capi_interface(struct capi_interface_user *userp){ struct capi_interface_user **pp; for (pp = &capi_users; *pp; pp = &(*pp)->next) { if (*pp == userp) { *pp = userp->next; userp->next = 0; MOD_DEC_USE_COUNT; printk(KERN_NOTICE "b1capi: %s detached\n", userp->name); return 0; } } printk(KERN_ERR "b1capi: double detach from %s\n", userp->name); return -1;}/* ------------------------------------------------------------- *//* -------- Init & Cleanup ------------------------------------- *//* ------------------------------------------------------------- */#ifdef HAS_NEW_SYMTABEXPORT_SYMBOL(attach_capi_interface);EXPORT_SYMBOL(detach_capi_interface);EXPORT_SYMBOL(avmb1_addcard);EXPORT_SYMBOL(avmb1_probecard);EXPORT_SYMBOL(avmb1_registercard);EXPORT_SYMBOL(avmb1_unregistercard);EXPORT_SYMBOL(avmb1_resetcard);EXPORT_SYMBOL(avmb1_detectcard);#elsestatic struct symbol_table capidev_syms ={#include <linux/symtab_begin.h> X(attach_capi_interface), X(detach_capi_interface), X(avmb1_addcard), X(avmb1_probecard), X(avmb1_registercard), X(avmb1_unregistercard), X(avmb1_resetcard), X(avmb1_detectcard),#include <linux/symtab_end.h>};#endif/* * init / exit functions */#ifdef MODULE#define avmb1_init init_module#endifint avmb1_init(void){ char *p; char rev[10];#ifndef HAS_NEW_SYMTAB /* No symbols to export, hide all symbols */ register_symtab(&capidev_syms);#endif skb_queue_head_init(&recv_queue); /* init_bh(CAPI_BH, do_capi_bh); */ tq_state_notify.routine = notify_handler; tq_state_notify.data = 0; tq_recv_notify.routine = recv_handler; tq_recv_notify.data = 0; if ((p = strchr(revision, ':'))) { strcpy(rev, p + 1); p = strchr(rev, '$'); *p = 0; } else strcpy(rev, " ??? ");#ifdef MODULE printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: loaded\n", rev);#else printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: started\n", rev);#endif return 0;}#ifdef MODULEvoid cleanup_module(void){ char rev[10]; char *p; int i; if ((p = strchr(revision, ':'))) { strcpy(rev, p + 1); p = strchr(rev, '$'); *p = 0; } else { strcpy(rev, " ??? "); } for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate != CARD_FREE) { /* * disable card */ B1_disable_irq(cards[i].port); avmb1_resetcard(i+1); /* * free kernel resources */ avmb1_unregistercard(i+1, 1); } } schedule(); /* execute queued tasks .... */ printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: unloaded\n", rev);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -