/* $OpenBSD: acxvar.h,v 1.14 2006/08/19 23:17:12 mglocker Exp $ */ /* * Copyright (c) 2006 Jonathan Gray * * 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. */ /* * Copyright (c) 2006 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Sepherosa Ziehau * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _IF_ACXVAR_H #define _IF_ACXVAR_H #ifdef ACX_DEBUG extern int acxdebug; #define DPRINTF(x) do { if (acxdebug) printf x; } while (0) #define DPRINTFN(n,x) do { if (acxdebug >= (n)) printf x; } while (0) #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif #define ACX_FRAME_HDRLEN sizeof(struct ieee80211_frame) #define ACX_MEMBLOCK_SIZE 256 #define ACX_TX_DESC_CNT 16 #define ACX_RX_DESC_CNT 16 #define ACX_TX_RING_SIZE \ (2 * ACX_TX_DESC_CNT * sizeof(struct acx_host_desc)) #define ACX_RX_RING_SIZE \ (ACX_RX_DESC_CNT * sizeof(struct acx_host_desc)) #define CSR_READ_1(sc, reg) \ bus_space_read_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ (sc)->chip_ioreg[(reg)]) #define CSR_READ_2(sc, reg) \ bus_space_read_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ (sc)->chip_ioreg[(reg)]) #define CSR_READ_4(sc, reg) \ bus_space_read_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ (sc)->chip_ioreg[(reg)]) #define CSR_WRITE_2(sc, reg, val) \ bus_space_write_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ (sc)->chip_ioreg[(reg)], val) #define CSR_WRITE_4(sc, reg, val) \ bus_space_write_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ (sc)->chip_ioreg[(reg)], val) #define CSR_SETB_2(sc, reg, b) \ CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) | (b)) #define CSR_CLRB_2(sc, reg, b) \ CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) & (~(b))) #define DESC_READ_1(sc, off) \ bus_space_read_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off)) #define DESC_READ_4(sc, off) \ bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off)) #define DESC_WRITE_1(sc, off, val) \ bus_space_write_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) #define DESC_WRITE_2(sc, off, val) \ bus_space_write_2((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) #define DESC_WRITE_4(sc, off, val) \ bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) #define DESC_WRITE_REGION_1(sc, off, d, dlen) \ bus_space_write_region_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \ (off), (const uint8_t *)(d), (dlen)) #define FW_TXDESC_SETFIELD(sc, mb, field, val, sz) \ DESC_WRITE_##sz((sc), (mb)->tb_fwdesc_ofs + \ offsetof(struct acx_fw_txdesc, field), (val)) #define FW_TXDESC_GETFIELD(sc, mb, field, sz) \ DESC_READ_##sz((sc), (mb)->tb_fwdesc_ofs + \ offsetof(struct acx_fw_txdesc, field)) #define FW_TXDESC_SETFIELD_1(sc, mb, field, val) \ FW_TXDESC_SETFIELD(sc, mb, field, val, 1) #define FW_TXDESC_SETFIELD_2(sc, mb, field, val) \ FW_TXDESC_SETFIELD(sc, mb, field, htole16(val), 2) #define FW_TXDESC_SETFIELD_4(sc, mb, field, val) \ FW_TXDESC_SETFIELD(sc, mb, field, htole32(val), 4) #define FW_TXDESC_GETFIELD_1(sc, mb, field) \ FW_TXDESC_GETFIELD(sc, mb, field, 1) #define FW_TXDESC_GETFIELD_4(sc, mb, field) \ letoh32(FW_TXDESC_GETFIELD(sc, mb, field, 4)) /* * Firmware TX descriptor * Fields are little endian */ struct acx_fw_txdesc { uint32_t f_tx_next_desc; /* next acx_fw_txdesc phyaddr */ uint32_t f_tx_host_desc; /* acx_host_desc phyaddr */ uint32_t f_tx_acx_ptr; uint32_t f_tx_time; uint16_t f_tx_len; uint16_t f_tx_reserved; uint32_t f_tx_dev_spec[4]; uint8_t f_tx_ctrl; /* see DESC_CTRL_ */ uint8_t f_tx_ctrl2; uint8_t f_tx_error; /* see DESC_ERR_ */ uint8_t f_tx_ack_fail; uint8_t f_tx_rts_fail; uint8_t f_tx_rts_ok; /* XXX should be moved to chip specific file */ union { struct { uint8_t rate100; /* acx100 tx rate */ uint8_t queue_ctrl; } __packed r1; struct { uint16_t rate111; /* acx111 tx rate */ } __packed r2; } u; #define f_tx_rate100 u.r1.rate100 #define f_tx_queue_ctrl u.r1.queue_ctrl #define f_tx_rate111 u.r2.rate111 uint32_t f_tx_queue_info; } __packed; /* * Firmware RX descriptor * Fields are little endian */ struct acx_fw_rxdesc { uint32_t f_rx_next_desc; /* next acx_fw_rxdesc phyaddr */ uint32_t f_rx_host_desc; /* acx_host_desc phyaddr */ uint32_t f_rx_acx_ptr; uint32_t f_rx_time; uint16_t f_rx_len; uint16_t f_rx_wep_len; uint32_t f_rx_wep_ofs; uint8_t f_rx_dev_spec[16]; uint8_t f_rx_ctrl; /* see DESC_CTRL_ */ uint8_t f_rx_rate; uint8_t f_rx_error; uint8_t f_rx_snr; /* signal noise ratio */ uint8_t f_rx_level; uint8_t f_rx_queue_ctrl; uint16_t f_rx_unknown0; uint32_t f_rx_unknown1; } __packed; /* * Host TX/RX descriptor * Fields are little endian */ struct acx_host_desc { uint32_t h_data_paddr; /* data phyaddr */ uint16_t h_data_ofs; uint16_t h_reserved; uint16_t h_ctrl; /* see DESC_CTRL_ */ uint16_t h_data_len; /* data length */ uint32_t h_next_desc; /* next acx_host_desc phyaddr */ uint32_t h_pnext; uint32_t h_status; /* see DESC_STATUS_ */ } __packed; #define DESC_STATUS_FULL 0x80000000 #define DESC_CTRL_SHORT_PREAMBLE 0x01 #define DESC_CTRL_FIRST_FRAG 0x02 #define DESC_CTRL_AUTODMA 0x04 #define DESC_CTRL_RECLAIM 0x08 #define DESC_CTRL_HOSTDONE 0x20 /* host finished buf proc */ #define DESC_CTRL_ACXDONE 0x40 /* chip finished buf proc */ #define DESC_CTRL_HOSTOWN 0x80 /* host controls desc */ #define DESC_ERR_OTHER_FRAG 0x01 #define DESC_ERR_ABORT 0x02 #define DESC_ERR_PARAM 0x04 #define DESC_ERR_NO_WEPKEY 0x08 #define DESC_ERR_MSDU_TIMEOUT 0x10 #define DESC_ERR_EXCESSIVE_RETRY 0x20 #define DESC_ERR_BUF_OVERFLOW 0x40 #define DESC_ERR_DMA 0x80 /* * Extra header in receiving buffer * Fields are little endian */ struct acx_rxbuf_hdr { uint16_t rbh_len; /* ACX_RXBUG_LEN_MASK part is len */ uint8_t rbh_memblk_cnt; uint8_t rbh_status; uint8_t rbh_stat_baseband; /* see ACX_RXBUF_STAT_ */ uint8_t rbh_plcp; uint8_t rbh_level; /* signal level */ uint8_t rbh_snr; /* signal noise ratio */ uint32_t rbh_time; /* recv timestamp */ /* * XXX may have 4~8 byte here which * depends on firmware version */ } __packed; #define ACX_RXBUF_LEN_MASK 0xfff #define ACX_RXBUF_STAT_LNA 0x80 /* low noise amplifier */ struct acx_ring_data { struct acx_host_desc *rx_ring; bus_dma_segment_t rx_ring_seg; bus_dmamap_t rx_ring_dmamap; uint32_t rx_ring_paddr; struct acx_host_desc *tx_ring; bus_dma_segment_t tx_ring_seg; bus_dmamap_t tx_ring_dmamap; uint32_t tx_ring_paddr; }; struct acx_txbuf { struct mbuf *tb_mbuf; bus_dmamap_t tb_mbuf_dmamap; struct acx_host_desc *tb_desc1; struct acx_host_desc *tb_desc2; uint32_t tb_fwdesc_ofs; /* * Used by tx rate updating */ struct acx_node *tb_node; /* remote node */ int tb_rate; /* current tx rate */ }; struct acx_rxbuf { struct mbuf *rb_mbuf; bus_dmamap_t rb_mbuf_dmamap; struct acx_host_desc *rb_desc; }; struct acx_buf_data { struct acx_rxbuf rx_buf[ACX_RX_DESC_CNT]; struct acx_txbuf tx_buf[ACX_TX_DESC_CNT]; bus_dmamap_t mbuf_tmp_dmamap; int rx_scan_start; int tx_free_start; int tx_used_start; int tx_used_count; }; struct acx_node { struct ieee80211_node ni; /* must be first */ struct ieee80211_amrr_node amn; }; struct acx_config { uint8_t antenna; uint8_t regdom; uint8_t cca_mode; /* acx100 */ uint8_t ed_thresh; /* acx100 */ }; struct acx_stats { uint64_t err_oth_frag; /* XXX error in other frag?? */ uint64_t err_abort; /* tx abortion */ uint64_t err_param; /* tx desc contains invalid param */ uint64_t err_no_wepkey; /* no WEP key exists */ uint64_t err_msdu_timeout; /* MSDU timed out */ uint64_t err_ex_retry; /* excessive tx retry */ uint64_t err_buf_oflow; /* buffer overflow */ uint64_t err_dma; /* DMA error */ uint64_t err_unkn; /* XXX unknown error */ }; #define ACX_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_RSSI)) struct acx_rx_radiotap_hdr { struct ieee80211_radiotap_header wr_ihdr; uint8_t wr_flags; uint16_t wr_chan_freq; uint16_t wr_chan_flags; uint8_t wr_rssi; uint8_t wr_max_rssi; } __packed; #define ACX_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL)) \ struct acx_tx_radiotap_hdr { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; } __packed; struct acx_softc { /* * sc_xxx are filled in by common code * chip_xxx are filled in by chip specific code */ struct device sc_dev; struct ieee80211com sc_ic; struct timeout sc_chanscan_timer; uint32_t sc_flags; /* see ACX_FLAG_ */ uint32_t sc_firmware_ver; uint32_t sc_hardware_id; bus_dma_tag_t sc_dmat; struct ieee80211_amrr amrr; struct timeout amrr_ch; /* * MMIO 1 */ struct resource *sc_mem1_res; bus_space_tag_t sc_mem1_bt; bus_space_handle_t sc_mem1_bh; int chip_mem1_rid; /* * MMIO 2 */ struct resource *sc_mem2_res; bus_space_tag_t sc_mem2_bt; bus_space_handle_t sc_mem2_bh; int chip_mem2_rid; struct resource *sc_irq_res; void *sc_irq_handle; int sc_irq_rid; int (*sc_enable)(struct acx_softc *); void (*sc_disable)(struct acx_softc *); void (*sc_power)(struct acx_softc *, int); uint32_t sc_cmd; /* cmd reg (MMIO 2) */ uint32_t sc_cmd_param; /* cmd param reg (MMIO 2) */ uint32_t sc_info; /* unused */ uint32_t sc_info_param; /* unused */ const uint16_t *chip_ioreg; /* reg map (MMIO 1) */ /* * NOTE: * chip_intr_enable is not necessarily same as * ~chip_intr_disable */ uint16_t chip_intr_enable; uint16_t chip_intr_disable; int chip_hw_crypt; uint16_t chip_gpio_pled; /* power led */ uint16_t chip_chan_flags; /* see IEEE80211_CHAN_ */ uint16_t chip_txdesc1_len; int chip_rxbuf_exhdr; /* based on fw ver */ uint32_t chip_ee_eaddr_ofs; enum ieee80211_phymode chip_phymode; /* see IEEE80211_MODE_ */ uint8_t chip_fw_txdesc_ctrl; uint8_t sc_eeprom_ver; /* unused */ uint8_t sc_form_factor; /* unused */ uint8_t sc_radio_type; /* see ACX_RADIO_TYPE_ */ struct acx_ring_data sc_ring_data; struct acx_buf_data sc_buf_data; struct acx_stats sc_stats; /* statistics */ /* * Per interface sysctl variables */ int sc_txtimer; int sc_long_retry_limit; int sc_short_retry_limit; int sc_msdu_lifetime; int (*sc_newstate) (struct ieee80211com *, enum ieee80211_state, int); int (*chip_init) /* non-NULL */ (struct acx_softc *); int (*chip_set_wepkey) (struct acx_softc *, struct ieee80211_wepkey *, int); int (*chip_read_config) (struct acx_softc *, struct acx_config *); int (*chip_write_config) (struct acx_softc *, struct acx_config *); void (*chip_set_fw_txdesc_rate) /* non-NULL */ (struct acx_softc *, struct acx_txbuf *, int); void (*chip_set_bss_join_param) /* non-NULL */ (struct acx_softc *, void *, int); void (*chip_proc_wep_rxbuf) (struct acx_softc *, struct mbuf *, int *); #if NBPFILTER > 0 caddr_t sc_drvbpf; union { struct acx_rx_radiotap_hdr th; uint8_t pad[64]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th int sc_rxtap_len; union { struct acx_tx_radiotap_hdr th; uint8_t pad[64]; } sc_txtapu; #define sc_txtap sc_txtapu.th int sc_txtap_len; #endif }; #define ACX_FLAG_FW_LOADED 0x01 #define ACX_FLAG_ACX111 0x02 #define ACX_RADIO_TYPE_MAXIM 0x0d #define ACX_RADIO_TYPE_RFMD 0x11 #define ACX_RADIO_TYPE_RALINK 0x15 #define ACX_RADIO_TYPE_RADIA 0x16 #define ACX_RADIO_TYPE_UNKN17 0x17 #define ACX_RADIO_TYPE_UNKN19 0x19 #define ACX_RADIO_RSSI_MAXIM 120 /* 100dB */ #define ACX_RADIO_RSSI_RFMD 215 /* 215dB */ #define ACX_RADIO_RSSI_RALINK 0 /* XXX unknown yet */ #define ACX_RADIO_RSSI_RADIA 78 /* 78db */ #define ACX_RADIO_RSSI_UNKN 0 /* unknown radio */ extern const struct ieee80211_rateset acx_rates_11b; extern const struct ieee80211_rateset acx_rates_11g; extern int acx_beacon_intvl; void acx100_set_param(struct acx_softc *); void acx111_set_param(struct acx_softc *); int acx_init_tmplt_ordered(struct acx_softc *); void acx_write_phyreg(struct acx_softc *, uint32_t, uint8_t); int acx_set_tmplt(struct acx_softc *, uint16_t, void *, uint16_t); int acx_get_conf(struct acx_softc *, uint16_t, void *, uint16_t); int acx_set_conf(struct acx_softc *, uint16_t, void *, uint16_t); int acx_exec_command(struct acx_softc *, uint16_t, void *, uint16_t, void *, uint16_t); int acx_attach(struct acx_softc *); int acx_detach(void *); int acx_intr(void *); #endif /* !_IF_ACXVAR_H */