| /* |
| * Copyright 2010 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| /* |
| * Copyright (c) 2008 Atheros Communications Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| #ifndef _ARN_CORE_H |
| #define _ARN_CORE_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <sys/note.h> |
| #include <sys/list.h> |
| #include <sys/net80211.h> |
| |
| #include "arn_ath9k.h" |
| #include "arn_rc.h" |
| |
| struct ath_node; |
| |
| /* |
| * Node type of wifi device |
| */ |
| #ifndef DDI_NT_NET_WIFI |
| #define DDI_NT_NET_WIFI "ddi_network:wifi" |
| #endif |
| #define ARN_NODENAME "arn" |
| |
| #define ARN_LOCK(_sc) mutex_enter(&(_sc)->sc_genlock) |
| #define ARN_UNLOCK(_sc) mutex_exit(&(_sc)->sc_genlock) |
| #define ARN_LOCK_ASSERT(_sc) ASSERT(mutex_owned(&(_sc)->sc_genlock)) |
| |
| #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0])) |
| |
| #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) |
| |
| #define ARN_MIN(a, b) ((a) < (b) ? (a) : (b)) |
| #define ARN_MAX(a, b) ((a) > (b) ? (a) : (b)) |
| |
| #define abs(x) ((x) >= 0 ? (x) : -(x)) |
| |
| enum ath9k_key_len { |
| ATH9K_LEN_WEP40 = 5, |
| ATH9K_LEN_WEP104 = 13, |
| }; |
| |
| /* |
| * Sync a DMA area described by a dma_area_t |
| */ |
| #define ARN_DMA_SYNC(area, flag) ((void) ddi_dma_sync((area).dma_hdl, \ |
| (area).offset, (area).alength, (flag))) |
| |
| #define list_empty(a) ((a)->list_head.list_next == &(a)->list_head) |
| #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset)) |
| #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) |
| #define list_entry(ptr, type, member) \ |
| ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) |
| #define list_is_last(node, list) \ |
| ((node)->list_next == &(list)->list_head) |
| |
| #define list_for_each_entry_safe(object, temp, list_t) \ |
| for (object = list_head(list_t), \ |
| temp = list_object((list_t), ((list_d2l(list_t, object))->list_next));\ |
| ((list_d2l(list_t, temp))->list_next) != &((list_t)->list_head);\ |
| object = temp, \ |
| temp = list_object((list_t), (list_d2l(list_t, temp))->list_next)) |
| |
| /* |
| * Insert src list after dst list. reinitialize src list thereafter. |
| */ |
| static __inline__ void |
| /* LINTED E_STATIC_UNUSED */ |
| list_splice_tail_init(list_t *dst, list_t *src) |
| { |
| list_node_t *dstnode = &dst->list_head; |
| list_node_t *srcnode = &src->list_head; |
| |
| ASSERT(dst->list_size == src->list_size); |
| ASSERT(dst->list_offset == src->list_offset); |
| |
| if (list_empty(src)) |
| return; |
| |
| dstnode->list_prev->list_next = srcnode->list_next; |
| srcnode->list_next->list_prev = dstnode->list_prev; |
| dstnode->list_prev = srcnode->list_prev; |
| srcnode->list_prev->list_next = dstnode; |
| |
| /* reinitialize src list */ |
| srcnode->list_next = srcnode->list_prev = srcnode; |
| } |
| |
| #define ARN_LE_READ_16(p) \ |
| ((uint16_t) \ |
| ((((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8))) |
| |
| #define ARN_LE_READ_32(p) \ |
| ((uint32_t) \ |
| ((((uint8_t *)(p))[0]) | (((uint8_t *)(p))[1] << 8) | \ |
| (((uint8_t *)(p))[2] << 16) | (((uint8_t *)(p))[3] << 24))) |
| |
| #define swab16(value) \ |
| ((((value) & 0xff) << 8) | ((value) >> 8)) |
| |
| #define swab32(value) \ |
| (((uint32_t)swab16((uint16_t)((value) & 0xffff)) << 16) | \ |
| (uint32_t)swab16((uint16_t)((value) >> 16))) |
| |
| #define swab64(value) \ |
| (((uint64_t)swab32((uint32_t)((value) & 0xffffffff)) \ |
| << 32) | \ |
| (uint64_t)swab32((uint32_t)((value) >> 32))) |
| |
| /* Bit map related macros. */ |
| #define set_bit(i, a) ((a)[(i)/NBBY] |= (1 << ((i)%NBBY))) |
| #define clr_bit(i, a) ((a)[(i)/NBBY] &= ~(1 << ((i)%NBBY))) |
| #define is_set(i, a) ((a)[(i)/NBBY] & (1 << ((i)%NBBY))) |
| #define is_clr(i, a) (!((a)[(i)/NBBY] & (1 << ((i)%NBBY)))) |
| |
| /* Macro to expand scalars to 64-bit objects */ |
| |
| #define ito64(x) (sizeof (x) == 8) ? \ |
| (((unsigned long long int)(x)) & (0xff)) : \ |
| (sizeof (x) == 16) ? \ |
| (((unsigned long long int)(x)) & 0xffff) : \ |
| ((sizeof (x) == 32) ? \ |
| (((unsigned long long int)(x)) & 0xffffffff) : \ |
| (unsigned long long int)(x)) |
| |
| /* increment with wrap-around */ |
| #define INCR(_l, _sz) do { \ |
| (_l)++; \ |
| (_l) &= ((_sz) - 1); \ |
| } while (0) |
| |
| /* decrement with wrap-around */ |
| #define DECR(_l, _sz) do { \ |
| (_l)--; \ |
| (_l) &= ((_sz) - 1); \ |
| } while (0) |
| |
| #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) |
| |
| #define TSF_TO_TU(_h, _l) \ |
| ((((uint32_t)(_h)) << 22) | (((uint32_t)(_l)) >> 10)) |
| |
| #define ARN_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i)) |
| |
| #define IEEE80211_IS_CHAN_HTA(_c) \ |
| (IEEE80211_IS_CHAN_5GHZ(_c) && \ |
| ((_c)->ich_flags & IEEE80211_CHAN_HT)) |
| |
| #define IEEE80211_IS_CHAN_HTG(_c) \ |
| (IEEE80211_IS_CHAN_2GHZ(_c) && \ |
| ((_c)->ich_flags & IEEE80211_CHAN_HT)) |
| |
| #define IEEE80211_IS_DATA(_wh) \ |
| (((_wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == \ |
| IEEE80211_FC0_TYPE_DATA) |
| |
| #define IEEE80211_IS_DATA_QOS(_wh) \ |
| (((_wh)->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | \ |
| IEEE80211_FC0_SUBTYPE_QOS)) == \ |
| (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) |
| |
| #define IEEE80211_IS_MGMT(_wh) \ |
| (((_wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == \ |
| IEEE80211_FC0_TYPE_MGT) |
| |
| #define IEEE80211_IS_CTL(_wh) \ |
| (((_wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == \ |
| IEEE80211_FC0_TYPE_CTL) |
| |
| #define IEEE80211_IS_PSPOLL(_wh) \ |
| (((_wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == \ |
| IEEE80211_FC0_SUBTYPE_PS_POLL) |
| |
| #define IEEE80211_IS_BACK_REQ(_wh) \ |
| (((_wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \ |
| IEEE80211_FC0_SUBTYPE_BAR) |
| |
| #define IEEE80211_HAS_MOREFRAGS(_wh) \ |
| (((_wh)->i_fc[1] & IEEE80211_FC1_MORE_FRAG) == \ |
| IEEE80211_FC1_MORE_FRAG) |
| |
| /* Debugging */ |
| enum ARN_DEBUG { |
| ARN_DBG_HW = 0x00000001, |
| ARN_DBG_REG_IO = 0x00000002, |
| ARN_DBG_QUEUE = 0x00000004, |
| ARN_DBG_EEPROM = 0x00000008, |
| ARN_DBG_XMIT = 0x00000010, |
| ARN_DBG_RECV = 0x00000020, |
| ARN_DBG_CALIBRATE = 0x00000040, |
| ARN_DBG_CHANNEL = 0x00000080, |
| ARN_DBG_INTERRUPT = 0x00000100, |
| ARN_DBG_REGULATORY = 0x00000200, |
| ARN_DBG_ANI = 0x00000400, |
| ARN_DBG_POWER_MGMT = 0x00000800, |
| ARN_DBG_KEYCACHE = 0x00001000, |
| ARN_DBG_BEACON = 0x00002000, |
| ARN_DBG_RATE = 0x00004000, |
| ARN_DBG_INIT = 0x00008000, |
| ARN_DBG_ATTACH = 0x00010000, |
| ARN_DBG_DEATCH = 0x00020000, |
| ARN_DBG_AGGR = 0x00040000, |
| ARN_DBG_RESET = 0x00080000, |
| ARN_DBG_FATAL = 0x00100000, |
| ARN_DBG_ANY = 0x00200000, |
| ARN_DBG_ALL = 0x00FFFFFF, |
| }; |
| |
| /* Debug and log functions */ |
| void arn_dbg(uint32_t dbg_flags, const int8_t *fmt, ...); /* debug function */ |
| void arn_log(const int8_t *fmt, ...); /* event log function */ |
| void arn_problem(const int8_t *fmt, ...); /* run-time problem function */ |
| |
| #ifdef DEBUG |
| #define ARN_DDB(command) do { \ |
| { command; } \ |
| _NOTE(CONSTANTCONDITION)\ |
| } while (0) |
| #else |
| #define ARN_DDB(command) |
| #endif /* DEBUG */ |
| |
| #define ARN_DBG(args) ARN_DDB(arn_dbg args) |
| |
| struct ath_stats { |
| uint32_t ast_hardware; /* fatal hardware error interrupts */ |
| uint32_t ast_rxorn; /* rx overrun interrupts */ |
| uint32_t ast_rxeol; /* rx eol interrupts */ |
| uint32_t ast_txurn; /* tx underrun interrupts */ |
| uint32_t ast_tx_mgmt; /* management frames transmitted */ |
| uint32_t ast_tx_discard; /* frames discarded prior to assoc */ |
| uint32_t ast_tx_invalid; /* frames discarded 'cuz device gone */ |
| uint32_t ast_tx_qstop; /* tx queue stopped 'cuz full */ |
| uint32_t ast_tx_nobuf; /* tx failed 'cuz no tx buffer (data) */ |
| uint32_t ast_tx_nobufmgt; /* tx failed 'cuz no tx buffer(mgmt) */ |
| uint32_t ast_tx_xretries; /* tx failed 'cuz too many retries */ |
| uint32_t ast_tx_fifoerr; /* tx failed 'cuz FIFO underrun */ |
| uint32_t ast_tx_filtered; /* tx failed 'cuz xmit filtered */ |
| uint32_t ast_tx_shortretry; /* tx on-chip retries (short) */ |
| uint32_t ast_tx_longretry; /* tx on-chip retries (long) */ |
| uint32_t ast_tx_noack; /* tx frames with no ack marked */ |
| uint32_t ast_tx_rts; /* tx frames with rts enabled */ |
| uint32_t ast_tx_shortpre; /* tx frames with short preamble */ |
| uint32_t ast_tx_altrate; /* tx frames with alternate rate */ |
| uint32_t ast_tx_protect; /* tx frames with protection */ |
| int16_t ast_tx_rssi; /* tx rssi of last ack */ |
| int16_t ast_tx_rssidelta; /* tx rssi delta */ |
| uint32_t ast_rx_crcerr; /* rx failed 'cuz of bad CRC */ |
| uint32_t ast_rx_fifoerr; /* rx failed 'cuz of FIFO overrun */ |
| uint32_t ast_rx_badcrypt; /* rx failed 'cuz decryption */ |
| uint32_t ast_rx_phyerr; /* rx PHY error summary count */ |
| uint32_t ast_rx_phy[32]; /* rx PHY error per-code counts */ |
| uint32_t ast_rx_tooshort; /* rx discarded 'cuz frame too short */ |
| uint32_t ast_per_cal; /* periodic calibration calls */ |
| uint32_t ast_per_calfail; /* periodic calibration failed */ |
| uint32_t ast_per_rfgain; /* periodic calibration rfgain reset */ |
| uint32_t ast_rate_calls; /* rate control checks */ |
| uint32_t ast_rate_raise; /* rate control raised xmit rate */ |
| uint32_t ast_rate_drop; /* rate control dropped xmit rate */ |
| }; |
| |
| struct dma_area { |
| ddi_acc_handle_t acc_hdl; /* handle for memory */ |
| caddr_t mem_va; /* CPU VA of memory */ |
| uint32_t nslots; /* number of slots */ |
| uint32_t size; /* size per slot */ |
| size_t alength; /* allocated size */ |
| /* >= product of above */ |
| |
| ddi_dma_handle_t dma_hdl; /* DMA handle */ |
| offset_t offset; /* relative to handle */ |
| ddi_dma_cookie_t cookie; /* associated cookie */ |
| uint32_t ncookies; /* must be 1 */ |
| uint32_t token; /* arbitrary identifier */ |
| }; |
| typedef struct dma_area dma_area_t; |
| |
| /* Load-time Configuration */ |
| |
| /* |
| * Per-instance load-time (note: NOT run-time) |
| * configurations for Atheros Device |
| */ |
| struct ath_config { |
| uint32_t ath_aggr_prot; |
| uint16_t txpowlimit; |
| uint16_t txpowlimit_override; |
| uint8_t cabqReadytime; /* Cabq Readytime % */ |
| uint8_t swBeaconProcess; /* Process received beacons in SW (vs HW) */ |
| }; |
| |
| /* Descriptor Management */ |
| |
| #define ATH_TXBUF_RESET(_bf) do { \ |
| (_bf)->bf_status = 0; \ |
| (_bf)->bf_lastbf = NULL; \ |
| (_bf)->bf_lastfrm = NULL; \ |
| (_bf)->bf_next = NULL; \ |
| (void) memset(&((_bf)->bf_state), 0, \ |
| sizeof (struct ath_buf_state)); \ |
| (void) memset(&((_bf)->tx_info_priv), 0, \ |
| sizeof (struct ath_tx_info_priv)); \ |
| _NOTE(CONSTCOND) \ |
| } while (0) |
| |
| enum buffer_type { |
| BUF_DATA = BIT(0), |
| BUF_AGGR = BIT(1), |
| BUF_AMPDU = BIT(2), |
| BUF_HT = BIT(3), |
| BUF_RETRY = BIT(4), |
| BUF_XRETRY = BIT(5), |
| BUF_SHORT_PREAMBLE = BIT(6), |
| BUF_BAR = BIT(7), |
| BUF_PSPOLL = BIT(8), |
| BUF_AGGR_BURST = BIT(9), |
| BUF_CALC_AIRTIME = BIT(10), |
| }; |
| |
| struct ath_buf_state { |
| int bfs_nframes; /* # frames in aggregate */ |
| uint16_t bfs_al; /* length of aggregate */ |
| uint16_t bfs_frmlen; /* length of frame */ |
| int bfs_seqno; /* sequence number */ |
| int bfs_tidno; /* tid of this frame */ |
| int bfs_retries; /* current retries */ |
| uint32_t bf_type; /* BUF_* (enum buffer_type) */ |
| /* key type used to encrypt this frame */ |
| uint32_t bfs_keyix; |
| enum ath9k_key_type bfs_keytype; |
| }; |
| |
| #define bf_nframes bf_state.bfs_nframes |
| #define bf_al bf_state.bfs_al |
| #define bf_frmlen bf_state.bfs_frmlen |
| #define bf_retries bf_state.bfs_retries |
| #define bf_seqno bf_state.bfs_seqno |
| #define bf_tidno bf_state.bfs_tidno |
| #define bf_rcs bf_state.bfs_rcs |
| #define bf_keyix bf_state.bfs_keyix |
| #define bf_keytype bf_state.bfs_keytype |
| #define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA) |
| #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) |
| #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) |
| #define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) |
| #define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) |
| #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) |
| #define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE) |
| #define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR) |
| #define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL) |
| #define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST) |
| |
| /* |
| * Abstraction of a contiguous buffer to transmit/receive. |
| * There is only a single hw descriptor encapsulated here. |
| */ |
| struct ath_buf { |
| /* last buf of this unit (a frame or an aggregate) */ |
| struct ath_buf *bf_lastbf; |
| struct ath_buf *bf_lastfrm; /* last buf of this frame */ |
| struct ath_buf *bf_next; /* next subframe in the aggregate */ |
| mblk_t *bf_m; |
| struct ath_desc *bf_desc; /* virtual addr of desc */ |
| uint32_t bf_daddr; /* physical addr of desc */ |
| dma_area_t bf_dma; /* dma area for buf */ |
| struct ieee80211_node *bf_in; /* pointer to the node */ |
| uint32_t bf_status; |
| uint16_t bf_flags; /* tx descriptor flags */ |
| struct ath_buf_state bf_state; /* buffer state */ |
| |
| /* Temp workground for rc */ |
| struct ath9k_tx_rate rates[4]; |
| struct ath_tx_info_priv tx_info_priv; |
| |
| /* we're in list of sc->sc_txbuf_list or sc->sc_rxbuf_list */ |
| list_node_t bf_node; |
| }; |
| |
| /* |
| * reset the rx buffer. |
| * any new fields added to the athbuf and require |
| * reset need to be added to this macro. |
| * currently bf_status is the only one requires that |
| * requires reset. |
| */ |
| #define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) |
| |
| /* hw processing complete, desc processed by hal */ |
| #define ATH_BUFSTATUS_DONE 0x00000001 |
| /* hw processing complete, desc hold for hw */ |
| #define ATH_BUFSTATUS_STALE 0x00000002 |
| /* Rx-only: OS is done with this packet and it's ok to queued it to hw */ |
| #define ATH_BUFSTATUS_FREE 0x00000004 |
| |
| /* RX / TX */ |
| |
| #define ATH_MAX_ANTENNA 3 |
| #define ATH_RXBUF 512 |
| #define WME_NUM_TID 16 |
| |
| void arn_rx_buf_link(struct arn_softc *sc, struct ath_buf *bf); |
| int arn_startrecv(struct arn_softc *sc); |
| boolean_t arn_stoprecv(struct arn_softc *sc); |
| void arn_flushrecv(struct arn_softc *sc); |
| uint32_t arn_calcrxfilter(struct arn_softc *sc); |
| int arn_rx_init(struct arn_softc *sc, int nbufs); |
| void arn_rx_cleanup(struct arn_softc *sc); |
| uint_t arn_softint_handler(caddr_t data); |
| void arn_setdefantenna(struct arn_softc *sc, uint32_t antenna); |
| |
| #define ATH_TXBUF 512 |
| /* max number of transmit attempts (tries) */ |
| #define ATH_TXMAXTRY 13 |
| /* max number of 11n transmit attempts (tries) */ |
| #define ATH_11N_TXMAXTRY 10 |
| /* max number of tries for management and control frames */ |
| #define ATH_MGT_TXMAXTRY 4 |
| #define WME_BA_BMP_SIZE 64 |
| #define WME_MAX_BA WME_BA_BMP_SIZE |
| #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
| |
| /* Wireless Multimedia Extension Defines */ |
| #define WME_AC_BE 0 /* best effort */ |
| #define WME_AC_BK 1 /* background */ |
| #define WME_AC_VI 2 /* video */ |
| #define WME_AC_VO 3 /* voice */ |
| #define WME_NUM_AC 4 |
| |
| /* |
| * Data transmit queue state. One of these exists for each |
| * hardware transmit queue. Packets sent to us from above |
| * are assigned to queues based on their priority. Not all |
| * devices support a complete set of hardware transmit queues. |
| * For those devices the array sc_ac2q will map multiple |
| * priorities to fewer hardware queues (typically all to one |
| * hardware queue). |
| */ |
| |
| struct ath_txq { |
| uint32_t axq_qnum; /* hardware q number */ |
| uint32_t *axq_link; /* link ptr in last TX desc */ |
| list_t axq_list; /* transmit queue */ |
| kmutex_t axq_lock; /* lock on q and link */ |
| unsigned long axq_lockflags; /* intr state when must cli */ |
| uint32_t axq_depth; /* queue depth (stat only) */ |
| uint8_t axq_aggr_depth; /* aggregates queued */ |
| uint32_t axq_totalqueued; /* total ever queued */ |
| boolean_t stopped; |
| struct ath_buf *axq_linkbuf; /* virtual addr of last buffer */ |
| /* first desc of the last descriptor that contains CTS */ |
| struct ath_desc *axq_lastdsWithCTS; |
| |
| /* |
| * final desc of the gating desc that determines whether |
| * lastdsWithCTS has been DMA'ed or not |
| */ |
| struct ath_desc *axq_gatingds; |
| |
| list_t axq_acq; |
| |
| uint32_t axq_intrcnt; /* interrupt count */ |
| }; |
| |
| |
| #define AGGR_CLEANUP BIT(1) |
| #define AGGR_ADDBA_COMPLETE BIT(2) |
| #define AGGR_ADDBA_PROGRESS BIT(3) |
| |
| /* per TID aggregate tx state for a destination */ |
| struct ath_atx_tid { |
| list_node_t list; |
| list_t buf_q; |
| struct ath_node *an; |
| struct ath_atx_ac *ac; |
| struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; /* active tx frames */ |
| uint16_t seq_start; |
| uint16_t seq_next; |
| uint16_t baw_size; |
| int tidno; |
| int baw_head; /* first un-acked tx buffer */ |
| int baw_tail; /* next unused tx buffer slot */ |
| int sched; |
| int paused; |
| uint8_t state; |
| int addba_exchangeattempts; |
| }; |
| |
| /* per access-category aggregate tx state for a destination */ |
| struct ath_atx_ac { |
| int sched; /* dest-ac is scheduled */ |
| int qnum; /* H/W queue number associated with this AC */ |
| list_node_t list; |
| list_t tid_q; |
| }; |
| |
| /* per dest tx state */ |
| struct ath_atx { |
| struct ath_atx_tid tid[WME_NUM_TID]; |
| struct ath_atx_ac ac[WME_NUM_AC]; |
| }; |
| |
| /* per-frame tx control block */ |
| struct ath_tx_control { |
| struct ath_txq *txq; |
| int if_id; |
| }; |
| |
| /* per frame tx status block */ |
| struct ath_xmit_status { |
| /* number of retries to successufully transmit this frame */ |
| int retries; |
| int flags; /* status of transmit */ |
| #define ATH_TX_ERROR 0x01 |
| #define ATH_TX_XRETRY 0x02 |
| #define ATH_TX_BAR 0x04 |
| }; |
| |
| struct ath_tx_stat { |
| int rssi; /* RSSI (noise floor ajusted) */ |
| int rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ |
| int rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ |
| int rateieee; /* data rate xmitted (IEEE rate code) */ |
| int rateKbps; /* data rate xmitted (Kbps) */ |
| int ratecode; /* phy rate code */ |
| int flags; /* validity flags */ |
| /* if any of ctl,extn chain rssis are valid */ |
| #define ATH_TX_CHAIN_RSSI_VALID 0x01 |
| /* if extn chain rssis are valid */ |
| #define ATH_TX_RSSI_EXTN_VALID 0x02 |
| uint32_t airtime; /* time on air per final tx rate */ |
| }; |
| |
| void arn_tx_node_init(struct arn_softc *sc, struct ath_node *an); |
| void arn_tx_node_cleanup(struct arn_softc *sc, struct ieee80211_node *in); |
| struct ath_txq *arn_txq_setup(struct arn_softc *sc, int qtype, int subtype); |
| void arn_tx_cleanupq(struct arn_softc *sc, struct ath_txq *txq); |
| int arn_tx_setup(struct arn_softc *sc, int haltype); |
| void arn_draintxq(struct arn_softc *sc, boolean_t retry_tx); |
| void arn_tx_draintxq(struct arn_softc *sc, struct ath_txq *txq); |
| void arn_txq_schedule(struct arn_softc *sc, struct ath_txq *txq); |
| int arn_tx(ieee80211com_t *ic, mblk_t *mp, uint8_t type); |
| int arn_txq_update(struct arn_softc *sc, int qnum, |
| struct ath9k_tx_queue_info *qinfo); |
| void arn_tx_int_proc(void *arg); |
| |
| /* Node / Aggregation */ |
| |
| #define ADDBA_EXCHANGE_ATTEMPTS 10 |
| #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ |
| #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ |
| /* number of delimiters for encryption padding */ |
| #define ATH_AGGR_ENCRYPTDELIM 10 |
| /* minimum h/w qdepth to be sustained to maximize aggregation */ |
| #define ATH_AGGR_MIN_QDEPTH 2 |
| #define ATH_AMPDU_SUBFRAME_DEFAULT 32 |
| #define IEEE80211_SEQ_SEQ_SHIFT 4 |
| #define IEEE80211_SEQ_MAX 4096 |
| #define IEEE80211_MIN_AMPDU_BUF 0x8 |
| #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 |
| |
| /* |
| * return whether a bit at index _n in bitmap _bm is set |
| * _sz is the size of the bitmap |
| */ |
| #define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ |
| ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) |
| |
| /* return block-ack bitmap index given sequence and starting sequence */ |
| #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) |
| |
| /* returns delimiter padding required given the packet length */ |
| #define ATH_AGGR_GET_NDELIM(_len) \ |
| (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ |
| (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) |
| |
| #define BAW_WITHIN(_start, _bawsz, _seqno) \ |
| ((((_seqno) - (_start)) & 4095) < (_bawsz)) |
| |
| #define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) |
| #define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) |
| #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) |
| #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
| |
| #define ATH_TX_ERROR 0x01 |
| #define ATH_TX_XRETRY 0x02 |
| #define ATH_TX_BAR 0x04 |
| |
| enum ATH_AGGR_STATUS { |
| ATH_AGGR_DONE, |
| ATH_AGGR_BAW_CLOSED, |
| ATH_AGGR_LIMITED, |
| }; |
| |
| struct aggr_rifs_param { |
| int param_max_frames; |
| int param_max_len; |
| int param_rl; |
| int param_al; |
| struct ath_rc_series *param_rcs; |
| }; |
| |
| /* RSSI correction */ |
| void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah); |
| |
| #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 |
| #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 |
| #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 |
| |
| #define ATH_RSSI_LPF_LEN 10 |
| #define RSSI_LPF_THRESHOLD -20 |
| #define ATH9K_RSSI_BAD -128 |
| #define ATH_RSSI_EP_MULTIPLIER (1<<7) |
| #define ATH_EP_MUL(x, mul) ((x) * (mul)) |
| #define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) |
| #define ATH_LPF_RSSI(x, y, len) \ |
| ((x != ATH_RSSI_DUMMY_MARKER) ? \ |
| (((x) * ((len) - 1) + (y)) / (len)) : (y)) |
| #define ATH_RSSI_LPF(x, y) do { \ |
| if ((y) >= RSSI_LPF_THRESHOLD) \ |
| x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ |
| } while (0) |
| #define ATH_EP_RND(x, mul) \ |
| ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
| |
| /* driver-specific node state */ |
| struct ath_node { |
| struct ieee80211_node an_node; /* base class */ |
| uint32_t an_tx_times; /* rate ctl times on one rate */ |
| uint32_t an_tx_ok; /* tx ok pkt */ |
| uint32_t an_tx_err; /* tx !ok pkt */ |
| uint32_t an_tx_retr; /* tx retry count */ |
| int32_t an_tx_upper; /* tx upper rate req cnt */ |
| uint32_t an_tx_antenna; /* antenna for last good frame */ |
| uint8_t an_tx_rix0; /* series 0 rate index */ |
| uint8_t an_tx_try0; /* series 0 try count */ |
| uint8_t an_tx_mgtrate; /* h/w rate for management/ctl frames */ |
| uint8_t an_tx_mgtratesp; /* short preamble h/w rate for " " */ |
| uint8_t an_tx_rate0; /* series 0 h/w rate */ |
| uint8_t an_tx_rate1; /* series 1 h/w rate */ |
| uint8_t an_tx_rate2; /* series 2 h/w rate */ |
| uint8_t an_tx_rate3; /* series 3 h/w rate */ |
| uint8_t an_tx_rate0sp; /* series 0 short preamble h/w rate */ |
| uint8_t an_tx_rate1sp; /* series 1 short preamble h/w rate */ |
| uint8_t an_tx_rate2sp; /* series 2 short preamble h/w rate */ |
| uint8_t an_tx_rate3sp; /* series 3 short preamble h/w rate */ |
| struct ath_rate_priv rate_priv; |
| struct ath_atx_tid tid[WME_NUM_TID]; |
| struct ath_atx_ac ac[WME_NUM_AC]; |
| uint16_t maxampdu; |
| uint8_t mpdudensity; |
| int last_rssi; |
| }; |
| #define ATH_NODE(_n) ((struct ath_node *)(_n)) |
| |
| /* |
| * Define the scheme that we select MAC address for multiple |
| * BSS on the same radio. The very first VAP will just use the MAC |
| * address from the EEPROM. For the next 3 VAPs, we set the |
| * U/L bit (bit 1) in MAC address, and use the next two bits as the |
| * index of the VAP. |
| */ |
| |
| #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ |
| ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02)) |
| |
| |
| /* driver-specific vap state */ |
| struct ath_vap { |
| int av_bslot; /* beacon slot index */ |
| enum ath9k_opmode av_opmode; /* VAP operational mode */ |
| struct ath_buf *av_bcbuf; /* beacon buffer */ |
| struct ath_tx_control av_btxctl; /* txctl information for beacon */ |
| }; |
| |
| /* Beacon Handling */ |
| |
| /* |
| * Regardless of the number of beacons we stagger, (i.e. regardless of the |
| * number of BSSIDs) if a given beacon does not go out even after waiting this |
| * number of beacon intervals, the game's up. |
| */ |
| #define BSTUCK_THRESH (9 * ATH_BCBUF) |
| #define ATH_BCBUF 4 /* number of beacon buffers */ |
| #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ |
| #define ATH_DEFAULT_BMISS_LIMIT 10 |
| #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
| |
| /* beacon configuration */ |
| struct ath_beacon_config { |
| uint16_t beacon_interval; |
| uint16_t listen_interval; |
| uint16_t dtim_period; |
| uint16_t bmiss_timeout; |
| uint8_t dtim_count; |
| uint8_t tim_offset; |
| union { |
| uint64_t last_tsf; |
| uint8_t last_tstamp[8]; |
| } u; /* last received beacon/probe response timestamp of this BSS. */ |
| }; |
| |
| uint32_t arn_beaconq_setup(struct ath_hal *ah); |
| int arn_beacon_alloc(struct arn_softc *sc, struct ieee80211_node *in); |
| void arn_beacon_config(struct arn_softc *sc); |
| void arn_beacon_return(struct arn_softc *sc); |
| void arn_beacon_sync(struct arn_softc *sc); |
| void arn_bmiss_proc(void *arg); |
| |
| void arn_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, |
| struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp); |
| |
| /* ANI */ |
| |
| /* |
| * ANI values for STA only. |
| * FIXME: Add appropriate values for AP later |
| */ |
| |
| #define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */ |
| #define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */ |
| #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */ |
| #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */ |
| |
| struct ath_ani { |
| boolean_t sc_caldone; |
| int16_t sc_noise_floor; |
| unsigned int sc_longcal_timer; |
| unsigned int sc_shortcal_timer; |
| unsigned int sc_resetcal_timer; |
| unsigned int sc_checkani_timer; |
| }; |
| |
| /* LED Control */ |
| #define ATH_LED_PIN 1 |
| |
| enum ath_led_type { |
| ATH_LED_RADIO, |
| ATH_LED_ASSOC, |
| ATH_LED_TX, |
| ATH_LED_RX |
| }; |
| |
| struct ath_led { |
| struct arn_softc *sc; |
| enum ath_led_type led_type; |
| char name[32]; |
| boolean_t registered; |
| }; |
| |
| /* Rfkill */ |
| #define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */ |
| |
| /* Main driver core */ |
| /* |
| * Default cache line size, in bytes. |
| * Used when PCI device not fully initialized by bootrom/BIOS |
| */ |
| #define DEFAULT_CACHELINE 32 |
| #define ATH_DEFAULT_NOISE_FLOOR -95 |
| #define ATH_REGCLASSIDS_MAX 10 |
| #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
| #define ATH_MAX_SW_RETRIES 10 |
| #define ATH_CHAN_MAX 255 |
| #define IEEE80211_WEP_NKID 4 /* number of key ids */ |
| #define IEEE80211_RATE_VAL 0x7f |
| /* |
| * The key cache is used for h/w cipher state and also for |
| * tracking station state such as the current tx antenna. |
| * We also setup a mapping table between key cache slot indices |
| * and station state to short-circuit node lookups on rx. |
| * Different parts have different size key caches. We handle |
| * up to ATH_KEYMAX entries (could dynamically allocate state). |
| */ |
| #define ATH_KEYMAX 128 /* max key cache size we handle */ |
| |
| #define ATH_IF_ID_ANY 0xff |
| #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
| #define ATH_RSSI_DUMMY_MARKER 0x127 |
| #define ATH_RATE_DUMMY_MARKER 0 |
| |
| enum PROT_MODE { |
| PROT_M_NONE = 0, |
| PROT_M_RTSCTS, |
| PROT_M_CTSONLY |
| }; |
| |
| #define SC_OP_INVALID BIT(0) |
| #define SC_OP_BEACONS BIT(1) |
| #define SC_OP_RXAGGR BIT(2) |
| #define SC_OP_TXAGGR BIT(3) |
| #define SC_OP_CHAINMASK_UPDATE BIT(4) |
| #define SC_OP_FULL_RESET BIT(5) |
| #define SC_OP_NO_RESET BIT(6) |
| #define SC_OP_PREAMBLE_SHORT BIT(7) |
| #define SC_OP_PROTECT_ENABLE BIT(8) |
| #define SC_OP_RXFLUSH BIT(9) |
| #define SC_OP_LED_ASSOCIATED BIT(10) |
| #define SC_OP_RFKILL_REGISTERED BIT(11) |
| #define SC_OP_RFKILL_SW_BLOCKED BIT(12) |
| #define SC_OP_RFKILL_HW_BLOCKED BIT(13) |
| |
| /* HT */ |
| typedef struct ht_conf { |
| boolean_t ht_supported; |
| uint16_t cap; |
| uint8_t ampdu_factor; |
| uint8_t ampdu_density; |
| uint8_t rx_mcs_mask[10]; |
| } arn_ht_conf; |
| |
| uint8_t parse_mpdudensity(uint8_t mpdudensity); |
| |
| void arn_ampdu_recv_action(struct ieee80211_node *in, |
| const uint8_t *frm, const uint8_t *efrm); |
| int arn_ampdu_send_action(struct ieee80211_node *in, |
| int category, int action, uint16_t args[4]); |
| void arn_dump_line(unsigned char *p, uint32_t len, boolean_t isaddress, |
| uint32_t group); |
| void arn_dump_pkg(unsigned char *p, uint32_t len, boolean_t isaddress, |
| uint32_t group); |
| |
| struct arn_softc { |
| ieee80211com_t sc_isc; /* IEEE 802.11 common */ |
| dev_info_t *sc_dev; /* back pointer to dev_info_t */ |
| ddi_taskq_t *sc_tq; /* private task queue */ |
| struct ath_hal *sc_ah; |
| struct ath_config sc_config; |
| caddr_t mem; |
| |
| uint8_t sc_isrunning; /* device is operational */ |
| uint8_t sc_mrretry; /* multi-rate retry support */ |
| uint8_t sc_have11g; /* have 11g support */ |
| uint8_t sc_bsync; /* beacon sync */ |
| |
| ddi_acc_handle_t sc_cfg_handle; /* DDI I/O handle */ |
| ddi_acc_handle_t sc_io_handle; /* DDI I/O handle */ |
| ddi_acc_handle_t sc_EEPROM_handle; /* DDI I/O handle */ |
| ddi_iblock_cookie_t sc_iblock; |
| ddi_softintr_t sc_softint_id; |
| |
| /* 802.11n/HT capabilities */ |
| arn_ht_conf sc_ht_conf; |
| void (*sc_recv_action)(ieee80211_node_t *, |
| const uint8_t *, const uint8_t *); |
| int (*sc_send_action)(ieee80211_node_t *, |
| int, int, uint16_t[4]); |
| |
| /* TX/RX descriptors */ |
| struct ath_desc *sc_desc; |
| /* descriptor structure */ |
| dma_area_t sc_desc_dma; |
| /* pointer to the first "struct ath_buf" */ |
| struct ath_buf *sc_vbufptr; |
| /* length of all allocated "struct ath_buf" */ |
| uint32_t sc_vbuflen; |
| /* size of one DMA TX/RX buffer based on 802.11 MTU */ |
| uint32_t tx_dmabuf_size; |
| uint32_t rx_dmabuf_size; |
| |
| uint8_t sc_curbssid[6]; |
| uint8_t sc_myaddr[6]; |
| uint8_t sc_bssidmask[6]; |
| |
| int sc_debug; |
| uint32_t sc_intrstatus; |
| uint32_t sc_flags; /* SC_OP_* */ |
| unsigned int rx_filter; |
| uint16_t sc_curtxpow; |
| uint16_t sc_curaid; |
| uint16_t sc_cachelsz; |
| int sc_slotupdate; /* slot to next advance fsm */ |
| int sc_slottime; |
| int sc_bslot[ATH_BCBUF]; |
| uint8_t sc_tx_chainmask; |
| uint8_t sc_rx_chainmask; |
| enum ath9k_int sc_imask; |
| enum PROT_MODE sc_protmode; |
| |
| uint8_t sc_nbcnvaps; /* # of vaps sending beacons */ |
| uint16_t sc_nvaps; /* # of active virtual ap's */ |
| |
| uint8_t sc_mcastantenna; |
| uint8_t sc_defant; /* current default antenna */ |
| uint8_t sc_rxotherant; /* rx's on non-default antenna */ |
| |
| struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ |
| enum ath9k_ht_extprotspacing sc_ht_extprotspacing; |
| enum ath9k_ht_macmode tx_chan_width; |
| |
| enum { |
| OK, /* no change needed */ |
| UPDATE, /* update pending */ |
| COMMIT /* beacon sent, commit change */ |
| } sc_updateslot; /* slot time update fsm */ |
| |
| /* Crypto */ |
| uint32_t sc_keymax; /* size of key cache */ |
| uint8_t sc_keymap[16]; /* bit map of key cache use */ |
| uint8_t sc_splitmic; /* split TKIP MIC keys */ |
| |
| /* RX */ |
| list_t sc_rxbuf_list; |
| int sc_rxbufsize; /* rx size based on mtu */ |
| uint32_t *sc_rxlink; /* link ptr in last RX desc */ |
| uint32_t sc_rx_pend; |
| uint64_t sc_lastrx; /* tsf at last rx'd frame */ |
| |
| /* TX */ |
| list_t sc_txbuf_list; |
| struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES]; |
| uint32_t sc_txqsetup; |
| int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ |
| uint16_t seq_no; /* TX sequence number */ |
| |
| /* Beacon */ |
| struct ath9k_tx_queue_info sc_beacon_qi; |
| struct ath_txq *sc_cabq; |
| list_t sc_bcbuf_list; /* beacon buffer */ |
| uint32_t sc_beaconq; |
| uint32_t sc_bmisscount; |
| uint32_t ast_be_xmit; /* beacons transmitted */ |
| uint64_t bc_tstamp; |
| struct ieee80211_beacon_offsets asc_boff; /* dynamic update state */ |
| |
| /* Rate */ |
| struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; |
| struct ath_rate_table *sc_currates; /* current rate table */ |
| uint8_t asc_rixmap[256]; /* IEEE to h/w rate table ix */ |
| uint8_t sc_protrix; /* protection rate index */ |
| |
| /* mode */ |
| enum wireless_mode sc_curmode; /* current phy mode */ |
| |
| /* Channel, Band */ |
| struct ath9k_channel sc_curchan; |
| |
| /* Locks */ |
| kmutex_t sc_genlock; |
| kmutex_t sc_serial_rw; |
| kmutex_t sc_rxbuflock; /* recv lock */ |
| kmutex_t sc_txbuflock; /* txbuf lock */ |
| kmutex_t sc_rxflushlock; |
| kmutex_t sc_resetlock; |
| kmutex_t sc_bcbuflock; /* beacon buffer lock */ |
| kmutex_t sc_resched_lock; |
| boolean_t sc_resched_needed; |
| |
| /* LEDs */ |
| struct ath_led radio_led; |
| struct ath_led assoc_led; |
| struct ath_led tx_led; |
| struct ath_led rx_led; |
| |
| uint8_t sc_mcast_refs[64]; /* refer count */ |
| uint32_t sc_mcast_hash[2]; /* multicast hash table */ |
| |
| /* Rfkill */ |
| |
| /* ANI */ |
| struct ath_ani sc_ani; |
| |
| /* interface statistics */ |
| struct ath_stats sc_stats; |
| |
| boolean_t sc_promisc; /* Promiscuous mode enabled */ |
| |
| timeout_id_t sc_scan_timer; |
| timeout_id_t sc_cal_timer; |
| |
| int (*sc_newstate)(ieee80211com_t *, enum ieee80211_state, int); |
| void (*sc_recv_mgmt)(ieee80211com_t *, mblk_t *, ieee80211_node_t *, |
| int, int, uint32_t); |
| }; |
| |
| int arn_reset(ieee80211com_t *ic); |
| |
| int arn_get_hal_qnum(uint16_t queue, struct arn_softc *sc); |
| |
| int ath_cabq_update(struct arn_softc *); |
| |
| void arn_update_chainmask(struct arn_softc *sc); |
| |
| /* |
| * Read and write, they both share the same lock. We do this to serialize |
| * reads and writes on Atheros 802.11n PCI devices only. This is required |
| * as the FIFO on these devices can only accept sanely 2 requests. After |
| * that the device goes bananas. Serializing the reads/writes prevents this |
| * from happening. |
| */ |
| void |
| arn_iowrite32(struct ath_hal *ah, uint32_t reg_offset, uint32_t val); |
| unsigned int |
| arn_ioread32(struct ath_hal *ah, uint32_t reg_offset); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _ARN_CORE_H */ |