diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c index 37e64bc86cdd..68e5f018cc6c 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c @@ -1,1000 +1,1019 @@ /* * Copyright (c) 2012, 2013 Adrian Chadd . * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ah_desc.h" #include "ar9300.h" #include "ar9300reg.h" #include "ar9300phy.h" #include "ar9300desc.h" #include "ar9300_freebsd.h" #include "ar9300_stub.h" #include "ar9300_stub_funcs.h" #define FIX_NOISE_FLOOR 1 #define NEXT_TBTT_NOW 5 static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix); static HAL_BOOL ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix); static void ar9300_beacon_set_beacon_timers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt); static void ar9300SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, uint32_t rx_chainmask) { AH9300(ah)->ah_tx_chainmask = tx_chainmask & AH_PRIVATE(ah)->ah_caps.halTxChainMask; AH9300(ah)->ah_rx_chainmask = rx_chainmask & AH_PRIVATE(ah)->ah_caps.halRxChainMask; } static u_int ar9300GetSlotTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; return (ath_hal_mac_usec(ah, clks)); /* convert from system clocks */ } static HAL_BOOL ar9300_freebsd_set_tx_power_limit(struct ath_hal *ah, uint32_t limit) { return (ar9300_set_tx_power_limit(ah, limit, 0, 0)); } static uint64_t ar9300_get_next_tbtt(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_NEXT_TBTT_TIMER)); } +static u_int +ar9300_get_nav(struct ath_hal *ah) +{ + uint32_t reg; + + reg = OS_REG_READ(ah, AR_NAV); + if (reg == 0xdeadbeef) + return 0; + return reg; +} + +static void +ar9300_set_nav(struct ath_hal *ah, u_int nav) +{ + + OS_REG_WRITE(ah, AR_NAV, nav); +} /* * TODO: implement the antenna diversity control for AR9485 and * other LNA mixing based NICs. * * For now we'll just go with the HAL default and make these no-ops. */ static HAL_ANT_SETTING ar9300_freebsd_get_antenna_switch(struct ath_hal *ah) { return (HAL_ANT_VARIABLE); } static HAL_BOOL ar9300_freebsd_set_antenna_switch(struct ath_hal *ah, HAL_ANT_SETTING setting) { return (AH_TRUE); } static u_int ar9300_freebsd_get_cts_timeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } static void ar9300_freebsd_set_tsf64(struct ath_hal *ah, uint64_t tsf64) { /* * XXX TODO: read ar5416SetTsf64() - we should wait before we do * this. */ OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); } /* Flags for pulse_bw_info */ #define PRI_CH_RADAR_FOUND 0x01 #define EXT_CH_RADAR_FOUND 0x02 #define EXT_CH_RADAR_EARLY_FOUND 0x04 static HAL_BOOL ar9300_freebsd_proc_radar_event(struct ath_hal *ah, struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) { HAL_BOOL doDfsExtCh; HAL_BOOL doDfsEnhanced; HAL_BOOL doDfsCombinedRssi; uint8_t rssi = 0, ext_rssi = 0; uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0; uint32_t dur = 0; int pri_found = 1, ext_found = 0; int early_ext = 0; int is_dc = 0; uint16_t datalen; /* length from the RX status field */ /* Check whether the given phy error is a radar event */ if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) { return AH_FALSE; } /* Grab copies of the capabilities; just to make the code clearer */ doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport; doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport; doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi; datalen = rxs->rs_datalen; /* If hardware supports it, use combined RSSI, else use chain 0 RSSI */ if (doDfsCombinedRssi) rssi = (uint8_t) rxs->rs_rssi; else rssi = (uint8_t) rxs->rs_rssi_ctl[0]; /* Set this; but only use it if doDfsExtCh is set */ ext_rssi = (uint8_t) rxs->rs_rssi_ext[0]; /* Cap it at 0 if the RSSI is a negative number */ if (rssi & 0x80) rssi = 0; if (ext_rssi & 0x80) ext_rssi = 0; /* * Fetch the relevant data from the frame */ if (doDfsExtCh) { if (datalen < 3) return AH_FALSE; /* Last three bytes of the frame are of interest */ pulse_length_pri = *(buf + datalen - 3); pulse_length_ext = *(buf + datalen - 2); pulse_bw_info = *(buf + datalen - 1); HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d," " pulse_length_ext=%d, pulse_bw_info=%x\n", __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext, pulse_bw_info); } else { /* The pulse width is byte 0 of the data */ if (datalen >= 1) dur = ((uint8_t) buf[0]) & 0xff; else dur = 0; if (dur == 0 && rssi == 0) { HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__); return AH_FALSE; } HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur); /* Single-channel only */ pri_found = 1; ext_found = 0; } /* * If doing extended channel data, pulse_bw_info must * have one of the flags set. */ if (doDfsExtCh && pulse_bw_info == 0x0) return AH_FALSE; /* * If the extended channel data is available, calculate * which to pay attention to. */ if (doDfsExtCh) { /* If pulse is on DC, take the larger duration of the two */ if ((pulse_bw_info & EXT_CH_RADAR_FOUND) && (pulse_bw_info & PRI_CH_RADAR_FOUND)) { is_dc = 1; if (pulse_length_ext > pulse_length_pri) { dur = pulse_length_ext; pri_found = 0; ext_found = 1; } else { dur = pulse_length_pri; pri_found = 1; ext_found = 0; } } else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) { dur = pulse_length_ext; pri_found = 0; ext_found = 1; early_ext = 1; } else if (pulse_bw_info & PRI_CH_RADAR_FOUND) { dur = pulse_length_pri; pri_found = 1; ext_found = 0; } else if (pulse_bw_info & EXT_CH_RADAR_FOUND) { dur = pulse_length_ext; pri_found = 0; ext_found = 1; } } /* * For enhanced DFS (Merlin and later), pulse_bw_info has * implications for selecting the correct RSSI value. */ if (doDfsEnhanced) { switch (pulse_bw_info & 0x03) { case 0: /* No radar? */ rssi = 0; break; case PRI_CH_RADAR_FOUND: /* Radar in primary channel */ /* Cannot use ctrl channel RSSI if ext channel is stronger */ if (ext_rssi >= (rssi + 3)) { rssi = 0; } break; case EXT_CH_RADAR_FOUND: /* Radar in extended channel */ /* Cannot use ext channel RSSI if ctrl channel is stronger */ if (rssi >= (ext_rssi + 12)) { rssi = 0; } else { rssi = ext_rssi; } break; case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): /* When both are present, use stronger one */ if (rssi < ext_rssi) rssi = ext_rssi; break; } } /* * If not doing enhanced DFS, choose the ext channel if * it is stronger than the main channel */ if (doDfsExtCh && !doDfsEnhanced) { if ((ext_rssi > rssi) && (ext_rssi < 128)) rssi = ext_rssi; } /* * XXX what happens if the above code decides the RSSI * XXX wasn't valid, an sets it to 0? */ /* * Fill out dfs_event structure. */ event->re_full_ts = fulltsf; event->re_ts = rxs->rs_tstamp; event->re_rssi = rssi; event->re_dur = dur; event->re_flags = 0; if (pri_found) event->re_flags |= HAL_DFS_EVENT_PRICH; if (ext_found) event->re_flags |= HAL_DFS_EVENT_EXTCH; if (early_ext) event->re_flags |= HAL_DFS_EVENT_EXTEARLY; if (is_dc) event->re_flags |= HAL_DFS_EVENT_ISDC; 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; 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->ah_getNav = ar9300_get_nav; + ah->ah_setNav = ar9300_set_nav; /* 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; } HAL_BOOL ar9300_reset_freebsd(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_BOOL bChannelChange, HAL_RESET_TYPE resetType, HAL_STATUS *status) { HAL_BOOL r; HAL_HT_MACMODE macmode; struct ath_hal_private *ap = AH_PRIVATE(ah); macmode = IEEE80211_IS_CHAN_HT40(chan) ? HAL_HT_MACMODE_2040 : HAL_HT_MACMODE_20; r = ar9300_reset(ah, opmode, chan, macmode, ap->ah_caps.halTxChainMask, ap->ah_caps.halRxChainMask, HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */ bChannelChange, status, resetType, AH_FALSE); /* XXX should really extend ath_hal_reset() */ return (r); } void ar9300_config_pcie_freebsd(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL powerOff) { ar9300_config_pci_power_save(ah, restore ? 1 : 0, powerOff ? 1 : 0); } /* * This is a copy from ar9300_eeprom_get(), purely because the FreeBSD * API is very silly and inconsistent. * * The AR93xx HAL doesn't call the eepromGetFlag() function, so this * only occurs for FreeBSD code. * * When I fix this particular API, I'll undo this. */ HAL_STATUS ar9300_eeprom_get_freebsd(struct ath_hal *ah, int param, void *val) { switch (param) { case AR_EEP_FSTCLK_5G: return HAL_OK; default: ath_hal_printf(ah, "%s: called, param=%d\n", __func__, param); return HAL_EIO; } } HAL_BOOL ar9300_stop_tx_dma_freebsd(struct ath_hal *ah, u_int q) { return ar9300_stop_tx_dma(ah, q, 1000); } void ar9300_ani_poll_freebsd(struct ath_hal *ah, const struct ieee80211_channel *chan) { HAL_NODE_STATS stats; HAL_ANISTATS anistats; HAL_SURVEY_SAMPLE survey; OS_MEMZERO(&stats, sizeof(stats)); OS_MEMZERO(&anistats, sizeof(anistats)); OS_MEMZERO(&survey, sizeof(survey)); ar9300_ani_ar_poll(ah, &stats, chan, &anistats); /* * If ANI stats are valid, use them to update the * channel survey. */ if (anistats.valid) { survey.cycle_count = anistats.cyclecnt_diff; survey.chan_busy = anistats.rxclr_cnt; survey.ext_chan_busy = anistats.extrxclr_cnt; survey.tx_busy = anistats.txframecnt_diff; survey.rx_busy = anistats.rxframecnt_diff; ath_hal_survey_add_sample(ah, &survey); } } /* * Setup the configuration parameters in the style the AR9300 HAL * wants. */ void ar9300_config_defaults_freebsd(struct ath_hal *ah, HAL_OPS_CONFIG *ah_config) { /* Until FreeBSD's HAL does this by default - just copy */ OS_MEMCPY(&ah->ah_config, ah_config, sizeof(HAL_OPS_CONFIG)); ah->ah_config.ath_hal_enable_ani = AH_TRUE; } HAL_BOOL ar9300_stop_dma_receive_freebsd(struct ath_hal *ah) { return ar9300_stop_dma_receive(ah, 1000); } HAL_BOOL ar9300_get_pending_interrupts_freebsd(struct ath_hal *ah, HAL_INT *masked) { /* Non-MSI, so no MSI vector; and 'nortc' = 0 */ return ar9300_get_pending_interrupts(ah, masked, HAL_INT_LINE, 0, 0); } HAL_INT ar9300_set_interrupts_freebsd(struct ath_hal *ah, HAL_INT ints) { /* nortc = 0 */ return ar9300_set_interrupts(ah, ints, 0); } HAL_BOOL ar9300_per_calibration_freebsd(struct ath_hal *ah, struct ieee80211_channel *chan, u_int rxchainmask, HAL_BOOL long_cal, HAL_BOOL *isCalDone) { /* XXX fake scheduled calibrations for now */ u_int32_t sched_cals = 0xfffffff; return ar9300_calibration(ah, chan, AH_PRIVATE(ah)->ah_caps.halRxChainMask, long_cal, isCalDone, 0, /* is_scan */ &sched_cals); } HAL_BOOL ar9300_reset_cal_valid_freebsd(struct ath_hal *ah, const struct ieee80211_channel *chan) { HAL_BOOL is_cal_done = AH_TRUE; ar9300_reset_cal_valid(ah, chan, &is_cal_done, 0xffffffff); return (is_cal_done); } /* * FreeBSD will just pass in the descriptor value as 'pa'. * The Atheros HAL treats 'pa' as the physical address of the RX * descriptor and 'bufaddr' as the physical address of the RX buffer. * I'm not sure why they didn't collapse them - the AR9300 RX descriptor * routine doesn't check 'pa'. */ HAL_STATUS ar9300_proc_rx_desc_freebsd(struct ath_hal *ah, struct ath_desc *ds, uint32_t pa, struct ath_desc *ds_next, uint64_t tsf, struct ath_rx_status *rxs) { return (ar9300_proc_rx_desc_fast(ah, ds, 0, ds_next, rxs, (void *) ds)); } /* * This is the primary way the ANI code gets the node statistics per packet. */ void ar9300_ani_rxmonitor_freebsd(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi; } void ar9300_freebsd_get_desc_link(struct ath_hal *ah, void *ds, uint32_t *link) { struct ar9300_txc *ads = AR9300TXC(ds); (*link) = ads->ds_link; } /* * TX descriptor field setting wrappers - eek. */ HAL_BOOL ar9300_freebsd_setup_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsCtsDuration, u_int compicvLen, u_int compivLen, u_int comp) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_KEY_TYPE keyType = 0; /* XXX No padding */ if (keyIx != HAL_TXKEYIX_INVALID) keyType = ahp->ah_keytype[keyIx]; /* XXX bounds check keyix */ ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx, keyType, flags); return AH_TRUE; } HAL_BOOL ar9300_freebsd_setup_x_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int txRate1, u_int txTries1, u_int txRate2, u_int txTries2, u_int txRate3, u_int txTries3) { #if 0 ath_hal_printf(ah, "%s: called, 0x%x/%d, 0x%x/%d, 0x%x/%d\n", __func__, txRate1, txTries1, txRate2, txTries2, txRate3, txTries3); #endif /* XXX should only be called during probe */ return (AH_TRUE); } HAL_BOOL ar9300_freebsd_fill_tx_desc(struct ath_hal *ah, struct ath_desc *ds, HAL_DMA_ADDR *bufListPtr, uint32_t *segLenPtr, u_int descId, u_int qid, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0) { HAL_KEY_TYPE keyType = 0; const struct ar9300_txc *ads = AR9300TXC_CONST(ds0); /* * FreeBSD's HAL doesn't pass the keytype to fill_tx_desc(); * it's copied as part of the descriptor chaining. * * So, extract it from ds0. */ keyType = MS(ads->ds_ctl17, AR_encr_type); return ar9300_fill_tx_desc(ah, ds, bufListPtr, segLenPtr, descId, qid, keyType, firstSeg, lastSeg, ds0); } HAL_BOOL ar9300_freebsd_get_tx_completion_rates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; /* XXX for now */ } /* * 802.11n TX descriptor wrappers */ void ar9300_freebsd_set_11n_rate_scenario(struct ath_hal *ah, struct ath_desc *ds, u_int durUpdateEn, u_int rtsctsRate, HAL_11N_RATE_SERIES series[], u_int nseries, u_int flags) { /* lastds=NULL, rtscts_duration is 0, smart antenna is 0 */ ar9300_set_11n_rate_scenario(ah, (void *) ds, (void *)ds, durUpdateEn, rtsctsRate, 0, series, nseries, flags, 0); } /* chaintxdesc */ HAL_BOOL ar9300_freebsd_chain_tx_desc(struct ath_hal *ah, struct ath_desc *ds, HAL_DMA_ADDR *bufLenList, uint32_t *segLenList, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx, HAL_CIPHER cipher, uint8_t numDelims, HAL_BOOL firstSeg, HAL_BOOL lastSeg, HAL_BOOL lastAggr) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } /* setupfirsttxdesc */ HAL_BOOL ar9300_freebsd_setup_first_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen, u_int flags, u_int txPower, u_int txRate0, u_int txTries0, u_int antMode, u_int rtsctsRate, u_int rtsctsDuration) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } /* setuplasttxdesc */ /* * This gets called but for now let's not log anything; * it's only used to update the rate control information. */ HAL_BOOL ar9300_freebsd_setup_last_tx_desc(struct ath_hal *ah, struct ath_desc *ds, const struct ath_desc *ds0) { // ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } void ar9300_freebsd_setup_11n_desc(struct ath_hal *ah, void *ds, u_int pktLen, HAL_PKT_TYPE type, u_int txPower, u_int keyIx, u_int flags) { ath_hal_printf(ah, "%s: called\n", __func__); #if 0 struct ath_hal_9300 *ahp = AH9300(ah); HAL_KEY_TYPE keyType = 0; /* XXX No padding */ if (keyIx != HAL_TXKEYIX_INVALID) keyType = ahp->ah_keytype[keyIx]; /* XXX bounds check keyix */ ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx, keyType, flags); #endif } HAL_STATUS ar9300_freebsd_proc_tx_desc(struct ath_hal *ah, struct ath_desc *ds, struct ath_tx_status *ts) { return ar9300_proc_tx_desc(ah, ts); } void ar9300_freebsd_beacon_init(struct ath_hal *ah, uint32_t next_beacon, uint32_t beacon_period) { ar9300_beacon_init(ah, next_beacon, beacon_period, 0, AH_PRIVATE(ah)->ah_opmode); } HAL_BOOL ar9300_freebsd_get_mib_cycle_counts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) { return (AH_FALSE); } /* * Clear multicast filter by index - from FreeBSD ar5212_recv.c */ static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) { uint32_t val; if (ix >= 64) return (AH_FALSE); if (ix >= 32) { val = OS_REG_READ(ah, AR_MCAST_FIL1); OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); } else { val = OS_REG_READ(ah, AR_MCAST_FIL0); OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) return (AH_FALSE); if (ix >= 32) { val = OS_REG_READ(ah, AR_MCAST_FIL1); OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); } else { val = OS_REG_READ(ah, AR_MCAST_FIL0); OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<bt_nexttbtt)); OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba)); OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba)); OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER, TU_TO_USEC(bt->bt_nextatim)); bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD); AH9300(ah)->ah_beaconInterval = bt->bt_intval & HAL_BEACON_PERIOD; OS_REG_WRITE(ah, AR_BEACON_PERIOD, bperiod); OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bperiod); OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod); OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod); /* * Reset TSF if required. */ if (bt->bt_intval & HAL_BEACON_RESET_TSF) ar9300_reset_tsf(ah); /* enable timers */ /* NB: flags == 0 handled specially for backwards compatibility */ OS_REG_SET_BIT(ah, AR_TIMER_MODE, bt->bt_flags != 0 ? bt->bt_flags : AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN); } /* * RF attach stubs */ static HAL_BOOL rf9330_attach(struct ath_hal *ah, HAL_STATUS *status) { (*status) = HAL_EINVAL; return (AH_FALSE); } static HAL_BOOL rf9330_probe(struct ath_hal *ah) { return (AH_FALSE); } AH_RF(RF9330, rf9330_probe, rf9330_attach); diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index e39ff2b7d03d..4e811a5237ac 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -1,1712 +1,1714 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #ifndef _ATH_AH_H_ #define _ATH_AH_H_ /* * Atheros Hardware Access Layer * * Clients of the HAL call ath_hal_attach to obtain a reference to an ath_hal * structure for use with the device. Hardware-related operations that * follow must call back into the HAL through interface, supplying the * reference as the first parameter. */ #include "ah_osdep.h" /* * Endianness macros; used by various structures and code. */ #define AH_BIG_ENDIAN 4321 #define AH_LITTLE_ENDIAN 1234 #if _BYTE_ORDER == _BIG_ENDIAN #define AH_BYTE_ORDER AH_BIG_ENDIAN #else #define AH_BYTE_ORDER AH_LITTLE_ENDIAN #endif /* * The maximum number of TX/RX chains supported. * This is intended to be used by various statistics gathering operations * (NF, RSSI, EVM). */ #define AH_MAX_CHAINS 3 #define AH_MIMO_MAX_EVM_PILOTS 6 /* * __ahdecl is analogous to _cdecl; it defines the calling * convention used within the HAL. For most systems this * can just default to be empty and the compiler will (should) * use _cdecl. For systems where _cdecl is not compatible this * must be defined. See linux/ah_osdep.h for an example. */ #ifndef __ahdecl #define __ahdecl #endif /* * Status codes that may be returned by the HAL. Note that * interfaces that return a status code set it only when an * error occurs--i.e. you cannot check it for success. */ typedef enum { HAL_OK = 0, /* No error */ HAL_ENXIO = 1, /* No hardware present */ HAL_ENOMEM = 2, /* Memory allocation failed */ HAL_EIO = 3, /* Hardware didn't respond as expected */ HAL_EEMAGIC = 4, /* EEPROM magic number invalid */ HAL_EEVERSION = 5, /* EEPROM version invalid */ HAL_EELOCKED = 6, /* EEPROM unreadable */ HAL_EEBADSUM = 7, /* EEPROM checksum invalid */ HAL_EEREAD = 8, /* EEPROM read problem */ HAL_EEBADMAC = 9, /* EEPROM mac address invalid */ HAL_EESIZE = 10, /* EEPROM size not supported */ HAL_EEWRITE = 11, /* Attempt to change write-locked EEPROM */ HAL_EINVAL = 12, /* Invalid parameter to function */ HAL_ENOTSUPP = 13, /* Hardware revision not supported */ HAL_ESELFTEST = 14, /* Hardware self-test failed */ HAL_EINPROGRESS = 15, /* Operation incomplete */ HAL_EEBADREG = 16, /* EEPROM invalid regulatory contents */ HAL_EEBADCC = 17, /* EEPROM invalid country code */ HAL_INV_PMODE = 18, /* Couldn't bring out of sleep state */ } HAL_STATUS; typedef enum { AH_FALSE = 0, /* NB: lots of code assumes false is zero */ AH_TRUE = 1, } HAL_BOOL; typedef enum { HAL_CAP_REG_DMN = 0, /* current regulatory domain */ HAL_CAP_CIPHER = 1, /* hardware supports cipher */ HAL_CAP_TKIP_MIC = 2, /* handle TKIP MIC in hardware */ HAL_CAP_TKIP_SPLIT = 3, /* hardware TKIP uses split keys */ HAL_CAP_PHYCOUNTERS = 4, /* hardware PHY error counters */ HAL_CAP_DIVERSITY = 5, /* hardware supports fast diversity */ HAL_CAP_KEYCACHE_SIZE = 6, /* number of entries in key cache */ HAL_CAP_NUM_TXQUEUES = 7, /* number of hardware xmit queues */ HAL_CAP_VEOL = 9, /* hardware supports virtual EOL */ HAL_CAP_PSPOLL = 10, /* hardware has working PS-Poll support */ HAL_CAP_DIAG = 11, /* hardware diagnostic support */ HAL_CAP_COMPRESSION = 12, /* hardware supports compression */ HAL_CAP_BURST = 13, /* hardware supports packet bursting */ HAL_CAP_FASTFRAME = 14, /* hardware supoprts fast frames */ HAL_CAP_TXPOW = 15, /* global tx power limit */ HAL_CAP_TPC = 16, /* per-packet tx power control */ HAL_CAP_PHYDIAG = 17, /* hardware phy error diagnostic */ HAL_CAP_BSSIDMASK = 18, /* hardware supports bssid mask */ HAL_CAP_MCAST_KEYSRCH = 19, /* hardware has multicast key search */ HAL_CAP_TSF_ADJUST = 20, /* hardware has beacon tsf adjust */ /* 21 was HAL_CAP_XR */ HAL_CAP_WME_TKIPMIC = 22, /* hardware can support TKIP MIC when WMM is turned on */ /* 23 was HAL_CAP_CHAN_HALFRATE */ /* 24 was HAL_CAP_CHAN_QUARTERRATE */ HAL_CAP_RFSILENT = 25, /* hardware has rfsilent support */ HAL_CAP_TPC_ACK = 26, /* ack txpower with per-packet tpc */ HAL_CAP_TPC_CTS = 27, /* cts txpower with per-packet tpc */ HAL_CAP_11D = 28, /* 11d beacon support for changing cc */ HAL_CAP_PCIE_PS = 29, HAL_CAP_HT = 30, /* hardware can support HT */ HAL_CAP_GTXTO = 31, /* hardware supports global tx timeout */ HAL_CAP_FAST_CC = 32, /* hardware supports fast channel change */ HAL_CAP_TX_CHAINMASK = 33, /* mask of TX chains supported */ HAL_CAP_RX_CHAINMASK = 34, /* mask of RX chains supported */ HAL_CAP_NUM_GPIO_PINS = 36, /* number of GPIO pins */ HAL_CAP_CST = 38, /* hardware supports carrier sense timeout */ HAL_CAP_RIFS_RX = 39, HAL_CAP_RIFS_TX = 40, HAL_CAP_FORCE_PPM = 41, HAL_CAP_RTS_AGGR_LIMIT = 42, /* aggregation limit with RTS */ HAL_CAP_4ADDR_AGGR = 43, /* hardware is capable of 4addr aggregation */ HAL_CAP_DFS_DMN = 44, /* current DFS domain */ HAL_CAP_EXT_CHAN_DFS = 45, /* DFS support for extension channel */ HAL_CAP_COMBINED_RADAR_RSSI = 46, /* Is combined RSSI for radar accurate */ HAL_CAP_AUTO_SLEEP = 48, /* hardware can go to network sleep automatically after waking up to receive TIM */ HAL_CAP_MBSSID_AGGR_SUPPORT = 49, /* Support for mBSSID Aggregation */ HAL_CAP_SPLIT_4KB_TRANS = 50, /* hardware supports descriptors straddling a 4k page boundary */ HAL_CAP_REG_FLAG = 51, /* Regulatory domain flags */ HAL_CAP_BB_RIFS_HANG = 52, HAL_CAP_RIFS_RX_ENABLED = 53, HAL_CAP_BB_DFS_HANG = 54, HAL_CAP_RX_STBC = 58, HAL_CAP_TX_STBC = 59, HAL_CAP_BT_COEX = 60, /* hardware is capable of bluetooth coexistence */ HAL_CAP_DYNAMIC_SMPS = 61, /* Dynamic MIMO Power Save hardware support */ HAL_CAP_DS = 67, /* 2 stream */ HAL_CAP_BB_RX_CLEAR_STUCK_HANG = 68, HAL_CAP_MAC_HANG = 69, /* can MAC hang */ HAL_CAP_MFP = 70, /* Management Frame Protection in hardware */ HAL_CAP_TS = 72, /* 3 stream */ HAL_CAP_ENHANCED_DMA_SUPPORT = 75, /* DMA FIFO support */ HAL_CAP_NUM_TXMAPS = 76, /* Number of buffers in a transmit descriptor */ HAL_CAP_TXDESCLEN = 77, /* Length of transmit descriptor */ HAL_CAP_TXSTATUSLEN = 78, /* Length of transmit status descriptor */ HAL_CAP_RXSTATUSLEN = 79, /* Length of transmit status descriptor */ HAL_CAP_RXFIFODEPTH = 80, /* Receive hardware FIFO depth */ HAL_CAP_RXBUFSIZE = 81, /* Receive Buffer Length */ HAL_CAP_NUM_MR_RETRIES = 82, /* limit on multirate retries */ HAL_CAP_OL_PWRCTRL = 84, /* Open loop TX power control */ HAL_CAP_SPECTRAL_SCAN = 90, /* Hardware supports spectral scan */ HAL_CAP_BB_PANIC_WATCHDOG = 92, HAL_CAP_HT20_SGI = 96, /* hardware supports HT20 short GI */ HAL_CAP_LDPC = 99, HAL_CAP_RXTSTAMP_PREC = 100, /* rx desc tstamp precision (bits) */ HAL_CAP_ANT_DIV_COMB = 105, /* Enable antenna diversity/combining */ HAL_CAP_PHYRESTART_CLR_WAR = 106, /* in some cases, clear phy restart to fix bb hang */ HAL_CAP_ENTERPRISE_MODE = 107, /* Enterprise mode features */ HAL_CAP_LDPCWAR = 108, HAL_CAP_CHANNEL_SWITCH_TIME_USEC = 109, /* Channel change time, usec */ HAL_CAP_ENABLE_APM = 110, /* APM enabled */ HAL_CAP_PCIE_LCR_EXTSYNC_EN = 111, HAL_CAP_PCIE_LCR_OFFSET = 112, HAL_CAP_ENHANCED_DFS_SUPPORT = 117, /* hardware supports enhanced DFS */ HAL_CAP_MCI = 118, HAL_CAP_SMARTANTENNA = 119, HAL_CAP_TRAFFIC_FAST_RECOVER = 120, HAL_CAP_TX_DIVERSITY = 121, HAL_CAP_CRDC = 122, /* The following are private to the FreeBSD HAL (224 onward) */ HAL_CAP_INTMIT = 229, /* interference mitigation */ HAL_CAP_RXORN_FATAL = 230, /* HAL_INT_RXORN treated as fatal */ HAL_CAP_BB_HANG = 235, /* can baseband hang */ HAL_CAP_INTRMASK = 237, /* bitmask of supported interrupts */ HAL_CAP_BSSIDMATCH = 238, /* hardware has disable bssid match */ HAL_CAP_STREAMS = 239, /* how many 802.11n spatial streams are available */ HAL_CAP_RXDESC_SELFLINK = 242, /* support a self-linked tail RX descriptor */ HAL_CAP_BB_READ_WAR = 244, /* baseband read WAR */ HAL_CAP_SERIALISE_WAR = 245, /* serialise register access on PCI */ HAL_CAP_ENFORCE_TXOP = 246, /* Enforce TXOP if supported */ HAL_CAP_RX_LNA_MIXING = 247, /* RX hardware uses LNA mixing */ HAL_CAP_DO_MYBEACON = 248, /* Supports HAL_RX_FILTER_MYBEACON */ HAL_CAP_TOA_LOCATIONING = 249, /* time of flight / arrival locationing */ HAL_CAP_TXTSTAMP_PREC = 250, /* tx desc tstamp precision (bits) */ } HAL_CAPABILITY_TYPE; /* * "States" for setting the LED. These correspond to * the possible 802.11 operational states and there may * be a many-to-one mapping between these states and the * actual hardware state for the LED's (i.e. the hardware * may have fewer states). */ typedef enum { HAL_LED_INIT = 0, HAL_LED_SCAN = 1, HAL_LED_AUTH = 2, HAL_LED_ASSOC = 3, HAL_LED_RUN = 4 } HAL_LED_STATE; /* * Transmit queue types/numbers. These are used to tag * each transmit queue in the hardware and to identify a set * of transmit queues for operations such as start/stop dma. */ typedef enum { HAL_TX_QUEUE_INACTIVE = 0, /* queue is inactive/unused */ HAL_TX_QUEUE_DATA = 1, /* data xmit q's */ HAL_TX_QUEUE_BEACON = 2, /* beacon xmit q */ HAL_TX_QUEUE_CAB = 3, /* "crap after beacon" xmit q */ HAL_TX_QUEUE_UAPSD = 4, /* u-apsd power save xmit q */ HAL_TX_QUEUE_PSPOLL = 5, /* power save poll xmit q */ HAL_TX_QUEUE_CFEND = 6, HAL_TX_QUEUE_PAPRD = 7, } HAL_TX_QUEUE; #define HAL_NUM_TX_QUEUES 10 /* max possible # of queues */ /* * Receive queue types. These are used to tag * each transmit queue in the hardware and to identify a set * of transmit queues for operations such as start/stop dma. */ typedef enum { HAL_RX_QUEUE_HP = 0, /* high priority recv queue */ HAL_RX_QUEUE_LP = 1, /* low priority recv queue */ } HAL_RX_QUEUE; #define HAL_NUM_RX_QUEUES 2 /* max possible # of queues */ #define HAL_TXFIFO_DEPTH 8 /* transmit fifo depth */ /* * Transmit queue subtype. These map directly to * WME Access Categories (except for UPSD). Refer * to Table 5 of the WME spec. */ typedef enum { HAL_WME_AC_BK = 0, /* background access category */ HAL_WME_AC_BE = 1, /* best effort access category*/ HAL_WME_AC_VI = 2, /* video access category */ HAL_WME_AC_VO = 3, /* voice access category */ HAL_WME_UPSD = 4, /* uplink power save */ } HAL_TX_QUEUE_SUBTYPE; /* * Transmit queue flags that control various * operational parameters. */ typedef enum { /* * Per queue interrupt enables. When set the associated * interrupt may be delivered for packets sent through * the queue. Without these enabled no interrupts will * be delivered for transmits through the queue. */ HAL_TXQ_TXOKINT_ENABLE = 0x0001, /* enable TXOK interrupt */ HAL_TXQ_TXERRINT_ENABLE = 0x0001, /* enable TXERR interrupt */ HAL_TXQ_TXDESCINT_ENABLE = 0x0002, /* enable TXDESC interrupt */ HAL_TXQ_TXEOLINT_ENABLE = 0x0004, /* enable TXEOL interrupt */ HAL_TXQ_TXURNINT_ENABLE = 0x0008, /* enable TXURN interrupt */ /* * Enable hardware compression for packets sent through * the queue. The compression buffer must be setup and * packets must have a key entry marked in the tx descriptor. */ HAL_TXQ_COMPRESSION_ENABLE = 0x0010, /* enable h/w compression */ /* * Disable queue when veol is hit or ready time expires. * By default the queue is disabled only on reaching the * physical end of queue (i.e. a null link ptr in the * descriptor chain). */ HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE = 0x0020, /* * Schedule frames on delivery of a DBA (DMA Beacon Alert) * event. Frames will be transmitted only when this timer * fires, e.g to transmit a beacon in ap or adhoc modes. */ HAL_TXQ_DBA_GATED = 0x0040, /* schedule based on DBA */ /* * Each transmit queue has a counter that is incremented * each time the queue is enabled and decremented when * the list of frames to transmit is traversed (or when * the ready time for the queue expires). This counter * must be non-zero for frames to be scheduled for * transmission. The following controls disable bumping * this counter under certain conditions. Typically this * is used to gate frames based on the contents of another * queue (e.g. CAB traffic may only follow a beacon frame). * These are meaningful only when frames are scheduled * with a non-ASAP policy (e.g. DBA-gated). */ HAL_TXQ_CBR_DIS_QEMPTY = 0x0080, /* disable on this q empty */ HAL_TXQ_CBR_DIS_BEMPTY = 0x0100, /* disable on beacon q empty */ /* * Fragment burst backoff policy. Normally the no backoff * is done after a successful transmission, the next fragment * is sent at SIFS. If this flag is set backoff is done * after each fragment, regardless whether it was ack'd or * not, after the backoff count reaches zero a normal channel * access procedure is done before the next transmit (i.e. * wait AIFS instead of SIFS). */ HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE = 0x00800000, /* * Disable post-tx backoff following each frame. */ HAL_TXQ_BACKOFF_DISABLE = 0x00010000, /* disable post backoff */ /* * DCU arbiter lockout control. This controls how * lower priority tx queues are handled with respect to * to a specific queue when multiple queues have frames * to send. No lockout means lower priority queues arbitrate * concurrently with this queue. Intra-frame lockout * means lower priority queues are locked out until the * current frame transmits (e.g. including backoffs and bursting). * Global lockout means nothing lower can arbitrary so * long as there is traffic activity on this queue (frames, * backoff, etc). */ HAL_TXQ_ARB_LOCKOUT_INTRA = 0x00020000, /* intra-frame lockout */ HAL_TXQ_ARB_LOCKOUT_GLOBAL = 0x00040000, /* full lockout s */ HAL_TXQ_IGNORE_VIRTCOL = 0x00080000, /* ignore virt collisions */ HAL_TXQ_SEQNUM_INC_DIS = 0x00100000, /* disable seqnum increment */ } HAL_TX_QUEUE_FLAGS; typedef struct { uint32_t tqi_ver; /* hal TXQ version */ HAL_TX_QUEUE_SUBTYPE tqi_subtype; /* subtype if applicable */ HAL_TX_QUEUE_FLAGS tqi_qflags; /* flags (see above) */ uint32_t tqi_priority; /* (not used) */ uint32_t tqi_aifs; /* aifs */ uint32_t tqi_cwmin; /* cwMin */ uint32_t tqi_cwmax; /* cwMax */ uint16_t tqi_shretry; /* rts retry limit */ uint16_t tqi_lgretry; /* long retry limit (not used)*/ uint32_t tqi_cbrPeriod; /* CBR period (us) */ uint32_t tqi_cbrOverflowLimit; /* threshold for CBROVF int */ uint32_t tqi_burstTime; /* max burst duration (us) */ uint32_t tqi_readyTime; /* frame schedule time (us) */ uint32_t tqi_compBuf; /* comp buffer phys addr */ } HAL_TXQ_INFO; #define HAL_TQI_NONVAL 0xffff /* token to use for aifs, cwmin, cwmax */ #define HAL_TXQ_USEDEFAULT ((uint32_t) -1) /* compression definitions */ #define HAL_COMP_BUF_MAX_SIZE 9216 /* 9K */ #define HAL_COMP_BUF_ALIGN_SIZE 512 /* * Transmit packet types. This belongs in ah_desc.h, but * is here so we can give a proper type to various parameters * (and not require everyone include the file). * * NB: These values are intentionally assigned for * direct use when setting up h/w descriptors. */ typedef enum { HAL_PKT_TYPE_NORMAL = 0, HAL_PKT_TYPE_ATIM = 1, HAL_PKT_TYPE_PSPOLL = 2, HAL_PKT_TYPE_BEACON = 3, HAL_PKT_TYPE_PROBE_RESP = 4, HAL_PKT_TYPE_CHIRP = 5, HAL_PKT_TYPE_GRP_POLL = 6, HAL_PKT_TYPE_AMPDU = 7, } HAL_PKT_TYPE; /* Rx Filter Frame Types */ typedef enum { /* * These bits correspond to AR_RX_FILTER for all chips. * Not all bits are supported by all chips. */ HAL_RX_FILTER_UCAST = 0x00000001, /* Allow unicast frames */ HAL_RX_FILTER_MCAST = 0x00000002, /* Allow multicast frames */ HAL_RX_FILTER_BCAST = 0x00000004, /* Allow broadcast frames */ HAL_RX_FILTER_CONTROL = 0x00000008, /* Allow control frames */ HAL_RX_FILTER_BEACON = 0x00000010, /* Allow beacon frames */ HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */ HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */ HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */ HAL_RX_FILTER_MYBEACON = 0x00000200, /* Filter beacons other than mine */ HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */ HAL_RX_FILTER_COMP_BA = 0x00000800, /* Allow compressed blockack */ HAL_RX_FILTER_PHYRADAR = 0x00002000, /* Allow phy radar errors */ HAL_RX_FILTER_PSPOLL = 0x00004000, /* Allow PS-POLL frames */ HAL_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, /* Allow all mcast/bcast frames */ /* * Magic RX filter flags that aren't targeting hardware bits * but instead the HAL sets individual bits - eg PHYERR will result * in OFDM/CCK timing error frames being received. */ HAL_RX_FILTER_BSSID = 0x40000000, /* Disable BSSID match */ } HAL_RX_FILTER; typedef enum { HAL_PM_AWAKE = 0, HAL_PM_FULL_SLEEP = 1, HAL_PM_NETWORK_SLEEP = 2, HAL_PM_UNDEFINED = 3 } HAL_POWER_MODE; /* * Enterprise mode flags */ #define AH_ENT_DUAL_BAND_DISABLE 0x00000001 #define AH_ENT_CHAIN2_DISABLE 0x00000002 #define AH_ENT_5MHZ_DISABLE 0x00000004 #define AH_ENT_10MHZ_DISABLE 0x00000008 #define AH_ENT_49GHZ_DISABLE 0x00000010 #define AH_ENT_LOOPBACK_DISABLE 0x00000020 #define AH_ENT_TPC_PERF_DISABLE 0x00000040 #define AH_ENT_MIN_PKT_SIZE_DISABLE 0x00000080 #define AH_ENT_SPECTRAL_PRECISION 0x00000300 #define AH_ENT_SPECTRAL_PRECISION_S 8 #define AH_ENT_RTSCTS_DELIM_WAR 0x00010000 #define AH_FIRST_DESC_NDELIMS 60 /* * NOTE WELL: * These are mapped to take advantage of the common locations for many of * the bits on all of the currently supported MAC chips. This is to make * the ISR as efficient as possible, while still abstracting HW differences. * When new hardware breaks this commonality this enumerated type, as well * as the HAL functions using it, must be modified. All values are directly * mapped unless commented otherwise. */ typedef enum { HAL_INT_RX = 0x00000001, /* Non-common mapping */ HAL_INT_RXDESC = 0x00000002, /* Legacy mapping */ HAL_INT_RXERR = 0x00000004, HAL_INT_RXHP = 0x00000001, /* EDMA */ HAL_INT_RXLP = 0x00000002, /* EDMA */ HAL_INT_RXNOFRM = 0x00000008, HAL_INT_RXEOL = 0x00000010, HAL_INT_RXORN = 0x00000020, HAL_INT_TX = 0x00000040, /* Non-common mapping */ HAL_INT_TXDESC = 0x00000080, HAL_INT_TIM_TIMER= 0x00000100, HAL_INT_MCI = 0x00000200, HAL_INT_BBPANIC = 0x00000400, HAL_INT_TXURN = 0x00000800, HAL_INT_MIB = 0x00001000, HAL_INT_RXPHY = 0x00004000, HAL_INT_RXKCM = 0x00008000, HAL_INT_SWBA = 0x00010000, HAL_INT_BRSSI = 0x00020000, HAL_INT_BMISS = 0x00040000, HAL_INT_BNR = 0x00100000, HAL_INT_TIM = 0x00200000, /* Non-common mapping */ HAL_INT_DTIM = 0x00400000, /* Non-common mapping */ HAL_INT_DTIMSYNC= 0x00800000, /* Non-common mapping */ HAL_INT_GPIO = 0x01000000, HAL_INT_CABEND = 0x02000000, /* Non-common mapping */ HAL_INT_TSFOOR = 0x04000000, /* Non-common mapping */ HAL_INT_TBTT = 0x08000000, /* Non-common mapping */ /* Atheros ref driver has a generic timer interrupt now..*/ HAL_INT_GENTIMER = 0x08000000, /* Non-common mapping */ HAL_INT_CST = 0x10000000, /* Non-common mapping */ HAL_INT_GTT = 0x20000000, /* Non-common mapping */ HAL_INT_FATAL = 0x40000000, /* Non-common mapping */ #define HAL_INT_GLOBAL 0x80000000 /* Set/clear IER */ HAL_INT_BMISC = HAL_INT_TIM | HAL_INT_DTIM | HAL_INT_DTIMSYNC | HAL_INT_CABEND | HAL_INT_TBTT, /* Interrupt bits that map directly to ISR/IMR bits */ HAL_INT_COMMON = HAL_INT_RXNOFRM | HAL_INT_RXDESC | HAL_INT_RXEOL | HAL_INT_RXORN | HAL_INT_TXDESC | HAL_INT_TXURN | HAL_INT_MIB | HAL_INT_RXPHY | HAL_INT_RXKCM | HAL_INT_SWBA | HAL_INT_BMISS | HAL_INT_BRSSI | HAL_INT_BNR | HAL_INT_GPIO, } HAL_INT; /* * MSI vector assignments */ typedef enum { HAL_MSIVEC_MISC = 0, HAL_MSIVEC_TX = 1, HAL_MSIVEC_RXLP = 2, HAL_MSIVEC_RXHP = 3, } HAL_MSIVEC; typedef enum { HAL_INT_LINE = 0, HAL_INT_MSI = 1, } HAL_INT_TYPE; /* For interrupt mitigation registers */ typedef enum { HAL_INT_RX_FIRSTPKT=0, HAL_INT_RX_LASTPKT, HAL_INT_TX_FIRSTPKT, HAL_INT_TX_LASTPKT, HAL_INT_THRESHOLD } HAL_INT_MITIGATION; /* XXX this is duplicate information! */ typedef struct { u_int32_t cyclecnt_diff; /* delta cycle count */ u_int32_t rxclr_cnt; /* rx clear count */ u_int32_t extrxclr_cnt; /* ext chan rx clear count */ u_int32_t txframecnt_diff; /* delta tx frame count */ u_int32_t rxframecnt_diff; /* delta rx frame count */ u_int32_t listen_time; /* listen time in msec - time for which ch is free */ u_int32_t ofdmphyerr_cnt; /* OFDM err count since last reset */ u_int32_t cckphyerr_cnt; /* CCK err count since last reset */ u_int32_t ofdmphyerrcnt_diff; /* delta OFDM Phy Error Count */ HAL_BOOL valid; /* if the stats are valid*/ } HAL_ANISTATS; typedef struct { u_int8_t txctl_offset; u_int8_t txctl_numwords; u_int8_t txstatus_offset; u_int8_t txstatus_numwords; u_int8_t rxctl_offset; u_int8_t rxctl_numwords; u_int8_t rxstatus_offset; u_int8_t rxstatus_numwords; u_int8_t macRevision; } HAL_DESC_INFO; typedef enum { HAL_GPIO_OUTPUT_MUX_AS_OUTPUT = 0, HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED = 1, HAL_GPIO_OUTPUT_MUX_PCIE_POWER_LED = 2, HAL_GPIO_OUTPUT_MUX_MAC_NETWORK_LED = 3, HAL_GPIO_OUTPUT_MUX_MAC_POWER_LED = 4, HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE = 5, HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME = 6, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX, HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE, HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA, HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0, HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1, HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2, HAL_GPIO_OUTPUT_MUX_NUM_ENTRIES } HAL_GPIO_MUX_TYPE; typedef enum { HAL_GPIO_INTR_LOW = 0, HAL_GPIO_INTR_HIGH = 1, HAL_GPIO_INTR_DISABLE = 2 } HAL_GPIO_INTR_TYPE; typedef struct halCounters { u_int32_t tx_frame_count; u_int32_t rx_frame_count; u_int32_t rx_clear_count; u_int32_t cycle_count; u_int8_t is_rx_active; // true (1) or false (0) u_int8_t is_tx_active; // true (1) or false (0) } HAL_COUNTERS; typedef enum { HAL_RFGAIN_INACTIVE = 0, HAL_RFGAIN_READ_REQUESTED = 1, HAL_RFGAIN_NEED_CHANGE = 2 } HAL_RFGAIN; typedef uint16_t HAL_CTRY_CODE; /* country code */ typedef uint16_t HAL_REG_DOMAIN; /* regulatory domain code */ #define HAL_ANTENNA_MIN_MODE 0 #define HAL_ANTENNA_FIXED_A 1 #define HAL_ANTENNA_FIXED_B 2 #define HAL_ANTENNA_MAX_MODE 3 typedef struct { uint32_t ackrcv_bad; uint32_t rts_bad; uint32_t rts_good; uint32_t fcs_bad; uint32_t beacons; } HAL_MIB_STATS; /* * These bits represent what's in ah_currentRDext. */ typedef enum { REG_EXT_FCC_MIDBAND = 0, REG_EXT_JAPAN_MIDBAND = 1, REG_EXT_FCC_DFS_HT40 = 2, REG_EXT_JAPAN_NONDFS_HT40 = 3, REG_EXT_JAPAN_DFS_HT40 = 4, REG_EXT_FCC_CH_144 = 5, } REG_EXT_BITMAP; enum { HAL_MODE_11A = 0x001, /* 11a channels */ HAL_MODE_TURBO = 0x002, /* 11a turbo-only channels */ HAL_MODE_11B = 0x004, /* 11b channels */ HAL_MODE_PUREG = 0x008, /* 11g channels (OFDM only) */ #ifdef notdef HAL_MODE_11G = 0x010, /* 11g channels (OFDM/CCK) */ #else HAL_MODE_11G = 0x008, /* XXX historical */ #endif HAL_MODE_108G = 0x020, /* 11g+Turbo channels */ HAL_MODE_108A = 0x040, /* 11a+Turbo channels */ HAL_MODE_11A_HALF_RATE = 0x200, /* 11a half width channels */ HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11a quarter width channels */ HAL_MODE_11G_HALF_RATE = 0x800, /* 11g half width channels */ HAL_MODE_11G_QUARTER_RATE = 0x1000, /* 11g quarter width channels */ HAL_MODE_11NG_HT20 = 0x008000, HAL_MODE_11NA_HT20 = 0x010000, HAL_MODE_11NG_HT40PLUS = 0x020000, HAL_MODE_11NG_HT40MINUS = 0x040000, HAL_MODE_11NA_HT40PLUS = 0x080000, HAL_MODE_11NA_HT40MINUS = 0x100000, HAL_MODE_ALL = 0xffffff }; typedef struct { int rateCount; /* NB: for proper padding */ uint8_t rateCodeToIndex[256]; /* back mapping */ struct { uint8_t valid; /* valid for rate control use */ uint8_t phy; /* CCK/OFDM/XR */ uint32_t rateKbps; /* transfer rate in kbs */ uint8_t rateCode; /* rate for h/w descriptors */ uint8_t shortPreamble; /* mask for enabling short * preamble in CCK rate code */ uint8_t dot11Rate; /* value for supported rates * info element of MLME */ uint8_t controlRate; /* index of next lower basic * rate; used for dur. calcs */ uint16_t lpAckDuration; /* long preamble ACK duration */ uint16_t spAckDuration; /* short preamble ACK duration*/ } info[64]; } HAL_RATE_TABLE; typedef struct { u_int rs_count; /* number of valid entries */ uint8_t rs_rates[64]; /* rates */ } HAL_RATE_SET; /* * 802.11n specific structures and enums */ typedef enum { HAL_CHAINTYPE_TX = 1, /* Tx chain type */ HAL_CHAINTYPE_RX = 2, /* RX chain type */ } HAL_CHAIN_TYPE; typedef struct { u_int Tries; u_int Rate; /* hardware rate code */ u_int RateIndex; /* rate series table index */ u_int PktDuration; u_int ChSel; u_int RateFlags; #define HAL_RATESERIES_RTS_CTS 0x0001 /* use rts/cts w/this series */ #define HAL_RATESERIES_2040 0x0002 /* use ext channel for series */ #define HAL_RATESERIES_HALFGI 0x0004 /* use half-gi for series */ #define HAL_RATESERIES_STBC 0x0008 /* use STBC for series */ u_int tx_power_cap; /* in 1/2 dBm units XXX TODO */ } HAL_11N_RATE_SERIES; typedef enum { HAL_HT_MACMODE_20 = 0, /* 20 MHz operation */ HAL_HT_MACMODE_2040 = 1, /* 20/40 MHz operation */ } HAL_HT_MACMODE; typedef enum { HAL_HT_PHYMODE_20 = 0, /* 20 MHz operation */ HAL_HT_PHYMODE_2040 = 1, /* 20/40 MHz operation */ } HAL_HT_PHYMODE; typedef enum { HAL_HT_EXTPROTSPACING_20 = 0, /* 20 MHz spacing */ HAL_HT_EXTPROTSPACING_25 = 1, /* 25 MHz spacing */ } HAL_HT_EXTPROTSPACING; typedef enum { HAL_RX_CLEAR_CTL_LOW = 0x1, /* force control channel to appear busy */ HAL_RX_CLEAR_EXT_LOW = 0x2, /* force extension channel to appear busy */ } HAL_HT_RXCLEAR; typedef enum { HAL_FREQ_BAND_5GHZ = 0, HAL_FREQ_BAND_2GHZ = 1, } HAL_FREQ_BAND; /* * Antenna switch control. By default antenna selection * enables multiple (2) antenna use. To force use of the * A or B antenna only specify a fixed setting. Fixing * the antenna will also disable any diversity support. */ typedef enum { HAL_ANT_VARIABLE = 0, /* variable by programming */ HAL_ANT_FIXED_A = 1, /* fixed antenna A */ HAL_ANT_FIXED_B = 2, /* fixed antenna B */ } HAL_ANT_SETTING; typedef enum { HAL_M_STA = 1, /* infrastructure station */ HAL_M_IBSS = 0, /* IBSS (adhoc) station */ HAL_M_HOSTAP = 6, /* Software Access Point */ HAL_M_MONITOR = 8 /* Monitor mode */ } HAL_OPMODE; typedef enum { HAL_RESET_NORMAL = 0, /* Do normal reset */ HAL_RESET_BBPANIC = 1, /* Reset because of BB panic */ HAL_RESET_FORCE_COLD = 2, /* Force full reset */ } HAL_RESET_TYPE; enum { HAL_RESET_POWER_ON, HAL_RESET_WARM, HAL_RESET_COLD }; typedef struct { uint8_t kv_type; /* one of HAL_CIPHER */ uint8_t kv_apsd; /* Mask for APSD enabled ACs */ uint16_t kv_len; /* length in bits */ uint8_t kv_val[16]; /* enough for 128-bit keys */ uint8_t kv_mic[8]; /* TKIP MIC key */ uint8_t kv_txmic[8]; /* TKIP TX MIC key (optional) */ } HAL_KEYVAL; /* * This is the TX descriptor field which marks the key padding requirement. * The naming is unfortunately unclear. */ #define AH_KEYTYPE_MASK 0x0F typedef enum { HAL_KEY_TYPE_CLEAR, HAL_KEY_TYPE_WEP, HAL_KEY_TYPE_AES, HAL_KEY_TYPE_TKIP, } HAL_KEY_TYPE; typedef enum { HAL_CIPHER_WEP = 0, HAL_CIPHER_AES_OCB = 1, HAL_CIPHER_AES_CCM = 2, HAL_CIPHER_CKIP = 3, HAL_CIPHER_TKIP = 4, HAL_CIPHER_CLR = 5, /* no encryption */ HAL_CIPHER_MIC = 127 /* TKIP-MIC, not a cipher */ } HAL_CIPHER; enum { HAL_SLOT_TIME_6 = 6, /* NB: for turbo mode */ HAL_SLOT_TIME_9 = 9, HAL_SLOT_TIME_20 = 20, }; /* * Per-station beacon timer state. Note that the specified * beacon interval (given in TU's) can also include flags * to force a TSF reset and to enable the beacon xmit logic. * If bs_cfpmaxduration is non-zero the hardware is setup to * coexist with a PCF-capable AP. */ typedef struct { uint32_t bs_nexttbtt; /* next beacon in TU */ uint32_t bs_nextdtim; /* next DTIM in TU */ uint32_t bs_intval; /* beacon interval+flags */ /* * HAL_BEACON_PERIOD, HAL_BEACON_ENA and HAL_BEACON_RESET_TSF * are all 1:1 correspondances with the pre-11n chip AR_BEACON * register. */ #define HAL_BEACON_PERIOD 0x0000ffff /* beacon interval period */ #define HAL_BEACON_PERIOD_TU8 0x0007ffff /* beacon interval, tu/8 */ #define HAL_BEACON_ENA 0x00800000 /* beacon xmit enable */ #define HAL_BEACON_RESET_TSF 0x01000000 /* clear TSF */ #define HAL_TSFOOR_THRESHOLD 0x00004240 /* TSF OOR thresh (16k uS) */ uint32_t bs_dtimperiod; uint16_t bs_cfpperiod; /* CFP period in TU */ uint16_t bs_cfpmaxduration; /* max CFP duration in TU */ uint32_t bs_cfpnext; /* next CFP in TU */ uint16_t bs_timoffset; /* byte offset to TIM bitmap */ uint16_t bs_bmissthreshold; /* beacon miss threshold */ uint32_t bs_sleepduration; /* max sleep duration */ uint32_t bs_tsfoor_threshold; /* TSF out of range threshold */ } HAL_BEACON_STATE; /* * Like HAL_BEACON_STATE but for non-station mode setup. * NB: see above flag definitions for bt_intval. */ typedef struct { uint32_t bt_intval; /* beacon interval+flags */ uint32_t bt_nexttbtt; /* next beacon in TU */ uint32_t bt_nextatim; /* next ATIM in TU */ uint32_t bt_nextdba; /* next DBA in 1/8th TU */ uint32_t bt_nextswba; /* next SWBA in 1/8th TU */ uint32_t bt_flags; /* timer enables */ #define HAL_BEACON_TBTT_EN 0x00000001 #define HAL_BEACON_DBA_EN 0x00000002 #define HAL_BEACON_SWBA_EN 0x00000004 } HAL_BEACON_TIMERS; /* * Per-node statistics maintained by the driver for use in * optimizing signal quality and other operational aspects. */ typedef struct { uint32_t ns_avgbrssi; /* average beacon rssi */ uint32_t ns_avgrssi; /* average data rssi */ uint32_t ns_avgtxrssi; /* average tx rssi */ } HAL_NODE_STATS; #define HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ /* * This is the ANI state and MIB stats. * * It's used by the HAL modules to keep state /and/ by the debug ioctl * to fetch ANI information. */ typedef struct { uint32_t ast_ani_niup; /* ANI increased noise immunity */ uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ uint32_t ast_ani_spurup; /* ANI increased spur immunity */ uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ uint32_t ast_ani_stepup; /* ANI increased first step level */ uint32_t ast_ani_stepdown;/* ANI decreased first step level */ uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ } HAL_ANI_STATS; typedef struct { uint8_t noiseImmunityLevel; /* Global for pre-AR9380; OFDM later*/ uint8_t cckNoiseImmunityLevel; /* AR9380: CCK specific NI */ uint8_t spurImmunityLevel; uint8_t firstepLevel; uint8_t ofdmWeakSigDetectOff; uint8_t cckWeakSigThreshold; uint8_t mrcCck; /* MRC CCK is enabled */ uint32_t listenTime; /* NB: intentionally ordered so data exported to user space is first */ uint32_t txFrameCount; /* Last txFrameCount */ uint32_t rxFrameCount; /* Last rx Frame count */ uint32_t cycleCount; /* Last cycleCount (to detect wrap-around) */ uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ uint32_t cckPhyErrCount; /* CCK err count since last reset */ } HAL_ANI_STATE; struct ath_desc; struct ath_tx_status; struct ath_rx_status; struct ieee80211_channel; /* * This is a channel survey sample entry. * * The AR5212 ANI routines fill these samples. The ANI code then uses it * when calculating listen time; it is also exported via a diagnostic * API. */ typedef struct { uint32_t seq_num; uint32_t tx_busy; uint32_t rx_busy; uint32_t chan_busy; uint32_t ext_chan_busy; uint32_t cycle_count; /* XXX TODO */ uint32_t ofdm_phyerr_count; uint32_t cck_phyerr_count; } HAL_SURVEY_SAMPLE; /* * This provides 3.2 seconds of sample space given an * ANI time of 1/10th of a second. This may not be enough! */ #define CHANNEL_SURVEY_SAMPLE_COUNT 32 typedef struct { HAL_SURVEY_SAMPLE samples[CHANNEL_SURVEY_SAMPLE_COUNT]; uint32_t cur_sample; /* current sample in sequence */ uint32_t cur_seq; /* current sequence number */ } HAL_CHANNEL_SURVEY; /* * ANI commands. * * These are used both internally and externally via the diagnostic * API. * * Note that this is NOT the ANI commands being used via the INTMIT * capability - that has a different mapping for some reason. */ typedef enum { HAL_ANI_PRESENT = 0, /* is ANI support present */ HAL_ANI_NOISE_IMMUNITY_LEVEL = 1, /* set level (global or ofdm) */ HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION = 2, /* enable/disable */ HAL_ANI_CCK_WEAK_SIGNAL_THR = 3, /* enable/disable */ HAL_ANI_FIRSTEP_LEVEL = 4, /* set level */ HAL_ANI_SPUR_IMMUNITY_LEVEL = 5, /* set level */ HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ HAL_ANI_PHYERR_RESET = 7, /* reset phy error stats */ HAL_ANI_MRC_CCK = 8, HAL_ANI_CCK_NOISE_IMMUNITY_LEVEL = 9, /* set level (cck) */ } HAL_ANI_CMD; #define HAL_ANI_ALL 0xffffffff /* * This is the layout of the ANI INTMIT capability. * * Notice that the command values differ to HAL_ANI_CMD. */ typedef enum { HAL_CAP_INTMIT_PRESENT = 0, HAL_CAP_INTMIT_ENABLE = 1, HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL = 2, HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL = 3, HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR = 4, HAL_CAP_INTMIT_FIRSTEP_LEVEL = 5, HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL = 6 } HAL_CAP_INTMIT_CMD; typedef struct { int32_t pe_firpwr; /* FIR pwr out threshold */ int32_t pe_rrssi; /* Radar rssi thresh */ int32_t pe_height; /* Pulse height thresh */ int32_t pe_prssi; /* Pulse rssi thresh */ int32_t pe_inband; /* Inband thresh */ /* The following params are only for AR5413 and later */ u_int32_t pe_relpwr; /* Relative power threshold in 0.5dB steps */ u_int32_t pe_relstep; /* Pulse Relative step threshold in 0.5dB steps */ u_int32_t pe_maxlen; /* Max length of radar sign in 0.8us units */ int32_t pe_usefir128; /* Use the average in-band power measured over 128 cycles */ int32_t pe_blockradar; /* * Enable to block radar check if pkt detect is done via OFDM * weak signal detect or pkt is detected immediately after tx * to rx transition */ int32_t pe_enmaxrssi; /* * Enable to use the max rssi instead of the last rssi during * fine gain changes for radar detection */ int32_t pe_extchannel; /* Enable DFS on ext channel */ int32_t pe_enabled; /* Whether radar detection is enabled */ int32_t pe_enrelpwr; int32_t pe_en_relstep_check; } HAL_PHYERR_PARAM; #define HAL_PHYERR_PARAM_NOVAL 65535 typedef struct { u_int16_t ss_fft_period; /* Skip interval for FFT reports */ u_int16_t ss_period; /* Spectral scan period */ u_int16_t ss_count; /* # of reports to return from ss_active */ u_int16_t ss_short_report;/* Set to report ony 1 set of FFT results */ u_int8_t radar_bin_thresh_sel; /* strong signal radar FFT threshold configuration */ u_int16_t ss_spectral_pri; /* are we doing a noise power cal ? */ int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */ int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */ int32_t ss_nf_temp_data; /* temperature data taken during nf scan */ int ss_enabled; int ss_active; } HAL_SPECTRAL_PARAM; #define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF #define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ /* * DFS operating mode flags. */ typedef enum { HAL_DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */ HAL_DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */ HAL_DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */ HAL_DFS_MKK4_DOMAIN = 3, /* Japan dfs domain */ } HAL_DFS_DOMAIN; /* * MFP decryption options for initializing the MAC. */ typedef enum { HAL_MFP_QOSDATA = 0, /* Decrypt MFP frames like QoS data frames. All chips before Merlin. */ HAL_MFP_PASSTHRU, /* Don't decrypt MFP frames at all. Passthrough */ HAL_MFP_HW_CRYPTO /* hardware decryption enabled. Merlin can do it. */ } HAL_MFP_OPT_T; /* LNA config supported */ typedef enum { HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2 = 0, HAL_ANT_DIV_COMB_LNA2 = 1, HAL_ANT_DIV_COMB_LNA1 = 2, HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2 = 3, } HAL_ANT_DIV_COMB_LNA_CONF; typedef struct { u_int8_t main_lna_conf; u_int8_t alt_lna_conf; u_int8_t fast_div_bias; u_int8_t main_gaintb; u_int8_t alt_gaintb; u_int8_t antdiv_configgroup; int8_t lna1_lna2_delta; } HAL_ANT_COMB_CONFIG; #define DEFAULT_ANTDIV_CONFIG_GROUP 0x00 #define HAL_ANTDIV_CONFIG_GROUP_1 0x01 #define HAL_ANTDIV_CONFIG_GROUP_2 0x02 #define HAL_ANTDIV_CONFIG_GROUP_3 0x03 /* * Flag for setting QUIET period */ typedef enum { HAL_QUIET_DISABLE = 0x0, HAL_QUIET_ENABLE = 0x1, HAL_QUIET_ADD_CURRENT_TSF = 0x2, /* add current TSF to next_start offset */ HAL_QUIET_ADD_SWBA_RESP_TIME = 0x4, /* add beacon response time to next_start offset */ } HAL_QUIET_FLAG; #define HAL_DFS_EVENT_PRICH 0x0000001 #define HAL_DFS_EVENT_EXTCH 0x0000002 #define HAL_DFS_EVENT_EXTEARLY 0x0000004 #define HAL_DFS_EVENT_ISDC 0x0000008 struct hal_dfs_event { uint64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ uint32_t re_ts; /* Original 15 bit recv timestamp */ uint8_t re_rssi; /* rssi of radar event */ uint8_t re_dur; /* duration of radar pulse */ uint32_t re_flags; /* Flags (see above) */ }; typedef struct hal_dfs_event HAL_DFS_EVENT; /* * Generic Timer domain */ typedef enum { HAL_GEN_TIMER_TSF = 0, HAL_GEN_TIMER_TSF2, HAL_GEN_TIMER_TSF_ANY } HAL_GEN_TIMER_DOMAIN; /* * BT Co-existence definitions */ #include "ath_hal/ah_btcoex.h" struct hal_bb_panic_info { u_int32_t status; u_int32_t tsf; u_int32_t phy_panic_wd_ctl1; u_int32_t phy_panic_wd_ctl2; u_int32_t phy_gen_ctrl; u_int32_t rxc_pcnt; u_int32_t rxf_pcnt; u_int32_t txf_pcnt; u_int32_t cycles; u_int32_t wd; u_int32_t det; u_int32_t rdar; u_int32_t r_odfm; u_int32_t r_cck; u_int32_t t_odfm; u_int32_t t_cck; u_int32_t agc; u_int32_t src; }; /* Serialize Register Access Mode */ typedef enum { SER_REG_MODE_OFF = 0, SER_REG_MODE_ON = 1, SER_REG_MODE_AUTO = 2, } SER_REG_MODE; typedef struct { int ah_debug; /* only used if AH_DEBUG is defined */ int ah_ar5416_biasadj; /* enable AR2133 radio specific bias fiddling */ /* NB: these are deprecated; they exist for now for compatibility */ int ah_dma_beacon_response_time;/* in TU's */ int ah_sw_beacon_response_time; /* in TU's */ int ah_additional_swba_backoff; /* in TU's */ int ah_force_full_reset; /* force full chip reset rather then warm reset */ int ah_serialise_reg_war; /* force serialisation of register IO */ /* XXX these don't belong here, they're just for the ar9300 HAL port effort */ int ath_hal_desc_tpc; /* Per-packet TPC */ int ath_hal_sta_update_tx_pwr_enable; /* GreenTX */ int ath_hal_sta_update_tx_pwr_enable_S1; /* GreenTX */ int ath_hal_sta_update_tx_pwr_enable_S2; /* GreenTX */ int ath_hal_sta_update_tx_pwr_enable_S3; /* GreenTX */ /* I'm not sure what the default values for these should be */ int ath_hal_pll_pwr_save; int ath_hal_pcie_power_save_enable; int ath_hal_intr_mitigation_rx; int ath_hal_intr_mitigation_tx; int ath_hal_pcie_clock_req; #define AR_PCIE_PLL_PWRSAVE_CONTROL (1<<0) #define AR_PCIE_PLL_PWRSAVE_ON_D3 (1<<1) #define AR_PCIE_PLL_PWRSAVE_ON_D0 (1<<2) int ath_hal_pcie_waen; int ath_hal_pcie_ser_des_write; /* these are important for correct AR9300 behaviour */ int ath_hal_ht_enable; /* needs to be enabled for AR9300 HT */ int ath_hal_diversity_control; int ath_hal_antenna_switch_swap; int ath_hal_ext_lna_ctl_gpio; int ath_hal_spur_mode; int ath_hal_6mb_ack; /* should set this to 1 for 11a/11na? */ int ath_hal_enable_msi; /* enable MSI interrupts (needed?) */ int ath_hal_beacon_filter_interval; /* ok to be 0 for now? */ /* For now, set this to 0 - net80211 needs to know about hardware MFP support */ int ath_hal_mfp_support; int ath_hal_enable_ani; /* should set this.. */ int ath_hal_cwm_ignore_ext_cca; int ath_hal_show_bb_panic; int ath_hal_ant_ctrl_comm2g_switch_enable; int ath_hal_ext_atten_margin_cfg; int ath_hal_min_gainidx; int ath_hal_war70c; uint32_t ath_hal_mci_config; } HAL_OPS_CONFIG; /* * Hardware Access Layer (HAL) API. * * Clients of the HAL call ath_hal_attach to obtain a reference to an * ath_hal structure for use with the device. Hardware-related operations * that follow must call back into the HAL through interface, supplying * the reference as the first parameter. Note that before using the * reference returned by ath_hal_attach the caller should verify the * ABI version number. */ struct ath_hal { uint32_t ah_magic; /* consistency check magic number */ uint16_t ah_devid; /* PCI device ID */ uint16_t ah_subvendorid; /* PCI subvendor ID */ HAL_SOFTC ah_sc; /* back pointer to driver/os state */ HAL_BUS_TAG ah_st; /* params for register r+w */ HAL_BUS_HANDLE ah_sh; HAL_CTRY_CODE ah_countryCode; uint32_t ah_macVersion; /* MAC version id */ uint16_t ah_macRev; /* MAC revision */ uint16_t ah_phyRev; /* PHY revision */ /* NB: when only one radio is present the rev is in 5Ghz */ uint16_t ah_analog5GhzRev;/* 5GHz radio revision */ uint16_t ah_analog2GhzRev;/* 2GHz radio revision */ uint16_t *ah_eepromdata; /* eeprom buffer, if needed */ uint32_t ah_intrstate[8]; /* last int state */ uint32_t ah_syncstate; /* last sync intr state */ /* Current powerstate from HAL calls */ HAL_POWER_MODE ah_powerMode; HAL_OPS_CONFIG ah_config; const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, u_int mode); void __ahdecl(*ah_detach)(struct ath_hal*); /* Reset functions */ HAL_BOOL __ahdecl(*ah_reset)(struct ath_hal *, HAL_OPMODE, struct ieee80211_channel *, HAL_BOOL bChannelChange, HAL_RESET_TYPE resetType, HAL_STATUS *status); HAL_BOOL __ahdecl(*ah_phyDisable)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_disable)(struct ath_hal *); void __ahdecl(*ah_configPCIE)(struct ath_hal *, HAL_BOOL restore, HAL_BOOL power_off); void __ahdecl(*ah_disablePCIE)(struct ath_hal *); void __ahdecl(*ah_setPCUConfig)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_perCalibration)(struct ath_hal*, struct ieee80211_channel *, HAL_BOOL *); HAL_BOOL __ahdecl(*ah_perCalibrationN)(struct ath_hal *, struct ieee80211_channel *, u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); HAL_BOOL __ahdecl(*ah_resetCalValid)(struct ath_hal *, const struct ieee80211_channel *); HAL_BOOL __ahdecl(*ah_setTxPower)(struct ath_hal *, const struct ieee80211_channel *, uint16_t *); HAL_BOOL __ahdecl(*ah_setTxPowerLimit)(struct ath_hal *, uint32_t); HAL_BOOL __ahdecl(*ah_setBoardValues)(struct ath_hal *, const struct ieee80211_channel *); /* Transmit functions */ HAL_BOOL __ahdecl(*ah_updateTxTrigLevel)(struct ath_hal*, HAL_BOOL incTrigLevel); int __ahdecl(*ah_setupTxQueue)(struct ath_hal *, HAL_TX_QUEUE, const HAL_TXQ_INFO *qInfo); HAL_BOOL __ahdecl(*ah_setTxQueueProps)(struct ath_hal *, int q, const HAL_TXQ_INFO *qInfo); HAL_BOOL __ahdecl(*ah_getTxQueueProps)(struct ath_hal *, int q, HAL_TXQ_INFO *qInfo); HAL_BOOL __ahdecl(*ah_releaseTxQueue)(struct ath_hal *ah, u_int q); HAL_BOOL __ahdecl(*ah_resetTxQueue)(struct ath_hal *ah, u_int q); uint32_t __ahdecl(*ah_getTxDP)(struct ath_hal*, u_int); HAL_BOOL __ahdecl(*ah_setTxDP)(struct ath_hal*, u_int, uint32_t txdp); uint32_t __ahdecl(*ah_numTxPending)(struct ath_hal *, u_int q); HAL_BOOL __ahdecl(*ah_startTxDma)(struct ath_hal*, u_int); HAL_BOOL __ahdecl(*ah_stopTxDma)(struct ath_hal*, u_int); HAL_BOOL __ahdecl(*ah_setupTxDesc)(struct ath_hal *, struct ath_desc *, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsctsDuration, u_int compicvLen, u_int compivLen, u_int comp); HAL_BOOL __ahdecl(*ah_setupXTxDesc)(struct ath_hal *, struct ath_desc*, u_int txRate1, u_int txTries1, u_int txRate2, u_int txTries2, u_int txRate3, u_int txTries3); HAL_BOOL __ahdecl(*ah_fillTxDesc)(struct ath_hal *, struct ath_desc *, HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *); HAL_STATUS __ahdecl(*ah_procTxDesc)(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); void __ahdecl(*ah_getTxIntrQueue)(struct ath_hal *, uint32_t *); void __ahdecl(*ah_reqTxIntrDesc)(struct ath_hal *, struct ath_desc*); HAL_BOOL __ahdecl(*ah_getTxCompletionRates)(struct ath_hal *, const struct ath_desc *ds, int *rates, int *tries); void __ahdecl(*ah_setTxDescLink)(struct ath_hal *ah, void *ds, uint32_t link); void __ahdecl(*ah_getTxDescLink)(struct ath_hal *ah, void *ds, uint32_t *link); void __ahdecl(*ah_getTxDescLinkPtr)(struct ath_hal *ah, void *ds, uint32_t **linkptr); void __ahdecl(*ah_setupTxStatusRing)(struct ath_hal *, void *ts_start, uint32_t ts_paddr_start, uint16_t size); void __ahdecl(*ah_getTxRawTxDesc)(struct ath_hal *, u_int32_t *); /* Receive Functions */ uint32_t __ahdecl(*ah_getRxDP)(struct ath_hal*, HAL_RX_QUEUE); void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp, HAL_RX_QUEUE); void __ahdecl(*ah_enableReceive)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_stopDmaReceive)(struct ath_hal*); void __ahdecl(*ah_startPcuReceive)(struct ath_hal*, HAL_BOOL); void __ahdecl(*ah_stopPcuReceive)(struct ath_hal*); void __ahdecl(*ah_setMulticastFilter)(struct ath_hal*, uint32_t filter0, uint32_t filter1); HAL_BOOL __ahdecl(*ah_setMulticastFilterIndex)(struct ath_hal*, uint32_t index); HAL_BOOL __ahdecl(*ah_clrMulticastFilterIndex)(struct ath_hal*, uint32_t index); uint32_t __ahdecl(*ah_getRxFilter)(struct ath_hal*); void __ahdecl(*ah_setRxFilter)(struct ath_hal*, uint32_t); HAL_BOOL __ahdecl(*ah_setupRxDesc)(struct ath_hal *, struct ath_desc *, uint32_t size, u_int flags); HAL_STATUS __ahdecl(*ah_procRxDesc)(struct ath_hal *, struct ath_desc *, uint32_t phyAddr, struct ath_desc *next, uint64_t tsf, struct ath_rx_status *); void __ahdecl(*ah_rxMonitor)(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); void __ahdecl(*ah_aniPoll)(struct ath_hal *, const struct ieee80211_channel *); void __ahdecl(*ah_procMibEvent)(struct ath_hal *, const HAL_NODE_STATS *); /* Misc Functions */ HAL_STATUS __ahdecl(*ah_getCapability)(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t capability, uint32_t *result); HAL_BOOL __ahdecl(*ah_setCapability)(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t capability, uint32_t setting, HAL_STATUS *); HAL_BOOL __ahdecl(*ah_getDiagState)(struct ath_hal *, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); void __ahdecl(*ah_getMacAddress)(struct ath_hal *, uint8_t *); HAL_BOOL __ahdecl(*ah_setMacAddress)(struct ath_hal *, const uint8_t*); void __ahdecl(*ah_getBssIdMask)(struct ath_hal *, uint8_t *); HAL_BOOL __ahdecl(*ah_setBssIdMask)(struct ath_hal *, const uint8_t*); HAL_BOOL __ahdecl(*ah_setRegulatoryDomain)(struct ath_hal*, uint16_t, HAL_STATUS *); void __ahdecl(*ah_setLedState)(struct ath_hal*, HAL_LED_STATE); void __ahdecl(*ah_writeAssocid)(struct ath_hal*, const uint8_t *bssid, uint16_t assocId); HAL_BOOL __ahdecl(*ah_gpioCfgOutput)(struct ath_hal *, uint32_t gpio, HAL_GPIO_MUX_TYPE); HAL_BOOL __ahdecl(*ah_gpioCfgInput)(struct ath_hal *, uint32_t gpio); uint32_t __ahdecl(*ah_gpioGet)(struct ath_hal *, uint32_t gpio); HAL_BOOL __ahdecl(*ah_gpioSet)(struct ath_hal *, uint32_t gpio, uint32_t val); void __ahdecl(*ah_gpioSetIntr)(struct ath_hal*, u_int, uint32_t); uint32_t __ahdecl(*ah_getTsf32)(struct ath_hal*); uint64_t __ahdecl(*ah_getTsf64)(struct ath_hal*); void __ahdecl(*ah_setTsf64)(struct ath_hal *, uint64_t); void __ahdecl(*ah_resetTsf)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_detectCardPresent)(struct ath_hal*); void __ahdecl(*ah_updateMibCounters)(struct ath_hal*, HAL_MIB_STATS*); HAL_RFGAIN __ahdecl(*ah_getRfGain)(struct ath_hal*); u_int __ahdecl(*ah_getDefAntenna)(struct ath_hal*); void __ahdecl(*ah_setDefAntenna)(struct ath_hal*, u_int); HAL_ANT_SETTING __ahdecl(*ah_getAntennaSwitch)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setAntennaSwitch)(struct ath_hal*, HAL_ANT_SETTING); HAL_BOOL __ahdecl(*ah_setSifsTime)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getSifsTime)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setSlotTime)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getSlotTime)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setAckTimeout)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getAckTimeout)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setAckCTSRate)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getAckCTSRate)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setCTSTimeout)(struct ath_hal*, u_int); u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int); void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int); HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); void __ahdecl(*ah_setChainMasks)(struct ath_hal *, uint32_t, uint32_t); + u_int __ahdecl(*ah_getNav)(struct ath_hal*); + void __ahdecl(*ah_setNav)(struct ath_hal*, u_int); /* DFS functions */ void __ahdecl(*ah_enableDfs)(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); void __ahdecl(*ah_getDfsThresh)(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); HAL_BOOL __ahdecl(*ah_getDfsDefaultThresh)(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); HAL_BOOL __ahdecl(*ah_procRadarEvent)(struct ath_hal *ah, struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event); HAL_BOOL __ahdecl(*ah_isFastClockEnabled)(struct ath_hal *ah); void __ahdecl(*ah_setDfsCacTxQuiet)(struct ath_hal *, HAL_BOOL); /* Spectral Scan functions */ void __ahdecl(*ah_spectralConfigure)(struct ath_hal *ah, HAL_SPECTRAL_PARAM *sp); void __ahdecl(*ah_spectralGetConfig)(struct ath_hal *ah, HAL_SPECTRAL_PARAM *sp); void __ahdecl(*ah_spectralStart)(struct ath_hal *); void __ahdecl(*ah_spectralStop)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_spectralIsEnabled)(struct ath_hal *); HAL_BOOL __ahdecl(*ah_spectralIsActive)(struct ath_hal *); /* XXX getNfPri() and getNfExt() */ /* Key Cache Functions */ uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_resetKeyCacheEntry)(struct ath_hal*, uint16_t); HAL_BOOL __ahdecl(*ah_isKeyCacheEntryValid)(struct ath_hal *, uint16_t); HAL_BOOL __ahdecl(*ah_setKeyCacheEntry)(struct ath_hal*, uint16_t, const HAL_KEYVAL *, const uint8_t *, int); HAL_BOOL __ahdecl(*ah_setKeyCacheEntryMac)(struct ath_hal*, uint16_t, const uint8_t *); /* Power Management Functions */ HAL_BOOL __ahdecl(*ah_setPowerMode)(struct ath_hal*, HAL_POWER_MODE mode, int setChip); HAL_POWER_MODE __ahdecl(*ah_getPowerMode)(struct ath_hal*); int16_t __ahdecl(*ah_getChanNoise)(struct ath_hal *, const struct ieee80211_channel *); /* Beacon Management Functions */ void __ahdecl(*ah_setBeaconTimers)(struct ath_hal*, const HAL_BEACON_TIMERS *); /* NB: deprecated, use ah_setBeaconTimers instead */ void __ahdecl(*ah_beaconInit)(struct ath_hal *, uint32_t nexttbtt, uint32_t intval); void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*, const HAL_BEACON_STATE *); void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*); uint64_t __ahdecl(*ah_getNextTBTT)(struct ath_hal *); /* 802.11n Functions */ HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *, struct ath_desc *, HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int, u_int, HAL_PKT_TYPE, u_int, HAL_CIPHER, uint8_t, HAL_BOOL, HAL_BOOL, HAL_BOOL); HAL_BOOL __ahdecl(*ah_setupFirstTxDesc)(struct ath_hal *, struct ath_desc *, u_int, u_int, u_int, u_int, u_int, u_int, u_int, u_int); HAL_BOOL __ahdecl(*ah_setupLastTxDesc)(struct ath_hal *, struct ath_desc *, const struct ath_desc *); void __ahdecl(*ah_set11nRateScenario)(struct ath_hal *, struct ath_desc *, u_int, u_int, HAL_11N_RATE_SERIES [], u_int, u_int); /* * The next 4 (set11ntxdesc -> set11naggrlast) are specific * to the EDMA HAL. Descriptors are chained together by * using filltxdesc (not ChainTxDesc) and then setting the * aggregate flags appropriately using first/middle/last. */ void __ahdecl(*ah_set11nTxDesc)(struct ath_hal *, void *, u_int, HAL_PKT_TYPE, u_int, u_int, u_int); void __ahdecl(*ah_set11nAggrFirst)(struct ath_hal *, struct ath_desc *, u_int, u_int); void __ahdecl(*ah_set11nAggrMiddle)(struct ath_hal *, struct ath_desc *, u_int); void __ahdecl(*ah_set11nAggrLast)(struct ath_hal *, struct ath_desc *); void __ahdecl(*ah_clr11nAggr)(struct ath_hal *, struct ath_desc *); void __ahdecl(*ah_set11nBurstDuration)(struct ath_hal *, struct ath_desc *, u_int); void __ahdecl(*ah_set11nVirtMoreFrag)(struct ath_hal *, struct ath_desc *, u_int); HAL_BOOL __ahdecl(*ah_getMibCycleCounts) (struct ath_hal *, HAL_SURVEY_SAMPLE *); uint32_t __ahdecl(*ah_get11nExtBusy)(struct ath_hal *); void __ahdecl(*ah_set11nMac2040)(struct ath_hal *, HAL_HT_MACMODE); HAL_HT_RXCLEAR __ahdecl(*ah_get11nRxClear)(struct ath_hal *ah); void __ahdecl(*ah_set11nRxClear)(struct ath_hal *, HAL_HT_RXCLEAR); /* Interrupt functions */ HAL_BOOL __ahdecl(*ah_isInterruptPending)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_getPendingInterrupts)(struct ath_hal*, HAL_INT*); HAL_INT __ahdecl(*ah_getInterrupts)(struct ath_hal*); HAL_INT __ahdecl(*ah_setInterrupts)(struct ath_hal*, HAL_INT); /* Bluetooth Coexistence functions */ void __ahdecl(*ah_btCoexSetInfo)(struct ath_hal *, HAL_BT_COEX_INFO *); void __ahdecl(*ah_btCoexSetConfig)(struct ath_hal *, HAL_BT_COEX_CONFIG *); void __ahdecl(*ah_btCoexSetQcuThresh)(struct ath_hal *, int); void __ahdecl(*ah_btCoexSetWeights)(struct ath_hal *, uint32_t); void __ahdecl(*ah_btCoexSetBmissThresh)(struct ath_hal *, uint32_t); void __ahdecl(*ah_btCoexSetParameter)(struct ath_hal *, uint32_t, uint32_t); void __ahdecl(*ah_btCoexDisable)(struct ath_hal *); int __ahdecl(*ah_btCoexEnable)(struct ath_hal *); /* Bluetooth MCI methods */ void __ahdecl(*ah_btMciSetup)(struct ath_hal *, uint32_t, void *, uint16_t, uint32_t); HAL_BOOL __ahdecl(*ah_btMciSendMessage)(struct ath_hal *, uint8_t, uint32_t, uint32_t *, uint8_t, HAL_BOOL, HAL_BOOL); uint32_t __ahdecl(*ah_btMciGetInterrupt)(struct ath_hal *, uint32_t *, uint32_t *); uint32_t __ahdecl(*ah_btMciState)(struct ath_hal *, uint32_t, uint32_t *); void __ahdecl(*ah_btMciDetach)(struct ath_hal *); /* LNA diversity configuration */ void __ahdecl(*ah_divLnaConfGet)(struct ath_hal *, HAL_ANT_COMB_CONFIG *); void __ahdecl(*ah_divLnaConfSet)(struct ath_hal *, HAL_ANT_COMB_CONFIG *); }; /* * Check the PCI vendor ID and device ID against Atheros' values * and return a printable description for any Atheros hardware. * AH_NULL is returned if the ID's do not describe Atheros hardware. */ extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid); /* * Attach the HAL for use with the specified device. The device is * defined by the PCI device ID. The caller provides an opaque pointer * to an upper-layer data structure (HAL_SOFTC) that is stored in the * HAL state block for later use. Hardware register accesses are done * using the specified bus tag and handle. On successful return a * reference to a state block is returned that must be supplied in all * subsequent HAL calls. Storage associated with this reference is * dynamically allocated and must be freed by calling the ah_detach * method when the client is done. If the attach operation fails a * null (AH_NULL) reference will be returned and a status code will * be returned if the status parameter is non-zero. */ extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC, HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS* status); extern const char *ath_hal_mac_name(struct ath_hal *); extern const char *ath_hal_rf_name(struct ath_hal *); /* * Regulatory interfaces. Drivers should use ath_hal_init_channels to * request a set of channels for a particular country code and/or * regulatory domain. If CTRY_DEFAULT and SKU_NONE are specified then * this list is constructed according to the contents of the EEPROM. * ath_hal_getchannels acts similarly but does not alter the operating * state; this can be used to collect information for a particular * regulatory configuration. Finally ath_hal_set_channels installs a * channel list constructed outside the driver. The HAL will adopt the * channel list and setup internal state according to the specified * regulatory configuration (e.g. conformance test limits). * * For all interfaces the channel list is returned in the supplied array. * maxchans defines the maximum size of this array. nchans contains the * actual number of channels returned. If a problem occurred then a * status code != HAL_OK is returned. */ struct ieee80211_channel; /* * Return a list of channels according to the specified regulatory. */ extern HAL_STATUS __ahdecl ath_hal_getchannels(struct ath_hal *, struct ieee80211_channel *chans, u_int maxchans, int *nchans, u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn, HAL_BOOL enableExtendedChannels); /* * Return a list of channels and install it as the current operating * regulatory list. */ extern HAL_STATUS __ahdecl ath_hal_init_channels(struct ath_hal *, struct ieee80211_channel *chans, u_int maxchans, int *nchans, u_int modeSelect, HAL_CTRY_CODE cc, HAL_REG_DOMAIN rd, HAL_BOOL enableExtendedChannels); /* * Install the list of channels as the current operating regulatory * and setup related state according to the country code and sku. */ extern HAL_STATUS __ahdecl ath_hal_set_channels(struct ath_hal *, struct ieee80211_channel *chans, int nchans, HAL_CTRY_CODE cc, HAL_REG_DOMAIN regDmn); /* * Fetch the ctl/ext noise floor values reported by a MIMO * radio. Returns 1 for valid results, 0 for invalid channel. */ extern int __ahdecl ath_hal_get_mimo_chan_noise(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t *nf_ctl, int16_t *nf_ext); /* * Calibrate noise floor data following a channel scan or similar. * This must be called prior retrieving noise floor data. */ extern void __ahdecl ath_hal_process_noisefloor(struct ath_hal *ah); /* * Return bit mask of wireless modes supported by the hardware. */ extern u_int __ahdecl ath_hal_getwirelessmodes(struct ath_hal*); /* * Get the HAL wireless mode for the given channel. */ extern int ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan); /* * Calculate the packet TX time for a legacy or 11n frame */ extern uint32_t __ahdecl ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble, HAL_BOOL includeSifs); /* * Calculate the duration of an 11n frame. */ extern uint32_t __ahdecl ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40, HAL_BOOL isShortGI); /* * Calculate the transmit duration of a legacy frame. */ extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *, const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, HAL_BOOL shortPreamble, HAL_BOOL includeSifs); /* * Adjust the TSF. */ extern void __ahdecl ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta); /* * Enable or disable CCA. */ void __ahdecl ath_hal_setcca(struct ath_hal *ah, int ena); /* * Get CCA setting. */ int __ahdecl ath_hal_getcca(struct ath_hal *ah); /* * Enable/disable and get self-gen frame (ACK, CTS) for CAC. */ void __ahdecl ath_hal_set_dfs_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL ena); /* * Read EEPROM data from ah_eepromdata */ HAL_BOOL __ahdecl ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data); /* * For now, simply pass through MFP frames. */ static inline u_int32_t ath_hal_get_mfp_qos(struct ath_hal *ah) { //return AH_PRIVATE(ah)->ah_mfp_qos; return HAL_MFP_QOSDATA; } /* * Convert between microseconds and core system clocks. */ extern u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs); extern u_int ath_hal_mac_usec(struct ath_hal *ah, u_int clks); extern uint64_t ath_hal_mac_psec(struct ath_hal *ah, u_int clks); #endif /* _ATH_AH_H_ */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h index 373c676e25b3..f09e99b1ce9e 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210.h +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -1,305 +1,307 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2004 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #ifndef _ATH_AR5210_H_ #define _ATH_AR5210_H_ #define AR5210_MAGIC 0x19980124 #if 0 /* * RTS_ENABLE includes LONG_PKT because they essentially * imply the same thing, and are set or not set together * for this chip */ #define AR5210_TXD_CTRL_A_HDR_LEN(_val) (((_val) ) & 0x0003f) #define AR5210_TXD_CTRL_A_TX_RATE(_val) (((_val) << 6) & 0x003c0) #define AR5210_TXD_CTRL_A_RTS_ENABLE ( 0x00c00) #define AR5210_TXD_CTRL_A_CLEAR_DEST_MASK(_val) (((_val) << 12) & 0x01000) #define AR5210_TXD_CTRL_A_ANT_MODE(_val) (((_val) << 13) & 0x02000) #define AR5210_TXD_CTRL_A_PKT_TYPE(_val) (((_val) << 14) & 0x1c000) #define AR5210_TXD_CTRL_A_INT_REQ ( 0x20000) #define AR5210_TXD_CTRL_A_KEY_VALID ( 0x40000) #define AR5210_TXD_CTRL_B_KEY_ID(_val) (((_val) ) & 0x0003f) #define AR5210_TXD_CTRL_B_RTS_DURATION(_val) (((_val) << 6) & 0x7ffc0) #endif #define INIT_CONFIG_STATUS 0x00000000 #define INIT_ACKTOPS 0x00000008 #define INIT_BCON_CNTRL_REG 0x00000000 #define INIT_SLOT_TIME 0x00000168 #define INIT_SLOT_TIME_TURBO 0x000001e0 /* More aggressive turbo slot timing = 6 us */ #define INIT_ACK_CTS_TIMEOUT 0x04000400 #define INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 #define INIT_USEC 0x27 #define INIT_USEC_TURBO 0x4f #define INIT_USEC_32 0x1f #define INIT_TX_LATENCY 0x36 #define INIT_RX_LATENCY 0x1D #define INIT_TRANSMIT_LATENCY \ ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ (INIT_USEC_32 << 7) | INIT_USEC ) #define INIT_TRANSMIT_LATENCY_TURBO \ ((INIT_RX_LATENCY << AR_USEC_RX_LATENCY_S) | \ (INIT_TX_LATENCY << AR_USEC_TX_LATENCY_S) | \ (INIT_USEC_32 << 7) | INIT_USEC_TURBO) #define INIT_SIFS 0x230 /* = 16 us - 2 us */ #define INIT_SIFS_TURBO 0x1E0 /* More aggressive turbo SIFS timing - 8 us - 2 us */ /* * Various fifo fill before Tx start, in 64-byte units * i.e. put the frame in the air while still DMAing */ #define MIN_TX_FIFO_THRESHOLD 0x1 #define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) #define INIT_NEXT_CFP_START 0xffffffff #define INIT_BEACON_PERIOD 0xffff #define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ #define INIT_BEACON_CONTROL \ ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ (INIT_TIM_OFFSET<<16) | INIT_BEACON_PERIOD) #define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to max value of 7 */ #define INIT_ProgIFS 0x398 /* PIFS - 2us */ #define INIT_ProgIFS_TURBO 0x3C0 #define INIT_EIFS 0xd70 #define INIT_EIFS_TURBO 0x1ae0 #define INIT_CARR_SENSE_EN 1 #define INIT_PROTO_TIME_CNTRL ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS << 12) | \ (INIT_ProgIFS) ) #define INIT_PROTO_TIME_CNTRL_TURBO ( (INIT_CARR_SENSE_EN << 26) | (INIT_EIFS_TURBO << 12) | \ (INIT_ProgIFS_TURBO) ) #define AR5210_MAX_RATE_POWER 60 #undef HAL_NUM_TX_QUEUES /* from ah.h */ #define HAL_NUM_TX_QUEUES 3 struct ath_hal_5210 { struct ath_hal_private ah_priv; /* base definitions */ uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; /* * Runtime state. */ uint32_t ah_maskReg; /* shadow of IMR+IER regs */ uint32_t ah_txOkInterruptMask; uint32_t ah_txErrInterruptMask; uint32_t ah_txDescInterruptMask; uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; uint8_t ah_bssid[IEEE80211_ADDR_LEN]; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */ /* * Station mode support. */ uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ uint32_t ah_rssiThr; /* RSSI_THR settings */ u_int ah_sifstime; /* user-specified sifs time */ u_int ah_slottime; /* user-specified slot time */ u_int ah_acktimeout; /* user-specified ack timeout */ u_int ah_ctstimeout; /* user-specified cts timeout */ uint16_t ah_associd; /* association id */ }; #define AH5210(ah) ((struct ath_hal_5210 *)(ah)) struct ath_hal; extern void ar5210Detach(struct ath_hal *ah); extern HAL_BOOL ar5210Reset(struct ath_hal *, HAL_OPMODE, struct ieee80211_channel *, HAL_BOOL bChannelChange, HAL_RESET_TYPE, HAL_STATUS *); extern void ar5210SetPCUConfig(struct ath_hal *); extern HAL_BOOL ar5210PhyDisable(struct ath_hal *); extern HAL_BOOL ar5210Disable(struct ath_hal *); extern HAL_BOOL ar5210ChipReset(struct ath_hal *, struct ieee80211_channel *); extern HAL_BOOL ar5210PerCalibration(struct ath_hal *, struct ieee80211_channel *, HAL_BOOL *); extern HAL_BOOL ar5210PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); extern HAL_BOOL ar5210ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *); extern int16_t ar5210GetNoiseFloor(struct ath_hal *); extern int16_t ar5210GetNfAdjust(struct ath_hal *, const HAL_CHANNEL_INTERNAL *); extern HAL_BOOL ar5210SetTxPowerLimit(struct ath_hal *, uint32_t limit); extern HAL_BOOL ar5210SetTransmitPower(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar5210CalNoiseFloor(struct ath_hal *, HAL_CHANNEL_INTERNAL *); extern HAL_BOOL ar5210ResetDma(struct ath_hal *, HAL_OPMODE); extern HAL_BOOL ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo); extern int ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5210ResetTxQueue(struct ath_hal *ah, u_int q); extern uint32_t ar5210GetTxDP(struct ath_hal *, u_int); extern HAL_BOOL ar5210SetTxDP(struct ath_hal *, u_int, uint32_t txdp); extern HAL_BOOL ar5210UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); extern uint32_t ar5210NumTxPending(struct ath_hal *, u_int); extern HAL_BOOL ar5210StartTxDma(struct ath_hal *, u_int); extern HAL_BOOL ar5210StopTxDma(struct ath_hal *, u_int); extern HAL_BOOL ar5210SetupTxDesc(struct ath_hal *, struct ath_desc *, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txRetries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsctsDuration, u_int compicvLen, u_int compivLen, u_int comp); extern HAL_BOOL ar5210SetupXTxDesc(struct ath_hal *, struct ath_desc *, u_int txRate1, u_int txRetries1, u_int txRate2, u_int txRetries2, u_int txRate3, u_int txRetries3); extern HAL_BOOL ar5210FillTxDesc(struct ath_hal *, struct ath_desc *, HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0); extern HAL_STATUS ar5210ProcTxDesc(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); extern void ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); extern HAL_BOOL ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *, int *rates, int *tries); extern void ar5210SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link); extern void ar5210GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link); extern void ar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr); extern uint32_t ar5210GetRxDP(struct ath_hal *, HAL_RX_QUEUE); extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5210EnableReceive(struct ath_hal *); extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *); extern void ar5210StartPcuReceive(struct ath_hal *, HAL_BOOL); extern void ar5210StopPcuReceive(struct ath_hal *); extern void ar5210SetMulticastFilter(struct ath_hal *, uint32_t filter0, uint32_t filter1); extern HAL_BOOL ar5210ClrMulticastFilterIndex(struct ath_hal *, uint32_t); extern HAL_BOOL ar5210SetMulticastFilterIndex(struct ath_hal *, uint32_t); extern uint32_t ar5210GetRxFilter(struct ath_hal *); extern void ar5210SetRxFilter(struct ath_hal *, uint32_t); extern HAL_BOOL ar5210SetupRxDesc(struct ath_hal *, struct ath_desc *, uint32_t, u_int flags); extern HAL_STATUS ar5210ProcRxDesc(struct ath_hal *, struct ath_desc *, uint32_t, struct ath_desc *, uint64_t, struct ath_rx_status *); extern void ar5210GetMacAddress(struct ath_hal *, uint8_t *); extern HAL_BOOL ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *); extern void ar5210GetBssIdMask(struct ath_hal *, uint8_t *); extern HAL_BOOL ar5210SetBssIdMask(struct ath_hal *, const uint8_t *); extern HAL_BOOL ar5210EepromRead(struct ath_hal *, u_int off, uint16_t *data); extern HAL_BOOL ar5210EepromWrite(struct ath_hal *, u_int off, uint16_t data); extern HAL_BOOL ar5210SetRegulatoryDomain(struct ath_hal *, uint16_t, HAL_STATUS *); extern u_int ar5210GetWirelessModes(struct ath_hal *ah); extern void ar5210EnableRfKill(struct ath_hal *); extern HAL_BOOL ar5210GpioCfgInput(struct ath_hal *, uint32_t gpio); extern HAL_BOOL ar5210GpioCfgOutput(struct ath_hal *, uint32_t gpio, HAL_GPIO_MUX_TYPE); extern uint32_t ar5210GpioGet(struct ath_hal *, uint32_t gpio); extern HAL_BOOL ar5210GpioSet(struct ath_hal *, uint32_t gpio, uint32_t); extern void ar5210Gpio0SetIntr(struct ath_hal *, u_int, uint32_t ilevel); extern void ar5210SetLedState(struct ath_hal *, HAL_LED_STATE); extern u_int ar5210GetDefAntenna(struct ath_hal *); extern void ar5210SetDefAntenna(struct ath_hal *, u_int); extern HAL_ANT_SETTING ar5210GetAntennaSwitch(struct ath_hal *); extern HAL_BOOL ar5210SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); extern void ar5210WriteAssocid(struct ath_hal *, const uint8_t *bssid, uint16_t assocId); extern uint32_t ar5210GetTsf32(struct ath_hal *); extern uint64_t ar5210GetTsf64(struct ath_hal *); extern void ar5210ResetTsf(struct ath_hal *); extern uint32_t ar5210GetRandomSeed(struct ath_hal *); extern HAL_BOOL ar5210DetectCardPresent(struct ath_hal *); extern void ar5210UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); extern void ar5210EnableHwEncryption(struct ath_hal *); extern void ar5210DisableHwEncryption(struct ath_hal *); extern HAL_RFGAIN ar5210GetRfgain(struct ath_hal *); extern HAL_BOOL ar5210SetSifsTime(struct ath_hal *, u_int); extern u_int ar5210GetSifsTime(struct ath_hal *); extern HAL_BOOL ar5210SetSlotTime(struct ath_hal *, u_int); extern u_int ar5210GetSlotTime(struct ath_hal *); extern HAL_BOOL ar5210SetAckTimeout(struct ath_hal *, u_int); extern u_int ar5210GetAckTimeout(struct ath_hal *); extern HAL_BOOL ar5210SetAckCTSRate(struct ath_hal *, u_int); extern u_int ar5210GetAckCTSRate(struct ath_hal *); extern HAL_BOOL ar5210SetCTSTimeout(struct ath_hal *, u_int); extern u_int ar5210GetCTSTimeout(struct ath_hal *); extern HAL_BOOL ar5210SetDecompMask(struct ath_hal *, uint16_t, int); void ar5210SetCoverageClass(struct ath_hal *, uint8_t, int); extern HAL_STATUS ar5210SetQuiet(struct ath_hal *, uint32_t, uint32_t, uint32_t, HAL_QUIET_FLAG); extern HAL_STATUS ar5210GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t *); extern HAL_BOOL ar5210SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t, HAL_STATUS *); extern HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); extern uint32_t ar5210Get11nExtBusy(struct ath_hal *); extern HAL_BOOL ar5210GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); extern void ar5210SetChainMasks(struct ath_hal *, uint32_t, uint32_t); extern void ar5210EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5210GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val); +extern void ar5210SetNav(struct ath_hal *ah, u_int val); +extern u_int ar5210GetNav(struct ath_hal *ah); extern u_int ar5210GetKeyCacheSize(struct ath_hal *); extern HAL_BOOL ar5210IsKeyCacheEntryValid(struct ath_hal *, uint16_t); extern HAL_BOOL ar5210ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); extern HAL_BOOL ar5210SetKeyCacheEntry(struct ath_hal *, uint16_t entry, const HAL_KEYVAL *, const uint8_t *mac, int xorKey); extern HAL_BOOL ar5210SetKeyCacheEntryMac(struct ath_hal *, uint16_t, const uint8_t *); extern HAL_BOOL ar5210SetPowerMode(struct ath_hal *, uint32_t powerRequest, int setChip); extern HAL_POWER_MODE ar5210GetPowerMode(struct ath_hal *); extern void ar5210SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *); extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t); extern void ar5210SetStaBeaconTimers(struct ath_hal *, const HAL_BEACON_STATE *); extern void ar5210ResetStaBeaconTimers(struct ath_hal *); extern uint64_t ar5210GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *); extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *); extern HAL_INT ar5210GetInterrupts(struct ath_hal *); extern HAL_INT ar5210SetInterrupts(struct ath_hal *, HAL_INT ints); extern const HAL_RATE_TABLE *ar5210GetRateTable(struct ath_hal *, u_int mode); extern HAL_BOOL ar5210AniControl(struct ath_hal *, HAL_ANI_CMD, int ); extern void ar5210AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5210RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); extern void ar5210MibEvent(struct ath_hal *, const HAL_NODE_STATS *); #endif /* _ATH_AR5210_H_ */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c index 22afc12a6dcc..8bbd7e9d600e 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -1,419 +1,421 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2004 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ar5210/ar5210.h" #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" #include "ah_eeprom_v1.h" static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *, uint16_t flags, uint16_t *low, uint16_t *high); static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan); static void ar5210ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_on); static void ar5210DisablePCIE(struct ath_hal *ah); static const struct ath_hal_private ar5210hal = {{ .ah_magic = AR5210_MAGIC, .ah_getRateTable = ar5210GetRateTable, .ah_detach = ar5210Detach, /* Reset Functions */ .ah_reset = ar5210Reset, .ah_phyDisable = ar5210PhyDisable, .ah_disable = ar5210Disable, .ah_configPCIE = ar5210ConfigPCIE, .ah_disablePCIE = ar5210DisablePCIE, .ah_setPCUConfig = ar5210SetPCUConfig, .ah_perCalibration = ar5210PerCalibration, .ah_perCalibrationN = ar5210PerCalibrationN, .ah_resetCalValid = ar5210ResetCalValid, .ah_setTxPowerLimit = ar5210SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, /* Transmit functions */ .ah_updateTxTrigLevel = ar5210UpdateTxTrigLevel, .ah_setupTxQueue = ar5210SetupTxQueue, .ah_setTxQueueProps = ar5210SetTxQueueProps, .ah_getTxQueueProps = ar5210GetTxQueueProps, .ah_releaseTxQueue = ar5210ReleaseTxQueue, .ah_resetTxQueue = ar5210ResetTxQueue, .ah_getTxDP = ar5210GetTxDP, .ah_setTxDP = ar5210SetTxDP, .ah_numTxPending = ar5210NumTxPending, .ah_startTxDma = ar5210StartTxDma, .ah_stopTxDma = ar5210StopTxDma, .ah_setupTxDesc = ar5210SetupTxDesc, .ah_setupXTxDesc = ar5210SetupXTxDesc, .ah_fillTxDesc = ar5210FillTxDesc, .ah_procTxDesc = ar5210ProcTxDesc, .ah_getTxIntrQueue = ar5210GetTxIntrQueue, .ah_reqTxIntrDesc = ar5210IntrReqTxDesc, .ah_getTxCompletionRates = ar5210GetTxCompletionRates, .ah_setTxDescLink = ar5210SetTxDescLink, .ah_getTxDescLink = ar5210GetTxDescLink, .ah_getTxDescLinkPtr = ar5210GetTxDescLinkPtr, /* RX Functions */ .ah_getRxDP = ar5210GetRxDP, .ah_setRxDP = ar5210SetRxDP, .ah_enableReceive = ar5210EnableReceive, .ah_stopDmaReceive = ar5210StopDmaReceive, .ah_startPcuReceive = ar5210StartPcuReceive, .ah_stopPcuReceive = ar5210StopPcuReceive, .ah_setMulticastFilter = ar5210SetMulticastFilter, .ah_setMulticastFilterIndex = ar5210SetMulticastFilterIndex, .ah_clrMulticastFilterIndex = ar5210ClrMulticastFilterIndex, .ah_getRxFilter = ar5210GetRxFilter, .ah_setRxFilter = ar5210SetRxFilter, .ah_setupRxDesc = ar5210SetupRxDesc, .ah_procRxDesc = ar5210ProcRxDesc, .ah_rxMonitor = ar5210RxMonitor, .ah_aniPoll = ar5210AniPoll, .ah_procMibEvent = ar5210MibEvent, /* Misc Functions */ .ah_getCapability = ar5210GetCapability, .ah_setCapability = ar5210SetCapability, .ah_getDiagState = ar5210GetDiagState, .ah_getMacAddress = ar5210GetMacAddress, .ah_setMacAddress = ar5210SetMacAddress, .ah_getBssIdMask = ar5210GetBssIdMask, .ah_setBssIdMask = ar5210SetBssIdMask, .ah_setRegulatoryDomain = ar5210SetRegulatoryDomain, .ah_setLedState = ar5210SetLedState, .ah_writeAssocid = ar5210WriteAssocid, .ah_gpioCfgInput = ar5210GpioCfgInput, .ah_gpioCfgOutput = ar5210GpioCfgOutput, .ah_gpioGet = ar5210GpioGet, .ah_gpioSet = ar5210GpioSet, .ah_gpioSetIntr = ar5210Gpio0SetIntr, .ah_getTsf32 = ar5210GetTsf32, .ah_getTsf64 = ar5210GetTsf64, .ah_resetTsf = ar5210ResetTsf, .ah_detectCardPresent = ar5210DetectCardPresent, .ah_updateMibCounters = ar5210UpdateMibCounters, .ah_getRfGain = ar5210GetRfgain, .ah_getDefAntenna = ar5210GetDefAntenna, .ah_setDefAntenna = ar5210SetDefAntenna, .ah_getAntennaSwitch = ar5210GetAntennaSwitch, .ah_setAntennaSwitch = ar5210SetAntennaSwitch, .ah_setSifsTime = ar5210SetSifsTime, .ah_getSifsTime = ar5210GetSifsTime, .ah_setSlotTime = ar5210SetSlotTime, .ah_getSlotTime = ar5210GetSlotTime, .ah_setAckTimeout = ar5210SetAckTimeout, .ah_getAckTimeout = ar5210GetAckTimeout, .ah_setAckCTSRate = ar5210SetAckCTSRate, .ah_getAckCTSRate = ar5210GetAckCTSRate, .ah_setCTSTimeout = ar5210SetCTSTimeout, .ah_getCTSTimeout = ar5210GetCTSTimeout, .ah_setDecompMask = ar5210SetDecompMask, .ah_setCoverageClass = ar5210SetCoverageClass, .ah_setQuiet = ar5210SetQuiet, .ah_get11nExtBusy = ar5210Get11nExtBusy, .ah_getMibCycleCounts = ar5210GetMibCycleCounts, .ah_setChainMasks = ar5210SetChainMasks, .ah_enableDfs = ar5210EnableDfs, .ah_getDfsThresh = ar5210GetDfsThresh, /* XXX procRadarEvent */ /* XXX isFastClockEnabled */ + .ah_getNav = ar5210GetNav, + .ah_setNav = ar5210SetNav, /* Key Cache Functions */ .ah_getKeyCacheSize = ar5210GetKeyCacheSize, .ah_resetKeyCacheEntry = ar5210ResetKeyCacheEntry, .ah_isKeyCacheEntryValid = ar5210IsKeyCacheEntryValid, .ah_setKeyCacheEntry = ar5210SetKeyCacheEntry, .ah_setKeyCacheEntryMac = ar5210SetKeyCacheEntryMac, /* Power Management Functions */ .ah_setPowerMode = ar5210SetPowerMode, .ah_getPowerMode = ar5210GetPowerMode, /* Beacon Functions */ .ah_setBeaconTimers = ar5210SetBeaconTimers, .ah_beaconInit = ar5210BeaconInit, .ah_setStationBeaconTimers = ar5210SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers, .ah_getNextTBTT = ar5210GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5210IsInterruptPending, .ah_getPendingInterrupts = ar5210GetPendingInterrupts, .ah_getInterrupts = ar5210GetInterrupts, .ah_setInterrupts = ar5210SetInterrupts }, .ah_getChannelEdges = ar5210GetChannelEdges, .ah_getWirelessModes = ar5210GetWirelessModes, .ah_eepromRead = ar5210EepromRead, #ifdef AH_SUPPORT_WRITE_EEPROM .ah_eepromWrite = ar5210EepromWrite, #endif .ah_getChipPowerLimits = ar5210GetChipPowerLimits, }; static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah); /* * Attach for an AR5210 part. */ static struct ath_hal * ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5210 *ahp; struct ath_hal *ah; uint32_t revid, pcicfg; uint16_t eeval; HAL_STATUS ecode; int i; HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5210)); if (ahp == AH_NULL) { HALDEBUG(AH_NULL, HAL_DEBUG_ANY, "%s: no memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; } ah = &ahp->ah_priv.h; /* set initial values */ OS_MEMCPY(&ahp->ah_priv, &ar5210hal, sizeof(struct ath_hal_private)); ah->ah_sc = sc; ah->ah_st = st; ah->ah_sh = sh; ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ah->ah_powerMode = HAL_PM_UNDEFINED; ahp->ah_staId1Defaults = 0; ahp->ah_rssiThr = INIT_RSSI_THR; ahp->ah_sifstime = (u_int) -1; ahp->ah_slottime = (u_int) -1; ahp->ah_acktimeout = (u_int) -1; ahp->ah_ctstimeout = (u_int) -1; if (!ar5210ChipReset(ah, AH_NULL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; } /* Read Revisions from Chips */ AH_PRIVATE(ah)->ah_macVersion = 1; AH_PRIVATE(ah)->ah_macRev = OS_REG_READ(ah, AR_SREV) & 0xff; AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIPID); AH_PRIVATE(ah)->ah_analog2GhzRev = 0; /* Read Radio Chip Rev Extract */ OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); for (i = 0; i < 4; i++) OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); revid = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 28) & 0xf; /* Chip labelling is 1 greater than revision register for AR5110 */ AH_PRIVATE(ah)->ah_analog5GhzRev = ath_hal_reverseBits(revid, 4) + 1; /* * Read all the settings from the EEPROM and stash * ones we'll use later. */ pcicfg = OS_REG_READ(ah, AR_PCICFG); OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); ecode = ath_hal_v1EepromAttach(ah); if (ecode != HAL_OK) { goto eebad; } ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read regulatory domain from EEPROM\n", __func__); goto eebad; } AH_PRIVATE(ah)->ah_currentRD = eeval; ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error getting mac address from EEPROM\n", __func__); goto eebad; } OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ AH_PRIVATE(ah)->ah_getNfAdjust = ar5210GetNfAdjust; /* * Got everything we need now to setup the capabilities. */ (void) ar5210FillCapabilityInfo(ah); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); return ah; eebad: OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */ bad: if (ahp) ath_hal_free(ahp); if (status) *status = ecode; return AH_NULL; #undef N } void ar5210Detach(struct ath_hal *ah) { HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5210_MAGIC); ath_hal_eepromDetach(ah); ath_hal_free(ah); } /* * Store the channel edges for the requested operational mode */ static HAL_BOOL ar5210GetChannelEdges(struct ath_hal *ah, uint16_t flags, uint16_t *low, uint16_t *high) { if (flags & IEEE80211_CHAN_5GHZ) { *low = 5120; *high = 5430; return AH_TRUE; } else { return AH_FALSE; } } static HAL_BOOL ar5210GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) { /* XXX fill in, this is just a placeholder */ HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: no min/max power for %u/0x%x\n", __func__, chan->ic_freq, chan->ic_flags); chan->ic_maxpower = AR5210_MAX_RATE_POWER; chan->ic_minpower = 0; return AH_TRUE; } static void ar5210ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) { } static void ar5210DisablePCIE(struct ath_hal *ah) { } /* * Fill all software cached or static hardware state information. */ static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah) { struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; pCap->halWirelessModes |= HAL_MODE_11A; pCap->halLow5GhzChan = 5120; pCap->halHigh5GhzChan = 5430; pCap->halSleepAfterBeaconBroken = AH_TRUE; pCap->halPSPollBroken = AH_FALSE; pCap->halNumMRRetries = 1; /* No hardware MRR support */ pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ pCap->halTotalQueues = HAL_NUM_TX_QUEUES; pCap->halKeyCacheSize = 64; /* XXX not needed */ pCap->halChanHalfRate = AH_FALSE; pCap->halChanQuarterRate = AH_FALSE; /* * RSSI uses the combined field; some 11n NICs may use * the control chain RSSI. */ pCap->halUseCombinedRadarRssi = AH_TRUE; if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL)) { /* * Setup initial rfsilent settings based on the EEPROM * contents. Pin 0, polarity 0 is fixed; record this * using the EEPROM format found in later parts. */ ahpriv->ah_rfsilent = SM(0, AR_EEPROM_RFSILENT_GPIO_SEL) | SM(0, AR_EEPROM_RFSILENT_POLARITY); ahpriv->ah_rfkillEnabled = AH_TRUE; pCap->halRfSilentSupport = AH_TRUE; } pCap->halTxTstampPrecision = 16; pCap->halRxTstampPrecision = 15; /* NB: s/w extended from 13 */ pCap->halIntrMask = (HAL_INT_COMMON - HAL_INT_BNR) | HAL_INT_RX | HAL_INT_TX | HAL_INT_FATAL ; pCap->hal4kbSplitTransSupport = AH_TRUE; pCap->halHasRxSelfLinkedTail = AH_TRUE; ahpriv->ah_rxornIsFatal = AH_TRUE; return AH_TRUE; } static const char* ar5210Probe(uint16_t vendorid, uint16_t devid) { if (vendorid == ATHEROS_VENDOR_ID && (devid == AR5210_PROD || devid == AR5210_DEFAULT)) return "Atheros 5210"; return AH_NULL; } AH_CHIP(AR5210, ar5210Probe, ar5210Attach); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c index 347ad8891e36..7c4df40a712f 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c @@ -1,712 +1,735 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2004 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ar5210/ar5210.h" #include "ar5210/ar5210reg.h" #include "ar5210/ar5210phy.h" #include "ah_eeprom_v1.h" #define AR_NUM_GPIO 6 /* 6 GPIO bits */ #define AR_GPIOD_MASK 0x2f /* 6-bit mask */ void ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac) { struct ath_hal_5210 *ahp = AH5210(ah); OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); } HAL_BOOL ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac) { struct ath_hal_5210 *ahp = AH5210(ah); OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); return AH_TRUE; } void ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask) { static const uint8_t ones[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); } HAL_BOOL ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) { return AH_FALSE; } /* * Read 16 bits of data from the specified EEPROM offset. */ HAL_BOOL ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) { (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */ if (!ath_hal_wait(ah, AR_EP_STA, AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", __func__, AR_EP_AIR(off)); return AH_FALSE; } *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff; return AH_TRUE; } #ifdef AH_SUPPORT_WRITE_EEPROM /* * Write 16 bits of data to the specified EEPROM offset. */ HAL_BOOL ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) { return AH_FALSE; } #endif /* AH_SUPPORT_WRITE_EEPROM */ /* * Attempt to change the cards operating regulatory domain to the given value */ HAL_BOOL ar5210SetRegulatoryDomain(struct ath_hal *ah, uint16_t regDomain, HAL_STATUS *status) { HAL_STATUS ecode; if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { ecode = HAL_EINVAL; goto bad; } /* * Check if EEPROM is configured to allow this; must * be a proper version and the protection bits must * permit re-writing that segment of the EEPROM. */ if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { ecode = HAL_EEWRITE; goto bad; } ecode = HAL_EIO; /* disallow all writes */ bad: if (status) *status = ecode; return AH_FALSE; } /* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. * */ u_int ar5210GetWirelessModes(struct ath_hal *ah) { /* XXX could enable turbo mode but can't do all rates */ return HAL_MODE_11A; } /* * Called if RfKill is supported (according to EEPROM). Set the interrupt and * GPIO values so the ISR and can disable RF on a switch signal */ void ar5210EnableRfKill(struct ath_hal *ah) { uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); /* * If radio disable switch connection to GPIO bit 0 is enabled * program GPIO interrupt. * If rfkill bit on eeprom is 1, setupeeprommap routine has already * verified that it is a later version of eeprom, it has a place for * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware * connection is present. */ ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity)); } /* * Configure GPIO Output lines */ HAL_BOOL ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) { HALASSERT(gpio < AR_NUM_GPIO); OS_REG_WRITE(ah, AR_GPIOCR, (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) | AR_GPIOCR_OUT1(gpio)); return AH_TRUE; } /* * Configure GPIO Input lines */ HAL_BOOL ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio) { HALASSERT(gpio < AR_NUM_GPIO); OS_REG_WRITE(ah, AR_GPIOCR, (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) | AR_GPIOCR_IN(gpio)); return AH_TRUE; } /* * Once configured for I/O - set output lines */ HAL_BOOL ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) { uint32_t reg; HALASSERT(gpio < AR_NUM_GPIO); reg = OS_REG_READ(ah, AR_GPIODO); reg &= ~(1 << gpio); reg |= (val&1) << gpio; OS_REG_WRITE(ah, AR_GPIODO, reg); return AH_TRUE; } /* * Once configured for I/O - get input lines */ uint32_t ar5210GpioGet(struct ath_hal *ah, uint32_t gpio) { if (gpio < AR_NUM_GPIO) { uint32_t val = OS_REG_READ(ah, AR_GPIODI); val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; return val; } else { return 0xffffffff; } } /* * Set the GPIO 0 Interrupt */ void ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) { uint32_t val = OS_REG_READ(ah, AR_GPIOCR); /* Clear the bits that we will modify. */ val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | AR_GPIOCR_ALL(gpio)); val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA; if (ilevel) val |= AR_GPIOCR_INT_SELH; /* Don't need to change anything for low level interrupt. */ OS_REG_WRITE(ah, AR_GPIOCR, val); /* Change the interrupt mask. */ ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO); } /* * Change the LED blinking pattern to correspond to the connectivity */ void ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state) { uint32_t val; val = OS_REG_READ(ah, AR_PCICFG); switch (state) { case HAL_LED_INIT: val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); break; case HAL_LED_RUN: /* normal blink when connected */ val &= ~AR_PCICFG_LED_PEND; val |= AR_PCICFG_LED_ACT; break; default: val |= AR_PCICFG_LED_PEND; val &= ~AR_PCICFG_LED_ACT; break; } OS_REG_WRITE(ah, AR_PCICFG, val); } /* * Return 1 or 2 for the corresponding antenna that is in use */ u_int ar5210GetDefAntenna(struct ath_hal *ah) { uint32_t val = OS_REG_READ(ah, AR_STA_ID1); return (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1); } void ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna) { uint32_t val = OS_REG_READ(ah, AR_STA_ID1); if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1)) { /* * Antenna change requested, force a toggle of the default. */ OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA); } } HAL_ANT_SETTING ar5210GetAntennaSwitch(struct ath_hal *ah) { return HAL_ANT_VARIABLE; } HAL_BOOL ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) { /* XXX not sure how to fix antenna */ return (settings == HAL_ANT_VARIABLE); } /* * Change association related fields programmed into the hardware. * Writing a valid BSSID to the hardware effectively enables the hardware * to synchronize its TSF to the correct beacons and receive frames coming * from that BSSID. It is called by the SME JOIN operation. */ void ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) { struct ath_hal_5210 *ahp = AH5210(ah); /* XXX save bssid for possible re-use on reset */ OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); ahp->ah_associd = assocId; OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | ((assocId & 0x3fff)<> 19) & 0x1ff; if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); return (OS_REG_READ(ah, AR_TSF_U32) ^ OS_REG_READ(ah, AR_TSF_L32) ^ nf); } /* * Detect if our card is present */ HAL_BOOL ar5210DetectCardPresent(struct ath_hal *ah) { /* * Read the Silicon Revision register and compare that * to what we read at attach time. If the same, we say * a card/device is present. */ return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff)); } /* * Update MIB Counters */ void ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) { stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); } HAL_BOOL ar5210SetSifsTime(struct ath_hal *ah, u_int us) { struct ath_hal_5210 *ahp = AH5210(ah); if (us > ath_hal_mac_usec(ah, 0x7ff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", __func__, us); ahp->ah_sifstime = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS, ath_hal_mac_clks(ah, us)); ahp->ah_sifstime = us; return AH_TRUE; } } u_int ar5210GetSifsTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff; return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5210SetSlotTime(struct ath_hal *ah, u_int us) { struct ath_hal_5210 *ahp = AH5210(ah); if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", __func__, us); ahp->ah_slottime = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us)); ahp->ah_slottime = us; return AH_TRUE; } } u_int ar5210GetSlotTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff; return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5210SetAckTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5210 *ahp = AH5210(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", __func__, us); ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); ahp->ah_acktimeout = us; return AH_TRUE; } } u_int ar5210GetAckTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } u_int ar5210GetAckCTSRate(struct ath_hal *ah) { return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); } HAL_BOOL ar5210SetAckCTSRate(struct ath_hal *ah, u_int high) { struct ath_hal_5210 *ahp = AH5210(ah); if (high) { OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; } else { OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; } return AH_TRUE; } HAL_BOOL ar5210SetCTSTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5210 *ahp = AH5210(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", __func__, us); ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); ahp->ah_ctstimeout = us; return AH_TRUE; } } u_int ar5210GetCTSTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) { /* nothing to do */ return AH_TRUE; } void ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) { } HAL_STATUS ar5210SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t next_start, HAL_QUIET_FLAG flags) { return HAL_OK; } /* * Control Adaptive Noise Immunity Parameters */ HAL_BOOL ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) { return AH_FALSE; } void ar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { } void ar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) { } void ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) { } HAL_STATUS ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result) { switch (type) { case HAL_CAP_CIPHER: /* cipher handled in hardware */ #if 0 return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP); #else return HAL_ENOTSUPP; #endif default: return ath_hal_getcapability(ah, type, capability, result); } } HAL_BOOL ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t setting, HAL_STATUS *status) { switch (type) { case HAL_CAP_DIAG: /* hardware diagnostic support */ /* * NB: could split this up into virtual capabilities, * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly * seems worth the additional complexity. */ #ifdef AH_DEBUG AH_PRIVATE(ah)->ah_diagreg = setting; #else AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ #endif ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg); return AH_TRUE; case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ return AH_FALSE; /* NB: disallow */ default: return ath_hal_setcapability(ah, type, capability, setting, status); } } HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize) { #ifdef AH_PRIVATE_DIAG uint32_t pcicfg; HAL_BOOL ok; switch (request) { case HAL_DIAG_EEPROM: /* XXX */ break; case HAL_DIAG_EEREAD: if (argsize != sizeof(uint16_t)) return AH_FALSE; pcicfg = OS_REG_READ(ah, AR_PCICFG); OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result); OS_REG_WRITE(ah, AR_PCICFG, pcicfg); if (ok) *resultsize = sizeof(uint16_t); return ok; } #endif return ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize); } /* * Return what percentage of the extension channel is busy. * This is always disabled for AR5210 series NICs. */ uint32_t ar5210Get11nExtBusy(struct ath_hal *ah) { return (0); } /* * There's no channel survey support for the AR5210. */ HAL_BOOL ar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) { return (AH_FALSE); } void ar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, uint32_t rxchainmask) { } void ar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { } void ar5210GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { } /* * Update the diagnostic register. * * This merges in the diagnostic register setting with the default * value, which may or may not involve disabling hardware encryption. */ void ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val) { /* Disable all hardware encryption */ val |= AR_DIAG_SW_DIS_CRYPTO; OS_REG_WRITE(ah, AR_DIAG_SW, val); } + +/* + * Get the current NAV value from the hardware. + */ +u_int +ar5210GetNav(struct ath_hal *ah) +{ + uint32_t reg; + + reg = OS_REG_READ(ah, AR_NAV); + return (reg); +} + +/* + * Set the current NAV value to the hardware. + */ +void +ar5210SetNav(struct ath_hal *ah, u_int val) +{ + + OS_REG_WRITE(ah, AR_NAV, val); +} + diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h index 186e69e9cd84..94a60162cbd8 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h @@ -1,331 +1,333 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2006 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #ifndef _ATH_AR5211_H_ #define _ATH_AR5211_H_ #include "ah_eeprom.h" #define AR5211_MAGIC 0x19570405 /* Classes for WME streams */ #define AC_BK 0 #define AC_BE 1 #define AC_VI 2 #define AC_VO 3 /* DCU Transmit Filter macros */ #define CALC_MMR(dcu, idx) \ ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) #define TXBLK_FROM_MMR(mmr) \ (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) #define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) #define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) /* MAC register values */ #define INIT_INTERRUPT_MASK \ ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ AR_IMR_HIUERR ) #define INIT_BEACON_CONTROL \ ( (INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD ) #define INIT_CONFIG_STATUS 0x00000000 #define INIT_RSSI_THR 0x00000700 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ #define INIT_IQCAL_LOG_COUNT_MAX 0xF #define INIT_BCON_CNTRL_REG 0x00000000 #define INIT_BEACON_PERIOD 0xffff #define INIT_TIM_OFFSET 0 #define INIT_BEACON_EN 0 /* this should be set by AP only when it's ready */ #define INIT_RESET_TSF 0 /* * Various fifo fill before Tx start, in 64-byte units * i.e. put the frame in the air while still DMAing */ #define MIN_TX_FIFO_THRESHOLD 0x1 #define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD /* * Gain support. */ typedef struct _gainOptStep { int16_t paramVal[4]; int32_t stepGain; int8_t stepName[16]; } GAIN_OPTIMIZATION_STEP; typedef struct { uint32_t numStepsInLadder; uint32_t defaultStepNum; GAIN_OPTIMIZATION_STEP optStep[10]; } GAIN_OPTIMIZATION_LADDER; typedef struct { uint32_t currStepNum; uint32_t currGain; uint32_t targetGain; uint32_t loTrig; uint32_t hiTrig; uint32_t active; const GAIN_OPTIMIZATION_STEP *currStep; } GAIN_VALUES; enum { RFGAIN_INACTIVE, RFGAIN_READ_REQUESTED, RFGAIN_NEED_CHANGE }; /* * Header Info - general parameters and * values set for each chipset board solution * that are programmed every reset */ struct ath_hal_5211 { struct ath_hal_private ah_priv; /* base class */ GAIN_VALUES ah_gainValues; uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; uint8_t ah_bssid[IEEE80211_ADDR_LEN]; /* * Runtime state. */ uint32_t ah_maskReg; /* copy of AR_IMR */ uint32_t ah_txOkInterruptMask; uint32_t ah_txErrInterruptMask; uint32_t ah_txDescInterruptMask; uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; HAL_ANT_SETTING ah_diversityControl; /* antenna setting */ uint32_t ah_calibrationTime; HAL_BOOL ah_bIQCalibration; int ah_rfgainState; uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ uint32_t ah_beaconInterval; uint32_t ah_rssiThr; /* RSSI_THR settings */ u_int ah_sifstime; /* user-specified sifs time */ u_int ah_slottime; /* user-specified slot time */ u_int ah_acktimeout; /* user-specified ack timeout */ u_int ah_ctstimeout; /* user-specified cts timeout */ /* * RF Silent handling. */ uint32_t ah_gpioSelect; /* GPIO pin to use */ uint32_t ah_polarity; /* polarity to disable RF */ uint32_t ah_gpioBit; /* after init, prev value */ }; #define AH5211(ah) ((struct ath_hal_5211 *)(ah)) struct ath_hal; extern void ar5211Detach(struct ath_hal *); extern HAL_BOOL ar5211Reset(struct ath_hal *, HAL_OPMODE, struct ieee80211_channel *, HAL_BOOL bChannelChange, HAL_RESET_TYPE, HAL_STATUS *); extern HAL_BOOL ar5211PhyDisable(struct ath_hal *); extern HAL_BOOL ar5211Disable(struct ath_hal *); extern HAL_BOOL ar5211ChipReset(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar5211PerCalibration(struct ath_hal *, struct ieee80211_channel *, HAL_BOOL *); extern HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); extern HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *); extern HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *, uint32_t limit); extern HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar5211SetAntennaSwitchInternal(struct ath_hal *, HAL_ANT_SETTING, const struct ieee80211_channel *); extern int16_t ar5211GetNfAdjust(struct ath_hal *, const HAL_CHANNEL_INTERNAL *); extern HAL_BOOL ar5211ResetDma(struct ath_hal *, HAL_OPMODE); extern void ar5211InitializeGainValues(struct ath_hal *); extern HAL_RFGAIN ar5211GetRfgain(struct ath_hal *); extern void ar5211SetPCUConfig(struct ath_hal *); extern HAL_BOOL ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo); extern int ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5211ResetTxQueue(struct ath_hal *ah, u_int q); extern uint32_t ar5211GetTxDP(struct ath_hal *, u_int); extern HAL_BOOL ar5211SetTxDP(struct ath_hal *, u_int, uint32_t txdp); extern HAL_BOOL ar5211UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL); extern HAL_BOOL ar5211StartTxDma(struct ath_hal *, u_int); extern HAL_BOOL ar5211StopTxDma(struct ath_hal *, u_int); extern uint32_t ar5211NumTxPending(struct ath_hal *, u_int qnum); extern HAL_BOOL ar5211IsTxQueueStopped(struct ath_hal *, u_int); extern HAL_BOOL ar5211GetTransmitFilterIndex(struct ath_hal *, uint32_t); extern HAL_BOOL ar5211SetupTxDesc(struct ath_hal *, struct ath_desc *, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsctsDuration, u_int compicvLen, u_int compivLen, u_int comp); extern HAL_BOOL ar5211SetupXTxDesc(struct ath_hal *, struct ath_desc *, u_int txRate1, u_int txRetries1, u_int txRate2, u_int txRetries2, u_int txRate3, u_int txRetries3); extern HAL_BOOL ar5211FillTxDesc(struct ath_hal *, struct ath_desc *, HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0); extern HAL_STATUS ar5211ProcTxDesc(struct ath_hal *, struct ath_desc *, struct ath_tx_status *); extern void ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); extern HAL_BOOL ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries); extern void ar5211SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link); extern void ar5211GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link); extern void ar5211GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr); extern uint32_t ar5211GetRxDP(struct ath_hal *, HAL_RX_QUEUE); extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5211EnableReceive(struct ath_hal *); extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *); extern void ar5211StartPcuReceive(struct ath_hal *, HAL_BOOL); extern void ar5211StopPcuReceive(struct ath_hal *); extern void ar5211SetMulticastFilter(struct ath_hal *, uint32_t filter0, uint32_t filter1); extern HAL_BOOL ar5211ClrMulticastFilterIndex(struct ath_hal *, uint32_t); extern HAL_BOOL ar5211SetMulticastFilterIndex(struct ath_hal *, uint32_t); extern uint32_t ar5211GetRxFilter(struct ath_hal *); extern void ar5211SetRxFilter(struct ath_hal *, uint32_t); extern HAL_BOOL ar5211SetupRxDesc(struct ath_hal *, struct ath_desc *, uint32_t, u_int flags); extern HAL_STATUS ar5211ProcRxDesc(struct ath_hal *, struct ath_desc *, uint32_t, struct ath_desc *, uint64_t, struct ath_rx_status *); extern void ar5211GetMacAddress(struct ath_hal *, uint8_t *); extern HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *); extern void ar5211GetBssIdMask(struct ath_hal *, uint8_t *); extern HAL_BOOL ar5211SetBssIdMask(struct ath_hal *, const uint8_t *); extern HAL_BOOL ar5211EepromRead(struct ath_hal *, u_int off, uint16_t *data); extern HAL_BOOL ar5211EepromWrite(struct ath_hal *, u_int off, uint16_t data); extern HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *, uint16_t, HAL_STATUS *); extern u_int ar5211GetWirelessModes(struct ath_hal *); extern void ar5211EnableRfKill(struct ath_hal *); extern uint32_t ar5211GpioGet(struct ath_hal *, uint32_t gpio); extern void ar5211GpioSetIntr(struct ath_hal *, u_int, uint32_t ilevel); extern HAL_BOOL ar5211GpioCfgOutput(struct ath_hal *, uint32_t gpio, HAL_GPIO_MUX_TYPE); extern HAL_BOOL ar5211GpioCfgInput(struct ath_hal *, uint32_t gpio); extern HAL_BOOL ar5211GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); extern void ar5211SetLedState(struct ath_hal *, HAL_LED_STATE); extern u_int ar5211AntennaGet(struct ath_hal *); extern void ar5211WriteAssocid(struct ath_hal *, const uint8_t *bssid, uint16_t assocId); extern uint64_t ar5211GetTsf64(struct ath_hal *); extern uint32_t ar5211GetTsf32(struct ath_hal *); extern void ar5211ResetTsf(struct ath_hal *); extern uint32_t ar5211GetMaxTurboRate(struct ath_hal *); extern uint32_t ar5211GetRandomSeed(struct ath_hal *); extern HAL_BOOL ar5211DetectCardPresent(struct ath_hal *); extern void ar5211UpdateMibCounters(struct ath_hal *, HAL_MIB_STATS *); extern void ar5211EnableHwEncryption(struct ath_hal *); extern void ar5211DisableHwEncryption(struct ath_hal *); extern HAL_BOOL ar5211SetSlotTime(struct ath_hal *, u_int); extern u_int ar5211GetSlotTime(struct ath_hal *); extern HAL_BOOL ar5211SetAckTimeout(struct ath_hal *, u_int); extern u_int ar5211GetAckTimeout(struct ath_hal *); extern HAL_BOOL ar5211SetAckCTSRate(struct ath_hal *, u_int); extern u_int ar5211GetAckCTSRate(struct ath_hal *); extern HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *, u_int); extern u_int ar5211GetCTSTimeout(struct ath_hal *); extern HAL_BOOL ar5211SetSifsTime(struct ath_hal *, u_int); extern u_int ar5211GetSifsTime(struct ath_hal *); extern HAL_BOOL ar5211SetDecompMask(struct ath_hal *, uint16_t, int); extern void ar5211SetCoverageClass(struct ath_hal *, uint8_t, int); extern HAL_STATUS ar5211SetQuiet(struct ath_hal *, uint32_t, uint32_t, uint32_t, HAL_QUIET_FLAG); extern uint32_t ar5211GetCurRssi(struct ath_hal *); extern u_int ar5211GetDefAntenna(struct ath_hal *); extern void ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna); extern HAL_ANT_SETTING ar5211GetAntennaSwitch(struct ath_hal *); extern HAL_BOOL ar5211SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); extern HAL_STATUS ar5211GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t *); extern HAL_BOOL ar5211SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t, HAL_STATUS *); extern HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); extern uint32_t ar5211Get11nExtBusy(struct ath_hal *); extern HAL_BOOL ar5211GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); extern void ar5211SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t); +extern void ar5211SetNav(struct ath_hal *ah, u_int); +extern u_int ar5211GetNav(struct ath_hal *ah); extern void ar5211EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5211GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); extern u_int ar5211GetKeyCacheSize(struct ath_hal *); extern HAL_BOOL ar5211IsKeyCacheEntryValid(struct ath_hal *, uint16_t); extern HAL_BOOL ar5211ResetKeyCacheEntry(struct ath_hal *, uint16_t entry); extern HAL_BOOL ar5211SetKeyCacheEntry(struct ath_hal *, uint16_t entry, const HAL_KEYVAL *, const uint8_t *mac, int xorKey); extern HAL_BOOL ar5211SetKeyCacheEntryMac(struct ath_hal *, uint16_t, const uint8_t *); extern HAL_BOOL ar5211SetPowerMode(struct ath_hal *, uint32_t powerRequest, int setChip); extern HAL_POWER_MODE ar5211GetPowerMode(struct ath_hal *); extern void ar5211SetBeaconTimers(struct ath_hal *, const HAL_BEACON_TIMERS *); extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t); extern void ar5211SetStaBeaconTimers(struct ath_hal *, const HAL_BEACON_STATE *); extern void ar5211ResetStaBeaconTimers(struct ath_hal *); extern uint64_t ar5211GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *); extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *); extern HAL_INT ar5211GetInterrupts(struct ath_hal *); extern HAL_INT ar5211SetInterrupts(struct ath_hal *, HAL_INT ints); extern const HAL_RATE_TABLE *ar5211GetRateTable(struct ath_hal *, u_int mode); extern HAL_BOOL ar5211AniControl(struct ath_hal *, HAL_ANI_CMD, int ); extern void ar5211RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); extern void ar5211AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5211MibEvent(struct ath_hal *, const HAL_NODE_STATS *); #endif /* _ATH_AR5211_H_ */ diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c index 1914cc3ea4cf..6253e7b8c9c5 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c @@ -1,556 +1,558 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2006 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ar5211/ar5211.h" #include "ar5211/ar5211reg.h" #include "ar5211/ar5211phy.h" #include "ah_eeprom_v3.h" static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, uint16_t flags, uint16_t *low, uint16_t *high); static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan); static void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off); static void ar5211DisablePCIE(struct ath_hal *ah); static const struct ath_hal_private ar5211hal = {{ .ah_magic = AR5211_MAGIC, .ah_getRateTable = ar5211GetRateTable, .ah_detach = ar5211Detach, /* Reset Functions */ .ah_reset = ar5211Reset, .ah_phyDisable = ar5211PhyDisable, .ah_disable = ar5211Disable, .ah_configPCIE = ar5211ConfigPCIE, .ah_disablePCIE = ar5211DisablePCIE, .ah_setPCUConfig = ar5211SetPCUConfig, .ah_perCalibration = ar5211PerCalibration, .ah_perCalibrationN = ar5211PerCalibrationN, .ah_resetCalValid = ar5211ResetCalValid, .ah_setTxPowerLimit = ar5211SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, /* Transmit functions */ .ah_updateTxTrigLevel = ar5211UpdateTxTrigLevel, .ah_setupTxQueue = ar5211SetupTxQueue, .ah_setTxQueueProps = ar5211SetTxQueueProps, .ah_getTxQueueProps = ar5211GetTxQueueProps, .ah_releaseTxQueue = ar5211ReleaseTxQueue, .ah_resetTxQueue = ar5211ResetTxQueue, .ah_getTxDP = ar5211GetTxDP, .ah_setTxDP = ar5211SetTxDP, .ah_numTxPending = ar5211NumTxPending, .ah_startTxDma = ar5211StartTxDma, .ah_stopTxDma = ar5211StopTxDma, .ah_setupTxDesc = ar5211SetupTxDesc, .ah_setupXTxDesc = ar5211SetupXTxDesc, .ah_fillTxDesc = ar5211FillTxDesc, .ah_procTxDesc = ar5211ProcTxDesc, .ah_getTxIntrQueue = ar5211GetTxIntrQueue, .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, .ah_getTxCompletionRates = ar5211GetTxCompletionRates, .ah_setTxDescLink = ar5211SetTxDescLink, .ah_getTxDescLink = ar5211GetTxDescLink, .ah_getTxDescLinkPtr = ar5211GetTxDescLinkPtr, /* RX Functions */ .ah_getRxDP = ar5211GetRxDP, .ah_setRxDP = ar5211SetRxDP, .ah_enableReceive = ar5211EnableReceive, .ah_stopDmaReceive = ar5211StopDmaReceive, .ah_startPcuReceive = ar5211StartPcuReceive, .ah_stopPcuReceive = ar5211StopPcuReceive, .ah_setMulticastFilter = ar5211SetMulticastFilter, .ah_setMulticastFilterIndex = ar5211SetMulticastFilterIndex, .ah_clrMulticastFilterIndex = ar5211ClrMulticastFilterIndex, .ah_getRxFilter = ar5211GetRxFilter, .ah_setRxFilter = ar5211SetRxFilter, .ah_setupRxDesc = ar5211SetupRxDesc, .ah_procRxDesc = ar5211ProcRxDesc, .ah_rxMonitor = ar5211RxMonitor, .ah_aniPoll = ar5211AniPoll, .ah_procMibEvent = ar5211MibEvent, /* Misc Functions */ .ah_getCapability = ar5211GetCapability, .ah_setCapability = ar5211SetCapability, .ah_getDiagState = ar5211GetDiagState, .ah_getMacAddress = ar5211GetMacAddress, .ah_setMacAddress = ar5211SetMacAddress, .ah_getBssIdMask = ar5211GetBssIdMask, .ah_setBssIdMask = ar5211SetBssIdMask, .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, .ah_setLedState = ar5211SetLedState, .ah_writeAssocid = ar5211WriteAssocid, .ah_gpioCfgInput = ar5211GpioCfgInput, .ah_gpioCfgOutput = ar5211GpioCfgOutput, .ah_gpioGet = ar5211GpioGet, .ah_gpioSet = ar5211GpioSet, .ah_gpioSetIntr = ar5211GpioSetIntr, .ah_getTsf32 = ar5211GetTsf32, .ah_getTsf64 = ar5211GetTsf64, .ah_resetTsf = ar5211ResetTsf, .ah_detectCardPresent = ar5211DetectCardPresent, .ah_updateMibCounters = ar5211UpdateMibCounters, .ah_getRfGain = ar5211GetRfgain, .ah_getDefAntenna = ar5211GetDefAntenna, .ah_setDefAntenna = ar5211SetDefAntenna, .ah_getAntennaSwitch = ar5211GetAntennaSwitch, .ah_setAntennaSwitch = ar5211SetAntennaSwitch, .ah_setSifsTime = ar5211SetSifsTime, .ah_getSifsTime = ar5211GetSifsTime, .ah_setSlotTime = ar5211SetSlotTime, .ah_getSlotTime = ar5211GetSlotTime, .ah_setAckTimeout = ar5211SetAckTimeout, .ah_getAckTimeout = ar5211GetAckTimeout, .ah_setAckCTSRate = ar5211SetAckCTSRate, .ah_getAckCTSRate = ar5211GetAckCTSRate, .ah_setCTSTimeout = ar5211SetCTSTimeout, .ah_getCTSTimeout = ar5211GetCTSTimeout, .ah_setDecompMask = ar5211SetDecompMask, .ah_setCoverageClass = ar5211SetCoverageClass, .ah_setQuiet = ar5211SetQuiet, .ah_get11nExtBusy = ar5211Get11nExtBusy, .ah_getMibCycleCounts = ar5211GetMibCycleCounts, .ah_setChainMasks = ar5211SetChainMasks, .ah_enableDfs = ar5211EnableDfs, .ah_getDfsThresh = ar5211GetDfsThresh, /* XXX procRadarEvent */ /* XXX isFastClockEnabled */ + .ah_setNav = ar5211SetNav, + .ah_getNav = ar5211GetNav, /* Key Cache Functions */ .ah_getKeyCacheSize = ar5211GetKeyCacheSize, .ah_resetKeyCacheEntry = ar5211ResetKeyCacheEntry, .ah_isKeyCacheEntryValid = ar5211IsKeyCacheEntryValid, .ah_setKeyCacheEntry = ar5211SetKeyCacheEntry, .ah_setKeyCacheEntryMac = ar5211SetKeyCacheEntryMac, /* Power Management Functions */ .ah_setPowerMode = ar5211SetPowerMode, .ah_getPowerMode = ar5211GetPowerMode, /* Beacon Functions */ .ah_setBeaconTimers = ar5211SetBeaconTimers, .ah_beaconInit = ar5211BeaconInit, .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, .ah_getNextTBTT = ar5211GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5211IsInterruptPending, .ah_getPendingInterrupts = ar5211GetPendingInterrupts, .ah_getInterrupts = ar5211GetInterrupts, .ah_setInterrupts = ar5211SetInterrupts }, .ah_getChannelEdges = ar5211GetChannelEdges, .ah_getWirelessModes = ar5211GetWirelessModes, .ah_eepromRead = ar5211EepromRead, #ifdef AH_SUPPORT_WRITE_EEPROM .ah_eepromWrite = ar5211EepromWrite, #endif .ah_getChipPowerLimits = ar5211GetChipPowerLimits, }; static HAL_BOOL ar5211ChipTest(struct ath_hal *); static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah); /* * Return the revsion id for the radio chip. This * fetched via the PHY. */ static uint32_t ar5211GetRadioRev(struct ath_hal *ah) { uint32_t val; int i; OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); for (i = 0; i < 8; i++) OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff; val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); return ath_hal_reverseBits(val, 8); } /* * Attach for an AR5211 part. */ static struct ath_hal * ar5211Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5211 *ahp; struct ath_hal *ah; uint32_t val; uint16_t eeval; HAL_STATUS ecode; HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); if (ahp == AH_NULL) { HALDEBUG(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; } ah = &ahp->ah_priv.h; /* set initial values */ OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private)); ah->ah_sc = sc; ah->ah_st = st; ah->ah_sh = sh; ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ahp->ah_diversityControl = HAL_ANT_VARIABLE; ahp->ah_staId1Defaults = 0; ahp->ah_rssiThr = INIT_RSSI_THR; ahp->ah_sifstime = (u_int) -1; ahp->ah_slottime = (u_int) -1; ahp->ah_acktimeout = (u_int) -1; ahp->ah_ctstimeout = (u_int) -1; if (!ar5211ChipReset(ah, AH_NULL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; } if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) { /* set it back to OFDM mode to be able to read analog rev id */ OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM); OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); OS_DELAY(1000); } /* Read Revisions from Chips */ val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M; if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 || AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Mac Chip Rev 0x%x is not supported by this driver\n", __func__, AH_PRIVATE(ah)->ah_macVersion); ecode = HAL_ENOTSUPP; goto bad; } AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); if (!ar5211ChipTest(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", __func__); ecode = HAL_ESELFTEST; goto bad; } /* Set correct Baseband to analog shift setting to access analog chips. */ if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); } else { OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); } OS_DELAY(2000); /* Read Radio Chip Rev Extract */ AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah); if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 5G Radio Chip Rev 0x%02X is not supported by this " "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); ecode = HAL_ENOTSUPP; goto bad; } val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >> AR_PCICFG_EEPROM_SIZE_S; if (val != AR_PCICFG_EEPROM_SIZE_16K) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size " "%u (0x%x) found\n", __func__, val, val); ecode = HAL_EESIZE; goto bad; } ecode = ath_hal_legacyEepromAttach(ah); if (ecode != HAL_OK) { goto bad; } /* If Bmode and AR5211, verify 2.4 analog exists */ if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU && ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { /* Set correct Baseband to analog shift setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007); OS_DELAY(2000); AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah); /* Set baseband for 5GHz chip */ OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); OS_DELAY(2000); if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 2G Radio Chip Rev 0x%x is not supported by " "this driver\n", __func__, AH_PRIVATE(ah)->ah_analog2GhzRev); ecode = HAL_ENOTSUPP; goto bad; } } else { ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE); } ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read regulatory domain from EEPROM\n", __func__); goto bad; } AH_PRIVATE(ah)->ah_currentRD = eeval; AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; /* * Got everything we need now to setup the capabilities. */ (void) ar5211FillCapabilityInfo(ah); /* Initialize gain ladder thermal calibration structure */ ar5211InitializeGainValues(ah); ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error getting mac address from EEPROM\n", __func__); goto bad; } HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); return ah; bad: if (ahp) ar5211Detach((struct ath_hal *) ahp); if (status) *status = ecode; return AH_NULL; #undef N } void ar5211Detach(struct ath_hal *ah) { HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5211_MAGIC); ath_hal_eepromDetach(ah); ath_hal_free(ah); } static HAL_BOOL ar5211ChipTest(struct ath_hal *ah) { uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; uint32_t regHold[2]; uint32_t patternData[4] = { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; int i, j; /* Test PHY & MAC registers */ for (i = 0; i < 2; i++) { uint32_t addr = regAddr[i]; uint32_t wrData, rdData; regHold[i] = OS_REG_READ(ah, addr); for (j = 0; j < 0x100; j++) { wrData = (j << 16) | j; OS_REG_WRITE(ah, addr, wrData); rdData = OS_REG_READ(ah, addr); if (rdData != wrData) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wrData, rdData); return AH_FALSE; } } for (j = 0; j < 4; j++) { wrData = patternData[j]; OS_REG_WRITE(ah, addr, wrData); rdData = OS_REG_READ(ah, addr); if (wrData != rdData) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wrData, rdData); return AH_FALSE; } } OS_REG_WRITE(ah, regAddr[i], regHold[i]); } OS_DELAY(100); return AH_TRUE; } /* * Store the channel edges for the requested operational mode */ static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, uint16_t flags, uint16_t *low, uint16_t *high) { if (flags & IEEE80211_CHAN_5GHZ) { *low = 4920; *high = 6100; return AH_TRUE; } if (flags & IEEE80211_CHAN_2GHZ && ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { *low = 2312; *high = 2732; return AH_TRUE; } return AH_FALSE; } static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) { /* XXX fill in, this is just a placeholder */ HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: no min/max power for %u/0x%x\n", __func__, chan->ic_freq, chan->ic_flags); chan->ic_maxpower = MAX_RATE_POWER; chan->ic_minpower = 0; return AH_TRUE; } static void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) { } static void ar5211DisablePCIE(struct ath_hal *ah) { } /* * Fill all software cached or static hardware state information. */ static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah) { struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; /* Construct wireless mode from EEPROM */ pCap->halWirelessModes = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { pCap->halWirelessModes |= HAL_MODE_11A; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) pCap->halWirelessModes |= HAL_MODE_TURBO; } if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) pCap->halWirelessModes |= HAL_MODE_11B; pCap->halLow2GhzChan = 2312; pCap->halHigh2GhzChan = 2732; pCap->halLow5GhzChan = 4920; pCap->halHigh5GhzChan = 6100; pCap->halChanSpreadSupport = AH_TRUE; pCap->halSleepAfterBeaconBroken = AH_TRUE; pCap->halPSPollBroken = AH_TRUE; pCap->halVEOLSupport = AH_TRUE; pCap->halNumMRRetries = 1; /* No hardware MRR support */ pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ pCap->halTotalQueues = HAL_NUM_TX_QUEUES; pCap->halKeyCacheSize = 128; /* XXX not needed */ pCap->halChanHalfRate = AH_FALSE; pCap->halChanQuarterRate = AH_FALSE; /* * RSSI uses the combined field; some 11n NICs may use * the control chain RSSI. */ pCap->halUseCombinedRadarRssi = AH_TRUE; if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { /* NB: enabled by default */ ahpriv->ah_rfkillEnabled = AH_TRUE; pCap->halRfSilentSupport = AH_TRUE; } pCap->halRxTstampPrecision = 13; pCap->halTxTstampPrecision = 16; pCap->halIntrMask = HAL_INT_COMMON | HAL_INT_RX | HAL_INT_TX | HAL_INT_FATAL | HAL_INT_BNR | HAL_INT_TIM ; pCap->hal4kbSplitTransSupport = AH_TRUE; pCap->halHasRxSelfLinkedTail = AH_TRUE; /* XXX might be ok w/ some chip revs */ ahpriv->ah_rxornIsFatal = AH_TRUE; return AH_TRUE; } static const char* ar5211Probe(uint16_t vendorid, uint16_t devid) { if (vendorid == ATHEROS_VENDOR_ID) { if (devid == AR5211_DEVID || devid == AR5311_DEVID || devid == AR5211_DEFAULT) return "Atheros 5211"; if (devid == AR5211_FPGA11B) return "Atheros 5211 (FPGA)"; } return AH_NULL; } AH_CHIP(AR5211, ar5211Probe, ar5211Attach); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c index ea1327b11a6a..5bdae89a3055 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c @@ -1,735 +1,758 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2006 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ar5211/ar5211.h" #include "ar5211/ar5211reg.h" #include "ar5211/ar5211phy.h" #include "ah_eeprom_v3.h" #define AR_NUM_GPIO 6 /* 6 GPIO bits */ #define AR_GPIOD_MASK 0x2f /* 6-bit mask */ void ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac) { struct ath_hal_5211 *ahp = AH5211(ah); OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); } HAL_BOOL ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac) { struct ath_hal_5211 *ahp = AH5211(ah); OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); return AH_TRUE; } void ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask) { static const uint8_t ones[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); } HAL_BOOL ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) { return AH_FALSE; } /* * Read 16 bits of data from the specified EEPROM offset. */ HAL_BOOL ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) { OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); if (!ath_hal_wait(ah, AR_EEPROM_STS, AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, AR_EEPROM_STS_READ_COMPLETE)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", __func__, off); return AH_FALSE; } *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; return AH_TRUE; } #ifdef AH_SUPPORT_WRITE_EEPROM /* * Write 16 bits of data to the specified EEPROM offset. */ HAL_BOOL ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) { return AH_FALSE; } #endif /* AH_SUPPORT_WRITE_EEPROM */ /* * Attempt to change the cards operating regulatory domain to the given value */ HAL_BOOL ar5211SetRegulatoryDomain(struct ath_hal *ah, uint16_t regDomain, HAL_STATUS *status) { HAL_STATUS ecode; if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { ecode = HAL_EINVAL; goto bad; } /* * Check if EEPROM is configured to allow this; must * be a proper version and the protection bits must * permit re-writing that segment of the EEPROM. */ if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { ecode = HAL_EEWRITE; goto bad; } #ifdef AH_SUPPORT_WRITE_REGDOMAIN if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: set regulatory domain to %u (0x%x)\n", __func__, regDomain, regDomain); AH_PRIVATE(ah)->ah_currentRD = regDomain; return AH_TRUE; } #endif ecode = HAL_EIO; bad: if (status) *status = ecode; return AH_FALSE; } /* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. * */ u_int ar5211GetWirelessModes(struct ath_hal *ah) { u_int mode = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { mode = HAL_MODE_11A; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) mode |= HAL_MODE_TURBO | HAL_MODE_108A; } if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) mode |= HAL_MODE_11B; return mode; } #if 0 HAL_BOOL ar5211GetTurboDisable(struct ath_hal *ah) { return (AH5211(ah)->ah_turboDisable != 0); } #endif /* * Called if RfKill is supported (according to EEPROM). Set the interrupt and * GPIO values so the ISR and can disable RF on a switch signal */ void ar5211EnableRfKill(struct ath_hal *ah) { uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); /* * Configure the desired GPIO port for input * and enable baseband rf silence. */ ar5211GpioCfgInput(ah, select); OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000); /* * If radio disable switch connection to GPIO bit x is enabled * program GPIO interrupt. * If rfkill bit on eeprom is 1, setupeeprommap routine has already * verified that it is a later version of eeprom, it has a place for * rfkill bit and it is set to 1, indicating that GPIO bit x hardware * connection is present. */ ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity)); } /* * Configure GPIO Output lines */ HAL_BOOL ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) { uint32_t reg; HALASSERT(gpio < AR_NUM_GPIO); reg = OS_REG_READ(ah, AR_GPIOCR); reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT); OS_REG_WRITE(ah, AR_GPIOCR, reg); return AH_TRUE; } /* * Configure GPIO Input lines */ HAL_BOOL ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio) { uint32_t reg; HALASSERT(gpio < AR_NUM_GPIO); reg = OS_REG_READ(ah, AR_GPIOCR); reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT); OS_REG_WRITE(ah, AR_GPIOCR, reg); return AH_TRUE; } /* * Once configured for I/O - set output lines */ HAL_BOOL ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) { uint32_t reg; HALASSERT(gpio < AR_NUM_GPIO); reg = OS_REG_READ(ah, AR_GPIODO); reg &= ~(1 << gpio); reg |= (val&1) << gpio; OS_REG_WRITE(ah, AR_GPIODO, reg); return AH_TRUE; } /* * Once configured for I/O - get input lines */ uint32_t ar5211GpioGet(struct ath_hal *ah, uint32_t gpio) { if (gpio < AR_NUM_GPIO) { uint32_t val = OS_REG_READ(ah, AR_GPIODI); val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; return val; } else { return 0xffffffff; } } /* * Set the GPIO 0 Interrupt (gpio is ignored) */ void ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) { uint32_t val = OS_REG_READ(ah, AR_GPIOCR); /* Clear the bits that we will modify. */ val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | AR_GPIOCR_0_CR_A); val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA; if (ilevel) val |= AR_GPIOCR_INT_SELH; /* Don't need to change anything for low level interrupt. */ OS_REG_WRITE(ah, AR_GPIOCR, val); /* Change the interrupt mask. */ ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO); } /* * Change the LED blinking pattern to correspond to the connectivity */ void ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state) { static const uint32_t ledbits[8] = { AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */ AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */ AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */ AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/ AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */ AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, }; OS_REG_WRITE(ah, AR_PCICFG, (OS_REG_READ(ah, AR_PCICFG) &~ (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE)) | ledbits[state & 0x7] ); } /* * Change association related fields programmed into the hardware. * Writing a valid BSSID to the hardware effectively enables the hardware * to synchronize its TSF to the correct beacons and receive frames coming * from that BSSID. It is called by the SME JOIN operation. */ void ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) { struct ath_hal_5211 *ahp = AH5211(ah); /* XXX save bssid for possible re-use on reset */ OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | ((assocId & 0x3fff)<> 19) & 0x1ff; if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); return (OS_REG_READ(ah, AR_TSF_U32) ^ OS_REG_READ(ah, AR_TSF_L32) ^ nf); } /* * Detect if our card is present */ HAL_BOOL ar5211DetectCardPresent(struct ath_hal *ah) { uint16_t macVersion, macRev; uint32_t v; /* * Read the Silicon Revision register and compare that * to what we read at attach time. If the same, we say * a card/device is present. */ v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; macVersion = v >> AR_SREV_ID_S; macRev = v & AR_SREV_REVISION_M; return (AH_PRIVATE(ah)->ah_macVersion == macVersion && AH_PRIVATE(ah)->ah_macRev == macRev); } /* * Update MIB Counters */ void ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) { stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); } HAL_BOOL ar5211SetSifsTime(struct ath_hal *ah, u_int us) { struct ath_hal_5211 *ahp = AH5211(ah); if (us > ath_hal_mac_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", __func__, us); ahp->ah_sifstime = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); ahp->ah_slottime = us; return AH_TRUE; } } u_int ar5211GetSifsTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5211SetSlotTime(struct ath_hal *ah, u_int us) { struct ath_hal_5211 *ahp = AH5211(ah); if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", __func__, us); ahp->ah_slottime = us; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); ahp->ah_slottime = us; return AH_TRUE; } } u_int ar5211GetSlotTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5211SetAckTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5211 *ahp = AH5211(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", __func__, us); ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); ahp->ah_acktimeout = us; return AH_TRUE; } } u_int ar5211GetAckTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } u_int ar5211GetAckCTSRate(struct ath_hal *ah) { return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); } HAL_BOOL ar5211SetAckCTSRate(struct ath_hal *ah, u_int high) { struct ath_hal_5211 *ahp = AH5211(ah); if (high) { OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; } else { OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; } return AH_TRUE; } HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5211 *ahp = AH5211(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", __func__, us); ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); ahp->ah_ctstimeout = us; return AH_TRUE; } } u_int ar5211GetCTSTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) { /* nothing to do */ return AH_TRUE; } void ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) { } HAL_STATUS ar5211SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t next_start, HAL_QUIET_FLAG flags) { return HAL_OK; } /* * Control Adaptive Noise Immunity Parameters */ HAL_BOOL ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) { return AH_FALSE; } void ar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) { } void ar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { } void ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) { } /* * Get the rssi of frame curently being received. */ uint32_t ar5211GetCurRssi(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); } u_int ar5211GetDefAntenna(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); } void ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna) { OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); } HAL_ANT_SETTING ar5211GetAntennaSwitch(struct ath_hal *ah) { return AH5211(ah)->ah_diversityControl; } HAL_BOOL ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) { const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; if (chan == AH_NULL) { AH5211(ah)->ah_diversityControl = settings; return AH_TRUE; } return ar5211SetAntennaSwitchInternal(ah, settings, chan); } HAL_STATUS ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result) { switch (type) { case HAL_CAP_CIPHER: /* cipher handled in hardware */ switch (capability) { case HAL_CIPHER_AES_OCB: case HAL_CIPHER_WEP: case HAL_CIPHER_CLR: return HAL_OK; default: return HAL_ENOTSUPP; } default: return ath_hal_getcapability(ah, type, capability, result); } } HAL_BOOL ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t setting, HAL_STATUS *status) { switch (type) { case HAL_CAP_DIAG: /* hardware diagnostic support */ /* * NB: could split this up into virtual capabilities, * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly * seems worth the additional complexity. */ #ifdef AH_DEBUG AH_PRIVATE(ah)->ah_diagreg = setting; #else AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ #endif OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); return AH_TRUE; default: return ath_hal_setcapability(ah, type, capability, setting, status); } } HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize) { struct ath_hal_5211 *ahp = AH5211(ah); (void) ahp; if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) return AH_TRUE; switch (request) { case HAL_DIAG_EEPROM: return ath_hal_eepromDiag(ah, request, args, argsize, result, resultsize); case HAL_DIAG_RFGAIN: *result = &ahp->ah_gainValues; *resultsize = sizeof(GAIN_VALUES); return AH_TRUE; case HAL_DIAG_RFGAIN_CURSTEP: *result = __DECONST(void *, ahp->ah_gainValues.currStep); *resultsize = (*result == AH_NULL) ? 0 : sizeof(GAIN_OPTIMIZATION_STEP); return AH_TRUE; } return AH_FALSE; } /* * Return what percentage of the extension channel is busy. * This is always disabled for AR5211 series NICs. */ uint32_t ar5211Get11nExtBusy(struct ath_hal *ah) { return (0); } /* * There's no channel survey support for the AR5211. */ HAL_BOOL ar5211GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) { return (AH_FALSE); } void ar5211SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, uint32_t rxchainmask) { } void ar5211EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { } void ar5211GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { } + +/* + * Get the current NAV value from the hardware. + */ +u_int +ar5211GetNav(struct ath_hal *ah) +{ + uint32_t reg; + + reg = OS_REG_READ(ah, AR_NAV); + return (reg); +} + +/* + * Set the current NAV value to the hardware. + */ +void +ar5211SetNav(struct ath_hal *ah, u_int val) +{ + + OS_REG_WRITE(ah, AR_NAV, val); +} + diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h index f80f88c5df85..3a08c1911a1c 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h @@ -1,661 +1,663 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #ifndef _ATH_AR5212_H_ #define _ATH_AR5212_H_ #include "ah_eeprom.h" #define AR5212_MAGIC 0x19541014 /* DCU Transmit Filter macros */ #define CALC_MMR(dcu, idx) \ ( (4 * dcu) + (idx < 32 ? 0 : (idx < 64 ? 1 : (idx < 96 ? 2 : 3))) ) #define TXBLK_FROM_MMR(mmr) \ (AR_D_TXBLK_BASE + ((mmr & 0x1f) << 6) + ((mmr & 0x20) >> 3)) #define CALC_TXBLK_ADDR(dcu, idx) (TXBLK_FROM_MMR(CALC_MMR(dcu, idx))) #define CALC_TXBLK_VALUE(idx) (1 << (idx & 0x1f)) /* MAC register values */ #define INIT_INTERRUPT_MASK \ ( AR_IMR_TXERR | AR_IMR_TXOK | AR_IMR_RXORN | \ AR_IMR_RXERR | AR_IMR_RXOK | AR_IMR_TXURN | \ AR_IMR_HIUERR ) #define INIT_BEACON_CONTROL \ ((INIT_RESET_TSF << 24) | (INIT_BEACON_EN << 23) | \ (INIT_TIM_OFFSET << 16) | INIT_BEACON_PERIOD) #define INIT_CONFIG_STATUS 0x00000000 #define INIT_RSSI_THR 0x00000781 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ #define INIT_IQCAL_LOG_COUNT_MAX 0xF #define INIT_BCON_CNTRL_REG 0x00000000 #define INIT_USEC 40 #define HALF_RATE_USEC 19 /* ((40 / 2) - 1 ) */ #define QUARTER_RATE_USEC 9 /* ((40 / 4) - 1 ) */ #define RX_NON_FULL_RATE_LATENCY 63 #define TX_HALF_RATE_LATENCY 108 #define TX_QUARTER_RATE_LATENCY 216 #define IFS_SLOT_FULL_RATE 0x168 /* 9 us half, 40 MHz core clock (9*40) */ #define IFS_SLOT_HALF_RATE 0x104 /* 13 us half, 20 MHz core clock (13*20) */ #define IFS_SLOT_QUARTER_RATE 0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */ #define IFS_EIFS_FULL_RATE 0xE60 /* (74 + (2 * 9)) * 40MHz core clock */ #define IFS_EIFS_HALF_RATE 0xDAC /* (149 + (2 * 13)) * 20MHz core clock */ #define IFS_EIFS_QUARTER_RATE 0xD48 /* (298 + (2 * 21)) * 10MHz core clock */ #define ACK_CTS_TIMEOUT_11A 0x3E8 /* ACK timeout in 11a core clocks */ /* Tx frame start to tx data start delay */ #define TX_FRAME_D_START_HALF_RATE 0xc #define TX_FRAME_D_START_QUARTER_RATE 0xd /* * Various fifo fill before Tx start, in 64-byte units * i.e. put the frame in the air while still DMAing */ #define MIN_TX_FIFO_THRESHOLD 0x1 #define MAX_TX_FIFO_THRESHOLD ((IEEE80211_MAX_LEN / 64) + 1) #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD #define HAL_DECOMP_MASK_SIZE 128 /* 1 byte per key */ /* * Gain support. */ #define NUM_CORNER_FIX_BITS 4 #define NUM_CORNER_FIX_BITS_5112 7 #define DYN_ADJ_UP_MARGIN 15 #define DYN_ADJ_LO_MARGIN 20 #define PHY_PROBE_CCK_CORRECTION 5 #define CCK_OFDM_GAIN_DELTA 15 enum GAIN_PARAMS { GP_TXCLIP, GP_PD90, GP_PD84, GP_GSEL, }; enum GAIN_PARAMS_5112 { GP_MIXGAIN_OVR, GP_PWD_138, GP_PWD_137, GP_PWD_136, GP_PWD_132, GP_PWD_131, GP_PWD_130, }; typedef struct _gainOptStep { int16_t paramVal[NUM_CORNER_FIX_BITS_5112]; int32_t stepGain; int8_t stepName[16]; } GAIN_OPTIMIZATION_STEP; typedef struct { uint32_t numStepsInLadder; uint32_t defaultStepNum; GAIN_OPTIMIZATION_STEP optStep[10]; } GAIN_OPTIMIZATION_LADDER; typedef struct { uint32_t currStepNum; uint32_t currGain; uint32_t targetGain; uint32_t loTrig; uint32_t hiTrig; uint32_t active; const GAIN_OPTIMIZATION_STEP *currStep; } GAIN_VALUES; /* RF HAL structures */ typedef struct RfHalFuncs { void *priv; /* private state */ void (*rfDetach)(struct ath_hal *ah); void (*writeRegs)(struct ath_hal *, u_int modeIndex, u_int freqIndex, int regWrites); uint32_t *(*getRfBank)(struct ath_hal *ah, int bank); HAL_BOOL (*setChannel)(struct ath_hal *, const struct ieee80211_channel *); HAL_BOOL (*setRfRegs)(struct ath_hal *, const struct ieee80211_channel *, uint16_t modesIndex, uint16_t *rfXpdGain); HAL_BOOL (*setPowerTable)(struct ath_hal *ah, int16_t *minPower, int16_t *maxPower, const struct ieee80211_channel *, uint16_t *rfXpdGain); HAL_BOOL (*getChannelMaxMinPower)(struct ath_hal *ah, const struct ieee80211_channel *, int16_t *maxPow, int16_t *minPow); int16_t (*getNfAdjust)(struct ath_hal *, const HAL_CHANNEL_INTERNAL*); } RF_HAL_FUNCS; struct ar5212AniParams { int maxNoiseImmunityLevel; /* [0..4] */ int totalSizeDesired[5]; int coarseHigh[5]; int coarseLow[5]; int firpwr[5]; int maxSpurImmunityLevel; /* [0..7] */ int cycPwrThr1[8]; int maxFirstepLevel; /* [0..2] */ int firstep[3]; uint32_t ofdmTrigHigh; uint32_t ofdmTrigLow; uint32_t cckTrigHigh; uint32_t cckTrigLow; int32_t rssiThrLow; uint32_t rssiThrHigh; int period; /* update listen period */ /* NB: intentionally ordered so data exported to user space is first */ uint32_t ofdmPhyErrBase; /* Base value for ofdm err counter */ uint32_t cckPhyErrBase; /* Base value for cck err counters */ }; /* * Per-channel ANI state private to the driver. */ struct ar5212AniState { uint8_t noiseImmunityLevel; uint8_t spurImmunityLevel; uint8_t firstepLevel; uint8_t ofdmWeakSigDetectOff; uint8_t cckWeakSigThreshold; uint32_t listenTime; /* NB: intentionally ordered so data exported to user space is first */ uint32_t txFrameCount; /* Last txFrameCount */ uint32_t rxFrameCount; /* Last rx Frame count */ uint32_t cycleCount; /* Last cycleCount (to detect wrap-around) */ uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ uint32_t cckPhyErrCount; /* CCK err count since last reset */ const struct ar5212AniParams *params; }; #define HAL_ANI_ENA 0x00000001 /* ANI operation enabled */ #define HAL_RSSI_ANI_ENA 0x00000002 /* rssi-based processing ena'd*/ #if 0 struct ar5212Stats { uint32_t ast_ani_niup; /* ANI increased noise immunity */ uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ uint32_t ast_ani_spurup; /* ANI increased spur immunity */ uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ uint32_t ast_ani_stepup; /* ANI increased first step level */ uint32_t ast_ani_stepdown;/* ANI decreased first step level */ uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ }; #endif /* * NF Cal history buffer */ #define AR5212_CCA_MAX_GOOD_VALUE -95 #define AR5212_CCA_MAX_HIGH_VALUE -62 #define AR5212_CCA_MIN_BAD_VALUE -125 #define AR512_NF_CAL_HIST_MAX 5 struct ar5212NfCalHist { int16_t nfCalBuffer[AR512_NF_CAL_HIST_MAX]; int16_t privNF; uint8_t currIndex; uint8_t first_run; uint8_t invalidNFcount; }; struct ath_hal_5212 { struct ath_hal_private ah_priv; /* base class */ /* * Per-chip common Initialization data. * NB: RF backends have their own ini data. */ HAL_INI_ARRAY ah_ini_modes; HAL_INI_ARRAY ah_ini_common; GAIN_VALUES ah_gainValues; uint8_t ah_macaddr[IEEE80211_ADDR_LEN]; uint8_t ah_bssid[IEEE80211_ADDR_LEN]; uint8_t ah_bssidmask[IEEE80211_ADDR_LEN]; uint16_t ah_assocId; /* * Runtime state. */ uint32_t ah_maskReg; /* copy of AR_IMR */ HAL_ANI_STATS ah_stats; /* various statistics */ RF_HAL_FUNCS *ah_rfHal; uint32_t ah_txDescMask; /* mask for TXDESC */ uint32_t ah_txOkInterruptMask; uint32_t ah_txErrInterruptMask; uint32_t ah_txDescInterruptMask; uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; uint32_t ah_intrTxqs; /* tx q interrupt state */ /* decomp mask array */ uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; HAL_ANT_SETTING ah_antControl; /* antenna setting */ HAL_BOOL ah_diversity; /* fast diversity setting */ enum { IQ_CAL_INACTIVE, IQ_CAL_RUNNING, IQ_CAL_DONE } ah_bIQCalibration; /* IQ calibrate state */ HAL_RFGAIN ah_rfgainState; /* RF gain calibrartion state */ uint32_t ah_tx6PowerInHalfDbm; /* power output for 6Mb tx */ uint32_t ah_staId1Defaults; /* STA_ID1 default settings */ uint32_t ah_miscMode; /* MISC_MODE settings */ uint32_t ah_rssiThr; /* RSSI_THR settings */ HAL_BOOL ah_cwCalRequire; /* for ap51 */ HAL_BOOL ah_tpcEnabled; /* per-packet tpc enabled */ HAL_BOOL ah_phyPowerOn; /* PHY power state */ HAL_BOOL ah_isHb63; /* cached HB63 check */ uint32_t ah_macTPC; /* tpc register */ uint32_t ah_beaconInterval; /* XXX */ enum { AUTO_32KHZ, /* use it if 32kHz crystal present */ USE_32KHZ, /* do it regardless */ DONT_USE_32KHZ, /* don't use it regardless */ } ah_enable32kHzClock; /* whether to sleep at 32kHz */ uint32_t ah_ofdmTxPower; int16_t ah_txPowerIndexOffset; /* * Noise floor cal histogram support. */ struct ar5212NfCalHist ah_nfCalHist; u_int ah_slottime; /* user-specified slot time */ u_int ah_acktimeout; /* user-specified ack timeout */ u_int ah_ctstimeout; /* user-specified cts timeout */ u_int ah_sifstime; /* user-specified sifs time */ /* * RF Silent handling; setup according to the EEPROM. */ uint32_t ah_gpioSelect; /* GPIO pin to use */ uint32_t ah_polarity; /* polarity to disable RF */ uint32_t ah_gpioBit; /* after init, prev value */ /* * ANI support. */ uint32_t ah_procPhyErr; /* Process Phy errs */ HAL_BOOL ah_hasHwPhyCounters; /* Hardware has phy counters */ struct ar5212AniParams ah_aniParams24; /* 2.4GHz parameters */ struct ar5212AniParams ah_aniParams5; /* 5GHz parameters */ struct ar5212AniState *ah_curani; /* cached last reference */ struct ar5212AniState ah_ani[AH_MAXCHAN]; /* per-channel state */ /* AR5416 uses some of the AR5212 ANI code; these are the ANI methods */ HAL_BOOL (*ah_aniControl) (struct ath_hal *, HAL_ANI_CMD cmd, int param); /* * Transmit power state. Note these are maintained * here so they can be retrieved by diagnostic tools. */ uint16_t *ah_pcdacTable; u_int ah_pcdacTableSize; uint16_t ah_ratesArray[37]; uint8_t ah_txTrigLev; /* current Tx trigger level */ uint8_t ah_maxTxTrigLev; /* max tx trigger level */ /* * Channel Tx, Rx, Rx Clear State */ uint32_t ah_cycleCount; uint32_t ah_ctlBusy; uint32_t ah_rxBusy; uint32_t ah_txBusy; uint32_t ah_rx_chainmask; uint32_t ah_tx_chainmask; /* Used to return ANI statistics to the diagnostic API */ HAL_ANI_STATS ext_ani_stats; }; #define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) /* * IS_XXXX macros test the MAC version * IS_RADXXX macros test the radio/RF version (matching both 2G-only and 2/5G) * * Some single chip radios have equivalent radio/RF (e.g. 5112) * for those use IS_RADXXX_ANY macros. */ #define IS_2317(ah) \ ((AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1) || \ (AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)) #define IS_2316(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2415) #define IS_2413(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah)) #define IS_5424(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5424 || \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 && \ AH_PRIVATE(ah)->ah_macRev <= AR_SREV_D2PLUS_MS)) #define IS_5413(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah)) #define IS_2425(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) #define IS_2417(ah) \ ((AH_PRIVATE(ah)->ah_macVersion) == AR_SREV_2417) #define IS_HB63(ah) (AH5212(ah)->ah_isHb63 == AH_TRUE) #define AH_RADIO_MAJOR(ah) \ (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) #define AH_RADIO_MINOR(ah) \ (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MINOR) #define IS_RAD5111(ah) \ (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR || \ AH_RADIO_MAJOR(ah) == AR_RAD2111_SREV_MAJOR) #define IS_RAD5112(ah) \ (AH_RADIO_MAJOR(ah) == AR_RAD5112_SREV_MAJOR || \ AH_RADIO_MAJOR(ah) == AR_RAD2112_SREV_MAJOR) /* NB: does not include 5413 as Atheros' IS_5112 macro does */ #define IS_RAD5112_ANY(ah) \ (AR_RAD5112_SREV_MAJOR <= AH_RADIO_MAJOR(ah) && \ AH_RADIO_MAJOR(ah) <= AR_RAD2413_SREV_MAJOR) #define IS_RAD5112_REV1(ah) \ (IS_RAD5112(ah) && \ AH_RADIO_MINOR(ah) < (AR_RAD5112_SREV_2_0 & AR_RADIO_SREV_MINOR)) #define IS_RADX112_REV2(ah) \ (AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_0 || \ AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_0 || \ AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD2112_SREV_2_1 || \ AH_PRIVATE(ah)->ah_analog5GhzRev == AR_RAD5112_SREV_2_1) #define ar5212RfDetach(ah) do { \ if (AH5212(ah)->ah_rfHal != AH_NULL) \ AH5212(ah)->ah_rfHal->rfDetach(ah); \ } while (0) #define ar5212GetRfBank(ah, b) \ AH5212(ah)->ah_rfHal->getRfBank(ah, b) /* * Hack macros for Nala/San: 11b is handled * using 11g; flip the channel flags to accomplish this. */ #define SAVE_CCK(_ah, _chan, _flag) do { \ if ((IS_2425(_ah) || IS_2417(_ah)) && \ (((_chan)->ic_flags) & IEEE80211_CHAN_CCK)) { \ (_chan)->ic_flags &= ~IEEE80211_CHAN_CCK; \ (_chan)->ic_flags |= IEEE80211_CHAN_DYN; \ (_flag) = AH_TRUE; \ } else \ (_flag) = AH_FALSE; \ } while (0) #define RESTORE_CCK(_ah, _chan, _flag) do { \ if ((_flag) && (IS_2425(_ah) || IS_2417(_ah))) { \ (_chan)->ic_flags &= ~IEEE80211_CHAN_DYN; \ (_chan)->ic_flags |= IEEE80211_CHAN_CCK; \ } \ } while (0) struct ath_hal; extern uint32_t ar5212GetRadioRev(struct ath_hal *ah); extern void ar5212InitState(struct ath_hal_5212 *, uint16_t devid, HAL_SOFTC, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); extern void ar5212Detach(struct ath_hal *ah); extern HAL_BOOL ar5212ChipTest(struct ath_hal *ah); extern HAL_BOOL ar5212GetChannelEdges(struct ath_hal *ah, uint16_t flags, uint16_t *low, uint16_t *high); extern HAL_BOOL ar5212FillCapabilityInfo(struct ath_hal *ah); extern void ar5212SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *); extern void ar5212BeaconInit(struct ath_hal *ah, uint32_t next_beacon, uint32_t beacon_period); extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah); extern void ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *); extern uint64_t ar5212GetNextTBTT(struct ath_hal *); extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah); extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *); extern HAL_INT ar5212GetInterrupts(struct ath_hal *ah); extern HAL_INT ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints); extern uint32_t ar5212GetKeyCacheSize(struct ath_hal *); extern HAL_BOOL ar5212IsKeyCacheEntryValid(struct ath_hal *, uint16_t entry); extern HAL_BOOL ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry); extern HAL_BOOL ar5212SetKeyCacheEntryMac(struct ath_hal *, uint16_t entry, const uint8_t *mac); extern HAL_BOOL ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, const HAL_KEYVAL *k, const uint8_t *mac, int xorKey); extern void ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac); extern HAL_BOOL ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *); extern void ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mac); extern HAL_BOOL ar5212SetBssIdMask(struct ath_hal *, const uint8_t *); extern HAL_BOOL ar5212EepromRead(struct ath_hal *, u_int off, uint16_t *data); extern HAL_BOOL ar5212EepromWrite(struct ath_hal *, u_int off, uint16_t data); extern HAL_BOOL ar5212SetRegulatoryDomain(struct ath_hal *ah, uint16_t regDomain, HAL_STATUS *stats); extern u_int ar5212GetWirelessModes(struct ath_hal *ah); extern void ar5212EnableRfKill(struct ath_hal *); extern HAL_BOOL ar5212GpioCfgOutput(struct ath_hal *, uint32_t gpio, HAL_GPIO_MUX_TYPE); extern HAL_BOOL ar5212GpioCfgInput(struct ath_hal *, uint32_t gpio); extern HAL_BOOL ar5212GpioSet(struct ath_hal *, uint32_t gpio, uint32_t val); extern uint32_t ar5212GpioGet(struct ath_hal *ah, uint32_t gpio); extern void ar5212GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel); extern void ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state); extern void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId); extern uint32_t ar5212GetTsf32(struct ath_hal *ah); extern uint64_t ar5212GetTsf64(struct ath_hal *ah); extern void ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64); extern void ar5212ResetTsf(struct ath_hal *ah); extern void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *pSet); extern uint32_t ar5212GetRandomSeed(struct ath_hal *ah); extern HAL_BOOL ar5212DetectCardPresent(struct ath_hal *ah); extern void ar5212EnableMibCounters(struct ath_hal *); extern void ar5212DisableMibCounters(struct ath_hal *); extern void ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats); extern HAL_BOOL ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah); extern uint32_t ar5212GetCurRssi(struct ath_hal *ah); extern u_int ar5212GetDefAntenna(struct ath_hal *ah); extern void ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna); extern HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *); extern HAL_BOOL ar5212SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING); extern HAL_BOOL ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah); extern HAL_BOOL ar5212SetSifsTime(struct ath_hal *, u_int); extern u_int ar5212GetSifsTime(struct ath_hal *); extern HAL_BOOL ar5212SetSlotTime(struct ath_hal *, u_int); extern u_int ar5212GetSlotTime(struct ath_hal *); extern HAL_BOOL ar5212SetAckTimeout(struct ath_hal *, u_int); extern u_int ar5212GetAckTimeout(struct ath_hal *); extern HAL_BOOL ar5212SetAckCTSRate(struct ath_hal *, u_int); extern u_int ar5212GetAckCTSRate(struct ath_hal *); extern HAL_BOOL ar5212SetCTSTimeout(struct ath_hal *, u_int); extern u_int ar5212GetCTSTimeout(struct ath_hal *); extern HAL_BOOL ar5212SetDecompMask(struct ath_hal *, uint16_t, int); void ar5212SetCoverageClass(struct ath_hal *, uint8_t, int); extern void ar5212SetPCUConfig(struct ath_hal *); extern HAL_BOOL ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode); extern void ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode); extern void ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode); extern int16_t ar5212GetNfAdjust(struct ath_hal *, const HAL_CHANNEL_INTERNAL *); extern void ar5212SetCompRegs(struct ath_hal *ah); extern HAL_STATUS ar5212GetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t *); extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE, uint32_t, uint32_t, HAL_STATUS *); extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); extern HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); extern void ar5212SetChainMasks(struct ath_hal *, uint32_t, uint32_t); +extern u_int ar5212GetNav(struct ath_hal *); +extern void ar5212SetNav(struct ath_hal *, u_int); extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip); extern HAL_POWER_MODE ar5212GetPowerMode(struct ath_hal *ah); extern HAL_BOOL ar5212GetPowerStatus(struct ath_hal *ah); extern uint32_t ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE); extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5212EnableReceive(struct ath_hal *ah); extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah); extern void ar5212StartPcuReceive(struct ath_hal *ah, HAL_BOOL); extern void ar5212StopPcuReceive(struct ath_hal *ah); extern void ar5212SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1); extern HAL_BOOL ar5212ClrMulticastFilterIndex(struct ath_hal *, uint32_t ix); extern HAL_BOOL ar5212SetMulticastFilterIndex(struct ath_hal *, uint32_t ix); extern uint32_t ar5212GetRxFilter(struct ath_hal *ah); extern void ar5212SetRxFilter(struct ath_hal *ah, uint32_t bits); extern HAL_BOOL ar5212SetupRxDesc(struct ath_hal *, struct ath_desc *, uint32_t size, u_int flags); extern HAL_STATUS ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *, uint32_t, struct ath_desc *, uint64_t, struct ath_rx_status *); extern HAL_BOOL ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_BOOL bChannelChange, HAL_RESET_TYPE, HAL_STATUS *status); extern HAL_BOOL ar5212SetChannel(struct ath_hal *, const struct ieee80211_channel *); extern void ar5212SetOperatingMode(struct ath_hal *ah, int opmode); extern HAL_BOOL ar5212PhyDisable(struct ath_hal *ah); extern HAL_BOOL ar5212Disable(struct ath_hal *ah); extern HAL_BOOL ar5212ChipReset(struct ath_hal *ah, const struct ieee80211_channel *); extern HAL_BOOL ar5212PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL *isIQdone); extern HAL_BOOL ar5212PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone); extern HAL_BOOL ar5212ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *); extern int16_t ar5212GetNoiseFloor(struct ath_hal *ah); extern void ar5212InitNfCalHistBuffer(struct ath_hal *); extern int16_t ar5212GetNfHistMid(const int16_t calData[]); extern void ar5212SetSpurMitigation(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, const struct ieee80211_channel *); extern HAL_BOOL ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit); extern HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan); extern void ar5212InitializeGainValues(struct ath_hal *); extern HAL_RFGAIN ar5212GetRfgain(struct ath_hal *ah); extern void ar5212RequestRfgain(struct ath_hal *); extern HAL_BOOL ar5212UpdateTxTrigLevel(struct ath_hal *, HAL_BOOL IncTrigLevel); extern HAL_BOOL ar5212SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5212GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo); extern int ar5212SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, const HAL_TXQ_INFO *qInfo); extern HAL_BOOL ar5212ReleaseTxQueue(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5212ResetTxQueue(struct ath_hal *ah, u_int q); extern uint32_t ar5212GetTxDP(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp); extern HAL_BOOL ar5212StartTxDma(struct ath_hal *ah, u_int q); extern uint32_t ar5212NumTxPending(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5212StopTxDma(struct ath_hal *ah, u_int q); extern HAL_BOOL ar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsctsDuration, u_int compicvLen, u_int compivLen, u_int comp); extern HAL_BOOL ar5212SetupXTxDesc(struct ath_hal *, struct ath_desc *, u_int txRate1, u_int txRetries1, u_int txRate2, u_int txRetries2, u_int txRate3, u_int txRetries3); extern HAL_BOOL ar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0); extern HAL_STATUS ar5212ProcTxDesc(struct ath_hal *ah, struct ath_desc *, struct ath_tx_status *); extern void ar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *); extern void ar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *); extern HAL_BOOL ar5212GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries); extern void ar5212SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link); extern void ar5212GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link); extern void ar5212GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr); extern const HAL_RATE_TABLE *ar5212GetRateTable(struct ath_hal *, u_int mode); extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *, HAL_BOOL ena); extern void ar5212AniDetach(struct ath_hal *); extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *); extern HAL_ANI_STATS *ar5212AniGetCurrentStats(struct ath_hal *); extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); extern HAL_BOOL ar5212AniSetParams(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *); struct ath_rx_status; extern void ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs); extern void ar5212ProcessMibIntr(struct ath_hal *, const HAL_NODE_STATS *); extern void ar5212RxMonitor(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *); extern void ar5212AniPoll(struct ath_hal *, const struct ieee80211_channel *); extern void ar5212AniReset(struct ath_hal *, const struct ieee80211_channel *, HAL_OPMODE, int); extern HAL_BOOL ar5212IsNFCalInProgress(struct ath_hal *ah); extern HAL_BOOL ar5212WaitNFCalComplete(struct ath_hal *ah, int i); extern void ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); extern HAL_BOOL ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); extern void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); extern HAL_BOOL ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event); extern HAL_BOOL ar5212IsFastClockEnabled(struct ath_hal *ah); extern uint32_t ar5212Get11nExtBusy(struct ath_hal *ah); #endif /* _ATH_AR5212_H_ */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c index 82bc762f75d2..0dd26558506a 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c @@ -1,950 +1,952 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ar5212/ar5212.h" #include "ar5212/ar5212reg.h" #include "ar5212/ar5212phy.h" #define AH_5212_COMMON #include "ar5212/ar5212.ini" static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off); static void ar5212DisablePCIE(struct ath_hal *ah); static const struct ath_hal_private ar5212hal = {{ .ah_magic = AR5212_MAGIC, .ah_getRateTable = ar5212GetRateTable, .ah_detach = ar5212Detach, /* Reset Functions */ .ah_reset = ar5212Reset, .ah_phyDisable = ar5212PhyDisable, .ah_disable = ar5212Disable, .ah_configPCIE = ar5212ConfigPCIE, .ah_disablePCIE = ar5212DisablePCIE, .ah_setPCUConfig = ar5212SetPCUConfig, .ah_perCalibration = ar5212PerCalibration, .ah_perCalibrationN = ar5212PerCalibrationN, .ah_resetCalValid = ar5212ResetCalValid, .ah_setTxPowerLimit = ar5212SetTxPowerLimit, .ah_getChanNoise = ath_hal_getChanNoise, /* Transmit functions */ .ah_updateTxTrigLevel = ar5212UpdateTxTrigLevel, .ah_setupTxQueue = ar5212SetupTxQueue, .ah_setTxQueueProps = ar5212SetTxQueueProps, .ah_getTxQueueProps = ar5212GetTxQueueProps, .ah_releaseTxQueue = ar5212ReleaseTxQueue, .ah_resetTxQueue = ar5212ResetTxQueue, .ah_getTxDP = ar5212GetTxDP, .ah_setTxDP = ar5212SetTxDP, .ah_numTxPending = ar5212NumTxPending, .ah_startTxDma = ar5212StartTxDma, .ah_stopTxDma = ar5212StopTxDma, .ah_setupTxDesc = ar5212SetupTxDesc, .ah_setupXTxDesc = ar5212SetupXTxDesc, .ah_fillTxDesc = ar5212FillTxDesc, .ah_procTxDesc = ar5212ProcTxDesc, .ah_getTxIntrQueue = ar5212GetTxIntrQueue, .ah_reqTxIntrDesc = ar5212IntrReqTxDesc, .ah_getTxCompletionRates = ar5212GetTxCompletionRates, .ah_setTxDescLink = ar5212SetTxDescLink, .ah_getTxDescLink = ar5212GetTxDescLink, .ah_getTxDescLinkPtr = ar5212GetTxDescLinkPtr, /* RX Functions */ .ah_getRxDP = ar5212GetRxDP, .ah_setRxDP = ar5212SetRxDP, .ah_enableReceive = ar5212EnableReceive, .ah_stopDmaReceive = ar5212StopDmaReceive, .ah_startPcuReceive = ar5212StartPcuReceive, .ah_stopPcuReceive = ar5212StopPcuReceive, .ah_setMulticastFilter = ar5212SetMulticastFilter, .ah_setMulticastFilterIndex = ar5212SetMulticastFilterIndex, .ah_clrMulticastFilterIndex = ar5212ClrMulticastFilterIndex, .ah_getRxFilter = ar5212GetRxFilter, .ah_setRxFilter = ar5212SetRxFilter, .ah_setupRxDesc = ar5212SetupRxDesc, .ah_procRxDesc = ar5212ProcRxDesc, .ah_rxMonitor = ar5212RxMonitor, .ah_aniPoll = ar5212AniPoll, .ah_procMibEvent = ar5212ProcessMibIntr, /* Misc Functions */ .ah_getCapability = ar5212GetCapability, .ah_setCapability = ar5212SetCapability, .ah_getDiagState = ar5212GetDiagState, .ah_getMacAddress = ar5212GetMacAddress, .ah_setMacAddress = ar5212SetMacAddress, .ah_getBssIdMask = ar5212GetBssIdMask, .ah_setBssIdMask = ar5212SetBssIdMask, .ah_setRegulatoryDomain = ar5212SetRegulatoryDomain, .ah_setLedState = ar5212SetLedState, .ah_writeAssocid = ar5212WriteAssocid, .ah_gpioCfgInput = ar5212GpioCfgInput, .ah_gpioCfgOutput = ar5212GpioCfgOutput, .ah_gpioGet = ar5212GpioGet, .ah_gpioSet = ar5212GpioSet, .ah_gpioSetIntr = ar5212GpioSetIntr, .ah_getTsf32 = ar5212GetTsf32, .ah_getTsf64 = ar5212GetTsf64, .ah_setTsf64 = ar5212SetTsf64, .ah_resetTsf = ar5212ResetTsf, .ah_detectCardPresent = ar5212DetectCardPresent, .ah_updateMibCounters = ar5212UpdateMibCounters, .ah_getRfGain = ar5212GetRfgain, .ah_getDefAntenna = ar5212GetDefAntenna, .ah_setDefAntenna = ar5212SetDefAntenna, .ah_getAntennaSwitch = ar5212GetAntennaSwitch, .ah_setAntennaSwitch = ar5212SetAntennaSwitch, .ah_setSifsTime = ar5212SetSifsTime, .ah_getSifsTime = ar5212GetSifsTime, .ah_setSlotTime = ar5212SetSlotTime, .ah_getSlotTime = ar5212GetSlotTime, .ah_setAckTimeout = ar5212SetAckTimeout, .ah_getAckTimeout = ar5212GetAckTimeout, .ah_setAckCTSRate = ar5212SetAckCTSRate, .ah_getAckCTSRate = ar5212GetAckCTSRate, .ah_setCTSTimeout = ar5212SetCTSTimeout, .ah_getCTSTimeout = ar5212GetCTSTimeout, .ah_setDecompMask = ar5212SetDecompMask, .ah_setCoverageClass = ar5212SetCoverageClass, .ah_setQuiet = ar5212SetQuiet, .ah_getMibCycleCounts = ar5212GetMibCycleCounts, .ah_setChainMasks = ar5212SetChainMasks, + .ah_getNav = ar5212GetNav, + .ah_setNav = ar5212SetNav, /* DFS Functions */ .ah_enableDfs = ar5212EnableDfs, .ah_getDfsThresh = ar5212GetDfsThresh, .ah_getDfsDefaultThresh = ar5212GetDfsDefaultThresh, .ah_procRadarEvent = ar5212ProcessRadarEvent, .ah_isFastClockEnabled = ar5212IsFastClockEnabled, .ah_get11nExtBusy = ar5212Get11nExtBusy, /* Key Cache Functions */ .ah_getKeyCacheSize = ar5212GetKeyCacheSize, .ah_resetKeyCacheEntry = ar5212ResetKeyCacheEntry, .ah_isKeyCacheEntryValid = ar5212IsKeyCacheEntryValid, .ah_setKeyCacheEntry = ar5212SetKeyCacheEntry, .ah_setKeyCacheEntryMac = ar5212SetKeyCacheEntryMac, /* Power Management Functions */ .ah_setPowerMode = ar5212SetPowerMode, .ah_getPowerMode = ar5212GetPowerMode, /* Beacon Functions */ .ah_setBeaconTimers = ar5212SetBeaconTimers, .ah_beaconInit = ar5212BeaconInit, .ah_setStationBeaconTimers = ar5212SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers, .ah_getNextTBTT = ar5212GetNextTBTT, /* Interrupt Functions */ .ah_isInterruptPending = ar5212IsInterruptPending, .ah_getPendingInterrupts = ar5212GetPendingInterrupts, .ah_getInterrupts = ar5212GetInterrupts, .ah_setInterrupts = ar5212SetInterrupts }, .ah_getChannelEdges = ar5212GetChannelEdges, .ah_getWirelessModes = ar5212GetWirelessModes, .ah_eepromRead = ar5212EepromRead, #ifdef AH_SUPPORT_WRITE_EEPROM .ah_eepromWrite = ar5212EepromWrite, #endif .ah_getChipPowerLimits = ar5212GetChipPowerLimits, }; uint32_t ar5212GetRadioRev(struct ath_hal *ah) { uint32_t val; int i; /* Read Radio Chip Rev Extract */ OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16); for (i = 0; i < 8; i++) OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); return ath_hal_reverseBits(val, 8); } static void ar5212AniSetup(struct ath_hal *ah) { static const struct ar5212AniParams aniparams = { .maxNoiseImmunityLevel = 4, /* levels 0..4 */ .totalSizeDesired = { -55, -55, -55, -55, -62 }, .coarseHigh = { -14, -14, -14, -14, -12 }, .coarseLow = { -64, -64, -64, -64, -70 }, .firpwr = { -78, -78, -78, -78, -80 }, .maxSpurImmunityLevel = 2, /* NB: depends on chip rev */ .cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 }, .maxFirstepLevel = 2, /* levels 0..2 */ .firstep = { 0, 4, 8 }, .ofdmTrigHigh = 500, .ofdmTrigLow = 200, .cckTrigHigh = 200, .cckTrigLow = 100, .rssiThrHigh = 40, .rssiThrLow = 7, .period = 100, }; if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) { struct ar5212AniParams tmp; OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams)); tmp.maxSpurImmunityLevel = 7; /* Venice and earlier */ ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE); } else ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); /* Set overridable ANI methods */ AH5212(ah)->ah_aniControl = ar5212AniControl; } /* * Attach for an AR5212 part. */ void ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; struct ath_hal *ah; ah = &ahp->ah_priv.h; /* set initial values */ OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private)); ah->ah_sc = sc; ah->ah_st = st; ah->ah_sh = sh; ah->ah_devid = devid; /* NB: for alq */ AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ahp->ah_antControl = HAL_ANT_VARIABLE; ahp->ah_diversity = AH_TRUE; ahp->ah_bIQCalibration = AH_FALSE; /* * Enable MIC handling. */ ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ahp->ah_rssiThr = INIT_RSSI_THR; ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */ ahp->ah_phyPowerOn = AH_FALSE; ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK) | SM(MAX_RATE_POWER, AR_TPC_CTS) | SM(MAX_RATE_POWER, AR_TPC_CHIRP); ahp->ah_beaconInterval = 100; /* XXX [20..1000] */ ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */ ahp->ah_slottime = (u_int) -1; ahp->ah_acktimeout = (u_int) -1; ahp->ah_ctstimeout = (u_int) -1; ahp->ah_sifstime = (u_int) -1; ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD; ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD; OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); #undef N } /* * Validate MAC version and revision. */ static HAL_BOOL ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev) { #define N(a) (sizeof(a)/sizeof(a[0])) static const struct { uint8_t version; uint8_t revMin, revMax; } macs[] = { { AR_SREV_VERSION_VENICE, AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, { AR_SREV_VERSION_GRIFFIN, AR_SREV_D2PLUS, AR_SREV_REVISION_MAX }, { AR_SREV_5413, AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, { AR_SREV_5424, AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, { AR_SREV_2425, AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, { AR_SREV_2417, AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX }, }; int i; for (i = 0; i < N(macs); i++) if (macs[i].version == macVersion && macs[i].revMin <= macRev && macRev <= macs[i].revMax) return AH_TRUE; return AH_FALSE; #undef N } /* * Attach for an AR5212 part. */ static struct ath_hal * ar5212Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { #define AH_EEPROM_PROTECT(ah) \ (AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT) struct ath_hal_5212 *ahp; struct ath_hal *ah; struct ath_hal_rf *rf; uint32_t val; uint16_t eeval; HAL_STATUS ecode; HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { HALDEBUG(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; } ar5212InitState(ahp, devid, sc, st, sh, status); ah = &ahp->ah_priv.h; if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__); ecode = HAL_EIO; goto bad; } /* Read Revisions from Chips before taking out of reset */ val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah); if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Mac Chip Rev 0x%02x.%x not supported\n" , __func__, AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); ecode = HAL_ENOTSUPP; goto bad; } /* setup common ini data; rf backends handle remainder */ HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); if (!ar5212ChipReset(ah, AH_NULL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; } AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); if (AH_PRIVATE(ah)->ah_ispcie) { /* XXX: build flag to disable this? */ ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE); } if (!ar5212ChipTest(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", __func__); ecode = HAL_ESELFTEST; goto bad; } /* Enable PCI core retry fix in software for Hainan and up */ if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE) OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN); /* * Set correct Baseband to analog shift * setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); /* Read Radio Chip Rev Extract */ AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); rf = ath_hal_rfprobe(ah, &ecode); if (rf == AH_NULL) goto bad; /* NB: silently accept anything in release code per Atheros */ switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { case AR_RAD5111_SREV_MAJOR: case AR_RAD5112_SREV_MAJOR: case AR_RAD2112_SREV_MAJOR: case AR_RAD2111_SREV_MAJOR: case AR_RAD2413_SREV_MAJOR: case AR_RAD5413_SREV_MAJOR: case AR_RAD5424_SREV_MAJOR: break; default: if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { /* * When RF_Silent is used, the * analog chip is reset. So when the system boots * up with the radio switch off we cannot determine * the RF chip rev. To workaround this check the * mac+phy revs and if Hainan, set the radio rev * to Derby. */ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN && AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) { AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN; break; } if (IS_2413(ah)) { /* Griffin */ AH_PRIVATE(ah)->ah_analog5GhzRev = AR_RAD2413_SREV_MAJOR | 0x1; break; } if (IS_5413(ah)) { /* Eagle */ AH_PRIVATE(ah)->ah_analog5GhzRev = AR_RAD5413_SREV_MAJOR | 0x2; break; } if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */ AH_PRIVATE(ah)->ah_analog5GhzRev = AR_RAD5424_SREV_MAJOR | 0x2; break; } } #ifdef AH_DEBUG HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 5G Radio Chip Rev 0x%02X is not supported by " "this driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); ecode = HAL_ENOTSUPP; goto bad; #endif } if (IS_RAD5112_REV1(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 5112 Rev 1 is not supported by this " "driver (analog5GhzRev 0x%x)\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); ecode = HAL_ENOTSUPP; goto bad; } val = OS_REG_READ(ah, AR_PCICFG); val = MS(val, AR_PCICFG_EEPROM_SIZE); if (val == 0) { if (!AH_PRIVATE(ah)->ah_ispcie) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size %u (0x%x) found\n", __func__, val, val); ecode = HAL_EESIZE; goto bad; } /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */ } else if (val != AR_PCICFG_EEPROM_SIZE_16K) { if (AR_PCICFG_EEPROM_SIZE_FAILED == val) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size %u (0x%x) found\n", __func__, val, val); ecode = HAL_EESIZE; goto bad; } HALDEBUG(ah, HAL_DEBUG_ANY, "%s: EEPROM size = %d. Must be %d (16k).\n", __func__, val, AR_PCICFG_EEPROM_SIZE_16K); ecode = HAL_EESIZE; goto bad; } ecode = ath_hal_legacyEepromAttach(ah); if (ecode != HAL_OK) { goto bad; } ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON); /* * If Bmode and AR5212, verify 2.4 analog exists */ if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { /* * Set correct Baseband to analog shift * setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); OS_DELAY(2000); AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); /* Set baseband for 5GHz chip */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); OS_DELAY(2000); if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: 2G Radio Chip Rev 0x%02X is not " "supported by this driver\n", __func__, AH_PRIVATE(ah)->ah_analog2GhzRev); ecode = HAL_ENOTSUPP; goto bad; } } ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read regulatory domain from EEPROM\n", __func__); goto bad; } AH_PRIVATE(ah)->ah_currentRD = eeval; /* XXX record serial number */ /* * Got everything we need now to setup the capabilities. */ if (!ar5212FillCapabilityInfo(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: failed ar5212FillCapabilityInfo\n", __func__); ecode = HAL_EEREAD; goto bad; } if (!rf->attach(ah, &ecode)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", __func__, ecode); goto bad; } /* * Set noise floor adjust method; we arrange a * direct call instead of thunking. */ AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; /* Initialize gain ladder thermal calibration structure */ ar5212InitializeGainValues(ah); ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error getting mac address from EEPROM\n", __func__); goto bad; } ar5212AniSetup(ah); /* Setup of Radar/AR structures happens in ath_hal_initchannels*/ ar5212InitNfCalHistBuffer(ah); /* XXX EAR stuff goes here */ HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); return ah; bad: if (ahp) ar5212Detach((struct ath_hal *) ahp); if (status) *status = ecode; return AH_NULL; #undef AH_EEPROM_PROTECT } void ar5212Detach(struct ath_hal *ah) { HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5212_MAGIC); ar5212AniDetach(ah); ar5212RfDetach(ah); ar5212Disable(ah); ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); ath_hal_eepromDetach(ah); ath_hal_free(ah); } HAL_BOOL ar5212ChipTest(struct ath_hal *ah) { uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; uint32_t regHold[2]; uint32_t patternData[4] = { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; int i, j; /* Test PHY & MAC registers */ for (i = 0; i < 2; i++) { uint32_t addr = regAddr[i]; uint32_t wrData, rdData; regHold[i] = OS_REG_READ(ah, addr); for (j = 0; j < 0x100; j++) { wrData = (j << 16) | j; OS_REG_WRITE(ah, addr, wrData); rdData = OS_REG_READ(ah, addr); if (rdData != wrData) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wrData, rdData); return AH_FALSE; } } for (j = 0; j < 4; j++) { wrData = patternData[j]; OS_REG_WRITE(ah, addr, wrData); rdData = OS_REG_READ(ah, addr); if (wrData != rdData) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wrData, rdData); return AH_FALSE; } } OS_REG_WRITE(ah, regAddr[i], regHold[i]); } OS_DELAY(100); return AH_TRUE; } /* * Store the channel edges for the requested operational mode */ HAL_BOOL ar5212GetChannelEdges(struct ath_hal *ah, uint16_t flags, uint16_t *low, uint16_t *high) { if (flags & IEEE80211_CHAN_5GHZ) { *low = 4915; *high = 6100; return AH_TRUE; } if ((flags & IEEE80211_CHAN_2GHZ) && (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) || ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) { *low = 2312; *high = 2732; return AH_TRUE; } return AH_FALSE; } /* * Disable PLL when in L0s as well as receiver clock when in L1. * This power saving option must be enabled through the Serdes. * * Programming the Serdes must go through the same 288 bit serial shift * register as the other analog registers. Hence the 9 writes. * * XXX Clean up the magic numbers. */ static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) { OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); /* RX shut off when elecidle is asserted */ OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); /* Shut off PLL and CLKREQ active in L1 */ OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); /* Load the new settings */ OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } static void ar5212DisablePCIE(struct ath_hal *ah) { /* NB: fill in for 9100 */ } /* * Fill all software cached or static hardware state information. * Return failure if capabilities are to come from EEPROM and * cannot be read. */ HAL_BOOL ar5212FillCapabilityInfo(struct ath_hal *ah) { #define AR_KEYTABLE_SIZE 128 #define IS_GRIFFIN_LITE(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \ AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE) #define IS_COBRA(ah) \ (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA) #define IS_2112(ah) \ ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR) struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; uint16_t capField, val; /* Read the capability EEPROM location */ if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to read caps from eeprom\n", __func__); return AH_FALSE; } if (IS_2112(ah)) ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE); if (capField == 0 && IS_GRIFFIN_LITE(ah)) { /* * For griffin-lite cards with unprogrammed capabilities. */ ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n", __func__, capField); } /* Modify reg domain on newer cards that need to work with older sw */ if (ahpriv->ah_opmode != HAL_M_HOSTAP && ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) { if (ahpriv->ah_currentRD == 0x64 || ahpriv->ah_currentRD == 0x65) ahpriv->ah_currentRD += 5; else if (ahpriv->ah_currentRD == 0x41) ahpriv->ah_currentRD = 0x43; HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n", __func__, ahpriv->ah_currentRD); } if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 || AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) { HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: enable Bmode and disable turbo for Swan/Nala\n", __func__); ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE); ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE); ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE); ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE); ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE); } /* Construct wireless mode from EEPROM */ pCap->halWirelessModes = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { pCap->halWirelessModes |= HAL_MODE_11A; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) pCap->halWirelessModes |= HAL_MODE_TURBO; } if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) pCap->halWirelessModes |= HAL_MODE_11B; if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { pCap->halWirelessModes |= HAL_MODE_11G; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) pCap->halWirelessModes |= HAL_MODE_108G; } pCap->halLow2GhzChan = 2312; /* XXX 2417 too? */ if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah)) pCap->halHigh2GhzChan = 2500; else pCap->halHigh2GhzChan = 2732; /* * For AR5111 version < 4, the lowest centre frequency supported is * 5130MHz. For AR5111 version 4, the 4.9GHz channels are supported * but only in 10MHz increments. * * In addition, the programming method is wrong - it uses the IEEE * channel number to calculate the frequency, rather than the * channel centre. Since half/quarter rates re-use some of the * 5GHz channel IEEE numbers, this will result in a badly programmed * synth. * * Until the relevant support is written, just limit lower frequency * support for AR5111 so things aren't incorrectly programmed. * * XXX It's also possible this code doesn't correctly limit the * centre frequencies of potential channels; this is very important * for half/quarter rate! */ if (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR) { pCap->halLow5GhzChan = 5120; /* XXX lowest centre = 5130MHz */ } else { pCap->halLow5GhzChan = 4915; } pCap->halHigh5GhzChan = 6100; pCap->halCipherCkipSupport = AH_FALSE; pCap->halCipherTkipSupport = AH_TRUE; pCap->halCipherAesCcmSupport = (ath_hal_eepromGetFlag(ah, AR_EEP_AES) && ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) || ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) && (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU)))); pCap->halMicCkipSupport = AH_FALSE; pCap->halMicTkipSupport = AH_TRUE; pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); /* * Starting with Griffin TX+RX mic keys can be combined * in one key cache slot. */ if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN) pCap->halTkipMicTxRxKeySupport = AH_TRUE; else pCap->halTkipMicTxRxKeySupport = AH_FALSE; pCap->halChanSpreadSupport = AH_TRUE; pCap->halSleepAfterBeaconBroken = AH_TRUE; if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) { pCap->halCompressSupport = ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) && (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST); pCap->halFastFramesSupport = ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) && (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0; pCap->halChapTuningSupport = AH_TRUE; pCap->halTurboPrimeSupport = AH_TRUE; } pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ pCap->halNumMRRetries = 4; /* Hardware supports 4 MRR */ pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ pCap->halVEOLSupport = AH_TRUE; pCap->halBssIdMaskSupport = AH_TRUE; pCap->halMcastKeySrchSupport = AH_TRUE; if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE && ahpriv->ah_macRev == 8) || ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE) pCap->halTsfAddSupport = AH_TRUE; if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) pCap->halTotalQueues = val; else pCap->halTotalQueues = HAL_NUM_TX_QUEUES; if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) pCap->halKeyCacheSize = val; else pCap->halKeyCacheSize = AR_KEYTABLE_SIZE; pCap->halChanHalfRate = AH_TRUE; pCap->halChanQuarterRate = AH_TRUE; /* * RSSI uses the combined field; some 11n NICs may use * the control chain RSSI. */ pCap->halUseCombinedRadarRssi = AH_TRUE; if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { /* NB: enabled by default */ ahpriv->ah_rfkillEnabled = AH_TRUE; pCap->halRfSilentSupport = AH_TRUE; } /* NB: this is a guess, no one seems to know the answer */ ahpriv->ah_rxornIsFatal = (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE); /* enable features that first appeared in Hainan */ if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) || AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) { /* h/w phy counters */ pCap->halHwPhyCounterSupport = AH_TRUE; /* bssid match disable */ pCap->halBssidMatchSupport = AH_TRUE; } pCap->halRxTstampPrecision = 15; pCap->halTxTstampPrecision = 16; pCap->halIntrMask = HAL_INT_COMMON | HAL_INT_RX | HAL_INT_TX | HAL_INT_FATAL | HAL_INT_BNR | HAL_INT_BMISC ; if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) pCap->halIntrMask &= ~HAL_INT_TBTT; pCap->hal4kbSplitTransSupport = AH_TRUE; pCap->halHasRxSelfLinkedTail = AH_TRUE; return AH_TRUE; #undef IS_COBRA #undef IS_GRIFFIN_LITE #undef AR_KEYTABLE_SIZE } static const char* ar5212Probe(uint16_t vendorid, uint16_t devid) { if (vendorid == ATHEROS_VENDOR_ID || vendorid == ATHEROS_3COM_VENDOR_ID || vendorid == ATHEROS_3COM2_VENDOR_ID) { switch (devid) { case AR5212_FPGA: return "Atheros 5212 (FPGA)"; case AR5212_DEVID: case AR5212_DEVID_IBM: case AR5212_DEFAULT: return "Atheros 5212"; case AR5212_AR2413: return "Atheros 2413"; case AR5212_AR2417: return "Atheros 2417"; case AR5212_AR5413: return "Atheros 5413"; case AR5212_AR5424: return "Atheros 5424/2424"; } } return AH_NULL; } AH_CHIP(AR5212, ar5212Probe, ar5212Attach); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c index 577e1e7491b3..e6239902d713 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c @@ -1,1460 +1,1487 @@ /*- * SPDX-License-Identifier: ISC * * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ah_desc.h" /* NB: for HAL_PHYERR* */ #include "ar5212/ar5212.h" #include "ar5212/ar5212reg.h" #include "ar5212/ar5212phy.h" #include "ah_eeprom_v3.h" #define AR_NUM_GPIO 6 /* 6 GPIO pins */ #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ void ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) { struct ath_hal_5212 *ahp = AH5212(ah); OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); } HAL_BOOL ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) { struct ath_hal_5212 *ahp = AH5212(ah); OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); return AH_TRUE; } void ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) { struct ath_hal_5212 *ahp = AH5212(ah); OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); } HAL_BOOL ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) { struct ath_hal_5212 *ahp = AH5212(ah); /* save it since it must be rewritten on reset */ OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); return AH_TRUE; } /* * Attempt to change the cards operating regulatory domain to the given value */ HAL_BOOL ar5212SetRegulatoryDomain(struct ath_hal *ah, uint16_t regDomain, HAL_STATUS *status) { HAL_STATUS ecode; if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { ecode = HAL_EINVAL; goto bad; } if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { ecode = HAL_EEWRITE; goto bad; } #ifdef AH_SUPPORT_WRITE_REGDOMAIN if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: set regulatory domain to %u (0x%x)\n", __func__, regDomain, regDomain); AH_PRIVATE(ah)->ah_currentRD = regDomain; return AH_TRUE; } #endif ecode = HAL_EIO; bad: if (status) *status = ecode; return AH_FALSE; } /* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. */ u_int ar5212GetWirelessModes(struct ath_hal *ah) { u_int mode = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { mode = HAL_MODE_11A; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) mode |= HAL_MODE_TURBO | HAL_MODE_108A; if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) mode |= HAL_MODE_11A_HALF_RATE; if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) mode |= HAL_MODE_11A_QUARTER_RATE; } if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) mode |= HAL_MODE_11B; if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { mode |= HAL_MODE_11G; if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) mode |= HAL_MODE_108G; if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) mode |= HAL_MODE_11G_HALF_RATE; if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) mode |= HAL_MODE_11G_QUARTER_RATE; } return mode; } /* * Set the interrupt and GPIO values so the ISR can disable RF * on a switch signal. Assumes GPIO port and interrupt polarity * are set prior to call. */ void ar5212EnableRfKill(struct ath_hal *ah) { uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); /* * Configure the desired GPIO port for input * and enable baseband rf silence. */ ath_hal_gpioCfgInput(ah, select); OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); /* * If radio disable switch connection to GPIO bit x is enabled * program GPIO interrupt. * If rfkill bit on eeprom is 1, setupeeprommap routine has already * verified that it is a later version of eeprom, it has a place for * rfkill bit and it is set to 1, indicating that GPIO bit x hardware * connection is present. */ ath_hal_gpioSetIntr(ah, select, (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); } /* * Change the LED blinking pattern to correspond to the connectivity */ void ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) { static const uint32_t ledbits[8] = { AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ AR_PCICFG_LEDCTL_NONE, AR_PCICFG_LEDCTL_NONE, AR_PCICFG_LEDCTL_NONE, }; uint32_t bits; bits = OS_REG_READ(ah, AR_PCICFG); if (IS_2417(ah)) { /* * Enable LED for Nala. There is a bit marked reserved * that must be set and we also turn on the power led. * Because we mark s/w LED control setting the control * status bits below is meangless (the driver must flash * the LED(s) using the GPIO lines). */ bits = (bits &~ AR_PCICFG_LEDMODE) | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) #if 0 | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) #endif | 0x08000000; } bits = (bits &~ AR_PCICFG_LEDCTL) | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); OS_REG_WRITE(ah, AR_PCICFG, bits); } /* * Change association related fields programmed into the hardware. * Writing a valid BSSID to the hardware effectively enables the hardware * to synchronize its TSF to the correct beacons and receive frames coming * from that BSSID. It is called by the SME JOIN operation. */ void ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) { struct ath_hal_5212 *ahp = AH5212(ah); /* save bssid for possible re-use on reset */ OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); ahp->ah_assocId = assocId; OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | ((assocId & 0x3fff)<> 32) & 0xffffffff); } /* * Reset the current hardware tsf for stamlme. */ void ar5212ResetTsf(struct ath_hal *ah) { uint32_t val = OS_REG_READ(ah, AR_BEACON); OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); /* * When resetting the TSF, write twice to the * corresponding register; each write to the RESET_TSF bit toggles * the internal signal to cause a reset of the TSF - but if the signal * is left high, it will reset the TSF on the next chip reset also! * writing the bit an even number of times fixes this issue */ OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); } /* * Set or clear hardware basic rate bit * Set hardware basic rate set if basic rate is found * and basic rate is equal or less than 2Mbps */ void ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs) { const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; uint32_t reg; uint8_t xset; int i; if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan)) return; xset = 0; for (i = 0; i < rs->rs_count; i++) { uint8_t rset = rs->rs_rates[i]; /* Basic rate defined? */ if ((rset & 0x80) && (rset &= 0x7f) >= xset) xset = rset; } /* * Set the h/w bit to reflect whether or not the basic * rate is found to be equal or less than 2Mbps. */ reg = OS_REG_READ(ah, AR_STA_ID1); if (xset && xset/2 <= 2) OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); else OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); } /* * Grab a semi-random value from hardware registers - may not * change often */ uint32_t ar5212GetRandomSeed(struct ath_hal *ah) { uint32_t nf; nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); return (OS_REG_READ(ah, AR_TSF_U32) ^ OS_REG_READ(ah, AR_TSF_L32) ^ nf); } /* * Detect if our card is present */ HAL_BOOL ar5212DetectCardPresent(struct ath_hal *ah) { uint16_t macVersion, macRev; uint32_t v; /* * Read the Silicon Revision register and compare that * to what we read at attach time. If the same, we say * a card/device is present. */ v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; macVersion = v >> AR_SREV_ID_S; macRev = v & AR_SREV_REVISION; return (AH_PRIVATE(ah)->ah_macVersion == macVersion && AH_PRIVATE(ah)->ah_macRev == macRev); } void ar5212EnableMibCounters(struct ath_hal *ah) { /* NB: this just resets the mib counter machinery */ OS_REG_WRITE(ah, AR_MIBC, ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); } void ar5212DisableMibCounters(struct ath_hal *ah) { OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); } /* * Update MIB Counters */ void ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) { stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); } /* * Detect if the HW supports spreading a CCK signal on channel 14 */ HAL_BOOL ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) { return AH_TRUE; } /* * Get the rssi of frame curently being received. */ uint32_t ar5212GetCurRssi(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); } u_int ar5212GetDefAntenna(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); } void ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) { OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); } HAL_ANT_SETTING ar5212GetAntennaSwitch(struct ath_hal *ah) { return AH5212(ah)->ah_antControl; } HAL_BOOL ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) { struct ath_hal_5212 *ahp = AH5212(ah); const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; if (!ahp->ah_phyPowerOn || chan == AH_NULL) { /* PHY powered off, just stash settings */ ahp->ah_antControl = setting; ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); return AH_TRUE; } return ar5212SetAntennaSwitchInternal(ah, setting, chan); } HAL_BOOL ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) { return AH_TRUE; } HAL_BOOL ar5212SetSifsTime(struct ath_hal *ah, u_int us) { struct ath_hal_5212 *ahp = AH5212(ah); if (us > ath_hal_mac_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", __func__, us); ahp->ah_sifstime = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); ahp->ah_sifstime = us; return AH_TRUE; } } u_int ar5212GetSifsTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */ } HAL_BOOL ar5212SetSlotTime(struct ath_hal *ah, u_int us) { struct ath_hal_5212 *ahp = AH5212(ah); if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", __func__, us); ahp->ah_slottime = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); ahp->ah_slottime = us; return AH_TRUE; } } u_int ar5212GetSlotTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } HAL_BOOL ar5212SetAckTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5212 *ahp = AH5212(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", __func__, us); ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); ahp->ah_acktimeout = us; return AH_TRUE; } } u_int ar5212GetAckTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } u_int ar5212GetAckCTSRate(struct ath_hal *ah) { return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); } HAL_BOOL ar5212SetAckCTSRate(struct ath_hal *ah, u_int high) { struct ath_hal_5212 *ahp = AH5212(ah); if (high) { OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; } else { OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; } return AH_TRUE; } HAL_BOOL ar5212SetCTSTimeout(struct ath_hal *ah, u_int us) { struct ath_hal_5212 *ahp = AH5212(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", __func__, us); ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); ahp->ah_ctstimeout = us; return AH_TRUE; } } u_int ar5212GetCTSTimeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ } /* Setup decompression for given key index */ HAL_BOOL ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) { struct ath_hal_5212 *ahp = AH5212(ah); if (keyidx >= HAL_DECOMP_MASK_SIZE) return AH_FALSE; OS_REG_WRITE(ah, AR_DCM_A, keyidx); OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); ahp->ah_decompMask[keyidx] = en; return AH_TRUE; } /* Setup coverage class */ void ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) { uint32_t slot, timeout, eifs; u_int clkRate; AH_PRIVATE(ah)->ah_coverageClass = coverageclass; if (now) { if (AH_PRIVATE(ah)->ah_coverageClass == 0) return; /* Don't apply coverage class to non A channels */ if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) return; /* Get core clock rate */ clkRate = ath_hal_mac_clks(ah, 1); /* Compute EIFS */ slot = coverageclass * 3 * clkRate; eifs = coverageclass * 6 * clkRate; if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) { slot += IFS_SLOT_HALF_RATE; eifs += IFS_EIFS_HALF_RATE; } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) { slot += IFS_SLOT_QUARTER_RATE; eifs += IFS_EIFS_QUARTER_RATE; } else { /* full rate */ slot += IFS_SLOT_FULL_RATE; eifs += IFS_EIFS_FULL_RATE; } /* * Add additional time for air propagation for ACK and CTS * timeouts. This value is in core clocks. */ timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); /* * Write the values: slot, eifs, ack/cts timeouts. */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); OS_REG_WRITE(ah, AR_TIME_OUT, SM(timeout, AR_TIME_OUT_CTS) | SM(timeout, AR_TIME_OUT_ACK)); } } HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag) { OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S)); if (flag & HAL_QUIET_ENABLE) { OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16)); } else { OS_REG_WRITE(ah, AR_QUIET1, nextStart); } return HAL_OK; } void ar5212SetPCUConfig(struct ath_hal *ah) { ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); } /* * Return whether an external 32KHz crystal should be used * to reduce power consumption when sleeping. We do so if * the crystal is present (obtained from EEPROM) and if we * are not running as an AP and are configured to use it. */ HAL_BOOL ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) { if (opmode != HAL_M_HOSTAP) { struct ath_hal_5212 *ahp = AH5212(ah); return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && (ahp->ah_enable32kHzClock == USE_32KHZ || ahp->ah_enable32kHzClock == AUTO_32KHZ); } else return AH_FALSE; } /* * If 32KHz clock exists, use it to lower power consumption during sleep * * Note: If clock is set to 32 KHz, delays on accessing certain * baseband registers (27-31, 124-127) are required. */ void ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) { if (ar5212Use32KHzclock(ah, opmode)) { /* * Enable clocks to be turned OFF in BB during sleep * and also enable turning OFF 32MHz/40MHz Refclk * from A2. */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); /* # Set sleep clock rate to 32 KHz. */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); } else { OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); } } else { OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); if (IS_2417(ah)) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); else if (IS_HB63(ah)) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); else OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); } } /* * If 32KHz clock exists, turn it off and turn back on the 32Mhz */ void ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) { if (ar5212Use32KHzclock(ah, opmode)) { /* # Set sleep clock rate back to 32 MHz. */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); /* * Restore BB registers to power-on defaults */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); } } /* * Adjust NF based on statistical values for 5GHz frequencies. * Default method: this may be overridden by the rf backend. */ int16_t ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) { static const struct { uint16_t freqLow; int16_t adjust; } adjustDef[] = { { 5790, 11 }, /* NB: ordered high -> low */ { 5730, 10 }, { 5690, 9 }, { 5660, 8 }, { 5610, 7 }, { 5530, 5 }, { 5450, 4 }, { 5379, 2 }, { 5209, 0 }, { 3000, 1 }, { 0, 0 }, }; int i; for (i = 0; c->channel <= adjustDef[i].freqLow; i++) ; return adjustDef[i].adjust; } HAL_STATUS ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result) { #define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion struct ath_hal_5212 *ahp = AH5212(ah); const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; const struct ar5212AniState *ani; switch (type) { case HAL_CAP_CIPHER: /* cipher handled in hardware */ switch (capability) { case HAL_CIPHER_AES_CCM: return pCap->halCipherAesCcmSupport ? HAL_OK : HAL_ENOTSUPP; case HAL_CIPHER_AES_OCB: case HAL_CIPHER_TKIP: case HAL_CIPHER_WEP: case HAL_CIPHER_MIC: case HAL_CIPHER_CLR: return HAL_OK; default: return HAL_ENOTSUPP; } case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return (ahp->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ switch (capability) { case 0: /* hardware capability */ return pCap->halTkipMicTxRxKeySupport ? HAL_ENXIO : HAL_OK; case 1: /* current setting */ return (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; } return HAL_EINVAL; case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ /* XXX move to capability bit */ return MACVERSION(ah) > AR_SREV_VERSION_VENICE || (MACVERSION(ah) == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: /* current setting */ return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; case HAL_CAP_STRONG_DIV: *result = OS_REG_READ(ah, AR_PHY_RESTART); *result = MS(*result, AR_PHY_RESTART_DIV_GC); return HAL_OK; } return HAL_EINVAL; case HAL_CAP_DIAG: *result = AH_PRIVATE(ah)->ah_diagreg; return HAL_OK; case HAL_CAP_TPC: switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; } return HAL_OK; case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ switch (capability) { case HAL_CAP_RADAR: return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? HAL_OK: HAL_ENXIO; case HAL_CAP_AR: return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? HAL_OK: HAL_ENXIO; } return HAL_ENXIO; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ switch (capability) { case 0: /* hardware capability */ return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO; case 1: return (ahp->ah_staId1Defaults & AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ switch (capability) { case 0: /* hardware capability */ return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; case 1: return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TPC_ACK: *result = MS(ahp->ah_macTPC, AR_TPC_ACK); return HAL_OK; case HAL_CAP_TPC_CTS: *result = MS(ahp->ah_macTPC, AR_TPC_CTS); return HAL_OK; case HAL_CAP_INTMIT: /* interference mitigation */ switch (capability) { case HAL_CAP_INTMIT_PRESENT: /* hardware capability */ return HAL_OK; case HAL_CAP_INTMIT_ENABLE: return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? HAL_OK : HAL_ENXIO; case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL: case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL: case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR: case HAL_CAP_INTMIT_FIRSTEP_LEVEL: case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL: ani = ar5212AniGetCurrentState(ah); if (ani == AH_NULL) return HAL_ENXIO; switch (capability) { case 2: *result = ani->noiseImmunityLevel; break; case 3: *result = !ani->ofdmWeakSigDetectOff; break; case 4: *result = ani->cckWeakSigThreshold; break; case 5: *result = ani->firstepLevel; break; case 6: *result = ani->spurImmunityLevel; break; } return HAL_OK; } return HAL_EINVAL; default: return ath_hal_getcapability(ah, type, capability, result); } #undef MACVERSION } HAL_BOOL ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t setting, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5212 *ahp = AH5212(ah); const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; uint32_t v; switch (type) { case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ if (setting) ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; else ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; return AH_TRUE; case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ if (!pCap->halTkipMicTxRxKeySupport) return AH_FALSE; /* NB: true =>'s use split key cache layout */ if (setting) ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; else ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; /* NB: write here so keys can be setup w/o a reset */ OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); return AH_TRUE; case HAL_CAP_DIVERSITY: switch (capability) { case 0: return AH_FALSE; case 1: /* setting */ if (ahp->ah_phyPowerOn) { if (capability == HAL_CAP_STRONG_DIV) { v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); if (setting) v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; else v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); } } ahp->ah_diversity = (setting != 0); return AH_TRUE; case HAL_CAP_STRONG_DIV: if (! ahp->ah_phyPowerOn) return AH_FALSE; v = OS_REG_READ(ah, AR_PHY_RESTART); v &= ~AR_PHY_RESTART_DIV_GC; v |= SM(setting, AR_PHY_RESTART_DIV_GC); OS_REG_WRITE(ah, AR_PHY_RESTART, v); return AH_TRUE; default: return AH_FALSE; } case HAL_CAP_DIAG: /* hardware diagnostic support */ /* * NB: could split this up into virtual capabilities, * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly * seems worth the additional complexity. */ AH_PRIVATE(ah)->ah_diagreg = setting; OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); return AH_TRUE; case HAL_CAP_TPC: ahp->ah_tpcEnabled = (setting != 0); return AH_TRUE; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ if (setting) ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; else ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; return AH_TRUE; case HAL_CAP_TPC_ACK: case HAL_CAP_TPC_CTS: setting += ahp->ah_txPowerIndexOffset; if (setting > 63) setting = 63; if (type == HAL_CAP_TPC_ACK) { ahp->ah_macTPC &= AR_TPC_ACK; ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); } else { ahp->ah_macTPC &= AR_TPC_CTS; ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); } OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); return AH_TRUE; case HAL_CAP_INTMIT: { /* interference mitigation */ /* This maps the public ANI commands to the internal ANI commands */ /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */ static const HAL_ANI_CMD cmds[] = { HAL_ANI_PRESENT, HAL_ANI_MODE, HAL_ANI_NOISE_IMMUNITY_LEVEL, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, HAL_ANI_CCK_WEAK_SIGNAL_THR, HAL_ANI_FIRSTEP_LEVEL, HAL_ANI_SPUR_IMMUNITY_LEVEL, }; return capability < N(cmds) ? AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) : AH_FALSE; } case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ if (pCap->halTsfAddSupport) { if (setting) ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; else ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; return AH_TRUE; } /* fall thru... */ default: return ath_hal_setcapability(ah, type, capability, setting, status); } #undef N } HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize) { struct ath_hal_5212 *ahp = AH5212(ah); HAL_ANI_STATS *astats; (void) ahp; if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) return AH_TRUE; switch (request) { case HAL_DIAG_EEPROM: case HAL_DIAG_EEPROM_EXP_11A: case HAL_DIAG_EEPROM_EXP_11B: case HAL_DIAG_EEPROM_EXP_11G: case HAL_DIAG_RFGAIN: return ath_hal_eepromDiag(ah, request, args, argsize, result, resultsize); case HAL_DIAG_RFGAIN_CURSTEP: *result = __DECONST(void *, ahp->ah_gainValues.currStep); *resultsize = (*result == AH_NULL) ? 0 : sizeof(GAIN_OPTIMIZATION_STEP); return AH_TRUE; case HAL_DIAG_PCDAC: *result = ahp->ah_pcdacTable; *resultsize = ahp->ah_pcdacTableSize; return AH_TRUE; case HAL_DIAG_TXRATES: *result = &ahp->ah_ratesArray[0]; *resultsize = sizeof(ahp->ah_ratesArray); return AH_TRUE; case HAL_DIAG_ANI_CURRENT: *result = ar5212AniGetCurrentState(ah); *resultsize = (*result == AH_NULL) ? 0 : sizeof(struct ar5212AniState); return AH_TRUE; case HAL_DIAG_ANI_STATS: OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats)); astats = ar5212AniGetCurrentStats(ah); if (astats == NULL) { *result = NULL; *resultsize = 0; } else { OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS)); *result = &ahp->ext_ani_stats; *resultsize = sizeof(ahp->ext_ani_stats); } return AH_TRUE; case HAL_DIAG_ANI_CMD: if (argsize != 2*sizeof(uint32_t)) return AH_FALSE; AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0], ((const uint32_t *)args)[1]); return AH_TRUE; case HAL_DIAG_ANI_PARAMS: /* * NB: We assume struct ar5212AniParams is identical * to HAL_ANI_PARAMS; if they diverge then we'll need * to handle it here */ if (argsize == 0 && args == AH_NULL) { struct ar5212AniState *aniState = ar5212AniGetCurrentState(ah); if (aniState == AH_NULL) return AH_FALSE; *result = __DECONST(void *, aniState->params); *resultsize = sizeof(struct ar5212AniParams); return AH_TRUE; } else { if (argsize != sizeof(struct ar5212AniParams)) return AH_FALSE; return ar5212AniSetParams(ah, args, args); } break; } return AH_FALSE; } /* * Check whether there's an in-progress NF completion. * * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE * otherwise. */ HAL_BOOL ar5212IsNFCalInProgress(struct ath_hal *ah) { if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) return AH_TRUE; return AH_FALSE; } /* * Wait for an in-progress NF calibration to complete. * * The completion function waits "i" times 10uS. * It returns AH_TRUE if the NF calibration completed (or was never * in progress); AH_FALSE if it was still in progress after "i" checks. */ HAL_BOOL ar5212WaitNFCalComplete(struct ath_hal *ah, int i) { int j; if (i <= 0) i = 1; /* it should run at least once */ for (j = 0; j < i; j++) { if (! ar5212IsNFCalInProgress(ah)) return AH_TRUE; OS_DELAY(10); } return AH_FALSE; } void ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { uint32_t val; val = OS_REG_READ(ah, AR_PHY_RADAR_0); if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_FIRPWR; val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); } if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_RRSSI; val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); } if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_HEIGHT; val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); } if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_PRSSI; val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_INBAND; val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); } if (pe->pe_enabled) val |= AR_PHY_RADAR_0_ENA; else val &= ~ AR_PHY_RADAR_0_ENA; if (IS_5413(ah)) { if (pe->pe_blockradar == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_BLOCKOFDMWEAK); else OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_BLOCKOFDMWEAK); if (pe->pe_en_relstep_check == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENRELSTEPCHK); else OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENRELSTEPCHK); if (pe->pe_usefir128 == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_USEFIR128); else OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_USEFIR128); if (pe->pe_enmaxrssi == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENMAXRSSI); else OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENMAXRSSI); if (pe->pe_enrelpwr == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENRELPWRCHK); else OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_ENRELPWRCHK); if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr); if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep); if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen); } OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); } /* * Parameters for the AR5212 PHY. */ #define AR5212_DFS_FIRPWR -35 #define AR5212_DFS_RRSSI 20 #define AR5212_DFS_HEIGHT 14 #define AR5212_DFS_PRSSI 6 #define AR5212_DFS_INBAND 4 /* * Default parameters for the AR5413 PHY. */ #define AR5413_DFS_FIRPWR -34 #define AR5413_DFS_RRSSI 20 #define AR5413_DFS_HEIGHT 10 #define AR5413_DFS_PRSSI 15 #define AR5413_DFS_INBAND 6 #define AR5413_DFS_RELPWR 8 #define AR5413_DFS_RELSTEP 31 #define AR5413_DFS_MAXLEN 255 HAL_BOOL ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { if (IS_5413(ah)) { pe->pe_firpwr = AR5413_DFS_FIRPWR; pe->pe_rrssi = AR5413_DFS_RRSSI; pe->pe_height = AR5413_DFS_HEIGHT; pe->pe_prssi = AR5413_DFS_PRSSI; pe->pe_inband = AR5413_DFS_INBAND; pe->pe_relpwr = AR5413_DFS_RELPWR; pe->pe_relstep = AR5413_DFS_RELSTEP; pe->pe_maxlen = AR5413_DFS_MAXLEN; pe->pe_usefir128 = 0; pe->pe_blockradar = 1; pe->pe_enmaxrssi = 1; pe->pe_enrelpwr = 1; pe->pe_en_relstep_check = 0; } else { pe->pe_firpwr = AR5212_DFS_FIRPWR; pe->pe_rrssi = AR5212_DFS_RRSSI; pe->pe_height = AR5212_DFS_HEIGHT; pe->pe_prssi = AR5212_DFS_PRSSI; pe->pe_inband = AR5212_DFS_INBAND; pe->pe_relpwr = 0; pe->pe_relstep = 0; pe->pe_maxlen = 0; pe->pe_usefir128 = 0; pe->pe_blockradar = 0; pe->pe_enmaxrssi = 0; pe->pe_enrelpwr = 0; pe->pe_en_relstep_check = 0; } return (AH_TRUE); } void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { uint32_t val,temp; val = OS_REG_READ(ah, AR_PHY_RADAR_0); temp = MS(val,AR_PHY_RADAR_0_FIRPWR); temp |= 0xFFFFFF80; pe->pe_firpwr = temp; pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA); pe->pe_relpwr = 0; pe->pe_relstep = 0; pe->pe_maxlen = 0; pe->pe_usefir128 = 0; pe->pe_blockradar = 0; pe->pe_enmaxrssi = 0; pe->pe_enrelpwr = 0; pe->pe_en_relstep_check = 0; pe->pe_extchannel = AH_FALSE; if (IS_5413(ah)) { val = OS_REG_READ(ah, AR_PHY_RADAR_2); pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR); pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP); pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN); pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128); pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK); pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI); pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK); pe->pe_en_relstep_check = !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK); } } /* * Process the radar phy error and extract the pulse duration. */ HAL_BOOL ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) { uint8_t dur; uint8_t rssi; /* Check whether the given phy error is a radar event */ if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) return AH_FALSE; /* * The first byte is the pulse width - if there's * no data, simply set the duration to 0 */ if (rxs->rs_datalen >= 1) /* The pulse width is byte 0 of the data */ dur = ((uint8_t) buf[0]) & 0xff; else dur = 0; /* Pulse RSSI is the normal reported RSSI */ rssi = (uint8_t) rxs->rs_rssi; /* 0 duration/rssi is not a valid radar event */ if (dur == 0 && rssi == 0) return AH_FALSE; HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur); /* Record the event */ event->re_full_ts = fulltsf; event->re_ts = rxs->rs_tstamp; event->re_rssi = rssi; event->re_dur = dur; event->re_flags = HAL_DFS_EVENT_PRICH; return AH_TRUE; } /* * Return whether 5GHz fast-clock (44MHz) is enabled. * It's always disabled for AR5212 series NICs. */ HAL_BOOL ar5212IsFastClockEnabled(struct ath_hal *ah) { return AH_FALSE; } /* * Return what percentage of the extension channel is busy. * This is always disabled for AR5212 series NICs. */ uint32_t ar5212Get11nExtBusy(struct ath_hal *ah) { return 0; } /* * Channel survey support. */ HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) { struct ath_hal_5212 *ahp = AH5212(ah); u_int32_t good = AH_TRUE; /* XXX freeze/unfreeze mib counters */ uint32_t rc = OS_REG_READ(ah, AR_RCCNT); uint32_t rf = OS_REG_READ(ah, AR_RFCNT); uint32_t tf = OS_REG_READ(ah, AR_TFCNT); uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { /* * Cycle counter wrap (or initial call); it's not possible * to accurately calculate a value because the registers * right shift rather than wrap--so punt and return 0. */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n", __func__); good = AH_FALSE; } else { hsample->cycle_count = cc - ahp->ah_cycleCount; hsample->chan_busy = rc - ahp->ah_ctlBusy; hsample->ext_chan_busy = 0; hsample->rx_busy = rf - ahp->ah_rxBusy; hsample->tx_busy = tf - ahp->ah_txBusy; } /* * Keep a copy of the MIB results so the next sample has something * to work from. */ ahp->ah_cycleCount = cc; ahp->ah_rxBusy = rf; ahp->ah_ctlBusy = rc; ahp->ah_txBusy = tf; return (good); } void ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, uint32_t rx_chainmask) { } + +/* + * Get the current NAV value from the hardware. + * + * 0xdeadbeef indicates the hardware is currently powered off. + */ +u_int +ar5212GetNav(struct ath_hal *ah) +{ + uint32_t reg; + + reg = OS_REG_READ(ah, AR_NAV); + + if (reg == 0xdeadbeef) + return (0); + return (reg); +} + +/* + * Set the current NAV value to the hardware. + */ +void +ar5212SetNav(struct ath_hal *ah, u_int val) +{ + + OS_REG_WRITE(ah, AR_NAV, val); +}