三 Linux 网络驱动-MAC、PHY层驱动框架( 三 )


I. 网络驱动源码简析 1、 函数简析
对于 I. 而言网络驱动主要分两部分:I. 网络外设驱动以及 PHY 芯片驱 动 , 网络外设驱动是 NXP 编写的 , PHY 芯片有通用驱动文件 , 有些 PHY 芯片厂商还会针对自 己的芯片编写对应的 PHY 驱动 。总体来说 , SOC 内置网络 MAC+外置 PHY 芯片这种方案我们 是不需要编写什么驱动的 , 基本可以直接使用 。但是为了学习 , 我们还是要简单分析一下具体 的网络驱动编写过程 。
首先来看一下 I. 的网络控制器部分驱动 , 从示例代码 69.4.1.1 中可以看出 , 属性有两个值“fsl,-fec”和“fsl,imx6q-fec” , 通过在 linux 内核源码中搜索这两个 字符串即可找到对应的驱动文件 , 驱动文件为 /net///.c , 打开 .c , 找到如下所示内容:
1 static const struct of_device_id fec_dt_ids[] = {2{ .compatible = "fsl,imx25-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX25_FEC], },3{ .compatible ="fsl,imx27-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX27_FEC], },4{ .compatible ="fsl,imx28-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX28_FEC], },5{ .compatible ="fsl,imx6q-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX6Q_FEC], },6{ .compatible ="fsl,mvf600-fec", .data =http://www.kingceram.com/post/&fec_devtype[MVF600_FEC], },7{ .compatible ="fsl,imx6sx-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX6SX_FEC], },8{ .compatible ="fsl,imx6ul-fec", .data =http://www.kingceram.com/post/&fec_devtype[IMX6UL_FEC], },9{ /* sentinel */ }10 };1112 static struct platform_driver fec_driver = {13.driver = {14.name = DRIVER_NAME,15.pm = &fec_pm_ops,16.of_match_table = fec_dt_ids,17},18.id_table = fec_devtype,19.probe = fec_probe,20.remove = fec_drv_remove,21 };
第 8 行 , 匹配表包含“fsl,-fec” , 因此设备树和驱动匹配上 , 当匹配成功以后第 19 行 的函数就会执行 , 我们简单分析一下函数 , 函数内容如下:
1 static int fec_probe(struct platform_device *pdev)2 {3struct fec_enet_private *fep;4struct fec_platform_data *pdata;5struct net_device *ndev;6int i, irq, ret = 0;7struct resource *r;8const struct of_device_id *of_id;9static int dev_id;10struct device_node *np = pdev->dev.of_node, *phy_node;11int num_tx_qs;12int num_rx_qs;13 14fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);15 16/* Init network device */17ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private),18num_tx_qs, num_rx_qs);19if (!ndev)20return -ENOMEM;21 22SET_NETDEV_DEV(ndev, &pdev->dev);23 24/* setup board info structure */25fep = netdev_priv(ndev);26 27of_id = of_match_device(fec_dt_ids, &pdev->dev);28if (of_id)29pdev->id_entry = of_id->data;30fep->quirks = pdev->id_entry->driver_data;31 32fep->netdev = ndev;33fep->num_rx_queues = num_rx_qs;34fep->num_tx_queues = num_tx_qs;35 36 #if !defined(CONFIG_M5272)37/* default enable pause frame auto negotiation */38if (fep->quirks & FEC_QUIRK_HAS_GBIT)39fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;40 #endif41 42/* Select default pin state */43pinctrl_pm_select_default_state(&pdev->dev);44 45r = platform_get_resource(pdev, IORESOURCE_MEM, 0);46fep->hwp = devm_ioremap_resource(&pdev->dev, r);47if (IS_ERR(fep->hwp)) {48ret = PTR_ERR(fep->hwp);49goto failed_ioremap;50}51 52fep->pdev = pdev;53fep->dev_id = dev_id++;54 55platform_set_drvdata(pdev, ndev);56 57fec_enet_of_parse_stop_mode(pdev);58 59if (of_get_property(np, "fsl,magic-packet", NULL))60fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;61 62phy_node = of_parse_phandle(np, "phy-handle", 0);63if (!phy_node && of_phy_is_fixed_link(np)) {64ret = of_phy_register_fixed_link(np);65if (ret < 0) {66dev_err(&pdev->dev,67"broken fixed-link specification\n");68goto failed_phy;69}70phy_node = of_node_get(np);71}72fep->phy_node = phy_node;73 74ret = of_get_phy_mode(pdev->dev.of_node);75if (ret