2005-04-18 18:47:38 +00:00
|
|
|
/* $FreeBSD$ */
|
|
|
|
|
|
|
|
/*-
|
2006-04-27 21:43:37 +00:00
|
|
|
* Copyright (c) 2004, 2005
|
2005-04-18 18:47:38 +00:00
|
|
|
* Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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 unmodified, 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.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct iwi_rx_radiotap_header {
|
|
|
|
struct ieee80211_radiotap_header wr_ihdr;
|
|
|
|
uint8_t wr_flags;
|
|
|
|
uint8_t wr_rate;
|
|
|
|
uint16_t wr_chan_freq;
|
|
|
|
uint16_t wr_chan_flags;
|
|
|
|
uint8_t wr_antsignal;
|
|
|
|
uint8_t wr_antenna;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IWI_RX_RADIOTAP_PRESENT \
|
|
|
|
((1 << IEEE80211_RADIOTAP_FLAGS) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_RATE) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_ANTENNA))
|
|
|
|
|
|
|
|
struct iwi_tx_radiotap_header {
|
|
|
|
struct ieee80211_radiotap_header wt_ihdr;
|
|
|
|
uint8_t wt_flags;
|
|
|
|
uint16_t wt_chan_freq;
|
|
|
|
uint16_t wt_chan_flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IWI_TX_RADIOTAP_PRESENT \
|
|
|
|
((1 << IEEE80211_RADIOTAP_FLAGS) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_CHANNEL))
|
|
|
|
|
|
|
|
struct iwi_cmd_ring {
|
|
|
|
bus_dma_tag_t desc_dmat;
|
|
|
|
bus_dmamap_t desc_map;
|
|
|
|
bus_addr_t physaddr;
|
|
|
|
struct iwi_cmd_desc *desc;
|
|
|
|
int count;
|
|
|
|
int queued;
|
|
|
|
int cur;
|
|
|
|
int next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iwi_tx_data {
|
|
|
|
bus_dmamap_t map;
|
|
|
|
struct mbuf *m;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iwi_tx_ring {
|
|
|
|
bus_dma_tag_t desc_dmat;
|
|
|
|
bus_dma_tag_t data_dmat;
|
|
|
|
bus_dmamap_t desc_map;
|
|
|
|
bus_addr_t physaddr;
|
2005-08-20 16:49:03 +00:00
|
|
|
bus_addr_t csr_ridx;
|
|
|
|
bus_addr_t csr_widx;
|
2005-04-18 18:47:38 +00:00
|
|
|
struct iwi_tx_desc *desc;
|
|
|
|
struct iwi_tx_data *data;
|
|
|
|
int count;
|
|
|
|
int queued;
|
|
|
|
int cur;
|
|
|
|
int next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iwi_rx_data {
|
|
|
|
bus_dmamap_t map;
|
|
|
|
bus_addr_t physaddr;
|
|
|
|
uint32_t reg;
|
|
|
|
struct mbuf *m;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iwi_rx_ring {
|
|
|
|
bus_dma_tag_t data_dmat;
|
|
|
|
struct iwi_rx_data *data;
|
|
|
|
int count;
|
|
|
|
int cur;
|
|
|
|
};
|
|
|
|
|
2005-09-19 18:59:04 +00:00
|
|
|
struct iwi_node {
|
|
|
|
struct ieee80211_node in_node;
|
|
|
|
int in_station;
|
|
|
|
#define IWI_MAX_IBSSNODE 32
|
|
|
|
};
|
|
|
|
|
2006-04-27 21:43:37 +00:00
|
|
|
struct iwi_fw {
|
Cleanup and document the implementation of firmware(9) based on
a version that i posted earlier on the -current mailing list,
and subsequent feedback received.
The core of the change is just in sys/firmware.h and kern/subr_firmware.c,
while other files are just adaptation of the clients to the ABI change
(const-ification of some parameters and hiding of internal info,
so this is fully compatible at the binary level).
In detail:
- reduce the amount of information exported to clients in struct firmware,
and constify the pointer;
- internally, document and simplify the implementation of the various
functions, and make sure error conditions are dealt with properly.
The diffs are large, but the code is really straightforward now (i hope).
Note also that there is a subtle issue with the implementation of
firmware_register(): currently, as in the previous version, we just
store a reference to the 'imagename' argument, but we should rather
copy it because there is no guarantee that this is a static string.
I realised this while testing this code, but i prefer to fix it in
a later commit -- there is no regression with respect to the past.
Note, too, that the version in RELENG_6 has various bugs including
missing locks around the module release calls, mishandling of modules
loaded by /boot/loader, and so on, so an MFC is absolutely necessary
there. I was just postponing it until this cleanup to avoid doing
things twice.
MFC after: 1 week
2007-02-15 17:21:31 +00:00
|
|
|
const struct firmware *fp; /* image handle */
|
2006-04-27 21:43:37 +00:00
|
|
|
const char *data; /* firmware image data */
|
|
|
|
size_t size; /* firmware image size */
|
|
|
|
const char *name; /* associated image name */
|
|
|
|
};
|
|
|
|
|
2005-04-18 18:47:38 +00:00
|
|
|
struct iwi_softc {
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *sc_ifp;
|
2005-04-18 18:47:38 +00:00
|
|
|
struct ieee80211com sc_ic;
|
|
|
|
int (*sc_newstate)(struct ieee80211com *,
|
|
|
|
enum ieee80211_state, int);
|
2005-09-19 18:59:04 +00:00
|
|
|
void (*sc_node_free)(struct ieee80211_node *);
|
2005-04-18 18:47:38 +00:00
|
|
|
device_t sc_dev;
|
|
|
|
|
|
|
|
struct mtx sc_mtx;
|
2006-04-27 21:43:37 +00:00
|
|
|
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
|
2005-09-19 18:59:04 +00:00
|
|
|
struct unrhdr *sc_unr;
|
2006-04-27 21:43:37 +00:00
|
|
|
struct taskqueue *sc_tq; /* private task queue */
|
|
|
|
#if __FreeBSD_version < 700000
|
|
|
|
struct proc *sc_tqproc;
|
|
|
|
#endif
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
uint32_t flags;
|
2005-11-19 16:54:55 +00:00
|
|
|
#define IWI_FLAG_FW_INITED (1 << 0)
|
|
|
|
#define IWI_FLAG_SCANNING (1 << 1)
|
2006-04-27 21:43:37 +00:00
|
|
|
#define IWI_FLAG_FW_LOADING (1 << 2)
|
|
|
|
#define IWI_FLAG_BUSY (1 << 3) /* busy sending a command */
|
|
|
|
#define IWI_FLAG_ASSOCIATED (1 << 4) /* currently associated */
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
struct iwi_cmd_ring cmdq;
|
2005-08-20 16:49:03 +00:00
|
|
|
struct iwi_tx_ring txq[WME_NUM_AC];
|
2005-04-18 18:47:38 +00:00
|
|
|
struct iwi_rx_ring rxq;
|
|
|
|
|
|
|
|
struct resource *irq;
|
|
|
|
struct resource *mem;
|
|
|
|
bus_space_tag_t sc_st;
|
|
|
|
bus_space_handle_t sc_sh;
|
|
|
|
void *sc_ih;
|
|
|
|
int mem_rid;
|
|
|
|
int irq_rid;
|
|
|
|
|
2007-02-20 15:45:59 +00:00
|
|
|
/*
|
|
|
|
* The card needs external firmware images to work, which is made of a
|
|
|
|
* bootloader, microcode and firmware proper. In version 3.00 and
|
|
|
|
* above, all pieces are contained in a single image, preceded by a
|
|
|
|
* struct iwi_firmware_hdr indicating the size of the 3 pieces.
|
|
|
|
* Old firmware < 3.0 has separate boot and ucode, so we need to
|
|
|
|
* load all of them explicitly.
|
|
|
|
* To avoid issues related to fragmentation, we keep the block of
|
|
|
|
* dma-ble memory around until detach time, and reallocate it when
|
|
|
|
* it becomes too small. fw_dma_size is the size currently allocated.
|
|
|
|
*/
|
2006-04-27 21:43:37 +00:00
|
|
|
int fw_dma_size;
|
2007-02-20 15:45:59 +00:00
|
|
|
uint32_t fw_flags; /* allocation status */
|
|
|
|
#define IWI_FW_HAVE_DMAT 0x01
|
|
|
|
#define IWI_FW_HAVE_MAP 0x02
|
|
|
|
#define IWI_FW_HAVE_PHY 0x04
|
2006-04-27 21:43:37 +00:00
|
|
|
bus_dma_tag_t fw_dmat;
|
|
|
|
bus_dmamap_t fw_map;
|
|
|
|
bus_addr_t fw_physaddr;
|
|
|
|
void *fw_virtaddr;
|
|
|
|
enum ieee80211_opmode fw_mode; /* mode of current firmware */
|
|
|
|
struct iwi_fw fw_boot; /* boot firmware */
|
|
|
|
struct iwi_fw fw_uc; /* microcode */
|
|
|
|
struct iwi_fw fw_fw; /* operating mode support */
|
|
|
|
|
|
|
|
int curchan; /* current h/w channel # */
|
2005-05-22 18:55:32 +00:00
|
|
|
int antenna;
|
2005-04-18 18:47:38 +00:00
|
|
|
int dwelltime;
|
|
|
|
int bluetooth;
|
2006-04-27 21:43:37 +00:00
|
|
|
struct iwi_associate assoc;
|
|
|
|
struct iwi_wme_params wme[3];
|
|
|
|
|
|
|
|
struct task sc_radiontask; /* radio on processing */
|
|
|
|
struct task sc_radiofftask; /* radio off processing */
|
|
|
|
struct task sc_scanstarttask;/* scan start processing */
|
|
|
|
struct task sc_scanaborttask;/* scan abort processing */
|
|
|
|
struct task sc_scandonetask;/* scan completed processing */
|
|
|
|
struct task sc_scantask; /* scan channel processing */
|
|
|
|
struct task sc_setwmetask; /* set wme params processing */
|
|
|
|
struct task sc_downtask; /* disassociate processing */
|
|
|
|
struct task sc_restarttask; /* restart adapter processing */
|
|
|
|
|
|
|
|
unsigned int sc_softled : 1, /* enable LED gpio status */
|
|
|
|
sc_ledstate: 1, /* LED on/off state */
|
|
|
|
sc_blinking: 1; /* LED blink operation active */
|
|
|
|
u_int sc_nictype; /* NIC type from EEPROM */
|
|
|
|
u_int sc_ledpin; /* mask for activity LED */
|
|
|
|
u_int sc_ledidle; /* idle polling interval */
|
|
|
|
int sc_ledevent; /* time of last LED event */
|
|
|
|
u_int8_t sc_rxrate; /* current rx rate for LED */
|
|
|
|
u_int8_t sc_rxrix;
|
|
|
|
u_int8_t sc_txrate; /* current tx rate for LED */
|
|
|
|
u_int8_t sc_txrix;
|
|
|
|
u_int16_t sc_ledoff; /* off time for current blink */
|
|
|
|
struct callout sc_ledtimer; /* led off timer */
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
int sc_tx_timer;
|
2006-04-27 21:43:37 +00:00
|
|
|
int sc_rfkill_timer;/* poll for rfkill change */
|
|
|
|
int sc_scan_timer; /* scan request timeout */
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
struct bpf_if *sc_drvbpf;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct iwi_rx_radiotap_header th;
|
|
|
|
uint8_t pad[64];
|
|
|
|
} sc_rxtapu;
|
|
|
|
#define sc_rxtap sc_rxtapu.th
|
|
|
|
int sc_rxtap_len;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct iwi_tx_radiotap_header th;
|
|
|
|
uint8_t pad[64];
|
|
|
|
} sc_txtapu;
|
|
|
|
#define sc_txtap sc_txtapu.th
|
|
|
|
int sc_txtap_len;
|
|
|
|
};
|
|
|
|
|
2006-04-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* NB.: This models the only instance of async locking in iwi_init_locked
|
|
|
|
* and must be kept in sync.
|
|
|
|
*/
|
|
|
|
#define IWI_LOCK_DECL int __waslocked = 0
|
2007-02-20 17:32:30 +00:00
|
|
|
#define IWI_LOCK_CHECK(sc) do { \
|
2007-02-20 15:45:59 +00:00
|
|
|
if (!mtx_owned(&(sc)->sc_mtx)) \
|
2007-02-20 17:32:30 +00:00
|
|
|
DPRINTF(("%s iwi_lock not held\n", __func__)); \
|
2007-02-20 15:45:59 +00:00
|
|
|
} while (0)
|
2006-04-27 21:43:37 +00:00
|
|
|
#define IWI_LOCK(sc) do { \
|
|
|
|
if (!(__waslocked = mtx_owned(&(sc)->sc_mtx))) \
|
|
|
|
mtx_lock(&(sc)->sc_mtx); \
|
|
|
|
} while (0)
|
|
|
|
#define IWI_UNLOCK(sc) do { \
|
|
|
|
if (!__waslocked) \
|
|
|
|
mtx_unlock(&(sc)->sc_mtx); \
|
|
|
|
} while (0)
|