Linux网络设备phy

一.结构体

1.PHY设备

[cpp]  view plain copy
  1. struct phy_device {  
  2.     struct phy_driver *drv; //PHY设备驱动  
  3.     struct mii_bus *bus;    //对应的MII总线  
  4.     struct device dev;  //设备文件  
  5.     u32 phy_id; //PHY ID  
  6.     enum phy_state state;   //PHY状态  
  7.     u32 dev_flags;  
  8.     phy_interface_t interface;  //PHY接口  
  9.     int addr;   //PHY 总线地址(0~31)  
  10.     int speed;  //速度  
  11.     int duplex; //双工模式  
  12.     int pause;  //停止  
  13.     int asym_pause; //  
  14.     int link;     
  15.     u32 interrupts; //中断使能标志  
  16.     u32 supported;    
  17.     u32 advertising;  
  18.     int autoneg;  
  19.     int link_timeout;   //026  
  20.     int irq;    //中断号  
  21.     void *priv; //私有数据  
  22.     struct work_struct phy_queue;   //PHY工作队列  
  23.     struct delayed_work state_queue;    //PHY延时工作队列  
  24.     atomic_t irq_disable;     
  25.     struct mutex lock;  
  26.     struct net_device *attached_dev;    //网络设备  
  27.     void (*adjust_link)(struct net_device *dev);  
  28.     void (*adjust_state)(struct net_device *dev);  
  29. };  

2.PHY驱动

[cpp]  view plain copy
  1. struct phy_driver {  
  2.     u32 phy_id;     //PHY ID  
  3.     char *name;     //PHY名  
  4.     unsigned int phy_id_mask;  
  5.     u32 features;   //特性  
  6.     u32 flags;  //标记  
  7.     int (*config_init)(struct phy_device *phydev);  //配置初始化  
  8.     int (*probe)(struct phy_device *phydev);    //探测到 probe方法  
  9.     int (*suspend)(struct phy_device *phydev);  //唤醒  
  10.     int (*resume)(struct phy_device *phydev);   //挂起  
  11.     int (*config_aneg)(struct phy_device *phydev);  //支援(Auto-negotiation)配置  
  12.     int (*read_status)(struct phy_device *phydev);  //读支援(Auto-negotiation)状态  
  13.     int (*ack_interrupt)(struct phy_device *phydev);    //清中断  
  14.     int (*config_intr)(struct phy_device *phydev);  //使能/禁用 中断  
  15.     int (*did_interrupt)(struct phy_device *phydev);    //判断是否由中断  
  16.     void (*remove)(struct phy_device *phydev);  //移除  
  17.     int  (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); //时间戳处理  
  18.     bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);    //接收时间戳  
  19.     void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);    //发送时间戳  
  20.     struct device_driver driver;    //设备驱动文件  
  21. };  

二.设备与驱动的注册函数

1.注册PHY设备

[cpp]  view plain copy
  1. int phy_device_register(struct phy_device *phydev)  
  2. {  
  3.     int err;  
  4.     if (phydev->bus->phy_map[phydev->addr])    //判断PHY是否已经给注册了  
  5.         return -EINVAL;  
  6.     phydev->bus->phy_map[phydev->addr] = phydev;   //添加PHY到总线的phy_map里  
  7.     phy_scan_fixups(phydev);    //执行匹配的fixups  
  8.     err = device_register(&phydev->dev); //注册设备  
  9.     if (err) {  
  10.         pr_err("phy %d failed to register\n", phydev->addr);  
  11.         goto out;  
  12.     }  
  13.     return 0;  
  14.  out:  
  15.     phydev->bus->phy_map[phydev->addr] = NULL;  
  16.     return err;  
  17. }  
  18. EXPORT_SYMBOL(phy_device_register);  

PHY的设备一般是动态注册的在注册之前一般会调用get_phy_device函数

[cpp]  view plain copy
  1. struct phy_device * get_phy_device(struct mii_bus *bus, int addr)  
  2. {  
  3.     struct phy_device *dev = NULL;  
  4.     u32 phy_id;  
  5.     int r;  
  6.     r = get_phy_id(bus, addr, &phy_id); //获取PHY ID  
  7.     if (r)  
  8.         return ERR_PTR(r);  
  9.     if ((phy_id & 0x1fffffff) == 0x1fffffff)  
  10.         return NULL;  
  11.     dev = phy_device_create(bus, addr, phy_id); //创建PHY设备  
  12.     return dev;  
  13. }  
  14. EXPORT_SYMBOL(get_phy_device);  

获取PHY ID

[cpp]  view plain copy
  1. int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)  
  2. {  
  3.     int phy_reg;  
  4.     //调用PHY的总线也就是mii总线的读方法获取PHY ID  
  5.     phy_reg = bus->read(bus, addr, MII_PHYSID1); //获取PHYS ID1命令  
  6.     if (phy_reg < 0)  
  7.         return -EIO;  
  8.     *phy_id = (phy_reg & 0xffff) << 16;  
  9.     phy_reg = bus->read(bus, addr, MII_PHYSID2); //获取PHYS ID1命令  
  10.     if (phy_reg < 0)  
  11.         return -EIO;  
  12.     *phy_id |= (phy_reg & 0xffff);  
  13.     return 0;  
  14. }  
  15. EXPORT_SYMBOL(get_phy_id);  

创建PHY设备

[cpp]  view plain copy
  1. static struct phy_device* phy_device_create(struct mii_bus *bus,int addr, int phy_id)  
  2. {  
  3.     struct phy_device *dev;  
  4.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);    //分配phy设备内存  
  5.     if (NULL == dev)  
  6.         return (struct phy_device*) PTR_ERR((void*)-ENOMEM);  
  7.     dev->dev.release = phy_device_release;  
  8.     dev->speed = 0;  //速度  
  9.     dev->duplex = -1;    //双工模式  
  10.     dev->pause = dev->asym_pause = 0;  
  11.     dev->link = 1;     
  12.     dev->interface = PHY_INTERFACE_MODE_GMII;    //接口模式GMII  
  13.     dev->autoneg = AUTONEG_ENABLE;   //自动使能  
  14.     dev->addr = addr; //地址  
  15.     dev->phy_id = phy_id; //PHY ID  
  16.     dev->bus = bus;  //mii总线  
  17.     dev->dev.parent = bus->parent;    //父设备  
  18.     dev->dev.bus = &mdio_bus_type;   //总线类型  
  19.     dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;   //中断/轮询  
  20.     dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);   //PHY 设备文件名  
  21.     dev->state = PHY_DOWN;   //状态DOWN  
  22.     mutex_init(&dev->lock);  
  23.     INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);    //初始化PHY状态机  
  24.     request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id));  
  25.     return dev;  
  26. }  

2.注册PHY驱动

[cpp]  view plain copy
  1. int phy_driver_register(struct phy_driver *new_driver)  
  2. {  
  3.     int retval;  
  4.     new_driver->driver.name = new_driver->name;   //驱动名  
  5.     new_driver->driver.bus = &mdio_bus_type; //总线类型  
  6.     new_driver->driver.probe = phy_probe;    //探测函数  
  7.     new_driver->driver.remove = phy_remove;  //移除函数  
  8.     retval = driver_register(&new_driver->driver);   //注册设备驱动  
  9.     if (retval) {  
  10.         printk(KERN_ERR "%s: Error %d in registering driver\n",new_driver->name, retval);  
  11.         return retval;  
  12.     }  
  13.     pr_debug("%s: Registered new driver\n", new_driver->name);  
  14.     return 0;  
  15. }  
  16. EXPORT_SYMBOL(phy_driver_register);  

3.匹配

PHY设备和PHY驱动的总线类型都是mdio_bus_type

[cpp]  view plain copy
  1. struct bus_type mdio_bus_type = {  
  2.     .name       = "mdio_bus",  
  3.     .match      = mdio_bus_match,   //匹配方法  
  4.     .pm     = MDIO_BUS_PM_OPS,  
  5. };  
  6. EXPORT_SYMBOL(mdio_bus_type);  

匹配函数mdio_bus_match

[cpp]  view plain copy
  1. static int mdio_bus_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     struct phy_device *phydev = to_phy_device(dev); //获取PHY设备  
  4.     struct phy_driver *phydrv = to_phy_driver(drv); //获取PHY驱动  
  5.     return ((phydrv->phy_id & phydrv->phy_id_mask) ==(phydev->phy_id & phydrv->phy_id_mask));   //比较phy_id  
  6. }  

