启动顺序

由于适配器驱动程序作为内核模式驱动程序服务安装,因此操作系统在系统启动时加载适配器驱动程序并调用驱动程序的 DriverEntry 例程。 DriverEntry 例程接收两个参数:驱动程序对象和注册表路径名称。 DriverEntry 应使用驱动程序对象和注册表路径名称参数以及第三个参数调用 PortCls 函数 PcInitializeAdapterDriver,这是指向适配器驱动程序的 AddDevice 函数的指针。

在以下示例中,驱动程序的 DriverEntry 函数传递函数指针,该指针MyAddDevice指向驱动程序的 AddDevice 函数,作为 PcInitializeAdapterDriver 例程的第三个参数

NTSTATUS 
  DriverEntry( 
    PDRIVER_OBJECT  DriverObject,
    PUNICODE_STRING  RegistryPath
    )
  {
      return PcInitializeAdapterDriver(DriverObject, RegistryPath, MyAddDevice);
  }

PcInitializeAdapterDriver 例程在驱动程序对象的驱动程序扩展中安装提供的 AddDevice 例程,并在驱动程序对象本身中安装 PortCls 驱动程序的 IRP 处理程序。

以下代码是驱动程序 MyAddDevice 函数的示例实现。

#define MAX_MINIPORTS 6    // maximum number of miniports
NTSTATUS
  MyAddDevice(
    PDRIVER_OBJECT  DriverObject,
    PDEVICE_OBJECT  PhysicalDeviceObject 
    )
  {
      return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, MyStartDevice,
                                MAX_MINIPORTS, 0);
  }

此函数调用 PortCls 函数 PcAddAdapterDevice,该函数创建指定的适配器设备、将驱动程序与设备关联,并存储指向适配器驱动程序函数的MyStartDevice指针,该函数在操作系统启动设备时调用(请参阅启动设备)。 PcAddAdapterDevice 例程创建一个功能设备对象(FDO),并将其与系统提供的物理设备对象(PDO)相关联。 新的 FDO 是使用 PortCls 用来存储有关设备的上下文信息的扩展创建的。 此上下文包括 MyStartDeviceMyAddDevice..

操作系统确定要分配给设备的哪些资源(中断、DMA 通道、I/O 端口地址等),它会向设备发送启动请求(IRP_MN_START_DEVICE)。 为了响应此请求,PortCls 驱动程序中的请求处理程序调用适配器驱动程序的 MyStartDevice 函数,如以下示例代码所示:

NTSTATUS
  MyStartDevice(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PRESOURCELIST ResourceList
    )
  {
    ...
  }

请求处理程序提供 MyStartDevice 指向设备对象的指针、IRP_MN_START_DEVICE请求和资源列表(请参阅 IResourceList)。 该 MyStartDevice 函数将资源列表分区到需要启动的每个微型端口驱动程序所需的资源中。 然后,该函数启动每个微型端口驱动程序,并将控制权返回到 PortCls,后者完成 IRP 并将控制权返回到操作系统。

有关驱动程序启动代码的更多示例,请参阅 Microsoft Windows 驱动程序工具包(WDK)中的音频适配器驱动程序示例。