view usr/src/uts/common/io/arn/core.h @ 9928:7e332a7c18f5

6814300 Need support for Atheros AR9280 and AR9281 6834736 Need support for new wireless chipset AR9285
author lin wang - Sun Microsystems - Beijing China <Wang.Lin@Sun.COM>
date Tue, 23 Jun 2009 01:08:49 +0800
parents
children
line wrap: on
line source

/*
 * Copyright 2009 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 _CORE_H
#define	_CORE_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/note.h>
#include <sys/list.h>
#include <sys/net80211.h>

#include "ath9k.h"
#include "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	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))

// static const uint8_t ath_bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

/* 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;		\
		memset(&((_bf)->bf_state), 0,	\
		sizeof (struct ath_buf_state));	\
	} 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 */

	/* we're in list of sc->sc_txbuf_list or asc->asc_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)
#define	TID_TO_WME_AC(_tid)				\
	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
	(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
	(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
	WME_AC_VO)

/* 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 {
	uint_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 */
	uint_t		axq_depth; /* queue depth (stat only) */
	uint8_t 	axq_aggr_depth; /* aggregates queued */
	uint32_t 	axq_totalqueued; /* total ever queued */
	struct ath_buf	*axq_linkbuf; /* virtual addr of last buffer */
	/* first desc of the last descriptor that contains CTS */
	struct ath_desc *axq_lastdsWithCTS;
	uint_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_node_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_node_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 */
};

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);
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)->an_aggr.tx.tid[(_tidno)])

enum ATH_AGGR_STATUS {
	ATH_AGGR_DONE,
	ATH_AGGR_BAW_CLOSED,
	ATH_AGGR_LIMITED,
	ATH_AGGR_SHORTPKT,
	ATH_AGGR_8K_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;
};

/* 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 arn_softc *an_sc;
#ifdef ARN_11N
	struct ath_node_aggr an_aggr;
#endif
	uint16_t maxampdu;
	uint8_t mpdudensity;
};
#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)

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;

	/* 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 */
	int32_t sc_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 *);

/*
 * 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 /* _CORE_H */