Linux以太网驱动架构
linux以太网架构共包含三个部分
1 linux的网络架构
2 以太网mac数据驱动(收发)
3 以太网phy的驱动
linux的网络驱动架构及流程
申请注册及初始化设备
1 注册模块及平台设备
static struct platform_driver ethps_driver = {
.driver = {
.name = "ethps",
.pm = ðps_pm_ops,
.of_match_table = ethps_of_matches,
},
.probe = ethps_probe,
.remove = ethps_remove,
};
static int __init ETHplpsirq_init(void)
{
return platform_driver_register(ðps_driver);
}
static void __exit ETHplpsirq_exit(void)
{
platform_driver_unregister(ðps_driver);
}
module_init(ETHplpsirq_init);
module_exit(ETHplpsirq_exit);
2 在probe里 申请网络结构体net_device、对相关变量函数赋值,注册网络结构体net_device
ndev = alloc_etherdev(sizeof(struct board_info));
if (!ndev)
return -ENOMEM;
SET_NETDEV_DEV(ndev, &pdev->dev);
/* setup board info structure */
db = netdev_priv(ndev);
db->dev = &pdev->dev;
db->ndev = ndev;
mac = of_get_mac_address(np);//设置mac地址
ether_addr_copy(db->ndev->dev_addr, mac);
strcpy(ndev->name,"ethyzd");
ndev->netdev_ops = ðps_netdev_ops;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
ndev->ethtool_ops = ðps_ethtool_ops;
platform_set_drvdata(pdev, ndev);
ret = register_netdev(ndev);
接收(NAPI方式)
napi是在数据来到时,先关闭中断,循环读取缓存区中的数据
需要做的是:
1 编写poll函数
2 在probe函数中初始化poll函数
netif_napi_add(dev, &bp->napi, xx_poll, 64);
64为最大循环次数,这个值会传递给xx_poll函数
3 在中断中关闭接收中断并启用napi调度
if (napi_schedule_prep(&bp->napi)) {
__napi_schedule(&bp->napi);
}
发送
上层协议会将数据保存在sk_buff中通过 eth_start_xmit(struct sk_buff *skb, struct net_device *dev)函数传下来,eth_start_xmit这个函数包含在之前的注册函数中 ndev->netdev_ops = ðps_netdev_ops;
在这个函数中,我们要做的
1 将sk_buff中传过来的有效数据放入缓冲区
2 将缓冲区的数据通过mac发送出去
以太网mac数据驱动(收发)
接收
很多芯片都包含mac,以太网mac的收发控制依赖于以太网描述符,以XC7Z020为例
描述符一共由两个32位寄存器组成,包含一个地址和很多的状态控制器。描述符可以有很多个,将描述符的首地址和数量写入寄存器,以太网数据就会通过dma自动将数存入描述符所指向的地址中,一个描述符的地址写满之后处理器会自动继续将数据写入下一个描述中指向的地址。
发送
发送的数据地址已经保存在sk_buff ,根据其数量,将其分成一块块的数据,每块大小为描述符所指向的缓存大小,再将描述符相应的状态位做上标记(置1或置0)。就可以将数据发送出去了。
以太网phy的驱动
phy驱动只要包括phy的初始化,以及网络状态的读取