linux_phy_reg

本文章介绍linux下应用层访问phy寄存器的几种方式 便于开发者开发

厂家提供节点

一些厂家会直接提供类似/dev/mdio类似的节点,可以find -name 搜索一下看看。通过操作节点可以直接操作phy寄存器

uboot

uboot下可以通过mii cmd来实现读写phy寄存器

ioctl

套接字

API
1
2
3
4
5
6
7
/*	成功时返回文件描述符,失败时返回-1
domain: 套接字中使用的协议族(Protocol Family)
type: 套接字数据传输的类型信息
protocol: 计算机间通信中使用的协议信息
*/
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
协议族

image-20241009093230037

套接字类型

常用:

  • SOCK_STREAM

    流,TCP。面向连接。

    • 传输过程中数据不会消失。
    • 按序传输数据。
    • 传输的数据不存在数据边界(Boundary)。
    • 缓冲区不会因为满而丢失数据,因为有滑动窗口控制,能接收多少都会告诉对端。
  • SOCK_DGRAM

    面向消息的,不可靠的。

    • 强调快速传输而非传输有序。
    • 传输的数据可能丢失也可能损毁。
    • 传输的数据有边界。
    • 限制每次传输数据的大小。

ioctl实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LONG skfd = -1;
struct mii_data *data;
struct ifreq ifr;

skfd = socket(PF_UNIX, SOCK_STREAM, 0); // #define PF_UNIX AF_UNIX --> Unix domain sockets 常用于本地连接
data = (struct mii_data *)&ifr.ifr_data;
data->phy_id = (unsigned short)ucMiiAddr; //phy地址
data->reg_num = (unsigned short)ucRegAddr; //寄存器地址

ioctl(skfd, SIOCGMIIREG, &ifr);
*pusData = data->val_out;

// include/uapi/linux/socketios.h中
#define SIOCGMIIREG 0x8948 /* Read MII PHY register. */
#define SIOCSMIIREG 0x8949 /* Write MII PHY register. */

底层调用实现

1
2
3
4
5
// 内核通用框架
dev_ioctl --> dev_ifsioc --> dev_do_ioctl --> ndo_do_ioctl

// 底层芯片厂商驱动实现
mstar_emac_drv_init_module --> Mstar_emac_driver --> mstar_emac_drv_probe --> MDev_EMAC_init --> MDev_EMAC_setup --> dev->do_ioctl = MDev_EMAC_ioctl;