platform驱动之probe函数

来源:互联网 发布:淘宝店铺简介 编辑:程序博客网 时间:2024/06/15 23:57

http://blog.csdn.net/gchww/article/details/7367718

驱动注册的probe函数


probe函数在设备驱动注册最后收尾工作,当设备的device 和其对应的driver 在总线上完成配对之后,系统就调用platform设备的probe函数完成驱动注册最后工作。资源、中断调用函数以及其他相关工作。下面是probe被调用的一些程序流程。

从driver_register看起:

[cpp] view plaincopy
  1. int driver_register(struct device_driver * drv)  
  2. {  
  3.     klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);  
  4.     init_completion(&drv->unloaded);  
  5.     return bus_add_driver(drv);  
  6. }  
klist_init与init_completion没去管它,可能是2.6的这个设备模型要做的一些工作。直觉告诉我要去bus_add_driver。

bus_add_driver中:
都是些Kobject 与 klist 、attr等。还是与设备模型有关的。但是其中有一句:
driver_attach(drv);
单听名字就很像:
[cpp] view plaincopy
  1. void driver_attach(struct device_driver * drv)  
  2. {  
  3.     bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  
这个熟悉,遍历总线上的设备并设用__driver_attach。
在__driver_attach中又主要是这样:
driver_probe_device(drv, dev);
跑到driver_probe_device中去看看:
有一段很重要:
if (drv->bus->match && !drv->bus->match(dev, drv))
goto Done;
明显,是调用的驱动的总线上的match函数。如果返回1,则可以继续,否则就Done了。
继承执行的话:
[cpp] view plaincopy
  1. if (drv->probe)  
  2.     ret = drv->probe(dev);  
  3. if (ret) {  
  4.     dev->driver = NULL;  
  5.     goto ProbeFailed;  
  6. }  
只要probe存在则调用之。至此就完成了probe的调用。

这个过程链的关键还是在drv->bus->match ,因为其余的地方出错的话就是注册失败,而只要注册不失败且match返回1,那么就铁定会调用驱程的probe了。你可以注册一个总线类型和总线,并在 match中总是返回 1, 会发现,只要struct device_driver中的bus类型正确时,probe函数总是被调用.

有两个重要的链表挂在bus上,一个是设备device链表,一个是驱动driver链表。

每当我们向一根bus注册一个驱动driver时,套路是这样的:

driver_register(struct device_driver * drv) -> bus_add_driver() -> driver_attach() ->

bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

bus_for_each_dev遍历该总线上所有的device,执行一次__driver_attach(),看能不能将驱动关联(attach)到某个设备上去。

__driver_attach()

->driver_probe_device()

->drv->bus->match(dev, drv), // 调用bus的match函数,看device和driver匹不匹配。如果匹配上,

继续执行really_probe()。

->really_probe()

->driver->probe()。(如果bus->probe非空,则调用bus->probe)

而每当我们向一根bus添加一个硬件时时,套路是这样的:

device_add()

\\ device_add 中有很多操作kobject,注册sysfs,形成硬件hiberarchy结构的代码。

如果您忘记了,先回头去参考参考"我是sysfs"

->bus_attach_device() -> device_attach() ->bus_for_each_drv()

bus_for_each_drv与bus_for_each_dev类似,遍历该总线上所有的driver,执行一次__device_attach(),看能不能将设备关联(attach)到某个已登记的驱动上去。

__device_attach()

->driver_probe_device() //后面与上面一样

总结一些,一句话,注册一个某个bus的驱动就是先把驱动自己链入到bus驱动链表中去,在从bus的设备链表中一一寻找,看有没有自己可以关联上的设备。找到就probe,再把二者bind起来。反之,添加设备道理也是一样的。


论坛讨论帖:

1. 在看platform驱动是,发现一个很低能的问题,static int __devinitdm9000_probe(struct platform_device *pdev) 中的struct platform_device *pdev是从那里来的device,跟踪platform_driver_register(&dm9000_driver);一直没有发现platform_device的出现,但是现在probe函数中突然出现了这个变量,那么这个变量是从和而来?

2. platform驱动分为platform_driver和platform_device两个结构体表示,前者表示平台驱动,后者表示平台设备,这个struct platform_device *pdev就是在平台相关文件里注册的。平台下会定义一个platform_device,然后platform_device_register(&platform_device),所以你注册的平台驱动,当在platform_bus上探测到有个设备的时候,这个你之前在平台文件里注册的platform_device就会传过来。

3. "platform_bus上探测到有个设备的时候"此句怎么理解,是怎么探测到的呢?

4. 驱动肯定是自己注册了。至于设备的注册,有些设备所使用的协议有枚举过程,从这处过程中可以得到设备信息,进而生成相应设备结构体,然后注册在相应总线上。

在总线上注册设备时,会遍历该总线上已注册的驱动,用总线的match方法判断是否有匹配的驱动,如果有,则调用驱动的probe函数;在总线上注册驱动时,会遍历该总线上已注册的设备,用总线的match方法判断是否有匹配的设备,如果有,则调用驱动的probe函数。即,不管是先注册设备还是先注册驱动,总线的match方法会作用于所有组合,如果匹配了,则调用驱动的probe方法,这样就探测到了。

platform_bus是虚拟的总线,没有具体的协议。上面所讲设备的结构体是在枚举时动态生成的,设备的注册也是在枚举时触发的,而platform_device的定义与注册是在平台初始化文件里手动做的。后面的情况就是一样的了。其它一些没有类似枚举之类过程的总线,如I2C,也是这种流程。

5. 内核启动的时候, platform_device 是优先于 platform_driver 注册的。 比如 platform_device A , 是在arch/arm/mach-XXXX/mach-XXXX.c 文件里注册的, 而这个文件的代码是 优先于 platform_driver_register 执行的。
所以在你platform_driver_register执行的时候, platform_device A已经被挂在platform_bus总线上了, 而platform_driver_register()有个功能是到platform_bus上去挨个找寻,找寻挂在上面的platform_bus上的platform_device。找到了就执行probe()。

6. 可不可以这样,我没有试过。
但是因为驱动中有 开发者实现的 probe 函数。 如果先注册驱动, 驱动就找不到设备, 从而不执行probe函数,而驱动中最重要的就是probe函数,硬件的初始化,寄存器的配置,时钟的使能都在probe函数里完成。从这一点来说,驱动先于设备注册,应该不可行。

7. 你好,关于I2C驱动,目前有三个问题想请教下:   
    1,请问用i2c_add_driver注册I2C的client端的驱动的时候,这个client是怎么和哪个adapter attach的(在此之前,系统中注册了四个bit-style的adapter)?注意,我的i2c_driver中,并没有赋值attach_adapter,但是赋值了probe
    2,注册adapter是用的 i2c_add_adapter,跟了下这个函数,发现它call的是->i2c_register_adapter->
                                   adap->dev.bus = &i2c_bus_type;
                           adap->dev.type = &i2c_adapter_type;
                           res = device_register(&adap->dev);
          这里是注册的是一个device,那么根据device-driver的模型,那adapter的driver是怎么被赋值的呢?
   3,i2c_add_driver是向哪跟总线上注册的,是i2c_bus_type吗?i2c_register_adapter又是向哪跟总线注册的呢? 也是i2c_bus_type吗?
   谢谢

8. i2c_driver并不是要跟adapter绑定,而是要和i2c_client绑定 。注册一个i2c_driver时并不知道它支持的设备在哪条总线上。例如一个系统有两个i2c控制器,每个控制器上有一个相同型号的EEPROM,它们只需一个i2c_driver。关键在于如何发现哪条总线上有i2c_driver所支持设备。

老I2C框架里,由i2c_driver负责发现设备,每注册一个adapter遍历已注册i2c_driver,每注册一个i2c_driver遍历已注册的i2c_adapter,不让他们错过任何一次组合,让i2c_driver在adapter上探测一下是否有它支持的设备,如果有,则生成一个i2c_client实例。当然由于i2c协议很弱,这种探测很不可靠。

现在(尤其在SOC系统中)倾向于静态定义这些信息:如果我知道哪条总线上有哪个设备,我就犯不着让i2c_driver去找它们了。于是在平台初始化函数里注册i2c_board_info,这个结构体就是一个i2c_client模板。i2c_board_info里有个bus_num作为匹配的凭证,如果bus_num与i2c_adapter的bus_num相同,那就匹配上了。所有注册的i2c_board_info会放在一个链表里,每注册一个i2c_adapter就去扫描这个链表,如果匹配就生成i2c_client。

在老框架,i2c_client肯定是在i2c_driver时调用attach_adapter时出现的;新框架里则可以在没有i2c_driver的情况下根据静态信息生成i2c_client。另外让i2c_driver探测设备时,顶多能知道设备地址,而欲查询设备其它属性,i2c协议里没有通用的方法。而i2c_board_info静态了提供了这些属性。 

而对于旧框架,新框架一方面在接口上保持兼容,另一方面在功能上也有更新。新框架里通过bus_num来区别是扫描静态的i2c_board_info链表。如果不是,那就又归到老式的方法:让i2c_driver去找设备。这个过程跟上面讲的老框架的过程一样,添加adapter或者driver时相互遍历已注册的对方。新方法里有个i2c_detect,看起来是把以前散落在各个i2c_driver->attach_adapter中的代码抽象出来了,最后再调用i2c_driver->detect,这个的功能应该和i2c_driver->attach_adapter是一样的。只不过它只负责是否检测到驱动支持的设备,而i2c_client的生成则放在外面框架代码里了。最后再调用i2c_driver->attach_adapter,兼容旧驱动。注释里说这个方法以后可能会消失。其实在SOC系统里,一般到静态扫描就完了,也不会去调用detect方法。

不管通过什么方法生成i2c_client,注册它后,下面就是经典设备模型里的match/probe了。

i2c_driver与i2c_adapter都是注册在i2c_bus_type上,至于i2c_adapter的driver,我以前看代码时也没找着。现在看来,它根本没有另一半。其实看i2c_bus_type->match方法,它是通过i2c_verify_client把device转成i2c_client的,这里只验证device->type是不是i2c_client_type,也就是说,这条总线根本没准备为i2c_adapter匹配任何东西

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 遇到尴尬的事情自己缓不过来怎么办 注销微信账号显示非法请求怎么办 微信备份以前的被覆盖了怎么办 之前微信号被新微信号覆盖了怎么办 微信发出的消息变成绿色怎么办 收了客户的资金被骗走了怎么办 淘宝退回去的衣服店家不接收怎么办 淘宝同款衣服价格相差很大该怎么办 淘宝买的衣服退回去了不退钱怎么办 淘宝客人退回的衣服有口红印怎么办 淘宝拍产品照片被投诉著作权怎么办 员工总在节假日忙的时候请假怎么办 买东西商家少给了货应该怎么办 买家退回的衣服有污渍卖家该怎么办 商家说衣服有污渍不退怎么办 退回商家换货不给寄应怎么办 毕业照跟拍摄影师拍砸了怎么办 韵达快递寄快递快递单号丢了怎么办 韵达快递把我的户口本弄丢了怎么办 淘宝卖家发货与实际货物不符怎么办 寄出去的快递不知道物流单号怎么办 淘宝买家所需要的货物填错怎么办 淘宝卖家顾客拒绝签收货要怎么办 闲鱼买家申请退货退款不发货怎么办 在闲鱼买东西买家恶意退货怎么办 淘宝卖家给的退货地址是国外怎么办 淘宝顾客下单了一件代发怎么办 闲鱼上卖东西快递单号填错了怎么办 淘宝收货后快递显示不签收怎么办 淘宝快递显示签收但没收到货怎么办 国外客人收到货后嫌弃质量差怎么办 理发15涨到20客人少了怎么办 微店买家收到货了又退款怎么办 百世快递单号查不到物流信息怎么办 知道快递单号怎么查物流信息怎么办 快递单号一直查不到物流信息怎么办 买家未收到货就发起仅退款怎么办 拼多多收货码短信没了怎么办 淘宝运费险快递单号填错怎么办 如果淘宝小二判定退款不同意怎么办 商品退回卖家电话关机不收货怎么办