linux设备模型分析之bus_register()

bus_register()大致分析:

struct bus_type mini_bus_type ={
	.name = "mini",
	.match = mini_match
};

static int __init test_init(void)
{
	return bus_register(&mini_bus_type);	
}

bus_register:工作就是完成bus_type_private的初始化.创建 注册的这条总线需要的目录文件.
             在这条总线目录下创建/device  /driver 目录
             初始化这条总线上的设备链表:struct klist klist_devices;
             初始化这条总线上的驱动链表:struct klist klist_drivers;
             
int bus_register(struct bus_type *bus)
{
	int retval;
	struct bus_type_private *priv;						//是上面mini_bus_type的成员.

	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->bus = bus;							//struct bus_type_private *p;所指向的内容动态分配.
	bus->p = priv;								//p关联到mini_bus_type

	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);		//kobject对应一个目录,这个目录就是我们看到的总线名字/bus/mini
	if (retval)
		goto out;
										//bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
	priv->subsys.kobj.kset = bus_kset;					//mini目录在bus下,即/bus/mini:初始化kset的成员kobject,为kset_register()做准备.   
	priv->subsys.kobj.ktype = &bus_ktype;					//static struct kobj_type bus_ktype = {    .sysfs_ops = &bus_sysfs_ops, };    
	priv->drivers_autoprobe = 1;						//设置该标志,	当有driver注册时,会自动匹配devices上的设备并用probe初始化,
										//		当有device注册时,也同样找到driver并会初始化  
										//int bus_add_driver(struct device_driver *drv)
										//	if (drv->bus->p->drivers_autoprobe) { error = driver_attach(drv); }
										  		 											                                   								                                       									    							      
	retval = kset_register(&priv->subsys);					//注册kset,创建目录结构,以及层次关系  生成/bus/mini                               
	if (retval)                                                                                                                           
		goto out;                                 
										//kset_register(&priv->subsys);
											//kobject_add_internal(&k->kobj);
												//error = create_dir(kobj); 
													//error = sysfs_create_dir(kobj);
										//&priv->subsys---->mini_bus_type->p->subsys  		
										//priv->subsys.kobj.kset = bus_kset;
																						                      
	retval = bus_create_file(bus, &bus_attr_uevent);			//mini目录下生成bus_attr_uevent属性文件 
	if (retval)
		goto bus_uevent_fail;

	priv->devices_kset = kset_create_and_add("devices", NULL,		//在mini下面创建一个mini/device,是mini这条总线的device的根目录.
						 &priv->subsys.kobj);		//为什么在mini目录下?  (device这个目录:kset->kobj) kset->kobj.parent = &priv->subsys.kobj;
										//在某个目录下:kset->kob.kset =  x    	这个目录在x目录下,这个目录下面“还可有”目录
										//             kobj.parent =     y	这个目录在y目录下,这个目录下面“没有”有目录
	if (!priv->devices_kset) {
		retval = -ENOMEM;
		goto bus_devices_fail;
	}

	priv->drivers_kset = kset_create_and_add("drivers", NULL,		//在mini下面创建一个mini/driver,是mini这条总线的driver的根目录.
						 &priv->subsys.kobj);		//struct kset *drivers_kset  指针.  
	if (!priv->drivers_kset) {
		retval = -ENOMEM;
		goto bus_drivers_fail;
	}

	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);	//初始化 mini_bus_type->p->klist_devices  就是初始化device的list_head
	klist_init(&priv->klist_drivers, NULL, NULL);				//					 就是初始化driver的list_head
										//device,driver注册都挂在对应的链表上.

	retval = add_probe_files(bus);						//创建文件
	if (retval)
		goto bus_probe_files_fail;

	retval = bus_add_attrs(bus);
	if (retval)
		goto bus_attrs_fail;

	pr_debug("bus: '%s': registered\n", bus->name);
	return 0;

bus_attrs_fail:
	remove_probe_files(bus);
bus_probe_files_fail:
	kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
	kset_unregister(bus->p->devices_kset);
bus_devices_fail:
	bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
	kset_unregister(&bus->p->subsys);
out:
	kfree(bus->p);
	bus->p = NULL;
	return retval;
}

struct bus_type {
	const char		*name;							//总线名称
	struct bus_attribute	*bus_attrs;						//总线属性(设备节点和这个有关系么?)
	struct device_attribute	*dev_attrs;						//设备属性   
	struct driver_attribute	*drv_attrs;						//驱动属性

	int (*match)(struct device *dev, struct device_driver *drv);			//用于匹配总线下的dev和driver
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);			//用于总线环境变量的添加
	int (*probe)(struct device *dev);						//总线和驱动匹配成功调用,platform不是设备和驱动匹配才调用么?没搞清楚.
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);						//关机

	int (*suspend)(struct device *dev, pm_message_t state);				//挂起
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;							//电源管理.

	struct bus_type_private *p;							//将bus device sysfs关联起来,怎么关联的不明白呀
};

struct bus_type_private {
	struct kset subsys;								//sysfs
	struct kset *drivers_kset;							//bus目录下的 drvier子目录
	struct kset *devices_kset;							//bus目录下的 device子目录
	struct klist klist_devices;							//bus目录下的设备列表
	struct klist klist_drivers;							//bus目录下的驱动列表
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;
};

struct bus_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct bus_type *bus, char *buf);
	ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
};

#define BUS_ATTR(_name, _mode, _show, _store)	\
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

#define __ATTR(_name,_mode,_show,_store) { \
	.attr = {.name = __stringify(_name), .mode = _mode },	\
	.show	= _show,					\
	.store	= _store,					\
}

#define __stringify_1(x...)	#x
#define __stringify(x...)	__stringify_1(x)

struct klist {
	spinlock_t		k_lock;
	struct list_head	k_list;
	void			(*get)(struct klist_node *);
	void			(*put)(struct klist_node *);
} __attribute__ ((aligned (sizeof(void *))));



你可能感兴趣的:(linux)