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

本文深入探讨了MACB平台驱动的实现细节,包括资源申请、PHY设备扫描、NAPI机制的应用及I350网卡驱动的具体实现。通过对两种驱动的对比分析,帮助读者理解Linux内核中网络接口控制器驱动的设计理念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

/**
 *     这些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)
{
	
}
数据集介绍:神经元细胞核检测数据集 一、基础信息 数据集名称:神经元细胞核检测数据集 图片数量: - 训练集:16,353张 - 测试集:963张 分类类别: - Neuron(神经元细胞核):中枢神经系统的基本功能单位,检测其形态特征对神经科学研究具有重要意义。 标注格式: - YOLO格式,包含边界框坐标及类别标签,适用于目标检测任务 - 数据来源于显微镜成像,覆盖多种细胞分布形态和成像条件 二、适用场景 神经科学研究: 支持构建神经元定位分析工具,助力脑科学研究和神经系统疾病机理探索 医学影像分析: 适用于开发自动化细胞核检测系统,辅助病理诊断和细胞计数任务 AI辅助诊断工具开发: 可用于训练检测神经元退行性病变的模型,支持阿尔茨海默症等神经疾病的早期筛查 生物教育及研究: 提供标准化的神经元检测数据,适用于高校生物学实验室和科研机构的教学实验 三、数据集优势 大规模训练样本: 包含超1.6万张训练图像,充分覆盖细胞核的多样分布状态,支持模型深度学习 精准定位标注: 所有标注框均严格贴合细胞核边缘,确保目标检测模型的训练精度 任务适配性强: 原生YOLO格式可直接应用于主流检测框架(YOLOv5/v7/v8等),支持快速模型迭代 生物学特性突出: 专注神经元细胞核的形态特征,包含密集分布、重叠细胞等真实生物场景样本 跨领域应用潜力: 检测结果可延伸应用于细胞计数、病理分析、药物研发等多个生物医学领域
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值