LAN9221網卡驅動分析之一 發送數據

轉載請註明出處:http://blog.csdn.net/qq405180763/article/details/8794887

在LAN9221網卡驅動中,以字對齊往網卡緩存發數據,所以發送數據之前要考慮字對齊,並將發送字的次數計算出來。當網卡中TX_FIFO空間餘量小於1600個字節時,通知上層停止發送隊列,餘量大於3200的時候網卡觸發中斷繼續發送數據。

static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
unsigned int freespace;
unsigned int tx_cmd_a;
unsigned int tx_cmd_b;
unsigned int temp;
u32 wrsz;
ulong bufp;

freespace = smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TDFREE_;//讀TX_FIFO_INF寄存器獲取低十六位,

//得到TX_FIFO中剩餘空間的大小

if (unlikely(freespace < TX_FIFO_LOW_THRESHOLD))
SMSC_WARNING(TX_ERR,
"Tx data fifo low, space available: %d", freespace);

/* Word alignment adjustment */
tx_cmd_a = (u32)((ulong)skb->data & 0x03) << 16; //skb->data低兩位給Data Start Offset,在網卡緩存中空幾個字節使數據字對齊
tx_cmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
tx_cmd_a |= (unsigned int)skb->len;

tx_cmd_b = ((unsigned int)skb->len) << 16;  //雖然skb->len是32位的數據,但skb->len的最大值爲1536,小於11位
tx_cmd_b |= (unsigned int)skb->len;  //所以這裏的兩次複製,只是把套接字的長度給了Command_B的Packte Tag和Packte Length,
用包的長度作爲包的唯一標示
smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_a);
smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_b); //寫入command A和command B

bufp = (ulong)skb->data & (~0x3);  //數據發送指針前移相應位,使包字對齊,並且強制轉換成ulong型,減一就跳過四個字節
wrsz = (u32)skb->len + 3; //??
wrsz += (u32)((ulong)skb->data & 0x3);
wrsz >>= 2;  //以字爲單位將數據發給網卡,計算髮送的次數

smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz); //按字發送數據給網卡
freespace -= (skb->len + 32);
dev_kfree_skb(skb);
dev->trans_start = jiffies;

if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
smsc911x_tx_update_txcounters(dev);

if (freespace < TX_FIFO_LOW_THRESHOLD) {  //剩餘空間小於1600B時,通知上層暫停發送數據
netif_stop_queue(dev);
temp = smsc911x_reg_read(pdata, FIFO_INT);
temp &= 0x00FFFFFF;
temp |= 0x32000000;  //設置當TX_FIFO剩餘空間大於3200B的時候觸發中斷
smsc911x_reg_write(pdata, FIFO_INT, temp);
}

return NETDEV_TX_OK;
}

發佈了26 篇原創文章 · 獲贊 21 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章