将总线相对地址映射到虚拟地址

某些处理器实现单独的内存和 I/O 地址空间,而其他处理器则不实现。 由于硬件平台存在这些差异,驱动程序用于访问 I/O 或内存驻留设备资源的机制因平台而异。

驱动程序请求设备 I/O 和内存资源,以响应 PnP 管理器的 IRP_MN_QUERY_RESOURCE_REQUIREMENTS IRP。 根据硬件体系结构,HAL 可以在 I/O 空间或内存空间中分配 I/O 资源,并且可以在 I/O 空间或内存空间中分配内存资源。

如果 HAL 使用总线相对内存空间访问设备资源 ((例如设备寄存器) ),驱动程序必须将 I/O 空间映射到虚拟内存,以便可以访问这些资源。 驱动程序可以通过检查 PnP 管理器在设备启动时传递给驱动程序的已转换资源来确定资源是 I/O 还是内存驻留资源。 如果 HAL 使用 I/O 空间,则无需映射。

具体而言,当驱动程序收到IRP_MN_START_DEVICE请求时,它应检查 IrpSp-Parameters.StartDevice.AllocatedResources>IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> 中的结构,它们分别描述 PnP 管理器分配给设备的原始 (总线相对) 和转换的资源。 驱动程序应保存设备扩展中每个资源列表的副本,以辅助调试。

资源列表 CM_RESOURCE_LIST 结构配对,其中原始列表的每个元素对应于已翻译列表的同一个元素。 例如,如果 AllocatedResources.List[0] 描述原始 I/O 端口范围, 则 AllocatedResourcesTranslated.List[0] 在转换后描述相同的范围。 每个已翻译的资源都包含一个物理地址和资源类型。

如果为驱动程序分配了已转换的内存资源 (CmResourceTypeMemory) ,则必须调用 MmMapIoSpace 将物理地址映射到可以访问设备寄存器的虚拟地址。 若要使驱动程序以与平台无关的方式运行,它应检查每个返回的已转换资源,并在必要时对其进行映射。

内核模式驱动程序应执行以下步骤,以响应IRP_MN_START_DEVICE请求,以确保访问所有设备资源

  1. IrpSp-Parameters.StartDevice.AllocatedResources> 复制到设备扩展。

  2. IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> 复制到设备扩展。

  3. 在循环中,检查 AllocatedResourcesTranslated 中的每个描述符元素。 如果描述符资源类型为 CmResourceTypeMemory,请调用 MmMapIoSpace,传递已转换资源的物理地址和长度。

当驱动程序收到来自 PnP 管理器 的IRP_MN_STOP_DEVICEIRP_MN_REMOVE_DEVICE 请求时,它必须通过在类似的循环中调用 MmUnmapIoSpace 来释放映射。 如果驱动程序必须使IRP_MN_START_DEVICE请求失败,则驱动程序还应调用 MmUnmapIoSpace

原始资源类型指示驱动程序应调用哪个 HAL 访问例程 (READ_REGISTER_XXXWRITE_REGISTER_XXXREAD_PORT_XXXWRITE_PORT_XXX) 。 大多数驱动程序不必检查原始资源列表来确定要使用哪些例程,因为驱动程序本身请求了资源,或者驱动程序编写者知道设备硬件的性质所需的类型。

对于 I/O 空间中的资源 (CmResourceTypePortCmResourceTypeInterruptCmResourceTypeDma) ,驱动程序应使用返回的物理地址的低序 32 位来访问设备资源,例如,通过 HAL 的读取和写入READ_REGISTER_XXXWRITE_REGISTER_XXX、READ_PORT_XXXWRITE_PORT_XXX 例程。