📄 icn.c
字号:
card->interface.statcallb(&cmd); return;}static voidicn_putmsg(icn_card * card, unsigned char c){ ulong flags; save_flags(flags); cli(); *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; if (card->msg_buf_write == card->msg_buf_read) { if (++card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } if (card->msg_buf_write > card->msg_buf_end) card->msg_buf_write = card->msg_buf; restore_flags(flags);}static voidicn_polldchan(unsigned long data){ icn_card *card = (icn_card *) data; int mch = card->secondhalf ? 2 : 0; int avail = 0; int left; u_char c; int ch; int flags; int i; u_char *p; isdn_ctrl cmd; if (icn_trymaplock_channel(card, mch)) { avail = msg_avail; for (left = avail, i = readb(&msg_o); left > 0; i++, left--) { c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]); icn_putmsg(card, c); if (c == 0xff) { card->imsg[card->iptr] = 0; card->iptr = 0; if (card->imsg[0] == '0' && card->imsg[1] >= '0' && card->imsg[1] <= '2' && card->imsg[2] == ';') { ch = (card->imsg[1] - '0') - 1; p = &card->imsg[3]; icn_parse_status(p, ch, card); } else { p = card->imsg; if (!strncmp(p, "DRV1.", 5)) { u_char vstr[10]; u_char *q = vstr; printk(KERN_INFO "icn: (%s) %s\n", CID, p); if (!strncmp(p + 7, "TC", 2)) { card->ptype = ISDN_PTYPE_1TR6; card->interface.features |= ISDN_FEATURE_P_1TR6; printk(KERN_INFO "icn: (%s) 1TR6-Protocol loaded and running\n", CID); } if (!strncmp(p + 7, "EC", 2)) { card->ptype = ISDN_PTYPE_EURO; card->interface.features |= ISDN_FEATURE_P_EURO; printk(KERN_INFO "icn: (%s) Euro-Protocol loaded and running\n", CID); } p = strstr(card->imsg, "BRV") + 3; while (*p) { if (*p >= '0' && *p <= '9') *q++ = *p; p++; } *q = '\0'; strcat(vstr, "000"); vstr[3] = '\0'; card->fw_rev = (int) simple_strtoul(vstr, NULL, 10); continue; } } } else { card->imsg[card->iptr] = c; if (card->iptr < 59) card->iptr++; } } writeb((readb(&msg_o) + avail) & 0xff, &msg_o); icn_release_channel(); } if (avail) { cmd.command = ISDN_STAT_STAVAIL; cmd.driver = card->myid; cmd.arg = avail; card->interface.statcallb(&cmd); } if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) if (!(card->flags & ICN_FLAGS_RBTIMER)) { /* schedule b-channel polling */ card->flags |= ICN_FLAGS_RBTIMER; save_flags(flags); cli(); del_timer(&card->rb_timer); card->rb_timer.function = icn_pollbchan; card->rb_timer.data = (unsigned long) card; card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; add_timer(&card->rb_timer); restore_flags(flags); } /* schedule again */ save_flags(flags); cli(); mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD); restore_flags(flags);}/* Append a packet to the transmit buffer-queue. * Parameters: * channel = Number of B-channel * skb = pointer to sk_buff * card = pointer to card-struct * Return: * Number of bytes transferred, -E??? on error */static inticn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card){ int len = skb->len; unsigned long flags; struct sk_buff *nskb; if (len > 4000) { printk(KERN_WARNING "icn: Send packet too large\n"); return -EINVAL; } if (len) { if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) return 0; if (card->sndcount[channel] > ICN_MAX_SQUEUE) return 0; save_flags(flags); cli(); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { /* Push ACK flag as one * byte in front of data. */ *(skb_push(nskb, 1)) = ack?1:0; skb_queue_tail(&card->spqueue[channel], nskb); dev_kfree_skb(skb); } else len = 0; card->sndcount[channel] += len; restore_flags(flags); } return len;}/* * Check card's status after starting the bootstrap loader. * On entry, the card's shared memory has already to be mapped. * Return: * 0 on success (Boot loader ready) * -EIO on failure (timeout) */static inticn_check_loader(int cardnumber){ int timer = 0; while (1) {#ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d ?\n", cardnumber);#endif if (readb(&dev.shmem->data_control.scns) || readb(&dev.shmem->data_control.scnr)) { if (timer++ > 5) { printk(KERN_WARNING "icn: Boot-Loader %d timed out.\n", cardnumber); icn_release_channel(); return -EIO; }#ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);#endif current->state = TASK_INTERRUPTIBLE; schedule_timeout(ICN_BOOT_TIMEOUT1); } else {#ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d OK\n", cardnumber);#endif icn_release_channel(); return 0; } }}/* Load the boot-code into the interface-card's memory and start it. * Always called from user-process. * * Parameters: * buffer = pointer to packet * Return: * 0 if successfully loaded */#ifdef BOOT_DEBUG#define SLEEP(sec) { \int slsec = sec; \ printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \ while (slsec) { \ current->state = TASK_INTERRUPTIBLE; \ schedule_timeout(HZ); \ slsec--; \ } \}#else#define SLEEP(sec)#endifstatic inticn_loadboot(u_char * buffer, icn_card * card){ int ret; ulong flags; u_char *codebuf;#ifdef BOOT_DEBUG printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);#endif if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) { printk(KERN_WARNING "icn: Could not allocate code buffer\n"); return -ENOMEM; } if ((ret = copy_from_user(codebuf, buffer, ICN_CODE_STAGE1))) { kfree(codebuf); return ret; } save_flags(flags); cli(); if (!card->rvalid) { if (check_region(card->port, ICN_PORTLEN)) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", CID, card->port, card->port + ICN_PORTLEN); restore_flags(flags); kfree(codebuf); return -EBUSY; } request_region(card->port, ICN_PORTLEN, card->regname); card->rvalid = 1; if (card->doubleS0) card->other->rvalid = 1; } if (!dev.mvalid) { if (check_shmem((ulong) dev.shmem, 0x4000)) { printk(KERN_WARNING "icn: memory at 0x%08lx in use.\n", (ulong) dev.shmem); restore_flags(flags); return -EBUSY; } request_shmem((ulong) dev.shmem, 0x4000, "icn"); dev.mvalid = 1; } restore_flags(flags); OUTB_P(0, ICN_RUN); /* Reset Controller */ OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ icn_shiftout(ICN_CFG, 0x0f, 3, 4); /* Windowsize= 16k */ icn_shiftout(ICN_CFG, (unsigned long) dev.shmem, 23, 10); /* Set RAM-Addr. */#ifdef BOOT_DEBUG printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev.shmem);#endif SLEEP(1);#ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n");#endif save_flags(flags); cli(); icn_map_channel(card, 0); /* Select Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */ restore_flags(flags); SLEEP(1); memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */#ifdef BOOT_DEBUG printk(KERN_DEBUG "Bootloader transfered\n");#endif if (card->doubleS0) { SLEEP(1);#ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 8\n");#endif save_flags(flags); cli(); icn_release_channel(); icn_map_channel(card, 2); /* Select Bank 8 */ icn_lock_channel(card, 2); /* Lock Bank 8 */ restore_flags(flags); SLEEP(1); memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */#ifdef BOOT_DEBUG printk(KERN_DEBUG "Bootloader transfered\n");#endif } kfree(codebuf); SLEEP(1); OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) return ret; if (!card->doubleS0) return 0; /* reached only, if we have a Double-S0-Card */#ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n");#endif save_flags(flags); cli(); icn_map_channel(card, 0); /* Select Bank 0 */ icn_lock_channel(card, 0); /* Lock Bank 0 */ restore_flags(flags); SLEEP(1); return (icn_check_loader(1));}static inticn_loadproto(u_char * buffer, icn_card * card){ register u_char *p = buffer; u_char codebuf[256]; uint left = ICN_CODE_STAGE2; uint cnt; int timer; int ret; unsigned long flags;#ifdef BOOT_DEBUG printk(KERN_DEBUG "icn_loadproto called\n");#endif if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2))) return ret; timer = 0; save_flags(flags); cli(); if (card->secondhalf) { icn_map_channel(card, 2); icn_lock_channel(card, 2); } else { icn_map_channel(card, 0); icn_lock_channel(card, 0); } restore_flags(flags); while (left) { if (sbfree) { /* If there is a free buffer... */ cnt = MIN(256, left); if (copy_from_user(codebuf, p, cnt)) { icn_maprelease_channel(card, 0); return -EFAULT; } memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */ sbnext; /* switch to next buffer */ p += cnt; left -= cnt; timer = 0; } else {#ifdef BOOT_DEBUG printk(KERN_DEBUG "boot 2 !sbfree\n");#endif if (timer++ > 5) { icn_maprelease_channel(card, 0); return -EIO; } current->state = TASK_INTERRUPTIBLE; schedule_timeout(10); } } writeb(0x20, &sbuf_n); timer = 0; while (1) { if (readb(&cmd_o) || readb(&cmd_i)) {#ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto?\n");#endif if (timer++ > 5) { printk(KERN_WARNING "icn: (%s) Protocol timed out.\n", CID);#ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto TO!\n");#endif icn_maprelease_channel(card, 0); return -EIO; }#ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto TO?\n");#endif current->state = TASK_INTERRUPTIBLE; schedule_timeout(ICN_BOOT_TIMEOUT1); } else { if ((card->secondhalf) || (!card->doubleS0)) {#ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", card->secondhalf);#endif save_flags(flags); cli(); init_timer(&card->st_timer); card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; card->st_timer.function = icn_polldchan; card->st_timer.data = (unsigned long) card; add_timer(&card->st_timer); card->flags |= ICN_FLAGS_RUNNING; if (card->doubleS0) { init_timer(&card->other->st_timer); card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD; card->other->st_timer.function = icn_polldchan; card->other->st_timer.data = (unsigned long) card->other; add_timer(&card->other->st_timer); card->other->flags |= ICN_FLAGS_RUNNING; } restore_flags(flags); } icn_maprelease_channel(card, 0); return 0; } }}/* Read the Status-replies from the Interface */static inticn_readstatus(u_char * buf, int len, int user, icn_card * card){ int count; u_char *p; for (p = buf, count = 0; count < len; p++, count++) { if (card->msg_buf_read == card->msg_buf_write) return count; if (user) put_user(*card->msg_buf_read++, p); else *p = *card->msg_buf_read++; if (card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } return count;}/* Put command-strings into the command-queue of the Interface */static inticn_writecmd(const u_char * buf, int len, int user, icn_card * card){ int mch = card->secondhalf ? 2 : 0; int avail; int pp; int i; int count; int xcount; int ocount; int loop; unsigned long flags; int lastmap_channel; struct icn_card *lastmap_card; u_char *p; isdn_ctrl cmd; u_char msg[0x100]; ocount = 1; xcount = loop = 0; while (len) { save_flags(flags); cli(); lastmap_card = dev.mcard; lastmap_channel = dev.channel; icn_map_channel(card, mch); avail = cmd_free; count = MIN(avail, len); if (user) copy_from_user(msg, buf, count); else memcpy(msg, buf, count); icn_putmsg(card, '>'); for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp ++) { writeb((*p == '\n') ? 0xff : *p, &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]); len--; xcount++; icn_putmsg(card, *p); if ((*p == '\n') && (i > 1)) { icn_putmsg(card, '>'); ocount++; } ocount++; } writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); if (lastmap_card) icn_map_channel(lastmap_card, lastmap_channel); restore_flags(flags); if (len) { mdelay(1); if (loop++ > 20) break; } else break; } if (len && (!user)) printk(KERN_WARNING "icn: writemsg incomplete!\n"); cmd.command = ISDN_STAT_STAVAIL; cmd.driver = card->myid; cmd.arg = ocount; card->interface.statcallb(&cmd); return xcount;}/* * Delete card's pending timers, send STOP to linklevel */static voidicn_stopcard(icn_card * card){ unsigned long flags; isdn_ctrl cmd; save_flags(flags); cli(); if (card->flags & ICN_FLAGS_RUNNING) { card->flags &= ~ICN_FLAGS_RUNNING; del_timer(&card->st_timer); del_timer(&card->rb_timer); cmd.command = ISDN_STAT_STOP; cmd.driver = card->myid; card->interface.statcallb(&cmd); if (card->doubleS0) icn_stopcard(card->other); } restore_flags(flags);}static voidicn_stopallcards(void){ icn_card *p = cards; while (p) { icn_stopcard(p); p = p->next; }}/* * Unmap all cards, because some of them may be mapped accidetly during * autoprobing of some network drivers (SMC-driver?) */static voidicn_disable_cards(void){ icn_card *card = cards; unsigned long flags; save_flags(flags); cli(); while (card) { if (check_region(card->port, ICN_PORTLEN)) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", CID, card->port, card->port + ICN_PORTLEN); cli(); } else { OUTB_P(0, ICN_RUN); /* Reset Controller */ OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -