cs8900网卡驱动解析(三)

上次说到的cs8900_start函数中,完成了中断申请任务。什么是中断?中断是一种电信号,由硬件设备产生,并直接送入中断控制器的输入引脚上,然后再由中断控制器向处理器发送相应的信号。

 

其中中断处理函数cs8900_interrupt没有讲。中断处理函数是中断发生时系统要执行的函数。本文将主要介绍中断处理函数的功能。我们不分析中断实现机制,而是关心中断发生时,要做哪些事情。要知道,中断处理函数设计的好坏,会直接关心到性能乃至稳定问题。

 

虽然我不会讲中断的实现,但是你必须清楚中断的两种类型:

1.        轮询(polling让内核定期对设备的状态进行查询,然后做出相应的处理;

2.        中断(interrupt让硬件在需要的时候向内核发出信号(变内核主动为硬件主动)。

我们的中断处理函数通过switch/case语句判断中断类型,并进行相应处理。具体过程是:首先读出ISQ寄存器的值,然后根据ISQ的值分别处理各种情况。当中断发生时,这些中断实际反映在相应的寄存器中,ISQ寄存器用低6位记录了当前寄存器的编号,高10位记录了当前寄存器的实际内容。代码如下:








/*网卡的接收数据主要由中断引发设备的中断处理函数*/ 
static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
    struct net_device *dev = dev_id;
    struct net_local *lp;
    int ioaddr, status;

    ioaddr = dev->base_addr;
	//还在lp
    lp = (struct net_local *)dev->priv;

    /* we MUST read all the events out of the ISQ, otherwise we'll never
       get interrupted again.  As a consequence, we can't have any limit
       on the number of times we loop in the interrupt handler.  The
       hardware guarantees that eventually we'll run out of events.  Of
       course, if you're on a slow machine, and packets are arriving
       faster than you can read them off, you're screwed.  Hasta la
       vista, baby!  */
	   //读取中断寄存器中的状态。
    while ((status = readword(dev, ISQ_PORT))) {
      DPRINTK(4, "%s: event=%04x\n", dev->name, status);
      switch(status & ISQ_EVENT_MASK) {
      case ISQ_RECEIVER_EVENT:
	/* Got a packet(s). */
	//读取数据包,所以这个case的作用是用来接收的。
	//这个函数的主要作用是将sk_buffer传递给上层协议。
	net_rx(dev);
	break;
      case ISQ_TRANSMITTER_EVENT:
	lp->stats.tx_packets++;
	//唤醒队列。
	netif_wake_queue(dev);	/* Inform upper layers. */
	if ((status & (	TX_OK |
			TX_LOST_CRS | TX_SQE_ERROR |
			TX_LATE_COL | TX_16_COL)) != TX_OK) {
	  if ((status & TX_OK) == 0) lp->stats.tx_errors++;
	  if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
	  if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
	  if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
	  if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
	}
	break;
      case ISQ_BUFFER_EVENT:
	if (status & READY_FOR_TX) {
	  /* we tried to transmit a packet earlier,
	     but inexplicably ran out of buffers.
	     That shouldn't happen since we only ever
	     load one packet.  Shrug.  Do the right
	     thing anyway. */
	  netif_wake_queue(dev);	/* Inform upper layers. */
	}
	if (status & TX_UNDERRUN) {
	  DPRINTK(1, "%s: transmit underrun\n", dev->name);
	  lp->send_underrun++;
	  if (lp->send_underrun == 3)		lp->send_cmd = TX_AFTER_381;
	  else if (lp->send_underrun == 6)	lp->send_cmd = TX_AFTER_ALL;
	  /* transmit cycle is done, although
	     frame wasn't transmitted - this
	     avoids having to wait for the upper
	     layers to timeout on us, in the
	     event of a tx underrun */
	  netif_wake_queue(dev);	/* Inform upper layers. */
	}
	break;
      case ISQ_RX_MISS_EVENT:
	  //继续打问号???
	lp->stats.rx_missed_errors += (status >>6);
	break;
      case ISQ_TX_COL_EVENT:
	lp->stats.collisions += (status >>6);
	break;
      }
    }
}

在这个终端函数中数据包接收的那一部分是清楚了,但是其他的部分不是特别懂。

同时还要说一下自己的一个巨大的误区:网络接收数据的主要方法就是由中断引发设备的中断处理函数!!!

大神一句话总结:中断处理函数是中断产生时执行的函数,它根据中断种类进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值