匹配成功就会调用phy驱动的probe方法,也即是phy_probe

[cpp]  view plain copy
  1. static int phy_probe(struct device *dev)  
  2. {  
  3.     struct phy_device *phydev;  
  4.     struct phy_driver *phydrv;  
  5.     struct device_driver *drv;  
  6.     int err = 0;  
  7.     phydev = to_phy_device(dev);    //获取PHY设备  
  8.     drv = get_driver(phydev->dev.driver);  
  9.     phydrv = to_phy_driver(drv);    //获取PHY驱动  
  10.     phydev->drv = phydrv;    //捆绑一下  
  11.     if (!(phydrv->flags & PHY_HAS_INTERRUPT))    //设置中断方式  
  12.         phydev->irq = PHY_POLL;  
  13.     mutex_lock(&phydev->lock);  
  14.     phydev->supported = phydrv->features; //设置PHY设备特性  
  15.     phydev->advertising = phydrv->features;   //设置PHY设备特性  
  16.     phydev->state = PHY_READY;   //状态设置为"准备好"  
  17.     if (phydev->drv->probe)   //如果驱动有probe方法  
  18.         err = phydev->drv->probe(phydev); //则调用  
  19.     mutex_unlock(&phydev->lock);  
  20.     return err;  
  21. }  

三.初始化过程

[cpp]  view plain copy
  1. static int __init phy_init(void)  
  2. {  
  3.     int rc;  
  4.     rc = mdio_bus_init();   //初始化mdio总线  
  5.     if (rc)  
  6.         return rc;  
  7.     rc = phy_driver_register(&genphy_driver);   //注册通用的PHY设备驱动  
  8.     if (rc)  
  9.         mdio_bus_exit();  
  10.     return rc;  
  11. }  

初始化过程主要是初始化mdio总线

接着注册通用的PHY设备驱动

[cpp]  view plain copy
  1. static struct phy_driver genphy_driver = {  
  2.     .phy_id = 0xffffffff,  
  3.     .phy_id_mask = 0xffffffff,  
  4.     .name   = "Generic PHY",  
  5.     .config_init = genphy_config_init, //初始化函数  
  6.     .features   = 0,  
  7.     .config_aneg = genphy_config_aneg, //配置 支援(Auto-negotiation)  
  8.     .read_status = genphy_read_status, //读状态  
  9.     .suspend    = genphy_suspend,  
  10.     .resume = genphy_resume,  
  11.     .driver = {.owner= THIS_MODULE, },  
  12. };  

初始化配置方法

[cpp]  view plain copy
  1. static int genphy_config_init(struct phy_device *phydev)  
  2. {  
  3.     int val;  
  4.     u32 features;  
  5.     //默认支持特性  
  6.     features = (SUPPORTED_TP | SUPPORTED_MII| SUPPORTED_AUI | SUPPORTED_FIBRE |SUPPORTED_BNC);  
  7.     val = phy_read(phydev, MII_BMSR);   //读基础状态  
  8.     if (val < 0)  
  9.         return val;  
  10.     if (val & BMSR_ANEGCAPABLE) //支持(auto-negotiation)  
  11.         features |= SUPPORTED_Autoneg;  
  12.     if (val & BMSR_100FULL) //100兆全双工  
  13.         features |= SUPPORTED_100baseT_Full;  
  14.     if (val & BMSR_100HALF) //100兆半双工  
  15.         features |= SUPPORTED_100baseT_Half;  
  16.     if (val & BMSR_10FULL)  //10兆全双工  
  17.         features |= SUPPORTED_10baseT_Full;  
  18.     if (val & BMSR_10HALF)  //10兆半双工  
  19.         features |= SUPPORTED_10baseT_Half;  
  20.     if (val & BMSR_ESTATEN) {  
  21.         val = phy_read(phydev, MII_ESTATUS);    //读扩展状态  
  22.         if (val < 0)  
  23.             return val;  
  24.         if (val & ESTATUS_1000_TFULL)   //1000兆全双工  
  25.             features |= SUPPORTED_1000baseT_Full;  
  26.         if (val & ESTATUS_1000_THALF)   //1000兆半双工  
  27.             features |= SUPPORTED_1000baseT_Half;  
  28.     }  
  29.     phydev->supported = features;    //PHY特性  
  30.     phydev->advertising = features;  
  31.     return 0;  
  32. }  

