📄 sdlamain.c
字号:
err = wpf_init(card, conf); break;#endif#ifdef CONFIG_WANPIPE_PPP case SFID_PPP502: case SFID_PPP508: err = wpp_init(card, conf); break;#endif default: printk(KERN_ERR "%s: this firmware is not supported!\n", wandev->name) ; err = -EINVAL; } if (err) { sdla_down(&card->hw); free_irq(irq, card); return err; } /* Reserve I/O region and schedule background task *//* printk(KERN_INFO "about to request\n");*/ request_region(card->hw.port, card->hw.io_range, wandev->name);/* printk(KERN_INFO "request done\n");*/ if (++active == 1) queue_task(&sdla_tq, &tq_scheduler); wandev->critical = 0; return 0;}/*============================================================================ * Shut down WAN link driver. * o shut down adapter hardware * o release system resources. * * This function is called by the router when device is being unregistered or * when it handles ROUTER_DOWN IOCTL. */static int shutdown (wan_device_t* wandev){ sdla_t* card; /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; if (wandev->state == WAN_UNCONFIGURED) return 0; /* If wee are in a critical section we lose */ if (test_and_set_bit(0, (void*)&wandev->critical)) return -EAGAIN; card = wandev->private; wandev->state = WAN_UNCONFIGURED; if (--active == 0) schedule(); /* stop background thread */ /* printk(KERN_INFO "active now %d\n", active); printk(KERN_INFO "About to call sdla_down\n");*/ sdla_down(&card->hw);/* printk(KERN_INFO "sdla_down done\n"); printk(KERN_INFO "About to call free_irq\n");*/ free_irq(wandev->irq, card);/* printk(KERN_INFO "free_irq done\n"); printk(KERN_INFO "About to call release_region\n");*/ release_region(card->hw.port, card->hw.io_range);/* printk(KERN_INFO "release_region done\n");*/ wandev->critical = 0; return 0;}/*============================================================================ * Driver I/O control. * o verify arguments * o perform requested action * * This function is called when router handles one of the reserved user * IOCTLs. Note that 'arg' stil points to user address space. */static int ioctl (wan_device_t* wandev, unsigned cmd, unsigned long arg){ int err; /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT ; if (wandev->state == WAN_UNCONFIGURED) return -ENODEV ; if (test_and_set_bit(0, (void*)&wandev->critical)) return -EAGAIN ; switch (cmd) { case WANPIPE_DUMP: err = ioctl_dump(wandev->private, (void*)arg); break; case WANPIPE_EXEC: err = ioctl_exec(wandev->private, (void*)arg); break; default: err = -EINVAL; } wandev->critical = 0; return err;}/****** Driver IOCTL Hanlers ************************************************//*============================================================================ * Dump adapter memory to user buffer. * o verify request structure * o copy request structure to kernel data space * o verify length/offset * o verify user buffer * o copy adapter memory image to user buffer * * Note: when dumping memory, this routine switches curent dual-port memory * vector, so care must be taken to avoid racing conditions. */static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump){ sdla_dump_t dump; unsigned winsize; unsigned long oldvec; /* DPM window vector */ unsigned long flags; int err = 0; if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t))) return -EFAULT; if ((dump.magic != WANPIPE_MAGIC) || (dump.offset + dump.length > card->hw.memory)) return -EINVAL; winsize = card->hw.dpmsize; save_flags(flags); cli(); /* >>> critical section start <<< */ oldvec = card->hw.vector; while (dump.length) { unsigned pos = dump.offset % winsize; /* current offset */ unsigned long vec = dump.offset - pos; /* current vector */ unsigned len = (dump.length > (winsize - pos)) ? (winsize - pos) : dump.length ; if (sdla_mapmem(&card->hw, vec) != 0) /* relocate window */ { err = -EIO; break; } /* FIXME::: COPY TO KERNEL BUFFER FIRST ?? */ sti(); /* Not ideal but tough we have to do this */ if(copy_to_user((void *)dump.ptr, (u8 *)card->hw.dpmbase + pos, len)) return -EFAULT; cli(); dump.length -= len; dump.offset += len; (char*)dump.ptr += len; } sdla_mapmem(&card->hw, oldvec); /* restore DPM window position */ restore_flags(flags); /* >>> critical section end <<< */ return err;}/*============================================================================ * Execute adapter firmware command. * o verify request structure * o copy request structure to kernel data space * o call protocol-specific 'exec' function */static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec){ sdla_exec_t exec; if (card->exec == NULL) return -ENODEV; if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t))) return -EFAULT; if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL)) return -EINVAL; return card->exec(card, exec.cmd, exec.data);}/******* Miscellaneous ******************************************************//*============================================================================ * SDLA Interrupt Service Routine. * o acknowledge SDLA hardware interrupt. * o call protocol-specific interrupt service routine, if any. */STATIC void sdla_isr (int irq, void* dev_id, struct pt_regs *regs){#define card ((sdla_t*)dev_id) if (!card || (card->wandev.state == WAN_UNCONFIGURED)) return ; if (card->in_isr) { printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n", card->devname, card->wandev.irq) ; return; } sdla_intack(&card->hw); if (card->isr) card->isr(card);#undef card}/*============================================================================ * SDLA polling routine. * This routine simulates kernel thread to perform various housekeeping job. * * o for each configured device call its poll() routine * o if there is at least one active card, then reschedule itself once again */STATIC void sdla_poll (void* data){ int i; for (i = 0; i < ncards; ++i) { sdla_t* card = &card_array[i]; if ((card->wandev.state != WAN_UNCONFIGURED) && card->poll && !card->wandev.critical) { card->poll(card); } } if (active) queue_task(&sdla_tq, &tq_scheduler);}/*============================================================================ * This routine is called by the protocol-specific modules when network * interface is being open. The only reason we need this, is because we * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's * defined more than once into the same kernel module. */void wanpipe_open (sdla_t* card){ ++card->open_cnt; MOD_INC_USE_COUNT;}/*============================================================================ * This routine is called by the protocol-specific modules when network * interface is being closed. The only reason we need this, is because we * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's * defined more than once into the same kernel module. */void wanpipe_close (sdla_t* card){ --card->open_cnt; MOD_DEC_USE_COUNT;}/*============================================================================ * Set WAN device state. */void wanpipe_set_state (sdla_t* card, int state){ unsigned long flags; save_flags(flags); cli(); if (card->wandev.state != state) { switch (state) { case WAN_CONNECTED: printk (KERN_INFO "%s: link connected!\n", card->devname) ; break; case WAN_CONNECTING: printk (KERN_INFO "%s: link connecting...\n", card->devname) ; break; case WAN_DISCONNECTED: printk (KERN_INFO "%s: link disconnected!\n", card->devname) ; break; } card->wandev.state = state; } card->state_tick = jiffies; restore_flags(flags);}/****** End *****************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -