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

📄 nicstar.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   /* Receive Status Queue is full */   if (stat_r & NS_STAT_RSQF)   {      writel(NS_STAT_RSQF, card->membase + STAT);      printk("nicstar%d: RSQ full.\n", card->index);      process_rsq(card);   }   /* Complete CS-PDU received */   if (stat_r & NS_STAT_EOPDU)   {      RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index);      process_rsq(card);      writel(NS_STAT_EOPDU, card->membase + STAT);   }   /* Raw cell received */   if (stat_r & NS_STAT_RAWCF)   {      writel(NS_STAT_RAWCF, card->membase + STAT);#ifndef RCQ_SUPPORT      printk("nicstar%d: Raw cell received and no support yet...\n",             card->index);#endif /* RCQ_SUPPORT */      /* NOTE: the following procedure may keep a raw cell pending untill the               next interrupt. As this preliminary support is only meant to               avoid buffer leakage, this is not an issue. */      while (readl(card->membase + RAWCT) != card->rawch)      {         ns_rcqe *rawcell;         rawcell = (ns_rcqe *) bus_to_virt(card->rawch);         if (ns_rcqe_islast(rawcell))         {            struct sk_buff *oldbuf;            oldbuf = card->rcbuf;            card->rcbuf = (struct sk_buff *) ns_rcqe_nextbufhandle(rawcell);            card->rawch = (u32) virt_to_bus(card->rcbuf->data);            recycle_rx_buf(card, oldbuf);         }         else            card->rawch += NS_RCQE_SIZE;      }   }   /* Small buffer queue is empty */   if (stat_r & NS_STAT_SFBQE)   {      int i;      struct sk_buff *sb;      writel(NS_STAT_SFBQE, card->membase + STAT);      printk("nicstar%d: Small free buffer queue empty.\n",             card->index);      for (i = 0; i < card->sbnr.min; i++)      {         sb = alloc_skb(NS_SMSKBSIZE, GFP_ATOMIC);         if (sb == NULL)         {            writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG);            card->efbie = 0;            break;         }         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);      }      card->sbfqc = i;      process_rsq(card);   }   /* Large buffer queue empty */   if (stat_r & NS_STAT_LFBQE)   {      int i;      struct sk_buff *lb;      writel(NS_STAT_LFBQE, card->membase + STAT);      printk("nicstar%d: Large free buffer queue empty.\n",             card->index);      for (i = 0; i < card->lbnr.min; i++)      {         lb = alloc_skb(NS_LGSKBSIZE, GFP_ATOMIC);         if (lb == NULL)         {            writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG);            card->efbie = 0;            break;         }         skb_queue_tail(&card->lbpool.queue, lb);         skb_reserve(lb, NS_SMBUFSIZE);         push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);      }      card->lbfqc = i;      process_rsq(card);   }   /* Receive Status Queue is 7/8 full */   if (stat_r & NS_STAT_RSQAF)   {      writel(NS_STAT_RSQAF, card->membase + STAT);      RXPRINTK("nicstar%d: RSQ almost full.\n", card->index);      process_rsq(card);   }      spin_unlock_irqrestore(&card->int_lock, flags);   PRINTK("nicstar%d: end of interrupt service\n", card->index);}static int ns_open(struct atm_vcc *vcc, short vpi, int vci){   ns_dev *card;   vc_map *vc;   int error;   unsigned long tmpl, modl;   int tcr, tcra;	/* target cell rate, and absolute value */   int n = 0;		/* Number of entries in the TST. Initialized to remove                           the compiler warning. */   u32 u32d[4];   int frscdi = 0;	/* Index of the SCD. Initialized to remove the compiler                           warning. How I wish compilers were clever enough to			   tell which variables can truly be used			   uninitialized... */   int inuse;		/* tx or rx vc already in use by another vcc */   card = (ns_dev *) vcc->dev->dev_data;   PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int) vpi, vci);   if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0)   {      PRINTK("nicstar%d: unsupported AAL.\n", card->index);      return -EINVAL;   }   if ((error = atm_find_ci(vcc, &vpi, &vci)))   {      PRINTK("nicstar%d: error in atm_find_ci().\n", card->index);      return error;   }   vc = &(card->vcmap[vpi << card->vcibits | vci]);   vcc->vpi = vpi;   vcc->vci = vci;   vcc->dev_data = vc;   inuse = 0;   if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx)      inuse = 1;   if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx)      inuse += 2;   if (inuse)   {      printk("nicstar%d: %s vci already in use.\n", card->index,             inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");      return -EINVAL;   }   set_bit(ATM_VF_ADDR,&vcc->flags);   /* NOTE: You are not allowed to modify an open connection's QOS. To change      that, remove the ATM_VF_PARTIAL flag checking. There may be other changes      needed to do that. */   if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))   {      scq_info *scq;            set_bit(ATM_VF_PARTIAL,&vcc->flags);      if (vcc->qos.txtp.traffic_class == ATM_CBR)      {         /* Check requested cell rate and availability of SCD */         if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0 &&             vcc->qos.txtp.min_pcr == 0)         {            PRINTK("nicstar%d: trying to open a CBR vc with cell rate = 0 \n",	           card->index);	    clear_bit(ATM_VF_PARTIAL,&vcc->flags);	    clear_bit(ATM_VF_ADDR,&vcc->flags);            return -EINVAL;         }         tcr = atm_pcr_goal(&(vcc->qos.txtp));         tcra = tcr >= 0 ? tcr : -tcr;               PRINTK("nicstar%d: target cell rate = %d.\n", card->index,                vcc->qos.txtp.max_pcr);         tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES;         modl = tmpl % card->max_pcr;         n = (int)(tmpl / card->max_pcr);         if (tcr > 0)         {            if (modl > 0) n++;         }         else if (tcr == 0)         {            if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0)	    {               PRINTK("nicstar%d: no CBR bandwidth free.\n", card->index);	       clear_bit(ATM_VF_PARTIAL,&vcc->flags);	       clear_bit(ATM_VF_ADDR,&vcc->flags);               return -EINVAL;            }         }         if (n == 0)         {            printk("nicstar%d: selected bandwidth < granularity.\n", card->index);	    clear_bit(ATM_VF_PARTIAL,&vcc->flags);	    clear_bit(ATM_VF_ADDR,&vcc->flags);            return -EINVAL;         }         if (n > (card->tst_free_entries - NS_TST_RESERVED))         {            PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index);	    clear_bit(ATM_VF_PARTIAL,&vcc->flags);	    clear_bit(ATM_VF_ADDR,&vcc->flags);            return -EINVAL;         }         else            card->tst_free_entries -= n;         XPRINTK("nicstar%d: writing %d tst entries.\n", card->index, n);         for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++)         {            if (card->scd2vc[frscdi] == NULL)            {               card->scd2vc[frscdi] = vc;               break;	    }         }         if (frscdi == NS_FRSCD_NUM)         {            PRINTK("nicstar%d: no SCD available for CBR channel.\n", card->index);            card->tst_free_entries += n;	    clear_bit(ATM_VF_PARTIAL,&vcc->flags);	    clear_bit(ATM_VF_ADDR,&vcc->flags);	    return -EBUSY;         }         vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;         scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);         if (scq == (scq_info *) NULL)         {            PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);            card->scd2vc[frscdi] = NULL;            card->tst_free_entries += n;	    clear_bit(ATM_VF_PARTIAL,&vcc->flags);	    clear_bit(ATM_VF_ADDR,&vcc->flags);            return -ENOMEM;         }	 vc->scq = scq;         u32d[0] = (u32) virt_to_bus(scq->base);         u32d[1] = (u32) 0x00000000;         u32d[2] = (u32) 0xffffffff;         u32d[3] = (u32) 0x00000000;         ns_write_sram(card, vc->cbr_scd, u32d, 4);         	 fill_tst(card, n, vc);      }      else /* not CBR */      {         vc->cbr_scd = 0x00000000;	 vc->scq = card->scq0;      }            if (vcc->qos.txtp.traffic_class != ATM_NONE)      {         vc->tx = 1;	 vc->tx_vcc = vcc;	 vc->tbd_count = 0;      }      if (vcc->qos.rxtp.traffic_class != ATM_NONE)      {         u32 status;               vc->rx = 1;         vc->rx_vcc = vcc;         vc->rx_iov = NULL;	 /* Open the connection in hardware */	 if (vcc->qos.aal == ATM_AAL5)	    status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN;	 else /* vcc->qos.aal == ATM_AAL0 */	    status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN;#ifdef RCQ_SUPPORT         status |= NS_RCTE_RAWCELLINTEN;#endif /* RCQ_SUPPORT */         ns_write_sram(card, NS_RCT + (vpi << card->vcibits | vci) *	               NS_RCT_ENTRY_SIZE, &status, 1);      }         }      set_bit(ATM_VF_READY,&vcc->flags);   return 0;}static void ns_close(struct atm_vcc *vcc){   vc_map *vc;   ns_dev *card;   u32 data;   int i;      vc = vcc->dev_data;   card = vcc->dev->dev_data;   PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index,          (int) vcc->vpi, vcc->vci);   clear_bit(ATM_VF_READY,&vcc->flags);      if (vcc->qos.rxtp.traffic_class != ATM_NONE)   {      u32 addr;      unsigned long flags;            addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE;      ns_grab_res_lock(card, flags);      while(CMD_BUSY(card));      writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD);      spin_unlock_irqrestore(&card->res_lock, flags);            vc->rx = 0;      if (vc->rx_iov != NULL)      {	 struct sk_buff *iovb;	 u32 stat;            stat = readl(card->membase + STAT);         card->sbfqc = ns_stat_sfbqc_get(stat);            card->lbfqc = ns_stat_lfbqc_get(stat);         PRINTK("nicstar%d: closing a VC with pending rx buffers.\n",	        card->index);         iovb = vc->rx_iov;         recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,	                       ATM_SKB(iovb)->iovcnt);         ATM_SKB(iovb)->iovcnt = 0;         ATM_SKB(iovb)->vcc = NULL;         ns_grab_int_lock(card, flags);         recycle_iov_buf(card, iovb);         spin_unlock_irqrestore(&card->int_lock, flags);         vc->rx_iov = NULL;      }   }   if (vcc->qos.txtp.traffic_class != ATM_NONE)   {      vc->tx = 0;   }   if (vcc->qos.txtp.traffic_class == ATM_CBR)   {      unsigned long flags;      ns_scqe *scqep;      scq_info *scq;      scq = vc->scq;      for (;;)      {         ns_grab_scq_lock(card, scq, flags);         scqep = scq->next;         if (scqep == scq->base)            scqep = scq->last;         else            scqep--;         if (scqep == scq->tail)         {            spin_unlock_irqrestore(&scq->lock, flags);            break;         }         /* If the last entry is not a TSR, place one in the SCQ in order to            be able to completely drain it and then close. */         if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next)         {            ns_scqe tsr;            u32 scdi, scqi;            u32 data;            int index;            tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE);            scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE;            scqi = scq->next - scq->base;            tsr.word_2 = ns_tsr_mkword_2(scdi, scqi);            tsr.word_3 = 0x00000000;            tsr.word_4 = 0x00000000;            *scq->next = tsr;            index = (int) scqi;            scq->skb[index] = NULL;            if (scq->next == scq->last)               scq->next = scq->base;            else               scq->next++;            data = (u32) virt_to_bus(scq->next);            ns_write_sram(card, scq->scd, &data, 1);         }         spin_unlock_irqrestore(&scq->lock, flags);         schedule();      }      /* Free all TST entries */      data = NS_TST_OPCODE_VARIABLE;      for (i = 0; i < NS_TST_NUM_ENTRIES; i++)      {         if (card->tste2vc[i] == vc)	 {            ns_write_sram(card, card->tst_addr + i, &data, 1);            card->tste2vc[i] = NULL;            card->tst_free_entries++;	 }      }            card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL;      free_scq(vc->scq, vcc);   }   vcc->dev_data = NULL;   clear_bit(ATM_VF_PARTIAL,&vcc->flags);   clear_bit(ATM_VF_ADDR,&vcc->flags);#ifdef RX_DEBUG   {      u32 stat, cfg;      stat = readl(card->membase + STAT);      cfg = readl(card->membase + CFG);      printk("STAT = 0x%08X  CFG = 0x%08X  \n", stat, cfg);      printk("TSQ: base = 0x%08X  next = 0x%08X  last = 0x%08X  TSQT = 0x%08X \n",             (u32) card->tsq.base, (u32) card->tsq.next,(u32) card->tsq.last,	     readl(card->membase + TSQT));      printk("RSQ: base = 0x%08X  next = 0x%08X  last = 0x%08X  RSQT = 0x%08X \n",             (u32) card->rsq.base, (u32) card->rsq.next,(u32) card->rsq.last,	     readl(card->membase + RSQT));      printk("Empty free buffer queue interrupt %s \n",             card->efbie ? "enabled" : "disabled");      printk("SBCNT = %d  count = %d   LBCNT = %d count = %d \n",             ns_stat_sfbqc_get(stat), card->sbpool.count,	     ns_stat_lfbqc_get(stat), card->lbpool.count);      printk("hbpool.count = %d  iovpool.count = %d \n",             card->hbpool.count, card->iovpool.count);

⌨️ 快捷键说明

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