iniwf

风是温柔的,雨是伤心的,云是快乐的,月是多情的,爱是迷失的,恋是醉人的,情是难忘的,天是长久的,地是永恒的

驱动开发之六 --- 一个简单的显示驱动之一 [译文]

转自http://hi.baidu.com/combojiang/blog/item/aa6be0f3fcc74255352accd6.html

理论:

本篇我们将介绍下如何写一个简单的显示驱动。显示驱动是一种特殊类型的驱动,必须要满足一个框架,它不像我们前面讲的那些驱动。

示例程序演示了如何写一个简单的显示驱动,这个驱动无需关联任何硬件。它能实现图形到内存,然后由一个应用程序来显示这些图形。

显示驱动的体系结构

首先介绍的是windows NT下显示驱动的体系结构。在这里要特别说明的是windows vista使用了一种新的显示驱动模型,叫做LDDM.它是vista最新桌面窗口管理器的核心部分。就兼容方面,vista仍然可以与老的窗口管理器一起协作支持老的显示驱动。

显示驱动模型包括两部分,迷你小端口驱动和显示驱动。迷你小端口驱动加载到系统空间,负责枚举设备和管理设备资源。显示驱动加载到会话空间,负责实现实际的GDI图形调用。显示驱动完全控制怎样划线或者怎样实现透明效果。

下面的图表显示了windows显示驱动的体系结构。


迷你小端口驱动

迷你小端口驱动加载到系统空间,负责管理显示设备资源和枚举设备。这个驱动使用其它的驱动(VIDEOPRT.SYS作为它的框架。你的驱动会使用VIDEOPRT.SYS导出的API. 很奇怪驱动可以导出API吧?驱动使用pe格式,也有导入表和导出表。你可以从你的驱动中导出api,并且允许其他驱动链接使用它们,就像调用一个dll一样。实际上你使用的这些API连接着内核和其他驱动。

在这里要注意连接内核模式驱动和用户模式的驱动有些不同。如果一个驱动连接另一个驱动,而那个驱动当前没有加载到内存。那么那个驱动将会被加载进内存,然而那个驱动的DriverEntry不会被调用。DriverEntry自身不会被调用,只有使用ZwLoadDriver加载驱动,系统加载驱动或者使用我们前面展示过的服务api记载驱动才会调用DriverEntry。任何时候,你都可以从一个驱动中导出API,然后在另一个驱动中使用这些api. 在内核中没有类似于"GetProcAddress"api,你需要自己写一个。

你的迷你小端口驱动会调用VideoPrt.SYS导出的apiVideoPrt.SYS驱动做了很少的事情,其中之一就是实现了通用代码。所以视频驱动的开发者就不需要重新再写同样的代码。这个代码包括在win32子系统(win32k.sys)和你的迷你小端口驱动之间进行视频设备枚举。VideoPrt.SYS还创建了一个显示用的设备对象,当你调用这个初始化例程时,他会使你的驱动对象入口点指向VideoPrt.SYS

所有的VideoPrt.SYS API都是"VideoPort"开头的。你第一个调用的API应该是"VideoPortInitialize".如果你注意的话,可以看到开头的两个参数就是传递给你的DriverEntry例程的,他们被称作"Context1""Context2",仿佛你的视频迷你小端口驱动是特别的。不要被这些迷惑,第一参数"Context1"实际上就是你的驱动对象。一旦你传递你的驱动对象给VideoPortInitialize,所有你的驱动入口点都会指向VideoPrt.Sys的。除此之外,你还要传递给VIDEO_HW_INITIALIZATION_DATA结构不同的函数指针,VideoPrt.SYS在需要的时候会用到这些。

这意味着你不要直接处理在视频迷你小端口驱动中的IRP. VideoPrt.SYS会处理他们。你需要处理的是"VRP"(视频请求包),本质上讲它其实是一种简化的用不同数据结构的IRP版本。你需要简单的返回,不需要像IRP那样对这个数据结构进行处理。

在迷你小端口驱动中,你除了使用"VideoPort"开头的api外,由于它是系统层的驱动,你还可以使用内核的api.

由于我们没有任何硬件,因此我们的迷你小端口驱动会比较简单,下面的代码演示了如何编写视频迷你小端口驱动DriverEntry

/**********************************************************************

*

* DriverEntry

*

*    This is the entry point for this video miniport driver

*

**********************************************************************/

ULONG DriverEntry(PVOID pContext1, PVOID pContext2)

{

    VIDEO_HW_INITIALIZATION_DATA hwInitData;

    VP_STATUS vpStatus;

  /*

     * The Video Miniport is "technically" restricted to calling

     * "Video*" APIs.

     * There is a driver that encapsulates this driver by setting your

     * driver's entry points to locations in itself. It will then

     * handle your IRP's for you and determine which of the entry

     * points (provided below) into your driver that should be called.

     * This driver however does run in the context of system memory

     * unlike the GDI component.

     */

    VideoPortZeroMemory(&hwInitData,

                                sizeof(VIDEO_HW_INITIALIZATION_DATA));

    hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);

    hwInitData.HwFindAdapter             = FakeGfxCard_FindAdapter;

    hwInitData.HwInitialize             = FakeGfxCard_Initialize;

    hwInitData.HwStartIO                 = FakeGfxCard_StartIO;

    hwInitData.HwResetHw                 = FakeGfxCard_ResetHW;

    hwInitData.HwInterrupt               = FakeGfxCard_VidInterrupt;

    hwInitData.HwGetPowerState          = FakeGfxCard_GetPowerState;

    hwInitData.HwSetPowerState           = FakeGfxCard_SetPowerState;

    hwInitData.HwGetVideoChildDescriptor =

                                      FakeGfxCard_GetChildDescriptor;

    vpStatus = VideoPortInitialize(pContext1,

                                      pContext2, &hwInitData, NULL);

    return vpStatus;

}

