Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
48526 views
/*1* Copyright (c) 2012, 2013 Adrian Chadd <[email protected]>.2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES8* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF9* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR10* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES11* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN12* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF13* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.14*/1516#include "opt_ah.h"1718#include "ah.h"19#include "ah_internal.h"20#include "ah_devid.h"21#include "ah_desc.h"2223#include "ar9300.h"24#include "ar9300reg.h"25#include "ar9300phy.h"26#include "ar9300desc.h"2728#include "ar9300_freebsd.h"2930#include "ar9300_stub.h"31#include "ar9300_stub_funcs.h"3233#define FIX_NOISE_FLOOR 134#define NEXT_TBTT_NOW 535static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix);36static HAL_BOOL ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix);3738static void ar9300_beacon_set_beacon_timers(struct ath_hal *ah,39const HAL_BEACON_TIMERS *bt);4041static void42ar9300SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,43uint32_t rx_chainmask)44{45HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;4647AH9300(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask;48AH9300(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask;49}5051static u_int52ar9300GetSlotTime(struct ath_hal *ah)53{54u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;55return (ath_hal_mac_usec(ah, clks)); /* convert from system clocks */56}5758static HAL_BOOL59ar9300_freebsd_set_tx_power_limit(struct ath_hal *ah, uint32_t limit)60{61return (ar9300_set_tx_power_limit(ah, limit, 0, 0));62}6364static uint64_t65ar9300_get_next_tbtt(struct ath_hal *ah)66{67return (OS_REG_READ(ah, AR_NEXT_TBTT_TIMER));68}6970static u_int71ar9300_get_nav(struct ath_hal *ah)72{73uint32_t reg;7475reg = OS_REG_READ(ah, AR_NAV);76if (reg == 0xdeadbeef)77return 0;78return reg;79}8081static void82ar9300_set_nav(struct ath_hal *ah, u_int nav)83{8485OS_REG_WRITE(ah, AR_NAV, nav);86}8788/*89* TODO: implement the antenna diversity control for AR9485 and90* other LNA mixing based NICs.91*92* For now we'll just go with the HAL default and make these no-ops.93*/94static HAL_ANT_SETTING95ar9300_freebsd_get_antenna_switch(struct ath_hal *ah)96{9798return (HAL_ANT_VARIABLE);99}100101static HAL_BOOL102ar9300_freebsd_set_antenna_switch(struct ath_hal *ah, HAL_ANT_SETTING setting)103{104105return (AH_TRUE);106}107108static u_int109ar9300_freebsd_get_cts_timeout(struct ath_hal *ah)110{111u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);112return ath_hal_mac_usec(ah, clks); /* convert from system clocks */113}114115static void116ar9300_freebsd_set_tsf64(struct ath_hal *ah, uint64_t tsf64)117{118119/*120* XXX TODO: read ar5416SetTsf64() - we should wait before we do121* this.122*/123OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);124OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);125}126127/* Flags for pulse_bw_info */128#define PRI_CH_RADAR_FOUND 0x01129#define EXT_CH_RADAR_FOUND 0x02130#define EXT_CH_RADAR_EARLY_FOUND 0x04131132static HAL_BOOL133ar9300_freebsd_proc_radar_event(struct ath_hal *ah, struct ath_rx_status *rxs,134uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)135{136HAL_BOOL doDfsExtCh;137HAL_BOOL doDfsEnhanced;138HAL_BOOL doDfsCombinedRssi;139140uint8_t rssi = 0, ext_rssi = 0;141uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;142uint32_t dur = 0;143int pri_found = 1, ext_found = 0;144int early_ext = 0;145int is_dc = 0;146uint16_t datalen; /* length from the RX status field */147148/* Check whether the given phy error is a radar event */149if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&150(rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {151return AH_FALSE;152}153154/* Grab copies of the capabilities; just to make the code clearer */155doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;156doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;157doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;158159datalen = rxs->rs_datalen;160161/* If hardware supports it, use combined RSSI, else use chain 0 RSSI */162if (doDfsCombinedRssi)163rssi = (uint8_t) rxs->rs_rssi;164else165rssi = (uint8_t) rxs->rs_rssi_ctl[0];166167/* Set this; but only use it if doDfsExtCh is set */168ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];169170/* Cap it at 0 if the RSSI is a negative number */171if (rssi & 0x80)172rssi = 0;173174if (ext_rssi & 0x80)175ext_rssi = 0;176177/*178* Fetch the relevant data from the frame179*/180if (doDfsExtCh) {181if (datalen < 3)182return AH_FALSE;183184/* Last three bytes of the frame are of interest */185pulse_length_pri = *(buf + datalen - 3);186pulse_length_ext = *(buf + datalen - 2);187pulse_bw_info = *(buf + datalen - 1);188HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"189" pulse_length_ext=%d, pulse_bw_info=%x\n",190__func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,191pulse_bw_info);192} else {193/* The pulse width is byte 0 of the data */194if (datalen >= 1)195dur = ((uint8_t) buf[0]) & 0xff;196else197dur = 0;198199if (dur == 0 && rssi == 0) {200HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);201return AH_FALSE;202}203204HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);205206/* Single-channel only */207pri_found = 1;208ext_found = 0;209}210211/*212* If doing extended channel data, pulse_bw_info must213* have one of the flags set.214*/215if (doDfsExtCh && pulse_bw_info == 0x0)216return AH_FALSE;217218/*219* If the extended channel data is available, calculate220* which to pay attention to.221*/222if (doDfsExtCh) {223/* If pulse is on DC, take the larger duration of the two */224if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&225(pulse_bw_info & PRI_CH_RADAR_FOUND)) {226is_dc = 1;227if (pulse_length_ext > pulse_length_pri) {228dur = pulse_length_ext;229pri_found = 0;230ext_found = 1;231} else {232dur = pulse_length_pri;233pri_found = 1;234ext_found = 0;235}236} else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {237dur = pulse_length_ext;238pri_found = 0;239ext_found = 1;240early_ext = 1;241} else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {242dur = pulse_length_pri;243pri_found = 1;244ext_found = 0;245} else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {246dur = pulse_length_ext;247pri_found = 0;248ext_found = 1;249}250251}252253/*254* For enhanced DFS (Merlin and later), pulse_bw_info has255* implications for selecting the correct RSSI value.256*/257if (doDfsEnhanced) {258switch (pulse_bw_info & 0x03) {259case 0:260/* No radar? */261rssi = 0;262break;263case PRI_CH_RADAR_FOUND:264/* Radar in primary channel */265/* Cannot use ctrl channel RSSI if ext channel is stronger */266if (ext_rssi >= (rssi + 3)) {267rssi = 0;268}269break;270case EXT_CH_RADAR_FOUND:271/* Radar in extended channel */272/* Cannot use ext channel RSSI if ctrl channel is stronger */273if (rssi >= (ext_rssi + 12)) {274rssi = 0;275} else {276rssi = ext_rssi;277}278break;279case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):280/* When both are present, use stronger one */281if (rssi < ext_rssi)282rssi = ext_rssi;283break;284}285}286287/*288* If not doing enhanced DFS, choose the ext channel if289* it is stronger than the main channel290*/291if (doDfsExtCh && !doDfsEnhanced) {292if ((ext_rssi > rssi) && (ext_rssi < 128))293rssi = ext_rssi;294}295296/*297* XXX what happens if the above code decides the RSSI298* XXX wasn't valid, an sets it to 0?299*/300301/*302* Fill out dfs_event structure.303*/304event->re_full_ts = fulltsf;305event->re_ts = rxs->rs_tstamp;306event->re_rssi = rssi;307event->re_dur = dur;308309event->re_flags = 0;310if (pri_found)311event->re_flags |= HAL_DFS_EVENT_PRICH;312if (ext_found)313event->re_flags |= HAL_DFS_EVENT_EXTCH;314if (early_ext)315event->re_flags |= HAL_DFS_EVENT_EXTEARLY;316if (is_dc)317event->re_flags |= HAL_DFS_EVENT_ISDC;318319return AH_TRUE;320}321322void323ar9300_attach_freebsd_ops(struct ath_hal *ah)324{325326/* Global functions */327ah->ah_detach = ar9300_detach;328ah->ah_getRateTable = ar9300_get_rate_table;329330/* Reset functions */331ah->ah_reset = ar9300_reset_freebsd;332ah->ah_phyDisable = ar9300_phy_disable;333ah->ah_disable = ar9300_disable;334ah->ah_configPCIE = ar9300_config_pcie_freebsd;335// ah->ah_disablePCIE = ar9300_disable_pcie_phy;336ah->ah_setPCUConfig = ar9300_set_pcu_config;337// perCalibration338ah->ah_perCalibrationN = ar9300_per_calibration_freebsd;339ah->ah_resetCalValid = ar9300_reset_cal_valid_freebsd;340ah->ah_setTxPowerLimit = ar9300_freebsd_set_tx_power_limit;341ah->ah_getChanNoise = ath_hal_getChanNoise;342343/* Transmit functions */344ah->ah_setupTxQueue = ar9300_setup_tx_queue;345ah->ah_setTxQueueProps = ar9300_set_tx_queue_props;346ah->ah_getTxQueueProps = ar9300_get_tx_queue_props;347ah->ah_releaseTxQueue = ar9300_release_tx_queue;348ah->ah_resetTxQueue = ar9300_reset_tx_queue;349ah->ah_getTxDP = ar9300_get_tx_dp;350ah->ah_setTxDP = ar9300_set_tx_dp;351ah->ah_numTxPending = ar9300_num_tx_pending;352ah->ah_startTxDma = ar9300_start_tx_dma;353ah->ah_stopTxDma = ar9300_stop_tx_dma_freebsd;354ah->ah_setupTxDesc = ar9300_freebsd_setup_tx_desc;355ah->ah_setupXTxDesc = ar9300_freebsd_setup_x_tx_desc;356ah->ah_fillTxDesc = ar9300_freebsd_fill_tx_desc;357ah->ah_procTxDesc = ar9300_freebsd_proc_tx_desc;358ah->ah_getTxIntrQueue = ar9300_get_tx_intr_queue;359// reqTxIntrDesc360ah->ah_getTxCompletionRates = ar9300_freebsd_get_tx_completion_rates;361ah->ah_setTxDescLink = ar9300_set_desc_link;362ah->ah_getTxDescLink = ar9300_freebsd_get_desc_link;363ah->ah_getTxDescLinkPtr = ar9300_get_desc_link_ptr;364ah->ah_setupTxStatusRing = ar9300_setup_tx_status_ring;365ah->ah_getTxRawTxDesc = ar9300_get_raw_tx_desc;366ah->ah_updateTxTrigLevel = ar9300_update_tx_trig_level;367368/* RX functions */369ah->ah_getRxDP = ar9300_get_rx_dp;370ah->ah_setRxDP = ar9300_set_rx_dp;371ah->ah_enableReceive = ar9300_enable_receive;372ah->ah_stopDmaReceive = ar9300_stop_dma_receive_freebsd;373ah->ah_startPcuReceive = ar9300_start_pcu_receive;374ah->ah_stopPcuReceive = ar9300_stop_pcu_receive;375ah->ah_setMulticastFilter = ar9300_set_multicast_filter;376ah->ah_setMulticastFilterIndex = ar9300SetMulticastFilterIndex;377ah->ah_clrMulticastFilterIndex = ar9300ClrMulticastFilterIndex;378ah->ah_getRxFilter = ar9300_get_rx_filter;379ah->ah_setRxFilter = ar9300_set_rx_filter;380/* setupRxDesc */381ah->ah_procRxDesc = ar9300_proc_rx_desc_freebsd;382ah->ah_rxMonitor = ar9300_ani_rxmonitor_freebsd;383ah->ah_aniPoll = ar9300_ani_poll_freebsd;384ah->ah_procMibEvent = ar9300_process_mib_intr;385386/* Misc functions */387ah->ah_getCapability = ar9300_get_capability;388ah->ah_setCapability = ar9300_set_capability;389ah->ah_getDiagState = ar9300_get_diag_state;390ah->ah_getMacAddress = ar9300_get_mac_address;391ah->ah_setMacAddress = ar9300_set_mac_address;392ah->ah_getBssIdMask = ar9300_get_bss_id_mask;393ah->ah_setBssIdMask = ar9300_set_bss_id_mask;394ah->ah_setRegulatoryDomain = ar9300_set_regulatory_domain;395ah->ah_setLedState = ar9300_set_led_state;396ah->ah_writeAssocid = ar9300_write_associd;397ah->ah_gpioCfgInput = ar9300_gpio_cfg_input;398ah->ah_gpioCfgOutput = ar9300_gpio_cfg_output;399ah->ah_gpioGet = ar9300_gpio_get;400ah->ah_gpioSet = ar9300_gpio_set;401ah->ah_gpioSetIntr = ar9300_gpio_set_intr;402/* polarity */403/* mask */404ah->ah_getTsf32 = ar9300_get_tsf32;405ah->ah_getTsf64 = ar9300_get_tsf64;406ah->ah_resetTsf = ar9300_reset_tsf;407ah->ah_setTsf64 = ar9300_freebsd_set_tsf64;408ah->ah_detectCardPresent = ar9300_detect_card_present;409// ah->ah_updateMibCounters = ar9300_update_mib_counters;410ah->ah_getRfGain = ar9300_get_rfgain;411ah->ah_getDefAntenna = ar9300_get_def_antenna;412ah->ah_setDefAntenna = ar9300_set_def_antenna;413ah->ah_getAntennaSwitch = ar9300_freebsd_get_antenna_switch;414ah->ah_setAntennaSwitch = ar9300_freebsd_set_antenna_switch;415// ah->ah_setSifsTime = ar9300_set_sifs_time;416// ah->ah_getSifsTime = ar9300_get_sifs_time;417ah->ah_setSlotTime = ar9300_set_slot_time;418ah->ah_getSlotTime = ar9300GetSlotTime;419ah->ah_getAckTimeout = ar9300_get_ack_timeout;420ah->ah_setAckTimeout = ar9300_set_ack_timeout;421// XXX ack/ctsrate422// XXX CTS timeout423ah->ah_getCTSTimeout = ar9300_freebsd_get_cts_timeout;424// XXX decompmask425// coverageclass426ah->ah_setQuiet = ar9300_set_quiet;427ah->ah_getMibCycleCounts = ar9300_freebsd_get_mib_cycle_counts;428429/* DFS functions */430ah->ah_enableDfs = ar9300_enable_dfs;431ah->ah_getDfsThresh = ar9300_get_dfs_thresh;432ah->ah_getDfsDefaultThresh = ar9300_get_default_dfs_thresh;433ah->ah_procRadarEvent = ar9300_freebsd_proc_radar_event;434ah->ah_isFastClockEnabled = ar9300_is_fast_clock_enabled;435ah->ah_get11nExtBusy = ar9300_get_11n_ext_busy;436ah->ah_setDfsCacTxQuiet = ar9300_cac_tx_quiet;437438/* Spectral Scan Functions */439ah->ah_spectralConfigure = ar9300_configure_spectral_scan;440ah->ah_spectralGetConfig = ar9300_get_spectral_params;441ah->ah_spectralStart = ar9300_start_spectral_scan;442ah->ah_spectralStop = ar9300_stop_spectral_scan;443ah->ah_spectralIsEnabled = ar9300_is_spectral_enabled;444ah->ah_spectralIsActive = ar9300_is_spectral_active;445446/* Key cache functions */447ah->ah_getKeyCacheSize = ar9300_get_key_cache_size;448ah->ah_resetKeyCacheEntry = ar9300_reset_key_cache_entry;449ah->ah_isKeyCacheEntryValid = ar9300_is_key_cache_entry_valid;450ah->ah_setKeyCacheEntry = ar9300_set_key_cache_entry;451ah->ah_setKeyCacheEntryMac = ar9300_set_key_cache_entry_mac;452453/* Power management functions */454ah->ah_setPowerMode = ar9300_set_power_mode;455ah->ah_getPowerMode = ar9300_get_power_mode;456457/* Beacon functions */458/* ah_setBeaconTimers */459ah->ah_beaconInit = ar9300_freebsd_beacon_init;460ah->ah_setBeaconTimers = ar9300_beacon_set_beacon_timers;461ah->ah_setStationBeaconTimers = ar9300_set_sta_beacon_timers;462/* ah_resetStationBeaconTimers */463ah->ah_getNextTBTT = ar9300_get_next_tbtt;464465/* Interrupt functions */466ah->ah_isInterruptPending = ar9300_is_interrupt_pending;467ah->ah_getPendingInterrupts = ar9300_get_pending_interrupts_freebsd;468ah->ah_getInterrupts = ar9300_get_interrupts;469ah->ah_setInterrupts = ar9300_set_interrupts_freebsd;470471/* Regulatory/internal functions */472// AH_PRIVATE(ah)->ah_getNfAdjust = ar9300_get_nf_adjust;473AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word;474// AH_PRIVATE(ah)->ah_getChipPowerLimits = ar9300_get_chip_power_limits;475AH_PRIVATE(ah)->ah_getWirelessModes = ar9300_get_wireless_modes;476AH_PRIVATE(ah)->ah_getChannelEdges = ar9300_get_channel_edges;477478AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word;479/* XXX ah_eeprom */480/* XXX ah_eeversion */481/* XXX ah_eepromDetach */482/* XXX ah_eepromGet */483AH_PRIVATE(ah)->ah_eepromGet = ar9300_eeprom_get_freebsd;484/* XXX ah_eepromSet */485/* XXX ah_getSpurChan */486/* XXX ah_eepromDiag */487488/* 802.11n functions */489ah->ah_chainTxDesc = ar9300_freebsd_chain_tx_desc;490ah->ah_setupFirstTxDesc= ar9300_freebsd_setup_first_tx_desc;491ah->ah_setupLastTxDesc = ar9300_freebsd_setup_last_tx_desc;492ah->ah_set11nRateScenario = ar9300_freebsd_set_11n_rate_scenario;493ah->ah_set11nTxDesc = ar9300_freebsd_setup_11n_desc;494ah->ah_set11nAggrFirst = ar9300_set_11n_aggr_first;495ah->ah_set11nAggrMiddle = ar9300_set_11n_aggr_middle;496ah->ah_set11nAggrLast = ar9300_set_11n_aggr_last;497ah->ah_clr11nAggr = ar9300_clr_11n_aggr;498ah->ah_set11nBurstDuration = ar9300_set_11n_burst_duration;499/* ah_get11nExtBusy */500ah->ah_set11nMac2040 = ar9300_set_11n_mac2040;501ah->ah_setChainMasks = ar9300SetChainMasks;502ah->ah_getNav = ar9300_get_nav;503ah->ah_setNav = ar9300_set_nav;504/* ah_get11nRxClear */505/* ah_set11nRxClear */506507/* bluetooth coexistence functions */508ah->ah_btCoexSetInfo = ar9300_set_bt_coex_info;509ah->ah_btCoexSetConfig = ar9300_bt_coex_config;510ah->ah_btCoexSetQcuThresh = ar9300_bt_coex_set_qcu_thresh;511ah->ah_btCoexSetWeights = ar9300_bt_coex_set_weights;512ah->ah_btCoexSetBmissThresh = ar9300_bt_coex_setup_bmiss_thresh;513ah->ah_btCoexSetParameter = ar9300_bt_coex_set_parameter;514ah->ah_btCoexDisable = ar9300_bt_coex_disable;515ah->ah_btCoexEnable = ar9300_bt_coex_enable;516517/* MCI bluetooth functions */518if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {519/*520* Note: these are done in attach too for now, because521* at this point we haven't yet setup the mac/bb revision522* values, so this code is effectively NULL.523* However, I'm leaving this here so people digging524* into the code (a) see the MCI bits here, and (b)525* are now told they should look elsewhere for526* these methods.527*/528ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights;529ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable;530ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable;531}532ah->ah_btMciSetup = ar9300_mci_setup;533ah->ah_btMciSendMessage = ar9300_mci_send_message;534ah->ah_btMciGetInterrupt = ar9300_mci_get_interrupt;535ah->ah_btMciState = ar9300_mci_state;536ah->ah_btMciDetach = ar9300_mci_detach;537538/* LNA diversity functions */539ah->ah_divLnaConfGet = ar9300_ant_div_comb_get_config;540ah->ah_divLnaConfSet = ar9300_ant_div_comb_set_config;541}542543HAL_BOOL544ar9300_reset_freebsd(struct ath_hal *ah, HAL_OPMODE opmode,545struct ieee80211_channel *chan, HAL_BOOL bChannelChange,546HAL_RESET_TYPE resetType,547HAL_STATUS *status)548{549HAL_BOOL r;550HAL_HT_MACMODE macmode;551struct ath_hal_private *ap = AH_PRIVATE(ah);552553macmode =554IEEE80211_IS_CHAN_HT40(chan) ?555HAL_HT_MACMODE_2040 : HAL_HT_MACMODE_20;556557r = ar9300_reset(ah, opmode, chan, macmode,558ap->ah_caps.halTxChainMask,559ap->ah_caps.halRxChainMask,560HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */561bChannelChange,562status,563resetType,564AH_FALSE); /* XXX should really extend ath_hal_reset() */565566return (r);567}568569void570ar9300_config_pcie_freebsd(struct ath_hal *ah, HAL_BOOL restore,571HAL_BOOL powerOff)572{573574ar9300_config_pci_power_save(ah, restore ? 1 : 0, powerOff ? 1 : 0);575}576577/*578* This is a copy from ar9300_eeprom_get(), purely because the FreeBSD579* API is very silly and inconsistent.580*581* The AR93xx HAL doesn't call the eepromGetFlag() function, so this582* only occurs for FreeBSD code.583*584* When I fix this particular API, I'll undo this.585*/586HAL_STATUS587ar9300_eeprom_get_freebsd(struct ath_hal *ah, int param, void *val)588{589590switch (param) {591case AR_EEP_FSTCLK_5G:592return HAL_OK;593default:594ath_hal_printf(ah, "%s: called, param=%d\n",595__func__, param);596return HAL_EIO;597}598}599600HAL_BOOL601ar9300_stop_tx_dma_freebsd(struct ath_hal *ah, u_int q)602{603604return ar9300_stop_tx_dma(ah, q, 1000);605}606607void608ar9300_ani_poll_freebsd(struct ath_hal *ah,609const struct ieee80211_channel *chan)610{611612HAL_NODE_STATS stats;613HAL_ANISTATS anistats;614HAL_SURVEY_SAMPLE survey;615616OS_MEMZERO(&stats, sizeof(stats));617OS_MEMZERO(&anistats, sizeof(anistats));618OS_MEMZERO(&survey, sizeof(survey));619620ar9300_ani_ar_poll(ah, &stats, chan, &anistats);621622/*623* If ANI stats are valid, use them to update the624* channel survey.625*/626if (anistats.valid) {627survey.cycle_count = anistats.cyclecnt_diff;628survey.chan_busy = anistats.rxclr_cnt;629survey.ext_chan_busy = anistats.extrxclr_cnt;630survey.tx_busy = anistats.txframecnt_diff;631survey.rx_busy = anistats.rxframecnt_diff;632ath_hal_survey_add_sample(ah, &survey);633}634}635636/*637* Setup the configuration parameters in the style the AR9300 HAL638* wants.639*/640void641ar9300_config_defaults_freebsd(struct ath_hal *ah, HAL_OPS_CONFIG *ah_config)642{643644/* Until FreeBSD's HAL does this by default - just copy */645OS_MEMCPY(&ah->ah_config, ah_config, sizeof(HAL_OPS_CONFIG));646ah->ah_config.ath_hal_enable_ani = AH_TRUE;647}648649HAL_BOOL650ar9300_stop_dma_receive_freebsd(struct ath_hal *ah)651{652653return ar9300_stop_dma_receive(ah, 1000);654}655656HAL_BOOL657ar9300_get_pending_interrupts_freebsd(struct ath_hal *ah, HAL_INT *masked)658{659660/* Non-MSI, so no MSI vector; and 'nortc' = 0 */661return ar9300_get_pending_interrupts(ah, masked, HAL_INT_LINE, 0, 0);662}663664HAL_INT665ar9300_set_interrupts_freebsd(struct ath_hal *ah, HAL_INT ints)666{667668/* nortc = 0 */669return ar9300_set_interrupts(ah, ints, 0);670}671672HAL_BOOL673ar9300_per_calibration_freebsd(struct ath_hal *ah,674struct ieee80211_channel *chan, u_int rxchainmask, HAL_BOOL long_cal,675HAL_BOOL *isCalDone)676{677/* XXX fake scheduled calibrations for now */678u_int32_t sched_cals = 0xfffffff;679680return ar9300_calibration(ah, chan,681AH_PRIVATE(ah)->ah_caps.halRxChainMask,682long_cal,683isCalDone,6840, /* is_scan */685&sched_cals);686}687688HAL_BOOL689ar9300_reset_cal_valid_freebsd(struct ath_hal *ah,690const struct ieee80211_channel *chan)691{692693HAL_BOOL is_cal_done = AH_TRUE;694695ar9300_reset_cal_valid(ah, chan, &is_cal_done, 0xffffffff);696return (is_cal_done);697}698699700/*701* FreeBSD will just pass in the descriptor value as 'pa'.702* The Atheros HAL treats 'pa' as the physical address of the RX703* descriptor and 'bufaddr' as the physical address of the RX buffer.704* I'm not sure why they didn't collapse them - the AR9300 RX descriptor705* routine doesn't check 'pa'.706*/707HAL_STATUS708ar9300_proc_rx_desc_freebsd(struct ath_hal *ah, struct ath_desc *ds,709uint32_t pa, struct ath_desc *ds_next, uint64_t tsf,710struct ath_rx_status *rxs)711{712713return (ar9300_proc_rx_desc_fast(ah, ds, 0, ds_next, rxs,714(void *) ds));715}716717/*718* This is the primary way the ANI code gets the node statistics per packet.719*/720void721ar9300_ani_rxmonitor_freebsd(struct ath_hal *ah, const HAL_NODE_STATS *stats,722const struct ieee80211_channel *chan)723{724struct ath_hal_9300 *ahp = AH9300(ah);725726ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;727}728729void730ar9300_freebsd_get_desc_link(struct ath_hal *ah, void *ds, uint32_t *link)731{732struct ar9300_txc *ads = AR9300TXC(ds);733734(*link) = ads->ds_link;735}736737/*738* TX descriptor field setting wrappers - eek.739*/740741742HAL_BOOL743ar9300_freebsd_setup_tx_desc(struct ath_hal *ah, struct ath_desc *ds,744u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower,745u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags,746u_int rtsctsRate, u_int rtsCtsDuration, u_int compicvLen,747u_int compivLen, u_int comp)748{749struct ath_hal_9300 *ahp = AH9300(ah);750751HAL_KEY_TYPE keyType = 0; /* XXX No padding */752753if (keyIx != HAL_TXKEYIX_INVALID)754keyType = ahp->ah_keytype[keyIx];755756/* XXX bounds check keyix */757ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx,758keyType, flags);759760return AH_TRUE;761}762763HAL_BOOL764ar9300_freebsd_setup_x_tx_desc(struct ath_hal *ah, struct ath_desc *ds,765u_int txRate1, u_int txTries1,766u_int txRate2, u_int txTries2,767u_int txRate3, u_int txTries3)768{769770#if 0771ath_hal_printf(ah, "%s: called, 0x%x/%d, 0x%x/%d, 0x%x/%d\n",772__func__,773txRate1, txTries1,774txRate2, txTries2,775txRate3, txTries3);776#endif777778/* XXX should only be called during probe */779return (AH_TRUE);780}781782HAL_BOOL783ar9300_freebsd_fill_tx_desc(struct ath_hal *ah, struct ath_desc *ds,784HAL_DMA_ADDR *bufListPtr, uint32_t *segLenPtr, u_int descId, u_int qid,785HAL_BOOL firstSeg, HAL_BOOL lastSeg,786const struct ath_desc *ds0)787{788HAL_KEY_TYPE keyType = 0;789const struct ar9300_txc *ads = AR9300TXC_CONST(ds0);790791/*792* FreeBSD's HAL doesn't pass the keytype to fill_tx_desc();793* it's copied as part of the descriptor chaining.794*795* So, extract it from ds0.796*/797keyType = MS(ads->ds_ctl17, AR_encr_type);798799return ar9300_fill_tx_desc(ah, ds, bufListPtr, segLenPtr, descId,800qid, keyType, firstSeg, lastSeg, ds0);801}802803HAL_BOOL804ar9300_freebsd_get_tx_completion_rates(struct ath_hal *ah,805const struct ath_desc *ds0, int *rates, int *tries)806{807808ath_hal_printf(ah, "%s: called\n", __func__);809return AH_FALSE; /* XXX for now */810}811812813/*814* 802.11n TX descriptor wrappers815*/816void817ar9300_freebsd_set_11n_rate_scenario(struct ath_hal *ah, struct ath_desc *ds,818u_int durUpdateEn, u_int rtsctsRate, HAL_11N_RATE_SERIES series[],819u_int nseries, u_int flags)820{821822/* lastds=NULL, rtscts_duration is 0, smart antenna is 0 */823ar9300_set_11n_rate_scenario(ah, (void *) ds, (void *)ds, durUpdateEn,824rtsctsRate, 0, series, nseries, flags, 0);825}826827/* chaintxdesc */828HAL_BOOL829ar9300_freebsd_chain_tx_desc(struct ath_hal *ah, struct ath_desc *ds,830HAL_DMA_ADDR *bufLenList, uint32_t *segLenList,831u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx,832HAL_CIPHER cipher, uint8_t numDelims,833HAL_BOOL firstSeg, HAL_BOOL lastSeg, HAL_BOOL lastAggr)834{835836ath_hal_printf(ah, "%s: called\n", __func__);837return AH_FALSE;838}839840/* setupfirsttxdesc */841HAL_BOOL842ar9300_freebsd_setup_first_tx_desc(struct ath_hal *ah, struct ath_desc *ds,843u_int aggrLen, u_int flags, u_int txPower, u_int txRate0,844u_int txTries0, u_int antMode, u_int rtsctsRate, u_int rtsctsDuration)845{846847ath_hal_printf(ah, "%s: called\n", __func__);848return AH_FALSE;849}850851/* setuplasttxdesc */852/*853* This gets called but for now let's not log anything;854* it's only used to update the rate control information.855*/856HAL_BOOL857ar9300_freebsd_setup_last_tx_desc(struct ath_hal *ah, struct ath_desc *ds,858const struct ath_desc *ds0)859{860861// ath_hal_printf(ah, "%s: called\n", __func__);862return AH_FALSE;863}864865void866ar9300_freebsd_setup_11n_desc(struct ath_hal *ah, void *ds, u_int pktLen,867HAL_PKT_TYPE type, u_int txPower, u_int keyIx, u_int flags)868{869ath_hal_printf(ah, "%s: called\n", __func__);870#if 0871struct ath_hal_9300 *ahp = AH9300(ah);872873HAL_KEY_TYPE keyType = 0; /* XXX No padding */874875if (keyIx != HAL_TXKEYIX_INVALID)876keyType = ahp->ah_keytype[keyIx];877878/* XXX bounds check keyix */879ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx,880keyType, flags);881#endif882}883884HAL_STATUS885ar9300_freebsd_proc_tx_desc(struct ath_hal *ah, struct ath_desc *ds,886struct ath_tx_status *ts)887{888889return ar9300_proc_tx_desc(ah, ts);890}891892void893ar9300_freebsd_beacon_init(struct ath_hal *ah, uint32_t next_beacon,894uint32_t beacon_period)895{896897ar9300_beacon_init(ah, next_beacon, beacon_period, 0,898AH_PRIVATE(ah)->ah_opmode);899}900901HAL_BOOL902ar9300_freebsd_get_mib_cycle_counts(struct ath_hal *ah,903HAL_SURVEY_SAMPLE *hs)904905{906907return (AH_FALSE);908}909910/*911* Clear multicast filter by index - from FreeBSD ar5212_recv.c912*/913static HAL_BOOL914ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)915{916uint32_t val;917918if (ix >= 64)919return (AH_FALSE);920if (ix >= 32) {921val = OS_REG_READ(ah, AR_MCAST_FIL1);922OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32))));923} else {924val = OS_REG_READ(ah, AR_MCAST_FIL0);925OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<<ix)));926}927return AH_TRUE;928}929930/*931* Set multicast filter by index - from FreeBSD ar5212_recv.c932*/933static HAL_BOOL934ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)935{936uint32_t val;937938if (ix >= 64)939return (AH_FALSE);940if (ix >= 32) {941val = OS_REG_READ(ah, AR_MCAST_FIL1);942OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32))));943} else {944val = OS_REG_READ(ah, AR_MCAST_FIL0);945OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1<<ix)));946}947return (AH_TRUE);948}949950#define TU_TO_USEC(_tu) ((_tu) << 10)951#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7)952953/*954* Initializes all of the hardware registers used to955* send beacons. Note that for station operation the956* driver calls ar9300_set_sta_beacon_timers instead.957*/958static void959ar9300_beacon_set_beacon_timers(struct ath_hal *ah,960const HAL_BEACON_TIMERS *bt)961{962uint32_t bperiod;963964#if 0965HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP);966if (opmode == HAL_M_IBSS) {967OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);968}969#endif970971/* XXX TODO: should migrate the HAL code to always use ONE_EIGHTH_TU */972OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bt->bt_nexttbtt));973OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba));974OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba));975OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER, TU_TO_USEC(bt->bt_nextatim));976977bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);978AH9300(ah)->ah_beaconInterval = bt->bt_intval & HAL_BEACON_PERIOD;979OS_REG_WRITE(ah, AR_BEACON_PERIOD, bperiod);980OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bperiod);981OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod);982OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod);983984/*985* Reset TSF if required.986*/987if (bt->bt_intval & HAL_BEACON_RESET_TSF)988ar9300_reset_tsf(ah);989990/* enable timers */991/* NB: flags == 0 handled specially for backwards compatibility */992OS_REG_SET_BIT(ah, AR_TIMER_MODE,993bt->bt_flags != 0 ? bt->bt_flags :994AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN);995}996997998/*999* RF attach stubs1000*/10011002static HAL_BOOL1003rf9330_attach(struct ath_hal *ah, HAL_STATUS *status)1004{10051006(*status) = HAL_EINVAL;1007return (AH_FALSE);1008}10091010static HAL_BOOL1011rf9330_probe(struct ath_hal *ah)1012{1013return (AH_FALSE);1014}10151016AH_RF(RF9330, rf9330_probe, rf9330_attach);1017101810191020