使用PCI BIOS来枚举PCI设备

yl_lex072056232 2012-05-25 09:46:25
#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;
}

这程序小弟运行时在这块union REGS regs;出错, 因为是别人的代码,加上我个人技术不是太好。。 还麻烦大侠,帮忙指点下。 这个REGS共同体如何定义啊。 能让这个程序跑起来。

...全文
674 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
船过水无痕 2012-05-30
  • 打赏
  • 举报
回复
用TC 编译
yl_lex072056232 2012-05-30
  • 打赏
  • 举报
回复
谢谢楼上两位, 小弟已经从新找到一个代码。
// abc.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <conio.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) )
/* PCI配置空间寄存器 */
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
/* 填充PCI_CONFIG_ADDRESS */
#define MK_PCICFGADDR(bus,dev,func) (DWORD)(0x80000000L | (DWORD)MK_PDI(bus,dev,func)<<8)
/* 读32位端口 */
DWORD inpd(int portid) {
DWORD dwRet;
asm mov dx, portid;
asm lea bx, dwRet;
__emit__( 0x66,0x50, // push EAX
0x66,0xED, // in EAX,DX
0x66,0x89,0x07, // mov [BX],EAX
0x66,0x58); // pop EAX
return dwRet;}
/* 写32位端口 */
void outpd(int portid, DWORD dwVal){
asm mov dx, portid;
asm lea bx,
dwVal; __emit__(
0x66,0x50, // push EAX
0x66,0x8B,0x07, // mov EAX,[BX]
0x66,0xEF, // out DX,EAX
0x66,0x58); // pop EAX
return;}
int main(void){
int bus, dev, func;
int i;
DWORD dwAddr;
DWORD dwData;
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) { /* 计算地址 */
dwAddr = MK_PCICFGADDR(bus, dev, func); /* 获取厂商ID */
outpd(PCI_CONFIG_ADDRESS, dwAddr);
dwData = inpd(PCI_CONFIG_DATA);
/* 判断设备是否存在。FFFFh是非法厂商ID */
if ((WORD)dwData != 0xFFFF) { /* bus/dev/func */
printf("%2.2X\t%2.2X\t%1X\t", bus, dev, func);
/* Vendor/Device */
printf("%4.4X\t%4.4X\t", (WORD)dwData, dwData>>16);
/* Class Code */
outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x8);
dwData = inpd(PCI_CONFIG_DATA);
printf("%6.6lX\t", dwData>>8);
/* IRQ/intPin */
outpd(PCI_CONFIG_ADDRESS, dwAddr | 0x3C);
dwData = inpd(PCI_CONFIG_DATA);
printf("%d\t", (BYTE)dwData);
printf("%d", (BYTE)(dwData>>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 += 4) { /* Read */
outpd(PCI_CONFIG_ADDRESS, dwAddr | i);
dwData = inpd(PCI_CONFIG_DATA);
/* Write */
fwrite(&dwData, sizeof(dwData), 1, hF);
}
fclose(hF);
}
}
}
}
}
return 0;
}
WJN92 2012-05-29
  • 打赏
  • 举报
回复
直接嵌入汇编吧,这样看起来更乱

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