mdio读写

SMI 接口包括两根信号线:MDC和MDIO

通过MAC层芯片(或其它控制芯片)可以访问物理层芯片的寄存器,并通过这些寄存器来对物理层芯片进行控制和管理。SMI管理接口如下:

MDC:管理接口的时钟,是非周期信号,与TX_CLK和RX_CLK无任何关系。

MDIO:双向的数据线。传送MAC层的控制信息和物理层的状态信息。MDIO数据与MDC时钟同步,在MDC上升沿有效。

#define MII_MMD_CTRL 0x0d
#define MII_MMD_DATA 0x0e

static void mdio_read(int skfd)
{
	if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) {
		fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
				strerror(errno));
	}
}
 
static void mdio_write(int skfd)
{
	if (ioctl(skfd, SIOCSMIIREG, &ifr) < 0) {
		fprintf(stderr, "SIOCSMIIREG on %s failed: %s\n", ifr.ifr_name,
				strerror(errno));
	}
}

 
static inline void mdio_phy_mmd_indirect(int skfd, int devad, int reg) {
	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data;
	/* Write the desired MMD Devad */
	mii->val_in = devad;
	mii->reg_num = MII_MMD_CTRL;
	mdio_write(skfd);
	/* Write the desired MMD register address */
	mii->val_in = reg;
	mii->reg_num = MII_MMD_DATA;
	mdio_write(skfd);
	/* Select the Function: DATA with no post increment */
	mii->val_in = devad | MII_MMD_CTRL_NOINCR;
	mii->reg_num = MII_MMD_CTRL;
	mdio_write(skfd);
}

main

struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr.ifr_data;
	int phyaddr, devad, reg, val=0;
	int ret;
 
	
	phyaddr = strtol(argv[1], NULL, 0);
	devad = strtol(argv[2], NULL, 0);
	reg = strtol(argv[3], NULL, 0);
	
	fd = socket(AF_INET, SOCK_DGRAM,0);
	if (fd < 0) {
		perror("open");
		exit(1);
	}
	strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
 
	ret = ioctl(fd, SIOCGMIIPHY, &ifr);
	if (ret < 0) {
		fprintf(stderr, "SIOCGMIIPHY on %s failed: %s\n", ifr.ifr_name,
				strerror(errno));
		return -1;
	}
 
	if (phyaddr != mii->phy_id) {
		perror("wrong phy addr");
		exit(1);
	}

mdio_phy_mmd_indirect(fd, devad, reg);
		mii->reg_num = MII_MMD_DATA;
       		mdio_read(fd);
		printf("reading : 0x%04x\n", mii->val_out);

mdio_phy_mmd_indirect(fd, devad, reg);
		mii->reg_num = MII_MMD_DATA;
		mii->val_in = val;
		mdio_write(fd);
		printf("write done\n");

原文链接:https://blog.csdn.net/zgp2917/article/details/121373828

注:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE stream) 从给定流 stream 读取数据到 ptr 所指向的数组中
ptr – 这是指向带有最小尺寸 size
nmemb 字节的内存块的指针。
nmemb – 这是元素的个数,每个元素的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。

__DATE__  
__TIME__  
__STDC__ //当编译器以ANSI标准编译时,则定义为1
__FILE__  //当前文件名,一个字符串常量
__LINE__  //当前行号,一个十进制常量

strcmp(s1,s2); s1=s2,返回0;s1<s2,返回小于0;s1>s2,返回大于0。
strchr(s1,ch); 返回一个指针,指向字符串s1中字符ch的第一次出现的位置。
strstr(s1,s2); 返回一个指针,s1中字符串s2第一次出现。

\ 宏延续运算符

#include < > 引用的是编译器的类库路径里面的头文件。

#include " " 引用的是你程序目录的相对路径中的头文件

strerror() 返回一个指针,指针指向当前error值的文本表示形式。

inline 内联函数,编译器其他文件看不到这个函数,因此该函数只能在当前文件中被调用。

void *memset(void *s,int c,size_t n)
总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c

char *strncpy(char *dest, const char *src, size_t n)
dest – 指向用于存储复制内容的目标数组
src – 要复制的字符串
n – 要从源中复制的字符数

UDP套接字的名字SOCK_DGRAM
TCP套接字的名字SOCK_STREAM

socketpair与socket的domain参数,使用PF_LOCAL系列 协议
在初始化套接口地址结构时,则使用AF_LOCAL 地址

SIOCGMIIPHY phy地址
SIOCGMIIREG 读寄存器
SIOCSMIIREG 写寄存器
SIOCETHTOOL ethtool接口

strtoul函数:将字符串转换成unsigned long(无符号长整型数)


版权声明:本文为weixin_43490398原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。