📄 eicon_mod.c
字号:
eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); return 0; case ISDN_CMD_LOCK: MOD_INC_USE_COUNT; return 0; case ISDN_CMD_UNLOCK: MOD_DEC_USE_COUNT; return 0;#ifdef CONFIG_ISDN_TTY_FAX case ISDN_CMD_FAXCMD: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; if (!chan->fax) break; idi_fax_cmd(card, chan); return 0;#endif case ISDN_CMD_AUDIO: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num); return 0; case CAPI_PUT_MESSAGE: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; if (c->parm.cmsg.Length < 8) break; switch(c->parm.cmsg.Command) { case CAPI_FACILITY: if (c->parm.cmsg.Subcommand == CAPI_REQ) return(capipmsg(card, chan, &c->parm.cmsg)); break; case CAPI_MANUFACTURER: default: break; } return 0; } return -EINVAL;}/* * Find card with given driverId */static inline eicon_card *eicon_findcard(int driverid){ eicon_card *p = cards; while (p) { if (p->myid == driverid) return p; p = p->next; } return (eicon_card *) 0;}/* * Wrapper functions for interface to linklevel */static intif_command(isdn_ctrl * c){ eicon_card *card = eicon_findcard(c->driver); if (card) return (eicon_command(card, c)); printk(KERN_ERR "eicon: if_command %d called with invalid driverId %d!\n", c->command, c->driver); return -ENODEV;}static intif_writecmd(const u_char * buf, int len, int user, int id, int channel){ return (len);}static intif_readstatus(u_char * buf, int len, int user, int id, int channel){ int count = 0; int cnt = 0; ulong flags = 0; u_char *p = buf; struct sk_buff *skb; eicon_card *card = eicon_findcard(id); if (card) { if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; spin_lock_irqsave(&eicon_lock, flags); while((skb = skb_dequeue(&card->statq))) { if ((skb->len + count) > len) cnt = len - count; else cnt = skb->len; if (user) copy_to_user(p, skb->data, cnt); else memcpy(p, skb->data, cnt); count += cnt; p += cnt; if (cnt == skb->len) { dev_kfree_skb(skb); if (card->statq_entries > 0) card->statq_entries--; } else { skb_pull(skb, cnt); skb_queue_head(&card->statq, skb); spin_unlock_irqrestore(&eicon_lock, flags); return count; } } card->statq_entries = 0; spin_unlock_irqrestore(&eicon_lock, flags); return count; } printk(KERN_ERR "eicon: if_readstatus called with invalid driverId!\n"); return 0;}static intif_sendbuf(int id, int channel, int ack, struct sk_buff *skb){ eicon_card *card = eicon_findcard(id); eicon_chan *chan; int ret = 0; int len; len = skb->len; if (card) { if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, channel))) return -ENODEV; if (chan->fsm_state == EICON_STATE_ACTIVE) {#ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { if ((ret = idi_faxdata_send(card, chan, skb)) > 0) ret = len; } else#endif ret = idi_send_data(card, chan, ack, skb, 1, 1); return (ret); } else { return -ENODEV; } } printk(KERN_ERR "eicon: if_sendbuf called with invalid driverId!\n"); return -ENODEV;}/* jiftime() copied from HiSax */static inline int jiftime(char *s, long mark){ s += 8; *s-- = '\0'; *s-- = mark % 10 + '0'; mark /= 10; *s-- = mark % 10 + '0'; mark /= 10; *s-- = '.'; *s-- = mark % 10 + '0'; mark /= 10; *s-- = mark % 6 + '0'; mark /= 6; *s-- = ':'; *s-- = mark % 10 + '0'; mark /= 10; *s-- = mark % 10 + '0'; return(8);}voideicon_putstatus(eicon_card * card, char * buf){ ulong flags; int count; isdn_ctrl cmd; u_char *p; struct sk_buff *skb; if (!card) { if (!(card = cards)) return; } spin_lock_irqsave(&eicon_lock, flags); count = strlen(buf); skb = alloc_skb(count, GFP_ATOMIC); if (!skb) { spin_unlock_irqrestore(&eicon_lock, flags); printk(KERN_ERR "eicon: could not alloc skb in putstatus\n"); return; } p = skb_put(skb, count); memcpy(p, buf, count); skb_queue_tail(&card->statq, skb); if (card->statq_entries >= MAX_STATUS_BUFFER) { if ((skb = skb_dequeue(&card->statq))) { count -= skb->len; dev_kfree_skb(skb); } else count = 0; } else card->statq_entries++; spin_unlock_irqrestore(&eicon_lock, flags); if (count) { cmd.command = ISDN_STAT_STAVAIL; cmd.driver = card->myid; cmd.arg = count; card->interface.statcallb(&cmd); }}/* * Debug and Log */voideicon_log(eicon_card * card, int level, const char *fmt, ...){ va_list args; char Line[160]; u_char *p; if ((DebugVar & level) || (DebugVar & 256)) { va_start(args, fmt); if (DebugVar & level) { if (DebugVar & 256) { /* log-buffer */ p = Line; p += jiftime(p, jiffies); *p++ = 32; p += vsprintf(p, fmt, args); *p = 0; eicon_putstatus(card, Line); } else { /* printk, syslogd */ vsprintf(Line, fmt, args); printk(KERN_DEBUG "%s", Line); } } va_end(args); }}/* * Allocate a new card-struct, initialize it * link it into cards-list. */static voideicon_alloccard(int Type, int membase, int irq, char *id, int card_id){ int i; int j; int qloop;#ifdef CONFIG_ISDN_DRV_EICON_ISA char qid[5];#endif eicon_card *card; qloop = (Type == EICON_CTYPE_QUADRO)?2:0; for (i = 0; i <= qloop; i++) { if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { eicon_log(card, 1, "eicon: (%s) Could not allocate card-struct.\n", id); return; } memset((char *) card, 0, sizeof(eicon_card)); skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->rackq); skb_queue_head_init(&card->sackq); skb_queue_head_init(&card->statq); card->statq_entries = 0; card->snd_tq.routine = (void *) (void *) eicon_transmit; card->snd_tq.data = card; card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch; card->rcv_tq.data = card; card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch; card->ack_tq.data = card; card->interface.maxbufsize = 4000; card->interface.command = if_command; card->interface.writebuf_skb = if_sendbuf; card->interface.writecmd = if_writecmd; card->interface.readstat = if_readstatus; card->interface.features = ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 20; card->ptype = ISDN_PTYPE_UNKNOWN; strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); card->myid = -1; card->type = Type; switch (Type) {#ifdef CONFIG_ISDN_DRV_EICON_ISA#if CONFIG_MCA /* only needed for MCA */ case EICON_CTYPE_S: case EICON_CTYPE_SX: case EICON_CTYPE_SCOM: if (MCA_bus) { if (membase == -1) membase = EICON_ISA_MEMBASE; if (irq == -1) irq = EICON_ISA_IRQ; card->bus = EICON_BUS_MCA; card->hwif.isa.card = (void *)card; card->hwif.isa.shmem = (eicon_isa_shmem *)membase; card->hwif.isa.physmem = (unsigned long)membase; card->hwif.isa.master = 1; card->hwif.isa.irq = irq; card->hwif.isa.type = Type; card->nchannels = 2; card->interface.channels = 1; } else { printk(KERN_WARNING "eicon (%s): no MCA bus detected.\n", card->interface.id); kfree(card); return; } break;#endif /* CONFIG_MCA */ case EICON_CTYPE_QUADRO: if (membase == -1) membase = EICON_ISA_MEMBASE; if (irq == -1) irq = EICON_ISA_IRQ; card->bus = EICON_BUS_ISA; card->hwif.isa.card = (void *)card; card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET); card->hwif.isa.physmem = (unsigned long)(membase + (i+1) * EICON_ISA_QOFFSET); card->hwif.isa.master = 0; strcpy(card->interface.id, id); if (id[strlen(id) - 1] == 'a') { card->interface.id[strlen(id) - 1] = 'a' + i + 1; } else { sprintf(qid, "_%c",'2' + i); strcat(card->interface.id, qid); } printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n", card->interface.id); if (i == 0) { eicon_card *p = cards; while(p) { if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) { p->qnext = card; break; } p = p->next; } if (!p) { eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n"); kfree(card); return; } } else { cards->qnext = card; } card->hwif.isa.irq = irq; card->hwif.isa.type = Type; card->nchannels = 2; card->interface.channels = 1; break;#endif#ifdef CONFIG_PCI#ifdef CONFIG_ISDN_DRV_EICON_PCI case EICON_CTYPE_MAESTRA: card->bus = EICON_BUS_PCI; card->interface.features |= ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FCLASS2; card->hwif.pci.card = (void *)card; card->hwif.pci.master = card_id; card->hwif.pci.irq = irq; card->hwif.pci.type = Type; card->flags = 0; card->nchannels = 2; card->interface.channels = 1; break; case EICON_CTYPE_MAESTRAQ: card->bus = EICON_BUS_PCI; card->interface.features |= ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FCLASS2; card->hwif.pci.card = (void *)card; card->hwif.pci.master = card_id; card->hwif.pci.irq = irq; card->hwif.pci.type = Type; card->flags = 0; card->nchannels = 2; card->interface.channels = 1; break; case EICON_CTYPE_MAESTRAP: card->bus = EICON_BUS_PCI; card->interface.features |= ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FCLASS2; card->hwif.pci.card = (void *)card; card->hwif.pci.master = card_id; card->hwif.pci.irq = irq; card->hwif.pci.type = Type; card->flags = 0; card->nchannels = 30; card->interface.channels = 1; break;#endif#endif#ifdef CONFIG_ISDN_DRV_EICON_ISA case EICON_CTYPE_ISABRI: if (membase == -1) membase = EICON_ISA_MEMBASE; if (irq == -1) irq = EICON_ISA_IRQ; card->bus = EICON_BUS_ISA; card->hwif.isa.card = (void *)card; card->hwif.isa.shmem = (eicon_isa_shmem *)membase; card->hwif.isa.physmem = (unsigned long)membase; card->hwif.isa.master = 1; card->hwif.isa.irq = irq; card->hwif.isa.type = Type; card->nchannels = 2; card->interface.channels = 1; break; case EICON_CTYPE_ISAPRI: if (membase == -1) membase = EICON_ISA_MEMBASE; if (irq == -1) irq = EICON_ISA_IRQ; card->bus = EICON_BUS_ISA; card->hwif.isa.card = (void *)card; card->hwif.isa.shmem = (eicon_isa_shmem *)membase; card->hwif.isa.physmem = (unsigned long)membase; card->hwif.isa.master = 1; card->hwif.isa.irq = irq; card->hwif.isa.type = Type; card->nchannels = 30; card->interface.channels = 1; break;#endif default: eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type); kfree(card); return; } if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1) , GFP_KERNEL))) { eicon_log(card, 1, "eicon: (%s) Could not allocate bch-struct.\n", id); kfree(card); return; } for (j=0; j< (card->nchannels + 1); j++) { memset((char *)&card->bch[j], 0, sizeof(eicon_chan)); card->bch[j].statectrl = 0; card->bch[j].l2prot = ISDN_PROTO_L2_X75I; card->bch[j].l3prot = ISDN_PROTO_L3_TRANS; card->bch[j].e.D3Id = 0; card->bch[j].e.B2Id = 0; card->bch[j].e.Req = 0; card->bch[j].No = j; card->bch[j].tskb1 = NULL; card->bch[j].tskb2 = NULL; skb_queue_head_init(&card->bch[j].e.X); skb_queue_head_init(&card->bch[j].e.R); }#ifdef CONFIG_ISDN_DRV_EICON_PCI /* *** Diva Server *** */ if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2 , GFP_KERNEL))) { eicon_log(card, 1, "eicon: (%s) Could not allocate DBUFFER-struct.\n", id); kfree(card); kfree(card->bch); return; } if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) { eicon_log(card, 1, "eicon: (%s) Could not allocate BUFFERS-struct.\n", id); kfree(card); kfree(card->bch); kfree(card->dbuf); return; } if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) { eicon_log(card, 1, "eicon: (%s) Could not allocate BUFFERSP-struct.\n", id); kfree(card); kfree(card->bch); kfree(card->dbuf); kfree(card->sbuf); return; } for (j=0; j< (card->nchannels + 1); j++) { memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER)); card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j]; memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS)); card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)]; memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS)); card->bch[j].de.X = (BUFFERS *)&card->sbuf[j]; memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS)); card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)]; memset((char *)&card->sbufp[j], 0, 270); card->bch[j].de.X->P = (char *)&card->sbufp[j * 270]; memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270); card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -