Реализация функции обработчика 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.