linux網路裝置驅動DM9000驅動分析(4)

2021-07-03 15:47:17 字數 2553 閱讀 8612

14、接受資料

在中斷函式中,我們可以看到呼叫了dm9000_rx

。接收資料並存入

skbuff

,並提交協議上一層。

(1)首先看看下面這個結構體,這個結構體按照

dm9000

的接收格式封裝了

dm9000

接收的資料報資訊 

struct dm9000_rxhdr  __packed;

(2)接收函式dm9000_rx

,這段程式當中有乙個難點,就是在分配

skb的時候有個

+4指的是增加

fcs位這個字段包括

4位元組迴圈冗餘校檢碼

(crc)

用於檢查錯誤。

skb_reserve(skb, 2);  和rdptr = (u8 *) skb_put(skb, rxlen - 4);

skb_reserve可以在緩衝區的頭部預留一定的空間,它通常被用來在緩衝區中給協議頭預留空間或者在某個邊界上對齊。這個函式改變data

和tail

指標,而

data

和tail

指標分別指向負載的開頭和結尾。這個函式通常在分配緩衝區之後就呼叫,此時的

data

和tail

指標還是指向同乙個地方,在分配

skb之後,向資料快取區填充資料之前,會有這樣的一條語句

skb_reserve(skb, 2)

,這是因為乙太網頭長度為

14b,再加上

2b就正好

16位元組邊界對齊,所以大多數乙太網裝置都會在資料報之前保留2b。

skb->data

的前面保留

2位元組,為了對齊用。

| da |sa |type 

=14 bytes   ip packet

是16 byte

對齊的!

rdptr = (u8 *) skb_put(skb, rxlen - 4);  增加的rxlen-4

好像是為了儲存資料剩下的

fcs和

end。

static void

dm9000_rx(struct net_device *dev)

if (!(rxbyte & dm9000_pkt_rdy)) //0x01 沒有準備好,直接返回*/

return;

/* a packet ready now & get status/length */

goodpacket = true;

writeb(dm9000_mrcmd, db->io_addr); /* mrcmd是位址增加的資料讀取命令 讀指標自動增加*/

(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); //一次性讀入四個位元組的內容到rxhdr變數

//這四個位元組是儲存在rx_sram中的每個包的資訊頭

rxlen = le16_to_cpu(rxhdr.rxlen);

if (netif_msg_rx_status(db))

dev_dbg(db->dev, "rx: status %02x, length %04x\n",

rxhdr.rxstatus, rxlen);

/* packet status check */ //檢查包的完整性,需要用到mrcmd暫存器,

if (rxlen < 0x40)

if (rxlen > dm9000_pkt_max)

/* rxhdr.rxstatus is identical to rsr register. */ //也是檢查包

if (rxhdr.rxstatus & (rsr_foe | rsr_ce | rsr_ae | //這裡是rsr暫存器中各位對接收的校驗

rsr_ple | rsr_rwto |

rsr_lcs | rsr_rf))

if (rxhdr.rxstatus & rsr_ce)

if (rxhdr.rxstatus & rsr_rf)

} /* move data from dm9000 */

/*關鍵的**就是這裡。使用到了上面提到的sk_buff。將rx sram中的

data段資料放入sk_buff,然後傳送給上層,至於怎麼傳送,不用去驅動

操心了。sk_buff的protocol全部搞定*/

if (goodpacket &&

((skb = netdev_alloc_skb(dev, rxlen + 4)) != null))

netif_rx(skb); //將skbuff結構體交給上層

dev->stats.rx_packets++; //計數加1

} else

} while (rxbyte & dm9000_pkt_rdy);

}

———————————————end——————————————

linux網路裝置驅動

linux網路裝置驅動 linux網路驅動程式的體系結構可劃分為4個層次。linux核心源 中提供了網路裝置介面及以網路子系統的上層的 移植特定網路硬體的驅動程式的主要工作就是完成裝置驅動功能層的相應 根據底層具體的硬體特性,定義網路裝置介面struct net device型別的結構體變數,並實現...

linux 網路裝置驅動

linux 網路驅動 謹以此文紀念過往的歲月 一.前言 在linux中網路驅動也是乙個大頭,如何去理解網路驅動是作為乙個linux驅動工程師必備的技能。不過同樣的裝置,在不同人的手中會有不同的效果,其原因就在於驅動的好與否。二.裝置註冊 學習網路的驅動與學習普通cdev驅動一樣,都是學習其模板,然後...

Linux網路裝置驅動 一

一 網路裝置驅動基礎 1.乙太網基礎理論 乙太網是區域網的一種,它使用載波監聽多路訪問及衝突檢測技術 csma cd 並以10m s的速率執行在多種型別的電纜上,常用的網絡卡晶元有dm9000 dm9161 cs8900晶元。乙太網的拓撲結構有匯流排型和星型,乙太網的工作模式有半雙工和全雙工。目前雙...