/* $NetBSD: if_iwnreg.h,v 1.5 2008/11/13 12:04:09 blymn Exp $ */ /* OpenBSD: if_iwnreg.h,v 1.9 2007/11/27 20:59:40 damien Exp */ /*- * Copyright (c) 2007 * 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. */ #define IWN_TX_RING_COUNT 256 #define IWN_RX_RING_COUNT 64 #define IWN_NTXQUEUES 16 #define IWN_NTXCHAINS 2 #define IWN_BUF_ALIGN 4096 /* * Rings must be aligned on a 256-byte boundary. */ #define IWN_RING_DMA_ALIGN 256 /* maximum scatter/gather */ #define IWN_MAX_SCATTER 20 /* Rx buffers must be large enough to hold a full 4K A-MPDU */ #define IWN_RBUF_SIZE (8 * 1024) /* * Control and status registers. */ #define IWN_HWCONFIG 0x000 #define IWN_INTR_MIT 0x004 #define IWN_INTR 0x008 #define IWN_MASK 0x00c #define IWN_INTR_STATUS 0x010 #define IWN_RESET 0x020 #define IWN_GPIO_CTL 0x024 #define IWN_EEPROM_CTL 0x02c #define IWN_UCODE_CLR 0x05c #define IWN_CHICKEN 0x100 #define IWN_QUEUE_OFFSET(qid) (0x380 + (qid) * 8) #define IWN_MEM_WADDR 0x410 #define IWN_MEM_WDATA 0x418 #define IWN_WRITE_MEM_ADDR 0x444 #define IWN_READ_MEM_ADDR 0x448 #define IWN_WRITE_MEM_DATA 0x44c #define IWN_READ_MEM_DATA 0x450 #define IWN_TX_WIDX 0x460 #define IWN_KW_BASE 0x197c #define IWN_TX_BASE(qid) (0x19d0 + (qid) * 4) #define IWN_RW_WIDX_PTR 0x1bc0 #define IWN_RX_BASE 0x1bc4 #define IWN_RX_WIDX 0x1bc8 #define IWN_RX_CONFIG 0x1c00 #define IWN_RX_STATUS 0x1c44 #define IWN_TX_CONFIG(qid) (0x1d00 + (qid) * 32) #define IWN_TX_STATUS 0x1eb0 #define IWN_SRAM_BASE 0xa02c00 #define IWN_TX_ACTIVE (IWN_SRAM_BASE + 0x01c) #define IWN_QUEUE_RIDX(qid) (IWN_SRAM_BASE + 0x064 + (qid) * 4) #define IWN_SELECT_QCHAIN (IWN_SRAM_BASE + 0x0d0) #define IWN_QUEUE_INTR_MASK (IWN_SRAM_BASE + 0x0e4) #define IWN_TXQ_STATUS(qid) (IWN_SRAM_BASE + 0x104 + (qid) * 4) /* * NIC internal memory offsets. */ #define IWN_CLOCK_CTL 0x3000 #define IWN_MEM_CLOCK2 0x3008 #define IWN_MEM_POWER 0x300c #define IWN_MEM_PCIDEV 0x3010 #define IWN_MEM_UCODE_CTL 0x3400 #define IWN_MEM_UCODE_SRC 0x3404 #define IWN_MEM_UCODE_DST 0x3408 #define IWN_MEM_UCODE_SIZE 0x340c #define IWN_MEM_TEXT_BASE 0x3490 #define IWN_MEM_TEXT_SIZE 0x3494 #define IWN_MEM_DATA_BASE 0x3498 #define IWN_MEM_DATA_SIZE 0x349c #define IWN_MEM_UCODE_BASE 0x3800 /* possible flags for register IWN_HWCONFIG */ #define IWN_HW_EEPROM_LOCKED (1 << 21) /* possible flags for registers IWN_READ_MEM_ADDR/IWN_WRITE_MEM_ADDR */ #define IWN_MEM_4 ((sizeof (uint32_t) - 1) << 24) /* possible values for IWN_MEM_UCODE_DST */ #define IWN_FW_TEXT 0x00000000 /* possible flags for register IWN_RESET */ #define IWN_NEVO_RESET (1 << 0) #define IWN_SW_RESET (1 << 7) #define IWN_MASTER_DISABLED (1 << 8) #define IWN_STOP_MASTER (1 << 9) /* possible flags for register IWN_GPIO_CTL */ #define IWN_GPIO_CLOCK (1 << 0) #define IWN_GPIO_INIT (1 << 2) #define IWN_GPIO_MAC (1 << 3) #define IWN_GPIO_SLEEP (1 << 4) #define IWN_GPIO_PWR_STATUS 0x07000000 #define IWN_GPIO_PWR_SLEEP (4 << 24) #define IWN_GPIO_RF_ENABLED (1 << 27) /* possible flags for register IWN_CHICKEN */ #define IWN_CHICKEN_DISLOS (1 << 29) /* possible flags for register IWN_UCODE_CLR */ #define IWN_RADIO_OFF (1 << 1) #define IWN_DISABLE_CMD (1 << 2) #define IWN_CTEMP_STOP_RF (1 << 3) /* possible flags for IWN_RX_STATUS */ #define IWN_RX_IDLE (1 << 24) /* possible flags for register IWN_UC_CTL */ #define IWN_UC_ENABLE (1 << 30) #define IWN_UC_RUN (1 << 31) /* possible flags for register IWN_INTR */ #define IWN_ALIVE_INTR (1 << 0) #define IWN_WAKEUP_INTR (1 << 1) #define IWN_SW_RX_INTR (1 << 3) #define IWN_CT_REACHED (1 << 6) #define IWN_RF_TOGGLED (1 << 7) #define IWN_SW_ERROR (1 << 25) #define IWN_TX_INTR (1 << 27) #define IWN_HW_ERROR (1 << 29) #define IWN_RX_INTR (1 << 31) #define IWN_INTR_MASK \ (IWN_SW_ERROR | IWN_HW_ERROR | IWN_TX_INTR | IWN_RX_INTR | \ IWN_ALIVE_INTR | IWN_WAKEUP_INTR | IWN_SW_RX_INTR | \ IWN_CT_REACHED | IWN_RF_TOGGLED) /* possible flags for register IWN_INTR_STATUS */ #define IWN_STATUS_TXQ(x) (1 << (x)) #define IWN_STATUS_RXQ(x) (1 << ((x) + 16)) #define IWN_STATUS_PRI (1 << 30) /* shortcuts for the above */ #define IWN_TX_STATUS_INTR \ (IWN_STATUS_TXQ(0) | IWN_STATUS_TXQ(1) | IWN_STATUS_TXQ(6)) #define IWN_RX_STATUS_INTR \ (IWN_STATUS_RXQ(0) | IWN_STATUS_RXQ(1) | IWN_STATUS_RXQ(2) | \ IWN_STATUS_PRI) /* possible flags for register IWN_TX_STATUS */ #define IWN_TX_IDLE(qid) (1 << ((qid) + 24) | 1 << ((qid) + 16)) /* possible flags for register IWN_EEPROM_CTL */ #define IWN_EEPROM_READY (1 << 0) #define IWN_EEPROM_CMD (1 << 1) /* possible flags for register IWN_TXQ_STATUS */ #define IWN_TXQ_STATUS_ACTIVE 0x0007fc01 /* possible flags for register IWN_MEM_POWER */ #define IWN_POWER_RESET (1 << 26) /* possible flags for register IWN_MEM_TEXT_SIZE */ #define IWN_FW_UPDATED (1 << 31) /* possible flags for device-specific PCI register 0xe8 */ #define IWN_DIS_NOSNOOP (1 << 11) /* possible flags for device-specific PCI register 0xf0 */ #define IWN_ENA_L1 (1 << 1) #define IWN_TX_WINDOW 64 struct iwn_shared { uint16_t len[IWN_NTXQUEUES][512]; /* 16KB total */ uint16_t closed_count; uint16_t closed_rx_count; uint16_t finished_count; uint16_t finished_rx_count; uint32_t reserved[2]; } __packed; struct iwn_tx_desc { uint32_t flags; struct { uint32_t w1; uint32_t w2; uint32_t w3; } __packed segs[IWN_MAX_SCATTER / 2]; /* pad to 128 bytes */ uint32_t reserved; } __packed; #define IWN_SET_DESC_NSEGS(d, x) \ (d)->flags = htole32(((x) & 0x1f) << 24) /* set a segment physical address and length in a Tx descriptor */ #define IWN_SET_DESC_SEG(d, n, addr, size) do { \ if ((n) & 1) { \ (d)->segs[(n) / 2].w2 |= \ htole32(((addr) & 0xffff) << 16); \ (d)->segs[(n) / 2].w3 = \ htole32((((addr) >> 16) & 0xffff) | (size) << 20); \ } else { \ (d)->segs[(n) / 2].w1 = htole32(addr); \ (d)->segs[(n) / 2].w2 = htole32((size) << 4); \ } \ } while (0) struct iwn_rx_desc { uint32_t len; uint8_t type; #define IWN_UC_READY 1 #define IWN_ADD_NODE_DONE 24 #define IWN_TX_DONE 28 #define IWN_START_SCAN 130 #define IWN_STOP_SCAN 132 #define IWN_RX_STATISTICS 156 #define IWN_BEACON_STATISTICS 157 #define IWN_STATE_CHANGED 161 #define IWN_BEACON_MISSED 162 #define IWN_AMPDU_RX_START 192 #define IWN_AMPDU_RX_DONE 193 #define IWN_RX_DONE 195 uint8_t flags; uint8_t idx; uint8_t qid; } __packed; /* possible Rx status flags */ #define IWN_RX_NO_CRC_ERR (1 << 0) #define IWN_RX_NO_OVFL_ERR (1 << 1) /* shortcut for the above */ #define IWN_RX_NOERROR (IWN_RX_NO_CRC_ERR | IWN_RX_NO_OVFL_ERR) struct iwn_tx_cmd { uint8_t code; #define IWN_CMD_CONFIGURE 16 #define IWN_CMD_ASSOCIATE 17 #define IWN_CMD_SET_WME 19 #define IWN_CMD_TSF 20 #define IWN_CMD_ADD_NODE 24 #define IWN_CMD_TX_DATA 28 #define IWN_CMD_NODE_MRR_SETUP 78 #define IWN_CMD_SET_LED 72 #define IWN_CMD_SET_POWER_MODE 119 #define IWN_CMD_SCAN 128 #define IWN_CMD_SCAN_ABORT 129 #define IWN_CMD_SET_BEACON 145 #define IWN_CMD_TXPOWER 151 #define IWN_CMD_BLUETOOTH 155 #define IWN_CMD_GET_STATISTICS 156 #define IWN_CMD_SET_CRITICAL_TEMP 164 #define IWN_SENSITIVITY 168 #define IWN_PHY_CALIB 176 uint8_t flags; uint8_t idx; uint8_t qid; uint8_t data[136]; } __packed; /* structure for command IWN_CMD_CONFIGURE */ struct iwn_config { uint8_t myaddr[IEEE80211_ADDR_LEN]; uint16_t reserved1; uint8_t bssid[IEEE80211_ADDR_LEN]; uint16_t reserved2; uint8_t wlap[IEEE80211_ADDR_LEN]; uint16_t reserved3; uint8_t mode; #define IWN_MODE_HOSTAP 1 #define IWN_MODE_STA 3 #define IWN_MODE_IBSS 4 #define IWN_MODE_MONITOR 6 uint8_t reserved4; uint16_t rxchain; #define IWN_RXCHAIN_ANTMSK_SHIFT 1 #define IWN_RXCHAIN_FORCE_MIMO (1 << 14) uint8_t ofdm_mask; uint8_t cck_mask; uint16_t associd; uint32_t flags; #define IWN_CONFIG_24GHZ (1 << 0) #define IWN_CONFIG_CCK (1 << 1) #define IWN_CONFIG_AUTO (1 << 2) #define IWN_CONFIG_SHSLOT (1 << 4) #define IWN_CONFIG_SHPREAMBLE (1 << 5) #define IWN_CONFIG_NODIVERSITY (1 << 7) #define IWN_CONFIG_ANTENNA_A (1 << 8) #define IWN_CONFIG_ANTENNA_B (1 << 9) #define IWN_CONFIG_TSF (1 << 15) uint32_t filter; #define IWN_FILTER_PROMISC (1 << 0) #define IWN_FILTER_CTL (1 << 1) #define IWN_FILTER_MULTICAST (1 << 2) #define IWN_FILTER_NODECRYPT (1 << 3) #define IWN_FILTER_BSS (1 << 5) uint16_t chan; uint8_t ht_single_mask; uint8_t ht_dual_mask; } __packed; /* structure for command IWN_CMD_ASSOCIATE */ struct iwn_assoc { uint32_t flags; uint32_t filter; uint8_t ofdm_mask; uint8_t cck_mask; uint16_t reserved; } __packed; /* structure for command IWN_CMD_SET_WME */ struct iwn_wme_setup { uint32_t flags; #define IWN_EDCA_UPDATE (1 << 0) #define IWN_EDCA_TXOP (1 << 4) struct { uint16_t cwmin; uint16_t cwmax; uint8_t aifsn; uint8_t reserved; uint16_t txop; } __packed ac[WME_NUM_AC]; } __packed; /* structure for command IWN_CMD_TSF */ struct iwn_cmd_tsf { uint64_t tstamp; uint16_t bintval; uint16_t atim; uint32_t binitval; uint16_t lintval; uint16_t reserved; } __packed; /* structure for command IWN_CMD_ADD_NODE */ struct iwn_node_info { uint8_t control; #define IWN_NODE_UPDATE (1 << 0) uint8_t reserved1[3]; uint8_t macaddr[IEEE80211_ADDR_LEN]; uint16_t reserved2; uint8_t id; #define IWN_ID_BSS 0 #define IWN_ID_BROADCAST 31 uint8_t flags; #define IWN_FLAG_SET_KEY (1 << 0) uint16_t reserved3; uint16_t security; uint8_t tsc2; /* TKIP TSC2 */ uint8_t reserved4; uint16_t ttak[5]; uint16_t reserved5; uint8_t key[IEEE80211_KEYBUF_SIZE]; uint32_t htflags; #define IWN_AMDPU_SIZE_FACTOR_SHIFT 19 #define IWN_AMDPU_DENSITY_SHIFT 23 uint32_t mask; uint16_t tid; uint8_t rate; uint8_t rflags; #define IWN_RFLAG_CCK (1 << 1) #define IWN_RFLAG_ANT_A (1 << 6) #define IWN_RFLAG_ANT_B (1 << 7) uint8_t add_imm; uint8_t del_imm; uint16_t add_imm_start; uint32_t reserved6; } __packed; /* structure for command IWN_CMD_TX_DATA */ struct iwn_cmd_data { uint16_t len; uint16_t lnext; uint32_t flags; #define IWN_TX_NEED_RTS (1 << 1) #define IWN_TX_NEED_CTS (1 << 2) #define IWN_TX_NEED_ACK (1 << 3) #define IWN_TX_USE_NODE_RATE (1 << 4) #define IWN_TX_FULL_TXOP (1 << 7) #define IWN_TX_BT_DISABLE (1 << 12) /* bluetooth coexistence */ #define IWN_TX_AUTO_SEQ (1 << 13) #define IWN_TX_INSERT_TSTAMP (1 << 16) #define IWN_TX_NEED_PADDING (1 << 20) uint8_t ntries; uint8_t bluetooth; uint16_t reserved1; uint8_t rate; uint8_t rflags; uint16_t xrflags; uint8_t id; uint8_t security; #define IWN_CIPHER_WEP40 1 #define IWN_CIPHER_CCMP 2 #define IWN_CIPHER_TKIP 3 #define IWN_CIPHER_WEP104 9 uint8_t ridx; uint8_t reserved2; uint8_t key[IEEE80211_KEYBUF_SIZE]; uint16_t fnext; uint16_t reserved3; uint32_t lifetime; #define IWN_LIFETIME_INFINITE 0xffffffff uint32_t loaddr; uint8_t hiaddr; uint8_t rts_ntries; uint8_t data_ntries; uint8_t tid; uint16_t timeout; uint16_t txop; } __packed; /* structure for command IWN_CMD_SET_BEACON */ struct iwn_cmd_beacon { uint16_t len; uint16_t reserved1; uint32_t flags; /* same as iwn_cmd_data */ uint8_t try_cnt; uint8_t kill_cnt; uint16_t reserved2; uint8_t rate; uint8_t flags2; uint16_t ext_flags; uint8_t id; uint8_t reserved3[23]; uint32_t lifetime; uint32_t reserved4; uint8_t reserved5; uint8_t reserved6; uint8_t reserved7; uint16_t reserved8[9]; uint16_t tim; uint8_t timsz; uint8_t reserved9; struct ieee80211_frame wh; } __packed; /* structure for command IWN_CMD_MRR_NODE_SETUP */ #define IWN_MAX_TX_RETRIES 16 struct iwn_cmd_mrr { uint8_t id; uint8_t reserved1; uint16_t ctl; uint8_t flags; uint8_t mimo; uint8_t ssmask; uint8_t dsmask; uint8_t ridx[WME_NUM_AC]; uint16_t ampdu_limit; uint8_t ampdu_disable; uint8_t ampdu_max; uint32_t reserved2; struct { uint8_t rate; #define IWN_CCK1 0 #define IWN_CCK11 3 #define IWN_OFDM6 4 #define IWN_OFDM54 11 uint8_t rflags; uint16_t xrflags; } table[IWN_MAX_TX_RETRIES]; uint32_t reserved3; } __packed; /* structure for command IWN_CMD_SET_LED */ struct iwn_cmd_led { uint32_t unit; /* multiplier (in usecs) */ uint8_t which; #define IWN_LED_ACTIVITY 1 #define IWN_LED_LINK 2 uint8_t off; uint8_t on; uint8_t reserved; } __packed; /* structure for command IWN_CMD_SET_POWER_MODE */ struct iwn_power { uint16_t flags; #define IWN_POWER_CAM 0 /* constantly awake mode */ uint8_t alive; uint8_t debug; uint32_t rx_timeout; uint32_t tx_timeout; uint32_t sleep[5]; uint32_t beacons; } __packed; /* structures for command IWN_CMD_SCAN */ struct iwn_scan_essid { uint8_t id; uint8_t len; uint8_t data[IEEE80211_NWID_LEN]; } __packed; #define IWN_MAX_PROBES 4 struct iwn_scan_hdr { uint16_t len; uint8_t reserved1; uint8_t nchan; uint16_t quiet; uint16_t plcp_threshold; uint16_t crc_threshold; uint16_t rxchain; uint32_t max_svc; /* background scans */ uint32_t pause_svc; /* background scans */ uint32_t flags; uint32_t filter; struct iwn_cmd_data tx_cmd; struct iwn_scan_essid scan_essid[IWN_MAX_PROBES]; struct ieee80211_frame wh; uint8_t data[0]; /* nchan x struct iwn_scan_chan */ } __packed; struct iwn_scan_chan { uint8_t flags; #define IWN_CHAN_ACTIVE (1 << 0) #define IWN_CHAN_DIRECT (1 << 1) uint8_t chan; uint8_t rf_gain; uint8_t dsp_gain; uint16_t active; /* msecs */ uint16_t passive; /* msecs */ } __packed; /* structure for command IWN_CMD_TXPOWER */ #define IWN_RIDX_MAX 32 struct iwn_cmd_txpower { uint8_t band; uint8_t reserved1; uint8_t chan; uint8_t reserved2; struct { uint8_t rf_gain[IWN_NTXCHAINS]; uint8_t dsp_gain[IWN_NTXCHAINS]; } power[IWN_RIDX_MAX + 1]; } __packed; /* structure for command IWN_CMD_BLUETOOTH */ struct iwn_bluetooth { uint8_t flags; uint8_t lead; uint8_t kill; uint8_t reserved; uint32_t ack; uint32_t cts; } __packed; /* structure for command IWN_CMD_SET_CRITICAL_TEMP */ struct iwn_critical_temp { uint32_t reserved; uint32_t tempM; uint32_t tempR; /* degK <-> degC conversion macros */ #define IWN_CTOK(c) ((c) + 273) #define IWN_KTOC(k) ((k) - 273) #define IWN_CTOMUK(c) (((c) * 1000000) + 273150000) } __packed; /* structure for command IWN_SENSITIVITY */ struct iwn_sensitivity_cmd { uint16_t which; #define IWN_SENSITIVITY_DEFAULTTBL 0 #define IWN_SENSITIVITY_WORKTBL 1 uint16_t energy_cck; uint16_t energy_ofdm; uint16_t corr_ofdm_x1; uint16_t corr_ofdm_mrc_x1; uint16_t corr_cck_mrc_x4; uint16_t corr_ofdm_x4; uint16_t corr_ofdm_mrc_x4; uint16_t corr_barker; uint16_t corr_barker_mrc; uint16_t corr_cck_x4; uint16_t energy_ofdm_th; } __packed; /* structure for command IWN_PHY_CALIB */ struct iwn_phy_calib_cmd { uint8_t code; #define IWN_SET_DIFF_GAIN 7 uint8_t flags; uint16_t reserved1; int8_t gain[3]; #define IWN_GAIN_SET (1 << 2) uint8_t reserved2; } __packed; /* structure for IWN_UC_READY notification */ #define IWN_NATTEN_GROUPS 5 struct iwn_ucode_info { uint8_t minor; uint8_t major; uint16_t reserved1; uint8_t revision[8]; uint8_t type; uint8_t subtype; #define IWN_UCODE_RUNTIME 0 #define IWN_UCODE_INIT 9 uint16_t reserved2; uint32_t logptr; uint32_t errorptr; uint32_t tstamp; uint32_t valid; /* the following fields are for UCODE_INIT only */ int32_t volt; struct { int32_t chan20MHz; int32_t chan40MHz; } __packed temp[4]; int32_t atten[IWN_NATTEN_GROUPS][IWN_NTXCHAINS]; } __packed; /* structure for IWN_TX_DONE notification */ struct iwn_tx_stat { uint8_t nframes; uint8_t nkill; uint8_t nrts; uint8_t ntries; uint8_t rate; uint8_t rflags; uint16_t xrflags; uint16_t duration; uint16_t reserved; uint32_t power[2]; uint32_t status; /* from FreeBSD driver... XXX */ #define IWN_TX_SUCCESS 0x00 #define IWN_TX_FAIL 0x80 /* all failures have 0x80 set */ #define IWN_TX_FAIL_SHORT_LIMIT 0x82 /* too many RTS retries */ #define IWN_TX_FAIL_LONG_LIMIT 0x83 /* too many retries */ #define IWN_TX_FAIL_FIFO_UNDERRRUN 0x84 /* tx fifo not kept running */ #define IWN_TX_FAIL_DEST_IN_PS 0x88 /* sta found in power save */ #define IWN_TX_FAIL_TX_LOCKED 0x90 /* waiting to see traffic */ } __packed; /* structure for IWN_BEACON_MISSED notification */ struct iwn_beacon_missed { uint32_t consecutive; uint32_t total; uint32_t expected; uint32_t received; } __packed; /* structure for IWN_AMPDU_RX_DONE notification */ struct iwn_rx_ampdu { uint16_t len; uint16_t reserved; } __packed; /* structure for IWN_RX_DONE and IWN_AMPDU_RX_START notifications */ struct iwn_rx_stat { uint8_t phy_len; uint8_t cfg_phy_len; #define IWN_STAT_MAXLEN 20 uint8_t id; uint8_t reserved1; uint64_t tstamp; uint32_t beacon; uint16_t flags; uint16_t chan; uint16_t antenna; uint16_t agc; uint8_t rssi[6]; #define IWN_RSSI_TO_DBM 44 uint8_t reserved2[22]; uint8_t rate; uint8_t rflags; uint16_t xrflags; uint16_t len; uint16_t reserve3; } __packed; /* structure for IWN_START_SCAN notification */ struct iwn_start_scan { uint64_t tstamp; uint32_t tbeacon; uint8_t chan; uint8_t band; uint16_t reserved; uint32_t status; } __packed; /* structure for IWN_STOP_SCAN notification */ struct iwn_stop_scan { uint8_t nchan; uint8_t status; uint8_t reserved; uint8_t chan; uint64_t tsf; } __packed; /* structure for IWN_{RX,BEACON}_STATISTICS notification */ struct iwn_rx_phy_stats { uint32_t ina; uint32_t fina; uint32_t bad_plcp; uint32_t bad_crc32; uint32_t overrun; uint32_t eoverrun; uint32_t good_crc32; uint32_t fa; uint32_t bad_fina_sync; uint32_t sfd_timeout; uint32_t fina_timeout; uint32_t no_rts_ack; uint32_t rxe_limit; uint32_t ack; uint32_t cts; uint32_t ba_resp; uint32_t dsp_kill; uint32_t bad_mh; uint32_t rssi_sum; uint32_t reserved; } __packed; struct iwn_rx_general_stats { uint32_t bad_cts; uint32_t bad_ack; uint32_t not_bss; uint32_t filtered; uint32_t bad_chan; uint32_t beacons; uint32_t missed_beacons; uint32_t adc_saturated; /* time in 0.8us */ uint32_t ina_searched; /* time in 0.8us */ uint32_t noise[3]; uint32_t flags; uint32_t load; uint32_t fa; uint32_t rssi[3]; uint32_t energy[3]; } __packed; struct iwn_rx_ht_phy_stats { uint32_t bad_plcp; uint32_t overrun; uint32_t eoverrun; uint32_t good_crc32; uint32_t bad_crc32; uint32_t bad_mh; uint32_t good_ampdu_crc32; uint32_t ampdu; uint32_t fragment; uint32_t reserved; } __packed; struct iwn_rx_stats { struct iwn_rx_phy_stats ofdm; struct iwn_rx_phy_stats cck; struct iwn_rx_general_stats general; struct iwn_rx_ht_phy_stats ht; } __packed; struct iwn_tx_stats { uint32_t preamble; uint32_t rx_detected; uint32_t bt_defer; uint32_t bt_kill; uint32_t short_len; uint32_t cts_timeout; uint32_t ack_timeout; uint32_t exp_ack; uint32_t ack; uint32_t msdu; uint32_t busrt_err1; uint32_t burst_err2; uint32_t cts_collision; uint32_t ack_collision; uint32_t ba_timeout; uint32_t ba_resched; uint32_t query_ampdu; uint32_t query; uint32_t query_ampdu_frag; uint32_t query_mismatch; uint32_t not_ready; uint32_t underrun; uint32_t bt_ht_kill; uint32_t rx_ba_resp; uint32_t reserved[2]; } __packed; struct iwn_general_stats { uint32_t temp; uint32_t temp_m; uint32_t burst_check; uint32_t burst; uint32_t reserved1[4]; uint32_t sleep; uint32_t slot_out; uint32_t slot_idle; uint32_t ttl_tstamp; uint32_t tx_ant_a; uint32_t tx_ant_b; uint32_t exec; uint32_t probe; uint32_t reserved2[2]; uint32_t rx_enabled; uint32_t reserved3[3]; } __packed; struct iwn_stats { uint32_t flags; struct iwn_rx_stats rx; struct iwn_tx_stats tx; struct iwn_general_stats general; } __packed; /* firmware image header */ struct iwn_firmware_hdr { uint32_t version; uint32_t main_textsz; uint32_t main_datasz; uint32_t init_textsz; uint32_t init_datasz; uint32_t boot_textsz; } __packed; #define IWN_FW_MAIN_TEXT_MAXSZ (96 * 1024) #define IWN_FW_MAIN_DATA_MAXSZ (40 * 1024) #define IWN_FW_INIT_TEXT_MAXSZ (96 * 1024) #define IWN_FW_INIT_DATA_MAXSZ (40 * 1024) #define IWN_FW_BOOT_TEXT_MAXSZ 1024 /* * Offsets into EEPROM. */ #define IWN_EEPROM_MAC 0x015 #define IWN_EEPROM_DOMAIN 0x060 #define IWN_EEPROM_BAND1 0x063 #define IWN_EEPROM_BAND2 0x072 #define IWN_EEPROM_BAND3 0x080 #define IWN_EEPROM_BAND4 0x08d #define IWN_EEPROM_BAND5 0x099 #define IWN_EEPROM_BAND6 0x0a0 #define IWN_EEPROM_BAND7 0x0a8 #define IWN_EEPROM_MAXPOW 0x0e8 #define IWN_EEPROM_VOLTAGE 0x0e9 #define IWN_EEPROM_BANDS 0x0ea struct iwn_eeprom_chan { uint8_t flags; #define IWN_EEPROM_CHAN_VALID (1 << 0) #define IWN_EEPROM_CHAN_IBSS (1 << 1) #define IWN_EEPROM_CHAN_ACTIVE (1 << 3) #define IWN_EEPROM_CHAN_RADAR (1 << 4) int8_t maxpwr; } __packed; #define IWN_NSAMPLES 3 struct iwn_eeprom_chan_samples { uint8_t num; struct { uint8_t temp; uint8_t gain; uint8_t power; int8_t pa_det; } samples[IWN_NTXCHAINS][IWN_NSAMPLES]; } __packed; #define IWN_NBANDS 8 struct iwn_eeprom_band { uint8_t lo; /* low channel number */ uint8_t hi; /* high channel number */ struct iwn_eeprom_chan_samples chans[2]; } __packed; #define IWN_CHAN_BANDS_COUNT 7 #define IWN_MAX_CHAN_PER_BAND 14 static const struct iwn_chan_band { uint32_t addr; /* offset in EEPROM */ uint8_t nchan; uint8_t chan[IWN_MAX_CHAN_PER_BAND]; } iwn_bands[] = { { IWN_EEPROM_BAND1, 14, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } }, { IWN_EEPROM_BAND2, 13, { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } }, { IWN_EEPROM_BAND3, 12, { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } }, { IWN_EEPROM_BAND4, 11, { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } }, { IWN_EEPROM_BAND5, 6, { 145, 149, 153, 157, 161, 165 } }, { IWN_EEPROM_BAND6, 7, { 1, 2, 3, 4, 5, 6, 7 } }, { IWN_EEPROM_BAND7, 11, { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 } } }; static const uint8_t iwn_ridx_to_plcp[] = { 10, 20, 55, 110, /* CCK */ 0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, 0x3 /* OFDM R1-R4 */ }; /* allow fallback from CCK11 to OFDM9 and from OFDM6 to CCK5 */ static const uint8_t iwn_prev_ridx[] = { 0, 0, 1, 5, /* CCK */ 2, 4, 3, 6, 7, 8, 9, 10, 10 /* OFDM */ }; #define IWN_MAX_PWR_INDEX 107 /* * RF Tx gain values from highest to lowest power (values obtained from * the reference driver.) */ static const uint8_t iwn_rf_gain_2ghz[IWN_MAX_PWR_INDEX + 1] = { 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t iwn_rf_gain_5ghz[IWN_MAX_PWR_INDEX + 1] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23, 0x22, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x08, 0x08, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* * DSP pre-DAC gain values from highest to lowest power (values obtained * from the reference driver.) */ static const uint8_t iwn_dsp_gain_2ghz[IWN_MAX_PWR_INDEX + 1] = { 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b }; static const uint8_t iwn_dsp_gain_5ghz[IWN_MAX_PWR_INDEX + 1] = { 0x7b, 0x75, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x5d, 0x58, 0x53, 0x4e }; #define IWN_READ(sc, reg) \ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) #define IWN_WRITE(sc, reg, val) \ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) #define IWN_WRITE_REGION_4(sc, offset, datap, count) \ bus_space_write_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \ (datap), (count))