1. 程式人生 > >cs8900網絡卡驅動解析(三)

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;
      }
    }
}

在這個終端函式中資料包接收的那一部分是清楚了,但是其他的部分不是特別懂。

同時還要說一下自己的一個巨大的誤區:網路接收資料的主要方法就是由中斷引發裝置的中斷處理函式!!!

大神一句話總結:中斷處理函式是中斷產生時執行的函式,它根據中斷種類進行處理。