📄 toshoboe.c
字号:
/*FIXME: need to test this carefully to check which one */ /*of the two possible startup logics the chip uses */ /*although it won't make any difference if no-one xmits durining init */ /*and none what soever if using ONETASK */ self->rxs = inb_p (OBOE_RCVT); self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;#if 0 self->rxs = 0; self->txs = 0;#endif#if 0 self->rxs = RX_SLOTS - 1; self->txs = 0;#endif self->txpending = 0; restore_flags (flags);}static inttoshoboe_net_open (struct net_device *dev){ struct toshoboe_cb *self; char hwname[32]; IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (dev != NULL, return -1; ); 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); /* Give self a hardware name */ sprintf(hwname, "Toshiba-FIR @ 0x%03x", self->base); /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ self->irlap = irlap_open(dev, &self->qos, hwname); 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)) { ret = -EPERM; goto out; } /* 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)) { ret = -EPERM; goto out; } 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; }out: restore_flags(flags); return ret;}MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");MODULE_LICENSE("GPL");MODULE_PARM (max_baud, "i");MODULE_PARM_DESC(max_baus, "Maximum baud rate");static voidtoshoboe_remove (struct pci_dev *pci_dev){ int i; struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (self != NULL, return; ); 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;}static inttoshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid){ struct toshoboe_cb *self; struct net_device *dev; int i = 0; int ok = 0; int err; IRDA_DEBUG (4, __FUNCTION__ "()\n"); if ((err=pci_enable_device(pci_dev))) return err; 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)); self->open = 0; self->stopped = 0; self->pdev = pci_dev; self->base = pci_resource_start(pci_dev,0); 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 */ if (NULL==request_region (self->io.sir_base, self->io.sir_ext, driver_name)) { IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", self->io.sir_base); err = -EBUSY; goto freeself; } 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"); err = -ENOMEM; goto freeregion; } 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"); err = -ENOMEM; goto freebufs; } if (!(dev = dev_alloc("irda%d", &err))) { ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); err = -ENOMEM; goto freebufs; } 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"); /* XXX there is not freeing for dev? */ goto freebufs; } pci_set_drvdata(pci_dev,self); printk (KERN_WARNING "ToshOboe: Using ");#ifdef ONETASK printk ("single");#else printk ("multiple");#endif printk (" tasks, version %s\n", rcsid); return (0);freebufs: 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->taskfilebuf);freeregion: release_region (self->io.sir_base, self->io.sir_ext);freeself: kfree (self); return err;}static inttoshoboe_suspend (struct pci_dev *pci_dev, u32 crap){ int i = 10; struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); printk (KERN_WARNING "ToshOboe: suspending\n"); if (!self || self->stopped) return 0; self->stopped = 1; if (!self->open) return 0;/*FIXME: can't sleep here wait one second */ while ((i--) && (self->txpending)) udelay (100); toshoboe_stopchip (self); toshoboe_disablebm (self); self->txpending = 0; return 0;}static int toshoboe_resume (struct pci_dev *pci_dev){ struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); unsigned long flags; if (!self) return 0; if (!self->stopped) return 0; if (!self->open) { self->stopped = 0; return 0; } 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"); return 0;}static struct pci_driver toshoboe_pci_driver = { name : "toshoboe", id_table : toshoboe_pci_tbl, probe : toshoboe_probe, remove : toshoboe_remove, suspend : toshoboe_suspend, resume : toshoboe_resume };int __inittoshoboe_init (void){ return pci_module_init(&toshoboe_pci_driver);}voidtoshoboe_cleanup (void){ pci_unregister_driver(&toshoboe_pci_driver);}module_init(toshoboe_init);module_exit(toshoboe_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -