/* * Once configured for I/O - set output lines */ HAL_BOOL ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) { uint32_t reg; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, val=%d\n", __func__, gpio, val); reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); if (val & 1) reg |= AR_GPIO_BIT(gpio); else reg &= ~AR_GPIO_BIT(gpio); OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); return AH_TRUE; }
/* * Initialize RX descriptor, by clearing the status and setting * the size (and any other flags). */ HAL_BOOL ar5212SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, uint32_t size, u_int flags) { struct ar5212_desc *ads = AR5212DESC(ds); HALASSERT((size &~ AR_BufLen) == 0); ads->ds_ctl0 = 0; ads->ds_ctl1 = size & AR_BufLen; if (flags & HAL_RXDESC_INTREQ) ads->ds_ctl1 |= AR_RxInterReq; ads->ds_rxstatus0 = ads->ds_rxstatus1 = 0; return AH_TRUE; }
static void ar5416AniCckErrTrigger(struct ath_hal *ah) { struct ath_hal_5212 *ahp = AH5212(ah); const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; struct ar5212AniState *aniState; const struct ar5212AniParams *params; HALASSERT(chan != AH_NULL); if (!ANI_ENA(ah)) return; /* first, raise noise immunity level, up to max */ aniState = ahp->ah_curani; params = aniState->params; if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL) && aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) { ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; } if (ANI_ENA_RSSI(ah)) { int32_t rssi = BEACON_RSSI(ahp); if (rssi > params->rssiThrLow) { /* * Beacon signal in mid and high range, * raise firstep level. */ if (aniState->firstepLevel+1 < params->maxFirstepLevel) ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); } else { /* * Beacon rssi is low, zero firstep level to maximize * CCK sensitivity in 11b/g mode. */ if (IEEE80211_IS_CHAN_CCK(chan)) { if (aniState->firstepLevel > 0) ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); } } } }
/* * Initialize RX descriptor, by clearing the status and setting * the size (and any other flags). */ HAL_BOOL ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, uint32_t size, u_int flags) { struct ar5416_desc *ads = AR5416DESC(ds); HALASSERT((size &~ AR_BufLen) == 0); ads->ds_ctl1 = size & AR_BufLen; if (flags & HAL_RXDESC_INTREQ) ads->ds_ctl1 |= AR_RxIntrReq; /* this should be enough */ ads->ds_rxstatus8 &= ~AR_RxDone; return AH_TRUE; }
/* * Return a reference to the requested RF Bank. */ static u_int32_t * ar2316GetRfBank(struct ath_hal *ah, int bank) { struct ath_hal_5212 *ahp = AH5212(ah); AR5212_RF_BANKS_2316 *pRfBank2316 = ahp->ah_analogBanks; HALASSERT(ahp->ah_analogBanks != AH_NULL); switch (bank) { case 1: return pRfBank2316->Bank1Data; case 2: return pRfBank2316->Bank2Data; case 3: return pRfBank2316->Bank3Data; case 6: return pRfBank2316->Bank6Data; case 7: return pRfBank2316->Bank7Data; } HALDEBUG(ah, "%s: unknown RF Bank %d requested\n", __func__, bank); return AH_NULL; }
/* * Return a reference to the requested RF Bank. */ static u_int32_t * ar2425GetRfBank(struct ath_hal *ah, int bank) { struct ath_hal_5212 *ahp = AH5212(ah); AR5212_RF_BANKS_2425 *pRfBank2425 = ahp->ah_analogBanks; HALASSERT(ahp->ah_analogBanks != AH_NULL); switch (bank) { case 1: return pRfBank2425->Bank1Data; case 2: return pRfBank2425->Bank2Data; case 3: return pRfBank2425->Bank3Data; case 6: return pRfBank2425->Bank6Data; case 7: return pRfBank2425->Bank7Data; } HDPRINTF(ah, HAL_DBG_RF_PARAM, "%s: unknown RF Bank %d requested\n", __func__, bank); return AH_NULL; }
/* * Return a reference to the requested RF Bank. */ static uint32_t * ar2316GetRfBank(struct ath_hal *ah, int bank) { struct ar2316State *priv = AR2316(ah); HALASSERT(priv != AH_NULL); switch (bank) { case 1: return priv->Bank1Data; case 2: return priv->Bank2Data; case 3: return priv->Bank3Data; case 6: return priv->Bank6Data; case 7: return priv->Bank7Data; } HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", __func__, bank); return AH_NULL; }
static void ar5212AniCckErrTrigger(struct ath_hal *ah) { struct ath_hal_5212 *ahp = AH5212(ah); HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; struct ar5212AniState *aniState; WIRELESS_MODE mode; int32_t rssi; HALASSERT(chan != AH_NULL); if (!DO_ANI(ah)) return; /* first, raise noise immunity level, up to max */ aniState = ahp->ah_curani; if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1); return; } /* Do not play with OFDM and CCK weak detection in AP mode */ if( AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { return; } rssi = BEACON_RSSI(aniState); if (rssi > aniState->rssiThrLow) { /* * Beacon signal in mid and high range, raise firsteplevel. */ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); } else { /* * Beacon rssi is low, zero firstepLevel to maximize * CCK sensitivity. */ mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) chan); if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) { if (aniState->firstepLevel > 0) ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); } } }
/* * Configure GPIO Output lines */ HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) { uint32_t gpio_shift, reg; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); /* NB: type maps directly to hardware */ //cfgOutputMux(ah, gpio, type); gpio_shift = gpio << 1; /* 2 bits per output mode */ reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); return AH_TRUE; }
/* * Configure GPIO Input lines */ HAL_BOOL ar5416GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* TODO: configure input mux for AR5416 */ /* If configured as input, set output to tristate */ gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); return AH_TRUE; }
/* * Configure GPIO Input lines */ HAL_BOOL ar7010GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* If configured as input, set output to tristate */ gpio_shift = gpio; /* Per bit output enable. 1: enable the input driver */ OS_REG_RMW(ah, AR7010_GPIO_OE, (AR7010_GPIO_OE_AS_INPUT << gpio_shift), (AR7010_GPIO_OE_MASK << gpio_shift)); return AH_TRUE; }
/* * Configure GPIO Input lines */ HAL_BOOL ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) { uint32_t gpio_shift, reg; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); /* TODO: configure input mux for AR5416 */ /* If configured as input, set output to tristate */ gpio_shift = gpio << 1; reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); return AH_TRUE; }
HAL_BOOL ar5416FillTxDesc(struct ath_hal *ah, void *ds, dma_addr_t *bufAddr, u_int32_t *seg_len, u_int desc_id, u_int qcu, HAL_KEY_TYPE keyType, HAL_BOOL first_seg, HAL_BOOL last_seg, const void *ds0) { struct ar5416_desc *ads = AR5416DESC(ds); HALASSERT((seg_len[0] &~ AR_BufLen) == 0); OS_MEMZERO(&(ads->u.tx.tx_status), sizeof(ads->u.tx.tx_status)); /* Set the buffer addresses */ ads->ds_data = bufAddr[0]; if (first_seg) { /* * First descriptor, don't clobber xmit control data * setup by ar5416SetupTxDesc. */ ads->ds_ctl1 |= seg_len[0] | (last_seg ? 0 : AR_TxMore); } else if (last_seg) { /* !first_seg && last_seg */ /* * Last descriptor in a multi-descriptor frame, * copy the multi-rate transmit parameters from * the first frame for processing on completion. */ ads->ds_ctl0 = 0; ads->ds_ctl1 = seg_len[0]; #ifdef AH_NEED_DESC_SWAP ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); #else ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; #endif } else { /* !first_seg && !last_seg */ /* * Intermediate descriptor in a multi-descriptor frame. */ ads->ds_ctl0 = 0; ads->ds_ctl1 = seg_len[0] | AR_TxMore; ads->ds_ctl2 = 0; ads->ds_ctl3 = 0; } return AH_TRUE; }
/* * Calculate air time of a transmit packet */ u_int32_t ar5416CalcTxAirtime(struct ath_hal *ah, void *ds, struct ath_tx_status *ts, HAL_BOOL comp_wastedt, u_int8_t nbad, u_int8_t nframes) { struct ar5416_desc *ads = AR5416DESC(ds); int finalindex_tries; int status9; /* * Number of attempts made on the final index * Note: If no BA was recv, then the data_fail_cnt is the number of tries * made on the final index. If BA was recv, then add 1 to account for the * successful attempt. */ finalindex_tries = ts->ts_longretry + (ts->ts_flags & HAL_TX_BA)? 1 : 0; /* * Use a local copy of the ads in the cacheable memory to * improve the d-cache efficiency. */ status9 = ads->ds_txstatus9; status9 = MS(status9, AR_FinalTxIdx); /* * Calculate time of transmit on air for packet including retries * at different rates. */ if (status9 == 0) { return MS(ads->ds_ctl4, AR_PacketDur0) * finalindex_tries; } else if (status9 == 1) { return (MS(ads->ds_ctl4, AR_PacketDur1) * finalindex_tries) + (MS(ads->ds_ctl2, AR_XmitDataTries0) * MS(ads->ds_ctl4, AR_PacketDur0)); } else if (status9 == 2) { return (MS(ads->ds_ctl5, AR_PacketDur2) * finalindex_tries) + (MS(ads->ds_ctl2, AR_XmitDataTries1) * MS(ads->ds_ctl4, AR_PacketDur1)) + (MS(ads->ds_ctl2, AR_XmitDataTries0) * MS(ads->ds_ctl4, AR_PacketDur0)); } else if (status9 == 3) { return (MS(ads->ds_ctl5, AR_PacketDur3) * finalindex_tries) + (MS(ads->ds_ctl2, AR_XmitDataTries2) * MS(ads->ds_ctl5, AR_PacketDur2)) + (MS(ads->ds_ctl2, AR_XmitDataTries1) * MS(ads->ds_ctl4, AR_PacketDur1)) + (MS(ads->ds_ctl2, AR_XmitDataTries0) * MS(ads->ds_ctl4, AR_PacketDur0)); } else { HALASSERT(0); return 0; } }
/* * Configure GPIO Output lines - LED Off */ HAL_BOOL ar5416GpioCfgOutputLEDoff(struct ath_hal *ah, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE halSignalType) { #define N(a) (sizeof(a)/sizeof(a[0])) u_int32_t ah_signal_type; u_int32_t gpio_shift; static const u_int32_t MuxSignalConversionTable[] = { /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT */ AR_GPIO_OUTPUT_MUX_AS_OUTPUT, /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */ AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED */ AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED */ AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED */ AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE */ AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL, /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME */ AR_GPIO_OUTPUT_MUX_AS_TX_FRAME, }; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); // Convert HAL signal type definitions to hardware-specific values. if ((halSignalType >= 0) && (halSignalType < N(MuxSignalConversionTable))) { ah_signal_type = MuxSignalConversionTable[halSignalType]; } else { return AH_FALSE; } // Configure the MUX ar5416GpioCfgOutputMux(ah, gpio, ah_signal_type); // 2 bits per output mode gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); return AH_TRUE; #undef N }
/* * Return indices surrounding the value in sorted integer lists. * * NB: the input list is assumed to be sorted in ascending order */ static void GetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, uint32_t *vlo, uint32_t *vhi) { int16_t target = v; const int16_t *ep = lp+listSize; const int16_t *tp; /* * Check first and last elements for out-of-bounds conditions. */ if (target < lp[0]) { *vlo = *vhi = 0; return; } if (target >= ep[-1]) { *vlo = *vhi = listSize - 1; return; } /* look for value being near or between 2 values in list */ for (tp = lp; tp < ep; tp++) { /* * If value is close to the current value of the list * then target is not between values, it is one of the values */ if (*tp == target) { *vlo = *vhi = tp - (const int16_t *) lp; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < tp[1]) { *vlo = tp - (const int16_t *) lp; *vhi = *vlo + 1; return; } } HALASSERT(AH_FALSE); /* should not reach here */ *vlo = *vhi = 0; }
/* * Configure GPIO Input lines */ HAL_BOOL ar9300GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { #ifndef AR9340_EMULATION u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); /* TODO: configure input mux for AR9300 */ /* If configured as input, set output to tristate */ gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); #endif return AH_TRUE; }
HAL_BOOL ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int32_t size, u_int flags) { struct ar5416_desc *ads = AR5416DESC(ds); HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; HALASSERT((size &~ AR_BufLen) == 0); ads->ds_ctl1 = size & AR_BufLen; if (flags & HAL_RXDESC_INTREQ) ads->ds_ctl1 |= AR_RxIntrReq; /* this should be enough */ ads->ds_rxstatus8 &= ~AR_RxDone; if (! pCap->halAutoSleepSupport) { /* If AutoSleep not supported, clear all fields. */ OS_MEMZERO(&(ads->u), sizeof(ads->u)); } return AH_TRUE; }
/* * Get the TXDP for the "main" data queue. Needs to be extended * for multiple Q functionality */ uint32_t ar5210GetTxDP(struct ath_hal *ah, u_int q) { struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; HALASSERT(q < HAL_NUM_TX_QUEUES); qi = &ahp->ah_txq[q]; switch (qi->tqi_type) { case HAL_TX_QUEUE_DATA: return OS_REG_READ(ah, AR_TXDP0); case HAL_TX_QUEUE_INACTIVE: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", __func__, q); /* fall thru... */ default: break; } return 0xffffffff; }
/* * Initializes all of the hardware registers used to * send beacons. Note that for station operation the * driver calls ar9300_set_sta_beacon_timers instead. */ static void ar9300_beacon_set_beacon_timers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) { uint32_t bperiod; #if 0 HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP); if (opmode == HAL_M_IBSS) { OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); } #endif /* XXX TODO: should migrate the HAL code to always use ONE_EIGHTH_TU */ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bt->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); /* XXX TODO! */ // ahp->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); }
/* * Update ani stats in preparation for listen time processing. */ static void updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState) { struct ath_hal_5212 *ahp = AH5212(ah); const struct ar5212AniParams *params = aniState->params; uint32_t phyCnt1, phyCnt2; int32_t ofdmPhyErrCnt, cckPhyErrCnt; HALASSERT(ahp->ah_hasHwPhyCounters); /* Clear the mib counters and save them in the stats */ ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* NB: these are not reset-on-read */ phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1); phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2); /* NB: these are spec'd to never roll-over */ ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase; if (ofdmPhyErrCnt < 0) { HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n", ofdmPhyErrCnt, phyCnt1); ofdmPhyErrCnt = AR_PHY_COUNTMAX; } ahp->ah_stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount; aniState->ofdmPhyErrCount = ofdmPhyErrCnt; cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase; if (cckPhyErrCnt < 0) { HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n", cckPhyErrCnt, phyCnt2); cckPhyErrCnt = AR_PHY_COUNTMAX; } ahp->ah_stats.ast_ani_cckerrs += cckPhyErrCnt - aniState->cckPhyErrCount; aniState->cckPhyErrCount = cckPhyErrCnt; }
/* * Set the TxDP for the "main" data queue. */ HAL_BOOL ar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) { struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; HALASSERT(q < HAL_NUM_TX_QUEUES); HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", __func__, q, txdp); qi = &ahp->ah_txq[q]; switch (qi->tqi_type) { case HAL_TX_QUEUE_DATA: #ifdef AH_DEBUG /* * Make sure that TXE is deasserted before setting the * TXDP. If TXE is still asserted, setting TXDP will * have no effect. */ if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", __func__, OS_REG_READ(ah, AR_CR)); #endif OS_REG_WRITE(ah, AR_TXDP0, txdp); break; case HAL_TX_QUEUE_BEACON: case HAL_TX_QUEUE_CAB: OS_REG_WRITE(ah, AR_TXDP1, txdp); break; case HAL_TX_QUEUE_INACTIVE: HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", __func__, q); /* fall thru... */ default: return AH_FALSE; } return AH_TRUE; }
/* * Set the GPIO Interrupt */ void ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) { uint32_t val; HALASSERT(gpio < AR_NUM_GPIO); /* XXX bounds check gpio */ val = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_INTR_CTRL); if (ilevel) /* 0 == interrupt on pin high */ val &= ~AR_GPIO_BIT(gpio); else /* 1 == interrupt on pin low */ val |= AR_GPIO_BIT(gpio); OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_INTR_CTRL, val); /* Change the interrupt mask. */ val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), AR_INTR_GPIO); val |= AR_GPIO_BIT(gpio); OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_GPIO, val); val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), AR_INTR_GPIO); val |= AR_GPIO_BIT(gpio); OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, AR_INTR_GPIO, val); }
HAL_BOOL ar5210FillTxDesc(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) { struct ar5210_desc *ads = AR5210DESC(ds); uint32_t segLen = segLenList[0]; HALASSERT((segLen &~ AR_BufLen) == 0); ds->ds_data = bufAddrList[0]; if (firstSeg) { /* * First descriptor, don't clobber xmit control data * setup by ar5210SetupTxDesc. */ ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); } else if (lastSeg) { /* !firstSeg && lastSeg */ /* * Last descriptor in a multi-descriptor frame, * copy the transmit parameters from the first * frame for processing on completion. */ ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; ads->ds_ctl1 = segLen; } else { /* !firstSeg && !lastSeg */ /* * Intermediate descriptor in a multi-descriptor frame. */ ads->ds_ctl0 = 0; ads->ds_ctl1 = segLen | AR_More; } ads->ds_status0 = ads->ds_status1 = 0; return AH_TRUE; }
uint32_t ar5210NumTxPending(struct ath_hal *ah, u_int q) { struct ath_hal_5210 *ahp = AH5210(ah); HAL_TX_QUEUE_INFO *qi; uint32_t v; HALASSERT(q < HAL_NUM_TX_QUEUES); HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); qi = &ahp->ah_txq[q]; switch (qi->tqi_type) { case HAL_TX_QUEUE_DATA: v = OS_REG_READ(ah, AR_CFG); return MS(v, AR_CFG_TXCNT); case HAL_TX_QUEUE_INACTIVE: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", __func__, q); /* fall thru... */ default: break; } return 0; }
int16_t ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index, u_int8_t chainmask, u_int8_t xmit_mode) { struct ath_hal_9300 *ahp = AH9300(ah); int num_chains = ar9300_get_ntxchains(chainmask); switch (xmit_mode) { case AR9300_DEF_MODE: return ahp->txpower[rate_index][num_chains-1]; case AR9300_STBC_MODE: return ahp->txpower_stbc[rate_index][num_chains-1]; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n", __func__, xmit_mode); HALASSERT(0); break; } return ahp->txpower[rate_index][num_chains-1]; }
/* * Configure GPIO Output lines */ HAL_BOOL ar7010GpioCfgOutput(struct ath_hal *ah, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE halSignalType) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* Magpie only support GPIO normal output */ if (halSignalType > HAL_GPIO_OUTPUT_MUX_AS_OUTPUT) { return AH_FALSE; } /* 1 bits per output mode */ gpio_shift = gpio; /* Per bit output enable. 0: enable the output driver */ OS_REG_RMW(ah, AR7010_GPIO_OE, (AR7010_GPIO_OE_AS_OUTPUT<< gpio_shift), (AR7010_GPIO_OE_MASK << gpio_shift)); return AH_TRUE; }
static void ar9285AniSetup(struct ath_hal *ah) { /* * These are the parameters from the AR5416 ANI code; * they likely need quite a bit of adjustment for the * AR9285. */ 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 = 7, .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, }; /* NB: disable ANI noise immmunity for reliable RIFS rx */ AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); } static const char * ar9285_lna_conf[] = { "LNA1-LNA2", "LNA2", "LNA1", "LNA1+LNA2", }; static void ar9285_eeprom_print_diversity_settings(struct ath_hal *ah) { const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; ath_hal_printf(ah, "[ath] AR9285 Main LNA config: %s\n", ar9285_lna_conf[(pModal->antdiv_ctl2 >> 2) & 0x3]); ath_hal_printf(ah, "[ath] AR9285 Alt LNA config: %s\n", ar9285_lna_conf[pModal->antdiv_ctl2 & 0x3]); ath_hal_printf(ah, "[ath] LNA diversity %s, Diversity %s\n", ((pModal->antdiv_ctl1 & 0x1) ? "enabled" : "disabled"), ((pModal->antdiv_ctl1 & 0x8) ? "enabled" : "disabled")); } /* * Attach for an AR9285 part. */ static struct ath_hal * ar9285Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *status) { struct ath_hal_9285 *ahp9285; struct ath_hal_5212 *ahp; struct ath_hal *ah; uint32_t val; HAL_STATUS ecode; HAL_BOOL rfStatus; 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 */ ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); if (ahp9285 == AH_NULL) { HALDEBUG(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; } ahp = AH5212(ahp9285); ah = &ahp->ah_priv.h; ar5416InitState(AH5416(ah), devid, sc, st, sh, status); /* * Use the "local" EEPROM data given to us by the higher layers. * This is a private copy out of system flash. The Linux ath9k * commit for the initial AR9130 support mentions MMIO flash * access is "unreliable." -adrian */ if (eepromdata != AH_NULL) { AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead; AH_PRIVATE(ah)->ah_eepromWrite = NULL; ah->ah_eepromdata = eepromdata; } /* override with 9285 specific state */ AH5416(ah)->ah_initPLL = ar9280InitPLL; AH5416(ah)->ah_btCoexSetDiversity = ar9285BTCoexAntennaDiversity; ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch; ah->ah_configPCIE = ar9285ConfigPCIE; ah->ah_disablePCIE = ar9285DisablePCIE; ah->ah_setTxPower = ar9285SetTransmitPower; ah->ah_setBoardValues = ar9285SetBoardValues; ah->ah_btCoexSetParameter = ar9285BTCoexSetParameter; ah->ah_divLnaConfGet = ar9285_antdiv_comb_conf_get; ah->ah_divLnaConfSet = ar9285_antdiv_comb_conf_set; AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; AH5416(ah)->ah_writeIni = ar9285WriteIni; AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__); ecode = HAL_EIO; goto bad; } if (!ar5416SetPowerMode(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); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); /* NB: include chip type to differentiate from pre-Sowl versions */ AH_PRIVATE(ah)->ah_macVersion = (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; /* setup common ini data; rf backends handle remainder */ if (AR_SREV_KITE_12_OR_LATER(ah)) { HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6); HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2); HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9285PciePhy_clkreq_always_on_L1_v2, 2); } else { HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6); HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2); HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9285PciePhy_clkreq_always_on_L1, 2); } ar5416AttachPCIE(ah); /* Attach methods that require MAC version/revision info */ if (AR_SREV_KITE_12_OR_LATER(ah)) AH5416(ah)->ah_cal_initcal = ar9285InitCalHardware; if (AR_SREV_KITE_11_OR_LATER(ah)) AH5416(ah)->ah_cal_pacal = ar9002_hw_pa_cal; ecode = ath_hal_v4kEepromAttach(ah); if (ecode != HAL_OK) goto bad; if (!ar5416ChipReset(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 (!ar5212ChipTest(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. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); /* Read Radio Chip Rev Extract */ AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ break; default: if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { AH_PRIVATE(ah)->ah_analog5GhzRev = AR_RAD5133_SREV_MAJOR; 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 } rfStatus = ar9285RfAttach(ah, &ecode); if (!rfStatus) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", __func__, ecode); goto bad; } HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2, 6); if (AR_SREV_9285E_20(ah)) ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n"); /* setup txgain table */ switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { case AR5416_EEP_TXGAIN_HIGH_POWER: if (AR_SREV_9285E_20(ah)) HAL_INI_INIT(&ahp9285->ah_ini_txgain, ar9285Modes_XE2_0_high_power, 6); else HAL_INI_INIT(&ahp9285->ah_ini_txgain, ar9285Modes_high_power_tx_gain_v2, 6); break; case AR5416_EEP_TXGAIN_ORIG: if (AR_SREV_9285E_20(ah)) HAL_INI_INIT(&ahp9285->ah_ini_txgain, ar9285Modes_XE2_0_normal_power, 6); else HAL_INI_INIT(&ahp9285->ah_ini_txgain, ar9285Modes_original_tx_gain_v2, 6); break; default: HALASSERT(AH_FALSE); goto bad; /* XXX ? try to continue */ } /* * Got everything we need now to setup the capabilities. */ if (!ar9285FillCapabilityInfo(ah)) { ecode = HAL_EEREAD; goto bad; } /* * Print out the EEPROM antenna configuration mapping. * Some devices have a hard-coded LNA configuration profile; * others enable diversity. */ ar9285_eeprom_print_diversity_settings(ah); /* Print out whether the EEPROM settings enable AR9285 diversity */ if (ar9285_check_div_comb(ah)) { ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n"); } /* Disable 11n for the AR2427 */ if (devid == AR2427_DEVID_PCIE) AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE; 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; } /* XXX How about the serial number ? */ /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); /* * For Kite and later chipsets, the following bits are not * programmed in EEPROM and so are set as enabled always. */ AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT; /* * ah_miscMode is populated by ar5416FillCapabilityInfo() * starting from griffin. Set here to make sure that * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is * placed into hardware. */ if (ahp->ah_miscMode != 0) OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); ar9285AniSetup(ah); /* Anti Noise Immunity */ /* Setup noise floor min/max/nominal values */ AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; /* XXX no 5ghz values? */ ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); return ah; bad: if (ah != AH_NULL) ah->ah_detach(ah); if (status) *status = ecode; return AH_NULL; } static void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) { uint32_t val; /* * This workaround needs some integration work with the HAL * config parameters and the if_ath_pci.c glue. * Specifically, read the value of the PCI register 0x70c * (4 byte PCI config space register) and store it in ath_hal_war70c. * Then if it's non-zero, the below WAR would override register * 0x570c upon suspend/resume. */ #if 0 if (AR_SREV_9285E_20(ah)) { val = AH_PRIVATE(ah)->ah_config.ath_hal_war70c; if (val) { val &= 0xffff00ff; val |= 0x6f00; OS_REG_WRITE(ah, 0x570c, val); } } #endif if (AH_PRIVATE(ah)->ah_ispcie && !restore) { ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); OS_DELAY(1000); } /* * Set PCIe workaround bits * * NOTE: * * In Merlin and Kite, bit 14 in WA register (disable L1) should only * be set when device enters D3 and be cleared when device comes back * to D0. */ if (power_off) { /* Power-off */ OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); val = OS_REG_READ(ah, AR_WA); /* * Disable bit 6 and 7 before entering D3 to prevent * system hang. */ val &= ~(AR_WA_BIT6 | AR_WA_BIT7); /* * See above: set AR_WA_D3_L1_DISABLE when entering D3 state. * * XXX The reference HAL does it this way - it only sets * AR_WA_D3_L1_DISABLE if it's set in AR9280_WA_DEFAULT, * which it (currently) isn't. So the following statement * is currently a NOP. */ if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE) val |= AR_WA_D3_L1_DISABLE; if (AR_SREV_9285E_20(ah)) val |= AR_WA_BIT23; OS_REG_WRITE(ah, AR_WA, val); } else { /* Power-on */ val = AR9285_WA_DEFAULT; /* * See note above: make sure L1_DISABLE is not set. */ val &= (~AR_WA_D3_L1_DISABLE); /* Software workaroud for ASPM system hang. */ val |= (AR_WA_BIT6 | AR_WA_BIT7); if (AR_SREV_9285E_20(ah)) val |= AR_WA_BIT23; OS_REG_WRITE(ah, AR_WA, val); /* set bit 19 to allow forcing of pcie core into L1 state */ OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); } }
/* * Set all the beacon related bits on the h/w for stations * i.e. initializes the corresponding h/w timers; * also tells the h/w whether to anticipate PCF beacons * * dtim_count and cfp_count from the current beacon - their current * values aren't necessarily maintained in the device struct */ void ar5210SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) { struct ath_hal_5210 *ahp = AH5210(ah); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__); HALASSERT(bs->bs_intval != 0); /* if the AP will do PCF */ if (bs->bs_cfpmaxduration != 0) { /* tell the h/w that the associated AP is PCF capable */ OS_REG_WRITE(ah, AR_STA_ID1, (OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_DEFAULT_ANTENNA) | AR_STA_ID1_PCF); /* set CFP_PERIOD(1.024ms) register */ OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod); /* set CFP_DUR(1.024ms) register to max cfp duration */ OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration); /* set TIMER2(128us) to anticipated time of next CFP */ OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3); } else { /* tell the h/w that the associated AP is not PCF capable */ OS_REG_WRITE(ah, AR_STA_ID1, OS_REG_READ(ah, AR_STA_ID1) &~ (AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); } /* * Set TIMER0(1.024ms) to the anticipated time of the next beacon. */ OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt); /* * Start the beacon timers by setting the BEACON register * to the beacon interval; also write the tim offset which * we should know by now. The code, in ar5211WriteAssocid, * also sets the tim offset once the AID is known which can * be left as such for now. */ OS_REG_WRITE(ah, AR_BEACON, (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM)) | SM(bs->bs_intval, AR_BEACON_PERIOD) | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM) ); /* * Configure the BMISS interrupt. Note that we * assume the caller blocks interrupts while enabling * the threshold. */ /* * Interrupt works only on Crete. */ if (AH_PRIVATE(ah)->ah_macRev < AR_SREV_CRETE) return; /* * Counter is only 3-bits. * Count of 0 with BMISS interrupt enabled will hang the system * with too many interrupts */ if (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_CRETE && (bs->bs_bmissthreshold&7) == 0) { #ifdef AH_DEBUG ath_hal_printf(ah, "%s: invalid beacon miss threshold %u\n", __func__, bs->bs_bmissthreshold); #endif return; } #define BMISS_MAX (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S) /* * Configure the BMISS interrupt. Note that we * assume the caller blocks interrupts while enabling * the threshold. * * NB: the beacon miss count field is only 3 bits which * is much smaller than what's found on later parts; * clamp overflow values as a safeguard. */ ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR) | SM(bs->bs_bmissthreshold > BMISS_MAX ? BMISS_MAX : bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR); OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); #undef BMISS_MAX }
static HAL_BOOL ar9280SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) { struct ath_hal_5416 *ahp = AH5416(ah); u_int16_t bMode, fracMode, aModeRefSel = 0; u_int32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; CHAN_CENTERS centers; u_int32_t refDivA = 24; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); ar5416GetChannelCenters(ah, chan, ¢ers); freq = centers.synth_center; reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; if (freq < 4800) { /* 2 GHz, fractional mode */ u_int32_t txctl; int regWrites = 0; bMode = 1; fracMode = 1; aModeRefSel = 0; channelSel = (freq * 0x10000)/15; if (AR_SREV_KIWI_11_OR_LATER(ah)) { if (freq == 2484) { REG_WRITE_ARRAY(&ahp->ah_iniCckfirJapan2484, 1, regWrites); } else { REG_WRITE_ARRAY(&ahp->ah_iniCckfirNormal, 1, regWrites); } } else { txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); if (freq == 2484) { /* Enable channel spreading for channel 14 */ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl | AR_PHY_CCK_TX_CTRL_JAPAN); } else { OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); } } } else { bMode = 0; fracMode = 0; HALASSERT(aModeRefSel == 0); switch (ar5416EepromGet(ahp, EEP_FRAC_N_5G)) { case 0: if ((freq % 20) == 0) { aModeRefSel = 3; } else if ((freq % 10) == 0) { aModeRefSel = 2; } if (aModeRefSel) break; case 1: default: aModeRefSel = 0; /* Enable 2G (fractional) mode for channels which are 5MHz spaced */ fracMode = 1; refDivA = 1; channelSel = (freq * 0x8000)/15; /* RefDivA setting */ analogShiftRegRMW(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, AR_AN_SYNTH9_REFDIVA_S, refDivA); } if (!fracMode) { ndiv = (freq * (refDivA >> aModeRefSel))/60; channelSel = ndiv & 0x1ff; channelFrac = (ndiv & 0xfffffe00) * 2; channelSel = (channelSel << 17) | channelFrac; } }