// First disable interrupts and then deregister interrupts VOID Hw11Stop( __in PHW Hw, __in NDIS_HALT_ACTION HaltAction ) { UNREFERENCED_PARAMETER(HaltAction); HW_ACQUIRE_HARDWARE_LOCK(Hw, FALSE); HW_SET_ADAPTER_STATUS(Hw, HW_ADAPTER_HALTING); HW_RELEASE_HARDWARE_LOCK(Hw, FALSE); // // Deregister interrupts. We must disable them before deregistering interrupts // // MpTrace(COMP_TESTING, DBG_SERIOUS, ("Hw11Stop \n")); HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTOP); HwDeregisterInterrupt(Hw); // There must be no pending operations at this time MPASSERT(Hw->AsyncFuncRef == 0); // // Ensure that we have stop beaconing // Hw->MacState.BeaconEnabled = FALSE; Hw->MacState.BSSStarted = FALSE; // // Flush all the MSDU in the reassembly line // HwFlushMSDUReassemblyLine(Hw); // Stop everything in the H/W (We may restart things for context switches, etc) HalStop(Hw->Hal); }
VOID Hw11Shutdown( __in PHW Hw, __in NDIS_SHUTDOWN_ACTION ShutdownAction ) { UNREFERENCED_PARAMETER(ShutdownAction); // // No I/O if device has been surprise removed // if (!HW_TEST_ADAPTER_STATUS(Hw, HW_ADAPTER_SURPRISE_REMOVED)) { // // Disable Interrupts only if adapter has not been removed // // MpTrace(COMP_TESTING, DBG_SERIOUS, ("Hw11Shutdown \n")); HwDisableInterrupt(Hw, HW_ISR_TRACKING_SHUTDOWN); // // Issue a halt to the HAL. HAL should go into a known state // and shut off power to the antenna. If surprise removal has // occurred, we will not do this. // HalHaltNic(Hw->Hal); } }
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; }
// // 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 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; }
NDIS_STATUS Hw11Start( __in PHW Hw, __out NDIS_ERROR_CODE* ErrorCode, __out PULONG ErrorValue ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN interruptRegistered = FALSE, hardwareStarted = FALSE; // // Disable interrupts // We should disable interrupts before the are registered. // They will be enabled right at the end of Initialize // HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTART); do { // // Register interrupt with NDIS // ndisStatus = HwRegisterInterrupt( Hw, ErrorCode, ErrorValue ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to register interrupt with NDIS\n")); break; } interruptRegistered = TRUE; Hw->PhyState.Debug_SoftwareRadioOff = Hw->PhyState.SoftwareRadioOff; if (Hw->PhyState.SoftwareRadioOff) { HalSetRFPowerState(Hw->Hal, RF_SHUT_DOWN); } else { HalSetRFPowerState(Hw->Hal, RF_ON); } // // Start the HAL. If anything fails after this point, // we must issue a Halt to the HAL before returning // from initialize // ndisStatus = HalStart(Hw->Hal, FALSE); if(ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to start HAL successfully.\n")); break; } hardwareStarted = TRUE; // Enable the interrupts on the hardware HwEnableInterrupt(Hw, HW_ISR_TRACKING_HWSTART); }while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { // Disable interrupts and deregister them first HwDisableInterrupt(Hw, HW_ISR_TRACKING_HWSTART); if (interruptRegistered) HwDeregisterInterrupt(Hw); if (hardwareStarted) { HalStop(Hw->Hal); HalHaltNic(Hw->Hal); } } 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; }