summaryrefslogtreecommitdiff
path: root/sys/dev/ic/athnvar.h
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2009-11-14 16:55:12 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2009-11-14 16:55:12 +0000
commit07f1b17cbe2d5d588c48d41b1c9e7f38d757329f (patch)
tree5ea86d4058aa63b25ddea485dfbd960941df0d05 /sys/dev/ic/athnvar.h
parent243dc61326c89d883d7414f28251ebfa80ca99b8 (diff)
athn(4), a driver for Atheros 802.11a/g/n devices.
written from scratch based on the vendor driver for Linux (ath9k). AR9285 and AR9287 parts are 100% untested. only basic functionnalities are enabled for now. committed over an AR9281. "commit" deraadt
Diffstat (limited to 'sys/dev/ic/athnvar.h')
-rw-r--r--sys/dev/ic/athnvar.h513
1 files changed, 513 insertions, 0 deletions
diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h
new file mode 100644
index 00000000000..d727bf7dce4
--- /dev/null
+++ b/sys/dev/ic/athnvar.h
@@ -0,0 +1,513 @@
+/* $OpenBSD: athnvar.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * Permission to use, copy, modify, and 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.
+ */
+
+#define ATHN_DEBUG 1
+#define ATHN_INTR_MITIGATION 1
+#define ATHN_BT_COEXISTENCE 1
+
+#ifdef ATHN_DEBUG
+#define DPRINTF(x) do { if (athn_debug > 0) printf x; } while (0)
+#define DPRINTFN(n, x) do { if (athn_debug >= (n)) printf x; } while (0)
+extern int athn_debug;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n, x)
+#endif
+
+#define ATHN_RXBUFSZ 3872
+#define ATHN_TXBUFSZ 4096
+
+#define ATHN_NRXBUFS 64
+#define ATHN_NTXBUFS 64 /* Shared between all Tx queues. */
+#define ATHN_MAX_SCATTER 16
+
+struct athn_rx_radiotap_header {
+ struct ieee80211_radiotap_header wr_ihdr;
+ uint64_t wr_tsft;
+ uint8_t wr_flags;
+ uint8_t wr_rate;
+ uint16_t wr_chan_freq;
+ uint16_t wr_chan_flags;
+ int8_t wr_dbm_antsignal;
+ uint8_t wr_antenna;
+} __packed;
+
+#define ATHN_RX_RADIOTAP_PRESENT \
+ (1 << IEEE80211_RADIOTAP_TSFT | \
+ 1 << IEEE80211_RADIOTAP_FLAGS | \
+ 1 << IEEE80211_RADIOTAP_RATE | \
+ 1 << IEEE80211_RADIOTAP_CHANNEL | \
+ 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \
+ 1 << IEEE80211_RADIOTAP_ANTENNA)
+
+struct athn_tx_radiotap_header {
+ struct ieee80211_radiotap_header wt_ihdr;
+ uint8_t wt_flags;
+ uint8_t wt_rate;
+ uint16_t wt_chan_freq;
+ uint16_t wt_chan_flags;
+ uint8_t wt_hwqueue;
+} __packed;
+
+#define ATHN_TX_RADIOTAP_PRESENT \
+ (1 << IEEE80211_RADIOTAP_FLAGS | \
+ 1 << IEEE80211_RADIOTAP_RATE | \
+ 1 << IEEE80211_RADIOTAP_CHANNEL | \
+ 1 << IEEE80211_RADIOTAP_HWQUEUE)
+
+struct athn_tx_buf {
+ SIMPLEQ_ENTRY(athn_tx_buf) bf_list;
+
+ struct ar_tx_desc *bf_descs;
+ bus_dmamap_t bf_map;
+ bus_addr_t bf_daddr;
+
+ struct mbuf *bf_m;
+ struct ieee80211_node *bf_ni;
+};
+
+struct athn_txq {
+ SIMPLEQ_HEAD(, athn_tx_buf) head;
+ struct ar_tx_desc *lastds;
+};
+
+struct athn_rx_buf {
+ SIMPLEQ_ENTRY(athn_rx_buf) bf_list;
+
+ struct ar_rx_desc *bf_desc;
+ bus_dmamap_t bf_map;
+
+ struct mbuf *bf_m;
+ bus_addr_t bf_daddr;
+};
+
+struct athn_rxq {
+ struct athn_rx_buf bf[ATHN_NRXBUFS];
+
+ struct ar_rx_desc *descs;
+ struct ar_rx_desc *lastds;
+ bus_dmamap_t map;
+ bus_dma_segment_t seg;
+
+ SIMPLEQ_HEAD(, athn_rx_buf) head;
+};
+
+/* Software rate indexes. */
+#define ATHN_RIDX_CCK1 0
+#define ATHN_RIDX_OFDM6 4
+#define ATHN_RIDX_MCS0 12
+#define ATHN_RIDX_MCS15 27
+#define ATHN_RIDX_MAX 27
+#define ATHN_IS_OFDM_RIDX(ridx) (athn_rates[ridx].phy == IEEE80211_T_OFDM)
+#define ATHN_IS_HT_RIDX(ridx) ((ridx) >= ATHN_RIDX_MCS0)
+
+static const struct athn_rate {
+ uint8_t rate; /* Rate in 500Kbps unit or MCS if 0x80. */
+ uint8_t hwrate; /* HW representation. */
+ enum ieee80211_phytype phy;
+} athn_rates[] = {
+ { 2, 0x1b, IEEE80211_T_DS },
+ { 4, 0x1a, IEEE80211_T_DS },
+ { 11, 0x19, IEEE80211_T_DS },
+ { 22, 0x18, IEEE80211_T_DS },
+ { 12, 0x0b, IEEE80211_T_OFDM },
+ { 18, 0x0f, IEEE80211_T_OFDM },
+ { 24, 0x0a, IEEE80211_T_OFDM },
+ { 36, 0x0e, IEEE80211_T_OFDM },
+ { 48, 0x09, IEEE80211_T_OFDM },
+ { 72, 0x0d, IEEE80211_T_OFDM },
+ { 96, 0x08, IEEE80211_T_OFDM },
+ { 108, 0x0c, IEEE80211_T_OFDM },
+ { 0x80, 0x80, IEEE80211_T_OFDM },
+ { 0x81, 0x81, IEEE80211_T_OFDM },
+ { 0x82, 0x82, IEEE80211_T_OFDM },
+ { 0x83, 0x83, IEEE80211_T_OFDM },
+ { 0x84, 0x84, IEEE80211_T_OFDM },
+ { 0x85, 0x85, IEEE80211_T_OFDM },
+ { 0x86, 0x86, IEEE80211_T_OFDM },
+ { 0x87, 0x87, IEEE80211_T_OFDM },
+ { 0x88, 0x88, IEEE80211_T_OFDM },
+ { 0x89, 0x89, IEEE80211_T_OFDM },
+ { 0x8a, 0x8a, IEEE80211_T_OFDM },
+ { 0x8b, 0x8b, IEEE80211_T_OFDM },
+ { 0x8c, 0x8c, IEEE80211_T_OFDM },
+ { 0x8d, 0x8d, IEEE80211_T_OFDM },
+ { 0x8e, 0x8e, IEEE80211_T_OFDM },
+ { 0x8f, 0x8f, IEEE80211_T_OFDM }
+};
+
+struct athn_series {
+ uint8_t tries;
+ uint8_t hwrate;
+ uint16_t dur;
+};
+
+struct athn_pier {
+ uint8_t fbin;
+ const uint8_t *pwr[AR_PD_GAINS_IN_MASK];
+ const uint8_t *vpd[AR_PD_GAINS_IN_MASK];
+};
+
+/*
+ * Structures used to store initialization values.
+ */
+struct athn_ini {
+ int nregs;
+ const uint16_t *regs;
+ const uint32_t *vals_5g20;
+#ifndef IEEE80211_NO_HT
+ const uint32_t *vals_5g40;
+ const uint32_t *vals_2g40;
+#endif
+ const uint32_t *vals_2g20;
+ int ncmregs;
+ const uint16_t *cmregs;
+ const uint32_t *cmvals;
+};
+
+struct athn_gain {
+ int nregs;
+ const uint16_t *regs;
+ const uint32_t *vals_5g;
+ const uint32_t *vals_2g;
+};
+
+struct athn_addac {
+ int nvals;
+ const uint32_t *vals;
+};
+
+/* Tx queue software indexes. */
+#define ATHN_QID_AC_BE 0
+#define ATHN_QID_PSPOLL 1
+#define ATHN_QID_AC_BK 2
+#define ATHN_QID_AC_VI 3
+#define ATHN_QID_AC_VO 4
+#define ATHN_QID_UAPSD 5
+#define ATHN_QID_CAB 6
+#define ATHN_QID_BEACON 7
+#define ATHN_QID_COUNT 8
+
+/* Map Access Category to Tx queue Id. */
+static const uint8_t athn_ac2qid[EDCA_NUM_AC] = {
+ ATHN_QID_AC_BE, /* EDCA_AC_BE */
+ ATHN_QID_AC_BK, /* EDCA_AC_BK */
+ ATHN_QID_AC_VI, /* EDCA_AC_VI */
+ ATHN_QID_AC_VO /* EDCA_AC_VO */
+};
+
+static const uint8_t athn_5ghz_chans[] = {
+ /* UNII 1. */
+ 36, 40, 44, 48,
+ /* UNII 2. */
+ 52, 56, 60, 64,
+ /* Middle band. */
+ 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
+ /* UNII 3. */
+ 149, 153, 157, 161, 165
+};
+
+/* Number of data bits per OFDM symbol for MCS[0-15]. */
+/* See tables 20-29, 20-30, 20-33, 20-34. */
+static const uint16_t ar_mcs_ndbps[][2] = {
+ /* 20MHz 40MHz */
+ { 26, 54 }, /* MCS0 */
+ { 52, 108 }, /* MCS1 */
+ { 78, 162 }, /* MCS2 */
+ { 104, 216 }, /* MCS3 */
+ { 156, 324 }, /* MCS4 */
+ { 208, 432 }, /* MCS5 */
+ { 234, 486 }, /* MCS6 */
+ { 260, 540 }, /* MCS7 */
+ { 26, 108 }, /* MCS8 */
+ { 52, 216 }, /* MCS9 */
+ { 78, 324 }, /* MCS10 */
+ { 104, 432 }, /* MCS11 */
+ { 156, 648 }, /* MCS12 */
+ { 208, 864 }, /* MCS13 */
+ { 234, 972 }, /* MCS14 */
+ { 260, 1080 } /* MCS15 */
+};
+
+#define ATHN_POWER_OFDM6 0
+#define ATHN_POWER_OFDM9 1
+#define ATHN_POWER_OFDM12 2
+#define ATHN_POWER_OFDM18 3
+#define ATHN_POWER_OFDM24 4
+#define ATHN_POWER_OFDM36 5
+#define ATHN_POWER_OFDM48 6
+#define ATHN_POWER_OFDM54 7
+#define ATHN_POWER_CCK1_LP 8
+#define ATHN_POWER_CCK2_LP 9
+#define ATHN_POWER_CCK2_SP 10
+#define ATHN_POWER_CCK55_LP 11
+#define ATHN_POWER_CCK55_SP 12
+#define ATHN_POWER_CCK11_LP 13
+#define ATHN_POWER_CCK11_SP 14
+#define ATHN_POWER_XR 15
+#define ATHN_POWER_HT20(mcs) (16 + (mcs))
+#define ATHN_POWER_HT40(mcs) (24 + (mcs))
+#define ATHN_POWER_CCK_DUP 32
+#define ATHN_POWER_OFDM_DUP 33
+#define ATHN_POWER_CCK_EXT 34
+#define ATHN_POWER_OFDM_EXT 35
+#define ATHN_POWER_COUNT 36
+
+struct athn_node {
+ struct ieee80211_node ni;
+ struct ieee80211_amrr_node amn;
+ uint8_t ridx[IEEE80211_RATE_MAXSIZE];
+ uint8_t fallback[IEEE80211_RATE_MAXSIZE];
+};
+
+#define ATHN_ANI_PERIOD 100
+#define ATHN_ANI_RSSI_THR_HIGH 40
+#define ATHN_ANI_RSSI_THR_LOW 7
+struct athn_ani {
+ uint8_t noise_immunity_level;
+ uint8_t spur_immunity_level;
+ uint8_t firstep_level;
+ uint8_t ofdm_weak_signal;
+ uint8_t cck_weak_signal;
+
+ uint32_t listen_time;
+
+ uint32_t ofdm_trig_high;
+ uint32_t ofdm_trig_low;
+
+ int32_t cck_trig_high;
+ int32_t cck_trig_low;
+
+ uint32_t ofdm_phy_err_base;
+ uint32_t cck_phy_err_base;
+ uint32_t ofdm_phy_err_count;
+ uint32_t cck_phy_err_count;
+
+ uint32_t cyccnt;
+ uint32_t txfcnt;
+ uint32_t rxfcnt;
+};
+
+struct athn_iq_cal {
+ uint32_t pwr_meas_i;
+ uint32_t pwr_meas_q;
+ int32_t iq_corr_meas;
+};
+
+struct athn_adc_cal {
+ uint32_t pwr_meas_odd_i;
+ uint32_t pwr_meas_even_i;
+ uint32_t pwr_meas_odd_q;
+ uint32_t pwr_meas_even_q;
+};
+
+struct athn_calib {
+ int nsamples;
+ struct athn_iq_cal iq[AR_MAX_CHAINS];
+ struct athn_adc_cal adc_gain[AR_MAX_CHAINS];
+ struct athn_adc_cal adc_dc_offset[AR_MAX_CHAINS];
+};
+
+#define ATHN_NF_CAL_HIST_MAX 5
+
+struct athn_softc;
+
+struct athn_ops {
+ void (*setup)(struct athn_softc *);
+ void (*set_txpower)(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+ void (*spur_mitigate)(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+ const struct ar_spur_chan *(*get_spur_chans)(struct athn_softc *, int);
+ void (*init_from_rom)(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+ int (*set_synth)(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+ void (*swap_rom)(struct athn_softc *);
+ void (*olpc_init)(struct athn_softc *);
+};
+
+struct athn_softc {
+ struct device sc_dev;
+ struct ieee80211com sc_ic;
+
+ int (*sc_enable)(struct athn_softc *);
+ void (*sc_disable)(struct athn_softc *);
+ void (*sc_power)(struct athn_softc *, int);
+ void (*sc_disable_aspm)(struct athn_softc *);
+
+ int (*sc_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
+
+ bus_dma_tag_t sc_dmat;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+
+ struct timeout scan_to;
+ struct timeout calib_to;
+ struct ieee80211_amrr amrr;
+
+ u_int flags;
+#define ATHN_FLAG_PCIE (1 << 0)
+#define ATHN_FLAG_OLPC (1 << 1)
+#define ATHN_FLAG_SPLIT_MMIC (1 << 2)
+#define ATHN_FLAG_RFSILENT (1 << 3)
+#define ATHN_FLAG_RFSILENT_REVERSED (1 << 4)
+#define ATHN_FLAG_BTCOEX2WIRE (1 << 5)
+#define ATHN_FLAG_BTCOEX3WIRE (1 << 6)
+/* Shortcut. */
+#define ATHN_FLAG_BTCOEX (ATHN_FLAG_BTCOEX2WIRE | ATHN_FLAG_BTCOEX3WIRE)
+
+ uint8_t ngpiopins;
+ int rfsilent_pin;
+
+ uint16_t mac_ver;
+ uint8_t mac_rev;
+ uint8_t rf_rev;
+ uint16_t eep_rev;
+ uint32_t phy_rev;
+
+ uint8_t txchainmask;
+ uint8_t rxchainmask;
+ uint8_t ntxchains;
+ uint8_t nrxchains;
+
+ uint8_t calib_mask;
+#define ATHN_CAL_IQ (1 << 0)
+#define ATHN_CAL_ADC_GAIN (1 << 1)
+#define ATHN_CAL_ADC_DC (1 << 2)
+
+ /* Open Loop Power Control. */
+ int8_t tx_gain_tbl[AR9280_TX_GAIN_TABLE_SIZE];
+ int8_t pdadc;
+ int8_t tcomp;
+
+ uint32_t rwbuf[64];
+
+ int kc_entries;
+
+ void *eep;
+ uint32_t eep_base;
+ uint32_t eep_size;
+
+ struct athn_rxq rxq;
+ struct athn_txq txq[31]; /* 0x1f ??? */
+
+ struct ar_tx_desc *descs;
+ bus_dmamap_t map;
+ bus_dma_segment_t seg;
+ SIMPLEQ_HEAD(, athn_tx_buf) txbufs;
+ struct athn_tx_buf txpool[ATHN_NTXBUFS];
+
+ int sc_tx_timer;
+
+ const struct athn_ini *ini;
+ const struct athn_gain *rx_gain;
+ const struct athn_gain *tx_gain;
+ const struct athn_addac *addac;
+ const uint32_t *serdes;
+ uint32_t workaround;
+
+
+ struct athn_ops ops;
+
+ int fixed_ridx;
+
+ int16_t def_nf;
+ struct {
+ int16_t nf[AR_MAX_CHAINS];
+ int16_t nf_ext[AR_MAX_CHAINS];
+ } nf_hist[ATHN_NF_CAL_HIST_MAX];
+ int nf_hist_cur;
+ int16_t nf_priv[AR_MAX_CHAINS];
+ int16_t nf_ext_priv[AR_MAX_CHAINS];
+
+ struct athn_calib calib;
+ struct athn_ani ani;
+
+#if NBPFILTER > 0
+ caddr_t sc_drvbpf;
+
+ union {
+ struct athn_rx_radiotap_header th;
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
+ } sc_rxtapu;
+#define sc_rxtap sc_rxtapu.th
+ int sc_rxtap_len;
+
+ union {
+ struct athn_tx_radiotap_header th;
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
+ } sc_txtapu;
+#define sc_txtap sc_txtapu.th
+ int sc_txtap_len;
+#endif
+};
+
+extern int athn_attach(struct athn_softc *);
+extern void athn_detach(struct athn_softc *);
+extern int athn_intr(void *);
+extern int ar5416_attach(struct athn_softc *);
+extern int ar9280_attach(struct athn_softc *);
+extern int ar9285_attach(struct athn_softc *);
+extern int ar9287_attach(struct athn_softc *);
+extern uint8_t athn_reverse_bits(uint8_t, int);
+extern uint8_t athn_chan2fbin(struct ieee80211_channel *);
+extern void athn_set_viterbi_mask(struct athn_softc *, int);
+extern void athn_write_txpower(struct athn_softc *, int16_t[]);
+extern void athn_get_lg_tpow(struct athn_softc *,
+ struct ieee80211_channel *, uint8_t,
+ const struct ar_cal_target_power_leg *, int, uint8_t[]);
+extern void athn_get_ht_tpow(struct athn_softc *,
+ struct ieee80211_channel *, uint8_t,
+ const struct ar_cal_target_power_ht *, int, uint8_t[]);
+extern void athn_get_pdadcs(struct athn_softc *, uint8_t,
+ struct athn_pier *, struct athn_pier *, int, int, uint8_t,
+ uint8_t *, uint8_t *);
+extern void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *,
+ int *);
+/* XXX not here. */
+extern void ar5416_set_txpower(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar5416_swap_rom(struct athn_softc *);
+extern void ar9280_2_0_olpc_get_pdadcs(struct athn_softc *,
+ struct ieee80211_channel *, int, uint8_t[], uint8_t[],
+ uint8_t *);
+extern int ar9280_set_synth(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9280_spur_mitigate(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9287_1_2_enable_async_fifo(struct athn_softc *);
+extern void ar9287_1_2_setup_async_fifo(struct athn_softc *);
+extern const struct ar_spur_chan *ar5416_get_spur_chans(struct athn_softc *,
+ int);
+extern int ar5416_init_calib(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern int ar9285_1_2_init_calib(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9285_pa_calib(struct athn_softc *);
+extern void ar9280_reset_rx_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar9280_reset_tx_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_reset_addac(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_reset_bb_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_rf_reset(struct athn_softc *,
+ struct ieee80211_channel *);