看板 DFBSD_kernel 關於我們 聯絡資訊
--MP_/7kLc1vNOi9uTUCh+2Y3IB1x Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi, since I had a few hours of free coding time at hand last night and was in need of a wlan card for a server, I decided to try bringing the if_bwi driver back into head. I therefore backported the changes from freebsd and changed the locking procedure to use the wlan_serialize calls. Right now the module compiles and can be loadded correctly. The firmware is however not loaded / found. Does anyone Have a pointer to what I might be doing wrong there ? The changes I made are attached as patch files, if anyone else wants to try them. Greetings, Tobias --MP_/7kLc1vNOi9uTUCh+2Y3IB1x Content-Type: text/x-patch Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0001-Bring-in-bwi-driver-changes-from-freebsd.patch From a8ec7a056c71ca4cc6e9fef1eb96809d07cc4fb7 Mon Sep 17 00:00:00 2001 From: Jost Tobias Springenberg <k-gee@wrfl.de> Date: Wed, 5 Jan 2011 06:10:45 +0100 Subject: [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, &regs, 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);
檔案過大!部分文章無法顯示
- 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 From da30d4db3c911b0ec0feaab0ce837db5e626bc87 Mon Sep 17 00:00:00 2001 From: Jost Tobias Springenberg <k-gee@wrfl.de> Date: Wed, 5 Jan 2011 06:14:19 +0100 Subject: [PATCH 2/3] reenable building of bwi --- sys/dev/netif/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/netif/Makefile b/sys/dev/netif/Makefile index 9e51736..95968fc 100644 --- a/sys/dev/netif/Makefile +++ b/sys/dev/netif/Makefile @@ -1,13 +1,13 @@ # $DragonFly: src/sys/dev/netif/Makefile,v 1.34 2008/07/26 14:26:30 sephe Exp $ # -SUBDIR= an age alc ale ar ath aue axe bce bfe bge \ +SUBDIR= an age alc ale ar ath aue axe bce bfe bge bwi \ cue dc ed em ep et e1000 fwe \ fxp ic iwi iwn jme kue lge lnc mii_layer my msk mxge nfe nge pcn \ ral re rl rue sbni sbsh sf sis sk sln sr ste stge ti tl tx txp \ vge vr vx wb wi wpi xe xl ig_hal emx ae # XXX need to be updated to the new net80211 stack -# SUBDIR= acx bwi iwl rtw rum ural +# SUBDIR= acx iwl rtw rum ural .include <bsd.subdir.mk> -- 1.7.3.4 --MP_/7kLc1vNOi9uTUCh+2Y3IB1x Content-Type: text/x-patch Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0003-change-bwi-driver-to-use-wlan_serialize_enter-exit-a.patch From e822f4f73c38de6a22d25aa459da1d701dc386f4 Mon Sep 17 00:00:00 2001 From: Jost Tobias Springenberg <k-gee@wrfl.de> Date: Wed, 5 Jan 2011 16:10:59 +0100 Subject: [PATCH 3/3] change bwi driver to use wlan_serialize_enter/exit and fix some small bugs --- sys/dev/netif/bwi/Makefile | 5 +- sys/dev/netif/bwi/bwimac.c | 10 ++-- sys/dev/netif/bwi/if_bwi.c | 90 ++++++++++++++++++---------------------- sys/dev/netif/bwi/if_bwi_pci.c | 23 +++++++++- sys/dev/netif/bwi/if_bwivar.h | 11 ----- 5 files changed, 69 insertions(+), 70 deletions(-) diff --git a/sys/dev/netif/bwi/Makefile b/sys/dev/netif/bwi/Makefile index acaf2d9..71c8f75 100644 --- a/sys/dev/netif/bwi/Makefile +++ b/sys/dev/netif/bwi/Makefile @@ -1,7 +1,8 @@ # $DragonFly: src/sys/dev/netif/bwi/Makefile,v 1.2 2007/09/30 12:32:20 sephe Exp $ KMOD = if_bwi -SRCS = if_bwi.c bwimac.c bwiphy.c bwirf.c -SRCS += device_if.h bus_if.h pci_if.h +SRCS = if_bwi.c bwimac.c bwiphy.c bwirf.c if_bwi_pci.c +SRCS += bitops.h bus_if.h bwimac.h bwiphy.h bwirf.h device_if.h if_bwireg.h if_bwivar.h pci_if.h + .include <bsd.kmod.mk> diff --git a/sys/dev/netif/bwi/bwimac.c b/sys/dev/netif/bwi/bwimac.c index 288a41a..144dffb 100644 --- a/sys/dev/netif/bwi/bwimac.c +++ b/sys/dev/netif/bwi/bwimac.c @@ -883,7 +883,7 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) * module would be loaded automatically */ if (mac->mac_stub == NULL) { - snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH, + ksnprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH, sc->sc_fw_version); mac->mac_stub = firmware_get(fwname); if (mac->mac_stub == NULL) { @@ -893,7 +893,7 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) } if (mac->mac_ucode == NULL) { - snprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH, + ksnprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH, sc->sc_fw_version, mac->mac_rev >= 5 ? 5 : mac->mac_rev); @@ -908,7 +908,7 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) } if (mac->mac_pcm == NULL) { - snprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH, + ksnprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH, sc->sc_fw_version, mac->mac_rev < 5 ? 4 : 5); @@ -934,7 +934,7 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) return ENODEV; } - snprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH, + ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH, sc->sc_fw_version, idx); mac->mac_iv = firmware_get(fwname); @@ -960,7 +960,7 @@ bwi_mac_fw_alloc(struct bwi_mac *mac) return ENODEV; } - snprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH, + ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH, sc->sc_fw_version, idx); mac->mac_iv_ext = firmware_get(fwname); diff --git a/sys/dev/netif/bwi/if_bwi.c b/sys/dev/netif/bwi/if_bwi.c index 902fa01..c887684 100644 --- a/sys/dev/netif/bwi/if_bwi.c +++ b/sys/dev/netif/bwi/if_bwi.c @@ -349,7 +349,7 @@ bwi_attach(struct bwi_softc *sc) struct sysctl_ctx_list *ctx; struct sysctl_oid *tree; - BWI_LOCK_INIT(sc); + wlan_serialize_enter(); /* * Initialize taskq and various tasks @@ -360,6 +360,7 @@ bwi_attach(struct bwi_softc *sc) device_get_nameunit(dev)); TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc); + callout_init(&sc->sc_calib_ch); /* * Initialize sysctl variables */ @@ -451,7 +452,7 @@ bwi_attach(struct bwi_softc *sc) ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_maxlen = ifqmaxlen; ifq_set_ready(&ifp->if_snd); - //callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0); + callout_init(&sc->sc_watchdog_timer); /* * Setup ratesets, phytype, channels and get MAC address @@ -560,10 +561,11 @@ bwi_attach(struct bwi_softc *sc) #endif if (bootverbose) ieee80211_announce(ic); - + + wlan_serialize_exit(); return (0); fail: - BWI_LOCK_DESTROY(sc); + wlan_serialize_exit(); return (error); } @@ -575,6 +577,8 @@ bwi_detach(struct bwi_softc *sc) int i; bwi_stop(sc, 1); + + wlan_serialize_enter(); callout_stop(&sc->sc_led_blink_ch); callout_stop(&sc->sc_calib_ch); callout_stop(&sc->sc_watchdog_timer); @@ -588,7 +592,7 @@ bwi_detach(struct bwi_softc *sc) if_free(ifp); taskqueue_free(sc->sc_tq); - BWI_LOCK_DESTROY(sc); + wlan_serialize_exit(); return (0); } @@ -604,7 +608,7 @@ bwi_vap_create(struct ieee80211com *ic, if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap), + bvp = (struct bwi_vap *) kmalloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO); if (bvp == NULL) return NULL; @@ -634,7 +638,7 @@ bwi_vap_delete(struct ieee80211vap *vap) ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); - free(bvp, M_80211_VAP); + kfree(bvp, M_80211_VAP); } void @@ -1218,9 +1222,9 @@ bwi_init(void *xsc) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - BWI_LOCK(sc); + wlan_serialize_enter(); bwi_init_statechg(sc, 1); - BWI_UNLOCK(sc); + wlan_serialize_exit(); if (ifp->if_flags & IFF_RUNNING) ieee80211_start_all(ic); /* start all vap's */ @@ -1312,7 +1316,7 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *ucred) switch (cmd) { case SIOCSIFFLAGS: - BWI_LOCK(sc); + wlan_serialize_enter(); if (IS_RUNNING(ifp)) { struct bwi_mac *mac; int promisc = -1; @@ -1345,7 +1349,7 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *ucred) if (ifp->if_flags & IFF_RUNNING) bwi_stop_locked(sc, 1); } - BWI_UNLOCK(sc); + wlan_serialize_exit(); if (startall) ieee80211_start_all(ic); break; @@ -1366,11 +1370,11 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *ucred) static void bwi_start(struct ifnet *ifp) { - struct bwi_softc *sc = ifp->if_softc; - - BWI_LOCK(sc); + //struct bwi_softc *sc = ifp->if_softc; + + wlan_serialize_enter(); bwi_start_locked(ifp); - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static void @@ -1450,7 +1454,7 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return ENETDOWN; } - BWI_LOCK(sc); + wlan_serialize_enter(); idx = tbd->tbd_idx; KASSERT(tbd->tbd_buf[idx].tb_mbuf == NULL, ("slot %d not empty", idx)); if (params == NULL) { @@ -1477,7 +1481,7 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, ieee80211_free_node(ni); ifp->if_oerrors++; } - BWI_UNLOCK(sc); + wlan_serialize_exit(); return error; } @@ -1489,7 +1493,6 @@ bwi_watchdog(void *arg) 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++; @@ -1501,9 +1504,9 @@ bwi_watchdog(void *arg) static void bwi_stop(struct bwi_softc *sc, int statechg) { - BWI_LOCK(sc); + wlan_serialize_enter(); bwi_stop_locked(sc, statechg); - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static void @@ -1513,8 +1516,6 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg) struct bwi_mac *mac; int i, error, pwr_off = 0; - BWI_ASSERT_LOCKED(sc); - callout_stop(&sc->sc_calib_ch); callout_stop(&sc->sc_led_blink_ch); sc->sc_led_blinking = 0; @@ -1565,11 +1566,8 @@ bwi_intr(void *xsc) uint32_t txrx_intr_status[BWI_TXRX_NRING]; int i, txrx_error, tx = 0, rx_data = -1; - BWI_LOCK(sc); - if ((ifp->if_flags & IFF_RUNNING) == 0 || (sc->sc_flags & BWI_F_STOP)) { - BWI_UNLOCK(sc); return; } /* @@ -1577,7 +1575,6 @@ bwi_intr(void *xsc) */ intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); if (intr_status == 0xffffffff) { /* Not for us */ - BWI_UNLOCK(sc); return; } @@ -1585,7 +1582,6 @@ bwi_intr(void *xsc) intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); if (intr_status == 0) { /* Nothing is interesting */ - BWI_UNLOCK(sc); return; } @@ -1650,7 +1646,6 @@ bwi_intr(void *xsc) if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { if_printf(ifp, "%s: intr PHY TX error\n", __func__); taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); - BWI_UNLOCK(sc); return; } } @@ -1679,7 +1674,6 @@ bwi_intr(void *xsc) 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; } } @@ -1717,7 +1711,6 @@ bwi_intr(void *xsc) bwi_led_event(sc, evt); } - BWI_UNLOCK(sc); } static void @@ -1725,10 +1718,10 @@ bwi_scan_start(struct ieee80211com *ic) { struct bwi_softc *sc = ic->ic_ifp->if_softc; - BWI_LOCK(sc); + wlan_serialize_enter(); /* Enable MAC beacon promiscuity */ CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static void @@ -1738,7 +1731,7 @@ bwi_set_channel(struct ieee80211com *ic) struct ieee80211_channel *c = ic->ic_curchan; struct bwi_mac *mac; - BWI_LOCK(sc); + wlan_serialize_enter(); 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; @@ -1754,7 +1747,7 @@ bwi_set_channel(struct ieee80211com *ic) sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = htole16(c->ic_flags & 0xffff); - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static void @@ -1762,9 +1755,9 @@ bwi_scan_end(struct ieee80211com *ic) { struct bwi_softc *sc = ic->ic_ifp->if_softc; - BWI_LOCK(sc); + wlan_serialize_enter(); CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static int @@ -1779,7 +1772,7 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) struct bwi_mac *mac; int error; - BWI_LOCK(sc); + wlan_serialize_enter(); callout_stop(&sc->sc_calib_ch); @@ -1833,7 +1826,7 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc); } back: - BWI_UNLOCK(sc); + wlan_serialize_exit(); return error; } @@ -2078,7 +2071,7 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, bus_size_t dma_size; int error; - st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT | M_ZERO); + st = kmalloc(sizeof(*st), M_DEVBUF, M_NOWAIT | M_ZERO); if (st == NULL) { device_printf(sc->sc_dev, "can't allocate txstats data\n"); return ENOMEM; @@ -2200,7 +2193,7 @@ bwi_dma_txstats_free(struct bwi_softc *sc) bus_dma_tag_destroy(st->stats_dtag); } - free(st, M_DEVBUF); + kfree(st, M_DEVBUF); } static void @@ -2625,6 +2618,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx) int idx, rx_data = 0; idx = rbd->rbd_idx; + //wlan_serialize_enter(); while (idx != end_idx) { struct bwi_rxbuf *rb = &rbd->rbd_buf[idx]; struct bwi_rxbuf_hdr *hdr; @@ -2680,7 +2674,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx) m_adj(m, -IEEE80211_CRC_LEN); - BWI_UNLOCK(sc); + wlan_serialize_exit(); wh = mtod(m, struct ieee80211_frame_min *); ni = ieee80211_find_rxnode(ic, wh); @@ -2694,7 +2688,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx) sc->sc_rx_rate = rate; } - BWI_LOCK(sc); + wlan_serialize_enter(); next: idx = (idx + 1) % BWI_RX_NDESC; @@ -3740,7 +3734,7 @@ bwi_updateslot(struct ifnet *ifp) struct ieee80211com *ic = ifp->if_l2com; struct bwi_mac *mac; - BWI_LOCK(sc); + wlan_serialize_enter(); if (ifp->if_flags & IFF_RUNNING) { DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__); @@ -3750,7 +3744,7 @@ bwi_updateslot(struct ifnet *ifp) bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT)); } - BWI_UNLOCK(sc); + wlan_serialize_exit(); } static void @@ -3763,8 +3757,6 @@ bwi_calibrate(void *xsc) #endif struct bwi_mac *mac; - BWI_ASSERT_LOCKED(sc); - KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR, ("opmode %d", ic->ic_opmode)); @@ -3900,7 +3892,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_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);*/ + callout_init(&sc->sc_led_blink_ch); } static __inline uint16_t @@ -4059,10 +4051,10 @@ bwi_restart(void *xsc, int pending) struct ifnet *ifp = sc->sc_ifp; if_printf(ifp, "%s begin, help!\n", __func__); - BWI_LOCK(sc); + wlan_serialize_enter(); bwi_init_statechg(xsc, 0); #if 0 bwi_start_locked(ifp); #endif - BWI_UNLOCK(sc); + wlan_serialize_exit(); } diff --git a/sys/dev/netif/bwi/if_bwi_pci.c b/sys/dev/netif/bwi/if_bwi_pci.c index 973e01d..0c1130a 100644 --- a/sys/dev/netif/bwi/if_bwi_pci.c +++ b/sys/dev/netif/bwi/if_bwi_pci.c @@ -100,16 +100,19 @@ bwi_pci_probe(device_t dev) { const struct bwi_dev *b; uint16_t did, vid; - + + wlan_serialize_enter(); 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); + wlan_serialize_exit(); return BUS_PROBE_DEFAULT; } } + wlan_serialize_exit(); return ENXIO; } @@ -117,9 +120,12 @@ static int bwi_pci_attach(device_t dev) { struct bwi_pci_softc *psc = device_get_softc(dev); - struct bwi_softc *sc = &psc->sc_sc; + struct bwi_softc *sc; int error = ENXIO; + wlan_serialize_enter(); + + sc = &psc->sc_sc; sc->sc_dev = dev; /* @@ -169,8 +175,9 @@ bwi_pci_attach(device_t dev) sc->sc_pci_subvid = pci_get_subvendor(dev); sc->sc_pci_subdid = pci_get_subdevice(dev); + wlan_serialize_exit(); error = bwi_attach(sc); - if (error == 0) /* success */ + if (error == 0) /* success */ return 0; bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); @@ -179,6 +186,7 @@ bad2: bad1: bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, sc->sc_mem_res); bad: + wlan_serialize_exit(); return (error); } @@ -188,16 +196,22 @@ bwi_pci_detach(device_t dev) struct bwi_pci_softc *psc = device_get_softc(dev); struct bwi_softc *sc = &psc->sc_sc; + wlan_serialize_enter(); + /* check if device was removed */ sc->sc_invalid = !bus_child_present(dev); + wlan_serialize_exit(); bwi_detach(sc); + wlan_serialize_enter(); 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); + + wlan_serialize_exit(); return (0); } @@ -208,6 +222,7 @@ bwi_pci_shutdown(device_t dev) struct bwi_pci_softc *psc = device_get_softc(dev); bwi_shutdown(&psc->sc_sc); + return (0); } @@ -251,4 +266,6 @@ 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 */ +#if 0 MODULE_DEPEND(bwi, wlan_amrr, 1, 1, 1); +#endif diff --git a/sys/dev/netif/bwi/if_bwivar.h b/sys/dev/netif/bwi/if_bwivar.h index 49a07a9..a15f1b6 100644 --- a/sys/dev/netif/bwi/if_bwivar.h +++ b/sys/dev/netif/bwi/if_bwivar.h @@ -666,17 +666,6 @@ 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 *); -- 1.7.3.4 --MP_/7kLc1vNOi9uTUCh+2Y3IB1x--