linux driver 
top

ローダブルモジュールの登録は、

#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 };

imported