VOID Hw11Restart( __in PHW Hw ) { // // Clear the paused flag // HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_PAUSED); // // Reenable the disabled interrupts // // // If receives are available, we would temporarily enable the // RDU interrupt to ensure that we get interrupt again. Keeping this // interrupt on all the time would cause problems with Reset/Pause // scenarios where we cannot empty the receive descriptors, and // so may keep getting interrupted // if (HwIsReceiveAvailable(Hw, FALSE)) { // // New receives are available, but we didnt indicate // them in this interrupt. Enable RDU in IntrMask. This would be // reset by the ClearInterrupt routine // HalInterlockedOrIntrMask(Hw->Hal, HAL_ISR_RX_DS_UNAVAILABLE); } // MpTrace(COMP_TESTING, DBG_SERIOUS, ("Hw11Restart \n")); HwEnableInterrupt(Hw, HW_ISR_TRACKING_PAUSE); }
NDIS_STATUS Hw11Pause( __in PHW Hw ) { // // Set the in progress flag. This would stop any new receives // from getting processed. // HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_PAUSING); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // // Wait for any current send/receive interrupt handlers to finish. New ones // may increment the counter but would abort once they find the above flag // set // HW_WAIT_FOR_ACTIVE_OPERATIONS_TO_FINISH(Hw); // Wait for active sends to be finish HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw); // For performance reason we also disable the interrupt // MpTrace(COMP_TESTING, DBG_SERIOUS, ("Hw11Pause \n")); HwDisableInterrupt(Hw, HW_ISR_TRACKING_PAUSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_PAUSED); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_PAUSING); return NDIS_STATUS_SUCCESS; }
VOID Hw11CtxSComplete( __in PHW Hw ) { // // Clear the in progress flag. This would let receive // MpTrace(COMP_MISC, DBG_SERIOUS, ("H/W context switch completed")); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_CONTEXT_SWITCH); return; }
NDIS_STATUS HwSetChannel( _In_ PHW Hw, _In_ ULONG PhyId, _In_ UCHAR Channel ) { // Must only be called for the active phy MPASSERT(PhyId == Hw->PhyState.OperatingPhyId); // When setting the channel, we dont check if we are not already on that // channel. This is because this may be called after setting a PhyID and // that does not necessarily set the channel HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_CHANNEL_SWITCH); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // Wait for active send threads to finish. We dont wait // for anything else on an HAL reset since some of those // operations themselves may be causing the reset (Eg. channel // switch of a scan) HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw); // MpTrace(COMP_TESTING, DBG_SERIOUS, ("HwSetChannel \n")); HwDisableInterrupt(Hw, HW_ISR_TRACKING_CHANNEL); // Flush the sends HwFlushSendEngine(Hw, FALSE); HalSwitchChannel(Hw->Hal, PhyId, Channel, FALSE ); HwResetSendEngine(Hw, FALSE); HwResetReceiveEngine(Hw, FALSE); HalStartReceive(Hw->Hal); // MpTrace(COMP_TESTING, DBG_SERIOUS, ("HwSetChannel \n")); HwEnableInterrupt(Hw, HW_ISR_TRACKING_CHANNEL); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_CHANNEL_SWITCH); return NDIS_STATUS_SUCCESS; }
// // Reset Step 3 - Restart the hardware // NDIS_STATUS Hw11NdisResetStep3( __in PHW Hw, __out PBOOLEAN AddressingReset ) { *AddressingReset = FALSE; HalStart(Hw->Hal, TRUE); // Push the new state on the hardware HwSetNicState(Hw); HalResetEnd(Hw->Hal); // Renable the interrupts HwEnableInterrupt(Hw, HW_ISR_TRACKING_NDIS_RESET); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_IN_RESET); // TODO: Should we return NDIS_STATUS_HARD_ERRORS if we are hung return NDIS_STATUS_SUCCESS; }
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; }
NDIS_STATUS HwResetHAL( __in PHW Hw, __in PHW_HAL_RESET_PARAMETERS ResetParams, __in BOOLEAN DispatchLevel ) { UNREFERENCED_PARAMETER(ResetParams); UNREFERENCED_PARAMETER(DispatchLevel); MPASSERT(!DispatchLevel); // Since we wait, we cannot be called at dispatch HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_HAL_IN_RESET); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // Wait for active send threads to finish. We dont wait // for anything else on an HAL reset since some of those // operations themselves may be causing the reset (Eg. channel // switch of a scan) HW_WAIT_FOR_ACTIVE_SENDS_TO_FINISH(Hw); HwDisableInterrupt(Hw, HW_ISR_TRACKING_HAL_RESET); if (ResetParams->FullReset) { // Perform a full reset of the HW HalResetStart(Hw->Hal); HalStop(Hw->Hal); // Reset the send and receive engine HwWaitForPendingReceives(Hw, NULL); HwResetSendEngine(Hw, FALSE); HwResetReceiveEngine(Hw, FALSE); // Remove old keys, etc HwClearNicState(Hw); // Reset our MAC & PHY state HwResetSoftwareMacState(Hw); HwResetSoftwarePhyState(Hw); HalStart(Hw->Hal, TRUE); // Push the new state on the hardware HwSetNicState(Hw); HalResetEnd(Hw->Hal); } else { // TODO: Currently we are overloading the HalSwitchChannel API for doing a HalReset HalSwitchChannel(Hw->Hal, Hw->PhyState.OperatingPhyId, HalGetPhyMIB(Hw->Hal, Hw->PhyState.OperatingPhyId)->Channel, FALSE ); HwResetReceiveEngine(Hw, FALSE); HwResetSendEngine(Hw, FALSE); HalStartReceive(Hw->Hal); } HwEnableInterrupt(Hw, HW_ISR_TRACKING_HAL_RESET); HW_CLEAR_ADAPTER_STATUS(Hw, HW_ADAPTER_HAL_IN_RESET); return NDIS_STATUS_SUCCESS; }