视频微端口驱动程序

 Windows NT/Windows 2000视频微端口驱动程序(Video Miniport Driver)是特定适配器的、内核模式的驱动程序。每一种可在Windows NT/Windows 2000中应用的图形卡都必须有视频微端口驱动程序和显示驱动程序。

        视频小驱动程序将它自身链接到视频端口驱动程序上,视频端口驱动程序是一个系统提供的内核模式的动态链接库(DLL)。视频端口驱动程序的VideoPortXxx函数调用微端口驱动程序来与系统及它的硬件进行通信。

        Windows 2000微端口驱动程序必须以即插即用(PnP:Plug and Play)的驱动程序来实现。Windows 2000视频端口驱动程序同时继承性地支持Windows NT 4.0驱动程序。

        本章提供了视频微端口驱动程序实现及编写的详细资料,描述了微端口驱动程序与显示驱动程序以及视频端口驱动程序的交互操作。对所有视频端口和微端口驱动程序的函数参考可以在图形驱动程序参考的在线DDK中查到。

        显示驱动程序将主要在第一章显示介绍及第二章显示驱动程序中讨论。

 

6.1视频微端口头文件、示例代码及参考

        Windows NT/Windows 2000视频微端口驱动程序包括下列头文件:

        文件                                                                   内容

 

dderror.h 

由微端口驱动程序返回给视频端口驱动程序的win32状态常量,也可以返回到与微端口驱动程序对应的内核模式显示驱动程序

devioctl.h 

用于定义I/O控制代码的宏及常量

miniport.h

视频微端口和SCSI微端口驱动程序所需的基本类型、常量和结构

ntddvdeo.h

系统定义的I/O控制(IOCTLs)以及相应的结构等,可以按视频请求包VRPs传送到视频微端口驱动程序。

tvout.h

用于实现TV连接以及拷贝保护支持的VIDEOPARAMETERS结构以及此结构中使用的常量

video.h

VideoPortXxx和SvgaHwIoPortXxx视频端口函数声明。视频专用的结构如VIDEO_REQUEST_PACKET以及HwVidXxx视频微端口函数原型

videoagp.h

AGP专用的结构,AgpXxx微端口驱动程序函数原型。以及支持视频微端口驱动程序的实现图形端口(AGP:Accelerated Graphics Port)加速所需的VideoPortXxx函数声明

DriverEntry 

初始化视频微端口驱动程序

HwVidFindAdapter 

获取设备可枚举的总线的范围,如果可能,确定设备的类型。

HwVidGetPowerState

查询设备是否可以支持需要的电源状态

HwVidGetVideoChildDescriptor

枚举附加于特定设备的子设备

HwVidInitialize 

执行以前的对于相应的显示驱动程序的适配器的初始化。该函数调用是作为打开适配器的请求的响应。

HwVidSetPowerState

设置特定设备的电源状态

HwVidStatrtIO

开始处理进入的VRP

HwVidInterrupt

处理适配器产生的中断,如果微端口驱动程序的适配器产生中断则该函数是必需的。

HwVidResetHw

重新设置适配器到字符模式,这样HAL可以在系统被控制宕机或崩溃时显示系统的关闭信息,或者在软启动时显示初始化信息。如果适配器的寄存器不能自动设定为INT 10复位,该函数是必需的。

HwVidSynchronizeExecutionCallback  

同步存取由HwVidInterrupt中断所共享的数据。允许关键部分的代码以更高的软件或硬件优先级别运行(IRQL,具有设备或系统中断屏蔽)。如果与HwVidInterrupt小驱动程序函数共享,则它是必需的。

HwVidLegacyResources

返回一个特殊设备的继承资源

HwVidQueryDeviceCallback    和/或

HwVidQueryNamedValueCallback

处理存储在寄存器中的配置信息。该函数在小驱动程序的HwvidFindAdpter函数利用I/O总线类型专用的配置信息或驱动程序提供的默认值时是可选的。

HwVidQueryInterface 

返回一个微端口驱动程序实现的函数接口,该函数接口可以由子设备来调用

HwVidTimer 

由视频微端口驱动程序大约隔一秒钟周期性调用一次

SvgaHwIoPortXxx 函数

由基于x86的全屏的MS-DOS应用程序校验存取I/O端口的有效性,这些函数是对VGA兼容的SVGA微端口驱动程序。可以参考VGA兼容的微端口的SvgaHwIoPortXxx获取更多的信息。

Chip type

HardwareInformation.ChipType

包含芯片名称的以NULL结尾的字符串

DAC type

HardwareInformation.DacType

包含DAC名称或ID的以NULL结尾的字符串

Memory Size

HardwareInformation.MemorySize

包含ULONG,以MB为单位,适配器上视频内存的总量

Adapter ID

HardwareInformaiton.AdapterString

包含适配器名称的以NULL结尾的字符串

BIOS  

HardwareInformation.BiosString  

包含BIOS信息的以NULL结尾的字符串

HwLegacyResourceList  

指向一个VIDEO_ACCESS_RANGE结构,每一个结构描述了视频驱动程序未列入PCI配置空间的设备I/O端口或者内存区间。

HwLegacyResourceCount

HwLegacyResourceList指向的数组所包含的元素个数

                       

        这些头文件与Windows 2000 DDK一起发布。需要包含在这些头文件中的函数、结构、系统定义的I/O控制代码、常量的更详细信息,可参考在线DDK中图形驱动程序参考部分的内容。

        Windows 2000 DDK同样提供好几个视频微端口驱动程序工作的实例代码,其内容放在video/miniport目录下。3dlabs微端口驱动程序实例实现了广泛的功能;s3virge微端口驱动程序实例则实现了VPE;mirror实例则包含该驱动程序专用的微端口驱动程序实现。

 

6.2在图形体系结构中的视频微端口驱动程序

        图 6-1显示了Windows NT/Windows 2000图形子系统中的视频微端口驱动程序。

 

        插入图6-1  Windows NT/Windows 2000图形体系结构

 

        每一个视频微端口驱动程序提供硬件级的显示驱动程序支持,显示驱动程序调用图形引擎函数EngDeviceIocontrol请求下面的视频微端口驱动程序支持,并依次调用一个I/O系统服务以通过视频端口驱动程序向微端口驱动程序发送请求。

        在大多数情况下,显示驱动程序完成对用户可见的时间关键的操作,而其下层的微端口驱动程序则提供对非经常性请求操作的支持,或者提供对不能被中断或设备环境转换到另外一个进程所剥夺的真正的时间关键性操作的支持。

        显示驱动程序不能支持设备中断,只有微端口驱动程序可以建立起设备内存并将它映射到显示驱动程序的虚拟地址空间。

        视频端口驱动程序是系统提供的用于支持视频微端口的驱动程序模块,并充当显示驱动程序与视频微端口驱动程序之间的中介。

        要获得更多的Windows NT/Windows 2000的显示驱动程序的信息,参考第一章显示介绍及第二章显示驱动程序中的内容。

 

6.2.1视频微端口驱动程序特定平台的详细内容

        在基于x86的Windows NT/Windows 2000平台,有两种视频微端口驱动程序:非VGA兼容微端口驱动程序和VGA兼容微端口驱动程序。

 

6.2.1.1VGA兼容、基于x86的微端口驱动程序

        许多微端口驱动程序是非VGA兼容的并因此非常容易实现。非VGA兼容的视频微端口驱动程序依赖于系统提供的VGA微端口驱动程序(vga.sys)或另外一个当前装载的VGA兼容的SVGA微端口驱动程序。这些微端口驱动程序的设置是在registry注册文件中将vgacompatible设置为零(FALSE)并且具有以下特征:

它对全屏的、基于X86机器的MS-DOS应用程序不支持。但是,它是随着系统提供VGA(或者可能是VGA兼容的SVGA)微端口驱动程序的装载来提供对全屏的MS-DOS应用程序的支持。

在大多数情况下,它是对没有VGA兼容模式适配器而编写的或者是为独立工作于VGA的加速器而编写的。

 

6.2.1.2VGA兼容的基于x86的微端口驱动程序

        VGA兼容的微端口驱动程序主要包括以下特点:

