注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

Linux MTD子系统学习6—MTD设备的注册及流程之一  

2012-01-12 21:22:52|  分类: LINUX内核驱动 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

Linux MTD子系统学习6—MTD设备的注册及流程之一

一直在讲PROBE的过程,在这个过程发现了一些问题,就是这些设备中一些设备的资源如何得来的,一些数据结构体如res  = pdev->resource;的值从哪里进行设置的,他们是怎么被动态加载到内存中,又怎么和driver取得了联系,虽然这个系列的博文主要是讲驱动,但设备device是无法和driver割裂开来的。

转到正题,今天插播这一段来龙去脉,可能理解的还是不太深入,有BUG或讲得模糊的地方希望大家能指出来,互相学习,共同进步。

不厌其烦从下面的函数开始,很熟悉吧,正是s3c2410.c中的注册过程:

s3c2410_nand_init()-àplatform_driver_register()--àbus_add_driver()àdriver_attach()àbus_for_each_dev()-à__driver_attach()-àdriver_probe_device()-àreally_probe()。

在这个函数里调用:

         if (dev->bus->probe) {

                   ret = dev->bus->probe(dev);

                   if (ret)

                            goto probe_failed;

         } else if (drv->probe) {

                   ret = drv->probe(dev);

                   if (ret)

                            goto probe_failed;

         }

在platform_driver_register()这个函数里,(调用过程如下 )

static int __init s3c2410_nand_init(void)

{

         printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");

 

         return platform_driver_register(&s3c24xx_nand_driver);

}

然后:

int platform_driver_register(struct platform_driver *drv)

{

         drv->driver.bus = &platform_bus_type;

         if (drv->probe)

                   drv->driver.probe = platform_drv_probe;//重点在这儿

         if (drv->remove)

                   drv->driver.remove = platform_drv_remove;

         if (drv->shutdown)

                   drv->driver.shutdown = platform_drv_shutdown;

 

         return driver_register(&drv->driver);

}

看到第一行:drv->driver.bus = &platform_bus_type;

跳过去:

struct bus_type platform_bus_type = {

         .name                = "platform",

         .dev_attrs        = platform_dev_attrs,

         .match               = platform_match,

         .uevent              = platform_uevent,

         .pm           = &platform_dev_pm_ops,

};

在跳到struct bus_type这个结构体来看:

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);

         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 (*resume)(struct device *dev);

 

         const struct dev_pm_ops *pm;

 

         struct bus_type_private *p;

};

发现了吧,这里面的probe这个函数指针,在上面的数据结构里并没有赋值,也就是说在最前面的if语句的判断里,程序会调用:else if 中的drv->probe(dev),而这个函数我们在以前已经介绍过了,被赋值给了:s3c24xx_nand_probe这个函数指针。

在int platform_driver_register(struct platform_driver *drv)有下面的这段代码: 

if (drv->probe)

                   drv->driver.probe = platform_drv_probe;

 

而在前面分析过,这个platform_drv_probe这个函数会返回s3c24xx_nand_probe这个函数指针,也就是说把platform_driver结构体中的probe函数注册到了device_driver中的probe函数中。这样就明白了吧。

犯了一个天大的最简单的错误,唉,把if (drv->probe)当成了判断互斥性赋值,其实是判断其真就把这个函数注册到驱动的probe中去。

谦虚谨慎,谦虚谨慎。

  评论这张
 
阅读(808)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017