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 – 这是指向带有最小尺寸 sizenmemb 字节的内存块的指针。
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(无符号长整型数)