管理 NDIS 选择性挂起的 IRP 资源

如果微型端口驱动程序支持并启用 NDIS 选择性挂起,则 NDIS 调用 MiniportIdleNotification ,以在网络适配器变为非活动状态时向驱动程序发出空闲通知。 微型端口驱动程序处理此通知时,可能需要向基础总线驱动程序发出 I/O 请求数据包 (IRP) 。 这些 IRP 通知总线驱动程序适配器的空闲状态,并请求确认适配器可以转换为低功耗状态。

微型端口驱动程序颁发的 IRP 特定于总线。 例如,当 NDIS 调用 MiniportIdleNotification 时,USB 微型端口会发出 USB 空闲请求 (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION) IRP 到基础 USB 总线驱动程序。

初始化驱动程序后,NDIS 可能会多次向微型端口驱动程序发出空闲通知。 因此,建议驱动程序在调用驱动程序的 MiniportInitializeEx 函数的上下文中为 USB 空闲请求 IRP 分配资源。

以下示例演示微型端口驱动程序如何分配 IRP 资源。

//
// MiniportInitializeEx()
//
// In the miniport's initialization routine, the miniport should allocate
// an IRP.  It can also set up the USB_IDLE_CALLBACK_INFO structure that
// will be used with each successive USB idle request.
//
NDIS_STATUS MiniportInitializeEx(
    _In_ NDIS_HANDLE MiniportAdapterHandle,
    _In_ NDIS_HANDLE MiniportDriverContext,
    _In_ PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters
    )
    {
    PIRP UsbSsIrp;
    USB_IDLE_CALLBACK_INFO UsbSsCallback;
    ...

    UsbSsIrp = IoAllocateIrp(Adapter->Fdo->StackSize, FALSE);
    if (!UsbSsIrp)
       {
       // Handle failure
       return NDIS_STATUS_RESOURCES;
       }

    UsbSsCallback.IdleCallback = MiniportUsbIdleRequestCallback;
    UsbSsCallback.IdleContext = Adapter;

    // Save these in the adapter structure for later use
    Adapter->UsbSsIrp = UsbSsIrp;
    Adapter->UsbSsCallback = UsbSsCallback;
    ...
    }

如果微型端口驱动程序在调用 MiniportInitializeEx 期间分配 IRP 资源,则驱动程序必须在调用 MiniportHaltEx 期间释放这些资源。

以下示例演示微型端口驱动程序如何释放 IRP 资源。

//
// MiniportHaltEx
//
// During halt (or when the miniport performs its cleanup from 
// MiniportInitializeEx) the miniport should free the IRP allocated 
// earlier.
//
VOID MiniportHaltEx(
     _In_  NDIS_HANDLE MiniportAdapterContext,
     _In_  NDIS_HALT_ACTION HaltAction
    )
    {
    ...
    if (Adapter->UsbSsIrp)
        {
        IoFreeIrp(Adapter->UsbSsIrp);
        Adapter->UsbSsIrp = NULL;
        }
    ...
    }