VideoPortInitialize的返回值作为DriverEntry函数的返回值,返回调用者。

在你直接简单的传递DriverObjectVideoPrt.SYS之前,你还需要填充一个数据结构,这个数据结构中包含了你驱动中的入口点,这些入口点会被VideoPrt.SYS驱动调用来执行不同的动作。"HwStartIO"是指你可以处理IOCTLs,在显示驱动和视频迷你小端口驱动之间,你可以使用IOCTLs。显示驱动只需要简单调用"EngDeviceIoControl",迷你小端口驱动中的HwStartIO就会处理IOCTL。代码如下:

/*#pragma alloc_text(PAGE, FakeGfxCard_ResetHW)       Cannot be Paged*/
/*#pragma alloc_text(PAGE, FakeGfxCard_VidInterrupt) Cannot be Paged*/
#pragma alloc_text(PAGE, FakeGfxCard_GetPowerState)
#pragma alloc_text(PAGE, FakeGfxCard_SetPowerState)
#pragma alloc_text(PAGE, FakeGfxCard_GetChildDescriptor)
#pragma alloc_text(PAGE, FakeGfxCard_FindAdapter)
#pragma alloc_text(PAGE, FakeGfxCard_Initialize)
#pragma alloc_text(PAGE, FakeGfxCard_StartIO)
/**********************************************************************
* FakeGfxCard_ResetHW

*     This routine would reset the hardware when a soft reboot is
*     performed. Returning FALSE from this routine would force
*     the HAL to perform an INT 10h and set Mode 3 (Text).
*     We are not real hardware so we will just return TRUE so the HAL
*     does nothing.
**********************************************************************/
BOOLEAN FakeGfxCard_ResetHW(PVOID HwDeviceExtension,
                                 ULONG Columns, ULONG Rows)
{
   return TRUE;
}

/*********************************************************************
* FakeGfxCard_VidInterrupt

*     Checks if it's adapter generated an interrupt and dismisses it
*     or returns FALSE if it did not.

**********************************************************************/
BOOLEAN FakeGfxCard_VidInterrupt(PVOID HwDeviceExtension)
{
   return FALSE;
}

/*********************************************************************
* FakeGfxCard_GetPowerState
*         Queries if the device can support the requested power state.
**********************************************************************/
VP_STATUS FakeGfxCard_GetPowerState(PVOID HwDeviceExtension,
          ULONG HwId, PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{            
   return NO_ERROR;
}

/**********************************************************************
* FakeGfxCard_SetPowerState
* Sets the power state.
**********************************************************************/

VP_STATUS FakeGfxCard_SetPowerState(PVOID HwDeviceExtension,
          ULONG HwId, PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{
return NO_ERROR;

}

/**********************************************************************

*

* FakeGfxCard_GetChildDescriptor

*

*        Returns an identifer for any child device supported

*        by the miniport.

*

**********************************************************************/

ULONG FakeGfxCard_GetChildDescriptor (PVOID HwDeviceExtension,

      PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, PVIDEO_CHILD_TYPE pChildType,

      PVOID pChildDescriptor, PULONG pUId, PULONG pUnused)

{

   return ERROR_NO_MORE_DEVICES;

}

/**********************************************************************

*

* FakeGfxCard_FindAdapter

*

*        This function performs initialization specific to devices

*        maintained by this miniport driver.

*

**********************************************************************/

VP_STATUS FakeGfxCard_FindAdapter(PVOID HwDeviceExtension,

            PVOID HwContext, PWSTR ArgumentString,

            PVIDEO_PORT_CONFIG_INFO ConfigInfo, PUCHAR Again)

{

   return NO_ERROR;

}

/**********************************************************************

*

* FakeGfxCard_Initialize

*

*      This initializes the device.

*

**********************************************************************/

BOOLEAN FakeGfxCard_Initialize(PVOID HwDeviceExtension)

{

   return TRUE;

}

/**********************************************************************

*

* FakeGfxCard_StartIO

*

*      This routine executes requests on behalf of the GDI Driver

*      and the system. The GDI driver is allowed to issue IOCTLs

*      which would then be sent to this routine to be performed

*      on it's behalf.

*

*      We can add our own proprietary IOCTLs here to be processed

*      from the GDI driver.

*

**********************************************************************/

BOOLEAN FakeGfxCard_StartIO(PVOID HwDeviceExtension,

                PVIDEO_REQUEST_PACKET RequestPacket)

{

   RequestPacket->StatusBlock->Status      = 0;

   RequestPacket->StatusBlock->Information = 0;

   return TRUE;

}

由于我没有任何硬件,对于迷你小端口驱动,简单实现就足够了。如果我需要在系统上访问或者执行一个操作,显示驱动靠它自己有限的API函数集是不能做到的。我会用到的唯一的API就是"StartIO"。可是在这个实现中,我们不需要做什么。记住,迷你小端口驱动的主要用途就是枚举硬件设备/资源和管理他们。如果你没有什么硬件设备/资源,那么为了让驱动模型高兴,除了必需的外删除其他的。

posted on 2009-03-23 22:13 iniwf 阅读(482) 评论(0)  编辑 收藏 引用 所属分类: 驱动


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿(2)

随笔分类

随笔档案

收藏夹

IT技术

积分与排名

最新评论

阅读排行榜

评论排行榜