svn commit: r192873 - in head/sys: dev/usb/wlan modules/usb/urtw

Weongyo Jeong weongyo at FreeBSD.org
Wed May 27 03:57:39 UTC 2009


Author: weongyo
Date: Wed May 27 03:57:38 2009
New Revision: 192873
URL: http://svn.freebsd.org/changeset/base/192873

Log:
  ports urtw(4) for USB2.  Additionally it supports a 8187B chipset weakly
  that it needs more stabilization.

Added:
  head/sys/dev/usb/wlan/if_urtw.c   (contents, props changed)
  head/sys/dev/usb/wlan/if_urtwreg.h   (contents, props changed)
  head/sys/dev/usb/wlan/if_urtwvar.h   (contents, props changed)
  head/sys/modules/usb/urtw/
  head/sys/modules/usb/urtw/Makefile   (contents, props changed)

Added: head/sys/dev/usb/wlan/if_urtw.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/usb/wlan/if_urtw.c	Wed May 27 03:57:38 2009	(r192873)
@@ -0,0 +1,4241 @@
+/*-
+ * Copyright (c) 2008 Weongyo Jeong <weongyo at FreeBSD.org>
+ *
+ * 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$");
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_error.h>
+#include <dev/usb/usb_lookup.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_util.h>
+#include "usbdevs.h"
+
+#include <dev/usb/wlan/if_urtwreg.h>
+#include <dev/usb/wlan/if_urtwvar.h>
+
+SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L");
+#ifdef URTW_DEBUG
+int urtw_debug = 0;
+SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW, &urtw_debug, 0,
+    "control debugging printfs");
+TUNABLE_INT("hw.usb.urtw.debug", &urtw_debug);
+enum {
+	URTW_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
+	URTW_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
+	URTW_DEBUG_RESET	= 0x00000004,	/* reset processing */
+	URTW_DEBUG_TX_PROC	= 0x00000008,	/* tx ISR proc */
+	URTW_DEBUG_RX_PROC	= 0x00000010,	/* rx ISR proc */
+	URTW_DEBUG_STATE	= 0x00000020,	/* 802.11 state transitions */
+	URTW_DEBUG_STAT		= 0x00000040,	/* statistic */
+	URTW_DEBUG_INIT		= 0x00000080,	/* initialization of dev */
+	URTW_DEBUG_ANY		= 0xffffffff
+};
+#define	DPRINTF(sc, m, fmt, ...) do {				\
+	if (sc->sc_debug & (m))					\
+		printf(fmt, __VA_ARGS__);			\
+} while (0)
+#else
+#define	DPRINTF(sc, m, fmt, ...) do {				\
+	(void) sc;						\
+} while (0)
+#endif
+int urtw_preamble_mode = URTW_PREAMBLE_MODE_LONG;
+SYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RW,
+    &urtw_preamble_mode, 0, "set the preable mode (long or short)");
+TUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode);
+
+/* recognized device vendors/products */
+#define urtw_lookup(v, p)						\
+	((const struct urtw_type *)usb_lookup(urtw_devs, v, p))
+#define	URTW_DEV_B(v,p)							\
+	{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187B) }
+#define	URTW_DEV_L(v,p)							\
+	{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187L) }
+#define	URTW_REV_RTL8187B	0
+#define	URTW_REV_RTL8187L	1
+static const struct usb2_device_id urtw_devs[] = {
+	{ USB_VPI(USB_VENDOR_BELKIN, 0x705e, URTW_REV_RTL8187B) },
+	{ USB_VPI(USB_VENDOR_REALTEK, 0x8189, URTW_REV_RTL8187B) },
+	{ USB_VPI(USB_VENDOR_REALTEK, 0x8197, URTW_REV_RTL8187B) },
+	{ USB_VPI(USB_VENDOR_REALTEK, 0x8198, URTW_REV_RTL8187B) },
+	{ USB_VPI(USB_VENDOR_NETGEAR, 0x4260, URTW_REV_RTL8187B) },
+	{ USB_VPI(0x1b75, 0x8187, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_ASUS, 0x171d, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_DICKSMITH, 0x9401, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_HP, 0xca02, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_LOGITEC, 0x010c, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_NETGEAR, 0x6100, URTW_REV_RTL8187L) },
+	URTW_DEV_L(NETGEAR, WG111V2),
+	URTW_DEV_L(REALTEK, RTL8187),
+	{ USB_VPI(USB_VENDOR_SITECOMEU, 0x000d, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_SPHAIRON, 0x0150, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_SURECOM, 0x11f2, URTW_REV_RTL8187L) },
+	{ USB_VPI(USB_VENDOR_QCOM, 0x6232, URTW_REV_RTL8187L) },
+#undef URTW_DEV_L
+#undef URTW_DEV_B
+};
+
+#define urtw_read8_m(sc, val, data)	do {			\
+	error = urtw_read8_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_write8_m(sc, val, data)	do {			\
+	error = urtw_write8_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_read16_m(sc, val, data)	do {			\
+	error = urtw_read16_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_write16_m(sc, val, data)	do {			\
+	error = urtw_write16_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_read32_m(sc, val, data)	do {			\
+	error = urtw_read32_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_write32_m(sc, val, data)	do {			\
+	error = urtw_write32_c(sc, val, data);			\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_8187_write_phy_ofdm(sc, val, data)	do {		\
+	error = urtw_8187_write_phy_ofdm_c(sc, val, data);	\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_8187_write_phy_cck(sc, val, data)	do {		\
+	error = urtw_8187_write_phy_cck_c(sc, val, data);	\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+#define urtw_8225_write(sc, val, data)	do {			\
+	error = urtw_8225_write_c(sc, val, data);		\
+	if (error != 0)						\
+		goto fail;					\
+} while (0)
+
+struct urtw_pair {
+	uint32_t	reg;
+	uint32_t	val;
+};
+
+static uint8_t urtw_8225_agc[] = {
+	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b,
+	0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
+	0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85,
+	0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a,
+	0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f,
+	0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24,
+	0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19,
+	0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
+	0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static uint8_t urtw_8225z2_agc[] = {
+	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51,
+	0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b,
+	0x39, 0x37, 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25,
+	0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f,
+	0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x19,
+	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x21, 0x22, 0x23,
+	0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
+	0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
+	0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31,
+	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
+};
+
+static uint32_t urtw_8225_channel[] = {
+	0x0000,		/* dummy channel 0  */
+	0x085c,		/* 1  */
+	0x08dc,		/* 2  */
+	0x095c,		/* 3  */
+	0x09dc,		/* 4  */
+	0x0a5c,		/* 5  */
+	0x0adc,		/* 6  */
+	0x0b5c,		/* 7  */
+	0x0bdc,		/* 8  */
+	0x0c5c,		/* 9  */
+	0x0cdc,		/* 10  */
+	0x0d5c,		/* 11  */
+	0x0ddc,		/* 12  */
+	0x0e5c,		/* 13  */
+	0x0f72,		/* 14  */
+};
+
+static uint8_t urtw_8225_gain[] = {
+	0x23, 0x88, 0x7c, 0xa5,		/* -82dbm  */
+	0x23, 0x88, 0x7c, 0xb5,		/* -82dbm  */
+	0x23, 0x88, 0x7c, 0xc5,		/* -82dbm  */
+	0x33, 0x80, 0x79, 0xc5,		/* -78dbm  */
+	0x43, 0x78, 0x76, 0xc5,		/* -74dbm  */
+	0x53, 0x60, 0x73, 0xc5,		/* -70dbm  */
+	0x63, 0x58, 0x70, 0xc5,		/* -66dbm  */
+};
+
+static struct urtw_pair urtw_8225_rf_part1[] = {
+	{ 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
+	{ 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a },
+	{ 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 },
+	{ 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 },
+};
+
+static struct urtw_pair urtw_8225_rf_part2[] = {
+	{ 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 },
+	{ 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 },
+	{ 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 },
+	{ 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 },
+	{ 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 },
+	{ 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef },
+	{ 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 },
+	{ 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 },
+	{ 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 },
+	{ 0x27, 0x88 }
+};
+
+static struct urtw_pair urtw_8225_rf_part3[] = {
+	{ 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 },
+	{ 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b },
+	{ 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 },
+	{ 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d },
+	{ 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e },
+	{ 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a },
+	{ 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 }
+};
+
+static uint16_t urtw_8225_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static uint8_t urtw_8225_threshold[] = {
+	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd,
+};
+
+static uint8_t urtw_8225_tx_gain_cck_ofdm[] = {
+	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static uint8_t urtw_8225_txpwr_cck[] = {
+	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static uint8_t urtw_8225_txpwr_cck_ch14[] = {
+	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static uint8_t urtw_8225_txpwr_ofdm[]={
+	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static uint8_t urtw_8225v2_gain_bg[]={
+	0x23, 0x15, 0xa5,		/* -82-1dbm  */
+	0x23, 0x15, 0xb5,		/* -82-2dbm  */
+	0x23, 0x15, 0xc5,		/* -82-3dbm  */
+	0x33, 0x15, 0xc5,		/* -78dbm  */
+	0x43, 0x15, 0xc5,		/* -74dbm  */
+	0x53, 0x15, 0xc5,		/* -70dbm  */
+	0x63, 0x15, 0xc5,		/* -66dbm  */
+};
+
+static struct urtw_pair urtw_8225v2_rf_part1[] = {
+	{ 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
+	{ 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a },
+	{ 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb },
+	{ 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 }
+};
+
+static struct urtw_pair urtw_8225v2b_rf_part1[] = {
+	{ 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
+	{ 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a },
+	{ 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb },
+	{ 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 }
+};
+
+static struct urtw_pair urtw_8225v2_rf_part2[] = {
+	{ 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 },
+	{ 0x04, 0x00 },	{ 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 },
+	{ 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 },
+	{ 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 },
+	{ 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 },
+	{ 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 },
+	{ 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 },
+	{ 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 },
+	{ 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 },
+	{ 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 }
+};
+
+static struct urtw_pair urtw_8225v2b_rf_part2[] = {
+	{ 0x00, 0x10 }, { 0x01, 0x0d }, { 0x02, 0x01 }, { 0x03, 0x00 },
+	{ 0x04, 0x14 }, { 0x05, 0xfb }, { 0x06, 0xfb }, { 0x07, 0x60 },
+	{ 0x08, 0x00 }, { 0x09, 0x60 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+	{ 0x0c, 0x00 }, { 0x0d, 0x5c }, { 0x0e, 0x00 }, { 0x0f, 0x00 },
+	{ 0x10, 0x40 }, { 0x11, 0x00 }, { 0x12, 0x40 }, { 0x13, 0x00 },
+	{ 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0xa8 }, { 0x17, 0x26 },
+	{ 0x18, 0x32 }, { 0x19, 0x33 }, { 0x1a, 0x07 }, { 0x1b, 0xa5 },
+	{ 0x1c, 0x6f }, { 0x1d, 0x55 }, { 0x1e, 0xc8 }, { 0x1f, 0xb3 },
+	{ 0x20, 0x0a }, { 0x21, 0xe1 }, { 0x22, 0x2C }, { 0x23, 0x8a },
+	{ 0x24, 0x86 }, { 0x25, 0x83 }, { 0x26, 0x34 }, { 0x27, 0x0f },
+	{ 0x28, 0x4f }, { 0x29, 0x24 }, { 0x2a, 0x6f }, { 0x2b, 0xc2 },
+	{ 0x2c, 0x6b }, { 0x2d, 0x40 }, { 0x2e, 0x80 }, { 0x2f, 0x00 },
+	{ 0x30, 0xc0 }, { 0x31, 0xc1 }, { 0x32, 0x58 }, { 0x33, 0xf1 },
+	{ 0x34, 0x00 }, { 0x35, 0xe4 }, { 0x36, 0x90 }, { 0x37, 0x3e },
+	{ 0x38, 0x6d }, { 0x39, 0x3c }, { 0x3a, 0xfb }, { 0x3b, 0x07 }
+};
+
+static struct urtw_pair urtw_8225v2_rf_part3[] = {
+	{ 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 },
+	{ 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 },
+	{ 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 },
+	{ 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 },
+	{ 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d },
+	{ 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 },
+	{ 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 },
+	{ 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 }
+};
+
+static uint16_t urtw_8225v2_rxgain[] = {
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
+	0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
+	0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
+	0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
+	0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
+	0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
+	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
+	0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
+	0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
+	0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
+	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static uint16_t urtw_8225v2b_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+};
+
+static uint8_t urtw_8225v2_txpwr_cck[] = {
+	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static uint8_t urtw_8225v2_txpwr_cck_ch14[] = {
+	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static uint8_t urtw_8225v2b_txpwr_cck[] = {
+	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
+	0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
+	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
+	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
+};
+
+static uint8_t urtw_8225v2b_txpwr_cck_ch14[] = {
+	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
+	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
+	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
+	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static struct urtw_pair urtw_ratetable[] = {
+	{  2,  0 }, {   4,  1 }, { 11, 2 }, { 12, 4 }, { 18, 5 },
+	{ 22,  3 }, {  24,  6 }, { 36, 7 }, { 48, 8 }, { 72, 9 },
+	{ 96, 10 }, { 108, 11 }
+};
+
+static const uint8_t urtw_8187b_reg_table[][3] = {
+	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
+	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
+	{ 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
+	{ 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
+	{ 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
+	{ 0xff, 0x00, 0 }, { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 },
+	{ 0x5a, 0x4b, 1 }, { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 },
+	{ 0x61, 0x09, 1 }, { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 },
+	{ 0xce, 0x0f, 1 }, { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 },
+	{ 0xe1, 0x0f, 1 }, { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 },
+	{ 0xf1, 0x01, 1 }, { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 },
+	{ 0xf4, 0x04, 1 }, { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 },
+	{ 0xf7, 0x07, 1 }, { 0xf8, 0x08, 1 }, { 0x4e, 0x00, 2 },
+	{ 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, { 0x22, 0x68, 2 },
+	{ 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, { 0x25, 0x7d, 2 },
+	{ 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, { 0x4d, 0x08, 2 },
+	{ 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, { 0x52, 0x04, 2 },
+	{ 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, { 0x55, 0x23, 2 },
+	{ 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, { 0x58, 0x08, 2 },
+	{ 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, { 0x5b, 0x08, 2 },
+	{ 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, { 0x62, 0x08, 2 },
+	{ 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, { 0x72, 0x56, 2 },
+	{ 0x73, 0x9a, 2 }, { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 },
+	{ 0x5b, 0x40, 0 }, { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 },
+	{ 0x88, 0x54, 0 }, { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 },
+	{ 0x8d, 0x00, 0 }, { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 },
+	{ 0x96, 0x00, 0 }, { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 },
+	{ 0x9f, 0x10, 0 }, { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 },
+	{ 0xdb, 0x00, 0 }, { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
+	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
+	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
+};
+
+static usb2_callback_t urtw_bulk_rx_callback;
+static usb2_callback_t urtw_bulk_tx_callback;
+
+static const struct usb2_config urtw_8187b_usbconfig[URTW_8187B_N_XFERS] = {
+	[URTW_8187B_BULK_RX] = {
+		.type = UE_BULK,
+		.endpoint = 0x83,
+		.direction = UE_DIR_IN,
+		.bufsize = MCLBYTES,
+		.flags = {
+			.ext_buffer = 1,
+			.pipe_bof = 1,
+			.short_xfer_ok = 1
+		},
+		.callback = urtw_bulk_rx_callback
+	},
+	[URTW_8187B_BULK_TX_BE] = {
+		.type = UE_BULK,
+		.endpoint = URTW_8187B_TXPIPE_BE,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+	[URTW_8187B_BULK_TX_BK] = {
+		.type = UE_BULK,
+		.endpoint = URTW_8187B_TXPIPE_BK,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+	[URTW_8187B_BULK_TX_VI] = {
+		.type = UE_BULK,
+		.endpoint = URTW_8187B_TXPIPE_VI,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+	[URTW_8187B_BULK_TX_VO] = {
+		.type = UE_BULK,
+		.endpoint = URTW_8187B_TXPIPE_VO,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+	[URTW_8187B_BULK_TX_EP12] = {
+		.type = UE_BULK,
+		.endpoint = 0xc,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	}
+};
+
+static const struct usb2_config urtw_8187l_usbconfig[URTW_8187L_N_XFERS] = {
+	[URTW_8187L_BULK_RX] = {
+		.type = UE_BULK,
+		.endpoint = 0x81,
+		.direction = UE_DIR_IN,
+		.bufsize = MCLBYTES,
+		.flags = {
+			.ext_buffer = 1,
+			.pipe_bof = 1,
+			.short_xfer_ok = 1
+		},
+		.callback = urtw_bulk_rx_callback
+	},
+	[URTW_8187L_BULK_TX_LOW] = {
+		.type = UE_BULK,
+		.endpoint = 0x2,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+	[URTW_8187L_BULK_TX_NORMAL] = {
+		.type = UE_BULK,
+		.endpoint = 0x3,
+		.direction = UE_DIR_OUT,
+		.bufsize = URTW_TX_MAXSIZE,
+		.flags = {
+			.ext_buffer = 1,
+			.force_short_xfer = 1,
+			.pipe_bof = 1,
+		},
+		.callback = urtw_bulk_tx_callback,
+		.timeout = URTW_DATA_TIMEOUT
+	},
+};
+
+static struct ieee80211vap *urtw_vap_create(struct ieee80211com *,
+			    const char name[IFNAMSIZ], int unit, int opmode,
+			    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
+			    const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void		urtw_vap_delete(struct ieee80211vap *);
+static void		urtw_init(void *);
+static void		urtw_stop(struct ifnet *, int);
+static void		urtw_stop_locked(struct ifnet *, int);
+static int		urtw_ioctl(struct ifnet *, u_long, caddr_t);
+static void		urtw_start(struct ifnet *);
+static int		urtw_alloc_rx_data_list(struct urtw_softc *);
+static int		urtw_alloc_tx_data_list(struct urtw_softc *);
+static int		urtw_raw_xmit(struct ieee80211_node *, struct mbuf *,
+			    const struct ieee80211_bpf_params *);
+static void		urtw_scan_start(struct ieee80211com *);
+static void		urtw_scan_end(struct ieee80211com *);
+static void		urtw_set_channel(struct ieee80211com *);
+static void		urtw_update_mcast(struct ifnet *);
+static int		urtw_tx_start(struct urtw_softc *,
+			    struct ieee80211_node *, struct mbuf *,
+			    struct urtw_data *, int);
+static int		urtw_newstate(struct ieee80211vap *,
+			    enum ieee80211_state, int);
+static void		urtw_led_ch(void *);
+static void		urtw_ledtask(void *, int);
+static void		urtw_watchdog(void *);
+static void		urtw_set_multi(void *);
+static int		urtw_isbmode(uint16_t);
+static uint16_t		urtw_rate2rtl(int);
+static uint16_t		urtw_rtl2rate(int);
+static usb2_error_t	urtw_set_rate(struct urtw_softc *);
+static usb2_error_t	urtw_update_msr(struct urtw_softc *);
+static usb2_error_t	urtw_read8_c(struct urtw_softc *, int, uint8_t *);
+static usb2_error_t	urtw_read16_c(struct urtw_softc *, int, uint16_t *);
+static usb2_error_t	urtw_read32_c(struct urtw_softc *, int, uint32_t *);
+static usb2_error_t	urtw_write8_c(struct urtw_softc *, int, uint8_t);
+static usb2_error_t	urtw_write16_c(struct urtw_softc *, int, uint16_t);
+static usb2_error_t	urtw_write32_c(struct urtw_softc *, int, uint32_t);
+static usb2_error_t	urtw_eprom_cs(struct urtw_softc *, int);
+static usb2_error_t	urtw_eprom_ck(struct urtw_softc *);
+static usb2_error_t	urtw_eprom_sendbits(struct urtw_softc *, int16_t *,
+			    int);
+static usb2_error_t	urtw_eprom_read32(struct urtw_softc *, uint32_t,
+			    uint32_t *);
+static usb2_error_t	urtw_eprom_readbit(struct urtw_softc *, int16_t *);
+static usb2_error_t	urtw_eprom_writebit(struct urtw_softc *, int16_t);
+static usb2_error_t	urtw_get_macaddr(struct urtw_softc *);
+static usb2_error_t	urtw_get_txpwr(struct urtw_softc *);
+static usb2_error_t	urtw_get_rfchip(struct urtw_softc *);
+static usb2_error_t	urtw_led_init(struct urtw_softc *);
+static usb2_error_t	urtw_8185_rf_pins_enable(struct urtw_softc *);
+static usb2_error_t	urtw_8185_tx_antenna(struct urtw_softc *, uint8_t);
+static usb2_error_t	urtw_8187_write_phy(struct urtw_softc *, uint8_t,
+			    uint32_t);
+static usb2_error_t	urtw_8187_write_phy_ofdm_c(struct urtw_softc *,
+			    uint8_t, uint32_t);
+static usb2_error_t	urtw_8187_write_phy_cck_c(struct urtw_softc *, uint8_t,
+			    uint32_t);
+static usb2_error_t	urtw_8225_setgain(struct urtw_softc *, int16_t);
+static usb2_error_t	urtw_8225_usb_init(struct urtw_softc *);
+static usb2_error_t	urtw_8225_write_c(struct urtw_softc *, uint8_t,
+			    uint16_t);
+static usb2_error_t	urtw_8225_write_s16(struct urtw_softc *, uint8_t, int,
+			    uint16_t *);
+static usb2_error_t	urtw_8225_read(struct urtw_softc *, uint8_t,
+			    uint32_t *);
+static usb2_error_t	urtw_8225_rf_init(struct urtw_softc *);
+static usb2_error_t	urtw_8225_rf_set_chan(struct urtw_softc *, int);
+static usb2_error_t	urtw_8225_rf_set_sens(struct urtw_softc *, int);
+static usb2_error_t	urtw_8225_set_txpwrlvl(struct urtw_softc *, int);
+static usb2_error_t	urtw_8225_rf_stop(struct urtw_softc *);
+static usb2_error_t	urtw_8225v2_rf_init(struct urtw_softc *);
+static usb2_error_t	urtw_8225v2_rf_set_chan(struct urtw_softc *, int);
+static usb2_error_t	urtw_8225v2_set_txpwrlvl(struct urtw_softc *, int);
+static usb2_error_t	urtw_8225v2_setgain(struct urtw_softc *, int16_t);
+static usb2_error_t	urtw_8225_isv2(struct urtw_softc *, int *);
+static usb2_error_t	urtw_8225v2b_rf_init(struct urtw_softc *);
+static usb2_error_t	urtw_8225v2b_rf_set_chan(struct urtw_softc *, int);
+static usb2_error_t	urtw_read8e(struct urtw_softc *, int, uint8_t *);
+static usb2_error_t	urtw_write8e(struct urtw_softc *, int, uint8_t);
+static usb2_error_t	urtw_8180_set_anaparam(struct urtw_softc *, uint32_t);
+static usb2_error_t	urtw_8185_set_anaparam2(struct urtw_softc *, uint32_t);
+static usb2_error_t	urtw_intr_enable(struct urtw_softc *);
+static usb2_error_t	urtw_intr_disable(struct urtw_softc *);
+static usb2_error_t	urtw_reset(struct urtw_softc *);
+static usb2_error_t	urtw_led_on(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_ctl(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_blink(struct urtw_softc *);
+static usb2_error_t	urtw_led_mode0(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_mode1(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_mode2(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_mode3(struct urtw_softc *, int);
+static usb2_error_t	urtw_rx_setconf(struct urtw_softc *);
+static usb2_error_t	urtw_rx_enable(struct urtw_softc *);
+static usb2_error_t	urtw_tx_enable(struct urtw_softc *sc);
+static void		urtw_free_tx_data_list(struct urtw_softc *);
+static void		urtw_free_rx_data_list(struct urtw_softc *);
+static void		urtw_free_data_list(struct urtw_softc *,
+			    struct urtw_data data[], int, int);
+static usb2_error_t	urtw_adapter_start(struct urtw_softc *);
+static usb2_error_t	urtw_adapter_start_b(struct urtw_softc *);
+static usb2_error_t	urtw_set_mode(struct urtw_softc *, uint32_t);
+static usb2_error_t	urtw_8187b_cmd_reset(struct urtw_softc *);
+static usb2_error_t	urtw_write16_i(struct urtw_softc *, int, uint16_t, int);
+static usb2_error_t	urtw_write8_i(struct urtw_softc *, int, uint8_t, int);
+static usb2_error_t	urtw_write32_i(struct urtw_softc *, int, uint32_t, int);
+static usb2_error_t	urtw_do_request(struct urtw_softc *,
+			    struct usb2_device_request *, void *);
+static usb2_error_t	urtw_8225v2b_set_txpwrlvl(struct urtw_softc *, int);
+static usb2_error_t	urtw_led_off(struct urtw_softc *, int);
+static void		urtw_abort_xfers(struct urtw_softc *);
+static struct urtw_data *
+			urtw_getbuf(struct urtw_softc *sc);
+
+static int
+urtw_match(device_t dev)
+{
+	struct usb2_attach_arg *uaa = device_get_ivars(dev);
+
+	if (uaa->usb_mode != USB_MODE_HOST)
+		return (ENXIO);
+	if (uaa->info.bConfigIndex != URTW_CONFIG_INDEX)
+		return (ENXIO);
+	if (uaa->info.bIfaceIndex != URTW_IFACE_INDEX)
+		return (ENXIO);
+
+	return (usb2_lookup_id_by_uaa(urtw_devs, sizeof(urtw_devs), uaa));
+}
+
+static int
+urtw_attach(device_t dev)
+{
+	const struct usb2_config *setup_start;
+	int ret = ENXIO;
+	struct urtw_softc *sc = device_get_softc(dev);
+	struct usb2_attach_arg *uaa = device_get_ivars(dev);
+	struct ieee80211com *ic;
+	struct ifnet *ifp;
+	uint8_t bands, iface_index = URTW_IFACE_INDEX;		/* XXX */
+	uint16_t n_setup;
+	uint32_t data;
+	usb2_error_t error;
+
+	device_set_usb2_desc(dev);
+
+	sc->sc_dev = dev;
+	sc->sc_udev = uaa->device;
+	if (USB_GET_DRIVER_INFO(uaa) == URTW_REV_RTL8187B)
+		sc->sc_flags |= URTW_RTL8187B;
+#ifdef URTW_DEBUG
+	sc->sc_debug = urtw_debug;
+#endif
+
+	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
+	    MTX_DEF);
+	usb2_callout_init_mtx(&sc->sc_led_ch, &sc->sc_mtx, 0);
+	TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc);
+	callout_init(&sc->sc_watchdog_ch, 0);
+
+	if (sc->sc_flags & URTW_RTL8187B) {
+		setup_start = urtw_8187b_usbconfig;
+		n_setup = URTW_8187B_N_XFERS;
+	} else {
+		setup_start = urtw_8187l_usbconfig;
+		n_setup = URTW_8187L_N_XFERS;
+	}
+
+	error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+	    setup_start, n_setup, sc, &sc->sc_mtx);
+	if (error) {
+		device_printf(dev, "could not allocate USB transfers, "
+		    "err=%s\n", usb2_errstr(error));
+		ret = ENXIO;
+		goto fail0;
+	}
+
+	URTW_LOCK(sc);
+
+	urtw_read32_m(sc, URTW_RX, &data);
+	sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 :
+	    URTW_EEPROM_93C46;
+
+	error = urtw_get_rfchip(sc);
+	if (error != 0)
+		goto fail;
+	error = urtw_get_macaddr(sc);
+	if (error != 0)
+		goto fail;
+	error = urtw_get_txpwr(sc);
+	if (error != 0)
+		goto fail;
+	error = urtw_led_init(sc);
+	if (error != 0)
+		goto fail;
+
+	URTW_UNLOCK(sc);
+
+	sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY;
+	sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY;
+	sc->sc_currate = 3;
+	sc->sc_preamble_mode = urtw_preamble_mode;
+
+	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+	if (ifp == NULL) {
+		device_printf(sc->sc_dev, "can not allocate ifnet\n");
+		ret = ENOMEM;
+		goto fail1;
+	}
+
+	ifp->if_softc = sc;
+	if_initname(ifp, "urtw", device_get_unit(sc->sc_dev));
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_init = urtw_init;
+	ifp->if_ioctl = urtw_ioctl;
+	ifp->if_start = urtw_start;
+	/* XXX URTW_TX_DATA_LIST_COUNT */
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+	IFQ_SET_READY(&ifp->if_snd);
+
+	ic = ifp->if_l2com;
+	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_MONITOR |	/* monitor mode supported */
+	    IEEE80211_C_TXPMGT |	/* tx power management */
+	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
+	    IEEE80211_C_SHSLOT |	/* short slot time supported */
+	    IEEE80211_C_BGSCAN |	/* capable of bg scanning */
+	    IEEE80211_C_WPA;		/* 802.11i */
+
+	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 = urtw_raw_xmit;
+	ic->ic_scan_start = urtw_scan_start;
+	ic->ic_scan_end = urtw_scan_end;
+	ic->ic_set_channel = urtw_set_channel;
+
+	ic->ic_vap_create = urtw_vap_create;
+	ic->ic_vap_delete = urtw_vap_delete;
+	ic->ic_update_mcast = urtw_update_mcast;
+
+	ieee80211_radiotap_attach(ic,
+	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
+	    URTW_TX_RADIOTAP_PRESENT,
+	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
+	    URTW_RX_RADIOTAP_PRESENT);
+
+	if (bootverbose)
+		ieee80211_announce(ic);
+	return (0);
+
+fail:	URTW_UNLOCK(sc);
+fail1:	usb2_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
+	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
+fail0:
+	return (ret);
+}
+
+static int
+urtw_detach(device_t dev)
+{
+	struct urtw_softc *sc = device_get_softc(dev);
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+
+	if (!device_is_attached(dev))
+		return (0);
+
+	urtw_stop(ifp, 1);
+	ieee80211_draintask(ic, &sc->sc_led_task);
+
+	usb2_callout_drain(&sc->sc_led_ch);
+	callout_drain(&sc->sc_watchdog_ch);
+
+	usb2_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
+	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
+	ieee80211_ifdetach(ic);
+
+	urtw_free_tx_data_list(sc);
+	urtw_free_rx_data_list(sc);
+
+	if_free(ifp);
+	mtx_destroy(&sc->sc_mtx);
+
+	return (0);
+}
+
+static void
+urtw_free_tx_data_list(struct urtw_softc *sc)
+{
+
+	urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0);
+}
+
+static void
+urtw_free_rx_data_list(struct urtw_softc *sc)
+{
+
+	urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1);
+}
+
+static void
+urtw_free_data_list(struct urtw_softc *sc, struct urtw_data data[], int ndata,
+    int fillmbuf)
+{
+	int i;
+
+	for (i = 0; i < ndata; i++) {
+		struct urtw_data *dp = &data[i];
+
+		if (fillmbuf == 1) {
+			if (dp->m != NULL) {
+				m_freem(dp->m);
+				dp->m = NULL;
+				dp->buf = NULL;
+			}
+		} else {
+			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 ieee80211vap *
+urtw_vap_create(struct ieee80211com *ic,
+	const char name[IFNAMSIZ], int unit, int opmode, int flags,
+	const uint8_t bssid[IEEE80211_ADDR_LEN],
+	const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+	struct urtw_vap *uvp;
+	struct ieee80211vap *vap;
+
+	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
+		return (NULL);
+	uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap),
+	    M_80211_VAP, M_NOWAIT | M_ZERO);
+	if (uvp == NULL)
+		return (NULL);
+	vap = &uvp->vap;
+	/* enable s/w bmiss handling for sta mode */
+	ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+
+	/* override state transition machine */
+	uvp->newstate = vap->iv_newstate;
+	vap->iv_newstate = urtw_newstate;
+
+	/* complete setup */
+	ieee80211_vap_attach(vap, ieee80211_media_change,
+	    ieee80211_media_status);
+	ic->ic_opmode = opmode;
+	return (vap);
+}
+
+static void
+urtw_vap_delete(struct ieee80211vap *vap)
+{
+	struct urtw_vap *uvp = URTW_VAP(vap);
+
+	ieee80211_vap_detach(vap);
+	free(uvp, M_80211_VAP);
+}
+
+static void
+urtw_init_locked(void *arg)
+{
+	int ret;
+	struct urtw_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
+	usb2_error_t error;
+
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		urtw_stop_locked(ifp, 0);
+
+	error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
+	    urtw_adapter_start(sc);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list