📄 b1capi.c
字号:
} card->interrupt = 1; B1_handle_interrupt(card); card->interrupt = 0;}/* -------- Notifier ------------------------------------------ */static void notify_up(__u16 contr){ struct capi_interface_user *p; printk(KERN_NOTICE "b1capi: notify up contr %d\n", contr); for (p = capi_users; p; p = p->next) { if (p->callback) (*p->callback) (KCI_CONTRUP, contr, (capi_profile *) CARD(contr)->version[VER_PROFILE]); }}static void notify_down(__u16 contr){ struct capi_interface_user *p; printk(KERN_NOTICE "b1capi: notify down contr %d\n", contr); for (p = capi_users; p; p = p->next) { if (p->callback) (*p->callback) (KCI_CONTRDOWN, contr, 0); }}static void notify_handler(void *dummy){ __u16 contr; for (contr=1; VALID_CARD(contr); contr++) if (test_and_clear_bit(contr, ¬ify_up_set)) notify_up(contr); for (contr=1; VALID_CARD(contr); contr++) if (test_and_clear_bit(contr, ¬ify_down_set)) notify_down(contr);}/* -------- card ready callback ------------------------------- */void avmb1_card_ready(avmb1_card * card){ struct capi_profile *profp = (struct capi_profile *)card->version[VER_PROFILE]; char *dversion = card->version[VER_DRIVER]; __u16 appl; char *cardname, cname[20]; __u32 flag; int nbchan = profp->nbchannel; card->cversion.majorversion = 2; card->cversion.minorversion = 0; card->cversion.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); card->cversion.majormanuversion |= ((dversion[2] - '0') & 0xf); card->cversion.minormanuversion = (dversion[3] - '0') << 4; card->cversion.minormanuversion |= (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); card->cardstate = CARD_RUNNING; for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { if (VALID_APPLID(appl) && !APPL(appl)->releasing) { int nconn, want = APPL(appl)->rparam.level3cnt; if (want > 0) nconn = want; else nconn = nbchan * -want; if (nconn == 0) nconn = nbchan; B1_send_register(card->port, appl, 1024 * (nconn+1), nconn, APPL(appl)->rparam.datablkcnt, APPL(appl)->rparam.datablklen); } } set_bit(CARDNR(card), ¬ify_up_set); queue_task(&tq_state_notify, &tq_scheduler); flag = ((__u8 *)(profp->manu))[1]; switch (flag) { case 0: cardname = cardtype2str(card->cardtype); break; case 3: cardname = "PCMCIA B"; break; case 4: cardname = "PCMCIA M1"; break; case 5: cardname = "PCMCIA M2"; break; case 6: cardname = "B1 V3.0"; break; case 7: cardname = "B1 PCI"; break; default: cardname = cname; break; sprintf(cname, "AVM?%u", (unsigned int)flag); break; } printk(KERN_NOTICE "b1capi: card %d \"%s\" ready.\n", CARDNR(card), cardname); flag = ((__u8 *)(profp->manu))[3]; if (flag) printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n", CARDNR(card), (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", (flag & 0x04) ? " VN3" : "", (flag & 0x08) ? " NI1" : "", (flag & 0x10) ? " AUSTEL" : "", (flag & 0x20) ? " ESS" : "", (flag & 0x40) ? " 1TR6" : "" ); flag = ((__u8 *)(profp->manu))[5]; if (flag) printk(KERN_NOTICE "b1capi: card %d Linetype:%s%s%s%s\n", CARDNR(card), (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", (flag & 0x08) ? " leased line without D-channel" : "", (flag & 0x04) ? " leased line with D-channel" : "" );}static void avmb1_card_down(avmb1_card * card, int notify){ __u16 appl; card->cardstate = CARD_DETECTED; for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { avmb1_ncci **pp, **nextpp; for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { if (NCCI2CTRL((*pp)->ncci) == card->cnr) { avmb1_ncci *np = *pp; *pp = np->next; printk(KERN_INFO "b1capi: appl %d ncci 0x%x forced down!\n", appl, np->ncci); kfree(np); nextpp = pp; } else { nextpp = &(*pp)->next; } } } set_bit(CARDNR(card), ¬ify_down_set); queue_task(&tq_state_notify, &tq_scheduler); printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card));}/* ------------------------------------------------------------- */int avmb1_registercard(int port, int irq, int cardtype, int allocio){ struct avmb1_card *card; int irqval,i; for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ; if (i == CAPI_MAXCONTR) { printk(KERN_ERR "b1capi: out of controller slots\n"); return -ENFILE; } card = &cards[i]; memset(card, 0, sizeof(avmb1_card)); sprintf(card->name, "avmb1-%d", CARDNR(card)); if (allocio) request_region(port, AVMB1_PORTLEN, card->name); if ((irqval = request_irq(irq, avmb1_interrupt, SA_SHIRQ, card->name, card)) != 0) { printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n", irq, irqval); release_region(port, AVMB1_PORTLEN); return -EBUSY; } card->cardstate = CARD_DETECTED; ncards++; card->cnr = CARDNR(card); card->port = port; card->irq = irq; card->cardtype = cardtype; return card->cnr;}int avmb1_addcard(int port, int irq, int cardtype){ return avmb1_registercard(port, irq, cardtype, 1);}int avmb1_detectcard(int port, int irq, int cardtype){ int rc; if (!B1_valid_irq(irq, cardtype)) { printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n", irq, cardtype2str(cardtype)); return -EINVAL; } if (!B1_valid_port(port, cardtype)) { printk(KERN_WARNING "b1capi: port 0x%x not valid for %s-card.\n", port, cardtype2str(cardtype)); return -EINVAL; } B1_reset(port); if ((rc = B1_detect(port, cardtype)) != 0) { printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n", cardtype2str(cardtype), port, rc); return -EIO; } B1_reset(port); switch (cardtype) { default: case AVM_CARDTYPE_M1: case AVM_CARDTYPE_M2: case AVM_CARDTYPE_B1: printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port); break; case AVM_CARDTYPE_T1: break; } return 0;}int avmb1_probecard(int port, int irq, int cardtype){ if (check_region(port, AVMB1_PORTLEN)) { printk(KERN_WARNING "b1capi: ports 0x%03x-0x%03x in use.\n", port, port + AVMB1_PORTLEN); return -EBUSY; } return avmb1_detectcard(port, irq, cardtype);}int avmb1_unregistercard(int cnr, int freeio){ avmb1_card * card; if (!VALID_CARD(cnr)) return -ESRCH; card = CARD(cnr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate == CARD_RUNNING) avmb1_card_down(card, freeio); if (card->cardstate != CARD_FREE) if (card->cardtype == AVM_CARDTYPE_T1) T1_reset(card->port); free_irq(card->irq, card); if (freeio) release_region(card->port, AVMB1_PORTLEN); card->cardstate = CARD_FREE; return 0;}int avmb1_resetcard(int cnr){ avmb1_card * card; if (!VALID_CARD(cnr)) return -ESRCH; card = CARD(cnr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate == CARD_RUNNING) avmb1_card_down(card, 0); B1_reset(card->port); B1_reset(card->port); card->cardstate = CARD_DETECTED; return 0;}/* ------------------------------------------------------------- *//* -------- CAPI2.0 Interface ---------------------------------- *//* ------------------------------------------------------------- */static int capi_installed(void){ int i; for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate == CARD_RUNNING) return 1; } return 0;}static __u16 capi_register(capi_register_params * rparam, __u16 * applidp){ int nconn, want = rparam->level3cnt; int i; int appl; if (rparam->datablklen < 128) return CAPI_LOGBLKSIZETOSMALL; for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { if (APPL_IS_FREE(appl)) break; } if (appl > CAPI_MAXAPPL) return CAPI_TOOMANYAPPLS; APPL_MARK_USED(appl); skb_queue_head_init(&APPL(appl)->recv_queue); memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params)); for (i = 0; i < CAPI_MAXCONTR; i++) { struct capi_profile *profp = (struct capi_profile *)cards[i].version[VER_PROFILE]; if (cards[i].cardstate != CARD_RUNNING) continue; if (want > 0) nconn = want; else nconn = profp->nbchannel * -want; if (nconn == 0) nconn = profp->nbchannel; B1_send_register(cards[i].port, appl, 1024 * (nconn+1), nconn, APPL(appl)->rparam.datablkcnt, APPL(appl)->rparam.datablklen); } *applidp = appl; printk(KERN_INFO "b1capi: appl %d up\n", appl); return CAPI_NOERROR;}static __u16 capi_release(__u16 applid){ struct sk_buff *skb; int i; if (!VALID_APPLID(applid) || APPL(applid)->releasing) return CAPI_ILLAPPNR; while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0) kfree_skb(skb, FREE_READ); for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate != CARD_RUNNING) { continue; } APPL(applid)->releasing++; B1_send_release(cards[i].port, applid); } if (APPL(applid)->releasing <= 0) { APPL(applid)->signal = 0; APPL_MARK_FREE(applid); printk(KERN_INFO "b1capi: appl %d down\n", applid); } return CAPI_NOERROR;}static __u16 capi_put_message(__u16 applid, struct sk_buff *skb){ avmb1_ncci *np; int contr; if (ncards == 0) return CAPI_REGNOTINSTALLED; if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; if (skb->len < 12 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; contr = CAPIMSG_CONTROLLER(skb->data); if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) { contr = 1; if (CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; } if (CARD(contr)->blocked) return CAPI_SENDQUEUEFULL; if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ && (np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0 && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0) return CAPI_SENDQUEUEFULL; B1_send_message(CARD(contr)->port, skb); return CAPI_NOERROR;}static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp){ struct sk_buff *skb; if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0) return CAPI_RECEIVEQUEUEEMPTY; *msgp = skb; return CAPI_NOERROR;}static __u16 capi_set_signal(__u16 applid, void (*signal) (__u16 applid, __u32 param), __u32 param){ if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; APPL(applid)->signal = signal; APPL(applid)->param = param; return CAPI_NOERROR;}static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]){ if (contr == 0) { strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return 0x2002; strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -