Linux 下smi/mdio总线通信
韩大卫@吉林师范大学
下面代码描述了在用户层访问smi/mdio总线, 读写phy芯片寄存器的通用代码。Linux内核2.6以上通用。
将下面代码编译后,将可执行文件a.out 重命名为mdio

mdio eth0 1  		读取phy寄存器1的数值
mdio eth0 0 0x1120 将0x1120写入 phy寄存器1 eth0 为mac层控制器的名称, 一般为eth0 或mgmt0。
#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> #define reteck(ret) \
if(ret < 0){ \
printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \
goto lab; \
} #define help() \
printf("mdio:\n"); \
printf("read operation: mdio reg_addr\n"); \
printf("write operation: mdio reg_addr value\n"); \
printf("For example:\n"); \
printf("mdio eth0 1\n"); \
printf("mdio eth0 0 0x12\n\n"); \
exit(0); int sockfd; int main(int argc, char *argv[]){ if(argc == 1 || !strcmp(argv[1], "-h")){
help();
} struct mii_ioctl_data *mii = NULL;
struct ifreq ifr;
int ret; memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, argv[1], IFNAMSIZ - 1); sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
reteck(sockfd); //get phy address in smi bus
ret = ioctl(sockfd, SIOCGMIIPHY, &ifr);
reteck(ret); mii = (struct mii_ioctl_data*)&ifr.ifr_data; if(argc == 3){ mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0); ret = ioctl(sockfd, SIOCGMIIREG, &ifr);
reteck(ret); printf("read phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_out);
}else if(argc == 4){ mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0);
mii->val_in = (uint16_t)strtoul(argv[3], NULL, 0); ret = ioctl(sockfd, SIOCSMIIREG, &ifr);
reteck(ret); printf("write phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_in);
} lab:
close(sockfd);
return 0;
}
很多人在read操作里面判断phy的link状态,

if(mii->val_out& 0x0004){

printf("linkup\n");

}else{

printf("linkdown\n");

}

其实这个做法是比较通用可行的。

解释一下,关于 mii->val_out& 0x0004

大多数phy芯片的寄存器0为控制寄存器, 寄存器1 为状态寄存器, 

寄存器3和4为 Identifiier Register
, 这里的内容为phy芯片产商的识别码。 举个实例,marvell 88E1116, 无论是光口模式还是电口模式, 寄存器1都是 Status register 一般寄存器有16个bit, 第2个bit为link 状态, 第5个bit为自动协商, 一般这个状态寄存器的数值为: 0x796d 意思是: 14bit : 有能力实现全双工100BASE-X工作模式 13bit : 有能力实现半双工 100BASE-X工作模式 12bit : 有能力实现全双工 10BASE-T工作模式 11 bit : 有能力实现半双工 10BASE-T工作模式 8bit : 扩展信息描述在寄存器15. 6bit : MF报头抑制 5bit : 自动协商完成 3bit : 有能力自动协商 2bit : link 状态: up 0bit : 有扩展寄存器 NOTE: 上面的ioctl()在linux最底层的实现函数是在drivers/net/phy/
目录下, 如octeon处理器平台: drivers/net/phy/mdio-octeon.c 这里面有mii总线读写phy寄存器的方法的实现函数: octeon_mdiobus_read
octeon_mdiobus_write ioctl的执行路径是: 用户层ioctl系统调用 --> drivers/net层接口函数 ndo_do_ioctl --> drivers/net/phy层接口函数 phy_mii_ioctl --> 通用接口函数mdiobus_read , 封装了mii_bus->read --> 最终是read的实现函数drivers/net/phy/mdio-octeon.c : octeon_mdiobus_read
												

