linux driver
ローダブルモジュールの登録は、
#ifdef MODULE
module_init(tridentfb_init);
#endif
tridentfb_init()に実体がある。
int __init tridentfb_init(void)
{
output("Trident framebuffer %s initializing\n", VERSION);
return pci_module_init(&tridentfb_pci_driver);
}
- この__initはなんだろう?
- output()でコンソールに出力できる。printf式のフォーマッティングもできるようだ。 pci_module_init()でPCIのデバイスを検出する設定を行う?
1434 static struct pci_driver tridentfb_pci_driver = {
1435 name:"tridentfb",
1436 id_table:trident_devices,
1437 <font color="red">probe:trident_pci_probe</font>,
1438 remove:__devexit_p(trident_pci_remove),
1439 };
pci_module_init()に渡される設定は上記の構造体に書かれている。probeが注目すべきもので、ここで、trident_pci_probe()が何らかのタイミングで呼ばれることが分かる。
include/linux/pci.h
683 /*
684 * a helper function which helps ensure correct pci_driver
685 * setup and cleanup for commonly-encountered hotplug/modular cases
686 *
687 * This MUST stay in a header, as it checks for -DMODULE
688 */
689 static inline int pci_module_init(struct pci_driver *drv)
690 {
691 int rc = <FONT COLOR="red">pci_register_driver (drv)</FONT>;
692
693 if (rc > 0)
694 return 0;
695
696 /* iff CONFIG_HOTPLUG and built into kernel, we should
697 * leave the driver around for future hotplug events.
698 * For the module case, a hotplug daemon of some sort
699 * should load a module in response to an insert event. */
700 #if defined(CONFIG_HOTPLUG) && !defined(MODULE)
701 if (rc == 0)
702 return 0;
703 #else
704 if (rc == 0)
705 rc = -ENODEV;
706 #endif
707
708 /* if we get here, we need to clean up pci driver instance
709 * and return some sort of error */
710 pci_unregister_driver (drv);
711
712 return rc;
713 }
714
715 #endif /* !CONFIG_PCI */
要するにpci_register_driver(drv)が主な作業。
pci_register_driver(drv)は、
651 /**
652 * pci_register_driver - register a new pci driver
653 * @drv: the driver structure to register
654 *
655 * Adds the driver structure to the list of registered drivers
656 * Returns the number of pci devices which were claimed by the driver
657 * during registration. The driver remains registered even if the
658 * return value is zero.
659 */
660 int
661 pci_register_driver(struct pci_driver *drv)
662 {
663 struct pci_dev *dev;
664 int count = 0;
665
666 list_add_tail(&drv->node, &pci_drivers);
667 pci_for_each_dev(dev) {
668 if (!pci_dev_driver(dev))
669 count += pci_announce_device(drv, dev);
670 }
671 return count;
672 }
多分、まだドライバが設定されていないPCIデバイスについて、pci_announce_device()を実行する。
626 static int
627 <FONT COLOR="red">pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)</FONT>
628 {
629 const struct pci_device_id *id;
630 int ret = 0;
631
632 if (drv->id_table) {
633 id = pci_match_device(drv->id_table, dev);
634 if (!id) {
635 ret = 0;
636 goto out;
637 }
638 } else
639 id = NULL;
640
641 dev_probe_lock();
642 if (<FONT COLOR="red">drv->probe(dev, id)</FONT> >= 0) {
643 dev->driver = drv;
644 ret = 1;
645 }
646 dev_probe_unlock();
647 out:
648 return ret;
649 }
対応するデバイスが見つかった場合は、drv->probe()でデバイスドライバのコードが実行される。その作業は、セマフォを使って排他制御された状態で行われる。dev_probe_lock()とdev_probe_unlock()。さっきみたtridentfbの場合だと、drv->probe()は、trident_pci_probe()なので、これがここで呼ばれる。
1434 static struct pci_driver tridentfb_pci_driver = {
1435 name:"tridentfb",
1436 id_table:trident_devices,
1437 probe:trident_pci_probe,
1438 remove:__devexit_p(trident_pci_remove),
1439 };