它基于系统提供的VGA微端口驱动程序,可以修改一定的代码来支持特定适配器的特性。系统提供的VGA显示驱动程序利用VGA兼容的微端口驱动程序支持,这样VGA兼容的适配器的微端口驱动程序开发者就不需要再编写新的显示驱动程序。

它提供全屏MS-DOS应用程序的支持可以直接对适配器寄存器进行I/O操作。它同时作为一个视频检验器以防止这些应用程序发布任何使系统中止的指令序列。

        许多SVGA适配器的微端口驱动程序也归入此类。但是对非SGVA适配器的任何新的微端口驱动程序可以根据驱动程序设计者的判断来提供VGA兼容支持。

        VGA兼容的微端口驱动程序可以由在注册表中的vgacompatible设置成为1(TRUE)来配置。

 

6.3视频微端口驱动程序接口

        接下来的部分枚举了构成视频微端口驱动程序接口的函数,一些函数是必需的,其他的函数有的是有条件的,有的是可选择的。而它们在微端口驱动程序中的包含则取决于适配器的特性和驱动程序的开发者。

        除了DriverEntry函数,本文档建议对每一个必需的标准的微端口驱动程序都用假名。换句话说,即给出的每一个标准的微端口驱动程序除DriverEntry之外都可以由微端口驱动程序的开发者任意选择。

 

6.3.1必需的微端口驱动程序函数

        以下系统定义的函数必须在每一个视频微端口驱动程序中实现。除了DriverEntry函数,所有其他的微端口驱动程序都是按字母顺序排列的。

    必需的函数                                                           描述

 

6.3.2一定条件下必需的视频微端口驱动程序函数

        下面的系统定义的函数是在一定条件必需的视频微端口驱动程序函数。依赖于给定的适配器的特征及驱动程序的设备。它们同样按字母顺序排列:

    一定条件下必须的函数                                       描述

 

       

6.3.3可选的视频微端口驱动程序

        下面的系统定义的函数可以在视频微端口驱动程序中选择性地实现,函数以字母顺序排列。

 可选函数                                                                  描述

     

6.4视频微端口驱动程序初始化

        视频微端口驱动程序初始化发生在NT内核、HAL及核心驱动程序如PCI总线驱动等装载及初始化之后。基本的系统初始化发生顺序如下:

■NT内核及HAL加载并初始化。

内核驱动程序如PCI总线驱动程序加载并初始化。

■PCI总线驱动程序从每个子PCI的配置空间获得PCI资源信息及设备ID、供应商ID,并将这些信息报告给系统。

如果PnP管理识别出设备或供应商的ID,I/O管理器将从已知的位置加载相应的视频微端口驱动程序和视频端口驱动程序。如果PnP管理器不能识别出这些ID,则它给用户提示加载微端口驱动程序的位置。

■I/O管理器用两个系统提供的指针调用微端口驱动程序的DriverEntry例程。DriverEntry用驱动程序特定及适配器专用的值分配并初始化一个VIDEO_HWINITIALIZATION_DATA结构,包括指向微端口驱动程序其他条目的指针。DriverEntry也必须声明其他继承资源,这些资源没有被列入设备PCI配置空间但是由设备进行解码。可参考声明遗资源部分获得更详细信息。

微端口驱动程序的DriverEntry函数调用VideoPortInitalize函数。VideoPortInitialize执行微端口驱动程序初始化方面的工作,这是对所有的微端口驱动程序者非常一般性的工作。例如,对非即插即用的驱动程序,VideoPortInitialize验证微端口驱动程序初始化的VIDEO_HW_INITIALIZATION的结构,初始化一些系统产生的设备对象的公有成员,并对这些设备对象及扩展对象分配内存,收集并存储相关的扩展设备的信息。可以参见视频微端口驱动程序扩展部分获得更详细的信息。对即插即用的驱动程序来说,设备的对象相关动作则发生在以后的时间里。

如果VideoPortInitialize返回,DriverEntry将其返回值再传播给VideoPortInitialize调用者。微端口驱动程序开发者应当对VideoPortInitialize的返回值不作任何的假设。

        在这一点上来说,系统已经装载并且初始化了视频微端口驱动程序。下一步就是PnP管理器启动设备,可参考启动视频微端口驱动程序部分了解详细内容。

 

6.4.1启动视频微端口驱动程序

        PnP管理器向视频端口驱动程序发送IRP消息请求启动图形适配器,视频端口驱动程序分派HwVidFindAdapter例程对IRP响应,HwVidFindAdapter的详细任务的讨论将在本部分的后面内容中叙述到。

■6.4.1.1建立视频适配器存取区间

■6.4.1.2设置注册表中的硬件信息

■6.4.1.3改变适配器中的状态

 

6.4.1.1建立视频适配器存取区间

        一个VIDEO_ACCESS_RANGE类型的元素数组描述一个视频适配器解码内存和/或I/O端口的一个或多个区间,在这个数组中的每个存取区间元素都包含总线相关的物理地址值。

        微端口驱动程序例程HwVidFindAdapter例程必须声明所有的PCI内存及端口或者适配器可以响应的所有区间的端口。依赖于适配器及在VIDEO_PORT_CONFIG_INFO中的AdapterInterfaceType值,HwVidFindAdapter可以调用下面VideoPortXxx函数以得到必要的总线相关的配置数据:

■VideoPortGetAccessRanges

■VideoPortGetBufData

■VideoPortGetDeviceData

■VideoPortGetRegistryParameters

■VideoPortVerifyAccessRanges

        如果HwVidFindAdapter不能通过调用VideoPortGetBusData或VideoPortGetAccessRanges函数,或者利用VideoPortGetDeviceData或VideoPortGetRegistryParameters函数从寄存器中得到总线相关的可存取区间的相关信息,微端口驱动程序应当有一套总线相关的存取区间的默认值。

        小驱动程序试图与适配器通信之前,HwVidFindAdapter函数应当映射每一个声明的总线相关的物理地址区到用VideoPortGetDeviceBase函数得到的内核模式的地址空间的区间。HAL能够将总线相关的存取区间值重新映射到系统地址的逻辑地址区间,尤其是在多条总线的机器中。

        利用映射的逻辑区间地址,驱动程序可以调用VideoPortReadXxx和VideoPortWriteXxx函数以读或写到一个适配器,这些内核模式的地址也可以被传递到VideoPortCompareMemory,VedeoPortMoveMemory,VideoPortZeroDeviceMemory和/或VideoPortZeroMemory。对一个被映射的I/O空间中的区间来说,微端口驱动程序调用VideoPortReadPortXxx和VideoPortWriterPortXxx函数。对一个在内存中映射的区间来说,微端口驱动程序调用VideoPortReadRegisterXxx及VideoPortWriterRegisterXxx函数。

        HwVidFindAdapter函数应当总是在调用VideoPortGetDeviceBase函数之前成功调用VideoPortVerityAccessRanges或者VideoPortGetAccessRanges。

任何对VideoPortVerifyAccessRanges或VideoPortGetAccessRanges的成功调用将建立起一个微端口驱动程序的声明,即声明特定总线的视频内存和寄存器地址或适配器在注册表中的I/O端口。非常值得注意的是接下来对VideoPortVerityAccessRanges或VideoPortGetAccessRanges的任何顺序的调用都会导致驱动程序以前声明的资源被删除或者传送给最近调用函数的值所代替。因此,如果驱动程序单独调用函数声明区间,它必须传递到所有区间的数组,包括那些已经声明的区间。

■HwVidFindAdapter可以从适配器要求一小部分的存取区间,利用这一小部分区间来决定该适配器是否是微端口驱动程序支持的,并且利用另外一个函数调用VideoPortGetAccessRanges或者VideoPortVerityAccessRanges要求一个全部的对适配器支持的存取区间。同样的,对某专用的适配器的这些VideoPortAccessRanges例程的成功调用,都会导致调用者以前在注册表中声明的信息覆盖。

声明其他类型的硬件资源,如中断向量,一个微端口驱动程序应当在VIDEO_PORT_CONFIG_INFO中设置合适的值并调用VideoPortVerityAccessRanges或它应当调用VideoPortGetAccessRanges函数。

VideoPortGetAccessRanges或VideoPortVerifyAccessRanges的成功调用保证了微端口驱动程序不去使用已经由另外一个驱动程序使用的寄存器或设备内存地址。

在寄存器中声明适配器的总线相关硬件资源,防止后来加载的驱动程序企图利用其他适配器的同一存取区间(即其他硬件地址)。它同样防止按顺序装载的驱动程序更改视频适配器的初始状态。

        硬件解码的微端口驱动程序继承资源时必须通过它的DriverEntry例程来声明,或者,如果实现,则必须通过HwVidLegacyResources例程,继承资源是那些没有列入设备的PCI配置空间但由设备解码的资源。可以参考声明继承资源部分获得详细内容。

        在微端口驱动程序装载之后,它的HwVidInitialize函数便已经运行,微端口驱动程序的HwVidStartIO函数调用,以映射那些微端口驱动程序对显示驱动程序可见的视频内存存取区间。

 

6.4.1.2在注册表中设置硬件信息

        HwVidFindAdapter可以调用VideoPortGetRegistryParameters及VideoPortSetRegistryParameters函数来获得并设置注册表中的配置信息。例如,HwVidFindAdapter可以调用VideoPortsSetRegistryParameters来设置下一次启动时非易失性的注册表配置信息。也可以调用VideoPortGetRegistryParameters来获得由一个安装程序写入到注册表中特定适配器的、总线相关的配置参数。

        推荐使用通过微端口驱动程序设置注册表中的一定的硬件信息,来向用户显示有用的信息或在调试时显示信息。微端口驱动程序可以设置芯片类型、DAC类型、适配器内存大小、鉴别适配器的字符串等,这些信息都是通过控制面板(Control Panel)的显示小应用程序来显示的。

        驱动程序通过调用VideoPortSetRegistryParameters函数来设置这些信息,而且通常是驱动程序在它的HwVidFindAdapter例程中调用。

        下表描述了驱动程序可以注册并提供的VideoPortSetRegistryParameters中ValueName和ValueData参数的详细信息:

条目信息                                        ValueName                                      ValueData

 

     

6.4.1.3改变适配器的状态

        微端口驱动程序在调用HwVidInitialize例程之前不能永久性改变适配器的状态。微端口驱动程序例程在HwVidInitalize函数之前调用,如HwVidFindAdapter函数,它不能改变任何不需要的视频适配器的状态并且不能永久性改变任何视频适配器的状态。

        当HwVidFindAdapter运行时,HAL已经控制了视频适配器,因此它可以在系统启动的早期阶段将信息写到屏幕上。如果HwVidFindAdapter试图签别适配器是否影响适配器状态,这一例程应当立即恢复原先的状态信息。因此一经HwVidFindAdapter返回,HAL就可以继续显示启动的消息。

        例如,HwVidFindAdapter应当推迟决定一个适配器的DAC类型到HwVidInitalize函数,由于做这一决定并不会影响微端口驱动程序是否已经被装载,但是永久性地改变了适配器的状态。

 

6.4.2声明继承资源

        视频微端口驱动程序必须在驱动程序初始化过程中在VIDEO_HW_INITIALIZATION_DATA结构中声明并报告所有的继承资源。继承资源是那些没有列在PCI配置空间但由设备解码的资源。Windows NT/Windows 2000遇到那些没有在本部分以提纲形式列出的未报告的继承资源时,将禁止电源管理及停靠功能。

        微端口驱动程序必须在报告继承资源时做如下事情:

如果对设备列出的继承资源在编译时可知,则将填充VIDEO_HW_INITIALIZATION_DATA结构中的两上字段,它是在DriverEntry例程中创建和初始化的。

结构成员                                                           定义

如果列出的设备的继承资源在编译时是未知的,则实现一个HwVidLegacyResources函数,初始化VIDEO_HW_INITIALIZATIONH_DATA结构的GetLegacyResources成员并指向该函数。例如,一个支持具有不同继承资源设置的两个设备微端口驱动程序可以实现HwVidLegacyResources以在运行时报告继承资源。小视频端口驱动程序实现HwVidLegacyResources函数时,视频端口驱动程序将忽略VIDEO_HW_INITIALIZATION_DATA结构的HwLegacyResourceList及HwLegacyResourceCount成员。

根据微端口驱动程序的定义,对每一个VIDEO_ACCES_RANGE结构填充其RangePassive字段值。设置RangePassive为VIDEO_RANGE_PASSIVE_DECODE意味着该区由硬件进行解码,但是显示及视频微端口驱动程序将永不会接触到它。设置RangePassive为VIDEO_RANGE_10_BIT_DECODE意指设备对该区的端口地址进行10位解码。

        同样,驱动程序应当包括一种由硬件解码的但没有被PCI声明的资源。驱动程序中声明的较小的继承资源的代码也许看起来如下边代码所示:

 

        //      RangeStart      RangeLength

        //      |           |   RangeInIoSpace

        //      |           |   |    RangeVisible

        //     +……+……+          |  |    |    RangeShareable

        //    low           high        |   |    |    |    RangePassive

        //      v                   v                            v            v   v   v    v

        VIDEO_ACCESS_RANGE    AccessRanges[]={

    //[0]  (0x3b0-0x3bb)

    {0x000003b0,0x00000000,0x000000c,1,1,1,0},

    //[1](0x3c0-0x3df)

    {0x000003c0,0x0000000,0x00000010,1,1,1,0},

    //[2](0xa0000-0xaffff)

    {0x000A0000,0x00000000,0x00010000,1,0,0,0},

    };

 

    //Within the DriverEntry routine:

    VIDEO_HW_INITIALIZATION_DATA  hwInitData;

    hwInitData.HwLegacyResourceList=AccessRanges;

    hwInitData.HwLegacyResourceCount=3;

 

        微端口驱动程序可以按顺序调用VideoPortVerityAccessRanges重声明继承资源。但是,视频端口驱动程序简单地忽略任何以前声明的继承资源。如果微端口驱动程序企图在VideoPortVerifyAccessRanges声明一个继承存取区间,但是并没有在DriverEntry的HwlegacyResourceList中声明过或通过hwVidLegacyResources的legacyResourceList参数返回时,将不支持电源管理及停靠管理。

 

6.4.3初始化视频微端口与显示驱动程序的通讯

        对每一个由PnP管理器发现的适配器,都可以由微端口视频驱动程序进行成功的配置,微端口驱动程序的HwVidInitialize函数在相应的显示驱动程序加载时调用。HwVidInitialize可以初始化软件的状态信息,但是它不应当配置成适配器上的可见状态信息。对HwVidInitialize函数返回,适配器应当设置成与微端口驱动程序的HwVidResetHw例程返回值相同的状态值。更多的HwVidResetHw信息,参考重新设置视频微端口驱动程序部分。

        如果需要,微端口驱动程序的HwVidInitialize函数可以对适配器执行一次由HwVidFindAdapter发起的初始化操作。例如,一个微端口驱动程序可以推迟对适配器加载微代码并利用hwVidInitalize函数调用VideoportGetRegistryParameters。

        当HwVidInitialize函数返回控制,图形引擎则对微端口驱动程序适配置器进行处理。相应的显示驱动程序可以调用引擎的EngDeviceIoControl函数以请求存取映射的视频内存或请求任何其他操作。视频端口驱动程序以VRP将这样的请求发送到微端口驱动程序的HwVidStartIO函数。参考视频请求处理部分获得更多信息。

        通常,显示驱动程序控制显示给终端用户所见的内容,除了在偶然情况下即基于X86的Windows NT/Windows 2000机器上运行一个全屏的MS-DOS应用程序。关于支持这一特征的VGA兼容模式的微端口驱动程序,可以参考VAG兼容的微端口的SvgaHwIoPortXxx部分获得详细内容。

        HwVidInitialize函数调用VideoPortGetRegistryParameters或者VideoPortSetRegistryParameters以获得或设置在注册表中的配置信息。例如,HwVidInitaialize可以调用VideoPortSetRegistryParameters来在注册表中设置下一次启动时的非易失性信息。它也可以调用VideoportGetRegistryParameters来获得特定适配器、总线相关的配置参数并由安装程序写入注册表中。

 

6.5视频微端口设备扩展

        设备扩展是每个微端口驱动程序特定适配器状态信息唯一的全局存储地。

        每个微端口驱动程序定义大小、内部结构及设备扩展的内容。视频端口驱动程序将一个指针作为一个系统定义的除DriverEntry之外的微端口驱动程序函数HwVidSynchronizeExecutionCallback及SvgaHwIoPortXxx函数的输入参数传送到每一个设备扩展,同时,许多VideoPortXxx函数需要将这一指针作为参数。

        微端口驱动程序必须用设备扩展来维持单一适配器的状态信息。每一个系统检测到的适配器都在设备扩展里有一份单独的状态信息。微端口驱动程序不需要全局变量来存储任何适配器的状态。这对提供无缝的多显示器支持也是格外严格的。

 

6.6视频微端口驱动的注册回调信号

        微端口驱动程序的HwVidFindAdapter函数可以请求检索注册表中的配置信息,并通过用驱动程序提供的回调函数调用下面一种的视频端口驱动程序函数。

■VideoPortGetDeviceData函数。该函数的 CallbackRoutine参数设置的指针指向一个驱动程序提供的HwVidQueryDeviceCallBak。

■VideoPortGetRegistryParameters函数。该函数的CallbackRoutine参数设置的指针指向一个驱动程序提供的HwVidQueryNamedValueCallback。

        VideoPortGetDeviceData和VideoPortGetRegistryParameters从注册表的不同关键字中检检信息。相应地,每一个都声明微端口驱动程序来提供一个系统定义的具有不同格式参数的HwVidCallbak函数。

        任一HwVidCallbak函数都不能检索显示驱动程序注册表中默认的配置信息,因为,它们常常是在显示驱动程序被系统加载之前调用的。

        微端口驱动程序也可以调用VideoPortsSetRegistryParameters来存储信息,如在注册表中/CurrentControlSet/Services/DriverName/DeviceNumber关键字下的芯片及DAC类型信息。更多的注册表中关于硬件的信息,可以参考设置注册表中硬件信息部分的内容。以后再从注册表中检索信息,则微端口驱动程序可调用VideoPortSetRegistryParameters。

        需要注意的是,注册表信息可以通过调用VideoPortGetDeviceData来得到,但这是易失性的:它每一次都在系统装载时重新生成。同时也要注意,对视频微端口驱动程序,视频端口驱动程序由VideoPortGetRegistryParameters函数调用得到这些信息及配置信息。微端口驱动程序不能调用VideoPortSetRegistryParameters来向它相应的显示驱动程序传递配置信息。

 

6.7处理视频请求

        那些产生于显示驱动程序调用EngDeviceIoControl的所有的I/O请求都被视频端口驱动程序从IRP映射到VRP。视频端口驱动程序然后用一个它自已建立起来的到每一个VIDEO_REQUEST_PACKET结构的指针。所有的VRP发送到HwVidStatIO,其IoControlCode成员被设置为IOCTL_VIDEO_XXX。

        视频端口驱动程序同样同步管理所有对视频微端口驱动程序的请求,它向每一个微端口驱动程序HwVidStartIO例程一次只发送并处理一个VRP。HwVidStartIO拥有每一个输入VRP,直到微端口驱动程序完成请求的操作并且返回控制。当微端口驱动程序完成当前的VRP,视频端口驱动程序特有I/O管理器发送的任何突出的IRP,以响应由相应显示驱动程序对EngDeviceIoControl的后续调用。

        对于收到一个视频请求,HwVidStartIO必须检查VRP,处理对适配器的视频请求,设置适当的状态以及其他在VRP中的信息,并返回TRUE值。

 

6.7.1系统定义的IOCTL_VIDEO_XXX请求

        典型地,许多视频微端口驱动程序支持下列请求:

■IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES

■IOCTL_VIDEO_QUERY_AVAIL_MODES

■IOCTL_VIDEO_QUERY_CURRENT_MODE

■IOCTL_VIDEO_SET_CURRENT_MODE

■IOCTL_VIDEO_RESET_DEVICE

■IOCTL_VIDEO_MAP_VIDEO_MEMORY

■IOCTL_VIDEO_UNMAP_VIDEO_MEMORY

■IOCTL_VIDEO_SHARE_VIDEO_MEMORY

■IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY

■IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES

■IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES

■IOCTL_VIDEO_GET_POWER_MANAGEMENT

■IOCTL_VIDEO_SET_POWER_MANAGEMENT

■IOCTL_VIDEO_GET_CHILD_STATE

■IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION

■IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION

       

        依赖于适配器的特性,视频微端口驱动程序可以支持下列附加的请求:

■IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES

■IOCTL_VIDEO_SET_COLOR_REGISTERS(如果设备有模析则必需)

■IOCTL_VIDEO_DISABLE_POINTER

■IOCTL_VIDEO_ENABLE_POINTER

■IOCTL_VIDEO_VIDEIO_QUERY_POINTER_CAPABILITIES

■IOCTL_VIDEO_QUERY_POINTER_ATTR

■IOCTL_VIDEO_SET_POINTER_POSITION

■IOCTL_VIDEO_QUERY_POINTER_POSITION

■IOCTL_VIDEO_SET_POINTER_POSITION

■IOCTL_VIDEO_HANDLE_VIDEOARAMETERS

 

        VGA兼容的SVGA微端口驱动程序需要支持下列附加的请求:

■IOCTL_VIDEO_SAVE_HARDWARE_STATE

■IOCTL_VIDEO_RESTORE_HARDWARE_STATE

■IOCTL_VIDEO_DISABLE_CURSOR

■IOCTL_VIDEO_ENABLE_CURSOR

■IOCTL_VIDEO_QUERY_CORSOR_ATTR

■IOCTL_VIDEO_SET_CURSOR_ATTR

■IOCTL_VIDEO_QUERY_CURSOR_ATTR

■IOCTL_VIDEO_SET_CURSOR_POSITION

■IOCTL_VIDEO_GET_BANK_SELECT_CODE

■IOCTL_VIDEO_SET_PALETTER_REGISTERS

■IOCTL_VIDEO_LOAD_AND_SET_FONT

 

        每一个IOCTL的详细信息可以在在线DDK的视频I/O控制代码部分查找到。微端口驱动程序开发者不应当使用不在文档中的、由系统定义的IOCTL。

 

6.7.2自定义的显示微端口IOCTL_VIDEO_XXX请求

        一个微端口驱动程序可以为自已相应的显示驱动程序定义一个或多个自定义I/O控制代码。

        但是,只有专用的显示微端口驱动程序对可以使用自定义的I/O控制代码。也就是,被设计运行于一个已经存在的显示驱动程序下的微端口驱动程序不应当定义私有的I/O控制代码,因为已经存在的显示驱动程序如果不被重写或者如果可能不破坏它已使用的微端口驱动程序就不能构建新的I/O控制请求。已经存在的在许多不同模式的适配器上的一类显示驱动程序,如SVGA适配器,同样不能依赖于私自定义的I/O控制代码来在每一个下层的微端口驱动程序中起到相同的作用。

 

6.7.3处理不支持的IOCTL_VIDEO_XXX请求

        每一个HwVidStartIO函数也必须处理对不支持的IOCTL_VIDEO_XXX函数的接收,如下:

1.设置输入的VRP的Status字段值为ERROR_INVALID_FUNCTION。

2.设置输入的VRP的Information字段为零。

3.返回TRUE值意味着请求被处理。

        参考VIDEO_REQUEST_PACKET和STATUS_BLOCK结构获得更详细信息。

 

6.8在视频微端口中支持PnP及电源管理

        所有的Windows 2000微端口驱动程序必支持PnP和电源管理,包括枚举子设备如DDC监示器、I2C(I2C)设备以及二级适配器的能力。

        视频端口驱动程序为微端口驱动程序管理许多PnP需求,包括创建功能设备对象(FDO:Functional Device Object)及代表微端口驱动程序接收和发送PnP专用的IRP。

        微端口驱动程序必须实现以下的函数以支持PnP和电源管理:

■HwVidSetPowerState

■HwVidGetPowerState

■HwVidGetVideoChildDescriptor

        一个继承的微端口驱动程序的图形适配器不能在系统运行时被删除掉,也不能在加入到一个正在运行的系统时自动检测到。

        可参考图形适配器子设备部分获得关于检测及与适配器子设备通信的内容。对PnP驱动程序的一般性知识,参考即插即用、电源管理及建立设计指南部分。

 

6.9在视频微端口驱动程序中使用AGP

        视频微端口驱动程序提供AGP支持,这样便允许微端口驱动程序设备直接存取系统的(物理)内存。

        为使用AGP,微端口驱动程序必须首先检索视频端口的驱动程序实现的AGP来支持调用VideoPortGetAgpServices例程。视频端口对AGP返回一个指针并支持在微端口驱动程序中分配的将VIDEO_PORT_AGP_SERVICES结构传送给VideoPortGetAgpServices的例程。

        一个微端口驱动程序可以基于系统的物理内存总量来设计它的AGP内存使用,这一信息保存在VIDEO_PORT_CONFIG_INFO结构的SystemMemorySize成员中。

 

6.9.1通过AGP存取系统内存

        微端口驱动程序应当调用以下驱动程序提供的视频端口函数来使其设备可以存取主内存:

1.调用AgpReserverPhysical来在系统总线上保留一段物理内存区间,AGP控制器可以对其响应。

2.调用AgpCommitPhysical来锁定物理内存并将它映射到AgpReservePhysical返回的AGP解码的一部分物理地址上,微端口驱动程序可以多次调用AgpCommitPhysical来执行多次小的提交而不是执行一次大的提交。

        这样,对一个可以看见并使用这一提交的AGP控制的内存应用程序来说,视频微端口驱动程序必须调用如下函数:

1.调用AgpReserverVirtual来在应用程序的地址空间预留一段虚拟地址空间。

2.调用AgpCommitVirtual来锁定虚拟内存并将虚拟内存映射到由AgpReservePhysical返回的AGP解码的物理地址区间。

            应用程序可以使用这些提交的虚拟地址空间,如同这些虚拟地址空间是连续的一样。

 

6.9.2AGP使用中释放内存

        微端口驱动程序负责释放所有它保留的以及它提交的虚拟内存和物理内存,如同在通过AGP存取系统内存部分中简述的一样,它是通过调用下列的视频端口驱动程序的AGP服务例程来释放内存的。

■AgpFreeVirtual去除以前的AgpCommitVirtual函数调用所锁住的虚拟内存映射。

■AgpReleaseVirtual释放由以前的AgpReserveVirtual函数所保留的虚拟地址区间。

■AgpFreePhysical去消由以前的AgpCommitPhysical函数所锁住的物理内存的映射。

■AgpReleasePhyscal释放由以前的AgpReservePhysical函数所保留的物理地址区间。

 

6.10图形适配器的子设备

        以下两部分讨论具有一个或多个子设备的图形适配器对微端口驱动程序的影响问题。

 

6.10.1侦测子设备

        必须在微端口驱动程序中实现HwVidGetVideoChildDescripter来使PnP管理器可以侦测到图形适配器的子设备。

        默认情况下,HwVidGetVideoChildDescriptor函数在父设备未启动之前不能调用。也就是,HwVidGetVideoChildDescriptor在HwVidFindAdapter结束之后才可以调用。为了覆盖这一默认值,以允许枚举在任何时间发生的的子设备,可以设置VIDEO_HW_INITIALIZATION_DATA结构的AllowEarlyEnumeration成员为TRUE即可。

        一个设备在新硬件连接到系统或已经存在的硬件脱离开系统时都会产生中断,为处理这些中断,微端口驱动程序必须做以下事情:

实现一个调用VideoPortEnumerateChildren函数的DPC(PMINIPORT_DPC_ROUTINE)。

当一个设备上的中断产生时,实现一个调用VideoPortqueue到DPC队列的中断句柄(HwVidInterrupt)。

        对每一个父设备的子设备,如果调用了HwVidGetVideoChildDescriptor函数,则也需调用VideoPortEnumerateChild函数对适配器的子设备进行重行枚举,PnP管理器根据需要修改父设备与子设备之间的关系。

 

6.10.2与子设备驱动程序通信

        视频微端口驱动程序与子设备的驱动程序可以人为地定义一个允许子设备驱动程序与它的硬件通过父微端口驱动程序通信的接口。子设备驱动程序通过向父微端口驱动程序的视频端口驱动程序发送一个IRP_MN_QUERY_INTERFACE请求获得这一接口,接收到这样的请求后,视频端口驱动程序调用微端口驱动程序的HwVidQueryInterface函数,如果它已定义,并且微端口驱动程序返回一个接口的接针,则子设备的驱动程序就可以在任何时间通过HwVidQueryInterface函数将它调入到微端口驱动程序中。

        如果微端口驱动程序没有实现HwVidQueryInterface或者调用失败,则视频端口驱动程序将请求传给微端口驱动程序设备的父,如果子驱动程序向该微端口驱动程序的另一个子设备发送了IRP_MN_QUERY_INTERFACE且另一子设备没有实现HwVidQueryInterface或者调用失败,则视频端口驱动程序返回一个错误。

        由于子设备驱动程序可以无需知道任何视频端口驱动程序的相关知识而调入微端口驱动程序,微端口驱动程序就必须在所有HwVidQueryInterface发起的函数中同步存取它自身。它可以通过分别调用VideoPortAcquireDeviceLock和VideoPortReleaseDeviceLock来获得或释放视频端口驱动程序维持的设备锁。

        子设备枚举是通过HwVidGetVideoChildDescriptor函数完成的。

 

6.11视频微端口中的中断

        适配器的微端口驱动程序产生中断必须实现一个HwVidInterrupt例程,微端口驱动程序的DriverEntry例程应当初始化VIDEO_HW_INITALIZATION_DATA的成员HwInterrupt以指向中断句柄。

        如果适配器产生中断,则视频端口驱动程序为微端口驱动程序建立起中断对象,由于它是由视频端口驱动程序产生并管理的,不需要了解进一步的关于中断对象的信息。如果感兴趣,可以参考内核模式的驱动程序指南获得详细信息。

        如果微端口驱动程序的HwVidFindAdapter函数发现视频适配器实际上没有产生中断或者它不能决定对该适配器有效的中断向量或中断层次,则HwVidFindAdapter应当将VIDEO_PROT_CONFIG_INFO结构中的InterruptLevel和InterruptVector设置为零。

        当HwVidFindAdapter返回控制,视频端口驱动程序检查在VIDEO_PORT_CONFIG_INFO中的中断配置成员,都为零,它不将中断连接到一个微端口驱动程序。如果微端口驱动程序允许函数入口点,则它的驱动程序是由DriverEntry函数建立来的。HwVidfindAdapter中断成员明确地设置为零将禁止HevidInterrupt的入口点,

        需要注意的是,HwVidInterrupt可以存取微端口驱动程序的设备扩展,即使它没有分页。依赖于微端口驱动程序的设计,也许对其他的驱动程序函数安全地使用HwVidInterrupt,从共享设备或设备扩展一些特殊地区是不可能的。。

        例如,假定微端口驱动程序的HwVidStartIO函数在适配器中断时用于存取设备扩展,HwVidInterrupt运行在另外一个处理器上,并且hwVidInterrupt也可以存取设备扩展,如果这种情况发生,则HwVidStartIO应当由驱动程序提供的HwVidSynchronizeExecutionCallback的函数去调用VideoPortSynchronizeExecution。

 

6.11.1何时实现HwVidSynchronizeExecutionCallbak例程

        适配器的产生中断的微端口驱动程序很少用HwVidSychronizeExecutionCallback函数去调用VideoPortsynchronizeExecution,实际上,微端口驱动程序都有一个HwVidInterrupt函数而没有必要有HwVidSynchronizeExecutionCallback函数。因为视频端口驱动程序在处理完以前的请求之前不向微端口驱动程序的hwVidStartIO函数发送请求(参考处理视频请求部分),微端口驱动程序很少调用VideoPortSynchronizeExecution。

        对微端口驱动程序HwVidSynchronizeExecutionCallback函数有两种可能的使用:

用微端口驱动程序的驱动程序函数的设备扩展而不是HwVidInterrupt函数存取适配器寄存器。当HwVidsynchronizeExecutionCallback函数给定控制,从适配器来的中断也被屏蔽,这样微端口驱动程序的HwVidInterrupt函数将不能改变HwVidSynchronizeExecutionCallback函数运行在SMP机器上时设备扩展的状态。

如果适配器需要,向适配器寄存器或者端口写命令是非常快的。当HwVidSynchronizeExecutionCallback给定控制,几乎所有的系统中断被屏蔽掉,这样HwVidSynchronizeExecutionCallback函数将不能被一个设备中断(或时钟中断)剥夺。并且,hwVidsynchronizeExecutionCallback函数必须尽可能快地返回控制。

        对上面第一种类型的HwVidsynchronizeExecutionCallback函数,微端口驱动程序按设置给VpMediumPriority的Priority值来调用VideoPortsynchronizeExecution。对第二种类型的HwVidsynchronizeExecutionCallback函数,如果驱动程序没有HwVidInterrupt函数,则微端口驱动程序同样按设置于VpMediumPriority的Priority值来调用。否则,这样的微端口驱动程序将按设置于VpHighPriority的Priority来调用。

        一般情况下,微端口驱动程序不能用第二种类型的HwVidSynchronizeEcecutionCallback函数调用VideoPortsynchronizeExecution,除非驱动程序设计者有其他的选择——即,适配器被用系统的中断屏蔽来编程。否则,微端口驱动程序应按设置于VpLowPriority的priority值来调用VideoPortSynchronizeExecution函数。

        HwVidSynchronizeExecutionCallback函数,像hwVidInterrupt函数不能被分页也不能不用系统重启就调用某些VideoPortXxx函数。对VideoPortXxx函数总体来说,HwVidSynchronizeExecutionCallback函数可安全地调用它们,可参考在线DDK。

 

6.12视频微端口的定时器

        任何微端口驱动程序都可以根据驱动程序开发者的意愿而有一个HwVidTimer函数。HwVidtimer函数允许微端口驱动程序中止操作或者通过VideoPortStallExecution来监控大致的时间间隔中的状态变化。HwVidTimer同时也防止其他系统的操作发生,如VideoPortStallExecution所做的那样。

        例如,适配器的微端口驱动程序仿效VGA的功能可以有一个HwVidTimer函数来定期监视它的适配器的VGA寄存器的状态,这样驱动程序就可以仿效VGA格式的图形。

        在调用VideoPortStartTimer之后,端口驱动程序又每秒调用一次HwVidTimer函数,直到微端口驱动程序调用VideoPortStopTimer之后。微端口驱动程序可以允许或禁止对HwVidTimer函数重复调用。

        需注意的是,HwVidTimer函数不能用VideoPortStopTimer禁止对它自身的调用,另外一个微端口驱动程序函数必须控制通过VideoPortStartTimer和VideoPortStopTimer允许或禁止对HwVidTimer函数的调用。

 

6.13在视频微端口中对适配器重置

        每一个微端口驱动程序必须有HwVidResetHw函数。

        HwVidResetHw由HAL在机器将要崩溃或用户想软启动机器时调用。HwVidResetHw重置适配器到专用的字符模式,这样HAL就可以在关闭系统时显示关闭信息而在软启动机器时显示初始化信息。

        HwVidResetHw不能调用BIOS,不能调用任何的可分页代码,也不能进行分页。如果可能,它只调用VideoPortReadXxx和VideoPortWriteXxx函数,但也可以调用下面函数的任何一个。

■VideoPortStallExecution

■VideoPortZeroDeviceMemory

■VideoPortZeroMemory

 

6.14微端口驱动中的镜像驱动程序支持

        Windows 2000提供了视频微端口驱动程序对镜像驱动程序的支持,这样,微端口驱动程序不需要任何特殊的代码来支持。可以参考第二章镜像驱动程序部分的内容来获得关于在镜像系统中的显示驱动程序的详细信息。

        微端口驱动程序中的镜像驱动程序的需求是最小的,唯一必须实现的函数是DriverEntry,它是由微端口驱动程序导出的,也可以由以下函数导出:

■HwVidFindAdapter

■HwVidInitialize

■HwVidStartIo

        既然没有物理的显示设备与一个镜像的表面相关联,这三个函数可以空执行并且总是返回成功。

 

6.15视频微端口的TV连接器及拷贝保护支持

        所有的视频微端口驱动程序应当用IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS I/O控制代码处理VRPs,这个IOCTL被发送到微端口驱动程序查询硬件能力、TV连接器当前设置及拷贝保护或者设置拷贝保护的硬件功能。微端口驱动程序根据检查VIDEOPARAMETERS结构的dwCommand字段值决定要执行的动作,它被传送到VRP的InputBuffer中。如果一个微端口驱动程序不处理这一VRP,则系统根本不允许DVD回放。

        如果设备没有TV连接器,微端口驱动程序将总是在VRP的StatusBlock结构的Status字段值返回NO_ERROR值,这样的微端口驱动程序不能以任何方式修改VIDEOPARAMETERS结构值。

        接下来的两部分将提供微端口驱动程序设备的TV连接器实现的详细内容。

 

6.15.1查询TV连接器及硬件的拷贝保护

        微端口驱动程序在VIDEOPARAMETERS结构的dwCommand字段值为VP_Commnad_GET时及设备具有TV连接器时做如下工作:

验证Guid(必需的)

如果硬件可以更改模式或标准,则在dwFlags中都设置VP_FLAGS_TV_MODE和VP_FLAGS_TV_STANDARD。微端口驱动程序也应当对其他所支持的能力设置合适的标志位。例如,如果设备支持闪烁过滤,则它应当设置VP_FALGS_TV_FLAGS

dwMode中设置合适的位则意指目前设备的显示器模式(可选的)。如果TV连接器正处于激活状态即向TV显示图像,则微端口驱动程序设置VP_MODE_TV_PLAYBACK,如果设备只是向CRT播放,则应当设置为VP_MODE_WIN_GRAPHIC,或者两个位同时都设置则表示设备同时向TV及CRT播放。

用设备支持的回放模式填充dwAvailableModes,所有的驱动程序必须设置成VP_MODE_WIN_GRAPHICS。如果设备能够打开全部扫描而关闭闪烁过滤,则微端口驱动程序还应当设置VP_MODE_TV_PLAYBACK。

如果设备正通过TV连接器在显示,则应以目前世界上电视显示的标准频率填充dwTVStandard(可选)。如果TV输出被禁止,微端口驱动程序将仅设置VP_TV_STANDARD_WIN_VGA位。

TV连接器支持的TV标准填充dwAvailableTVStandard。

设置dwMaxUnscaledX和dwMaxUnscaledY,即TV显示器能支持的最大x值及y值,不是硬件尺度必需的。

        

        如果,对TV连接器来说,设备还提供了硬件拷贝保护,则微端口驱动程序将修改下列函数的VIDEOPARAMETERS结构的字段值。

dwFlags中设置VP_FLAGS_COPYPROTECT(如同VP_FLAGS_TM_MODE和VP_FLAGS_TV_STANDARD)。

设置dwCPType为拷贝保护状态。

设置dwCPStandard为拷贝保护工作状态时的TV标准。

 

6.15.2设置TV连接器及拷贝保护硬件

        对由微端口驱动程序设置的VIDEOPARAMETERS的dwFlags成员的VP_COMMAND_GET任一位来说,微端口驱动程序可以执行对VP_COMMAND_SET的一个设定。调用者负责调用微端口驱动程序并设置微端口驱动程序支持VP_COMMAND_GET的未设定功能。微端口驱动程序应当为VP_COMMAND_GET作出响应,而这是通过设置硬件的VIDEOPARAMETERS字段的dwFlags中的相应的字段值来实现的。例如:

如果微端口驱动程序在VP_COMMAND_GET上设置了VP_FLAGS_TV_MODE位,当VP_FLAGS_TV_MODE在VP_COMMAND_SET上设置时,它应当改变VP_MODE_WIN_GRAPHICS状态到VP_MODE_TV_PLAYBACK状态。

如果微端口驱动程序在VP_COMMAND_GET上设置VP_FLAGS_TV_STANDARD位,当VP_FLAGS_TV_STANDARD设置在VP_COMMAND_SET上时,它应当改变TV标准到dwTVStandard指示的标准。

如果微端口驱动程序在VP_COMMAND_GET上设置VP_FLAGS_CONTRAST位,当VP_FLAGS_CONTRAST设置于VP_COMMAND_SET上时,它应当设置对比值为dwContrast中的值。

        如果相应的位在dwFlags中没有设置,则VIDEOPARAMETERS字段包含未定义的数据

 

6.15.2.1设置拷贝保护硬件(Copy Protection Hardware)

        那些在VIDEOPARAMETERS结构的dwFlags成员在VP_COMMAND_GET上返回VP_FALGS_PROTECTED的微端口驱动程序,应当按以下方式对VP_COMMAND_SET命令进行响应,并依赖VIDEOPARAMETERS结构的dwCPCommand成员:

如果dwCPCommand是VP_CP_CMD_ACTIVATE,微端口驱动程序应当打开拷贝保护,产生并返回一个在dwCPKey中的唯一性保护键。

如果dwCPCommand是VP_CP_CMD_DEACTIVATE并且在dwCPKey中的拷贝保护键是有效的,则微端口驱动程序应当关闭拷贝保护。

如果dwCPCommand是VP_CP_CMD_CHANG并且在dwCPKey中的拷贝保护键也合法,微端口驱动程序将根据bCP_APSTriggerBits中的触发数据改变保护状态。

        对没有拷贝保护硬件的设备的微端口驱动程序,只需简单地在VRP的StatusBlock结构的Status字段返回NO_ERROR。

 

6.15.2.2多会话拷贝保护

        具有拷贝保护的设备的微端口驱动程序可选择性地支持多个同步拷贝保护会话,如果这样做的话,微端口驱动程序应当如下这样做:

对每一个拷贝保护的激活,都返回一个在dwCPKey中的唯一的拷贝保护关键字。

在所有的会话都临时性关闭(通过VP_CP_CMD_CHANGE)或解除(VP_CP_CMD_DEACTIVATE)之前都可以保持拷贝允许。例如,微端口驱动程序可以在每次拷贝保护激活及解除或关闭时,增加或减少引用的总数,当总数为零时,所有的拷贝保护才被禁止。

 

6.16VGA兼容的微端口SvgaHwIoPortXxx

        在基于x86的机器中,VGA兼容的微端口驱动程序替换了系统提供的VGA微端口驱动程序,因而,VGA兼容的微端口驱动程序可以有一套SvgaHwIoPortXxx函数来支持全屏的MS-DOS应用程序,就如同系统提供的VGA微端口驱动程序所做的一样。

        VGA兼容的新的SVGA微端口驱动程序的设计者应当使之适应一种根据适配器特性的由系统提供的SVGA微端口驱动程序的SvgaHwIoPortXxx函数。如同在基于x86的VGA兼容微端口部分中提到的,对其他基于x86类型适配器的微端口驱动程序的机器可以有一套SvgaHwioPortXxx例程并且可以根据设计者自身判断是否提供相同的支持或者在VGA微端口驱动程序加载时能不能被同时装载。

 

6.16.1基于x86机器的窗口式VDM

        每一个MS-DOS应用程序都作为一个Windows VDM来运行,它同样在Win32保护子系统中作为一个控制台管理程序运行。

        在Windows NT/Windows 2000平台上,一个称作V86仿真器的内核模式的部件捕获MS-DOS应用程序的指令,只要这一应用程序运行于一个窗口,任何对视频适配器的访问都被捕获并反射回系统提供VDD,VDD主要用于仿真适配器对应用程序的行为。换句话说,显示驱动程序在VDM运行于一个窗口时保留有对视频适配器的控制。

 

6.16.2基于x86机器的全屏VDM

        由于性能的原因,当用户切换一个基于X86机器的MS-DOS应用程序到全屏模式时,显示驱动程序放弃对适配器控制。系统的VGA或VGA兼容的微端口驱动程序则从V86仿真器中分出所有的I/O指令,如应用程序相关的IN,REP INSB/INSW/INSD,OUT以及REPOUTSB/OUTSW/OUTSD指令到视频I/O端口。这些被分出的I/O操作转交给VAG兼容的微端口驱动程序的SvgaHwIoPortSxx函数。

        然而,为了更高的性能,微端口驱动程序可以调用VideoPortSetTrappedEmulatorPorts来允许一些I/O端口可以直接被应用程序访问,微端口驱动程序继续用它的SvgaHwIoPortXxx分出到其他的I/O端口,以验证对这些端口的应用程序相关的指令流。

        为了防止全屏应用程序发布一系列指令而使系统挂起,SvgaHwIoPortXxx函数监视到一个驱动程序确定的适配器寄存器应用程序的指令流。微端口驱动程序必须允许只对这些I/O端口的完全安全的直接存取。例如,对顺序生成器端口及杂项输出寄存器端口应当始终被V86仿真器分出并并捕获到微端口驱动程序提供的SvgaHwIoPortXxx函数进行验证。

        应用程序是否直接存取I/O端口取决于VGA兼容的微端口驱动程序通过调用VideoPortSetTrappedEmulatorPorts设置的IOPM(I/O permission map:即x86上的I/O允许映射)。但要注意,微端口驱动程序可以通过调用这一函数,使其具有一定的存取区间来调节IOPM,它描述了I/O端口,释放给应用程序直接存取或者由SvgaHwIoPortXxx重新捕获。当前的IOPM决定了哪能一端口能被应用程序直接存取以及哪一个保留有V86仿真器的钩子或以SvgaHwIoProtXxx函数捕获进行验证。

        默认情况下,所有的I/O端口建立起这一个微端口驱动程序仿真器的存取数组,并被捕获到相应的SvgaHwIoPortXxx函数。但是,VGA兼容的微端口驱动程序常常在收到一个IOCTL_VIDEO_ENABLE_VDM,即请求重新为VDM设置IOPM以允许直接存取一些I/O端口时调用VideoPortSetTrappedEmulatorPorts。大多数情况下,这一驱动程序允许直接存取除VGA顺序生成器寄存器、杂项输出寄存器及任何SVGA特定适配器寄存器等驱动程序开发者认为应当一直由SvgaHwIoPortXxx函数验证有效性之外所有的视频适配器寄存器。

        关于VideoportSetTrappedEmulatorPorts,可参考在线DDK中的图形驱动程序参考部分。

 

6.16.3VGA兼容的微端口的HwFindAdapter

        VGA兼容的微端口驱动程序的HwVidFindAdapter函数(或寄存器HwVidCallback)必须在VIDEO_PORT_CONFIG_INFO中建立起如下缓冲区:

■NumEmulatorAccessEntries,意指在EmulatorAccessEntries数组中的条目数。

■EmulatorAccessEntries,指向一个包含给定数量的EMULATOR_ACCESS_ENTRY类型元素的静态数组,每一个都描述了一个从V86仿真器分出的I/O端口。默认的,其值都传递给SvgaHwIoPortXxx函数。每一个条目都包括一个起始的I/O地址、一个区间长度、被捕获的存取的大小(UCHAR,USHORT或ULONG),微端口驱动程序是否支持通过I/O端口输入或输出字符串数据,微端口驱动程序提供的SvgaHwIoPortXxx函数以进行实际验证,可能的话还会传输数据。每一个SvgaHwIoPortXxx函数处理读(IN或REP INSB/INSW/INSD)和/或写(OUT或REP OUTSB/OUTSW/OUTSD)传输的UCHAR-,USHORT-,或ULONG-尺寸的数据。

■EmulatorAccessEntriesContext,一个存储的指针,如微端口驱动程序的设备扩展中的一个区域,在这个区域中,微端口驱动程序的SvgaHwIoPortXxx函数可以批次处理一个验证需要的应用程序相关的指令序列。

