一、mii-tool

安装

sudo apt install net-tools

显示信息(-vvv)

  • PHY 32 个寄存器值
  • 根据寄存器值,解析 PHY 状态
    • 能力
    • 协商状态
    • 速率
    • 连接状态
liyongjun@box:~$ sudo mii-tool enp2s0 -vvv
Using SIOCGMIIPHY=0x8947
enp2s0: negotiated 1000baseT-FD flow-control, link ok
  registers for MII PHY 32:
    1040 79ed 001c c800 0de1 c5e1 006d 2801
    6801 0200 3800 0000 0000 0000 0000 2000
    0023 0000 ffff 0000 0000 0400 0f00 0f00
    319f 0053 30ec 80d9 7078 0000 0000 0000
  product info: vendor 00:07:32, model 0 rev 0
  basic mode:   autonegotiation enabled
  basic status: autonegotiation complete, link ok
  capabilities: 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
  advertising:  1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control
  link partner: 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control

重启自动协商过程(-r)

liyongjun@box:~$ sudo mii-tool enp2s0 -r
restarting autonegotiation...

reset PHY(-R)

liyongjun@box:~$ sudo mii-tool enp2s0 -R
resetting the transceiver...

监控 PHY 连接状态(-w)

liyongjun@box:~$ sudo mii-tool enp2s0 -w
22:07:02 enp2s0: negotiated 1000baseT-FD flow-control, link ok
22:07:10 enp2s0: no link
22:07:31 enp2s0: negotiated 100baseTx-FD flow-control, link ok

强制指定速率和全双工半双工模式(-F)

注:插拔网线,配置仍然生效。想要恢复,使用 -r 选项重新自动协商;或者使用 -R 选项 reset PHY。

强制设置为 100M 全双工
liyongjun@box:~$ sudo mii-tool enp2s0 -F 100baseTx-FD
liyongjun@box:~$

查看结果,变成了 100M 全双工

liyongjun@box:~$
liyongjun@box:~$ sudo mii-tool enp2s0 -vvv
Using SIOCGMIIPHY=0x8947
enp2s0: 100 Mbit, full duplex, link ok
  registers for MII PHY 32:
    2100 79cd 001c c800 0de1 0080 0064 2001
    0000 0200 0000 0000 0000 0000 0000 2000
    0023 0000 ffff 0000 0000 0400 0f00 0f00
    319f 0053 201c 80d9 7078 0000 0000 0000
  product info: vendor 00:07:32, model 0 rev 0
  basic mode:   100 Mbit, full duplex
  basic status: link ok
  capabilities: 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
  advertising:  1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control
  link partner: 100baseTx-HD
强制设置为 10M 全双工
liyongjun@box:~$ sudo mii-tool enp2s0 -F 10baseT-FD
liyongjun@box:~$

查看结果

liyongjun@box:~$ sudo mii-tool enp2s0 -vvv
Using SIOCGMIIPHY=0x8947
enp2s0: 10 Mbit, full duplex, link ok
  registers for MII PHY 32:
    0100 79cd 001c c800 0de1 0020 0064 2001
    0000 0200 0000 0000 0000 0000 0000 2000
    0023 0000 ffff 0000 0000 0400 0f00 0f00
    319f 0053 210c 80d9 7078 0000 0000 0000
  product info: vendor 00:07:32, model 0 rev 0
  basic mode:   10 Mbit, full duplex
  basic status: link ok
  capabilities: 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
  advertising:  1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control
  link partner: 10baseT-HD

强制设置为 100M 半双工
liyongjun@box:~$ sudo mii-tool enp2s0 -F 100baseTx-HD

查看结果

liyongjun@box:~$ sudo mii-tool enp2s0 -vvv
Using SIOCGMIIPHY=0x8947
enp2s0: 100 Mbit, half duplex, link ok
  registers for MII PHY 32:
    2000 79cd 001c c800 0de1 0080 0064 2001
    0000 0200 0000 0000 0000 0000 0000 2000
    0023 0000 ffff 0000 0000 0400 0f00 0f00
    319f 0053 2014 80d9 7078 0000 0000 0000
  product info: vendor 00:07:32, model 0 rev 0
  basic mode:   100 Mbit, half duplex
  basic status: link ok
  capabilities: 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
  advertising:  1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control
  link partner: 100baseTx-HD

