⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 donauboe.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 4 页
字号:
      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 + -