DragonFly kernel List (threaded) for 2011-01
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]
[PATCH 1/3] Bring in bwi driver changes from freebsd.
---
sys/dev/netif/bwi/bitops.h | 81 ++
sys/dev/netif/bwi/bus_if.h | 265 ++++++
sys/dev/netif/bwi/bwimac.c | 212 +++--
sys/dev/netif/bwi/bwimac.h | 1 +
sys/dev/netif/bwi/bwiphy.c | 27 +-
sys/dev/netif/bwi/bwiphy.h | 1 +
sys/dev/netif/bwi/bwirf.c | 140 ++--
sys/dev/netif/bwi/bwirf.h | 7 +
sys/dev/netif/bwi/device_if.h | 79 ++
sys/dev/netif/bwi/if_bwi.c | 1992 +++++++++++++++++++++-------------------
sys/dev/netif/bwi/if_bwi_pci.c | 254 +++++
sys/dev/netif/bwi/if_bwireg.h | 9 +-
sys/dev/netif/bwi/if_bwivar.h | 117 ++-
sys/dev/netif/bwi/pci_if.h | 190 ++++
14 files changed, 2204 insertions(+), 1171 deletions(-)
create mode 100644 sys/dev/netif/bwi/bitops.h
create mode 100644 sys/dev/netif/bwi/bus_if.h
create mode 100644 sys/dev/netif/bwi/device_if.h
create mode 100644 sys/dev/netif/bwi/if_bwi_pci.c
create mode 100644 sys/dev/netif/bwi/pci_if.h
diff --git a/sys/dev/netif/bwi/bitops.h b/sys/dev/netif/bwi/bitops.h
new file mode 100644
index 0000000..0d6dee8
--- /dev/null
+++ b/sys/dev/netif/bwi/bitops.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2004, 2005 David Young. All rights reserved.
+ *
+ * Programmed for NetBSD by David Young.
+ *
+ * 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. The name of David Young may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY David Young ``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 David
+ * Young 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.
+ *
+ * $DragonFly: src/sys/dev/netif/bwi/bitops.h,v 1.1 2007/09/08 06:15:54 sephe Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _BITOPS_H
+#define _BITOPS_H
+
+/*
+ * __BIT(n): Return a bitmask with bit m set, where the least
+ * significant bit is bit 0.
+ *
+ * __BITS(m, n): Return a bitmask with bits m through n, inclusive,
+ * set. It does not matter whether m>n or m<=n. The
+ * least significant bit is bit 0.
+ *
+ * A "bitfield" is a span of consecutive bits defined by a bitmask,
+ * where 1s select the bits in the bitfield. __SHIFTIN, __SHIFTOUT,
+ * and SHIFTOUT_MASK help read and write bitfields from device registers.
+ *
+ * __SHIFTIN(v, mask): Left-shift bits `v' into the bitfield
+ * defined by `mask', and return them. No
+ * side-effects.
+ *
+ * __SHIFTOUT(v, mask): Extract and return the bitfield selected
+ * by `mask' from `v', right-shifting the
+ * bits so that the rightmost selected bit
+ * is at bit 0. No side-effects.
+ *
+ * __SHIFTOUT_MASK(mask): Right-shift the bits in `mask' so that
+ * the rightmost non-zero bit is at bit
+ * 0. This is useful for finding the
+ * greatest unsigned value that a bitfield
+ * can hold. No side-effects. Note that
+ * SHIFTOUT_MASK(m) = SHIFTOUT(m, m).
+ */
+
+/* __BIT(n): nth bit, where __BIT(0) == 0x1. */
+#define __BIT(__n) (((__n) == 32) ? 0 : ((uint32_t)1 << (__n)))
+
+/* __BITS(m, n): bits m through n, m < n. */
+#define __BITS(__m, __n) \
+ ((__BIT(MAX((__m), (__n)) + 1) - 1) ^ (__BIT(MIN((__m), (__n))) - 1))
+
+/* Find least significant bit that is set */
+#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
+
+#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
+#define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask))
+#define __SHIFTOUT_MASK(__mask) __SHIFTOUT((__mask), (__mask))
+
+#endif /* !_BITOPS_H */
diff --git a/sys/dev/netif/bwi/bus_if.h b/sys/dev/netif/bwi/bus_if.h
new file mode 100644
index 0000000..70e0af4
--- /dev/null
+++ b/sys/dev/netif/bwi/bus_if.h
@@ -0,0 +1,265 @@
+/*
+ * This file is produced automatically.
+ * Do not modify anything in here by hand.
+ *
+ * Created from source file
+ * @/kern/bus_if.m
+ * with
+ * makeobjops.awk
+ *
+ * See the source file for legal information
+ */
+
+#ifndef _bus_if_h_
+#define _bus_if_h_
+
+extern struct kobjop_desc bus_print_child_desc;
+typedef int bus_print_child_t(device_t dev, device_t child);
+static __inline int BUS_PRINT_CHILD(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_print_child);
+ return ((bus_print_child_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc bus_probe_nomatch_desc;
+typedef void bus_probe_nomatch_t(device_t dev, device_t child);
+static __inline void BUS_PROBE_NOMATCH(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_probe_nomatch);
+ ((bus_probe_nomatch_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc bus_read_ivar_desc;
+typedef int bus_read_ivar_t(device_t dev, device_t child, int index,
+ uintptr_t *result);
+static __inline int BUS_READ_IVAR(device_t dev, device_t child, int index,
+ uintptr_t *result)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_read_ivar);
+ return ((bus_read_ivar_t *) _m)(dev, child, index, result);
+}
+
+extern struct kobjop_desc bus_write_ivar_desc;
+typedef int bus_write_ivar_t(device_t dev, device_t child, int index,
+ uintptr_t value);
+static __inline int BUS_WRITE_IVAR(device_t dev, device_t child, int index,
+ uintptr_t value)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_write_ivar);
+ return ((bus_write_ivar_t *) _m)(dev, child, index, value);
+}
+
+extern struct kobjop_desc bus_child_detached_desc;
+typedef void bus_child_detached_t(device_t dev, device_t child);
+static __inline void BUS_CHILD_DETACHED(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_child_detached);
+ ((bus_child_detached_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc bus_driver_added_desc;
+typedef void bus_driver_added_t(device_t dev, driver_t *driver);
+static __inline void BUS_DRIVER_ADDED(device_t dev, driver_t *driver)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_driver_added);
+ ((bus_driver_added_t *) _m)(dev, driver);
+}
+
+extern struct kobjop_desc bus_add_child_desc;
+typedef device_t bus_add_child_t(device_t bus, device_t parent, int order,
+ const char *name, int unit);
+static __inline device_t BUS_ADD_CHILD(device_t bus, device_t parent, int order,
+ const char *name, int unit)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)bus)->ops, bus_add_child);
+ return ((bus_add_child_t *) _m)(bus, parent, order, name, unit);
+}
+
+extern struct kobjop_desc bus_alloc_resource_desc;
+typedef struct resource * bus_alloc_resource_t(device_t dev, device_t child,
+ int type, int *rid, u_long start,
+ u_long end, u_long count,
+ u_int flags);
+static __inline struct resource * BUS_ALLOC_RESOURCE(device_t dev,
+ device_t child, int type,
+ int *rid, u_long start,
+ u_long end, u_long count,
+ u_int flags)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_alloc_resource);
+ return ((bus_alloc_resource_t *) _m)(dev, child, type, rid, start, end, count, flags);
+}
+
+extern struct kobjop_desc bus_activate_resource_desc;
+typedef int bus_activate_resource_t(device_t dev, device_t child, int type,
+ int rid, struct resource *r);
+static __inline int BUS_ACTIVATE_RESOURCE(device_t dev, device_t child,
+ int type, int rid, struct resource *r)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_activate_resource);
+ return ((bus_activate_resource_t *) _m)(dev, child, type, rid, r);
+}
+
+extern struct kobjop_desc bus_deactivate_resource_desc;
+typedef int bus_deactivate_resource_t(device_t dev, device_t child, int type,
+ int rid, struct resource *r);
+static __inline int BUS_DEACTIVATE_RESOURCE(device_t dev, device_t child,
+ int type, int rid,
+ struct resource *r)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_deactivate_resource);
+ return ((bus_deactivate_resource_t *) _m)(dev, child, type, rid, r);
+}
+
+extern struct kobjop_desc bus_release_resource_desc;
+typedef int bus_release_resource_t(device_t dev, device_t child, int type,
+ int rid, struct resource *res);
+static __inline int BUS_RELEASE_RESOURCE(device_t dev, device_t child, int type,
+ int rid, struct resource *res)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_release_resource);
+ return ((bus_release_resource_t *) _m)(dev, child, type, rid, res);
+}
+
+extern struct kobjop_desc bus_setup_intr_desc;
+typedef int bus_setup_intr_t(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_intr_t *intr, void *arg,
+ void **cookiep, lwkt_serialize_t serializer);
+static __inline int BUS_SETUP_INTR(device_t dev, device_t child,
+ struct resource *irq, int flags,
+ driver_intr_t *intr, void *arg,
+ void **cookiep, lwkt_serialize_t serializer)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_setup_intr);
+ return ((bus_setup_intr_t *) _m)(dev, child, irq, flags, intr, arg, cookiep, serializer);
+}
+
+extern struct kobjop_desc bus_teardown_intr_desc;
+typedef int bus_teardown_intr_t(device_t dev, device_t child,
+ struct resource *irq, void *cookie);
+static __inline int BUS_TEARDOWN_INTR(device_t dev, device_t child,
+ struct resource *irq, void *cookie)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_teardown_intr);
+ return ((bus_teardown_intr_t *) _m)(dev, child, irq, cookie);
+}
+
+extern struct kobjop_desc bus_enable_intr_desc;
+typedef void bus_enable_intr_t(device_t dev, device_t child, void *cookie);
+static __inline void BUS_ENABLE_INTR(device_t dev, device_t child, void *cookie)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_enable_intr);
+ ((bus_enable_intr_t *) _m)(dev, child, cookie);
+}
+
+extern struct kobjop_desc bus_disable_intr_desc;
+typedef int bus_disable_intr_t(device_t dev, device_t child, void *cookie);
+static __inline int BUS_DISABLE_INTR(device_t dev, device_t child, void *cookie)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_disable_intr);
+ return ((bus_disable_intr_t *) _m)(dev, child, cookie);
+}
+
+extern struct kobjop_desc bus_set_resource_desc;
+typedef int bus_set_resource_t(device_t dev, device_t child, int type, int rid,
+ u_long start, u_long count);
+static __inline int BUS_SET_RESOURCE(device_t dev, device_t child, int type,
+ int rid, u_long start, u_long count)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_set_resource);
+ return ((bus_set_resource_t *) _m)(dev, child, type, rid, start, count);
+}
+
+extern struct kobjop_desc bus_get_resource_desc;
+typedef int bus_get_resource_t(device_t dev, device_t child, int type, int rid,
+ u_long *startp, u_long *countp);
+static __inline int BUS_GET_RESOURCE(device_t dev, device_t child, int type,
+ int rid, u_long *startp, u_long *countp)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_get_resource);
+ return ((bus_get_resource_t *) _m)(dev, child, type, rid, startp, countp);
+}
+
+extern struct kobjop_desc bus_delete_resource_desc;
+typedef void bus_delete_resource_t(device_t dev, device_t child, int type,
+ int rid);
+static __inline void BUS_DELETE_RESOURCE(device_t dev, device_t child, int type,
+ int rid)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, bus_delete_resource);
+ ((bus_delete_resource_t *) _m)(dev, child, type, rid);
+}
+
+extern struct kobjop_desc bus_get_resource_list_desc;
+typedef struct resource_list * bus_get_resource_list_t(device_t _dev,
+ device_t _child);
+static __inline struct resource_list * BUS_GET_RESOURCE_LIST(device_t _dev,
+ device_t _child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops, bus_get_resource_list);
+ return ((bus_get_resource_list_t *) _m)(_dev, _child);
+}
+
+extern struct kobjop_desc bus_child_present_desc;
+typedef int bus_child_present_t(device_t _dev, device_t _child);
+static __inline int BUS_CHILD_PRESENT(device_t _dev, device_t _child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops, bus_child_present);
+ return ((bus_child_present_t *) _m)(_dev, _child);
+}
+
+extern struct kobjop_desc bus_child_pnpinfo_str_desc;
+typedef int bus_child_pnpinfo_str_t(device_t _dev, device_t _child, char *_buf,
+ size_t _buflen);
+static __inline int BUS_CHILD_PNPINFO_STR(device_t _dev, device_t _child,
+ char *_buf, size_t _buflen)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops, bus_child_pnpinfo_str);
+ return ((bus_child_pnpinfo_str_t *) _m)(_dev, _child, _buf, _buflen);
+}
+
+extern struct kobjop_desc bus_child_location_str_desc;
+typedef int bus_child_location_str_t(device_t _dev, device_t _child, char *_buf,
+ size_t _buflen);
+static __inline int BUS_CHILD_LOCATION_STR(device_t _dev, device_t _child,
+ char *_buf, size_t _buflen)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops, bus_child_location_str);
+ return ((bus_child_location_str_t *) _m)(_dev, _child, _buf, _buflen);
+}
+
+extern struct kobjop_desc bus_config_intr_desc;
+typedef int bus_config_intr_t(device_t _dev, device_t _child, int _irq,
+ enum intr_trigger _trig, enum intr_polarity _pol);
+static __inline int BUS_CONFIG_INTR(device_t _dev, device_t _child, int _irq,
+ enum intr_trigger _trig,
+ enum intr_polarity _pol)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops, bus_config_intr);
+ return ((bus_config_intr_t *) _m)(_dev, _child, _irq, _trig, _pol);
+}
+
+#endif /* _bus_if_h_ */
diff --git a/sys/dev/netif/bwi/bwimac.c b/sys/dev/netif/bwi/bwimac.c
index 592cda2..288a41a 100644
--- a/sys/dev/netif/bwi/bwimac.c
+++ b/sys/dev/netif/bwi/bwimac.c
@@ -58,7 +58,7 @@
#include <netproto/802_11/ieee80211_radiotap.h>
#include <netproto/802_11/ieee80211_var.h>
-#include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
#include <bus/pci/pcireg.h>
#include <bus/pci/pcivar.h>
@@ -83,6 +83,7 @@ static int bwi_mac_get_property(struct bwi_mac *);
static void bwi_mac_set_retry_lim(struct bwi_mac *,
const struct bwi_retry_lim *);
static void bwi_mac_set_ackrates(struct bwi_mac *,
+ const struct ieee80211_rate_table *rt,
const struct ieee80211_rateset *);
static int bwi_mac_gpio_init(struct bwi_mac *);
@@ -95,7 +96,7 @@ static int bwi_mac_fw_alloc(struct bwi_mac *);
static void bwi_mac_fw_free(struct bwi_mac *);
static int bwi_mac_fw_load(struct bwi_mac *);
static int bwi_mac_fw_init(struct bwi_mac *);
-static int bwi_mac_fw_load_iv(struct bwi_mac *, const struct fw_image *);
+static int bwi_mac_fw_load_iv(struct bwi_mac *, const struct firmware *);
static void bwi_mac_setup_tpctl(struct bwi_mac *);
static void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
@@ -292,7 +293,7 @@ bwi_mac_init(struct bwi_mac *mac)
if (error)
return error;
- /* XXX work around for hardware bugs? */
+ /* do timeout fixup */
if (sc->sc_bus_regwin.rw_rev <= 5 &&
sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
CSR_SETBITS_4(sc, BWI_CONF_LO,
@@ -303,7 +304,7 @@ bwi_mac_init(struct bwi_mac *mac)
/* Calibrate PHY */
error = bwi_phy_calibrate(mac);
if (error) {
- if_printf(&sc->sc_ic.ic_if, "PHY calibrate failed\n");
+ device_printf(sc->sc_dev, "PHY calibrate failed\n");
return error;
}
@@ -356,7 +357,7 @@ bwi_mac_init(struct bwi_mac *mac)
*/
bwi_mac_opmode_init(mac);
- /* XXX what's these */
+ /* set up Beacon interval */
if (mac->mac_rev < 3) {
CSR_WRITE_2(sc, 0x60e, 0);
CSR_WRITE_2(sc, 0x610, 0x8000);
@@ -381,7 +382,7 @@ bwi_mac_init(struct bwi_mac *mac)
CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
}
- /* XXX what's this */
+ /* allow the MAC to control the PHY clock (dynamic on/off) */
CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
/* Setup MAC power up delay */
@@ -406,7 +407,7 @@ bwi_mac_init(struct bwi_mac *mac)
for (i = 0; i < BWI_TX_NRING; ++i) {
error = sc->sc_init_tx_ring(sc, i);
if (error) {
- if_printf(&sc->sc_ic.ic_if,
+ device_printf(sc->sc_dev,
"can't initialize %dth TX ring\n", i);
return error;
}
@@ -417,7 +418,7 @@ bwi_mac_init(struct bwi_mac *mac)
*/
error = sc->sc_init_rx_ring(sc);
if (error) {
- if_printf(&sc->sc_ic.ic_if, "can't initialize RX ring\n");
+ device_printf(sc->sc_dev, "can't initialize RX ring\n");
return error;
}
@@ -427,13 +428,13 @@ bwi_mac_init(struct bwi_mac *mac)
if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
error = sc->sc_init_txstats(sc);
if (error) {
- if_printf(&sc->sc_ic.ic_if,
+ device_printf(sc->sc_dev,
"can't initialize TX stats ring\n");
return error;
}
}
- /* XXX what's these */
+ /* update PRETBTT */
CSR_WRITE_2(sc, 0x612, 0x50); /* Force Pre-TBTT to 80? */
MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
@@ -497,11 +498,14 @@ bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
struct bwi_tpctl *tpctl = &mac->mac_tpctl;
if (new_tpctl != NULL) {
- KKASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX);
- KKASSERT(new_tpctl->rf_atten <=
+ KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX,
+ ("bbp_atten %d", new_tpctl->bbp_atten));
+ KASSERT(new_tpctl->rf_atten <=
(rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
- : BWI_RF_ATTEN_MAX1));
- KKASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX);
+ : BWI_RF_ATTEN_MAX1),
+ ("rf_atten %d", new_tpctl->rf_atten));
+ KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX,
+ ("tp_ctrl1 %d", new_tpctl->tp_ctrl1));
tpctl->bbp_atten = new_tpctl->bbp_atten;
tpctl->rf_atten = new_tpctl->rf_atten;
@@ -753,7 +757,8 @@ bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
struct bwi_tpctl tpctl_orig;
int restore_tpctl = 0;
- KKASSERT(phy->phy_mode != IEEE80211_MODE_11A);
+ KASSERT(phy->phy_mode != IEEE80211_MODE_11A,
+ ("phy_mode %d", phy->phy_mode));
if (BWI_IS_BRCM_BU4306(sc))
return;
@@ -800,7 +805,7 @@ bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
"base tssi %d\n", rf->rf_base_tssi);
if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
- if_printf(&sc->sc_ic.ic_if, "base tssi measure failed\n");
+ device_printf(sc->sc_dev, "base tssi measure failed\n");
mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
}
@@ -819,44 +824,43 @@ bwi_mac_detach(struct bwi_mac *mac)
}
static __inline int
-bwi_fwimage_is_valid(struct bwi_softc *sc, const struct fw_image *fw,
+bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
uint8_t fw_type)
{
const struct bwi_fwhdr *hdr;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
- if (fw->fw_imglen < sizeof(*hdr)) {
+ if (fw->datasize < sizeof(*hdr)) {
if_printf(ifp, "invalid firmware (%s): invalid size %zu\n",
- fw->fw_name, fw->fw_imglen);
+ fw->name, fw->datasize);
return 0;
}
- hdr = (const struct bwi_fwhdr *)fw->fw_image;
+ hdr = (const struct bwi_fwhdr *)fw->data;
if (fw_type != BWI_FW_T_IV) {
/*
* Don't verify IV's size, it has different meaning
*/
- if (be32toh(hdr->fw_size) != fw->fw_imglen - sizeof(*hdr)) {
- if_printf(ifp,
- "invalid firmware (%s): size mismatch, "
- "fw %u, real %zu\n",
- fw->fw_name, be32toh(hdr->fw_size),
- fw->fw_imglen - sizeof(*hdr));
+ if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
+ if_printf(ifp, "invalid firmware (%s): size mismatch, "
+ "fw %u, real %zu\n", fw->name,
+ be32toh(hdr->fw_size),
+ fw->datasize - sizeof(*hdr));
return 0;
}
}
if (hdr->fw_type != fw_type) {
if_printf(ifp, "invalid firmware (%s): type mismatch, "
- "fw \'%c\', target \'%c\'\n", fw->fw_name,
+ "fw \'%c\', target \'%c\'\n", fw->name,
hdr->fw_type, fw_type);
return 0;
}
if (hdr->fw_gen != BWI_FW_GEN_1) {
if_printf(ifp, "invalid firmware (%s): wrong generation, "
- "fw %d, target %d\n", fw->fw_name,
+ "fw %d, target %d\n", fw->name,
hdr->fw_gen, BWI_FW_GEN_1);
return 0;
}
@@ -870,27 +874,30 @@ static int
bwi_mac_fw_alloc(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
- struct fw_image *img;
+ struct ifnet *ifp = sc->sc_ifp;
char fwname[64];
int idx;
/*
- * NB: serializer need to be released before loading firmware
- * image to avoid possible dead lock
+ * Try getting the firmware stub so firmware
+ * module would be loaded automatically
*/
- ASSERT_SERIALIZED(ifp->if_serializer);
+ if (mac->mac_stub == NULL) {
+ snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH,
+ sc->sc_fw_version);
+ mac->mac_stub = firmware_get(fwname);
+ if (mac->mac_stub == NULL) {
+ if_printf(ifp, "request firmware %s failed\n", fwname);
+ return ENOMEM;
+ }
+ }
if (mac->mac_ucode == NULL) {
- ksnprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH,
+ snprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH,
sc->sc_fw_version,
mac->mac_rev >= 5 ? 5 : mac->mac_rev);
- lwkt_serialize_exit(ifp->if_serializer);
- img = firmware_image_load(fwname, NULL);
- lwkt_serialize_enter(ifp->if_serializer);
-
- mac->mac_ucode = img;
+ mac->mac_ucode = firmware_get(fwname);
if (mac->mac_ucode == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
@@ -901,15 +908,11 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
}
if (mac->mac_pcm == NULL) {
- ksnprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH,
+ snprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH,
sc->sc_fw_version,
mac->mac_rev < 5 ? 4 : 5);
- lwkt_serialize_exit(ifp->if_serializer);
- img = firmware_image_load(fwname, NULL);
- lwkt_serialize_enter(ifp->if_serializer);
-
- mac->mac_pcm = img;
+ mac->mac_pcm = firmware_get(fwname);
if (mac->mac_pcm == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
@@ -926,19 +929,15 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
idx = 5;
} else {
- if_printf(ifp, "no suitable IV for MAC rev %d\n",
+ if_printf(ifp, "no suitible IV for MAC rev %d\n",
mac->mac_rev);
return ENODEV;
}
- ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH,
+ snprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH,
sc->sc_fw_version, idx);
- lwkt_serialize_exit(ifp->if_serializer);
- img = firmware_image_load(fwname, NULL);
- lwkt_serialize_enter(ifp->if_serializer);
-
- mac->mac_iv = img;
+ mac->mac_iv = firmware_get(fwname);
if (mac->mac_iv == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
@@ -961,14 +960,10 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
return ENODEV;
}
- ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH,
+ snprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH,
sc->sc_fw_version, idx);
- lwkt_serialize_exit(ifp->if_serializer);
- img = firmware_image_load(fwname, NULL);
- lwkt_serialize_enter(ifp->if_serializer);
-
- mac->mac_iv_ext = img;
+ mac->mac_iv_ext = firmware_get(fwname);
if (mac->mac_iv_ext == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
@@ -984,31 +979,36 @@ static void
bwi_mac_fw_free(struct bwi_mac *mac)
{
if (mac->mac_ucode != NULL) {
- firmware_image_unload(mac->mac_ucode);
+ firmware_put(mac->mac_ucode, FIRMWARE_UNLOAD);
mac->mac_ucode = NULL;
}
if (mac->mac_pcm != NULL) {
- firmware_image_unload(mac->mac_pcm);
+ firmware_put(mac->mac_pcm, FIRMWARE_UNLOAD);
mac->mac_pcm = NULL;
}
if (mac->mac_iv != NULL) {
- firmware_image_unload(mac->mac_iv);
+ firmware_put(mac->mac_iv, FIRMWARE_UNLOAD);
mac->mac_iv = NULL;
}
if (mac->mac_iv_ext != NULL) {
- firmware_image_unload(mac->mac_iv_ext);
+ firmware_put(mac->mac_iv_ext, FIRMWARE_UNLOAD);
mac->mac_iv_ext = NULL;
}
+
+ if (mac->mac_stub != NULL) {
+ firmware_put(mac->mac_stub, FIRMWARE_UNLOAD);
+ mac->mac_stub = NULL;
+ }
}
static int
bwi_mac_fw_load(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
const uint32_t *fw;
uint16_t fw_rev;
int fw_len, i;
@@ -1017,8 +1017,8 @@ bwi_mac_fw_load(struct bwi_mac *mac)
* Load ucode image
*/
fw = (const uint32_t *)
- ((const uint8_t *)mac->mac_ucode->fw_image + BWI_FWHDR_SZ);
- fw_len = (mac->mac_ucode->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t);
+ ((const uint8_t *)mac->mac_ucode->data + BWI_FWHDR_SZ);
+ fw_len = (mac->mac_ucode->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
BWI_MOBJ_CTRL_VAL(
@@ -1032,8 +1032,8 @@ bwi_mac_fw_load(struct bwi_mac *mac)
* Load PCM image
*/
fw = (const uint32_t *)
- ((const uint8_t *)mac->mac_pcm->fw_image + BWI_FWHDR_SZ);
- fw_len = (mac->mac_pcm->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t);
+ ((const uint8_t *)mac->mac_pcm->data + BWI_FWHDR_SZ);
+ fw_len = (mac->mac_pcm->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
@@ -1135,26 +1135,26 @@ bwi_mac_gpio_fini(struct bwi_mac *mac)
}
static int
-bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct fw_image *fw)
+bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
const struct bwi_fwhdr *hdr;
const struct bwi_fw_iv *iv;
int n, i, iv_img_size;
/* Get the number of IVs in the IV image */
- hdr = (const struct bwi_fwhdr *)fw->fw_image;
+ hdr = (const struct bwi_fwhdr *)fw->data;
n = be32toh(hdr->fw_iv_cnt);
DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
"IV count %d\n", n);
/* Calculate the IV image size, for later sanity check */
- iv_img_size = fw->fw_imglen - sizeof(*hdr);
+ iv_img_size = fw->datasize - sizeof(*hdr);
/* Locate the first IV */
iv = (const struct bwi_fw_iv *)
- ((const uint8_t *)fw->fw_image + sizeof(*hdr));
+ ((const uint8_t *)fw->data + sizeof(*hdr));
for (i = 0; i < n; ++i) {
uint16_t iv_ofs, ofs;
@@ -1215,7 +1215,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct fw_image *fw)
static int
bwi_mac_fw_init(struct bwi_mac *mac)
{
- struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if;
+ struct ifnet *ifp = mac->mac_sc->sc_ifp;
int error;
error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
@@ -1236,13 +1236,13 @@ static void
bwi_mac_opmode_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t mac_status;
uint16_t pre_tbtt;
CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
- CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
/* Set probe resp timeout to infinite */
MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
@@ -1254,6 +1254,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac)
mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
BWI_MAC_STATUS_PASS_CTL |
+ BWI_MAC_STATUS_PASS_BCN |
BWI_MAC_STATUS_PASS_BADPLCP |
BWI_MAC_STATUS_PASS_BADFCS |
BWI_MAC_STATUS_PROMISC);
@@ -1285,7 +1286,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac)
break;
}
- if (ic->ic_if.if_flags & IFF_PROMISC)
+ if (ic->ic_ifp->if_flags & IFF_PROMISC)
mac_status |= BWI_MAC_STATUS_PROMISC;
CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
@@ -1336,6 +1337,9 @@ bwi_mac_bss_param_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_phy *phy = &mac->mac_phy;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ const struct ieee80211_rate_table *rt;
struct bwi_retry_lim lim;
uint16_t cw_min;
@@ -1358,12 +1362,19 @@ bwi_mac_bss_param_init(struct bwi_mac *mac)
/*
* XXX MAC level acknowledge and CW min/max should depend
* on the char rateset of the IBSS/BSS to join.
+ * XXX this is all wrong; should be done on channel change
*/
-
- /*
- * Set MAC level acknowledge rates
- */
- bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]);
+ if (phy->phy_mode == IEEE80211_MODE_11B) {
+ rt = ieee80211_get_ratetable(
+ ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_B));
+ bwi_mac_set_ackrates(mac, rt,
+ &ic->ic_sup_rates[IEEE80211_MODE_11B]);
+ } else {
+ rt = ieee80211_get_ratetable(
+ ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_G));
+ bwi_mac_set_ackrates(mac, rt,
+ &ic->ic_sup_rates[IEEE80211_MODE_11G]);
+ }
/*
* Set CW min
@@ -1398,27 +1409,28 @@ bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
}
static void
-bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs)
+bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rate_table *rt,
+ const struct ieee80211_rateset *rs)
{
int i;
/* XXX not standard conforming */
for (i = 0; i < rs->rs_nrates; ++i) {
- enum ieee80211_modtype modtype;
+ enum ieee80211_phytype modtype;
uint16_t ofs;
- modtype = ieee80211_rate2modtype(rs->rs_rates[i]);
+ modtype = ieee80211_rate2phytype(rt, rs->rs_rates[i]);
switch (modtype) {
- case IEEE80211_MODTYPE_DS:
+ case IEEE80211_T_DS:
ofs = 0x4c0;
break;
- case IEEE80211_MODTYPE_OFDM:
+ case IEEE80211_T_OFDM:
ofs = 0x480;
break;
default:
panic("unsupported modtype %u\n", modtype);
}
- ofs += (bwi_rate2plcp(rs->rs_rates[i]) & 0xf) * 2;
+ ofs += 2*(ieee80211_rate2plcp(rs->rs_rates[i], modtype) & 0xf);
MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
@@ -1462,7 +1474,7 @@ bwi_mac_stop(struct bwi_mac *mac)
DELAY(1);
}
if (i == NRETRY) {
- if_printf(&sc->sc_ic.ic_if, "can't stop MAC\n");
+ device_printf(sc->sc_dev, "can't stop MAC\n");
return ETIMEDOUT;
}
#undef NRETRY
@@ -1496,7 +1508,7 @@ bwi_mac_config_ps(struct bwi_mac *mac)
DELAY(10);
}
if (i == NRETRY) {
- if_printf(&sc->sc_ic.ic_if, "config PS failed\n");
+ device_printf(sc->sc_dev, "config PS failed\n");
return ETIMEDOUT;
}
#undef NRETRY
@@ -1615,7 +1627,8 @@ bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
struct bwi_mac *mac;
int i;
- KKASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0);
+ KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0,
+ ("sc_nmac %d", sc->sc_nmac));
if (sc->sc_nmac == BWI_MAC_MAX) {
device_printf(sc->sc_dev, "too many MACs\n");
@@ -1626,7 +1639,7 @@ bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
* More than one MAC is only supported by BCM4309
*/
if (sc->sc_nmac != 0 &&
- pci_get_device(sc->sc_dev) != PCI_PRODUCT_BROADCOM_BCM4309) {
+ sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
"ignore second MAC");
return 0;
@@ -1715,7 +1728,8 @@ bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
}
/* RF attenuation MUST be within range */
- KKASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0);
+ KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0,
+ ("rf_atten %d", rf_atten));
/*
* Clamp BBP attenuation
@@ -1904,9 +1918,11 @@ static void
bwi_mac_lock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
- KKASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0);
+ KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
+ ("mac_flags 0x%x", mac->mac_flags));
if (mac->mac_rev < 3)
bwi_mac_stop(mac);
@@ -1926,9 +1942,11 @@ static void
bwi_mac_unlock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
- KKASSERT(mac->mac_flags & BWI_MAC_F_LOCKED);
+ KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
+ ("mac_flags 0x%x", mac->mac_flags));
CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
diff --git a/sys/dev/netif/bwi/bwimac.h b/sys/dev/netif/bwi/bwimac.h
index 73add90..2c5275e 100644
--- a/sys/dev/netif/bwi/bwimac.h
+++ b/sys/dev/netif/bwi/bwimac.h
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*
* $DragonFly: src/sys/dev/netif/bwi/bwimac.h,v 1.2 2008/02/15 11:15:38 sephe Exp $
+ * $FreeBSD$
*/
#ifndef _BWI_MAC_H
diff --git a/sys/dev/netif/bwi/bwiphy.c b/sys/dev/netif/bwi/bwiphy.c
index dc57f26..5b17b2f 100644
--- a/sys/dev/netif/bwi/bwiphy.c
+++ b/sys/dev/netif/bwi/bwiphy.c
@@ -57,7 +57,7 @@
#include <netproto/802_11/ieee80211_radiotap.h>
#include <netproto/802_11/ieee80211_var.h>
-#include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
#include <bus/pci/pcireg.h>
#include <bus/pci/pcivar.h>
@@ -132,7 +132,6 @@ bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
{
struct bwi_softc *sc = mac->mac_sc;
- /* TODO: 11A */
CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
CSR_WRITE_2(sc, BWI_PHY_DATA, data);
}
@@ -142,7 +141,6 @@ bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl)
{
struct bwi_softc *sc = mac->mac_sc;
- /* TODO: 11A */
CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
return CSR_READ_2(sc, BWI_PHY_DATA);
}
@@ -265,7 +263,9 @@ bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data)
{
struct bwi_phy *phy = &mac->mac_phy;
- KKASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0);
+ KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0,
+ ("phy_tbl_ctrl %d phy_tbl_data_lo %d",
+ phy->phy_tbl_ctrl, phy->phy_tbl_data_lo));
PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
PHY_WRITE(mac, phy->phy_tbl_data_lo, data);
}
@@ -275,8 +275,10 @@ bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data)
{
struct bwi_phy *phy = &mac->mac_phy;
- KKASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
- phy->phy_tbl_ctrl != 0);
+ KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
+ phy->phy_tbl_ctrl != 0,
+ ("phy_tbl_data_lo %d phy_tbl_data_hi %d phy_tbl_ctrl %d",
+ phy->phy_tbl_data_lo, phy->phy_tbl_data_hi, phy->phy_tbl_ctrl));
PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16);
@@ -368,7 +370,7 @@ bwi_phy_init_11g(struct bwi_mac *mac)
RF_WRITE(mac, 0x52,
(tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2);
} else {
- RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl1);
+ RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2);
}
if (phy->phy_rev >= 6) {
@@ -397,10 +399,12 @@ bwi_phy_init_11g(struct bwi_mac *mac)
bwi_rf_set_nrssi_thr(mac);
} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) {
- KKASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI);
+ KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI,
+ ("rf_nrssi[1] %d", rf->rf_nrssi[1]));
bwi_rf_calc_nrssi_slope(mac);
} else {
- KKASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI);
+ KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI,
+ ("rf_nrssi[1] %d", rf->rf_nrssi[1]));
bwi_rf_set_nrssi_thr(mac);
}
}
@@ -420,7 +424,7 @@ static void
bwi_phy_init_11b_rev2(struct bwi_mac *mac)
{
/* TODO:11B */
- if_printf(&mac->mac_sc->sc_ic.ic_if,
+ if_printf(mac->mac_sc->sc_ifp,
"%s is not implemented yet\n", __func__);
}
@@ -655,6 +659,9 @@ bwi_phy_init_11b_rev6(struct bwi_mac *mac)
for (ofs = 0xa8; ofs < 0xc8; ++ofs) {
PHY_WRITE(mac, ofs, (val & 0x3f3f));
val += 0x202;
+
+ /* XXX: delay 10 us to avoid PCI parity errors with BCM4318 */
+ DELAY(10);
}
if (phy->phy_mode == IEEE80211_MODE_11G) {
diff --git a/sys/dev/netif/bwi/bwiphy.h b/sys/dev/netif/bwi/bwiphy.h
index 6a90aeb..f865f1f 100644
--- a/sys/dev/netif/bwi/bwiphy.h
+++ b/sys/dev/netif/bwi/bwiphy.h
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*
* $DragonFly: src/sys/dev/netif/bwi/bwiphy.h,v 1.1 2007/09/08 06:15:54 sephe Exp $
+ * $FreeBSD$
*/
#ifndef _BWI_PHY_H
diff --git a/sys/dev/netif/bwi/bwirf.c b/sys/dev/netif/bwi/bwirf.c
index 9d90229..26ef982 100644
--- a/sys/dev/netif/bwi/bwirf.c
+++ b/sys/dev/netif/bwi/bwirf.c
@@ -56,7 +56,7 @@
#include <netproto/802_11/ieee80211_radiotap.h>
#include <netproto/802_11/ieee80211_var.h>
-#include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
#include <bus/pci/pcireg.h>
#include <bus/pci/pcivar.h>
@@ -103,7 +103,7 @@ struct rf_saveregs {
#define RESTORE_PHY_REG(mac, regs, n) PHY_WRITE((mac), 0x##n, (regs)->phy_##n)
static int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]);
-static void bwi_rf_workaround(struct bwi_mac *, u_int);
+static void bwi_rf_work_around(struct bwi_mac *, u_int);
static int bwi_rf_gain_max_reached(struct bwi_mac *, int);
static uint16_t bwi_rf_calibval(struct bwi_mac *);
static uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *);
@@ -132,6 +132,9 @@ static int bwi_rf_calc_rssi_bcm2053(struct bwi_mac *,
const struct bwi_rxbuf_hdr *);
static int bwi_rf_calc_rssi_bcm2060(struct bwi_mac *,
const struct bwi_rxbuf_hdr *);
+static int bwi_rf_calc_noise_bcm2050(struct bwi_mac *);
+static int bwi_rf_calc_noise_bcm2053(struct bwi_mac *);
+static int bwi_rf_calc_noise_bcm2060(struct bwi_mac *);
static void bwi_rf_on_11a(struct bwi_mac *);
static void bwi_rf_on_11bg(struct bwi_mac *);
@@ -166,7 +169,7 @@ bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten)
int n;
n = rf_atten + (14 * (bbp_atten / 2));
- KKASSERT(n < BWI_RFLO_MAX);
+ KASSERT(n < BWI_RFLO_MAX, ("n %d", n));
return &mac->mac_rf.rf_lo[n];
}
@@ -178,7 +181,7 @@ bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
int idx;
idx = lo - rf->rf_lo;
- KKASSERT(idx >= 0 && idx < BWI_RFLO_MAX);
+ KASSERT(idx >= 0 && idx < BWI_RFLO_MAX, ("idx %d", idx));
return isset(rf->rf_lo_used, idx);
}
@@ -270,14 +273,17 @@ bwi_rf_attach(struct bwi_mac *mac)
rf->rf_on = bwi_rf_on_11a;
rf->rf_off = bwi_rf_off_11a;
rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060;
+ rf->rf_calc_noise = bwi_rf_calc_noise_bcm2060;
break;
case IEEE80211_MODE_11B:
if (type == BWI_RF_T_BCM2050) {
rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
+ rf->rf_calc_noise = bwi_rf_calc_noise_bcm2050;
} else if (type == BWI_RF_T_BCM2053) {
rf->rf_ctrl_adj = 1;
rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053;
+ rf->rf_calc_noise = bwi_rf_calc_noise_bcm2053;
} else {
device_printf(sc->sc_dev, "only BCM2050/BCM2053 RF "
"is supported for 11B PHY\n");
@@ -307,6 +313,7 @@ bwi_rf_attach(struct bwi_mac *mac)
rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g;
rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g;
rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
+ rf->rf_calc_noise = bwi_rf_calc_noise_bcm2050;
rf->rf_lo_update = bwi_rf_lo_update_11g;
break;
default:
@@ -335,7 +342,7 @@ bwi_rf_set_chan(struct bwi_mac *mac, u_int chan, int work_around)
/* TODO: 11A */
if (work_around)
- bwi_rf_workaround(mac, chan);
+ bwi_rf_work_around(mac, chan);
CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
@@ -368,6 +375,7 @@ bwi_rf_get_gains(struct bwi_mac *mac)
0x0810, 0x002b, 0x0015
};
+ struct bwi_softc *sc = mac->mac_sc;
struct bwi_phy *phy = &mac->mac_phy;
struct bwi_rf *rf = &mac->mac_rf;
uint16_t save_phy[SAVE_PHY_MAX];
@@ -435,7 +443,7 @@ bwi_rf_get_gains(struct bwi_mac *mac)
PHY_SETBITS(mac, 0x811, 0x100);
PHY_CLRBITS(mac, 0x812, 0x3000);
- if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA) &&
+ if ((sc->sc_card_flags & BWI_CARD_F_EXT_LNA) &&
phy->phy_rev >= 7) {
PHY_SETBITS(mac, 0x811, 0x800);
PHY_SETBITS(mac, 0x812, 0x8000);
@@ -548,14 +556,13 @@ bwi_rf_off_11g_rev5(struct bwi_mac *mac)
}
static void
-bwi_rf_workaround(struct bwi_mac *mac, u_int chan)
+bwi_rf_work_around(struct bwi_mac *mac, u_int chan)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_rf *rf = &mac->mac_rf;
if (chan == IEEE80211_CHAN_ANY) {
- if_printf(&mac->mac_sc->sc_ic.ic_if,
- "%s invalid channel!!\n", __func__);
+ device_printf(sc->sc_dev, "%s invalid channel!!\n", __func__);
return;
}
@@ -597,7 +604,7 @@ bwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
{ 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
#if 0
- KKASSERT(rf_atten < MAP_MAX);
+ KASSERT(rf_atten < MAP_MAX, ("rf_atten %d", rf_atten));
rf_atten = map[rf_atten];
#else
if (rf_atten >= MAP_MAX) {
@@ -968,7 +975,7 @@ bwi_rf_init_bcm2050(struct bwi_mac *mac)
CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex);
PHY_WRITE(mac, 0x35, phyr_35);
- bwi_rf_workaround(mac, rf->rf_curchan);
+ bwi_rf_work_around(mac, rf->rf_curchan);
if (phy->phy_mode == IEEE80211_MODE_11B) {
PHY_WRITE(mac, 0x30, phyr_30);
@@ -1004,7 +1011,8 @@ bwi_rf_calibval(struct bwi_mac *mac)
val = RF_READ(mac, BWI_RFR_BBP_ATTEN);
idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX);
- KKASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])));
+ KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])),
+ ("idx %d", idx));
calib = rf_calibvals[idx] << 1;
if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT)
@@ -1161,7 +1169,7 @@ bwi_rf_map_txpower(struct bwi_mac *mac)
const int8_t *txpower_map;
if (phy->phy_mode == IEEE80211_MODE_11A) {
- if_printf(&sc->sc_ic.ic_if,
+ device_printf(sc->sc_dev,
"no tssi2dbm table for 11a PHY\n");
return ENXIO;
}
@@ -1218,7 +1226,7 @@ bwi_rf_map_txpower(struct bwi_mac *mac)
error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i,
pa_params);
if (error) {
- if_printf(&sc->sc_ic.ic_if,
+ device_printf(sc->sc_dev,
"bwi_rf_calc_txpower failed\n");
break;
}
@@ -1245,7 +1253,7 @@ static void
bwi_rf_lo_update_11g(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_rf *rf = &mac->mac_rf;
struct bwi_phy *phy = &mac->mac_phy;
struct bwi_tpctl *tpctl = &mac->mac_tpctl;
@@ -1254,8 +1262,6 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
uint8_t devi_ctrl;
u_int orig_chan;
- DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__);
-
/*
* Save RF/PHY registers for later restoration
*/
@@ -1449,7 +1455,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
{ 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
- struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if;
+ struct ifnet *ifp = mac->mac_sc->sc_ifp;
struct bwi_rf_lo lo_save, *lo;
uint8_t devi_ctrl = 0;
int idx, adj_rf7a = 0;
@@ -1580,11 +1586,12 @@ bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
if (i < LO_ADJUST_MIN)
i += LO_ADJUST_MAX;
- KKASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN);
+ KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN, ("i %d", i));
if (fin > LO_ADJUST_MAX)
fin -= LO_ADJUST_MAX;
- KKASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN);
+ KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN,
+ ("fin %d", fin));
bcopy(&lo_min, &lo_base, sizeof(lo_base));
for (;;) {
@@ -1708,7 +1715,7 @@ bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac)
for (i = 1; i < 4; ++i)
PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
- bwi_rf_workaround(mac, rf->rf_curchan);
+ bwi_rf_work_around(mac, rf->rf_curchan);
if (phy->phy_version != 0)
CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
@@ -2049,7 +2056,7 @@ bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac)
for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
- bwi_rf_workaround(mac, rf->rf_curchan);
+ bwi_rf_work_around(mac, rf->rf_curchan);
PHY_SETBITS(mac, 0x802, 0x3);
bwi_set_gains(mac, NULL);
PHY_SETBITS(mac, 0x429, 0x8000);
@@ -2284,9 +2291,9 @@ bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode)
struct bwi_phy *phy = &mac->mac_phy;
uint16_t val;
- KKASSERT(ant_mode == BWI_ANT_MODE_0 ||
- ant_mode == BWI_ANT_MODE_1 ||
- ant_mode == BWI_ANT_MODE_AUTO);
+ KASSERT(ant_mode == BWI_ANT_MODE_0 ||
+ ant_mode == BWI_ANT_MODE_1 ||
+ ant_mode == BWI_ANT_MODE_AUTO, ("ant_mode %d", ant_mode));
HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
@@ -2404,8 +2411,6 @@ bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
flags1 = le16toh(hdr->rxh_flags1);
flags3 = le16toh(hdr->rxh_flags3);
-#define NEW_BCM2050_RSSI
-#ifdef NEW_BCM2050_RSSI
if (flags1 & BWI_RXH_F1_OFDM) {
if (rssi > 127)
rssi -= 256;
@@ -2463,40 +2468,6 @@ bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
default:
panic("impossible lna gain %d", lna_gain);
}
-#else /* !NEW_BCM2050_RSSI */
- lna_gain = 0; /* shut up gcc warning */
-
- if (flags1 & BWI_RXH_F1_OFDM) {
- if (rssi > 127)
- rssi -= 256;
- rssi = (rssi * 73) / 64;
-
- if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
- rssi += 25;
- else
- rssi -= 3;
- return rssi;
- }
-
- if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
- struct bwi_rf *rf = &mac->mac_rf;
-
- if (rssi >= BWI_NRSSI_TBLSZ)
- rssi = BWI_NRSSI_TBLSZ - 1;
-
- rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
- rssi -= 57;
- } else {
- rssi = ((31 - rssi) * -149) / 128;
- rssi -= 68;
- }
-
- if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
- return rssi;
-
- if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
- rssi += 25;
-#endif /* NEW_BCM2050_RSSI */
return rssi;
}
@@ -2527,6 +2498,51 @@ bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
return rssi;
}
+static int
+bwi_rf_calc_noise_bcm2050(struct bwi_mac *mac)
+{
+ uint16_t val;
+ int noise;
+
+ val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE);
+ noise = (int)val; /* XXX check bounds? */
+
+ if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
+ struct bwi_rf *rf = &mac->mac_rf;
+
+ if (noise >= BWI_NRSSI_TBLSZ)
+ noise = BWI_NRSSI_TBLSZ - 1;
+
+ noise = ((31 - (int)rf->rf_nrssi_table[noise]) * -131) / 128;
+ noise -= 67;
+ } else {
+ noise = ((31 - noise) * -149) / 128;
+ noise -= 68;
+ }
+ return noise;
+}
+
+static int
+bwi_rf_calc_noise_bcm2053(struct bwi_mac *mac)
+{
+ uint16_t val;
+ int noise;
+
+ val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE);
+ noise = (int)val; /* XXX check bounds? */
+
+ noise = ((noise - 11) * 103) / 64;
+ noise -= 109;
+ return noise;
+}
+
+static int
+bwi_rf_calc_noise_bcm2060(struct bwi_mac *mac)
+{
+ /* XXX Dont know how to calc */
+ return (BWI_NOISE_FLOOR);
+}
+
static uint16_t
bwi_rf_lo_measure_11b(struct bwi_mac *mac)
{
@@ -2665,5 +2681,5 @@ bwi_rf_lo_update_11b(struct bwi_mac *mac)
}
RESTORE_PHY_REG(mac, ®s, 15);
- bwi_rf_workaround(mac, rf->rf_curchan);
+ bwi_rf_work_around(mac, rf->rf_curchan);
}
diff --git a/sys/dev/netif/bwi/bwirf.h b/sys/dev/netif/bwi/bwirf.h
index d926e37..af2ce17 100644
--- a/sys/dev/netif/bwi/bwirf.h
+++ b/sys/dev/netif/bwi/bwirf.h
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*
* $DragonFly: src/sys/dev/netif/bwi/bwirf.h,v 1.3 2007/10/03 04:53:19 sephe Exp $
+ * $FreeBSD$
*/
#ifndef _BWI_RF_H
@@ -95,6 +96,12 @@ bwi_rf_calc_rssi(struct bwi_mac *_mac, const struct bwi_rxbuf_hdr *_hdr)
return _mac->mac_rf.rf_calc_rssi(_mac, _hdr);
}
+static __inline int
+bwi_rf_calc_noise(struct bwi_mac *_mac)
+{
+ return _mac->mac_rf.rf_calc_noise(_mac);
+}
+
static __inline void
bwi_rf_lo_update(struct bwi_mac *_mac)
{
diff --git a/sys/dev/netif/bwi/device_if.h b/sys/dev/netif/bwi/device_if.h
new file mode 100644
index 0000000..2559ce4
--- /dev/null
+++ b/sys/dev/netif/bwi/device_if.h
@@ -0,0 +1,79 @@
+/*
+ * This file is produced automatically.
+ * Do not modify anything in here by hand.
+ *
+ * Created from source file
+ * @/kern/device_if.m
+ * with
+ * makeobjops.awk
+ *
+ * See the source file for legal information
+ */
+
+#ifndef _device_if_h_
+#define _device_if_h_
+
+extern struct kobjop_desc device_probe_desc;
+typedef int device_probe_t(device_t dev);
+static __inline int DEVICE_PROBE(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_probe);
+ return ((device_probe_t *) _m)(dev);
+}
+
+extern struct kobjop_desc device_identify_desc;
+typedef int device_identify_t(driver_t *driver, device_t parent);
+static __inline int DEVICE_IDENTIFY(driver_t *driver, device_t parent)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(driver->ops, device_identify);
+ return ((device_identify_t *) _m)(driver, parent);
+}
+
+extern struct kobjop_desc device_attach_desc;
+typedef int device_attach_t(device_t dev);
+static __inline int DEVICE_ATTACH(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_attach);
+ return ((device_attach_t *) _m)(dev);
+}
+
+extern struct kobjop_desc device_detach_desc;
+typedef int device_detach_t(device_t dev);
+static __inline int DEVICE_DETACH(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_detach);
+ return ((device_detach_t *) _m)(dev);
+}
+
+extern struct kobjop_desc device_shutdown_desc;
+typedef int device_shutdown_t(device_t dev);
+static __inline int DEVICE_SHUTDOWN(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_shutdown);
+ return ((device_shutdown_t *) _m)(dev);
+}
+
+extern struct kobjop_desc device_suspend_desc;
+typedef int device_suspend_t(device_t dev);
+static __inline int DEVICE_SUSPEND(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_suspend);
+ return ((device_suspend_t *) _m)(dev);
+}
+
+extern struct kobjop_desc device_resume_desc;
+typedef int device_resume_t(device_t dev);
+static __inline int DEVICE_RESUME(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, device_resume);
+ return ((device_resume_t *) _m)(dev);
+}
+
+#endif /* _device_if_h_ */
diff --git a/sys/dev/netif/bwi/if_bwi.c b/sys/dev/netif/bwi/if_bwi.c
index ef6bfb7..902fa01 100644
--- a/sys/dev/netif/bwi/if_bwi.c
+++ b/sys/dev/netif/bwi/if_bwi.c
@@ -31,7 +31,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/dev/netif/bwi/if_bwi.c,v 1.22 2008/05/18 08:10:03 sephe Exp $
+ * $DragonFly: src/sys/dev/netif/bwi/if_bwi.c,v 1.19 2008/02/15 11:15:38 sephe Exp $
*/
#include <sys/param.h>
@@ -50,6 +50,7 @@
#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_types.h>
#include <net/bpf.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
@@ -58,7 +59,9 @@
#include <netproto/802_11/ieee80211_radiotap.h>
#include <netproto/802_11/ieee80211_var.h>
-#include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
+#include <netproto/802_11/ieee80211_input.h>
+#include <netproto/802_11/ieee80211_regdomain.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
#include <bus/pci/pcireg.h>
#include <bus/pci/pcivar.h>
@@ -79,29 +82,44 @@ struct bwi_myaddr_bssid {
uint8_t bssid[IEEE80211_ADDR_LEN];
} __packed;
-static int bwi_probe(device_t);
-static int bwi_attach(device_t);
-static int bwi_detach(device_t);
-static int bwi_shutdown(device_t);
-
+static struct ieee80211vap *bwi_vap_create(struct ieee80211com *,
+ const char [IFNAMSIZ], int, int, int,
+ const uint8_t [IEEE80211_ADDR_LEN],
+ const uint8_t [IEEE80211_ADDR_LEN]);
+static void bwi_vap_delete(struct ieee80211vap *);
static void bwi_init(void *);
-static int bwi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
+static int bwi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *ucred);
static void bwi_start(struct ifnet *);
-static void bwi_watchdog(struct ifnet *);
-static int bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
+static void bwi_start_locked(struct ifnet *);
+static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
+ const struct ieee80211_bpf_params *);
+static void bwi_watchdog(void *);
+static void bwi_scan_start(struct ieee80211com *);
+static void bwi_set_channel(struct ieee80211com *);
+static void bwi_scan_end(struct ieee80211com *);
+static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void bwi_updateslot(struct ifnet *);
static int bwi_media_change(struct ifnet *);
-static void *bwi_ratectl_attach(struct ieee80211com *, u_int);
-static void bwi_next_scan(void *);
static void bwi_calibrate(void *);
-static void bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
+static int bwi_calc_rssi(struct bwi_softc *, const struct bwi_rxbuf_hdr *);
+static int bwi_calc_noise(struct bwi_softc *);
+static __inline uint8_t bwi_ofdm_plcp2rate(const uint32_t *);
+static __inline uint8_t bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *);
+static void bwi_rx_radiotap(struct bwi_softc *, struct mbuf *,
+ struct bwi_rxbuf_hdr *, const void *, int, int, int);
+
+static void bwi_restart(void *, int);
static void bwi_init_statechg(struct bwi_softc *, int);
-static int bwi_stop(struct bwi_softc *, int);
+static void bwi_stop(struct bwi_softc *, int);
+static void bwi_stop_locked(struct bwi_softc *, int);
static int bwi_newbuf(struct bwi_softc *, int, int);
static int bwi_encap(struct bwi_softc *, int, struct mbuf *,
- struct ieee80211_node **, int);
+ struct ieee80211_node *);
+static int bwi_encap_raw(struct bwi_softc *, int, struct mbuf *,
+ struct ieee80211_node *,
+ const struct ieee80211_bpf_params *);
static void bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t,
bus_addr_t, int, int);
@@ -133,16 +151,12 @@ static int bwi_rxeof64(struct bwi_softc *);
static void bwi_start_tx64(struct bwi_softc *, uint32_t, int);
static void bwi_txeof_status64(struct bwi_softc *);
-static void bwi_intr(void *);
static int bwi_rxeof(struct bwi_softc *, int);
static void _bwi_txeof(struct bwi_softc *, uint16_t, int, int);
static void bwi_txeof(struct bwi_softc *);
static void bwi_txeof_status(struct bwi_softc *, int);
static void bwi_enable_intrs(struct bwi_softc *, uint32_t);
static void bwi_disable_intrs(struct bwi_softc *, uint32_t);
-static int bwi_calc_rssi(struct bwi_softc *, const struct bwi_rxbuf_hdr *);
-static void bwi_rx_radiotap(struct bwi_softc *, struct mbuf *,
- struct bwi_rxbuf_hdr *, const void *, int, int);
static int bwi_dma_alloc(struct bwi_softc *);
static void bwi_dma_free(struct bwi_softc *);
@@ -166,7 +180,6 @@ static int bwi_get_pwron_delay(struct bwi_softc *sc);
static void bwi_set_addr_filter(struct bwi_softc *, uint16_t,
const uint8_t *);
static void bwi_set_bssid(struct bwi_softc *, const uint8_t *);
-static int bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *);
static void bwi_get_card_flags(struct bwi_softc *);
static void bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *);
@@ -188,73 +201,6 @@ static void bwi_led_blink_start(struct bwi_softc *, int, int);
static void bwi_led_blink_next(void *);
static void bwi_led_blink_end(void *);
-static const struct bwi_dev {
- uint16_t vid;
- uint16_t did;
- const char *desc;
-} bwi_devices[] = {
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4301,
- "Broadcom BCM4301 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4307,
- "Broadcom BCM4307 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4311,
- "Broadcom BCM4311 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4312,
- "Broadcom BCM4312 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_1,
- "Broadcom BCM4306 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_2,
- "Broadcom BCM4306 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_3,
- "Broadcom BCM4306 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4309,
- "Broadcom BCM4309 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4318,
- "Broadcom BCM4318 802.11 Wireless Lan" },
-
- { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4319,
- "Broadcom BCM4319 802.11 Wireless Lan" }
-};
-
-static device_method_t bwi_methods[] = {
- DEVMETHOD(device_probe, bwi_probe),
- DEVMETHOD(device_attach, bwi_attach),
- DEVMETHOD(device_detach, bwi_detach),
- DEVMETHOD(device_shutdown, bwi_shutdown),
-#if 0
- DEVMETHOD(device_suspend, bwi_suspend),
- DEVMETHOD(device_resume, bwi_resume),
-#endif
- { 0, 0 }
-};
-
-static driver_t bwi_driver = {
- "bwi",
- bwi_methods,
- sizeof(struct bwi_softc)
-};
-
-static devclass_t bwi_devclass;
-
-DRIVER_MODULE(bwi, pci, bwi_driver, bwi_devclass, 0, 0);
-DRIVER_MODULE(bwi, cardbus, bwi_driver, bwi_devclass, 0, 0);
-
-MODULE_DEPEND(bwi, wlan, 1, 1, 1);
-MODULE_DEPEND(bwi, wlan_ratectl_onoe, 1, 1, 1);
-#if 0
-MODULE_DEPEND(bwi, wlan_ratectl_amrr, 1, 1, 1);
-#endif
-MODULE_DEPEND(bwi, pci, 1, 1, 1);
-MODULE_DEPEND(bwi, cardbus, 1, 1, 1);
-
static const struct {
uint16_t did_min;
uint16_t did_max;
@@ -308,11 +254,15 @@ static const struct {
}
static const struct {
+#define PCI_VENDOR_COMPAQ 0x0e11
+#define PCI_VENDOR_LINKSYS 0x1737
uint16_t vid;
uint8_t led_act[BWI_LED_MAX];
} bwi_vendor_led_act[] = {
VENDOR_LED_ACT(COMPAQ),
VENDOR_LED_ACT(LINKSYS)
+#undef PCI_VENDOR_LINKSYS
+#undef PCI_VENDOR_COMPAQ
};
static const uint8_t bwi_default_led_act[BWI_LED_MAX] =
@@ -341,7 +291,7 @@ static const struct {
#ifdef BWI_DEBUG
#ifdef BWI_DEBUG_VERBOSE
-static uint32_t bwi_debug = BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_TXPOWER;
+static uint32_t bwi_debug = BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_TXPOWER;
#else
static uint32_t bwi_debug;
#endif
@@ -350,11 +300,6 @@ TUNABLE_INT("hw.bwi.debug", (int *)&bwi_debug);
static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN];
-static const struct ieee80211_rateset bwi_rateset_11b =
- { 4, { 2, 4, 11, 22 } };
-static const struct ieee80211_rateset bwi_rateset_11g =
- { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
-
uint16_t
bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs)
{
@@ -390,262 +335,41 @@ bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
desc->ctrl = htole32(ctrl);
}
-/* XXX does not belong here */
-uint8_t
-bwi_rate2plcp(uint8_t rate)
-{
- rate &= IEEE80211_RATE_VAL;
-
- switch (rate) {
- case 2: return 0xa;
- case 4: return 0x14;
- case 11: return 0x37;
- case 22: return 0x6e;
- case 44: return 0xdc;
-
- case 12: return 0xb;
- case 18: return 0xf;
- case 24: return 0xa;
- case 36: return 0xe;
- case 48: return 0x9;
- case 72: return 0xd;
- case 96: return 0x8;
- case 108: return 0xc;
-
- default:
- panic("unsupported rate %u\n", rate);
- }
-}
-
-/* XXX does not belong here */
-#define IEEE80211_OFDM_PLCP_RATE_MASK __BITS(3, 0)
-#define IEEE80211_OFDM_PLCP_LEN_MASK __BITS(16, 5)
-
-static __inline void
-bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate)
-{
- uint32_t plcp;
-
- plcp = __SHIFTIN(bwi_rate2plcp(rate), IEEE80211_OFDM_PLCP_RATE_MASK) |
- __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK);
- *plcp0 = htole32(plcp);
-}
-
-/* XXX does not belong here */
-struct ieee80211_ds_plcp_hdr {
- uint8_t i_signal;
- uint8_t i_service;
- uint16_t i_length;
- uint16_t i_crc;
-} __packed;
-
-#define IEEE80211_DS_PLCP_SERVICE_LOCKED 0x04
-#define IEEE80211_DS_PLCL_SERVICE_PBCC 0x08
-#define IEEE80211_DS_PLCP_SERVICE_LENEXT5 0x20
-#define IEEE80211_DS_PLCP_SERVICE_LENEXT6 0x40
-#define IEEE80211_DS_PLCP_SERVICE_LENEXT7 0x80
-
-static __inline void
-bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len,
- uint8_t rate)
-{
- int len, service, pkt_bitlen;
-
- pkt_bitlen = pkt_len * NBBY;
- len = howmany(pkt_bitlen * 2, rate);
-
- service = IEEE80211_DS_PLCP_SERVICE_LOCKED;
- if (rate == (11 * 2)) {
- int pkt_bitlen1;
-
- /*
- * PLCP service field needs to be adjusted,
- * if TX rate is 11Mbytes/s
- */
- pkt_bitlen1 = len * 11;
- if (pkt_bitlen1 - pkt_bitlen >= NBBY)
- service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7;
- }
-
- plcp->i_signal = bwi_rate2plcp(rate);
- plcp->i_service = service;
- plcp->i_length = htole16(len);
- /* NOTE: do NOT touch i_crc */
-}
-
-static __inline void
-bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate)
-{
- enum ieee80211_modtype modtype;
-
- /*
- * Assume caller has zeroed 'plcp'
- */
-
- modtype = ieee80211_rate2modtype(rate);
- if (modtype == IEEE80211_MODTYPE_OFDM)
- bwi_ofdm_plcp_header(plcp, pkt_len, rate);
- else if (modtype == IEEE80211_MODTYPE_DS)
- bwi_ds_plcp_header(plcp, pkt_len, rate);
- else
- panic("unsupport modulation type %u\n", modtype);
-}
-
-static __inline uint8_t
-bwi_ofdm_plcp2rate(const uint32_t *plcp0)
-{
- uint32_t plcp;
- uint8_t plcp_rate;
-
- plcp = le32toh(*plcp0);
- plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK);
- return ieee80211_plcp2rate(plcp_rate, 1);
-}
-
-static __inline uint8_t
-bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr)
-{
- return ieee80211_plcp2rate(hdr->i_signal, 0);
-}
-
-static int
-bwi_probe(device_t dev)
-{
- const struct bwi_dev *b;
- uint16_t did, vid;
-
- did = pci_get_device(dev);
- vid = pci_get_vendor(dev);
-
- for (b = bwi_devices; b->desc != NULL; ++b) {
- if (b->did == did && b->vid == vid) {
- device_set_desc(dev, b->desc);
- return 0;
- }
- }
- return ENXIO;
-}
-
-static int
-bwi_attach(device_t dev)
+int
+bwi_attach(struct bwi_softc *sc)
{
- struct bwi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
+ struct ieee80211com *ic;
+ device_t dev = sc->sc_dev;
+ struct ifnet *ifp;
struct bwi_mac *mac;
struct bwi_phy *phy;
int i, error;
+ uint8_t bands;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+
+ BWI_LOCK_INIT(sc);
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- sc->sc_dev = dev;
+ /*
+ * Initialize taskq and various tasks
+ */
+ sc->sc_tq = taskqueue_create("bwi_taskq", M_NOWAIT | M_ZERO,
+ taskqueue_thread_enqueue, &sc->sc_tq);
+ taskqueue_start_threads(&sc->sc_tq, 1, TDPRI_KERN_DAEMON /* PI_NET */, -1, "%s taskq",
+ device_get_nameunit(dev));
+ TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc);
/*
* Initialize sysctl variables
*/
sc->sc_fw_version = BWI_FW_VERSION3;
- sc->sc_dwell_time = 200;
sc->sc_led_idle = (2350 * hz) / 1000;
sc->sc_led_blink = 1;
sc->sc_txpwr_calib = 1;
#ifdef BWI_DEBUG
sc->sc_debug = bwi_debug;
#endif
-
- callout_init(&sc->sc_scan_ch);
- callout_init(&sc->sc_calib_ch);
-
-#ifndef BURN_BRIDGES
- if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
- uint32_t irq, mem;
-
- /* XXX Save more PCIR */
- irq = pci_read_config(dev, PCIR_INTLINE, 4);
- mem = pci_read_config(dev, BWI_PCIR_BAR, 4);
-
- device_printf(dev, "chip is in D%d power mode "
- "-- setting to D0\n", pci_get_powerstate(dev));
-
- pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-
- pci_write_config(dev, PCIR_INTLINE, irq, 4);
- pci_write_config(dev, BWI_PCIR_BAR, mem, 4);
- }
-#endif /* !BURN_BRIDGE */
-
- pci_enable_busmaster(dev);
-
- /* Get more PCI information */
- sc->sc_pci_revid = pci_get_revid(dev);
- sc->sc_pci_subvid = pci_get_subvendor(dev);
- sc->sc_pci_subdid = pci_get_subdevice(dev);
-
- /*
- * Allocate IO memory
- */
- sc->sc_mem_rid = BWI_PCIR_BAR;
- sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->sc_mem_rid, RF_ACTIVE);
- if (sc->sc_mem_res == NULL) {
- device_printf(dev, "can't allocate IO memory\n");
- return ENXIO;
- }
- sc->sc_mem_bt = rman_get_bustag(sc->sc_mem_res);
- sc->sc_mem_bh = rman_get_bushandle(sc->sc_mem_res);
-
- /*
- * Allocate IRQ
- */
- sc->sc_irq_rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &sc->sc_irq_rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(dev, "can't allocate irq\n");
- error = ENXIO;
- goto fail;
- }
-
- /*
- * Create sysctl tree
- */
- sysctl_ctx_init(&sc->sc_sysctl_ctx);
- sc->sc_sysctl_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_hw),
- OID_AUTO,
- device_get_nameunit(dev),
- CTLFLAG_RD, 0, "");
- if (sc->sc_sysctl_tree == NULL) {
- device_printf(dev, "can't add sysctl node\n");
- error = ENXIO;
- goto fail;
- }
-
- SYSCTL_ADD_UINT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "dwell_time", CTLFLAG_RW, &sc->sc_dwell_time, 0,
- "Channel dwell time during scan (msec)");
- SYSCTL_ADD_UINT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "fw_version", CTLFLAG_RD, &sc->sc_fw_version, 0,
- "Firmware version");
- SYSCTL_ADD_UINT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "led_idle", CTLFLAG_RW, &sc->sc_led_idle, 0,
- "# ticks before LED enters idle state");
- SYSCTL_ADD_INT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "led_blink", CTLFLAG_RW, &sc->sc_led_blink, 0,
- "Allow LED to blink");
- SYSCTL_ADD_INT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "txpwr_calib", CTLFLAG_RW, &sc->sc_txpwr_calib, 0,
- "Enable software TX power calibration");
-#ifdef BWI_DEBUG
- SYSCTL_ADD_UINT(&sc->sc_sysctl_ctx,
- SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO,
- "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
-#endif
-
bwi_power_on(sc, 1);
error = bwi_bbp_attach(sc);
@@ -708,173 +432,230 @@ bwi_attach(device_t dev)
if (error)
goto fail;
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ error = ENOSPC;
+ goto fail;
+ }
+ ic = ifp->if_l2com;
+
+ /* set these up early for if_printf use */
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = bwi_init;
ifp->if_ioctl = bwi_ioctl;
ifp->if_start = bwi_start;
- ifp->if_watchdog = bwi_watchdog;
- ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
+ ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifq_set_ready(&ifp->if_snd);
-
- /* Get locale */
- sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),
- BWI_SPROM_CARD_INFO_LOCALE);
- DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale);
+ //callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0);
/*
* Setup ratesets, phytype, channels and get MAC address
*/
+ bands = 0;
if (phy->phy_mode == IEEE80211_MODE_11B ||
phy->phy_mode == IEEE80211_MODE_11G) {
- uint16_t chan_flags;
-
- ic->ic_sup_rates[IEEE80211_MODE_11B] = bwi_rateset_11b;
-
+ setbit(&bands, IEEE80211_MODE_11B);
if (phy->phy_mode == IEEE80211_MODE_11B) {
- chan_flags = IEEE80211_CHAN_B;
ic->ic_phytype = IEEE80211_T_DS;
} else {
- chan_flags = IEEE80211_CHAN_CCK |
- IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_DYN |
- IEEE80211_CHAN_2GHZ;
ic->ic_phytype = IEEE80211_T_OFDM;
- ic->ic_sup_rates[IEEE80211_MODE_11G] =
- bwi_rateset_11g;
+ setbit(&bands, IEEE80211_MODE_11G);
}
- /* XXX depend on locale */
- for (i = 1; i <= 14; ++i) {
- ic->ic_channels[i].ic_freq =
- ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
- ic->ic_channels[i].ic_flags = chan_flags;
- }
-
- bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr);
- if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
- bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr);
- if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
- device_printf(dev, "invalid MAC address: "
- "%6D\n", ic->ic_myaddr, ":");
+ bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, macaddr);
+ if (IEEE80211_IS_MULTICAST(macaddr)) {
+ bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, macaddr);
+ if (IEEE80211_IS_MULTICAST(macaddr)) {
+ device_printf(dev,
+ "invalid MAC address: %6D\n",
+ macaddr, ":");
}
}
} else if (phy->phy_mode == IEEE80211_MODE_11A) {
/* TODO:11A */
+ setbit(&bands, IEEE80211_MODE_11A);
error = ENXIO;
goto fail;
} else {
panic("unknown phymode %d\n", phy->phy_mode);
}
- ic->ic_caps = IEEE80211_C_SHSLOT |
+ /* Get locale */
+ sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),
+ BWI_SPROM_CARD_INFO_LOCALE);
+ DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale);
+ /* XXX use locale */
+ ieee80211_init_channels(ic, NULL, &bands);
+
+ ic->ic_ifp = ifp;
+ ic->ic_caps = IEEE80211_C_STA |
+ IEEE80211_C_SHSLOT |
IEEE80211_C_SHPREAMBLE |
IEEE80211_C_WPA |
+ IEEE80211_C_BGSCAN |
IEEE80211_C_MONITOR;
- ic->ic_state = IEEE80211_S_INIT;
ic->ic_opmode = IEEE80211_M_STA;
+ ieee80211_ifattach(ic, macaddr);
- IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param);
- ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE;
- ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE;
- ic->ic_ratectl.rc_st_attach = bwi_ratectl_attach;
+ ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
+ /* override default methods */
+ ic->ic_vap_create = bwi_vap_create;
+ ic->ic_vap_delete = bwi_vap_delete;
+ ic->ic_raw_xmit = bwi_raw_xmit;
ic->ic_updateslot = bwi_updateslot;
+ ic->ic_scan_start = bwi_scan_start;
+ ic->ic_scan_end = bwi_scan_end;
+ ic->ic_set_channel = bwi_set_channel;
- ieee80211_ifattach(ic);
-
- ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
- ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
-
- sc->sc_newstate = ic->ic_newstate;
- ic->ic_newstate = bwi_newstate;
+ sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
- ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status);
+ ieee80211_radiotap_attach(ic,
+ &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
+ BWI_TX_RADIOTAP_PRESENT,
+ &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
+ BWI_RX_RADIOTAP_PRESENT);
/*
- * Attach radio tap
+ * Add sysctl nodes
*/
- bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO,
- sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
- &sc->sc_drvbpf);
-
- sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(uint32_t));
- sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
- sc->sc_tx_th.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT);
-
- sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(uint32_t));
- sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
- sc->sc_rx_th.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT);
-
- error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, bwi_intr, sc,
- &sc->sc_irq_handle, ifp->if_serializer);
- if (error) {
- device_printf(dev, "can't setup intr\n");
- bpfdetach(ifp);
- ieee80211_ifdetach(ic);
- goto fail;
- }
-
- ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->sc_irq_res));
- KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
-
+ ctx = &sc->sc_sysctl_ctx;
+ sysctl_ctx_init(ctx);
+ tree = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
+ OID_AUTO,
+ device_get_nameunit(sc->sc_dev),
+ CTLFLAG_RD, 0, "");
+ if (tree == NULL) {
+ device_printf(sc->sc_dev, "can't add sysctl node\n");
+ goto fail;
+ }
+
+ sc->sc_sysctl_tree = tree;
+
+ SYSCTL_ADD_UINT(ctx,//device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(tree), OID_AUTO,
+ "fw_version", CTLFLAG_RD, &sc->sc_fw_version, 0,
+ "Firmware version");
+ SYSCTL_ADD_UINT(ctx,//device_get_sysctl_ctx(dev),(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(tree), OID_AUTO,
+ "led_idle", CTLFLAG_RW, &sc->sc_led_idle, 0,
+ "# ticks before LED enters idle state");
+ SYSCTL_ADD_INT(ctx,//device_get_sysctl_ctx(dev),(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(tree), OID_AUTO,
+ "led_blink", CTLFLAG_RW, &sc->sc_led_blink, 0,
+ "Allow LED to blink");
+ SYSCTL_ADD_INT(ctx,//device_get_sysctl_ctx(dev),(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(tree), OID_AUTO,
+ "txpwr_calib", CTLFLAG_RW, &sc->sc_txpwr_calib, 0,
+ "Enable software TX power calibration");
+#ifdef BWI_DEBUG
+ SYSCTL_ADD_UINT(ctx,//device_get_sysctl_ctx(dev),(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(tree), OID_AUTO,
+ "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
+#endif
if (bootverbose)
ieee80211_announce(ic);
- return 0;
+ return (0);
fail:
- bwi_detach(dev);
- return error;
+ BWI_LOCK_DESTROY(sc);
+ return (error);
}
-static int
-bwi_detach(device_t dev)
+int
+bwi_detach(struct bwi_softc *sc)
{
- struct bwi_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ int i;
- if (device_is_attached(dev)) {
- struct ifnet *ifp = &sc->sc_ic.ic_if;
- int i;
+ bwi_stop(sc, 1);
+ callout_stop(&sc->sc_led_blink_ch);
+ callout_stop(&sc->sc_calib_ch);
+ callout_stop(&sc->sc_watchdog_timer);
+ ieee80211_ifdetach(ic);
- lwkt_serialize_enter(ifp->if_serializer);
- bwi_stop(sc, 1);
- bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
- lwkt_serialize_exit(ifp->if_serializer);
+ for (i = 0; i < sc->sc_nmac; ++i)
+ bwi_mac_detach(&sc->sc_mac[i]);
+ if (sc->sc_sysctl_tree != NULL)
+ sysctl_ctx_free(&sc->sc_sysctl_ctx);
+ bwi_dma_free(sc);
+ if_free(ifp);
+ taskqueue_free(sc->sc_tq);
- bpfdetach(ifp);
- ieee80211_ifdetach(&sc->sc_ic);
+ BWI_LOCK_DESTROY(sc);
- for (i = 0; i < sc->sc_nmac; ++i)
- bwi_mac_detach(&sc->sc_mac[i]);
- }
+ return (0);
+}
- if (sc->sc_sysctl_tree != NULL)
- sysctl_ctx_free(&sc->sc_sysctl_ctx);
+static struct ieee80211vap *
+bwi_vap_create(struct ieee80211com *ic,
+ const char name[IFNAMSIZ], int unit, int opmode, int flags,
+ const uint8_t bssid[IEEE80211_ADDR_LEN],
+ const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+ struct bwi_vap *bvp;
+ struct ieee80211vap *vap;
- if (sc->sc_irq_res != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid,
- sc->sc_irq_res);
- }
+ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
+ return NULL;
+ bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap),
+ M_80211_VAP, M_WAITOK | M_ZERO);
+ if (bvp == NULL)
+ return NULL;
+ vap = &bvp->bv_vap;
+ /* enable s/w bmiss handling for sta mode */
+ ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+
+ /* override default methods */
+ bvp->bv_newstate = vap->iv_newstate;
+ vap->iv_newstate = bwi_newstate;
+#if 0
+ vap->iv_update_beacon = bwi_beacon_update;
+#endif
+ ieee80211_ratectl_init(vap);
- if (sc->sc_mem_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
- sc->sc_mem_res);
- }
+ /* complete setup */
+ ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
+ ic->ic_opmode = opmode;
+ return vap;
+}
- bwi_dma_free(sc);
+static void
+bwi_vap_delete(struct ieee80211vap *vap)
+{
+ struct bwi_vap *bvp = BWI_VAP(vap);
- return 0;
+ ieee80211_ratectl_deinit(vap);
+ ieee80211_vap_detach(vap);
+ free(bvp, M_80211_VAP);
}
-static int
-bwi_shutdown(device_t dev)
+void
+bwi_suspend(struct bwi_softc *sc)
+{
+ bwi_stop(sc, 1);
+}
+
+void
+bwi_resume(struct bwi_softc *sc)
{
- struct bwi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ if (ifp->if_flags & IFF_UP)
+ bwi_init(sc);
+}
- lwkt_serialize_enter(ifp->if_serializer);
+int
+bwi_shutdown(struct bwi_softc *sc)
+{
bwi_stop(sc, 1);
- lwkt_serialize_exit(ifp->if_serializer);
return 0;
}
@@ -953,7 +734,7 @@ bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw,
if (sc->sc_cur_regwin != rw) {
error = bwi_regwin_select(sc, rw->rw_id);
if (error) {
- if_printf(&sc->sc_ic.ic_if, "can't select regwin %d\n",
+ device_printf(sc->sc_dev, "can't select regwin %d\n",
rw->rw_id);
return error;
}
@@ -1030,23 +811,20 @@ bwi_bbp_attach(struct bwi_softc *sc)
sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY);
} else {
- uint16_t did = pci_get_device(sc->sc_dev);
- uint8_t revid = pci_get_revid(sc->sc_dev);
-
for (i = 0; i < N(bwi_bbpid_map); ++i) {
- if (did >= bwi_bbpid_map[i].did_min &&
- did <= bwi_bbpid_map[i].did_max) {
+ if (sc->sc_pci_did >= bwi_bbpid_map[i].did_min &&
+ sc->sc_pci_did <= bwi_bbpid_map[i].did_max) {
bbp_id = bwi_bbpid_map[i].bbp_id;
break;
}
}
if (bbp_id == 0) {
device_printf(sc->sc_dev, "no BBP id for device id "
- "0x%04x\n", did);
+ "0x%04x\n", sc->sc_pci_did);
return ENXIO;
}
- info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK) |
+ info = __SHIFTIN(sc->sc_pci_revid, BWI_INFO_BBPREV_MASK) |
__SHIFTIN(0, BWI_INFO_BBPPKG_MASK);
}
@@ -1125,7 +903,7 @@ bwi_bbp_attach(struct bwi_softc *sc)
device_printf(sc->sc_dev, "no MAC was found\n");
return ENXIO;
}
- KKASSERT(sc->sc_nmac > 0);
+ KASSERT(sc->sc_nmac > 0, ("no mac's"));
/* Bus regwin must exist */
if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
@@ -1150,7 +928,7 @@ bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac)
int error;
bus = &sc->sc_bus_regwin;
- KKASSERT(sc->sc_cur_regwin == &mac->mac_regwin);
+ KASSERT(sc->sc_cur_regwin == &mac->mac_regwin, ("not cur regwin"));
/*
* Tell bus to generate requested interrupts
@@ -1243,16 +1021,25 @@ back:
static void
bwi_get_card_flags(struct bwi_softc *sc)
{
+#define PCI_VENDOR_APPLE 0x106b
+#define PCI_VENDOR_DELL 0x1028
sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS);
if (sc->sc_card_flags == 0xffff)
sc->sc_card_flags = 0;
+ if (sc->sc_pci_subvid == PCI_VENDOR_DELL &&
+ sc->sc_bbp_id == BWI_BBPID_BCM4301 &&
+ sc->sc_pci_revid == 0x74)
+ sc->sc_card_flags |= BWI_CARD_F_BT_COEXIST;
+
if (sc->sc_pci_subvid == PCI_VENDOR_APPLE &&
sc->sc_pci_subdid == 0x4e && /* XXX */
sc->sc_pci_revid > 0x40)
sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9;
DPRINTF(sc, BWI_DBG_ATTACH, "card flags 0x%04x\n", sc->sc_card_flags);
+#undef PCI_VENDOR_DELL
+#undef PCI_VENDOR_APPLE
}
static void
@@ -1277,9 +1064,9 @@ bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq)
bzero(freq, sizeof(*freq));
com = &sc->sc_com_regwin;
- KKASSERT(BWI_REGWIN_EXIST(com));
- KKASSERT(sc->sc_cur_regwin == com);
- KKASSERT(sc->sc_cap & BWI_CAP_CLKMODE);
+ KASSERT(BWI_REGWIN_EXIST(com), ("regwin does not exist"));
+ KASSERT(sc->sc_cur_regwin == com, ("wrong regwin"));
+ KASSERT(sc->sc_cap & BWI_CAP_CLKMODE, ("wrong clock mode"));
/*
* Calculate clock frequency
@@ -1315,8 +1102,8 @@ bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq)
div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV) + 1) << 2;
}
- KKASSERT(src >= 0 && src < BWI_CLKSRC_MAX);
- KKASSERT(div != 0);
+ KASSERT(src >= 0 && src < BWI_CLKSRC_MAX, ("bad src %d", src));
+ KASSERT(div != 0, ("div zero"));
DPRINTF(sc, BWI_DBG_ATTACH, "clksrc %s\n",
src == BWI_CLKSRC_PCI ? "PCI" :
@@ -1427,24 +1214,26 @@ bwi_set_clock_delay(struct bwi_softc *sc)
static void
bwi_init(void *xsc)
{
- bwi_init_statechg(xsc, 1);
+ struct bwi_softc *sc = xsc;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ BWI_LOCK(sc);
+ bwi_init_statechg(sc, 1);
+ BWI_UNLOCK(sc);
+
+ if (ifp->if_flags & IFF_RUNNING)
+ ieee80211_start_all(ic); /* start all vap's */
}
static void
bwi_init_statechg(struct bwi_softc *sc, int statechg)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int error;
- ASSERT_SERIALIZED(ifp->if_serializer);
-
- error = bwi_stop(sc, statechg);
- if (error) {
- if_printf(ifp, "can't stop\n");
- return;
- }
+ bwi_stop_locked(sc, statechg);
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
@@ -1452,19 +1241,21 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
mac = &sc->sc_mac[0];
error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
- if (error)
- goto back;
-
+ if (error) {
+ if_printf(ifp, "%s: error %d on regwin switch\n",
+ __func__, error);
+ goto bad;
+ }
error = bwi_mac_init(mac);
- if (error)
- goto back;
+ if (error) {
+ if_printf(ifp, "%s: error %d on MAC init\n", __func__, error);
+ goto bad;
+ }
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
-
- bcopy(IF_LLADDR(ifp), ic->ic_myaddr, sizeof(ic->ic_myaddr));
bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */
- bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, ic->ic_myaddr);
+ bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, IF_LLADDR(ifp));
bwi_mac_reset_hwkeys(mac);
@@ -1482,7 +1273,7 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
CSR_READ_4(sc, BWI_TXSTATUS1);
}
if (i == NRETRY)
- if_printf(ifp, "can't drain TX status\n");
+ if_printf(ifp, "%s: can't drain TX status\n", __func__);
#undef NRETRY
}
@@ -1491,49 +1282,44 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
/* Start MAC */
error = bwi_mac_start(mac);
- if (error)
- goto back;
+ if (error) {
+ if_printf(ifp, "%s: error %d starting MAC\n", __func__, error);
+ goto bad;
+ }
- /* Enable intrs */
- bwi_enable_intrs(sc, BWI_INIT_INTRS);
+ /* Clear stop flag before enabling interrupt */
+ sc->sc_flags &= ~BWI_F_STOP;
ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
+ callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
- if (statechg) {
- if (ic->ic_opmode != IEEE80211_M_MONITOR) {
- if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
- } else {
- ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
- }
- } else {
- ieee80211_new_state(ic, ic->ic_state, -1);
- }
-back:
- if (error)
- bwi_stop(sc, 1);
- else
- ifp->if_start(ifp);
+ /* Enable intrs */
+ bwi_enable_intrs(sc, BWI_INIT_INTRS);
+ return;
+bad:
+ bwi_stop_locked(sc, 1);
}
static int
-bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req, struct ucred *cr)
+bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *ucred)
{
+#define IS_RUNNING(ifp) \
+ ((ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
struct bwi_softc *sc = ifp->if_softc;
- int error = 0;
-
- ASSERT_SERIALIZED(ifp->if_serializer);
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0, startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
- if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
- (IFF_UP | IFF_RUNNING)) {
+ BWI_LOCK(sc);
+ if (IS_RUNNING(ifp)) {
struct bwi_mac *mac;
int promisc = -1;
- KKASSERT(sc->sc_cur_regwin->rw_type ==
- BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d",
+ sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
if ((ifp->if_flags & IFF_PROMISC) &&
@@ -1551,105 +1337,69 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req, struct ucred *cr)
}
if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- bwi_init(sc);
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ bwi_init_statechg(sc, 1);
+ startall = 1;
+ }
} else {
if (ifp->if_flags & IFF_RUNNING)
- bwi_stop(sc, 1);
+ bwi_stop_locked(sc, 1);
}
+ BWI_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
+ break;
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ case SIOCGIFADDR:
+ error = ether_ioctl(ifp, cmd, data);
break;
default:
- error = ieee80211_ioctl(&sc->sc_ic, cmd, req, cr);
+ error = EINVAL;
break;
}
-
- if (error == ENETRESET) {
- if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
- (IFF_UP | IFF_RUNNING))
- bwi_init(sc);
- error = 0;
- }
return error;
+#undef IS_RUNNING
}
static void
bwi_start(struct ifnet *ifp)
{
struct bwi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = &sc->sc_ic;
+
+ BWI_LOCK(sc);
+ bwi_start_locked(ifp);
+ BWI_UNLOCK(sc);
+}
+
+static void
+bwi_start_locked(struct ifnet *ifp)
+{
+ struct bwi_softc *sc = ifp->if_softc;
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+ struct ieee80211_key *k;
+ struct mbuf *m;
int trans, idx;
- ASSERT_SERIALIZED(ifp->if_serializer);
-
- if ((ifp->if_flags & IFF_OACTIVE) ||
- (ifp->if_flags & IFF_RUNNING) == 0)
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
return;
trans = 0;
idx = tbd->tbd_idx;
while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- struct mbuf *m;
- int mgt_pkt = 0;
-
- if (!IF_QEMPTY(&ic->ic_mgtq)) {
- IF_DEQUEUE(&ic->ic_mgtq, m);
-
- ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
- m->m_pkthdr.rcvif = NULL;
-
- mgt_pkt = 1;
- } else if (!ifq_is_empty(&ifp->if_snd)) {
- struct ether_header *eh;
-
- if (ic->ic_state != IEEE80211_S_RUN) {
- ifq_purge(&ifp->if_snd);
- break;
- }
-
- m = ifq_dequeue(&ifp->if_snd, NULL);
- if (m == NULL)
- break;
-
- if (m->m_len < sizeof(*eh)) {
- m = m_pullup(m, sizeof(*eh));
- if (m == NULL) {
- ifp->if_oerrors++;
- continue;
- }
- }
- eh = mtod(m, struct ether_header *);
-
- ni = ieee80211_find_txnode(ic, eh->ether_dhost);
- if (ni == NULL) {
- m_freem(m);
- ifp->if_oerrors++;
- continue;
- }
-
- /* TODO: PS */
-
- BPF_MTAP(ifp, m);
-
- m = ieee80211_encap(ic, m, ni);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
- } else {
+ ifq_dequeue(&ifp->if_snd, m); /* XXX: LOCK */
+ if (m == NULL)
break;
- }
-
- if (ic->ic_rawbpf != NULL)
- bpf_mtap(ic->ic_rawbpf, m);
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
wh = mtod(m, struct ieee80211_frame *);
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
- if (ieee80211_crypto_encap(ic, ni, m) == NULL) {
+ k = ieee80211_crypto_encap(ni, m);
+ if (k == NULL) {
ieee80211_free_node(ni);
m_freem(m);
ifp->if_oerrors++;
@@ -1658,7 +1408,7 @@ bwi_start(struct ifnet *ifp)
}
wh = NULL; /* Catch any invalid use */
- if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) {
+ if (bwi_encap(sc, idx, m, ni) != 0) {
/* 'm' is freed in bwi_encap() if we reach here */
if (ni != NULL)
ieee80211_free_node(ni);
@@ -1670,6 +1420,8 @@ bwi_start(struct ifnet *ifp)
tbd->tbd_used++;
idx = (idx + 1) % BWI_TX_NDESC;
+ ifp->if_opackets++;
+
if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
ifp->if_flags |= IFF_OACTIVE;
break;
@@ -1679,50 +1431,98 @@ bwi_start(struct ifnet *ifp)
if (trans)
sc->sc_tx_timer = 5;
- ifp->if_timer = 1;
}
-static void
-bwi_watchdog(struct ifnet *ifp)
+static int
+bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
+ const struct ieee80211_bpf_params *params)
{
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = ic->ic_ifp;
struct bwi_softc *sc = ifp->if_softc;
+ /* XXX wme? */
+ struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
+ int idx, error;
- ASSERT_SERIALIZED(ifp->if_serializer);
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ ieee80211_free_node(ni);
+ m_freem(m);
+ return ENETDOWN;
+ }
- ifp->if_timer = 0;
+ BWI_LOCK(sc);
+ idx = tbd->tbd_idx;
+ KASSERT(tbd->tbd_buf[idx].tb_mbuf == NULL, ("slot %d not empty", idx));
+ if (params == NULL) {
+ /*
+ * Legacy path; interpret frame contents to decide
+ * precisely how to send the frame.
+ */
+ error = bwi_encap(sc, idx, m, ni);
+ } else {
+ /*
+ * Caller supplied explicit parameters to use in
+ * sending the frame.
+ */
+ error = bwi_encap_raw(sc, idx, m, ni, params);
+ }
+ if (error == 0) {
+ ifp->if_opackets++;
+ if (++tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC)
+ ifp->if_flags |= IFF_OACTIVE;
+ tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC;
+ sc->sc_tx_timer = 5;
+ } else {
+ /* NB: m is reclaimed on encap failure */
+ ieee80211_free_node(ni);
+ ifp->if_oerrors++;
+ }
+ BWI_UNLOCK(sc);
+ return error;
+}
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- return;
+static void
+bwi_watchdog(void *arg)
+{
+ struct bwi_softc *sc;
+ struct ifnet *ifp;
- if (sc->sc_tx_timer) {
- if (--sc->sc_tx_timer == 0) {
- if_printf(ifp, "watchdog timeout\n");
- ifp->if_oerrors++;
- /* TODO */
- } else {
- ifp->if_timer = 1;
- }
+ sc = arg;
+ ifp = sc->sc_ifp;
+ BWI_ASSERT_LOCKED(sc);
+ if (sc->sc_tx_timer != 0 && --sc->sc_tx_timer == 0) {
+ if_printf(ifp, "watchdog timeout\n");
+ ifp->if_oerrors++;
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
}
- ieee80211_watchdog(&sc->sc_ic);
+ callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
}
-static int
-bwi_stop(struct bwi_softc *sc, int state_chg)
+static void
+bwi_stop(struct bwi_softc *sc, int statechg)
+{
+ BWI_LOCK(sc);
+ bwi_stop_locked(sc, statechg);
+ BWI_UNLOCK(sc);
+}
+
+static void
+bwi_stop_locked(struct bwi_softc *sc, int statechg)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int i, error, pwr_off = 0;
- ASSERT_SERIALIZED(ifp->if_serializer);
+ BWI_ASSERT_LOCKED(sc);
- if (state_chg)
- ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
- else
- bwi_newstate_begin(sc, IEEE80211_S_INIT);
+ callout_stop(&sc->sc_calib_ch);
+ callout_stop(&sc->sc_led_blink_ch);
+ sc->sc_led_blinking = 0;
+ sc->sc_flags |= BWI_F_STOP;
if (ifp->if_flags & IFF_RUNNING) {
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
bwi_disable_intrs(sc, BWI_ALL_INTRS);
@@ -1751,40 +1551,46 @@ bwi_stop(struct bwi_softc *sc, int state_chg)
bwi_bbp_power_off(sc);
sc->sc_tx_timer = 0;
- ifp->if_timer = 0;
+ callout_stop(&sc->sc_watchdog_timer);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
- return 0;
}
-static void
+void
bwi_intr(void *xsc)
{
struct bwi_softc *sc = xsc;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
uint32_t intr_status;
uint32_t txrx_intr_status[BWI_TXRX_NRING];
int i, txrx_error, tx = 0, rx_data = -1;
- ASSERT_SERIALIZED(ifp->if_serializer);
+ BWI_LOCK(sc);
- if ((ifp->if_flags & IFF_RUNNING) == 0)
+ if ((ifp->if_flags & IFF_RUNNING) == 0 ||
+ (sc->sc_flags & BWI_F_STOP)) {
+ BWI_UNLOCK(sc);
return;
-
+ }
/*
* Get interrupt status
*/
intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
- if (intr_status == 0xffffffff) /* Not for us */
+ if (intr_status == 0xffffffff) { /* Not for us */
+ BWI_UNLOCK(sc);
return;
+ }
DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status);
intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK);
- if (intr_status == 0) /* Nothing is interesting */
+ if (intr_status == 0) { /* Nothing is interesting */
+ BWI_UNLOCK(sc);
return;
+ }
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
txrx_error = 0;
@@ -1804,8 +1610,9 @@ bwi_intr(void *xsc)
i, txrx_intr_status[i]);
if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
- if_printf(ifp, "intr fatal TX/RX (%d) error 0x%08x\n",
- i, txrx_intr_status[i]);
+ if_printf(ifp,
+ "%s: intr fatal TX/RX (%d) error 0x%08x\n",
+ __func__, i, txrx_intr_status[i]);
txrx_error = 1;
}
}
@@ -1822,11 +1629,28 @@ bwi_intr(void *xsc)
/* Disable all interrupts */
bwi_disable_intrs(sc, BWI_ALL_INTRS);
+ /*
+ * http://bcm-specs.sipsolutions.net/Interrupts
+ * Says for this bit (0x800):
+ * "Fatal Error
+ *
+ * We got this one while testing things when by accident the
+ * template ram wasn't set to big endian when it should have
+ * been after writing the initial values. It keeps on being
+ * triggered, the only way to stop it seems to shut down the
+ * chip."
+ *
+ * Suggesting that we should never get it and if we do we're not
+ * feeding TX packets into the MAC correctly if we do... Apparently,
+ * it is valid only on mac version 5 and higher, but I couldn't
+ * find a reference for that... Since I see them from time to time
+ * on my card, this suggests an error in the tx path still...
+ */
if (intr_status & BWI_INTR_PHY_TXERR) {
if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
- if_printf(ifp, "intr PHY TX error\n");
- /* XXX to netisr0? */
- bwi_init_statechg(sc, 0);
+ if_printf(ifp, "%s: intr PHY TX error\n", __func__);
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
+ BWI_UNLOCK(sc);
return;
}
}
@@ -1852,8 +1676,13 @@ bwi_intr(void *xsc)
if (intr_status & BWI_INTR_NOISE)
if_printf(ifp, "intr noise\n");
- if (txrx_intr_status[0] & BWI_TXRX_INTR_RX)
+ if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) {
rx_data = sc->sc_rxeof(sc);
+ if (sc->sc_flags & BWI_F_STOP) {
+ BWI_UNLOCK(sc);
+ return;
+ }
+ }
if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) {
sc->sc_txeof_status(sc);
@@ -1887,50 +1716,105 @@ bwi_intr(void *xsc)
if (evt != BWI_LED_EVENT_NONE)
bwi_led_event(sc, evt);
}
+
+ BWI_UNLOCK(sc);
}
static void
-bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
+bwi_scan_start(struct ieee80211com *ic)
{
- callout_stop(&sc->sc_scan_ch);
- callout_stop(&sc->sc_calib_ch);
+ struct bwi_softc *sc = ic->ic_ifp->if_softc;
- ieee80211_ratectl_newstate(&sc->sc_ic, nstate);
- bwi_led_newstate(sc, nstate);
+ BWI_LOCK(sc);
+ /* Enable MAC beacon promiscuity */
+ CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
+ BWI_UNLOCK(sc);
+}
- if (nstate == IEEE80211_S_INIT)
- sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
+static void
+bwi_set_channel(struct ieee80211com *ic)
+{
+ struct bwi_softc *sc = ic->ic_ifp->if_softc;
+ struct ieee80211_channel *c = ic->ic_curchan;
+ struct bwi_mac *mac;
+
+ BWI_LOCK(sc);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
+ bwi_rf_set_chan(mac, ieee80211_chan2ieee(ic, c), 0);
+
+ sc->sc_rates = ieee80211_get_ratetable(c);
+
+ /*
+ * Setup radio tap channel freq and flags
+ */
+ sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
+ htole16(c->ic_freq);
+ sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
+ htole16(c->ic_flags & 0xffff);
+
+ BWI_UNLOCK(sc);
+}
+
+static void
+bwi_scan_end(struct ieee80211com *ic)
+{
+ struct bwi_softc *sc = ic->ic_ifp->if_softc;
+
+ BWI_LOCK(sc);
+ CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
+ BWI_UNLOCK(sc);
}
static int
-bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
+bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
- struct bwi_softc *sc = ic->ic_if.if_softc;
- struct ifnet *ifp = &ic->ic_if;
+ struct bwi_vap *bvp = BWI_VAP(vap);
+ const struct ieee80211_txparam *tp;
+ struct ieee80211com *ic= vap->iv_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ enum ieee80211_state ostate = vap->iv_state;
+ struct bwi_softc *sc = ifp->if_softc;
+ struct bwi_mac *mac;
int error;
- ASSERT_SERIALIZED(ifp->if_serializer);
+ BWI_LOCK(sc);
- bwi_newstate_begin(sc, nstate);
+ callout_stop(&sc->sc_calib_ch);
if (nstate == IEEE80211_S_INIT)
+ sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
+
+ bwi_led_newstate(sc, nstate);
+
+ error = bvp->bv_newstate(vap, nstate, arg);
+ if (error != 0)
goto back;
- error = bwi_set_chan(sc, ic->ic_curchan);
- if (error) {
- if_printf(ifp, "can't set channel to %u\n",
- ieee80211_chan2ieee(ic, ic->ic_curchan));
- return error;
+ /*
+ * Clear the BSSID when we stop a STA
+ */
+ if (vap->iv_opmode == IEEE80211_M_STA) {
+ if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
+ /*
+ * Clear out the BSSID. If we reassociate to
+ * the same AP, this will reinialize things
+ * correctly...
+ */
+ if (ic->ic_opmode == IEEE80211_M_STA &&
+ !(sc->sc_flags & BWI_F_STOP))
+ bwi_set_bssid(sc, bwi_zero_addr);
+ }
}
- if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ if (vap->iv_opmode == IEEE80211_M_MONITOR) {
/* Nothing to do */
} else if (nstate == IEEE80211_S_RUN) {
- struct bwi_mac *mac;
-
- bwi_set_bssid(sc, ic->ic_bss->ni_bssid);
+ bwi_set_bssid(sc, vap->iv_bss->ni_bssid);
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
/* Initial TX power calibration */
@@ -1940,37 +1824,26 @@ bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
#else
sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
#endif
- } else {
- bwi_set_bssid(sc, bwi_zero_addr);
- }
-back:
- error = sc->sc_newstate(ic, nstate, arg);
+ /* Initializes ratectl for a node. */
+ tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
+ if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
+ ieee80211_ratectl_node_init(vap->iv_bss);
- if (nstate == IEEE80211_S_SCAN) {
- callout_reset(&sc->sc_scan_ch,
- (sc->sc_dwell_time * hz) / 1000,
- bwi_next_scan, sc);
- } else if (nstate == IEEE80211_S_RUN) {
callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc);
}
+back:
+ BWI_UNLOCK(sc);
+
return error;
}
static int
bwi_media_change(struct ifnet *ifp)
{
- int error;
-
- ASSERT_SERIALIZED(ifp->if_serializer);
-
- error = ieee80211_media_change(ifp);
- if (error != ENETRESET)
- return error;
-
- if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
- bwi_init(ifp->if_softc);
- return 0;
+ int error = ieee80211_media_change(ifp);
+ /* NB: only the fixed rate can change and that doesn't need a reset */
+ return (error == ENETRESET ? 0 : error);
}
static int
@@ -2035,9 +1908,9 @@ bwi_dma_alloc(struct bwi_softc *sc)
break;
}
- KKASSERT(lowaddr != 0);
- KKASSERT(desc_sz != 0);
- KKASSERT(txrx_ctrl_step != 0);
+ KASSERT(lowaddr != 0, ("lowaddr zero"));
+ KASSERT(desc_sz != 0, ("desc_sz zero"));
+ KASSERT(txrx_ctrl_step != 0, ("txrx_ctrl_step zero"));
tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN);
rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN);
@@ -2045,13 +1918,16 @@ bwi_dma_alloc(struct bwi_softc *sc)
/*
* Create top level DMA tag
*/
- error = bus_dma_tag_create(NULL, BWI_ALIGN, 0,
- lowaddr, BUS_SPACE_MAXADDR,
- NULL, NULL,
- MAXBSIZE,
- BUS_SPACE_UNRESTRICTED,
- BUS_SPACE_MAXSIZE_32BIT,
- 0, &sc->sc_parent_dtag);
+ error = bus_dma_tag_create(NULL/*bus_get_dma_tag(sc->sc_dev)*/, /* parent */
+ BWI_ALIGN, 0, /* alignment, bounds */
+ lowaddr, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAXBSIZE, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ &sc->sc_parent_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create parent DMA tag\n");
return error;
@@ -2062,11 +1938,16 @@ bwi_dma_alloc(struct bwi_softc *sc)
/*
* Create TX ring DMA stuffs
*/
- error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL,
- tx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT,
- 0, &sc->sc_txring_dtag);
+ error = bus_dma_tag_create(sc->sc_parent_dtag,
+ BWI_RING_ALIGN, 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ tx_ring_sz,
+ 1,
+ BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_ALLOCNOW,
+ &sc->sc_txring_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create TX ring DMA tag\n");
return error;
@@ -2086,11 +1967,16 @@ bwi_dma_alloc(struct bwi_softc *sc)
/*
* Create RX ring DMA stuffs
*/
- error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL,
- rx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT,
- 0, &sc->sc_rxring_dtag);
+ error = bus_dma_tag_create(sc->sc_parent_dtag,
+ BWI_RING_ALIGN, 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ rx_ring_sz,
+ 1,
+ BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_ALLOCNOW,
+ &sc->sc_rxring_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create RX ring DMA tag\n");
return error;
@@ -2172,7 +2058,7 @@ bwi_dma_ring_alloc(struct bwi_softc *sc, bus_dma_tag_t dtag,
error = bus_dmamap_load(dtag, rd->rdata_dmap, rd->rdata_desc, size,
bwi_dma_ring_addr, &rd->rdata_paddr,
- BUS_DMA_WAITOK);
+ BUS_DMA_NOWAIT);
if (error) {
device_printf(sc->sc_dev, "can't load DMA mem\n");
bus_dmamem_free(dtag, rd->rdata_desc, rd->rdata_dmap);
@@ -2192,7 +2078,11 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
bus_size_t dma_size;
int error;
- st = kmalloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO);
+ st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (st == NULL) {
+ device_printf(sc->sc_dev, "can't allocate txstats data\n");
+ return ENOMEM;
+ }
sc->sc_txstats = st;
/*
@@ -2200,11 +2090,17 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
*/
dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN);
- error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL,
- dma_size, 1, BUS_SPACE_MAXSIZE_32BIT,
- 0, &st->stats_ring_dtag);
+ error = bus_dma_tag_create(sc->sc_parent_dtag,
+ BWI_RING_ALIGN,
+ 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ dma_size,
+ 1,
+ BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_ALLOCNOW,
+ &st->stats_ring_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create txstats ring "
"DMA tag\n");
@@ -2225,7 +2121,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
error = bus_dmamap_load(st->stats_ring_dtag, st->stats_ring_dmap,
st->stats_ring, dma_size,
bwi_dma_ring_addr, &st->stats_ring_paddr,
- BUS_DMA_WAITOK);
+ BUS_DMA_NOWAIT);
if (error) {
device_printf(sc->sc_dev, "can't load txstats ring DMA mem\n");
bus_dmamem_free(st->stats_ring_dtag, st->stats_ring,
@@ -2241,11 +2137,17 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC,
BWI_ALIGN);
- error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_ALIGN, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL,
- dma_size, 1, BUS_SPACE_MAXSIZE_32BIT,
- 0, &st->stats_dtag);
+ error = bus_dma_tag_create(sc->sc_parent_dtag,
+ BWI_ALIGN,
+ 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ dma_size,
+ 1,
+ BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_ALLOCNOW,
+ &st->stats_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create txstats DMA tag\n");
return error;
@@ -2263,7 +2165,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
error = bus_dmamap_load(st->stats_dtag, st->stats_dmap, st->stats,
dma_size, bwi_dma_ring_addr, &st->stats_paddr,
- BUS_DMA_WAITOK);
+ BUS_DMA_NOWAIT);
if (error) {
device_printf(sc->sc_dev, "can't load txstats DMA mem\n");
bus_dmamem_free(st->stats_dtag, st->stats, st->stats_dmap);
@@ -2298,7 +2200,7 @@ bwi_dma_txstats_free(struct bwi_softc *sc)
bus_dma_tag_destroy(st->stats_dtag);
}
- kfree(st, M_DEVBUF);
+ free(st, M_DEVBUF);
}
static void
@@ -2317,11 +2219,17 @@ bwi_dma_mbuf_create(struct bwi_softc *sc)
/*
* Create TX/RX mbuf DMA tag
*/
- error = bus_dma_tag_create(sc->sc_parent_dtag, 1, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL, MCLBYTES, 1,
- BUS_SPACE_MAXSIZE_32BIT,
- 0, &sc->sc_buf_dtag);
+ error = bus_dma_tag_create(sc->sc_parent_dtag,
+ 1,
+ 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ MCLBYTES,
+ 1,
+ BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_ALLOCNOW,
+ &sc->sc_buf_dtag);
if (error) {
device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
return error;
@@ -2451,7 +2359,7 @@ bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx)
struct bwi_txbuf_data *tbd;
uint32_t val, addr_hi, addr_lo;
- KKASSERT(ring_idx < BWI_TX_NRING);
+ KASSERT(ring_idx < BWI_TX_NRING, ("ring_idx %d", ring_idx));
rd = &sc->sc_tx_rdata[ring_idx];
tbd = &sc->sc_tx_bdata[ring_idx];
@@ -2511,7 +2419,7 @@ bwi_init_rx_ring32(struct bwi_softc *sc)
for (i = 0; i < BWI_RX_NDESC; ++i) {
error = bwi_newbuf(sc, i, 1);
if (error) {
- if_printf(&sc->sc_ic.ic_if,
+ device_printf(sc->sc_dev,
"can't allocate %dth RX buffer\n", i);
return error;
}
@@ -2556,7 +2464,7 @@ bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
{
struct bwi_ring_data *rd = &sc->sc_rx_rdata;
- KKASSERT(buf_idx < BWI_RX_NDESC);
+ KASSERT(buf_idx < BWI_RX_NDESC, ("buf_idx %d", buf_idx));
bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx,
paddr, buf_len, 0);
}
@@ -2565,7 +2473,7 @@ static void
bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd,
int buf_idx, bus_addr_t paddr, int buf_len)
{
- KKASSERT(buf_idx < BWI_TX_NDESC);
+ KASSERT(buf_idx < BWI_TX_NDESC, ("buf_idx %d", buf_idx));
bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx,
paddr, buf_len, 1);
}
@@ -2626,9 +2534,9 @@ bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init)
struct mbuf *m;
int error;
- KKASSERT(buf_idx < BWI_RX_NDESC);
+ KASSERT(buf_idx < BWI_RX_NDESC, ("buf_idx %d", buf_idx));
- m = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR);
+ m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
error = ENOBUFS;
@@ -2648,8 +2556,7 @@ bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init)
* Try to load RX buf into temporary DMA map
*/
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, rbd->rbd_tmp_dmap, m,
- bwi_dma_buf_addr, &paddr,
- init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
+ bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
if (error) {
m_freem(m);
@@ -2709,63 +2616,12 @@ bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs,
}
static int
-bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c)
-{
- struct ieee80211com *ic = &sc->sc_ic;
-#ifdef INVARIANTS
- struct ifnet *ifp = &ic->ic_if;
-#endif
- struct bwi_mac *mac;
- uint16_t flags;
- u_int chan;
-
- ASSERT_SERIALIZED(ifp->if_serializer);
-
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
- mac = (struct bwi_mac *)sc->sc_cur_regwin;
-
- chan = ieee80211_chan2ieee(ic, c);
-
- bwi_rf_set_chan(mac, chan, 0);
-
- /*
- * Setup radio tap channel freq and flags
- */
- if (IEEE80211_IS_CHAN_G(c))
- flags = IEEE80211_CHAN_G;
- else
- flags = IEEE80211_CHAN_B;
-
- sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
- htole16(c->ic_freq);
- sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
- htole16(flags);
-
- return 0;
-}
-
-static void
-bwi_next_scan(void *xsc)
-{
- struct bwi_softc *sc = xsc;
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
-
- lwkt_serialize_enter(ifp->if_serializer);
-
- if (ic->ic_state == IEEE80211_S_SCAN)
- ieee80211_next_scan(ic);
-
- lwkt_serialize_exit(ifp->if_serializer);
-}
-
-static int
bwi_rxeof(struct bwi_softc *sc, int end_idx)
{
struct bwi_ring_data *rd = &sc->sc_rx_rdata;
struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
int idx, rx_data = 0;
idx = rbd->rbd_idx;
@@ -2777,7 +2633,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
struct mbuf *m;
const void *plcp;
uint16_t flags2;
- int buflen, wh_ofs, hdr_extra, rssi, type, rate;
+ int buflen, wh_ofs, hdr_extra, rssi, noise, type, rate;
m = rb->rb_mbuf;
bus_dmamap_sync(sc->sc_buf_dtag, rb->rb_dmap,
@@ -2798,8 +2654,8 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
buflen = le16toh(hdr->rxh_buflen);
if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
- if_printf(ifp, "short frame %d, hdr_extra %d\n",
- buflen, hdr_extra);
+ if_printf(ifp, "%s: zero length data, hdr_extra %d\n",
+ __func__, hdr_extra);
ifp->if_ierrors++;
m_freem(m);
goto next;
@@ -2807,6 +2663,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
plcp = ((const uint8_t *)(hdr + 1) + hdr_extra);
rssi = bwi_calc_rssi(sc, hdr);
+ noise = bwi_calc_noise(sc);
m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
@@ -2818,29 +2675,42 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
rate = bwi_ds_plcp2rate(plcp);
/* RX radio tap */
- if (sc->sc_drvbpf != NULL)
- bwi_rx_radiotap(sc, m, hdr, plcp, rate, rssi);
+ if (ieee80211_radiotap_active(ic))
+ bwi_rx_radiotap(sc, m, hdr, plcp, rate, rssi, noise);
m_adj(m, -IEEE80211_CRC_LEN);
+ BWI_UNLOCK(sc);
+
wh = mtod(m, struct ieee80211_frame_min *);
ni = ieee80211_find_rxnode(ic, wh);
-
- type = ieee80211_input(ic, m, ni, rssi - BWI_NOISE_FLOOR,
- le16toh(hdr->rxh_tsf));
- ieee80211_free_node(ni);
-
+ if (ni != NULL) {
+ type = ieee80211_input(ni, m, rssi - noise, noise);
+ ieee80211_free_node(ni);
+ } else
+ type = ieee80211_input_all(ic, m, rssi - noise, noise);
if (type == IEEE80211_FC0_TYPE_DATA) {
rx_data = 1;
sc->sc_rx_rate = rate;
}
+
+ BWI_LOCK(sc);
next:
idx = (idx + 1) % BWI_RX_NDESC;
+
+ if (sc->sc_flags & BWI_F_STOP) {
+ /*
+ * Take the fast lane, don't do
+ * any damage to softc
+ */
+ return -1;
+ }
}
rbd->rbd_idx = idx;
bus_dmamap_sync(sc->sc_rxring_dtag, rd->rdata_dmap,
BUS_DMASYNC_PREWRITE);
+
return rx_data;
}
@@ -2857,10 +2727,10 @@ bwi_rxeof32(struct bwi_softc *sc)
sizeof(struct bwi_desc32);
rx_data = bwi_rxeof(sc, end_idx);
-
- CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
- end_idx * sizeof(struct bwi_desc32));
-
+ if (rx_data >= 0) {
+ CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
+ end_idx * sizeof(struct bwi_desc32));
+ }
return rx_data;
}
@@ -2891,7 +2761,7 @@ bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl)
DELAY(1000);
}
if (i == NRETRY)
- if_printf(&sc->sc_ic.ic_if, "reset rx ring timedout\n");
+ device_printf(sc->sc_dev, "reset rx ring timedout\n");
#undef NRETRY
@@ -2929,11 +2799,11 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
{
struct bwi_ring_data *rd;
struct bwi_txbuf_data *tbd;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t state, val;
int i;
- KKASSERT(ring_idx < BWI_TX_NRING);
+ KASSERT(ring_idx < BWI_TX_NRING, ("ring_idx %d", ring_idx));
rd = &sc->sc_tx_rdata[ring_idx];
tbd = &sc->sc_tx_bdata[ring_idx];
@@ -2950,8 +2820,8 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY) {
- if_printf(ifp, "wait for TX ring(%d) stable timed out\n",
- ring_idx);
+ if_printf(ifp, "%s: wait for TX ring(%d) stable timed out\n",
+ __func__, ring_idx);
}
CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
@@ -2964,7 +2834,8 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY)
- if_printf(ifp, "reset TX ring (%d) timed out\n", ring_idx);
+ if_printf(ifp, "%s: reset TX ring (%d) timed out\n",
+ __func__, ring_idx);
#undef NRETRY
@@ -3005,33 +2876,98 @@ bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx)
/* TODO:64 */
}
+/* XXX does not belong here */
+#define IEEE80211_OFDM_PLCP_RATE_MASK __BITS(3, 0)
+#define IEEE80211_OFDM_PLCP_LEN_MASK __BITS(16, 5)
+
+static __inline void
+bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate)
+{
+ uint32_t plcp;
+
+ plcp = __SHIFTIN(ieee80211_rate2plcp(rate, IEEE80211_T_OFDM),
+ IEEE80211_OFDM_PLCP_RATE_MASK) |
+ __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK);
+ *plcp0 = htole32(plcp);
+}
+
+static __inline void
+bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len,
+ uint8_t rate)
+{
+ int len, service, pkt_bitlen;
+
+ pkt_bitlen = pkt_len * NBBY;
+ len = howmany(pkt_bitlen * 2, rate);
+
+ service = IEEE80211_PLCP_SERVICE_LOCKED;
+ if (rate == (11 * 2)) {
+ int pkt_bitlen1;
+
+ /*
+ * PLCP service field needs to be adjusted,
+ * if TX rate is 11Mbytes/s
+ */
+ pkt_bitlen1 = len * 11;
+ if (pkt_bitlen1 - pkt_bitlen >= NBBY)
+ service |= IEEE80211_PLCP_SERVICE_LENEXT7;
+ }
+
+ plcp->i_signal = ieee80211_rate2plcp(rate, IEEE80211_T_CCK);
+ plcp->i_service = service;
+ plcp->i_length = htole16(len);
+ /* NOTE: do NOT touch i_crc */
+}
+
+static __inline void
+bwi_plcp_header(const struct ieee80211_rate_table *rt,
+ void *plcp, int pkt_len, uint8_t rate)
+{
+ enum ieee80211_phytype modtype;
+
+ /*
+ * Assume caller has zeroed 'plcp'
+ */
+ modtype = ieee80211_rate2phytype(rt, rate);
+ if (modtype == IEEE80211_T_OFDM)
+ bwi_ofdm_plcp_header(plcp, pkt_len, rate);
+ else if (modtype == IEEE80211_T_DS)
+ bwi_ds_plcp_header(plcp, pkt_len, rate);
+ else
+ panic("unsupport modulation type %u\n", modtype);
+}
+
static int
bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
- struct ieee80211_node **ni0, int mgt_pkt)
+ struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211_node *ni = *ni0;
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
struct bwi_mac *mac;
struct bwi_txbuf_hdr *hdr;
struct ieee80211_frame *wh;
+ const struct ieee80211_txparam *tp;
uint8_t rate, rate_fb;
uint32_t mac_ctrl;
uint16_t phy_ctrl;
bus_addr_t paddr;
- int pkt_len, error, mcast_pkt = 0;
+ int type, ismcast, pkt_len, error, rix;
#if 0
const uint8_t *p;
int i;
#endif
- KKASSERT(ni != NULL);
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
wh = mtod(m, struct ieee80211_frame *);
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
/* Get 802.11 frame len before prepending TX header */
pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
@@ -3039,66 +2975,43 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
/*
* Find TX rate
*/
- bzero(tb->tb_rateidx, sizeof(tb->tb_rateidx));
- if (!mgt_pkt) {
- if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
- int idx;
-
- rate = IEEE80211_RS_RATE(&ni->ni_rates,
- ic->ic_fixed_rate);
+ tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
+ if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL)) {
+ rate = rate_fb = tp->mgmtrate;
+ } else if (ismcast) {
+ rate = rate_fb = tp->mcastrate;
+ } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
+ rate = rate_fb = tp->ucastrate;
+ } else {
+ rix = ieee80211_ratectl_rate(ni, NULL, pkt_len);
+ rate = ni->ni_txrate;
- if (ic->ic_fixed_rate >= 1)
- idx = ic->ic_fixed_rate - 1;
- else
- idx = 0;
- rate_fb = IEEE80211_RS_RATE(&ni->ni_rates, idx);
+ if (rix > 0) {
+ rate_fb = ni->ni_rates.rs_rates[rix-1] &
+ IEEE80211_RATE_VAL;
} else {
- tb->tb_rateidx_cnt = ieee80211_ratectl_findrate(ni,
- m->m_pkthdr.len, tb->tb_rateidx, BWI_NTXRATE);
-
- rate = IEEE80211_RS_RATE(&ni->ni_rates,
- tb->tb_rateidx[0]);
- if (tb->tb_rateidx_cnt == BWI_NTXRATE) {
- rate_fb = IEEE80211_RS_RATE(&ni->ni_rates,
- tb->tb_rateidx[1]);
- } else {
- rate_fb = rate;
- }
- tb->tb_buflen = m->m_pkthdr.len;
+ rate_fb = rate;
}
- } else {
- /* Fixed at 1Mbits/s for mgt frames */
- rate = rate_fb = (1 * 2);
- }
-
- if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- rate = rate_fb = ic->ic_mcast_rate;
- mcast_pkt = 1;
- }
-
- if (rate == 0 || rate_fb == 0) {
- /* XXX this should not happen */
- if_printf(&ic->ic_if, "invalid rate %u or fallback rate %u",
- rate, rate_fb);
- rate = rate_fb = (1 * 2); /* Force 1Mbits/s */
}
+ tb->tb_rate[0] = rate;
+ tb->tb_rate[1] = rate_fb;
sc->sc_tx_rate = rate;
/*
* TX radio tap
*/
- if (sc->sc_drvbpf != NULL) {
+ if (ieee80211_radiotap_active_vap(vap)) {
sc->sc_tx_th.wt_flags = 0;
if (wh->i_fc[1] & IEEE80211_FC1_WEP)
sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
- if (ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_DS &&
+ if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_DS &&
(ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
rate != (1 * 2)) {
sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
}
sc->sc_tx_th.wt_rate = rate;
- bpf_ptap(sc->sc_drvbpf, m, &sc->sc_tx_th, sc->sc_tx_th_len);
+ ieee80211_radiotap_tx(vap, m);
}
/*
@@ -3106,7 +3019,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
*/
M_PREPEND(m, sizeof(*hdr), MB_DONTWAIT);
if (m == NULL) {
- if_printf(&ic->ic_if, "prepend TX header failed\n");
+ if_printf(ifp, "%s: prepend TX header failed\n", __func__);
return ENOBUFS;
}
hdr = mtod(m, struct bwi_txbuf_hdr *);
@@ -3116,14 +3029,11 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc));
bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1));
- if (!mcast_pkt) {
+ if (!ismcast) {
uint16_t dur;
- uint8_t ack_rate;
- ack_rate = ieee80211_ack_rate(ni, rate_fb);
- dur = ieee80211_txtime(ni,
- sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
- ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
+ dur = ieee80211_ack_duration(sc->sc_rates, rate,
+ ic->ic_flags & ~IEEE80211_F_SHPREAMBLE);
hdr->txh_fb_duration = htole16(dur);
}
@@ -3131,20 +3041,20 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) |
__SHIFTIN(idx, BWI_TXH_ID_IDX_MASK);
- bwi_plcp_header(hdr->txh_plcp, pkt_len, rate);
- bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate_fb);
+ bwi_plcp_header(sc->sc_rates, hdr->txh_plcp, pkt_len, rate);
+ bwi_plcp_header(sc->sc_rates, hdr->txh_fb_plcp, pkt_len, rate_fb);
phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,
BWI_TXH_PHY_C_ANTMODE_MASK);
- if (ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
+ if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
phy_ctrl |= BWI_TXH_PHY_C_OFDM;
else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1))
phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE;
mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG;
- if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
+ if (!ismcast)
mac_ctrl |= BWI_TXH_MAC_C_ACK;
- if (ieee80211_rate2modtype(rate_fb) == IEEE80211_MODTYPE_OFDM)
+ if (ieee80211_rate2phytype(sc->sc_rates, rate_fb) == IEEE80211_T_OFDM)
mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM;
hdr->txh_mac_ctrl = htole32(mac_ctrl);
@@ -3158,7 +3068,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
if (error && error != EFBIG) {
- if_printf(&ic->ic_if, "can't load TX buffer (1) %d\n", error);
+ if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ __func__, error);
goto back;
}
@@ -3167,7 +3078,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
m_new = m_defrag(m, MB_DONTWAIT);
if (m_new == NULL) {
- if_printf(&ic->ic_if, "can't defrag TX buffer\n");
+ if_printf(ifp, "%s: can't defrag TX buffer\n",
+ __func__);
error = ENOBUFS;
goto back;
} else {
@@ -3178,8 +3090,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
bwi_dma_buf_addr, &paddr,
BUS_DMA_NOWAIT);
if (error) {
- if_printf(&ic->ic_if, "can't load TX buffer (2) %d\n",
- error);
+ if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
+ __func__, error);
goto back;
}
}
@@ -3187,11 +3099,6 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
bus_dmamap_sync(sc->sc_buf_dtag, tb->tb_dmap, BUS_DMASYNC_PREWRITE);
- if (mgt_pkt || mcast_pkt) {
- /* Don't involve mcast/mgt packets into TX rate control */
- ieee80211_free_node(ni);
- *ni0 = ni = NULL;
- }
tb->tb_mbuf = m;
tb->tb_ni = ni;
@@ -3199,12 +3106,11 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
p = mtod(m, const uint8_t *);
for (i = 0; i < m->m_pkthdr.len; ++i) {
if (i != 0 && i % 8 == 0)
- kprintf("\n");
- kprintf("%02x ", p[i]);
+ printf("\n");
+ printf("%02x ", p[i]);
}
- kprintf("\n");
+ printf("\n");
#endif
-
DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n",
idx, pkt_len, m->m_pkthdr.len);
@@ -3222,6 +3128,168 @@ back:
return error;
}
+static int
+bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
+ struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = ni->ni_ic;
+ struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
+ struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
+ struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
+ struct bwi_mac *mac;
+ struct bwi_txbuf_hdr *hdr;
+ struct ieee80211_frame *wh;
+ uint8_t rate, rate_fb;
+ uint32_t mac_ctrl;
+ uint16_t phy_ctrl;
+ bus_addr_t paddr;
+ int ismcast, pkt_len, error;
+
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
+
+ /* Get 802.11 frame len before prepending TX header */
+ pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
+
+ /*
+ * Find TX rate
+ */
+ rate = params->ibp_rate0;
+ if (!ieee80211_isratevalid(ic->ic_rt, rate)) {
+ /* XXX fall back to mcast/mgmt rate? */
+ m_freem(m);
+ return EINVAL;
+ }
+ if (params->ibp_try1 != 0) {
+ rate_fb = params->ibp_rate1;
+ if (!ieee80211_isratevalid(ic->ic_rt, rate_fb)) {
+ /* XXX fall back to rate0? */
+ m_freem(m);
+ return EINVAL;
+ }
+ } else
+ rate_fb = rate;
+ tb->tb_rate[0] = rate;
+ tb->tb_rate[1] = rate_fb;
+ sc->sc_tx_rate = rate;
+
+ /*
+ * TX radio tap
+ */
+ if (ieee80211_radiotap_active_vap(vap)) {
+ sc->sc_tx_th.wt_flags = 0;
+ /* XXX IEEE80211_BPF_CRYPTO */
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP)
+ sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
+ if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
+ sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ sc->sc_tx_th.wt_rate = rate;
+
+ ieee80211_radiotap_tx(vap, m);
+ }
+
+ /*
+ * Setup the embedded TX header
+ */
+ M_PREPEND(m, sizeof(*hdr), MB_DONTWAIT);
+ if (m == NULL) {
+ if_printf(ifp, "%s: prepend TX header failed\n", __func__);
+ return ENOBUFS;
+ }
+ hdr = mtod(m, struct bwi_txbuf_hdr *);
+
+ bzero(hdr, sizeof(*hdr));
+
+ bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc));
+ bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1));
+
+ mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG;
+ if (!ismcast && (params->ibp_flags & IEEE80211_BPF_NOACK) == 0) {
+ uint16_t dur;
+
+ dur = ieee80211_ack_duration(sc->sc_rates, rate_fb, 0);
+
+ hdr->txh_fb_duration = htole16(dur);
+ mac_ctrl |= BWI_TXH_MAC_C_ACK;
+ }
+
+ hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) |
+ __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK);
+
+ bwi_plcp_header(sc->sc_rates, hdr->txh_plcp, pkt_len, rate);
+ bwi_plcp_header(sc->sc_rates, hdr->txh_fb_plcp, pkt_len, rate_fb);
+
+ phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,
+ BWI_TXH_PHY_C_ANTMODE_MASK);
+ if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
+ phy_ctrl |= BWI_TXH_PHY_C_OFDM;
+ mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM;
+ } else if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
+ phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE;
+
+ hdr->txh_mac_ctrl = htole32(mac_ctrl);
+ hdr->txh_phy_ctrl = htole16(phy_ctrl);
+
+ /* Catch any further usage */
+ hdr = NULL;
+ wh = NULL;
+
+ /* DMA load */
+ error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
+ bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ struct mbuf *m_new;
+
+ if (error != EFBIG) {
+ if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ __func__, error);
+ goto back;
+ }
+ m_new = m_defrag(m, MB_DONTWAIT);
+ if (m_new == NULL) {
+ if_printf(ifp, "%s: can't defrag TX buffer\n",
+ __func__);
+ error = ENOBUFS;
+ goto back;
+ }
+ m = m_new;
+ error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
+ bwi_dma_buf_addr, &paddr,
+ BUS_DMA_NOWAIT);
+ if (error) {
+ if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
+ __func__, error);
+ goto back;
+ }
+ }
+
+ bus_dmamap_sync(sc->sc_buf_dtag, tb->tb_dmap, BUS_DMASYNC_PREWRITE);
+
+ tb->tb_mbuf = m;
+ tb->tb_ni = ni;
+
+ DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n",
+ idx, pkt_len, m->m_pkthdr.len);
+
+ /* Setup TX descriptor */
+ sc->sc_setup_txdesc(sc, rd, idx, paddr, m->m_pkthdr.len);
+ bus_dmamap_sync(sc->sc_txring_dtag, rd->rdata_dmap,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Kick start */
+ sc->sc_start_tx(sc, rd->rdata_txrx_ctrl, idx);
+back:
+ if (error)
+ m_freem(m);
+ return error;
+}
+
static void
bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
{
@@ -3239,7 +3307,7 @@ bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
static void
bwi_txeof_status32(struct bwi_softc *sc)
{
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t val, ctrl_base;
int end_idx;
@@ -3267,69 +3335,67 @@ bwi_txeof_status64(struct bwi_softc *sc)
static void
_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
{
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_txbuf_data *tbd;
struct bwi_txbuf *tb;
int ring_idx, buf_idx;
+ struct ieee80211_node *ni;
+ struct ieee80211vap *vap;
if (tx_id == 0) {
- if_printf(ifp, "zero tx id\n");
+ if_printf(ifp, "%s: zero tx id\n", __func__);
return;
}
ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK);
buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK);
- KKASSERT(ring_idx == BWI_TX_DATA_RING);
- KKASSERT(buf_idx < BWI_TX_NDESC);
+ KASSERT(ring_idx == BWI_TX_DATA_RING, ("ring_idx %d", ring_idx));
+ KASSERT(buf_idx < BWI_TX_NDESC, ("buf_idx %d", buf_idx));
tbd = &sc->sc_tx_bdata[ring_idx];
- KKASSERT(tbd->tbd_used > 0);
+ KASSERT(tbd->tbd_used > 0, ("tbd_used %d", tbd->tbd_used));
tbd->tbd_used--;
tb = &tbd->tbd_buf[buf_idx];
-
DPRINTF(sc, BWI_DBG_TXEOF, "txeof idx %d, "
"acked %d, data_txcnt %d, ni %p\n",
buf_idx, acked, data_txcnt, tb->tb_ni);
bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap);
- m_freem(tb->tb_mbuf);
- tb->tb_mbuf = NULL;
+ ni = tb->tb_ni;
if (tb->tb_ni != NULL) {
- struct ieee80211_ratectl_res res[BWI_NTXRATE];
- int res_len, retry;
-
- if (data_txcnt <= BWI_SHRETRY_FB || tb->tb_rateidx_cnt == 1) {
- res_len = 1;
- res[0].rc_res_rateidx = tb->tb_rateidx[0];
- res[0].rc_res_tries = data_txcnt;
- } else {
- res_len = BWI_NTXRATE;
- res[0].rc_res_rateidx = tb->tb_rateidx[0];
- res[0].rc_res_tries = BWI_SHRETRY_FB;
- res[1].rc_res_rateidx = tb->tb_rateidx[1];
- res[1].rc_res_tries = data_txcnt - BWI_SHRETRY_FB;
- }
+ const struct bwi_txbuf_hdr *hdr =
+ mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
+ vap = ni->ni_vap;
- if (acked) {
- ifp->if_opackets++;
- retry = data_txcnt > 0 ? data_txcnt - 1 : 0;
- } else {
- ifp->if_oerrors++;
- retry = data_txcnt;
+ /* NB: update rate control only for unicast frames */
+ if (hdr->txh_mac_ctrl & htole32(BWI_TXH_MAC_C_ACK)) {
+ /*
+ * Feed back 'acked and data_txcnt'. Note that the
+ * generic AMRR code only understands one tx rate
+ * and the estimator doesn't handle real retry counts
+ * well so to avoid over-aggressive downshifting we
+ * treat any number of retries as "1".
+ */
+ ieee80211_ratectl_tx_complete(vap, ni,
+ (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
+ IEEE80211_RATECTL_TX_FAILURE, &acked, NULL);
}
- ieee80211_ratectl_tx_complete(tb->tb_ni, tb->tb_buflen,
- res, res_len, retry, 0, !acked);
+ /*
+ * Do any tx complete callback. Note this must
+ * be done before releasing the node reference.
+ */
+ if (tb->tb_mbuf->m_flags & M_TXCB)
+ ieee80211_process_callback(ni, tb->tb_mbuf, !acked);
ieee80211_free_node(tb->tb_ni);
tb->tb_ni = NULL;
- } else {
- /* XXX mgt packet error */
- ifp->if_opackets++;
}
+ m_freem(tb->tb_mbuf);
+ tb->tb_mbuf = NULL;
if (tbd->tbd_used == 0)
sc->sc_tx_timer = 0;
@@ -3366,7 +3432,7 @@ bwi_txeof_status(struct bwi_softc *sc, int end_idx)
static void
bwi_txeof(struct bwi_softc *sc)
{
- struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ifnet *ifp = sc->sc_ifp;
for (;;) {
uint32_t tx_status0, tx_status1;
@@ -3385,8 +3451,8 @@ bwi_txeof(struct bwi_softc *sc)
if (tx_status0 & (BWI_TXSTATUS0_AMPDU | BWI_TXSTATUS0_PENDING))
continue;
- _bwi_txeof(sc, tx_id, tx_status0 & BWI_TXSTATUS0_ACKED,
- data_txcnt);
+ _bwi_txeof(sc, le16toh(tx_id), tx_status0 & BWI_TXSTATUS0_ACKED,
+ data_txcnt);
}
if ((ifp->if_flags & IFF_OACTIVE) == 0)
@@ -3416,7 +3482,7 @@ bwi_get_pwron_delay(struct bwi_softc *sc)
int error;
com = &sc->sc_com_regwin;
- KKASSERT(BWI_REGWIN_EXIST(com));
+ KASSERT(BWI_REGWIN_EXIST(com), ("no regwin"));
if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
return 0;
@@ -3638,19 +3704,20 @@ bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
static void
bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
struct bwi_myaddr_bssid buf;
const uint8_t *p;
uint32_t val;
int n, i;
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
- bcopy(ic->ic_myaddr, buf.myaddr, sizeof(buf.myaddr));
+ bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr));
bcopy(bssid, buf.bssid, sizeof(buf.bssid));
n = sizeof(buf) / sizeof(val);
@@ -3670,47 +3737,46 @@ static void
bwi_updateslot(struct ifnet *ifp)
{
struct bwi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = ifp->if_l2com;
struct bwi_mac *mac;
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- return;
-
- ASSERT_SERIALIZED(ifp->if_serializer);
-
- DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
+ BWI_LOCK(sc);
+ if (ifp->if_flags & IFF_RUNNING) {
+ DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
- mac = (struct bwi_mac *)sc->sc_cur_regwin;
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
- bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT));
+ bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT));
+ }
+ BWI_UNLOCK(sc);
}
static void
bwi_calibrate(void *xsc)
{
struct bwi_softc *sc = xsc;
- struct ieee80211com *ic = &sc->sc_ic;
- struct ifnet *ifp = &ic->ic_if;
-
- lwkt_serialize_enter(ifp->if_serializer);
+#ifdef INVARIANTS
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+#endif
+ struct bwi_mac *mac;
- if (ic->ic_state == IEEE80211_S_RUN) {
- struct bwi_mac *mac;
+ BWI_ASSERT_LOCKED(sc);
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
- mac = (struct bwi_mac *)sc->sc_cur_regwin;
+ KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR,
+ ("opmode %d", ic->ic_opmode));
- if (ic->ic_opmode != IEEE80211_M_MONITOR) {
- bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
- sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
- }
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
- /* XXX 15 seconds */
- callout_reset(&sc->sc_calib_ch, hz * 15, bwi_calibrate, sc);
- }
+ bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
+ sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
- lwkt_serialize_exit(ifp->if_serializer);
+ /* XXX 15 seconds */
+ callout_reset(&sc->sc_calib_ch, hz * 15, bwi_calibrate, sc);
}
static int
@@ -3718,21 +3784,48 @@ bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr)
{
struct bwi_mac *mac;
- KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
return bwi_rf_calc_rssi(mac, hdr);
}
+static int
+bwi_calc_noise(struct bwi_softc *sc)
+{
+ struct bwi_mac *mac;
+
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
+
+ return bwi_rf_calc_noise(mac);
+}
+
+static __inline uint8_t
+bwi_ofdm_plcp2rate(const uint32_t *plcp0)
+{
+ uint32_t plcp;
+ uint8_t plcp_rate;
+
+ plcp = le32toh(*plcp0);
+ plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK);
+ return ieee80211_plcp2rate(plcp_rate, IEEE80211_T_OFDM);
+}
+
+static __inline uint8_t
+bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr)
+{
+ return ieee80211_plcp2rate(hdr->i_signal, IEEE80211_T_DS);
+}
+
static void
bwi_rx_radiotap(struct bwi_softc *sc, struct mbuf *m,
- struct bwi_rxbuf_hdr *hdr, const void *plcp,
- int rate, int rssi)
+ struct bwi_rxbuf_hdr *hdr, const void *plcp, int rate, int rssi, int noise)
{
const struct ieee80211_frame_min *wh;
- KKASSERT(sc->sc_drvbpf != NULL);
-
sc->sc_rx_th.wr_flags = IEEE80211_RADIOTAP_F_FCS;
if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_SHPREAMBLE)
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
@@ -3744,9 +3837,7 @@ bwi_rx_radiotap(struct bwi_softc *sc, struct mbuf *m,
sc->sc_rx_th.wr_tsf = hdr->rxh_tsf; /* No endian convertion */
sc->sc_rx_th.wr_rate = rate;
sc->sc_rx_th.wr_antsignal = rssi;
- sc->sc_rx_th.wr_antnoise = BWI_NOISE_FLOOR;
-
- bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, sc->sc_rx_th_len);
+ sc->sc_rx_th.wr_antnoise = noise;
}
static void
@@ -3809,7 +3900,7 @@ bwi_led_attach(struct bwi_softc *sc)
"%dth led, act %d, lowact %d\n", i,
led->l_act, led->l_flags & BWI_LED_F_ACTLOW);
}
- callout_init(&sc->sc_led_blink_ch);
+ /*callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);*/
}
static __inline uint16_t
@@ -3827,7 +3918,8 @@ bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
static void
bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t val;
int i;
@@ -3836,7 +3928,7 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
sc->sc_led_blinking = 0;
}
- if ((ic->ic_if.if_flags & IFF_RUNNING) == 0)
+ if ((ic->ic_ifp->if_flags & IFF_RUNNING) == 0)
return;
val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
@@ -3850,14 +3942,14 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
if ((led->l_flags & BWI_LED_F_BLINK) &&
nstate != IEEE80211_S_INIT)
- continue;
+ continue;
switch (led->l_act) {
- case BWI_LED_ACT_ON: /* Always on */
+ case BWI_LED_ACT_ON: /* Always on */
on = 1;
break;
- case BWI_LED_ACT_OFF: /* Always off */
- case BWI_LED_ACT_5GHZ: /* TODO: 11A */
+ case BWI_LED_ACT_OFF: /* Always off */
+ case BWI_LED_ACT_5GHZ: /* TODO: 11A */
on = 0;
break;
default:
@@ -3883,7 +3975,6 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
}
CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
}
-
static void
bwi_led_event(struct bwi_softc *sc, int event)
{
@@ -3916,7 +4007,7 @@ bwi_led_event(struct bwi_softc *sc, int event)
break;
}
bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur,
- bwi_led_duration[rate].off_dur);
+ bwi_led_duration[rate].off_dur);
}
static void
@@ -3951,30 +4042,27 @@ bwi_led_blink_next(void *xsc)
CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
- bwi_led_blink_end, sc);
+ bwi_led_blink_end, sc);
}
static void
bwi_led_blink_end(void *xsc)
{
struct bwi_softc *sc = xsc;
-
sc->sc_led_blinking = 0;
}
-static void *
-bwi_ratectl_attach(struct ieee80211com *ic, u_int rc)
+static void
+bwi_restart(void *xsc, int pending)
{
- struct bwi_softc *sc = ic->ic_if.if_softc;
+ struct bwi_softc *sc = xsc;
+ struct ifnet *ifp = sc->sc_ifp;
- switch (rc) {
- case IEEE80211_RATECTL_ONOE:
- return &sc->sc_onoe_param;
- case IEEE80211_RATECTL_NONE:
- /* This could only happen during detaching */
- return NULL;
- default:
- panic("unknown rate control algo %u\n", rc);
- return NULL;
- }
+ if_printf(ifp, "%s begin, help!\n", __func__);
+ BWI_LOCK(sc);
+ bwi_init_statechg(xsc, 0);
+#if 0
+ bwi_start_locked(ifp);
+#endif
+ BWI_UNLOCK(sc);
}
diff --git a/sys/dev/netif/bwi/if_bwi_pci.c b/sys/dev/netif/bwi/if_bwi_pci.c
new file mode 100644
index 0000000..973e01d
--- /dev/null
+++ b/sys/dev/netif/bwi/if_bwi_pci.c
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * 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, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * 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 NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+/*
+ * PCI/Cardbus front-end for the Broadcom Wireless LAN controller driver.
+ */
+
+#include <sys/param.h>
+#include <sys/bitops.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/serialize.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/ifq_var.h>
+
+#include <netproto/802_11/ieee80211_radiotap.h>
+#include <netproto/802_11/ieee80211_var.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcidevs.h>
+
+#include <dev/netif/bwi/if_bwireg.h>
+#include <dev/netif/bwi/if_bwivar.h>
+#include <dev/netif/bwi/bwiphy.h>
+#include <dev/netif/bwi/bwirf.h>
+#include <dev/netif/bwi/bwimac.h>
+
+/*
+ * PCI glue.
+ */
+
+struct bwi_pci_softc {
+ struct bwi_softc sc_sc;
+};
+
+#define BS_BAR 0x10
+#define PCIR_RETRY_TIMEOUT 0x41
+
+static const struct bwi_dev {
+ uint16_t vid;
+ uint16_t did;
+ const char *desc;
+} bwi_devices[] = {
+ { PCI_VENDOR_BROADCOM, 0x4301,"Broadcom BCM4301 802.11b Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4307,"Broadcom BCM4307 802.11b Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4311,"Broadcom BCM4311 802.11b/g Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4312,"Broadcom BCM4312 802.11a/b/g Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4313,"Broadcom BCM4312 802.11a Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4320,"Broadcom BCM4306 802.11b/g Wireless Lan"},
+ { PCI_VENDOR_BROADCOM, 0x4321,"Broadcom BCM4306 802.11a Wireless Lan"},
+ { PCI_VENDOR_BROADCOM, 0x4325,"Broadcom BCM4306 802.11b/g Wireless Lan"},
+ { PCI_VENDOR_BROADCOM, 0x4324,"Broadcom BCM4309 802.11a/b/g Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4318,"Broadcom BCM4318 802.11b/g Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x4319,"Broadcom BCM4318 802.11a/b/g Wireless Lan" },
+ { PCI_VENDOR_BROADCOM, 0x431a,"Broadcom BCM4318 802.11a Wireless Lan" },
+ { 0, 0, NULL }
+};
+
+static int
+bwi_pci_probe(device_t dev)
+{
+ const struct bwi_dev *b;
+ uint16_t did, vid;
+
+ did = pci_get_device(dev);
+ vid = pci_get_vendor(dev);
+
+ for (b = bwi_devices; b->desc != NULL; ++b) {
+ if (b->did == did && b->vid == vid) {
+ device_set_desc(dev, b->desc);
+ return BUS_PROBE_DEFAULT;
+ }
+ }
+ return ENXIO;
+}
+
+static int
+bwi_pci_attach(device_t dev)
+{
+ struct bwi_pci_softc *psc = device_get_softc(dev);
+ struct bwi_softc *sc = &psc->sc_sc;
+ int error = ENXIO;
+
+ sc->sc_dev = dev;
+
+ /*
+ * Enable bus mastering.
+ */
+ pci_enable_busmaster(dev);
+
+ /*
+ * Setup memory-mapping of PCI registers.
+ */
+ sc->sc_mem_rid = BWI_PCIR_BAR;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->sc_mem_rid, RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "cannot map register space\n");
+ goto bad;
+ }
+ sc->sc_mem_bt = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_mem_bh = rman_get_bushandle(sc->sc_mem_res);
+ /*
+ * Mark device invalid so any interrupts (shared or otherwise)
+ * that arrive before the card is setup are discarded.
+ */
+ sc->sc_invalid = 1;
+
+ /*
+ * Arrange interrupt line.
+ */
+ sc->sc_irq_rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->sc_irq_rid,
+ RF_SHAREABLE|RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "could not map interrupt\n");
+ goto bad1;
+ }
+ if (bus_setup_intr(dev, sc->sc_irq_res,
+ INTR_MPSAFE,
+ bwi_intr, sc, &sc->sc_irq_handle, &wlan_global_serializer)) {
+ device_printf(dev, "could not establish interrupt\n");
+ goto bad2;
+ }
+
+ /* Get more PCI information */
+ sc->sc_pci_did = pci_get_device(dev);
+ sc->sc_pci_revid = pci_get_revid(dev);
+ sc->sc_pci_subvid = pci_get_subvendor(dev);
+ sc->sc_pci_subdid = pci_get_subdevice(dev);
+
+ error = bwi_attach(sc);
+ if (error == 0) /* success */
+ return 0;
+
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
+bad2:
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+bad1:
+ bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, sc->sc_mem_res);
+bad:
+ return (error);
+}
+
+static int
+bwi_pci_detach(device_t dev)
+{
+ struct bwi_pci_softc *psc = device_get_softc(dev);
+ struct bwi_softc *sc = &psc->sc_sc;
+
+ /* check if device was removed */
+ sc->sc_invalid = !bus_child_present(dev);
+
+ bwi_detach(sc);
+
+ bus_generic_detach(dev);
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+
+ bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, sc->sc_mem_res);
+
+ return (0);
+}
+
+static int
+bwi_pci_shutdown(device_t dev)
+{
+ struct bwi_pci_softc *psc = device_get_softc(dev);
+
+ bwi_shutdown(&psc->sc_sc);
+ return (0);
+}
+
+static int
+bwi_pci_suspend(device_t dev)
+{
+ struct bwi_pci_softc *psc = device_get_softc(dev);
+
+ bwi_suspend(&psc->sc_sc);
+
+ return (0);
+}
+
+static int
+bwi_pci_resume(device_t dev)
+{
+ struct bwi_pci_softc *psc = device_get_softc(dev);
+
+ bwi_resume(&psc->sc_sc);
+
+ return (0);
+}
+
+static device_method_t bwi_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bwi_pci_probe),
+ DEVMETHOD(device_attach, bwi_pci_attach),
+ DEVMETHOD(device_detach, bwi_pci_detach),
+ DEVMETHOD(device_shutdown, bwi_pci_shutdown),
+ DEVMETHOD(device_suspend, bwi_pci_suspend),
+ DEVMETHOD(device_resume, bwi_pci_resume),
+
+ { 0,0 }
+};
+static driver_t bwi_driver = {
+ "bwi",
+ bwi_pci_methods,
+ sizeof (struct bwi_pci_softc)
+};
+static devclass_t bwi_devclass;
+DRIVER_MODULE(bwi, pci, bwi_driver, bwi_devclass, 0, 0);
+MODULE_DEPEND(bwi, wlan, 1, 1, 1); /* 802.11 media layer */
+MODULE_DEPEND(bwi, firmware, 1, 1, 1); /* firmware support */
+MODULE_DEPEND(bwi, wlan_amrr, 1, 1, 1);
diff --git a/sys/dev/netif/bwi/if_bwireg.h b/sys/dev/netif/bwi/if_bwireg.h
index 8abd31e..f376911 100644
--- a/sys/dev/netif/bwi/if_bwireg.h
+++ b/sys/dev/netif/bwi/if_bwireg.h
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*
* $DragonFly: src/sys/dev/netif/bwi/if_bwireg.h,v 1.4 2007/10/19 14:27:04 sephe Exp $
+ * $FreeBSD$
*/
#ifndef _IF_BWIREG_H
@@ -203,6 +204,7 @@
#define BWI_COMM_MOBJ_HFLAGS_MI 0x60
#define BWI_COMM_MOBJ_HFLAGS_HI 0x62
#define BWI_COMM_MOBJ_RF_ATTEN 0x64
+#define BWI_COMM_MOBJ_RF_NOISE 0x6e
#define BWI_COMM_MOBJ_TSSI_OFDM 0x70
#define BWI_COMM_MOBJ_PROBE_RESP_TO 0x74
#define BWI_COMM_MOBJ_CHAN 0xa0
@@ -273,7 +275,8 @@
#define BWI_PHYINFO_TYPE_11A 0
#define BWI_PHYINFO_TYPE_11B 1
#define BWI_PHYINFO_TYPE_11G 2
-#define BWI_PHYINFO_TYPE_11N 5
+#define BWI_PHYINFO_TYPE_11N 4
+#define BWI_PHYINFO_TYPE_11LP 5
#define BWI_PHYINFO_VER_MASK __BITS(15, 12)
#define BWI_RF_ANTDIV 0x3e2 /* Antenna Diversity?? */
@@ -335,6 +338,9 @@
*/
#define BWI_GPIO_CTRL 0x6c
+#define PCI_VENDOR_BROADCOM 0x14e4 /* Broadcom */
+#define PCI_PRODUCT_BROADCOM_BCM4309 0x4324
+
/*
* Extended PCI registers
*/
@@ -395,6 +401,7 @@
/*
* SPROM card flags
*/
+#define BWI_CARD_F_BT_COEXIST __BIT(0) /* Bluetooth coexist */
#define BWI_CARD_F_PA_GPIO9 __BIT(1) /* GPIO 9 controls PA */
#define BWI_CARD_F_SW_NRSSI __BIT(3)
#define BWI_CARD_F_NO_SLOWCLK __BIT(5) /* no slow clock */
diff --git a/sys/dev/netif/bwi/if_bwivar.h b/sys/dev/netif/bwi/if_bwivar.h
index ba679b8..49a07a9 100644
--- a/sys/dev/netif/bwi/if_bwivar.h
+++ b/sys/dev/netif/bwi/if_bwivar.h
@@ -32,6 +32,7 @@
* SUCH DAMAGE.
*
* $DragonFly: src/sys/dev/netif/bwi/if_bwivar.h,v 1.14 2008/02/15 11:15:38 sephe Exp $
+ * $FreeBSD$
*/
#ifndef _IF_BWIVAR_H
@@ -96,19 +97,18 @@ enum bwi_txpwrcb_type {
#define CSR_CLRBITS_2(sc, reg, bits) \
CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) & ~(bits))
-#define BWI_DEBUG
#ifdef BWI_DEBUG
#define DPRINTF(sc, dbg, fmt, ...) \
do { \
if ((sc)->sc_debug & (dbg)) \
- if_printf(&(sc)->sc_ic.ic_if, fmt, __VA_ARGS__); \
+ device_printf((sc)->sc_dev, fmt, __VA_ARGS__); \
} while (0)
#define _DPRINTF(sc, dbg, fmt, ...) \
do { \
if ((sc)->sc_debug & (dbg)) \
- kprintf(fmt, __VA_ARGS__); \
+ printf(fmt, __VA_ARGS__); \
} while (0)
#else /* !BWI_DEBUG */
@@ -233,10 +233,7 @@ struct bwi_txbuf {
bus_dmamap_t tb_dmap;
struct ieee80211_node *tb_ni;
- int tb_buflen;
-#define BWI_NTXRATE 2
- int tb_rateidx_cnt;
- int tb_rateidx[BWI_NTXRATE];
+ int tb_rate[2];
};
struct bwi_txbuf_data {
@@ -293,11 +290,12 @@ struct bwi_fwhdr {
#define BWI_FW_VERSION4 4
#define BWI_FW_VERSION3_REVMAX 0x128
-#define BWI_FW_PATH "bwi/v%d/"
-#define BWI_FW_UCODE_PATH BWI_FW_PATH "ucode%d.fw"
-#define BWI_FW_PCM_PATH BWI_FW_PATH "pcm%d.fw"
-#define BWI_FW_IV_PATH BWI_FW_PATH "b0g0initvals%d.fw"
-#define BWI_FW_IV_EXT_PATH BWI_FW_PATH "b0g0bsinitvals%d.fw"
+#define BWI_FW_PATH "bwi_v%d_"
+#define BWI_FW_STUB_PATH BWI_FW_PATH "ucode"
+#define BWI_FW_UCODE_PATH BWI_FW_PATH "ucode%d"
+#define BWI_FW_PCM_PATH BWI_FW_PATH "pcm%d"
+#define BWI_FW_IV_PATH BWI_FW_PATH "b0g0initvals%d"
+#define BWI_FW_IV_EXT_PATH BWI_FW_PATH "b0g0bsinitvals%d"
struct bwi_fw_iv {
/* Big endian */
@@ -422,6 +420,7 @@ struct bwi_rf {
int (*rf_calc_rssi)
(struct bwi_mac *,
const struct bwi_rxbuf_hdr *);
+ int (*rf_calc_noise)(struct bwi_mac *);
void (*rf_lo_update)(struct bwi_mac *);
@@ -450,7 +449,7 @@ struct bwi_rf {
#define BWI_ANT_MODE_AUTO 3
struct bwi_softc;
-struct fw_image;
+struct firmware;
struct bwi_mac {
struct bwi_regwin mac_regwin; /* MUST be first field */
@@ -467,10 +466,11 @@ struct bwi_mac {
struct bwi_tpctl mac_tpctl; /* TX power control */
uint32_t mac_flags; /* BWI_MAC_F_ */
- struct fw_image *mac_ucode;
- struct fw_image *mac_pcm;
- struct fw_image *mac_iv;
- struct fw_image *mac_iv_ext;
+ const struct firmware *mac_stub;
+ const struct firmware *mac_ucode;
+ const struct firmware *mac_pcm;
+ const struct firmware *mac_iv;
+ const struct firmware *mac_iv_ext;
};
#define BWI_MAC_F_BSWAP 0x1
@@ -492,7 +492,7 @@ do { \
} while (0)
#define BWI_MAC_MAX 2
-#define BWI_LED_MAX 4
+#define BWI_LED_MAX 4
enum bwi_bus_space {
BWI_BUS_SPACE_30BIT = 1,
@@ -533,10 +533,19 @@ struct bwi_rx_radiotap_hdr {
/* TODO: sq */
};
+struct bwi_vap {
+ struct ieee80211vap bv_vap;
+ int (*bv_newstate)(struct ieee80211vap *,
+ enum ieee80211_state, int);
+};
+#define BWI_VAP(vap) ((struct bwi_vap *)(vap))
+
struct bwi_softc {
- struct ieee80211com sc_ic;
+ struct ifnet *sc_ifp;
uint32_t sc_flags; /* BWI_F_ */
device_t sc_dev;
+ struct lock sc_lock;
+ int sc_invalid;
uint32_t sc_cap; /* BWI_CAP_ */
uint16_t sc_bbp_id; /* BWI_BBPID_ */
@@ -544,6 +553,7 @@ struct bwi_softc {
uint8_t sc_bbp_pkg;
uint8_t sc_pci_revid;
+ uint16_t sc_pci_did;
uint16_t sc_pci_subvid;
uint16_t sc_pci_subdid;
@@ -560,8 +570,8 @@ struct bwi_softc {
bus_space_tag_t sc_mem_bt;
bus_space_handle_t sc_mem_bh;
- struct callout sc_scan_ch;
struct callout sc_calib_ch;
+ struct callout sc_watchdog_timer;
struct bwi_regwin *sc_cur_regwin;
struct bwi_regwin sc_com_regwin;
@@ -596,26 +606,13 @@ struct bwi_softc {
struct bwi_txstats_data *sc_txstats;
int sc_tx_timer;
+ const struct ieee80211_rate_table *sc_rates;
- struct bpf_if *sc_drvbpf;
+ struct bwi_tx_radiotap_hdr sc_tx_th;
+ struct bwi_rx_radiotap_hdr sc_rx_th;
- union {
- struct bwi_tx_radiotap_hdr u_tx_th;
- uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN];
- } sc_u_tx_th;
-#define sc_tx_th sc_u_tx_th.u_tx_th
- int sc_tx_th_len;
-
- union {
- struct bwi_rx_radiotap_hdr u_rx_th;
- uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN];
- } sc_u_rx_th;
-#define sc_rx_th sc_u_rx_th.u_rx_th
- int sc_rx_th_len;
-
- int (*sc_newstate)
- (struct ieee80211com *,
- enum ieee80211_state, int);
+ struct taskqueue *sc_tq;
+ struct task sc_restart_task;
int (*sc_init_tx_ring)(struct bwi_softc *, int);
void (*sc_free_tx_ring)(struct bwi_softc *, int);
@@ -638,24 +635,20 @@ struct bwi_softc {
void (*sc_txeof_status)(struct bwi_softc *);
- struct sysctl_ctx_list sc_sysctl_ctx;
- struct sysctl_oid *sc_sysctl_tree;
-
- struct ieee80211_onoe_param sc_onoe_param;
-
- /*
- * Sysctl variables
- */
+ /* Sysctl variables */
int sc_fw_version; /* BWI_FW_VERSION[34] */
int sc_dwell_time; /* milliseconds */
- uint32_t sc_debug; /* BWI_DBG_ */
int sc_led_idle;
int sc_led_blink;
int sc_txpwr_calib;
+ uint32_t sc_debug; /* BWI_DBG_ */
+ struct sysctl_ctx_list sc_sysctl_ctx;
+ struct sysctl_oid *sc_sysctl_tree;
};
#define BWI_F_BUS_INITED 0x1
#define BWI_F_PROMISC 0x2
+#define BWI_F_STOP 0x4
#define BWI_DBG_MAC 0x00000001
#define BWI_DBG_RF 0x00000002
@@ -673,6 +666,26 @@ struct bwi_softc {
#define BWI_DBG_TXEOF 0x00001000
#define BWI_DBG_LED 0x00002000
+#define BWI_LOCK_INIT(sc) \
+ lockinit(&(sc)->sc_lock, \
+ __DECONST(char *, device_get_nameunit((sc)->sc_dev)), \
+ 0, LK_CANRECURSE)
+
+#define BWI_LOCK_DESTROY(sc) lockuninit(&(sc)->sc_lock)
+#define BWI_ASSERT_LOCKED(sc) \
+ KKASSERT(lockstatus(&(sc)->sc_lock, curthread) == LK_EXCLUSIVE)
+#define BWI_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE)
+#define BWI_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE)
+
+int bwi_attach(struct bwi_softc *);
+int bwi_detach(struct bwi_softc *);
+void bwi_suspend(struct bwi_softc *);
+void bwi_resume(struct bwi_softc *);
+int bwi_shutdown(struct bwi_softc *);
+void bwi_intr(void *);
+
+int bwi_bus_init(struct bwi_softc *, struct bwi_mac *mac);
+
uint16_t bwi_read_sprom(struct bwi_softc *, uint16_t);
int bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *,
struct bwi_regwin **);
@@ -681,9 +694,15 @@ void bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *,
uint32_t);
void bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *,
uint32_t);
-int bwi_bus_init(struct bwi_softc *, struct bwi_mac *);
-uint8_t bwi_rate2plcp(uint8_t); /* XXX belongs to 802.11 */
#define abs(a) __builtin_abs(a)
+/* XXX does not belong here */
+struct ieee80211_ds_plcp_hdr {
+ uint8_t i_signal;
+ uint8_t i_service;
+ uint16_t i_length;
+ uint16_t i_crc;
+} __packed;
+
#endif /* !_IF_BWIVAR_H */
diff --git a/sys/dev/netif/bwi/pci_if.h b/sys/dev/netif/bwi/pci_if.h
new file mode 100644
index 0000000..4fd056e
--- /dev/null
+++ b/sys/dev/netif/bwi/pci_if.h
@@ -0,0 +1,190 @@
+/*
+ * This file is produced automatically.
+ * Do not modify anything in here by hand.
+ *
+ * Created from source file
+ * @/bus/pci/pci_if.m
+ * with
+ * makeobjops.awk
+ *
+ * See the source file for legal information
+ */
+
+#ifndef _pci_if_h_
+#define _pci_if_h_
+
+extern struct kobjop_desc pci_read_config_desc;
+typedef u_int32_t pci_read_config_t(device_t dev, device_t child, int reg,
+ int width);
+static __inline u_int32_t PCI_READ_CONFIG(device_t dev, device_t child, int reg,
+ int width)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_read_config);
+ return ((pci_read_config_t *) _m)(dev, child, reg, width);
+}
+
+extern struct kobjop_desc pci_write_config_desc;
+typedef void pci_write_config_t(device_t dev, device_t child, int reg,
+ u_int32_t val, int width);
+static __inline void PCI_WRITE_CONFIG(device_t dev, device_t child, int reg,
+ u_int32_t val, int width)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_write_config);
+ ((pci_write_config_t *) _m)(dev, child, reg, val, width);
+}
+
+extern struct kobjop_desc pci_get_powerstate_desc;
+typedef int pci_get_powerstate_t(device_t dev, device_t child);
+static __inline int PCI_GET_POWERSTATE(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_get_powerstate);
+ return ((pci_get_powerstate_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_set_powerstate_desc;
+typedef int pci_set_powerstate_t(device_t dev, device_t child, int state);
+static __inline int PCI_SET_POWERSTATE(device_t dev, device_t child, int state)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_set_powerstate);
+ return ((pci_set_powerstate_t *) _m)(dev, child, state);
+}
+
+extern struct kobjop_desc pci_get_vpd_ident_desc;
+typedef int pci_get_vpd_ident_t(device_t dev, device_t child,
+ const char **identptr);
+static __inline int PCI_GET_VPD_IDENT(device_t dev, device_t child,
+ const char **identptr)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_get_vpd_ident);
+ return ((pci_get_vpd_ident_t *) _m)(dev, child, identptr);
+}
+
+extern struct kobjop_desc pci_get_vpd_readonly_desc;
+typedef int pci_get_vpd_readonly_t(device_t dev, device_t child, const char *kw,
+ const char **vptr);
+static __inline int PCI_GET_VPD_READONLY(device_t dev, device_t child,
+ const char *kw, const char **vptr)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_get_vpd_readonly);
+ return ((pci_get_vpd_readonly_t *) _m)(dev, child, kw, vptr);
+}
+
+extern struct kobjop_desc pci_enable_busmaster_desc;
+typedef int pci_enable_busmaster_t(device_t dev, device_t child);
+static __inline int PCI_ENABLE_BUSMASTER(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_enable_busmaster);
+ return ((pci_enable_busmaster_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_disable_busmaster_desc;
+typedef int pci_disable_busmaster_t(device_t dev, device_t child);
+static __inline int PCI_DISABLE_BUSMASTER(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_disable_busmaster);
+ return ((pci_disable_busmaster_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_enable_io_desc;
+typedef int pci_enable_io_t(device_t dev, device_t child, int space);
+static __inline int PCI_ENABLE_IO(device_t dev, device_t child, int space)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_enable_io);
+ return ((pci_enable_io_t *) _m)(dev, child, space);
+}
+
+extern struct kobjop_desc pci_disable_io_desc;
+typedef int pci_disable_io_t(device_t dev, device_t child, int space);
+static __inline int PCI_DISABLE_IO(device_t dev, device_t child, int space)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_disable_io);
+ return ((pci_disable_io_t *) _m)(dev, child, space);
+}
+
+extern struct kobjop_desc pci_assign_interrupt_desc;
+typedef int pci_assign_interrupt_t(device_t dev, device_t child);
+static __inline int PCI_ASSIGN_INTERRUPT(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_assign_interrupt);
+ return ((pci_assign_interrupt_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_find_extcap_desc;
+typedef int pci_find_extcap_t(device_t dev, device_t child, int capability,
+ int *capreg);
+static __inline int PCI_FIND_EXTCAP(device_t dev, device_t child,
+ int capability, int *capreg)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_find_extcap);
+ return ((pci_find_extcap_t *) _m)(dev, child, capability, capreg);
+}
+
+extern struct kobjop_desc pci_alloc_msi_desc;
+typedef int pci_alloc_msi_t(device_t dev, device_t child, int *count);
+static __inline int PCI_ALLOC_MSI(device_t dev, device_t child, int *count)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_alloc_msi);
+ return ((pci_alloc_msi_t *) _m)(dev, child, count);
+}
+
+extern struct kobjop_desc pci_alloc_msix_desc;
+typedef int pci_alloc_msix_t(device_t dev, device_t child, int *count);
+static __inline int PCI_ALLOC_MSIX(device_t dev, device_t child, int *count)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_alloc_msix);
+ return ((pci_alloc_msix_t *) _m)(dev, child, count);
+}
+
+extern struct kobjop_desc pci_remap_msix_desc;
+typedef int pci_remap_msix_t(device_t dev, device_t child, int count,
+ const u_int *vectors);
+static __inline int PCI_REMAP_MSIX(device_t dev, device_t child, int count,
+ const u_int *vectors)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_remap_msix);
+ return ((pci_remap_msix_t *) _m)(dev, child, count, vectors);
+}
+
+extern struct kobjop_desc pci_release_msi_desc;
+typedef int pci_release_msi_t(device_t dev, device_t child);
+static __inline int PCI_RELEASE_MSI(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_release_msi);
+ return ((pci_release_msi_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_msi_count_desc;
+typedef int pci_msi_count_t(device_t dev, device_t child);
+static __inline int PCI_MSI_COUNT(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_msi_count);
+ return ((pci_msi_count_t *) _m)(dev, child);
+}
+
+extern struct kobjop_desc pci_msix_count_desc;
+typedef int pci_msix_count_t(device_t dev, device_t child);
+static __inline int PCI_MSIX_COUNT(device_t dev, device_t child)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops, pci_msix_count);
+ return ((pci_msix_count_t *) _m)(dev, child);
+}
+
+#endif /* _pci_if_h_ */
--
1.7.3.4
--MP_/7kLc1vNOi9uTUCh+2Y3IB1x
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=0002-reenable-building-of-bwi.patch
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]