Linux网络驱动fec_probe函数解析

涉及到的主要结构体,整体框架

这些结构体就是linux内核提供的接口,实现这些结构体的成员变量的过程就是驱动开发

struct device_node      //路径 include/linux/of.h

struct platform_driver //路径 include/linux/platform_device.h

struct net_device      //路径 include/linux/netdevice.h

struct mii_bus         //路径  include/linux/phy.h

struct phy_device      //路径  include/linux/phy.h

驱动开发的整体框架简单的来说如下四个表格

table 1
**实现 fec_device 和注册 fec_device 由设备树完成

实现 struct platform_device fec_device 向内核platform总线注册 fec_device
实现 struct platform_device fec_device 向内核platform总线注册 fec_device

table 2.

申请 net_device 初始化 net_devie 向内核注册 net_device

table 3.

申请 mii_bus 初始化 mii_bus 向内核注册 mii_bus

table 4.

申请 phy_device 初始化 phy_device 向内核注册 phy_device
table3、table4 的过程嵌套在 table2 的过程中

fec_probe函数主要执行步奏

当内核启动的时候会执行module_platform_driver(fec_driver);
platform 总线注册 mac 驱动,当设备树的compatible和驱动的compatible匹配成功之后,会调用fec_probe函数,此为mac驱动的真正入口。
主要代码解析如下

static int fec_probe(struct platform_device *pdev)    
{
	//1、获取设备树节点的句柄, 2、创建一个phy的设备树节点句柄
	struct device_node *np = pdev->dev.of_node, *phy_node;
	
	//从设备树中获取 fsl,num-tx-queues fsl,num-rx-queues 属性值			
	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);

	//申请 net_device
	nde = alloc_etherdev_mqs(sizeof(struct fec_enet_private) + FEC_STATS_SIZE, num_tx_qs, num_rx_qs);

	//获取私有数据空间首地址
	netdev_priv(ndev);

	//从mac的设备树节点中获取phy子节点
	of_parse_phandle(np, "phy-handle", 0);	

	//从设备树节点中获取phy模式,phy-mode = "rgmii-id";
	of_get_phy_mode(pdev->dev.of_node);

	//复位phy
	fec_reset_phy(pdev);

	//申请队列和DMA,设置MAC地址
	fec_enet_init(struct net_device *ndev)

	//唤醒中断
	of_property_read_u32(np, "fsl,wakeup_irq", &irq);

	//注册MDIO总线、注册phy_device,详解见下文
	fec_enet_mii_init(pdev);
		->mdiobus_alloc();
		->of_get_child_by_name(pdev->dev.of_node, "mdio");
		->of_mdiobus_register(fep->mii_bus, node);

	//向内核注册net_device
	register_netdev(ndev);
}
//注册MDIO总线、注册phy_device,主要代码解析如下
static int fec_enet_mii_init(struct platform_device *pdev)
{
	//申请MDIO总线
	fep->mii_bus = mdiobus_alloc();

	//获取phy节点句柄
	node = of_get_child_by_name(pdev->dev.of_node, "mdio");

	//向内核注册MDIO总线,获取phy芯片id,向内核注册phy_device
	of_mdiobus_register(fep->mii_bus, node);
		->mdiobus_register(mdio);
		-> get_phy_device(mdio, addr, xxx);
		-> phy_device_register(phy);
}
上一篇:Springcloud开发之OpenFeign调用和认证


下一篇:WiFi probe request/response