Conditionally Defining Power Management in the NDIS Miniport Driver Object Identifier Functions (Windows CE 5.0)
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
In the MPQueryInformation function definition, use the
#ifdef
,#ifndef
, and#endif
directives to conditionally include or exclude local variables that the Windows 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 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
In the MPQueryInformation function definition, exclude the
case OID_GEN_SUPPORTED_GUIDS
statement from the Windows 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
In the MPQueryInformation function definition, use WINCE_PM_ENABLE to conditionally include the
case OID_PNP_CAPABILITIES
andcase 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
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
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
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
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
From the IDE Build menu, choose Open Build Release Directory.
Navigate to the directory containing your Windows CE NDIS miniport driver.
Be sure your NDIS miniport driver is in %_WINCEROOT%\Platform\%_TGTPLAT%\Drivers\CENDISMiniport.
Build the Windows 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
How to Migrate a Windows-based Desktop NDIS Miniport Driver to Windows CE
Send Feedback on this topic to the authors