杜工上个礼拜就说,我们的PCI驱动程序在台湾的工控机上装不了,这周又打来电话,我只好花时间研究了一下。
首先了解一下PCI总线的资源枚举基础知识吧:
计算机的接口卡一般会用到I/O端口、存储器空间、中断及DMA等计算机资源。传统ISA接口卡通过更改跳线来避免多块卡之间的资源冲突,PCI接口卡则摒弃了硬件跳线,由软件统筹分配资源,这被称为即插即用。为实现此功能,PCI协议除了可以对I/O空间、存储器空间读写外,还定义了对配置空间的读写(C/BE0~C/BE3=1010、1011)。所谓配置空间,是指映射到每块接口卡上的256字节的特殊功能寄存器。设计者事先在配置空间的指定位置写入需要申请使用的资源量,主板上电后,由PnP-Bios读取各卡的配置空间,对它们所需的资源进行统筹分配,再将分配结果写回对应的配置空间地址,完成自动配置。
这段话提供了很重要的信息:PCI卡的资源分配动作,是由BIOS完成的。分配的实质,是将PCI的地址空间分配到PC机的虚拟地址空间,比如PCI设备有4M字节大小的存储器,那PC机肯定也要有4M的虚拟地址空间,否则PC机就访问不到PCI设备或者访问时跟别的设备冲突。
PCI总线标准的配置寄存器中有6个BAR(Base Address Register),分别命名为BAR0~BAR5,6205只用到了3个,即:BAR0、BAR1、BAR2,6205复位时,它会为为这三个BAR置不同区段的地址(因为6205知道每个区段应该预留多大的空间,因此,它预置的值可以保证不重叠),PC机上电时,BIOS读入这三个地址区段,然后在PC机地址空间找出一段地址映射给三个空间,最后又把这个映射后的空间写回给6205的配置寄存器。而BAR3、BAR4、BAR5在6205复位时,都会被预置成0,因此,BIOS若要给他们都分配空间,必定会造成地址重叠,我看到的现象正是如此!
在WINDOWS的设备管理器中,可以看到6205有三个地址区段都被映射到0x80000000-0x8fffffff,系统显示这三个区段资源冲突,板卡找不到足够的资源,因而不能工作。
后来我用windriver看了所有的寄存器,与在设备管理器中看到的结果相同。反复重装了很多遍PCI驱动,仍然无效,只好狠心把driverstudio装了一遍,调试发现,PCI驱动只接收到了4个IRP包,而且全部都是IRP_MJ_PNP包,其中三个包的minor域是IRP_MN_QUERY_INTERFACE,另外一个是IRP_MN_QUERY_CAPABILITIES,非常关键的IRP_MN_START_DEVICE包没有出现,这说明操作系统根本不认为这个设备可以被启动。
下午3点,我已经很疲惫了,我只能怀疑操作系统出问题了!
征得杜工同意以后,下午重装了工控机的系统,再插上板卡,装驱动!居然就ok了!
虽然花了1天时间,才把不是问题的问题找出来,但还是很有收获,至少我对PCI设备的资源何时分配这一点应该深信不疑了,但是疑问仍然存在,为什么那个被我格掉的系统会有资源冲突?按我上面的分析,的确应该有冲突才对,但为什么一般情况下又不会冲突?难道操作系统检查到冲突就把它忽略了?还是操作系统发现PCI设备的配置寄存器值为0,认为是非法值而不进行映射?
是windows在启动的时候又扫描了一次
发现基地址是全0,就没有给它们分配空间