PCIe實踐之路:設備枚舉

人的一生是一個不斷認識自我,發展自我的過程。

認識PCIe設備的枚舉過程需要以下知識:

  1. 拓撲結構
  2. 設備的表徵及配置空間的訪問
  3. BAR空間的含義和訪問

其中第1/2點在總線結構與配置空間已經介紹過了,第3點在BAR空間和TLP也已經進行過詳細的介紹,可以說是萬事具備。接下來涉及的過程有以下幾個:

  1. 根據深度優先搜索進行設備總線號的分配
  2. BAR空間的映射和簡單訪問測試

上面就是枚舉過程中做的事情了。

一、基於深度優先搜索的總線號分配

1.1 原理闡述

每一個switch代表一級bus,掛在該switch下的所有設備(包括SW和EP)都屬於這級bus。

SW配置空間中的總線號有Primary Bus、Secondary Bus和Subordinate Bus。含義如下

總線號 含義
Primary Bus 當前級別的總線號,從該設備往下的所有設備都屬於primary bus
Secondary Bus 下一級總線號
Subordinate Bus 從當前級別總線開始最遠端的總線號

現在假設有一個tlp過來,首先瞅了瞅當前switch的subordinate bus number,發現比自己的bus number還小,那就很知趣的不往這級bus上路由了;如果發現subordinate bus比自己的大,她就知道我要去的地方在這一級bus上,然後就繼續往secondary bus路由,繼續重複上述過程。如果primary bus number等於tlp自己的bus number,那麼這一級bus就是tlp的歸宿了。上述這個tlp的路由過程由SW完成。

1.2 代碼舉例

init BUS[0]
push BUS[0] to bus_stack

while bus_stack != NULL:
    bus = pop(bus_stack)
    while find_next_sw(bus) is true:
        child.prim_bus = bus.prim_bus
        child.second_bus = bus.prim_bus+1
        child.subord_bus = bus.second_bus
        push(child)
    // find an EP
    update_subord_bus(bus_stack)

這個代碼是剛敲的(風格似乎有點python的感覺),只是表示基於深度優先搜索的配置PCIe設備bus number的算法,其中的find_next_sw負責找到當前sw下游的設備(如果發現設備0是EP,那麼應該繼續根據是否是多功能設備來搜索設備1,2,…,直到找到SW,或者沒有)。如果發現SW,則繼續入棧,否則(是EP)更新當前棧上所有設備的subordinate bus number爲最後一個SW的primary bus number,然後棧頂彈出SW,進行下一個分支的深度搜索。

二、映射BAR空間

前面的枚舉過程是在鏈路上通過發送配置讀寫請求來進行的,PCIe協議規定:訪問SW配置要通過類型1的配置請求,訪問EP配置要通過類型0的配置請求。

那麼如果我們想要訪問PCIe設備內部的mem空間呢?就要通過mem rd/wr請求。請求裏面包含了需要訪問的mem地址,PCIe網絡根據這個地址把tlp路由到對應的設備上去處理。所以我們需要在系統枚舉的階段配置好各個設備的BAR空間範圍,這樣mem/io tlp就能根據地址是不是在BAR範圍內來判斷是不是應該訪問該設備。

這裏再次注意:這裏的tlp中的地址和系統ram空間的地址沒有必然聯繫,只是PCIe內部分配的地址(上一篇文章已經提到過這個點了)。

而BAR的配置地址是在configuration空間的,所以在枚舉階段我們通過發送cfg rd/wr tlp來配置BAR就行,具體關於BAR的介紹在大話PCIe:BAR空間和TLP中有說明了。

上一篇文章遺留了兩個問題,到這裏可以進行解答了。

一是關於配置空間及其地址的問題。

每個設備都有其配置空間,而且是固定地址0~4096 Byte,前面64字節是PCI兼容的。這個配置空間的地址和外部總線地址並沒有什麼關係。通過指定tlp中的bus number、device number、function number+偏移地址(這個就是寫到tlp中的地址)就可以訪問到對應設備的配置空間。

二是關於如何發起cfg tlp的問題。

上篇文章介紹了一個功能模塊ATU,這是和總線對接的一個模塊,除了地址轉換之外,還根據配置產生tlp。一般是這樣的,系統會爲PCIe設備預留256MB空間,訪問這256MB空間的時候就會觸發產生一個mem request tlp,然後ATU根據配置(如果配置了cfg type)將其轉換成cfg request,其中的target地址就寫入了tlp中。然後PCIe網絡就將這個tlp路由到對應地址的設備功能上了。舉例如下:

系統ram空間地址基址爲0x40000000,ATU配置source address爲0x40000000,target address爲0x00000000,ATU type = cfg 0,size=0x10000000(256MB),那麼CPU讀0x40000000地址的時候觸發了一個mem read request,經過ATU之後產生了一個cfg type 0 rd的request;同樣的,如果往0x40000000寫一筆數據,就會觸發mem write request,處理過程也是類似的。如果訪問0x40100000,轉換後的target地址就成了0x100000。

關於PCIe設備的枚舉過程內容都在這裏了。接下來重點介紹PCIe dma和MSI(-X)中斷。

下篇預告: PCIe設備dma和MSI(-X)

發佈了146 篇原創文章 · 獲贊 81 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章