📄 toshoboe.c
字号:
); self = (struct toshoboe_cb *) dev->priv; ASSERT (self != NULL, return 0; ); if (self->stopped) return 0; if (request_irq (self->io.irq, toshoboe_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self)) { return -EAGAIN; } toshoboe_initbuffs (self); toshoboe_enablebm (self); toshoboe_startchip (self); toshoboe_initptrs (self); /* Ready to play! */ netif_start_queue(dev); /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ self->irlap = irlap_open(dev, &self->qos); self->open = 1; MOD_INC_USE_COUNT; return 0;}static inttoshoboe_net_close (struct net_device *dev){ struct toshoboe_cb *self; IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (dev != NULL, return -1; ); self = (struct toshoboe_cb *) dev->priv; /* Stop device */ netif_stop_queue(dev); /* Stop and remove instance of IrLAP */ if (self->irlap) irlap_close(self->irlap); self->irlap = NULL; self->open = 0; free_irq (self->io.irq, (void *) self); if (!self->stopped) { toshoboe_stopchip (self); toshoboe_disablebm (self); } MOD_DEC_USE_COUNT; return 0;}/* * Function toshoboe_net_ioctl (dev, rq, cmd) * * Process IOCTL commands for this device * */static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ struct if_irda_req *irq = (struct if_irda_req *) rq; struct toshoboe_cb *self; unsigned long flags; int ret = 0; ASSERT(dev != NULL, return -1;); self = dev->priv; ASSERT(self != NULL, return -1;); IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); /* Disable interrupts & save flags */ save_flags(flags); cli(); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ if (!capable(CAP_NET_ADMIN)) return -EPERM; /* toshoboe_setbaud(self, irq->ifr_baudrate); */ /* Just change speed once - inserted by Paul Bristow */ self->new_speed = irq->ifr_baudrate; break; case SIOCSMEDIABUSY: /* Set media busy */ if (!capable(CAP_NET_ADMIN)) return -EPERM; irda_device_set_media_busy(self->netdev, TRUE); break; case SIOCGRECEIVING: /* Check if we are receiving right now */ irq->ifr_receiving = 0; /* Can't tell */ break; default: ret = -EOPNOTSUPP; } restore_flags(flags); return ret;}#ifdef MODULEMODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");MODULE_PARM (max_baud, "i");MODULE_PARM_DESC(max_baus, "Maximum baud rate");static inttoshoboe_close (struct toshoboe_cb *self){ int i; IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (self != NULL, return -1; ); if (!self->stopped) { toshoboe_stopchip (self); toshoboe_disablebm (self); } release_region (self->io.sir_base, self->io.sir_ext); for (i = 0; i < TX_SLOTS; ++i) { kfree (self->xmit_bufs[i]); self->xmit_bufs[i] = NULL; } for (i = 0; i < RX_SLOTS; ++i) { kfree (self->recv_bufs[i]); self->recv_bufs[i] = NULL; } if (self->netdev) { /* Remove netdevice */ rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } kfree (self->taskfilebuf); self->taskfilebuf = NULL; self->taskfile = NULL; return (0);}#endifstatic inttoshoboe_open (struct pci_dev *pci_dev){ struct toshoboe_cb *self; struct net_device *dev; struct pm_dev *pmdev; int i = 0; int ok = 0; int err; IRDA_DEBUG (4, __FUNCTION__ "()\n"); while (dev_self[i]) i++; if (i == NSELFS) { printk (KERN_ERR "Oboe: No more instances available"); return -ENOMEM; } self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL); if (self == NULL) { printk (KERN_ERR "IrDA: Can't allocate memory for " "IrDA control block!\n"); return -ENOMEM; } memset (self, 0, sizeof (struct toshoboe_cb)); dev_self[i] = self; /*This needs moving if we ever get more than one chip */ self->open = 0; self->stopped = 0; self->pdev = pci_dev; self->base = pci_dev->resource[0].start; self->io.sir_base = self->base; self->io.irq = pci_dev->irq; self->io.sir_ext = CHIP_IO_EXTENT; self->io.speed = 9600; /* Lock the port that we need */ i = check_region (self->io.sir_base, self->io.sir_ext); if (i < 0) { IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", self->io.sir_base); dev_self[i] = NULL; kfree (self); return -ENODEV; } irda_init_max_qos_capabilies (&self->qos); self->qos.baud_rate.bits = 0; if (max_baud >= 2400) self->qos.baud_rate.bits |= IR_2400; /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */ if (max_baud >= 9600) self->qos.baud_rate.bits |= IR_9600; if (max_baud >= 19200) self->qos.baud_rate.bits |= IR_19200; if (max_baud >= 115200) self->qos.baud_rate.bits |= IR_115200;#ifdef ENABLE_FAST if (max_baud >= 576000) self->qos.baud_rate.bits |= IR_576000; if (max_baud >= 1152000) self->qos.baud_rate.bits |= IR_1152000; if (max_baud >= 4000000) self->qos.baud_rate.bits |= (IR_4000000 << 8);#endif self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */ irda_qos_bits_to_value (&self->qos); self->flags = IFF_SIR | IFF_DMA | IFF_PIO;#ifdef ENABLE_FAST if (max_baud >= 576000) self->flags |= IFF_FIR;#endif /* Now setup the endless buffers we need */ self->txs = 0; self->rxs = 0; self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL); if (!self->taskfilebuf) { printk (KERN_ERR "toshoboe: kmalloc for DMA failed()\n"); kfree (self); return -ENOMEM; } memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN); /*We need to align the taskfile on a taskfile size boundary */ { __u32 addr; addr = (__u32) self->taskfilebuf; addr &= ~(sizeof (struct OboeTaskFile) - 1); addr += sizeof (struct OboeTaskFile); self->taskfile = (struct OboeTaskFile *) addr; } for (i = 0; i < TX_SLOTS; ++i) { self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); if (self->xmit_bufs[i]) ok++; } for (i = 0; i < RX_SLOTS; ++i) { self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); if (self->recv_bufs[i]) ok++; } if (ok != RX_SLOTS + TX_SLOTS) { printk (KERN_ERR "toshoboe: kmalloc for buffers failed()\n"); for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree (self->xmit_bufs[i]); for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree (self->recv_bufs[i]); kfree (self); return -ENOMEM; } request_region (self->io.sir_base, self->io.sir_ext, driver_name); if (!(dev = dev_alloc("irda%d", &err))) { ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); return -ENOMEM; } dev->priv = (void *) self; self->netdev = dev; MESSAGE("IrDA: Registered device %s\n", dev->name); dev->init = toshoboe_net_init; dev->hard_start_xmit = toshoboe_hard_xmit; dev->open = toshoboe_net_open; dev->stop = toshoboe_net_close; dev->do_ioctl = toshoboe_net_ioctl; rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); return -1; } pmdev = pm_register (PM_PCI_DEV, PM_PCI_ID(pci_dev), toshoboe_pmproc); if (pmdev) pmdev->data = self; printk (KERN_WARNING "ToshOboe: Using ");#ifdef ONETASK printk ("single");#else printk ("multiple");#endif printk (" tasks, version %s\n", rcsid); return (0);}static void toshoboe_gotosleep (struct toshoboe_cb *self){ int i = 10; printk (KERN_WARNING "ToshOboe: suspending\n"); if (self->stopped) return; self->stopped = 1; if (!self->open) return;/*FIXME: can't sleep here wait one second */ while ((i--) && (self->txpending)) mdelay (100); toshoboe_stopchip (self); toshoboe_disablebm (self); self->txpending = 0;}static void toshoboe_wakeup (struct toshoboe_cb *self){ unsigned long flags; if (!self->stopped) return; if (!self->open) { self->stopped = 0; return; } save_flags (flags); cli (); toshoboe_initbuffs (self); toshoboe_enablebm (self); toshoboe_startchip (self); toshoboe_setbaud (self, self->io.speed); toshoboe_initptrs (self); netif_wake_queue(self->netdev); restore_flags (flags); printk (KERN_WARNING "ToshOboe: waking up\n");}static int toshoboe_pmproc (struct pm_dev *dev, pm_request_t rqst, void *data){ struct toshoboe_cb *self = (struct toshoboe_cb *) dev->data; if (self) { switch (rqst) { case PM_SUSPEND: toshoboe_gotosleep (self); break; case PM_RESUME: toshoboe_wakeup (self); break; } } return 0;}int __init toshoboe_init (void){ struct pci_dev *pci_dev = NULL; int found = 0; do { pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, pci_dev); if (pci_dev) { printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n", pci_dev->resource[0].start, pci_dev->irq); if (!toshoboe_open (pci_dev)) found++; } } while (pci_dev); if (found) { return 0; } return -ENODEV;}#ifdef MODULEstatic voidtoshoboe_cleanup (void){ int i; IRDA_DEBUG (4, __FUNCTION__ "()\n"); for (i = 0; i < 4; i++) { if (dev_self[i]) toshoboe_close (dev_self[i]); } pm_unregister_all (toshoboe_pmproc);}intinit_module (void){ return toshoboe_init ();}voidcleanup_module (void){ toshoboe_cleanup ();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -