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-all mailing list