四.PHY状态机

1.状态分类

[cpp]  view plain copy
  1. enum phy_state {  
  2.     PHY_DOWN=0,  
  3.     PHY_STARTING,   //开始  
  4.     PHY_READY,  //准备好  
  5.     PHY_PENDING,    //挂起  
  6.     PHY_UP,     //开启  
  7.     PHY_AN,     //判断连接状态中 negotiating  
  8.     PHY_RUNNING,    //运行  
  9.     PHY_NOLINK, //开启 未连接  
  10.     PHY_FORCING,    //设置中  
  11.     PHY_CHANGELINK, //连接状态改变  
  12.     PHY_HALTED, //停止  
  13.     PHY_RESUMING    //唤醒  
  14. };  

2.状态机phy_state_machine

在phy_device_create函数中,开启了状态机

[cpp]  view plain copy
  1. void phy_state_machine(struct work_struct *work)  
  2. {  
  3.     struct delayed_work *dwork = to_delayed_work(work);  
  4.     struct phy_device *phydev = container_of(dwork, struct phy_device, state_queue);  
  5.     int needs_aneg = 0;  
  6.     int err = 0;  
  7.     mutex_lock(&phydev->lock);  
  8.     if (phydev->adjust_state)  
  9.         phydev->adjust_state(phydev->attached_dev);  
  10.     switch(phydev->state) {  
  11.         case PHY_DOWN:      //关闭((ifconfig eth0 down)  
  12.         case PHY_STARTING:  //开始  
  13.         case PHY_READY:     //准备好  
  14.         case PHY_PENDING:   //挂起  
  15.             break;  
  16.         case PHY_UP:    //开启(ifconfig eth0 up)  
  17.             needs_aneg = 1;  
  18.             phydev->link_timeout = PHY_AN_TIMEOUT;  
  19.             break;  
  20.         case PHY_AN:    //判断连接状态中 negotiating  
  21.             err = phy_read_status(phydev);  
  22.             if (err < 0)  
  23.                 break;  
  24.             if (!phydev->link) {  
  25.                 phydev->state = PHY_NOLINK;  
  26.                 netif_carrier_off(phydev->attached_dev);  
  27.                 phydev->adjust_link(phydev->attached_dev);  
  28.                 break;  
  29.             }  
  30.             err = phy_aneg_done(phydev);  
  31.             if (err < 0)  
  32.                 break;  
  33.             if (err > 0) {  
  34.                 phydev->state = PHY_RUNNING;  
  35.                 netif_carrier_on(phydev->attached_dev);  
  36.                 phydev->adjust_link(phydev->attached_dev);  
  37.   
  38.             }   
  39.             else if (0 == phydev->link_timeout--) {  
  40.                 int idx;  
  41.                 needs_aneg = 1;  
  42.                 if (phydev->drv->flags & PHY_HAS_MAGICANEG)  
  43.                     break;  
  44.                 idx = phy_find_valid(0, phydev->supported);  
  45.                 phydev->speed = settings[idx].speed;  
  46.                 phydev->duplex = settings[idx].duplex;  
  47.                 phydev->autoneg = AUTONEG_DISABLE;  
  48.                 pr_info("Trying %d/%s\n", phydev->speed,DUPLEX_FULL ==phydev->duplex ?"FULL" : "HALF");  
  49.             }  
  50.             break;  
  51.         case PHY_NOLINK:    //开启 未连接  
  52.             err = phy_read_status(phydev);  
  53.             if (err)  
  54.                 break;  
  55.             if (phydev->link) {  
  56.                 phydev->state = PHY_RUNNING;  
  57.                 netif_carrier_on(phydev->attached_dev);  
  58.                 phydev->adjust_link(phydev->attached_dev);  
  59.             }  
  60.             break;  
  61.         case PHY_FORCING:   //设置中  
  62.             err = genphy_update_link(phydev);  
  63.             if (err)  
  64.                 break;  
  65.             if (phydev->link) {  
  66.                 phydev->state = PHY_RUNNING;  
  67.                 netif_carrier_on(phydev->attached_dev);  
  68.             }   
  69.             else {  
  70.                 if (0 == phydev->link_timeout--) {  
  71.                     phy_force_reduction(phydev);  
  72.                     needs_aneg = 1;  
  73.                 }  
  74.             }  
  75.             phydev->adjust_link(phydev->attached_dev);  
  76.             break;  
  77.         case PHY_RUNNING:   //运行  
  78.             if (PHY_POLL == phydev->irq)  
  79.                 phydev->state = PHY_CHANGELINK;  
  80.             break;  
  81.         case PHY_CHANGELINK:    //连接状态改变  
  82.             err = phy_read_status(phydev);  
  83.             if (err)  
  84.                 break;  
  85.             if (phydev->link) {  
  86.                 phydev->state = PHY_RUNNING;  
  87.                 netif_carrier_on(phydev->attached_dev);  
  88.             }   
  89.             else {  
  90.                 phydev->state = PHY_NOLINK;  
  91.                 netif_carrier_off(phydev->attached_dev);  
  92.             }  
  93.             phydev->adjust_link(phydev->attached_dev);  
  94.             if (PHY_POLL != phydev->irq)  
  95.                 err = phy_config_interrupt(phydev,PHY_INTERRUPT_ENABLED);  
  96.             break;  
  97.         case PHY_HALTED:    //停止  
  98.             if (phydev->link) {  
  99.                 phydev->link = 0;  
  100.                 netif_carrier_off(phydev->attached_dev);  
  101.                 phydev->adjust_link(phydev->attached_dev);  
  102.             }  
  103.             break;  
  104.         case PHY_RESUMING:  //唤醒  
  105.             err = phy_clear_interrupt(phydev);  
  106.             if (err)  
  107.                 break;  
  108.             err = phy_config_interrupt(phydev,PHY_INTERRUPT_ENABLED);  
  109.             if (err)  
  110.                 break;  
  111.             if (AUTONEG_ENABLE == phydev->autoneg) {  
  112.                 err = phy_aneg_done(phydev);  
  113.                 if (err < 0)  
  114.                     break;  
  115.                 if (err > 0) {  
  116.                     err = phy_read_status(phydev);  
  117.                     if (err)  
  118.                         break;  
  119.                     if (phydev->link) {  
  120.                         phydev->state = PHY_RUNNING;  
  121.                         netif_carrier_on(phydev->attached_dev);  
  122.                     }   
  123.                     else  
  124.                         phydev->state = PHY_NOLINK;  
  125.                     phydev->adjust_link(phydev->attached_dev);  
  126.                 }   
  127.                 else {  
  128.                     phydev->state = PHY_AN;  
  129.                     phydev->link_timeout = PHY_AN_TIMEOUT;  
  130.                 }  
  131.             }  
  132.             else {  
  133.                 err = phy_read_status(phydev);  
  134.                 if (err)  
  135.                     break;  
  136.                 if (phydev->link) {  
  137.                     phydev->state = PHY_RUNNING;  
  138.                     netif_carrier_on(phydev->attached_dev);  
  139.                 }   
  140.                 else  
  141.                     phydev->state = PHY_NOLINK;  
  142.                 phydev->adjust_link(phydev->attached_dev);  
  143.             }  
  144.             break;  
  145.     }  
  146.     mutex_unlock(&phydev->lock);  
  147.     if (needs_aneg) //需要自动配置(例如ifconfig eth0 up就会调用)  
  148.         err = phy_start_aneg(phydev);   //开始自动配置  
  149.     if (err < 0)  
  150.         phy_error(phydev);  
  151.     schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);  
  152. }  

3.运行ifconfig eth0 up命令的过程

进入分支状态机分支

[cpp]  view plain copy
  1. case PHY_UP:    //开启(ifconfig eth0 up)  
  2.             needs_aneg = 1;  
  3.             phydev->link_timeout = PHY_AN_TIMEOUT;  
  4.             break;  

相应处理

[cpp]  view plain copy
  1. if (needs_aneg) //需要自动协商机制(例如ifconfig eth0 up就会调用)  
  2.         err = phy_start_aneg(phydev);   //开始自动配置  

调用phy_start_aneg函数

[cpp]  view plain copy
  1. int phy_start_aneg(struct phy_device *phydev)  
  2. {  
  3.     int err;  
  4.     mutex_lock(&phydev->lock);  
  5.     if (AUTONEG_DISABLE == phydev->autoneg)  
  6.         phy_sanitize_settings(phydev);  
  7.     err = phydev->drv->config_aneg(phydev);   //调用驱动的config_aneg方法,默认是genphy_config_aneg  
  8.     if (err < 0)  
  9.         goto out_unlock;  
  10.     if (phydev->state != PHY_HALTED) {   //调整修改PHY设备状态  
  11.         if (AUTONEG_ENABLE == phydev->autoneg) {  
  12.             phydev->state = PHY_AN;  
  13.             phydev->link_timeout = PHY_AN_TIMEOUT;  
  14.         }   
  15.         else {  
  16.             phydev->state = PHY_FORCING;  
  17.             phydev->link_timeout = PHY_FORCE_TIMEOUT;  
  18.         }  
  19.     }  
  20. out_unlock:  
  21.     mutex_unlock(&phydev->lock);  
  22.     return err;  
  23. }  
  24. EXPORT_SYMBOL(phy_start_aneg);  

