io空間訪問
㈠ PCIe掃盲——Memory & IO 地址空間
早期的PC中,所有的IO設備(除了存儲設備之外的設備)的內部存儲或者寄存器都只能通過IO地址空間進行訪問(Intel乾的好事)。但是這種方式局限性很大,而且效率低,於是乎,軟體開發者和硬體廠商都不能忍了……然後一種新的東西就出來了——MMIO。MMIO,即Memory Mapped IO,也就是說把這些IO設備中的內部存儲和寄存器都映射到統一的存儲地址空間(Memory Address Space)中。但是,為了兼容一些之前開發的軟體,PCIe仍然支持IO地址空間,只是建議在新開發的軟體中採用MMIO。
註: PCIe Spec中明確指出,IO地址空間只是為了兼容早期的PCI設備(Legacy Device),在新設計中都應當使用MMIO,因為IO地址空間可能會被新版本的PCI Spec所拋棄。
IO地址空間的大小是4GB(32bits),而MMIO則取決於處理器(和操作系統),並且由處理器進行統一分配管理。
如下圖所示,PCIe匯流排中有兩種MMIO:P-MMIO和NP-MMIO。
P-MMIO,即可預取的MMIO(Prefetchable MMIO);NP-MMIO,即不可預取的MMIO(Non-Prefetchable MMIO)。其中P-MMIO讀取數據並不會改變數據的值。
註: P-MMIO和NP-MMIO主要是為了兼容早期的PCI設備,因為PCIe請求中明確包含了每次的傳輸的大小(Transfer Size),而PCI並沒有這些信息
MMIO(Memory-mapped I/O )即 內存映射I/O ,它是PCI規范的一部分, I/O設備 被放置在內存空間而不是I/O空間。從處理器的角度看,內存映射I/O後系統設備訪問起來和內存一樣。這樣訪問AGP/PCI-E顯卡上的 幀緩存 ,BIOS,PCI設備就可以使用讀寫內存一樣的 匯編指令 完成,簡化了程序設計的難度和介面的復雜性。
㈡ IO空間和內存空間主要什麼區別
IO地址是CPU讀寫外部設備時使用的地址。
內存地址是CPU讀寫內存(括REM和ROM)時使用的地址。
多數精簡指令CPU不區分訪問的是內存還是外設,使用統一的指令和統一的地址空間去訪
問外設和內存。在這種情況下,需要解碼電路把所有的外設I/O地址和內存地址按照規則安排在一個空間里,學慣了X86CPU的也可把這叫作I/O地址映射成內存地址空間吧,雖然實際上這些CPU並沒有I/O地址空間和內存地址空間的概念。
並不是所有的體系結構都有IO空間這個定義的,我所了解的只有X86體繫上有,而ARM體系結構就沒有這種區別,在X86上IO空間和內存是獨立的,他們各自有各自的匯流排,並且IO空間一般是64K,即16位內存空間為4G,可見他們的差別是很大。
㈢ X86的IO地址空間
IO 埠
當 CPU 需要與某個外圍設備通信時,它要通過一個 IO 埠(有時只是簡單的 埠)。當 CPU 需要向
外圍設備發送數據或者控制信息時,它向某個埠寫入數據。當設備為 CPU 准備好了數據或者狀態,CPU
從某個埠去讀取數據或狀態。大部分設備都擁有不止一個與之相關聯的埠,通常是 2 的若干次冪(
指數較小),比如 8、16 或者 32。數據傳輸通常是每次一個或兩個位元組。設備不能共享埠,所以,如
果有 ISA 卡,那麼必須確保每個設備都有其分配到了自己的埠。以前,這需要通過設備卡上的開關或
者跳線來實現。一些晚期的 ISA 卡使用了一個名為 Plug and Play (PnP)的系統,本節稍後將討論到
。 PCI 卡全都有 PnP 配置。
在 /proc 文件系統中,/proc/ioports 文件告訴我們關於系統中可用 IO 埠的信息。運行 cat
/proc/ioports 命令可以看到類似清單 2 所示的輸出。
清單 2. /proc/ioports
0000-001f : dma1
0020-003f : pic1
0040-005f : timer
0060-006f : keyboard
0070-007f : rtc
0080-008f : dma page reg
00a0-00bf : pic2
00c0-00df : dma2
00f0-00ff : fpu
0170-0177 : ide1
01f0-01f7 : ide0
02f8-02ff : serial(auto)
0376-0376 : ide1
0378-037a : parport0
03c0-03df : vga+
03f6-03f6 : ide0
03f8-03ff : serial(auto)
0cf8-0cff : PCI conf1
1800-181f : Intel Corp. 82801DB USB (Hub #1)
1800-181f : usb-uhci
1820-183f : Intel Corp. 82801DB USB (Hub #2)
1820-183f : usb-uhci
1840-185f : Intel Corp. 82801DB USB (Hub #3)
1840-185f : usb-uhci
1860-186f : Intel Corp. 82801DB Ultra ATA Storage Controller
1860-1867 : ide0
1868-186f : ide1
1880-189f : Intel Corp. 82801DB/DBM SMBus Controller
18c0-18ff : Intel Corp. 82801DB AC'97 Audio Controller
18c0-18ff : Intel ICH4
1c00-1cff : Intel Corp. 82801DB AC'97 Audio Controller
1c00-1cff : Intel ICH4
2000-203f : Intel Corp. 82801BD PRO/100 VE (LOM) Ethernet Controller
2000-203f : e100
埠編號是十六進制的(基數為 16)。肯定會發現有一些看起來很熟悉,比如鍵盤、計時器、並行埠
(列印機)、串列埠(數據機)和顯示器(vga+)。將這些與清單 3 中給出了在 PC 中某些標准
IO 埠分配進行比較。例如,要注意的是,在 /proc/ioports 中為第一個並行埠(parport0)分配的
地址范圍是從 0378 到 037A,而標准中允許它(LPT!)使用的是從 378 到 37F。
清單 3. 標准 I/O 埠設置
1FO-1F8 - Hard Drive Controller, 16-bit ISA
200-20F - Game Control
210 - Game I/O
220 - Soundcard
278-27F - LPT2
2F8-2FF - COM2
320-32F - Hard Drive Controller, 8-bit ISA
378-37F - LPT1
3B0-3BF - Monochrome Graphics Adapter (MGA)
3D0-3DF - Colour Graphics Adapter (CGA)
3F0-3F7 - Floppy Controller
3F8-3FF - COM1
給你解決個問題還冒著生命危險,唉,這世道!
㈣ 52寄存器中的128位和IO口如何訪問
通過定址方式來訪問的。
高128位元組RAM與SFR的訪問,是通過定址方式來區別的。52單片機ram高128位元組地址空間,可以通過間接定址方法實現。直接定址的,就是SFR。間接定址的,就是高128位元組RAM。
IO即inputoutput,是計算機種輸入輸出系統,用於cpu與外界進行信息交互,例如cpu讀內存數據需要io系統,cpu輸出數據到屏幕顯示出來也需要io系統,信息在io系統上傳輸有並行或並行,所謂串列就是數據在一條線上傳輸,並行就是數據在多條線上傳輸,即並行一次傳輸多個bit,串列每次傳輸一個bit,但隨著技術的發展這兩種傳輸優勢是在不斷變化的。
㈤ driverworks開發pci的驅動程序怎樣獲取資源的io空間地址
0 引言
如果把PC機作為控制系統的操作平台,PCI匯流排作為一種先進的高性能32/64位局部匯流排正迅速取代原來的ISA匯流排的主導地位,以用於高速外設,並成為微型計算機系統的主流系統,因而也成為工程開發人員用於工業控制的首選。為了縮短開發周期,一般都採用專用的介面器件。本文就是採用PLX公司的PCI9052來把PCI匯流排上的操作轉換為對局部匯流排的操作,同時通過雙口RAM實現和下位機的存儲轉接。針對一般PCI匯流排開發時由於軟硬體分離使開發的軟硬體不能很好結合的現象,本文結合實例介紹了應用程序並給出了如何通過DriverStudio開發的PCI設備驅動程序來訪問PCI設備卡硬體資源的具體程序。
1 PCI的配置空間及其配置
PCI匯流排支持存儲器地址空間、I/O地址空間和配置空間等三個物理空間。其中,配置空間是PCI匯流排所特有的一個空間,PCI匯流排能實現即插即用的功能,正是通過它特有的配置空間來實現的。PCI配置空間的大小為256位元組,分為頭標區和設備有關區。直接影響設備特性的配置寄存器在頭標區,其他部分則因設備而異。PCI匯流排的配置空間通常與PCI介面晶元相關。該配置空間包括一系列的PCI配置寄存器。本文採用的PCI9052晶元的配置寄存器分為PCI配置寄存器和局部配置寄存器,二者都可以由PCI匯流排和串列EEPROM訪問。
在PCI配置寄存器中的設備ID、製造商ID、版本號、首區類代碼、類別代碼、指令寄存器和狀態寄存器等寄存器在所有的PCI設備中都必須實現,具體設置可參考文獻[1]。通常情況下,操作系統可使用這些寄存器的內容來決定該PCI設備的載入其驅動程序。
PCI匯流排最重要的功能之一是通過基地址寄存器和局部配置寄存器在地址空間重定位PCI設備。系統上電時,通過上層應用軟體能判斷系統中存在那些設備,並建立協調的地址映射。所以,基地址寄存器和局部配置寄存器是實現驅動程序的關鍵。
PCI配置寄存器提供有6個基地址寄存器(BASE0~BASE5)這些基地址都是系統中的物理地址,其中BASE0和BASE1是用來訪問局部配置寄存器的基地址,BASE0是映射到內存的基地址,BASE1是映射到I/O的基地址,可用於通過內存和I/O來訪問局部配置寄存器。這兩個基地址可固定用於PCI9052晶元的寄存器操作。
通過BASE2~BASE5四個空間最多可以訪問局部端所接的4個晶元,實現4個局部地址空間(局部空間0~3)的PCI匯流排訪問。PCI匯流排對局部端所接晶元的局部地址映射是通過4個寄存器組(PCI基地址寄存器,局部范圍寄存器,局部基地址寄存器,局部匯流排區域描述符)來實現的。這個組定義了每個空間以及相應局部空間的特性。它們將局部端的晶元通過局部端地址(在局部配置寄存器中設置)翻譯成PCI匯流排地址,也就是將本地的晶元映射到系統的內存或I/O口。而片選信號寄存器則是用來選定這些局部端所接的晶元的。這樣,用程序操作這一段內存(或I/O)實際上就是對本地晶元的操作。其映射關系如圖1所示。這些寄存器的內容必須在晶元復位時通過串列E2PROM進行載入,而正確配置E2PROM的內容則是使用PCI9052的關鍵。
本設計選取LAS0(Local Address Space 0)來訪問局部端的雙口RAM晶元中的2 KB定址空間,與其有關的寄存器有四個:LAS0范圍寄存器、LAS0局部基址寄存器、LAS0局部匯流排區域描述符和片選0基址寄存器。LAS0范圍寄存器規定了地址空間的大小。由於需要2 KB的內存空間,而計算機預留了32 KB空間(即8000H),所以其寄存器值為0xFFFF8000H,而類型則是不可預取的;LAS0局部基地址寄存器定義了設備卡資源上所佔用的基地址,它的最終目的是將這個基地址重新映射到PCI地址空間。由於基地址必須是32KB的整數倍,因此,為方便起見,可以將基地址定為00000000H,又由於位0為空間使能位,所以,寄存器的值為00000001H;LAS0局部匯流排區域描述符用來定義地址空間0的具體工作特性。
該匯流排採用16位匯流排寬度,工作方式定義為不使能突發和不預取,因此,該寄存器的數值初步確定為4043A1C0H,最終的值則需要不斷測試才能確定;片選0基址寄存器使用PCI9052的CS0#作為雙口RAM的片選信號,CS0#片選信號的起始地址和地址范圍由片選0基址寄存器設置,局部匯流排的容量是2 KB,第11位為1,基地址是該范圍的16倍,一般將倍數放置在范圍位之後,所以寄存器值設置為0xO008401。當從局部空間0基址開始的2 KB空間范圍落在CS0基地址寄存器所設置的范圍內,CS0端有效,這種方式可減少地址解碼得到的片選邏輯。
用PLX9052可將PCI匯流排上的操作轉換為對局部匯流排的操作,即通過LAD0~LAD7、RD、WR、CS等對局部端晶元訪問。如果系統分配給本卡的存儲空間為FFFF0000H~FFFF7FFFFH。那麼,當系統通過PCI匯流排訪問這個區域時,PLX9052就會應答,並將其轉換為局部地址0x0000H~0x07FFH,另外,PLX9052自身也有一些內部寄存器,它們被自動映射到另一片內存區域,可通過PCI匯流排直接訪問。
PCI9052提供了兩種類型的中斷源(硬體中斷和軟體中斷)。中斷可通過PCI9052中斷控制/狀態寄存器來(INTCSR)允許和禁止。PCI9052通過2個局部中斷引腳來實現硬體中斷,它們支持邊緣和電平觸發中斷,可以通過對INTCSR寄存器的編程來實現局部中斷,然後產生PCI中斷(INTA),並生成PCI中斷INTA#方式。PCI9052可以軟體方式產生中斷,設計時只需要將INTCSR寄存器的軟體中斷位設置為1即可。
2 驅動程序的開發
在開發PCI板卡功能驅動程序之前,首先要明白所需的PCI硬體資源,並針對設備卡的硬體資源來處理PCI設備的內存、埠的讀寫,以及中斷處理,從而實現PCI設備功能。
2.1 驅動程序在操作系統體系結構中的位置
操作系統結構可分為五層模型:
(1)用戶應用程序;
(2)IO管理層;
(3)驅動程序;
(4)HAL(硬體抽象層);
(5)硬體。
圖2給出了Windows2000操作系統驅動程序開發者所關心的特徵,一般情況下,軟體要麼在用戶模式中執行,要麼在內核模式下執行。從驅動開發的角度上看,WDM模型為存在於Win-dows2000系統中的驅動程序提供了一個參考框架。作為Windows2000系統結構開發人員,由於操作系統為應用程序,而在驅動程序和硬體之間提供有系統服務介面和平台相關操作,因此,設計時只需要關注應用程序和設備驅動程序的開發。
2.2 設備資源
PCI設備的硬體資源分配與管理是驅動程序很重要的部分,設備的硬體資源包括內存空間、I/O空間和中斷。由於PCI匯流排為PnP匯流排,PCI設備的硬體資源是由PCI配置機構動態分配給PCI配置寄存器的,因此,驅動程序首先需要取得這些資源才能操作硬體。當PnP管理器檢測到PCI設備時,系統就會發送IRP_MN_START_DEVICE的IRP給驅動程序,驅動程序調用OnStartDevice以啟動常式處理,並在啟動常式里獲取該IRP棧,同時把它包含的系統分配給該設備的資源信息。
用DriverStudio開發驅動程序時,應在Wizard中設置好PCI設備的資源。對於實際的PCI9052設備卡,其基地址寄存器0和1分別固定用於PCI9052局部寄存器的內存映射地址和I/O映射地址,基地址寄存器2則用於設備卡的內存映射地址,並使用局部中斷引腳來產生PCI中斷,以分別生成對應的KIoRange類、KMemoryRange類和KInterrupt類。這些配置信息由配置管理器發送到OnStartDevice中重載該成員函數,而開發者則不必再處理。在一般情況下,驅動程序無需再訪問PCI設備的配置空間,如果需要訪問,則可通過類KPciConfiguration,該類包含了通過向PCI匯流排發送瀆寫配置空間的IRP操作。也可定義類KRe-sourceAssignment來獲取PCI的埠地址和中斷號以及內存地址和大小,並把得到的資源放在用戶自己定義的變數中。
2.3 WDM驅動程序對硬體資源的訪問
獲取設備的硬體資源以後,就可以對硬體資源進行訪問了。對硬體的訪問一般包括I/O埠訪問和內存訪問,它們分別對應PCI配置空間的I/O空間和內存空間。從圖2可以看出,當應用程序需要訪問設備時,它就會調用Win32API函數(如ReadFile)。Win32子系統模塊通過調用平台相關的系統服務介面實現該API,而平台相關的系統服務則調用內核模式來支持常式。即在調用ReadFile函數時,首先到達系統的人口點,然後調用系統服務介面,最後由系統調用內核模式的服務常式。執行時首先檢查傳遞給它們的參數,然後創建一個「I/O請求包(IRP)」的數據結構,並把這個數據結構送到某個驅動程序的入口點執行IRP設備驅動程序,最後再訪問硬體。對於PIO方式的設備,一個IRP_MJ_READ操作將直接讀取設備的埠或設備的內存寄存器。一般會使用硬體抽象層(HAL)來訪問硬體。IRP貫穿於驅動程序之間,它在應用程序、驅動程序和設備之間起著橋梁作用,可稱之為內核態的「消息」。驅動程序完成一個I/O操作後,可通過調用一個特殊內核模式服務常式來完成該IRP,完成操作時再處理IRP的最後工作,以它使等待的應用程序恢復運行。
用DriverStudio開發驅動程序時,可根據配置聲明KIoRange類、KMemoryRange類和KInterrupt類來實現對內存空間、I/O空間、中斷的操作。在本例中,基地址寄存器0和1固定用於PCI9052晶元的操作寄存器內存映射地址和I/O映射地址,基地址寄存器2則用於雙口RAM的內存映射。通過一個外部引腳即可產生中斷。標識兩個KMem-oryRange類實例、一個KIoRange類實例和一個KInterrupt類實例的具體實現細節如下:
(1) I/O埠的訪問
I/O埠的訪問流程如圖3所示,應用程序通過API函數DeviceIoControl的調用,並調用驅動程序的分發常式DeviceControl,同時通過KIoRange類來實現對I/O映射空間的訪問。需要注意的是,當DeviceloControl非同步調用的時候,必須在驅動程序中添加取消常式,並在DeviceControl常式中阻止一個應用程序對其的多次調用。KIoRange類的成員函數outb、inb、outw、inw、ind、outd可分別用於從埠讀或寫一個位元組、字和雙字數據。在WDM中,對於I/O埠,系統可將其看成寄存器,一般用於數字傳輸量比較小的地方。在對PCI設備的訪問中,I/O埠的訪問通常比較頻繁。
(2) 內存的訪問
在基於DriverStudio開發的驅動程序中,向存儲器空間讀寫大量數據一般選用Write/Read函數,但對於一個實際存在的物理設備的訪問,在某一時刻只能進行一個操作,因而在訪問內存對象的時候,一般都要求一個IRP排隊的隊列,可通過設備類的成員函數QueueIrp將IRP插入隊列。DriverWorks提供有KDeviceQueue類,其成員函數StartIo用於處理設備對象的IRP隊列。具體的操作是通過KMemoryRange類來實現對設備內存映射空間的訪問。其訪問流程見圖4所示。需要注意的是,當IRP隊列為空時,調用QueueIrp時,系統將同步調用StartIo函數。
㈥ 8086的I/O定址空間有多大
8086是20位地址匯流排。
所以整個可訪問空間就是2的20次方。
但是,由於i/o介面的模式只有a0~a15,所以i/o定址空間就是2的16次方=65536kb
㈦ 已知存儲晶元的連接圖,分析晶元地址的范圍
已知存儲晶元的連接圖,分析晶元地址的范圍:首地址【40】H,FC00H;末地址【41】H,FDFFH。
用末地址減首地址,加1即為十六進制數,再用二進制的權位表示即可,所以根據該題中EPROM晶元的地址范圍為:30800H ~ 30FFFH,可得晶元的存儲容量為2KB,另外一般EPROM晶元的存儲容量為4KB,再由於無地址重疊,所以晶元存儲容量為2KB。
在C語言等高級語言
裡面沒有訪問IO的指令,所以那樣的話在C裡面就無法訪問IO,只能通過嵌入匯編或者通過調用系統函數來訪問IO了。採用IO映射後就不同了,因為IO空間和內存空間本來不同,有不同的訪問指令,那麼,將IO空間映射到內存空間,就可以通過使用訪問內存的方法來訪問IO了,例如在C語言裡面可以通過指針來訪問內存單元,從而訪問到被映射的IO。
㈧ 8086/8088微處理器可定址訪問的最大I/O空間為
8086/8088微處理器的寄存器中,能在i/o埠定址時做埠地址寄存器的是(dx)
㈨ 如何訪問pcie整個4k的配置空間
目前用於訪問PCIe配置空間寄存器的方法需要追溯到原始的PCI規范。為了發起PCI匯流排配置周期,Intel實現的PCI規范使用IO空間的CF8h和CFCh來分別作為索引和數據寄存器,這種方法可以訪問所有PCI設備的255 bytes配置寄存器。Intel Chipsets目前仍然支持這種訪問PCI配置空間的方法。
PCIe規范在PCI規范的基礎上,將配置空間擴展到4K bytes,至於為什麼擴展到4K,具體可以參考PCIe規范,這些功能都需要配置空間。原來的CF8/CFC方法仍然可以訪問所有PCIe設備配置空間的頭255 bytes,但是該方法訪問不了剩下的(4K-255)配置空間。怎麼辦呢?Intel提供了另外一種PCIe配置空間訪問方法。Intel Chipset通過將配置空間映射到內存地址空間,PCIe配置空間可以像對映射范圍內的內存進行read/write一樣來訪問了。這種映射是由北橋晶元來完成的,但是不同晶元的映射方式也是不同的。
1、CF8h/CFCH Method
Intel Chipsets使用IO空間的CF8h/CFCh地址來訪問PCI設備的配置寄存器,該方法同樣可以訪問PCIe設備的頭255配置寄存器。
為了對已知PCI設備發起一個PCI匯流排配置周期,軟體必須執行以下步驟:
PCI設備的匯流排號必須被填寫到IO地址CF8h的[23:16] bits
PCI設備的設備號必須被填寫到IO地址CF8h的[15:11] bits
PCI設備的功能號必須被填寫到IO地址CF8h的[10:8] bits
需要訪問的寄存器雙字地址必須被填寫到IO地址CF8h的[7:2] bits
CF8h的最高位為配置位,該位必須設置為1
對於寫操作,將設備的特定信息組合成一個雙字(4bytes)後,寫到CFCh地址
對於讀操作,將設備的特定信息組合成一個雙字後,把數據從CFCh讀回來
當執行6或者7步驟時,相應的PCI配置read/write cycle被Created by Intel Chipset,並在需要時傳遞到整個系統。在步驟4配置需要讀寫的寄存器地址時,該空間只有6位,也就說只有64個地址可寫,但是PCI配置空間不是256嗎?別急,記得是雙字地址,一個Dword=4 bytes,也就是說4 * 64 = 256,剛好,不是嗎?
2、Memory Mapped Method
PCIe規范為每個PCIe設備添加了更多的配置寄存器,空間為4K,盡管CF8h/CFCh方法仍然能夠訪問lower 255 bytes,但是必須提供另外一種方法來訪問剩下的4K range寄存器。Intel的解決方案是使用了預留256MB內存地址空間,對這段內存的任何訪問都會發起PCI 配置cycle。但是為什麼是256MB???聽我慢慢解釋給大家聽:猶豫4K的配置空間是directly mapped to memory的,那麼PCIe規范必須保證所有的PCIe設備的配置空間佔用不同的內存地址,按照PCIe規范,支持最多256個buses,每個Bus支持最多32個PCI devices,每個device支持最多8個function,也就是說:佔用內存的最大值為:256 * 32 * 8 * 4K = 256MB。
這段256MB的內存區將根據intel chipset的不同,可以映射到系統內存映射范圍內的任何位置,一般北橋晶元都會有一個寄存器來指明PCI配置空間的內存映射地址,它叫PCIe Configuration Register Base Address Register (BAR),如下圖:
當軟體訪問指定PCIe設備的配置寄存器時,必須正確計算該寄存器映射到內存的具體地址,那麼怎麼計算呢,參考上圖我們可以知道,busNo=0,deviceNo=0,funcNo=0的地址剛好是BAR,一條匯流排佔用的最大空間計算如下:
SIZE_PER_BUS = 4K * 32 * 8 = 256K = 1M = 100000h
SIZE_PER_DEVICE = 4K * 8 = 8000h
SIZE_PER_FUNC = 4K = 1000h
訪問匯流排號為busNo,設備號為DevNo,功能號為funcNo的offset寄存器的計算公式是:
Memory Address = PCIe Configuration Register Base Address Register (BAR)
+ busNo * SIZE_PER_BUS
+ devNo * SIZE_PER_DEVICE
+ funcNo * SIZE_PER_FUNC
+ offset
For example, to access the following configuration register:
• PCI Express Configuration Register F0000000h
• Bus Number 15h
• Device Number 00h
• Function Number 05h
• Register Offset 84h
Memory Address = F0000000h + 15h * 100000h + 00h * 8000h + 05h * 1000h + 84h
= F1505084h
現在我們可以從已知的busNo,devNo,funcNo和offset來計算映射後的內存地址,那麼反過來,給定的內存地址,我們想知道這個地址的busNo, devNo, funcNo和offset信息,可以嗎?當然可以,計算公式如下:
busNo = (Memory Address - BAR) / SIZE_PER_BUS;
devNo = (Memory Address - BAR - busNo * SIZE_PER_BUS) / SIZE_PER_DEVICE;
funcNo = (Memory Address - BAR - busNo * SIZE_PER_BUS
- devNo * SIZE_PER_DEVICE) / SIZE _PER_FUNC;
offset = Memory Address - BAR - busNo * SIZE_PER_BUS - devNo * SIZE_PER_DEVICE
- funcNo * SIZE_PER_FUNC;
又或offset = Memory Address & 0x0FFFh;(為什麼是0x0FFFh?自己想想啦)
想起來了么?因此PCIe的配置空間大小就是4K啊。
3、晶元組的異同
上面說的BAR,也就是PCI配置空間寄存器映射到內存的基地址寄存器,在intel chipset中的實現方式也千差萬別。在前期的intel chipset中,該寄存器被包含在晶元組(MCH ,GMCH)的內存控制器部分。
另外,由於被PCIe配置空間佔用的256M內存空間會屏蔽掉DRAM使用該段內存區,大部分的Intel Chipset允許BIOS來配置該空間大小,因此在實際應用中,一般就應用前面幾個匯流排號,BIOS通過檢測PCIe匯流排的擴展深度來動態設置該映射內存區的大小,比如PM965晶元組,如果配置軟體檢測系統使用不大於64的匯流排號,那麼該軟體將編程內存映射大小為64M,剩下的(256M-64M = 192M)留給DRAM。
4、PCIe配置空間的內存映射對32bit系統的影響
由於PCIe配置空間佔用了256M內存空間,而且該被佔用空間對DRAM來說是不可用的,這意味著256M空間消失於系統內存,這在32bit系統中更為明顯。
比如,在32 bit WINxp中,理論上可以訪問到的內存是4G,如果4G空間都被DRAM給佔用,由於PCIe的存在,被PCIe佔用的那部分內存空間對OS來說是不可用的,莫名的消失了最多256M內存,這也是大部分Intel Chipset允許BIOS來配置該空間大小的原因。
在64 bit 系統中,不存在這個問題,因為系統可以訪問超過4G的內存空間,Intel Chipset會包含控制邏輯把該PCIe的內存映射到above 4G,這樣跟DRAM就沒有沖突。在64bit系統中,不可能使用2的64次方的內存吧。哈哈,總會沒有使用到的內存空間。
5、訪問PCIe配置空間的C轉換代碼
//**********************************************************************
unsigned long PCIeBase = 0xF0000000UL;
unsigned long FinalAddress;
unsigned long Bus = 0;
unsigned long Device = 0;
unsigned long Function = 0;
unsigned long Register = 0;
//**********************************************************************
void Convert_to_Memory()
{
FinalAddress = PCIeBase +
(Bus*0x100000UL) +
(Device*0x8000) +
(Function*0x1000) +
Register;
}
//**********************************************************************
void Convert_to_Register()
{
Bus = (FinalAddress-PCIeBase) / (0x100000UL);
Device = (FinalAddress-PCIeBase - (Bus*0x100000UL)) / (0x8000);
Function = (FinalAddress-PCIeBase - (Bus*0x100000UL) -
(Device*0x8000)) / (0x1000);
Register = (FinalAddress) & (0x00000FFF)
}
㈩ 8086cpu訪問I/O埠的最大空間是多少
8086/8088 CPU最多能夠管理64K個埠 A0--A15 地址從0000H ---- FFFFH