📄 subject_51661.htm
字号:
<p>
序号:51661 发表者:佳雨 发表日期:2003-09-03 11:09:27
<br>主题:请教:如何获取PCI卡资源?
<br>内容:我近期要开发一PnPPCI卡驱动,我需要知道该卡的资源,如中断口,I/O口等,却不知道如何获得该卡资源.有那位做过的,请指点迷津,不胜感谢!
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:lonehawk 回复日期:2003-09-03 12:46:11
<br>内容:这个问题应该属于PCI配置空间的问题。通常情况下,在PCI卡上面的EPROM中间会标志出硬件所需要的资源,例如中断或者I/O。对于一个支持PnP的卡来说,这个不是定死的,而是可选的。当卡插到PCI总线上以后,总线会把每一个硬件的信息都映射到内存的一块区域中间,当然这就包含了vendor ID、device type和资源要求等等。这块空间就叫着PCI配置空间。<BR>你想知道的硬件的信息就是要读这个配置表。则是一个比较常见的问题,虽然和操作系统的平台有关,但是都不是太难实现。转一篇文章给你吧。<BR><BR><BR>发信人: ohg2001 (戒指~~铁杆~~DDK), 信区: WinDDK <BR>标 题: nt/2000pci设备驱动程序详解1 <BR>发信站: BBS 水木清华站 (Tue Apr 3 04:58:37 2001) <BR><BR>发信人: huyuguang (不再困惑), 信区: SysInternals WWW-POST <BR>标 题: nt/2000pci设备驱动程序详解 <BR>发信站: 武汉白云黄鹤站 (Fri Oct 6 15:25:41 2000) , 站内信件 <BR>常常有朋友问我关于pci驱动程序的问题,但是在和他们的交谈中 <BR>我发现有一些问题非常重复,也没有什么特别的地方(真有什么特别 <BR>的地方,我也搞不定:-)),对于一些问题,其实卡的结构非常 <BR>普通,只要熟悉pci驱动程序的一些基本概念就可以解决的。 <BR>下面我把pci驱动程序的一些基本概念整理整理:首先讲一讲pci的配置空间。 <BR>这个概念本来是非常简单的,但是我这个有灌水的爱好,为了让文章能够 <BR>更成体系,加上这一段。 <BR>pci的配置空间的结构不在这里重复,任何一本pci的书里都有。 <BR>对于pci的配置空间操作,我用过的操作系统中,linux下是最简单的, <BR>linux提供了许多函数,细节可看linux device driver。 <BR>我在这里简单的给出一个操作x86结构下pci的方法就结束这一段。 <BR>我在写第一个pci driver的时候是在dos下,最早我操作pci的方法就是用 <BR>int 1a,需要bios支持,现在的主板是没有不支持得了。后来我发现了另外 <BR>一种方法,更为简单,int 1a的方法就记不得了,如果想知道,可以去查 <BR>int 1a中断,要96年以后的书(int 1a是时钟,但是扩展为pci操作)。 <BR>由于不同操作系统提供的函数不同,使得代码可移植性变差,其实这些实现 <BR>几乎都是基于BIOS的int 1a中断调用。由于在不同系统中调用1a中断的实现 <BR>也很不相同,而且一般都需要写驱动程序。下面是我写的一个通用的操作PCI <BR>配置空间的程序如下,该方法和int 1a内部机制相同,都是基于PCI规范实现 <BR>的,只用到了端口操作。代码如下: <BR>#include "stdio.h" <BR>#include "windows.h" <BR>DWORD DWORD_In(WORD io_Port) <BR>{ DWORD val; <BR> _asm { <BR> mov dx,io_Port <BR> in eax,dx <BR> mov val,eax <BR> } <BR> return val; <BR>} <BR>DWORD DWORD_Out(WORD io_Port,DWORD val) <BR>{ <BR> _asm { <BR> mov dx,io_Port <BR> mov eax,val <BR> out dx,eax <BR> } <BR> return 0; <BR>} <BR>int main() <BR>{ <BR> DWORD io_CF8; // port 0xcf8 <BR> DWORD io_CFC; // port 0xcfc <BR> int i; <BR> io_CF8=0x80000000; //because the first bit is enable/disable <BR> for(;;) //so must be 1,so from 0x800000000 <BR> { <BR> DWORD_Out(0xcf8,io_CF8); <BR> io_CFC=DWORD_In(0xcfc); <BR> if (io_CFC!=0xffffffff) //if =0xffffffff,then is a invalid <BR> { //bus number and device number <BR> printf("\nPCI device has found,the pci config address=%lx\n",io_ <BR>CF8) <BR>; <BR> printf("its Bus Numer is %lx \n",(io_CF8&0x00ff0000) <BR>/0x1 <BR>0000); <BR> printf("its Device Number is %lx \n",(io_CF8&0x0000f <BR>800) <BR>/0x800); <BR> printf("its Functin Number is %lx \n",(io_CF8&0x700) <BR>/0x1 <BR>00); <BR> printf("this device's deviceID and vendorID=%lx\n",i <BR>o_CF <BR>C); <BR> for (i=0 ;i<=15;i++) <BR> { <BR> DWORD_Out(0xcf8,io_CF8+4*i); //read DWORD <BR> switch (i) <BR> { <BR> case 0: <BR> printf("Device Number and Vendor Number =%lx"); <BR> break; <BR> case 1: <BR> printf("Status and Command ="); <BR> break; <BR> case 2: <BR> printf("Class Code and Revision ID="); <BR> break; <BR> case 3: <BR> printf("Bist and Header Type and Latency Tim <BR>er a <BR>nd Cacne Line <BR>Size="); <BR> break; <BR> case 4: //PCI Configration has 6 base addres <BR>s <BR> case 5: //register <BR> case 6: <BR> case 7: <BR> case 8: <BR> case 9: <BR> printf("Base Address Register="); <BR> break; <BR> case 10: <BR> case 11: <BR> case 13: <BR> case 14: <BR> printf("Reserved ="); <BR> break; <BR> case 12: <BR> printf("Expansion ROM Base Address="); <BR> break; <BR> case 15: //attention:the interrupt IRQ= this result&0xff <BR> printf("Max_Lat Min_Gnt Interrupt Pin Interr <BR>upt <BR>line="); <BR> break; <BR> } <BR> printf("%lx\n",DWORD_In(0xcfc)); <BR> } <BR> } <BR> io_CF8+=0x800; <BR> if (io_CF8>=0x80FFFF00) <BR> break; <BR> } <BR> return 0; <BR>} <BR>这个程序是我97年的时候写的,后来就没有改过,在各种场合下用过很多次,我一般在 <BR>写pc <BR>i <BR>driver for 9x/nt的时候都要先用它来scan一遍pci空间,看看硬件有没有问题。 <BR>程序中用到了双字读写,这个似乎c库中不提供,不过没有关系,简单的写一个小汇编就 <BR>解?<BR> 了。 <BR>这个程序可以在9x和dos下用,因为nt对于所有的io操作都是禁止的,所以在nt下,需要 <BR>写?<BR>桓?<BR>小sys,提供io操作。9x对于部分io操作也是禁止的,不过这里用到的cf8,cfc <BR>没有禁止。 <BR>资料来源:我当时手头上的一本PCI2.1规范,我没有遇到过PCI66M,64bit的卡(好像是P <BR>CI2. <BR>2), <BR>还有一点要说明的是,9x/nt都是提供包装的更好,更安全的系统函数来读写pci配置空 <BR>间, <BR>但是 <BR>如果不考虑什么兼容性,这些代码完全可以用在9x/nt的驱动程序里面。linux就没有必 <BR>要, <BR>因为, <BR>linux下提供的函数不像nt的那样晦涩,非常易懂。<BR><BR>不一定和你的问题完全一样,但是解决的思路都差不多。想学驱动的话,推荐你几个地方:<BR>水木清华DriverDev版、白云黄鹤WinDrvProgram版和驱动开发网都可以。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -