Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3125577
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: LINUX

2015-01-12 16:44:07

原文地址:



一、总线(bus)

    总线是CPU与外设之间的通道。在设备模型中,所有的设备都通过总线相连。用bus_type结构表示总线( ):
struct bus_type {
 const char  *name;//总线名,显示在/sysfs/bus/目录下,如/sysfs/bus/i2c
 struct bus_attribute *bus_attrs;//总线的缺省属性
 struct device_attribute *dev_attrs;//总线上设备的缺省属性
 struct driver_attribute *drv_attrs;//总线上挂接的驱动的缺省属性


//以下是总线的方法

 int (*match)(struct device *dev, struct device_driver *drv);
 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
 int (*probe)(struct device *dev);
 int (*remove)(struct device *dev);
 void (*shutdown)(struct device *dev);

 int (*suspend)(struct device *dev, pm_message_t state);
 int (*suspend_late)(struct device *dev, pm_message_t state);
 int (*resume_early)(struct device *dev);
 int (*resume)(struct device *dev);

 struct dev_pm_ops *pm;//电源管理接口,这里不讨论

 struct bus_type_private *p;//总线的私有数据,定义于driver/base/base.h
};

struct bus_type_private {
 struct kset subsys;//代表该总线的kset
 struct kset *drivers_kset;//挂接在该总线上的驱动的kset,如/sysfs/bus/i2c/drivers
 struct kset *devices_kset;//挂载在该总线上的设备的kset,如/sysfs/bus/i2c/devices
 struct klist klist_devices;//挂接在该总线上的设备链表
 struct klist klist_drivers;//挂接在该总线上的驱动链表
 struct blocking_notifier_head bus_notifier;//通知链,暂不讨论
 unsigned int drivers_autoprobe:1;
 struct bus_type *bus;//指向与之关联的bus_type
};


1、总线的注册


    函数bus_register用来向系统注册一个总线:int bus_register(struct bus_type *bus);


    以i2c总线为例,看看内核如何注册i2c总线的。首先,要准备名为“i2c”的bus_type结构:


/* drivers\i2c\i2c-core.c */


struct bus_type i2c_bus_type = {
 .name  = "i2c",
 .dev_attrs = i2c_dev_attrs,
/* 以下暂时省略总线的方法 */
};

  然后调用bus_register来注册i2c总线:


static int __init i2c_init(void)
{
 int retval;


 retval = bus_register(&i2c_bus_type);
......
}


    在调用bus_register(&i2c_bus_type)之后,将会在/sysfs/bus下看到i2c目录,在/sysfs/bus/i2c目录下看到devices和drivers目录。下面简单跟一下bus_register的源码(不考虑操作失败的情况):


首先,分配bus_type对应的私有数据结构
 struct bus_type_private *priv;


 priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);


将私有数据结构和bus_type对应起来


 priv->bus = bus;
 bus->p = priv;


设置总线的名字如“i2c” 


retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);


设置总线所属的kset,此处设置为bus_kset,bus_kset是在buses_init内创建的:


        int __init buses_init(void)
        {
             bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
             ......
        }
不清楚将bus_kset当成/sysfs/bus目录,而priv->subsys当成/sysfs/bus/xxx(如/sysfs/bus/i2c)目录是否更容易理解其中的层次关系?


 priv->subsys.kobj.kset = bus_kset;

阅读(701) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~