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

📄 donauboe.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 4 页
字号:
      self->txs %= TX_SLOTS;      toshoboe_dumptx (self);      /* Turn on TX and RX and loopback */      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);      i = 0;      n = fir ? 1 : 4;      while (toshoboe_numvalidrcvs (self) != n)        {          if (i > 4800)              return toshoboe_probefail (self, "filter test");          udelay ((9600*(TT_LEN+16))/self->speed);          i++;        }      n = fir ? 203 : 102;      while ((toshoboe_numrcvs(self) != self->int_rx) || (self->int_tx != n))        {          if (i > 4800)              return toshoboe_probefail (self, "interrupt test");          udelay ((9600*(TT_LEN+16))/self->speed);          i++;        }     toshoboe_dumprx (self,i);     }  /* test 2: SIR in char at a time */  toshoboe_stopchip (self);  self->int_rx = self->int_tx = 0;  spin_lock_irqsave(&self->spinlock, flags);  toshoboe_startchip (self);  spin_unlock_irqrestore(&self->spinlock, flags);  self->async = 1;  self->speed = 115200;  toshoboe_setbaud (self);  self->ring->tx[self->txs].control =    OBOE_CTL_TX_RTCENTX | OBOE_CTL_TX_HW_OWNS;  self->ring->tx[self->txs].len = 4;  ((unsigned char *) self->tx_bufs[self->txs])[0] = 'f';  ((unsigned char *) self->tx_bufs[self->txs])[1] = 'i';  ((unsigned char *) self->tx_bufs[self->txs])[2] = 's';  ((unsigned char *) self->tx_bufs[self->txs])[3] = 'h';  toshoboe_dumptx (self);  toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);  i = 0;  while (toshoboe_numvalidrcvs (self) != 4)    {      if (i > 100)          return toshoboe_probefail (self, "Async test");      udelay (100);      i++;    }  while ((toshoboe_numrcvs (self) != self->int_rx) || (self->int_tx != 1))    {      if (i > 100)          return toshoboe_probefail (self, "Async interrupt test");      udelay (100);      i++;    }  toshoboe_dumprx (self,i);  self->async = 0;  self->speed = 9600;  toshoboe_setbaud (self);  toshoboe_stopchip (self);  free_irq (self->io.irq, (void *) self);  printk (KERN_WARNING DRIVER_NAME ": Self test passed ok\n");  return 1;}#endif/******************************************************************//* Netdev style code *//* Transmit something */static inttoshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev){  struct toshoboe_cb *self;  __s32 speed;  int mtt, len, ctl;  unsigned long flags;  struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;  self = (struct toshoboe_cb *) dev->priv;  IRDA_ASSERT (self != NULL, return 0; );  IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __FUNCTION__      ,skb->len,self->txpending,INB (OBOE_ENABLEH));  if (!cb->magic) {      IRDA_DEBUG (2, "%s.Not IrLAP:%x\n", __FUNCTION__, cb->magic);#ifdef DUMP_PACKETS      _dumpbufs(skb->data,skb->len,'>');#endif    }  /* change speed pending, wait for its execution */  if (self->new_speed)      return -EBUSY;  /* device stopped (apm) wait for restart */  if (self->stopped)      return -EBUSY;  toshoboe_checkstuck (self);  dev->trans_start = jiffies; /* Check if we need to change the speed */  /* But not now. Wait after transmission if mtt not required */  speed=irda_get_next_speed(skb);  if ((speed != self->io.speed) && (speed != -1))    {      spin_lock_irqsave(&self->spinlock, flags);      if (self->txpending || skb->len)        {          self->new_speed = speed;          IRDA_DEBUG (1, "%s: Queued TxDone scheduled speed change %d\n" ,		      __FUNCTION__, speed);          /* if no data, that's all! */          if (!skb->len)            {	      spin_unlock_irqrestore(&self->spinlock, flags);              dev_kfree_skb (skb);              return 0;            }          /* True packet, go on, but */          /* do not accept anything before change speed execution */          netif_stop_queue(dev);          /* ready to process TxDone interrupt */	  spin_unlock_irqrestore(&self->spinlock, flags);        }      else        {          /* idle and no data, change speed now */          self->speed = speed;          toshoboe_setbaud (self);	  spin_unlock_irqrestore(&self->spinlock, flags);          dev_kfree_skb (skb);          return 0;        }    }  if ((mtt = irda_get_mtt(skb)))    {      /* This is fair since the queue should be empty anyway */      spin_lock_irqsave(&self->spinlock, flags);      if (self->txpending)        {	  spin_unlock_irqrestore(&self->spinlock, flags);          return -EBUSY;        }      /* If in SIR mode we need to generate a string of XBOFs */      /* In MIR and FIR we need to generate a string of data */      /* which we will add a wrong checksum to */      mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt);      IRDA_DEBUG (1, "%s.mtt:%x(%x)%d\n", __FUNCTION__          ,skb->len,mtt,self->txpending);      if (mtt)        {          self->ring->tx[self->txs].len = mtt & 0xfff;          ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;          if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)            {              ctl |= OBOE_CTL_TX_BAD_CRC | OBOE_CTL_TX_SIP ;            }#ifdef USE_MIR          else if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_MIRON)            {              ctl |= OBOE_CTL_TX_BAD_CRC;            }#endif          self->ring->tx[self->txs].control = ctl;          OUTB (0x0, OBOE_ENABLEH);          /* It is only a timer. Do not send mtt packet outside! */          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);          self->txpending++;          self->txs++;          self->txs %= TX_SLOTS;        }      else        {          printk(KERN_ERR DRIVER_NAME ": problem with mtt packet - ignored\n");        }      spin_unlock_irqrestore(&self->spinlock, flags);    }#ifdef DUMP_PACKETSdumpbufs(skb->data,skb->len,'>');#endif  spin_lock_irqsave(&self->spinlock, flags);  if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS)    {      IRDA_DEBUG (0, "%s.ful:%x(%x)%x\n", __FUNCTION__          ,skb->len, self->ring->tx[self->txs].control, self->txpending);      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);      spin_unlock_irqrestore(&self->spinlock, flags);      return -EBUSY;    }  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON)    {      len = async_wrap_skb (skb, self->tx_bufs[self->txs], TX_BUF_SZ);    }  else    {      len = skb->len;      memcpy (self->tx_bufs[self->txs], skb->data, len);    }  self->ring->tx[self->txs].len = len & 0x0fff;  /*Sometimes the HW doesn't see us assert RTCENTX in the interrupt code */  /*later this plays safe, we garuntee the last packet to be transmitted */  /*has RTCENTX set */  ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)    {      ctl |= OBOE_CTL_TX_SIP ;    }  self->ring->tx[self->txs].control = ctl;  /* If transmitter is idle start in one-shot mode */  if (!self->txpending)      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);  self->txpending++;  self->txs++;  self->txs %= TX_SLOTS;  spin_unlock_irqrestore(&self->spinlock, flags);  dev_kfree_skb (skb);  return 0;}/*interrupt handler */static irqreturn_ttoshoboe_interrupt (int irq, void *dev_id){  struct toshoboe_cb *self = dev_id;  __u8 irqstat;  struct sk_buff *skb = NULL;  irqstat = INB (OBOE_ISR);/* was it us */  if (!(irqstat & OBOE_INT_MASK))      return IRQ_NONE;/* Ack all the interrupts */  OUTB (irqstat, OBOE_ISR);  toshoboe_isntstuck (self);/* Txdone */  if (irqstat & OBOE_INT_TXDONE)    {      int txp, txpc;      int i;      txp = self->txpending;      self->txpending = 0;      for (i = 0; i < TX_SLOTS; ++i)        {          if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS)              self->txpending++;        }      IRDA_DEBUG (1, "%s.txd(%x)%x/%x\n", __FUNCTION__          ,irqstat,txp,self->txpending);      txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK;      /* Got anything queued ? start it together */      if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS)        {          txpc = txp;#ifdef OPTIMIZE_TX          while (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)            {              txp = txpc;              txpc++;              txpc %= TX_SLOTS;              self->stats.tx_packets++;              if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)                  self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX;            }          self->stats.tx_packets--;#else          self->stats.tx_packets++;#endif          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);        }      if ((!self->txpending) && (self->new_speed))        {          self->speed = self->new_speed;          IRDA_DEBUG (1, "%s: Executed TxDone scheduled speed change %d\n",		      __FUNCTION__, self->speed);          toshoboe_setbaud (self);        }      /* Tell network layer that we want more frames */      if (!self->new_speed)          netif_wake_queue(self->netdev);    }  if (irqstat & OBOE_INT_RXDONE)    {      while (!(self->ring->rx[self->rxs].control & OBOE_CTL_RX_HW_OWNS))        {          int len = self->ring->rx[self->rxs].len;          skb = NULL;          IRDA_DEBUG (3, "%s.rcv:%x(%x)\n", __FUNCTION__		      ,len,self->ring->rx[self->rxs].control);#ifdef DUMP_PACKETSdumpbufs(self->rx_bufs[self->rxs],len,'<');#endif          if (self->ring->rx[self->rxs].control == 0)            {              __u8 enable = INB (OBOE_ENABLEH);              /* In SIR mode we need to check the CRC as this */              /* hasn't been done by the hardware */              if (enable & OBOE_ENABLEH_SIRON)                {                  if (!toshoboe_checkfcs (self->rx_bufs[self->rxs], len))                      len = 0;                  /*Trim off the CRC */                  if (len > 1)                      len -= 2;                  else                      len = 0;                  IRDA_DEBUG (1, "%s.SIR:%x(%x)\n", __FUNCTION__, len,enable);                }#ifdef USE_MIR              else if (enable & OBOE_ENABLEH_MIRON)                {                  if (len > 1)                      len -= 2;                  else                      len = 0;                  IRDA_DEBUG (2, "%s.MIR:%x(%x)\n", __FUNCTION__, len,enable);                }#endif              else if (enable & OBOE_ENABLEH_FIRON)                {                  if (len > 3)                      len -= 4;   /*FIXME: check this */                  else                      len = 0;                  IRDA_DEBUG (1, "%s.FIR:%x(%x)\n", __FUNCTION__, len,enable);                }              else                  IRDA_DEBUG (0, "%s.?IR:%x(%x)\n", __FUNCTION__, len,enable);              if (len)                {                  skb = dev_alloc_skb (len + 1);                  if (skb)                    {                      skb_reserve (skb, 1);                      skb_put (skb, len);                      memcpy (skb->data, self->rx_bufs[self->rxs], len);                      self->stats.rx_packets++;                      skb->dev = self->netdev;                      skb->mac.raw = skb->data;                      skb->protocol = htons (ETH_P_IRDA);                    }                  else                    {                      printk (KERN_INFO                              "%s(), memory squeeze, dropping frame.\n",			      __FUNCTION__);                    }                }            }          else            {            /* TODO: =========================================== */            /*  if OBOE_CTL_RX_LENGTH, our buffers are too small */            /* (MIR or FIR) data is lost. */            /* (SIR) data is splitted in several slots. */            /* we have to join all the received buffers received */            /*in a large buffer before checking CRC. */            IRDA_DEBUG (0, "%s.err:%x(%x)\n", __FUNCTION__                ,len,self->ring->rx[self->rxs].control);            }          self->ring->rx[self->rxs].len = 0x0;          self->ring->rx[self->rxs].control = OBOE_CTL_RX_HW_OWNS;          self->rxs++;          self->rxs %= RX_SLOTS;          if (skb)              netif_rx (skb);        }    }  if (irqstat & OBOE_INT_TXUNDER)    {      printk (KERN_WARNING DRIVER_NAME ": tx fifo underflow\n");    }  if (irqstat & OBOE_INT_RXOVER)    {      printk (KERN_WARNING DRIVER_NAME ": rx fifo overflow\n");    }/* This must be useful for something... */  if (irqstat & OBOE_INT_SIP)    {      self->int_sip++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -