MiniportIdleNotification ハンドラー関数の実装

NDIS は、ネットワーク アダプターを選択的に中断するためにミニポート ドライバーの MiniportIdleNotification ハンドラー関数を呼び出します。 NDIS がアダプターを低電力状態に移行すると、アダプターは中断されます。

ミニポート ドライバーは、ネットワーク アダプターがまだ使用されている場合、アイドル状態の通知を拒否できます。 ドライバーは、 MiniportIdleNotification ハンドラー関数からNDIS_STATUS_BUSYを返すことによってこれを行います。

ミニポートドライバーは、 MiniportIdleNotification ハンドラー関数の ForceIdle パラメーターが TRUE に設定されている場合、アイドル状態の通知を拒否できません。

ミニポート ドライバーがアイドル状態の通知を拒否しない場合は、基になるバス ドライバーにバス固有の I/O 要求パケット (IRP) を発行する必要があります。 これらの IRP は、アダプターのアイドル状態についてバス ドライバーに通知し、アダプターが低電力状態に移行できることを確認するように要求します。

たとえば、 MiniportIdleNotification が呼び出されると、USB ミニポート ドライバーは、USB アイドル要求 (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION) の I/O 要求パケット (IRP) を準備します。 ミニポート ドライバーは、IRP を準備するときに、コールバック関数を指定する必要があります。 ドライバーは、IRP の完了ルーチンを指定する IoSetCompletionRoutine または IoSetCompletionRoutineEx を呼び出す必要があります。 ミニポート ドライバーは、USB バス ドライバーに IRP を発行する IoCallDriver を呼び出します。

USB バス ドライバーは、IRP をすぐに完了しません。 IRP は、低電力遷移によって保留中の状態のままです。 バス ドライバーは、ミニポート ドライバーによって取り消されるか、USB ハブからのネットワーク アダプターの突然の削除などのハードウェア イベントが発生した場合にのみ IRP を完了します。

USB ミニポート ドライバーの MiniportIdleNotification ハンドラー関数の例を次に示します。 この例では、基になる USB ドライバーへの USB アイドル要求 IRP の発行に関連する手順を示します。 この例では、以前に MiniportInitializeEx で割り当てられていた IRP リソースを 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 コールバック ルーチンの実装」を参照してください。