📄 icn.c
字号:
* 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; \ current->timeout = jiffies + HZ; \ schedule(); \ 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; current->timeout = jiffies + 10; schedule(); } } 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; current->timeout = jiffies + ICN_BOOT_TIMEOUT1; schedule(); } 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) { udelay(1000); 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 */ } card = card->next; } restore_flags(flags);}static inticn_command(isdn_ctrl * c, icn_card * card){ ulong a; ulong flags; int i; char cbuf[60]; isdn_ctrl cmd; icn_cdef cdef; switch (c->command) { case ISDN_CMD_IOCTL: memcpy(&a, c->parm.num, sizeof(ulong)); switch (c->arg) { case ICN_IOCTL_SETMMIO: if ((unsigned long) dev.shmem != (a & 0x0ffc000)) { if (check_shmem((ulong) (a & 0x0ffc000), 0x4000)) { printk(KERN_WARNING "icn: memory at 0x%08lx in use.\n", (ulong) (a & 0x0ffc000)); return -EINVAL; } icn_stopallcards(); save_flags(flags); cli(); if (dev.mvalid) release_shmem((ulong) dev.shmem, 0x4000); dev.mvalid = 0; dev.shmem = (icn_shmem *) (a & 0x0ffc000); restore_flags(flags); printk(KERN_INFO "icn: (%s) mmio set to 0x%08lx\n", CID, (unsigned long) dev.shmem); } break; case ICN_IOCTL_GETMMIO: return (long) dev.shmem; case ICN_IOCTL_SETPORT: if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330 || a == 0x340 || a == 0x350 || a == 0x360 || a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 || a == 0x348 || a == 0x358 || a == 0x368) { if (card->port != (unsigned short) a) { if (check_region((unsigned short) a, ICN_PORTLEN)) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", CID, (int) a, (int) a + ICN_PORTLEN); return -EINVAL; } icn_stopcard(card); save_flags(flags); cli(); if (card->rvalid) release_region(card->port, ICN_PORTLEN); card->port = (unsigned short) a; card->rvalid = 0; if (card->doubleS0) { card->other->port = (unsigned short) a; card->other->rvalid = 0; } restore_flags(flags); printk(KERN_INFO "icn: (%s) port set to 0x%03x\n", CID, card->port); } } else return -EINVAL; break; case ICN_IOCTL_GETPORT: return (int) card->port; case ICN_IOCTL_GETDOUBLE: return (int) card->doubleS0; case ICN_IOCTL_DEBUGVAR: if ((i = copy_to_user((char *) a, (char *) &card, sizeof(ulong)))) return i; a += sizeof(ulong); { ulong l = (ulong) & dev; if ((i = copy_to_user((char *) a, (char *) &l, sizeof(ulong)))) return i; } return 0; case ICN_IOCTL_LOADBOOT: if (dev.firstload) { icn_disable_cards(); dev.firstload = 0; } icn_stopcard(card); return (icn_loadboot((u_char *) a, card)); case ICN_IOCTL_LOADPROTO: icn_stopcard(card); if ((i = (icn_loadproto((u_char *) a, card)))) return i; if (card->doubleS0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -