diff options
Diffstat (limited to 'sys/dev/ath/ath_hal/ar5210')
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210.h | 305 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_attach.c | 419 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c | 202 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c | 134 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c | 156 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_misc.c | 733 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_phy.c | 85 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_power.c | 138 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_recv.c | 269 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_reset.c | 1005 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c | 670 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210desc.h | 130 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210phy.h | 59 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5210reg.h | 413 | ||||
| -rw-r--r-- | sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini | 192 |
15 files changed, 4910 insertions, 0 deletions
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h new file mode 100644 index 000000000000..567fea567cba --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -0,0 +1,305 @@ +/*- + * 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. + */ +#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 *, HAL_POWER_MODE mode, + 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 new file mode 100644 index 000000000000..4f67330ca830 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -0,0 +1,419 @@ +/*- + * 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. + */ +#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_beacon.c b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c new file mode 100644 index 000000000000..96c31ddc6d70 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c @@ -0,0 +1,202 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Return the hardware NextTBTT in TSF + */ +uint64_t +ar5210GetNextTBTT(struct ath_hal *ah) +{ +#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10) + return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0)); +#undef TU_TO_TSF +} + +/* + * Initialize all of the hardware registers used to send beacons. + */ +void +ar5210SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) +{ + + OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt); + OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba); + OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba); + OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim); + /* + * Set the Beacon register after setting all timers. + */ + OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval); +} + +/* + * Legacy api to Initialize all of the beacon registers. + */ +void +ar5210BeaconInit(struct ath_hal *ah, + uint32_t next_beacon, uint32_t beacon_period) +{ + HAL_BEACON_TIMERS bt; + + bt.bt_nexttbtt = next_beacon; + + if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) { + bt.bt_nextdba = (next_beacon - + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + bt.bt_nextswba = (next_beacon - + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + /* + * The SWBA interrupt is not used for beacons in ad hoc mode + * as we don't yet support ATIMs. So since the beacon never + * changes, the beacon descriptor is set up once and read + * into a special HW buffer, from which it will be + * automagically retrieved at each DMA Beacon Alert (DBA). + */ + + /* Set the ATIM window */ + bt.bt_nextatim = next_beacon + 0; /* NB: no ATIMs */ + } else { + bt.bt_nextdba = ~0; + bt.bt_nextswba = ~0; + bt.bt_nextatim = 1; + } + bt.bt_intval = beacon_period & + (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); + ar5210SetBeaconTimers(ah, &bt); +} + +void +ar5210ResetStaBeaconTimers(struct ath_hal *ah) +{ + uint32_t val; + + OS_REG_WRITE(ah, AR_TIMER0, 0); /* no beacons */ + val = OS_REG_READ(ah, AR_STA_ID1); + val |= AR_STA_ID1_NO_PSPOLL; /* XXX */ + /* tell the h/w that the associated AP is not PCF capable */ + OS_REG_WRITE(ah, AR_STA_ID1, + val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF)); + OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD); +} + +/* + * 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 +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c b/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c new file mode 100644 index 000000000000..63baafd11d9f --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c @@ -0,0 +1,134 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Return non-zero if an interrupt is pending. + */ +HAL_BOOL +ar5210IsInterruptPending(struct ath_hal *ah) +{ + return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE); +} + +/* + * Read the Interrupt Status Register value and return + * an abstracted bitmask of the data found in the ISR. + * Note that reading the ISR clear pending interrupts. + */ +HAL_BOOL +ar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) +{ +#define AR_FATAL_INT \ + (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT) + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t isr; + + isr = OS_REG_READ(ah, AR_ISR); + if (isr == 0xffffffff) { + *masked = 0; + return AH_FALSE; + } + + /* + * Mask interrupts that have no device-independent + * representation; these are added back below. We + * also masked with the abstracted IMR to insure no + * status bits leak through that weren't requested + * (e.g. RXNOFRM) and that might confuse the caller. + */ + *masked = (isr & (HAL_INT_COMMON - HAL_INT_BNR)) & ahp->ah_maskReg; + + if (isr & AR_FATAL_INT) + *masked |= HAL_INT_FATAL; + if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT)) + *masked |= HAL_INT_RX; + if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT)) + *masked |= HAL_INT_TX; + + /* + * On fatal errors collect ISR state for debugging. + */ + if (*masked & HAL_INT_FATAL) { + AH_PRIVATE(ah)->ah_fatalState[0] = isr; + } + + return AH_TRUE; +#undef AR_FATAL_INT +} + +HAL_INT +ar5210GetInterrupts(struct ath_hal *ah) +{ + return AH5210(ah)->ah_maskReg; +} + +HAL_INT +ar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t omask = ahp->ah_maskReg; + uint32_t mask; + + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", + __func__, omask, ints); + + /* + * Disable interrupts here before reading & modifying + * the mask so that the ISR does not modify the mask + * out from under us. + */ + if (omask & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + } + + mask = ints & (HAL_INT_COMMON - HAL_INT_BNR); + if (ints & HAL_INT_RX) + mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT; + if (ints & HAL_INT_TX) { + if (ahp->ah_txOkInterruptMask) + mask |= AR_IMR_TXOK_INT; + if (ahp->ah_txErrInterruptMask) + mask |= AR_IMR_TXERR_INT; + if (ahp->ah_txDescInterruptMask) + mask |= AR_IMR_TXDESC_INT; + if (ahp->ah_txEolInterruptMask) + mask |= AR_IMR_TXEOL_INT; + } + + /* Write the new IMR and store off our SW copy. */ + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); + OS_REG_WRITE(ah, AR_IMR, mask); + ahp->ah_maskReg = ints; + + /* Re-enable interrupts as appropriate. */ + if (ints & HAL_INT_GLOBAL) { + HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); + OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + } + + return omask; +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c b/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c new file mode 100644 index 000000000000..4a04a2760902 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c @@ -0,0 +1,156 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +#define AR_KEYTABLE_SIZE 64 +#define KEY_XOR 0xaa + +/* + * Return the size of the hardware key cache. + */ +u_int +ar5210GetKeyCacheSize(struct ath_hal *ah) +{ + return AR_KEYTABLE_SIZE; +} + +/* + * Return the size of the hardware key cache. + */ +HAL_BOOL +ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Clear the specified key cache entry. + */ +HAL_BOOL +ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) +{ + if (entry < AR_KEYTABLE_SIZE) { + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the mac part of the specified key cache entry and mark it valid. + */ +HAL_BOOL +ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) +{ + uint32_t macHi, macLo; + + if (entry < AR_KEYTABLE_SIZE) { + /* + * Set MAC address -- shifted right by 1. MacLo is + * the 4 MSBs, and MacHi is the 2 LSBs. + */ + if (mac != AH_NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24)| (mac[2] << 16) + | (mac[1] << 8) | mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; /* carry */ + macHi >>= 1; + } else { + macLo = macHi = 0; + } + + OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), + macHi | AR_KEYTABLE_VALID); + return AH_TRUE; + } + return AH_FALSE; +} + +/* + * Sets the contents of the specified key cache entry. + */ +HAL_BOOL +ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, + const HAL_KEYVAL *k, const uint8_t *mac, int xorKey) +{ + uint32_t key0, key1, key2, key3, key4; + uint32_t keyType; + uint32_t xorMask= xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + + if (entry >= AR_KEYTABLE_SIZE) + return AH_FALSE; + if (k->kv_type != HAL_CIPHER_WEP) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_FALSE; + } + + /* NB: only WEP supported */ + if (k->kv_len < 40 / NBBY) + return AH_FALSE; + if (k->kv_len <= 40 / NBBY) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= 104 / NBBY) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + + key0 = LE_READ_4(k->kv_val+0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val+6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val+12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) + key4 &= 0xff; + + /* + * Note: WEP key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * understanding this! + */ + OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + return ar5210SetKeyCacheEntryMac(ah, entry, mac); +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c new file mode 100644 index 000000000000..209dcfa9114a --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c @@ -0,0 +1,733 @@ +/*- + * 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. + */ +#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)<<AR_BSS_ID1_AID_S)); + if (assocId == 0) + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); + else + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); +} + +/* + * Get the current hardware tsf for stamlme. + */ +uint64_t +ar5210GetTsf64(struct ath_hal *ah) +{ + uint32_t low1, low2, u32; + + /* sync multi-word read */ + low1 = OS_REG_READ(ah, AR_TSF_L32); + u32 = OS_REG_READ(ah, AR_TSF_U32); + low2 = OS_REG_READ(ah, AR_TSF_L32); + if (low2 < low1) { /* roll over */ + /* + * If we are not preempted this will work. If we are + * then we re-reading AR_TSF_U32 does no good as the + * low bits will be meaningless. Likewise reading + * L32, U32, U32, then comparing the last two reads + * to check for rollover doesn't help if preempted--so + * we take this approach as it costs one less PCI + * read which can be noticeable when doing things + * like timestamping packets in monitor mode. + */ + u32++; + } + return (((uint64_t) u32) << 32) | ((uint64_t) low2); +} + +/* + * Get the current hardware tsf for stamlme. + */ +uint32_t +ar5210GetTsf32(struct ath_hal *ah) +{ + return OS_REG_READ(ah, AR_TSF_L32); +} + +/* + * Reset the current hardware tsf for stamlme + */ +void +ar5210ResetTsf(struct ath_hal *ah) +{ + uint32_t val = OS_REG_READ(ah, AR_BEACON); + + OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); +} + +/* + * Grab a semi-random value from hardware registers - may not + * change often + */ +uint32_t +ar5210GetRandomSeed(struct ath_hal *ah) +{ + uint32_t nf; + + nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 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/ar5210/ar5210_phy.c b/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c new file mode 100644 index 000000000000..10ac4fe49413 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c @@ -0,0 +1,85 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" + +/* shorthands to compact tables for readability */ +#define OFDM IEEE80211_T_OFDM +#define TURBO IEEE80211_T_TURBO + +HAL_RATE_TABLE ar5210_11a_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 } + }, +}; + +HAL_RATE_TABLE ar5210_turbo_table = { + 8, /* number of rates */ + { 0 }, + { +/* short ctrl */ +/* valid rateCode Preamble dot11Rate Rate */ +/* 6 Mb */ { AH_TRUE, TURBO, 12000, 0x0b, 0x00, (0x80|12), 0 }, +/* 9 Mb */ { AH_TRUE, TURBO, 18000, 0x0f, 0x00, 18, 0 }, +/* 12 Mb */ { AH_TRUE, TURBO, 24000, 0x0a, 0x00, (0x80|24), 2 }, +/* 18 Mb */ { AH_TRUE, TURBO, 36000, 0x0e, 0x00, 36, 2 }, +/* 24 Mb */ { AH_TRUE, TURBO, 48000, 0x09, 0x00, (0x80|48), 4 }, +/* 36 Mb */ { AH_TRUE, TURBO, 72000, 0x0d, 0x00, 72, 4 }, +/* 48 Mb */ { AH_TRUE, TURBO, 96000, 0x08, 0x00, 96, 4 }, +/* 54 Mb */ { AH_TRUE, TURBO, 108000, 0x0c, 0x00, 108, 4 } + }, +}; + +#undef OFDM +#undef TURBO + +const HAL_RATE_TABLE * +ar5210GetRateTable(struct ath_hal *ah, u_int mode) +{ + HAL_RATE_TABLE *rt; + switch (mode) { + case HAL_MODE_11A: + rt = &ar5210_11a_table; + break; + case HAL_MODE_TURBO: + rt = &ar5210_turbo_table; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", + __func__, mode); + return AH_NULL; + } + ath_hal_setupratetable(ah, rt); + return rt; +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_power.c b/sys/dev/ath/ath_hal/ar5210/ar5210_power.c new file mode 100644 index 000000000000..7aa5883ba2a8 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_power.c @@ -0,0 +1,138 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, set Power Mode of chip to auto/normal. + */ +static void +ar5210SetPowerModeAuto(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_ALLOW); +} + +/* + * Notify Power Mgt is enabled in self-generated frames. + * If requested, force chip awake. + * + * Returns A_OK if chip is awake or successfully forced awake. + * + * WARNING WARNING WARNING + * There is a problem with the chip where sometimes it will not wake up. + */ +static HAL_BOOL +ar5210SetPowerModeAwake(struct ath_hal *ah, int setChip) +{ +#define POWER_UP_TIME 2000 + uint32_t val; + int i; + + if (setChip) { + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_WAKE); + OS_DELAY(2000); /* Give chip the chance to awake */ + + for (i = POWER_UP_TIME / 200; i != 0; i--) { + val = OS_REG_READ(ah, AR_PCICFG); + if ((val & AR_PCICFG_SPWR_DN) == 0) + break; + OS_DELAY(200); + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, + AR_SCR_SLE_WAKE); + } + if (i == 0) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n", + __func__, POWER_UP_TIME/20); +#endif + return AH_FALSE; + } + } + + OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + return AH_TRUE; +#undef POWER_UP_TIME +} + +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */ +static void +ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip) +{ + OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SV); + if (setChip) + OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLE, AR_SCR_SLE_SLP); +} + +HAL_BOOL +ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) +{ +#ifdef AH_DEBUG + static const char* modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; +#endif + int status = AH_TRUE; + + HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, + modes[ah->ah_powerMode], modes[mode], + setChip ? "set chip " : ""); + switch (mode) { + case HAL_PM_AWAKE: + if (setChip) + ah->ah_powerMode = mode; + status = ar5210SetPowerModeAwake(ah, setChip); + break; + case HAL_PM_FULL_SLEEP: + ar5210SetPowerModeSleep(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + case HAL_PM_NETWORK_SLEEP: + ar5210SetPowerModeAuto(ah, setChip); + if (setChip) + ah->ah_powerMode = mode; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", + __func__, mode); + return AH_FALSE; + } + return status; +} + +HAL_POWER_MODE +ar5210GetPowerMode(struct ath_hal *ah) +{ + /* Just so happens the h/w maps directly to the abstracted value */ + return MS(OS_REG_READ(ah, AR_SCR), AR_SCR_SLE); +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c new file mode 100644 index 000000000000..47ea92688104 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c @@ -0,0 +1,269 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210desc.h" + +/* + * Get the RXDP. + */ +uint32_t +ar5210GetRxDP(struct ath_hal *ah, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + return OS_REG_READ(ah, AR_RXDP); +} + +/* + * Set the RxDP. + */ +void +ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) +{ + + HALASSERT(qtype == HAL_RX_QUEUE_HP); + OS_REG_WRITE(ah, AR_RXDP, rxdp); +} + +/* + * Set Receive Enable bits. + */ +void +ar5210EnableReceive(struct ath_hal *ah) +{ + OS_REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +/* + * Stop Receive at the DMA engine + */ +HAL_BOOL +ar5210StopDmaReceive(struct ath_hal *ah) +{ + int i; + + OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) + return AH_TRUE; + OS_DELAY(10); + } +#ifdef AH_DEBUG + ath_hal_printf(ah, "ar5210: dma receive failed to stop in 10ms\n"); + ath_hal_printf(ah, "AR_CR=0x%x\n", OS_REG_READ(ah, AR_CR)); + ath_hal_printf(ah, "AR_DIAG_SW=0x%x\n", OS_REG_READ(ah, AR_DIAG_SW)); +#endif + return AH_FALSE; +} + +/* + * Start Transmit at the PCU engine (unpause receive) + */ +void +ar5210StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) +{ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); +} + +/* + * Stop Transmit at the PCU engine (pause receive) + */ +void +ar5210StopPcuReceive(struct ath_hal *ah) +{ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter 0 (lower 32-bits) + * filter 1 (upper 32-bits) + */ +void +ar5210SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1) +{ + OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); + OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +/* + * Clear multicast filter by index + */ +HAL_BOOL +ar5210ClrMulticastFilterIndex(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<<ix))); + } + return AH_TRUE; +} + +/* + * Set multicast filter by index + */ +HAL_BOOL +ar5210SetMulticastFilterIndex(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<<ix))); + } + return AH_TRUE; +} + +/* + * Return the receive packet filter. + */ +uint32_t +ar5210GetRxFilter(struct ath_hal *ah) +{ + /* XXX can't be sure if promiscuous mode is set because of PHYRADAR */ + return OS_REG_READ(ah, AR_RX_FILTER); +} + +/* + * Turn off/on bits in the receive packet filter. + */ +void +ar5210SetRxFilter(struct ath_hal *ah, uint32_t bits) +{ + if (bits & HAL_RX_FILTER_PHYRADAR) { + /* must enable promiscuous mode to get radar */ + bits = (bits &~ HAL_RX_FILTER_PHYRADAR) | AR_RX_FILTER_PROMISCUOUS; + } + OS_REG_WRITE(ah, AR_RX_FILTER, bits); +} + +/* + * Initialize RX descriptor, by clearing the status and clearing + * the size. This is not strictly HW dependent, but we want the + * control and status words to be opaque above the hal. + */ +HAL_BOOL +ar5210SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t size, u_int flags) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + (void) flags; + + ads->ds_ctl0 = 0; + ads->ds_ctl1 = size & AR_BufLen; + if (ads->ds_ctl1 != size) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: buffer size %u too large\n", + __func__, size); + return AH_FALSE; + } + if (flags & HAL_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxInterReq; + ads->ds_status0 = ads->ds_status1 = 0; + + return AH_TRUE; +} + +/* + * Process an RX descriptor, and return the status to the caller. + * Copy some hardware specific items into the software portion + * of the descriptor. + * + * NB: the caller is responsible for validating the memory contents + * of the descriptor (e.g. flushing any cached copy). + */ +HAL_STATUS +ar5210ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, + uint32_t pa, struct ath_desc *nds, uint64_t tsf, + struct ath_rx_status *rs) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + struct ar5210_desc *ands = AR5210DESC(nds); + uint32_t now, rstamp; + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + /* + * Given the use of a self-linked tail be very sure that the hw is + * done with this descriptor; the hw may have done this descriptor + * once and picked it up again...make sure the hw has moved on. + */ + if ((ands->ds_status1 & AR_Done) == 0 && OS_REG_READ(ah, AR_RXDP) == pa) + return HAL_EINPROGRESS; + + rs->rs_datalen = ads->ds_status0 & AR_DataLen; + rstamp = MS(ads->ds_status1, AR_RcvTimestamp); + /* + * Convert timestamp. The value in the + * descriptor is bits [10..22] of the TSF. + */ + now = (OS_REG_READ(ah, AR_TSF_L32) >> 10) & 0xffff; + if ((now & 0x1fff) < rstamp) + rstamp |= (now - 0x2000) & 0xffff; + else + rstamp |= now; + /* NB: keep only 15 bits for consistency w/ other chips */ + rs->rs_tstamp = rstamp & 0x7fff; + rs->rs_status = 0; + if ((ads->ds_status1 & AR_FrmRcvOK) == 0) { + if (ads->ds_status1 & AR_CRCErr) + rs->rs_status |= HAL_RXERR_CRC; + else if (ads->ds_status1 & AR_DecryptCRCErr) + rs->rs_status |= HAL_RXERR_DECRYPT; + else if (ads->ds_status1 & AR_FIFOOverrun) + rs->rs_status |= HAL_RXERR_FIFO; + else { + rs->rs_status |= HAL_RXERR_PHY; + rs->rs_phyerr = + (ads->ds_status1 & AR_PHYErr) >> AR_PHYErr_S; + } + } + /* XXX what about KeyCacheMiss? */ + rs->rs_rssi = MS(ads->ds_status0, AR_RcvSigStrength); + if (ads->ds_status1 & AR_KeyIdxValid) + rs->rs_keyix = MS(ads->ds_status1, AR_KeyIdx); + else + rs->rs_keyix = HAL_RXKEYIX_INVALID; + /* NB: caller expected to do rate table mapping */ + rs->rs_rate = MS(ads->ds_status0, AR_RcvRate); + rs->rs_antenna = (ads->ds_status0 & AR_RcvAntenna) ? 1 : 0; + rs->rs_more = (ads->ds_status0 & AR_More) ? 1 : 0; + + return HAL_OK; +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c new file mode 100644 index 000000000000..dc4f002164fa --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c @@ -0,0 +1,1005 @@ +/*- + * 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. + */ +#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" + +typedef struct { + uint32_t Offset; + uint32_t Value; +} REGISTER_VAL; + +static const REGISTER_VAL ar5k0007_init[] = { +#include "ar5210/ar5k_0007.ini" +}; + +/* Default Power Settings for channels outside of EEPROM range */ +static const uint8_t ar5k0007_pwrSettings[17] = { +/* gain delta pc dac */ +/* 54 48 36 24 18 12 9 54 48 36 24 18 12 9 6 ob db */ + 9, 9, 0, 0, 0, 0, 0, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2 +}; + +/* + * The delay, in usecs, between writing AR_RC with a reset + * request and waiting for the chip to settle. If this is + * too short then the chip does not come out of sleep state. + * Note this value was empirically derived and may be dependent + * on the host machine (don't know--the problem was identified + * on an IBM 570e laptop; 10us delays worked on other systems). + */ +#define AR_RC_SETTLE_TIME 20000 + +static HAL_BOOL ar5210SetResetReg(struct ath_hal *, + uint32_t resetMask, u_int delay); +static HAL_BOOL ar5210SetChannel(struct ath_hal *, struct ieee80211_channel *); +static void ar5210SetOperatingMode(struct ath_hal *, int opmode); + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + * + * bChannelChange is used to preserve DMA/PCU registers across + * a HW Reset during channel change. + */ +HAL_BOOL +ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, + struct ieee80211_channel *chan, HAL_BOOL bChannelChange, + HAL_RESET_TYPE resetType, + HAL_STATUS *status) +{ +#define N(a) (sizeof (a) /sizeof (a[0])) +#define FAIL(_code) do { ecode = _code; goto bad; } while (0) + struct ath_hal_5210 *ahp = AH5210(ah); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + HAL_CHANNEL_INTERNAL *ichan; + HAL_STATUS ecode; + uint32_t ledstate; + int i, q; + + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: opmode %u channel %u/0x%x %s channel\n", __func__, + opmode, chan->ic_freq, chan->ic_flags, + bChannelChange ? "change" : "same"); + + if (!IEEE80211_IS_CHAN_5GHZ(chan)) { + /* Only 11a mode */ + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: channel not 5GHz\n", __func__); + FAIL(HAL_EINVAL); + } + /* + * Map public channel to private. + */ + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: invalid channel %u/0x%x; no mapping\n", + __func__, chan->ic_freq, chan->ic_flags); + FAIL(HAL_EINVAL); + } + switch (opmode) { + case HAL_M_STA: + case HAL_M_IBSS: + case HAL_M_HOSTAP: + case HAL_M_MONITOR: + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", + __func__, opmode); + FAIL(HAL_EINVAL); + break; + } + + ledstate = OS_REG_READ(ah, AR_PCICFG) & + (AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); + + if (!ar5210ChipReset(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", + __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); + OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)); + ar5210SetOperatingMode(ah, opmode); + + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG); + OS_REG_WRITE(ah, AR_PCICFG, + AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL); + break; + } + + /* Restore previous led state */ + OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); + +#if 0 + 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)); +#endif + /* BSSID, association id, ps-poll */ + ar5210WriteAssocid(ah, ahp->ah_bssid, ahp->ah_associd); + + OS_REG_WRITE(ah, AR_TXDP0, 0); + OS_REG_WRITE(ah, AR_TXDP1, 0); + OS_REG_WRITE(ah, AR_RXDP, 0); + + /* + * Initialize interrupt state. + */ + (void) OS_REG_READ(ah, AR_ISR); /* cleared on read */ + OS_REG_WRITE(ah, AR_IMR, 0); + OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + ahp->ah_maskReg = 0; + + (void) OS_REG_READ(ah, AR_BSR); /* cleared on read */ + OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B); + OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B); + + OS_REG_WRITE(ah, AR_TOPS, 8); /* timeout prescale */ + OS_REG_WRITE(ah, AR_RXNOFRM, 8); /* RX no frame timeout */ + OS_REG_WRITE(ah, AR_RPGTO, 0); /* RX frame gap timeout */ + OS_REG_WRITE(ah, AR_TXNOFRM, 0); /* TX no frame timeout */ + + OS_REG_WRITE(ah, AR_SFR, 0); + OS_REG_WRITE(ah, AR_MIBC, 0); /* unfreeze ctrs + clr state */ + OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); + OS_REG_WRITE(ah, AR_CFP_DUR, 0); + + ar5210SetRxFilter(ah, 0); /* nothing for now */ + OS_REG_WRITE(ah, AR_MCAST_FIL0, 0); /* multicast filter */ + OS_REG_WRITE(ah, AR_MCAST_FIL1, 0); /* XXX was 2 */ + + OS_REG_WRITE(ah, AR_TX_MASK0, 0); + OS_REG_WRITE(ah, AR_TX_MASK1, 0); + OS_REG_WRITE(ah, AR_CLR_TMASK, 1); + OS_REG_WRITE(ah, AR_TRIG_LEV, 1); /* minimum */ + + ar5210UpdateDiagReg(ah, 0); + + OS_REG_WRITE(ah, AR_CFP_PERIOD, 0); + OS_REG_WRITE(ah, AR_TIMER0, 0); /* next beacon time */ + OS_REG_WRITE(ah, AR_TSF_L32, 0); /* local clock */ + OS_REG_WRITE(ah, AR_TIMER1, ~0); /* next DMA beacon alert */ + OS_REG_WRITE(ah, AR_TIMER2, ~0); /* next SW beacon alert */ + OS_REG_WRITE(ah, AR_TIMER3, 1); /* next ATIM window */ + + /* Write the INI values for PHYreg initialization */ + for (i = 0; i < N(ar5k0007_init); i++) { + uint32_t reg = ar5k0007_init[i].Offset; + /* On channel change, don't reset the PCU registers */ + if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000))) + OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value); + } + + /* Setup the transmit power values for cards since 0x0[0-2]05 */ + if (!ar5210SetTransmitPower(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: error init'ing transmit power\n", __func__); + FAIL(HAL_EIO); + } + + OS_REG_WRITE(ah, AR_PHY(10), + (OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) | + (ee->ee_xlnaOn << 8)); + OS_REG_WRITE(ah, AR_PHY(13), + (ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) | + (ee->ee_xpaOn << 8) | ee->ee_xpaOn); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) | + ((ee->ee_antenna >> 1) & 0x3F80)); + OS_REG_WRITE(ah, AR_PHY(18), + (OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) | + ((ee->ee_antenna << 10) & 0x3F000)); + OS_REG_WRITE(ah, AR_PHY(25), + (OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) | + ((ee->ee_thresh62 << 12) & 0x7F000)); + OS_REG_WRITE(ah, AR_PHY(68), + (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | + (ee->ee_antenna & 0x3)); + + if (!ar5210SetChannel(ah, chan)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n", + __func__); + FAIL(HAL_EIO); + } + if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) + chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + + /* Activate the PHY */ + OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE); + + OS_DELAY(1000); /* Wait a bit (1 msec) */ + + /* calibrate the HW and poll the bit going to 0 for completion */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + (void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0); + + /* Perform noise floor calibration and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + HALDEBUG(ah, HAL_DEBUG_ANY, + "%s: noise floor calibration failed\n", __func__); + FAIL(HAL_EIO); + } + + for (q = 0; q < HAL_NUM_TX_QUEUES; q++) + ar5210ResetTxQueue(ah, q); + + if (AH_PRIVATE(ah)->ah_rfkillEnabled) + ar5210EnableRfKill(ah); + + /* + * Writing to AR_BEACON will start timers. Hence it should be + * the last register to be written. Do not reset tsf, do not + * enable beacons at this point, but preserve other values + * like beaconInterval. + */ + OS_REG_WRITE(ah, AR_BEACON, + (OS_REG_READ(ah, AR_BEACON) & + ~(AR_BEACON_EN | AR_BEACON_RESET_TSF))); + + /* Restore user-specified slot time and timeouts */ + if (ahp->ah_sifstime != (u_int) -1) + ar5210SetSifsTime(ah, ahp->ah_sifstime); + if (ahp->ah_slottime != (u_int) -1) + ar5210SetSlotTime(ah, ahp->ah_slottime); + if (ahp->ah_acktimeout != (u_int) -1) + ar5210SetAckTimeout(ah, ahp->ah_acktimeout); + if (ahp->ah_ctstimeout != (u_int) -1) + ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout); + if (AH_PRIVATE(ah)->ah_diagreg != 0) + ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg); + + AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); + + return AH_TRUE; +bad: + if (status != AH_NULL) + *status = ecode; + return AH_FALSE; +#undef FAIL +#undef N +} + +static void +ar5210SetOperatingMode(struct ath_hal *ah, int opmode) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + uint32_t val; + + val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff; + switch (opmode) { + case HAL_M_HOSTAP: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_AP + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_IBSS: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_ADHOC + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_DESC_ANTENNA + | ahp->ah_staId1Defaults); + break; + case HAL_M_STA: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | AR_STA_ID1_PWR_SV + | ahp->ah_staId1Defaults); + break; + case HAL_M_MONITOR: + OS_REG_WRITE(ah, AR_STA_ID1, val + | AR_STA_ID1_NO_PSPOLL + | ahp->ah_staId1Defaults); + break; + } +} + +void +ar5210SetPCUConfig(struct ath_hal *ah) +{ + ar5210SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); +} + +/* + * Places the PHY and Radio chips into reset. A full reset + * must be called to leave this state. The PCI/MAC/PCU are + * not placed into reset as we must receive interrupt to + * re-enable the hardware. + */ +HAL_BOOL +ar5210PhyDisable(struct ath_hal *ah) +{ + return ar5210SetResetReg(ah, AR_RC_RPHY, 10); +} + +/* + * Places all of hardware into reset + */ +HAL_BOOL +ar5210Disable(struct ath_hal *ah) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* + * Reset the HW - PCI must be reset after the rest of the + * device has been reset + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + (void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME); + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + return AH_TRUE; +#undef AR_RC_HW +} + +/* + * Places the hardware into reset and then pulls it out of reset + */ +HAL_BOOL +ar5210ChipReset(struct ath_hal *ah, struct ieee80211_channel *chan) +{ +#define AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC) + + HALDEBUG(ah, HAL_DEBUG_RESET, "%s turbo %s\n", __func__, + chan && IEEE80211_IS_CHAN_TURBO(chan) ? + "enabled" : "disabled"); + + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Place chip in turbo before reset to cleanly reset clocks */ + OS_REG_WRITE(ah, AR_PHY_FRCTL, + chan && IEEE80211_IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0); + + /* + * Reset the HW. + * PCI must be reset after the rest of the device has been reset. + */ + if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(1000); + if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME)) + return AH_FALSE; + OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */ + + /* + * Bring out of sleep mode (AGAIN) + * + * WARNING WARNING WARNING + * + * There is a problem with the chip where it doesn't always indicate + * that it's awake, so initializePowerUp() will fail. + */ + if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + return AH_FALSE; + + /* Clear warm reset reg */ + return ar5210SetResetReg(ah, 0, 10); +#undef AR_RC_HW +} + +enum { + FIRPWR_M = 0x03fc0000, + FIRPWR_S = 18, + KCOARSEHIGH_M = 0x003f8000, + KCOARSEHIGH_S = 15, + KCOARSELOW_M = 0x00007f80, + KCOARSELOW_S = 7, + ADCSAT_ICOUNT_M = 0x0001f800, + ADCSAT_ICOUNT_S = 11, + ADCSAT_THRESH_M = 0x000007e0, + ADCSAT_THRESH_S = 5 +}; + +/* + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +HAL_BOOL +ar5210PerCalibrationN(struct ath_hal *ah, + struct ieee80211_channel *chan, u_int chainMask, + HAL_BOOL longCal, HAL_BOOL *isCalDone) +{ + uint32_t regBeacon; + uint32_t reg9858, reg985c, reg9868; + HAL_CHANNEL_INTERNAL *ichan; + + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == AH_NULL) + return AH_FALSE; + /* Disable tx and rx */ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Disable Beacon Enable */ + regBeacon = OS_REG_READ(ah, AR_BEACON); + OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN); + + /* Delay 4ms to ensure that all tx and rx activity has ceased */ + OS_DELAY(4000); + + /* Disable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + /* Wait for the AGC traffic to cease. */ + OS_DELAY(10); + + /* Change Channel to relock synth */ + if (!ar5210SetChannel(ah, chan)) + return AH_FALSE; + + /* wait for the synthesizer lock to stabilize */ + OS_DELAY(1000); + + /* Re-enable AGC to radio traffic */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* + * Configure the AGC so that it is highly unlikely (if not + * impossible) for it to send any gain changes to the analog + * chip. We store off the current values so that they can + * be rewritten below. Setting the following values: + * firpwr = -1 + * Kcoursehigh = -1 + * Kcourselow = -127 + * ADCsat_icount = 2 + * ADCsat_thresh = 12 + */ + reg9858 = OS_REG_READ(ah, 0x9858); + reg985c = OS_REG_READ(ah, 0x985c); + reg9868 = OS_REG_READ(ah, 0x9868); + + OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) | + ((-1 << FIRPWR_S) & FIRPWR_M)); + OS_REG_WRITE(ah, 0x985c, + (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) | + ((-1 << KCOARSEHIGH_S) & KCOARSEHIGH_M) | + ((-127 << KCOARSELOW_S) & KCOARSELOW_M)); + OS_REG_WRITE(ah, 0x9868, + (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) | + ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) | + ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M)); + + /* Wait for AGC changes to be enacted */ + OS_DELAY(20); + + /* + * We disable RF mix/gain stages for the PGA to avoid a + * race condition that will occur with receiving a frame + * and performing the AGC calibration. This will be + * re-enabled at the end of offset cal. We turn off AGC + * writes during this write as it will go over the analog bus. + */ + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000); + OS_DELAY(10); /* wait for the AGC traffic to cease */ + OS_REG_WRITE(ah, 0x98D4, 0x21); + OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000)); + + /* wait to make sure that additional AGC traffic has quiesced */ + OS_DELAY(1000); + + /* AGC calibration (this was added to make the NF threshold check work) */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL); + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n", + __func__); + } + + /* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */ + OS_REG_WRITE(ah, 0x9858, reg9858); + OS_REG_WRITE(ah, 0x985c, reg985c); + OS_REG_WRITE(ah, 0x9868, reg9868); + + /* Perform noise floor and set status */ + if (!ar5210CalNoiseFloor(ah, ichan)) { + /* + * Delay 5ms before retrying the noise floor - + * just to make sure. We're in an error + * condition here + */ + HALDEBUG(ah, HAL_DEBUG_NFCAL | HAL_DEBUG_PERCAL, + "%s: Performing 2nd Noise Cal\n", __func__); + OS_DELAY(5000); + if (!ar5210CalNoiseFloor(ah, ichan)) + chan->ic_state |= IEEE80211_CHANSTATE_CWINT; + } + + /* Clear tx and rx disable bit */ + ar5210UpdateDiagReg(ah, + OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX)); + + /* Re-enable Beacons */ + OS_REG_WRITE(ah, AR_BEACON, regBeacon); + + *isCalDone = AH_TRUE; + + return AH_TRUE; +} + +HAL_BOOL +ar5210PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, + HAL_BOOL *isIQdone) +{ + return ar5210PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone); +} + +HAL_BOOL +ar5210ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ + return AH_TRUE; +} + +/* + * Writes the given reset bit mask into the reset register + */ +static HAL_BOOL +ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int delay) +{ + uint32_t mask = resetMask ? resetMask : ~0; + HAL_BOOL rt; + + OS_REG_WRITE(ah, AR_RC, resetMask); + /* need to wait at least 128 clocks when reseting PCI before read */ + OS_DELAY(delay); + + resetMask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + mask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC; + rt = ath_hal_wait(ah, AR_RC, mask, resetMask); + if ((resetMask & AR_RC_RMAC) == 0) { + if (isBigEndian()) { + /* + * Set CFG, little-endian for descriptor accesses. + */ + mask = INIT_CONFIG_STATUS | AR_CFG_SWTD | AR_CFG_SWRD; + OS_REG_WRITE(ah, AR_CFG, mask); + } else + OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); + } + return rt; +} + +/* + * Returns: the pcdac value + */ +static uint8_t +getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm) +{ + int32_t i; + int useNextEntry = AH_FALSE; + uint32_t interp; + + for (i = AR_TP_SCALING_ENTRIES - 1; i >= 0; i--) { + /* Check for exact entry */ + if (dBm == AR_I2DBM(i)) { + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + useNextEntry = AH_TRUE; + } else if (dBm + 1 == AR_I2DBM(i) && i > 0) { + /* Interpolate for between entry with a logish scale */ + if (pRD->pcdac[i] != 63 && pRD->pcdac[i-1] != 63) { + interp = (350 * (pRD->pcdac[i] - pRD->pcdac[i-1])) + 999; + interp = (interp / 1000) + pRD->pcdac[i-1]; + return interp; + } + useNextEntry = AH_TRUE; + } else if (useNextEntry == AH_TRUE) { + /* Grab the next lowest */ + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + } + } + + /* Return the lowest Entry if we haven't returned */ + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) + if (pRD->pcdac[i] != 63) + return pRD->pcdac[i]; + + /* No value to return from table */ +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: empty transmit power table?\n", __func__); +#endif + return 1; +} + +/* + * Find or interpolates the gainF value from the table ptr. + */ +static uint8_t +getGainF(struct ath_hal *ah, const struct tpcMap *pRD, + uint8_t pcdac, uint8_t *dBm) +{ + uint32_t interp; + int low, high, i; + + low = high = -1; + + for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) { + if(pRD->pcdac[i] == 63) + continue; + if (pcdac == pRD->pcdac[i]) { + *dBm = AR_I2DBM(i); + return pRD->gainF[i]; /* Exact Match */ + } + if (pcdac > pRD->pcdac[i]) + low = i; + if (pcdac < pRD->pcdac[i]) { + high = i; + if (low == -1) { + *dBm = AR_I2DBM(i); + /* PCDAC is lower than lowest setting */ + return pRD->gainF[i]; + } + break; + } + } + if (i >= AR_TP_SCALING_ENTRIES && low == -1) { + /* No settings were found */ +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no valid entries in the pcdac table: %d\n", + __func__, pcdac); +#endif + return 63; + } + if (i >= AR_TP_SCALING_ENTRIES) { + /* PCDAC setting was above the max setting in the table */ + *dBm = AR_I2DBM(low); + return pRD->gainF[low]; + } + /* Only exact if table has no missing entries */ + *dBm = (low + high) + 3; + + /* + * Perform interpolation between low and high values to find gainF + * linearly scale the pcdac between low and high + */ + interp = ((pcdac - pRD->pcdac[low]) * 1000) / + (pRD->pcdac[high] - pRD->pcdac[low]); + /* + * Multiply the scale ratio by the gainF difference + * (plus a rnd up factor) + */ + interp = ((interp * (pRD->gainF[high] - pRD->gainF[low])) + 999) / 1000; + + /* Add ratioed gain_f to low gain_f value */ + return interp + pRD->gainF[low]; +} + +HAL_BOOL +ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit) +{ + AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER); + /* XXX flush to h/w */ + return AH_TRUE; +} + +/* + * Get TXPower values and set them in the radio + */ +static HAL_BOOL +setupPowerSettings(struct ath_hal *ah, const struct ieee80211_channel *chan, + uint8_t cp[17]) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom; + uint8_t gainFRD, gainF36, gainF48, gainF54; + uint8_t dBmRD, dBm36, dBm48, dBm54, dontcare; + uint32_t rd, group; + const struct tpcMap *pRD; + + /* Set OB/DB Values regardless of channel */ + cp[15] = (ee->ee_biasCurrents >> 4) & 0x7; + cp[16] = ee->ee_biasCurrents & 0x7; + + if (freq < 5170 || freq > 5320) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n", + __func__, freq); + return AH_FALSE; + } + + HALASSERT(ee->ee_version >= AR_EEPROM_VER1 && + ee->ee_version < AR_EEPROM_VER3); + + /* Match regulatory domain */ + for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++) + if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd]) + break; + if (rd == AR_REG_DOMAINS_MAX) { +#ifdef AH_DEBUG + ath_hal_printf(ah, + "%s: no calibrated regulatory domain matches the " + "current regularly domain (0x%0x)\n", __func__, + AH_PRIVATE(ah)->ah_currentRD); +#endif + return AH_FALSE; + } + group = ((freq - 5170) / 10); + + if (group > 11) { + /* Pull 5.29 into the 5.27 group */ + group--; + } + + /* Integer divide will set group from 0 to 4 */ + group = group / 3; + pRD = &ee->ee_tpc[group]; + + /* Set PC DAC Values */ + cp[14] = pRD->regdmn[rd]; + cp[9] = AH_MIN(pRD->regdmn[rd], pRD->rate36); + cp[8] = AH_MIN(pRD->regdmn[rd], pRD->rate48); + cp[7] = AH_MIN(pRD->regdmn[rd], pRD->rate54); + + /* Find Corresponding gainF values for RD, 36, 48, 54 */ + gainFRD = getGainF(ah, pRD, pRD->regdmn[rd], &dBmRD); + gainF36 = getGainF(ah, pRD, cp[9], &dBm36); + gainF48 = getGainF(ah, pRD, cp[8], &dBm48); + gainF54 = getGainF(ah, pRD, cp[7], &dBm54); + + /* Power Scale if requested */ + if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { + static const uint16_t tpcScaleReductionTable[5] = + { 0, 3, 6, 9, AR5210_MAX_RATE_POWER }; + uint16_t tpScale; + + tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; + if (dBmRD < tpScale+3) + dBmRD = 3; /* min */ + else + dBmRD -= tpScale; + cp[14] = getPcdac(ah, pRD, dBmRD); + gainFRD = getGainF(ah, pRD, cp[14], &dontcare); + dBm36 = AH_MIN(dBm36, dBmRD); + cp[9] = getPcdac(ah, pRD, dBm36); + gainF36 = getGainF(ah, pRD, cp[9], &dontcare); + dBm48 = AH_MIN(dBm48, dBmRD); + cp[8] = getPcdac(ah, pRD, dBm48); + gainF48 = getGainF(ah, pRD, cp[8], &dontcare); + dBm54 = AH_MIN(dBm54, dBmRD); + cp[7] = getPcdac(ah, pRD, dBm54); + gainF54 = getGainF(ah, pRD, cp[7], &dontcare); + } + /* Record current dBm at rate 6 */ + AH_PRIVATE(ah)->ah_maxPowerLevel = 2*dBmRD; + + cp[13] = cp[12] = cp[11] = cp[10] = cp[14]; + + /* Set GainF Values */ + cp[0] = gainFRD - gainF54; + cp[1] = gainFRD - gainF48; + cp[2] = gainFRD - gainF36; + /* 9, 12, 18, 24 have no gain_delta from 6 */ + cp[3] = cp[4] = cp[5] = cp[6] = 0; + return AH_TRUE; +} + +/* + * Places the device in and out of reset and then places sane + * values in the registers based on EEPROM config, initialization + * vectors (as determined by the mode), and station configuration + */ +HAL_BOOL +ar5210SetTransmitPower(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + static const uint32_t pwr_regs_start[17] = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf0000000, + 0xcc000000, 0x00000000, 0x00000000, + 0x00000000, 0x0a000000, 0x000000e2, + 0x0a000020, 0x01000002, 0x01000018, + 0x40000000, 0x00000418 + }; + uint16_t i; + uint8_t cp[sizeof(ar5k0007_pwrSettings)]; + uint32_t pwr_regs[17]; + + OS_MEMCPY(pwr_regs, pwr_regs_start, sizeof(pwr_regs)); + OS_MEMCPY(cp, ar5k0007_pwrSettings, sizeof(cp)); + + /* Check the EEPROM tx power calibration settings */ + if (!setupPowerSettings(ah, chan, cp)) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: unable to setup power settings\n", + __func__); +#endif + return AH_FALSE; + } + if (cp[15] < 1 || cp[15] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: OB out of range (%u)\n", + __func__, cp[15]); +#endif + return AH_FALSE; + } + if (cp[16] < 1 || cp[16] > 5) { +#ifdef AH_DEBUG + ath_hal_printf(ah, "%s: DB out of range (%u)\n", + __func__, cp[16]); +#endif + return AH_FALSE; + } + + /* reverse bits of the transmit power array */ + for (i = 0; i < 7; i++) + cp[i] = ath_hal_reverseBits(cp[i], 5); + for (i = 7; i < 15; i++) + cp[i] = ath_hal_reverseBits(cp[i], 6); + + /* merge transmit power values into the register - quite gross */ + pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F); + pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) | + ((cp[1] >> 3) & 0x03); + pwr_regs[2] |= ((cp[4] << 4) & 0xF0) | ((cp[3] >> 1) & 0x0F); + pwr_regs[3] |= ((cp[6] << 6) & 0xC0) | ((cp[5] << 1) & 0x3E) | + ((cp[4] >> 4) & 0x01); + pwr_regs[4] |= ((cp[7] << 3) & 0xF8) | ((cp[6] >> 2) & 0x07); + pwr_regs[5] |= ((cp[9] << 7) & 0x80) | ((cp[8] << 1) & 0x7E) | + ((cp[7] >> 5) & 0x01); + pwr_regs[6] |= ((cp[10] << 5) & 0xE0) | ((cp[9] >> 1) & 0x1F); + pwr_regs[7] |= ((cp[11] << 3) & 0xF8) | ((cp[10] >> 3) & 0x07); + pwr_regs[8] |= ((cp[12] << 1) & 0x7E) | ((cp[11] >> 5) & 0x01); + pwr_regs[9] |= ((cp[13] << 5) & 0xE0); + pwr_regs[10] |= ((cp[14] << 3) & 0xF8) | ((cp[13] >> 3) & 0x07); + pwr_regs[11] |= ((cp[14] >> 5) & 0x01); + + /* Set OB */ + pwr_regs[8] |= (ath_hal_reverseBits(cp[15], 3) << 7) & 0x80; + pwr_regs[9] |= (ath_hal_reverseBits(cp[15], 3) >> 1) & 0x03; + + /* Set DB */ + pwr_regs[9] |= (ath_hal_reverseBits(cp[16], 3) << 2) & 0x1C; + + /* Write the registers */ + for (i = 0; i < N(pwr_regs)-1; i++) + OS_REG_WRITE(ah, 0x0000989c, pwr_regs[i]); + /* last write is a flush */ + OS_REG_WRITE(ah, 0x000098d4, pwr_regs[i]); + + return AH_TRUE; +#undef N +} + +/* + * Takes the MHz channel value and sets the Channel value + * + * ASSUMES: Writes enabled to analog bus before AGC is active + * or by disabling the AGC. + */ +static HAL_BOOL +ar5210SetChannel(struct ath_hal *ah, struct ieee80211_channel *chan) +{ + uint16_t freq = ath_hal_gethwchannel(ah, chan); + uint32_t data; + + /* Set the Channel */ + data = ath_hal_reverseBits((freq - 5120)/10, 5); + data = (data << 1) | 0x41; + OS_REG_WRITE(ah, AR_PHY(0x27), data); + OS_REG_WRITE(ah, AR_PHY(0x30), 0); + AH_PRIVATE(ah)->ah_curchan = chan; + return AH_TRUE; +} + +int16_t +ar5210GetNoiseFloor(struct ath_hal *ah) +{ + int16_t nf; + + nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + return nf; +} + +#define NORMAL_NF_THRESH (-72) +/* + * Peform the noisefloor calibration and check for + * any constant channel interference + * + * Returns: TRUE for a successful noise floor calibration; else FALSE + */ +HAL_BOOL +ar5210CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) +{ + int32_t nf, nfLoops; + + /* Calibrate the noise floor */ + OS_REG_WRITE(ah, AR_PHY_AGCCTL, + OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_NF); + + /* Do not read noise floor until it has done the first update */ + if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_NF, 0)) { +#ifdef ATH_HAL_DEBUG + ath_hal_printf(ah, " -PHY NF Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_AGCCTL)); + ath_hal_printf(ah, " -MAC Reset Reg state: 0x%x\n", + OS_REG_READ(ah, AR_RC)); + ath_hal_printf(ah, " -PHY Active Reg state: 0x%x\n", + OS_REG_READ(ah, AR_PHY_ACTIVE)); +#endif /* ATH_HAL_DEBUG */ + return AH_FALSE; + } + + nf = 0; + /* Keep checking until the floor is below the threshold or the nf is done */ + for (nfLoops = 0; ((nfLoops < 21) && (nf > NORMAL_NF_THRESH)); nfLoops++) { + OS_DELAY(1000); /* Sleep for 1 ms */ + nf = ar5210GetNoiseFloor(ah); + } + + if (nf > NORMAL_NF_THRESH) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Bad noise cal %d\n", + __func__, nf); + ichan->rawNoiseFloor = 0; + return AH_FALSE; + } + ichan->rawNoiseFloor = nf; + return AH_TRUE; +} + +/* + * Adjust NF based on statistical values for 5GHz frequencies. + */ +int16_t +ar5210GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) +{ + return 0; +} + +HAL_RFGAIN +ar5210GetRfgain(struct ath_hal *ah) +{ + return HAL_RFGAIN_INACTIVE; +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c b/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c new file mode 100644 index 000000000000..dbdeaf86a419 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c @@ -0,0 +1,670 @@ +/*- + * 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. + */ +#include "opt_ah.h" + +#include "ah.h" +#include "ah_internal.h" +#include "ah_desc.h" + +#include "ar5210/ar5210.h" +#include "ar5210/ar5210reg.h" +#include "ar5210/ar5210phy.h" +#include "ar5210/ar5210desc.h" + +/* + * Set the properties of the tx queue with the parameters + * from qInfo. The queue must previously have been setup + * with a call to ar5210SetupTxQueue. + */ +HAL_BOOL +ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); +} + +/* + * Return the properties for the specified tx queue. + */ +HAL_BOOL +ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); +} + +/* + * Allocate and initialize a tx DCU/QCU combination. + */ +int +ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, + const HAL_TXQ_INFO *qInfo) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + int q; + + switch (type) { + case HAL_TX_QUEUE_BEACON: + q = 2; + break; + case HAL_TX_QUEUE_CAB: + q = 1; + break; + case HAL_TX_QUEUE_DATA: + q = 0; + break; + default: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", + __func__, type); + return -1; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", + __func__, q); + return -1; + } + OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); + qi->tqi_type = type; + if (qInfo == AH_NULL) { + /* by default enable OK+ERR+DESC+URN interrupts */ + qi->tqi_qflags = + HAL_TXQ_TXOKINT_ENABLE + | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE + | HAL_TXQ_TXURNINT_ENABLE + ; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + } else + (void) ar5210SetTxQueueProps(ah, q, qInfo); + /* NB: must be followed by ar5210ResetTxQueue */ + return q; +} + +/* + * Free a tx DCU/QCU combination. + */ +HAL_BOOL +ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + HAL_TX_QUEUE_INFO *qi; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); + + qi->tqi_type = HAL_TX_QUEUE_INACTIVE; + ahp->ah_txOkInterruptMask &= ~(1 << q); + ahp->ah_txErrInterruptMask &= ~(1 << q); + ahp->ah_txDescInterruptMask &= ~(1 << q); + ahp->ah_txEolInterruptMask &= ~(1 << q); + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + return AH_TRUE; +#undef N +} + +HAL_BOOL +ar5210ResetTxQueue(struct ath_hal *ah, u_int q) +{ + struct ath_hal_5210 *ahp = AH5210(ah); + const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; + HAL_TX_QUEUE_INFO *qi; + uint32_t cwMin; + + if (q >= HAL_NUM_TX_QUEUES) { + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", + __func__, q); + return AH_FALSE; + } + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { + HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", + __func__, q); + return AH_FALSE; + } + + /* + * Ignore any non-data queue(s). + */ + if (qi->tqi_type != HAL_TX_QUEUE_DATA) + return AH_TRUE; + + /* Set turbo mode / base mode parameters on or off */ + if (IEEE80211_IS_CHAN_TURBO(chan)) { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) + << AR_IFS0_DIFS_S) + | INIT_SIFS_TURBO); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | + 0x2020 | + AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); + } else { + OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); + OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); + OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); + OS_REG_WRITE(ah, AR_IFS0, + ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) + << AR_IFS0_DIFS_S) + | INIT_SIFS); + OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); + OS_REG_WRITE(ah, AR_PHY(17), + (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); + OS_REG_WRITE(ah, AR_PHY_FRCTL, + AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | + AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | + AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); + } + + if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) + cwMin = INIT_CWMIN; + else + cwMin = qi->tqi_cwmin; + + /* Set cwmin and retry limit values */ + OS_REG_WRITE(ah, AR_RETRY_LMT, + (cwMin << AR_RETRY_LMT_CW_MIN_S) + | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) + | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) + | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) + | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) + ); + + if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) + ahp->ah_txOkInterruptMask |= 1 << q; + else + ahp->ah_txOkInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) + ahp->ah_txErrInterruptMask |= 1 << q; + else + ahp->ah_txErrInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) + ahp->ah_txDescInterruptMask |= 1 << q; + else + ahp->ah_txDescInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) + ahp->ah_txEolInterruptMask |= 1 << q; + else + ahp->ah_txEolInterruptMask &= ~(1 << q); + if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) + ahp->ah_txUrnInterruptMask |= 1 << q; + else + ahp->ah_txUrnInterruptMask &= ~(1 << q); + + 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; +} + +/* + * 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; +} + +/* + * Update Tx FIFO trigger level. + * + * Set bIncTrigLevel to TRUE to increase the trigger level. + * Set bIncTrigLevel to FALSE to decrease the trigger level. + * + * Returns TRUE if the trigger level was updated + */ +HAL_BOOL +ar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) +{ + uint32_t curTrigLevel; + HAL_INT ints = ar5210GetInterrupts(ah); + + /* + * Disable chip interrupts. This is because halUpdateTxTrigLevel + * is called from both ISR and non-ISR contexts. + */ + (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); + curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); + if (bIncTrigLevel){ + /* increase the trigger level */ + curTrigLevel = curTrigLevel + + ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); + } else { + /* decrease the trigger level if not already at the minimum */ + if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { + /* decrease the trigger level */ + curTrigLevel--; + } else { + /* no update to the trigger level */ + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_FALSE; + } + } + /* Update the trigger level */ + OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel); + /* re-enable chip interrupts */ + ar5210SetInterrupts(ah, ints); + return AH_TRUE; +} + +/* + * Set Transmit Enable bits for the specified queues. + */ +HAL_BOOL +ar5210StartTxDma(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); + + 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: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0); + break; + case HAL_TX_QUEUE_CAB: + OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1); /* enable altq xmit */ + OS_REG_WRITE(ah, AR_BCR, + AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV); + break; + case HAL_TX_QUEUE_BEACON: + /* XXX add CR_BCR_BCMD if IBSS mode */ + OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE); + break; + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fal thru... */ + default: + return AH_FALSE; + } + 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; +} + +/* + * Stop transmit on the specified queue + */ +HAL_BOOL +ar5210StopTxDma(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); + + 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: { + int i; + OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0); + for (i = 0; i < 1000; i++) { + if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0) + break; + OS_DELAY(10); + } + OS_REG_WRITE(ah, AR_CR, 0); + return (i < 1000); + } + case HAL_TX_QUEUE_BEACON: + return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0); + case HAL_TX_QUEUE_INACTIVE: + HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", + __func__, q); + /* fall thru... */ + default: + break; + } + return AH_FALSE; +} + +/* + * Descriptor Access Functions + */ + +#define VALID_PKT_TYPES \ + ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\ + (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\ + (1<<HAL_PKT_TYPE_BEACON)) +#define isValidPktType(_t) ((1<<(_t)) & VALID_PKT_TYPES) +#define VALID_TX_RATES \ + ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\ + (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\ + (1<<0x1d)|(1<<0x18)|(1<<0x1c)) +#define isValidTxRate(_r) ((1<<(_r)) & VALID_TX_RATES) + +HAL_BOOL +ar5210SetupTxDesc(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 ar5210_desc *ads = AR5210DESC(ds); + uint32_t frtype; + + (void) txPower; + (void) rtsctsDuration; + + HALASSERT(txTries0 != 0); + HALASSERT(isValidPktType(type)); + HALASSERT(isValidTxRate(txRate0)); + + if (type == HAL_PKT_TYPE_BEACON || type == HAL_PKT_TYPE_PROBE_RESP) + frtype = AR_Frm_NoDelay; + else + frtype = type << 26; + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (txRate0 << AR_XmitRate_S) + | ((hdrLen << AR_HdrLen_S) & AR_HdrLen) + | frtype + | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) + | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) + | (antMode ? AR_AntModeXmit : 0) + ; + if (keyIx != HAL_TXKEYIX_INVALID) { + ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; + ads->ds_ctl0 |= AR_EncryptKeyValid; + } else + ads->ds_ctl1 = 0; + if (flags & HAL_TXDESC_RTSENA) { + ads->ds_ctl0 |= AR_RTSCTSEnable; + ads->ds_ctl1 |= (rtsctsDuration << AR_RTSDuration_S) + & AR_RTSDuration; + } + return AH_TRUE; +} + +HAL_BOOL +ar5210SetupXTxDesc(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) +{ + (void) ah; (void) ds; + (void) txRate1; (void) txTries1; + (void) txRate2; (void) txTries2; + (void) txRate3; (void) txTries3; + return AH_FALSE; +} + +void +ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + ads->ds_ctl0 |= AR_TxInterReq; +} + +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; +} + +/* + * Processing of HW TX descriptor. + */ +HAL_STATUS +ar5210ProcTxDesc(struct ath_hal *ah, + struct ath_desc *ds, struct ath_tx_status *ts) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + if ((ads->ds_status1 & AR_Done) == 0) + return HAL_EINPROGRESS; + + /* Update software copies of the HW status */ + ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; + ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); + ts->ts_status = 0; + if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { + if (ads->ds_status0 & AR_ExcessiveRetries) + ts->ts_status |= HAL_TXERR_XRETRY; + if (ads->ds_status0 & AR_Filtered) + ts->ts_status |= HAL_TXERR_FILT; + if (ads->ds_status0 & AR_FIFOUnderrun) + ts->ts_status |= HAL_TXERR_FIFO; + } + ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); + ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); + ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); + ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); + ts->ts_antenna = 0; /* NB: don't know */ + ts->ts_finaltsi = 0; + + return HAL_OK; +} + +/* + * Determine which tx queues need interrupt servicing. + * STUB. + */ +void +ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) +{ + return; +} + +/* + * Retrieve the rate table from the given TX completion descriptor + */ +HAL_BOOL +ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) +{ + return AH_FALSE; +} + +/* + * Set the TX descriptor link pointer + */ +void +ar5210SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + ads->ds_link = link; +} + +/* + * Get the TX descriptor link pointer + */ +void +ar5210GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + *link = ads->ds_link; +} + +/* + * Get a pointer to the TX descriptor link pointer + */ +void +ar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) +{ + struct ar5210_desc *ads = AR5210DESC(ds); + + *linkptr = &ads->ds_link; +} diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210desc.h b/sys/dev/ath/ath_hal/ar5210/ar5210desc.h new file mode 100644 index 000000000000..9679824f4541 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210desc.h @@ -0,0 +1,130 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#ifndef _DEV_ATH_AR5210DESC_H +#define _DEV_ATH_AR5210DESC_H + +/* + * Defintions for the DMA descriptors used by the Atheros + * AR5210/AR5211 and AR5110 Wireless Lan controller parts. + */ + +/* DMA descriptors */ +struct ar5210_desc { + uint32_t ds_link; /* link pointer */ + uint32_t ds_data; /* data buffer pointer */ + uint32_t ds_ctl0; /* DMA control 0 */ + uint32_t ds_ctl1; /* DMA control 1 */ + uint32_t ds_status0; /* DMA status 0 */ + uint32_t ds_status1; /* DMA status 1 */ +} __packed; +#define AR5210DESC(_ds) ((struct ar5210_desc *)(_ds)) +#define AR5210DESC_CONST(_ds) ((const struct ar5210_desc *)(_ds)) + +/* TX ds_ctl0 */ +#define AR_FrameLen 0x00000fff /* frame length */ +#define AR_HdrLen 0x0003f000 /* header length */ +#define AR_HdrLen_S 12 +#define AR_XmitRate 0x003c0000 /* txrate */ +#define AR_XmitRate_S 18 +#define AR_Rate_6M 0xb +#define AR_Rate_9M 0xf +#define AR_Rate_12M 0xa +#define AR_Rate_18M 0xe +#define AR_Rate_24M 0x9 +#define AR_Rate_36M 0xd +#define AR_Rate_48M 0x8 +#define AR_Rate_54M 0xc +#define AR_RTSCTSEnable 0x00400000 /* RTS/CTS enable */ +#define AR_LongPkt 0x00800000 /* long packet indication */ +#define AR_ClearDestMask 0x01000000 /* Clear destination mask bit */ +#define AR_AntModeXmit 0x02000000 /* TX antenna seslection */ +#define AR_FrmType 0x1c000000 /* frame type indication */ +#define AR_FrmType_S 26 +#define AR_Frm_Normal 0x00000000 /* normal frame */ +#define AR_Frm_ATIM 0x04000000 /* ATIM frame */ +#define AR_Frm_PSPOLL 0x08000000 /* PS poll frame */ +#define AR_Frm_NoDelay 0x0c000000 /* no delay data */ +#define AR_Frm_PIFS 0x10000000 /* PIFS data */ +#define AR_TxInterReq 0x20000000 /* TX interrupt request */ +#define AR_EncryptKeyValid 0x40000000 /* EncryptKeyIdx is valid */ + +/* TX ds_ctl1 */ +#define AR_BufLen 0x00000fff /* data buffer length */ +#define AR_More 0x00001000 /* more desc in this frame */ +#define AR_EncryptKeyIdx 0x0007e000 /* ecnrypt key table index */ +#define AR_EncryptKeyIdx_S 13 +#define AR_RTSDuration 0xfff80000 /* lower 13bit of duration */ +#define AR_RTSDuration_S 19 + +/* RX ds_ctl1 */ +/* AR_BufLen 0x00000fff data buffer length */ +#define AR_RxInterReq 0x00002000 /* RX interrupt request */ + +/* TX ds_status0 */ +#define AR_FrmXmitOK 0x00000001 /* TX success */ +#define AR_ExcessiveRetries 0x00000002 /* excessive retries */ +#define AR_FIFOUnderrun 0x00000004 /* TX FIFO underrun */ +#define AR_Filtered 0x00000008 /* TX filter indication */ +/* NB: the spec has the Short+Long retry counts reversed */ +#define AR_LongRetryCnt 0x000000f0 /* long retry count */ +#define AR_LongRetryCnt_S 4 +#define AR_ShortRetryCnt 0x00000f00 /* short retry count */ +#define AR_ShortRetryCnt_S 8 +#define AR_SendTimestamp 0xffff0000 /* TX timestamp */ +#define AR_SendTimestamp_S 16 + +/* RX ds_status0 */ +#define AR_DataLen 0x00000fff /* RX data length */ +/* AR_More 0x00001000 more desc in this frame */ +#define AR_RcvAntenna 0x00004000 /* received on ant 1 */ +#define AR_RcvRate 0x00078000 /* reception rate */ +#define AR_RcvRate_S 15 +#define AR_RcvSigStrength 0x07f80000 /* receive signal strength */ +#define AR_RcvSigStrength_S 19 + +/* TX ds_status1 */ +#define AR_Done 0x00000001 /* descripter complete */ +#define AR_SeqNum 0x00001ffe /* TX sequence number */ +#define AR_AckSigStrength 0x001fe000 /* strength of ACK */ +#define AR_AckSigStrength_S 13 + +/* RX ds_status1 */ +/* AR_Done 0x00000001 descripter complete */ +#define AR_FrmRcvOK 0x00000002 /* frame reception success */ +#define AR_CRCErr 0x00000004 /* CRC error */ +#define AR_FIFOOverrun 0x00000008 /* RX FIFO overrun */ +#define AR_DecryptCRCErr 0x00000010 /* Decryption CRC fiailure */ +#define AR_PHYErr 0x000000e0 /* PHY error */ +#define AR_PHYErr_S 5 +#define AR_PHYErr_NoErr 0x00000000 /* No error */ +#define AR_PHYErr_Tim 0x00000020 /* Timing error */ +#define AR_PHYErr_Par 0x00000040 /* Parity error */ +#define AR_PHYErr_Rate 0x00000060 /* Illegal rate */ +#define AR_PHYErr_Len 0x00000080 /* Illegal length */ +#define AR_PHYErr_QAM 0x000000a0 /* 64 QAM rate */ +#define AR_PHYErr_Srv 0x000000c0 /* Service bit error */ +#define AR_PHYErr_TOR 0x000000e0 /* Transmit override receive */ +#define AR_KeyIdxValid 0x00000100 /* decryption key index valid */ +#define AR_KeyIdx 0x00007e00 /* Decryption key index */ +#define AR_KeyIdx_S 9 +#define AR_RcvTimestamp 0x0fff8000 /* timestamp */ +#define AR_RcvTimestamp_S 15 +#define AR_KeyCacheMiss 0x10000000 /* key cache miss indication */ + +#endif /* _DEV_ATH_AR5210DESC_H_ */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210phy.h b/sys/dev/ath/ath_hal/ar5210/ar5210phy.h new file mode 100644 index 000000000000..667533bff8c5 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210phy.h @@ -0,0 +1,59 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#ifndef _DEV_ATH_AR5210PHY_H +#define _DEV_ATH_AR5210PHY_H + +/* + * Definitions for the PHY on the Atheros AR5210 parts. + */ + +/* PHY Registers */ +#define AR_PHY_BASE 0x9800 /* PHY register base */ +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_FRCTL 0x9804 /* PHY frame control */ +#define AR_PHY_TURBO_MODE 0x00000001 /* PHY turbo mode */ +#define AR_PHY_TURBO_SHORT 0x00000002 /* PHY turbo short symbol */ +#define AR_PHY_TIMING_ERR 0x01000000 /* Detect PHY timing error */ +#define AR_PHY_PARITY_ERR 0x02000000 /* Detect signal parity err */ +#define AR_PHY_ILLRATE_ERR 0x04000000 /* Detect PHY illegal rate */ +#define AR_PHY_ILLLEN_ERR 0x08000000 /* Detect PHY illegal length */ +#define AR_PHY_SERVICE_ERR 0x20000000 /* Detect PHY nonzero service */ +#define AR_PHY_TXURN_ERR 0x40000000 /* DetectPHY TX underrun */ +#define AR_PHY_FRCTL_BITS \ + "\20\1TURBO_MODE\2TURBO_SHORT\30TIMING_ERR\31PARITY_ERR\32ILLRATE_ERR"\ + "\33ILLEN_ERR\35SERVICE_ERR\36TXURN_ERR" + +#define AR_PHY_AGC 0x9808 /* PHY AGC command */ +#define AR_PHY_AGC_DISABLE 0x08000000 /* Disable PHY AGC */ +#define AR_PHY_AGC_BITS "\20\33DISABLE" + +#define AR_PHY_CHIPID 0x9818 /* PHY chip revision */ + +#define AR_PHY_ACTIVE 0x981c /* PHY activation */ +#define AR_PHY_ENABLE 0x00000001 /* activate PHY */ +#define AR_PHY_DISABLE 0x00000002 /* deactivate PHY */ +#define AR_PHY_ACTIVE_BITS "\20\1ENABLE\2DISABLE" + +#define AR_PHY_AGCCTL 0x9860 /* PHY calibration and noise floor */ +#define AR_PHY_AGC_CAL 0x00000001 /* PHY internal calibration */ +#define AR_PHY_AGC_NF 0x00000002 /* calc PHY noise-floor */ +#define AR_PHY_AGCCTL_BITS "\20\1CAL\2NF" + +#endif /* _DEV_ATH_AR5210PHY_H */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210reg.h b/sys/dev/ath/ath_hal/ar5210/ar5210reg.h new file mode 100644 index 000000000000..92e32a06872c --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5210reg.h @@ -0,0 +1,413 @@ +/*- + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2002-2008 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. + */ +#ifndef _DEV_ATH_AR5210REG_H +#define _DEV_ATH_AR5210REG_H + +/* + * Register defintions for the Atheros AR5210/5110 MAC/Basedband + * Processor for IEEE 802.11a 5-GHz Wireless LANs. + */ + +#ifndef PCI_VENDOR_ATHEROS +#define PCI_VENDOR_ATHEROS 0x168c +#endif +#define PCI_PRODUCT_ATHEROS_AR5210 0x0007 +#define PCI_PRODUCT_ATHEROS_AR5210_OLD 0x0004 + +/* DMA Registers */ +#define AR_TXDP0 0x0000 /* TX queue pointer 0 register */ +#define AR_TXDP1 0x0004 /* TX queue pointer 1 register */ +#define AR_CR 0x0008 /* Command register */ +#define AR_RXDP 0x000c /* RX queue descriptor ptr register */ +#define AR_CFG 0x0014 /* Configuration and status register */ +#define AR_ISR 0x001c /* Interrupt status register */ +#define AR_IMR 0x0020 /* Interrupt mask register */ +#define AR_IER 0x0024 /* Interrupt global enable register */ +#define AR_BCR 0x0028 /* Beacon control register */ +#define AR_BSR 0x002c /* Beacon status register */ +#define AR_TXCFG 0x0030 /* TX configuration register */ +#define AR_RXCFG 0x0034 /* RX configuration register */ +#define AR_MIBC 0x0040 /* MIB control register */ +#define AR_TOPS 0x0044 /* Timeout prescale register */ +#define AR_RXNOFRM 0x0048 /* RX no frame timeout register */ +#define AR_TXNOFRM 0x004c /* TX no frame timeout register */ +#define AR_RPGTO 0x0050 /* RX frame gap timeout register */ +#define AR_RFCNT 0x0054 /* RX frame count limit register */ +#define AR_MISC 0x0058 /* Misc control and status register */ +#define AR_RC 0x4000 /* Reset control */ +#define AR_SCR 0x4004 /* Sleep control */ +#define AR_INTPEND 0x4008 /* Interrupt pending */ +#define AR_SFR 0x400c /* Force sleep */ +#define AR_PCICFG 0x4010 /* PCI configuration */ +#define AR_GPIOCR 0x4014 /* GPIO configuration */ +#define AR_GPIODO 0x4018 /* GPIO data output */ +#define AR_GPIODI 0x401c /* GPIO data input */ +#define AR_SREV 0x4020 /* Silicon revision */ +/* EEPROM Access Registers */ +#define AR_EP_AIR_BASE 0x6000 /* EEPROM access initiation regs base */ +#define AR_EP_AIR(n) (AR_EP_AIR_BASE + (n)*4) +#define AR_EP_RDATA 0x6800 /* EEPROM read data register */ +#define AR_EP_STA 0x6c00 /* EEPROM access status register */ +/* PCU Registers */ +#define AR_STA_ID0 0x8000 /* Lower 32bits of MAC address */ +#define AR_STA_ID1 0x8004 /* Upper 16bits of MAC address */ +#define AR_BSS_ID0 0x8008 /* Lower 32bits of BSSID */ +#define AR_BSS_ID1 0x800c /* Upper 16bits of BSSID */ +#define AR_SLOT_TIME 0x8010 /* Length of a back-off */ +#define AR_TIME_OUT 0x8014 /* Timeout to wait for ACK and CTS */ +#define AR_RSSI_THR 0x8018 /* Beacon RSSI warning threshold */ +#define AR_RETRY_LMT 0x801c /* Short and long frame retry limit */ +#define AR_USEC 0x8020 /* Transmit latency */ +#define AR_BEACON 0x8024 /* Beacon control */ +#define AR_CFP_PERIOD 0x8028 /* CFP period */ +#define AR_TIMER0 0x802c /* Next beacon time */ +#define AR_TIMER1 0x8030 /* Next DMA beacon alert time */ +#define AR_TIMER2 0x8034 /* Next software beacon alert time */ +#define AR_TIMER3 0x8038 /* Next ATIM window time */ +#define AR_IFS0 0x8040 /* Protocol timers */ +#define AR_IFS1 0x8044 /* Protocol time and control */ +#define AR_CFP_DUR 0x8048 /* Maximum CFP duration */ +#define AR_RX_FILTER 0x804c /* Receive filter */ +#define AR_MCAST_FIL0 0x8050 /* Lower 32bits of mcast filter mask */ +#define AR_MCAST_FIL1 0x8054 /* Upper 16bits of mcast filter mask */ +#define AR_TX_MASK0 0x8058 /* Lower 32bits of TX mask */ +#define AR_TX_MASK1 0x805c /* Upper 16bits of TX mask */ +#define AR_CLR_TMASK 0x8060 /* Clear TX mask */ +#define AR_TRIG_LEV 0x8064 /* Minimum FIFO fill level before TX */ +#define AR_DIAG_SW 0x8068 /* PCU control */ +#define AR_TSF_L32 0x806c /* Lower 32bits of local clock */ +#define AR_TSF_U32 0x8070 /* Upper 32bits of local clock */ +#define AR_LAST_TSTP 0x8080 /* Lower 32bits of last beacon tstamp */ +#define AR_RETRY_CNT 0x8084 /* Current short or long retry cnt */ +#define AR_BACKOFF 0x8088 /* Back-off status */ +#define AR_NAV 0x808c /* Current NAV value */ +#define AR_RTS_OK 0x8090 /* RTS success counter */ +#define AR_RTS_FAIL 0x8094 /* RTS failure counter */ +#define AR_ACK_FAIL 0x8098 /* ACK failure counter */ +#define AR_FCS_FAIL 0x809c /* FCS failure counter */ +#define AR_BEACON_CNT 0x80a0 /* Valid beacon counter */ +#define AR_KEYTABLE_0 0x9000 /* Encryption key table */ +#define AR_KEYTABLE(n) (AR_KEYTABLE_0 + ((n)*32)) + +#define AR_CR_TXE0 0x00000001 /* TX queue 0 enable */ +#define AR_CR_TXE1 0x00000002 /* TX queue 1 enable */ +#define AR_CR_RXE 0x00000004 /* RX enable */ +#define AR_CR_TXD0 0x00000008 /* TX queue 0 disable */ +#define AR_CR_TXD1 0x00000010 /* TX queue 1 disable */ +#define AR_CR_RXD 0x00000020 /* RX disable */ +#define AR_CR_SWI 0x00000040 /* software interrupt */ +#define AR_CR_BITS \ + "\20\1TXE0\2TXE1\3RXE\4TXD0\5TXD1\6RXD\7SWI" + +#define AR_CFG_SWTD 0x00000001 /* BE for TX desc */ +#define AR_CFG_SWTB 0x00000002 /* BE for TX data */ +#define AR_CFG_SWRD 0x00000004 /* BE for RX desc */ +#define AR_CFG_SWRB 0x00000008 /* BE for RX data */ +#define AR_CFG_SWRG 0x00000010 /* BE for registers */ +#define AR_CFG_EEBS 0x00000200 /* EEPROM busy */ +#define AR_CFG_TXCNT 0x00007800 /* number of TX desc in Q */ +#define AR_CFG_TXCNT_S 11 +#define AR_CFG_TXFSTAT 0x00008000 /* TX DMA status */ +#define AR_CFG_TXFSTRT 0x00010000 /* re-enable TX DMA */ +#define AR_CFG_BITS \ + "\20\1SWTD\2SWTB\3SWRD\4SWRB\5SWRG\14EEBS\17TXFSTAT\20TXFSTRT" + +#define AR_ISR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_ISR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_ISR_RXERR_INT 0x00000004 /* RX error */ +#define AR_ISR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_ISR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_ISR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_ISR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_ISR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_ISR_TXERR_INT 0x00000100 /* TX error */ +#define AR_ISR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_ISR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_ISR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_ISR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_ISR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_ISR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_ISR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_ISR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_ISR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_ISR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_ISR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_ISR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_ISR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_ISR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_ISR_BITS \ + "\20\1RXOK\2RXDESC\3RXERR\4RXNOFM\5RXEOL\6RXORN\7TXOK\10TXDESC"\ + "\11TXERR\12TXNOFRM\13TXEOL\14TXURN\15MIB\16SWI\17RXPHY\20RXKCM"\ + "\21SWBA\22BRSSI\23BMISS\24MCABT\25SSERR\26DPERR\27GPIO" + +#define AR_IMR_RXOK_INT 0x00000001 /* RX frame OK */ +#define AR_IMR_RXDESC_INT 0x00000002 /* RX intr request */ +#define AR_IMR_RXERR_INT 0x00000004 /* RX error */ +#define AR_IMR_RXNOFRM_INT 0x00000008 /* no frame received */ +#define AR_IMR_RXEOL_INT 0x00000010 /* RX desc empty */ +#define AR_IMR_RXORN_INT 0x00000020 /* RX fifo overrun */ +#define AR_IMR_TXOK_INT 0x00000040 /* TX frame OK */ +#define AR_IMR_TXDESC_INT 0x00000080 /* TX intr request */ +#define AR_IMR_TXERR_INT 0x00000100 /* TX error */ +#define AR_IMR_TXNOFRM_INT 0x00000200 /* no frame transmitted */ +#define AR_IMR_TXEOL_INT 0x00000400 /* TX desc empty */ +#define AR_IMR_TXURN_INT 0x00000800 /* TX fifo underrun */ +#define AR_IMR_MIB_INT 0x00001000 /* MIB interrupt */ +#define AR_IMR_SWI_INT 0x00002000 /* software interrupt */ +#define AR_IMR_RXPHY_INT 0x00004000 /* PHY RX error */ +#define AR_IMR_RXKCM_INT 0x00008000 /* Key cache miss */ +#define AR_IMR_SWBA_INT 0x00010000 /* software beacon alert */ +#define AR_IMR_BRSSI_INT 0x00020000 /* beacon threshold */ +#define AR_IMR_BMISS_INT 0x00040000 /* beacon missed */ +#define AR_IMR_MCABT_INT 0x00100000 /* master cycle abort */ +#define AR_IMR_SSERR_INT 0x00200000 /* SERR on PCI */ +#define AR_IMR_DPERR_INT 0x00400000 /* Parity error on PCI */ +#define AR_IMR_GPIO_INT 0x01000000 /* GPIO interrupt */ +#define AR_IMR_BITS AR_ISR_BITS + +#define AR_IER_DISABLE 0x00000000 /* pseudo-flag */ +#define AR_IER_ENABLE 0x00000001 /* global interrupt enable */ +#define AR_IER_BITS "\20\1ENABLE" + +#define AR_BCR_BCMD 0x00000001 /* ad hoc beacon mode */ +#define AR_BCR_BDMAE 0x00000002 /* beacon DMA enable */ +#define AR_BCR_TQ1FV 0x00000004 /* use TXQ1 for non-beacon */ +#define AR_BCR_TQ1V 0x00000008 /* TXQ1 valid for beacon */ +#define AR_BCR_BCGET 0x00000010 /* force a beacon fetch */ +#define AR_BCR_BITS "\20\1BCMD\2BDMAE\3TQ1FV\4TQ1V\5BCGET" + +#define AR_BSR_BDLYSW 0x00000001 /* software beacon delay */ +#define AR_BSR_BDLYDMA 0x00000002 /* DMA beacon delay */ +#define AR_BSR_TXQ1F 0x00000004 /* TXQ1 fetch */ +#define AR_BSR_ATIMDLY 0x00000008 /* ATIM delay */ +#define AR_BSR_SNPBCMD 0x00000100 /* snapshot of BCMD */ +#define AR_BSR_SNPBDMAE 0x00000200 /* snapshot of BDMAE */ +#define AR_BSR_SNPTQ1FV 0x00000400 /* snapshot of TQ1FV */ +#define AR_BSR_SNPTQ1V 0x00000800 /* snapshot of TQ1V */ +#define AR_BSR_SNAPPEDBCRVALID 0x00001000 /* snapshot of BCR are valid */ +#define AR_BSR_SWBA_CNT 0x00ff0000 /* software beacon alert cnt */ +#define AR_BSR_BITS \ + "\20\1BDLYSW\2BDLYDMA\3TXQ1F\4ATIMDLY\11SNPBCMD\12SNPBDMAE"\ + "\13SNPTQ1FV\14SNPTQ1V\15SNAPPEDBCRVALID" + +#define AR_TXCFG_SDMAMR 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_TXCFG_TXFSTP 0x00000008 /* Stop TX DMA on filtered */ +#define AR_TXCFG_TXFULL 0x00000070 /* TX DMA desc Q full thresh */ +#define AR_TXCFG_TXCONT_EN 0x00000080 /* Enable continuous TX mode */ +#define AR_TXCFG_BITS "\20\3TXFSTP\7TXCONT_EN" + +#define AR_RXCFG_SDMAMW 0x00000007 /* DMA burst size 2^(2+x) */ +#define AR_RXCFG_ZLFDMA 0x00000010 /* enable zero length DMA */ + +/* DMA sizes used for both AR_TXCFG_SDMAMR and AR_RXCFG_SDMAMW */ +#define AR_DMASIZE_4B 0 /* DMA size 4 bytes */ +#define AR_DMASIZE_8B 1 /* DMA size 8 bytes */ +#define AR_DMASIZE_16B 2 /* DMA size 16 bytes */ +#define AR_DMASIZE_32B 3 /* DMA size 32 bytes */ +#define AR_DMASIZE_64B 4 /* DMA size 64 bytes */ +#define AR_DMASIZE_128B 5 /* DMA size 128 bytes */ +#define AR_DMASIZE_256B 6 /* DMA size 256 bytes */ +#define AR_DMASIZE_512B 7 /* DMA size 512 bytes */ + +#define AR_MIBC_COW 0x00000001 /* counter overflow warning */ +#define AR_MIBC_FMC 0x00000002 /* freeze MIB counters */ +#define AR_MIBC_CMC 0x00000004 /* clear MIB counters */ +#define AR_MIBC_MCS 0x00000008 /* MIB counter strobe */ + +#define AR_RFCNT_RFCL 0x0000000f /* RX frame count limit */ + +#define AR_MISC_LED_DECAY 0x001c0000 /* LED decay rate */ +#define AR_MISC_LED_BLINK 0x00e00000 /* LED blink rate */ + +#define AR_RC_RPCU 0x00000001 /* PCU Warm Reset */ +#define AR_RC_RDMA 0x00000002 /* DMA Warm Reset */ +#define AR_RC_RMAC 0x00000004 /* MAC Warm Reset */ +#define AR_RC_RPHY 0x00000008 /* PHY Warm Reset */ +#define AR_RC_RPCI 0x00000010 /* PCI Core Warm Reset */ +#define AR_RC_BITS "\20\1RPCU\2RDMA\3RMAC\4RPHY\5RPCI" + +#define AR_SCR_SLDUR 0x0000ffff /* sleep duration */ +#define AR_SCR_SLE 0x00030000 /* sleep enable */ +#define AR_SCR_SLE_S 16 +/* + * The previous values for the following three defines were: + * + * AR_SCR_SLE_WAKE 0x00000000 + * AR_SCR_SLE_SLP 0x00010000 + * AR_SCR_SLE_ALLOW 0x00020000 + * + * However, these have been pre-shifted with AR_SCR_SLE_S. The + * OS_REG_READ() macro would attempt to shift them again, effectively + * shifting out any of the set bits completely. + */ +#define AR_SCR_SLE_WAKE 0 /* force wake */ +#define AR_SCR_SLE_SLP 1 /* force sleep */ +#define AR_SCR_SLE_ALLOW 2 /* allow to control sleep */ +#define AR_SCR_BITS "\20\20SLE_SLP\21SLE_ALLOW" + +#define AR_INTPEND_IP 0x00000001 /* interrupt pending */ +#define AR_INTPEND_BITS "\20\1IP" + +#define AR_SFR_SF 0x00000001 /* force sleep immediately */ + +#define AR_PCICFG_EEPROMSEL 0x00000001 /* EEPROM access enable */ +#define AR_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable */ +#define AR_PCICFG_LED_PEND 0x00000020 /* LED for assoc pending */ +#define AR_PCICFG_LED_ACT 0x00000040 /* LED for assoc active */ +#define AR_PCICFG_SL_INTEN 0x00000800 /* Enable sleep intr */ +#define AR_PCICFG_LED_BCTL 0x00001000 /* LED blink for local act */ +#define AR_PCICFG_SL_INPEN 0x00002800 /* sleep even intr pending */ +#define AR_PCICFG_SPWR_DN 0x00010000 /* sleep indication */ +#define AR_PCICFG_BITS \ + "\20\1EEPROMSEL\3CLKRUNEN\5LED_PEND\6LED_ACT\13SL_INTEN"\ + "\14LED_BCTL\20SPWR_DN" + +#define AR_GPIOCR_IN(n) (0<<((n)*2)) /* input-only */ +#define AR_GPIOCR_OUT0(n) (1<<((n)*2)) /* output-only if GPIODO = 0 */ +#define AR_GPIOCR_OUT1(n) (2<<((n)*2)) /* output-only if GPIODO = 1 */ +#define AR_GPIOCR_OUT(n) (3<<((n)*2)) /* always output */ +#define AR_GPIOCR_ALL(n) (3<<((n)*2)) /* all bits for pin */ +#define AR_GPIOCR_INT_SEL(n) ((n)<<12) /* GPIO interrupt pin select */ +#define AR_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ +#define AR_GPIOCR_INT_SELL 0x00000000 /* Interrupt if pin is low */ +#define AR_GPIOCR_INT_SELH 0x00010000 /* Interrupt if pin is high */ + +#define AR_SREV_CRETE 4 /* Crete 1st version */ +#define AR_SREV_CRETE_MS 5 /* Crete FCS version */ +#define AR_SREV_CRETE_23 8 /* Crete version 2.3 */ + +#define AR_EP_STA_RDERR 0x00000001 /* read error */ +#define AR_EP_STA_RDCMPLT 0x00000002 /* read complete */ +#define AR_EP_STA_WRERR 0x00000004 /* write error */ +#define AR_EP_STA_WRCMPLT 0x00000008 /* write complete */ +#define AR_EP_STA_BITS \ + "\20\1RDERR\2RDCMPLT\3WRERR\4WRCMPLT" + +#define AR_STA_ID1_AP 0x00010000 /* Access Point Operation */ +#define AR_STA_ID1_ADHOC 0x00020000 /* ad hoc Operation */ +#define AR_STA_ID1_PWR_SV 0x00040000 /* power save report enable */ +#define AR_STA_ID1_NO_KEYSRCH 0x00080000 /* key table search disable */ +#define AR_STA_ID1_NO_PSPOLL 0x00100000 /* auto PS-POLL disable */ +#define AR_STA_ID1_PCF 0x00200000 /* PCF observation enable */ +#define AR_STA_ID1_DESC_ANTENNA 0x00400000 /* use antenna in TX desc */ +#define AR_STA_ID1_DEFAULT_ANTENNA 0x00800000 /* toggle default antenna */ +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 /* use 6Mbps for ACK/CTS */ +#define AR_STA_ID1_BITS \ + "\20\20AP\21ADHOC\22PWR_SV\23NO_KEYSRCH\24NO_PSPOLL\25PCF"\ + "\26DESC_ANTENNA\27DEFAULT_ANTENNA\30ACKCTS_6MB" + +#define AR_BSS_ID1_AID 0xffff0000 /* association ID */ +#define AR_BSS_ID1_AID_S 16 + +#define AR_TIME_OUT_ACK 0x00001fff /* ACK timeout */ +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x1fff0000 /* CTS timeout */ +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR_BM_THR 0x00000700 /* missed beacon threshold */ +#define AR_RSSI_THR_BM_THR_S 8 + +#define AR_RETRY_LMT_SH_RETRY 0x0000000f /* short frame retry limit */ +#define AR_RETRY_LMT_SH_RETRY_S 0 +#define AR_RETRY_LMT_LG_RETRY 0x000000f0 /* long frame retry limit */ +#define AR_RETRY_LMT_LG_RETRY_S 4 +#define AR_RETRY_LMT_SSH_RETRY 0x00003f00 /* short station retry limit */ +#define AR_RETRY_LMT_SSH_RETRY_S 8 +#define AR_RETRY_LMT_SLG_RETRY 0x000fc000 /* long station retry limit */ +#define AR_RETRY_LMT_SLG_RETRY_S 14 +#define AR_RETRY_LMT_CW_MIN 0x3ff00000 /* minimum contention window */ +#define AR_RETRY_LMT_CW_MIN_S 20 + +#define AR_USEC_1 0x0000007f /* number of clk in 1us */ +#define AR_USEC_1_S 0 +#define AR_USEC_32 0x00003f80 /* number of 32MHz clk in 1us */ +#define AR_USEC_32_S 7 +#define AR_USEC_TX_LATENCY 0x000fc000 /* transmit latency in us */ +#define AR_USEC_TX_LATENCY_S 14 +#define AR_USEC_RX_LATENCY 0x03f00000 /* receive latency in us */ +#define AR_USEC_RX_LATENCY_S 20 + +#define AR_BEACON_PERIOD 0x0000ffff /* beacon period in TU/ms */ +#define AR_BEACON_PERIOD_S 0 +#define AR_BEACON_TIM 0x007f0000 /* byte offset */ +#define AR_BEACON_TIM_S 16 +#define AR_BEACON_EN 0x00800000 /* beacon transmission enable */ +#define AR_BEACON_RESET_TSF 0x01000000 /* TSF reset oneshot */ +#define AR_BEACON_BITS "\20\27ENABLE\30RESET_TSF" + +#define AR_IFS0_SIFS 0x000007ff /* SIFS in core clock cycles */ +#define AR_IFS0_SIFS_S 0 +#define AR_IFS0_DIFS 0x007ff800 /* DIFS in core clock cycles */ +#define AR_IFS0_DIFS_S 11 + +#define AR_IFS1_PIFS 0x00000fff /* Programmable IFS */ +#define AR_IFS1_PIFS_S 0 +#define AR_IFS1_EIFS 0x03fff000 /* EIFS in core clock cycles */ +#define AR_IFS1_EIFS_S 12 +#define AR_IFS1_CS_EN 0x04000000 /* carrier sense enable */ + +#define AR_RX_FILTER_UNICAST 0x00000001 /* unicast frame enable */ +#define AR_RX_FILTER_MULTICAST 0x00000002 /* multicast frame enable */ +#define AR_RX_FILTER_BROADCAST 0x00000004 /* broadcast frame enable */ +#define AR_RX_FILTER_CONTROL 0x00000008 /* control frame enable */ +#define AR_RX_FILTER_BEACON 0x00000010 /* beacon frame enable */ +#define AR_RX_FILTER_PROMISCUOUS 0x00000020 /* promiscuous receive enable */ +#define AR_RX_FILTER_BITS \ + "\20\1UCAST\2MCAST\3BCAST\4CONTROL\5BEACON\6PROMISC" + +#define AR_DIAG_SW_DIS_WEP_ACK 0x00000001 /* disable ACK if no key found*/ +#define AR_DIAG_SW_DIS_ACK 0x00000002 /* disable ACK generation */ +#define AR_DIAG_SW_DIS_CTS 0x00000004 /* disable CTS generation */ +#define AR_DIAG_SW_DIS_ENC 0x00000008 /* encryption disable */ +#define AR_DIAG_SW_DIS_DEC 0x00000010 /* decryption disable */ +#define AR_DIAG_SW_DIS_TX 0x00000020 /* TX disable */ +#define AR_DIAG_SW_DIS_RX 0x00000040 /* RX disable */ +#define AR_DIAG_SW_LOOP_BACK 0x00000080 /* TX data loopback enable */ +#define AR_DIAG_SW_CORR_FCS 0x00000100 /* corrupt FCS enable */ +#define AR_DIAG_SW_CHAN_INFO 0x00000200 /* channel information enable */ +#define AR_DIAG_SW_EN_SCRAM_SEED 0x00000400 /* use fixed scrambler seed */ +#define AR_DIAG_SW_SCVRAM_SEED 0x0003f800 /* fixed scrambler seed */ +#define AR_DIAG_SW_DIS_SEQ_INC 0x00040000 /* seq increment disable */ +#define AR_DIAG_SW_FRAME_NV0 0x00080000 /* accept frame vers != 0 */ +#define AR_DIAG_SW_DIS_CRYPTO (AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC) +#define AR_DIAG_SW_BITS \ + "\20\1DIS_WEP_ACK\2DIS_ACK\3DIS_CTS\4DIS_ENC\5DIS_DEC\6DIS_TX"\ + "\7DIS_RX\10LOOP_BACK\11CORR_FCS\12CHAN_INFO\13EN_SCRAM_SEED"\ + "\22DIS_SEQ_INC\24FRAME_NV0" + +#define AR_RETRY_CNT_SSH 0x0000003f /* current short retry count */ +#define AR_RETRY_CNT_SLG 0x00000fc0 /* current long retry count */ + +#define AR_BACKOFF_CW 0x000003ff /* current contention window */ +#define AR_BACKOFF_CNT 0x03ff0000 /* backoff count */ + +#define AR_KEYTABLE_KEY0(n) (AR_KEYTABLE(n) + 0) /* key bit 0-31 */ +#define AR_KEYTABLE_KEY1(n) (AR_KEYTABLE(n) + 4) /* key bit 32-47 */ +#define AR_KEYTABLE_KEY2(n) (AR_KEYTABLE(n) + 8) /* key bit 48-79 */ +#define AR_KEYTABLE_KEY3(n) (AR_KEYTABLE(n) + 12) /* key bit 80-95 */ +#define AR_KEYTABLE_KEY4(n) (AR_KEYTABLE(n) + 16) /* key bit 96-127 */ +#define AR_KEYTABLE_TYPE(n) (AR_KEYTABLE(n) + 20) /* key type */ +#define AR_KEYTABLE_TYPE_40 0x00000000 /* 40 bit key */ +#define AR_KEYTABLE_TYPE_104 0x00000001 /* 104 bit key */ +#define AR_KEYTABLE_TYPE_128 0x00000003 /* 128 bit key */ +#define AR_KEYTABLE_MAC0(n) (AR_KEYTABLE(n) + 24) /* MAC address 1-32 */ +#define AR_KEYTABLE_MAC1(n) (AR_KEYTABLE(n) + 28) /* MAC address 33-47 */ +#define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ + +#endif /* _DEV_ATH_AR5210REG_H */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini b/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini new file mode 100644 index 000000000000..ab7fc1a81c92 --- /dev/null +++ b/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2002-2008 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. + */ + + /* crete register init */ + { 0x00009800, 0x00000047 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0x09848ea6 }, + { 0x00009810, 0x3d32e000 }, + { 0x00009814, 0x0000076b }, + { 0x0000981c, 0x00000000 }, + { 0x00009820, 0x02020200 }, + { 0x00009824, 0x00000e0e }, + { 0x00009828, 0x0a020201 }, + { 0x0000982c, 0x00036ffc }, + { 0x00009830, 0x00000000 }, + { 0x00009834, 0x00000e0e }, + { 0x00009838, 0x00000007 }, + { 0x0000983c, 0x00020100 }, + { 0x00009840, 0x89630000 }, + { 0x00009844, 0x1372169c }, + { 0x00009848, 0x0018b633 }, + { 0x0000984c, 0x1284613c }, + { 0x00009850, 0x0de8b8e0 }, + { 0x00009854, 0x00074859 }, + { 0x00009858, 0x7e80beba }, + { 0x0000985c, 0x313a665e }, + { 0x00009860, 0x00001d08 }, + { 0x00009864, 0x0001ce00 }, + { 0x00009868, 0x409a4190 }, + { 0x00009870, 0x0000000f }, + { 0x00009874, 0x00000080 }, + { 0x00009878, 0x00000004 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00800000 }, + { 0x00009910, 0x00000003 }, + + + /* bb gain table */ + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000020 }, + { 0x00009b08, 0x00000010 }, + { 0x00009b0c, 0x00000030 }, + { 0x00009b10, 0x00000008 }, + { 0x00009b14, 0x00000028 }, + { 0x00009b18, 0x00000028 }, + { 0x00009b1c, 0x00000004 }, + { 0x00009b20, 0x00000024 }, + { 0x00009b24, 0x00000014 }, + { 0x00009b28, 0x00000034 }, + { 0x00009b2c, 0x0000000c }, + { 0x00009b30, 0x0000002c }, + { 0x00009b34, 0x00000002 }, + { 0x00009b38, 0x00000022 }, + { 0x00009b3c, 0x00000012 }, + { 0x00009b40, 0x00000032 }, + { 0x00009b44, 0x0000000a }, + { 0x00009b48, 0x0000002a }, + { 0x00009b4c, 0x00000001 }, + { 0x00009b50, 0x00000021 }, + { 0x00009b54, 0x00000011 }, + { 0x00009b58, 0x00000031 }, + { 0x00009b5c, 0x00000009 }, + { 0x00009b60, 0x00000029 }, + { 0x00009b64, 0x00000005 }, + { 0x00009b68, 0x00000025 }, + { 0x00009b6c, 0x00000015 }, + { 0x00009b70, 0x00000035 }, + { 0x00009b74, 0x0000000d }, + { 0x00009b78, 0x0000002d }, + { 0x00009b7c, 0x00000003 }, + { 0x00009b80, 0x00000023 }, + { 0x00009b84, 0x00000013 }, + { 0x00009b88, 0x00000033 }, + { 0x00009b8c, 0x0000000b }, + { 0x00009b90, 0x0000002b }, + { 0x00009b94, 0x00000007 }, + { 0x00009b98, 0x00000027 }, + { 0x00009b9c, 0x00000017 }, + { 0x00009ba0, 0x00000037 }, + { 0x00009ba4, 0x0000000f }, + { 0x00009ba8, 0x0000002f }, + { 0x00009bac, 0x0000002f }, + { 0x00009bb0, 0x0000002f }, + { 0x00009bb4, 0x0000002f }, + { 0x00009bb8, 0x0000002f }, + { 0x00009bbc, 0x0000002f }, + { 0x00009bc0, 0x0000002f }, + { 0x00009bc4, 0x0000002f }, + { 0x00009bc8, 0x0000002f }, + { 0x00009bcc, 0x0000002f }, + { 0x00009bd0, 0x0000002f }, + { 0x00009bd4, 0x0000002f }, + { 0x00009bd8, 0x0000002f }, + { 0x00009bdc, 0x0000002f }, + { 0x00009be0, 0x0000002f }, + { 0x00009be4, 0x0000002f }, + { 0x00009be8, 0x0000002f }, + { 0x00009bec, 0x0000002f }, + { 0x00009bf0, 0x0000002f }, + { 0x00009bf4, 0x0000002f }, + { 0x00009bf8, 0x0000002f }, + { 0x00009bfc, 0x0000002f }, + + /* rf gain table */ + { 0x00009a00, 0x0000001d }, + { 0x00009a04, 0x0000005d }, + { 0x00009a08, 0x0000009d }, + { 0x00009a0c, 0x000000dd }, + { 0x00009a10, 0x0000011d }, + { 0x00009a14, 0x00000021 }, + { 0x00009a18, 0x00000061 }, + { 0x00009a1c, 0x000000a1 }, + { 0x00009a20, 0x000000e1 }, + { 0x00009a24, 0x00000031 }, + { 0x00009a28, 0x00000071 }, + { 0x00009a2c, 0x000000b1 }, + { 0x00009a30, 0x0000001c }, + { 0x00009a34, 0x0000005c }, + { 0x00009a38, 0x00000029 }, + { 0x00009a3c, 0x00000069 }, + { 0x00009a40, 0x000000a9 }, + { 0x00009a44, 0x00000020 }, + { 0x00009a48, 0x00000019 }, + { 0x00009a4c, 0x00000059 }, + { 0x00009a50, 0x00000099 }, + { 0x00009a54, 0x00000030 }, + { 0x00009a58, 0x00000005 }, + { 0x00009a5c, 0x00000025 }, + { 0x00009a60, 0x00000065 }, + { 0x00009a64, 0x000000a5 }, + { 0x00009a68, 0x00000028 }, + { 0x00009a6c, 0x00000068 }, + { 0x00009a70, 0x0000001f }, + { 0x00009a74, 0x0000001e }, + { 0x00009a78, 0x00000018 }, + { 0x00009a7c, 0x00000058 }, + { 0x00009a80, 0x00000098 }, + { 0x00009a84, 0x00000003 }, + { 0x00009a88, 0x00000004 }, + { 0x00009a8c, 0x00000044 }, + { 0x00009a90, 0x00000084 }, + { 0x00009a94, 0x00000013 }, + { 0x00009a98, 0x00000012 }, + { 0x00009a9c, 0x00000052 }, + { 0x00009aa0, 0x00000092 }, + { 0x00009aa4, 0x000000d2 }, + { 0x00009aa8, 0x0000002b }, + { 0x00009aac, 0x0000002a }, + { 0x00009ab0, 0x0000006a }, + { 0x00009ab4, 0x000000aa }, + { 0x00009ab8, 0x0000001b }, + { 0x00009abc, 0x0000001a }, + { 0x00009ac0, 0x0000005a }, + { 0x00009ac4, 0x0000009a }, + { 0x00009ac8, 0x000000da }, + { 0x00009acc, 0x00000006 }, + { 0x00009ad0, 0x00000006 }, + { 0x00009ad4, 0x00000006 }, + { 0x00009ad8, 0x00000006 }, + { 0x00009adc, 0x00000006 }, + { 0x00009ae0, 0x00000006 }, + { 0x00009ae4, 0x00000006 }, + { 0x00009ae8, 0x00000006 }, + { 0x00009aec, 0x00000006 }, + { 0x00009af0, 0x00000006 }, + { 0x00009af4, 0x00000006 }, + { 0x00009af8, 0x00000006 }, + { 0x00009afc, 0x00000006 }, + + /* fez register init */ + { 0x000098d4, 0x00000020 }, + { 0x000098cc, 0x00000004 }, + { 0x000098c8, 0x00060106 }, + { 0x0000989c, 0x0000006d }, + { 0x000098c0, 0x00000000 }, + { 0x000098d0, 0x00000014 }, |
