zynq Ethernet device driver --- Linux kernel 实现欣赏

在这里插入图片描述
在这里插入图片描述

/**
 *     这些code 在 kernel中是怎么添加的、怎么匹配的、probe remove pm 是怎么被调用的,大家都十分熟悉了,
 *     这里就不在赘述了. 详情参考 : 
 *     https://blog.csdn.net/leesagacious/article/details/48306889
 *     https://blog.csdn.net/leesagacious/article/details/50246789
 */
static struct platform_driver macb_driver = {
	.probe		= macb_probe,
	.remove		= macb_remove,
	.driver		= {
		.name		= "macb",
		.of_match_table	= of_match_ptr(macb_dt_ids),
		.pm	= &macb_pm_ops,
	},
};

module_platform_driver(macb_driver);

先来看一张简单的框图, 先欣赏linux kernel 实现,然后欣赏 verilog 实现.
在这里插入图片描述
phy_device 最里层当然是封装了struct device, 因为它要往设备驱动模型中放入这个设备.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

			/*
			 *     #define PHY_MAX_ADDR	32
			 *     这个 32 意思很明确了, MDIO bus仅支持一个Mac作为主设备, 最多32个Phy做从设备.
			 * 
			 *     mii_bus 提供了read() 来读取 PHY Identifier Register的值
			 * 	   具体到 KSZ9031RNX 就是macb_mdio_read ()函数. 它在 macb_mii_init() 函数中被赋值.
			 *     ixgbe网卡则是 ixgbe_x550em_a_mii_bus_read()函数
			 */
			for (i = 0; i < PHY_MAX_ADDR; i++) {				
					phydev = mdiobus_scan(bp->mii_bus, i);
					if (IS_ERR(phydev) &&
					    PTR_ERR(phydev) != -ENODEV) {
						ret = PTR_ERR(phydev);
						break;
					}
				}

在这里插入图片描述

在这里插入图片描述
phy 状态’迁移变化
在这里插入图片描述

NAPI示意
在这里插入图片描述
在调用pool之前,需要一个条件
在这里插入图片描述
结构关系
在这里插入图片描述

/**
 *    该函数在蔽中断环境下运行.
 *    其目的是为了触发 Rx 软中断.
 */
static inline void ____napi_schedule(struct softnet_data *sd,
				     struct napi_struct *napi)
{
    /**
     *    把 napi_struct 挂到 softnet_data 持有的 poll_list 链表上.
     * 
     *    在 net_rx_action() 中遍历该 poll_list,取出entry. 即 struct napi_struct。
     *    执行该entry持有的 poll(). 即执行 macb_poll().
     *	  macb_poll() 是在 netif_napi_add()中被初始化的.	(KSZ9031RN)
     *    macb_init()
     *    {
     *         netif_napi_add();
     *    }
     */
	list_add_tail(&napi->poll_list, &sd->poll_list);	
	
	/**
     *     触发 Rx 软中断.
     *     net_rx_action()会被执行, net_rx_action() 在 net_dev_init()中注册.
     *     net_dev_init()
     *     {
     *          open_softirq(net_rx_action, NET_RX_SOFTIRQ);
     *     }
     */
	__raise_softirq_irqoff(NET_RX_SOFTIRQ);												
}

ok, 上面我们简单的介绍了一下PHY 和 napi,下面详细看它的实现. 以及I350网卡的实现.
对比两款NIC驱动实现的异同.

/**
 *      probe 函数好呀,资源的申请、释放可以胆大点了,
 *Use with resource management to register resources.
 * 		有设备驱动模型在罩着,你放心的去 request 吧. 因为他爸是李刚, 😄
 */
static int macb_probe(struct platform_device *pdev)
{
		/*
		 *     这种操作很恶心, 
		 *     作者就是想匹配不同的mac, 执行不同的init()函数、clk_init()来初始化mac
		 *     作者的思路很简单, 匹配不上, 你就用默认的.
		 */
		const struct macb_config *macb_config = &default_gem_config;
		/*
		 *     mac和clk初始化在这里直接使用默认的macb_init()、macb_clk_init().
		 *     ok吧!  cadence 这company设计的让人汗颜 . 尤其是 5 个 二级指针.
		 *     这code与Intel Corporation 差远了 .......
		 *     下面的变量还有很多, 这儿不一一说明, 用到在说吧.
		 */
		int (*clk_init)(struct platform_device *, struct clk **,
			struct clk **, struct clk **,  struct clk **,
			struct clk **) = macb_config->clk_init;
	    int (*init)(struct platform_device *) = macb_config->init;
	    struct device_node *np = pdev->dev.of_node;

		/*
		 *    ok. 获取 mac 基地址. 常规操作.
		 *    当然, 根节点的子节点被看作总线节点,(of_platform_bus_create(...)) 
		 *    被转换为platform device. (chosen、memory 等除外)
		 *    gem3: ethernet@ff0e0000 {
         *               compatible = "cdns,zynqmp-gem", "cdns,gem";
         *               status = "disabled";
         *               interrupt-parent = <&gic>;
         *               interrupts = <0 63 4>, <0 63 4>;
         *               reg = <0x0 0xff0e0000 0x0 0x1000>;
         *               clock-names = "pclk", "hclk", "tx_clk";
   		 *				.....
         *    };
		 */
		regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		/*
		 *    申请使用该memory + 映射.
		 *    这个操作是非常耗时的, 它底层执行ioremap().会导致建立页表的操作
		 */
		mem = devm_ioremap_resource(&pdev->dev, regs);
		if (IS_ERR(mem))
			return PTR_ERR(mem);
		
		if (np) {
			
		}			
		
}

在这里插入图片描述

/*
 *		和上面的probe有明显的不同,参数是两个,很显然,PCIe来了.
 */
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值