From: Sascha Wildner Date: Sun, 18 Aug 2013 13:53:40 +0000 (+0200) Subject: kernel/usb4bsd: Port run(4), add firmware too. X-Git-Tag: v3.7.0~528 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/10f2cea74b983f3efa36ee3cbc4d47e05c2d4d34 kernel/usb4bsd: Port run(4), add firmware too. Some minor issues might remain, but it works good here with various compatible adapters. While here, sync with FreeBSD's latest. Taken-from: FreeBSD --- diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 8355b3dc1a..7d9b6abb44 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -2241,4 +2241,9 @@ TO_REMOVE+=/usr/share/man/man8/usbcontrol.8.gz TO_REMOVE+=/boot/kernel/if_rum.ko TO_REMOVE+=/usr/share/man/cat4/rum.4.gz TO_REMOVE+=/usr/share/man/man4/rum.4.gz +TO_REMOVE+=/boot/kernel/if_run.ko +TO_REMOVE+=/usr/share/man/cat4/run.4.gz +TO_REMOVE+=/usr/share/man/man4/run.4.gz +TO_REMOVE+=/usr/share/man/cat4/runfw.4.gz +TO_REMOVE+=/usr/share/man/man4/runfw.4.gz .endif diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index de37bf747d..c4667feeed 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -504,8 +504,11 @@ MLINKS+=xe.4 if_xe.4 MLINKS+=xl.4 if_xl.4 .if defined(WANT_USB4BSD) -MAN+= rum.4 +MAN+= rum.4 \ + run.4 \ + runfw.4 MLINKS+=rum.4 if_rum.4 +MLINKS+=run.4 if_run.4 .endif .if ${MACHINE_ARCH} == "i386" diff --git a/share/man/man4/run.4 b/share/man/man4/run.4 new file mode 100644 index 0000000000..4823206a4a --- /dev/null +++ b/share/man/man4/run.4 @@ -0,0 +1,233 @@ +.\" $OpenBSD: run.4,v 1.22 2009/11/23 06:16:32 jmc Exp $ +.\" +.\" Copyright (c) 2008 Damien Bergamini +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $FreeBSD: src/share/man/man4/run.4,v 1.12 2013/02/14 01:11:38 svnexp Exp $ +.\" +.Dd August 18, 2013 +.Dt RUN 4 +.Os +.Sh NAME +.Nm run +.Nd Ralink Technology USB IEEE 802.11a/g/n wireless network device +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ehci" +.Cd "device uhci" +.Cd "device ohci" +.Cd "device usb" +.Cd "device run" +.Cd "device wlan" +.Cd "device wlan_amrr" +.Ed +.Pp +Firmware is also needed, and provided by: +.Bd -ragged -offset indent +.Cd "device runfw" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following lines in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_run_load="YES" +runfw_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver supports USB 2.0 wireless adapters based on the Ralink RT2700U, +RT2800U and RT3000U chipsets. +.Pp +The RT2700U chipset consists of two integrated chips, an RT2770 MAC/BBP and +an RT2720 (1T2R) or RT2750 (dual-band 1T2R) radio transceiver. +.Pp +The RT2800U chipset consists of two integrated chips, an RT2870 MAC/BBP and +an RT2820 (2T3R) or RT2850 (dual-band 2T3R) radio transceiver. +.Pp +The RT3000U is a single-chip solution based on an RT3070 MAC/BBP and +an RT3020 (1T1R), RT3021 (1T2R) or RT3022 (2T2R) single-band radio +transceiver. +.Pp +These are the modes the +.Nm +driver can operate in: +.Bl -tag -width "IBSS-masterXX" +.It BSS mode +Also known as +.Em infrastructure +mode, this is used when associating with an access point, through +which all traffic passes. +This mode is the default. +.It Host AP mode +In this mode the driver acts as an access point (base station) +for other cards. +.It monitor mode +In this mode the driver is able to receive packets without +associating with an access point. +This disables the internal receive filter and enables the card to +capture packets from networks which it wouldn't normally have access to, +or to scan for access points. +.El +.Pp +The +.Nm +driver can be configured to use +Wired Equivalent Privacy (WEP) or +Wi-Fi Protected Access (WPA-PSK and WPA2-PSK). +WPA is the de facto encryption standard for wireless networks. +It is strongly recommended that WEP +not be used as the sole mechanism +to secure wireless communication, +due to serious weaknesses in it. +The +.Nm +driver offloads both encryption and decryption of data frames to the +hardware for the WEP40, WEP104, TKIP(+MIC) and CCMP ciphers. +.Pp +The +.Nm +driver can be configured at runtime with +.Xr ifconfig 8 . +.Sh HARDWARE +The +.Nm +driver supports the following wireless adapters: +.Pp +.Bl -tag -width Ds -offset indent -compact +.It Airlink101 AWLL6090 +.It ASUS USB-N11 +.It ASUS USB-N13 ver. A1 +.It ASUS WL-160N +.It Belkin F5D8051 ver 3000 +.It Belkin F5D8053 +.It Belkin F5D8055 +.It Belkin F6D4050 ver 1 +.It Buffalo WLI-UC-AG300N +.It Buffalo WLI-UC-G300N +.It Buffalo WLI-UC-G301N +.It Buffalo WLI-UC-GN +.It Buffalo WLI-UC-GNM +.It Buffalo WLI-UC-GNM2 +.It Corega CG-WLUSB2GNL +.It Corega CG-WLUSB2GNR +.It Corega CG-WLUSB300AGN +.It Corega CG-WLUSB300GNM +.It D-Link DWA-130 rev B1 +.It D-Link DWA-140 rev B1, B2 +.It DrayTek Vigor N61 +.It Edimax EW-7711UAn +.It Edimax EW-7711UTn +.It Edimax EW-7717Un +.It Edimax EW-7718Un +.It Gigabyte GN-WB30N +.It Gigabyte GN-WB31N +.It Gigabyte GN-WB32L +.It Hawking HWDN1 +.It Hawking HWUN1 +.It Hawking HWUN2 +.It Hercules HWNU-300 +.It Linksys WUSB54GC v3 +.It Linksys WUSB600N +.It Logitec LAN-W150N/U2 +.It Mvix Nubbin MS-811N +.It Planex GW-USMicroN +.It Planex GW-US300MiniS +.It Sitecom WL-182 +.It Sitecom WL-188 +.It Sitecom WL-301 +.It Sitecom WL-302 +.It Sitecom WL-315 +.It SMC SMCWUSBS-N2 +.It Sweex LW303 +.It Sweex LW313 +.It Unex DNUR-81 +.It Unex DNUR-82 +.It ZyXEL NWD210N +.It ZyXEL NWD270N +.El +.Sh EXAMPLES +Join an existing BSS network (i.e., connect to an access point): +.Bd -literal -offset indent +ifconfig wlan create wlandev run0 inet 192.168.0.20 \e + netmask 0xffffff00 +.Ed +.Pp +Join a specific BSS network with network name +.Dq Li my_net : +.Pp +.Dl "ifconfig wlan create wlandev run0 ssid my_net up" +.Pp +Join a specific BSS network with 64-bit WEP encryption: +.Bd -literal -offset indent +ifconfig wlan create wlandev run0 ssid my_net \e + wepmode on wepkey 0x1234567890 weptxkey 1 up +.Ed +.Pp +Join a specific BSS network with 128-bit WEP encryption: +.Bd -literal -offset indent +ifconfig wlan create wlandev run0 wlanmode adhoc ssid my_net \e + wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 +.Ed +.Sh DIAGNOSTICS +.Bl -diag +.It "run%d: faild load firmware of file runfw" +For some reason, the driver was unable to read the microcode file from the +filesystem. +The file might be missing or corrupted. +.It "run%d: could not load 8051 microcode" +An error occurred while attempting to upload the microcode to the onboard 8051 +microcontroller unit. +.It "run%d: device timeout" +A frame dispatched to the hardware for transmission did not complete in time. +The driver will reset the hardware. +This should not happen. +.El +.Sh SEE ALSO +.Xr ifmedia 4 , +.Xr intro 4 , +.Xr netintro 4 , +.Xr runfw 4 , +.Xr usb 4 , +.Xr wlan 4 , +.Xr wlan_amrr 4 , +.Xr wlan_ccmp 4 , +.Xr wlan_tkip 4 , +.Xr wlan_wep 4 , +.Xr wlan_xauth 4 , +.Xr hostapd 8 , +.Xr ifconfig 8 , +.Xr wpa_supplicant 8 +.Pp +Ralink Technology: +.Pa http://www.ralinktech.com/ +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 4.5 . +.Sh AUTHORS +The +.Nm +driver was written by +.An Damien Bergamini Aq Mt damien@openbsd.org . +.Sh CAVEATS +The +.Nm +driver does not support any of the 802.11n capabilities offered by the +RT2800 and RT3000 chipsets. diff --git a/share/man/man4/runfw.4 b/share/man/man4/runfw.4 new file mode 100644 index 0000000000..0342a52cd9 --- /dev/null +++ b/share/man/man4/runfw.4 @@ -0,0 +1,51 @@ +.\" Copyright (c) 2010 Akinori Furukoshi +.\" Copyright (c) 2010 Warren Block +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR 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. +.\" +.\" $FreeBSD: src/share/man/man4/runfw.4,v 1.3 2012/11/17 01:50:46 svnexp Exp $ +.\" +.Dd August 18, 2013 +.Dt RUNFW 4 +.Os +.Sh NAME +.Nm runfw +.Nd "Firmware Module for Ralink driver" +.Sh SYNOPSIS +To compile this module into the kernel, place the following line in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device runfw" +.Ed +.Pp +This will include two firmware images, RT2870 and RT3071, inside the kernel. +.Xr run 4 +will load the appropriate image into the chip. +.Pp +Alternatively, to load the firmware images as a module at boot time, place +the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +runfw_load="YES" +.Ed +.Sh DESCRIPTION +This module provides firmware sets for the Ralink RT2700U, +RT2800U and RT3000U chip based USB WiFi adapters. +Please read Ralink's license, +.Pa /sys/contrib/dev/run/LICENSE . +.Sh SEE ALSO +.Xr run 4 , +.Xr firmware 9 diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4 index 7d845fc47f..40ba00533d 100644 --- a/share/man/man4/usb.4 +++ b/share/man/man4/usb.4 @@ -92,6 +92,8 @@ RealTek RTL8150 Ethernet driver NDIS miniport driver wrapper .It Xr rum 4 Ralink Technology RT2501USB/RT2601USB IEEE 802.11 driver +.It Xr run 4 +Ralink Technology RT2700U/RT2800U/RT3000U IEEE 802.11 driver .It Xr ubt 4 Bluetooth adapters .\".It Xr ural 4 diff --git a/share/man/man4/wlan.4 b/share/man/man4/wlan.4 index 8ea25523fb..686a9eb260 100644 --- a/share/man/man4/wlan.4 +++ b/share/man/man4/wlan.4 @@ -241,6 +241,7 @@ may not interoperate. .Xr ral 4 , .\".Xr rtw 4 , .Xr rum 4 , +.Xr run 4 , .\".Xr uath 4 , .\".Xr upgt 4 , .\".Xr ural 4 , diff --git a/sys/bus/u4b/Makefile b/sys/bus/u4b/Makefile index 193a1e23f6..2728343903 100644 --- a/sys/bus/u4b/Makefile +++ b/sys/bus/u4b/Makefile @@ -1,4 +1,4 @@ -#SUBDIR= controller input misc net quirk serial storage template +#SUBDIR= misc serial template SUBDIR= usb audio controller input net quirk storage wlan diff --git a/sys/bus/u4b/usbdevs b/sys/bus/u4b/usbdevs index f1c5250f9d..16f8cb7424 100644 --- a/sys/bus/u4b/usbdevs +++ b/sys/bus/u4b/usbdevs @@ -2477,6 +2477,7 @@ product LOGITEC RT2870_2 0x0163 RT2870 product LOGITEC RT2870_3 0x0164 RT2870 product LOGITEC LANW300NU2 0x0166 LAN-W300N/U2 product LOGITEC LANW150NU2 0x0168 LAN-W150N/U2 +product LOGITEC LANW300NU2S 0x0169 LAN-W300N/U2S /* Longcheer Holdings, Ltd. products */ product LONGCHEER WM66 0x6061 Longcheer WM66 HSDPA diff --git a/sys/bus/u4b/usbdevs.h b/sys/bus/u4b/usbdevs.h index 1c1721b710..f1f471fc0d 100644 --- a/sys/bus/u4b/usbdevs.h +++ b/sys/bus/u4b/usbdevs.h @@ -2484,6 +2484,7 @@ #define USB_PRODUCT_LOGITEC_RT2870_3 0x0164 /* RT2870 */ #define USB_PRODUCT_LOGITEC_LANW300NU2 0x0166 /* LAN-W300N/U2 */ #define USB_PRODUCT_LOGITEC_LANW150NU2 0x0168 /* LAN-W150N/U2 */ +#define USB_PRODUCT_LOGITEC_LANW300NU2S 0x0169 /* LAN-W300N/U2S */ /* Longcheer Holdings, Ltd. products */ #define USB_PRODUCT_LONGCHEER_WM66 0x6061 /* Longcheer WM66 HSDPA */ diff --git a/sys/bus/u4b/usbdevs_data.h b/sys/bus/u4b/usbdevs_data.h index 2cfe010796..e26dffcdbb 100644 --- a/sys/bus/u4b/usbdevs_data.h +++ b/sys/bus/u4b/usbdevs_data.h @@ -7623,6 +7623,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Logitec", "LAN-W150N/U2", }, + { + USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LANW300NU2S, + 0, + "Logitec", + "LAN-W300N/U2S", + }, { USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_WM66, 0, diff --git a/sys/bus/u4b/wlan/Makefile b/sys/bus/u4b/wlan/Makefile index 7b8e6ff843..66baeb72fd 100644 --- a/sys/bus/u4b/wlan/Makefile +++ b/sys/bus/u4b/wlan/Makefile @@ -1,3 +1,3 @@ -SUBDIR= rum +SUBDIR= rum run runfw .include diff --git a/sys/bus/u4b/wlan/if_run.c b/sys/bus/u4b/wlan/if_run.c index b9784709d5..01bb7cbcd4 100644 --- a/sys/bus/u4b/wlan/if_run.c +++ b/sys/bus/u4b/wlan/if_run.c @@ -14,11 +14,10 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: src/sys/dev/usb/wlan/if_run.c,v 1.40 2013/03/19 02:17:34 svnexp Exp $ */ -#include -__FBSDID("$FreeBSD$"); - /*- * Ralink Technology RT2700U/RT2800U/RT3000U chipset driver. * http://www.ralinktech.com/ @@ -28,7 +27,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -39,10 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include #include #include @@ -52,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -59,22 +55,20 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include -#include +#include +#include +#include +#include -#include -#include -#include "usbdevs.h" +#include +#include +#include #define USB_DEBUG_VAR run_debug -#include - -#include -#include +#include -#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#include +#include #ifdef USB_DEBUG #define RUN_DEBUG @@ -136,6 +130,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(ASUS, RT2870_5), RUN_DEV(ASUS, USBN13), RUN_DEV(ASUS, RT3070_1), + RUN_DEV(ASUS, USB_N53), RUN_DEV(ASUS2, USBN11), RUN_DEV(AZUREWAVE, RT2870_1), RUN_DEV(AZUREWAVE, RT2870_2), @@ -209,6 +204,8 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(LOGITEC, RT2870_2), RUN_DEV(LOGITEC, RT2870_3), RUN_DEV(LOGITEC, LANW300NU2), + RUN_DEV(LOGITEC, LANW150NU2), + RUN_DEV(LOGITEC, LANW300NU2S), RUN_DEV(MELCO, RT2870_1), RUN_DEV(MELCO, RT2870_2), RUN_DEV(MELCO, WLIUCAG300N), @@ -216,6 +213,7 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(MELCO, WLIUCG301N), RUN_DEV(MELCO, WLIUCGN), RUN_DEV(MELCO, WLIUCGNM), + RUN_DEV(MELCO, WLIUCGNM2), RUN_DEV(MOTOROLA4, RT2770), RUN_DEV(MOTOROLA4, RT3070), RUN_DEV(MSI, RT3070_1), @@ -379,8 +377,9 @@ static int run_tx_param(struct run_softc *, struct mbuf *, const struct ieee80211_bpf_params *); static int run_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void run_start(struct ifnet *); -static int run_ioctl(struct ifnet *, u_long, caddr_t); +static void run_start_locked(struct ifnet *); +static void run_start(struct ifnet *, struct ifaltq_subque *); +static int run_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); static void run_set_agc(struct run_softc *, uint8_t); static void run_select_chan_group(struct run_softc *, int); static void run_set_rx_antenna(struct run_softc *, int); @@ -553,18 +552,21 @@ run_attach(device_t self) uint32_t ver; int i, ntries, error; uint8_t iface_index, bands; + char ethstr[ETHER_ADDRSTRLEN + 1]; + + wlan_serialize_enter(); device_set_usb_desc(self); sc->sc_udev = uaa->device; sc->sc_dev = self; - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), - MTX_NETWORK_LOCK, MTX_DEF); + lockinit(&sc->sc_lock, device_get_nameunit(sc->sc_dev), + 0, LK_CANRECURSE); iface_index = RT2860_IFACE_INDEX; error = usbd_transfer_setup(uaa->device, &iface_index, - sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_mtx); + sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_lock); if (error) { device_printf(self, "could not allocate USB transfers, " "err=%s\n", usbd_errstr(error)); @@ -598,13 +600,7 @@ run_attach(device_t self) device_printf(sc->sc_dev, "MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n", sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev), - sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid)); - - if ((error = run_load_microcode(sc)) != 0) { - device_printf(sc->sc_dev, "could not load 8051 microcode\n"); - RUN_UNLOCK(sc); - goto detach; - } + sc->ntxchains, sc->nrxchains, kether_ntoa(sc->sc_bssid, ethstr)); RUN_UNLOCK(sc); @@ -621,9 +617,10 @@ run_attach(device_t self) ifp->if_init = run_init; ifp->if_ioctl = run_ioctl; ifp->if_start = run_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); + ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); +#if 0 /* XXX swildner: see c3d4131842e47b168d93a0650d58d425ebeef789 */ + ifq_set_ready(&ifp->if_snd); +#endif ic->ic_ifp = ifp; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -664,7 +661,7 @@ run_attach(device_t self) sc->rf_rev == RT2860_RF_2850 || sc->rf_rev == RT3070_RF_3052) { /* set supported .11a rates */ - for (i = 14; i < nitems(rt2860_rf2850); i++) { + for (i = 14; i < NELEM(rt2860_rf2850); i++) { uint8_t chan = rt2860_rf2850[i].chan; ic->ic_channels[ic->ic_nchans].ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A); @@ -699,14 +696,16 @@ run_attach(device_t self) TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc); TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc); - callout_init((struct callout *)&sc->ratectl_ch, 1); + usb_callout_init_mtx(&sc->ratectl_ch, &sc->sc_lock, 1); if (bootverbose) ieee80211_announce(ic); + wlan_serialize_exit(); return (0); detach: + wlan_serialize_exit(); run_detach(self); return (ENXIO); } @@ -719,6 +718,9 @@ run_detach(device_t self) struct ieee80211com *ic; int i; + wlan_serialize_enter(); + sc->sc_detached = 1; + /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER); @@ -742,8 +744,9 @@ run_detach(device_t self) if_free(ifp); } - mtx_destroy(&sc->sc_mtx); + lockuninit(&sc->sc_lock); + wlan_serialize_exit(); return (0); } @@ -795,8 +798,8 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, return (NULL); } - rvp = (struct run_vap *) malloc(sizeof(struct run_vap), - M_80211_VAP, M_WAITOK | M_ZERO); + rvp = (struct run_vap *) kmalloc(sizeof(struct run_vap), + M_80211_VAP, M_INTWAIT | M_ZERO); if (rvp == NULL) return (NULL); vap = &rvp->vap; @@ -881,7 +884,7 @@ run_vap_delete(struct ieee80211vap *vap) ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); - free(rvp, M_80211_VAP); + kfree(rvp, M_80211_VAP); } /* @@ -973,10 +976,14 @@ run_load_microcode(struct run_softc *sc) int ntries, error; const uint64_t *temp; uint64_t bytes; + int wlan_serialized; - RUN_UNLOCK(sc); + wlan_serialized = IS_SERIALIZED(&wlan_global_serializer); + if (wlan_serialized) + wlan_serialize_exit(); fw = firmware_get("runfw"); - RUN_LOCK(sc); + if (wlan_serialized) + wlan_serialize_enter(); if (fw == NULL) { device_printf(sc->sc_dev, "failed loadfirmware of file %s\n", "runfw"); @@ -1023,7 +1030,7 @@ run_load_microcode(struct run_softc *sc) USETW(req.wValue, 8); USETW(req.wIndex, 0); USETW(req.wLength, 0); - if ((error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)) + if ((error = usbd_do_request(sc->sc_udev, &sc->sc_lock, &req, NULL)) != 0) { device_printf(sc->sc_dev, "firmware reset failed\n"); goto fail; @@ -1050,8 +1057,9 @@ run_load_microcode(struct run_softc *sc) error = ETIMEDOUT; goto fail; } - device_printf(sc->sc_dev, "firmware %s loaded\n", - (base == fw->data) ? "RT2870" : "RT3071"); + device_printf(sc->sc_dev, "firmware %s ver. %u.%u loaded\n", + (base == fw->data) ? "RT2870" : "RT3071", + *(base + 4092), *(base + 4093)); fail: firmware_put(fw, FIRMWARE_UNLOAD); @@ -1062,13 +1070,15 @@ int run_reset(struct run_softc *sc) { usb_device_request_t req; + usb_error_t error; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = RT2870_RESET; USETW(req.wValue, 1); USETW(req.wIndex, 0); USETW(req.wLength, 0); - return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); + error = usbd_do_request(sc->sc_udev, &sc->sc_lock, &req, NULL); + return (error); } static usb_error_t @@ -1081,7 +1091,7 @@ run_do_request(struct run_softc *sc, RUN_LOCK_ASSERT(sc, MA_OWNED); while (ntries--) { - err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, + err = usbd_do_request_flags(sc->sc_udev, &sc->sc_lock, req, data, 0, NULL, 250 /* ms */); if (err == 0) break; @@ -1240,7 +1250,7 @@ run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) USETW(req.wIndex, addr); USETW(req.wLength, sizeof tmp); - error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &tmp); + error = usbd_do_request(sc->sc_udev, &sc->sc_lock, &req, &tmp); if (error == 0) *val = le16toh(tmp); else @@ -1694,7 +1704,7 @@ run_read_eeprom(struct run_softc *sc) static struct ieee80211_node * run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) { - return malloc(sizeof (struct run_node), M_DEVBUF, M_WAITOK | M_ZERO); + return kmalloc(sizeof (struct run_node), M_DEVBUF, M_WAITOK | M_ZERO); } static int @@ -1734,7 +1744,7 @@ run_media_change(struct ifnet *ifp) #if 0 if ((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)){ + (ifp->if_flags & IFF_RUNNING)){ run_init_locked(sc); } #endif @@ -1763,7 +1773,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_state_name[ostate], ieee80211_state_name[nstate]); - IEEE80211_UNLOCK(ic); RUN_LOCK(sc); ratectl = sc->ratectl_run; /* remember current state */ @@ -1835,6 +1844,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (vap->iv_opmode != IEEE80211_M_MONITOR) { struct ieee80211_node *ni; + if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) + return (-1); run_updateslot(ic->ic_ifp); run_enable_mrr(sc); run_set_txpreamble(sc); @@ -1867,7 +1878,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); RUN_UNLOCK(sc); - IEEE80211_LOCK(ic); return(rvp->newstate(vap, nstate, arg)); } @@ -1932,7 +1942,8 @@ run_wme_update(struct ieee80211com *ic) { struct run_softc *sc = ic->ic_ifp->if_softc; - /* sometime called wothout lock */ +#if 0 /* XXX swildner */ + /* sometime called without lock */ if (mtx_owned(&ic->ic_comlock.mtx)) { uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); DPRINTF("cmdq_store=%d\n", i); @@ -1941,6 +1952,7 @@ run_wme_update(struct ieee80211com *ic) ieee80211_runtask(ic, &sc->cmdq_task); return (0); } +#endif RUN_LOCK(sc); run_wme_update_cb(ic); @@ -2016,7 +2028,8 @@ run_key_set_cb(void *arg) wcid = 0; /* NB: update WCID0 for group keys */ base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix); } else { - wcid = RUN_AID2WCID(associd); + wcid = (vap->iv_opmode == IEEE80211_M_STA) ? + 1 : RUN_AID2WCID(associd); base = RT2860_PKEY(wcid); } @@ -2371,8 +2384,12 @@ run_newassoc(struct ieee80211_node *ni, int isnew) struct run_softc *sc = ic->ic_ifp->if_softc; uint8_t rate; uint8_t ridx; - uint8_t wcid = RUN_AID2WCID(ni->ni_associd); + uint8_t wcid; int i, j; + char ethstr[ETHER_ADDRSTRLEN + 1]; + + wcid = (vap->iv_opmode == IEEE80211_M_STA) ? + 1 : RUN_AID2WCID(ni->ni_associd); if (wcid > RT2870_WCID_MAX) { device_printf(sc->sc_dev, "wcid=%d out of range\n", wcid); @@ -2396,7 +2413,7 @@ run_newassoc(struct ieee80211_node *ni, int isnew) } DPRINTF("new assoc isnew=%d associd=%x addr=%s\n", - isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr)); + isnew, ni->ni_associd, kether_ntoa(ni->ni_macaddr, ethstr)); for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; @@ -2528,8 +2545,8 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) struct run_rx_radiotap_header *tap = &sc->sc_rxtap; tap->wr_flags = 0; - tap->wr_chan_freq = htole16(ic->ic_bsschan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_bsschan->ic_flags); + tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); + tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wr_antsignal = rssi; tap->wr_antenna = ant; tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant); @@ -2579,8 +2596,8 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) DPRINTFN(15, "rx done, actlen=%d\n", xferlen); - if (xferlen < sizeof (uint32_t) + - sizeof (struct rt2860_rxwi) + sizeof (struct rt2870_rxd)) { + if (xferlen < (int)(sizeof(uint32_t) + + sizeof(struct rt2860_rxwi) + sizeof(struct rt2870_rxd))) { DPRINTF("xfer too short %d\n", xferlen); goto tr_setup; } @@ -2592,7 +2609,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) case USB_ST_SETUP: tr_setup: if (sc->rx_m == NULL) { - sc->rx_m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, + sc->rx_m = m_getjcl(MB_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE /* xfer can be bigger than MCLBYTES */); } if (sc->rx_m == NULL) { @@ -2645,11 +2662,12 @@ tr_setup: for(;;) { dmalen = le32toh(*mtod(m, uint32_t *)) & 0xffff; - if ((dmalen == 0) || ((dmalen & 3) != 0)) { + if ((dmalen >= (uint32_t)-8) || (dmalen == 0) || + ((dmalen & 3) != 0)) { DPRINTF("bad DMA length %u\n", dmalen); break; } - if ((dmalen + 8) > xferlen) { + if ((dmalen + 8) > (uint32_t)xferlen) { DPRINTF("bad DMA length %u > %d\n", dmalen + 8, xferlen); break; @@ -2665,7 +2683,7 @@ tr_setup: } /* copy aggregated frames to another mbuf */ - m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m0 = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m0 == NULL)) { DPRINTF("could not allocate mbuf\n"); ifp->if_ierrors++; @@ -2733,7 +2751,7 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, unsigned int ind data = usbd_xfer_get_priv(xfer); run_tx_free(pq, data, 0); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + ifq_clr_oactive(&ifp->if_snd); usbd_xfer_set_priv(xfer, NULL); @@ -2782,8 +2800,8 @@ tr_setup: tap->wt_flags = 0; tap->wt_rate = rt2860_rates[data->ridx].rate; - tap->wt_chan_freq = htole16(vap->iv_bss->ni_chan->ic_freq); - tap->wt_chan_flags = htole16(vap->iv_bss->ni_chan->ic_flags); + tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); + tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_hwqueue = index; if (le16toh(txwi->phy) & RT2860_PHY_SHPRE) tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; @@ -2799,9 +2817,7 @@ tr_setup: usbd_transfer_submit(xfer); - RUN_UNLOCK(sc); - run_start(ifp); - RUN_LOCK(sc); + run_start_locked(ifp); break; @@ -2965,7 +2981,9 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) uint8_t xflags = 0; int hasqos; +#if 0 /* XXX swildner: lock needed? */ RUN_LOCK_ASSERT(sc, MA_OWNED); +#endif wh = mtod(m, struct ieee80211_frame *); @@ -3040,8 +3058,12 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) txd->flags = qflags; txwi = (struct rt2860_txwi *)(txd + 1); txwi->xflags = xflags; - txwi->wcid = IEEE80211_IS_MULTICAST(wh->i_addr1) ? - 0 : RUN_AID2WCID(ni->ni_associd); + if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { + txwi->wcid = 0; + } else { + txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ? + 1 : RUN_AID2WCID(ni->ni_associd); + } /* clear leftover garbage bits */ txwi->flags = 0; txwi->txop = 0; @@ -3097,7 +3119,9 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) STAILQ_INSERT_TAIL(&sc->sc_epq[qid].tx_qh, data, next); + RUN_LOCK(sc); usbd_transfer_start(sc->sc_xfer[qid]); + RUN_UNLOCK(sc); DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", m->m_pkthdr.len + (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)), @@ -3143,7 +3167,7 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (sc->sc_epq[0].tx_nfree == 0) { /* let caller free mbuf */ - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + ifq_set_oactive(&ifp->if_snd); return (EIO); } data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh); @@ -3215,7 +3239,7 @@ run_sendprot(struct run_softc *sc, /* check that there are free slots before allocating the mbuf */ if (sc->sc_epq[0].tx_nfree == 0) { /* let caller free mbuf */ - sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE; + ifq_set_oactive(&sc->sc_ifp->if_snd); return (ENOBUFS); } @@ -3310,7 +3334,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni, if (sc->sc_epq[0].tx_nfree == 0) { /* let caller free mbuf */ - sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE; + ifq_set_oactive(&sc->sc_ifp->if_snd); DPRINTF("sending raw frame, but tx ring is full\n"); return (EIO); } @@ -3356,7 +3380,7 @@ run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, RUN_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(ifp->if_flags & IFF_RUNNING)) { error = ENETDOWN; goto done; } @@ -3392,56 +3416,65 @@ done: } static void -run_start(struct ifnet *ifp) +run_start_locked(struct ifnet *ifp) { struct run_softc *sc = ifp->if_softc; struct ieee80211_node *ni; - struct mbuf *m; - - RUN_LOCK(sc); + struct mbuf *m = NULL; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - RUN_UNLOCK(sc); + if ((ifp->if_flags & IFF_RUNNING) == 0) { + wlan_serialize_exit(); return; } for (;;) { /* send data frames */ - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + m = ifq_dequeue(&ifp->if_snd); if (m == NULL) break; ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (run_tx(sc, m, ni) != 0) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + ifq_prepend(&ifp->if_snd, m); + ifq_set_oactive(&ifp->if_snd); break; } } +} - RUN_UNLOCK(sc); +static void +run_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) +{ + ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); + run_start_locked(ifp); } static int -run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) { struct run_softc *sc = ifp->if_softc; struct ieee80211com *ic = sc->sc_ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; int startall = 0; - int error = 0; + int error; + + RUN_LOCK(sc); + error = sc->sc_detached ? ENXIO : 0; + RUN_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: RUN_LOCK(sc); if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){ + if (!(ifp->if_flags & IFF_RUNNING)){ startall = 1; run_init_locked(sc); } else run_update_promisc_locked(ifp); } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && + if (ifp->if_flags & IFF_RUNNING && (ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) { run_stop(sc); } @@ -3971,6 +4004,8 @@ run_update_beacon_cb(void *arg) if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) return; + if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) + return; /* * No need to call ieee80211_beacon_update(), run_update_beacon() @@ -4107,7 +4142,7 @@ run_update_promisc(struct ifnet *ifp) { struct run_softc *sc = ifp->if_softc; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((ifp->if_flags & IFF_RUNNING) == 0) return; RUN_LOCK(sc); @@ -4311,7 +4346,7 @@ run_bbp_init(struct run_softc *sc) return (ETIMEDOUT); /* initialize BBP registers to default values */ - for (i = 0; i < nitems(rt2860_def_bbp); i++) { + for (i = 0; i < NELEM(rt2860_def_bbp); i++) { run_bbp_write(sc, rt2860_def_bbp[i].reg, rt2860_def_bbp[i].val); } @@ -4346,12 +4381,12 @@ run_rt3070_rf_init(struct run_softc *sc) /* initialize RF registers to default value */ if (sc->mac_ver == 0x3572) { - for (i = 0; i < nitems(rt3572_def_rf); i++) { + for (i = 0; i < NELEM(rt3572_def_rf); i++) { run_rt3070_rf_write(sc, rt3572_def_rf[i].reg, rt3572_def_rf[i].val); } } else { - for (i = 0; i < nitems(rt3070_def_rf); i++) { + for (i = 0; i < NELEM(rt3070_def_rf); i++) { run_rt3070_rf_write(sc, rt3070_def_rf[i].reg, rt3070_def_rf[i].val); } @@ -4677,6 +4712,11 @@ run_init_locked(struct run_softc *sc) run_stop(sc); + if (run_load_microcode(sc) != 0) { + device_printf(sc->sc_dev, "could not load 8051 microcode\n"); + goto fail; + } + for (ntries = 0; ntries < 100; ntries++) { if (run_read(sc, RT2860_ASIC_VER_ID, &tmp) != 0) goto fail; @@ -4729,7 +4769,7 @@ run_init_locked(struct run_softc *sc) run_write(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); } - for (i = 0; i < nitems(rt2870_def_mac); i++) + for (i = 0; i < NELEM(rt2870_def_mac); i++) run_write(sc, rt2870_def_mac[i].reg, rt2870_def_mac[i].val); run_write(sc, RT2860_WMM_AIFSN_CFG, 0x00002273); run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344); @@ -4837,8 +4877,8 @@ run_init_locked(struct run_softc *sc) /* turn radio LED on */ run_set_leds(sc, RT2860_LED_RADIO); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifq_clr_oactive(&ifp->if_snd); + ifp->if_flags |= IFF_RUNNING; sc->cmdq_run = RUN_CMDQ_GO; for (i = 0; i != RUN_N_XFER; i++) @@ -4866,7 +4906,7 @@ run_init(void *arg) run_init_locked(sc); RUN_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (ifp->if_flags & IFF_RUNNING) ieee80211_start_all(ic); } @@ -4881,10 +4921,11 @@ run_stop(void *arg) RUN_LOCK_ASSERT(sc, MA_OWNED); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (ifp->if_flags & IFF_RUNNING) run_set_leds(sc, 0); /* turn all LEDs off */ - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + ifp->if_flags &= ~IFF_RUNNING; + ifq_clr_oactive(&ifp->if_snd); sc->ratectl_run = RUN_RATECTL_OFF; sc->cmdq_run = sc->cmdq_key_set; @@ -4935,8 +4976,10 @@ run_stop(void *arg) static void run_delay(struct run_softc *sc, unsigned int ms) { - usb_pause_mtx(mtx_owned(&sc->sc_mtx) ? - &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms)); + zsleep(sc, &wlan_global_serializer, 0, "rundelay", + USB_MS_TO_TICKS(ms)); +// usb_pause_mtx(lockowned(&sc->sc_lock) ? +// &sc->sc_lock : NULL, USB_MS_TO_TICKS(ms)); } static device_method_t run_methods[] = { @@ -4944,14 +4987,13 @@ static device_method_t run_methods[] = { DEVMETHOD(device_probe, run_match), DEVMETHOD(device_attach, run_attach), DEVMETHOD(device_detach, run_detach), - DEVMETHOD_END }; static driver_t run_driver = { - "run", - run_methods, - sizeof(struct run_softc) + .name = "run", + .methods = run_methods, + .size = sizeof(struct run_softc) }; static devclass_t run_devclass; diff --git a/sys/bus/u4b/wlan/if_runvar.h b/sys/bus/u4b/wlan/if_runvar.h index 8ee3679437..aa9ac95db1 100644 --- a/sys/bus/u4b/wlan/if_runvar.h +++ b/sys/bus/u4b/wlan/if_runvar.h @@ -17,7 +17,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD$ + * $FreeBSD: src/sys/dev/usb/wlan/if_runvar.h,v 1.10 2013/02/11 00:34:54 svnexp Exp $ */ #ifndef _IF_RUNVAR_H_ @@ -205,7 +205,7 @@ struct run_softc { uint8_t sc_bssid[6]; - struct mtx sc_mtx; + struct lock sc_lock; struct run_endpoint_queue sc_epq[RUN_EP_QUEUES]; @@ -239,6 +239,7 @@ struct run_softc { uint8_t sta_running; uint8_t rvp_cnt; uint8_t rvp_bmap; + uint8_t sc_detached; union { struct run_rx_radiotap_header th; @@ -255,8 +256,8 @@ struct run_softc { int sc_txtap_len; }; -#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) +#define RUN_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE) +#define RUN_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE) +#define RUN_LOCK_ASSERT(sc, t) KKASSERT(lockstatus(&(sc)->sc_lock, curthread) != 0) #endif /* _IF_RUNVAR_H_ */ diff --git a/sys/bus/u4b/wlan/run/Makefile b/sys/bus/u4b/wlan/run/Makefile new file mode 100644 index 0000000000..1552fd4459 --- /dev/null +++ b/sys/bus/u4b/wlan/run/Makefile @@ -0,0 +1,34 @@ +# +# $FreeBSD: src/sys/modules/usb/run/Makefile,v 1.2 2012/11/17 01:53:01 svnexp Exp $ +# +# Copyright (c) 2010 Hans Petter Selasky. 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. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +.PATH: ${.CURDIR}/.. + +KMOD= if_run +SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h \ + if_run.c + +.include diff --git a/sys/bus/u4b/wlan/runfw/Makefile b/sys/bus/u4b/wlan/runfw/Makefile new file mode 100644 index 0000000000..210d843fd0 --- /dev/null +++ b/sys/bus/u4b/wlan/runfw/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD: src/sys/modules/runfw/Makefile,v 1.3 2012/11/17 01:52:59 svnexp Exp $ + +KMOD= runfw +FIRMWS= runfw:runfw:1 + +CLEANFILES= runfw + +runfw: ${.CURDIR}/../../../../contrib/dev/run/rt2870.fw.uu + uudecode -p ${.CURDIR}/../../../../contrib/dev/run/rt2870.fw.uu > ${.TARGET} + +.include diff --git a/sys/conf/files b/sys/conf/files index 8c6990e580..b69786f520 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2234,6 +2234,21 @@ bus/u4b/net/if_udav.c optional udav uether usb4bsd # USB WLAN drivers # bus/u4b/wlan/if_rum.c optional rum usb4bsd +bus/u4b/wlan/if_run.c optional run usb4bsd +runfw.c optional runfw usb4bsd \ + compile-with "${AWK} -f $S/tools/fw_stub.awk run.fw:runfw -mrunfw -c${.TARGET}" \ + no-implicit-rule before-depend local \ + clean "runfw.c" +runfw.fwo optional runfw usb4bsd \ + dependency "run.fw" \ + compile-with "${NORMAL_FWO}" \ + no-implicit-rule \ + clean "runfw.fwo" +run.fw optional runfw usb4bsd \ + dependency "$S/contrib/dev/run/rt2870.fw.uu" \ + compile-with "${NORMAL_FW}" \ + no-obj no-implicit-rule \ + clean "run.fw" # # USB input drivers # diff --git a/sys/config/LINT b/sys/config/LINT index 8f20829f6d..c95ba44ab6 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -2209,6 +2209,9 @@ device rue # # Ralink Technology RT2501USB/RT2601USB device rum +# Ralink Technology RT2700U/RT2800U/RT3000U wireless driver +device run +device runfw # # Ralink Technology RT2500USB #device ural diff --git a/sys/config/LINT64 b/sys/config/LINT64 index da840782c0..df3bba8bf6 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -2040,6 +2040,9 @@ device rue # # Ralink Technology RT2501USB/RT2601USB device rum +# Ralink Technology RT2700U/RT2800U/RT3000U wireless driver +device run +device runfw # # Ralink Technology RT2500USB #device ural diff --git a/sys/contrib/dev/run/LICENSE b/sys/contrib/dev/run/LICENSE new file mode 100644 index 0000000000..ba790789d8 --- /dev/null +++ b/sys/contrib/dev/run/LICENSE @@ -0,0 +1,39 @@ +Copyright (c) 2007, Ralink Technology Corporation +All rights reserved. + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +* Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of Ralink Technology Corporation nor the names of its + suppliers may be used to endorse or promote products derived from this + software without specific prior written permission. +* No reverse engineering, decompilation, or disassembly of this software + is permitted. + +Limited patent license. Ralink Technology Corporation grants a world-wide, +royalty-free, non-exclusive license under patents it now or hereafter +owns or controls to make, have made, use, import, offer to sell and +sell ("Utilize") this software, but solely to the extent that any +such patent is necessary to Utilize the software alone, or in +combination with an operating system licensed under an approved Open +Source license as listed by the Open Source Initiative at +http://opensource.org/licenses. The patent license shall not apply to +any other combinations which include this software. No hardware per +se is licensed hereunder. + +DISCLAIMER. 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 MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/sys/contrib/dev/run/rt2870.fw.uu b/sys/contrib/dev/run/rt2870.fw.uu new file mode 100644 index 0000000000..872fbea80e --- /dev/null +++ b/sys/contrib/dev/run/rt2870.fw.uu @@ -0,0 +1,232 @@ +# Copyright (c) 2007, Ralink Technology Corporation +# All rights reserved. +# +# Redistribution. Redistribution and use in binary form, without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions must reproduce the above copyright notice and the +# following disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Ralink Technology Corporation nor the names of its +# suppliers may be used to endorse or promote products derived from this +# software without specific prior written permission. +# * No reverse engineering, decompilation, or disassembly of this software +# is permitted. +# +# Limited patent license. Ralink Technology Corporation grants a world-wide, +# royalty-free, non-exclusive license under patents it now or hereafter +# owns or controls to make, have made, use, import, offer to sell and +# sell ("Utilize") this software, but solely to the extent that any +# such patent is necessary to Utilize the software alone, or in +# combination with an operating system licensed under an approved Open +# Source license as listed by the Open Source Initiative at +# http://opensource.org/licenses. The patent license shall not apply to +# any other combinations which include this software. No hardware per +# se is licensed hereunder. +# +# DISCLAIMER. 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 MERCHANTABILITY AND +# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# This file contains two 4KB firmware, first half is RT2870 and last half +# is RT3071. On each 4KB firmware, the last 2 bytes are CRC, 3rd last byte +# is minor version number and 4th last byte is major version number. +# This file comes with +# RT2870 v. 0.236 +# RT3071 v. 0.236 +begin 644 rt2870.fw.uu +M____`A`H`A`R`A!]`A.[`A.\`A/;`A/@$A/<(@(8V@(:&@(5/`(4=S`%!B`- +M`Q(:_R*0`8S@,.,@Y5@PX!#E3##@!']`@`)_`)`0+^_PD`&,=`CPY)`!I_"0 +M`8S@,.`!4#_4ZY4>T"0CE.K0#`^3U +M1N5'M`H(Y3JT`0/D]4;D_:]6$@N1T@0BD'`1X/3_D'`0X%__D'`1X%4G3Y!P +M&/"0D`(I +M\#!'!*\G@`3E)_3_D`(H[_#E5O1P`P(3N@(3LY!P$.#^D'`1X/WM^.;U5_VO +M5A(+D9`$%'2`\.20#][?6"CH/@]5?] +MKU82"Y&0!!1T@/#DD'`3\.56]'`#`A.Z`A.SD!``X/57Y/58]5F0$`/@M"@% +M=5@!@#R0$`/@M#`%=5@"@#"0$`/@M#,%=5@$@"20$`/@M#4,D!`"X+1R!758 +M"(`1D!`#X+0U"I`0`N"TDP-U6!#E6##A&9`%".!$`?#]D`4%X%3[\$0$\.U4 +M_I`%"/#D]4[U3W4Z_W4\_ZU7KU82"Y'DD'`R\,(6]5SU6O5;D'`P\*/PD`04 +M=(#PY)!P$_#E5O1P`P(3NH!WD'`0X"3_DI/D_:]6$@N1D`04=(#PY)!P$_#E +M5O1@7X!6D'`0X"3_DDK2!:U7KU82"Y&0!!1T@/#DD'`3\.56]&`\@#.0#U7*U7KU82"Y&0!!1T@/"0<##E6O"CY5OPY/5:]5N00<"7@1`'P(B+E4W`:,&`)LDTP300%1L($Y4]%3F`(Y4\53W`"%4XB(L)" +MTR(P%#"0#_D'`9X/[O7I`"*?`P1P2O)X`$Y2?T +M_Y`"*._PPA0P%F#"KY`0!.#U5Y`"*.!4!?57Y5QD`7`AY5>0$`0PX`;@5/OP +M@`3@1`3PY50$`3@1`3PTJ\BPDO"3.5$$@J=%)D`%2<$%2,(%0,0%*T@%,U@ +M%-Z@```5*85(0X5*0H5,7N5'9`9@`P(5*8`;Y4C$5`_U0^5*Q%0/]4+E3,14 +M#_5>Y4=D!G!A4T,/@%R%24.%2T*%35[E1V0&<$V`&^5)Q%0/]4/E2\14#_5" +MY4W$5`_U7N5'9`9P,.5#5`]$$/5#@";E1V0$8`7E1[0%!D->!'5"">5'M`80 +MY4-4#T0P]4.`!M)+@`+23.3U)>5"Q%3P_^5#5`]/]5_28"+2%>5')/5@"R3+ +M8`PA7"K\($TJ\BPJ^0!!3@5`Y@!-(8@`CE3D5/)/^2 +M&-*OD`04X*+DDAET'O#E7U0/]2WE)7`3,!@%Y5\@Y0LP&1GE7U0P_[\P$>4E +M<`5U)0R``A4ETFS2;8`/Y5\PY@;";-)M@`32;,)MY4=D`W`A,$L&PFS2;8`8 +MY25P`S!,$<),Y25P!74E!X`"%272;-)MY4>T"13E1"#C"^4Z9`)@!>4ZM`,$ +MPFS2;>5'M`H3Y3JT`0;";-)M@`CE.G`$TFS";2!I!^5>(.`"LF@@:P?E7B#A +M`K)J(&T'Y5X@X@*R;'4N0"!I!*)H@"8P:`;E1J+B@!WE7B#@!'\!@`)_`.5& +M5/#^OO`$?@&``GX`[F\D_Y)SDG(@:P2B:H`F,&H&Y4:BXH`=Y5X@X01_`8`" +M?P#E1E3P_K[P!'X!@`)^`.YO)/^2=9)T(&T$HFR`)N5'9`IP(C!L!N5&HN.` +M%^4ZM`$&Y4:BXX`TY48@Y`,PY0/3@`'#@"8P;`;E1J+B@!WE7B#B!'\!@`)_ +M`.5&5/#^OO`$?@&``GX`[F\D_Y)QDG"0$`#@D!`L\)`0`^##E#!`%*)QDG>B +M<))VY2X3$U0_]2["=])VD!`OY2[PY4=D!G!'D`(HX#!'`_^``O3_CR>0`BG@ +M5/[PY4/$5`\48`PD_F`,)`-P$\(X@`_2.(`+Y48PX@/3@`'#DC@P1P6O)P(8 +MG^4G]/\"&)_E1V0'8`_E1V0(8`GE1V0)8`,"&`V0`BC@,$<#_X`"]/^/)Y`" +M*>!4_/#E.A1@(A1@)11@+23\8$DD^6`4)`YP4.5&$Q-4/W7P`X3E\"3_@#K2 +M.<(X@#[E1C#B`].`'<.`&N5&,.(-5#C#E#!0!GX`?P&`!'X`?P#N3R3_DCC" +M.8`3Y48PX@/3@`'#DCG".(`$PCC".3!'!*\G@`3E)_3_`AB?Y4=D#&`)Y4=D +M"V`#`ABDD`(HX#!'`_^``O3_CR>0`BG@5/WPY3H48"`48"$48"LD_&!%)/E@ +M$B0.<$KE1A,35#]U\`.$Y?"`*=(Y@#KE1C#B`].``<.2.8`MY48PX@U4.,.4 +M,%`&?@!_`8`$?@!_`.Y/)/^2.8`/Y48PX@/3@`'#DCF``L(Y,$<$KR>`!.4G +M]/^0`BCO\"+E1[0+$)`"*>!4Z_#E)U3K147U)R+DD`(I\#!'!*]%@`3E1?3_ +MD`(H[_`BCU#262*/5-)8(N3U8L*OY5$48$@48&8D`F`#`AG^TEEU50&0`J+@ +M5'_PH^`@YR.0!#3@M`(CX+0"$G\@$AC0D!`$X%3S\'51`0(9_N50 +M<`9U8@,"&?Z0$@#@5`-P$G\@$AC0D`*BX%2_\'51`@(9_N50<`,"&?F0`J/@ +M,.8#`AGUD`0WX&0B8`,"&?60`8IT?O"0`9;PD!($=`KPY5@PXQ7DD`4`\*-T +M"/"C=`'P=`/P?P$2#2J0$RC@D'`:\)`3*>"0!4\X`1X%3[\(`4Y3STD!,J8`C@ +M5/)%//"`!.!4^O"0!`'@5/WP=6(!=54"Y/51@`GE4'`%=6(#]5'E8F`5P@'D +M]5'"6:UBKT`2&LOE8K0#`M(#TJ\BPJ\P`1+DD`&6\/51PEG"`7T"KT`2&LOE +M4A1@#`1@`P(:R'52`755`Y`$`>!$#O#E6%088!Z03^=!0N]8+D-'#U@^"T_QET%"[U@N0T +M\)`0'.#U8I`0'N`@X?.0$!S@D'`H\)`0'>"0<"GPD!`> +MX)!P*O`P2@>0<"3@1`'PP@72KR(B(@`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````.SQ +M2O___P(0*`(0,@(0?0(3NP(3O`(3VP(3X!(3W"("&-H"&AH"%3P"%'"T"`9U3@%U3X20`D_Y)'(I`$!.`EX"1=]5>0T#`B0#T_Y!P$.!?_Y!P$>!5)T^0 +M#_D'`9X/[O7I`" +M*?`P1P2O)X`$Y2?T_Y`"*._PY5;T<`,"$[H"$[.0#][?CF]5?] +MKU82"ZJ0!!1T@/#DD'`3\.56]'`#`A.Z`A.SD'`0X/Z0WU@HZ#X/57 +M_:]6$@NJD`04=(#PY)!P$_#E5O1P`P(3N@(3LY`0`.#U5^3U6/59D!`#X+0H +M!758`8`\D!`#X+0P!758`H`PD!`#X+0S!758!(`DD!`#X+0U#)`0`N"T<@5U +M6`B`$9`0`^"T-0J0$`+@M),#=5@0Y5@PX1F0!0C@1`'P_9`%!>!4^_!$!/#M +M5/Z0!0CPY/5.]4]U.O]U//^M5Z]6$@NJY)!P,O#"%O5<]5KU6Y!P,/"C\)`$ +M%'2`\.200`BG@_Y!P&>#^[UZ0`BGP,$<$KR>`!.4G +M]/^0`BCO\,(4,!9@PJ^0$`3@]5>0`BC@5`7U5^5<9`%P(>57D!`$,.`&X%3[ +M\(`$X$0$\.57,.(Q!5OE6W`K!5J`)^57,.`;Y5R0$`1P!N!4^_"`!.!$!/`% +M6^5;<`L%6H`'D!`$X$0$\-*O(L)+PDSE1!(*MA29`!4G!!4C"!4#$!2M(!3- +M8!3>H```%2F%2$.%2D*%3%[E1V0&8`,"%2F`&^5(Q%0/]4/E2L14#_5"Y4S$ +M5`_U7N5'9`9P85-##X!Y4=D!G!-@!OE2<14#_5#Y4O$5`_U +M0N5-Q%0/]5[E1V0&<##E0U0/1!#U0X`FY4=D!&`%Y4>T!09#7@1U0@GE1[0& +M$.5#5`]$,/5#@`;22X`"TDSD]27E0L14\/_E0U0/3_5?TF`BTA7E1R3U8`LD +MRV`')$!P!L(5(A(8I1(57L(5PJ_"!-*O(L*OD`04X%0.8`32&(`(Y4Y%3R3_ +MDAC2KY`$%."BY)(9=![PY5]4#_4MY25P$S`8!>5?(.4+,!D9Y5]4,/^_,!'E +M)7`%=24,@`(5)=)LTFV`#^5?,.8&PFS2;8`$TFS";>5'9`-P(3!+!L)LTFV` +M&.4E<`,P3!'"3.4E<`5U)0>``A4ETFS2;>5'M`D4Y40@XPOE.F0"8`7E.K0# +M!,)LTFWE1[0*$^4ZM`$&PFS2;8`(Y3IP!-)LPFT@:0?E7B#@`K)H(&L'Y5X@ +MX0*R:B!M!^5>(.("LFQU+D`@:02B:(`F,&@&Y4:BXH`=Y5X@X`1_`8`"?P#E +M1E3P_K[P!'X!@`)^`.YO)/^25>(.$$?P&` +M`G\`Y494\/Z^\`1^`8`"?@#N;R3_DG62="!M!*)L@";E1V0*<"(P;`;E1J+C +M@!?E.K0!!N5&HN.`-.5&(.0#,.4#TX`!PX`F,&P&Y4:BXH`=Y5X@X@1_`8`" +M?P#E1E3P_K[P!'X!@`)^`.YO)/^2<9)PD!``X)`0+/"0$`/@PY0P0!2B<9)W +MHG"2=N4N$Q-4/_4NPG?2=I`0+^4N\.5'9`9P1Y`"*.`P1P/_@`+T_X\GD`(I +MX%3^\.5#Q%0/%&`,)/Y@#"0#0 +M`BG@5/SPY3H48"(48"448"TD_&!))/E@%"0.<%#E1A,35#]U\`.$Y?`D_X`Z +MTCG".(`^Y48PX@/3@!W#@!KE1C#B#50XPY0P4`9^`'\!@`1^`'\`[D\D_Y(X +MPCF`$^5&,.(#TX`!PY(YPCB`!,(XPCDP1P2O)X`$Y2?T_P(8G^5'9`Q@">5' +M9`M@`P(8I)`"*.`P1P/_@`+T_X\GD`(IX%3]\.4Z%&`@%&`A%&`K)/Q@123Y +M8!(D#G!*Y483$U0_=?`#A.7P@"G2.8`ZY48PX@/3@`'#DCF`+>5&,.(-5#C# +ME#!0!GX`?P&`!'X`?P#N3R3_DCF`#^5&,.(#TX`!PY(Y@`+".3!'!*\G@`3E +M)_3_D`(H[_`BY4>T"Q"0`BG@5.OPY2=4ZT5%]2!4^_"`%.4\])`3*F`( +MX%3R13SP@`3@5/KPD`0!X%3]\'5B`755`N3U48`)Y5!P!75B`_51Y6)@%<(! +MY/51PEFM8J]`$AK+Y6*T`P+2`]*O(L*O,`$2Y)`!EO#U4<)9P@%]`J]`$AK+ +MY5(48`P$8`,"&LAU4@%U50.0!`'@1`[PY5A4&&`>D'`:X)`3*/"0"0$!WPD'`JX)`0'O"0$!S@]6*0$![@(.'SD!`