一. 简介
前面一篇文章说明了有线网络的网络硬件方案。常用到的一种方案是:内部集成了MAC网络外设的SOC芯片(处理器),外接一个 PHY网络芯片。
前面文章也学习了Linux内核中的PHY子系统,也是为(上面这种方案)PHY网络芯片提供的驱动框架。
Linux内核内部提供了通用的PHY驱动。本文来学习一下Linux内核中的通用PHY驱动。
二. Linux内核中的通用PHY驱动(网络)
前面多次提到 Linux 内核已经集成了通用 PHY 驱动,通用 PHY 驱动名字为 “ Generic PHY ”,打开 drivers/net/phy/phy_device.c ,找到 phy_init 函数,内容如下:static int __init phy_init(void)
{
int rc;
rc = mdio_bus_init();
if (rc)
return rc;
rc = phy_drivers_register(genphy_driver,
ARRAY_SIZE(genphy_driver));
if (rc)
mdio_bus_exit();
return rc;
}
phy_init
是整个
PHY
子系统的入口函数,第
9
行会调用
phy_drivers_register
函数向内核直
接注册一个通用
PHY
驱动:
genphy_driver
,也就是通用
PHY
驱动,也就是说
Linux
系统启动
以后,默认就已经存在了通用
PHY
驱动。
genphy_driver
是一个数组,有两个数组元素,表示有两个通用的
PHY
驱动,一个是针对10/100/1000M
网络的,一个是针对
10G
网络的。
genphy_driver
定义在
drivers/net/phy/phy_device.c
里面,内容如下:
static struct phy_driver genphy_driver[] = {
{
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic PHY",
.soft_reset = genphy_soft_reset,
.config_init = genphy_config_init,
.features = PHY_GBIT_FEATURES | SUPPORTED_MII |
SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_BNC,
.config_aneg = genphy_config_aneg,
.aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
.driver = { .owner = THIS_MODULE, },
}, {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic 10G PHY",
.soft_reset = gen10g_soft_reset,
.config_init = gen10g_config_init,
.features = 0,
.config_aneg = gen10g_config_aneg,
.read_status = gen10g_read_status,
.suspend = gen10g_suspend,
.resume = gen10g_resume,
.driver = {.owner = THIS_MODULE, },
} };
genphy_driver
数组有两个元素,
genphy_driver[0]
为
10/100/1000M
的
PHY
驱动,名字为
“Generic PHY
”。
genphy_driver[1]
为
10G
的
PHY
驱动,名字为 “
Generic 10G PHY
”。
注意,很多另外编写的 PHY 驱动也会用到通用 PHY 驱动的一些函数
。
比如,正点原子
ALPHA
开发板所
用的
LAN8720A
是
SMSC
公司的产品,此公司针对自家的所有
PHY
芯片编写了一个驱动文件
smsc.c
,这驱动文件里面用到了大量的通用
PHY
驱动相关函数。