linux IDE驱动分析之总线枚举

总线枚举

[/linux/driver/ide/Ide.c]

155 struct bus_type ide_bus_type = {

156 .name = "ide",

157 .match = ide_bus_match,

158 .uevent = ide_uevent,

159 .probe = generic_ide_probe,

160 .remove = generic_ide_remove,

161 .shutdown = generic_ide_shutdown,

162 .dev_attrs = ide_dev_attrs,

163 .suspend = generic_ide_suspend,

164 .resume = generic_ide_resume,

165 };

前一节我们已经讲到,如果设备注册,将引发相应的总线发生machprobe等动作。那么对应到ide-bus-type也就是157159行。

157mach方法对应的函数为ide_bus_mach。来看一下源程序:

[/linux/driver/ide/Ide.c]

112 static int ide_bus_match(struct device *dev, struct device_driver *drv)

113 {

114 return 1;

115 }

这个函数简单的让人难以想象.

159probe方法对应的函数为generic_ide_probe。源代码如下:

[/linux/driver/ide/Ide.c]

127 static int generic_ide_probe(struct device *dev)

128 {

129 ide_drive_t *drive = to_ide_device(dev);

130 struct ide_driver *drv = to_ide_driver(dev->driver);

131

132 return drv->probe ? drv->probe(drive) : -ENODEV;

133 }

表面上看这个函数复杂不到哪去,但谁又知道单纯的她背后又藏着什么不可告人的秘密呢。这个函数的重点在132行,从ide_driver结构中我们不难得出这是个ide接口所对应的驱动,他实际上就是调用ide_driverprobe来进行枚举。在之前的分析中我们尚未发现这个ide-driver的相关的内容,而是一直在做drive方面的工作。这从设备模型的角度上来讲也就是是为了实现device的注册,至始至终并未涉及到device_driver相关的设置。基于device_driver在设备模型中的重要地位,这里,跟踪相应的device_driver的注册过程就成了当务之急,当然弄清了device_driver的注册也就很容易看出这个ide_driver的真实身份。

在详细了解device_driver的注册过程之前,我们先来聊点题外话。前面我们说过,每当一个设备或者驱动注册到系统中来的时候,都会调用相应总线的machprobe方法,这句话好像重复了千遍了,估计以后还会讲到。回顾前面的例子,当ide_generic设备注册进来以后,我们转到了对总线中probe的分析,然后遇到了dev->driver这个bug。因为在前面的代码中,还尚未对他进行赋值。那么是否真的132行就会因为drv->probe=NULL,而提前返回-ENODEV夭折了呢?其实答案并非如此,详细跟踪device_register的代码我们可以发现,当设备注册进来的时候,总线会为该设备寻找总线上所挂接的每一个设备驱动,并且最终调用一个叫做really_probe(),极为性感的函数。性感到什么程度我们不妨贴出他的部分内容片段。

104 static int really_probe(struct device *dev, struct device_driver *drv)

105 {

106 int ret = 0;

107

108 atomic_inc(&probe_count);

109 pr_debug("bus: '%s': %s: probing driver %s with device %s/n",

110  drv->bus->name, __func__, drv->name, dev_name(dev));

111 WARN_ON(!list_empty(&dev->devres_head));

112

113 dev->driver = drv;

114 if (driver_sysfs_add(dev)) {

115 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",

116 __func__, dev_name(dev));

117 goto probe_failed;

118 }

119

120 if (dev->bus->probe) {

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

122 if (ret)

123 goto probe_failed;

124 } else if (drv->probe) {

125 ret = drv->probe(dev);

126 if (ret)

127 goto probe_failed;

128 }

129

130 driver_bound(dev);

131 ret = 1;

132 pr_debug("bus: '%s': %s: bound device %s to driver %s/n",

133  drv->bus->name, __func__, dev_name(dev), drv->name);

134 goto done;

135

136 probe_failed:

137 devres_release_all(dev);

138 driver_sysfs_remove(dev);

139 dev->driver = NULL;

140

141 if (ret != -ENODEV && ret != -ENXIO) {

142 /* driver matched but the probe failed */

143 printk(KERN_WARNING

144        "%s: probe of %s failed with error %d/n",

145        drv->name, dev_name(dev), ret);

146 }

147 /*

148  * Ignore errors returned by ->probe so that the next driver can try

149  * its luck.

150  */

151 ret = 0;

152 done:

153 atomic_dec(&probe_count);

154 wake_up(&probe_waitqueue);

155 return ret;

156 }

毫无悬念,113 dev->driver = drv揭开了我们之前的种种困惑。也就是这个时候devicedevice_driver发生了关系,但是我可以很严肃的告诉你这是一种极其不负责任的做法。因为这时的device_driver还并未接受时间以及任何probe的考验,是否真是device命中注定的那个她,还不一定。接下来就是共同经历风雨的时候了,便调用了总线的probe函数,如果总线没有probe就调用驱动本身的,而我们这里就是通过总线的probe来调用的驱动的probe方法。当然如果一路走来,两个人都彼此心心相惜,那么就领证也就是130 driver_bound(dev);。当然天下没有这么好的美事,随便拉来的一个device_driver就成了他梦寐以求的白雪公主。现代社会讲究一夫一妻,linux也不例外,而且每个device也只可能对应到总线上唯一一个device_driver,那么刚才说的这种不负责任的做法是很有肯能goto probe_failed的,那么随来为这段该死的错误埋单了呢,当然就到了139dev->driver = NULL;,然后他们就彻底分手了。然后device又开始寻找新的device_driver,当然我们不能和他学,这也太不负责了。直到找遍了总线上所有的device_driver都没有找到能相守到老的那儿她,这时候device才明白。哦,原来自己生命生命中的另一半还未成来到这个世界,那么就只好等待,等待在等待.

看完这段颇像现代都市迷乱恋情的代码,才深深感觉到linux更像一部经典的言情小说。Linux作者的文学造诣远远高于他的C语言功底。说不准N年后又被某个导演相中了拍成电影,或许能流传千古.

好了言归正传,说了那么多联系到我们现在的这种情景的话,gendev所对应的驱动还尚未注册。所以probe失败也就是在所难免的了。好接下来的时间就到了device_driver表演的时候了.

你可能感兴趣的:(linux,工作,list,null,ide,语言)