■VdmPhysicalVideoMemoryAddress和VdmPhysicalVideoMemoryLeagth描述了一个必须映射到VDM地址空间以支持MS-DOS全屏应用程序BIOS INT10调用的视频内存的区间。当一个应用程序改变视频模式到微端口驱动程序适配器可以支持的一种模式时,微端口驱动程序可以调用VideoPortInt 10函数。

■HardwareStateSize,它描述了对适配器IOCTL_VIDEO_SAVE_HARDWARESTATE响应的存储硬件状态信息所需的最小字节数。当用户切换到运行在一个窗口的MS-DOS全屏模式的应用程序时,微端口驱动程序必须在显器驱动程序重新获取对视频适配器的控制之前存储适配器的状态。需要注意的是VGA兼容的微端口驱动程序同样必须支持可逆的IOCTL_VIDEO_RESTORE_HARDWARE_STATE请求,因为用户也可能从窗口化的应用程序转回到全屏模式。

        VGA兼容的微端口驱动程序仿真器存取专用的条目的子集,即适配器存取区间数组中指定的子集。仿真器存取条目可以是,而且经常是由HwVidFindAdapter函数建立起来的被映射的存取区间数组的所有I/O端口,存取的区间传送给VideoPortSetTrappedEmulatorPorts调用,它确定了当前的IOPM并决定由全屏MS-DOS应用程序可直接存取的I/O端口,指定了微端口驱动程序仿真器可存取条目的子集。

 

6.16.4SvgaHwIoPortXxx验证指令

        如同在VGA兼容的微端口HwFindAdapter中提到的,IOPM设置了可直接存取的I/O端口包括除顺序生成器寄存器和杂项输出寄存器之外的所有的SVGA寄存器,这些I/O端口继续VGA兼容的视频微端口驱动程序用SvgaHwIoPortXxx函数监视着。顺序生成器寄存器控制内部VGA兼容显示适配器上的芯片时钟。如果全屏MS-DOS应用程序在同步重新设置时触及其他适配器寄存器,则机器可以挂起。同样地,如果杂项输出寄存器设置选择一个不存在的时钟,机器同样将挂起。

        VGA兼容的微端口驱动程序必须保证全屏的MS-DOS应用程序不发布引起机器挂起的指令。每一个这样的微端口驱动程序必须提供SvgaHwIoPortXxx函数来监视应用程序的发给I/O端口的为适配器顺序生成器寄存器及杂项输出寄存器发出的指令。每一个具有新特性的适配器的新VGA兼容的微端口驱动程序必须监视并继续验证任何可能由应用发送到任何I/O端口的能引起机器挂起的任何指令序列。

        无论何时应用程序企图存取顺序生成器的时钟寄存器,SvgaHwIoportXxx函数必须改变IOPM的顺序以捕获所的有在同步重设置时进入的指令。一旦一个应用程序发送了一个影响顺序生成器或者企图向杂项输出寄存器写入的指令,则SvgaHwIoPortXxx函数将通过调用VideoPortSetTrappedEmulatorPorts来调节IOPM以禁止它直接存取所有的适配器寄存器。

        微端口驱动程序提供的SvgaHwIoPortXxx函数应当在EmulatorAccessEntriesContext区域中缓冲接下来的IN(或INSB/INSW/INSD)和/或OUT(或OUTSB/OUTSW/OUTSD)指令,这一区域是直到同步重置完成之后或者应用程序重新存储了杂项输出寄存器或重置它为安全时钟后建立起的VIDEO_PORT_CONFIG_INFO(参考VGA兼容的微端口的HwFindAdapter驱动程序)。

        微端口驱动程序这时负责检查缓冲的指令不能挂起机器。如果缓冲的指令不能挂起机器,微端口驱动程序将处理缓冲指令,通常情况都是通过用驱动程序提供的HwVidSynchronizeExecutionCallback调用VideoPortSynchronizeExecution函数,否则的话,微端口驱动程序将摒弃缓冲区指令。

 

6.16.5VGA兼容的HwVidStartIO

        当用户从一个全屏的MS-DOS应用程序切换到一个窗口下运行时,VGA兼容的微端口驱动程序的HwVidStartIO函数发送了一个带有I/O控制代码IOCTL_VIDEO_SAVE_HARDWARE_STATE的VRP。微端口驱动程序必须存储适配器的状态以备用户再切换回到应用程序的全屏模式。

        值得注意的是,微端口驱动程序的SvgaHwIoPortXxx函数必须具有一个缓冲的应用程序的IN和/或OUT序列,如同在SvgaHwIoPortXxx验证指令部分中所描述的那样。当它的HwVidStartIO例程调用以存储适配器的状态,在这种情况下,微端口驱动程序应当存储当前的状态,包括缓冲区中的指令,这样SvgaHwIoProtXxx函数可以重新准确地验证用户什么地方又将应用程序切换到全屏模式等一类的操作。

        当微端口驱动程序完成一个存储操作,端口驱动程序自动禁止当前对VDM和微端口驱动程序的SvgaHwIoPortXxx函数的IOPM。如果应用程序又切换到全屏模式,则视频微端口驱动程序重新自动存储IOPM。它也在响应IOCTL_VIDEO_RESTORE_HARDWARE_STATE请求并调用微端口驱动程序的HwVidStartIO例程之后重新调用微端口驱动程序的SvgaHwIoPortXxx函数。

 

6.17Windows NT 4.0的微端口驱动程序转换到Windows 2000

        好的Windows NT 4.0微端口驱动程序可以很容易地成为Windows 2000的微端口驱动程序,下面是一些在Windows 2000微端口驱动程序中由PnP支持提供的需要修改的内容:

实现在视频微端口驱动程序中支持PnP和电源管理部分中列出的新函数。但要确保初始化VIDEO_HW_INITALIZAITON_DATA的新成员要指向这些新函数。

DriveEntry函数中修改对VideoPortInitialize函数的调用。在Windows 2000中,第四个参数(Hwcontext)必须为NULL值。

修改HwVidFindAdapter函数,对可枚举的总线上的设备来说,必须如下改变HwVidFindAdapter:

第一、删去设备侦测到的大多数代码(由于在Windows 2000上对HwVidFindAdapter的调用意味着PnP管理器已经探测到设备)。

第二、调用VideoPortGetAccessRanges来获得设备响应的总线相关的物理地址,这些地址是由PnP管理器分配的。

第三、如果驱动程序支持一个以上的设备类型,则确定设备的类型。

第四、忽略Again参数。(由于系统对每个设备只调用一次HwVidFindAdapter)。

        对ISA等不可枚举的总线上的设备来说,PnP依旧企图启动设备,尽管HwVidFindAdapter负责决定设备是否存在。

修改驱动程序INF文件的.Mfg部分以包含设备及生产厂的ID。这一工作是必需的,这样PnP管理器可以与它的INF文件协调设备。Windows NT 4.0的例子及Windows 2000的修改后的.Mfg部分如下:

 

[ABC.Mfg]    ;Windows NT V4.0 INF

%ABC%  ABC  Graphics  Accelerator A=abc

%ABC%  ABC  Graphics  Accelerator B=abc

 

[ABC.Mfg]    ;Windows 2000 INF

%ABC%  ABC  Graphics Accelerator A=abc,PCI/VEN_ABCD&DEV_0123

%ABC%  ABC  Graphics Accelerator B=abc,PCI/VEN_ABCD&DEV_4567

 

        可以用与Windows 2000 DDK一起发布的geninf.exe工具来产生.INF。但要记住,geninf.exe不能为Windows NT 4.0产生INF,如果用geninf.exe生产的INF想支持Windows NT 4.0而不是Windows 2000,则必须修改由geninf.exe产生的INF文件。更多的内容可参考第一章创建图形的INF文件。

        Windows 2000的视频端口作为Windows NT 4.0的继承来支持微端口驱动程序。当系统正在运行时,微端口驱动程序继承的图形适配器不能删除掉。同样,继承的微端口加入到一个正在运行的系统时也不能被自动地侦测到。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值