root/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/pci/if_wpireg.h
/*      $OpenBSD: if_wpireg.h,v 1.28 2013/11/26 20:33:17 deraadt Exp $  */

/*-
 * Copyright (c) 2006-2008
 *      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 WPI_TX_RING_COUNT       256
#define WPI_TX_RING_LOMARK      192
#define WPI_TX_RING_HIMARK      224
#define WPI_RX_RING_COUNT_LOG   6
#define WPI_RX_RING_COUNT       (1 << WPI_RX_RING_COUNT_LOG)

#define WPI_NTXQUEUES           8
#define WPI_NDMACHNLS           6

/* Maximum scatter/gather. */
#define WPI_MAX_SCATTER 4

/* Maximum RX buffer size (larger than MCLBYTES.) */
#define WPI_RBUF_SIZE   (3 * 1024)

/* Base Address Register. */
#define WPI_PCI_BAR0    PCI_MAPREG_START

/*
 * Control and status registers.
 */
#define WPI_HW_IF_CONFIG        0x000
#define WPI_INT                 0x008
#define WPI_MASK                0x00c
#define WPI_FH_INT              0x010
#define WPI_GPIO_IN             0x018
#define WPI_RESET               0x020
#define WPI_GP_CNTRL            0x024
#define WPI_EEPROM              0x02c
#define WPI_EEPROM_GP           0x030
#define WPI_UCODE_GP1_CLR       0x05c
#define WPI_UCODE_GP2           0x060
#define WPI_GIO_CHICKEN         0x100
#define WPI_ANA_PLL             0x20c
#define WPI_MEM_RADDR           0x40c
#define WPI_MEM_WADDR           0x410
#define WPI_MEM_WDATA           0x418
#define WPI_MEM_RDATA           0x41c
#define WPI_PRPH_WADDR          0x444
#define WPI_PRPH_RADDR          0x448
#define WPI_PRPH_WDATA          0x44c
#define WPI_PRPH_RDATA          0x450
#define WPI_HBUS_TARG_WRPTR     0x460
#define WPI_FH_CBBC_CTRL(qid)   (0x940 + (qid) * 8)
#define WPI_FH_CBBC_BASE(qid)   (0x944 + (qid) * 8)
#define WPI_FH_RX_CONFIG        0xc00
#define WPI_FH_RX_BASE          0xc04
#define WPI_FH_RX_WPTR          0xc20
#define WPI_FH_RX_RPTR_ADDR     0xc24
#define WPI_FH_RSSR_TBL         0xcc0
#define WPI_FH_RX_STATUS        0xcc4
#define WPI_FH_TX_CONFIG(qid)   (0xd00 + (qid) * 32)
#define WPI_FH_TX_BASE          0xe80
#define WPI_FH_MSG_CONFIG       0xe88
#define WPI_FH_TX_STATUS        0xe90


/*
 * NIC internal memory offsets.
 */
#define WPI_ALM_SCHED_MODE              0x2e00
#define WPI_ALM_SCHED_ARASTAT           0x2e04
#define WPI_ALM_SCHED_TXFACT            0x2e10
#define WPI_ALM_SCHED_TXF4MF            0x2e14
#define WPI_ALM_SCHED_TXF5MF            0x2e20
#define WPI_ALM_SCHED_SBYPASS_MODE1     0x2e2c
#define WPI_ALM_SCHED_SBYPASS_MODE2     0x2e30
#define WPI_APMG_CLK_ENA                0x3004
#define WPI_APMG_CLK_DIS                0x3008
#define WPI_APMG_RFKILL                 0x3014
#define WPI_APMG_PS                     0x300c
#define WPI_APMG_PCI_STT                0x3010
#define WPI_BSM_WR_CTRL                 0x3400
#define WPI_BSM_WR_MEM_SRC              0x3404
#define WPI_BSM_WR_MEM_DST              0x3408
#define WPI_BSM_WR_DWCOUNT              0x340c
#define WPI_BSM_SRAM_BASE               0x3800
#define WPI_BSM_DRAM_TEXT_ADDR          0x3490
#define WPI_BSM_DRAM_TEXT_SIZE          0x3494
#define WPI_BSM_DRAM_DATA_ADDR          0x3498
#define WPI_BSM_DRAM_DATA_SIZE          0x349c


