OID_PM_PARAMETERS set operation is not setting WAKE_ON_LINK_CHANGE in WakeUpFlags field of the NDIS_PM_PARAMETERS structure

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.