// // Reset Step 1 - Cleanup any "pending" operations // VOID Hw11NdisResetStep1( __in PHW Hw ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; // if we are being reset because our sends are hung, we do not want to assert. however // if sends are not the cause, we do want to assert. if (!Hw11ArePktsPending(Hw)) { MPASSERT(FALSE); } // // Set state as in reset // HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_RESET); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // // Now cleanup everything // // Cancel scan (if it is running) HwCancelScan(Hw); // Wait for pending operations in the hardware to finish HW_WAIT_FOR_ACTIVE_OPERATIONS_TO_FINISH(Hw); // Wait for active sends to be finish HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw); // Disable interrupts HwDisableInterrupt(Hw, HW_ISR_TRACKING_NDIS_RESET); ndisStatus = HalResetStart(Hw->Hal); MPASSERT(ndisStatus == NDIS_STATUS_SUCCESS); HalStop(Hw->Hal); HwFlushSendEngine(Hw, FALSE); // Dont wait for pending receives here. They may be stuck in protocols on // sends & the sends may be queued in the ports. That would cause a deadlock }
NDIS_STATUS HwSetNicPowerState( _In_ PHW Hw, _In_ ULONG PhyId, _In_ BOOLEAN PowerOn ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; HW_HAL_RESET_PARAMETERS resetParams; // // Our RF cannot be selectively turned on/off. We turn on or turn off all the phys // anytime this OID is set // UNREFERENCED_PARAMETER(PhyId); // // Check if we are already in the specified state. // if (Hw->PhyState.SoftwareRadioOff == !PowerOn) { // No need to take status indications if we are // already in the correct state return NDIS_STATUS_SUCCESS; } if (!PowerOn) { // // Going to power save. Get everything into a stable state // // // If a scan is in progress, cancel scan // if (Hw->ScanContext.ScanInProgress) { HwCancelScan(Hw); } // // Before we turn off the radio, we reset the h/w. // This is to ensure that there isnt any pending operation sitting // on the hardware // NdisZeroMemory(&resetParams, sizeof(HW_HAL_RESET_PARAMETERS)); HwResetHAL(Hw, &resetParams, FALSE); // // Disable the interrupt // HwDisableInterruptWithSync(Hw, HW_ISR_TRACKING_RADIO_STATE); HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_RADIO_OFF); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); } // // Update Radio state // // Set flag so other threads (power save, scan timer, etc) wont change // state behind us Hw->PhyState.RadioStateChangeInProgress = TRUE; // We wait for ever for other threads to not reach this state while (Hw->PhyState.RadioAccessRef != 0); // // Set the Radio state // if (PowerOn) { Hw->PhyState.Debug_SoftwareRadioOff = FALSE; HalSetRFPowerState(Hw->Hal, RF_ON); Hw->PhyState.SoftwareRadioOff = FALSE; } else { Hw->PhyState.SoftwareRadioOff = TRUE; HalSetRFPowerState(Hw->Hal, RF_SHUT_DOWN); Hw->PhyState.Debug_SoftwareRadioOff = TRUE; } Hw->PhyState.RadioStateChangeInProgress = FALSE; if (PowerOn) { // Clear the radio off bit HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_RADIO_OFF); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // Re-reset the H/W to get it into a good state NdisZeroMemory(&resetParams, sizeof(HW_HAL_RESET_PARAMETERS)); resetParams.FullReset = TRUE; HwResetHAL(Hw, &resetParams, FALSE); // // Reenable the interrupt // HwEnableInterruptWithSync(Hw, HW_ISR_TRACKING_RADIO_STATE); } // // Save the new radio state in the registry // ndisStatus = HwPersistRadioPowerState(Hw, Hw->PhyState.SoftwareRadioOff); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_SERIOUS, ("Unable to persist new radio state in the registry\n")); return ndisStatus; } // // Report the new power state to the OS // HwIndicatePhyPowerState( Hw, DOT11_PHY_ID_ANY ); return ndisStatus; }