Implementazione di una funzione del gestore MiniportIdleNotification

NDIS chiama la funzione del gestore MiniportIdleNotification del driver miniport per sospendere in modo selettivo la scheda di rete. L'adattatore viene sospeso quando NDIS passa l'adattatore a uno stato di bassa potenza.

Il driver miniport può veto la notifica inattiva se la scheda di rete è ancora in uso. Il driver esegue questa operazione restituendo NDIS_STATUS_BUSY dalla funzione del gestore MiniportIdleNotification .

Nota Il driver miniport non può veto la notifica inattiva se il parametro ForceIdle della funzione del gestore MiniportIdleNotification è impostato su TRUE.

Se il driver miniport non ha il veto della notifica inattiva, potrebbe essere necessario inviare pacchetti di richiesta I/O specifici del bus (IRP) al driver del bus sottostante. Questi IRP notificano al driver del bus lo stato di inattività dell'adattatore e richiedere la conferma che l'adattatore può passare a uno stato a bassa potenza.

Ad esempio, quando viene chiamato MiniportIdleNotification , il driver miniport USB prepara un pacchetto di richiesta I/O (IRP) per una richiesta di inattività USB (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION). Quando il driver miniport prepara l'IRP, deve specificare una funzione di callback. Il driver deve anche chiamare IoSetCompletionRoutine o IoSetCompletionRoutineEx per specificare una routine di completamento per LRP. Il driver miniport chiama quindi IoCallDriver per inviare l'IRP al driver del bus USB.

Nota Il driver del bus USB non completa immediatamente l'IRP. L'IRP viene lasciato in uno stato in sospeso tramite la transizione a bassa potenza. Il driver del bus completa l'IRP solo quando viene annullato dal driver miniport o da un evento hardware, ad esempio la rimozione sorprendente della scheda di rete dall'hub USB.

Di seguito è riportato un esempio di funzione del gestore MiniportIdleNotification per un driver miniport USB. In questo esempio vengono illustrati i passaggi coinvolti nell'emissione di un'IRP richiesta usb inattiva al driver USB sottostante. Questo esempio mostra anche come le risorse IRP, che in precedenza sono state allocate in MiniportInitializeEx, possono essere riutilizzate per l'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;
}

Per linee guida sull'implementazione di una routine di callback per un'IRP di richiesta di inattività USB, vedere Implementazione di una routine di callback di richiesta inattiva USB.