/* Possible flags for register WPI_HW_IF_CONFIG. */
#define WPI_HW_IF_CONFIG_ALM_MB         (1 << 8)
#define WPI_HW_IF_CONFIG_ALM_MM         (1 << 9)
#define WPI_HW_IF_CONFIG_SKU_MRC        (1 << 10)
#define WPI_HW_IF_CONFIG_REV_D          (1 << 11)
#define WPI_HW_IF_CONFIG_TYPE_B         (1 << 12)

/* Possible flags for registers WPI_PRPH_RADDR/WPI_PRPH_WADDR. */
#define WPI_PRPH_DWORD  ((sizeof (uint32_t) - 1) << 24)

/* Possible values for WPI_BSM_WR_MEM_DST. */
#define WPI_FW_TEXT_BASE        0x00000000
#define WPI_FW_DATA_BASE        0x00800000

/* Possible flags for WPI_GPIO_IN. */
#define WPI_GPIO_IN_VMAIN       (1 << 9)

/* Possible flags for register WPI_RESET. */
#define WPI_RESET_NEVO                  (1 << 0)
#define WPI_RESET_SW                    (1 << 7)
#define WPI_RESET_MASTER_DISABLED       (1 << 8)
#define WPI_RESET_STOP_MASTER           (1 << 9)

/* Possible flags for register WPI_GP_CNTRL. */
#define WPI_GP_CNTRL_MAC_CLOCK_READY    (1 <<  0)
#define WPI_GP_CNTRL_MAC_ACCESS_ENA     (1 <<  0)
#define WPI_GP_CNTRL_INIT_DONE          (1 <<  2)
#define WPI_GP_CNTRL_MAC_ACCESS_REQ     (1 <<  3)
#define WPI_GP_CNTRL_SLEEP              (1 <<  4)
#define WPI_GP_CNTRL_PS_MASK            (7 << 24)
#define WPI_GP_CNTRL_MAC_PS             (4 << 24)
#define WPI_GP_CNTRL_RFKILL             (1 << 27)

/* Possible flags for register WPI_GIO_CHICKEN. */
#define WPI_GIO_CHICKEN_L1A_NO_L0S_RX   (1 << 23)

/* Possible flags for register WPI_FH_RX_CONFIG. */
#define WPI_FH_RX_CONFIG_DMA_ENA                (1U << 31)
#define WPI_FH_RX_CONFIG_RDRBD_ENA              (1U << 29)
#define WPI_FH_RX_CONFIG_WRSTATUS_ENA           (1U << 27)
#define WPI_FH_RX_CONFIG_MAXFRAG                (1U << 24)
#define WPI_FH_RX_CONFIG_NRBD(x)                ((x) << 20)
#define WPI_FH_RX_CONFIG_IRQ_DST_HOST           (1U << 12)
#define WPI_FH_RX_CONFIG_IRQ_RBTH(x)            ((x) << 4)

/* Possible flags for register WPI_ANA_PLL. */
#define WPI_ANA_PLL_INIT        (1 << 24)

/* Possible flags for register WPI_UCODE_GP1_CLR. */
#define WPI_UCODE_GP1_RFKILL            (1 << 1)
#define WPI_UCODE_GP1_CMD_BLOCKED       (1 << 2)

/* Possible flags for WPI_FH_RX_STATUS. */
#define WPI_FH_RX_STATUS_IDLE   (1 << 24)

/* Possible flags for register WPI_BSM_WR_CTRL. */
#define WPI_BSM_WR_CTRL_START_EN        (1U << 30)
#define WPI_BSM_WR_CTRL_START           (1U << 31)

/* Possible flags for register WPI_INT. */
#define WPI_INT_ALIVE           (1U <<  0)
#define WPI_INT_WAKEUP          (1U <<  1)
#define WPI_INT_SW_RX           (1U <<  3)
#define WPI_INT_RF_TOGGLED      (1U <<  7)
#define WPI_INT_SW_ERR          (1U << 25)
#define WPI_INT_FH_TX           (1U << 27)
#define WPI_INT_HW_ERR          (1U << 29)
#define WPI_INT_FH_RX           (1U << 31)

