Поделиться через


Реализация функции обработчика MiniportIdleNotification

NDIS вызывает функцию обработчика MiniportIdleNotification драйвера miniport , чтобы выборочно приостановить работу сетевого адаптера. Адаптер приостанавливается, когда NDIS переводит адаптер в состояние с низким энергопотреблением.

Драйвер мини-порта может наложить вето на уведомление о простое, если сетевой адаптер по-прежнему используется. Драйвер делает это, возвращая NDIS_STATUS_BUSY из функции обработчика MiniportIdleNotification .

Примечание Драйвер мини-порта не может наложить вето на уведомление о простое, если параметр ForceIdle функции обработчика MiniportIdleNotification имеет значение TRUE.

Если драйвер мини-порта не наложит вето на уведомление о бездействии, ему, возможно, придется выдавать пакеты запросов ввода-вывода для конкретной шины (IRP) базовому драйверу автобуса. Эти irP уведомляют водителя шины о состоянии простоя адаптера и запрашивают подтверждение того, что адаптер может перейти в состояние с низким энергопотреблением.

Например, при вызове MiniportIdleNotification драйвер USB-минипорта подготавливает пакет запроса ввода-вывода (IRP) для запроса простоя USB (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION). Когда драйвер мини-порта подготавливает IRP, он должен указать функцию обратного вызова. Драйвер также должен вызвать IoSetCompletionRoutine или IoSetCompletionRoutineEx , чтобы указать подпрограмму завершения для IRP. Затем драйвер мини-порта вызывает IoCallDriver , чтобы выдать IRP драйверу USB-шины.

Примечание Драйвер USB-шины не сразу завершает IRP. IRP остается в состоянии ожидания в результате перехода с низким энергопотреблением. Драйвер автобуса завершает IRP только в том случае, если он отменен драйвером мини-порта или происходит аппаратное событие, например неожиданное удаление сетевого адаптера из USB-концентратора.

Ниже приведен пример функции обработчика MiniportIdleNotification для usb-драйвера miniport. В этом примере показаны шаги, связанные с выдачей IRP-запроса бездействия USB базовому USB-драйверу. В этом примере также показано, как ресурсы 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;
}

Рекомендации по реализации подпрограммы обратного вызова для IRP бездействующих запросов USB см. в статье Реализация процедуры обратного вызова бездействующих запросов USB.