pci子系統的關鍵概念包括:pci裝置、pci插槽、pci域、pci匯流排、pci橋、熱插拔控制器、
pci裝置探測流程
linux啟動過程中會呼叫pci核心的探測函式進行pci裝置的探測,並建立起相關的拓撲關係以及記錄每個探測到的裝置的資訊;探測採用遞迴的方式從根控制器開始逐級往下探測,遇到橋控制器則繼續探測隱藏在它下面的裝置,依次類推。
pci探測的介面函式包括:pci_scan_root_bus、pci_scan_bus
在追蹤pci裝置探測的流程之前先看一下pci_sys_data這個資料結構,這個資料結構記錄了pci探測過程中需要的各種資訊,沒有這個資料結構,pci探測將無法實現。另外對於每個pci控制器都有這樣乙個例項(顯而易見,不同的控制器相關資訊也不同)。
struct pci_sys_data
而pci_sys_data中的資訊又通過啟動時初始化由hw_pci來獲取,這個地方不知道為什麼要轉換一次?先不管這麼多,直接看hw_pci這個結構體,到底都有哪些成員。
struct hw_pci
看起來和pci_sys_data很類似,又仔細看了下**才發現hw_pci和pci_sys_data的區別。hw_pci記錄的是系統中總的和pci相關的資訊,而pci_sys_data是針對每個控制器都有乙個,記錄的是單個控制器的資訊。
看下hw_pci的成員吧,知道了它就知道了pci_sys_data。
domain:因為pci規範允許單個系統擁有高達256個匯流排,所以匯流排編號是8位。但對於大型系統而言,這是不夠的,所以,引入了域的概念,每個pci域可以擁有最多256個匯流排,每個匯流排上可支援32個裝置,而每個裝置上最多可有8種功能。
nr_controllers:系統已知的控制器數量
scan:掃瞄匯流排以探測裝置和獲取裝置資訊
preinit:初始化pci控制器的硬體,使軟體可以在後面順利的通過控制器探測裝置
postinit:大多數情況下都不需要它,既然裝置什麼的都探測到了,也就不需要再去初始化了吧
swizzle和map_irq:這裡涉及到pci中斷機制,pci規範在硬體上規定了4根int管腳,pci裝置的每種功能都可以任意連線到4根int管腳中的一根,當有多個功能連線到一根int管腳上時採用線與的方式。同時裝置的每種功能還有中斷線,用於在控制器那邊區別到底是哪種功能裝置產生了中斷,該值需要在裝置探測過程中進行初始化。swizzle將pci裝置的中斷管腳一級一級路由到根控制器的中斷管腳上,對於大多數pci橋來說中斷管腳路由遵循(((pin - 1) + slot) % 4) + 1的規律。呼叫swizzle之後得到了遠端的pci裝置對映到根控制器的中斷管腳,可以根據這個資訊給pci裝置分配主機可以識別的虛擬中斷線,然後把分配的中斷線寫入pci裝置的配置空間。
瞧,中斷線在這裡配置:
中斷在橋裝置上的路由一般遵循以下規律:
了解了hw_pci這個東東,我們再來看驅動核心具體是如何初始化pci裝置列表的。我們的解讀以arm平台作為分析的目標,在arm平台上呼叫驅動核心進行裝置探測的api是pci_common_init這個函式。
void __init pci_common_init(struct hw_pci *hw)
/** tell drivers about devices found.
*/pci_bus_add_devices(bus);
}}
linux驅動子系統 MTD
mtd是各種型別儲存裝置的抽象,是介於高層抽象和底層物理硬體之間的橋梁,它遮蔽了底層硬體的技術細節,對上層模組提供無差別的訪問控制。分析mtd部分的 就不難發現,mtd採用3層設計思路,最上面一層用於和塊裝置層對接 中間層是mtd實現,最底層是硬體驅動層。mtd下層註冊介面為mtd device r...
linux驅動子系統 SCSI
scsi初始化流程 1 首先如果驅動核心發現了1個scsi控制器,則呼叫scsi host alloc建立scsi中間層的代表例項 2 呼叫scsi add host新增建立的scsi例項到scsi中間層 3 呼叫scsi scan host掃瞄scsi控制器下面的scsi裝置 4 探測到的scsi...
linux驅動子系統之輸入子系統 5
5.總結 5.1 事件資訊的上報過程分析 l 上報的大致過程 裝置驅動層 核心層 事件處理層 應用層 l 具體呼叫的函式 以evdev為例 input event input handle event input pass event handle handler event handle,type...