#include <stdio.h>
#include <conio.h>
#include <dos.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
/* PCI设备索引。bus/dev/func 共16位,为了方便处理可放在一个WORD中 */
#define PDI_BUS_SHIFT 8
#define PDI_BUS_SIZE 8
#define PDI_BUS_MAX 0xFF
#define PDI_BUS_MASK 0xFF00
#define PDI_DEVICE_SHIFT 3
#define PDI_DEVICE_SIZE 5
#define PDI_DEVICE_MAX 0x1F
#define PDI_DEVICE_MASK 0x00F8
#define PDI_FUNCTION_SHIFT 0
#define PDI_FUNCTION_SIZE 3
#define PDI_FUNCTION_MAX 0x7
#define PDI_FUNCTION_MASK 0x0007
#define MK_PDI(bus,dev,func) (WORD)((bus&PDI_BUS_MAX)<<PDI_BUS_SHIFT | (dev&PDI_DEVICE_MAX)<<PDI_DEVICE_SHIFT | (func&PDI_FUNCTION_MAX) )
int main(void)
{
int bus, dev, func;
int i;
union REGS regs;
WORD wAddr;
FILE* hF;
char szFile[0x10];
printf("\n");
printf("Bus#\tDevice#\tFunc#\tVendor\tDevice\tClass\tIRQ\tIntPin\n");
/* 枚举PCI设备 */
for(bus = 0; bus <= PDI_BUS_MAX; ++bus) {
for(dev = 0; dev <= PDI_DEVICE_MAX; ++dev) {
for(func = 0; func <= PDI_FUNCTION_MAX; ++func) {
/* 计算地址 */
wAddr = MK_PDI(bus, dev, func);
/* 获取厂商ID */
regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
regs.x.bx = wAddr;
regs.x.di = 0; // Vendor ID
regs.x.cx = 0xFFFF; // 非法的Vendor ID
int86(0x1A, ®s, ®s);
/* 判断设备是否存在。FFFFh是非法厂商ID */
if (regs.x.cx != 0xFFFF) {
/* bus/dev/func */
printf("%2.2X\t%2.2X\t%1X\t", bus, dev, func);
/* Vendor */
printf("%4.4X\t", regs.x.cx);
/* Device */
regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
regs.x.bx = wAddr;
regs.x.di = 2; // Device ID
int86(0x1A, ®s, ®s);
printf("%4.4X\t", regs.x.cx);
/* Class Code */
regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
regs.x.bx = wAddr;
regs.x.di = 0xA; // Class/SubClass
int86(0x1A, ®s, ®s);
printf("%4.4X\t", regs.x.cx);
/* IRQ/intPin */
regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
regs.x.bx = wAddr;
regs.x.di = 0x3C; // IRQ/IntPin
int86(0x1A, ®s, ®s);
printf("%d\t", (BYTE)regs.x.cx);
printf("%d", (BYTE)(regs.x.cx>>8));
printf("\n");
/* 写文件 */
sprintf(szFile, "PCI%2.2X%2.2X%X.bin", bus, dev, func);
hF = fopen(szFile, "wb");
if (hF != NULL) {
/* 256字节的PCI配置空间 */
for (i = 0; i < 0x100; i += 2) {
/* Read */
regs.x.ax = 0xB109; // PCI BIOS v2.0c+ - READ CONFIGURATION WORD
regs.x.bx = wAddr;
regs.x.di = i;
int86(0x1A, ®s, ®s);
/* Write */
fwrite(®s.x.cx, 2, 1, hF);
}
fclose(hF);
}
}
}
}
}
return 0;
}