cs8900網絡卡驅動解析(三)
阿新 • • 發佈:2019-01-30
上次說到的cs8900_start函式中,完成了中斷申請任務。什麼是中斷?中斷是一種電訊號,由硬體裝置產生,並直接送入中斷控制器的輸入引腳上,然後再由中斷控制器向處理器傳送相應的訊號。
其中中斷處理函式cs8900_interrupt沒有講。中斷處理函式是中斷髮生時系統要執行的函式。本文將主要介紹中斷處理函式的功能。我們不分析中斷實現機制,而是關心中斷髮生時,要做哪些事情。要知道,中斷處理函式設計的好壞,會直接關心到效能乃至穩定問題。
雖然我不會講中斷的實現,但是你必須清楚中斷的兩種型別:
1. 輪詢(polling)讓核心定期對裝置的狀態進行查詢,然後做出相應的處理;
2.
我們的中斷處理函式通過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; } } }
在這個終端函式中資料包接收的那一部分是清楚了,但是其他的部分不是特別懂。
同時還要說一下自己的一個巨大的誤區:網路接收資料的主要方法就是由中斷引發裝置的中斷處理函式!!!
大神一句話總結:中斷處理函式是中斷產生時執行的函式,它根據中斷種類進行處理。