Hi everyone!
I am working on the windows driver, where currently I need to implement Wake-On Link change event as the wake up event for my network device. I am using NDIS version 6.30.
I am enabling WakeMediaConDisConnect inf property through Advanced properties tab of the driver. I am using NDIS_PM_CAPABILITIES structure to advertise my NIC hardware capabilities and I am registering this using NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES structure using NdisMSetMiniportAttributes() api.
My code to register the hardware capabilities:
if (Adapter->PmCapabilities & WOL_LINK_CHANGE_ENABLE)
{
DbgPrint("EVB: Adapter->PmCapabilities is set to WOL_LINK_CHANGE_ENABLE\n");
#if NDIS_SUPPORT_NDIS630
if (Adapter->WakeMediaConDisConnect)
{
PmCapEx.SupportedWakeUpEvents |= NDIS_PM_WAKE_ON_MEDIA_CONNECT_SUPPORTED;
Adapter->NdisHwPmParams.WakeUpFlags |= NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED;
PmCapEx.SupportedWakeUpEvents |= NDIS_PM_WAKE_ON_MEDIA_DISCONNECT_SUPPORTED;
Adapter->NdisHwPmParams.WakeUpFlags |= NDIS_PM_WAKE_ON_MEDIA_DISCONNECT_ENABLED;
PmCapEx.MinLinkChangeWakeUp = Adapter->LowestDxWakeState;
}
else
{
PmCapEx.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
}
#else
Adapter->NdisHwPmParams.WakeUpFlags |= NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED;
PmCapEx.MinLinkChangeWakeUp = Adapter->LowestDxWakeState;
#endif
}
else
{
PmCapEx.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
}
My code to set the OID_PM_PARAMETERS:
#if NDIS_SUPPORT_NDIS630
if (SetPmParams->WakeUpFlags & NDIS_PM_SELECTIVE_SUSPEND_ENABLED)
{
DbgPrint("EVB: Inside OID_PM_PARAMETERS -> Enabling Link change and good rx\n");
DBGP(MP_MOD_PM, MP_INFO, ("Selective Suspend flag - Enabling Link Change & Wake on any good packet"));
Adapter->CurrentWakeEvents |= (NIC_FEATURE_LINK_CHANGE | NIC_FEATURE_WAKE_ON_GOOD_RX);
}
if (SetPmParams->WakeUpFlags & NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED)
{
DbgPrint("EVB: Inside OID_PM_PARAMETERS -> Enabling Link Change1\n");
DBGP(MP_MOD_PM, MP_INFO, ("Wake on link change (media conenct) flag - Enabling Link Change\n"));
Adapter->CurrentWakeEvents |= (NIC_FEATURE_LINK_CHANGE);
}
if (SetPmParams->WakeUpFlags & NDIS_PM_WAKE_ON_MEDIA_DISCONNECT_ENABLED)
{
DbgPrint("EVB: Inside OID_PM_PARAMETERS -> Enabling Link Change2\n");
DBGP(MP_MOD_PM, MP_INFO, ("Media disconnect flag - Enabling Link Change\n"));
Adapter->CurrentWakeEvents |= (NIC_FEATURE_LINK_CHANGE);
}
#else
if (SetPmParams->WakeUpFlags & NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED)
{
DBGP(MP_MOD_PM, MP_INFO, ("Enabling Link Change\n"));
Adapter->CurrentWakeEvents |= NIC_FEATURE_LINK_CHANGE;
}
#endif
The problem is in SetPmParams->WakeUpFlags never contains NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED as the WakeUpFlags in its field. I am printing the values while putting the system into sleep mode. And the output is below:
SetPmParams→WakeUpFlags : 0x0
As per my understanding OID_PM_PARAMETERS set operation OID request will be requested by overlying protocol driver to the NDIS to set the power management parameters of the NIC. During the initialization driver initialize the hardware capabilities using NDIS_PM_CAPABILITIES structure. When OID_PM_PARAMETERS is requested by protocol driver the InformationBuffer contains the fields that is decided by OS power policy.
I don’t understand why SetPmParams->WakeUpFlags is never sets NDIS_PM_WAKE_ON_LINK_CHANGE_ENABLED flag even though I advertised everything properly? Or I am missing anything else?
And In WinDbg If I run the command !ndiskd.miniport -pm command I am getting the following output:
8: kd> !ndiskd.miniport ffffc2880f74d1a0 -pm
POWER MANAGEMENT
Bus Capabilities (IRP_MN_QUERY_CAPABILITIES):
SystemWake PowerSystemHibernate
DeviceWake D2
System state Device state How to read this table?
Working D0
S1 D2
S2 D2
S3 D2
S4 (Hibernate) D2
S5 (Shutdown) D3
Cached DEVICE_CAPABILITIES structure ffffc2880f74d668
Device Capabilities (OID_PM_HARDWARE_CAPABILITIES):
Flags [No flags set]
WoL patterns WOL_BITMAP, WOL_MAGIC_PACKET
Protocol offloads [No flags set]
Num patterns 8
Wake events WAKE_ON_MEDIA_CONNECT, WAKE_ON_MEDIA_DISCONNECT
Wake event Minimum power required
Magic packet D3
Bitmap pattern D3
Link change D3
Current Capabilities (OID_PM_CURRENT_CAPABILITIES):
Flags [No flags set]
WoL patterns WOL_MAGIC_PACKET
Protocol offloads [No flags set]
Num patterns 8
Wake events WAKE_ON_MEDIA_CONNECT, WAKE_ON_MEDIA_DISCONNECT
Wake event Minimum power required
Magic packet D3
Bitmap pattern Not supported
Link change D3
Active Capabilities (OID_PM_PARAMETERS):
WoL patterns WOL_MAGIC_PACKET
Protocol offloads [No flags set]
Wake flags WAKE_ON_LINK_CHANGE
Active WoL patterns
Active protocol offloads
Selective Suspend details
AOAC details
8: kd> !ndiskd.help WAKE_ON_LINK_CHANGE
So From WinDbg output everything looks fine and it it says, OID_PM_PARAMETERS request contains WAKE_ON_LINK_CHANGE flag is set.
The ouput I am getting through WinDbg and my DbgPrints (SetPmParams→WakeUpFlags) both are condratict to each other.
One more observation from my side:
If I enable SelectiveSuspend property in Advacned property page, that time SetPmParams->WakeUpFlags contains NDIS_PM_SELECTIVE_SUSPEND_ENABLED flag. I don’t know how SelectiveSuspend inf property enablement enables the OS to set the WakeUpFlags properly but WakeOnMediaConDisConnect does nothing with OS policy.
Can anyone explain me this behaviour.