调用默认的自动协商方法genphy_config_aneg

[cpp]  view plain copy
  1. int genphy_config_aneg(struct phy_device *phydev)  
  2. {  
  3.     int result;  
  4.     if (AUTONEG_ENABLE != phydev->autoneg)  
  5.         return genphy_setup_forced(phydev);  
  6.     result = genphy_config_advert(phydev);  
  7.     if (result < 0) /* error */  
  8.         return result;  
  9.     if (result == 0) {  
  10.         int ctl = phy_read(phydev, MII_BMCR);   //获取状态  
  11.         if (ctl < 0)  
  12.             return ctl;  
  13.         if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))  
  14.             result = 1; /* do restart aneg */  
  15.     }  
  16.     if (result > 0)  
  17.         result = genphy_restart_aneg(phydev);   //重新开启自动协商机制  
  18.     return result;  
  19. }  
  20. EXPORT_SYMBOL(genphy_config_aneg);  

接着调用genphy_config_aneg

[cpp]  view plain copy
  1. int genphy_restart_aneg(struct phy_device *phydev)  
  2. {  
  3.     int ctl;  
  4.     ctl = phy_read(phydev, MII_BMCR);   //获取基本状态  
  5.     if (ctl < 0)  
  6.         return ctl;  
  7.     ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);    //使能自动协商机制及支援重启  
  8.     /* Don't isolate the PHY if we're negotiating */  
  9.     ctl &= ~(BMCR_ISOLATE);  
  10.     ctl = phy_write(phydev, MII_BMCR, ctl); //写命令  
  11.     return ctl;  
  12. }  
  13. EXPORT_SYMBOL(genphy_restart_aneg);  


五.其他常用的api