Linux 下smi/mdio总线通信的更多相关文章

  1. Linux下smi/mdio总线驱动

    Linux下smi/mdio总线驱动 韩大卫@吉林师范大学 MII(媒体独立接口), 是IEEE802.3定义的以太网行业标准接口, smi是mii中的标准管理接口, 有两跟管脚, mdio 和mdc ...

  2. Linux下简单的socket通信实例

    Linux下简单的socket通信实例 If you spend too much time thinking about a thing, you’ll never get it done. —Br ...

  3. linux下的qt串口通信

    1.linux下的qt串口通信跟windows唯一的差别就是端口号的名字,windows下面是COM,而linux是ttyUSB0的路径 2.一般情况下linux插上USB转串口线就可以在/dev/目 ...

  4. Linux下进程间管道通信小作业

    在进行这次作业之前,我们先来看看什么是管道吧! 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间, ...

  5. Linux下的USB总线驱动(一)

    版权所有,转载请说明转自 http://my.csdn.net/weiqing1981127 一.USB理论 1.      USB概念概述 USB1.0版本速度1.5Mbps(低速USB) USB1 ...

  6. win7系统无线 VirtualBox rehat 32位linux 下 host-only模式相互通信及上网 配置

    虚拟机环境:virtualBox虚拟环境 redhat 32位 主机环境 : win7 无线路由 模式: host-only win7下nat模式原先的设置基于 有网线连接的情形下,在使用了无线路由之 ...

  7. Linux下Tun/Tap设备通信原理

    Tun/Tap都是虚拟网卡,没有直接映射到物理网卡,是一种纯软件的实现.Tun是三层虚拟设备,能够处理三层即IP包,Tap是二层设备,能处理链路层网络包如以太网包.使用虚拟网络设备,可以实现隧道,如O ...

  8. Linux下C语言socket通信实现发送读取的文件内容--简单实现代码

    本次代码涉及到的内容:socket通讯,文件读取 读取的文件以及文件位置: 要读取的文件和c文件在同一个目录下.客户端(client)读取的是123.xml,服务端(server)读取的是23.xml ...

  9. linux下有名管道进程通信

    一.任务 1.学习mkfifo等函数: 2.了解有名管道的特点.阻塞打开与非阻塞打开等: 3.编写一个关于有名管道进程通信的程序,并运行. 二.相关概念 1.相关函数 创建有名管道的函数是mkfifo ...

随机推荐

  1. Java笔记之java.lang.String#trim

    String的trim()方法是使用频率频率很高的一个方法,直到不久前我不确定trim去除两端的空白符时对换行符是怎么处理的点进去看了下源码的实现,才发现String#trim的实现跟我想像的完全不一 ...

  2. AC自动机(Keywords Search)

    题目链接:https://cn.vjudge.net/contest/280743#problem/A 题目大意:首先给你T组测试样例,然后给你n个字符串,最后再给你一个模式串,然后问你这一些字符串中 ...

  3. os_cpu_a.asm

    在OS_CPU_A.ASM中,定义了开.关中断的方法,在uC/OS-II系统中有三种方法可以实现中断开关,而ARM只适用于模式三,即使用一个局部变量,在中断进入之间保存CPU状态,退出时候再恢复状态. ...

  4. C# IEqualityComparer类型参数写法

    最近在使用Union.Except时,由于默认的对比不太好使,所以需要自定义对比器,下面附上代码. class MaterialListComparer : IEqualityComparer< ...

  5. Linux网络状态工具ss命令使用详解【转】

    ss命令用于显示socket状态. 他可以显示PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix dom ...

  6. STS热部署,springboot项目中修改代码不用重新启动服务

    方法如下: 1.在pom文件中引入  devtools  依赖: <dependency> <groupId>org.springframework.boot</grou ...

  7. 解决Spring配置文件不显示design和source, namespace 问题

    之前撸代码一直没太关注这个问题,后来发现对于不太熟悉配置文件内容的小伙伴们来说是比较痛苦的,因为每个配置项都需要你记住或者拷贝别人现成配置 那么问题来了,今天在写发现我的Spring配置文件不显示de ...

  8. php如何优雅地把数组传递给前端js脚本?

    比如说http://echarts.baidu.com/demo...这个例子中,一般里面的timeData数组都是数据库的所有记录的单独某一个列的集合,而例子中第149行的 data:[ 1,2,3 ...

  9. SQL Server 1

    一.登陆服务器 连接服务器方式分为两类,一类是Windows身份验证,一类是SQL身份验证.后者需要用户名和密码,需要自己创建. 二.创建数据库 在左边对象资源管理器中,选中数据库,右键选择新建数据库 ...

  10. #JS 窗口resize避免触发多次

    window窗口改变时触发resize,如何避免多次执行,设置一个300ms定时器即可. //窗口变化监听,避免resize多次执行卡顿 var resizeTimer = null; $(windo ...