戏说BIOS之PCI SCANWord下载.docx
- 文档编号:17262383
- 上传时间:2022-11-29
- 格式:DOCX
- 页数:8
- 大小:368.23KB
戏说BIOS之PCI SCANWord下载.docx
《戏说BIOS之PCI SCANWord下载.docx》由会员分享,可在线阅读,更多相关《戏说BIOS之PCI SCANWord下载.docx(8页珍藏版)》请在冰豆网上搜索。
我的视角里PCI同经典的接口编程或者插件式设计非常接近。
接口本质上是一组规则的集合它是对同类事物行为上的表示,它的主要目标是实现相同类别的不同对象行为上的多态性。
面向接口的编程是OO思想的精髓所在。
它的好处体现在哪里呢?
首先它增强了系统的灵活性,只要遵循接口定义的规则,系统的底层实现部分就可以灵活的替换、扩充如:
PCI总线定出了设备的统一的硬件接口,这样遵循该接口pcidevice就可以方便的扩展入系统;
另外相同的接口可以接入不同厂家的设备就像同样的sata接口可以接三星的光驱也可以接LG的。
其次规则给出以后,实现该接口的部件就会有共通的接口但是不同的实现,如此系统端就可以通过接口灵活实现对部件的操作配置。
PCI定义出了三种规格的配置空间,根据配置空间提供的信息系统端可以方便的识别设备的种类,功能甚至于厂商和版本号,获得非常丰富的系统端知识;
而且该功能也使得设备可以动态的配置资源进而能够做到plug&
play。
3.PCIScan
PCIConfigurationSpace是大小为256字节的一块空间,它由header和devicespecific两个部分组成,其中header部分是固定的而devicespecific部分则是与device相关的,不同的device会有不同的layout。
配置空间被用于配置,初始化以及灾难性错误处理的功能。
下图1是type00hConfigura-tionSpaceHeader:
图1
PCIScan的重要任务就是读出该256bytes配置空间,那么如何读取这部分的信息呢?
有下述两种方法:
1.使用0CF8-0CFB,0CFC这两组IOport存取PCIConfigurationSpace。
将总线号、设备号、功能号和寄存器号组合成一个双字送到配置地址端口(CF8H-CFBH),然后读写配置数据端口(CFCH)即可获得配置空间的数据,下图2是配置地址寄存器的格式定义:
图2
所以我们先要build一个config-address然后再去透过端口存取配置空间。
下述代码用于buildconfig-address:
;
----------------------------------------------------------------------------
build_pci_cfg_add:
buildpciconfigaddress
usedregisters:
eax,ebx
-----------------------------------------------------------------------------
build_pci_cfg_add
proc
near
push
eax
ebx
xor
eax,eax
xor
ebx,ebx
mov
PCI_CFG_ADDRESS,80000000h
al,PCI_BUS_NUM
shl
ax,08h
bl,PCI_DEV_NUM
bx,03h
or
ax,bx
al,PCI_FUN_NUM
eax,08h
PCI_CFG_ADDRESS,eax
pop
eax
ret
endp
config-address准备好以后接下来就是透过IOport读取pciconfigurationspace了,下述代码演示读取的过程:
read_cfg_space
readpciconfigspaceuseioport
Calledwith:
NULL
eax,edx
returnedregs:
read_cfg_spaceproc
near
mov
eax,PCI_CFG_ADDRESS
dx,PCI_CFG_APORT
out
dx,eax
dx,PCI_CFG_DPORT
in
eax,dx
ret
read_cfg_spaceendp
理论上PCIbus支持256条总线,每条总线支持32个device,每个device又支持8个function,所以我们组合出上面所有的可能就可以遍历出所有的PCI设备了。
可是实际上PC上面PCI总线通常只有1条,最多也不会超过四条所以我们只扫4条总线就可以了,不用做太多的无用功。
有了前面的准备,我们就来实现一个类似RU中的PCIscan吧,下图3就是我写的pciscan运行的状况了:
图3
在该界面下按下esc就会退出该程序;
移动↑↓键就可以选中device,然后敲enter就会看到该device的Configurationspace如下图4所示
图4
当前界面下如果想返回到上一个界面只需要按下F6就会回到图3的界面了。
2.CallPCIBIOSint1A同样也可以获取PCIdevice的信息。
其中AH=B1h,AL=functionid所有的functionid如下所示:
01h:
INSTALLATIONCHECK
02h:
FINDPCIDEVICE
03h:
FINDPCICLASSCODE
06h:
PCIBUS-SPECIFICOPERATIONS
08h:
READCONFIGURATIONBYTE
09h:
READCONFIGURATIONWORD
0Ah:
READCONFIGURATIONDWORD
0Bh:
WRITECONFIGURATIONBYTE
0Ch:
WRITECONFIGURATIONWORD
0Dh:
WRITECONFIGURATIONDWORD
0Eh:
GETIRQROUTINGINFORMATION
0Fh:
SETPCIIRQ
81h:
INSTALLATIONCHECK(32-bit)
82h:
FINDPCIDEVICE(32-bit)
83h:
FINDPCICLASSCODE(32-bit)
86h:
PCIBUS-SPECIFICOPERATIONS(32-bit)
88h:
READCONFIGURATIONBYTE(32-bit)
89h:
READCONFIGURATIONWORD(32-bit)
8Ah:
READCONFIGURATIONDWORD(32-bit)
8Bh:
WRITECONFIGURATIONBYTE(32-bit)
8Ch:
WRITECONFIGURATIONWORD(32-bit)
8Dh:
WRITECONFIGURATIONDWORD(32-bit)
8Eh:
GETIRQROUTINGINFORMATION(32-bit)
8Fh:
SETPCIIRQ(32-bit)
我们使用functionid09h就可以从configurationspace中读取出一个字,这样的操作明显简单的多了,只需call一次int1a中断即可。
下述c代码演示了读取Vendorid的过程,如需读取其它部分只要算出具体config-address即可。
#include<
stdio.h>
conio.h>
dos.h>
intmain(intargc,char**argv)
{
unionREGSreg;
argc=argc;
argv=argv;
reg.x.ax=0xB109;
reg.x.bx=0x80000000;
reg.x.di=0;
int86(0x1A,&
reg,&
reg);
if(reg.x.cx!
=0xffff)
{
printf("
Vendor:
%4.4X\n"
reg.x.cx);
}
return0;
}
程序运行结果如下图5所示:
图5
最后依旧是开放完整的sourcecode和可执行文件供有兴趣的朋友下载。
Enjoyit!
That’sall!
Peter
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 戏说BIOS之PCI SCAN 戏说 BIOS PCI
![提示](https://static.bdocx.com/images/bang_tan.gif)