📄 eicon_mod.c
字号:
for(idi_length = 0; idi_length < 32; idi_length++) if (idi_d[idi_length].type == 0) break; if ((idi_length < 1) || (idi_length >= 32)) { eicon_log(card, 1, "eicon: invalid idi table length.\n"); break; } for(i = 3; i >= 0; i--) { if (!(card = eicon_findnpcicard(dstart.card_id - i))) return -EINVAL; card->flags |= EICON_FLAGS_LOADED; card->flags |= EICON_FLAGS_RUNNING; card->d = &idi_d[idi_length - (i+1)]; eicon_pci_init_conf(card); if (card->d->channels > 1) { cmd.command = ISDN_STAT_ADDCH; cmd.driver = card->myid; cmd.arg = card->d->channels - 1; card->interface.statcallb(&cmd); } cmd.command = ISDN_STAT_RUN; cmd.driver = card->myid; cmd.arg = 0; card->interface.statcallb(&cmd); eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n", 4-i, card->d->channels, card->d->features); } } } return ret;#else return -EINVAL;#endif#endif /* CONFIG_PCI */ } break; case ISDN_CMD_DIAL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; spin_lock_irqsave(&eicon_lock, flags); if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { spin_unlock_irqrestore(&eicon_lock, flags); eicon_log(card, 1, "Dial on channel %d with state %d\n", chan->No, chan->fsm_state); return -EBUSY; } chan->fsm_state = EICON_STATE_OCALL; spin_unlock_irqrestore(&eicon_lock, flags); ret = idi_connect_req(card, chan, c->parm.setup.phone, c->parm.setup.eazmsn, c->parm.setup.si1, c->parm.setup.si2); if (ret) { cmd.driver = card->myid; cmd.command = ISDN_STAT_DHUP; cmd.arg &= 0x1f; card->interface.statcallb(&cmd); } return ret; case ISDN_CMD_ACCEPTD: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; if (chan->fsm_state == EICON_STATE_ICALL) { idi_connect_res(card, chan); } return 0; case ISDN_CMD_ACCEPTB: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; return 0; case ISDN_CMD_HANGUP: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; idi_hangup(card, chan); return 0; case ISDN_CMD_SETEAZ: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; chan->eazmask = 0x3ff; eicon_idi_listen_req(card, chan); return 0; case ISDN_CMD_CLREAZ: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; chan->eazmask = 0; eicon_idi_listen_req(card, chan); return 0; case ISDN_CMD_SETL2: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; chan->l2prot = (c->arg >> 8); return 0; case ISDN_CMD_GETL2: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; return chan->l2prot; case ISDN_CMD_SETL3: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; chan->l3prot = (c->arg >> 8);#ifdef CONFIG_ISDN_TTY_FAX if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) { chan->fax = c->parm.fax; eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax); }#endif return 0; case ISDN_CMD_GETL3: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x1f))) break; return chan->l3prot; case ISDN_CMD_GETEAZ: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n"); return 0; case ISDN_CMD_SETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n"); return 0; case ISDN_CMD_GETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); return 0; case ISDN_CMD_LOCK:#ifdef MODULE mod_inc_use_count();#endif return 0; case ISDN_CMD_UNLOCK:#ifdef MODULE mod_dec_use_count();#endif 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -