mdio读写工具

这个程序实现了通过MDIO总线读写PHY芯片寄存器的功能,使用C语言编写。通过socket和ioctl调用进行操作,支持eth0接口。函数包括MdioWrite用于写入寄存器,MdioRead用于读取寄存器,并提供了参数检查确保输入格式正确。

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

该功能主要用于mdio总线读写phy芯片寄存器。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <math.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <net/if.h>  
#include <linux/sockios.h>
#include <linux/mii.h>
#include <ctype.h>

int MdioWrite(unsigned short u16RegNum, unsigned short u16Value)
{
	int sockfd, ret;
    struct mii_ioctl_data *mii = NULL;
    struct ifreq ifr;
    const char *s8Ifrname = "eth0";
   
    if(!s8Ifrname)
    {
		printf("mdio_write failed, addr null.\n");
		return -1;
	}
	
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, s8Ifrname, IFNAMSIZ - 1);
    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
    if(sockfd < 0)
	{
	   printf("Create socket is failed.\n");
       return  -1;	   
    }

    //get phy address in smi bus
    ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);
    if(ret < 0)
	{
	   printf("Get phy address is failed.\n");
	   close(sockfd);
	   return -1;
    }

    mii = (struct mii_ioctl_data*)&ifr.ifr_data;
	mii->reg_num   = u16RegNum;
	mii->val_in    = u16Value;
	ret = ioctl(sockfd, SIOCSMIIREG, &ifr);
    if(ret < 0)
	{	
       close(sockfd);
	   printf("Get phy reg value is failed.\n");
	   return -1;
    }
	
	close(sockfd);
   //printf("write phy addr:0x%x  reg:0x%x  value:0x%x\n", mii->phy_id, mii->reg_num, mii->val_in);

    return 0;
}


int MdioRead(unsigned short u16RegNum, unsigned short *u16Value)
{
	int sockfd, ret;
    struct mii_ioctl_data *mii = NULL;
    struct ifreq ifr;
	const char *s8Ifrname = "eth0";
	
    if(!s8Ifrname || !u16Value)
    {
		printf("mdio_read failed, addr null.\n");
		return -1;
	}

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, s8Ifrname, IFNAMSIZ - 1);
    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
    if(sockfd < 0)
	{
	   printf("Create socket is failed.\n");
       return -1;	   
    }

    //get phy address in smi bus
    ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);
    if(ret < 0)
	{
	   printf("Get phy address is failed.\n");
	   close(sockfd);
	   return -1;
    }

    mii = (struct mii_ioctl_data*)&ifr.ifr_data;
	mii->reg_num   = u16RegNum;
	ret = ioctl(sockfd, SIOCGMIIREG, &ifr);
    if(ret < 0)
	{
	   close(sockfd);	  
	   printf("Get phy reg value is failed.\n");
	   return -1; 
    }
	
	*u16Value = mii->val_out;
	close(sockfd);
    //printf("read phy addr:0x%x  reg:0x%x  value:0x%x\n", mii->phy_id, mii->reg_num, mii->val_out);
	
    return 0;
}

int CheckStr(char *str)
{
	int i;
	
	for(i = 0;i < strlen(str) - 1;i++)
	{
		if('0' == str[i] && ('x' == str[i + 1] || 'X' == str[i + 1]))
		{
		   return -1;
		}
	}
	
	return 0;
}

int main(int argc, char *argv[])
{    
	int s32Ret = -1, s32Flag;
	unsigned short u16Reg, u16Value;
		 
		 
	printf("arg: read/write[0/1] reg[xx]  value[xxxx]\n\n");
	s32Flag = atoi(argv[1]);
	printf("s32Flag = %d argc = %d\n\n", s32Flag, argc);
	if(s32Flag && 3 != argc)
	{
		printf("arg is err, must be 3.\n");
		return -1;
	}
	else if(!s32Flag && 4 != argc)
	{
		printf("arg is err, must be 4.\n");		
		return -1;
	}
	
	s32Ret = CheckStr(argv[2]);
	if(s32Ret < 0)
	{
	    printf("input reg format is err, Please enter correct hex without 0x.\n");	
		return -1;
	}
	
	u16Reg = (unsigned short)strtoul(argv[2], NULL, 16);
	if(!s32Flag)
	{
		s32Ret = CheckStr(argv[3]);
		if(s32Ret < 0)
		{
	        printf("input value format is err, Please enter correct hex without 0x.\n");	
		    return -1;
		}
		
	    u16Value = (unsigned short)strtoul(argv[3], NULL, 16);
	}
	
	if(s32Flag)
	{
	   s32Ret = MdioRead(u16Reg, &u16Value);
	}
	else
	{
	   s32Ret = MdioWrite(u16Reg, u16Value);
	}
	
	if(s32Ret < 0)
	{		
	   printf("mdio write is err.\n");	
	   return -1;
	}
	
    printf("reg = 0x%x, value = 0x%x\n", u16Reg, u16Value);
	return 0;
}
### 如何使用 MDIO 接口读写 PHY 寄存器 #### 工具介绍 Linux 系统中的 MDIO 读写工具提供了便捷的方法来操作 PHY 寄存器。此工具不仅适用于网络工程师,也适合嵌入式开发人员以及系统维护者[^2]。 #### 基础概念 MDIO (Management Data Input/Output) 是一种用于管理和配置以太网物理层器件(PHYs)的标准接口协议。它允许主机控制器访问连接在其上的多个 PHY 芯片,并对其进行初始化、监控和诊断等功能[^1]。 #### 实际应用案例 对于 Rockchip(RK)平台下的 Android 或 Linux 操作系统而言,在调试过程中可以利用 mdio 工具来进行 phy 的寄存器读写工作。这通常涉及到编写 C 文件 `mdio.c` 来定义具体的函数实现,并按照一定流程完成交叉编译后执行相应的命令进行实际的操作[^3]。 #### 特殊情况处理 当采用 Altera FPGA 平台时,由于存在 MAC 层作为中介,因此需要先经过 MAC IP 才能到达最终的目标——PHY 芯片的 MDIO 接口。此时需要注意的是,目标地址范围应位于 MDIO Space1 中,即十六进制表示法下从 A0 到 BF 地址区间内[^4]。 #### Python 示例代码展示如何调用此类功能(假设已安装相关库) ```python import os def read_phy_register(mdio_bus, phy_address, register): command = f"ethtool -d eth0 mii {hex(phy_address)} reg {hex(register)}" result = os.popen(command).read() return int(result.strip(), base=16) def write_phy_register(mdio_bus, phy_address, register, value): command = f"ethtool -E eth0 magic 0xdeadbeef sopaddr 0x{phy_address:x} data 0x{value:x}" os.system(command) ``` 上述代码片段展示了怎样借助 ethtool 这样的外部程序间接地实现了对 PHY 寄存器的读取与修改动作;其中 `eth0` 表示所使用的网络接口名称,而其他参数则对应着不同的硬件实体或数据值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值