Windows下遍历PCI设备

来源:互联网 发布:西安硅峰网络薪资 编辑:程序博客网 时间:2024/05/22 00:12

    一个系统上最多有256个PCI总线,每个总线最多有32个设备,每个设备最多有8个功能,每个功能最多有256字节的配置地址空间,所以总的配置地址空间是16M(256字节 ×8 ×32 ×256)。

 一个PCI设备可由bus号、device号、function号唯一确定。这三个参数构成PCI设备标识符。

 

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

bus

device

function

设备标识符
    PCI总线规范定义的配置空间总长度为256个字节,配置信息按一定的顺序和大小依次存放。前64个字节的配置空间称为配置头(如下图所示),对于所有的设备都一样,配置头的主要功能是用来识别设备、定义主机访问PCI卡的方式(I/O访问或者存储器访问,还有中断信息)。其余的192个字节称为本地配置空间,主要定义卡上局部总线的特性、本地空间基地址及范围等。

DW

Byte3

Byte2

Byte1

Byte0

Offset

0

Device ID

Vender ID

00H

1

Status

Command

04H

2

Class Code

Rev ID

08H

3

BIST

Header Type

Latency Timer

Cache Line

0CH

4

Base Address 0

10H

5

Base Address 1

14H

6

Base Address 2

18H

7

Base Address 3

1CH

8

Base Address 4

20H

9

Base Address 5

24H

10

Card Bus CIS pointer

28H

11

Subsystem Device ID

Subsystem Vendor ID

2CH

12

Expansion ROM Base Address

30H

13

Reserved(Capability List)

34H

14

Reserved

38H

15

Max_Lat

Min_Gnt

IRQ Pin

IRQ Line

3CH

 
   X86 CPU可以访问存储器或IO地址空间,但不能直接访问配置地址空间。CPU通过主桥(北桥或MCH)中的一个IO映射的地址端口和数据端口间接访问PCI配置空间。该地址端口位于IO空间CF8h~CFBh,而数据端口映射到CFCh~CFFh。
   CF8h: CONFIG_ADDRESS   PCI配置空间地址端口。
   CFCh: CONFIG_DATA        PCI配置空间数据端口。
   由于在Windows下有保护模式,不能直接访问底层,需要通过Winio访问,Winio可在以下网址下载:http://download.csdn.net/source/3524348
代码如下:
#include <windows.h>
#include "winio.h"
#include <stdlib.h>
#include <stdio.h>
#define PCI_CONFIG_ADDRESS 0xcf8
#define PCI_CONFIG_DATA 0xcfc
#pragma comment(lib,"winio.lib")
int main()
{
int bus,dev,func,count=0;
DWORD dwAddr,dwData,VID,DID;
if(InitializeWinIo())
{
printf("VID\tDID\tBUS#\tDev#\tFun#\n");
for(bus=0;bus<256;bus++)
{
for(dev=0;dev<32;dev++)
{
for(func=0;func<8;func++)
{
dwAddr=0x80000000+(bus<<16)+(dev<<11)+(func<<8);
SetPortVal(PCI_CONFIG_ADDRESS,dwAddr,4);
GetPortVal(PCI_CONFIG_DATA,&dwData,4);
if(dwData!=0xffffffff)
{
count++;
VID=dwData&0xffff;
DID=(dwData>>16)&0xffff;
printf("%04x\t%04x\t%02x\t%02x\t%02x\n",VID,DID,bus,dev,func);  
}
}  
}
}
printf("Find PCI Device %d",count);
 
ShutdownWinIo();
}
else
{
printf("Initialize Win IO Fail!\n");
exit(255);
}
getchar();
return 0;
}
 
 
原创粉丝点击