指定速率和全双工半双工模式(-A)

和 -F 类似

二、phytool

下载地址

https://github.com/wkz/phytool

用法

liyongjun@box:~/project/c/phytool (master)$ ./phytool
Usage: phytool read  IFACE/ADDR/REG
       phytool write IFACE/ADDR/REG <0-0xffff>
       phytool print IFACE/ADDR[/REG]

Clause 22:

ADDR := <0-0x1f>
REG  := <0-0x1f>

Clause 45 (not supported by all MDIO drivers):

ADDR := PORT:DEV
PORT := <0-0x1f>
DEV  := <0-0x1f>
REG  := <0-0xffff>

Examples:
       phytool read  eth0/0:4/0x1000
       phytool write eth0/0xa/0 0x1140
       phytool print eth0/0x1c

The `read` and `write` commands are simple register level
accessors. The `print` command will pretty-print a register. When
using the `print` command, the register is optional. If left out, the
most common registers will be shown.

Bug report address: https://github.com/wkz/phytool/issues

使用 phytool 需要知道 PHY 地址,可以使用 ethtoo 工具获取,如下,PHY 地址为 0

liyongjun@box:~/project/c/phytool (master)$ sudo ethtool enp2s0 | grep PHYAD
        PHYAD: 0

查看 PHY 寄存器信息

  • phy id
  • 寄存器 0
  • 寄存器 1
liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0
ieee-phy: id:0x001cc800

   ieee-phy: reg:BMCR(0x00) val:0x1040
      flags:          -reset -loopback +aneg-enable -power-down -isolate -aneg-restart -collision-test
      speed:          1000-half

   ieee-phy: reg:BMSR(0x01) val:0x79ed
      capabilities:   -100-b4 +100-f +100-h +10-f +10-h -100-t2-f -100-t2-h
      flags:          +ext-status +aneg-complete -remote-fault +aneg-capable +link -jabber +ext-register

查看指定寄存器值

分别查看 PHY 的 0、1、2、3、F 寄存器

liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0/0
ieee-phy: reg:BMCR(0x00) val:0x1040
   flags:          -reset -loopback +aneg-enable -power-down -isolate -aneg-restart -collision-test
   speed:          1000-half
liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0/1
ieee-phy: reg:BMSR(0x01) val:0x79ed
   capabilities:   -100-b4 +100-f +100-h +10-f +10-h -100-t2-f -100-t2-h
   flags:          +ext-status +aneg-complete -remote-fault +aneg-capable +link -jabber +ext-register
liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0/2
ieee-phy: reg:0x02 val:0x001c
liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0/3
ieee-phy: reg:0x03 val:0xc800
liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool print enp2s0/0/f
ieee-phy: reg:BMCR(0x00) val:0x1040
   flags:          -reset -loopback +aneg-enable -power-down -isolate -aneg-restart -collision-test
   speed:          1000-half

脚本

或者使用如下脚本,循环读取指定 PHY 地址的 32 个寄存器值


liyongjun@box:~/project/c/phytool (master)$ cat phytool_script.sh
#!/bin/bash

# 检查是否提供了一个参数
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <PHY Address>"
    exit 1
fi

# 读取参数
PHY_ADDRESS=$1

# 检查PHY地址是否为有效数字
if ! [[ "$PHY_ADDRESS" =~ ^[0-31]$ ]]; then
    echo "PHY Address must be a number between 0 and 31."
    exit 2
fi

# 循环读取0到31的寄存器地址
for REGISTER_ADDRESS in $(seq 0 31); do
    # echo "Reading register address: $REGISTER_ADDRESS"
    # 执行phytool命令
    sudo ./phytool print enp2s0/$PHY_ADDRESS/$REGISTER_ADDRESS
done

执行

liyongjun@box:~/project/c/phytool (master)$ ./phytool_script.sh 0
ieee-phy: reg:BMCR(0x00) val:0x1040
   flags:          -reset -loopback +aneg-enable -power-down -isolate -aneg-restart -collision-test
   speed:          1000-half
ieee-phy: reg:BMSR(0x01) val:0x79ed
   capabilities:   -100-b4 +100-f +100-h +10-f +10-h -100-t2-f -100-t2-h
   flags:          +ext-status +aneg-complete -remote-fault +aneg-capable +link -jabber +ext-register
