/* $OpenBSD: athnvar.h,v 1.30 2011/01/08 15:05:24 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini * * 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. */ #ifdef notyet #define ATHN_BT_COEXISTENCE 1 #endif #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 LE_READ_4(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24) #define LE_READ_2(p) ((p)[0] | (p)[1] << 8) #define ATHN_RXBUFSZ 3872 #define ATHN_TXBUFSZ 4096 #define ATHN_NRXBUFS 64 #define ATHN_NTXBUFS 64 /* Shared between all Tx queues. */ 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; void *bf_descs; bus_dmamap_t bf_map; bus_addr_t bf_daddr; struct mbuf *bf_m; struct ieee80211_node *bf_ni; int bf_txflags; #define ATHN_TXFLAG_PAPRD (1 << 0) }; struct athn_txq { SIMPLEQ_HEAD(, athn_tx_buf) head; void *lastds; struct athn_tx_buf *wait; int queued; }; struct athn_rx_buf { SIMPLEQ_ENTRY(athn_rx_buf) bf_list; void *bf_desc; bus_dmamap_t bf_map; struct mbuf *bf_m; bus_addr_t bf_daddr; }; struct athn_rxq { struct athn_rx_buf *bf; void *descs; void *lastds; bus_dmamap_t map; bus_dma_segment_t seg; int count; SIMPLEQ_HEAD(, athn_rx_buf) head; }; /* Software rate indexes. */ #define ATHN_RIDX_CCK1 0 #define ATHN_RIDX_CCK2 1 #define ATHN_RIDX_OFDM6 4 #define ATHN_RIDX_MCS0 12 #define ATHN_RIDX_MCS15 27 #define ATHN_RIDX_MAX 27 #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. */ uint8_t rspridx; /* Control Response Frame rate index. */ enum ieee80211_phytype phy; } athn_rates[] = { { 2, 0x1b, 0, IEEE80211_T_DS }, { 4, 0x1a, 1, IEEE80211_T_DS }, { 11, 0x19, 1, IEEE80211_T_DS }, { 22, 0x18, 1, IEEE80211_T_DS }, { 12, 0x0b, 4, IEEE80211_T_OFDM }, { 18, 0x0f, 4, IEEE80211_T_OFDM }, { 24, 0x0a, 6, IEEE80211_T_OFDM }, { 36, 0x0e, 6, IEEE80211_T_OFDM }, { 48, 0x09, 8, IEEE80211_T_OFDM }, { 72, 0x0d, 8, IEEE80211_T_OFDM }, { 96, 0x08, 8, IEEE80211_T_OFDM }, { 108, 0x0c, 8, IEEE80211_T_OFDM }, { 0x80, 0x80, 8, IEEE80211_T_OFDM }, { 0x81, 0x81, 8, IEEE80211_T_OFDM }, { 0x82, 0x82, 8, IEEE80211_T_OFDM }, { 0x83, 0x83, 8, IEEE80211_T_OFDM }, { 0x84, 0x84, 8, IEEE80211_T_OFDM }, { 0x85, 0x85, 8, IEEE80211_T_OFDM }, { 0x86, 0x86, 8, IEEE80211_T_OFDM }, { 0x87, 0x87, 8, IEEE80211_T_OFDM }, { 0x88, 0x88, 8, IEEE80211_T_OFDM }, { 0x89, 0x89, 8, IEEE80211_T_OFDM }, { 0x8a, 0x8a, 8, IEEE80211_T_OFDM }, { 0x8b, 0x8b, 8, IEEE80211_T_OFDM }, { 0x8c, 0x8c, 8, IEEE80211_T_OFDM }, { 0x8d, 0x8d, 8, IEEE80211_T_OFDM }, { 0x8e, 0x8e, 8, IEEE80211_T_OFDM }, { 0x8f, 0x8f, 8, IEEE80211_T_OFDM } }; struct athn_series { uint16_t dur; uint8_t hwrate; }; 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; int nfastregs; const uint16_t *fastregs; const uint32_t *fastvals_5g20; #ifndef IEEE80211_NO_HT const uint32_t *fastvals_5g40; #endif }; 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; }; /* Rx queue software indexes. */ #define ATHN_QID_LP 0 #define ATHN_QID_HP 0 /* 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) (40 + (mcs)) #define ATHN_POWER_CCK_DUP 64 #define ATHN_POWER_OFDM_DUP 65 #define ATHN_POWER_CCK_EXT 66 #define ATHN_POWER_OFDM_EXT 67 #define ATHN_POWER_COUNT 68 struct athn_node { struct ieee80211_node ni; struct ieee80211_amrr_node amn; uint8_t ridx[IEEE80211_RATE_MAXSIZE]; uint8_t fallback[IEEE80211_RATE_MAXSIZE]; uint8_t sta_index; }; /* * Adaptive noise immunity state. */ #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 { /* Bus callbacks. */ uint32_t (*read)(struct athn_softc *, uint32_t); void (*write)(struct athn_softc *, uint32_t, uint32_t); void (*write_barrier)(struct athn_softc *); 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 *); int (*read_rom_data)(struct athn_softc *, uint32_t, void *, int); const uint8_t * (*get_rom_template)(struct athn_softc *, uint8_t); void (*swap_rom)(struct athn_softc *); void (*olpc_init)(struct athn_softc *); void (*olpc_temp_compensation)(struct athn_softc *); /* GPIO callbacks. */ int (*gpio_read)(struct athn_softc *, int); void (*gpio_write)(struct athn_softc *, int, int); void (*gpio_config_input)(struct athn_softc *, int); void (*gpio_config_output)(struct athn_softc *, int, int); void (*rfsilent_init)(struct athn_softc *); /* DMA callbacks. */ int (*dma_alloc)(struct athn_softc *); void (*dma_free)(struct athn_softc *); void (*rx_enable)(struct athn_softc *); int (*intr)(struct athn_softc *); int (*tx)(struct athn_softc *, struct mbuf *, struct ieee80211_node *, int); /* PHY callbacks. */ void (*set_rf_mode)(struct athn_softc *, struct ieee80211_channel *); int (*rf_bus_request)(struct athn_softc *); void (*rf_bus_release)(struct athn_softc *); void (*set_phy)(struct athn_softc *, struct ieee80211_channel *, struct ieee80211_channel *); void (*set_delta_slope)(struct athn_softc *, struct ieee80211_channel *, struct ieee80211_channel *); void (*enable_antenna_diversity)(struct athn_softc *); void (*init_baseband)(struct athn_softc *); void (*disable_phy)(struct athn_softc *); void (*set_rxchains)(struct athn_softc *); void (*noisefloor_calib)(struct athn_softc *); void (*do_calib)(struct athn_softc *); void (*next_calib)(struct athn_softc *); void (*hw_init)(struct athn_softc *, struct ieee80211_channel *, struct ieee80211_channel *); void (*get_paprd_masks)(struct athn_softc *sc, struct ieee80211_channel *, uint32_t *, uint32_t *); /* ANI callbacks. */ void (*set_noise_immunity_level)(struct athn_softc *, int); void (*enable_ofdm_weak_signal)(struct athn_softc *); void (*disable_ofdm_weak_signal)(struct athn_softc *); void (*set_cck_weak_signal)(struct athn_softc *, int); void (*set_firstep_level)(struct athn_softc *, int); void (*set_spur_immunity_level)(struct athn_softc *, int); }; 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 *); void (*sc_enable_extsynch)( struct athn_softc *); int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); bus_dma_tag_t sc_dmat; struct timeout scan_to; struct timeout calib_to; struct ieee80211_amrr amrr; u_int flags; #define ATHN_FLAG_PCIE (1 << 0) #define ATHN_FLAG_USB (1 << 1) #define ATHN_FLAG_OLPC (1 << 2) #define ATHN_FLAG_PAPRD (1 << 3) #define ATHN_FLAG_FAST_PLL_CLOCK (1 << 4) #define ATHN_FLAG_RFSILENT (1 << 5) #define ATHN_FLAG_RFSILENT_REVERSED (1 << 6) #define ATHN_FLAG_BTCOEX2WIRE (1 << 7) #define ATHN_FLAG_BTCOEX3WIRE (1 << 8) /* Shortcut. */ #define ATHN_FLAG_BTCOEX (ATHN_FLAG_BTCOEX2WIRE | ATHN_FLAG_BTCOEX3WIRE) #define ATHN_FLAG_11A (1 << 9) #define ATHN_FLAG_11G (1 << 10) #define ATHN_FLAG_11N (1 << 11) #define ATHN_FLAG_AN_TOP2_FIXUP (1 << 12) #define ATHN_FLAG_NON_ENTERPRISE (1 << 13) #define ATHN_FLAG_3TREDUCE_CHAIN (1 << 14) uint8_t ngpiopins; int led_pin; int rfsilent_pin; int led_state; uint32_t isync; uint32_t imask; uint16_t mac_ver; uint8_t mac_rev; uint8_t rf_rev; uint16_t eep_rev; uint8_t txchainmask; uint8_t rxchainmask; uint8_t ntxchains; uint8_t nrxchains; uint8_t sup_calib_mask; uint8_t cur_calib_mask; #define ATHN_CAL_IQ (1 << 0) #define ATHN_CAL_ADC_GAIN (1 << 1) #define ATHN_CAL_ADC_DC (1 << 2) #define ATHN_CAL_TEMP (1 << 3) struct ieee80211_channel *curchan; struct ieee80211_channel *curchanext; /* Open Loop Power Control. */ int8_t tx_gain_tbl[AR9280_TX_GAIN_TABLE_SIZE]; int8_t pdadc; int8_t tcomp; int olpc_ticks; /* PA predistortion. */ uint16_t gain1[AR_MAX_CHAINS]; uint32_t txgain[AR9003_TX_GAIN_TABLE_SIZE]; int16_t pa_in[AR_MAX_CHAINS] [AR9003_PAPRD_MEM_TAB_SIZE]; int16_t angle[AR_MAX_CHAINS] [AR9003_PAPRD_MEM_TAB_SIZE]; int32_t trainpow; uint8_t paprd_curchain; uint32_t rwbuf[64]; int kc_entries; void *eep; const void *eep_def; uint32_t eep_base; uint32_t eep_size; struct athn_rxq rxq[2]; struct athn_txq txq[31]; void *descs; bus_dmamap_t map; bus_dma_segment_t seg; SIMPLEQ_HEAD(, athn_tx_buf) txbufs; struct athn_tx_buf *bcnbuf; struct athn_tx_buf txpool[ATHN_NTXBUFS]; bus_dmamap_t txsmap; bus_dma_segment_t txsseg; void *txsring; int txscur; int sc_if_flags; 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; uint32_t obs_off; uint32_t gpio_input_en_off; struct athn_ops ops; int fixed_ridx; int16_t cca_min_2g; int16_t cca_max_2g; int16_t cca_min_5g; int16_t cca_max_5g; 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]; int pa_calib_ticks; 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 void athn_suspend(struct athn_softc *); extern void athn_resume(struct athn_softc *); extern int athn_intr(void *);