实现 MiniportIdleNotification 处理程序函数

NDIS 调用微型端口驱动程序的 MiniportIdleNotification 处理程序函数,以便有选择地挂起网络适配器。 当 NDIS 将适配器转换为低功耗状态时,适配器将挂起。

如果仍在使用网络适配器,微型端口驱动程序可以否决空闲通知。 驱动程序通过从 MiniportIdleNotification 处理程序函数返回NDIS_STATUS_BUSY来执行此操作。

注意如果 MiniportIdleNotification 处理程序函数的 ForceIdle 参数设置为 TRUE,微型端口驱动程序将无法否决空闲通知。

如果微型端口驱动程序未否决空闲通知,则可能必须发出特定于总线的 I/O 请求数据包, (IRP) 基础总线驱动程序。 这些 IRP 通知总线驱动程序适配器的空闲状态,并请求确认适配器可以转换为低功耗状态。

例如,调用 MiniportIdleNotification 时,USB 微型端口驱动程序为 USB 空闲请求准备 I/O 请求数据包 (IRP) , (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION) 。 微型端口驱动程序准备 IRP 时,必须指定回调函数。 驱动程序还必须调用 IoSetCompletionRoutineIoSetCompletionRoutineEx 来指定 IRP 的完成例程。 然后,微型端口驱动程序调用 IoCallDriver 向 USB 总线驱动程序发出 IRP。

注意 USB 总线驱动程序不会立即完成 IRP。 通过低功耗转换,IRP 将保持挂起状态。 仅当微型端口驱动程序取消 IRP 或发生硬件事件(例如意外从 USB 集线器中删除网络适配器)时,总线驱动程序才会完成 IRP。

下面是 USB 微型端口驱动程序的 MiniportIdleNotification 处理程序函数的示例。 此示例演示向基础 USB 驱动程序发出 USB 空闲请求 IRP 所涉及的步骤。 此示例还演示了如何为 IRP 重复使用以前在 MiniportInitializeEx 中分配的 IRP 资源。

//
// MiniportIdleNotification()
//
// This routine is invoked by NDIS when it has detected that the miniport
// is idle.  The miniport must prepare to issue its selective suspend IRP
// to the USB stack.  The driver can return NDIS_STATUS_BUSY if it is
// unwilling to become idle at this moment; NDIS will then retry later.
// Otherwise, the miniport should return NDIS_STATUS_PENDING.
//
NDIS_STATUS MiniportIdleNotification(
    _In_ NDIS_HANDLE MiniportAdapterContext,
    _In_ BOOLEAN ForceIdle
    )
{
    PIO_STACK_LOCATION IoSp;

    IoReuseIrp(Adapter->UsbSsIrp, STATUS_NOT_SUPPORTED);

    IoSp = IoGetNextIrpStackLocation(Adapter->UsbSsIrp);
    IoSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    IoSp->Parameters.DeviceIoControl.IoControlCode 
            = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
    IoSp->Parameters.DeviceIoControl.InputBufferLength 
            = sizeof(Adapter->UsbSsCallback);
    IoSp->Parameters.DeviceIoControl.Type3InputBuffer 
            = Adapter->UsbSsCallback;

    IoSetCompletionRoutine(
            Adapter->UsbSsIrp,
            MiniportUsbIdleRequestCompletion,
            Adapter,
            TRUE,
            TRUE,
            TRUE);

    NtStatus = IoCallDriver(Adapter->Fdo, Adapter->UsbSsIrp);
    if (!NT_SUCCESS(NtStatus))
    {
       return NDIS_STATUS_FAILURE;
    }

    return NDIS_STATUS_PENDING;
}

有关为 USB 空闲请求 IRP 实现回调例程的指南,请参阅 实现 USB 空闲请求 IRP 回调例程