Linux驅動學習 初識PCI驅動 一

2021-10-17 19:26:16 字數 2840 閱讀 3334

pci是什麼

pci—peripheral component interconnect,外圍裝置互**線。是一種廣泛採用的匯流排標準,它提供了許多優於其它匯流排標準(如eisa)的新特性,目前已經成為計算機系統中應用最為廣泛,並且最為通用的匯流排標準。

對於pci的一些具體介紹可以參考: pci具體介紹

一、和pci驅動程式相關的幾個資料結構

驅動程式總是離不開資料結構,在linux中,用資料結構來表示各色各樣的裝置或者其他的東西。因此,我們掌握裝置驅動程式的關鍵之一,就是對各種資料結構的理解和運用。

cpu 可以訪問pci裝置上的所有位址空間,其中i/o空間和儲存空間提供給裝置驅動程式使用,而配置空間則由linux核心中的pci初始化**使用,核心在 啟動時負責對所有pci裝置進行初始化,配置好所有的pci裝置,包括中斷號以及i/o基址,並在檔案/proc/pci中列出所有找到的pci裝置,以 及這些我裝置的引數和屬性。

我們並不需要去了解配置暫存器的所有位代表了什麼,有什麼含義。我們只要用三個或者五個pci暫存器去標識乙個裝置即可。通常,我們會選擇下面三個暫存器:

vendorid: 標識硬體製造商,是乙個16位的暫存器;

deviceid:裝置id,由製造商選擇,也是乙個16位的暫存器。一般與廠商id配對生成乙個唯一的32位硬體裝置識別符號;

class:每個外部裝置屬於某個類(class),也是乙個16位的暫存器。當某個驅動程式可支援多個相似的裝置,每個具有不同的簽名,但都屬於同乙個類,這時,就可以用class類對它們的外設進行識別。

下面的資料結構就是–pci_device_id。

struct pci_device_id 

;

那現在問題又來了,我們前面說過,乙個驅動程式可以匹配乙個甚至多個裝置。那麼,此時我們又該如何呢?可以想到陣列,對吧。是的,不過這裡有點地方需要注意

staticstruct pci_device_id example_pci_tbl [

] __initdata =,}

;

不管你這裡匹配了多少裝置,記得最後乙個都是。

這裡還有兩個關於初始化該結構體的巨集,可以用來簡化相關的操作。

pci_device(vendor, device)

建立乙個僅和特定廠商及裝置id相匹配的struct pci_device_id。它把結構體的subvendor和subdevice設為pci_any_id。pci_any_id定義如下:

#define pci_any_id(~

0)

pci_device_class(device_class, device_class_mask)

建立乙個和特定pci類相匹配的struct pci_device_id。

2.pci_driver:

按照上面說的,你已經將你要匹配的裝置說明了,但這僅僅只是說明,核心如何去識別它們呢?那就要用到下面的資料結構了–pci_driver。

struct pci_driver 

;

從上面的結構體定義可以看出,它的作用並不僅僅是識別裝置的id_table結構,還包括了檢測裝置的 函式probe( )和解除安裝裝置的函式remove( ):這種結構體。

/*

* the pci_dev structure is used to describe pci devices.

*/struct pci_dev

; struct pci_ats *ats;

/* address translation service */

#endif

};

由上面的定義可以知道,它詳細描述了乙個pci裝置幾乎所有的硬體資訊,包括廠商id、裝置id、各種資源等。

二、基本框架

上面將我們要用到的一些基本資訊都做了一些簡單的介紹。下面,我們就來看看pci驅動程式的乙個基本的框架,如何將這些東西進行整理成乙個程式。

staticstruct pci_device_id example_pci_tbl [

] __initdata =,}

;/* 對特定pci裝置進行描述的資料結構 */

struct example_pci

/* 中斷處理模組 */

staticvoid example_interrupt

(int irq,

void

*dev_id,struct pt_regs *regs)

/* 裝置檔案操作介面 */

staticstruct file_operations example_fops =

;/* 裝置模組資訊 */

staticstruct pci_driver example_pci_driver =

; staticint __init example_init_module

(void

) staticvoid __exit example_cleanup_module

(void

)/* 載入驅動程式模組入口 */

module_init

( example_init_module)

;/* 解除安裝驅動程式模組入口 */

module_exit

( example_cleanup_module)

;

上面這段**給出了乙個典型的pci裝置驅動程式的框架,是一種相對固定的模式。

Linux驅動學習 初識PCI驅動 二

寫在前面的話 我們從下面幾個方面來講述 一,初始化裝置模組 當linux 核心啟動並完成對所有 pci裝置進行掃瞄 登入和分配資源等初始化操作的同時,會建立起系統中所有 pci裝置的拓撲結構,此後當 pci驅動程式需要對裝置進行初始化時,一般都會呼叫如下的 static int init examp...

linux驅動子系統 PCI

pci子系統的關鍵概念包括 pci裝置 pci插槽 pci域 pci匯流排 pci橋 熱插拔控制器 pci裝置探測流程 linux啟動過程中會呼叫pci核心的探測函式進行pci裝置的探測,並建立起相關的拓撲關係以及記錄每個探測到的裝置的資訊 探測採用遞迴的方式從根控制器開始逐級往下探測,遇到橋控制器...

Linux的PCI驅動分析

1.關鍵資料結構 pci裝置上有三種位址空間 pci的i o空間 pci的儲存空間和pci的配置空間。cpu可以訪問pci裝置上的所有位址空間,其中i o空間和儲存空間提供給裝置驅動程式使用,而配置空間則由linux核心中的pci初始化 使用。核心在啟動時負責對所有pci裝置進行初始化,配置好所有的...