2005-04-18 18:47:38 +00:00
|
|
|
/* $FreeBSD$ */
|
|
|
|
|
|
|
|
/*-
|
2006-03-12 19:01:00 +00:00
|
|
|
* Copyright (c) 2004-2006
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define IPW_MAX_NSEG 1
|
|
|
|
|
|
|
|
struct ipw_soft_bd {
|
|
|
|
struct ipw_bd *bd;
|
|
|
|
int type;
|
|
|
|
#define IPW_SBD_TYPE_NOASSOC 0
|
|
|
|
#define IPW_SBD_TYPE_COMMAND 1
|
|
|
|
#define IPW_SBD_TYPE_HEADER 2
|
|
|
|
#define IPW_SBD_TYPE_DATA 3
|
|
|
|
void *priv;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ipw_soft_hdr {
|
|
|
|
struct ipw_hdr hdr;
|
|
|
|
bus_dmamap_t map;
|
|
|
|
SLIST_ENTRY(ipw_soft_hdr) next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ipw_soft_buf {
|
|
|
|
struct mbuf *m;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
bus_dmamap_t map;
|
|
|
|
SLIST_ENTRY(ipw_soft_buf) next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ipw_rx_radiotap_header {
|
|
|
|
struct ieee80211_radiotap_header wr_ihdr;
|
|
|
|
uint8_t wr_flags;
|
|
|
|
uint16_t wr_chan_freq;
|
|
|
|
uint16_t wr_chan_flags;
|
|
|
|
uint8_t wr_antsignal;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IPW_RX_RADIOTAP_PRESENT \
|
|
|
|
((1 << IEEE80211_RADIOTAP_FLAGS) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL))
|
|
|
|
|
|
|
|
struct ipw_tx_radiotap_header {
|
|
|
|
struct ieee80211_radiotap_header wt_ihdr;
|
|
|
|
uint8_t wt_flags;
|
|
|
|
uint16_t wt_chan_freq;
|
|
|
|
uint16_t wt_chan_flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IPW_TX_RADIOTAP_PRESENT \
|
|
|
|
((1 << IEEE80211_RADIOTAP_FLAGS) | \
|
|
|
|
(1 << IEEE80211_RADIOTAP_CHANNEL))
|
|
|
|
|
|
|
|
struct ipw_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);
|
|
|
|
device_t sc_dev;
|
|
|
|
|
|
|
|
struct mtx sc_mtx;
|
2006-03-12 19:01:00 +00:00
|
|
|
struct task sc_init_task;
|
2007-10-12 05:23:00 +00:00
|
|
|
struct task sc_scan_task;
|
|
|
|
struct task sc_chan_task;
|
|
|
|
struct task sc_assoc_task;
|
|
|
|
struct task sc_disassoc_task;
|
|
|
|
struct callout sc_wdtimer; /* watchdog timer */
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
uint32_t flags;
|
2006-03-12 19:01:00 +00:00
|
|
|
#define IPW_FLAG_FW_INITED (1 << 0)
|
|
|
|
#define IPW_FLAG_INIT_LOCKED (1 << 1)
|
2005-04-18 18:47:38 +00:00
|
|
|
#define IPW_FLAG_HAS_RADIO_SWITCH (1 << 2)
|
2007-10-12 05:23:00 +00:00
|
|
|
#define IPW_FLAG_HACK (1 << 3)
|
|
|
|
#define IPW_FLAG_SCANNING (1 << 4)
|
|
|
|
#define IPW_FLAG_ENABLED (1 << 5)
|
|
|
|
#define IPW_FLAG_BUSY (1 << 6)
|
|
|
|
#define IPW_FLAG_ASSOCIATED (1 << 7)
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
int irq_rid;
|
|
|
|
int mem_rid;
|
|
|
|
struct resource *irq;
|
|
|
|
struct resource *mem;
|
|
|
|
bus_space_tag_t sc_st;
|
|
|
|
bus_space_handle_t sc_sh;
|
|
|
|
void *sc_ih;
|
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 *sc_firmware;
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
int sc_tx_timer;
|
2007-10-12 05:23:00 +00:00
|
|
|
int sc_scan_timer;
|
2005-04-18 18:47:38 +00:00
|
|
|
|
|
|
|
bus_dma_tag_t tbd_dmat;
|
|
|
|
bus_dma_tag_t rbd_dmat;
|
|
|
|
bus_dma_tag_t status_dmat;
|
|
|
|
bus_dma_tag_t cmd_dmat;
|
|
|
|
bus_dma_tag_t hdr_dmat;
|
|
|
|
bus_dma_tag_t txbuf_dmat;
|
|
|
|
bus_dma_tag_t rxbuf_dmat;
|
|
|
|
|
|
|
|
bus_dmamap_t tbd_map;
|
|
|
|
bus_dmamap_t rbd_map;
|
|
|
|
bus_dmamap_t status_map;
|
|
|
|
bus_dmamap_t cmd_map;
|
|
|
|
|
|
|
|
bus_addr_t tbd_phys;
|
|
|
|
bus_addr_t rbd_phys;
|
|
|
|
bus_addr_t status_phys;
|
|
|
|
|
|
|
|
struct ipw_bd *tbd_list;
|
|
|
|
struct ipw_bd *rbd_list;
|
|
|
|
struct ipw_status *status_list;
|
|
|
|
|
|
|
|
struct ipw_cmd cmd;
|
|
|
|
struct ipw_soft_bd stbd_list[IPW_NTBD];
|
|
|
|
struct ipw_soft_buf tx_sbuf_list[IPW_NDATA];
|
|
|
|
struct ipw_soft_hdr shdr_list[IPW_NDATA];
|
|
|
|
struct ipw_soft_bd srbd_list[IPW_NRBD];
|
|
|
|
struct ipw_soft_buf rx_sbuf_list[IPW_NRBD];
|
|
|
|
|
|
|
|
SLIST_HEAD(, ipw_soft_hdr) free_shdr;
|
|
|
|
SLIST_HEAD(, ipw_soft_buf) free_sbuf;
|
|
|
|
|
|
|
|
uint32_t table1_base;
|
|
|
|
uint32_t table2_base;
|
|
|
|
|
|
|
|
uint32_t txcur;
|
|
|
|
uint32_t txold;
|
|
|
|
uint32_t rxcur;
|
|
|
|
int txfree;
|
|
|
|
|
|
|
|
int dwelltime;
|
|
|
|
|
|
|
|
struct bpf_if *sc_drvbpf;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct ipw_rx_radiotap_header th;
|
|
|
|
uint8_t pad[64];
|
|
|
|
} sc_rxtapu;
|
|
|
|
#define sc_rxtap sc_rxtapu.th
|
|
|
|
int sc_rxtap_len;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct ipw_tx_radiotap_header th;
|
|
|
|
uint8_t pad[64];
|
|
|
|
} sc_txtapu;
|
|
|
|
#define sc_txtap sc_txtapu.th
|
|
|
|
int sc_txtap_len;
|
|
|
|
};
|
2007-10-12 05:23:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* NB.: This models the only instance of async locking in ipw_init_locked
|
|
|
|
* and must be kept in sync.
|
|
|
|
*/
|
|
|
|
#define IPW_LOCK_DECL int __waslocked = 0
|
|
|
|
#define IPW_LOCK(sc) do { \
|
|
|
|
if (!(__waslocked = mtx_owned(&(sc)->sc_mtx))) \
|
|
|
|
mtx_lock(&sc->sc_mtx); \
|
|
|
|
} while (0)
|
|
|
|
#define IPW_UNLOCK(sc) do { \
|
|
|
|
if (!__waslocked) \
|
|
|
|
mtx_unlock(&sc->sc_mtx); \
|
|
|
|
} while (0)
|
|
|
|
#define IPW_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|