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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章