实验五 即插即用配置资源的获取实验
掌握获取PCI总线设备的资源的方法
一、 实验目的和内容 二、 编程提示
1、 PCI设备资源寄存器地址分布
#define PCI_CS_VENDOR_ID 0x00 #define PCI_CS_DEVICE_ID 0x02 #define PCI_CS_COMMAND 0x04 #define PCI_CS_STATUS 0x06 #define PCI_CS_REVISION_ID 0x08 #define PCI_CS_CLASS_CODE 0x09 #define PCI_CS_CACHE_LINE_SIZE 0x0c #define PCI_CS_MASTER_LATENCY 0x0d #define PCI_CS_HEADER_TYPE 0x0e #define PCI_CS_BIST 0x0f #define PCI_CS_BASE_ADDRESS_0 0x10 #define PCI_CS_BASE_ADDRESS_1 0x14 #define PCI_CS_BASE_ADDRESS_2 0x18 #define PCI_CS_BASE_ADDRESS_3 0x1c #define PCI_CS_BASE_ADDRESS_4 0x20 #define PCI_CS_BASE_ADDRESS_5 0x24 #define PCI_CS_EXPANSION_ROM 0x30 #define PCI_CS_INTERRUPT_LINE 0x3c #define PCI_CS_INTERRUPT_PIN 0x3d #define PCI_CS_MIN_GNT 0x3e #define PCI_CS_MAX_LAT 0x3f
16
三. 程序框图 开始 N PCI BIOS支持存在否 (调用INT IAH,AH= Y Y 计算机原理仪存在吗?用 N Vendor_ID=10EB Device_ID=8376索引号=0,AH=BIH,AL=02H,INT IAH Y 读取该卡地址空间1起始地址,即I/O空间1
17
BIH,AL=01H 显示:PCI BIOS不存在 显示:设备未发现 N 读取该卡地址空间0起始地址,即I/O空间。 读取该卡地址空间2,即存储器空间起始地址 读取该卡IRQ号即INTERUPT_Line 显示I/O空间起始地址0、1存储器空间起始地址,IRQ号 退 出
四. 程序代码
//此程序的作用是读取PCI卡的各种资源,用TURBO C 3.0编译 #include
unsigned long int iobase0,iobase1,membase0,membase1; unsigned char bh; unsigned char bl;
int findPCIcard() //找寻PCI卡的总线号及设备号及功能号 {
union REGS regs; regs.h.ah=0xb1;
regs.h.al=0x02; //寻找指定厂商和设备号的PCI卡的位置 regs.x.cx=0x8376;
regs.x.dx=0x10eb; //输入要寻找的厂商号和设备号 regs.x.si=0x00; //输入要寻找的PCI卡索引号 int86(0x1a,®s,®s); //调用指定的X86中断
bl=regs.h.bl; //返回的设备号高5位,低3位为功能号 bh=regs.h.bh; //返回的总线号 return(regs.h.ah); //返回状态 }
int getPCIbase0() //获得PCI卡的IO0的地址 {
union REGS regs; //定义用C语言调用BIOS中断所用的寄存器组合 regs.h.ah=0xb1; //调用PCI BIOS中断 regs.h.al=0x09; //配置空间用字的方式读入 regs.x.di=0x14; //PCI配置空间中基地址0的地址
regs.h.bl=bl; //要读入配置空间的PCI卡的设备号和功能号 regs.h.bh=bh; //要读入配置空间的PCI卡的总线号 int86(0x1a,®s,®s); //调用指定的X86中断 iobase0=regs.x.cx; //CX为返回的IO0的基地址
18
return(regs.h.ah); //返回状态 }
int getPCIbase1() {
union REGS regs; //同上 regs.h.ah=0xb1; regs.h.al=0x09;
regs.x.di=0x1c; //PCI regs.h.bl=bl; regs.h.bh=bh;
int86(0x1a,®s,®s); iobase1=regs.x.cx; return(regs.h.ah); }
int getPCImembase0() {
union REGS regs; // regs.h.ah=0xb1; regs.h.al=0x09;
regs.x.di=0x18; //PCI地址
regs.h.bl=bl; regs.h.bh=bh;
int86(0x1a,®s,®s); membase0=regs.x.cx; return(regs.h.ah); }
int getPCImembase1() {
union REGS regs; // regs.h.ah=0xb1;
配置空间基地址1的地址 同上 配置空间存储器基地址0的低位同上 19
regs.h.al=0x09;
regs.x.di=0x1a; //PCI配置空间存储器基地址0的高位地址 regs.h.bl=bl; regs.h.bh=bh;
int86(0x1a,®s,®s); membase1=regs.x.cx; return(regs.h.ah); }
int getPCIIRQ() {
union REGS regs; //同上 regs.h.ah=0xb1; regs.h.al=0x09;
regs.x.di=0x3c; //PCI配置空间中断线的地址 regs.h.bl=bl; regs.h.bh=bh;
int86(0x1a,®s,®s); return(regs.h.cl); }
int main(void) {
int err;
err=findPCIcard(); err=getPCIbase0();
iobase0=iobase0&0xfffc; //从PCI配置空间读入的与地址空间有关
的数据其bit 0位为1,
printf(\表明此空间为IO空间参与PCI总
线地址译码
err=getPCIbase1(); iobase1=iobase1&0xfffc;
printf(\
20