长期潜藏于CSDN http://blog.csdn.net/npjocj
分类:
2012-11-21 14:59:03
原文地址:基于高通MSM 8x60的I2C驱动终极讲解(5) 作者:shangbaogen
asmlinkage void __init start_kernel(void)
{
......
rest_init();
}
start_kernel()中的函数rest_init()将创建第一个核心线程kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND),调用init()函数:
static int init(void * unused)-------------------
{
do_basic_setup();
}
static void __init do_basic_setup(void)-----------------
{
.......
driver_init(); //建立设备模型子系统
}
<./drivers/base/init.c>-------------------------
void __init driver_init(void)
{
platform_bus_init();
}
下面进去看看platform_bus_init();的实现。
int __init platform_bus_init(void)
{
device_register(&platform_bus);//注册platform_bus设备
bus_register(&platform_bus_type);//注册platform bus总线
}
下面看看这个平台总线到底怎么注册的:
int bus_register(struct bus_type *bus)
{
struct bus_type_private *priv;
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);//分配一个priv结构体
priv->bus = bus;//把priv结构体依附在该总线上
bus->p = priv;//把总线的p指针赋值为priv
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);//初始化通知链的
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);//设置priv->sybsys的name
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
retval = kset_register(&priv->subsys);//注册subsys
retval = bus_create_file(bus, &bus_attr_uevent);//为总线创建属性
/*初始化priv的两个kset,分别存放属于该总线的devices和drivers*/
priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
priv->drivers_kset = kset_create_and_add("drivers", NULL,&priv->subsys.kobj);
/*初始化priv的两个链表,该链表链接了该总线的设备与驱动*/
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);
}
上述函数总结起来如下:
建立一条总线,把她加入bus_kset专门存放bus的容器中,然后初始化该总线所用的devices kset,driver kset,devices driver链表,创建总线的属性等,以后在该总线上注册的驱动或者是设备,都会挂载到相应的链表和kset下。