ieee-phy: reg:0x02 val:0x001c
ieee-phy: reg:0x03 val:0xc800
ieee-phy: reg:0x04 val:0x0de1
ieee-phy: reg:0x05 val:0xc5e1
ieee-phy: reg:0x06 val:0x006d
ieee-phy: reg:0x07 val:0x2801
ieee-phy: reg:0x08 val:0x6801
ieee-phy: reg:0x09 val:0x0200
ieee-phy: reg:0x0a val:0x3800
ieee-phy: reg:0x0b val:0x0000
ieee-phy: reg:0x0c val:0x0000
ieee-phy: reg:0x0d val:0x0000
ieee-phy: reg:0x0e val:0x0000
ieee-phy: reg:0x0f val:0x2000
ieee-phy: reg:0x10 val:0x0023
ieee-phy: reg:0x11 val:0x0000
ieee-phy: reg:0x12 val:0xffff
ieee-phy: reg:0x13 val:0x0000
ieee-phy: reg:0x14 val:0x0000
ieee-phy: reg:0x15 val:0x0400
ieee-phy: reg:0x16 val:0x0f00
ieee-phy: reg:0x17 val:0x0f00
ieee-phy: reg:0x18 val:0x319f
ieee-phy: reg:0x19 val:0x0053
ieee-phy: reg:0x1a val:0x30ee
ieee-phy: reg:0x1b val:0x80d9
ieee-phy: reg:0x1c val:0x7078
ieee-phy: reg:0x1d val:0x0000
ieee-phy: reg:0x1e val:0x0000
ieee-phy: reg:0x1f val:0x0000

读取寄存器


liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool read enp2s0/0/0
0x1040

写寄存器

寄存器 0 的 bit15 为 PHY Reset 位,将该位置 1,触发 PHY Reset。该位置 1 后,寄存器的值由 0x1040 变为 0x9040

liyongjun@box:~/project/c/phytool (master)$ sudo ./phytool write enp2s0/0/0 0x9040
liyongjun@box:~/project/c/phytool (master)$

三、mdio-tool

下载地址

https://github.com/PieVo/mdio-tool

用法

liyongjun@box:~/project/c/mdio-tool/__build (master)$ sudo ./mdio-tool
Usage mii [r/w] [dev] [reg] [val]

读寄存器

liyongjun@box:~/project/c/mdio-tool/__build (master)$ sudo ./mdio-tool r enp2s0 0
0x1040

写寄存器

复位 PHY

liyongjun@box:~/project/c/mdio-tool/__build (master)$ sudo ./mdio-tool w enp2s0 0 0x9040

四、phyreg

源码

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/mii.h>
#include <linux/sockios.h>
#include <linux/types.h>
#include <net/if.h>

#define reteck(ret)                                            \
	if (ret < 0) {                                             \
		printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \
		goto lab;                                              \
	}

#define help()                                        \
	printf("phyreg:\n");                                \
	printf("read operation: phyreg reg_addr\n");        \
	printf("write operation: phyreg reg_addr value\n"); \
	printf("For example:\n");                         \
	printf("phyreg eth0 1\n");                          \
	printf("phyreg eth0 0 0x12\n\n");                   \
	exit(0);

int sockfd;

int main(int argc, char *argv[])
{
	struct mii_ioctl_data *mii = NULL;
	struct ifreq ifr;
	int ret;

	if (argc == 1 || !strcmp(argv[1], "-h")) {
		help();
	}

	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", 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", mii->phy_id, mii->reg_num, mii->val_in);
	}
lab:
	close(sockfd);
	return 0;
}

编译

liyongjun@box:~/project/c/phyreg$ gcc phyreg.c -o phyreg

用法

liyongjun@box:~/project/c/phyreg$ sudo ./phyreg
phyreg:
read operation: phyreg reg_addr
write operation: phyreg reg_addr value
For example:
phyreg eth0 1
phyreg eth0 0 0x12

读寄存器

liyongjun@box:~/project/c/phyreg$ sudo ./phyreg enp2s0 0
read phy addr: 0x20 reg: 0x0 value : 0x1040

可以看到,它甚至能读出 PHY 地址:phy addr: 0x20

写寄存器

复位 PHY

liyongjun@box:~/project/c/phyreg$ sudo ./phyreg enp2s0 0 0x9040
write phy addr: 0x20 reg: 0x0 value : 0x9040
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