changeset 10364:b6fbd1c0a94d

6850609 urtw driver needs to support RTL8187B chipset
author Qin Michael Li <Mikore.Li@Sun.COM>
date Fri, 21 Aug 2009 22:02:12 +0800
parents 4ab1c5069b3c
children 17f1ffe79b9e
files usr/src/pkgdefs/SUNWurtw/pkginfo.tmpl usr/src/pkgdefs/SUNWurtw/postinstall usr/src/uts/common/io/urtw/THIRDPARTYLICENSE usr/src/uts/common/io/urtw/THIRDPARTYLICENSE.descrip usr/src/uts/common/io/urtw/urtw.c usr/src/uts/common/io/urtw/urtw_reg.h usr/src/uts/common/io/urtw/urtw_var.h
diffstat 7 files changed, 1337 insertions(+), 443 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/pkgdefs/SUNWurtw/pkginfo.tmpl	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/pkgdefs/SUNWurtw/pkginfo.tmpl	Fri Aug 21 22:02:12 2009 +0800
@@ -25,7 +25,7 @@
 #
 
 PKG="SUNWurtw"
-NAME="RealTek RTL8187L USB 802.11b/g Wireless Driver"
+NAME="RealTek RTL8187L/B USB 802.11b/g Wireless Driver"
 ARCH="ISA"
 VERSION="ONVERS,REV=0.0.0"
 SUNW_PRODNAME="SunOS"
@@ -35,7 +35,7 @@
 MAXINST="1000"
 CATEGORY="system"
 VENDOR="Sun Microsystems, Inc."
-DESC="RealTek RTL8187L USB 802.11b/g Wireless Driver"
+DESC="RealTek RTL8187L/B USB 802.11b/g Wireless Driver"
 CLASSES="none"
 HOTLINE="Please contact your local service provider"
 EMAIL=""
--- a/usr/src/pkgdefs/SUNWurtw/postinstall	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/pkgdefs/SUNWurtw/postinstall	Fri Aug 21 22:02:12 2009 +0800
@@ -27,7 +27,9 @@
 
 # Driver info
 DRV=urtw
-DRVALIAS='"usb846,6a00"'
+DRVALIAS='"usb846,6a00"	"usb1371,9401" "usb789,10c" "usb114b,150"
+	"usbbda,8187" "usb769,11f2" "usb50d,705e" "usb846,4260"
+	"usbbda,8189" "usbbda,8197" "usbbda,8198" "usbdf6,28"'
 
 BASEDIR=${BASEDIR:-/}
 
--- a/usr/src/uts/common/io/urtw/THIRDPARTYLICENSE	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/uts/common/io/urtw/THIRDPARTYLICENSE	Fri Aug 21 22:02:12 2009 +0800
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2009 Martynas Venckus <martynas@openbsd.org>
  * Copyright (c) 2008 Weongyo Jeong
  * All rights reserved.
  *
--- a/usr/src/uts/common/io/urtw/THIRDPARTYLICENSE.descrip	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/uts/common/io/urtw/THIRDPARTYLICENSE.descrip	Fri Aug 21 22:02:12 2009 +0800
@@ -1,1 +1,1 @@
-REALTEK RTL8187L USB WIFI DRIVER
+REALTEK RTL8187L/B USB WIFI DRIVER
--- a/usr/src/uts/common/io/urtw/urtw.c	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/uts/common/io/urtw/urtw.c	Fri Aug 21 22:02:12 2009 +0800
@@ -63,7 +63,7 @@
 
 static struct modldrv urtw_modldrv = {
 	&mod_driverops,		/* Type of module.  This one is a driver */
-	"RTL8187L driver v1.1",	/* short description */
+	"RTL8187L/B driver v1.2",	/* short description */
 	&urtw_dev_ops		/* driver specific ops */
 };
 
@@ -83,6 +83,8 @@
 static void	urtw_m_ioctl(void *, queue_t *, mblk_t *);
 static int	urtw_m_setprop(void *, const char *, mac_prop_id_t,
     uint_t, const void *);
+static int urtw_m_getprop(void *, const char *, mac_prop_id_t,
+    uint_t, uint_t, void *, uint_t *);
 
 static mac_callbacks_t urtw_m_callbacks = {
 	MC_IOCTL | MC_SETPROP | MC_GETPROP,
@@ -98,7 +100,7 @@
 	NULL,
 	NULL,
 	urtw_m_setprop,
-	ieee80211_getprop
+	urtw_m_getprop
 };
 
 static int  urtw_tx_start(struct urtw_softc *, mblk_t *, int);
@@ -106,7 +108,7 @@
 
 
 /*
- * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
+ * Supported rates for 802.11b/g modes (in 500Kbps unit).
  */
 static const struct ieee80211_rateset urtw_rateset_11b =
 	{ 4, { 2, 4, 11, 22 } };
@@ -114,12 +116,138 @@
 static const struct ieee80211_rateset urtw_rateset_11g =
 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
 
+#define	USB_VENDOR_DICKSMITH	0x1371		/* Dick Smith Electronics */
+#define	USB_VENDOR_LOGITEC	0x0789		/* Logitec */
+#define	USB_VENDOR_NETGEAR	0x0846		/* BayNETGEAR */
+#define	USB_VENDOR_REALTEK	0x0bda		/* Realtek */
+#define	USB_VENDOR_SPHAIRON	0x114b		/* Sphairon Access Systems */
+#define	USB_VENDOR_SURECOM	0x0769		/* Surecom Technology */
+#define	USB_VENDOR_BELKIN	0x050d		/* Belkin Components */
+#define	USB_VENDOR_SITECOMEU	0x0df6		/* Sitecom Europe */
+
+#define	USB_PRODUCT_SPHAIRON_RTL8187	0x0150		/* RTL8187 */
+#define	USB_PRODUCT_DICKSMITH_RTL8187	0x9401		/* RTL8187 */
+#define	USB_PRODUCT_LOGITEC_RTL8187	0x010c		/* RTL8187 */
+#define	USB_PRODUCT_REALTEK_RTL8187	0x8187		/* RTL8187 */
+#define	USB_PRODUCT_NETGEAR_WG111V2	0x6a00		/* WG111v2 */
+#define	USB_PRODUCT_SURECOM_EP9001G2A	0x11f2		/* EP-9001-G rev 2A */
+#define	USB_PRODUCT_BELKIN_F5D7050E	0x705e		/* F5D705E 54g */
+#define	USB_PRODUCT_NETGEAR_WG111V3	0x4260		/* WG111v3 */
+#define	USB_PRODUCT_REALTEK_RTL8187B_0	0x8189		/* RTL8187B */
+#define	USB_PRODUCT_REALTEK_RTL8187B_1	0x8197		/* RTL8187B */
+#define	USB_PRODUCT_REALTEK_RTL8187B_2	0x8198		/* RTL8187B */
+#define	USB_PRODUCT_SITECOMEU_WL168	0x0028		/* WL-168 */
+
+#define	USB_PRODUCT_ANY	0xffff
+
+struct usb_devno {
+	uint16_t v;
+	uint16_t p;
+};
+
+/*
+ * Recognized device vendors/products.
+ */
+static struct urtw_type {
+	struct usb_devno	dev;
+	uint8_t			rev;
+} urtw_devs[] = {
+#define	URTW_DEV_RTL8187(v, p)	\
+	    { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187 }
+#define	URTW_DEV_RTL8187B(v, p)	\
+	    { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187B }
+	/* Realtek RTL8187 devices. */
+	URTW_DEV_RTL8187(DICKSMITH,	RTL8187),
+	URTW_DEV_RTL8187(LOGITEC,	RTL8187),
+	URTW_DEV_RTL8187(NETGEAR,	WG111V2),
+	URTW_DEV_RTL8187(REALTEK,	RTL8187),
+	URTW_DEV_RTL8187(SPHAIRON,	RTL8187),
+	URTW_DEV_RTL8187(SURECOM,	EP9001G2A),
+	/* Realtek RTL8187B devices. */
+	URTW_DEV_RTL8187B(BELKIN,	F5D7050E),
+	URTW_DEV_RTL8187B(NETGEAR,	WG111V3),
+	URTW_DEV_RTL8187B(REALTEK,	RTL8187B_0),
+	URTW_DEV_RTL8187B(REALTEK,	RTL8187B_1),
+	URTW_DEV_RTL8187B(REALTEK,	RTL8187B_2),
+	URTW_DEV_RTL8187B(SITECOMEU,	WL168)
+#undef	URTW_DEV_RTL8187
+#undef	URTW_DEV_RTL8187B
+};
+
+/*
+ * Search for a vendor/product pair in an array.  The item size is
+ * given as an argument.
+ */
+struct urtw_type *
+usb_match_device(struct urtw_type *tbl, uint32_t nentries,
+	uint16_t vendor, uint16_t product)
+{
+	while (nentries-- > 0) {
+		uint16_t tproduct = tbl[nentries].dev.p;
+		if (tbl[nentries].dev.v == vendor &&
+		    (tproduct == product || tproduct == USB_PRODUCT_ANY))
+		return (&tbl[nentries]);
+	}
+	return (NULL);
+}
+
+#define	usb_lookup(tbl, vendor, product) \
+	usb_match_device(tbl, sizeof (tbl) / sizeof ((tbl)[0]), \
+		(vendor), (product))
+
+#define	urtw_lookup(v, p)	(usb_lookup(urtw_devs, v, p))
 
 struct urtw_pair {
 	uint32_t	reg;
 	uint32_t	val;
 };
 
+struct urtw_pair_idx {
+	uint8_t		reg;
+	uint8_t		val;
+	uint8_t		idx;
+};
+
+static struct urtw_pair_idx urtw_8187b_regtbl[] = {
+	{ 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 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,
@@ -135,6 +263,36 @@
 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
 };
 
+static uint8_t urtw_8225v2_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 uint8_t urtw_8225v2_ofdm[] = {
+	0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
+	0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
+	0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
+	0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
+	0x0a, 0xe1, 0x2c, 0x8a, 0x86, 0x83, 0x34, 0x0f,
+	0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
+	0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
+	0x6d, 0x3c, 0xfb, 0x07
+};
+
 static uint32_t urtw_8225_channel[] = {
 	0x0000,		/* dummy channel 0  */
 	0x085c,		/* 1  */
@@ -280,16 +438,16 @@
 };
 
 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,
+	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
 };
@@ -304,11 +462,25 @@
 };
 
 static uint8_t urtw_8225v2_txpwr_cck[] = {
-	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+	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_8225v2_txpwr_cck_ch14[] = {
-	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+	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_8225v2_b_rf[] = {
+	{ 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 },
+	{ 0x00, 0x01b7 }
 };
 
 static struct urtw_pair urtw_ratetable[] = {
@@ -317,19 +489,25 @@
 	{ 96, 10 }, { 108, 11 }
 };
 
-static int		urtw_init(void *);
+static int		urtw_8187_init(void *);
 static void		urtw_stop(struct urtw_softc *);
 static int		urtw_set_channel(struct urtw_softc *);
 static void
 urtw_rxeof(usb_pipe_handle_t, usb_bulk_req_t *);
 static int
 urtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
-static usbd_status	urtw_read8_c(struct urtw_softc *, int, uint8_t *);
-static usbd_status	urtw_read16_c(struct urtw_softc *, int, uint16_t *);
-static usbd_status	urtw_read32_c(struct urtw_softc *, int, uint32_t *);
-static usbd_status	urtw_write8_c(struct urtw_softc *, int, uint8_t);
-static usbd_status	urtw_write16_c(struct urtw_softc *, int, uint16_t);
-static usbd_status	urtw_write32_c(struct urtw_softc *, int, uint32_t);
+static usbd_status
+urtw_read8_c(struct urtw_softc *, int, uint8_t *, uint8_t);
+static usbd_status
+urtw_read16_c(struct urtw_softc *, int, uint16_t *, uint8_t);
+static usbd_status
+urtw_read32_c(struct urtw_softc *, int, uint32_t *, uint8_t);
+static usbd_status
+urtw_write8_c(struct urtw_softc *, int, uint8_t, uint8_t);
+static usbd_status
+urtw_write16_c(struct urtw_softc *, int, uint16_t, uint8_t);
+static usbd_status
+urtw_write32_c(struct urtw_softc *, int, uint32_t, uint8_t);
 static usbd_status	urtw_eprom_cs(struct urtw_softc *, int);
 static usbd_status	urtw_eprom_ck(struct urtw_softc *);
 static usbd_status	urtw_eprom_sendbits(struct urtw_softc *, int16_t *,
@@ -344,15 +522,25 @@
 static usbd_status	urtw_led_init(struct urtw_softc *);
 static usbd_status
 urtw_8225_read(struct urtw_softc *, uint8_t, uint32_t *);
-static usbd_status	urtw_8225_rf_init(struct urtw_softc *);
-static usbd_status	urtw_8225_rf_set_chan(struct urtw_softc *, int);
-static usbd_status	urtw_8225_rf_set_sens(struct urtw_softc *, int);
-static usbd_status	urtw_8225v2_rf_init(struct urtw_softc *);
-static usbd_status	urtw_8225v2_rf_set_chan(struct urtw_softc *, int);
+static usbd_status	urtw_8225_rf_init(struct urtw_rf *);
+static usbd_status	urtw_8225_rf_set_chan(struct urtw_rf *, int);
+static usbd_status	urtw_8225_rf_set_sens(struct urtw_rf *);
+static usbd_status	urtw_8225v2_rf_init(struct urtw_rf *);
+static usbd_status	urtw_8225v2_rf_set_chan(struct urtw_rf *, int);
 static usbd_status	urtw_open_pipes(struct urtw_softc *);
 static void urtw_close_pipes(struct urtw_softc *);
 static void urtw_led_launch(void *);
 
+static void	urtw_8187b_update_wmm(struct urtw_softc *);
+static usbd_status	urtw_8187b_reset(struct urtw_softc *);
+static int	urtw_8187b_init(void *);
+static void	urtw_8225v2_b_config_mac(struct urtw_softc *);
+static void	urtw_8225v2_b_init_rfe(struct urtw_softc *);
+static usbd_status	urtw_8225v2_b_update_chan(struct urtw_softc *);
+static usbd_status	urtw_8225v2_b_rf_init(struct urtw_rf *);
+static usbd_status	urtw_8225v2_b_rf_set_chan(struct urtw_rf *, int);
+static void urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *, int);
+
 #ifdef DEBUG
 
 #define	URTW_DEBUG_XMIT		0x00000001
@@ -363,14 +551,13 @@
 #define	URTW_DEBUG_ATTACH 	0x00000020
 #define	URTW_DEBUG_ACTIVE 	0x00000040
 #define	URTW_DEBUG_HWTYPE	0x00000080
-#define	URTW_DEBUG_STATE	0x00000100
+#define	URTW_DEBUG_DEVREQ	0x00000100
 #define	URTW_DEBUG_HOTPLUG	0x00000200
-#define	URTW_DEBUG_STAT		0x00000400
+#define	URTW_DEBUG_STATE	0x00000400
 #define	URTW_DEBUG_TX_PROC	0x00000800
 #define	URTW_DEBUG_RX_PROC 	0x00001000
 #define	URTW_DEBUG_EEPROM	0x00002000
 #define	URTW_DEBUG_RESET	0x00004000
-#define	URTW_DEBUG_DEVREQ	0x00010000
 #define	URTW_DEBUG_ANY		0xffffffff
 
 uint32_t urtw8187_dbg_flags = 0;
@@ -407,7 +594,7 @@
 	uint32_t rev;
 	usbd_status error;
 
-	if (error = urtw_read8_c(sc, URTW_PSR, &sc->sc_psr))
+	if (error = urtw_read8_c(sc, URTW_PSR, &sc->sc_psr, 0))
 		goto fail;
 	error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev);
 	if (error != 0)
@@ -488,107 +675,109 @@
 	uint32_t mask = 0x80000000, value = 0;
 	usbd_status error;
 
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &o1))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &o1, 0))
 		goto fail;
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &o2))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &o2, 0))
 		goto fail;
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &o3))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &o3, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2 | 0xf))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2 | 0xf, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3 | 0xf))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3 | 0xf, 0))
 		goto fail;
 	o1 &= ~0xf;
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    o1 | URTW_BB_HOST_BANG_EN))
+	    o1 | URTW_BB_HOST_BANG_EN, 0))
 		goto fail;
 	DELAY(5);
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, o1))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, o1, 0))
 		goto fail;
 	DELAY(5);
 
 	for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) {
 		bit = ((d2w & mask) != 0) ? 1 : 0;
 
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1, 0))
 			goto fail;
 		DELAY(2);
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 |
-		    URTW_BB_HOST_BANG_CLK))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 |
-		    URTW_BB_HOST_BANG_CLK))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
 		mask = mask >> 1;
 		if (i == 2)
 			break;
 		bit = ((d2w & mask) != 0) ? 1 : 0;
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 |
-		    URTW_BB_HOST_BANG_CLK))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 |
-		    URTW_BB_HOST_BANG_CLK))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
-		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1))
+		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
+		    bit | o1, 0))
 			goto fail;
 		DELAY(1);
 	}
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    bit | o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK))
+	    bit | o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
 		goto fail;
 	DELAY(2);
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    bit | o1 | URTW_BB_HOST_BANG_RW))
+	    bit | o1 | URTW_BB_HOST_BANG_RW, 0))
 		goto fail;
 	DELAY(2);
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    o1 | URTW_BB_HOST_BANG_RW))
+	    o1 | URTW_BB_HOST_BANG_RW, 0))
 		goto fail;
 	DELAY(2);
 
 	mask = 0x800;
 	for (i = 0; i < rlen; i++, mask = mask >> 1) {
 		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-		    o1 | URTW_BB_HOST_BANG_RW))
+		    o1 | URTW_BB_HOST_BANG_RW, 0))
 			goto fail;
 		DELAY(2);
 		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK))
+		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
 		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK))
+		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
 		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK))
+		    o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
 			goto fail;
 		DELAY(2);
 
-		if (error = urtw_read16_c(sc, URTW_RF_PINS_INPUT, &tmp))
+		if (error = urtw_read16_c(sc, URTW_RF_PINS_INPUT, &tmp, 0))
 			goto fail;
 		value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0);
 		if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-		    o1 | URTW_BB_HOST_BANG_RW))
+		    o1 | URTW_BB_HOST_BANG_RW, 0))
 			goto fail;
 		DELAY(2);
 	}
 
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
 	    o1 | URTW_BB_HOST_BANG_EN |
-	    URTW_BB_HOST_BANG_RW))
+	    URTW_BB_HOST_BANG_RW, 0))
 		goto fail;
 	DELAY(2);
 
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3, 0))
 		goto fail;
-	error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x3a0);
+	error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x3a0, 0);
 
 	if (data != NULL)
 		*data = value;
@@ -608,42 +797,39 @@
 	uint16_t d80, d82, d84;
 	usbd_status error;
 
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &d80))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &d80, 0))
 		goto fail;
 	d80 &= 0xfff3;
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &d82))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &d82, 0))
 		goto fail;
-	if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &d84))
+	if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &d84, 0))
 		goto fail;
 	d84 &= 0xfff0;
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE,
-	    d82 | 0x0007))
+	    d82 | 0x0007, 0))
 		goto fail;
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT,
-	    d84 | 0x0007))
+	    d84 | 0x0007, 0))
 		goto fail;
-	DELAY(10);
 
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    d80 | URTW_BB_HOST_BANG_EN))
+	    d80 | URTW_BB_HOST_BANG_EN, 0))
 		goto fail;
-	DELAY(2);
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, d80))
+	urtw_delay_ms(2);
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, d80, 0))
 		goto fail;
-	DELAY(10);
 
 	error = urtw_8225_write_s16(sc, addr, 0x8225, &data);
 	if (error != 0)
 		goto fail;
 
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    d80 | URTW_BB_HOST_BANG_EN))
+	    d80 | URTW_BB_HOST_BANG_EN, 0))
 		goto fail;
-	DELAY(10);
 	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
-	    d80 | URTW_BB_HOST_BANG_EN))
+	    d80 | URTW_BB_HOST_BANG_EN, 0))
 		goto fail;
-	error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, d84);
+	error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, d84, 0);
 	urtw_delay_ms(2);
 fail:
 	return (error);
@@ -657,11 +843,11 @@
 
 	*ret = 1;
 
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0080))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0080, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x0080))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x0080, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x0080))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x0080, 0))
 		goto fail;
 	urtw_delay_ms(300);
 
@@ -689,41 +875,64 @@
 static usbd_status
 urtw_get_rfchip(struct urtw_softc *sc)
 {
+	struct urtw_rf *rf = &sc->sc_rf;
 	int ret;
 	uint32_t data;
 	usbd_status error;
 
-	error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data);
-	if (error != 0)
-		goto fail;
-	switch (data & 0xff) {
-	case URTW_EPROM_RFCHIPID_RTL8225U:
-		error = urtw_8225_isv2(sc, &ret);
-		if (error != 0)
+	rf->rf_sc = sc;
+
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data);
+		if (error != 0) {
+			cmn_err(CE_WARN, "RF ID read failed\n");
+			return (-1);
+		}
+		switch (data & 0xff) {
+		case URTW_EPROM_RFCHIPID_RTL8225U:
+			error = urtw_8225_isv2(sc, &ret);
+			if (error != 0) {
+				URTW8187_DBG(URTW_DEBUG_HWTYPE,
+				    (sc->sc_dev, CE_CONT,
+				    "8225 version check failed\n"));
+				goto fail;
+			}
+			if (ret == 0) {
+				URTW8187_DBG(URTW_DEBUG_HWTYPE,
+				    (sc->sc_dev, CE_CONT,
+				    "8225 detected\n"));
+				rf->init = urtw_8225_rf_init;
+				rf->set_chan = urtw_8225_rf_set_chan;
+				rf->set_sens = urtw_8225_rf_set_sens;
+			} else {
+				URTW8187_DBG(URTW_DEBUG_HWTYPE,
+				    (sc->sc_dev, CE_CONT,
+				    "8225 v2 detected\n"));
+				rf->init = urtw_8225v2_rf_init;
+				rf->set_chan = urtw_8225v2_rf_set_chan;
+				rf->set_sens = NULL;
+			}
+			break;
+		default:
 			goto fail;
-		if (ret == 0) {
-			URTW8187_DBG(URTW_DEBUG_HWTYPE,
-			    (sc->sc_dev, CE_CONT, "8225 RF chip detected\n"));
-			sc->sc_rf_init = urtw_8225_rf_init;
-			sc->sc_rf_set_sens = urtw_8225_rf_set_sens;
-			sc->sc_rf_set_chan = urtw_8225_rf_set_chan;
-		} else {
-			URTW8187_DBG(URTW_DEBUG_HWTYPE,
-			    (sc->sc_dev, CE_CONT,
-			    "8225 v2 RF chip detected\n"));
-			sc->sc_rf_init = urtw_8225v2_rf_init;
-			sc->sc_rf_set_chan = urtw_8225v2_rf_set_chan;
 		}
-		sc->sc_max_sens = URTW_8225_RF_MAX_SENS;
-		sc->sc_sens = URTW_8225_RF_DEF_SENS;
-		break;
-	default:
-		cmn_err(CE_WARN, "unsupported RF chip %d\n", data & 0xff);
-		error = -1;
+	} else {
+		URTW8187_DBG(URTW_DEBUG_HWTYPE,
+		    (sc->sc_dev, CE_CONT,
+		    "8225 v2 [b] detected\n"));
+		rf->init = urtw_8225v2_b_rf_init;
+		rf->set_chan = urtw_8225v2_b_rf_set_chan;
+		rf->set_sens = NULL;
 	}
 
+	rf->max_sens = URTW_8225_RF_MAX_SENS;
+	rf->sens = URTW_8225_RF_DEF_SENS;
+
+	return (0);
+
 fail:
-	return (error);
+	cmn_err(CE_WARN, "unsupported RF chip %d\n", data & 0xff);
+	return (-1);
 }
 
 static usbd_status
@@ -757,19 +966,47 @@
 		sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4;
 		sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12;
 	}
-	for (i = 1, j = 0; i < 4; i += 2, j++) {
-		error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, &data);
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		for (i = 1, j = 0; i < 4; i += 2, j++) {
+			error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j,
+			    &data);
+			if (error != 0)
+				goto fail;
+			sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf;
+			sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8;
+			sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4;
+			sc->sc_txpwr_ofdm[i + 6 + 4 + 1] =
+			    (data & 0xf000) >> 12;
+		}
+	} else {
+		/* Channel 11. */
+		error = urtw_eprom_read32(sc, 0x1b, &data);
 		if (error != 0)
 			goto fail;
-		sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf;
-		sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8;
-		sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4;
-		sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12;
+		sc->sc_txpwr_cck[11] = data & 0xf;
+		sc->sc_txpwr_ofdm[11] = (data & 0xf0) >> 4;
+
+		/* Channel 12. */
+		error = urtw_eprom_read32(sc, 0xa, &data);
+		if (error != 0)
+			goto fail;
+		sc->sc_txpwr_cck[12] = data & 0xf;
+		sc->sc_txpwr_ofdm[12] = (data & 0xf0) >> 4;
+
+		/* Channel 13, 14. */
+		error = urtw_eprom_read32(sc, 0x1c, &data);
+		if (error != 0)
+			goto fail;
+		sc->sc_txpwr_cck[13] = data & 0xf;
+		sc->sc_txpwr_ofdm[13] = (data & 0xf0) >> 4;
+		sc->sc_txpwr_cck[14] = (data & 0xf00) >> 8;
+		sc->sc_txpwr_ofdm[14] = (data & 0xf000) >> 12;
 	}
 fail:
 	return (error);
 }
 
+
 static usbd_status
 urtw_get_macaddr(struct urtw_softc *sc)
 {
@@ -814,7 +1051,7 @@
 
 	/* enable EPROM programming */
 	if (error = urtw_write8_c(sc, URTW_EPROM_CMD,
-	    URTW_EPROM_CMD_PROGRAM_MODE))
+	    URTW_EPROM_CMD_PROGRAM_MODE, 0))
 		goto fail;
 	DELAY(URTW_EPROM_DELAY);
 
@@ -873,7 +1110,8 @@
 		goto fail;
 
 	/* now disable EPROM programming */
-	error = urtw_write8_c(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_NORMAL_MODE);
+	error = urtw_write8_c(sc, URTW_EPROM_CMD,
+	    URTW_EPROM_CMD_NORMAL_MODE, 0);
 fail:
 	return (error);
 #undef URTW_READCMD_LEN
@@ -885,7 +1123,7 @@
 	uint8_t data8;
 	usbd_status error;
 
-	error = urtw_read8_c(sc, URTW_EPROM_CMD, &data8);
+	error = urtw_read8_c(sc, URTW_EPROM_CMD, &data8, 0);
 	*data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
 	DELAY(URTW_EPROM_DELAY);
 	return (error);
@@ -915,14 +1153,14 @@
 	uint8_t data;
 	usbd_status error;
 
-	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
 		goto fail;
 	if (bit != 0)
 		error = urtw_write8_c(sc, URTW_EPROM_CMD,
-		    data | URTW_EPROM_WRITEBIT);
+		    data | URTW_EPROM_WRITEBIT, 0);
 	else
 		error = urtw_write8_c(sc, URTW_EPROM_CMD,
-		    data & ~URTW_EPROM_WRITEBIT);
+		    data & ~URTW_EPROM_WRITEBIT, 0);
 	DELAY(URTW_EPROM_DELAY);
 fail:
 	return (error);
@@ -935,15 +1173,15 @@
 	usbd_status error;
 
 	/* masking  */
-	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK))
+	if (error = urtw_write8_c(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK, 0))
 		goto fail;
 	DELAY(URTW_EPROM_DELAY);
 	/* unmasking  */
-	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
 		goto fail;
-	error = urtw_write8_c(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK);
+	error = urtw_write8_c(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK, 0);
 	DELAY(URTW_EPROM_DELAY);
 fail:
 	return (error);
@@ -955,21 +1193,21 @@
 	uint8_t data;
 	usbd_status error;
 
-	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
 		goto fail;
 	if (able == URTW_EPROM_ENABLE)
 		error = urtw_write8_c(sc, URTW_EPROM_CMD,
-		    data | URTW_EPROM_CS);
+		    data | URTW_EPROM_CS, 0);
 	else
 		error = urtw_write8_c(sc, URTW_EPROM_CMD,
-		    data & ~URTW_EPROM_CS);
+		    data & ~URTW_EPROM_CS, 0);
 	DELAY(URTW_EPROM_DELAY);
 fail:
 	return (error);
 }
 
 static usbd_status
-urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data)
+urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -981,7 +1219,7 @@
 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_GETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint8_t);
 
 	error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
@@ -994,8 +1232,6 @@
 		return (error);
 	}
 	bcopy(mp->b_rptr, data, sizeof (uint8_t));
-	URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
-	    "urtw_read8_c: get regs data1 ok :0x%x", *data));
 	if (mp)
 		freemsg(mp);
 	return (error);
@@ -1029,15 +1265,13 @@
 
 	if (mp) {
 		bcopy(mp->b_rptr, data, sizeof (uint8_t));
-		URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
-		    "urtw_read8e: get regs data1 ok :0x%x", *data));
 		freemsg(mp);
 	}
 	return (error);
 }
 
 static usbd_status
-urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data)
+urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -1049,7 +1283,7 @@
 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_GETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint16_t);
 	req.attrs = USB_ATTRS_AUTOCLEARING;
 	error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
@@ -1064,15 +1298,13 @@
 	}
 	if (mp) {
 		bcopy(mp->b_rptr, data, sizeof (uint16_t));
-		URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
-		    "urtw_read16_c: get regs data2 ok :0x%x", *data));
 		freemsg(mp);
 	}
 	return (error);
 }
 
 static usbd_status
-urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data)
+urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -1084,7 +1316,7 @@
 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_GETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint32_t);
 	req.attrs = USB_ATTRS_AUTOCLEARING;
 
@@ -1100,15 +1332,13 @@
 
 	if (mp) {
 		bcopy(mp->b_rptr, data, sizeof (uint32_t));
-		URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
-		    "urtw_read32_c: get regs data4 ok :0x%x", *data));
 		freemsg(mp);
 	}
 	return (error);
 }
 
 static usbd_status
-urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data)
+urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -1120,7 +1350,7 @@
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_SETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint8_t);
 	req.attrs = USB_ATTRS_NONE;
 
@@ -1182,7 +1412,7 @@
 }
 
 static usbd_status
-urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data)
+urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -1194,7 +1424,7 @@
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_SETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint16_t);
 	req.attrs = USB_ATTRS_NONE;
 
@@ -1219,7 +1449,7 @@
 }
 
 static usbd_status
-urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
+urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data, uint8_t idx)
 {
 	usb_ctrl_setup_t req;
 	usb_cr_t cr;
@@ -1231,7 +1461,7 @@
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = URTW_8187_SETREGS_REQ;
 	req.wValue = val | 0xff00;
-	req.wIndex = 0;
+	req.wIndex = idx & 0x03;
 	req.wLength = sizeof (uint32_t);
 	req.attrs = USB_ATTRS_NONE;
 
@@ -1262,11 +1492,11 @@
 	uint8_t data;
 	usbd_status error;
 
-	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
 		goto fail;
 	data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
 	data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
-	error = urtw_write8_c(sc, URTW_EPROM_CMD, data);
+	error = urtw_write8_c(sc, URTW_EPROM_CMD, data, 0);
 fail:
 	return (error);
 }
@@ -1281,17 +1511,17 @@
 	if (error)
 		goto fail;
 
-	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data))
+	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
 		goto fail;
 	if (error = urtw_write8_c(sc, URTW_CONFIG3,
-	    data | URTW_CONFIG3_ANAPARAM_WRITE))
+	    data | URTW_CONFIG3_ANAPARAM_WRITE, 0))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_ANAPARAM, val))
+	if (error = urtw_write32_c(sc, URTW_ANAPARAM, val, 0))
 		goto fail;
-	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data))
+	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
 		goto fail;
 	if (error = urtw_write8_c(sc, URTW_CONFIG3,
-	    data & ~URTW_CONFIG3_ANAPARAM_WRITE))
+	    data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0))
 		goto fail;
 
 	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
@@ -1311,17 +1541,17 @@
 	if (error)
 		goto fail;
 
-	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data))
+	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
 		goto fail;
 	if (error = urtw_write8_c(sc, URTW_CONFIG3,
-	    data | URTW_CONFIG3_ANAPARAM_WRITE))
+	    data | URTW_CONFIG3_ANAPARAM_WRITE, 0))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_ANAPARAM2, val))
+	if (error = urtw_write32_c(sc, URTW_ANAPARAM2, val, 0))
 		goto fail;
-	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data))
+	if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
 		goto fail;
 	if (error = urtw_write8_c(sc, URTW_CONFIG3,
-	    data & ~URTW_CONFIG3_ANAPARAM_WRITE))
+	    data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0))
 		goto fail;
 
 	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
@@ -1336,20 +1566,20 @@
 {
 	usbd_status error;
 
-	error = urtw_write16_c(sc, URTW_INTR_MASK, 0);
+	error = urtw_write16_c(sc, URTW_INTR_MASK, 0, 0);
 	return (error);
 }
 
 static usbd_status
-urtw_reset(struct urtw_softc *sc)
+urtw_8187_reset(struct urtw_softc *sc)
 {
 	uint8_t data;
 	usbd_status error;
 
-	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
+	error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
 	if (error)
 		goto fail;
-	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
+	error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
 	if (error)
 		goto fail;
 
@@ -1369,14 +1599,14 @@
 		goto fail;
 	urtw_delay_ms(50);
 
-	if (error = urtw_read8_c(sc, URTW_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
 		goto fail;
 	data = (data & 2) | URTW_CMD_RST;
-	if (error = urtw_write8_c(sc, URTW_CMD, data))
+	if (error = urtw_write8_c(sc, URTW_CMD, data, 0))
 		goto fail;
 	urtw_delay_ms(50);
 
-	if (error = urtw_read8_c(sc, URTW_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
 		goto fail;
 	if (data & URTW_CMD_RST) {
 		cmn_err(CE_CONT, "urtw reset timeout\n");
@@ -1387,10 +1617,10 @@
 		goto fail;
 	urtw_delay_ms(50);
 
-	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
+	error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
 	if (error)
 		goto fail;
-	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
+	error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
 	if (error)
 		goto fail;
 fail:
@@ -1403,8 +1633,8 @@
 	if (type == URTW_LED_GPIO) {
 		switch (sc->sc_gpio_ledpin) {
 		case URTW_LED_PIN_GPIO0:
-			(void) urtw_write8_c(sc, URTW_GPIO, 0x01);
-			(void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x00);
+			(void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0);
+			(void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x00, 0);
 			break;
 		default:
 			cmn_err(CE_WARN, "unsupported LED PIN type 0x%x",
@@ -1426,8 +1656,8 @@
 	if (type == URTW_LED_GPIO) {
 		switch (sc->sc_gpio_ledpin) {
 		case URTW_LED_PIN_GPIO0:
-			(void) urtw_write8_c(sc, URTW_GPIO, 0x01);
-			(void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x01);
+			(void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0);
+			(void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x01, 0);
 			break;
 		default:
 			cmn_err(CE_WARN, "unsupported LED PIN type 0x%x",
@@ -1610,10 +1840,14 @@
 	uint8_t data;
 	usbd_status error;
 
-	if (error = urtw_read8_c(sc, URTW_MSR, &data))
+	if (error = urtw_read8_c(sc, URTW_MSR, &data, 0))
 		goto fail;
 	data &= ~URTW_MSR_LINK_MASK;
 
+	/* Should always be set. */
+	if (sc->sc_hwrev & URTW_HWREV_8187B)
+		data |= URTW_MSR_LINK_ENEDCA;
+
 	if (nstate == IEEE80211_S_RUN) {
 		switch (ic->ic_opmode) {
 		case IEEE80211_M_STA:
@@ -1634,8 +1868,7 @@
 	} else
 		data |= URTW_MSR_LINK_NONE;
 
-	error = urtw_write8_c(sc, URTW_MSR, data);
-	drv_usecwait(10000);
+	error = urtw_write8_c(sc, URTW_MSR, data, 0);
 fail:
 	return (error);
 }
@@ -1681,17 +1914,17 @@
 	max_rr_rate = urtw_rate2rtl(48);
 	if (error = urtw_write8_c(sc, URTW_RESP_RATE,
 	    max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
-	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT))
+	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT, 0))
 		goto fail;
 
-	if (error = urtw_read16_c(sc, URTW_BRSR, &data))
+	if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
 		goto fail;
 	data &= ~URTW_BRSR_MBR_8185;
 
 	for (i = 0; i <= basic_rate; i++)
 		data |= (1 << i);
 
-	error = urtw_write16_c(sc, URTW_BRSR, data);
+	error = urtw_write16_c(sc, URTW_BRSR, data, 0);
 fail:
 	return (error);
 }
@@ -1701,82 +1934,7 @@
 {
 	usbd_status error;
 
-	error = urtw_write16_c(sc, URTW_INTR_MASK, 0xffff);
-	return (error);
-}
-
-static usbd_status
-urtw_adapter_start(struct urtw_softc *sc)
-{
-	struct ieee80211com *ic = &sc->sc_ic;
-	usbd_status error;
-	int i = 0;
-
-	error = urtw_reset(sc);
-	if (error)
-		goto fail;
-
-	if (error = urtw_write8_c(sc, 0x85, 0))
-		goto fail;
-	if (error = urtw_write8_c(sc, URTW_GPIO, 0))
-		goto fail;
-
-	/* for led  */
-	if (error = urtw_write8_c(sc, 0x85, 4))
-		goto fail;
-	error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON);
-	if (error != 0)
-		goto fail;
-
-	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
-	if (error)
-		goto fail;
-	/* applying MAC address again.  */
-	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
-		(void) urtw_write8_c(sc, URTW_MAC0 + i,
-		    ic->ic_macaddr[i]);
-	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
-	if (error)
-		goto fail;
-
-	error = urtw_update_msr(sc, IEEE80211_S_INIT);
-	if (error)
-		goto fail;
-
-	if (error = urtw_write32_c(sc, URTW_INT_TIMEOUT, 0))
-		goto fail;
-	if (error = urtw_write8_c(sc, URTW_WPA_CONFIG, 0))
-		goto fail;
-	if (error = urtw_write8_c(sc, URTW_RATE_FALLBACK, 0x81))
-		goto fail;
-	error = urtw_set_rate(sc);
-	if (error != 0)
-		goto fail;
-
-	error = sc->sc_rf_init(sc);
-	if (error != 0)
-		goto fail;
-	if (sc->sc_rf_set_sens != NULL)
-		sc->sc_rf_set_sens(sc, sc->sc_sens);
-
-	if (error = urtw_write16_c(sc, 0x5e, 1))
-		goto fail;
-	if (error = urtw_write16_c(sc, 0xfe, 0x10))
-		goto fail;
-	if (error = urtw_write8_c(sc, URTW_TALLY_SEL, 0x80))
-		goto fail;
-	if (error = urtw_write8_c(sc, 0xff, 0x60))
-		goto fail;
-	if (error = urtw_write16_c(sc, 0x5e, 0))
-		goto fail;
-	if (error = urtw_write8_c(sc, 0x85, 4))
-		goto fail;
-	ic->ic_curchan = &ic->ic_sup_channels[1];
-	error = urtw_intr_enable(sc);
-	if (error != 0)
-		goto fail;
-
-fail:
+	error = urtw_write16_c(sc, URTW_INTR_MASK, 0xffff, 0);
 	return (error);
 }
 
@@ -1787,7 +1945,7 @@
 	uint32_t data, a, b;
 	usbd_status error;
 
-	if (urtw_read32_c(sc, URTW_RX, &data))
+	if (urtw_read32_c(sc, URTW_RX, &data, 0))
 		goto fail;
 	data = data &~ URTW_RX_FILTER_MASK;
 	data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
@@ -1808,7 +1966,7 @@
 	b = 0x80000000;
 	data = data | a | b;
 
-	error = urtw_write32_c(sc, URTW_RX, data);
+	error = urtw_write32_c(sc, URTW_RX, data, 0);
 fail:
 	return (error);
 }
@@ -1831,66 +1989,116 @@
 	if (error != 0)
 		goto fail;
 
-	if (error = urtw_read8_c(sc, URTW_CMD, &data))
+	if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
 		goto fail;
-	error = urtw_write8_c(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE);
+	error = urtw_write8_c(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE, 0);
 fail:
 	return (error);
 }
 
-static usbd_status
+void
 urtw_tx_enable(struct urtw_softc *sc)
 {
 	uint8_t data8;
 	uint32_t data;
-	usbd_status error;
-
-	if (error = urtw_read8_c(sc, URTW_CW_CONF, &data8))
-		goto fail;
-	data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY);
-	if (error = urtw_write8_c(sc, URTW_CW_CONF, data8))
-		goto fail;
-
-	if (error = urtw_read8_c(sc, URTW_TX_AGC_CTL, &data8))
-		goto fail;
-	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
-	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
-	data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
-	if (error = urtw_write8_c(sc, URTW_TX_AGC_CTL, data8))
-		goto fail;
-
-	if (error = urtw_read32_c(sc, URTW_TX_CONF, &data))
-		goto fail;
-	data &= ~URTW_TX_LOOPBACK_MASK;
-	data |= URTW_TX_LOOPBACK_NONE;
-	data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
-	data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
-	data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
-	data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
-	data |= URTW_TX_MXDMA_2048 | 0x80000000 | URTW_TX_DISCW;
-	data &= ~URTW_TX_SWPLCPLEN;
-	data |= URTW_TX_NOICV;
-	if (error = urtw_write32_c(sc, URTW_TX_CONF, data))
-		goto fail;
-	if (error = urtw_read8_c(sc, URTW_CMD, &data8))
-		goto fail;
-	error = urtw_write8_c(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
-fail:
-	return (error);
+
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		(void) urtw_read8_c(sc, URTW_CW_CONF, &data8, 0);
+		data8 &= ~(URTW_CW_CONF_PERPACKET_CW |
+		    URTW_CW_CONF_PERPACKET_RETRY);
+		(void) urtw_write8_c(sc, URTW_CW_CONF, data8, 0);
+		(void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data8, 0);
+		data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
+		data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
+		data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
+		(void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data8, 0);
+
+		(void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0);
+		data &= ~URTW_TX_LOOPBACK_MASK;
+		data |= URTW_TX_LOOPBACK_NONE;
+		data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
+		data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
+		data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
+		data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
+		data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
+		data &= ~URTW_TX_SWPLCPLEN;
+		data |= URTW_TX_NOICV;
+		(void) urtw_write32_c(sc, URTW_TX_CONF, data, 0);
+	} else {
+		data = URTW_TX_DURPROCMODE | URTW_TX_DISREQQSIZE |
+		    URTW_TX_MXDMA_2048 | URTW_TX_SHORTRETRY |
+		    URTW_TX_LONGRETRY;
+		(void) urtw_write32_c(sc, URTW_TX_CONF, data, 0);
+	}
+
+	(void) urtw_read8_c(sc, URTW_CMD, &data8, 0);
+	(void) urtw_write8_c(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE, 0);
 }
 
 static int
-urtw_init(void *arg)
+urtw_8187_init(void *arg)
 {
 	struct urtw_softc *sc = arg;
 	usbd_status error;
+	struct urtw_rf *rf = &sc->sc_rf;
+	int i;
 
 	urtw_stop(sc);
 	URTW_LOCK(sc);
-	error = urtw_open_pipes(sc);
+	error = urtw_8187_reset(sc);
+	if (error)
+		goto fail;
+
+	(void) urtw_write8_c(sc, 0x85, 0, 0);
+	(void) urtw_write8_c(sc, URTW_GPIO, 0, 0);
+
+	/* for led */
+	(void) urtw_write8_c(sc, 0x85, 4, 0);
+	error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON);
 	if (error != 0)
 		goto fail;
-	error = urtw_adapter_start(sc);
+
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
+	if (error)
+		goto fail;
+
+	/* applying MAC address again.  */
+	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
+		(void) urtw_write8_c(sc, URTW_MAC0 + i,
+		    sc->sc_ic.ic_macaddr[i], 0);
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
+	if (error)
+		goto fail;
+
+	error = urtw_update_msr(sc, IEEE80211_S_INIT);
+	if (error)
+		goto fail;
+
+	(void) urtw_write32_c(sc, URTW_INT_TIMEOUT, 0, 0);
+	(void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0);
+	(void) urtw_write8_c(sc, URTW_RATE_FALLBACK, 0x81, 0);
+	error = urtw_set_rate(sc);
+	if (error != 0)
+		goto fail;
+
+	error = rf->init(rf);
+	if (error != 0)
+		goto fail;
+	if (rf->set_sens != NULL)
+		rf->set_sens(rf);
+
+	(void) urtw_write16_c(sc, 0x5e, 1, 0);
+	(void) urtw_write16_c(sc, 0xfe, 0x10, 0);
+	(void) urtw_write8_c(sc, URTW_TALLY_SEL, 0x80, 0);
+	(void) urtw_write8_c(sc, 0xff, 0x60, 0);
+	(void) urtw_write16_c(sc, 0x5e, 0, 0);
+	(void) urtw_write8_c(sc, 0x85, 4, 0);
+
+	error = urtw_intr_enable(sc);
+	if (error != 0)
+		goto fail;
+
+	error = urtw_open_pipes(sc);
 	if (error != 0)
 		goto fail;
 	sc->sc_tx_low_queued = 0;
@@ -1898,13 +2106,11 @@
 	error = urtw_rx_enable(sc);
 	if (error != 0)
 		goto fail;
-	error = urtw_tx_enable(sc);
-	if (error != 0)
-		goto fail;
+	urtw_tx_enable(sc);
 
 	if (error == 0) {
 		URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev,
-		    CE_CONT, "urtw_init: succesfully done\n"));
+		    CE_CONT, "urtw_8187_init: succesfully done\n"));
 		sc->sc_flags |= URTW_FLAG_RUNNING;
 		URTW_UNLOCK(sc);
 		return (error);
@@ -1913,7 +2119,7 @@
 fail:
 	URTW_UNLOCK(sc);
 	urtw_stop(sc);
-	return (error);
+	return (EIO);
 }
 
 
@@ -1923,25 +2129,25 @@
 	uint8_t data;
 	usbd_status error;
 
-	if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 0))
+	if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 0, 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_GPIO, 0))
+	if (error = urtw_write8_c(sc, URTW_GPIO, 0, 0))
 		goto fail;
 	if (error = urtw_read8e(sc, 0x53, &data))
 		goto fail;
 	if (error = urtw_write8e(sc, 0x53, data | (1 << 7)))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 4))
+	if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 4, 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_GPIO, 0x20))
+	if (error = urtw_write8_c(sc, URTW_GPIO, 0x20, 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_GP_ENABLE, 0))
+	if (error = urtw_write8_c(sc, URTW_GP_ENABLE, 0, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x80))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x80, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x80))
+	if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x80, 0))
 		goto fail;
-	error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x80);
+	error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x80, 0);
 
 	urtw_delay_ms(100);
 fail:
@@ -1953,7 +2159,7 @@
 {
 	usbd_status error = 0;
 
-	error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1ff7);
+	error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1ff7, 0);
 	return (error);
 }
 
@@ -1964,14 +2170,17 @@
 	usbd_status error;
 
 	phyw = ((data << 8) | (addr | 0x80));
-	if (error = urtw_write8_c(sc, 0x7f, ((phyw & 0xff000000) >> 24)))
+	if (error = urtw_write8_c(sc, 0x7f, ((phyw & 0xff000000) >> 24), 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, 0x7e, ((phyw & 0x00ff0000) >> 16)))
+	if (error = urtw_write8_c(sc, 0x7e, ((phyw & 0x00ff0000) >> 16), 0))
+		goto fail;
+	if (error = urtw_write8_c(sc, 0x7d, ((phyw & 0x0000ff00) >> 8), 0))
 		goto fail;
-	if (error = urtw_write8_c(sc, 0x7d, ((phyw & 0x0000ff00) >> 8)))
-		goto fail;
-	error = urtw_write8_c(sc, 0x7c, ((phyw & 0x000000ff)));
-	urtw_delay_ms(1);
+	error = urtw_write8_c(sc, 0x7c, (phyw & 0x000000ff), 0);
+	/*
+	 * Delay removed from 8185 to 8187.
+	 * usbd_delay_ms(sc->sc_udev, 1);
+	 */
 fail:
 	return (error);
 }
@@ -2033,7 +2242,7 @@
 	    urtw_8225_txpwr_cck;
 
 	if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK,
-	    urtw_8225_tx_gain_cck_ofdm[set] >> 1))
+	    urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0))
 		goto fail;
 	for (i = 0; i < 8; i++) {
 		if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i,
@@ -2048,7 +2257,7 @@
 	idx = ofdm_pwrlvl % 6;
 	set = ofdm_pwrlvl / 6;
 
-	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
+	error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
 	if (error)
 		goto fail;
 	if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42))
@@ -2059,7 +2268,7 @@
 		goto fail;
 
 	if (error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
-	    urtw_8225_tx_gain_cck_ofdm[set] >> 1))
+	    urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0))
 		goto fail;
 	if (error = urtw_8187_write_phy_ofdm_c(sc, 0x5,
 	    urtw_8225_txpwr_ofdm[idx]))
@@ -2076,37 +2285,38 @@
 {
 	usbd_status error;
 
-	error = urtw_write8_c(sc, URTW_TX_ANTENNA, ant);
+	error = urtw_write8_c(sc, URTW_TX_ANTENNA, ant, 0);
 	urtw_delay_ms(1);
 	return (error);
 }
 
 static usbd_status
-urtw_8225_rf_init(struct urtw_softc *sc)
+urtw_8225_rf_init(struct urtw_rf *rf)
 {
 #define	N(a)	(sizeof (a) / sizeof ((a)[0]))
 	int i;
 	uint16_t data;
 	usbd_status error;
-
-	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
+	struct urtw_softc *sc = rf->rf_sc;
+
+	error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
 	if (error)
 		goto fail;
 
 	if (error = urtw_8225_usb_init(sc))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008))
+	if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0))
 		goto fail;
-	if (error = urtw_read16_c(sc, URTW_BRSR, &data))
+	if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff))
+	if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044))
+	if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0))
 		goto fail;
 
 	if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44))
+	if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0))
 		goto fail;
 	if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL))
 		goto fail;
@@ -2172,7 +2382,7 @@
 		urtw_delay_ms(1);
 	}
 
-	if (error = urtw_write8_c(sc, 0x5b, 0x0d))
+	if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0))
 		goto fail;
 	if (error = urtw_8225_set_txpwrlvl(sc, 1))
 		goto fail;
@@ -2186,23 +2396,25 @@
 	/* TX ant A, 0x0 for B */
 	if (error = urtw_8185_tx_antenna(sc, 0x3))
 		goto fail;
-	if (error = urtw_write32_c(sc, 0x94, 0x3dc00002))
+	if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0))
 		goto fail;
 
-	error = urtw_8225_rf_set_chan(sc, 1);
+	error = urtw_8225_rf_set_chan(rf,
+	    ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
 fail:
 	return (error);
 #undef N
 }
 
 static usbd_status
-urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
+urtw_8225_rf_set_chan(struct urtw_rf *rf, int chan)
 {
 #define	IEEE80211_CHAN_G	\
 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
 #define	IEEE80211_IS_CHAN_G(_c)		\
 	(((_c)->ich_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
 
+	struct urtw_softc *sc = rf->rf_sc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_channel *c = ic->ic_curchan;
 	short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0;
@@ -2214,30 +2426,30 @@
 		goto fail;
 	urtw_delay_ms(10);
 
-	if (error = urtw_write8_c(sc, URTW_SIFS, 0x22))
+	if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0))
 		goto fail;
 
 	if (ic->ic_state == IEEE80211_S_ASSOC &&
 	    ic->ic_flags & IEEE80211_F_SHSLOT)
-		if (error = urtw_write8_c(sc, URTW_SLOT, 0x9))
+		if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0))
 			goto fail;
 	else
-		if (error = urtw_write8_c(sc, URTW_SLOT, 0x14))
+		if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0))
 			goto fail;
 	if (gset) {
 		/* for G */
-		if (error = urtw_write8_c(sc, URTW_DIFS, 0x14))
+		if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14))
+		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0))
 			goto fail;
-		error = urtw_write8_c(sc, URTW_CW_VAL, 0x73);
+		error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0);
 	} else {
 		/* for B */
-		if (error = urtw_write8_c(sc, URTW_DIFS, 0x24))
+		if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24))
+		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0))
 			goto fail;
-		error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5);
+		error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0);
 	}
 
 fail:
@@ -2245,24 +2457,26 @@
 }
 
 static usbd_status
-urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens)
+urtw_8225_rf_set_sens(struct urtw_rf *rf)
 {
 	usbd_status error;
-
-	if (sens < 0 || sens > 6)
+	struct urtw_softc *sc = rf->rf_sc;
+
+	if (rf->sens < 0 || rf->sens > 6)
 		return (-1);
 
-	if (sens > 4)
+	if (rf->sens > 4)
 		if (error = urtw_8225_write_c(sc, 0x0c, 0x850))
 			goto fail;
 	else
 		if (error = urtw_8225_write_c(sc, 0x0c, 0x50))
 			goto fail;
 
-	sens = 6 - sens;
-	if (error = urtw_8225_setgain(sc, sens))
+	rf->sens = 6 - rf->sens;
+	if (error = urtw_8225_setgain(sc, rf->sens))
 		goto fail;
-	error = urtw_8187_write_phy_cck_c(sc, 0x41, urtw_8225_threshold[sens]);
+	error = urtw_8187_write_phy_cck_c(sc, 0x41,
+	    urtw_8225_threshold[rf->sens]);
 fail:
 	return (error);
 }
@@ -2304,8 +2518,8 @@
 	    mp == NULL) {
 		sc->sc_rx_err++;
 		URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
-		    "urtw_rxeof failed! %d\n",
-		    req->bulk_completion_reason));
+		    "urtw_rxeof failed! %d, mp %p\n",
+		    req->bulk_completion_reason, mp));
 		req->bulk_data = mp;
 		goto fail;
 	}
@@ -2313,8 +2527,13 @@
 	actlen = MBLKL(mp);
 	rxbuf = (uint8_t *)mp->b_rptr;
 
-	/* 4 dword and 4 byte CRC  */
-	len = actlen - (4 * 4);
+	if (sc->sc_hwrev & URTW_HWREV_8187)
+		/* 4 dword and 4 byte CRC  */
+		len = actlen - (4 * 4);
+	else
+		/* 5 dword and 4 byte CRC */
+		len = actlen - (4 * 5);
+
 	desc = rxbuf + len;
 	flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
 	if (flen > actlen) {
@@ -2326,20 +2545,26 @@
 	}
 
 	rate = (desc[2] & 0xf0) >> 4;
-	URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
-	    "urtw_rxeof: rate is %u\n", rate));
-	/* XXX correct?  */
-	rssi = (desc[6] & 0xfe) >> 1;
-	if (!urtw_isbmode(rate)) {
-		rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
-		rssi = ((90 - rssi) * 100) / 65;
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		rssi = (desc[6] & 0xfe) >> 1;
+
+		/* XXX correct? */
+		if (!urtw_isbmode(rate)) {
+			rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
+			rssi = ((90 - rssi) * 100) / 65;
+		} else {
+			rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
+			rssi = ((95 - rssi) * 100) / 65;
+		}
 	} else {
-		rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
-		rssi = ((95 - rssi) * 100) / 65;
+		rssi = 14 + desc[13]/2;
+		if (rssi >= 95)
+			rssi = 95;
+		URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
+		    "urtw_rxeof: rssi %u\n", rssi));
 	}
 
 	mp->b_wptr = mp->b_rptr + flen - 4;
-
 	wh = (struct ieee80211_frame *)mp->b_rptr;
 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)
 	    == IEEE80211_FC0_TYPE_DATA) {
@@ -2411,7 +2636,7 @@
 			goto fail;
 	}
 	if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK,
-	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]))
+	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl], 0))
 		goto fail;
 	urtw_delay_ms(1);
 
@@ -2421,7 +2646,7 @@
 	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
 	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
 
-	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
+	error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
 	if (error)
 		goto fail;
 
@@ -2437,36 +2662,37 @@
 		goto fail;
 
 	error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
-	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]);
+	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl], 0);
 	urtw_delay_ms(1);
 fail:
 	return (error);
 }
 
 static usbd_status
-urtw_8225v2_rf_init(struct urtw_softc *sc)
+urtw_8225v2_rf_init(struct urtw_rf *rf)
 {
 #define	N(a)	(sizeof (a)/ sizeof ((a)[0]))
 	int i;
 	uint16_t data;
 	uint32_t data32;
 	usbd_status error;
-
-	if (error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON))
+	struct urtw_softc *sc = rf->rf_sc;
+
+	if (error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON))
 		goto fail;
 	if (error = urtw_8225_usb_init(sc))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008))
+	if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0))
 		goto fail;
-	if (error = urtw_read16_c(sc, URTW_BRSR, &data))
+	if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
 		goto fail;
-	if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff))
+	if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0))
 		goto fail;
-	if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044))
+	if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0))
 		goto fail;
 	if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG))
 		goto fail;
-	if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44))
+	if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0))
 		goto fail;
 	if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL))
 		goto fail;
@@ -2565,7 +2791,7 @@
 		urtw_delay_ms(1);
 	}
 
-	if (error = urtw_write8_c(sc, 0x5b, 0x0d))
+	if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0))
 		goto fail;
 	if (error = urtw_8225v2_set_txpwrlvl(sc, 1))
 		goto fail;
@@ -2579,18 +2805,20 @@
 	/* TX ant A, 0x0 for B */
 	if (error = urtw_8185_tx_antenna(sc, 0x3))
 		goto fail;
-	if (error = urtw_write32_c(sc, 0x94, 0x3dc00002))
+	if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0))
 		goto fail;
 
-	error = urtw_8225_rf_set_chan(sc, 1);
+	error = urtw_8225_rf_set_chan(rf,
+	    ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
 fail:
 	return (error);
 #undef N
 }
 
 static usbd_status
-urtw_8225v2_rf_set_chan(struct urtw_softc *sc, int chan)
+urtw_8225v2_rf_set_chan(struct urtw_rf *rf, int chan)
 {
+	struct urtw_softc *sc = rf->rf_sc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_channel *c = ic->ic_curchan;
 	short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0;
@@ -2604,31 +2832,31 @@
 
 	urtw_delay_ms(10);
 
-	if (error = urtw_write8_c(sc, URTW_SIFS, 0x22))
+	if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0))
 		goto fail;
 
 	if (ic->ic_state == IEEE80211_S_ASSOC &&
 	    ic->ic_flags & IEEE80211_F_SHSLOT) {
-		if (error = urtw_write8_c(sc, URTW_SLOT, 0x9))
+		if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0))
 			goto fail;
 	} else
-		if (error = urtw_write8_c(sc, URTW_SLOT, 0x14))
+		if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0))
 			goto fail;
 	if (gset) {
 		/* for G */
-		if (error = urtw_write8_c(sc, URTW_DIFS, 0x14))
+		if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14))
+		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_CW_VAL, 0x73))
+		if (error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0))
 			goto fail;
 	} else {
 		/* for B */
-		if (error = urtw_write8_c(sc, URTW_DIFS, 0x24))
+		if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24))
+		if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0))
 			goto fail;
-		if (error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5))
+		if (error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0))
 			goto fail;
 	}
 
@@ -2640,21 +2868,22 @@
 urtw_set_channel(struct urtw_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
+	struct urtw_rf *rf = &sc->sc_rf;
 	uint32_t data;
 	usbd_status error;
 
-	if (error = urtw_read32_c(sc, URTW_TX_CONF, &data))
+	if (error = urtw_read32_c(sc, URTW_TX_CONF, &data, 0))
 		goto fail;
 	data &= ~URTW_TX_LOOPBACK_MASK;
 	if (error = urtw_write32_c(sc, URTW_TX_CONF,
-	    data | URTW_TX_LOOPBACK_MAC))
+	    data | URTW_TX_LOOPBACK_MAC, 0))
 		goto fail;
-	error = sc->sc_rf_set_chan(sc,
-	    ieee80211_chan2ieee(ic, ic->ic_curchan));
+	error = rf->set_chan(rf, ieee80211_chan2ieee(ic, ic->ic_curchan));
 	if (error)
 		goto fail;
-	urtw_delay_ms(10);
-	error = urtw_write32_c(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_NONE);
+	urtw_delay_ms(20);
+	error = urtw_write32_c(sc, URTW_TX_CONF,
+	    data | URTW_TX_LOOPBACK_NONE, 0);
 fail:
 	return (error);
 }
@@ -2736,6 +2965,483 @@
 	return (rate & IEEE80211_RATE_VAL);
 }
 
+void
+urtw_8187b_update_wmm(struct urtw_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211_channel *c = ic->ic_curchan;
+	uint32_t data;
+	uint8_t aifs, sifs, slot, ecwmin, ecwmax;
+
+	sifs = 0xa;
+	if (IEEE80211_IS_CHAN_G(c))
+		slot = 0x9;
+	else
+		slot = 0x14;
+
+	aifs = (2 * slot) + sifs;
+	ecwmin = 3;
+	ecwmax = 7;
+
+	data = ((uint32_t)aifs << 0) |		/* AIFS, offset 0 */
+	    ((uint32_t)ecwmin << 8) |		/* ECW minimum, offset 8 */
+	    ((uint32_t)ecwmax << 12);		/* ECW maximum, offset 16 */
+
+	(void) urtw_write32_c(sc, URTW_AC_VO, data, 0);
+	(void) urtw_write32_c(sc, URTW_AC_VI, data, 0);
+	(void) urtw_write32_c(sc, URTW_AC_BE, data, 0);
+	(void) urtw_write32_c(sc, URTW_AC_BK, data, 0);
+}
+
+usbd_status
+urtw_8187b_reset(struct urtw_softc *sc)
+{
+	uint8_t data;
+	usbd_status error;
+
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
+	if (error)
+		goto fail;
+
+	(void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
+	(void) urtw_write8_c(sc, URTW_CONFIG3,
+	    data | URTW_CONFIG3_ANAPARAM_WRITE |
+	    URTW_CONFIG3_GNT_SELECT, 0);
+
+	(void) urtw_write32_c(sc, URTW_ANAPARAM2,
+	    URTW_8187B_8225_ANAPARAM2_ON, 0);
+	(void) urtw_write32_c(sc, URTW_ANAPARAM,
+	    URTW_8187B_8225_ANAPARAM_ON, 0);
+	(void) urtw_write8_c(sc, URTW_ANAPARAM3,
+	    URTW_8187B_8225_ANAPARAM3_ON, 0);
+
+	(void) urtw_write8_c(sc, 0x61, 0x10, 0);
+	(void) urtw_read8_c(sc, 0x62, &data, 0);
+	(void) urtw_write8_c(sc, 0x62, data & ~(1 << 5), 0);
+	(void) urtw_write8_c(sc, 0x62, data | (1 << 5), 0);
+
+	(void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
+	(void) urtw_write8_c(sc, URTW_CONFIG3,
+	    data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0);
+
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
+	if (error)
+		goto fail;
+
+	(void) urtw_read8_c(sc, URTW_CMD, &data, 0);
+	data = (data & 2) | URTW_CMD_RST;
+	(void) urtw_write8_c(sc, URTW_CMD, data, 0);
+	urtw_delay_ms(100);
+
+	(void) urtw_read8_c(sc, URTW_CMD, &data, 0);
+	if (data & URTW_CMD_RST) {
+		cmn_err(CE_WARN, "urtw: 8187b reset timeout\n");
+		goto fail;
+	}
+
+fail:
+	return (error);
+}
+
+static int
+urtw_8187b_init(void *arg)
+{
+	struct urtw_softc *sc = arg;
+	struct urtw_rf *rf = &sc->sc_rf;
+	struct ieee80211com *ic = &sc->sc_ic;
+	int i;
+	uint8_t data;
+	usbd_status error;
+
+	urtw_stop(sc);
+	URTW_LOCK(sc);
+	urtw_8187b_update_wmm(sc);
+	error = urtw_8187b_reset(sc);
+	if (error)
+		goto fail;
+
+	error = urtw_open_pipes(sc);
+	if (error != 0)
+		goto fail;
+	/* Applying MAC address again. */
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
+	if (error)
+		goto fail;
+	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
+		(void) urtw_write8_c(sc, URTW_MAC0 + i,
+		    ic->ic_macaddr[i], 0);
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
+	if (error)
+		goto fail;
+
+	error = urtw_update_msr(sc, IEEE80211_S_INIT);
+	if (error)
+		goto fail;
+
+	error = rf->init(rf);
+	if (error != 0)
+		goto fail;
+	error = urtw_intr_enable(sc);
+	if (error != 0)
+		goto fail;
+
+	error = urtw_write8e(sc, 0x41, 0xf4);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x40, 0x00);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x42, 0x00);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x42, 0x01);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x40, 0x0f);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x42, 0x00);
+	if (error != 0)
+		goto fail;
+	error = urtw_write8e(sc, 0x42, 0x01);
+	if (error != 0)
+		goto fail;
+
+	(void) urtw_read8_c(sc, 0xdb, &data, 0);
+	(void) urtw_write8_c(sc, 0xdb, data | (1 << 2), 0);
+	(void) urtw_write16_c(sc, 0x72, 0x59fa, 3);
+	(void) urtw_write16_c(sc, 0x74, 0x59d2, 3);
+	(void) urtw_write16_c(sc, 0x76, 0x59d2, 3);
+	(void) urtw_write16_c(sc, 0x78, 0x19fa, 3);
+	(void) urtw_write16_c(sc, 0x7a, 0x19fa, 3);
+	(void) urtw_write16_c(sc, 0x7c, 0x00d0, 3);
+	(void) urtw_write8_c(sc, 0x61, 0, 0);
+	(void) urtw_write8_c(sc, 0x80, 0x0f, 1);
+	(void) urtw_write8_c(sc, 0x83, 0x03, 1);
+	(void) urtw_write8_c(sc, 0xda, 0x10, 0);
+	(void) urtw_write8_c(sc, 0x4d, 0x08, 2);
+
+	(void) urtw_write32_c(sc, URTW_HSSI_PARA, 0x0600321b, 0);
+	(void) urtw_write16_c(sc, 0xec, 0x0800, 1);
+	(void) urtw_write8_c(sc, URTW_ACM_CONTROL, 0, 0);
+
+	sc->sc_tx_low_queued = 0;
+	sc->sc_tx_normal_queued = 0;
+	error = urtw_rx_enable(sc);
+	if (error != 0)
+		goto fail;
+	urtw_tx_enable(sc);
+
+	if (error == 0) {
+		URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev,
+		    CE_CONT, "urtw_8187b_init: done\n"));
+		sc->sc_flags |= URTW_FLAG_RUNNING;
+		URTW_UNLOCK(sc);
+		return (error);
+	}
+
+fail:
+	cmn_err(CE_WARN, "urtw_8187b_init failed\n");
+	URTW_UNLOCK(sc);
+	urtw_stop(sc);
+	return (EIO);
+}
+
+void
+urtw_8225v2_b_config_mac(struct urtw_softc *sc)
+{
+	int i;
+	int nitems = sizeof (urtw_8187b_regtbl)
+	    / sizeof ((urtw_8187b_regtbl)[0]);
+
+	for (i = 0; i < nitems; i++) {
+		(void) urtw_write8_c(sc, urtw_8187b_regtbl[i].reg,
+		    urtw_8187b_regtbl[i].val, urtw_8187b_regtbl[i].idx);
+	}
+
+	(void) urtw_write16_c(sc, URTW_TID_AC_MAP, 0xfa50, 0);
+	(void) urtw_write16_c(sc, URTW_INT_MIG, 0, 0);
+
+	(void) urtw_write32_c(sc, 0xf0, 0, 1);
+	(void) urtw_write32_c(sc, 0xf4, 0, 1);
+	(void) urtw_write8_c(sc, 0xf8, 0, 1);
+
+	(void) urtw_write32_c(sc, URTW_RF_TIMING, 0x00004001, 0);
+}
+
+void
+urtw_8225v2_b_init_rfe(struct urtw_softc *sc)
+{
+	(void) urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0480, 0);
+	(void) urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x2488, 0);
+	(void) urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1fff, 0);
+	urtw_delay_ms(100);
+}
+
+usbd_status
+urtw_8225v2_b_update_chan(struct urtw_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211_channel *c = ic->ic_curchan;
+	uint8_t aifs, difs, eifs, sifs, slot;
+
+	(void) urtw_write8_c(sc, URTW_SIFS, 0x22, 0);
+
+	sifs = 0xa;
+	if (IEEE80211_IS_CHAN_G(c)) {
+		slot = 0x9;
+		difs = 0x1c;
+		eifs = 0x5b;
+	} else {
+		slot = 0x14;
+		difs = 0x32;
+		eifs = 0x5b;
+	}
+	aifs = (2 * slot) + sifs;
+
+	(void) urtw_write8_c(sc, URTW_SLOT, slot, 0);
+
+	(void) urtw_write8_c(sc, URTW_AC_VO, aifs, 0);
+	(void) urtw_write8_c(sc, URTW_AC_VI, aifs, 0);
+	(void) urtw_write8_c(sc, URTW_AC_BE, aifs, 0);
+	(void) urtw_write8_c(sc, URTW_AC_BK, aifs, 0);
+
+	(void) urtw_write8_c(sc, URTW_DIFS, difs, 0);
+	(void) urtw_write8_c(sc, URTW_8187B_EIFS, eifs, 0);
+	return (0);
+}
+
+usbd_status
+urtw_8225v2_b_rf_init(struct urtw_rf *rf)
+{
+	struct urtw_softc *sc = rf->rf_sc;
+	int i, nitems;
+	uint8_t data;
+	usbd_status error;
+
+	/* Set up ACK rate, retry limit, TX AGC, TX antenna. */
+	(void) urtw_write16_c(sc, URTW_8187B_BRSR, 0x0fff, 0);
+	(void) urtw_read8_c(sc, URTW_CW_CONF, &data, 0);
+	(void) urtw_write8_c(sc, URTW_CW_CONF, data |
+	    URTW_CW_CONF_PERPACKET_RETRY, 0);
+	(void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data, 0);
+	(void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data |
+	    URTW_TX_AGC_CTL_PERPACKET_GAIN |
+	    URTW_TX_AGC_CTL_PERPACKET_ANTSEL, 0);
+
+	/* Auto rate fallback control. */
+	(void) urtw_write16_c(sc, URTW_ARFR, 0x0fff, 1);	/* 1M ~ 54M */
+	(void) urtw_read8_c(sc, URTW_RATE_FALLBACK, &data, 0);
+	(void) urtw_write8_c(sc, URTW_RATE_FALLBACK, data |
+	    URTW_RATE_FALLBACK_ENABLE, 0);
+
+	(void) urtw_write16_c(sc, URTW_BEACON_INTERVAL, 0x3ff, 0);
+	(void) urtw_write16_c(sc, URTW_ATIM_WND, 2, 0);
+	(void) urtw_write16_c(sc, URTW_FEMR, 0xffff, 1);
+
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
+	if (error)
+		goto fail;
+	(void) urtw_read8_c(sc, URTW_CONFIG1, &data, 0);
+	(void) urtw_write8_c(sc, URTW_CONFIG1, (data & 0x3f) | 0x80, 0);
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
+	if (error)
+		goto fail;
+
+	(void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0);
+	urtw_8225v2_b_config_mac(sc);
+	(void) urtw_write16_c(sc, URTW_RFSW_CTRL, 0x569a, 2);
+
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
+	if (error)
+		goto fail;
+	(void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
+	(void) urtw_write8_c(sc, URTW_CONFIG3,
+	    data | URTW_CONFIG3_ANAPARAM_WRITE, 0);
+	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
+	if (error)
+		goto fail;
+
+	urtw_8225v2_b_init_rfe(sc);
+
+	nitems = sizeof (urtw_8225v2_b_rf) / sizeof ((urtw_8225v2_b_rf)[0]);
+	for (i = 0; i < nitems; i++) {
+		(void) urtw_8225_write_c(sc, urtw_8225v2_b_rf[i].reg,
+		    urtw_8225v2_b_rf[i].val);
+	}
+
+	nitems = sizeof (urtw_8225v2_rxgain) / sizeof ((urtw_8225v2_rxgain)[0]);
+	for (i = 0; i < nitems; i++) {
+		(void) urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1));
+		(void) urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i]);
+	}
+
+	(void) urtw_8225_write_c(sc, 0x03, 0x080);
+	(void) urtw_8225_write_c(sc, 0x05, 0x004);
+	(void) urtw_8225_write_c(sc, 0x00, 0x0b7);
+	(void) urtw_8225_write_c(sc, 0x02, 0xc4d);
+	urtw_delay_ms(10);
+	(void) urtw_8225_write_c(sc, 0x02, 0x44d);
+	urtw_delay_ms(10);
+	(void) urtw_8225_write_c(sc, 0x00, 0x2bf);
+	urtw_delay_ms(10);
+
+	(void) urtw_write8_c(sc, URTW_TX_GAIN_CCK, 0x03, 0);
+	(void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 0x07, 0);
+	(void) urtw_write8_c(sc, URTW_TX_ANTENNA, 0x03, 0);
+
+	(void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x12);
+	nitems = sizeof (urtw_8225v2_agc) / sizeof ((urtw_8225v2_agc)[0]);
+	for (i = 0; i < nitems; i++) {
+		(void) urtw_8187_write_phy_ofdm_c(sc, 0x0f, urtw_8225v2_agc[i]);
+		(void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, (uint8_t)i + 0x80);
+		(void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, 0);
+	}
+	(void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x10);
+
+	nitems = sizeof (urtw_8225v2_ofdm) / sizeof ((urtw_8225v2_ofdm)[0]);
+	for (i = 0; i < nitems; i++) {
+		(void) urtw_8187_write_phy_ofdm_c(sc, i, urtw_8225v2_ofdm[i]);
+	}
+	(void) urtw_8225v2_b_update_chan(sc);
+
+	(void) urtw_8187_write_phy_ofdm_c(sc, 0x97, 0x46);
+	(void) urtw_8187_write_phy_ofdm_c(sc, 0xa4, 0xb6);
+	(void) urtw_8187_write_phy_ofdm_c(sc, 0x85, 0xfc);
+	(void) urtw_8187_write_phy_cck_c(sc, 0xc1, 0x88);
+
+	error = urtw_8225v2_b_rf_set_chan(rf,
+	    ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
+fail:
+	return (error);
+}
+
+static usbd_status
+urtw_8225v2_b_rf_set_chan(struct urtw_rf *rf, int chan)
+{
+	struct urtw_softc *sc = rf->rf_sc;
+	int error = 0;
+
+	urtw_8225v2_b_set_txpwrlvl(sc, chan);
+	error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan]);
+	if (error)
+		goto fail;
+	/*
+	 * Delay removed from 8185 to 8187.
+	 * usbd_delay_ms(sc->sc_udev, 10);
+	 */
+
+	error = urtw_write16_c(sc, URTW_AC_VO, 0x5114, 0);
+	if (error)
+		goto fail;
+	error = urtw_write16_c(sc, URTW_AC_VI, 0x5114, 0);
+	if (error)
+		goto fail;
+	error = urtw_write16_c(sc, URTW_AC_BE, 0x5114, 0);
+	if (error)
+		goto fail;
+	error = urtw_write16_c(sc, URTW_AC_BK, 0x5114, 0);
+fail:
+	return (error);
+}
+
+void
+urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *sc, int chan)
+{
+	int i;
+	uint8_t *cck_pwrtable;
+	uint8_t cck_pwrlvl_min, cck_pwrlvl_max, ofdm_pwrlvl_min,
+	    ofdm_pwrlvl_max;
+	int8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
+	int8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
+
+	if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
+		cck_pwrlvl_min = 0;
+		cck_pwrlvl_max = 15;
+		ofdm_pwrlvl_min = 2;
+		ofdm_pwrlvl_max = 17;
+	} else {
+		cck_pwrlvl_min = 7;
+		cck_pwrlvl_max = 22;
+		ofdm_pwrlvl_min = 10;
+		ofdm_pwrlvl_max = 25;
+	}
+
+	/* CCK power setting */
+	cck_pwrlvl = (cck_pwrlvl > (cck_pwrlvl_max - cck_pwrlvl_min)) ?
+	    cck_pwrlvl_max : (cck_pwrlvl + cck_pwrlvl_min);
+
+	cck_pwrlvl += sc->sc_txpwr_cck_base;
+	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
+	cck_pwrlvl = (cck_pwrlvl < 0) ? 0 : cck_pwrlvl;
+
+	cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
+	    urtw_8225v2_txpwr_cck;
+
+	if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
+		if (cck_pwrlvl > 7 && cck_pwrlvl <= 11)
+			cck_pwrtable += 8;
+		if (cck_pwrlvl > 11)
+			cck_pwrtable += 16;
+	} else {
+		if (cck_pwrlvl > 5 && cck_pwrlvl <= 11)
+			cck_pwrtable += 8;
+		if (cck_pwrlvl > 12 && cck_pwrlvl <= 17)
+			cck_pwrtable += 16;
+		if (cck_pwrlvl > 17)
+			cck_pwrtable += 24;
+	}
+
+	for (i = 0; i < 8; i++) {
+		(void) urtw_8187_write_phy_cck_c(sc, 0x44 + i, cck_pwrtable[i]);
+	}
+
+	(void) urtw_write8_c(sc, URTW_TX_GAIN_CCK,
+	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1, 0);
+	/*
+	 * Delay removed from 8185 to 8187.
+	 * usbd_delay_ms(sc->sc_udev, 1);
+	 */
+
+	/* OFDM power setting */
+	ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
+	    ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
+
+	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
+	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
+	ofdm_pwrlvl = (ofdm_pwrlvl < 0) ? 0 : ofdm_pwrlvl;
+
+	(void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
+	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1, 0);
+
+	if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
+		if (ofdm_pwrlvl <= 11) {
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x60);
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x60);
+		} else {
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c);
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c);
+		}
+	} else {
+		if (ofdm_pwrlvl <= 11) {
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c);
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c);
+		} else if (ofdm_pwrlvl <= 17) {
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x54);
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x54);
+		} else {
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x50);
+			(void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x50);
+		}
+	}
+
+	/*
+	 * Delay removed from 8185 to 8187.
+	 * usbd_delay_ms(sc->sc_udev, 1);
+	 */
+}
+
+
 static int
 urtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
 {
@@ -2804,7 +3510,11 @@
 		wh = (struct ieee80211_frame *)m->b_rptr;
 	}
 
-	xferlen = MBLKL(m) + 4 * 3;
+	if (sc->sc_hwrev & URTW_HWREV_8187)
+		xferlen = MBLKL(m) + 4 * 3;
+	else
+		xferlen = MBLKL(m) + 4 * 8;
+
 	if ((0 == xferlen % 64) || (0 == xferlen % 512))
 		xferlen += 1;
 
@@ -2830,17 +3540,22 @@
 		buf[3] = urtw_rate2rtl(MAX(2, urtw_get_rate(ic)));
 	} else
 		buf[3] = sc->sc_currate;
-	buf[8] = 3;		/* CW minimum  */
-	buf[8] |= (7 << 4);	/* CW maximum  */
-	buf[9] |= 11;		/* retry limitation  */
-
-	bcopy(m->b_rptr, &buf[12], MBLKL(m));
+
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		buf[8] = 3;		/* CW minimum  */
+		buf[8] |= (7 << 4);	/* CW maximum  */
+		buf[9] |= 11;		/* retry limitation  */
+		bcopy(m->b_rptr, &buf[12], MBLKL(m));
+	} else {
+		buf[21] |= 11;		/* retry limitation */
+		bcopy(m->b_rptr, &buf[32], MBLKL(m));
+	}
 
 	(void) urtw_led_ctl(sc, URTW_LED_CTL_TX);
 	mtx->b_wptr = mtx->b_rptr + xferlen;
 
 	URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT,
-	    "sending data frame len=%u rate=%u xfer len=%u\n",
+	    "sending frame len=%u rate=%u xfer len=%u\n",
 	    MBLKL(m), buf[3], xferlen));
 
 	err = urtw_tx_start(sc, mtx, priority);
@@ -2939,6 +3654,8 @@
 		URTW8187_DBG(URTW_DEBUG_STATE,
 		    (sc->sc_dev, CE_CONT, "-> IEEE80211_S_INIT...arg(%d)\n",
 		    arg));
+		if (sc->sc_flags & URTW_FLAG_HP)
+			break;
 		(void) urtw_update_msr(sc, nstate);
 		(void) urtw_led_off(sc, URTW_LED_GPIO);
 		break;
@@ -2960,7 +3677,8 @@
 
 	case IEEE80211_S_AUTH:
 		URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
-		    "-> IEEE80211_S_AUTH ...arg(%d)\n", arg));
+		    "-> IEEE80211_S_AUTH ...arg(%d), chan (%d)\n", arg,
+		    ieee80211_chan2ieee(ic, ic->ic_curchan)));
 		error = urtw_set_channel(sc);
 		if (error) {
 			URTW8187_DBG(URTW_DEBUG_STATE,
@@ -2970,7 +3688,8 @@
 
 	case IEEE80211_S_ASSOC:
 		URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
-		    "-> IEEE80211_S_ASSOC ...arg(%d)\n", arg));
+		    "-> IEEE80211_S_ASSOC ...arg(%d), chan (%d)\n", arg,
+		    ieee80211_chan2ieee(ic, ic->ic_curchan)));
 		error = urtw_set_channel(sc);
 		if (error) {
 			URTW8187_DBG(URTW_DEBUG_STATE,
@@ -2980,8 +3699,9 @@
 
 	case IEEE80211_S_RUN:
 		URTW8187_DBG(URTW_DEBUG_STATE,
-		    (sc->sc_dev, CE_CONT, "-> IEEE80211_S_RUN ...arg(%d)\n",
-		    arg));
+		    (sc->sc_dev, CE_CONT,
+		    "-> IEEE80211_S_RUN ...arg(%d), chan (%d)\n",
+		    arg, ieee80211_chan2ieee(ic, ic->ic_curchan)));
 		error = urtw_set_channel(sc);
 		if (error) {
 			URTW8187_DBG(URTW_DEBUG_STATE,
@@ -2991,9 +3711,9 @@
 		ni = ic->ic_bss;
 		/* setting bssid.  */
 		(void) urtw_write32_c(sc, URTW_BSSID,
-		    ((uint32_t *)(uintptr_t)ni->in_bssid)[0]);
+		    ((uint32_t *)(uintptr_t)ni->in_bssid)[0], 0);
 		(void) urtw_write16_c(sc, URTW_BSSID + 4,
-		    ((uint16_t *)(uintptr_t)ni->in_bssid)[2]);
+		    ((uint16_t *)(uintptr_t)ni->in_bssid)[2], 0);
 		(void) urtw_update_msr(sc, nstate);
 
 		ni->in_txrate = ni->in_rates.ir_nrates - 1;
@@ -3002,8 +3722,11 @@
 fail:
 	URTW_UNLOCK(sc);
 
-	if (error)
+	if (error) {
+		URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
+		    "-> newstate error...arg(%d)\n", error));
 		return (EIO);
+	}
 	error = sc->sc_newstate(ic, nstate, arg);
 	return (error);
 }
@@ -3044,12 +3767,16 @@
 	usb_ep_data_t *ep_node;
 	usb_pipe_policy_t policy;
 	int err;
+	uint_t skip = 0;
 
 	if (sc->sc_rxpipe || sc->sc_txpipe_low || sc->sc_txpipe_normal)
 		return (USB_SUCCESS);
 
+	if ((sc->sc_hwrev & URTW_HWREV_8187) == 0) {
+		skip = 2;
+	}
 	ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0,
-	    LOW_PRIORITY_PIPE, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
+	    LOW_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
 
 	bzero(&policy, sizeof (usb_pipe_policy_t));
 	policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT;
@@ -3064,7 +3791,7 @@
 	}
 
 	ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0,
-	    NORMAL_PRIORITY_PIPE, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
+	    NORMAL_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
 
 	bzero(&policy, sizeof (usb_pipe_policy_t));
 	policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT;
@@ -3190,14 +3917,15 @@
 	URTW8187_DBG(URTW_DEBUG_HOTPLUG,
 	    (sc->sc_dev, CE_CONT, "urtw_offline()\n"));
 
-	ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
-	ieee80211_stop_watchdog(&sc->sc_ic);
 	if (URTW_IS_RUNNING(sc)) {
 		urtw_stop(sc);
 		URTW_LOCK(sc);
 		sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE;
 		URTW_UNLOCK(sc);
 	}
+	sc->sc_flags |= URTW_FLAG_HP;
+	ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
+	ieee80211_stop_watchdog(&sc->sc_ic);
 	return (DDI_SUCCESS);
 }
 
@@ -3212,15 +3940,16 @@
 		return (DDI_FAILURE);
 	URTW8187_DBG(URTW_DEBUG_HOTPLUG, (sc->sc_dev, CE_CONT,
 	    "urtw_online()\n"));
+	sc->sc_flags &= ~URTW_FLAG_HP;
 	if (URTW_IS_PLUGIN_ONLINE(sc)) {
-		error = urtw_init(sc);
+		error = sc->urtw_init(sc);
 		if (!error) {
 			URTW_LOCK(sc);
 			sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE;
 			URTW_UNLOCK(sc);
 		}
 	}
-	return (error);
+	return (error? DDI_FAILURE: DDI_SUCCESS);
 }
 
 static mblk_t *
@@ -3255,8 +3984,8 @@
 	int error = 0;
 
 	URTW8187_DBG(URTW_DEBUG_ACTIVE,
-	    (sc->sc_dev, CE_CONT, "urtw_m_start)\n"));
-	error = urtw_init(sc);
+	    (sc->sc_dev, CE_CONT, "urtw_m_start\n"));
+	error = sc->urtw_init(sc);
 	return (error);
 }
 
@@ -3294,6 +4023,18 @@
 }
 
 static int
+urtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
+    uint_t pr_flags, uint_t wldp_length, void *wldp_buf, uint_t *perm)
+{
+	struct urtw_softc *sc = (struct urtw_softc *)arg;
+	int err = 0;
+
+	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
+	    pr_flags, wldp_length, wldp_buf, perm);
+	return (err);
+}
+
+static int
 urtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
     uint_t wldp_length, const void *wldp_buf)
 {
@@ -3303,13 +4044,23 @@
 
 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
 	    wldp_length, wldp_buf);
+	URTW_LOCK(sc);
 	if (err == ENETRESET) {
-		if (ic->ic_des_esslen && URTW_IS_RUNNING(sc)) {
-			(void) urtw_init(sc);
+		if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) {
+			URTW_UNLOCK(sc);
+			err = sc->urtw_init(sc);
+			if (err) {
+				URTW8187_DBG(URTW_DEBUG_ACTIVE,
+				    (sc->sc_dev, CE_CONT,
+				    "urtw: setprop failed\n"));
+				return (err);
+			}
 			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+			URTW_LOCK(sc);
 		}
 		err = 0;
 	}
+	URTW_UNLOCK(sc);
 	return (err);
 }
 
@@ -3321,13 +4072,22 @@
 	int err;
 
 	err = ieee80211_ioctl(ic, wq, mp);
+	URTW_LOCK(sc);
 	if (err == ENETRESET) {
-		if (ic->ic_des_esslen && URTW_IS_RUNNING(sc)) {
-			(void) urtw_init(sc);
-			(void) ieee80211_new_state(ic,
-			    IEEE80211_S_SCAN, -1);
+		if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) {
+			URTW_UNLOCK(sc);
+			err = sc->urtw_init(sc);
+			if (err) {
+				URTW8187_DBG(URTW_DEBUG_ACTIVE,
+				    (sc->sc_dev,
+				    CE_CONT, "urtw: dev init failed\n"));
+				return;
+			}
+			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+			URTW_LOCK(sc);
 		}
 	}
+	URTW_UNLOCK(sc);
 }
 
 static int
@@ -3412,9 +4172,12 @@
 	switch (ic->ic_state) {
 		case IEEE80211_S_AUTH:
 		case IEEE80211_S_ASSOC:
-			if (ic->ic_bss->in_fails > 0)
+			if (ic->ic_bss->in_fails > 0) {
 				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
-			else
+				URTW8187_DBG(URTW_DEBUG_ACTIVE,
+				    (sc->sc_dev, CE_CONT,
+				    "urtw: watchdog begin\n"));
+			} else
 				ieee80211_watchdog(ic);
 			break;
 	}
@@ -3428,9 +4191,12 @@
 	struct ieee80211com *ic;
 	int error, i, instance;
 	uint32_t data = 0;
+	uint8_t data8 = 0;
 	char strbuf[32];
 	wifi_data_t wd = { 0 };
 	mac_register_t *macp;
+	struct urtw_type *e = 0;
+	char *urtw_name = NULL;
 
 	switch (cmd) {
 	case DDI_ATTACH:
@@ -3445,7 +4211,7 @@
 		sc->sc_flags &= ~URTW_FLAG_SUSPEND;
 		URTW_UNLOCK(sc);
 		if (URTW_IS_PLUGIN_ONLINE(sc)) {
-			error = urtw_init(sc);
+			error = sc->urtw_init(sc);
 			if (error == 0) {
 				URTW_LOCK(sc);
 				sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE;
@@ -3484,7 +4250,67 @@
 	mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL);
 	mutex_init(&sc->sc_ledlock, NULL, MUTEX_DRIVER, NULL);
 
-	if (urtw_read32_c(sc, URTW_RX, &data))
+	e = urtw_lookup(sc->sc_udev->dev_descr->idVendor,
+	    sc->sc_udev->dev_descr->idProduct);
+	if (e == NULL) {
+		cmn_err(CE_WARN, "(urtw) unknown device\n");
+		goto fail2;
+	}
+	sc->sc_hwrev = e->rev;
+
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		(void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0);
+		data &= URTW_TX_HWREV_MASK;
+		switch (data) {
+		case URTW_TX_HWREV_8187_D:
+			sc->sc_hwrev |= URTW_HWREV_8187_D;
+			urtw_name = "RTL8187 rev. D";
+			break;
+		case URTW_TX_HWREV_8187B_D:
+			/*
+			 * Detect Realtek RTL8187B devices that use
+			 * USB IDs of RTL8187.
+			 */
+			sc->sc_hwrev = URTW_HWREV_8187B | URTW_HWREV_8187B_B;
+			urtw_name = "RTL8187B rev. B (early)";
+			break;
+		default:
+			sc->sc_hwrev |= URTW_HWREV_8187_B;
+			urtw_name = "RTL8187 rev. B (default)";
+			break;
+		}
+	} else {
+		/* RTL8187B hwrev register. */
+		(void) urtw_read8_c(sc, URTW_8187B_HWREV, &data8, 0);
+		switch (data8) {
+		case URTW_8187B_HWREV_8187B_B:
+			sc->sc_hwrev |= URTW_HWREV_8187B_B;
+			urtw_name = "RTL8187B rev. B";
+			break;
+		case URTW_8187B_HWREV_8187B_D:
+			sc->sc_hwrev |= URTW_HWREV_8187B_D;
+			urtw_name = "RTL8187B rev. D";
+			break;
+		case URTW_8187B_HWREV_8187B_E:
+			sc->sc_hwrev |= URTW_HWREV_8187B_E;
+			urtw_name = "RTL8187B rev. E";
+			break;
+		default:
+			sc->sc_hwrev |= URTW_HWREV_8187B_B;
+			urtw_name = "RTL8187B rev. B (default)";
+			break;
+		}
+	}
+
+	URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT,
+	    "urtw_attach: actual device is %s\n", urtw_name));
+	if (sc->sc_hwrev & URTW_HWREV_8187) {
+		sc->urtw_init = urtw_8187_init;
+	} else {
+		sc->urtw_init = urtw_8187b_init;
+	}
+
+	if (urtw_read32_c(sc, URTW_RX, &data, 0))
 		goto fail3;
 	sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 :
 	    URTW_EEPROM_93C46;
@@ -3538,6 +4364,8 @@
 	}
 
 	ieee80211_attach(ic);
+	ic->ic_ibss_chan = &ic->ic_sup_channels[1];
+	ic->ic_curchan = ic->ic_ibss_chan;
 
 	/* register WPA door */
 	ieee80211_register_door(ic, ddi_driver_name(devinfo),
@@ -3550,7 +4378,7 @@
 	ieee80211_media_init(ic);
 	ic->ic_def_txkey = 0;
 
-	sc->dwelltime = 400;
+	sc->dwelltime = 250;
 	sc->sc_flags = 0;
 
 	/*
@@ -3600,7 +4428,6 @@
 
 	if (error != DDI_SUCCESS)
 		cmn_err(CE_WARN, "urtw: ddi_create_minor_node() failed\n");
-
 	/*
 	 * Notify link is down now
 	 */
@@ -3610,6 +4437,7 @@
 	    "urtw_attach: successfully.\n"));
 	return (DDI_SUCCESS);
 fail5:
+	(void) mac_disable(ic->ic_mach);
 	(void) mac_unregister(ic->ic_mach);
 fail4:
 	ieee80211_detach(ic);
--- a/usr/src/uts/common/io/urtw/urtw_reg.h	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/uts/common/io/urtw/urtw_reg.h	Fri Aug 21 22:02:12 2009 +0800
@@ -39,6 +39,17 @@
 extern "C" {
 #endif
 
+/*
+ * Known hardware revisions.
+ */
+#define	URTW_HWREV_8187			0x01
+#define	URTW_HWREV_8187_B		0x02
+#define	URTW_HWREV_8187_D		0x04
+#define	URTW_HWREV_8187B		0x08
+#define	URTW_HWREV_8187B_B		0x10
+#define	URTW_HWREV_8187B_D		0x20
+#define	URTW_HWREV_8187B_E		0x40
+
 /* for 8187  */
 #define	URTW_MAC0			0x0000		/* 1 byte  */
 #define	URTW_MAC1			0x0001		/* 1 byte  */
@@ -48,8 +59,10 @@
 #define	URTW_MAC5			0x0005		/* 1 byte  */
 #define	URTW_BRSR			0x002c		/* 2 byte  */
 #define	URTW_BRSR_MBR_8185		(0x0fff)
+#define	URTW_8187B_EIFS			0x002d		/* 1 byte */
 #define	URTW_BSSID			0x002e		/* 6 byte  */
 #define	URTW_RESP_RATE			0x0034		/* 1 byte  */
+#define	URTW_8187B_BRSR			0x0034		/* 2 byte */
 #define	URTW_RESP_MAX_RATE_SHIFT	(4)
 #define	URTW_RESP_MIN_RATE_SHIFT	(0)
 #define	URTW_EIFS			0x0035		/* 1 byte  */
@@ -59,6 +72,15 @@
 #define	URTW_CMD_RX_ENABLE		(0x8)
 #define	URTW_CMD_RST			(0x10)
 #define	URTW_TX_CONF			0x0040		/* 4 byte  */
+
+#define	URTW_TX_HWREV_MASK		(7 << 25)
+#define	URTW_TX_HWREV_8187_D	(5 << 25)
+#define	URTW_TX_HWREV_8187B_D	(6 << 25)
+#define	URTW_TX_DURPROCMODE		(1 << 30)
+#define	URTW_TX_DISREQQSIZE		(1 << 28)
+#define	URTW_TX_SHORTRETRY		(7 << 8)
+#define	URTW_TX_LONGRETRY		(7 << 0)
+
 #define	URTW_TX_LOOPBACK_SHIFT		(17)
 #define	URTW_TX_LOOPBACK_NONE		(0 << URTW_TX_LOOPBACK_SHIFT)
 #define	URTW_TX_LOOPBACK_MAC		(1 << URTW_TX_LOOPBACK_SHIFT)
@@ -74,7 +96,7 @@
 #define	URTW_TX_MXDMA_1024		(6 << URTW_TX_MXDMA_SHIFT)
 #define	URTW_TX_MXDMA_2048		(7 << URTW_TX_MXDMA_SHIFT)
 #define	URTW_TX_MXDMA_SHIFT		(21)
-#define	URTW_TX_CWMIN			(1 << 31)
+#define	URTW_TX_CWMIN			(0x80000000)
 #define	URTW_TX_DISCW			(1 << 20)
 #define	URTW_TX_SWPLCPLEN		(1 << 24)
 #define	URTW_TX_NOICV			(0x80000)
@@ -130,22 +152,34 @@
 #define	URTW_EPROM_WRITEBIT		(0x2)
 #define	URTW_EPROM_CK			(0x4)
 #define	URTW_EPROM_CS			(0x8)
-#define	URTW_CONFIG2			0x0053
+
+#define	URTW_CONFIG1			0x0052		/* 1 byte */
+#define	URTW_CONFIG2			0x0053		/* 1 byte */
+
 #define	URTW_ANAPARAM			0x0054		/* 4 byte  */
-#define	URTW_8225_ANAPARAM_ON		(0xa0000a59)
+#define	URTW_8187_8225_ANAPARAM_ON	(0xa0000a59)
+#define	URTW_8187B_8225_ANAPARAM_ON	(0x45090658)
+
 #define	URTW_MSR			0x0058		/* 1 byte  */
 #define	URTW_MSR_LINK_MASK		((1 << 2) | (1 << 3))
 #define	URTW_MSR_LINK_SHIFT		(2)
 #define	URTW_MSR_LINK_NONE		(0 << URTW_MSR_LINK_SHIFT)
 #define	URTW_MSR_LINK_ADHOC		(1 << URTW_MSR_LINK_SHIFT)
 #define	URTW_MSR_LINK_STA		(2 << URTW_MSR_LINK_SHIFT)
-#define	URTW_MSR_LINK_HOSTAP		(3 << URTW_MSR_LINK_SHIFT)
+#define	URTW_MSR_LINK_HOSTAP	(3 << URTW_MSR_LINK_SHIFT)
+#define	URTW_MSR_LINK_ENEDCA		(4 << URTW_MSR_LINK_SHIFT)
+
+
 #define	URTW_CONFIG3			0x0059		/* 1 byte  */
 #define	URTW_CONFIG3_ANAPARAM_WRITE	(0x40)
 #define	URTW_CONFIG3_ANAPARAM_W_SHIFT	(6)
+#define	URTW_CONFIG3_GNT_SELECT		(0x80)
+
 #define	URTW_PSR			0x005e		/* 1 byte  */
 #define	URTW_ANAPARAM2			0x0060		/* 4 byte  */
-#define	URTW_8225_ANAPARAM2_ON		(0x860c7312)
+#define	URTW_8187_8225_ANAPARAM2_ON	(0x860c7312)
+#define	URTW_8187B_8225_ANAPARAM2_ON	(0x727f3f52)
+
 #define	URTW_BEACON_INTERVAL		0x0070		/* 2 byte  */
 #define	URTW_ATIM_WND			0x0072		/* 2 byte  */
 #define	URTW_BEACON_INTERVAL_TIME	0x0074		/* 2 byte  */
@@ -161,6 +195,8 @@
 #define	URTW_RF_TIMING			0x008c		/* 4 byte  */
 #define	URTW_GP_ENABLE			0x0090		/* 1 byte  */
 #define	URTW_GPIO			0x0091		/* 1 byte  */
+#define	URTW_HSSI_PARA			0x0094
+
 #define	URTW_TX_AGC_CTL			0x009c		/* 1 byte  */
 #define	URTW_TX_AGC_CTL_PERPACKET_GAIN	(0x1)
 #define	URTW_TX_AGC_CTL_PERPACKET_ANTSEL	(0x2)
@@ -177,7 +213,25 @@
 #define	URTW_CW_CONF_PERPACKET_CW	(0x1)
 #define	URTW_CW_VAL			0x00bd		/* 1 byte  */
 #define	URTW_RATE_FALLBACK		0x00be		/* 1 byte  */
-#define	URTW_TALLY_SEL			0x00fc		/* 1 byte  */
+
+#define	URTW_RATE_FALLBACK_ENABLE	(0x80)
+#define	URTW_ACM_CONTROL		0x00bf		/* 1 byte */
+#define	URTW_8187B_HWREV		0x00e1		/* 1 byte */
+#define	URTW_8187B_HWREV_8187B_B	(0x0)
+#define	URTW_8187B_HWREV_8187B_D	(0x1)
+#define	URTW_8187B_HWREV_8187B_E	(0x2)
+#define	URTW_INT_MIG			0x00e2		/* 2 byte */
+#define	URTW_TID_AC_MAP			0x00e8		/* 2 byte */
+#define	URTW_ANAPARAM3			0x00ee		/* 4 byte */
+#define	URTW_8187B_8225_ANAPARAM3_ON	(0x0)
+#define	URTW_TALLY_SEL			0x00fc		/* 1 byte */
+#define	URTW_AC_VO			0x00f0		/* 1 byte */
+#define	URTW_AC_VI			0x00f4		/* 1 byte */
+#define	URTW_AC_BE			0x00f8		/* 1 byte */
+#define	URTW_AC_BK			0x00fc		/* 1 byte */
+#define	URTW_FEMR			0x01d4		/* 2 byte */
+#define	URTW_ARFR			0x01e0		/* 2 byte */
+#define	URTW_RFSW_CTRL			0x0272		/* 2 byte */
 
 /* for EEPROM  */
 #define	URTW_EPROM_TXPW_BASE		0x05
--- a/usr/src/uts/common/io/urtw/urtw_var.h	Fri Aug 21 07:04:46 2009 -0700
+++ b/usr/src/uts/common/io/urtw/urtw_var.h	Fri Aug 21 22:02:12 2009 +0800
@@ -38,7 +38,7 @@
 extern "C" {
 #endif
 
-#define	URTW_RX_DATA_LIST_COUNT	(1)
+#define	URTW_RX_DATA_LIST_COUNT	(2)
 #define	URTW_TX_DATA_LIST_COUNT	(16)
 #define	URTW_RX_MAXSIZE	(0x9c4)
 #define	URTW_TX_MAXSIZE	URTW_RX_MAXSIZE
@@ -60,6 +60,18 @@
 #define	URTW_LED_LINKOFF_BLINK	(1000*1000)
 #define	URTW_LED_LINKON_BLINK	(300*1000)
 
+struct urtw_rf {
+	/* RF methods */
+	usbd_status			(*init)(struct urtw_rf *);
+	usbd_status			(*set_chan)(struct urtw_rf *, int);
+	usbd_status			(*set_sens)(struct urtw_rf *);
+
+	/* RF attributes */
+	struct urtw_softc		*rf_sc;
+	uint32_t			max_sens;
+	int32_t				sens;
+};
+
 struct urtw_softc {
 	struct ieee80211com	sc_ic;
 	dev_info_t		*sc_dev;
@@ -93,15 +105,8 @@
 	uint8_t				sc_crcmon;
 	uint8_t				sc_bssid[IEEE80211_ADDR_LEN];
 
-	/* for RF  */
-	usbd_status			(*sc_rf_init)(struct urtw_softc *);
-	usbd_status			(*sc_rf_set_chan)(struct urtw_softc *,
-					    int);
-	usbd_status			(*sc_rf_set_sens)(struct urtw_softc *,
-					    int);
-	uint8_t				sc_rfchip;
-	uint32_t			sc_max_sens;
-	uint32_t			sc_sens;
+	struct urtw_rf			sc_rf;
+
 	/* for LED  */
 	kmutex_t			sc_ledlock;
 	timeout_id_t			sc_led_ch;
@@ -124,10 +129,14 @@
 	uint8_t				sc_txpwr_cck_base;
 	uint8_t				sc_txpwr_ofdm[URTW_MAX_CHANNELS];
 	uint8_t				sc_txpwr_ofdm_base;
+
+	uint8_t				sc_hwrev;
+	int				(*urtw_init)(void *);
 };
 #define	URTW_FLAG_RUNNING	(1 << 0)
 #define	URTW_FLAG_SUSPEND	(1 << 1)
-#define	URTW_FLAG_PLUGIN_ONLINE		(1 << 2)
+#define	URTW_FLAG_PLUGIN_ONLINE	(1 << 2)
+#define	URTW_FLAG_HP		(1 << 3)
 
 #define	URTW_IS_PLUGIN_ONLINE(_sc) \
 	((_sc)->sc_flags & URTW_FLAG_PLUGIN_ONLINE)