Implementando uma função de manipulador MiniportIdleNotification
O NDIS chama a função de manipulador MiniportIdleNotification do driver de miniport para suspender seletivamente o adaptador de rede. O adaptador é suspenso quando o NDIS faz a transição do adaptador para um estado de baixa potência.
O driver de miniporto poderá vetar a notificação ociosa se o adaptador de rede ainda estiver sendo usado. O driver faz isso retornando NDIS_STATUS_BUSY da função de manipulador MiniportIdleNotification .
Nota O driver de miniporto não poderá vetar a notificação ociosa se o parâmetro ForceIdle da função de manipulador MiniportIdleNotification estiver definido como TRUE.
Se o driver de miniporto não vetar a notificação ociosa, talvez seja necessário emitir IRPs (pacotes de solicitação de E/S) específicos do barramento para o motorista do ônibus subjacente. Esses IRPs notificam o motorista do barramento sobre o estado ocioso do adaptador e solicitam a confirmação de que o adaptador pode fazer a transição para um estado de baixa potência.
Por exemplo, quando MiniportIdleNotification é chamado, o driver de miniporto USB prepara um IRP (pacote de solicitação de E/S) para uma solicitação ociosa USB (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION). Quando o driver de miniporto prepara o IRP, ele deve especificar uma função de retorno de chamada. O driver também deve chamar IoSetCompletionRoutine ou IoSetCompletionRoutineEx para especificar uma rotina de conclusão para o IRP. Em seguida, o driver de miniporto chama IoCallDriver para emitir o IRP para o motorista do ônibus USB.
Nota O driver do ônibus USB não conclui imediatamente o IRP. O IRP é deixado em um estado pendente por meio da transição de baixa potência. O driver do barramento conclui o IRP somente quando ele é cancelado pelo driver de miniporto ou ocorre um evento de hardware, como a remoção surpresa do adaptador de rede do hub USB.
Veja a seguir um exemplo de uma função de manipulador MiniportIdleNotification para um driver de miniporto USB. Este exemplo mostra as etapas envolvidas na emissão de um IRP de solicitação ociosa USB para o driver USB subjacente. Este exemplo também mostra como os recursos IRP, que foram alocados anteriormente em MiniportInitializeEx, podem ser reutilizados para o 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;
}
Para obter diretrizes sobre como implementar uma rotina de retorno de chamada para um IRP de solicitação ociosa USB, consulte Implementando uma rotina de retorno de chamada IRP de solicitação ociosa USB.