📄 sdl_acb56.c
字号:
for (i=0;i<sizeof(preset);) { outb(preset[i],actrl); i++; outb(p->regs[i>>1]=preset[i],actrl); i++; } /* setup interface and clock modes */ outb(0x0b,actrl); outb(p->regs[0x0b]=mode_clock[mode_map[dev->ifmode]][clock_map[dev->ifclock]],actrl); /* setup baud rate generator */ if (dev->ifmode==DEV_MODE_DTE) { outb(0x0c,actrl);outb(p->regs[0xc]=0xca,actrl); outb(0x0d,actrl);outb(p->regs[0xd]=0x1c,actrl); } else if (dev->ifmode==DEV_MODE_LOC_LB) { outb(0x0c,actrl);outb(p->regs[0xc]=0x00,actrl); outb(0x0d,actrl);outb(p->regs[0xd]=0x00,actrl); } else { outb(0x0c,actrl);outb(p->regs[0xc]=0x40,actrl); outb(0x0d,actrl);outb(p->regs[0xd]=0x00,actrl); } /* special DPLL modes */ if (dev->ifclock==DEV_CLOCK_DPLL) { outb(0x0e,actrl);outb(0x60,actrl); outb(0x0e,actrl);outb(0xe0,actrl); if (dev->ifmode==DEV_MODE_DTE) { outb(0x0e,actrl);outb(0xa0,actrl); } else { outb(0x0e,actrl);outb(0x80,actrl); } outb(0x0e,actrl);outb(0x20,actrl); } outb(0x0e,actrl);outb(p->regs[0x0e]=0x02,actrl); /* setup loopback and echo modes */ switch(dev->ifmode) { case DEV_MODE_LOC_LB: outb(0x0e,actrl); outb(p->regs[0x0e]|=0x10,actrl); break; case DEV_MODE_ECHO: outb(0x0e,actrl); outb(p->regs[0x0e]|=0x08,actrl); break; case DEV_MODE_LB_ECHO: outb(0x0e,actrl); outb(p->regs[0x0e]|=0x18,actrl); break; } /* set up dma registers */ if (dev->dma_rx||dev->dma_tx) { outb(0x0e,actrl); outb(p->regs[0x0e]|=0x04,actrl); if (dev->dma_rx&&dev->dma_tx) { outb(0x01,actrl); outb(p->regs[0x01]|=0xf9,actrl); } if (dev->dma_tx) { outb(0x01,actrl); outb(p->regs[0x01]|=0xc1,actrl); } if (dev->dma_tx) { outb(0x01,actrl); outb(p->regs[0x01]|=0xfb,actrl); } outb(0x80,actrl+3); if (dev->dma_rx) enable_dma(dev->dma_rx); if (dev->dma_tx) enable_dma(dev->dma_tx); } else { outb(0x0e,actrl); outb(p->regs[0x0e]&=~0x04,actrl); outb(0x01,actrl); outb(p->regs[0x01]|=0x13,actrl); outb(0x00,actrl+3); } /* disable status fifo */ outb(0x0f,actrl); outb(0xfc,actrl); outb(0x09,actrl); outb(0x02,actrl); /* reset and enable transmitters and receivers */ outb(0x0E,actrl); outb(p->regs[0x0e]|=0x01,actrl); outb(0x03,actrl); outb(p->regs[0x0e]|=0x01,actrl); outb(0x00,actrl); outb(0x30,actrl); outb(0x05,actrl); outb(p->regs[0x0e]|=0x08,actrl); outb(0x00,actrl); outb(0x80,actrl); outb(0x00,actrl); outb(0xC0,actrl); outb(0x00,actrl); outb(0x10,actrl); outb(0x00,actrl); outb(0x10,actrl); dev->ifflags |= DEV_IF_TX_RUNNING; dev->ifflags |= DEV_IF_RX_RUNNING; bufq_init(&p->tinputq); acb56_resupply(NULL); p->tx_msg = bufq_dequeue(&acb56_supplyq); acb56_resupply(NULL); p->rx_msg = bufq_dequeue(&acb56_supplyq); acb56_resupply(NULL); p->cp_msg = bufq_dequeue(&acb56_supplyq); acb56_resupply(NULL); if ( !p->tx_msg || !p->rx_msg || !p->cp_msg ) { if ( p->tx_msg ) freemsg (p->tx_msg); if ( p->rx_msg ) freemsg (p->rx_msg); if ( p->cp_msg ) freemsg (p->cp_msg); spin_unlock_irqrestore(&dev->iflock, flags); return ENOBUFS; } *(p->tx_msg->b_wptr)++ = 0x80; /* Initial SIOS */ *(p->tx_msg->b_wptr)++ = 0x80; /* Initial SIOS */ *(p->tx_msg->b_wptr)++ = 0x01; /* Initial SIOS */ *(p->tx_msg->b_wptr)++ = 0x00; /* Initial SIOS */ /* enable master interrupt bit */ outb(0x09,actrl); outb(p->regs[0x09]|=0x08,actrl); /* we're running! phew! */ spin_unlock_irqrestore(&dev->iflock, flags); return (0);}/* * DISABLE: This should shut down the hardware and deactivate ISRs and other * routines, flush buffers to the point that kernel resource which were * allocated can be deallocated in the close. */static intacb56_disable(lmi_t *lmi){ acb56_t *p = (acb56_t *)lmi; dev_device_t *dev = &p->dev.iface; int actrl = dev->iobase+1; unsigned long flags; spin_lock_irqsave(&dev->iflock, flags); dev->ifflags &= ~DEV_IF_TX_RUNNING; dev->ifflags &= ~DEV_IF_RX_RUNNING; dev->ifflags &= ~DEV_IF_SU_COMPRESS; outb(0x09,actrl); outb(0xc0,actrl); /* force hw reset */ outb(0x09,actrl); outb(p->regs[0x09]&=~0x08,actrl); /* stop interrupts */ if (dev->dma_tx) { outb(0x0e,actrl); outb(p->regs[0x0e]&=~0x04,actrl); /* disable dma */ disable_dma(dev->dma_tx); } if (dev->dma_rx) { outb(0x01,actrl); outb(p->regs[0x01]&=~0xc0,actrl); /* disable dma */ disable_dma(dev->dma_rx); } outb(0x09,actrl); outb(0xc0,actrl); /* force hw reset */ bufq_purge(&p->tinputq); spin_unlock_irqrestore(&dev->iflock, flags); return(0);}/* * IOCTLS: These are ioctls which are general for SDL and which are specific * to device interfaces and which are privdte for the ACB56 drivers. They * are invoked at the stream head. */static int acb56_ioctl(lmi_t *sdl, int cmd, void *arg){ size_t size = _IOC_SIZE(cmd); acb56_t *p = (acb56_t *)sdl->device; dev_device_t *dev = &p->dev.iface; sdl_config_t *ureq = NULL; sdl_ulong uarg = 0; if ( _IOC_TYPE(cmd) == SDL_IOC_MAGIC ) switch ( cmd ) { case SDL_IOCTCONFIG: case SDL_IOCSCONFIG: if ( !arg || size < sizeof(dev_device_t) ) return EINVAL; ureq = arg; break; case SDL_IOCCCONFIG: case SDL_IOCCMRESET: break; default: return EOPNOTSUPP; } if ( _IOC_TYPE(cmd) == DEV_IOC_MAGIC ) switch ( cmd ) { case DEV_IOCGIFFLAGS: case DEV_IOCGIFTYPE: case DEV_IOCGGRPTYPE: case DEV_IOCGIFMODE: case DEV_IOCGIFRATE: case DEV_IOCGIFCLOCK: case DEV_IOCGIFCODING: case DEV_IOCGIFLEADS: case DEV_IOCSIFFLAGS: case DEV_IOCSIFTYPE: case DEV_IOCSGRPTYPE: case DEV_IOCSIFMODE: case DEV_IOCSIFRATE: case DEV_IOCSIFCLOCK: case DEV_IOCSIFCODING: case DEV_IOCSIFLEADS: case DEV_IOCCIFLEADS: if ( !arg || size < sizeof(dev_ulong) ) return EINVAL; uarg = *(dev_ulong *)arg; break; case DEV_IOCCIFRESET: case DEV_IOCCDISCTX: case DEV_IOCCCONNTX: break; default: return EOPNOTSUPP; } if ( _IOC_TYPE(cmd) == SDL_IOC_MAGIC ) switch ( cmd ) { case SDL_IOCTCONFIG: case SDL_IOCSCONFIG: case SDL_IOCCCONFIG: case SDL_IOCCMRESET: break; default: return EOPNOTSUPP; } if ( _IOC_TYPE(cmd) == DEV_IOC_MAGIC ) switch ( cmd ) { case DEV_IOCCIFRESET: break; /* gets */ case DEV_IOCGIFFLAGS: *(dev_ulong *)arg = dev->ifflags; return(0); case DEV_IOCGIFTYPE: *(dev_ulong *)arg = dev->iftype; return(0); case DEV_IOCGGRPTYPE: *(dev_ulong *)arg = dev->ifgtype; return(0); case DEV_IOCGIFMODE: *(dev_ulong *)arg = dev->ifmode; return(0); case DEV_IOCGIFRATE: *(dev_ulong *)arg = dev->ifrate; return(0); case DEV_IOCGIFCLOCK: *(dev_ulong *)arg = dev->ifclock; return(0); case DEV_IOCGIFCODING: *(dev_ulong *)arg = dev->ifcoding; return(0); case DEV_IOCGIFLEADS: *(dev_ulong *)arg = dev->ifleads; return(0); /* sets */ case DEV_IOCSIFFLAGS: if ( sdl->state == LMI_ENABLED ) return EBUSY; dev->ifflags = uarg; return(0); case DEV_IOCSIFTYPE: if ( sdl->state == LMI_ENABLED ) return EBUSY; if ( uarg != DEV_TYPE_V35 ) return EINVAL; return(0); case DEV_IOCSGRPTYPE: if ( sdl->state == LMI_ENABLED ) return EBUSY; if ( uarg != DEV_GTYPE_NONE ) return EINVAL; return(0); case DEV_IOCSIFMODE: ptrace(("uarg = %lu\n", uarg)); if ( sdl->state == LMI_ENABLED ) return EBUSY; switch ( uarg ) { case DEV_MODE_DTE: case DEV_MODE_DCE: case DEV_MODE_REM_LB: case DEV_MODE_LOC_LB: case DEV_MODE_LB_ECHO: case DEV_MODE_TEST: if ( mode_map[uarg]!=-1 ) { dev->ifmode = uarg; return(0); } default: return EINVAL; } return(0); case DEV_IOCSIFRATE: if ( sdl->state == LMI_ENABLED ) return EBUSY; if ( uarg != 56000 ) return EINVAL; return(0); case DEV_IOCSIFCLOCK: ptrace(("uarg = %lu\n", uarg)); if ( sdl->state == LMI_ENABLED ) return EBUSY; switch ( uarg ) { case DEV_CLOCK_INT: case DEV_CLOCK_EXT: case DEV_CLOCK_DPLL: if ( clock_map[uarg]!=-1 ) { dev->ifclock = uarg; return(0); } default: return EINVAL; } return(0); case DEV_IOCSIFCODING: if ( sdl->state == LMI_ENABLED ) return EBUSY; if ( uarg != DEV_CODING_NRZI ) return EINVAL; return(0); case DEV_IOCSIFLEADS: case DEV_IOCCIFLEADS: /* FIXME: control the leads */ if ( uarg ) return EINVAL; return(0); case DEV_IOCCDISCTX: dev->ifflags &= ~DEV_IF_TX_RUNNING; return(0); case DEV_IOCCCONNTX: dev->ifflags |= DEV_IF_TX_RUNNING; return(0); } return EOPNOTSUPP;}static struct lmi_ops acb56_lmi_ops ={ { acb56_devatt, /* dev.attach */ acb56_open, /* dev.open */ acb56_close, /* dev.close */ }, { acb56_info, /* lmi.info */ acb56_attach, /* lmi.attach */ acb56_detach, /* lmi.detach */ acb56_enable, /* lmi.enable */ acb56_disable, /* lmi.disable */ acb56_ioctl /* lmi.ioctl */ }};/* * ========================================================================= * * SERVICE ROUTINES * * ========================================================================= */static voidacb56_xmit(struct dev *dev, mblk_t *mp){ acb56_t *p = (acb56_t *)dev; unsigned long flags; spin_lock_irqsave(&dev->iface.iflock, flags); if ( !(dev->iface.ifflags & DEV_IF_TX_RUNNING) ) freemsg(mp); else bufq_queue(&p->tinputq, mp); spin_unlock_irqrestore(&dev->iface.iflock, flags);}static voidacb56_tx_start(struct dev *dev){ dev->iface.ifflags |= DEV_IF_TX_RUNNING;}static voidacb56_rx_start(struct dev *dev){ dev->iface.ifflags |= DEV_IF_RX_RUNNING;}static dev_dcalls_t acb56_dcalls ={ acb56_xmit, /* daedt_xmit */ acb56_tx_start, /* daedt_start */ acb56_rx_start /* daedr_start */};/* * ======================================================================= * * LiS Module Initialization (For registered driver.) * * ======================================================================= */static int acb56_initialized = 0;voidacb56_init(void){ if ( acb56_initialized > 0 ) return; printk(KERN_INFO ACB56_BANNER); /* console splash */ ptrace(("registering sdl_acb: cmajor %d, nminors %d\n", ACB56_CMAJOR, ACB56_NMINOR)); acb56_initialized = sdl_register_driver(ACB56_CMAJOR, ACB56_NMINOR, "sdl_acb", &acb56_lmi_ops, &acb56_dcalls); ptrace(("return (device major) = %d\n", acb56_initialized)); if ( acb56_initialized > 0 ) acb56_cmajor = acb56_initialized; if ( acb56_initialized == 0 ) acb56_initialized = acb56_cmajor; if ( debug != -1 ) acb56_debug = debug; bufq_init(&acb56_supplyq); bufq_init(&acb56_returnq);}voidacb56_terminate(void){ if ( acb56_initialized <= 0 ) return; ptrace(("unregistering sdl_acb cmajor %d\n", acb56_cmajor)); acb56_initialized = sdl_unregister_driver(acb56_cmajor); ptrace(("return = %d\n", acb56_initialized)); bufq_purge(&acb56_supplyq); bufq_purge(&acb56_returnq);}/* * ======================================================================= * * Kernel Module Initialization (For unregistered driver.) * * ======================================================================= */#ifdef MODULEintinit_module(void){ (void)acb56_debug; acb56_init(); if ( acb56_initialized < 0 ) return acb56_initialized; return (0);}voidcleanup_module(void){ acb56_terminate();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -