NDIS 6.2 MiniportDriver, HaltHandlerEx (HaltHandler) is not called

Hello from Germany,

a few years ago I have developed a NDIS 6.0 Miniport Driver, which runs a PCIx busmaster ethernet adapter.

The adapter has a processor on board, which can’t maintain its state information during sleep of the computer.
Therefore the adapter has to be reinitialized, when the computer awakes from sleep.
That works well with NDIS 6.0, because
NDIS calls the HaltHandlerEx before going to sleep
NDIS calls InitializeHandlerEx when returning from sleep

The same driver has been ported to NDIS 6.2:
The error is, that
NDIS does not call the HaltHandlerEx before going to sleep
NDIS does not call InitializeHandlerEx when returning from sleep

The feature, that NDIS calls the HaltHandlerEx when going to sleep is configured, when setting the
NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES with NdisMSetMiniportAttributes.
I am not setting the AttributeFlags NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND here, so the HaltHandlerEx should be called.

This is the code for NDIS 6.0 and NDIS 6.2 (called inside of the InitializeHandlerEx function):

NDIS_STATUS SetMiniportAttributesRegistration(NDIS_HANDLE MiniportAdapterHandle, PMP162X_ADAPTER Adapter) {

NDIS_STATUS status;
NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES miniportAttributesRegistration;

NdisZeroMemory(&miniportAttributesRegistration, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));

miniportAttributesRegistration.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
miniportAttributesRegistration.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
miniportAttributesRegistration.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;

miniportAttributesRegistration.MiniportAdapterContext = Adapter;
// not setting NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND here
miniportAttributesRegistration.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;
miniportAttributesRegistration.CheckForHangTimeInSeconds = 2;
miniportAttributesRegistration.InterfaceType = NdisInterfacePci;

status = NdisMSetMiniportAttributes(MiniportAdapterHandle,(PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&miniportAttributesRegistration);
return status;

} // end SetMiniportAttributesRegistration

I know that NDIS does not call MiniportHaltEx if there are outstanding OID requests or send requests.
It is checked inside of my driver, that when the PauseHandler returns, that there are no outstanding OID requests or send requests.

This is an abbreviated trace with NDIS 6.0:

WDM162X(DriverEntry): Start
WDM162X(DriverEntry): End, status: 0x0
WDM162X(MP162XInitializeEx): Start
WDM162X(MP162XInitializeEx): End, status: 0x0
… adapter is running …
… going to sleep now …
WDM162X(MP162XPause): Start, NDIS_PAUSE_LOW_POWER
WDM162X(MP162XPause): nBusyReceives=0, nReceiveBuffersBusy=0, nNBLsNotCompleted=0, nQueriesActuallyRunning=0, nSetsActuallyRunning=0
WDM162X(MP162XPause): End, status=0x0
… HaltHandlerEx is get called …
WDM162X(MP162XHaltEx): Start (nBusyReceives=0, nReceiveBuffersBusy=0, nNBLsNotCompleted=0, nQueriesActuallyRunning=0, nSetsActuallyRunning=0)
WDM162X(MP162XHaltEx): End
HAL: Current Time: 2015-02-24, 11:23:15:500 1d050244840dec0
HAL: Wake Alarm Set: 2015-02-25, 03:00:11:000 1d050a72b4d6f80
Inventoried: 136292 pages to hibernate
83366 ranges of consecutive physical pages
3359 pages not required to hibernate
… computer has awaked from sleep and InitializeHandlerEx is get called
CP1623_Miniport.sys: 0: WDM162X(MP162XInitializeEx): Start
CP1623_Miniport.sys: 1: WDM162X(MP162XInitializeEx): End, status: 0x0

This is an abbreviated trace of the NDIS 6.2 driver when going to sleep and back:

WDM162X(DriverEntry): Start
WDM162X(DriverEntry): End, status: 0x0
WDM162X(MP162XInitializeEx): Start
WDM162X(MP162XInitializeEx): End, status: 0x0
… adapter is running …
… going to sleep now …
WDM162X(MP162XPause): Start, NDIS_PAUSE_LOW_POWER
WDM162X(MP162XPause): nBusyReceives=0, nReceiveBuffersBusy=0, nNBLsNotCompleted=0, nQueriesActuallyRunning=0, nSetsActuallyRunning=0
WDM162X(MP162XPause): End, status=0x0
… Error: HaltHandlerEx is not get called !!! …
11:11:42,380 HAL: Current Time: 2015-02-24, 11:11:41:500 1d05022aa98dfc0
11:11:42,380 HAL: Wake Alarm Set: 2015-02-25, 03:00:11:000 1d050a72b4d6f80
11:11:42,442 Inventoried: 195712 pages to hibernate
11:11:42,458 114376 ranges of consecutive physical pages
11:11:42,458 3359 pages not required to hibernate
… computer has awaked from sleep …
… Error: InitializeHandlerEx is not get called !!! …
11:12:06,939 CP1623_Miniport.sys: 1: WDM162X(MP162XQueryInformation): ReserveDPRAMTransmitRingEntry NDIS_RING failed.
11:12:06,939 CP1623_Miniport.sys: 1: WDM162X(MP162XQueryInformation): ReserveDPRAMTransmitRingEntry NDIS_RING failed.
11:12:06,939 CP1623_Miniport.sys: 1: WDM162X(MP162XQueryInformation): ReserveDPRAMTransmitRingEntry NDIS_RING failed.
11:12:06,939 CP1623_Miniport.sys: 1: WDM162X(MP162XQueryInformation): ReserveDPRAMTransmitRingEntry NDIS_RING failed.

Thanks a lot for your help.

Carsten

I think, I found the solution:

When setting the NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES with NdisMSetMiniportAttributes,
I filled the PowerManagementCapabilitiesEx like follows:

NdisZeroMemory(&miniportPMCapabilities, sizeof(NDIS_PM_CAPABILITIES));
miniportPMCapabilities.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
miniportPMCapabilities.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_1;
miniportPMCapabilities.Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1;

miniportPMCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
miniportPMCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
miniportPMCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
miniportAttributesGeneral.PowerManagementCapabilitiesEx = &miniportPMCapabilities;
status = NdisMSetMiniportAttributes(MiniportAdapterHandle,(PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&miniportAttributesGeneral);

With these settings I get an OID_PNP_SET_POWER and the HaltHandlerEx will not be called.

When changing the PowerManagementCapabilitiesEx to
miniportAttributesGeneral.PowerManagementCapabilitiesEx = NULL;
then the HaltHandlerEx is called before transitioning to sleep.