通过sysfs文件系统来调试phy

        kobjetc是linux操作系统中非常重要的对象。我们知道,linux内核中有一个通用的惯例就是:对象一般都是嵌入到被管理的数据结构中。如struct list_head,struct rb_node...等对象都是嵌入到数据结构中,然后通过 struct list_head,struct rb_node...等对象将被管理的数据结构挂载到链表或者插入到红黑树中。

        kobjetc就是这样的对象。kobject和sysfs文件系统是进行了深度的绑定。sysfs中每个文件背后就是一个kobject,所以在struct device数据定义中存在一个Kobject成员。

struct device {
    struct device        *parent;

    struct device_private    *p;

    struct kobject kobj;

   ...

}

如何在sysfs文件系统中创建目录或者文件已经超过了本文的范畴。读者可以阅读其他相关的资料,也可以查看源码kobject.c文件。其中涉及的主要接口就两个:

static sysfs_create_file(struct kobject *kobj,const struct attribute *attr);

static void sysfs_remove_file(struct kobject *kobj,const struct attribute *attr);

其他类似的接口无非是这两个基础接口的变体

int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)

void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)

int sysfs_create_group(struct kobject *kobj,const struct attribute_group *grp);

调用上面的接口的效果就是在sysfs文件系统中kobj对应的入口目录下创建对应的文件。通过属性attribute中的show和store函数来实现读写文件的值。这样就相当于通过sysfs文件系统在内核和用户空间之间提供了一个桥梁,这个桥梁对于phy来说最直观也是最有价值的操作就是用来读写phy内部的寄存器从实现某些功能。当然通过phy-tools,socket,ioctl等方式也可以进行phy寄存器的操作,只是通过sysfs更加简便。

注意,相对于/proc的混乱,/sys的目录结构是经过尽心的设计的,不要随意在其顶层添加目录。大多数编程中几乎不会独立的创建kboject,也很少会在/sysfs中去创建文件和目录,涉及到在sysfs中创建目录和文件的操作,内核中已经完成了接口的封装并将其放在了合理的接口当中,如device_create函数,调用其时会在/sys/devices下创建对应的kboject入口目录,同时在/dev下创建对应的设备节点等等。所以除了非常充分的理由,开发中我们几乎不会去调用上述的添加属性的接口。

我们来看下,如何通过sysfs来调试phy。其实在内核代码中有厂家已经这么干了。请大家打开/drivers/net/phy/tja110x.c(什么?你没得内核代码,那说个锤子),NXP为tja110x的车载以太网实现的Phy驱动中就是这么干的。

/*一堆属性的定义*/

static DEVICE_ATTR(master_cfg, S_IWUSR | S_IRUSR,

sysfs_get_master_cfg, sysfs_set_master_cfg);

static DEVICE_ATTR(power_cfg, S_IWUSR | S_IRUSR,

sysfs_get_power_cfg, sysfs_set_power_cfg);

static DEVICE_ATTR(loopback_cfg, S_IWUSR | S_IRUSR,

sysfs_get_loopback_cfg, sysfs_set_loopback_cfg);

static DEVICE_ATTR(cable_test, S_IRUSR, sysfs_get_cable_test, NULL);

static DEVICE_ATTR(test_mode, S_IWUSR | S_IRUSR,

sysfs_get_test_mode, sysfs_set_test_mode);

static DEVICE_ATTR(led_cfg, S_IWUSR | S_IRUSR,

sysfs_get_led_cfg, sysfs_set_led_cfg);

static DEVICE_ATTR(link_status, S_IRUSR, sysfs_get_link_status, NULL);

static DEVICE_ATTR(wakeup_cfg, S_IWUSR | S_IRUSR,

sysfs_get_wakeup_cfg, sysfs_set_wakeup_cfg);

static DEVICE_ATTR(snr_wlimit_cfg, S_IWUSR | S_IRUSR,

sysfs_get_snr_wlimit_cfg, sysfs_set_snr_wlimit_cfg);

static struct attribute *nxp_sysfs_entries[] = {

        &dev_attr_master_cfg.attr,

        &dev_attr_power_cfg.attr,

        &dev_attr_loopback_cfg.attr,

        &dev_attr_cable_test.attr,

        &dev_attr_test_mode.attr,

        &dev_attr_led_cfg.attr,

        &dev_attr_link_status.attr,

        &dev_attr_wakeup_cfg.attr,

        &dev_attr_snr_wlimit_cfg.attr,

        NULL

};

static struct attribute_group nxp_attribute_group = {

.name = "configuration",

.attrs = nxp_sysfs_entries,

};

err = sysfs_create_group(&phydev->mdio.dev.kobj, &nxp_attribute_group);

调用sysfs_create_group把这些属性定义注册到sysfs中,就会在phydev->mdio.dev.kobj目录下生成属性对应的文件,通过cat和echo操作就可以实现phy功能的开关。

上面的注册部分,大家根据自己项目的需要把show和store函数修改掉,就可以编译到内核中去尝试下了,非常方便的方法。

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值