[cpp]  view plain copy
  1. static inline int phy_read(struct phy_device *phydev, u32 regnum);  //PHY读  
  2. static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val);    //PHY写  
  3. void phy_start(struct phy_device *phydev);  //PHY开始  
  4. void phy_stop(struct phy_device *phydev);   //PHY停止  
  5. int phy_init_hw(struct phy_device *phydev); //PHY初始化硬件  
  6. struct phy_device * phy_attach(struct net_device *dev,const char *bus_id, u32 flags, phy_interface_t interface);    //PHY接上  
  7. void phy_detach(struct phy_device *phydev); //PHY分离  
  8. struct phy_device *phy_find_first(struct mii_bus *bus); //查找mii_bus总线上第一个PHY  
  9. int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,void (*handler)(struct net_device *), u32 flags,phy_interface_t interface);    //PHY直接连接网络设备  
  10. struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,void (*handler)(struct net_device *), u32 flags,phy_interface_t interface);  //PHY连接网络设备  
  11. void phy_disconnect(struct phy_device *phydev); //PHY断开与网络设备的连接  
  12. int phy_start_interrupts(struct phy_device *phydev);//PHY开始中断  
  13. int phy_stop_interrupts(struct phy_device *phydev); //PHY停止中断  
  14. int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);   //ethtool工具sset功能  
  15. int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);   //ethtool工具gset功能  
  16. int phy_mii_ioctl(struct phy_device *phydev,struct ifreq *ifr, int cmd);    //通用PHY/mii接口  
  17. void phy_print_status(struct phy_device *phydev);   //PHY打印状态  




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux网络物理层(Linux net phy)是指Linux操作系统中处理网络物理层通信的相关功能和驱动程序。 在计算机网络中,物理层是网络通信的第一层,负责将比特流转换为物理信号并通过网络介质进行传输。Linux net phy提供了一些工具和接口,用于配置和管理物理层通信。通过这些工具和接口,可以设置网络接口的速度、双工模式、自动协商和带宽控制等参数,以确保网络通信的稳定性和高效性。 Linux net phy还包括了一系列物理层驱动程序,用于支持不同类型网络接口的物理层通信。这些驱动程序能够识别和管理网络接口所需的物理层设备,并与操作系统进行交互,将物理层信号转化为数字信号,并在接收端将数字信号转化为物理层信号。 此外,Linux net phy还提供了一些性能监测和故障诊断工具,可以帮助用户监测网络接口的工作状态和性能,及时发现和解决网络通信问题。 总之,Linux net phyLinux操作系统中用于管理和控制网络物理层通信的功能和驱动程序,为网络通信提供了一系列配置、管理和诊断工具,使网络通信更加稳定和高效。 ### 回答2: Linux Net PHYLinux 系统中的一个网络设备驱动层,用于管理物理网络设备的操作和通信。在计算机网络中,PHY (Physical layer) 是指物理层,它是网络通信过程中最底层的部分,负责将数据以电信号的形式传输给网络介质或接收从介质传来的信号。 Linux Net PHY 提供了一套抽象的 API 接口,使得应用程序和上层网络协议栈可以通过统一的接口来访问不同类型的物理网络设备,如以太网卡或无线网卡等。通过这些接口,可以对物理网络设备进行配置、管理和监控等操作。 Linux Net PHY 的主要功能包括: 1. 链接状态监测:可以实时检测物理网络设备的链接状态,如连接状态是否正常、是否存在传输错误等。 2. 链路速度设置:可以调整物理网络设备的传输速度,以适应不同的网络环境和需求。 3. 自动协商支持:可以自动协商物理网络设备的传输速度和双工模式等参数,并自动适配最佳的通信设置。 4. 错误检测与纠正:可以对物理网络设备传输过程中的错误进行检测和纠正,提高数据传输的可靠性。 5. 能量管理支持:可以对物理网络设备进行能量管理,如进入低功耗模式等,以降低能耗和延长电池寿命。 总之,Linux Net PHYLinux 系统中提供了一套统一的接口和功能,用于管理和控制物理网络设备的操作,方便应用程序和上层网络协议栈对物理网络的访问和控制。它的存在是为了帮助用户更方便地使用和管理物理网络设备,提高网络通信的可靠性和性能。 ### 回答3: Linux Net PHY是一个用于Linux网络接口物理层(PHY)驱动程序的子系统。 PHY是网络接口控制器(NIC)中负责物理层通信的一部分。它负责将来自计算机系统的数据转换为适合在传输介质(如电缆或光纤)上传输的信号,并将接收到的信号转换为计算机系统可以理解的数据。 Linux Net PHY子系统是Linux内核的一部分,它提供了与PHY驱动程序交互的接口。这些驱动程序位于内核中的网络设备驱动程序层。Linux Net PHY子系统为不同的网络设备提供了一个标准化的接口,使得开发人员能够轻松编写PHY驱动程序并将其集成到Linux内核中。 通过Linux Net PHY子系统,开发人员可以访问PHY设备的功能、配置、状态和统计信息,并根据需要进行读取和写入。这使得开发人员能够更灵活地管理和控制网络接口的物理层。 此外,Linux Net PHY子系统还提供了一些额外的功能,例如根据网络中的连接状态自动关闭或打开PHY设备,以及在接收到异常信号时执行错误处理操作。这些功能帮助开发人员更好地管理和维护网络连接。 总之,Linux Net PHY是一个用于Linux网络接口物理层驱动程序的子系统,它为开发人员提供了一个标准化的接口来管理和控制网络接口的物理层,并提供一些额外的功能来帮助开发人员更好地管理和维护网络连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值