网卡芯片为realteak 8201
1. net_device结构体的分配和注册
1) "/drivers/net/ethernet/sun7i/sun7i_wemac.c"
wemac_probe()
ndev = alloc_etherdev(sizeof(struct wemac_board_info)); 分配
ret = register_netdev(ndev); 注册
2) alloc_etherdev定义在 "/include/linux/etherdevice.h"
#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
#define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
3) alloc_etherdev_mqs定义在 "/net/ethernet/eth.c"
struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
unsigned int rxqs)
{
return alloc_netdev_mqs(sizeof_priv, "eth%d", ether_setup, txqs, rxqs);
}
2. 发包函数
"/drivers/net/ethernet/sun7i/sun7i_wemac.c"
/*
* Hardware start transmission.
* Send a packet to media from the upper layer.
*/
static int wemac_start_xmit(struct sk_buff *skb, struct net_device *dev)
1) dev->stats.tx_bytes += skb->len; 发包统计信息
2)将skb数据写入网卡
/* set TX len */
writel(skb->len, db->emac_vbase + EMAC_TX_PL0_REG);
/* start translate from fifo to phy */
writel(readl(db->emac_vbase + EMAC_TX_CTL0_REG)
| 1, db->emac_vbase + EMAC_TX_CTL0_REG);
dev->trans_start = jiffies; /* save the time stamp */
3) 释放skb
dev_kfree_skb(skb); 释放skb
4) netif_stop_queue(dev); 停止队列,数据发送完后由中断处理程序来唤醒队列
3. 中断处理程序
static irqreturn_t wemac_interrupt(int irq, void *dev_id)
1) wemac_tx_done(dev, db, int_status)
当数据发送完后,产生中断,此函数调用,然后调用netif_wake_queue(dev)来唤醒队列
2) wemac_rx(dev)
接收数据包,最终调用netif_rx接收skb
4. MAC地址设置
"/drivers/net/ethernet/sun7i/sun7i_wemac.c"
static int wemac_set_mac_address(struct net_device *dev, void *p)