Linux驅動學習 初識PCI驅動 二

2022-07-13 04:00:11 字數 4876 閱讀 1066

寫在前面的話:

我們從下面幾個方面來講述:

一,初始化裝置模組

當linux

核心啟動並完成對所有

pci裝置進行掃瞄、登入和分配資源等初始化操作的同時,會建立起系統中所有

pci裝置的拓撲結構,此後當

pci驅動程式需要對裝置進行初始化時,一般都會呼叫如下的**:

static

int __init example_init_module (void

)

/*...

*/return0;

}

從上面的省略號可以看出,這僅僅只是核心的一部分,其他的東西,就要看你具體的應用是在什麼地方。

僅僅使用上面的init函式是不夠的,因為此時你並不知道你的裝置是什麼樣的,是不是都已經準備好了,因此,還有更重要的一步---probe。探測完成對硬體的檢測工作。

static

int __init example_probe(struct pci_dev *pci_dev,conststruct pci_device_id *pci_id)

memset(my_pci,

0,sizeof(*my_pci));

/*讀取pci配置資訊

*/my_pci->iobase = pci_resource_start(pci_dev,1

); my_pci->pci_dev =pci_dev;

my_pci->pci_id = pci_id->device;

my_pci->irq = pci_dev->irq;

my_pci->next=devs;

my_pci->magic =example_magic;

/*設定成匯流排主dma模式

*/pci_set_master(pci_dev);

/*申請i/o資源

*/request_region(my_pci->iobase,64,my_pci_names[pci_id->driver_data]);

return0;

}

整個程式的思路很清晰,並不需要去太多的講解,只是對裡面的一些函式需要進行一下講解.

1.pci_enable_device

啟用pci裝置,在驅動程式可以訪問pci裝置的任何裝置資源之前(i/o區域或者中斷),驅動程式必須呼叫該函式:

int pci_enable_device(struct pci_dev *dev);                       /*

driver/pci/pci.c

*/

該函式實際的啟用裝置。它把裝置喚醒,在某些情況下還指派它的中斷線和i/o區域。

2.訪問pci位址空間

因而,首先來看看配置空間的訪問:

linux核心為我們想的很周到,在核心中就已經提供了訪問配置空間的標準介面,我們只要去直接呼叫就好了。

對於驅動程式而言,可通過8位,16位,32位的資料傳輸訪問配置空間。相關函式定義在中:

int pci_read_config_byte(conststruct pci_dev *dev,intwhere, u8 *val);/*

8位,讀入乙個位元組

*/int pci_read_config_word(conststruct pci_dev *dev,intwhere, u16 *val);/*

16位,讀入兩個位元組

*/int pci_read_config_dword(conststruct pci_dev *dev,intwhere, u32 *val);/*

32位,讀入四個位元組

*/

const struct pci_dev *dev:由dev標識的裝置配置空間;

int where:從配置空間起始位置計算的位元組偏移量;

u8/u16/u32 *val:從配置空間獲得的值通過val指標返回;

函式本身返回的值是錯誤碼。

注意:word和dword函式會將讀取到的little-endian值轉換成處理器固有的位元組序。我們自己無需處理位元組序。

上面的是讀的情況,寫的情況也是類似的:

int pci_write_config_byte(conststruct pci_dev *dev,intwhere, u8 *val);/*

8位,寫入乙個位元組

*/int pci_write_config_word(conststruct pci_dev *dev,intwhere, u16 *val);/*

16位,寫入兩個位元組

*/int pci_write_config_dword(conststruct pci_dev *dev,intwhere, u32 *val);/*

32位,寫入四個位元組

*/

因此,我們可以利用上面的函式讀取和修改裝置的資訊。

講完配置空間,接下來嘮叨一下i/o和記憶體空間。

乙個pci裝置可實現多達6個i/o位址區域,每個區域既可以使記憶體也可以是i/o位址。在核心中pci裝置的i/o區域已經被整合到通用資源管理器。因此,我們無需訪問配置變數來了解裝置被對映到記憶體或者i/o空間的何處。獲得區域資訊的首選介面是下面的巨集定義:

#define pci_resource_start(dev, bar)((dev)->resource[(bar)].start)

該巨集返回六個pci i/o區域之一的首位址(記憶體位址或者i/o埠號).該區域由整數的bar(base address register,基位址暫存器)指定,bar取值為0到5。

#define pci_resource_end(dev, bar)((dev)->resource[(bar)].end)

該巨集返回第bar個i/o區域的首位址。注意這是最後乙個可用的位址,而不是該區域之後的第乙個位址。

#define pci_resource_flags(dev, bar)((dev)->resource[(bar)].flags)

該巨集返回和該資源相關聯的標誌。

資源標誌用來定義單個資源的特性,對與pci i/o區域相關的pci資源,該資訊從基位址暫存器中獲得,但對於和pci無關的資源,它可能來自其他地方。所有資源標誌定義在。

二,開啟裝置模組

static

int example_open(struct inode *inode, struct file *file)

if(file->f_mode &fmode_write)

/*申請對裝置的控制權

*/down(&my_pci->open_sem);

while(my_pci->open_mode & file->f_mode)

else

}}

在這個模組裡主要實現申請中斷、檢查讀寫模式以及申請對裝置的控制權等。在申請控制權的時候,非阻塞方式遇忙返回,否則程序主動接受排程,進入睡眠狀態,等待其它程序釋 放對裝置的控制權。

三,資料讀寫和資訊控制模組

static

int example_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long

arg)

/*...

*/}

pci裝置驅動程式可以通過

example_fops

結構中的函式

example_ioctl( )

,向應用程式提供對硬體進行控制的介面。例如,通過它可以從

i/o暫存器裡讀取乙個資料,併發送到使用者空間裡。

四,中斷模組

static

void example_interrupt(int irq, void *dev_id, struct pt_regs *regs)

/*告訴裝置已經收到中斷

*/outl(status & int_mask, my_pci->iobase +glob_sta);

spin_unlock(&my_pci->lock

);

/*其它進一步的處理

*/}

pci的中斷資源比較有限,只有

0~15

的中斷號,因此大部分外部裝置都是以共享的形式申請中斷號的。當中斷發生的時候,中斷處理程式首先負責對中斷進行識別,然後再做進一步的處理。

五,釋放裝置模組

static

int example_release(struct inode *inode, struct file *file)

{

/*...

*//*

釋放對裝置的控制權

*/my_pci->open_mode &= (fmode_read |fmode_write);

/*喚醒其它等待獲取控制權的程序

*/wake_up(&my_pci->open_wait);

up(&my_pci->open_sem);

/*釋放中斷

*/free_irq(my_pci->irq, my_pci);

/*裝置開啟計數增1

*/mod_dec_use_count;

/*...

*/

釋放裝置模組主要負責釋放對裝置的控制權,釋放占用的記憶體和中斷等,所做的事情正好與開啟裝置模組相反。

以上就是我對pci驅動程式的現階段理解,比較初淺,若有任何不合適的地方,請大家指出。

Linux驅動學習 初識PCI驅動 一

pci是什麼 pci peripheral component interconnect,外圍裝置互 線。是一種廣泛採用的匯流排標準,它提供了許多優於其它匯流排標準 如eisa 的新特性,目前已經成為計算機系統中應用最為廣泛,並且最為通用的匯流排標準。對於pci的一些具體介紹可以參考 pci具體介紹...

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裝置進行初始化,配置好所有的...