Phy芯片一般通过mdio接口进行配置,如果满足以下条件
1、网卡驱动支持MDIO接口配置phy
2、确认驱动设置phy的方式,通过查看82599驱动代码确认:phyid包含两部分内容,phyaddr:phy地址和devnum:设备号,phyid=(phyaddr<<5)| (devnum & 0x1f)
3、确认应用层通过MDIO设置phy的方式,通常支持两种方式:ethtool和ioctl方式,具体支持那种方式也要通过驱动确认。
可以在应用层进行mdio读写配置,下面代码以Linux应用层通过ioctl接口配置phy:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/mii.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <linux/types.h>
#include <netinet/in.h>
#include <unistd.h>
#define reteck(ret) \
if(ret < 0){ \
printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \
goto lab; \
}
#define help() \
printf("mdio test:\n"); \
printf("read operation:mdio devname phyaddr reg_addr\n"); \
printf("write operation:mdio devname phyaddr reg_addr value\n"); \
printf("For example:\n"); \
printf("read:mdio eth0 0x1e 0x0\n"); \
printf("write:mdio eth0 0x1e 0x0 0x8489\n\n"); \
exit(0);
int main(int argc, char *argv[]){
int sockfd;
if(argc <= 3 || !strcmp(argv[1], "-h")){
help();
}
struct mii_ioctl_data *mii = NULL;
struct ethtool_value eth;
struct ifreq ifr;
int ret;
memset(&ifr, 0, sizeof(ifr));
memset(ð, 0 ,sizeof(eth));
eth.cmd = ETHTOOL_PHYS_ID;
strncpy(ifr.ifr_name, argv[1], IFNAMSIZ - 1);
sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
reteck(sockfd);
mii = (struct mii_ioctl_data*)&ifr.ifr_data;
if(argc == 4){
/*设置phyid, phyid包含两部分内容,phyaddr:phy地址和devnum:设备号,phyid=(phyaddr<<5)| (devnum & 0x1f)*/
mii->phy_id = (uint16_t)strtoul(argv[2], NULL, 0);
mii->reg_num = (uint16_t)strtoul(argv[3], NULL, 0);
ret = ioctl(sockfd, SIOCGMIIREG, &ifr);
printf("read phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_out);
reteck(ret);
}else if(argc == 5){
mii->phy_id = (uint16_t)strtoul(argv[2], NULL, 0);;
mii->reg_num = (uint16_t)strtoul(argv[3], NULL, 0);
mii->val_in = (uint16_t)strtoul(argv[4], NULL, 0);
ret = ioctl(sockfd, SIOCSMIIREG, &ifr);
printf("write phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_in);
reteck(ret);
}
lab:
close(sockfd);
return 0;
}
使用方式举例:
phy地址默认为0,读取功能号0x1e,寄存器号0,返回phy设备型号8489,例如以上代码编译生成mdio执行程序后输入参数运行:
./mdio eth0 0x1e 0x0
打印结果为:
read phy addr: 0x1e reg: 0x0 value : 0x8489