Conditionally Defining Power Management in the NDIS Miniport Driver Object Identifier Functions (Windows Embedded CE 6.0)

1/6/2010

After you modify the NDIS miniport driver send and receive functions, modify the NDIS miniport driver object identifier functions.

To conditionally define power management for the NDIS miniport driver object identifier functions

  1. In the MPQueryInformation function definition, use the #ifdef, #ifndef, and #endif directives to conditionally include or exclude local variables that the Windows Embedded CE NDIS miniport driver build may or may not require, depending on the existence of defines such as WINCE_PM_ENABLE.

    The following code example shows how to exclude these local variables from the Windows Embedded CE build.

    #ifdef WINCE_PM_ENABLE    
        NDIS_PNP_CAPABILITIES       Power_Management_Capabilities;
    #endif
    
        ULONG                       ulInfo = 0;
        ULONG64                     ul64Info = 0;
    
        USHORT                      usInfo = 0;
    #ifndef UNDER_CE    
        UCHAR                       arrInfo[ETH_LENGTH_OF_ADDRESS];
    #endif
        PVOID                       pInfo = (PVOID) &ulInfo;
        ULONG                       ulInfoLen = sizeof(ulInfo);
        ULONG                       ulBytesAvailable = ulInfoLen;
    #ifndef UNDER_CE    
        PNDIS_TASK_OFFLOAD_HEADER   pNdisTaskOffloadHdr;
    #endif
    
  2. In the MPQueryInformation function definition, exclude the case OID_GEN_SUPPORTED_GUIDS statement from the Windows Embedded CE build.

    The following code example shows how to exclude this statement from the build.

    #ifndef UNDER_CE
                // WMI support
            case OID_GEN_SUPPORTED_GUIDS:
                pInfo = (PUCHAR) &NICGuidList;
                ulBytesAvailable = ulInfoLen =  sizeof(NICGuidList);
                break;
    #endif            
    
  3. In the MPQueryInformation function definition, use WINCE_PM_ENABLE to conditionally include the case OID_PNP_CAPABILITIES and case OID_PNP_QUERY_POWER statements.

    The following code example shows how to conditionally include this statement.

    #ifdef WINCE_PM_ENABLE
            case OID_PNP_CAPABILITIES:
    
                MPFillPoMgmtCaps (Adapter, 
                                    &Power_Management_Capabilities, 
                                    &Status,
                                    &ulInfoLen);
                if (Status == NDIS_STATUS_SUCCESS)
                {
                    pInfo = (PVOID) &Power_Management_Capabilities;
                }
                else
                {
                    pInfo = NULL;
                }
    
                break;
    
            case OID_PNP_QUERY_POWER:
                // Status is pre-set in this routine to Success
    
                Status = NDIS_STATUS_SUCCESS; 
    
                break;
    #endif            
    
  4. In the MPSetInformation function definition, use WINCE_PM_ENABLE to conditionally include the NewPowerState local variable.

    The following code example shows how to conditionally include this variable.

    #ifdef WINCE_PM_ENABLE    
        NDIS_DEVICE_POWER_STATE     NewPowerState;
    #endif
    
  5. In the MPSetInformation function definition, use WINCE_PM_ENABLE to conditionally include the power related case statements.

    The following code example shows how to conditionally include these statements.

    #ifdef WINCE_PM_ENABLE
    
            case OID_PNP_SET_POWER:
    
                DBGPRINT(MP_LOUD, ("SET: Power State change, "PTR_FORMAT"!!!\n", InformationBuffer));
    
                if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
                {
                    return(NDIS_STATUS_INVALID_LENGTH);
                }
    
                NewPowerState = *(PNDIS_DEVICE_POWER_STATE    )InformationBuffer;
    
                //
                // Set the power state - Cannot fail this request
                //
                MPSetPower(Adapter ,NewPowerState );
    
                *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE    );
                Status = NDIS_STATUS_SUCCESS; 
                break;
    
            case OID_PNP_ADD_WAKE_UP_PATTERN:
                //
                // call a function that would program the adapter's wake
                // up pattern, return success
                //
                DBGPRINT(MP_LOUD, ("SET: Add Wake Up Pattern, !!!\n"));
    
                if (MPIsPoMgmtSupported(Adapter) )
                {
                    Status = MPAddWakeUpPattern(Adapter,InformationBuffer, InformationBufferLength); 
    
                    if (Status == NDIS_STATUS_SUCCESS)
                    {
                        *BytesRead = InformationBufferLength;   
                    }
                }
                else
                {
                    Status = NDIS_STATUS_NOT_SUPPORTED;
                }
                break;
    
    
            case OID_PNP_REMOVE_WAKE_UP_PATTERN:
                DBGPRINT(MP_LOUD, ("SET: Got a WakeUpPattern REMOVE Call\n"));
                //
                // call a function that would remove the adapter's wake
                // up pattern, return success
                //
                if (MPIsPoMgmtSupported(Adapter) )
                {
                    Status = MPRemoveWakeUpPattern(Adapter,InformationBuffer, InformationBufferLength );
    
                    if (Status == NDIS_STATUS_SUCCESS)
                    {
                        *BytesRead = InformationBufferLength;
                    }
                }
                else
                {
                    Status = NDIS_STATUS_NOT_SUPPORTED;
                }
                break;
    
            case OID_PNP_ENABLE_WAKE_UP:
                DBGPRINT(MP_LOUD, ("SET: Got a EnableWakeUp Call, "PTR_FORMAT"\n",InformationBuffer));
                //
                // call a function that would enable wake up on the adapter
                // return success
                //
                if (MPIsPoMgmtSupported(Adapter) )
                {
                    *BytesRead = InformationBufferLength;                         
                    Status = NDIS_STATUS_SUCCESS; 
                }
                else
                {
                    Status = NDIS_STATUS_NOT_SUPPORTED;
                }
    
                break;
    
    #endif  // WINCE_PM_ENABLE            
    
  6. Use WINCE_PM_ENABLE to conditionally include the MPSetPowerD0, MPSetPowerLow, and MPSetPower function definitions.

    The following code example shows how to conditionally include these functions.

    #ifdef WINCE_PM_ENABLE
    VOID
    MPSetPowerD0(
        PMP_ADAPTER  Adapter
        )
    /*++
    Routine Description:
    
        This routine is called when the adapter receives a SetPower 
        to D0.
    
    Arguments:
    
        Adapter                 Pointer to the adapter structure
        PowerState              NewPowerState
    
    Return Value:
    
    
    --*/
    {
    
        MPSetPowerD0Private (Adapter);       
        Adapter->CurrentPowerState = NdisDeviceStateD0;
    }
    
    #endif
    
    #ifdef WINCE_PM_ENABLE
    VOID
    MPSetPowerLow(
        PMP_ADAPTER              Adapter ,
        NDIS_DEVICE_POWER_STATE  PowerState 
        )
    /*++
    Routine Description:
    
        This routine is called when the adapter receives a SetPower 
        to a PowerState > D0
    
    Arguments:
    
        Adapter                 Pointer to the adapter structure
        PowerState              NewPowerState
    
    Return Value:
    
    
    --*/
    {
    
        NDIS_STATUS Status = NDIS_STATUS_FAILURE;
    
        do
        {
            Adapter->NextPowerState = PowerState;
    
            //        
            // Stop sending packets. Create a new flag and make it part 
            // of the Send Fail Mask
            //
    
            //
            // Stop hardware from receiving packets - Set the RU to idle 
            //
    
            //
            // Check the current status of the receive unit
            //
            if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
            {
                //
                // Issue an RU abort.  Since an interrupt will be issued, the
                // RU will be started by the DPC.
                //
                Status = D100IssueScbCommand(Adapter, SCB_RUC_ABORT, TRUE);
            }
    
            if (Status != NDIS_STATUS_SUCCESS)
            {
                break;
            }
    
            //
            // Wait for outstanding Receive packets
            //
            while (Adapter->PoMgmt.OutstandingRecv != 0)
            {
                //
                // Sleep for 2 Ms;
                //
                NdisMSleep (2000);
            }
    
            //
            // Wait for all incoming sends to complete
            //
    
            //
            // Start Hardware specific part of the transition to low power state
            // Setting up wake-up patterns, filters, wake-up events etc
            //
            NdisMSynchronizeWithInterrupt(
                    &Adapter->Interrupt,
                    MPSetPowerLowPrivate,
                    Adapter);
    
            Status = NDIS_STATUS_SUCCESS;
    
        } while (FALSE);
    
        return;
    }
    
    
    #endif
    
    #ifdef WINCE_PM_ENABLE
    VOID
    MPSetPower(
        PMP_ADAPTER     Adapter ,
        NDIS_DEVICE_POWER_STATE   PowerState 
        )
    /*++
    Routine Description:
    
        This routine is called when the adapter receives a SetPower 
        request. It redirects the call to an appropriate routine to
        Set the New PowerState
    
    Arguments:
    
        Adapter                 Pointer to the adapter structure
        PowerState              NewPowerState
    
    Return Value:
    
    
    --*/
    {
        if (PowerState == NdisDeviceStateD0)
        {
            MPSetPowerD0 (Adapter);
        }
        else
        {
            MPSetPowerLow (Adapter, PowerState);
        }
    }
    #endif
    
  7. Use WINCE_PM_ENABLE to conditionally include the MPAddWakeUpPattern function definition .

    The following code example shows how to conditionally include this function.

    #ifdef WINCE_PM_ENABLE
    NDIS_STATUS
    MPAddWakeUpPattern(
        IN PMP_ADAPTER  pAdapter,
        IN PVOID        InformationBuffer, 
        IN UINT         InformationBufferLength
        )
    /*++
    Routine Description:
    
        This routine will allocate a local memory structure, copy the pattern, 
        insert the pattern into a linked list and return success
    
        We are guaranteed that we wll get only one request at a time, so this is implemented
        without locks.
    
    Arguments:
    
        Adapter                 Adapter structure
        InformationBuffer       Wake up Pattern
        InformationBufferLength Wake Up Pattern Length
    
    Return Value:
    
        Success - if successful.
        NDIS_STATUS_FAILURE - if memory allocation fails. 
    
    --*/
    {
    
        NDIS_STATUS         Status = NDIS_STATUS_FAILURE;
        PMP_WAKE_PATTERN    pWakeUpPattern = NULL;
        UINT                AllocationLength = 0;
        PNDIS_PM_PACKET_PATTERN pPmPattern = NULL;
        ULONG               Signature = 0;
    
        do
        {
            pPmPattern = (PNDIS_PM_PACKET_PATTERN) InformationBuffer;
    
            //
            // Calculate the e100 signature
            //
            Status = MPCalculateE100PatternForFilter (
                (PUCHAR)pPmPattern+ pPmPattern->PatternOffset,
                pPmPattern->PatternSize,
                (PUCHAR)pPmPattern +sizeof(NDIS_PM_PACKET_PATTERN),
                pPmPattern->MaskSize,
                &Signature );
    
            if ( Status != NDIS_STATUS_SUCCESS)
            {
                break;
            }
    
            //
            // Allocate the memory to hold the WakeUp Pattern
            //
            AllocationLength = sizeof (MP_WAKE_PATTERN) + InformationBufferLength;
    
            Status = NdisAllocateMemoryWithTag( &pWakeUpPattern, 
                                                AllocationLength ,
                                                NIC_TAG );
    
            if (Status != NDIS_STATUS_SUCCESS)
            {
                pWakeUpPattern = NULL;
                break;
            }
    
            //
            // Initialize pWakeUpPattern
            //
            NdisZeroMemory (pWakeUpPattern, AllocationLength);
    
            pWakeUpPattern->AllocationSize = AllocationLength;
    
            pWakeUpPattern->Signature = Signature;
    
            //
            // Copy the pattern into local memory
            //
            NdisMoveMemory (&pWakeUpPattern->Pattern[0],InformationBuffer, InformationBufferLength);
    
            //
            // Insert the pattern into the list 
            //
            NdisInterlockedInsertHeadList (&pAdapter->PoMgmt.PatternList, 
                                            &pWakeUpPattern->linkListEntry, 
                                            &pAdapter->Lock);
    
            Status = NDIS_STATUS_SUCCESS;
    
        } while (FALSE);
    
        return Status;
    }
    #endif
    
  8. From the IDE Build menu, choose Open Build Release Directory.

  9. Navigate to the directory containing your Windows Embedded CE NDIS miniport driver.

    Be sure your NDIS miniport driver is in %_WINCEROOT%\Platform\%_TGTPLAT%\Drivers\CENDISMiniport.

  10. Build the Windows Embedded CE NDIS miniport driver with the Build tool.

    For more information about the Build tool, see Build Tool. Microsoft recommends using the -c parameter with the Build tool to delete all object files.

See Also

Tasks

How to Migrate a Windows-based Desktop NDIS Miniport Driver to Windows Embedded CE