PCI设备WINDOWS驱动程序的开发 - 数模混合 -
本文主要介绍了在Windows9x操作系统下开发PCI设备驱动程序的方法。
关键词:PCI设备 驱动程序
PCI设备概述
近几年来,随着诸如图形处理、图像处理、三维动画技术的发展,计算机与外设通信需要处理的数据量迅速增加,基于ISA总线的通信方式已经不能满足高速数据传输的要求,PCI局部总线的引用就是为了打破高速数据传输的瓶颈。PCI总线的英文全称是:Peripheral Component Interconnect Special Interest Group,简称PCISIG,即外部器件互连。PCI是先进的高性能局部总线,可同时支持多组外围设备,具体表现在:
(1) 以33MHz的时钟频率操作,(2) 采用32位数据总线,(3) 数据传送率可高达132MB/s;
(4) 支持突发传输,(5) 即总线主控设备(6) 发出地址之后,(7) 可以连续进行多次数据传送;
(8) 提供了配置空间,(9) 能够支持即插即用;
(10) 支持3.3V电压,(11) 有利于降低系统功耗。
为了减少开发难度,缩短开发周期,我们建议选择专用芯片。根据硬件要实现的功能,选择芯片。
以PLX公司的产品为例,PCI9052提供了5个局部地址存储空间、支持中断、支持从模式数据传输;PCI9054和PCI9080在PCI9052的基础上又增加了主模式数据传输、两个独立的DMA通道和八个邮箱寄存器等功能。
驱动程序的模式和开发工具的选择
以上是对PCI设备硬件方面的介绍,为了实现PCI设备与计算机的通信,还需要开发PCI设备驱动程序。驱动程序是用来管理系统资源的可执行二进制代码,与操作系统拥有相同的级别,不同的操作系统支持不同类型的驱动程序。目前在市场上比较流行的操作系统是Windows9x和WindowsNT这两种系列。Windows9x包括Windows95、Windows98、WindowsME;WindowsNT包括WindowsNT4.0、Windows2000。Windows95支持VXD类型的驱动程序,而WindowsNT支持WDM类型的驱动程序,Windows98兼容Windows95的VXD驱动程序,同时它又推出一个新的Win32 Drivers Mode (WDM)驱动类型。这个新的类型实际是在Windows NT的驱动模型的基础上增加了即插即用等内容。WDM驱动也可以用在Windows 2000(先前叫Windows NT5.0)中。一个完善的驱动程序应至少开发Windows 9X和Windows NT两个版本。目前,虽然Windows 2000非常流行,但由于Windows98仍占有相当规模的市场,而且它又兼容Windows95的VXD驱动程序,因此VXD驱动程序仍然实用。本文只介绍基于Windows9x系统下VXD驱动程序的开发。
VXD是虚拟设备驱动程序的简称,x 代表各种设备的名字,如虚拟键盘驱动程序(vkd),虚拟鼠标驱动程序(vmd)等等。开发驱动程序需要对硬件进行操作,由于Intel 80386以上的微处理器有4个优先级别:0级、1级、2级和3级,一般操作系统运行于优先级第0级上,而用户程序运行在第3级上,Windows9x操作系统对系统硬件采取了屏蔽的策略,限制了运行于第3级的应用程序对系统资源(如中断控制器、内存等)的操作。但VXD运行在最高级特权级——第0级,拥有操作系统的特权,可以超越这些屏蔽,直接进行系统硬件的操作。
开发设备驱动采用的主要开发工具是微软为设备开发者提供的软件包Device Driver Kit (DDK)。这个软件包包括有关设备开发的文档、编译需要的头文件和库文件、调试工具和程序范例。在DDK中还定义了一些设备驱动可以调用的系统底层服务,如DMA服务、中断服务、内存管理服务、可安装文件系统服务等等。这些都是编写设备驱动所必须的。但由于Windows 95的DDK主要使用汇编语言描述,代码可读性不强,开发起来比较困难。因此,我们在Windows 9x操作系统中采用了Numega公司的产品VtoolsD。VtoolsD是基于C/C++的,支持Borland C++和Visual C++,代码可读性强,使用和维护都较Windows DDK容易。
驱动程序的设计
编写设备驱动程序的目的是使被驱动的硬件可以管理系统资源,与PC机系统兼容,正常工作,通过设备驱动程序,多个进程可以同时使用这些资源(如内存、I/O、中断源等),实现多进程并行运行。驱动程序是针对具体硬件设计的,不同硬件有不同的驱动程序,下面仅讨论开发驱动程序几个必要的通用的步骤。
1、PCI配置空间简介
每个PCI设备都有自己的配置空间,用于支持即插即用,使之满足现行的系统配置结构。下面对PCI配置空间做一下简要介绍。
配置空间是一容量为256字节并具有特定结构的地址空间。这个空间又分为头标区和设备有关区两部分。头标区的长度是64字节,每个设备都必须配置该区的寄存器。该区中的各个字段用来唯一地识别设备。其余的192字节因设备而异。配置空间的头标区64个字节的使用情况如图1示。
为了实现即插即用,系统可根据硬件资源的使用情况,为PCI设备分配新的资源。因此编写设备驱动程序重点是获得基址寄存器(Base Address)和中断干线寄存器的内容。配置空间共有六个基址寄存器和一个中断干线寄存器,具体用法如下:
PCI Base Address 0寄存器:系统利用此寄存器为PCI接口芯片的配置寄存器分配一段PCI地址空间,通过这段地址我们可以以内存映射的形式访问PCI接口芯片的配置寄存器。
PCI Base Address 1寄存器:系统利用此寄存器为PCI接口芯片的配置寄存器分配一段PCI地址空间,通过这段地址我们可以以I/O的形式访问PCI接口芯片的配置寄存器。
PCI Base Address 2、3、4、5寄存器:系统BIOS利用这些寄存器分配PCI地址空间以支持PCI接口芯片的局部配置寄存器0、1、2、3的访问。
在所有基址寄存器中,第0位均为只读位,表示这段地址映射到存储器空间还是I/O空间,如果是“1”表示映射到I/O空间,如果是“0”则表示映射到存储器空间。
中断干线寄存器(Interrupt Line):用于说明中断线的连接情况,这个寄存器的值与标准8259的IRQ编号(0~15)对应。
设备识别号 供应商识别号
状态寄存器 命令寄存器
分类代码 修改版本
自测试 头标类型 延时计数 Cache
基址寄存器
保留
保留
扩展ROM基址寄存器
保留
保留
Max-Lat Min-Gnt中断引脚 中断干线
图1 配置空间头标区
2、设备初始化
PCI设备驱动程序要完成识别PCI器件、分配PCI硬件资源、响应PCI器件中断等功能,这就需要访问PCI配置空间来获得必需的参数。实现在Windows9x操作系统下访问PCI配置空间可以利用PCI系统BIOS功能调用,通过供应商识别号(VendorID)和设备识别号 (DeviceID)直接访问设备,也可以利用配置管理器(Configuration Manager)封装的功能函数,根据供应商识别号(VendorID)和设备识别号 (DeviceID)搜索设备结点树,查询PCI设备。由于编写PCI系统BIOS功能调用程序更为简捷,所以本文采用这种方法。
PCI系统BIOS功能提供了BIOS的访问与控制的具体方法,所有软件(设备驱动程序、扩展ROM码)将通过标准中断号1AH调用BIOS功能访问特殊部件。在驱动程序中调用VtoolsD系统服务Exec_VxD_Int()来实现PCI系统BIOS的1AH中断。
首先,通过PCI设备的供应商识别号(VendorID)、 设备识别号 (DeviceID)和索引号(Index)查找特定设备所在的总线号(Bus Num)、设备号(Device NUM)、功能号(Function Num)和寄存器号(Register Num)。总线号是从0到255的数值,在一个系统中,可把多达256条的PCI总线用桥连接在一起。由于编号是从0开始的,所以当系统有N条总线时,总线号会达到N-1;设备号是在0到31之间分配的任意值,并不拘于从0开始按顺序分配;功能号分配从0到7的值。代码如下:
ALLREGS* pRegisters; // pRegisters是指向寄存器结构体的指针
pRegisters->REAX =0xb102; // 0xb102是功能号
pRegisters->RECX =0x1001; // 假设Device ID=0x1001
pRegisters->REDX=0x102b; // 假设Vendor ID=0x102b
Exec_VxD_Int(0x1a,pRegisters); // 调用1AH中断
返回值是pRegisters->REBX。BH寄存器是总线号,BL寄存器的高5位是设备号,低3位是功能号。
然后,向配置空间地址寄存器CF8h写入总线号、设备号、功能号、索引号, 从配置空间数据寄存器CFCh读出配置空间的内容。
配置空间地址寄存器(CF8h)格式如下:
Bit31 30-24 23-16 15-11 10-8 7-2 10
使能位 保 留 总线号 设备号 功能号 寄存器号 00
使能位为“1”表示允许访问
配置空间数据寄存器(CFCh)存放要读写的数据。
代码如下:
DWORD d=0;
d=pRegisters->REBX;
(d<<=8)|=0x80000000;
for (short i=0;i<16;i++) // 读取64字节配置空间
{
_outpd(0xcf8,d+4*i); // 按DWORD类型一次读取四个字节
dprintf("%8x",_inpd(0xcfc)); // 打印输出
}
3、内存的读写
Winsows工作在32位保护模式下,保护模式与实模式的根本区别在于CPU寻址方式上的不同,这也是Windows驱动程序设计中需要着重解决的问题。Windows采用了分段、分页机制,这样使应用程序产生一种错觉,好象程序中可以使用非常大的物理存储空间。这样做最大的好处就是一个程序可以很容易地在物理内存容量不一样的、配置范围差别很大的计算机上运行,编程人员使用虚拟存储器可以写出比任何实际配置的物理存储器都大得多的程序。每个虚拟地址由16位的段选择字和32位段偏移量组成。通过分段机制,系统由虚拟地址产生线性地址。再通过分页机制,由线性地址产生物理地址(如图2)。线性地址被分割成页目录(Page Directory)、页表(Page Table)和页偏移(Offset)三个部分。当建立一个新的Win32进程时,操作系统会为它分配一块内存,并建立它自己的页目录、页表,页目录的地址也同时放入进程的现场信息中。当计算一个地址时,系统首先从CPU控制器CR3中读出页目录所在的地址,然后根据页目录得到页表所在的地址,再根据页表得到实际代码/数据页的页帧,最后再根据页偏移访问特定的单元。硬件设备读写的是物理内存,但应用程序读写的是虚拟地址,所以存在着将物理内存地址映射到用户程序线性地址的问题。
查看评论 回复
"PCI设备WINDOWS驱动程序的开发 - 数模混合 -"的相关文章
- 上一篇:SCI接口电路 - 数模混合 -
- 下一篇:pci卡设计心得 - 数模混合 -