/* * Control Adaptive Noise Immunity Parameters */ HAL_BOOL ar9300_ani_control(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) { struct ath_hal_9300 *ahp = AH9300(ah); struct ar9300_ani_state *ani_state = ahp->ah_curani; const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; int32_t value, value2; u_int level = param; u_int is_on; if (chan == NULL && cmd != HAL_ANI_MODE) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: ignoring cmd 0x%02x - no channel\n", __func__, cmd); return AH_FALSE; } switch (cmd & ahp->ah_ani_function) { case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { int m1_thresh_low, m2_thresh_low; int m1_thresh, m2_thresh; int m2_count_thr, m2_count_thr_low; int m1_thresh_low_ext, m2_thresh_low_ext; int m1_thresh_ext, m2_thresh_ext; /* * is_on == 1 means ofdm weak signal detection is ON * (default, less noise imm) * is_on == 0 means ofdm weak signal detection is OFF * (more noise imm) */ is_on = param ? 1 : 0; if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) goto skip_ws_det; /* * make register setting for default (weak sig detect ON) * come from INI file */ m1_thresh_low = is_on ? ani_state->ini_def.m1_thresh_low : m1_thresh_low_off; m2_thresh_low = is_on ? ani_state->ini_def.m2_thresh_low : m2_thresh_low_off; m1_thresh = is_on ? ani_state->ini_def.m1_thresh : m1_thresh_off; m2_thresh = is_on ? ani_state->ini_def.m2_thresh : m2_thresh_off; m2_count_thr = is_on ? ani_state->ini_def.m2_count_thr : m2_count_thr_off; m2_count_thr_low = is_on ? ani_state->ini_def.m2_count_thr_low : m2_count_thr_low_off; m1_thresh_low_ext = is_on ? ani_state->ini_def.m1_thresh_low_ext : m1_thresh_low_ext_off; m2_thresh_low_ext = is_on ? ani_state->ini_def.m2_thresh_low_ext : m2_thresh_low_ext_off; m1_thresh_ext = is_on ? ani_state->ini_def.m1_thresh_ext : m1_thresh_ext_off; m2_thresh_ext = is_on ? ani_state->ini_def.m2_thresh_ext : m2_thresh_ext_off; OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M1_THRESH, m1_thresh); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2_THRESH, m2_thresh); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2COUNT_THR, m2_count_thr); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2_count_thr_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1_thresh_low_ext); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2_thresh_low_ext); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH, m1_thresh_ext); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH, m2_thresh_ext); skip_ws_det: if (is_on) { OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); } else { OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); } if (!(is_on != ani_state->ofdm_weak_sig_detect_off)) { HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: ofdm weak signal: %s=>%s\n", __func__, chan->ic_freq, !ani_state->ofdm_weak_sig_detect_off ? "on" : "off", is_on ? "on" : "off"); if (is_on) { ahp->ah_stats.ast_ani_ofdmon++; } else { ahp->ah_stats.ast_ani_ofdmoff++; } ani_state->ofdm_weak_sig_detect_off = !is_on; } break; } case HAL_ANI_FIRSTEP_LEVEL: if (level >= ARRAY_LENGTH(firstep_table)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: HAL_ANI_FIRSTEP_LEVEL level out of range (%u > %u)\n", __func__, level, (unsigned) ARRAY_LENGTH(firstep_table)); return AH_FALSE; } /* * make register setting relative to default * from INI file & cap value */ value = firstep_table[level] - firstep_table[HAL_ANI_DEF_FIRSTEP_LVL] + ani_state->ini_def.firstep; if (value < HAL_SIG_FIRSTEP_SETTING_MIN) { value = HAL_SIG_FIRSTEP_SETTING_MIN; } if (value > HAL_SIG_FIRSTEP_SETTING_MAX) { value = HAL_SIG_FIRSTEP_SETTING_MAX; } OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP, value); /* * we need to set first step low register too * make register setting relative to default from INI file & cap value */ value2 = firstep_table[level] - firstep_table[HAL_ANI_DEF_FIRSTEP_LVL] + ani_state->ini_def.firstep_low; if (value2 < HAL_SIG_FIRSTEP_SETTING_MIN) { value2 = HAL_SIG_FIRSTEP_SETTING_MIN; } if (value2 > HAL_SIG_FIRSTEP_SETTING_MAX) { value2 = HAL_SIG_FIRSTEP_SETTING_MAX; } OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); if (level != ani_state->firstep_level) { HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n", __func__, chan->ic_freq, ani_state->firstep_level, level, HAL_ANI_DEF_FIRSTEP_LVL, value, ani_state->ini_def.firstep); HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: level %d=>%d[def:%d] " "firstep_low[level]=%d ini=%d\n", __func__, chan->ic_freq, ani_state->firstep_level, level, HAL_ANI_DEF_FIRSTEP_LVL, value2, ani_state->ini_def.firstep_low); if (level > ani_state->firstep_level) { ahp->ah_stats.ast_ani_stepup++; } else if (level < ani_state->firstep_level) { ahp->ah_stats.ast_ani_stepdown++; } ani_state->firstep_level = level; } break; case HAL_ANI_SPUR_IMMUNITY_LEVEL: if (level >= ARRAY_LENGTH(cycpwr_thr1_table)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL level " "out of range (%u > %u)\n", __func__, level, (unsigned) ARRAY_LENGTH(cycpwr_thr1_table)); return AH_FALSE; } /* * make register setting relative to default from INI file & cap value */ value = cycpwr_thr1_table[level] - cycpwr_thr1_table[HAL_ANI_DEF_SPUR_IMMUNE_LVL] + ani_state->ini_def.cycpwr_thr1; if (value < HAL_SIG_SPUR_IMM_SETTING_MIN) { value = HAL_SIG_SPUR_IMM_SETTING_MIN; } if (value > HAL_SIG_SPUR_IMM_SETTING_MAX) { value = HAL_SIG_SPUR_IMM_SETTING_MAX; } OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_CYCPWR_THR1, value); /* * set AR_PHY_EXT_CCA for extension channel * make register setting relative to default from INI file & cap value */ value2 = cycpwr_thr1_table[level] - cycpwr_thr1_table[HAL_ANI_DEF_SPUR_IMMUNE_LVL] + ani_state->ini_def.cycpwr_thr1_ext; if (value2 < HAL_SIG_SPUR_IMM_SETTING_MIN) { value2 = HAL_SIG_SPUR_IMM_SETTING_MIN; } if (value2 > HAL_SIG_SPUR_IMM_SETTING_MAX) { value2 = HAL_SIG_SPUR_IMM_SETTING_MAX; } OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CYCPWR_THR1, value2); if (level != ani_state->spur_immunity_level) { HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: level %d=>%d[def:%d] " "cycpwr_thr1[level]=%d ini=%d\n", __func__, chan->ic_freq, ani_state->spur_immunity_level, level, HAL_ANI_DEF_SPUR_IMMUNE_LVL, value, ani_state->ini_def.cycpwr_thr1); HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: level %d=>%d[def:%d] " "cycpwr_thr1_ext[level]=%d ini=%d\n", __func__, chan->ic_freq, ani_state->spur_immunity_level, level, HAL_ANI_DEF_SPUR_IMMUNE_LVL, value2, ani_state->ini_def.cycpwr_thr1_ext); if (level > ani_state->spur_immunity_level) { ahp->ah_stats.ast_ani_spurup++; } else if (level < ani_state->spur_immunity_level) { ahp->ah_stats.ast_ani_spurdown++; } ani_state->spur_immunity_level = level; } break; case HAL_ANI_MRC_CCK: /* * is_on == 1 means MRC CCK ON (default, less noise imm) * is_on == 0 means MRC CCK is OFF (more noise imm) */ is_on = param ? 1 : 0; if (!AR_SREV_POSEIDON(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, AR_PHY_MRC_CCK_ENABLE, is_on); OS_REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, AR_PHY_MRC_CCK_MUX_REG, is_on); } if (!(is_on != ani_state->mrc_cck_off)) { HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ** ch %d: MRC CCK: %s=>%s\n", __func__, chan->ic_freq, !ani_state->mrc_cck_off ? "on" : "off", is_on ? "on" : "off"); if (is_on) { ahp->ah_stats.ast_ani_ccklow++; } else { ahp->ah_stats.ast_ani_cckhigh++; } ani_state->mrc_cck_off = !is_on; } break; case HAL_ANI_PRESENT: break; #ifdef AH_PRIVATE_DIAG case HAL_ANI_MODE: if (param == 0) { ahp->ah_proc_phy_err &= ~HAL_PROCESS_ANI; /* Turn off HW counters if we have them */ ar9300_ani_detach(ah); if (AH_PRIVATE(ah)->ah_curchan == NULL) { return AH_TRUE; } /* if we're turning off ANI, reset regs back to INI settings */ if (ah->ah_config.ath_hal_enable_ani) { HAL_ANI_CMD savefunc = ahp->ah_ani_function; /* temporarly allow all functions so we can reset */ ahp->ah_ani_function = HAL_ANI_ALL; HALDEBUG(ah, HAL_DEBUG_ANI, "%s: disable all ANI functions\n", __func__); ar9300_ani_set_odfm_noise_immunity_level( ah, HAL_ANI_OFDM_DEF_LEVEL); ar9300_ani_set_cck_noise_immunity_level( ah, HAL_ANI_CCK_DEF_LEVEL); ahp->ah_ani_function = savefunc; } } else { /* normal/auto mode */ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: enabled\n", __func__); ahp->ah_proc_phy_err |= HAL_PROCESS_ANI; if (AH_PRIVATE(ah)->ah_curchan == NULL) { return AH_TRUE; } ar9300_enable_mib_counters(ah); ar9300_ani_reset(ah, AH_FALSE); ani_state = ahp->ah_curani; } HALDEBUG(ah, HAL_DEBUG_ANI, "5 ANC: ahp->ah_proc_phy_err %x \n", ahp->ah_proc_phy_err); break; case HAL_ANI_PHYERR_RESET: ahp->ah_stats.ast_ani_ofdmerrs = 0; ahp->ah_stats.ast_ani_cckerrs = 0; break; #endif /* AH_PRIVATE_DIAG */ default: #if HAL_ANI_DEBUG HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid cmd 0x%02x (allowed=0x%02x)\n", __func__, cmd, ahp->ah_ani_function); #endif return AH_FALSE; } #if HAL_ANI_DEBUG HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI parameters: SI=%d, ofdm_ws=%s FS=%d MRCcck=%s listen_time=%d " "CC=%d listen=%d ofdm_errs=%d cck_errs=%d\n", __func__, ani_state->spur_immunity_level, !ani_state->ofdm_weak_sig_detect_off ? "on" : "off", ani_state->firstep_level, !ani_state->mrc_cck_off ? "on" : "off", ani_state->listen_time, ani_state->cycle_count, ani_state->listen_time, ani_state->ofdm_phy_err_count, ani_state->cck_phy_err_count); #endif #ifndef REMOVE_PKT_LOG /* do pktlog */ { struct log_ani log_data; /* Populate the ani log record */ log_data.phy_stats_disable = DO_ANI(ah); log_data.noise_immun_lvl = ani_state->ofdm_noise_immunity_level; log_data.spur_immun_lvl = ani_state->spur_immunity_level; log_data.ofdm_weak_det = ani_state->ofdm_weak_sig_detect_off; log_data.cck_weak_thr = ani_state->cck_noise_immunity_level; log_data.fir_lvl = ani_state->firstep_level; log_data.listen_time = ani_state->listen_time; log_data.cycle_count = ani_state->cycle_count; /* express ofdm_phy_err_count as errors/second */ log_data.ofdm_phy_err_count = ani_state->listen_time ? ani_state->ofdm_phy_err_count * 1000 / ani_state->listen_time : 0; /* express cck_phy_err_count as errors/second */ log_data.cck_phy_err_count = ani_state->listen_time ? ani_state->cck_phy_err_count * 1000 / ani_state->listen_time : 0; log_data.rssi = ani_state->rssi; /* clear interrupt context flag */ ath_hal_log_ani(AH_PRIVATE(ah)->ah_sc, &log_data, 0); } #endif return AH_TRUE; }
void ar9300_attach_freebsd_ops(struct ath_hal *ah) { /* Global functions */ ah->ah_detach = ar9300_detach; ah->ah_getRateTable = ar9300_get_rate_table; /* Reset functions */ ah->ah_reset = ar9300_reset_freebsd; ah->ah_phyDisable = ar9300_phy_disable; ah->ah_disable = ar9300_disable; ah->ah_configPCIE = ar9300_config_pcie_freebsd; // ah->ah_disablePCIE = ar9300_disable_pcie_phy; ah->ah_setPCUConfig = ar9300_set_pcu_config; // perCalibration ah->ah_perCalibrationN = ar9300_per_calibration_freebsd; ah->ah_resetCalValid = ar9300_reset_cal_valid_freebsd; ah->ah_setTxPowerLimit = ar9300_freebsd_set_tx_power_limit; ah->ah_getChanNoise = ath_hal_getChanNoise; /* Transmit functions */ ah->ah_setupTxQueue = ar9300_setup_tx_queue; ah->ah_setTxQueueProps = ar9300_set_tx_queue_props; ah->ah_getTxQueueProps = ar9300_get_tx_queue_props; ah->ah_releaseTxQueue = ar9300_release_tx_queue; ah->ah_resetTxQueue = ar9300_reset_tx_queue; ah->ah_getTxDP = ar9300_get_tx_dp; ah->ah_setTxDP = ar9300_set_tx_dp; ah->ah_numTxPending = ar9300_num_tx_pending; ah->ah_startTxDma = ar9300_start_tx_dma; ah->ah_stopTxDma = ar9300_stop_tx_dma_freebsd; ah->ah_setupTxDesc = ar9300_freebsd_setup_tx_desc; ah->ah_setupXTxDesc = ar9300_freebsd_setup_x_tx_desc; ah->ah_fillTxDesc = ar9300_freebsd_fill_tx_desc; ah->ah_procTxDesc = ar9300_freebsd_proc_tx_desc; ah->ah_getTxIntrQueue = ar9300_get_tx_intr_queue; // reqTxIntrDesc ah->ah_getTxCompletionRates = ar9300_freebsd_get_tx_completion_rates; ah->ah_setTxDescLink = ar9300_set_desc_link; ah->ah_getTxDescLink = ar9300_freebsd_get_desc_link; ah->ah_getTxDescLinkPtr = ar9300_get_desc_link_ptr; ah->ah_setupTxStatusRing = ar9300_setup_tx_status_ring; ah->ah_getTxRawTxDesc = ar9300_get_raw_tx_desc; ah->ah_updateTxTrigLevel = ar9300_update_tx_trig_level; /* RX functions */ ah->ah_getRxDP = ar9300_get_rx_dp; ah->ah_setRxDP = ar9300_set_rx_dp; ah->ah_enableReceive = ar9300_enable_receive; ah->ah_stopDmaReceive = ar9300_stop_dma_receive_freebsd; ah->ah_startPcuReceive = ar9300_start_pcu_receive_freebsd; ah->ah_stopPcuReceive = ar9300_stop_pcu_receive; ah->ah_setMulticastFilter = ar9300_set_multicast_filter; ah->ah_setMulticastFilterIndex = ar9300SetMulticastFilterIndex; ah->ah_clrMulticastFilterIndex = ar9300ClrMulticastFilterIndex; ah->ah_getRxFilter = ar9300_get_rx_filter; ah->ah_setRxFilter = ar9300_set_rx_filter; /* setupRxDesc */ ah->ah_procRxDesc = ar9300_proc_rx_desc_freebsd; ah->ah_rxMonitor = ar9300_ani_rxmonitor_freebsd; ah->ah_aniPoll = ar9300_ani_poll_freebsd; ah->ah_procMibEvent = ar9300_process_mib_intr; /* Misc functions */ ah->ah_getCapability = ar9300_get_capability; ah->ah_setCapability = ar9300_set_capability; ah->ah_getDiagState = ar9300_get_diag_state; ah->ah_getMacAddress = ar9300_get_mac_address; ah->ah_setMacAddress = ar9300_set_mac_address; ah->ah_getBssIdMask = ar9300_get_bss_id_mask; ah->ah_setBssIdMask = ar9300_set_bss_id_mask; ah->ah_setRegulatoryDomain = ar9300_set_regulatory_domain; ah->ah_setLedState = ar9300_set_led_state; ah->ah_writeAssocid = ar9300_write_associd; ah->ah_gpioCfgInput = ar9300_gpio_cfg_input; ah->ah_gpioCfgOutput = ar9300_gpio_cfg_output; ah->ah_gpioGet = ar9300_gpio_get; ah->ah_gpioSet = ar9300_gpio_set; ah->ah_gpioSetIntr = ar9300_gpio_set_intr; /* polarity */ /* mask */ ah->ah_getTsf32 = ar9300_get_tsf32; ah->ah_getTsf64 = ar9300_get_tsf64; ah->ah_resetTsf = ar9300_reset_tsf; ah->ah_setTsf64 = ar9300_freebsd_set_tsf64; ah->ah_detectCardPresent = ar9300_detect_card_present; // ah->ah_updateMibCounters = ar9300_update_mib_counters; ah->ah_getRfGain = ar9300_get_rfgain; ah->ah_getDefAntenna = ar9300_get_def_antenna; ah->ah_setDefAntenna = ar9300_set_def_antenna; ah->ah_getAntennaSwitch = ar9300_freebsd_get_antenna_switch; ah->ah_setAntennaSwitch = ar9300_freebsd_set_antenna_switch; // ah->ah_setSifsTime = ar9300_set_sifs_time; // ah->ah_getSifsTime = ar9300_get_sifs_time; ah->ah_setSlotTime = ar9300_set_slot_time; ah->ah_getSlotTime = ar9300GetSlotTime; ah->ah_getAckTimeout = ar9300_get_ack_timeout; ah->ah_setAckTimeout = ar9300_set_ack_timeout; // XXX ack/ctsrate // XXX CTS timeout ah->ah_getCTSTimeout = ar9300_freebsd_get_cts_timeout; // XXX decompmask // coverageclass ah->ah_setQuiet = ar9300_set_quiet; ah->ah_getMibCycleCounts = ar9300_freebsd_get_mib_cycle_counts; /* DFS functions */ ah->ah_enableDfs = ar9300_enable_dfs; ah->ah_getDfsThresh = ar9300_get_dfs_thresh; ah->ah_getDfsDefaultThresh = ar9300_get_default_dfs_thresh; ah->ah_procRadarEvent = ar9300_freebsd_proc_radar_event; ah->ah_isFastClockEnabled = ar9300_is_fast_clock_enabled; ah->ah_get11nExtBusy = ar9300_get_11n_ext_busy; ah->ah_setDfsCacTxQuiet = ar9300_cac_tx_quiet; /* Spectral Scan Functions */ ah->ah_spectralConfigure = ar9300_configure_spectral_scan; ah->ah_spectralGetConfig = ar9300_get_spectral_params; ah->ah_spectralStart = ar9300_start_spectral_scan; ah->ah_spectralStop = ar9300_stop_spectral_scan; ah->ah_spectralIsEnabled = ar9300_is_spectral_enabled; ah->ah_spectralIsActive = ar9300_is_spectral_active; /* Key cache functions */ ah->ah_getKeyCacheSize = ar9300_get_key_cache_size; ah->ah_resetKeyCacheEntry = ar9300_reset_key_cache_entry; ah->ah_isKeyCacheEntryValid = ar9300_is_key_cache_entry_valid; ah->ah_setKeyCacheEntry = ar9300_set_key_cache_entry; ah->ah_setKeyCacheEntryMac = ar9300_set_key_cache_entry_mac; /* Power management functions */ ah->ah_setPowerMode = ar9300_set_power_mode; ah->ah_getPowerMode = ar9300_get_power_mode; /* Beacon functions */ /* ah_setBeaconTimers */ ah->ah_beaconInit = ar9300_freebsd_beacon_init; ah->ah_setBeaconTimers = ar9300_beacon_set_beacon_timers; ah->ah_setStationBeaconTimers = ar9300_set_sta_beacon_timers; /* ah_resetStationBeaconTimers */ ah->ah_getNextTBTT = ar9300_get_next_tbtt; /* Interrupt functions */ ah->ah_isInterruptPending = ar9300_is_interrupt_pending; ah->ah_getPendingInterrupts = ar9300_get_pending_interrupts_freebsd; ah->ah_getInterrupts = ar9300_get_interrupts; ah->ah_setInterrupts = ar9300_set_interrupts_freebsd; /* Regulatory/internal functions */ // AH_PRIVATE(ah)->ah_getNfAdjust = ar9300_get_nf_adjust; AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word; // AH_PRIVATE(ah)->ah_getChipPowerLimits = ar9300_get_chip_power_limits; AH_PRIVATE(ah)->ah_getWirelessModes = ar9300_get_wireless_modes; AH_PRIVATE(ah)->ah_getChannelEdges = ar9300_get_channel_edges; AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word; /* XXX ah_eeprom */ /* XXX ah_eeversion */ /* XXX ah_eepromDetach */ /* XXX ah_eepromGet */ AH_PRIVATE(ah)->ah_eepromGet = ar9300_eeprom_get_freebsd; /* XXX ah_eepromSet */ /* XXX ah_getSpurChan */ /* XXX ah_eepromDiag */ /* 802.11n functions */ ah->ah_chainTxDesc = ar9300_freebsd_chain_tx_desc; ah->ah_setupFirstTxDesc= ar9300_freebsd_setup_first_tx_desc; ah->ah_setupLastTxDesc = ar9300_freebsd_setup_last_tx_desc; ah->ah_set11nRateScenario = ar9300_freebsd_set_11n_rate_scenario; ah->ah_set11nTxDesc = ar9300_freebsd_setup_11n_desc; ah->ah_set11nAggrFirst = ar9300_set_11n_aggr_first; ah->ah_set11nAggrMiddle = ar9300_set_11n_aggr_middle; ah->ah_set11nAggrLast = ar9300_set_11n_aggr_last; ah->ah_clr11nAggr = ar9300_clr_11n_aggr; ah->ah_set11nBurstDuration = ar9300_set_11n_burst_duration; /* ah_get11nExtBusy */ ah->ah_set11nMac2040 = ar9300_set_11n_mac2040; ah->ah_setChainMasks = ar9300SetChainMasks; /* ah_get11nRxClear */ /* ah_set11nRxClear */ /* bluetooth coexistence functions */ ah->ah_btCoexSetInfo = ar9300_set_bt_coex_info; ah->ah_btCoexSetConfig = ar9300_bt_coex_config; ah->ah_btCoexSetQcuThresh = ar9300_bt_coex_set_qcu_thresh; ah->ah_btCoexSetWeights = ar9300_bt_coex_set_weights; ah->ah_btCoexSetBmissThresh = ar9300_bt_coex_setup_bmiss_thresh; ah->ah_btCoexSetParameter = ar9300_bt_coex_set_parameter; ah->ah_btCoexDisable = ar9300_bt_coex_disable; ah->ah_btCoexEnable = ar9300_bt_coex_enable; /* MCI bluetooth functions */ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* * Note: these are done in attach too for now, because * at this point we haven't yet setup the mac/bb revision * values, so this code is effectively NULL. * However, I'm leaving this here so people digging * into the code (a) see the MCI bits here, and (b) * are now told they should look elsewhere for * these methods. */ ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights; ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable; ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable; } ah->ah_btMciSetup = ar9300_mci_setup; ah->ah_btMciSendMessage = ar9300_mci_send_message; ah->ah_btMciGetInterrupt = ar9300_mci_get_interrupt; ah->ah_btMciState = ar9300_mci_state; ah->ah_btMciDetach = ar9300_mci_detach; /* LNA diversity functions */ ah->ah_divLnaConfGet = ar9300_ant_div_comb_get_config; ah->ah_divLnaConfSet = ar9300_ant_div_comb_set_config; }
/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus * * Actual Expression, * * For 2GHz channel, * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) * * For 5GHz channel, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) * (freq_ref = 40MHz/(24>>amode_ref_sel)) * * For 5GHz channels which are 5MHz spaced, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) */ static HAL_BOOL ar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0; u_int32_t freq, channel_sel, reg32; u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; CHAN_CENTERS centers; int load_synth_channel; #ifdef AH_DEBUG_ALQ HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); #endif /* * Put this behind AH_DEBUG_ALQ for now until the Hornet * channel_sel code below is made to work. */ #ifdef AH_DEBUG_ALQ OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel); #endif ar9300_get_channel_centers(ah, chan, ¢ers); freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ b_mode = 1; /* 2 GHz */ if (AR_SREV_HORNET(ah)) { #if 0 u_int32_t ichan = ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags); HALASSERT(ichan > 0 && ichan <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[ichan - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[ichan - 1]; } #endif uint32_t i; /* * Pay close attention to this bit! * * We need to map the actual desired synth frequency to * one of the channel select array entries. * * For HT20, it'll align with the channel we select. * * For HT40 though it won't - the centre frequency * will not be the frequency of chan->ic_freq or ichan->freq; * it needs to be whatever frequency maps to 'freq'. */ i = ath_hal_mhz2ieee_2ghz(ah, freq); HALASSERT(i > 0 && i <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[i - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[i - 1]; } } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { u_int32_t channel_frac; /* * freq_ref = (40 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; channel_sel = (channel_sel << 17) | (channel_frac); } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { u_int32_t channel_frac; if (clk_25mhz) { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 75; channel_frac = (((freq * 4) % 75) * 0x20000) / 75; } else { channel_sel = (freq * 2) / 75; channel_frac = (((freq * 2) % 75) * 0x20000) / 75; } } else { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ if (AR_SREV_SCORPION(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; } else { channel_sel = (freq * 2) / 120; channel_frac = (((freq * 2) % 120) * 0x20000) / 120; } } channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_2G(freq); } } else { b_mode = 0; /* 5 GHz */ if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){ u_int32_t channel_frac; /* * freq_ref = (50 / (refdiva >> amoderefsel)); * (refdiva = 1, amoderefsel = 0) * ndiv = ((chan_mhz * 2) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = freq / 75 ; channel_frac = ((freq % 75) * 0x20000) / 75; channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_5G(freq); /* Doubler is ON, so, divide channel_sel by 2. */ channel_sel >>= 1; } } /* Enable fractional mode for all channels */ frac_mode = 1; a_mode_ref_sel = 0; load_synth_channel = 0; reg32 = (b_mode << 29); OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); /* Enable Long shift Select for Synthesizer */ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); /* program synth. setting */ reg32 = (channel_sel << 2) | (a_mode_ref_sel << 28) | (frac_mode << 30) | (load_synth_channel << 31); if (IEEE80211_IS_CHAN_QUARTER(chan)) { reg32 += CHANSEL_5G_DOT5MHZ; } OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); /* Toggle Load Synth channel bit */ load_synth_channel = 1; reg32 |= load_synth_channel << 31; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE; }