ハードウェアを意識したプログラミングの基礎(後編)
ここでは,デバイス・ドライバが持っていない関数を,platformドライバで補完しています.補完が終わったらdriver_register()を呼びます(リスト14).
153: int driver_register(struct device_driver * drv)
154: {
155: if ((drv->bus->probe && drv->probe) ||
156: (drv->bus->remove && drv->remove) ||
157: (drv->bus->shutdown && drv->shutdown)) {
158: printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
159: }
160: klist_init(&drv->klist_devices, NULL, NULL);
161: return bus_add_driver(drv);
162: }
driver_register()では,デバイス・ドライバについて必要な関数を持っているかどうかをチェックします.その後,bus_add_driver()でバスにデバイス・ドライバを追加します(リスト15).
629: int bus_add_driver(struct device_driver *drv)
630: {
631: struct bus_type * bus = bus_get(drv->bus);
632: int error = 0;
633:
634: if (!bus)
635: return -EINVAL;
636:
637: pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
638: error = kobject_set_name(&drv->kobj, "%s", drv->name);
639: if (error)
640: goto out_put_bus;
641: drv->kobj.kset = &bus->drivers;
642: error = kobject_register(&drv->kobj);
643: if (error)
644: goto out_put_bus;
645:
646: if (drv->bus->drivers_autoprobe) {
647: error = driver_attach(drv);
bus.cの646行目のバスの設定が自動的にデバイスを見つけるようになっている場合,driver_attach()を呼び出します.この関数の中でデバイス・ドライバは自分が知っているデバイスが既にバスに登録されているかどうかを調べ始めます(リスト16).
279: int driver_attach(struct device_driver * drv)
280: {
281: return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
282: }
drv->busで指定されたバスに登録されているデバイスの一つ一つに対し,__driver_attach()を呼び出します(リスト17).
244: static int __driver_attach(struct device * dev, void * data)
245: {
246: struct device_driver * drv = data;
247:
:
258: if (dev->parent) /* Needed for USB */
259: down(&dev->parent->sem);
260: down(&dev->sem);
261: if (!dev->driver)
262: driver_probe_device(drv, dev);
セマフォで必要なロックをかけた後,デバイスがデバイス・ドライバを指定していない場合に,そのデバイスを調べます(リスト18).
186: int driver_probe_device(struct device_driver * drv, struct device * dev)
187: {
188: int ret = 0;
189:
190: if (!device_is_registered(dev))
191: return -ENODEV;
192: if (drv->bus->match && !drv->bus->match(dev, drv))
193: goto done;
調べ方はバスに依存します.バスが提供しているmatch()が呼ばれ,matchしなければ終了です.platformbusの場合,platform.cで定義されている platform
_match()が使われます(リスト19).
557: static int platform_match(struct device * dev, struct device_driver * drv)
558: {
559: struct platform_device *pdev = container_of(dev, struct platform_device, dev);
560:
561: return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
562: }