最近学习PCI,看手册看的头都大了,虽然网上有相关的PCI学习资料,也有说的很好的博主。
但是都是些文字的描述,还要看很多的文字描述,太复杂了,我不喜欢。所以我自己花时间将我的学习中的感悟和PCI配置空间弄成了一张图,方便记忆和查询。
(https://blog.csdn.net/bi511304183/article/details/9788617),我是看了这个博主的写的文章,加上朋友的帮助才明白了PCI的配置空间的访问的实现,以及一些细节的地方。
下面是我自己弄的PCI配置空间图片,平时很少弄这个,有不足之处,还望指正。
下面是PCI的枚举程序(也可以叫PCI的设备遍历),我是参考一位博主的PCI枚举程序改的,博主名忘了,抱歉!
PCI枚举程序是在UEFI的框架下写的.
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/ShellCEntryLib.h>
#include <Library/IoLib.h>
/**
Enter Pci Space of Congifuration
@param[in] index Address
**/
UINT32
PciChange(IN UINT32 index)
{
UINT32 pcidata; //use 32bit registers
IoWrite32(0x0CF8, index); //mov PCI index to 0xCF8h
pcidata = IoRead32(0x0CFC); //read data ftom 0xCFCh
return pcidata;
}
/**
as the real entry point for the application.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval other Some error occurs when executing this entry point.
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINT32 index,bus,dev,func,pci_addr,pci_data,VendorID,DeviceID,ClassCode;
Print(L"BusNum DevNum FuncNum DevID VenID Describe\n");
for(bus=0;bus<256;bus++)
{
for(dev=0;dev<32;dev++)
{
for(func=0;func<8;func++)
{
pci_addr=0x80000000|(bus<<16)|(dev<<11)|(func<<8);
pci_data=PciChange(pci_addr);
VendorID=pci_data & 0xFFFF;
//判断PCI设备是否存在
if(VendorID!=0xFFFF && VendorID!=0)
{
//get DeviceID
DeviceID=(pci_data >> 16) & 0xFFFF;
//Get the ClassCode
index = pci_addr + 0x3C;
pci_data=PciChange(index);
ClassCode=(pci_data >> 24) & 0xFFFF;
Print(L" %02x %02x %02x %04x %04x %04x %04x %s\n",bus,dev,func,DeviceID,VendorID);
}
}
}
}
return EFI_SUCCESS;
}
本来我想着要不弄成资源,需要积分下载,但是我想了一下,还是没有这样做.因为我深受开源思想的影响.
呃呃,我又在胡言乱语了,不必在意,希望对各位有帮助.