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

📄 nicstar.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      {         printk("nicstar%d: can't allocate %dth of %d small buffers.\n",                i, j, NUM_SB);         error = 15;         ns_init_card_error(card, error);	 return error;      }      skb_queue_tail(&card->sbpool.queue, sb);      skb_reserve(sb, NS_AAL0_HEADER);      push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);   }   /* Test for strange behaviour which leads to crashes */   if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min)   {      printk("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n",             i, j, bcount);      error = 15;      ns_init_card_error(card, error);      return error;   }         /* Allocate iovec buffers */   skb_queue_head_init(&card->iovpool.queue);   card->iovpool.count = 0;   for (j = 0; j < NUM_IOVB; j++)   {      struct sk_buff *iovb;      iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);      if (iovb == NULL)      {         printk("nicstar%d: can't allocate %dth of %d iovec buffers.\n",                i, j, NUM_IOVB);         error = 16;         ns_init_card_error(card, error);	 return error;      }      skb_queue_tail(&card->iovpool.queue, iovb);      card->iovpool.count++;   }   card->intcnt = 0;   /* Configure NICStAR */   if (card->rct_size == 4096)      ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES;   else /* (card->rct_size == 16384) */      ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES;   card->efbie = 1;   /* Register device */   card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);   if (card->atmdev == NULL)   {      printk("nicstar%d: can't register device.\n", i);      error = 17;      ns_init_card_error(card, error);      return error;   }         if (ns_parse_mac(mac[i], card->atmdev->esi))      nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,                         card->atmdev->esi, 6);   printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i,          card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2],          card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]);   card->atmdev->dev_data = card;   card->atmdev->ci_range.vpi_bits = card->vpibits;   card->atmdev->ci_range.vci_bits = card->vcibits;   card->atmdev->link_rate = card->max_pcr;   card->atmdev->phy = NULL;#ifdef CONFIG_ATM_NICSTAR_USE_SUNI   if (card->max_pcr == ATM_OC3_PCR) {      suni_init(card->atmdev);      MOD_INC_USE_COUNT;      /* Can't remove the nicstar driver or the suni driver would oops */   }#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105   if (card->max_pcr == ATM_25_PCR) {      idt77105_init(card->atmdev);      /* Note that for the IDT77105 PHY we don't need the awful       * module count hack that the SUNI needs because we can       * stop the '105 when the nicstar module is cleaned up.       */   }#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */   if (card->atmdev->phy && card->atmdev->phy->start)      card->atmdev->phy->start(card->atmdev);   writel(NS_CFG_RXPATH |          NS_CFG_SMBUFSIZE |          NS_CFG_LGBUFSIZE |          NS_CFG_EFBIE |          NS_CFG_RSQSIZE |          NS_CFG_VPIBITS |          ns_cfg_rctsize |          NS_CFG_RXINT_NODELAY |          NS_CFG_RAWIE |		/* Only enabled if RCQ_SUPPORT */          NS_CFG_RSQAFIE |          NS_CFG_TXEN |          NS_CFG_TXIE |          NS_CFG_TSQFIE_OPT |		/* Only enabled if ENABLE_TSQFIE */           NS_CFG_PHYIE,          card->membase + CFG);   num_cards++;   return error;}static void ns_init_card_error(ns_dev *card, int error){   if (error >= 17)   {      writel(0x00000000, card->membase + CFG);   }   if (error >= 16)   {      struct sk_buff *iovb;      while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL)         dev_kfree_skb_any(iovb);   }   if (error >= 15)   {      struct sk_buff *sb;      while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL)         dev_kfree_skb_any(sb);      free_scq(card->scq0, NULL);   }   if (error >= 14)   {      struct sk_buff *lb;      while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL)         dev_kfree_skb_any(lb);   }   if (error >= 13)   {      struct sk_buff *hb;      while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL)         dev_kfree_skb_any(hb);   }   if (error >= 12)   {      kfree(card->rsq.org);   }   if (error >= 11)   {      kfree(card->tsq.org);   }   if (error >= 10)   {      free_irq(card->pcidev->irq, card);   }   if (error >= 4)   {      iounmap((void *) card->membase);   }   if (error >= 3)   {      kfree(card);   }}static scq_info *get_scq(int size, u32 scd){   scq_info *scq;   int i;   if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)      return (scq_info *) NULL;   scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);   if (scq == (scq_info *) NULL)      return (scq_info *) NULL;   scq->org = kmalloc(2 * size, GFP_KERNEL);   if (scq->org == NULL)   {      kfree(scq);      return (scq_info *) NULL;   }   scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *                                          (size / NS_SCQE_SIZE), GFP_KERNEL);   if (scq->skb == (struct sk_buff **) NULL)   {      kfree(scq->org);      kfree(scq);      return (scq_info *) NULL;   }   scq->num_entries = size / NS_SCQE_SIZE;   scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size);   scq->next = scq->base;   scq->last = scq->base + (scq->num_entries - 1);   scq->tail = scq->last;   scq->scd = scd;   scq->num_entries = size / NS_SCQE_SIZE;   scq->tbd_count = 0;   init_waitqueue_head(&scq->scqfull_waitq);   scq->full = 0;   spin_lock_init(&scq->lock);   for (i = 0; i < scq->num_entries; i++)      scq->skb[i] = NULL;   return scq;}/* For variable rate SCQ vcc must be NULL */static void free_scq(scq_info *scq, struct atm_vcc *vcc){   int i;   if (scq->num_entries == VBR_SCQ_NUM_ENTRIES)      for (i = 0; i < scq->num_entries; i++)      {         if (scq->skb[i] != NULL)	 {            vcc = ATM_SKB(scq->skb[i])->vcc;            if (vcc->pop != NULL)	       vcc->pop(vcc, scq->skb[i]);	    else               dev_kfree_skb_any(scq->skb[i]);         }      }   else /* vcc must be != NULL */   {      if (vcc == NULL)      {         printk("nicstar: free_scq() called with vcc == NULL for fixed rate scq.");         for (i = 0; i < scq->num_entries; i++)            dev_kfree_skb_any(scq->skb[i]);      }      else         for (i = 0; i < scq->num_entries; i++)         {            if (scq->skb[i] != NULL)            {               if (vcc->pop != NULL)                  vcc->pop(vcc, scq->skb[i]);               else                  dev_kfree_skb_any(scq->skb[i]);            }         }   }   kfree(scq->skb);   kfree(scq->org);   kfree(scq);}/* The handles passed must be pointers to the sk_buff containing the small   or large buffer(s) cast to u32. */static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,                       u32 handle2, u32 addr2){   u32 stat;   unsigned long flags;   #ifdef GENERAL_DEBUG   if (!addr1)      printk("nicstar%d: push_rxbufs called with addr1 = 0.\n", card->index);#endif /* GENERAL_DEBUG */   stat = readl(card->membase + STAT);   card->sbfqc = ns_stat_sfbqc_get(stat);   card->lbfqc = ns_stat_lfbqc_get(stat);   if (type == BUF_SM)   {      if (!addr2)      {         if (card->sm_addr)	 {	    addr2 = card->sm_addr;	    handle2 = card->sm_handle;	    card->sm_addr = 0x00000000;	    card->sm_handle = 0x00000000;	 }	 else /* (!sm_addr) */	 {	    card->sm_addr = addr1;	    card->sm_handle = handle1;	 }      }         }   else /* type == BUF_LG */   {      if (!addr2)      {         if (card->lg_addr)	 {	    addr2 = card->lg_addr;	    handle2 = card->lg_handle;	    card->lg_addr = 0x00000000;	    card->lg_handle = 0x00000000;	 }	 else /* (!lg_addr) */	 {	    card->lg_addr = addr1;	    card->lg_handle = handle1;	 }      }         }   if (addr2)   {      if (type == BUF_SM)      {         if (card->sbfqc >= card->sbnr.max)         {            skb_unlink((struct sk_buff *) handle1);            dev_kfree_skb_any((struct sk_buff *) handle1);            skb_unlink((struct sk_buff *) handle2);            dev_kfree_skb_any((struct sk_buff *) handle2);            return;         }	 else            card->sbfqc += 2;      }      else /* (type == BUF_LG) */      {         if (card->lbfqc >= card->lbnr.max)         {            skb_unlink((struct sk_buff *) handle1);            dev_kfree_skb_any((struct sk_buff *) handle1);            skb_unlink((struct sk_buff *) handle2);            dev_kfree_skb_any((struct sk_buff *) handle2);            return;         }         else            card->lbfqc += 2;      }      ns_grab_res_lock(card, flags);      while (CMD_BUSY(card));      writel(addr2, card->membase + DR3);      writel(handle2, card->membase + DR2);      writel(addr1, card->membase + DR1);      writel(handle1, card->membase + DR0);      writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD);       spin_unlock_irqrestore(&card->res_lock, flags);      XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index,              (type == BUF_SM ? "small" : "large"), addr1, addr2);   }   if (!card->efbie && card->sbfqc >= card->sbnr.min &&       card->lbfqc >= card->lbnr.min)   {      card->efbie = 1;      writel((readl(card->membase + CFG) | NS_CFG_EFBIE), card->membase + CFG);   }   return;}static void ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs){   u32 stat_r;   ns_dev *card;   struct atm_dev *dev;   unsigned long flags;   card = (ns_dev *) dev_id;   dev = card->atmdev;   card->intcnt++;   PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);   ns_grab_int_lock(card, flags);      stat_r = readl(card->membase + STAT);   /* Transmit Status Indicator has been written to T. S. Queue */   if (stat_r & NS_STAT_TSIF)   {      TXPRINTK("nicstar%d: TSI interrupt\n", card->index);      process_tsq(card);      writel(NS_STAT_TSIF, card->membase + STAT);   }      /* Incomplete CS-PDU has been transmitted */   if (stat_r & NS_STAT_TXICP)   {      writel(NS_STAT_TXICP, card->membase + STAT);      TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n",               card->index);   }      /* Transmit Status Queue 7/8 full */   if (stat_r & NS_STAT_TSQF)   {      writel(NS_STAT_TSQF, card->membase + STAT);      PRINTK("nicstar%d: TSQ full.\n", card->index);      process_tsq(card);   }      /* Timer overflow */   if (stat_r & NS_STAT_TMROF)   {      writel(NS_STAT_TMROF, card->membase + STAT);      PRINTK("nicstar%d: Timer overflow.\n", card->index);   }      /* PHY device interrupt signal active */   if (stat_r & NS_STAT_PHYI)   {      writel(NS_STAT_PHYI, card->membase + STAT);      PRINTK("nicstar%d: PHY interrupt.\n", card->index);      if (dev->phy && dev->phy->interrupt) {         dev->phy->interrupt(dev);      }   }   /* Small Buffer Queue is full */   if (stat_r & NS_STAT_SFBQF)   {      writel(NS_STAT_SFBQF, card->membase + STAT);      printk("nicstar%d: Small free buffer queue is full.\n", card->index);   }      /* Large Buffer Queue is full */   if (stat_r & NS_STAT_LFBQF)   {      writel(NS_STAT_LFBQF, card->membase + STAT);      printk("nicstar%d: Large free buffer queue is full.\n", card->index);   }

⌨️ 快捷键说明

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