svn commit: r253789 - in head: share/man/man4 sys/conf sys/dev/usb/wlan sys/modules/usb sys/modules/usb/rsu
Rui Paulo
rpaulo at FreeBSD.org
Tue Jul 30 02:07:59 UTC 2013
Author: rpaulo
Date: Tue Jul 30 02:07:57 2013
New Revision: 253789
URL: http://svnweb.freebsd.org/changeset/base/253789
Log:
Import OpenBSD's rsu(4) WLAN driver.
Support chipsets are the Realtek RTL8188SU, RTL8191SU, and RTL8192SU.
Many thanks to Idwer Vollering for porting/writing the man page and for
testing.
Reviewed by: adrian, hselasky
Obtained from: OpenBSD
Tested by: kevlo, Idwer Vollering <vidwer at gmail.com>
Added:
head/share/man/man4/rsu.4 (contents, props changed)
head/share/man/man4/rsufw.4 (contents, props changed)
head/sys/dev/usb/wlan/if_rsu.c (contents, props changed)
head/sys/dev/usb/wlan/if_rsureg.h (contents, props changed)
head/sys/modules/usb/rsu/
head/sys/modules/usb/rsu/Makefile (contents, props changed)
Modified:
head/share/man/man4/Makefile
head/sys/conf/NOTES
head/sys/conf/WITHOUT_SOURCELESS_UCODE
head/sys/conf/files
head/sys/modules/usb/Makefile
Modified: head/share/man/man4/Makefile
==============================================================================
--- head/share/man/man4/Makefile Mon Jul 29 21:45:39 2013 (r253788)
+++ head/share/man/man4/Makefile Tue Jul 30 02:07:57 2013 (r253789)
@@ -385,6 +385,8 @@ MAN= aac.4 \
rndtest.4 \
route.4 \
rp.4 \
+ rsu.4 \
+ rsufw.4 \
rue.4 \
rum.4 \
run.4 \
Added: head/share/man/man4/rsu.4
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/share/man/man4/rsu.4 Tue Jul 30 02:07:57 2013 (r253789)
@@ -0,0 +1,178 @@
+.\" $OpenBSD: rsu.4,v 1.11 2013/02/14 07:40:42 jmc Exp $
+.\" $FreeBSD$
+.\"
+.\" Copyright (c) 2010 Damien Bergamini <damien.bergamini at free.fr>
+.\"
+.\" 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.
+.\"
+.Dd July 29 2013
+.Dt RSU 4
+.Os
+.Sh NAME
+.Nm rsu
+.Nd Realtek RTL8188SU/RTL8192SU USB IEEE 802.11b/g/n wireless network device
+.Sh SYNOPSIS
+.\.Cd "rsu* at uhub? port ?"
+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 rsu"
+.Cd "device wlan"
+.Ed
+.Pp
+Alternatively, to load the driver as a module at boot time,
+place the following line in
+.Xr loader.conf 5:
+.Bd -literal -offset indent
+.Xr if_rsu_load="YES"
+.Ed
+.Pp
+After you have read the license in /usr/share/doc/legal/realtek
+you will want to add the following lines to
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+legal.realtek.license_ack=1
+rsu-rtl8712fw_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver supports USB 2.0 wireless network devices based on Realtek
+RTL8188SU, RTL8191SU and RTL8192SU chipsets.
+.Pp
+The RTL8188SU is a highly integrated 802.11n adapter that combines
+a MAC, a 1T1R capable baseband and an RF in a single chip.
+It operates in the 2GHz spectrum only.
+.Pp
+The RTL8191SU is a highly integrated multiple-in, single-out (MISO)
+802.11n adapter that combines a MAC, a 1T2R capable baseband and an
+RF in a single chip.
+It operates in the 2GHz spectrum only.
+.Pp
+The RTL8192SU is a highly integrated multiple-in, multiple-out (MIMO)
+802.11n adapter that combines a MAC, a 2T2R capable baseband and an
+RF in a single chip.
+It operates in the 2GHz spectrum only.
+.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.
+.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.
+.Pp
+The
+.Nm
+driver can be configured at runtime with
+.Xr ifconfig 8
+or on boot with
+.Xr hostname 1 .
+.Sh FILES
+The driver needs at least version 1.2 of the following firmware file,
+which is loaded when an interface is attached:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It /boot/kernel/rsu-rtl8712fw.ko
+.El
+.Sh HARDWARE
+The following adapters should work:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It ASUS USB-N10
+.It Belkin F7D1101 v1
+.It D-Link DWA-131 A1
+.It EDUP EP-MS150N(W)
+.It Hercules HWGUn-54
+.It Hercules HWNUm-300
+.It Planex GW-USNano
+.It Sitecom WL-349 v1
+.It Sitecom WL-353
+.It Sweex LW154
+.It TRENDnet TEW-648UB
+.It TRENDnet TEW-649UB
+.Sh EXAMPLES
+Join an existing BSS network (i.e., connect to an access point):
+.Bd -literal -offset indent
+ifconfig wlan create wlandev rsu0 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 rsu0 ssid my_net up"
+.Pp
+Join a specific BSS network with 64-bit WEP encryption:
+.Bd -literal -offset indent
+ifconfig wlan create wlandev rsu0 ssid my_net \e
+ wepmode on wepkey 0x1234567890 weptxkey 1 up
+.Ed
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "%s: failed load firmware of file rsu-rtl8712fw"
+For some reason, the driver was unable to read the microcode file from the
+filesystem.
+The file might be missing or corrupted.
+.It "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 arp 8 ,
+.Xr intro 1 ,
+.Xr netintro 4 ,
+.Xr usb 3 ,
+.Xr hostname 1 ,
+.Xr ifconfig 8,
+.Xr wlan 4 ,
+.Xr rsufw 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.9 and
+.Fx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Damien Bergamini Aq damien at openbsd.org
+and ported by
+.An Rui Paulo Aq rpaulo at freebsd.org .
+.Sh CAVEATS
+The
+.Nm
+driver does not support any of the 802.11n capabilities offered by the
+adapters.
Added: head/share/man/man4/rsufw.4
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/share/man/man4/rsufw.4 Tue Jul 30 02:07:57 2013 (r253789)
@@ -0,0 +1,46 @@
+.\" $FreeBSD$
+.\" Copyright (c) 2013 Idwer Vollering <vidwer at gmail.com>
+.\"
+.\" 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.
+.\"
+.Dd July 21, 2013
+.Dt RSUFW 4
+.Os
+.Sh NAME
+.Nm rsufw
+.Nd "Firmware Module for Realtek 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 rsufw"
+.Ed
+.Pp
+This will include the firmware image, RTL8712, inside the kernel.
+.Xr rsu 4
+will load the 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
+rsu-rtl8712fw_load="YES"
+.Ed
+.Sh DESCRIPTION
+This module provides the firmware for the Realtek RTL8188SU and
+RTL8192SU chip based USB WiFi adapters.
+Please read Realtek's license,
+.Pa /usr/share/license/realtek .
+.Sh SEE ALSO
+.Xr rsu 4 ,
+.Xr firmware 9
Modified: head/sys/conf/NOTES
==============================================================================
--- head/sys/conf/NOTES Mon Jul 29 21:45:39 2013 (r253788)
+++ head/sys/conf/NOTES Tue Jul 30 02:07:57 2013 (r253789)
@@ -2739,6 +2739,8 @@ device mos
# HSxPA devices from Option N.V
device uhso
+# Realtek RTL8188SU/RTL8191SU/RTL8192SU wireless driver
+device rsu
#
# Ralink Technology RT2501USB/RT2601USB wireless driver
device rum
Modified: head/sys/conf/WITHOUT_SOURCELESS_UCODE
==============================================================================
--- head/sys/conf/WITHOUT_SOURCELESS_UCODE Mon Jul 29 21:45:39 2013 (r253788)
+++ head/sys/conf/WITHOUT_SOURCELESS_UCODE Tue Jul 30 02:07:57 2013 (r253789)
@@ -35,8 +35,11 @@ nodevice ds1
nodevice maestro3
# usb
+nodevice rsu
+nodevice rsufw
nodevice rum
nodevice uath
nodevice zyd
nodevice kue
+nodevice urtwn
nodevice urtwnfw
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Mon Jul 29 21:45:39 2013 (r253788)
+++ head/sys/conf/files Tue Jul 30 02:07:57 2013 (r253789)
@@ -2312,6 +2312,21 @@ dev/usb/net/uhso.c optional uhso
#
# USB WLAN drivers
#
+dev/usb/wlan/if_rsu.c optional rsu
+rsu-rtl8712fw.c optional rsu-rtl8712fw | rsufw \
+ compile-with "${AWK} -f $S/tools/fw_stub.awk rsu-rtl8712fw.fw:rsu-rtl8712fw:120 -mrsu-rtl8712fw -c${.TARGET}" \
+ no-implicit-rule before-depend local \
+ clean "rsu-rtl8712fw.c"
+rsu-rtl8712fw.fwo optional rsu-rtl8712fw | rsufw \
+ dependency "rsu-rtl8712fw.fw" \
+ compile-with "${NORMAL_FWO}" \
+ no-implicit-rule \
+ clean "rsu-rtl8712fw.fwo"
+rsu-rtl8712fw.fw optional rsu-rtl8712.fw | rsufw \
+ dependency "$S/contrib/dev/rsu/rsu-rtl8712fw.fw.uu" \
+ compile-with "${NORMAL_FW}" \
+ no-obj no-implicit-rule \
+ clean "rsu-rtl8712fw.fw"
dev/usb/wlan/if_rum.c optional rum
dev/usb/wlan/if_run.c optional run
runfw.c optional runfw \
Added: head/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/usb/wlan/if_rsu.c Tue Jul 30 02:07:57 2013 (r253789)
@@ -0,0 +1,2479 @@
+/* $OpenBSD: if_rsu.c,v 1.17 2013/04/15 09:23:01 mglocker Exp $ */
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini at free.fr>
+ *
+ * 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Driver for Realtek RTL8188SU/RTL8191SU/RTL8192SU.
+ *
+ * TODO:
+ * o 11n support
+ * o h/w crypto
+ * o hostap / ibss / mesh
+ */
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/firmware.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR rsu_debug
+#include <dev/usb/usb_debug.h>
+
+#include <dev/usb/wlan/if_rsureg.h>
+
+#ifdef USB_DEBUG
+static int rsu_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, rsu, CTLFLAG_RW, 0, "USB rsu");
+SYSCTL_INT(_hw_usb_rsu, OID_AUTO, debug, CTLFLAG_RW, &rsu_debug, 0,
+ "Debug level");
+#endif
+
+static const STRUCT_USB_HOST_ID rsu_devs[] = {
+#define RSU_HT_NOT_SUPPORTED 0
+#define RSU_HT_SUPPORTED 1
+#define RSU_DEV_HT(v,p) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
+ RSU_HT_SUPPORTED) }
+#define RSU_DEV(v,p) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
+ RSU_HT_NOT_SUPPORTED) }
+ RSU_DEV(ASUS, RTL8192SU),
+ RSU_DEV(AZUREWAVE, RTL8192SU_4),
+ RSU_DEV_HT(ACCTON, RTL8192SU),
+ RSU_DEV_HT(ASUS, USBN10),
+ RSU_DEV_HT(AZUREWAVE, RTL8192SU_1),
+ RSU_DEV_HT(AZUREWAVE, RTL8192SU_2),
+ RSU_DEV_HT(AZUREWAVE, RTL8192SU_3),
+ RSU_DEV_HT(AZUREWAVE, RTL8192SU_5),
+ RSU_DEV_HT(BELKIN, RTL8192SU_1),
+ RSU_DEV_HT(BELKIN, RTL8192SU_2),
+ RSU_DEV_HT(BELKIN, RTL8192SU_3),
+ RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_1),
+ RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_2),
+ RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_3),
+ RSU_DEV_HT(COREGA, RTL8192SU),
+ RSU_DEV_HT(DLINK2, DWA131A1),
+ RSU_DEV_HT(DLINK2, RTL8192SU_1),
+ RSU_DEV_HT(DLINK2, RTL8192SU_2),
+ RSU_DEV_HT(EDIMAX, RTL8192SU_1),
+ RSU_DEV_HT(EDIMAX, RTL8192SU_2),
+ RSU_DEV_HT(EDIMAX, RTL8192SU_3),
+ RSU_DEV_HT(GUILLEMOT, HWGUN54),
+ RSU_DEV_HT(GUILLEMOT, HWNUM300),
+ RSU_DEV_HT(HAWKING, RTL8192SU_1),
+ RSU_DEV_HT(HAWKING, RTL8192SU_2),
+ RSU_DEV_HT(PLANEX2, GWUSNANO),
+ RSU_DEV_HT(REALTEK, RTL8171),
+ RSU_DEV_HT(REALTEK, RTL8172),
+ RSU_DEV_HT(REALTEK, RTL8173),
+ RSU_DEV_HT(REALTEK, RTL8174),
+ RSU_DEV_HT(REALTEK, RTL8192SU),
+ RSU_DEV_HT(REALTEK, RTL8712),
+ RSU_DEV_HT(REALTEK, RTL8713),
+ RSU_DEV_HT(SENAO, RTL8192SU_1),
+ RSU_DEV_HT(SENAO, RTL8192SU_2),
+ RSU_DEV_HT(SITECOMEU, WL349V1),
+ RSU_DEV_HT(SITECOMEU, WL353),
+ RSU_DEV_HT(SWEEX2, LW154),
+#undef RSU_DEV_HT
+#undef RSU_DEV
+};
+
+static device_probe_t rsu_match;
+static device_attach_t rsu_attach;
+static device_detach_t rsu_detach;
+static usb_callback_t rsu_bulk_tx_callback;
+static usb_callback_t rsu_bulk_rx_callback;
+static usb_error_t rsu_do_request(struct rsu_softc *,
+ struct usb_device_request *, void *);
+static struct ieee80211vap *
+ rsu_vap_create(struct ieee80211com *, const char name[],
+ int, enum ieee80211_opmode, int, const uint8_t bssid[],
+ const uint8_t mac[]);
+static void rsu_vap_delete(struct ieee80211vap *);
+static void rsu_scan_start(struct ieee80211com *);
+static void rsu_scan_end(struct ieee80211com *);
+static void rsu_set_channel(struct ieee80211com *);
+static void rsu_update_mcast(struct ifnet *);
+static int rsu_alloc_rx_list(struct rsu_softc *);
+static void rsu_free_rx_list(struct rsu_softc *);
+static int rsu_alloc_tx_list(struct rsu_softc *);
+static void rsu_free_tx_list(struct rsu_softc *);
+static void rsu_free_list(struct rsu_softc *, struct rsu_data [], int);
+static struct rsu_data *_rsu_getbuf(struct rsu_softc *);
+static struct rsu_data *rsu_getbuf(struct rsu_softc *);
+static int rsu_write_region_1(struct rsu_softc *, uint16_t, uint8_t *,
+ int);
+static void rsu_write_1(struct rsu_softc *, uint16_t, uint8_t);
+static void rsu_write_2(struct rsu_softc *, uint16_t, uint16_t);
+static void rsu_write_4(struct rsu_softc *, uint16_t, uint32_t);
+static int rsu_read_region_1(struct rsu_softc *, uint16_t, uint8_t *,
+ int);
+static uint8_t rsu_read_1(struct rsu_softc *, uint16_t);
+static uint16_t rsu_read_2(struct rsu_softc *, uint16_t);
+static uint32_t rsu_read_4(struct rsu_softc *, uint16_t);
+static int rsu_fw_iocmd(struct rsu_softc *, uint32_t);
+static uint8_t rsu_efuse_read_1(struct rsu_softc *, uint16_t);
+static int rsu_read_rom(struct rsu_softc *);
+static int rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int);
+static void rsu_calib_task(void *, int);
+static int rsu_newstate(struct ieee80211vap *, enum ieee80211_state, int);
+#ifdef notyet
+static void rsu_set_key(struct rsu_softc *, const struct ieee80211_key *);
+static void rsu_delete_key(struct rsu_softc *, const struct ieee80211_key *);
+#endif
+static int rsu_site_survey(struct rsu_softc *, struct ieee80211vap *);
+static int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
+static int rsu_disconnect(struct rsu_softc *);
+static void rsu_event_survey(struct rsu_softc *, uint8_t *, int);
+static void rsu_event_join_bss(struct rsu_softc *, uint8_t *, int);
+static void rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
+static void rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
+static int8_t rsu_get_rssi(struct rsu_softc *, int, void *);
+static struct mbuf *
+ rsu_rx_frame(struct rsu_softc *, uint8_t *, int, int *);
+static struct mbuf *
+ rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int, int *);
+static struct mbuf *
+ rsu_rxeof(struct usb_xfer *, struct rsu_data *, int *);
+static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
+static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
+ const struct ieee80211_bpf_params *);
+static void rsu_init(void *);
+static void rsu_init_locked(struct rsu_softc *);
+static void rsu_watchdog(void *);
+static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
+ struct mbuf *, struct rsu_data *);
+static void rsu_start(struct ifnet *);
+static void rsu_start_locked(struct ifnet *);
+static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
+static void rsu_stop(struct ifnet *, int);
+static void rsu_stop_locked(struct ifnet *, int);
+
+static device_method_t rsu_methods[] = {
+ DEVMETHOD(device_probe, rsu_match),
+ DEVMETHOD(device_attach, rsu_attach),
+ DEVMETHOD(device_detach, rsu_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t rsu_driver = {
+ .name = "rsu",
+ .methods = rsu_methods,
+ .size = sizeof(struct rsu_softc)
+};
+
+static devclass_t rsu_devclass;
+
+DRIVER_MODULE(rsu, uhub, rsu_driver, rsu_devclass, NULL, 0);
+MODULE_DEPEND(rsu, wlan, 1, 1, 1);
+MODULE_DEPEND(rsu, usb, 1, 1, 1);
+MODULE_DEPEND(rsu, firmware, 1, 1, 1);
+MODULE_VERSION(rsu, 1);
+
+static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
+ [RSU_BULK_RX] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .bufsize = RSU_RXBUFSZ,
+ .flags = {
+ .pipe_bof = 1,
+ .short_xfer_ok = 1
+ },
+ .callback = rsu_bulk_rx_callback
+ },
+ [RSU_BULK_TX_BE] = {
+ .type = UE_BULK,
+ .endpoint = 0x06,
+ .direction = UE_DIR_OUT,
+ .bufsize = RSU_TXBUFSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .pipe_bof = 1,
+ .force_short_xfer = 1
+ },
+ .callback = rsu_bulk_tx_callback,
+ .timeout = RSU_TX_TIMEOUT
+ },
+ [RSU_BULK_TX_BK] = {
+ .type = UE_BULK,
+ .endpoint = 0x06,
+ .direction = UE_DIR_OUT,
+ .bufsize = RSU_TXBUFSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .pipe_bof = 1,
+ .force_short_xfer = 1
+ },
+ .callback = rsu_bulk_tx_callback,
+ .timeout = RSU_TX_TIMEOUT
+ },
+ [RSU_BULK_TX_VI] = {
+ .type = UE_BULK,
+ .endpoint = 0x04,
+ .direction = UE_DIR_OUT,
+ .bufsize = RSU_TXBUFSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .pipe_bof = 1,
+ .force_short_xfer = 1
+ },
+ .callback = rsu_bulk_tx_callback,
+ .timeout = RSU_TX_TIMEOUT
+ },
+ [RSU_BULK_TX_VO] = {
+ .type = UE_BULK,
+ .endpoint = 0x04,
+ .direction = UE_DIR_OUT,
+ .bufsize = RSU_TXBUFSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .pipe_bof = 1,
+ .force_short_xfer = 1
+ },
+ .callback = rsu_bulk_tx_callback,
+ .timeout = RSU_TX_TIMEOUT
+ },
+};
+
+static int
+rsu_match(device_t self)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(self);
+
+ if (uaa->usb_mode != USB_MODE_HOST ||
+ uaa->info.bIfaceIndex != 0 ||
+ uaa->info.bConfigIndex != 0)
+ return (ENXIO);
+
+ return (usbd_lookup_id_by_uaa(rsu_devs, sizeof(rsu_devs), uaa));
+}
+
+static int
+rsu_attach(device_t self)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(self);
+ struct rsu_softc *sc = device_get_softc(self);
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
+ int error;
+ uint8_t iface_index, bands;
+
+ device_set_usb_desc(self);
+ sc->sc_udev = uaa->device;
+ sc->sc_dev = self;
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
+ rsu_calib_task, sc);
+ callout_init(&sc->sc_watchdog_ch, 0);
+
+ iface_index = 0;
+ error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+ rsu_config, RSU_N_TRANSFER, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not allocate USB transfers, err=%s\n",
+ usbd_errstr(error));
+ goto detach;
+ }
+ RSU_LOCK(sc);
+ /* Read chip revision. */
+ sc->cut = MS(rsu_read_4(sc, R92S_PMC_FSM), R92S_PMC_FSM_CUT);
+ if (sc->cut != 3)
+ sc->cut = (sc->cut >> 1) + 1;
+ error = rsu_read_rom(sc);
+ if (error != 0) {
+ device_printf(self, "could not read ROM\n");
+ goto detach;
+ }
+ RSU_UNLOCK(sc);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]);
+ device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(self, "cannot allocate interface\n");
+ goto detach;
+ }
+ ic = ifp->if_l2com;
+ ifp->if_softc = sc;
+ if_initname(ifp, "rsu", device_get_unit(self));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = rsu_init;
+ ifp->if_ioctl = rsu_ioctl;
+ ifp->if_start = rsu_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capabilities |= IFCAP_RXCSUM;
+ ifp->if_capenable |= IFCAP_RXCSUM;
+ ifp->if_hwassist = CSUM_TCP;
+
+ ic->ic_ifp = ifp;
+ ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
+ ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
+
+ /* Set device capabilities. */
+ ic->ic_caps =
+ IEEE80211_C_STA | /* station mode */
+ IEEE80211_C_BGSCAN | /* Background scan. */
+ IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */
+ IEEE80211_C_SHSLOT | /* Short slot time supported. */
+ IEEE80211_C_WPA; /* WPA/RSN. */
+
+#if 0
+ /* Check if HT support is present. */
+ if (usb_lookup(rsu_devs_noht, uaa->vendor, uaa->product) == NULL) {
+ /* Set HT capabilities. */
+ ic->ic_htcaps =
+ IEEE80211_HTCAP_CBW20_40 |
+ IEEE80211_HTCAP_DSSSCCK40;
+ /* Set supported HT rates. */
+ for (i = 0; i < 2; i++)
+ ic->ic_sup_mcs[i] = 0xff;
+ }
+#endif
+
+ /* Set supported .11b and .11g rates. */
+ bands = 0;
+ setbit(&bands, IEEE80211_MODE_11B);
+ setbit(&bands, IEEE80211_MODE_11G);
+ ieee80211_init_channels(ic, NULL, &bands);
+
+ ieee80211_ifattach(ic, sc->sc_bssid);
+ ic->ic_raw_xmit = rsu_raw_xmit;
+ ic->ic_scan_start = rsu_scan_start;
+ ic->ic_scan_end = rsu_scan_end;
+ ic->ic_set_channel = rsu_set_channel;
+ ic->ic_vap_create = rsu_vap_create;
+ ic->ic_vap_delete = rsu_vap_delete;
+ ic->ic_update_mcast = rsu_update_mcast;
+
+ ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
+ sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
+ &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
+ RSU_RX_RADIOTAP_PRESENT);
+
+ if (bootverbose)
+ ieee80211_announce(ic);
+
+ return (0);
+
+detach:
+ rsu_detach(self);
+ return (ENXIO);
+}
+
+static int
+rsu_detach(device_t self)
+{
+ struct rsu_softc *sc = device_get_softc(self);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ if (!device_is_attached(self))
+ return (0);
+ rsu_stop(ifp, 1);
+ usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
+ ieee80211_ifdetach(ic);
+
+ callout_drain(&sc->sc_watchdog_ch);
+ taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
+
+ /* Free Tx/Rx buffers. */
+ rsu_free_tx_list(sc);
+ rsu_free_rx_list(sc);
+
+ if_free(ifp);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+static usb_error_t
+rsu_do_request(struct rsu_softc *sc, struct usb_device_request *req,
+ void *data)
+{
+ usb_error_t err;
+ int ntries = 10;
+
+ RSU_ASSERT_LOCKED(sc);
+
+ while (ntries--) {
+ err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx,
+ req, data, 0, NULL, 250 /* ms */);
+ if (err == 0 || !device_is_attached(sc->sc_dev))
+ break;
+ DPRINTFN(1, "Control request failed, %s (retrying)\n",
+ usbd_errstr(err));
+ usb_pause_mtx(&sc->sc_mtx, hz / 100);
+ }
+
+ return (err);
+}
+
+static struct ieee80211vap *
+rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
+ enum ieee80211_opmode opmode, int flags,
+ const uint8_t bssid[IEEE80211_ADDR_LEN],
+ const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+ struct rsu_vap *uvp;
+ struct ieee80211vap *vap;
+
+ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
+ return (NULL);
+
+ uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (uvp == NULL)
+ return (NULL);
+ vap = &uvp->vap;
+ ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags, bssid, mac);
+
+ /* override state transition machine */
+ uvp->newstate = vap->iv_newstate;
+ vap->iv_newstate = rsu_newstate;
+
+ /* complete setup */
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status);
+ ic->ic_opmode = opmode;
+
+ return (vap);
+}
+
+static void
+rsu_vap_delete(struct ieee80211vap *vap)
+{
+ struct rsu_vap *uvp = RSU_VAP(vap);
+
+ ieee80211_vap_detach(vap);
+ free(uvp, M_80211_VAP);
+}
+
+static void
+rsu_scan_start(struct ieee80211com *ic)
+{
+ int error;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rsu_softc *sc = ifp->if_softc;
+
+ /* Scanning is done by the firmware. */
+ RSU_LOCK(sc);
+ error = rsu_site_survey(sc, TAILQ_FIRST(&ic->ic_vaps));
+ RSU_UNLOCK(sc);
+ if (error != 0)
+ device_printf(sc->sc_dev,
+ "could not send site survey command\n");
+}
+
+static void
+rsu_scan_end(struct ieee80211com *ic)
+{
+ /* Nothing to do here. */
+}
+
+static void
+rsu_set_channel(struct ieee80211com *ic __unused)
+{
+ /* We are unable to switch channels, yet. */
+}
+
+static void
+rsu_update_mcast(struct ifnet *ifp)
+{
+ /* XXX do nothing? */
+}
+
+static int
+rsu_alloc_list(struct rsu_softc *sc, struct rsu_data data[],
+ int ndata, int maxsz)
+{
+ int i, error;
+
+ for (i = 0; i < ndata; i++) {
+ struct rsu_data *dp = &data[i];
+ dp->sc = sc;
+ dp->m = NULL;
+ dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
+ if (dp->buf == NULL) {
+ device_printf(sc->sc_dev,
+ "could not allocate buffer\n");
+ error = ENOMEM;
+ goto fail;
+ }
+ dp->ni = NULL;
+ }
+
+ return (0);
+fail:
+ rsu_free_list(sc, data, ndata);
+ return (error);
+}
+
+static int
+rsu_alloc_rx_list(struct rsu_softc *sc)
+{
+ int error, i;
+
+ error = rsu_alloc_list(sc, sc->sc_rx, RSU_RX_LIST_COUNT,
+ RSU_RXBUFSZ);
+ if (error != 0)
+ return (error);
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+
+ for (i = 0; i < RSU_RX_LIST_COUNT; i++)
+ STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next);
+
+ return (0);
+}
+
+static int
+rsu_alloc_tx_list(struct rsu_softc *sc)
+{
+ int error, i;
+
+ error = rsu_alloc_list(sc, sc->sc_tx, RSU_TX_LIST_COUNT,
+ RSU_TXBUFSZ);
+ if (error != 0)
+ return (error);
+
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ for (i = 0; i < RSU_TX_LIST_COUNT; i++) {
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], next);
+ }
+
+ return (0);
+}
+
+static void
+rsu_free_tx_list(struct rsu_softc *sc)
+{
+ rsu_free_list(sc, sc->sc_tx, RSU_TX_LIST_COUNT);
+}
+
+static void
+rsu_free_rx_list(struct rsu_softc *sc)
+{
+ rsu_free_list(sc, sc->sc_rx, RSU_RX_LIST_COUNT);
+}
+
+static void
+rsu_free_list(struct rsu_softc *sc, struct rsu_data data[], int ndata)
+{
+ int i;
+
+ for (i = 0; i < ndata; i++) {
+ struct rsu_data *dp = &data[i];
+
+ if (dp->buf != NULL) {
+ free(dp->buf, M_USBDEV);
+ dp->buf = NULL;
+ }
+ if (dp->ni != NULL) {
+ ieee80211_free_node(dp->ni);
+ dp->ni = NULL;
+ }
+ }
+}
+
+static struct rsu_data *
+_rsu_getbuf(struct rsu_softc *sc)
+{
+ struct rsu_data *bf;
+
+ bf = STAILQ_FIRST(&sc->sc_tx_inactive);
+ if (bf != NULL)
+ STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
+ else
+ bf = NULL;
+ if (bf == NULL)
+ DPRINTF("out of xmit buffers\n");
+ return (bf);
+}
+
+static struct rsu_data *
+rsu_getbuf(struct rsu_softc *sc)
+{
+ struct rsu_data *bf;
+
+ RSU_ASSERT_LOCKED(sc);
+
+ bf = _rsu_getbuf(sc);
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
+ DPRINTF("stop queue\n");
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
+ return (bf);
+}
+
+static int
+rsu_write_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
+ int len)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = R92S_REQ_REGS;
+ USETW(req.wValue, addr);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, len);
+
+ return (rsu_do_request(sc, &req, buf));
+}
+
+static void
+rsu_write_1(struct rsu_softc *sc, uint16_t addr, uint8_t val)
+{
+ rsu_write_region_1(sc, addr, &val, 1);
+}
+
+static void
+rsu_write_2(struct rsu_softc *sc, uint16_t addr, uint16_t val)
+{
+ val = htole16(val);
+ rsu_write_region_1(sc, addr, (uint8_t *)&val, 2);
+}
+
+static void
+rsu_write_4(struct rsu_softc *sc, uint16_t addr, uint32_t val)
+{
+ val = htole32(val);
+ rsu_write_region_1(sc, addr, (uint8_t *)&val, 4);
+}
+
+static int
+rsu_read_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
+ int len)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list