/* Shortcut. */
#define WPI_INT_MASK                                                    \
        (WPI_INT_SW_ERR | WPI_INT_HW_ERR | WPI_INT_FH_TX |              \
         WPI_INT_FH_RX | WPI_INT_ALIVE | WPI_INT_WAKEUP |               \
         WPI_INT_SW_RX | WPI_INT_RF_TOGGLED)

/* Possible flags for register WPI_FH_INT. */
#define WPI_FH_INT_RX_CHNL(x)   (1 << ((x) + 16))
#define WPI_FH_INT_HI_PRIOR     (1 << 30)
/* Shortcuts for the above. */
#define WPI_FH_INT_RX                   \
        (WPI_FH_INT_RX_CHNL(0) |        \
         WPI_FH_INT_RX_CHNL(1) |        \
         WPI_FH_INT_RX_CHNL(2) |        \
         WPI_FH_INT_HI_PRIOR)

/* Possible flags for register WPI_FH_TX_STATUS. */
#define WPI_FH_TX_STATUS_IDLE(qid)      \
        (1 << ((qid) + 24) | 1 << ((qid) + 16))

/* Possible flags for register WPI_EEPROM. */
#define WPI_EEPROM_READ_VALID   (1 << 0)
#define WPI_EEPROM_CMD          (1 << 1)

/* Possible flags for register WPI_EEPROM_GP. */
#define WPI_EEPROM_GP_IF_OWNER  0x00000180

/* Possible flags for register WPI_APMG_PS. */
#define WPI_APMG_PS_PWR_SRC_MASK        (3 << 24)

/* Possible flags for register WPI_APMG_CLK_ENA/WPI_APMG_CLK_DIS. */
#define WPI_APMG_CLK_DMA_CLK_RQT        (1 <<  9)
#define WPI_APMG_CLK_BSM_CLK_RQT        (1 << 11)

/* Possible flags for register WPI_APMG_PCI_STT. */
#define WPI_APMG_PCI_STT_L1A_DIS        (1 << 11)

struct wpi_shared {
        uint32_t        txbase[8];
        uint32_t        next;
        uint32_t        reserved[2];
} __packed;

#define WPI_MAX_SEG_LEN 65520
struct wpi_tx_desc {
        uint32_t        flags;
#define WPI_PAD32(x)    ((((x) + 3) & ~3) - (x))

        struct {
                uint32_t        addr;
                uint32_t        len;
        } __packed      segs[WPI_MAX_SCATTER];
        uint8_t         reserved[28];
} __packed;

struct wpi_tx_stat {
        uint8_t         nrts;
        uint8_t         retrycnt;
        uint8_t         nkill;
        uint8_t         rate;
        uint32_t        duration;
        uint32_t        status;
} __packed;

struct wpi_rx_desc {
        uint32_t        len;
        uint8_t         type;
#define WPI_UC_READY              1
#define WPI_ADD_NODE_DONE        24
#define WPI_RX_DONE              27
#define WPI_TX_DONE              28
#define WPI_START_SCAN          130
#define WPI_STOP_SCAN           132
#define WPI_STATE_CHANGED       161

        uint8_t         flags;
        uint8_t         idx;
        uint8_t         qid;
} __packed;

struct wpi_tx_cmd {
        uint8_t code;
#define WPI_CMD_RXON             16
#define WPI_CMD_ASSOCIATE        17
#define WPI_CMD_EDCA_PARAMS      19
#define WPI_CMD_TIMING           20
#define WPI_CMD_ADD_NODE         24
#define WPI_CMD_TX_DATA          28
#define WPI_CMD_MRR_SETUP        71
#define WPI_CMD_SET_LED          72
#define WPI_CMD_SET_POWER_MODE  119
#define WPI_CMD_SCAN            128
#define WPI_CMD_TXPOWER         151
#define WPI_CMD_BT_COEX         155

        uint8_t flags;
        uint8_t idx;
        uint8_t qid;
        uint8_t data[124];
} __packed;

/* Structure for command WPI_CMD_RXON. */
struct wpi_rxon {
        uint8_t         myaddr[IEEE80211_ADDR_LEN];
        uint16_t        reserved1;
        uint8_t         bssid[IEEE80211_ADDR_LEN];
        uint16_t        reserved2;
        uint32_t        reserved3[2];
        uint8_t         mode;
#define WPI_MODE_HOSTAP         1
#define WPI_MODE_STA            3
#define WPI_MODE_IBSS           4
#define WPI_MODE_MONITOR        6

        uint8_t         reserved4[3];
        uint8_t         ofdm_mask;
        uint8_t         cck_mask;
        uint16_t        associd;
        uint32_t        flags;
#define WPI_RXON_24GHZ          (1 <<  0)
#define WPI_RXON_CCK            (1 <<  1)
#define WPI_RXON_AUTO           (1 <<  2)
#define WPI_RXON_SHSLOT         (1 <<  4)
#define WPI_RXON_SHPREAMBLE     (1 <<  5)
#define WPI_RXON_NODIVERSITY    (1 <<  7)
#define WPI_RXON_ANT_A          (1 <<  8)
#define WPI_RXON_ANT_B          (1 <<  9)
#define WPI_RXON_TSF            (1 << 15)

        uint32_t        filter;
#define WPI_FILTER_PROMISC      (1 << 0)
#define WPI_FILTER_CTL          (1 << 1)
#define WPI_FILTER_MULTICAST    (1 << 2)
#define WPI_FILTER_NODECRYPT    (1 << 3)
#define WPI_FILTER_BSS          (1 << 5)

        uint8_t         chan;
        uint8_t         reserved6[3];
} __packed;

/* Structure for command WPI_CMD_ASSOCIATE. */
struct wpi_assoc {
        uint32_t        flags;
        uint32_t        filter;
        uint8_t         ofdm_mask;
        uint8_t         cck_mask;
        uint16_t        reserved;
} __packed;

/* Structure for command WPI_CMD_EDCA_PARAMS. */
struct wpi_edca_params {
        uint32_t        flags;
#define WPI_EDCA_UPDATE (1 << 0)
#define WPI_EDCA_TXOP   (1 << 4)

        struct {
                uint16_t        cwmin;
                uint16_t        cwmax;
                uint8_t         aifsn;
                uint8_t         reserved;
                uint16_t        txoplimit;
        } __packed      ac[EDCA_NUM_AC];
} __packed;

/* Structure for command WPI_CMD_TIMING. */
struct wpi_cmd_timing {
        uint64_t        tstamp;
        uint16_t        bintval;
        uint16_t        atim;
        uint32_t        binitval;
        uint16_t        lintval;
        uint16_t        reserved;
} __packed;

/* Structure for command WPI_CMD_ADD_NODE. */
struct wpi_node_info {
        uint8_t         control;
#define WPI_NODE_UPDATE         (1 << 0)

        uint8_t         reserved1[3];
        uint8_t         macaddr[IEEE80211_ADDR_LEN];
        uint16_t        reserved2;
        uint8_t         id;
#define WPI_ID_BSS              0
#define WPI_ID_BROADCAST        24

        uint8_t         flags;
#define WPI_FLAG_SET_KEY        (1 << 0)

        uint16_t        reserved3;
        uint16_t        kflags;
#define WPI_KFLAG_CCMP          (1 <<  1)
#define WPI_KFLAG_KID(kid)      ((kid) << 8)

        uint8_t         tsc2;
        uint8_t         reserved4;
        uint16_t        ttak[5];
        uint16_t        reserved5;
        uint8_t         key[16];

        uint32_t        action;
#define WPI_ACTION_SET_RATE     (1 << 2)

        uint32_t        mask;
        uint16_t        tid;
        uint8_t         plcp;
        uint8_t         antenna;
#define WPI_ANTENNA_A           (1 << 6)
#define WPI_ANTENNA_B           (1 << 7)
#define WPI_ANTENNA_BOTH        (WPI_ANTENNA_A | WPI_ANTENNA_B)

        uint8_t         add_imm;
        uint8_t         del_imm;
        uint16_t        add_imm_start;
} __packed;

/* Structure for command WPI_CMD_TX_DATA. */
struct wpi_cmd_data {
        uint16_t        len;
        uint16_t        lnext;
        uint32_t        flags;
#define WPI_TX_NEED_RTS         (1 <<  1)
#define WPI_TX_NEED_CTS         (1 <<  2)
#define WPI_TX_NEED_ACK         (1 <<  3)
#define WPI_TX_FULL_TXOP        (1 <<  7)
#define WPI_TX_BT_DISABLE       (1 << 12)       /* bluetooth coexistence */
#define WPI_TX_AUTO_SEQ         (1 << 13)
#define WPI_TX_INSERT_TSTAMP    (1 << 16)

        uint8_t         plcp;
        uint8_t         id;
        uint8_t         tid;
        uint8_t         security;
#define WPI_CIPHER_WEP40        1
#define WPI_CIPHER_CCMP         2
#define WPI_CIPHER_TKIP         3
#define WPI_CIPHER_WEP104       9

        uint8_t         key[IEEE80211_KEYBUF_SIZE];
        uint8_t         tkip[IEEE80211_TKIP_MICLEN];
        uint32_t        fnext;
        uint32_t        lifetime;
#define WPI_LIFETIME_INFINITE   0xffffffff

        uint8_t         ofdm_mask;
        uint8_t         cck_mask;
        uint8_t         rts_ntries;
        uint8_t         data_ntries;
        uint16_t        timeout;
        uint16_t        txop;
} __packed;

/* Structure for command WPI_CMD_MRR_SETUP. */
#define WPI_RIDX_MAX    11
struct wpi_mrr_setup {
        uint32_t        which;
#define WPI_MRR_CTL     0
#define WPI_MRR_DATA    1

        struct {
                uint8_t plcp;
                uint8_t flags;
                uint8_t ntries;
                uint8_t next;
        } __packed      rates[WPI_RIDX_MAX + 1];
} __packed;

/* Structure for command WPI_CMD_SET_LED. */
struct wpi_cmd_led {
        uint32_t        unit;   /* multiplier (in usecs) */
        uint8_t         which;
#define WPI_LED_ACTIVITY        1
#define WPI_LED_LINK            2

        uint8_t         off;
        uint8_t         on;
        uint8_t         reserved;
} __packed;

/* Structure for command WPI_CMD_SET_POWER_MODE. */
struct wpi_pmgt_cmd {
        uint32_t        flags;
#define WPI_PS_ALLOW_SLEEP      (1 << 0)
#define WPI_PS_SLEEP_OVER_DTIM  (1 << 2)
#define WPI_PS_PCI_PMGT         (1 << 3)

        uint32_t        rxtimeout;
        uint32_t        txtimeout;
        uint32_t        intval[5];
} __packed;

/* Structures for command WPI_CMD_SCAN. */
struct wpi_scan_essid {
        uint8_t id;
        uint8_t len;
        uint8_t data[IEEE80211_NWID_LEN];
} __packed;

struct wpi_scan_hdr {
        uint16_t        len;
        uint8_t         reserved1;
        uint8_t         nchan;
        uint16_t        quiet_time;
        uint16_t        quiet_threshold;
        uint16_t        crc_threshold;
        uint16_t        reserved2;
        uint32_t        max_svc;        /* background scans */
        uint32_t        pause_svc;      /* background scans */
        uint32_t        flags;
        uint32_t        filter;

        /* Followed by a struct wpi_cmd_data. */
        /* Followed by an array of 4 structq wpi_scan_essid. */
        /* Followed by probe request body. */
        /* Followed by an array of ``nchan'' structs wpi_scan_chan. */
} __packed;

struct wpi_scan_chan {
        uint8_t         flags;
#define WPI_CHAN_ACTIVE         (1 << 0)
#define WPI_CHAN_NPBREQS(x)     (((1 << (x)) - 1) << 1)

        uint8_t         chan;
        uint8_t         rf_gain;
        uint8_t         dsp_gain;
        uint16_t        active;         /* msecs */
        uint16_t        passive;        /* msecs */
} __packed;

/* Maximum size of a scan command. */
#define WPI_SCAN_MAXSZ  (MCLBYTES - 4)

/* Structure for command WPI_CMD_TXPOWER. */
struct wpi_cmd_txpower {
        uint8_t         band;
#define WPI_BAND_5GHZ   0
#define WPI_BAND_2GHZ   1

        uint8_t         reserved;
        uint16_t        chan;
        struct {
                uint8_t plcp;
                uint8_t rf_gain;
                uint8_t dsp_gain;
                uint8_t reserved;
        } __packed      rates[WPI_RIDX_MAX + 1];
} __packed;

/* Structure for command WPI_CMD_BT_COEX. */
struct wpi_bluetooth {
        uint8_t         flags;
#define WPI_BT_COEX_DISABLE     0
#define WPI_BT_COEX_MODE_2WIRE  1
#define WPI_BT_COEX_MODE_3WIRE  2
#define WPI_BT_COEX_MODE_4WIRE  3

        uint8_t         lead_time;
#define WPI_BT_LEAD_TIME_DEF    30

        uint8_t         max_kill;
#define WPI_BT_MAX_KILL_DEF     5

        uint8_t         reserved;
        uint32_t        kill_ack;
        uint32_t        kill_cts;
} __packed;

/* Structures for WPI_RX_DONE notification. */
struct wpi_rx_stat {
        uint8_t         len;
#define WPI_STAT_MAXLEN 20

        uint8_t         id;
        uint8_t         rssi;   /* received signal strength */
#define WPI_RSSI_OFFSET 95

        uint8_t         agc;    /* access gain control */
        uint16_t        signal;
        uint16_t        noise;
} __packed;

struct wpi_rx_head {
        uint16_t        chan;
        uint16_t        flags;
        uint8_t         reserved;
        uint8_t         rate;
        uint16_t        len;
} __packed;

struct wpi_rx_tail {
        uint32_t        flags;
#define WPI_RX_NO_CRC_ERR       (1 <<  0)
#define WPI_RX_NO_OVFL_ERR      (1 <<  1)
/* Shortcut for the above. */
#define WPI_RX_NOERROR          (WPI_RX_NO_CRC_ERR | WPI_RX_NO_OVFL_ERR)
#define WPI_RX_CIPHER_MASK      (7 <<  8)
#define WPI_RX_CIPHER_CCMP      (2 <<  8)
#define WPI_RX_DECRYPT_MASK     (3 << 11)
#define WPI_RX_DECRYPT_OK       (3 << 11)

        uint64_t        tstamp;
        uint32_t        tbeacon;
} __packed;

/* Structure for WPI_UC_READY notification. */
struct wpi_ucode_info {
        uint32_t        version;
        uint8_t         revision[8];
        uint8_t         type;
        uint8_t         subtype;
#define WPI_UCODE_INIT  9

        uint16_t        reserved;
        uint32_t        logptr;
        uint32_t        errptr;
        uint32_t        timestamp;
        uint32_t        valid;
} __packed;

/* Structure for WPI_START_SCAN notification. */
struct wpi_start_scan {
        uint64_t        tstamp;
        uint32_t        tbeacon;
        uint8_t         chan;
        uint8_t         band;
        uint16_t        reserved;
        uint32_t        status;
} __packed;

/* Structure for WPI_STOP_SCAN notification. */
struct wpi_stop_scan {
        uint8_t         nchan;
        uint8_t         status;
        uint8_t         reserved;
        uint8_t         chan;
        uint64_t        tsf;
} __packed;


/* Firmware error dump entry. */
struct wpi_fwdump {
        uint32_t        desc;
        uint32_t        time;
        uint32_t        blink[2];
        uint32_t        ilink[2];
        uint32_t        data;
} __packed;

/* Firmware image file header. */
struct wpi_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 WPI_FW_TEXT_MAXSZ       (80 * 1024)
#define WPI_FW_DATA_MAXSZ       (32 * 1024)
#define WPI_FW_BOOT_TEXT_MAXSZ  1024

#define WPI_FW_UPDATED  (1U << 31)

/*
 * Offsets into EEPROM.
 */
#define WPI_EEPROM_MAC          0x015
#define WPI_EEPROM_REVISION     0x035
#define WPI_EEPROM_CAPABILITIES 0x045
#define WPI_EEPROM_TYPE         0x04a
#define WPI_EEPROM_DOMAIN       0x060
#define WPI_EEPROM_BAND1        0x063
#define WPI_EEPROM_BAND2        0x072
#define WPI_EEPROM_BAND3        0x080
#define WPI_EEPROM_BAND4        0x08d
#define WPI_EEPROM_BAND5        0x099
#define WPI_EEPROM_POWER_GRP    0x100

struct wpi_eeprom_chan {
        uint8_t flags;
#define WPI_EEPROM_CHAN_VALID   (1 << 0)
#define WPI_EEPROM_CHAN_IBSS    (1 << 1)
#define WPI_EEPROM_CHAN_ACTIVE  (1 << 3)
#define WPI_EEPROM_CHAN_RADAR   (1 << 4)

        int8_t  maxpwr;
} __packed;

struct wpi_eeprom_sample {
        uint8_t         index;
        int8_t          power;
        uint16_t        volt;
} __packed;

#define WPI_POWER_GROUPS_COUNT  5
struct wpi_eeprom_group {
        struct          wpi_eeprom_sample samples[5];
        int32_t         coef[5];
        int32_t         corr[5];
        int8_t          maxpwr;
        uint8_t         chan;
        int16_t         temp;
} __packed;

#define WPI_CHAN_BANDS_COUNT    5
#define WPI_MAX_CHAN_PER_BAND   14
static const struct wpi_chan_band {
        uint32_t        addr;   /* offset in EEPROM */
        uint8_t         nchan;
        uint8_t         chan[WPI_MAX_CHAN_PER_BAND];
} wpi_bands[5] = {
        { WPI_EEPROM_BAND1, 14,
            { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } },
        { WPI_EEPROM_BAND2, 13,
            { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } },
        { WPI_EEPROM_BAND3, 12,
            { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } },
        { WPI_EEPROM_BAND4, 11,
            { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } },
        { WPI_EEPROM_BAND5, 6,
            { 145, 149, 153, 157, 161, 165 } }
};

/* HW rate indices. */
#define WPI_RIDX_OFDM6   0
#define WPI_RIDX_OFDM36  5
#define WPI_RIDX_OFDM48  6
#define WPI_RIDX_OFDM54  7
#define WPI_RIDX_CCK1    8
#define WPI_RIDX_CCK2    9
#define WPI_RIDX_CCK11  11

static const struct wpi_rate {
        uint8_t rate;
        uint8_t plcp;
} wpi_rates[WPI_RIDX_MAX + 1] = {
        {  12, 0xd },
        {  18, 0xf },
        {  24, 0x5 },
        {  36, 0x7 },
        {  48, 0x9 },
        {  72, 0xb },
        {  96, 0x1 },
        { 108, 0x3 },
        {   2,  10 },
        {   4,  20 },
        {  11,  55 },
        {  22, 110 }
};

#define WPI_MAX_PWR_INDEX       77
/*
 * RF Tx gain values from highest to lowest power (values obtained from
 * the reference driver.)
 */
static const uint8_t wpi_rf_gain_2ghz[WPI_MAX_PWR_INDEX + 1] = {
        0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb,
        0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3,
        0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb,
        0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b,
        0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3,
        0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63,
        0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03,
        0x03
};

static const uint8_t wpi_rf_gain_5ghz[WPI_MAX_PWR_INDEX + 1] = {
        0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xbb, 0xbb, 0x9b, 0x9b, 0x7b, 0x7b,
        0x7b, 0x7b, 0x5b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1b, 0x1b,
        0x1b, 0x73, 0x73, 0x73, 0x53, 0x53, 0x53, 0x53, 0x53, 0x33, 0x33,
        0x33, 0x33, 0x13, 0x13, 0x13, 0x13, 0x13, 0xab, 0xab, 0xab, 0x8b,
        0x8b, 0x8b, 0x8b, 0x6b, 0x6b, 0x6b, 0x6b, 0x4b, 0x4b, 0x4b, 0x4b,
        0x2b, 0x2b, 0x2b, 0x2b, 0x0b, 0x0b, 0x0b, 0x0b, 0x83, 0x83, 0x63,
        0x63, 0x63, 0x63, 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23,
        0x03
};

/*
 * DSP pre-DAC gain values from highest to lowest power (values obtained
 * from the reference driver.)
 */
static const uint8_t wpi_dsp_gain_2ghz[WPI_MAX_PWR_INDEX + 1] = {
        0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c,
        0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b,
        0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d,
        0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74,
        0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71,
        0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f,
        0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66,
        0x5f
};

static const uint8_t wpi_dsp_gain_5ghz[WPI_MAX_PWR_INDEX + 1] = {
        0x7f, 0x78, 0x72, 0x77, 0x65, 0x71, 0x66, 0x72, 0x67, 0x75, 0x6b,
        0x63, 0x5c, 0x6c, 0x7d, 0x76, 0x6d, 0x66, 0x60, 0x5a, 0x68, 0x62,
        0x5c, 0x76, 0x6f, 0x68, 0x7e, 0x79, 0x71, 0x69, 0x63, 0x76, 0x6f,
        0x68, 0x62, 0x74, 0x6d, 0x66, 0x62, 0x5d, 0x71, 0x6b, 0x63, 0x78,
        0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63,
        0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x6b, 0x63, 0x78,
        0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63,
        0x78
};

/*
 * Power saving settings (values obtained from the reference driver.)
 */
#define WPI_NDTIMRANGES         2
#define WPI_NPOWERLEVELS        6
static const struct wpi_pmgt {
        uint32_t        rxtimeout;
        uint32_t        txtimeout;
        uint32_t        intval[5];
        int             skip_dtim;
} wpi_pmgt[WPI_NDTIMRANGES][WPI_NPOWERLEVELS] = {
        /* DTIM <= 10 */
        {
        {   0,   0, {  0,  0,  0,  0,  0 }, 0 },        /* CAM */
        { 200, 500, {  1,  2,  3,  4,  4 }, 0 },        /* PS level 1 */
        { 200, 300, {  2,  4,  6,  7,  7 }, 0 },        /* PS level 2 */
        {  50, 100, {  2,  6,  9,  9, 10 }, 0 },        /* PS level 3 */
        {  50,  25, {  2,  7,  9,  9, 10 }, 1 },        /* PS level 4 */
        {  25,  25, {  4,  7, 10, 10, 10 }, 1 }         /* PS level 5 */
        },
        /* DTIM >= 11 */
        {
        {   0,   0, {  0,  0,  0,  0,  0 }, 0 },        /* CAM */
        { 200, 500, {  1,  2,  3,  4, -1 }, 0 },        /* PS level 1 */
        { 200, 300, {  2,  4,  6,  7, -1 }, 0 },        /* PS level 2 */
        {  50, 100, {  2,  6,  9,  9, -1 }, 0 },        /* PS level 3 */
        {  50,  25, {  2,  7,  9,  9, -1 }, 0 },        /* PS level 4 */
        {  25,  25, {  4,  7, 10, 10, -1 }, 0 }         /* PS level 5 */
        }
};

/* Firmware errors. */
static const char * const wpi_fw_errmsg[] = {
        "OK",
        "FAIL",
        "BAD_PARAM",
        "BAD_CHECKSUM",
        "NMI_INTERRUPT",
        "SYSASSERT",
        "FATAL_ERROR"
};

#define WPI_READ(sc, reg)                                               \
        bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))

#define WPI_WRITE(sc, reg, val)                                         \
        bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))

#define WPI_WRITE_REGION_4(sc, offset, datap, count)                    \
        bus_space_write_region_4((sc)->sc_st, (sc)->sc_sh, (offset),    \
            (datap), (count))

#define WPI_SETBITS(sc, reg, mask)                                      \
        WPI_WRITE(sc, reg, WPI_READ(sc, reg) | (mask))
 
#define WPI_CLRBITS(sc, reg, mask)                                      \
        WPI_WRITE(sc, reg, WPI_READ(sc, reg) & ~(mask))

#define WPI_BARRIER_WRITE(sc)                                           \
        bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,     \
            BUS_SPACE_BARRIER_WRITE)

#define WPI_BARRIER_READ_WRITE(sc)                                      \
        bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz,     \
            BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)