LDM上层建筑之Driver---局部窥探

在module_init(s3c_rtc_init); 时,

static int __init s3c_rtc_init(void)
{
printk(banner);
return platform_driver_register(&s3c2410_rtcdrv);
}

系统注册s3c_rtc时,将banner打出来了

static struct platform_driver s3c2410_rtcdrv = {
.probe  = s3c_rtc_probe,
.remove  = s3c_rtc_remove,
.suspend = s3c_rtc_suspend,
.resume  = s3c_rtc_resume,
.driver  = {
  .name = "s3c2410-rtc",
  .owner = THIS_MODULE,
},
};

int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;      //设置driver的bus type
if (drv->probe)                                               //在platform_driver s3c2410_rtcdrv 定义了.probe  = s3c_rtc_probe,
  drv->driver.probe = platform_drv_probe;    //将drv->driver.probe 设为platform_drv_probe   将drv->driver.probe和drv->probe都设置为platform_driver的probe函数,即是s3c_rtc_probe函数
if (drv->remove)
  drv->driver.remove = platform_drv_remove;  //同理
if (drv->shutdown)
  drv->driver.shutdown = platform_drv_shutdown;
if (drv->suspend)
  drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
  drv->driver.resume = platform_drv_resume;
return driver_register(&drv->driver);                    //这里就是关键的注册函数:driver_register
}

 

/**
* driver_register - register driver with bus
* @drv: driver to register
*
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
    int ret;

    if ((drv->bus->probe && drv->probe) ||
        (drv->bus->remove && drv->remove) ||
        (drv->bus->shutdown && drv->shutdown))
        printk(KERN_WARNING "Driver '%s' needs updating - please use "
            "bus_type methods/n", drv->name);
    ret = bus_add_driver(drv);                //We pass off most of the work to the bus_add_driver() call
    if (ret)
        return ret;
    ret = driver_add_groups(drv, drv->groups);
    if (ret)
        bus_remove_driver(drv);
    return ret;
}

/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/
int bus_add_driver(struct device_driver *drv)
{
    struct bus_type *bus;
    struct driver_private *priv;
    int error = 0;

    bus = bus_get(drv->bus);    //获取drv的bus tpye ,即bus为platform_bus_type
    if (!bus)
        return -EINVAL;

    pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name);

    priv = kzalloc(sizeof(*priv), GFP_KERNEL);                 //初始化driver_private *priv
    if (!priv) {
        error = -ENOMEM;
        goto out_put_bus;
    }
    klist_init(&priv->klist_devices, NULL, NULL);       //初始化drv结构体下的priv指针的dev设备列表
    priv->driver = drv;
    drv->p = priv;                                                     //这两句将priv结构体指针和drv联系在一起
    priv->kobj.kset = bus->p->drivers_kset;          

/* 指向bus的drivers_kset容器,该容器的作用与device_kset容器相同,前者是包含所
有注册到该bus的driver,后者是包含所有注册到该bus的device。*/


    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
                     "%s", drv->name);

//因为有上面的priv->kobj.kset = bus->p->drivers_kset;,所以这一句在/sys/bus/platform/drivers/下建立了"s3c2410-rtc"(drv->name)目录
    if (error)
        goto out_unregister;

    if (drv->bus->p->drivers_autoprobe) {     //因为在bus_register中有priv->drivers_autoprobe = 1;if会执行的
        error = driver_attach(drv);        //实际就是调用bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

//这个地方和bus_for_each_drv很是类似

//driver_attach-->bus_for_each_dev-->__driver_attach-->driver_probe_device-->really_probe
        if (error)
            goto out_unregister;
    }
    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);     //在bus的drivers列表上添加节点
    module_add_driver(drv->owner, drv);                                 //将driver添加到module模块,后面再看

    error = driver_create_file(drv, &driver_attr_uevent);

//生成/sys/bus/platform/drivers/s3c2410-rtc/uevent属性文件,其作用与device中的
uevent类似


    if (error) {
        printk(KERN_ERR "%s: uevent attr (%s) failed/n",
            __FUNCTION__, drv->name);
    }
    error = driver_add_attrs(bus, drv);

//添加bus的公有属性文件到/sys//sys/bus/platform/drivers/s3c2410-rtc/目录
    if (error) {
        /* How the hell do we get out of this pickle? Give up */
        printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",
            __FUNCTION__, drv->name);
    }
    error = add_bind_files(drv);

//如果配置了”CONFIG_HOTPLUG",则生成“bind”和"unbind”属性文件,可用于手动匹
配和移除 device与driver之间的关联,见下面的英文注释

/*
* Thanks to drivers making their tables __devinit, we can't allow manual
* bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
*/


    if (error) {
        /* Ditto */
        printk(KERN_ERR "%s: add_bind_files(%s) failed/n",
            __FUNCTION__, drv->name);
    }

    kobject_uevent(&priv->kobj, KOBJ_ADD);
    return error;
out_unregister:
    kobject_put(&priv->kobj);
out_put_bus:
    bus_put(bus);
    return error;
}

void module_add_driver(struct module *mod, struct device_driver *drv)
{
    char *driver_name;
    int no_warn;
    struct module_kobject *mk = NULL;

    if (!drv)
        return;

    if (mod)                    //因为设置了THIS_MODULE,所以执行
        mk = &mod->mkobj;
    else if (drv->mod_name) {
        struct kobject *mkobj;

        /* Lookup built-in module entry in /sys/modules */
        mkobj = kset_find_obj(module_kset, drv->mod_name);
        if (mkobj) {
            mk = container_of(mkobj, struct module_kobject, kobj);
            /* remember our module structure */
            drv->p->mkobj = mk;
            /* kset_find_obj took a reference */
            kobject_put(mkobj);
        }
    }

    if (!mk)
        return;

    /* Don't check return codes; these calls are idempotent */
    no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
 

//在/sys/bus/platform/drivers/s3c2410-rtc/目录下生成名为"module"的链接文件,指
向/sys/modules/rtc-s3c目录

  driver_name = make_driver_name(drv);

//将drv->bus->name和 drv->name组合在一起生成driver_name为platform:s3c2410-rtc
    if (driver_name) {
        module_create_drivers_dir(mk);     //生成/sys/modules/rtc-s3c目录下生成drivers目录
        no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
                        driver_name);

//在/sys/modules/rtc-s3c/drivers目录下生成名为“platform:s3c2410-rtc”的
链接文件,指向/sys/bus/platform/drivers/s3c2410-rtc/目录


        kfree(driver_name);
    }
}

这样driver就注册完成了。

你可能感兴趣的:(c,struct,function,Module,null,idempotent)