日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PCI驱动开发学习笔记(一)

發布時間:2023/12/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PCI驱动开发学习笔记(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • PCIE簡介

???????? PCIe作為串行總線的一種,它的發展必然和另一種總線架構密不可分:并行總線。

??????? 像PCIe接口的顯卡、聲卡、網卡,都屬于功能設備,在PCIe規范中,我們統稱為Endpoint(簡稱EP)。還有其他兩類設備,? 一個是Root Complex,簡稱RC,另一個是switch(或者PCI中稱為bridge),RC是根設備,通過switch和下游設備(可以是EP也可以是switch)進行橋接,從而各個PCIe設備組成了一個PCIe設備網絡,信息就以數據包(TLP、DLLP)的形式在網絡中傳遞。

一、PCI設備編號

???????? PCI設備的ID號由總線號(BUS NUMBER)、設備號(DEVICE NUMBER)和功能號(FUNCTION NUMBER)組成。

???????? 一條PCI總線的設備號由PCI設備的IDSEL信號與PCI總線地址線的連接關系確定,即每一個PCI插槽的總線號和設備號都是固定的,這是硬件工程師決定的。

???????? PCI功能號與PCI設備的具體設計相關。在一個PCI設備中最多有8個功能設備,而且每一個功能設備都有各自的PCI配置空間,而在絕大數PCI設備中只有一個功能設備。

lspci? --- 枚舉PCI設備
???????? 01:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 745] (rev a2)
??????? (bus number 0~0xff[2^8]):(device number 0~0x1f[2^5]).(function number 0~0x07[2^3])? Class:Vendor Device (revision)

二、PCI配置空間

每個PCI邏輯設備都有自己的配置空間,里面存儲了一些基本信息,生產商,IRQ中斷號,還有就是定義了mem空間和io空間的起始地址和大小。

HOST主橋使用寄存器號,訪問PCI設備配置空間的某個寄存器。

三、PCI驅動函數接口

???????? 1.? pci驅動注冊

????????? pci_register_driver(struct pci_driver *drv)

????????? pci_unregister_driver(struct pci_driver *drv)

static struct pci_device_id vt8623_devices[] = {{PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},{0, 0, 0, 0, 0, 0, 0} }; static struct pci_driver vt8623fb_pci_driver = {.name = "vt8623fb",.id_table = vt8623_devices,.probe = vt8623_pci_probe,.remove = vt8623_pci_remove,.suspend = vt8623_pci_suspend,.resume = vt8623_pci_resume, };pci_register_driver(&vt8623fb_pci_driver);

????????? 2. 激活PCI設備

??????????????? 在驅動程序可以訪問PCI設備的任何設備資源之前(I/O區域或者中斷),驅動程序必須調用該函數:

int pci_enable_device(struct pci_dev *dev); /*driver/pci/pci.c*/這個函數主要就是把PCI配置空間的Command域的0位和1?位置成了1,從而達到了開啟設備的目的。

????????? 3.? 訪問PCI配置空間

int pci_read_config_byte(conststruct pci_dev *dev,int where, u8 *val);/*8位,讀入一個字節*/int pci_read_config_word(conststruct pci_dev *dev,int where, u16 *val);/*16位,讀入兩個字節*/int pci_read_config_dword(conststruct pci_dev *dev,int where, u32 *val);/*32位,讀入四個字節*/ int pci_write_config_byte(conststruct pci_dev *dev,int where, u8 *val);/*8位,寫入一個字節*/int pci_write_config_word(conststruct pci_dev *dev,int where, u16 *val);/*16位,寫入兩個字節*/int pci_write_config_dword(conststruct pci_dev *dev,int where, u32 *val);/*32位,寫入四個字節*/

????????? 4. 申請IO端口和內存資源

?????????????? 通知內核該設備對應的IO端口和內存資源已經使用,其他的PCI設備不要再使用這個區域

???????????? int? pci_request_regions(struct pci_dev *dev, const char *res_name)

???????????? int? pci_release_regions(struct pci_dev *pdev)

???????????? int? pci_request_mem_regions(struct pci_dev *pdev, const char *name)

???????????? int? pci_release_mem_regions(struct pci_dev *pdev)

???????????? int? pci_request_io_regions(struct pci_dev *pdev, const char *name)

???????????? int? pci_release_io_regions(struct pci_dev *pdev)

?

?????????? 5. 訪問PCI的I/O和內存空間

???????????? int pci_resource_[start|end|flags|len](struct pci_dev *dev,? int bar)? //Bar值的范圍為0-5

?在硬件加電初始化時,BIOS固件統一檢查了所有的PCI設備,并統一為他們分配了一個和其他互不沖突的地址,讓他們的驅動程序可以向這些地址映射他們的寄存器,這些地址被BIOS寫進了各個設備的配置空間,因為這個活動是一個PCI的標準的活動,所以自然寫到各個設備的配置空間里而不是他們風格各異的控制寄存器空間里。當操作系統初始化時,他為每個PCI設備分配了pci_dev結構,并且把BIOS獲得的并寫到了配置空間中的地址讀出來寫到了pci_dev中的resource字段中。這樣以后我們在讀這些地址就不需要在訪問配置空間了,直接跟pci_dev要就可以了,我們這里的四個函數就是直接從pci_dev讀出了相關數據。

Linux認為這個地址是IO地址,如果要訪問的話可以通過ioremap映射到內核空間,然后通過readl/writel等IO接口進行操作。

?????????? 6.? 私有數據

???????????? pci_set_drvdata??? 設置驅動私有數據

???????????? pci_get_drvdata??? 獲取驅動私有數據

?????????? 7. 主設備模式

????????????? pci_set_master??? 設定設備工作在總線主設備模式

?

?

?

?

?

總結

以上是生活随笔為你收集整理的PCI驱动开发学习笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。