Linux那些事兒 之 我是PCI(4)初始化(一)
解析完了PCI的那些核心引數,再翻過多少座山跨過多少條河,核心就會遇到init/main.c裡一個名叫do_initcalls的函式。do_initcalls對核心來說只不過是漫長冒險旅程中的一個驛站,對PCI這個故事來說卻是命運轉輪的開始,核心在它裡邊完成了對.initcall.init節裡各種xxx_initcall函式的執行,PCI的那些自然也包括在內。你不用像新東方老羅“我走來走去,為中國的命運苦苦思索。”那樣走來走去為PCI的命運思索,因為決定PCI命運的那些xxx_initcall早列在之前的那張表裡了,也不用你再去驀然回首,這裡會再貼一遍。
檔案 | 函式 | 入口 | 記憶體位置 |
arch/i386/pci/acpi.c | pci_acpi_init | subsys_initcall |
.initcall4.init |
arch/i386/pci/common.c | pcibios_init | subsys_initcall | .initcall4.init |
arch/i386/pci/i386.c |
pcibios_assign_resources |
fs_initcall | .initcall5.init |
arch/i386/pci/legacy.c | pci_legacy_init | subsys_initcall | .initcall4.init |
drivers/pci/pci-acpi.c | acpi_pci_init | arch_initcall | .initcall3.init |
drivers/pci/pci- driver.c | pci_driver_init | postcore_initcall | .initcall2.init |
drivers/pci/pci- sysfs.c | pci_sysfs_init | late_initcall | .initcall7.init |
drivers/pci/pci.c | pci_init | device_initcall | .initcall6.init |
drivers/pci/probe.c | pcibus_class_init | postcore_initcall | .initcall2.init |
drivers/pci/proc.c | pci_proc_init | __initcall | .initcall6.init |
arch/i386/pci/init.c | pci_access_init | arch_initcall | .initcall3.init |
atmdmagraphicshwmoni2c-adapterinput
memmiscnetpci_busscsi_devicescsi_disk
scsi_hostsoundspi_hostspi_masterspi_transporttty
usb_deviceusb_endpointusb_hostvcvtconsole
想當初,usb子系統初始化的時候,呼叫了一次class_create(THIS_MODULE, "usb_host"),然後上邊兒就多了一個usb_host目錄,那麼現在呼叫這個class_register,上邊兒又會多出什麼?這個大家一眼就能看出來,即使一眼看不出來兩眼也能看出來了,賺錢買豬肉的本事沒有,尋找這種敏感地帶的本事還都是有的,憑空多出來的就是那個pci_bus。從這點兒看,create還是register對咱們來說都差不多,都是在/sys/class下邊兒建立了一個類,usb_host類的目錄裡是各個具體的主機控制器,pci_bus類的目錄裡對應的就是各個pci匯流排了。本來難得糊塗一下明白這些就成了,不過如果真想稍微不那麼糊塗一點兒,可以去掃兩眼class_create的定義,你就會發現它裡面最終也會呼叫一個class_register,這兩個的差別就是class_create要更傻瓜一些,你指定個類的名稱就可以呼叫它了,它裡面會幫你建立一個struct class結構體,而class_register則更費事一些,你需要自己親自動手建立一個struct class結構體。如果你覺得自己挺特殊,需要指定自己的release函式等,那就必須得使用class_register了,PCI就屬於這種情況,至於它怎麼個特殊,就是後話了。
pcibus_class_init之後,接著就應該是pci_driver_init
還記得linux裝置模型裡存在於匯流排、裝置、驅動之間的那個著名的三角關係麼?如果不記得,那就先聽俺講個小故事:
話說多少年以前有個人非常的健忘,他老婆很無奈,就對他說:“聽說南村的誰誰誰專治女性不孕男性健忘,你還是去找他醫一下吧!” 好男人準則第一條就是要聽老婆的話,於是這個人就背上弓箭,騎上馬出發了。人不是都有三急麼,半道兒上他想大便,就把馬拴在一棵大樹上,躲在樹後,順手把箭插在地上。方便過後,正在順爽,順爽,一順再順,順出新自我,忽然看見了地上的箭,驚出了一身冷汗,“好險,不知誰射來的箭,差點要了我的小命!”緊趕的往外跑,一腳踩在大便上,不禁連皺眉頭,大罵不已:“誰這麼缺德,不講公共衛生,在這裡隨地大小便……”。等到看到拴在樹上的馬,又高興起來,心想:雖然吃了點兒苦頭,撿到一匹馬著實得美,就像金帝美滋滋巧克力,全新的色彩,全新的味道。於是他騎上馬暈暈乎乎不知所之,沿著原路折了回去。一邊想著我這是在哪兒呢,一邊瞧見了一座房子。“咦,這房子好生面熟?……”這個時候,他老婆正從屋裡看見他糊里糊塗的樣子,氣不打一處來,出門兒來責備他。只見他不卑不亢的作了一個揖,說:“這位大嫂,你我素昧平生,何苦出言不遜?”
這個故事的教育意義就在於告訴我們健忘是一種病態,善忘是一種境界,做人不能健忘到如此地步。那個三角關係中的匯流排落實在USB就是usb_bus_type,落實在PCI就是上面的pci_bus_type,pci_driver_init函式的目的就是註冊PCI匯流排,只有匯流排存在了,才會有裝置的那條連結串列和驅動的那條連結串列,才會有裝置和驅動之間的match。