📄 donauboe.c
字号:
IRDA_DEBUG (1, "%s.sip:%x(%x)%x\n", __FUNCTION__ ,self->int_sip,irqstat,self->txpending); } return IRQ_HANDLED;}static inttoshoboe_net_open (struct net_device *dev){ struct toshoboe_cb *self; unsigned long flags; int rc; IRDA_DEBUG (4, "%s()\n", __FUNCTION__); self = netdev_priv(dev); if (self->async) return -EBUSY; if (self->stopped) return 0; rc = request_irq (self->io.irq, toshoboe_interrupt, IRQF_SHARED | IRQF_DISABLED, dev->name, self); if (rc) return rc; spin_lock_irqsave(&self->spinlock, flags); toshoboe_startchip (self); spin_unlock_irqrestore(&self->spinlock, flags); /* 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, driver_name); self->irdad = 1; return 0;}static inttoshoboe_net_close (struct net_device *dev){ struct toshoboe_cb *self; IRDA_DEBUG (4, "%s()\n", __FUNCTION__); IRDA_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->irdad = 0; free_irq (self->io.irq, (void *) self); if (!self->stopped) { toshoboe_stopchip (self); } return 0;}/* * Function toshoboe_net_ioctl (dev, rq, cmd) * * Process IOCTL commands for this device * */static inttoshoboe_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; IRDA_ASSERT (dev != NULL, return -1; ); self = dev->priv; IRDA_ASSERT (self != NULL, return -1; ); IRDA_DEBUG (5, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); /* Disable interrupts & save flags */ spin_lock_irqsave(&self->spinlock, flags); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ /* This function will also be used by IrLAP to change the * speed, so we still must allow for speed change within * interrupt context. */ IRDA_DEBUG (1, "%s(BANDWIDTH), %s, (%X/%ld\n", __FUNCTION__ ,dev->name, INB (OBOE_STATUS), irq->ifr_baudrate ); if (!in_interrupt () && !capable (CAP_NET_ADMIN)) { ret = -EPERM; goto out; } /* self->speed=irq->ifr_baudrate; */ /* toshoboe_setbaud(self); */ /* Just change speed once - inserted by Paul Bristow */ self->new_speed = irq->ifr_baudrate; break; case SIOCSMEDIABUSY: /* Set media busy */ IRDA_DEBUG (1, "%s(MEDIABUSY), %s, (%X/%x)\n", __FUNCTION__ ,dev->name, INB (OBOE_STATUS), capable (CAP_NET_ADMIN) ); 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 = (INB (OBOE_STATUS) & OBOE_STATUS_RXBUSY) ? 1 : 0; IRDA_DEBUG (3, "%s(RECEIVING), %s, (%X/%x)\n", __FUNCTION__ ,dev->name, INB (OBOE_STATUS), irq->ifr_receiving ); break; default: IRDA_DEBUG (1, "%s(?), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); ret = -EOPNOTSUPP; }out: spin_unlock_irqrestore(&self->spinlock, flags); return ret;}MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");MODULE_LICENSE("GPL");module_param (max_baud, int, 0);MODULE_PARM_DESC(max_baud, "Maximum baud rate");#ifdef USE_PROBEmodule_param (do_probe, bool, 0);MODULE_PARM_DESC(do_probe, "Enable/disable chip probing and self-test");#endifstatic voidtoshoboe_close (struct pci_dev *pci_dev){ int i; struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); IRDA_DEBUG (4, "%s()\n", __FUNCTION__); IRDA_ASSERT (self != NULL, return; ); if (!self->stopped) { toshoboe_stopchip (self); } release_region (self->io.fir_base, self->io.fir_ext); for (i = 0; i < TX_SLOTS; ++i) { kfree (self->tx_bufs[i]); self->tx_bufs[i] = NULL; } for (i = 0; i < RX_SLOTS; ++i) { kfree (self->rx_bufs[i]); self->rx_bufs[i] = NULL; } unregister_netdev(self->netdev); kfree (self->ringbuf); self->ringbuf = NULL; self->ring = NULL; free_netdev(self->netdev);}static inttoshoboe_open (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, "%s()\n", __FUNCTION__); if ((err=pci_enable_device(pci_dev))) return err; dev = alloc_irdadev(sizeof (struct toshoboe_cb)); if (dev == NULL) { printk (KERN_ERR DRIVER_NAME ": can't allocate memory for " "IrDA control block\n"); return -ENOMEM; } self = dev->priv; self->netdev = dev; self->pdev = pci_dev; self->base = pci_resource_start(pci_dev,0); self->io.fir_base = self->base; self->io.fir_ext = OBOE_IO_EXTENT; self->io.irq = pci_dev->irq; self->io.irqflags = IRQF_SHARED | IRQF_DISABLED; self->speed = self->io.speed = 9600; self->async = 0; /* Lock the port that we need */ if (NULL==request_region (self->io.fir_base, self->io.fir_ext, driver_name)) { printk (KERN_ERR DRIVER_NAME ": can't get iobase of 0x%03x\n" ,self->io.fir_base); err = -EBUSY; goto freeself; } spin_lock_init(&self->spinlock); 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 USE_MIR if (max_baud >= 1152000) { self->qos.baud_rate.bits |= IR_1152000; }#endif if (max_baud >= 4000000) { self->qos.baud_rate.bits |= (IR_4000000 << 8); } /*FIXME: work this out... */ self->qos.min_turn_time.bits = 0xff; irda_qos_bits_to_value (&self->qos); /* Allocate twice the size to guarantee alignment */ self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL); if (!self->ringbuf) { printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n"); err = -ENOMEM; goto freeregion; }#if (BITS_PER_LONG == 64)#error broken on 64-bit: casts pointer to 32-bit, and then back to pointer.#endif /*We need to align the taskfile on a taskfile size boundary */ { unsigned long addr; addr = (__u32) self->ringbuf; addr &= ~(OBOE_RING_LEN - 1); addr += OBOE_RING_LEN; self->ring = (struct OboeRing *) addr; } memset (self->ring, 0, OBOE_RING_LEN); self->io.mem_base = (__u32) self->ring; ok = 1; for (i = 0; i < TX_SLOTS; ++i) { self->tx_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL); if (!self->tx_bufs[i]) ok = 0; } for (i = 0; i < RX_SLOTS; ++i) { self->rx_bufs[i] = kmalloc (RX_BUF_SZ, GFP_KERNEL); if (!self->rx_bufs[i]) ok = 0; } if (!ok) { printk (KERN_ERR DRIVER_NAME ": can't allocate rx/tx buffers\n"); err = -ENOMEM; goto freebufs; }#ifdef USE_PROBE if (do_probe) if (!toshoboe_probe (self)) { err = -ENODEV; goto freebufs; }#endif SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pci_dev->dev); dev->hard_start_xmit = toshoboe_hard_xmit; dev->open = toshoboe_net_open; dev->stop = toshoboe_net_close; dev->do_ioctl = toshoboe_net_ioctl; err = register_netdev(dev); if (err) { printk (KERN_ERR DRIVER_NAME ": register_netdev() failed\n"); err = -ENOMEM; goto freebufs; } printk (KERN_INFO "IrDA: Registered device %s\n", dev->name); pci_set_drvdata(pci_dev,self); printk (KERN_INFO DRIVER_NAME ": Using multiple tasks, version %s\n", rcsid); return 0;freebufs: for (i = 0; i < TX_SLOTS; ++i) kfree (self->tx_bufs[i]); for (i = 0; i < RX_SLOTS; ++i) kfree (self->rx_bufs[i]); kfree(self->ringbuf);freeregion: release_region (self->io.fir_base, self->io.fir_ext);freeself: free_netdev(dev); return err;}static inttoshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap){ struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); unsigned long flags; int i = 10; IRDA_DEBUG (4, "%s()\n", __FUNCTION__); if (!self || self->stopped) return 0; if ((!self->irdad) && (!self->async)) return 0;/* Flush all packets */ while ((i--) && (self->txpending)) udelay (10000); spin_lock_irqsave(&self->spinlock, flags); toshoboe_stopchip (self); self->stopped = 1; self->txpending = 0; spin_unlock_irqrestore(&self->spinlock, flags); return 0;}static inttoshoboe_wakeup (struct pci_dev *pci_dev){ struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev); unsigned long flags; IRDA_DEBUG (4, "%s()\n", __FUNCTION__); if (!self || !self->stopped) return 0; if ((!self->irdad) && (!self->async)) return 0; spin_lock_irqsave(&self->spinlock, flags); toshoboe_startchip (self); self->stopped = 0; netif_wake_queue(self->netdev); spin_unlock_irqrestore(&self->spinlock, flags); return 0;}static struct pci_driver donauboe_pci_driver = { .name = "donauboe", .id_table = toshoboe_pci_tbl, .probe = toshoboe_open, .remove = toshoboe_close, .suspend = toshoboe_gotosleep, .resume = toshoboe_wakeup };static int __initdonauboe_init (void){ return pci_register_driver(&donauboe_pci_driver);}static void __exitdonauboe_cleanup (void){ pci_unregister_driver(&donauboe_pci_driver);}module_init(donauboe_init);module_exit(donauboe_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -