/* $OpenBSD: if_uathvar.h,v 1.3 2006/09/20 19:47:17 damien Exp $ */ /* $FreeBSD$ */ /*- * Copyright (c) 2006 * Damien Bergamini * Copyright (c) 2006 Sam Leffler, Errno Consulting * Copyright (c) 2008-2009 Weongyo Jeong * * 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. */ enum { UATH_INTR_RX, UATH_INTR_TX, UATH_BULK_RX, UATH_BULK_TX, UATH_N_XFERS = 4, }; #define UATH_ID_BSS 2 /* Connection ID */ #define UATH_RX_DATA_LIST_COUNT 128 #define UATH_TX_DATA_LIST_COUNT 16 #define UATH_CMD_LIST_COUNT 60 #define UATH_DATA_TIMEOUT 10000 #define UATH_CMD_TIMEOUT 1000 /* flags for sending firmware commands */ #define UATH_CMD_FLAG_ASYNC (1 << 0) #define UATH_CMD_FLAG_READ (1 << 1) #define UATH_CMD_FLAG_MAGIC (1 << 2) struct uath_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; u_int64_t wr_tsf; u_int8_t wr_flags; u_int8_t wr_rate; uint16_t wr_chan_freq; uint16_t wr_chan_flags; int8_t wr_antsignal; int8_t wr_antnoise; u_int8_t wr_antenna; } __packed; #define UATH_RX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_TSFT) | \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_ANTENNA) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ 0) struct uath_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; uint16_t wt_chan_freq; uint16_t wt_chan_flags; } __packed; #define UATH_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL)) struct uath_data { struct uath_softc *sc; uint8_t *buf; uint16_t buflen; struct mbuf *m; struct ieee80211_node *ni; /* NB: tx only */ STAILQ_ENTRY(uath_data) next; }; typedef STAILQ_HEAD(, uath_data) uath_datahead; struct uath_cmd { struct uath_softc *sc; uint32_t flags; uint32_t msgid; uint8_t *buf; uint16_t buflen; void *odata; /* NB: tx only */ int olen; /* space in odata */ STAILQ_ENTRY(uath_cmd) next; }; typedef STAILQ_HEAD(, uath_cmd) uath_cmdhead; struct uath_wme_settings { uint8_t aifsn; uint8_t logcwmin; uint8_t logcwmax; uint16_t txop; #define UATH_TXOP_TO_US(txop) ((txop) << 5) uint8_t acm; }; struct uath_devcap { uint32_t targetVersion; uint32_t targetRevision; uint32_t macVersion; uint32_t macRevision; uint32_t phyRevision; uint32_t analog5GhzRevision; uint32_t analog2GhzRevision; uint32_t regDomain; uint32_t regCapBits; uint32_t countryCode; uint32_t keyCacheSize; uint32_t numTxQueues; uint32_t connectionIdMax; uint32_t wirelessModes; #define UATH_WIRELESS_MODE_11A 0x01 #define UATH_WIRELESS_MODE_TURBO 0x02 #define UATH_WIRELESS_MODE_11B 0x04 #define UATH_WIRELESS_MODE_11G 0x08 #define UATH_WIRELESS_MODE_108G 0x10 uint32_t chanSpreadSupport; uint32_t compressSupport; uint32_t burstSupport; uint32_t fastFramesSupport; uint32_t chapTuningSupport; uint32_t turboGSupport; uint32_t turboPrimeSupport; uint32_t deviceType; uint32_t wmeSupport; uint32_t low2GhzChan; uint32_t high2GhzChan; uint32_t low5GhzChan; uint32_t high5GhzChan; uint32_t supportCipherWEP; uint32_t supportCipherAES_CCM; uint32_t supportCipherTKIP; uint32_t supportCipherMicAES_CCM; uint32_t supportMicTKIP; uint32_t twiceAntennaGain5G; uint32_t twiceAntennaGain2G; }; struct uath_stat { uint32_t st_badchunkseqnum; uint32_t st_invalidlen; uint32_t st_multichunk; uint32_t st_toobigrxpkt; uint32_t st_stopinprogress; uint32_t st_crcerr; uint32_t st_phyerr; uint32_t st_decrypt_crcerr; uint32_t st_decrypt_micerr; uint32_t st_decomperr; uint32_t st_keyerr; uint32_t st_err; /* CMD/RX/TX queues */ uint32_t st_cmd_active; uint32_t st_cmd_inactive; uint32_t st_cmd_pending; uint32_t st_cmd_waiting; uint32_t st_rx_active; uint32_t st_rx_inactive; uint32_t st_tx_active; uint32_t st_tx_inactive; uint32_t st_tx_pending; }; #define UATH_STAT_INC(sc, var) (sc)->sc_stat.var++ #define UATH_STAT_DEC(sc, var) (sc)->sc_stat.var-- struct uath_vap { struct ieee80211vap vap; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; #define UATH_VAP(vap) ((struct uath_vap *)(vap)) struct uath_softc { struct ifnet *sc_ifp; device_t sc_dev; struct usb_device *sc_udev; struct mtx sc_mtx; uint32_t sc_debug; struct uath_stat sc_stat; int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); struct usb_xfer *sc_xfer[UATH_N_XFERS]; struct uath_cmd sc_cmd[UATH_CMD_LIST_COUNT]; uath_cmdhead sc_cmd_active; uath_cmdhead sc_cmd_inactive; uath_cmdhead sc_cmd_pending; uath_cmdhead sc_cmd_waiting; struct uath_data sc_rx[UATH_RX_DATA_LIST_COUNT]; uath_datahead sc_rx_active; uath_datahead sc_rx_inactive; struct uath_data sc_tx[UATH_TX_DATA_LIST_COUNT]; uath_datahead sc_tx_active; uath_datahead sc_tx_inactive; uath_datahead sc_tx_pending; uint32_t sc_msgid; uint32_t sc_seqnum; int sc_tx_timer; struct callout watchdog_ch; struct callout stat_ch; /* multi-chunked support */ struct mbuf *sc_intrx_head; struct mbuf *sc_intrx_tail; uint8_t sc_intrx_nextnum; uint32_t sc_intrx_len; #define UATH_MAX_INTRX_SIZE 3616 struct uath_devcap sc_devcap; uint8_t sc_serial[16]; /* unsorted */ uint32_t sc_flags; #define UATH_FLAG_INVALID (1 << 1) #define UATH_FLAG_INITDONE (1 << 2) struct uath_rx_radiotap_header sc_rxtap; int sc_rxtap_len; struct uath_tx_radiotap_header sc_txtap; int sc_txtap_len; }; #define UATH_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define UATH_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) #define UATH_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define UATH_RESET_INTRX(sc) do { \ (sc)->sc_intrx_head = NULL; \ (sc)->sc_intrx_tail = NULL; \ (sc)->sc_intrx_nextnum = 0; \ (sc)->sc_intrx_len = 0; \ } while (0)