xref: /onnv-gate/usr/src/uts/common/io/ural/ural.c (revision 8099:b96df29cadab)
16629Szf162725 /*
26629Szf162725  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
36629Szf162725  * Use is subject to license terms.
46629Szf162725  */
56629Szf162725 
66629Szf162725 /*
76629Szf162725  * Copyright (c) 2005, 2006
86629Szf162725  *	Damien Bergamini <damien.bergamini@free.fr>
96629Szf162725  *
106629Szf162725  * Permission to use, copy, modify, and distribute this software for any
116629Szf162725  * purpose with or without fee is hereby granted, provided that the above
126629Szf162725  * copyright notice and this permission notice appear in all copies.
136629Szf162725  *
146629Szf162725  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
156629Szf162725  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
166629Szf162725  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
176629Szf162725  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
186629Szf162725  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
196629Szf162725  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
206629Szf162725  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
216629Szf162725  */
226629Szf162725 
236629Szf162725 /*
246629Szf162725  * Ralink Technology RT2500USB chipset driver
256629Szf162725  * http://www.ralinktech.com/
266629Szf162725  */
276629Szf162725 
286629Szf162725 #include <sys/types.h>
296629Szf162725 #include <sys/byteorder.h>
306629Szf162725 #include <sys/conf.h>
316629Szf162725 #include <sys/cmn_err.h>
326629Szf162725 #include <sys/stat.h>
336629Szf162725 #include <sys/ddi.h>
346629Szf162725 #include <sys/sunddi.h>
356629Szf162725 #include <sys/strsubr.h>
366629Szf162725 #include <sys/ethernet.h>
376629Szf162725 #include <inet/common.h>
386629Szf162725 #include <inet/nd.h>
396629Szf162725 #include <inet/mi.h>
406629Szf162725 #include <sys/note.h>
416629Szf162725 #include <sys/stream.h>
426629Szf162725 #include <sys/strsun.h>
436629Szf162725 #include <sys/modctl.h>
446629Szf162725 #include <sys/devops.h>
456629Szf162725 #include <sys/dlpi.h>
466629Szf162725 #include <sys/mac.h>
476629Szf162725 #include <sys/mac_wifi.h>
486629Szf162725 #include <sys/net80211.h>
496629Szf162725 #include <sys/net80211_proto.h>
506629Szf162725 #include <sys/varargs.h>
516629Szf162725 #include <sys/policy.h>
526629Szf162725 #include <sys/pci.h>
536629Szf162725 #include <sys/crypto/common.h>
546629Szf162725 #include <sys/crypto/api.h>
556629Szf162725 #include <inet/wifi_ioctl.h>
566629Szf162725 
576629Szf162725 #define	USBDRV_MAJOR_VER	2
586629Szf162725 #define	USBDRV_MINOR_VER	0
596629Szf162725 #include <sys/usb/usba.h>
606629Szf162725 
616629Szf162725 #include "ural_reg.h"
626629Szf162725 #include "ural_var.h"
636629Szf162725 
646629Szf162725 static void *ural_soft_state_p = NULL;
656629Szf162725 
666629Szf162725 #define	RAL_TXBUF_SIZE  	(IEEE80211_MAX_LEN)
676629Szf162725 #define	RAL_RXBUF_SIZE  	(IEEE80211_MAX_LEN)
686629Szf162725 
696629Szf162725 /* quickly determine if a given rate is CCK or OFDM */
706629Szf162725 #define	RAL_RATE_IS_OFDM(rate)	((rate) >= 12 && (rate) != 22)
716629Szf162725 #define	RAL_ACK_SIZE		14	/* 10 + 4(FCS) */
726629Szf162725 #define	RAL_CTS_SIZE		14	/* 10 + 4(FCS) */
736629Szf162725 #define	RAL_SIFS		10	/* us */
746629Szf162725 #define	RAL_RXTX_TURNAROUND	5	/* us */
756629Szf162725 
766629Szf162725 #define	URAL_N(a)		(sizeof (a) / sizeof ((a)[0]))
776629Szf162725 
786629Szf162725 /*
796629Szf162725  * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
806629Szf162725  */
816629Szf162725 static const struct ieee80211_rateset ural_rateset_11a =
826629Szf162725 	{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
836629Szf162725 
846629Szf162725 static const struct ieee80211_rateset ural_rateset_11b =
856629Szf162725 	{ 4, { 2, 4, 11, 22 } };
866629Szf162725 
876629Szf162725 static const struct ieee80211_rateset ural_rateset_11g =
886629Szf162725 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
896629Szf162725 
906629Szf162725 /*
916629Szf162725  * Default values for MAC registers; values taken from the reference driver.
926629Szf162725  */
936629Szf162725 static const struct {
946629Szf162725 	uint16_t	reg;
956629Szf162725 	uint16_t	val;
966629Szf162725 } ural_def_mac[] = {
976629Szf162725 	{ RAL_TXRX_CSR5,  0x8c8d },
986629Szf162725 	{ RAL_TXRX_CSR6,  0x8b8a },
996629Szf162725 	{ RAL_TXRX_CSR7,  0x8687 },
1006629Szf162725 	{ RAL_TXRX_CSR8,  0x0085 },
1016629Szf162725 	{ RAL_MAC_CSR13,  0x1111 },
1026629Szf162725 	{ RAL_MAC_CSR14,  0x1e11 },
1036629Szf162725 	{ RAL_TXRX_CSR21, 0xe78f },
1046629Szf162725 	{ RAL_MAC_CSR9,   0xff1d },
1056629Szf162725 	{ RAL_MAC_CSR11,  0x0002 },
1066629Szf162725 	{ RAL_MAC_CSR22,  0x0053 },
1076629Szf162725 	{ RAL_MAC_CSR15,  0x0000 },
1086629Szf162725 	{ RAL_MAC_CSR8,   0x0780 },
1096629Szf162725 	{ RAL_TXRX_CSR19, 0x0000 },
1106629Szf162725 	{ RAL_TXRX_CSR18, 0x005a },
1116629Szf162725 	{ RAL_PHY_CSR2,   0x0000 },
1126629Szf162725 	{ RAL_TXRX_CSR0,  0x1ec0 },
1136629Szf162725 	{ RAL_PHY_CSR4,   0x000f }
1146629Szf162725 };
1156629Szf162725 
1166629Szf162725 /*
1176629Szf162725  * Default values for BBP registers; values taken from the reference driver.
1186629Szf162725  */
1196629Szf162725 static const struct {
1206629Szf162725 	uint8_t	reg;
1216629Szf162725 	uint8_t	val;
1226629Szf162725 } ural_def_bbp[] = {
1236629Szf162725 	{  3, 0x02 },
1246629Szf162725 	{  4, 0x19 },
1256629Szf162725 	{ 14, 0x1c },
1266629Szf162725 	{ 15, 0x30 },
1276629Szf162725 	{ 16, 0xac },
1286629Szf162725 	{ 17, 0x48 },
1296629Szf162725 	{ 18, 0x18 },
1306629Szf162725 	{ 19, 0xff },
1316629Szf162725 	{ 20, 0x1e },
1326629Szf162725 	{ 21, 0x08 },
1336629Szf162725 	{ 22, 0x08 },
1346629Szf162725 	{ 23, 0x08 },
1356629Szf162725 	{ 24, 0x80 },
1366629Szf162725 	{ 25, 0x50 },
1376629Szf162725 	{ 26, 0x08 },
1386629Szf162725 	{ 27, 0x23 },
1396629Szf162725 	{ 30, 0x10 },
1406629Szf162725 	{ 31, 0x2b },
1416629Szf162725 	{ 32, 0xb9 },
1426629Szf162725 	{ 34, 0x12 },
1436629Szf162725 	{ 35, 0x50 },
1446629Szf162725 	{ 39, 0xc4 },
1456629Szf162725 	{ 40, 0x02 },
1466629Szf162725 	{ 41, 0x60 },
1476629Szf162725 	{ 53, 0x10 },
1486629Szf162725 	{ 54, 0x18 },
1496629Szf162725 	{ 56, 0x08 },
1506629Szf162725 	{ 57, 0x10 },
1516629Szf162725 	{ 58, 0x08 },
1526629Szf162725 	{ 61, 0x60 },
1536629Szf162725 	{ 62, 0x10 },
1546629Szf162725 	{ 75, 0xff }
1556629Szf162725 };
1566629Szf162725 
1576629Szf162725 /*
1586629Szf162725  * Default values for RF register R2 indexed by channel numbers.
1596629Szf162725  */
1606629Szf162725 static const uint32_t ural_rf2522_r2[] = {
1616629Szf162725 	0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814,
1626629Szf162725 	0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e
1636629Szf162725 };
1646629Szf162725 
1656629Szf162725 static const uint32_t ural_rf2523_r2[] = {
1666629Szf162725 	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
1676629Szf162725 	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
1686629Szf162725 };
1696629Szf162725 
1706629Szf162725 static const uint32_t ural_rf2524_r2[] = {
1716629Szf162725 	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
1726629Szf162725 	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
1736629Szf162725 };
1746629Szf162725 
1756629Szf162725 static const uint32_t ural_rf2525_r2[] = {
1766629Szf162725 	0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d,
1776629Szf162725 	0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346
1786629Szf162725 };
1796629Szf162725 
1806629Szf162725 static const uint32_t ural_rf2525_hi_r2[] = {
1816629Szf162725 	0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345,
1826629Szf162725 	0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e
1836629Szf162725 };
1846629Szf162725 
1856629Szf162725 static const uint32_t ural_rf2525e_r2[] = {
1866629Szf162725 	0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463,
1876629Szf162725 	0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b
1886629Szf162725 };
1896629Szf162725 
1906629Szf162725 static const uint32_t ural_rf2526_hi_r2[] = {
1916629Szf162725 	0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d,
1926629Szf162725 	0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241
1936629Szf162725 };
1946629Szf162725 
1956629Szf162725 static const uint32_t ural_rf2526_r2[] = {
1966629Szf162725 	0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229,
1976629Szf162725 	0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d
1986629Szf162725 };
1996629Szf162725 
2006629Szf162725 /*
2016629Szf162725  * For dual-band RF, RF registers R1 and R4 also depend on channel number;
2026629Szf162725  * values taken from the reference driver.
2036629Szf162725  */
2046629Szf162725 static const struct {
2056629Szf162725 	uint8_t		chan;
2066629Szf162725 	uint32_t	r1;
2076629Szf162725 	uint32_t	r2;
2086629Szf162725 	uint32_t	r4;
2096629Szf162725 } ural_rf5222[] = {
2106629Szf162725 	{   1, 0x08808, 0x0044d, 0x00282 },
2116629Szf162725 	{   2, 0x08808, 0x0044e, 0x00282 },
2126629Szf162725 	{   3, 0x08808, 0x0044f, 0x00282 },
2136629Szf162725 	{   4, 0x08808, 0x00460, 0x00282 },
2146629Szf162725 	{   5, 0x08808, 0x00461, 0x00282 },
2156629Szf162725 	{   6, 0x08808, 0x00462, 0x00282 },
2166629Szf162725 	{   7, 0x08808, 0x00463, 0x00282 },
2176629Szf162725 	{   8, 0x08808, 0x00464, 0x00282 },
2186629Szf162725 	{   9, 0x08808, 0x00465, 0x00282 },
2196629Szf162725 	{  10, 0x08808, 0x00466, 0x00282 },
2206629Szf162725 	{  11, 0x08808, 0x00467, 0x00282 },
2216629Szf162725 	{  12, 0x08808, 0x00468, 0x00282 },
2226629Szf162725 	{  13, 0x08808, 0x00469, 0x00282 },
2236629Szf162725 	{  14, 0x08808, 0x0046b, 0x00286 },
2246629Szf162725 
2256629Szf162725 	{  36, 0x08804, 0x06225, 0x00287 },
2266629Szf162725 	{  40, 0x08804, 0x06226, 0x00287 },
2276629Szf162725 	{  44, 0x08804, 0x06227, 0x00287 },
2286629Szf162725 	{  48, 0x08804, 0x06228, 0x00287 },
2296629Szf162725 	{  52, 0x08804, 0x06229, 0x00287 },
2306629Szf162725 	{  56, 0x08804, 0x0622a, 0x00287 },
2316629Szf162725 	{  60, 0x08804, 0x0622b, 0x00287 },
2326629Szf162725 	{  64, 0x08804, 0x0622c, 0x00287 },
2336629Szf162725 
2346629Szf162725 	{ 100, 0x08804, 0x02200, 0x00283 },
2356629Szf162725 	{ 104, 0x08804, 0x02201, 0x00283 },
2366629Szf162725 	{ 108, 0x08804, 0x02202, 0x00283 },
2376629Szf162725 	{ 112, 0x08804, 0x02203, 0x00283 },
2386629Szf162725 	{ 116, 0x08804, 0x02204, 0x00283 },
2396629Szf162725 	{ 120, 0x08804, 0x02205, 0x00283 },
2406629Szf162725 	{ 124, 0x08804, 0x02206, 0x00283 },
2416629Szf162725 	{ 128, 0x08804, 0x02207, 0x00283 },
2426629Szf162725 	{ 132, 0x08804, 0x02208, 0x00283 },
2436629Szf162725 	{ 136, 0x08804, 0x02209, 0x00283 },
2446629Szf162725 	{ 140, 0x08804, 0x0220a, 0x00283 },
2456629Szf162725 
2466629Szf162725 	{ 149, 0x08808, 0x02429, 0x00281 },
2476629Szf162725 	{ 153, 0x08808, 0x0242b, 0x00281 },
2486629Szf162725 	{ 157, 0x08808, 0x0242d, 0x00281 },
2496629Szf162725 	{ 161, 0x08808, 0x0242f, 0x00281 }
2506629Szf162725 };
2516629Szf162725 
2526629Szf162725 /*
2536629Szf162725  * device operations
2546629Szf162725  */
2556629Szf162725 static int ural_attach(dev_info_t *, ddi_attach_cmd_t);
2566629Szf162725 static int ural_detach(dev_info_t *, ddi_detach_cmd_t);
2576629Szf162725 
2586629Szf162725 /*
2596629Szf162725  * Module Loading Data & Entry Points
2606629Szf162725  */
2616629Szf162725 DDI_DEFINE_STREAM_OPS(ural_dev_ops, nulldev, nulldev, ural_attach,
262*8099SQuaker.Fang@Sun.COM     ural_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
2636629Szf162725 
2646629Szf162725 static struct modldrv ural_modldrv = {
2656629Szf162725 	&mod_driverops,		/* Type of module.  This one is a driver */
266*8099SQuaker.Fang@Sun.COM 	"ural driver v1.3",	/* short description */
2676629Szf162725 	&ural_dev_ops		/* driver specific ops */
2686629Szf162725 };
2696629Szf162725 
2706629Szf162725 static struct modlinkage modlinkage = {
2716629Szf162725 	MODREV_1,
2726629Szf162725 	(void *)&ural_modldrv,
2736629Szf162725 	NULL
2746629Szf162725 };
2756629Szf162725 
2766629Szf162725 static int	ural_m_stat(void *,  uint_t, uint64_t *);
2776629Szf162725 static int	ural_m_start(void *);
2786629Szf162725 static void	ural_m_stop(void *);
2796629Szf162725 static int	ural_m_promisc(void *, boolean_t);
2806629Szf162725 static int	ural_m_multicst(void *, boolean_t, const uint8_t *);
2816629Szf162725 static int	ural_m_unicst(void *, const uint8_t *);
2826629Szf162725 static mblk_t	*ural_m_tx(void *, mblk_t *);
2836629Szf162725 static void	ural_m_ioctl(void *, queue_t *, mblk_t *);
284*8099SQuaker.Fang@Sun.COM static int	ural_m_setprop(void *, const char *, mac_prop_id_t,
285*8099SQuaker.Fang@Sun.COM     uint_t, const void *);
286*8099SQuaker.Fang@Sun.COM static int	ural_m_getprop(void *, const char *, mac_prop_id_t,
287*8099SQuaker.Fang@Sun.COM     uint_t, uint_t, void *);
2886629Szf162725 
2896629Szf162725 static mac_callbacks_t ural_m_callbacks = {
290*8099SQuaker.Fang@Sun.COM 	MC_IOCTL | MC_SETPROP | MC_GETPROP,
2916629Szf162725 	ural_m_stat,
2926629Szf162725 	ural_m_start,
2936629Szf162725 	ural_m_stop,
2946629Szf162725 	ural_m_promisc,
2956629Szf162725 	ural_m_multicst,
2966629Szf162725 	ural_m_unicst,
2976629Szf162725 	ural_m_tx,
2986629Szf162725 	NULL,		/* mc_resources; */
2996629Szf162725 	ural_m_ioctl,
300*8099SQuaker.Fang@Sun.COM 	NULL,		/* mc_getcapab */
301*8099SQuaker.Fang@Sun.COM 	NULL,
302*8099SQuaker.Fang@Sun.COM 	NULL,
303*8099SQuaker.Fang@Sun.COM 	ural_m_setprop,
304*8099SQuaker.Fang@Sun.COM 	ural_m_getprop
3056629Szf162725 };
3066629Szf162725 
3076629Szf162725 extern const char *usb_str_cr(int);
3086629Szf162725 static void ural_amrr_start(struct ural_softc *, struct ieee80211_node *);
3096629Szf162725 static int  ural_tx_trigger(struct ural_softc *, mblk_t *);
3106629Szf162725 static int  ural_rx_trigger(struct ural_softc *);
3116629Szf162725 
3126629Szf162725 uint32_t ural_dbg_flags = 0;
3136629Szf162725 
3146629Szf162725 #ifdef DEBUG
3156629Szf162725 void
3166629Szf162725 ral_debug(uint32_t dbg_flags, const int8_t *fmt, ...)
3176629Szf162725 {
3186629Szf162725 	va_list args;
3196629Szf162725 
3206629Szf162725 	if (dbg_flags & ural_dbg_flags) {
3216629Szf162725 		va_start(args, fmt);
3226629Szf162725 		vcmn_err(CE_CONT, fmt, args);
3236629Szf162725 		va_end(args);
3246629Szf162725 	}
3256629Szf162725 }
3266629Szf162725 #endif
3276629Szf162725 
3286629Szf162725 static uint16_t
3296629Szf162725 ural_read(struct ural_softc *sc, uint16_t reg)
3306629Szf162725 {
3316629Szf162725 	usb_ctrl_setup_t req;
3326629Szf162725 	usb_cr_t cr;
3336629Szf162725 	usb_cb_flags_t cf;
3346629Szf162725 	mblk_t *mp;
3356629Szf162725 	int err;
3366629Szf162725 	uint16_t val;
3376629Szf162725 
3386629Szf162725 	bzero(&req, sizeof (req));
3396629Szf162725 	req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
3406629Szf162725 	req.bRequest = RAL_READ_MAC;
3416629Szf162725 	req.wValue = 0;
3426629Szf162725 	req.wIndex = reg;
3436629Szf162725 	req.wLength = sizeof (uint16_t);
3446629Szf162725 
3456629Szf162725 	mp = NULL;
3466629Szf162725 	err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
3476629Szf162725 	    &cr, &cf, 0);
3486629Szf162725 
3496629Szf162725 	if (err != USB_SUCCESS) {
3506629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
3516629Szf162725 		    "ural_read(): could not read MAC register:"
3526629Szf162725 		    " cr:%s(%d), cf:(%x)\n",
3536629Szf162725 		    usb_str_cr(cr), cr, cf);
3546629Szf162725 		return (0);
3556629Szf162725 	}
3566629Szf162725 
3576629Szf162725 	bcopy(mp->b_rptr, &val, sizeof (uint16_t));
3586629Szf162725 
3596629Szf162725 	if (mp)
3606629Szf162725 		freemsg(mp);
3616629Szf162725 
3626629Szf162725 	return (LE_16(val));
3636629Szf162725 }
3646629Szf162725 
3656629Szf162725 static void
3666629Szf162725 ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
3676629Szf162725 {
3686629Szf162725 	usb_ctrl_setup_t req;
3696629Szf162725 	usb_cr_t cr;
3706629Szf162725 	usb_cb_flags_t cf;
3716629Szf162725 	mblk_t *mp;
3726629Szf162725 	int err;
3736629Szf162725 
3746629Szf162725 	bzero(&req, sizeof (req));
3756629Szf162725 	req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
3766629Szf162725 	req.bRequest = RAL_READ_MULTI_MAC;
3776629Szf162725 	req.wValue = 0;
3786629Szf162725 	req.wIndex = reg;
3796629Szf162725 	req.wLength = (uint16_t)len;
3806629Szf162725 	req.attrs = USB_ATTRS_AUTOCLEARING;
3816629Szf162725 
3826629Szf162725 	mp = NULL;
3836629Szf162725 	err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
3846629Szf162725 	    &cr, &cf, 0);
3856629Szf162725 
3866629Szf162725 	if (err != USB_SUCCESS) {
3876629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
3886629Szf162725 		    "ural_read_multi(): could not read MAC register:"
3896629Szf162725 		    "cr:%s(%d), cf:(%x)\n",
3906629Szf162725 		    usb_str_cr(cr), cr, cf);
3916629Szf162725 		return;
3926629Szf162725 	}
3936629Szf162725 
3946629Szf162725 	bcopy(mp->b_rptr, buf, len);
3956629Szf162725 
3966629Szf162725 	if (mp)
3976629Szf162725 		freemsg(mp);
3986629Szf162725 }
3996629Szf162725 
4006629Szf162725 static void
4016629Szf162725 ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
4026629Szf162725 {
4036629Szf162725 	usb_ctrl_setup_t req;
4046629Szf162725 	usb_cr_t cr;
4056629Szf162725 	usb_cb_flags_t cf;
4066629Szf162725 	int err;
4076629Szf162725 
4086629Szf162725 	bzero(&req, sizeof (req));
4096629Szf162725 	req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
4106629Szf162725 	req.bRequest = RAL_WRITE_MAC;
4116629Szf162725 	req.wValue = val;
4126629Szf162725 	req.wIndex = reg;
4136629Szf162725 	req.wLength = 0;
4146629Szf162725 	req.attrs = USB_ATTRS_NONE;
4156629Szf162725 
4166629Szf162725 	err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL,
4176629Szf162725 	    &cr, &cf, 0);
4186629Szf162725 
4196629Szf162725 	if (err != USB_SUCCESS) {
4206629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
4216629Szf162725 		    "ural_write(): could not write MAC register:"
4226629Szf162725 		    "cr:%s(%d), cf:(%x)\n",
4236629Szf162725 		    usb_str_cr(cr), cr, cf);
4246629Szf162725 	}
4256629Szf162725 }
4266629Szf162725 
4276629Szf162725 /* ARGSUSED */
4286629Szf162725 static void
4296629Szf162725 ural_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
4306629Szf162725 {
4316629Szf162725 	struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private;
4326629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
4336629Szf162725 
4346629Szf162725 	RAL_DEBUG(RAL_DBG_TX,
4356629Szf162725 	    "ural_txeof(): cr:%s(%d), flags:0x%x, tx_queued:%d",
4366629Szf162725 	    usb_str_cr(req->bulk_completion_reason),
4376629Szf162725 	    req->bulk_completion_reason,
4386629Szf162725 	    req->bulk_cb_flags,
4396629Szf162725 	    sc->tx_queued);
4406629Szf162725 
4416629Szf162725 	if (req->bulk_completion_reason != USB_CR_OK)
4426629Szf162725 		sc->sc_tx_err++;
4436629Szf162725 
4446629Szf162725 	mutex_enter(&sc->tx_lock);
4456629Szf162725 
4466629Szf162725 	sc->tx_queued--;
4476629Szf162725 	sc->sc_tx_timer = 0;
4486629Szf162725 
4496629Szf162725 	if (sc->sc_need_sched) {
4506629Szf162725 		sc->sc_need_sched = 0;
4516629Szf162725 		mac_tx_update(ic->ic_mach);
4526629Szf162725 	}
4536629Szf162725 
4546629Szf162725 	mutex_exit(&sc->tx_lock);
4556629Szf162725 	usb_free_bulk_req(req);
4566629Szf162725 }
4576629Szf162725 
4586629Szf162725 /* ARGSUSED */
4596629Szf162725 static void
4606629Szf162725 ural_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
4616629Szf162725 {
4626629Szf162725 	struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private;
4636629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
4646629Szf162725 
4656629Szf162725 	struct ural_rx_desc *desc;
4666629Szf162725 	struct ieee80211_frame *wh;
4676629Szf162725 	struct ieee80211_node *ni;
4686629Szf162725 
4696629Szf162725 	mblk_t *m, *mp;
4706629Szf162725 	int len, pktlen;
4716629Szf162725 	char *rxbuf;
4726629Szf162725 
4736629Szf162725 	mp = req->bulk_data;
4746629Szf162725 	req->bulk_data = NULL;
4756629Szf162725 
4766629Szf162725 	RAL_DEBUG(RAL_DBG_RX,
4776629Szf162725 	    "ural_rxeof(): cr:%s(%d), flags:0x%x, rx_queued:%d",
4786629Szf162725 	    usb_str_cr(req->bulk_completion_reason),
4796629Szf162725 	    req->bulk_completion_reason,
4806629Szf162725 	    req->bulk_cb_flags,
4816629Szf162725 	    sc->rx_queued);
4826629Szf162725 
4836629Szf162725 	if (req->bulk_completion_reason != USB_CR_OK) {
4846629Szf162725 		sc->sc_rx_err++;
4856629Szf162725 		goto fail;
4866629Szf162725 	}
4876629Szf162725 
4886629Szf162725 	len = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
4896629Szf162725 	rxbuf = (char *)mp->b_rptr;
4906629Szf162725 
4916629Szf162725 	if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) {
4926629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
4936629Szf162725 		    "ural_rxeof(): xfer too short %d\n", len);
4946629Szf162725 		sc->sc_rx_err++;
4956629Szf162725 		goto fail;
4966629Szf162725 	}
4976629Szf162725 
4986629Szf162725 	/* rx descriptor is located at the end */
4996629Szf162725 	desc = (struct ural_rx_desc *)(rxbuf + len - RAL_RX_DESC_SIZE);
5006629Szf162725 
5016629Szf162725 	if ((LE_32(desc->flags) & RAL_RX_PHY_ERROR) ||
5026629Szf162725 	    (LE_32(desc->flags) & RAL_RX_CRC_ERROR)) {
5036629Szf162725 		/*
5046629Szf162725 		 * This should not happen since we did not request to receive
5056629Szf162725 		 * those frames when we filled RAL_TXRX_CSR2.
5066629Szf162725 		 */
5076629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "PHY or CRC error\n");
5086629Szf162725 		sc->sc_rx_err++;
5096629Szf162725 		goto fail;
5106629Szf162725 	}
5116629Szf162725 
5126629Szf162725 	pktlen = (LE_32(desc->flags) >> 16) & 0xfff;
5136629Szf162725 
5146629Szf162725 	if (pktlen > (len - RAL_RX_DESC_SIZE)) {
5156629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
5166629Szf162725 		    "ural_rxeof(): pktlen mismatch <%d, %d>.\n", pktlen, len);
5176629Szf162725 		goto fail;
5186629Szf162725 	}
5196629Szf162725 
5206629Szf162725 	/* Strip trailing 802.11 MAC FCS. */
5216629Szf162725 	pktlen -= IEEE80211_CRC_LEN;
5226629Szf162725 
5236629Szf162725 	if ((m = allocb(pktlen, BPRI_MED)) == NULL) {
5246629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
5256629Szf162725 		    "ural_rxeof(): allocate mblk failed.\n");
5266629Szf162725 		sc->sc_rx_nobuf++;
5276629Szf162725 		goto fail;
5286629Szf162725 	}
5296629Szf162725 
5306629Szf162725 	bcopy(rxbuf, m->b_rptr, pktlen);
5316629Szf162725 	m->b_wptr += pktlen;
5326629Szf162725 
5336629Szf162725 	wh = (struct ieee80211_frame *)m->b_rptr;
5346629Szf162725 	ni = ieee80211_find_rxnode(ic, wh);
5356629Szf162725 
5366629Szf162725 	/* send the frame to the 802.11 layer */
5376629Szf162725 	(void) ieee80211_input(ic, m, ni, desc->rssi, 0);
5386629Szf162725 
5396629Szf162725 	/* node is no longer needed */
5406629Szf162725 	ieee80211_free_node(ni);
5416629Szf162725 fail:
5426629Szf162725 	mutex_enter(&sc->rx_lock);
5436629Szf162725 	sc->rx_queued--;
5446629Szf162725 	mutex_exit(&sc->rx_lock);
5456629Szf162725 
5466629Szf162725 	freemsg(mp);
5476629Szf162725 	usb_free_bulk_req(req);
5486629Szf162725 
5496629Szf162725 	if (RAL_IS_RUNNING(sc))
5506629Szf162725 		(void) ural_rx_trigger(sc);
5516629Szf162725 }
5526629Szf162725 
5536629Szf162725 /*
5546629Szf162725  * Return the expected ack rate for a frame transmitted at rate `rate'.
5556629Szf162725  * this should depend on the destination node basic rate set.
5566629Szf162725  */
5576629Szf162725 static int
5586629Szf162725 ural_ack_rate(struct ieee80211com *ic, int rate)
5596629Szf162725 {
5606629Szf162725 	switch (rate) {
5616629Szf162725 	/* CCK rates */
5626629Szf162725 	case 2:
5636629Szf162725 		return (2);
5646629Szf162725 	case 4:
5656629Szf162725 	case 11:
5666629Szf162725 	case 22:
5676629Szf162725 		return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate);
5686629Szf162725 
5696629Szf162725 	/* OFDM rates */
5706629Szf162725 	case 12:
5716629Szf162725 	case 18:
5726629Szf162725 		return (12);
5736629Szf162725 	case 24:
5746629Szf162725 	case 36:
5756629Szf162725 		return (24);
5766629Szf162725 	case 48:
5776629Szf162725 	case 72:
5786629Szf162725 	case 96:
5796629Szf162725 	case 108:
5806629Szf162725 		return (48);
5816629Szf162725 	}
5826629Szf162725 
5836629Szf162725 	/* default to 1Mbps */
5846629Szf162725 	return (2);
5856629Szf162725 }
5866629Szf162725 
5876629Szf162725 /*
5886629Szf162725  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
5896629Szf162725  * The function automatically determines the operating mode depending on the
5906629Szf162725  * given rate. `flags' indicates whether short preamble is in use or not.
5916629Szf162725  */
5926629Szf162725 static uint16_t
5936629Szf162725 ural_txtime(int len, int rate, uint32_t flags)
5946629Szf162725 {
5956629Szf162725 	uint16_t txtime;
5966629Szf162725 
5976629Szf162725 	if (RAL_RATE_IS_OFDM(rate)) {
5986629Szf162725 		/* IEEE Std 802.11a-1999, pp. 37 */
5996629Szf162725 		txtime = (8 + 4 * len + 3 + rate - 1) / rate;
6006629Szf162725 		txtime = 16 + 4 + 4 * txtime + 6;
6016629Szf162725 	} else {
6026629Szf162725 		/* IEEE Std 802.11b-1999, pp. 28 */
6036629Szf162725 		txtime = (16 * len + rate - 1) / rate;
6046629Szf162725 		if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
6056629Szf162725 			txtime +=  72 + 24;
6066629Szf162725 		else
6076629Szf162725 			txtime += 144 + 48;
6086629Szf162725 	}
6096629Szf162725 	return (txtime);
6106629Szf162725 }
6116629Szf162725 
6126629Szf162725 static uint8_t
6136629Szf162725 ural_plcp_signal(int rate)
6146629Szf162725 {
6156629Szf162725 	switch (rate) {
6166629Szf162725 	/* CCK rates (returned values are device-dependent) */
6176629Szf162725 	case 2:		return (0x0);
6186629Szf162725 	case 4:		return (0x1);
6196629Szf162725 	case 11:	return (0x2);
6206629Szf162725 	case 22:	return (0x3);
6216629Szf162725 
6226629Szf162725 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
6236629Szf162725 	case 12:	return (0xb);
6246629Szf162725 	case 18:	return (0xf);
6256629Szf162725 	case 24:	return (0xa);
6266629Szf162725 	case 36:	return (0xe);
6276629Szf162725 	case 48:	return (0x9);
6286629Szf162725 	case 72:	return (0xd);
6296629Szf162725 	case 96:	return (0x8);
6306629Szf162725 	case 108:	return (0xc);
6316629Szf162725 
6326629Szf162725 	/* unsupported rates (should not get there) */
6336629Szf162725 	default:	return (0xff);
6346629Szf162725 	}
6356629Szf162725 }
6366629Szf162725 
6376629Szf162725 static void
6386629Szf162725 ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
6396629Szf162725     uint32_t flags, int len, int rate)
6406629Szf162725 {
6416629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
6426629Szf162725 	uint16_t plcp_length;
6436629Szf162725 	int remainder;
6446629Szf162725 
6456629Szf162725 	desc->flags = LE_32(flags);
6466629Szf162725 	desc->flags |= LE_32(RAL_TX_NEWSEQ);
6476629Szf162725 	desc->flags |= LE_32(len << 16);
6486629Szf162725 
6496629Szf162725 	desc->wme = LE_16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5));
6506629Szf162725 	desc->wme |= LE_16(RAL_IVOFFSET(sizeof (struct ieee80211_frame)));
6516629Szf162725 
6526629Szf162725 	/* setup PLCP fields */
6536629Szf162725 	desc->plcp_signal  = ural_plcp_signal(rate);
6546629Szf162725 	desc->plcp_service = 4;
6556629Szf162725 
6566629Szf162725 	len += IEEE80211_CRC_LEN;
6576629Szf162725 	if (RAL_RATE_IS_OFDM(rate)) {
6586629Szf162725 		desc->flags |= LE_32(RAL_TX_OFDM);
6596629Szf162725 
6606629Szf162725 		plcp_length = len & 0xfff;
6616629Szf162725 		desc->plcp_length_hi = plcp_length >> 6;
6626629Szf162725 		desc->plcp_length_lo = plcp_length & 0x3f;
6636629Szf162725 	} else {
6646629Szf162725 		plcp_length = (16 * len + rate - 1) / rate;
6656629Szf162725 		if (rate == 22) {
6666629Szf162725 			remainder = (16 * len) % 22;
6676629Szf162725 			if (remainder != 0 && remainder < 7)
6686629Szf162725 				desc->plcp_service |= RAL_PLCP_LENGEXT;
6696629Szf162725 		}
6706629Szf162725 		desc->plcp_length_hi = plcp_length >> 8;
6716629Szf162725 		desc->plcp_length_lo = plcp_length & 0xff;
6726629Szf162725 
6736629Szf162725 		if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
6746629Szf162725 			desc->plcp_signal |= 0x08;
6756629Szf162725 	}
6766629Szf162725 
6776629Szf162725 	desc->iv = 0;
6786629Szf162725 	desc->eiv = 0;
6796629Szf162725 }
6806629Szf162725 
6816629Szf162725 #define	RAL_TX_TIMEOUT		5
6826629Szf162725 
6836629Szf162725 static int
6846629Szf162725 ural_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
6856629Szf162725 {
6866629Szf162725 	struct ural_softc *sc = (struct ural_softc *)ic;
6876629Szf162725 	struct ural_tx_desc *desc;
6886629Szf162725 
6896629Szf162725 	struct ieee80211_frame *wh;
6906629Szf162725 	struct ieee80211_key *k;
6916629Szf162725 
6926629Szf162725 	uint16_t dur;
6936629Szf162725 	uint32_t flags = 0;
6946629Szf162725 	int rate, err = DDI_SUCCESS;
6956629Szf162725 
6966629Szf162725 	struct ieee80211_node *ni = NULL;
6976629Szf162725 	mblk_t *m, *m0;
6986629Szf162725 	int off, mblen, pktlen, xferlen;
6996629Szf162725 
7006629Szf162725 	mutex_enter(&sc->tx_lock);
7016629Szf162725 
7026629Szf162725 	if (sc->tx_queued > RAL_TX_LIST_COUNT) {
7036629Szf162725 		RAL_DEBUG(RAL_DBG_TX, "ural_send(): "
7046629Szf162725 		    "no TX buffer available!\n");
7056629Szf162725 		if ((type & IEEE80211_FC0_TYPE_MASK) ==
7066629Szf162725 		    IEEE80211_FC0_TYPE_DATA) {
7076629Szf162725 			sc->sc_need_sched = 1;
7086629Szf162725 		}
7096629Szf162725 		sc->sc_tx_nobuf++;
7106629Szf162725 		err = ENOMEM;
7116629Szf162725 		goto fail;
7126629Szf162725 	}
7136629Szf162725 
7146629Szf162725 	m = allocb(RAL_TXBUF_SIZE + RAL_TX_DESC_SIZE, BPRI_MED);
7156629Szf162725 	if (m == NULL) {
7166629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_send(): can't alloc mblk.\n");
7176629Szf162725 		err = DDI_FAILURE;
7186629Szf162725 		goto fail;
7196629Szf162725 	}
7206629Szf162725 
7216629Szf162725 	m->b_rptr += RAL_TX_DESC_SIZE;	/* skip TX descriptor */
7226629Szf162725 	m->b_wptr += RAL_TX_DESC_SIZE;
7236629Szf162725 
7246629Szf162725 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
7256629Szf162725 		mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr;
7266629Szf162725 		(void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
7276629Szf162725 		off += mblen;
7286629Szf162725 	}
7296629Szf162725 	m->b_wptr += off;
7306629Szf162725 
7316629Szf162725 	wh = (struct ieee80211_frame *)m->b_rptr;
7326629Szf162725 
7336629Szf162725 	ni = ieee80211_find_txnode(ic, wh->i_addr1);
7346629Szf162725 	if (ni == NULL) {
7356629Szf162725 		err = DDI_FAILURE;
7366629Szf162725 		sc->sc_tx_err++;
7376629Szf162725 		freemsg(m);
7386629Szf162725 		goto fail;
7396629Szf162725 	}
7406629Szf162725 
7416629Szf162725 	if ((type & IEEE80211_FC0_TYPE_MASK) ==
7426629Szf162725 	    IEEE80211_FC0_TYPE_DATA) {
7436629Szf162725 		(void) ieee80211_encap(ic, m, ni);
7446629Szf162725 	}
7456629Szf162725 
7466629Szf162725 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
7476629Szf162725 		k = ieee80211_crypto_encap(ic, m);
7486629Szf162725 		if (k == NULL) {
7496629Szf162725 			sc->sc_tx_err++;
7506629Szf162725 			freemsg(m);
7516629Szf162725 			err = DDI_FAILURE;
7526629Szf162725 			goto fail;
7536629Szf162725 		}
7546629Szf162725 		/* packet header may have moved, reset our local pointer */
7556629Szf162725 		wh = (struct ieee80211_frame *)m->b_rptr;
7566629Szf162725 	}
7576629Szf162725 
7586629Szf162725 	m->b_rptr -= RAL_TX_DESC_SIZE;	/* restore */
7596629Szf162725 	desc = (struct ural_tx_desc *)m->b_rptr;
7606629Szf162725 
7616629Szf162725 	if ((type & IEEE80211_FC0_TYPE_MASK) ==
7626629Szf162725 	    IEEE80211_FC0_TYPE_DATA) {	/* DATA */
7636629Szf162725 		if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
7646629Szf162725 			rate = ic->ic_bss->in_rates.ir_rates[ic->ic_fixed_rate];
7656629Szf162725 		else
7666629Szf162725 			rate = ni->in_rates.ir_rates[ni->in_txrate];
7676629Szf162725 
7686629Szf162725 		rate &= IEEE80211_RATE_VAL;
7696629Szf162725 		if (rate <= 0) {
7706629Szf162725 			rate = 2;	/* basic rate */
7716629Szf162725 		}
7726629Szf162725 
7736629Szf162725 		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
7746629Szf162725 			flags |= RAL_TX_ACK;
7756629Szf162725 			flags |= RAL_TX_RETRY(7);
7766629Szf162725 
7776629Szf162725 			dur = ural_txtime(RAL_ACK_SIZE, ural_ack_rate(ic, rate),
7786629Szf162725 			    ic->ic_flags) + RAL_SIFS;
7796629Szf162725 			*(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur);
7806629Szf162725 		}
7816629Szf162725 	} else {	/* MGMT */
7826629Szf162725 		rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
7836629Szf162725 
7846629Szf162725 		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
7856629Szf162725 			flags |= RAL_TX_ACK;
7866629Szf162725 
7876629Szf162725 			dur = ural_txtime(RAL_ACK_SIZE, rate, ic->ic_flags)
7886629Szf162725 			    + RAL_SIFS;
7896629Szf162725 			*(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur);
7906629Szf162725 
7916629Szf162725 			/* tell hardware to add timestamp for probe responses */
7926629Szf162725 			if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
7936629Szf162725 			    IEEE80211_FC0_TYPE_MGT &&
7946629Szf162725 			    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
7956629Szf162725 			    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
7966629Szf162725 				flags |= RAL_TX_TIMESTAMP;
7976629Szf162725 		}
7986629Szf162725 	}
7996629Szf162725 
8006629Szf162725 	pktlen = (uintptr_t)m->b_wptr - (uintptr_t)m->b_rptr - RAL_TX_DESC_SIZE;
8016629Szf162725 	ural_setup_tx_desc(sc, desc, flags, pktlen, rate);
8026629Szf162725 
8036629Szf162725 	/* align end on a 2-bytes boundary */
8046629Szf162725 	xferlen = (RAL_TX_DESC_SIZE + pktlen + 1) & ~1;
8056629Szf162725 
8066629Szf162725 	/*
8076629Szf162725 	 * No space left in the last URB to store the extra 2 bytes, force
8086629Szf162725 	 * sending of another URB.
8096629Szf162725 	 */
8106629Szf162725 	if ((xferlen % 64) == 0)
8116629Szf162725 		xferlen += 2;
8126629Szf162725 
8136629Szf162725 	m->b_wptr = m->b_rptr + xferlen;
8146629Szf162725 
8156629Szf162725 	RAL_DEBUG(RAL_DBG_TX, "sending data frame len=%u rate=%u xfer len=%u\n",
8166629Szf162725 	    pktlen, rate, xferlen);
8176629Szf162725 
8186629Szf162725 	(void) ural_tx_trigger(sc, m);
8196629Szf162725 
8206629Szf162725 	ic->ic_stats.is_tx_frags++;
8216629Szf162725 	ic->ic_stats.is_tx_bytes += pktlen;
8226629Szf162725 
8236629Szf162725 fail:
8246629Szf162725 	if (ni != NULL)
8256629Szf162725 		ieee80211_free_node(ni);
8266629Szf162725 
8276629Szf162725 	if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
8286629Szf162725 	    err == 0) {
8296629Szf162725 		freemsg(mp);
8306629Szf162725 	}
8316629Szf162725 
8326629Szf162725 	mutex_exit(&sc->tx_lock);
8336629Szf162725 
8346629Szf162725 	return (err);
8356629Szf162725 }
8366629Szf162725 
8376629Szf162725 static mblk_t *
8386629Szf162725 ural_m_tx(void *arg, mblk_t *mp)
8396629Szf162725 {
8406629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
8416629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
8426629Szf162725 	mblk_t *next;
8436629Szf162725 
8446629Szf162725 	/*
8456629Szf162725 	 * No data frames go out unless we're associated; this
8466629Szf162725 	 * should not happen as the 802.11 layer does not enable
8476629Szf162725 	 * the xmit queue until we enter the RUN state.
8486629Szf162725 	 */
8496629Szf162725 	if (ic->ic_state != IEEE80211_S_RUN) {
8506629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_m_tx(): "
8516629Szf162725 		    "discard, state %u\n", ic->ic_state);
8526629Szf162725 		freemsgchain(mp);
8536629Szf162725 		return (NULL);
8546629Szf162725 	}
8556629Szf162725 
8566629Szf162725 	while (mp != NULL) {
8576629Szf162725 		next = mp->b_next;
8586629Szf162725 		mp->b_next = NULL;
8596629Szf162725 		if (ural_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) {
8606629Szf162725 			mp->b_next = next;
8616629Szf162725 			freemsgchain(mp);
8626629Szf162725 			return (NULL);
8636629Szf162725 		}
8646629Szf162725 		mp = next;
8656629Szf162725 	}
8666629Szf162725 	return (mp);
8676629Szf162725 }
8686629Szf162725 
8696629Szf162725 static void
8706629Szf162725 ural_set_testmode(struct ural_softc *sc)
8716629Szf162725 {
8726629Szf162725 	usb_ctrl_setup_t req;
8736629Szf162725 	usb_cr_t cr;
8746629Szf162725 	usb_cb_flags_t cf;
8756629Szf162725 	int err;
8766629Szf162725 
8776629Szf162725 	bzero(&req, sizeof (req));
8786629Szf162725 	req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
8796629Szf162725 	req.bRequest = RAL_VENDOR_REQUEST;
8806629Szf162725 	req.wValue = 4;
8816629Szf162725 	req.wIndex = 1;
8826629Szf162725 	req.wLength = 0;
8836629Szf162725 	req.attrs = USB_ATTRS_NONE;
8846629Szf162725 
8856629Szf162725 	err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL,
8866629Szf162725 	    &cr, &cf, 0);
8876629Szf162725 
8886629Szf162725 	if (err != USB_SUCCESS) {
8896629Szf162725 		RAL_DEBUG(RAL_DBG_USB,
8906629Szf162725 		    "ural_set_testmode(): could not set test mode:"
8916629Szf162725 		    "cr:%s(%d), cf:%(x)\n",
8926629Szf162725 		    usb_str_cr(cr), cr, cf);
8936629Szf162725 	}
8946629Szf162725 }
8956629Szf162725 
8966629Szf162725 static void
8976629Szf162725 ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len)
8986629Szf162725 {
8996629Szf162725 	usb_ctrl_setup_t req;
9006629Szf162725 	usb_cr_t cr;
9016629Szf162725 	usb_cb_flags_t cf;
9026629Szf162725 	mblk_t *mp;
9036629Szf162725 	int err;
9046629Szf162725 
9056629Szf162725 	bzero(&req, sizeof (req));
9066629Szf162725 	req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
9076629Szf162725 	req.bRequest = RAL_READ_EEPROM;
9086629Szf162725 	req.wValue = 0;
9096629Szf162725 	req.wIndex = addr;
9106629Szf162725 	req.wLength = (uint16_t)len;
9116629Szf162725 
9126629Szf162725 	mp = NULL;
9136629Szf162725 	err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
9146629Szf162725 	    &cr, &cf, 0);
9156629Szf162725 
9166629Szf162725 	if (err != USB_SUCCESS) {
9176629Szf162725 		RAL_DEBUG(RAL_DBG_USB,
9186629Szf162725 		    "ural_eeprom_read(): could not read EEPROM:"
9196629Szf162725 		    "cr:%s(%d), cf:(%x)\n",
9206629Szf162725 		    usb_str_cr(cr), cr, cf);
9216629Szf162725 		return;
9226629Szf162725 	}
9236629Szf162725 
9246629Szf162725 	bcopy(mp->b_rptr, buf, len);
9256629Szf162725 
9266629Szf162725 	if (mp)
9276629Szf162725 		freemsg(mp);
9286629Szf162725 }
9296629Szf162725 
9306629Szf162725 static void
9316629Szf162725 ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val)
9326629Szf162725 {
9336629Szf162725 	uint16_t tmp;
9346629Szf162725 	int ntries;
9356629Szf162725 
9366629Szf162725 	for (ntries = 0; ntries < 5; ntries++) {
9376629Szf162725 		if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
9386629Szf162725 			break;
9396629Szf162725 	}
9406629Szf162725 	if (ntries == 5) {
9416629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
9426629Szf162725 		    "ural_bbp_write(): could not write to BBP\n");
9436629Szf162725 		return;
9446629Szf162725 	}
9456629Szf162725 
9466629Szf162725 	tmp = reg << 8 | val;
9476629Szf162725 	ural_write(sc, RAL_PHY_CSR7, tmp);
9486629Szf162725 }
9496629Szf162725 
9506629Szf162725 static uint8_t
9516629Szf162725 ural_bbp_read(struct ural_softc *sc, uint8_t reg)
9526629Szf162725 {
9536629Szf162725 	uint16_t val;
9546629Szf162725 	int ntries;
9556629Szf162725 
9566629Szf162725 	val = RAL_BBP_WRITE | reg << 8;
9576629Szf162725 	ural_write(sc, RAL_PHY_CSR7, val);
9586629Szf162725 
9596629Szf162725 	for (ntries = 0; ntries < 5; ntries++) {
9606629Szf162725 		if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
9616629Szf162725 			break;
9626629Szf162725 	}
9636629Szf162725 	if (ntries == 5) {
9646629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_bbp_read(): could not read BBP\n");
9656629Szf162725 		return (0);
9666629Szf162725 	}
9676629Szf162725 
9686629Szf162725 	return (ural_read(sc, RAL_PHY_CSR7) & 0xff);
9696629Szf162725 }
9706629Szf162725 
9716629Szf162725 static void
9726629Szf162725 ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
9736629Szf162725 {
9746629Szf162725 	uint32_t tmp;
9756629Szf162725 	int ntries;
9766629Szf162725 
9776629Szf162725 	for (ntries = 0; ntries < 5; ntries++) {
9786629Szf162725 		if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY))
9796629Szf162725 			break;
9806629Szf162725 	}
9816629Szf162725 	if (ntries == 5) {
9826629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
9836629Szf162725 		    "ural_rf_write(): could not write to RF\n");
9846629Szf162725 		return;
9856629Szf162725 	}
9866629Szf162725 
9876629Szf162725 	tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xffff) << 2 | (reg & 0x3);
9886629Szf162725 	ural_write(sc, RAL_PHY_CSR9,  tmp & 0xffff);
9896629Szf162725 	ural_write(sc, RAL_PHY_CSR10, tmp >> 16);
9906629Szf162725 
9916629Szf162725 	/* remember last written value in sc */
9926629Szf162725 	sc->rf_regs[reg] = val;
9936629Szf162725 
9946629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff);
9956629Szf162725 }
9966629Szf162725 
9976629Szf162725 /*
9986629Szf162725  * Disable RF auto-tuning.
9996629Szf162725  */
10006629Szf162725 static void
10016629Szf162725 ural_disable_rf_tune(struct ural_softc *sc)
10026629Szf162725 {
10036629Szf162725 	uint32_t tmp;
10046629Szf162725 
10056629Szf162725 	if (sc->rf_rev != RAL_RF_2523) {
10066629Szf162725 		tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
10076629Szf162725 		ural_rf_write(sc, RAL_RF1, tmp);
10086629Szf162725 	}
10096629Szf162725 
10106629Szf162725 	tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
10116629Szf162725 	ural_rf_write(sc, RAL_RF3, tmp);
10126629Szf162725 
10136629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "disabling RF autotune\n");
10146629Szf162725 }
10156629Szf162725 
10166629Szf162725 
10176629Szf162725 static void
10186629Szf162725 ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
10196629Szf162725 {
10206629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
10216629Szf162725 	uint8_t power, tmp;
10226629Szf162725 	uint_t i, chan;
10236629Szf162725 
10246629Szf162725 	chan = ieee80211_chan2ieee(ic, c);
10256629Szf162725 	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
10266629Szf162725 		return;
10276629Szf162725 
10286629Szf162725 	if (IEEE80211_IS_CHAN_2GHZ(c))
10296629Szf162725 		power = min(sc->txpow[chan - 1], 31);
10306629Szf162725 	else
10316629Szf162725 		power = 31;
10326629Szf162725 
10336629Szf162725 	/* adjust txpower using ifconfig settings */
10346629Szf162725 	power -= (100 - ic->ic_txpowlimit) / 8;
10356629Szf162725 
10366629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "setting channel to %u, txpower to %u\n",
10376629Szf162725 	    chan, power);
10386629Szf162725 
10396629Szf162725 	switch (sc->rf_rev) {
10406629Szf162725 	case RAL_RF_2522:
10416629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x00814);
10426629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]);
10436629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10446629Szf162725 		break;
10456629Szf162725 
10466629Szf162725 	case RAL_RF_2523:
10476629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x08804);
10486629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]);
10496629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044);
10506629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10516629Szf162725 		break;
10526629Szf162725 
10536629Szf162725 	case RAL_RF_2524:
10546629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x0c808);
10556629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]);
10566629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10576629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10586629Szf162725 		break;
10596629Szf162725 
10606629Szf162725 	case RAL_RF_2525:
10616629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x08808);
10626629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]);
10636629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10646629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10656629Szf162725 
10666629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x08808);
10676629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]);
10686629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10696629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10706629Szf162725 		break;
10716629Szf162725 
10726629Szf162725 	case RAL_RF_2525E:
10736629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x08808);
10746629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]);
10756629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10766629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
10776629Szf162725 		break;
10786629Szf162725 
10796629Szf162725 	case RAL_RF_2526:
10806629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]);
10816629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
10826629Szf162725 		ural_rf_write(sc, RAL_RF1, 0x08804);
10836629Szf162725 
10846629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]);
10856629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10866629Szf162725 		ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
10876629Szf162725 		break;
10886629Szf162725 
10896629Szf162725 	/* dual-band RF */
10906629Szf162725 	case RAL_RF_5222:
10916629Szf162725 		for (i = 0; ural_rf5222[i].chan != chan; i++) {
10926629Szf162725 			if (i > URAL_N(ural_rf5222)) break;
10936629Szf162725 		}
10946629Szf162725 
10956629Szf162725 		ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1);
10966629Szf162725 		ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2);
10976629Szf162725 		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10986629Szf162725 		ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4);
10996629Szf162725 		break;
11006629Szf162725 	}
11016629Szf162725 
11026629Szf162725 	if (ic->ic_opmode != IEEE80211_M_MONITOR &&
11036629Szf162725 	    ic->ic_state != IEEE80211_S_SCAN) {
11046629Szf162725 		/* set Japan filter bit for channel 14 */
11056629Szf162725 		tmp = ural_bbp_read(sc, 70);
11066629Szf162725 
11076629Szf162725 		tmp &= ~RAL_JAPAN_FILTER;
11086629Szf162725 		if (chan == 14)
11096629Szf162725 			tmp |= RAL_JAPAN_FILTER;
11106629Szf162725 
11116629Szf162725 		ural_bbp_write(sc, 70, tmp);
11126629Szf162725 
11136629Szf162725 		/* clear CRC errs */
11146629Szf162725 		(void) ural_read(sc, RAL_STA_CSR0);
11156629Szf162725 
11166629Szf162725 		drv_usecwait(10000);
11176629Szf162725 		ural_disable_rf_tune(sc);
11186629Szf162725 	}
11196629Szf162725 }
11206629Szf162725 
11216629Szf162725 /*
11226629Szf162725  * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
11236629Szf162725  * synchronization.
11246629Szf162725  */
11256629Szf162725 static void
11266629Szf162725 ural_enable_tsf_sync(struct ural_softc *sc)
11276629Szf162725 {
11286629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
11296629Szf162725 	uint16_t logcwmin, preload, tmp;
11306629Szf162725 
11316629Szf162725 	/* first, disable TSF synchronization */
11326629Szf162725 	ural_write(sc, RAL_TXRX_CSR19, 0);
11336629Szf162725 
11346629Szf162725 	tmp = (16 * ic->ic_bss->in_intval) << 4;
11356629Szf162725 	ural_write(sc, RAL_TXRX_CSR18, tmp);
11366629Szf162725 
11376629Szf162725 	logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0;
11386629Szf162725 	preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6;
11396629Szf162725 	tmp = logcwmin << 12 | preload;
11406629Szf162725 	ural_write(sc, RAL_TXRX_CSR20, tmp);
11416629Szf162725 
11426629Szf162725 	/* finally, enable TSF synchronization */
11436629Szf162725 	tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN;
11446629Szf162725 	if (ic->ic_opmode == IEEE80211_M_STA)
11456629Szf162725 		tmp |= RAL_ENABLE_TSF_SYNC(1);
11466629Szf162725 	else
11476629Szf162725 		tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR;
11486629Szf162725 	ural_write(sc, RAL_TXRX_CSR19, tmp);
11496629Szf162725 
11506629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "enabling TSF synchronization\n");
11516629Szf162725 }
11526629Szf162725 
11536629Szf162725 /*
11546629Szf162725  * This function can be called by ieee80211_set_shortslottime(). Refer to
11556629Szf162725  * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
11566629Szf162725  */
11576629Szf162725 /* ARGSUSED */
11586629Szf162725 static void
11596629Szf162725 ural_update_slot(struct ieee80211com *ic, int onoff)
11606629Szf162725 {
11616629Szf162725 	struct ural_softc *sc = (struct ural_softc *)ic;
11626629Szf162725 	uint16_t slottime, sifs, eifs;
11636629Szf162725 
11646629Szf162725 	slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
11656629Szf162725 	/* slottime = (onoff ? 9 : 20); */
11666629Szf162725 
11676629Szf162725 	/*
11686629Szf162725 	 * These settings may sound a bit inconsistent but this is what the
11696629Szf162725 	 * reference driver does.
11706629Szf162725 	 */
11716629Szf162725 	if (ic->ic_curmode == IEEE80211_MODE_11B) {
11726629Szf162725 		sifs = 16 - RAL_RXTX_TURNAROUND;
11736629Szf162725 		eifs = 364;
11746629Szf162725 	} else {
11756629Szf162725 		sifs = 10 - RAL_RXTX_TURNAROUND;
11766629Szf162725 		eifs = 64;
11776629Szf162725 	}
11786629Szf162725 
11796629Szf162725 	ural_write(sc, RAL_MAC_CSR10, slottime);
11806629Szf162725 	ural_write(sc, RAL_MAC_CSR11, sifs);
11816629Szf162725 	ural_write(sc, RAL_MAC_CSR12, eifs);
11826629Szf162725 }
11836629Szf162725 
11846629Szf162725 static void
11856629Szf162725 ural_set_txpreamble(struct ural_softc *sc)
11866629Szf162725 {
11876629Szf162725 	uint16_t tmp;
11886629Szf162725 
11896629Szf162725 	tmp = ural_read(sc, RAL_TXRX_CSR10);
11906629Szf162725 
11916629Szf162725 	tmp &= ~RAL_SHORT_PREAMBLE;
11926629Szf162725 	if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
11936629Szf162725 		tmp |= RAL_SHORT_PREAMBLE;
11946629Szf162725 
11956629Szf162725 	ural_write(sc, RAL_TXRX_CSR10, tmp);
11966629Szf162725 }
11976629Szf162725 
11986629Szf162725 static void
11996629Szf162725 ural_set_basicrates(struct ural_softc *sc)
12006629Szf162725 {
12016629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
12026629Szf162725 
12036629Szf162725 	/* update basic rate set */
12046629Szf162725 	if (ic->ic_curmode == IEEE80211_MODE_11B) {
12056629Szf162725 		/* 11b basic rates: 1, 2Mbps */
12066629Szf162725 		ural_write(sc, RAL_TXRX_CSR11, 0x3);
12076629Szf162725 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->in_chan)) {
12086629Szf162725 		/* 11a basic rates: 6, 12, 24Mbps */
12096629Szf162725 		ural_write(sc, RAL_TXRX_CSR11, 0x150);
12106629Szf162725 	} else {
12116629Szf162725 		/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
12126629Szf162725 		ural_write(sc, RAL_TXRX_CSR11, 0x15f);
12136629Szf162725 	}
12146629Szf162725 }
12156629Szf162725 
12166629Szf162725 static void
12176629Szf162725 ural_set_bssid(struct ural_softc *sc, uint8_t *bssid)
12186629Szf162725 {
12196629Szf162725 	uint16_t tmp;
12206629Szf162725 
12216629Szf162725 	tmp = bssid[0] | bssid[1] << 8;
12226629Szf162725 	ural_write(sc, RAL_MAC_CSR5, tmp);
12236629Szf162725 
12246629Szf162725 	tmp = bssid[2] | bssid[3] << 8;
12256629Szf162725 	ural_write(sc, RAL_MAC_CSR6, tmp);
12266629Szf162725 
12276629Szf162725 	tmp = bssid[4] | bssid[5] << 8;
12286629Szf162725 	ural_write(sc, RAL_MAC_CSR7, tmp);
12296629Szf162725 
12306629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "setting BSSID to " MACSTR "\n", MAC2STR(bssid));
12316629Szf162725 }
12326629Szf162725 
12336629Szf162725 static void
12346629Szf162725 ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
12356629Szf162725 {
12366629Szf162725 	uint16_t tmp;
12376629Szf162725 
12386629Szf162725 	tmp = addr[0] | addr[1] << 8;
12396629Szf162725 	ural_write(sc, RAL_MAC_CSR2, tmp);
12406629Szf162725 
12416629Szf162725 	tmp = addr[2] | addr[3] << 8;
12426629Szf162725 	ural_write(sc, RAL_MAC_CSR3, tmp);
12436629Szf162725 
12446629Szf162725 	tmp = addr[4] | addr[5] << 8;
12456629Szf162725 	ural_write(sc, RAL_MAC_CSR4, tmp);
12466629Szf162725 
12476629Szf162725 	RAL_DEBUG(RAL_DBG_HW,
12486629Szf162725 	    "setting MAC address to " MACSTR "\n", MAC2STR(addr));
12496629Szf162725 }
12506629Szf162725 
12516629Szf162725 static void
12526629Szf162725 ural_update_promisc(struct ural_softc *sc)
12536629Szf162725 {
12546629Szf162725 	uint32_t tmp;
12556629Szf162725 
12566629Szf162725 	tmp = ural_read(sc, RAL_TXRX_CSR2);
12576629Szf162725 
12586629Szf162725 	tmp &= ~RAL_DROP_NOT_TO_ME;
12596629Szf162725 	if (!(sc->sc_rcr & RAL_RCR_PROMISC))
12606629Szf162725 		tmp |= RAL_DROP_NOT_TO_ME;
12616629Szf162725 
12626629Szf162725 	ural_write(sc, RAL_TXRX_CSR2, tmp);
12636629Szf162725 
12646629Szf162725 	RAL_DEBUG(RAL_DBG_HW, "%s promiscuous mode\n",
12656629Szf162725 	    (sc->sc_rcr & RAL_RCR_PROMISC) ?  "entering" : "leaving");
12666629Szf162725 }
12676629Szf162725 
12686629Szf162725 static const char *
12696629Szf162725 ural_get_rf(int rev)
12706629Szf162725 {
12716629Szf162725 	switch (rev) {
12726629Szf162725 	case RAL_RF_2522:	return ("RT2522");
12736629Szf162725 	case RAL_RF_2523:	return ("RT2523");
12746629Szf162725 	case RAL_RF_2524:	return ("RT2524");
12756629Szf162725 	case RAL_RF_2525:	return ("RT2525");
12766629Szf162725 	case RAL_RF_2525E:	return ("RT2525e");
12776629Szf162725 	case RAL_RF_2526:	return ("RT2526");
12786629Szf162725 	case RAL_RF_5222:	return ("RT5222");
12796629Szf162725 	default:		return ("unknown");
12806629Szf162725 	}
12816629Szf162725 }
12826629Szf162725 
12836629Szf162725 static void
12846629Szf162725 ural_read_eeprom(struct ural_softc *sc)
12856629Szf162725 {
12866629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
12876629Szf162725 	uint16_t val;
12886629Szf162725 
12896629Szf162725 	ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
12906629Szf162725 	val = LE_16(val);
12916629Szf162725 	sc->rf_rev =   (val >> 11) & 0x7;
12926629Szf162725 	sc->hw_radio = (val >> 10) & 0x1;
12936629Szf162725 	sc->led_mode = (val >> 6)  & 0x7;
12946629Szf162725 	sc->rx_ant =   (val >> 4)  & 0x3;
12956629Szf162725 	sc->tx_ant =   (val >> 2)  & 0x3;
12966629Szf162725 	sc->nb_ant =   val & 0x3;
12976629Szf162725 
12986629Szf162725 	/* read MAC address */
12996629Szf162725 	ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
13006629Szf162725 
13016629Szf162725 	/* read default values for BBP registers */
13026629Szf162725 	ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
13036629Szf162725 
13046629Szf162725 	/* read Tx power for all b/g channels */
13056629Szf162725 	ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14);
13066629Szf162725 }
13076629Szf162725 
13086629Szf162725 static int
13096629Szf162725 ural_bbp_init(struct ural_softc *sc)
13106629Szf162725 {
13116629Szf162725 	int i, ntries;
13126629Szf162725 
13136629Szf162725 	/* wait for BBP to be ready */
13146629Szf162725 	for (ntries = 0; ntries < 100; ntries++) {
13156629Szf162725 		if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0)
13166629Szf162725 			break;
13176629Szf162725 		drv_usecwait(1000);
13186629Szf162725 	}
13196629Szf162725 	if (ntries == 100) {
13206629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "timeout waiting for BBP\n");
13216629Szf162725 		return (EIO);
13226629Szf162725 	}
13236629Szf162725 
13246629Szf162725 	/* initialize BBP registers to default values */
13256629Szf162725 	for (i = 0; i < URAL_N(ural_def_bbp); i++)
13266629Szf162725 		ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val);
13276629Szf162725 
13286629Szf162725 	return (0);
13296629Szf162725 }
13306629Szf162725 
13316629Szf162725 static void
13326629Szf162725 ural_set_txantenna(struct ural_softc *sc, int antenna)
13336629Szf162725 {
13346629Szf162725 	uint16_t tmp;
13356629Szf162725 	uint8_t tx;
13366629Szf162725 
13376629Szf162725 	tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK;
13386629Szf162725 	if (antenna == 1)
13396629Szf162725 		tx |= RAL_BBP_ANTA;
13406629Szf162725 	else if (antenna == 2)
13416629Szf162725 		tx |= RAL_BBP_ANTB;
13426629Szf162725 	else
13436629Szf162725 		tx |= RAL_BBP_DIVERSITY;
13446629Szf162725 
13456629Szf162725 	/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
13466629Szf162725 	if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 ||
13476629Szf162725 	    sc->rf_rev == RAL_RF_5222)
13486629Szf162725 		tx |= RAL_BBP_FLIPIQ;
13496629Szf162725 
13506629Szf162725 	ural_bbp_write(sc, RAL_BBP_TX, tx);
13516629Szf162725 
13526629Szf162725 	/* update values in PHY_CSR5 and PHY_CSR6 */
13536629Szf162725 	tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7;
13546629Szf162725 	ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7));
13556629Szf162725 
13566629Szf162725 	tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7;
13576629Szf162725 	ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7));
13586629Szf162725 }
13596629Szf162725 
13606629Szf162725 static void
13616629Szf162725 ural_set_rxantenna(struct ural_softc *sc, int antenna)
13626629Szf162725 {
13636629Szf162725 	uint8_t rx;
13646629Szf162725 
13656629Szf162725 	rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK;
13666629Szf162725 	if (antenna == 1)
13676629Szf162725 		rx |= RAL_BBP_ANTA;
13686629Szf162725 	else if (antenna == 2)
13696629Szf162725 		rx |= RAL_BBP_ANTB;
13706629Szf162725 	else
13716629Szf162725 		rx |= RAL_BBP_DIVERSITY;
13726629Szf162725 
13736629Szf162725 	/* need to force no I/Q flip for RF 2525e and 2526 */
13746629Szf162725 	if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526)
13756629Szf162725 		rx &= ~RAL_BBP_FLIPIQ;
13766629Szf162725 
13776629Szf162725 	ural_bbp_write(sc, RAL_BBP_RX, rx);
13786629Szf162725 }
13796629Szf162725 
13806629Szf162725 /*
13816629Szf162725  * This function is called periodically (every 200ms) during scanning to
13826629Szf162725  * switch from one channel to another.
13836629Szf162725  */
13846629Szf162725 static void
13856629Szf162725 ural_next_scan(void *arg)
13866629Szf162725 {
13876629Szf162725 	struct ural_softc *sc = arg;
13886629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
13896629Szf162725 
13906629Szf162725 	if (ic->ic_state == IEEE80211_S_SCAN)
13916629Szf162725 		ieee80211_next_scan(ic);
13926629Szf162725 }
13936629Szf162725 
13946629Szf162725 static int
13956629Szf162725 ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
13966629Szf162725 {
13976629Szf162725 	struct ural_softc *sc = (struct ural_softc *)ic;
13986629Szf162725 	enum ieee80211_state ostate;
13996629Szf162725 	struct ieee80211_node *ni;
14006629Szf162725 	int err;
14016629Szf162725 
14026629Szf162725 	RAL_LOCK(sc);
14036629Szf162725 
14046629Szf162725 	ostate = ic->ic_state;
14056629Szf162725 
14066629Szf162725 	if (sc->sc_scan_id != 0) {
14076629Szf162725 		(void) untimeout(sc->sc_scan_id);
14086629Szf162725 		sc->sc_scan_id = 0;
14096629Szf162725 	}
14106629Szf162725 
14116629Szf162725 	if (sc->sc_amrr_id != 0) {
14126629Szf162725 		(void) untimeout(sc->sc_amrr_id);
14136629Szf162725 		sc->sc_amrr_id = 0;
14146629Szf162725 	}
14156629Szf162725 
14166629Szf162725 	switch (nstate) {
14176629Szf162725 	case IEEE80211_S_INIT:
14186629Szf162725 		if (ostate == IEEE80211_S_RUN) {
14196629Szf162725 			/* abort TSF synchronization */
14206629Szf162725 			ural_write(sc, RAL_TXRX_CSR19, 0);
14216629Szf162725 			/* force tx led to stop blinking */
14226629Szf162725 			ural_write(sc, RAL_MAC_CSR20, 0);
14236629Szf162725 		}
14246629Szf162725 		break;
14256629Szf162725 
14266629Szf162725 	case IEEE80211_S_SCAN:
14276629Szf162725 		ural_set_chan(sc, ic->ic_curchan);
14286629Szf162725 		sc->sc_scan_id = timeout(ural_next_scan, (void *)sc,
14296629Szf162725 		    drv_usectohz(sc->dwelltime * 1000));
14306629Szf162725 		break;
14316629Szf162725 
14326629Szf162725 	case IEEE80211_S_AUTH:
14336629Szf162725 		RAL_DEBUG(RAL_DBG_MSG, "-> IEEE80211_S_AUTH ...\n");
14346629Szf162725 		ural_set_chan(sc, ic->ic_curchan);
14356629Szf162725 		break;
14366629Szf162725 
14376629Szf162725 	case IEEE80211_S_ASSOC:
14386629Szf162725 		RAL_DEBUG(RAL_DBG_MSG, "-> IEEE80211_S_ASSOC ...\n");
14396629Szf162725 		ural_set_chan(sc, ic->ic_curchan);
14406629Szf162725 		break;
14416629Szf162725 
14426629Szf162725 	case IEEE80211_S_RUN:
14436629Szf162725 		RAL_DEBUG(RAL_DBG_MSG, "-> IEEE80211_S_RUN ...\n");
14446629Szf162725 		ural_set_chan(sc, ic->ic_curchan);
14456629Szf162725 
14466629Szf162725 		ni = ic->ic_bss;
14476629Szf162725 
14486629Szf162725 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
14496629Szf162725 			ural_update_slot(ic, 1);
14506629Szf162725 			ural_set_txpreamble(sc);
14516629Szf162725 			ural_set_basicrates(sc);
14526629Szf162725 			ural_set_bssid(sc, ni->in_bssid);
14536629Szf162725 		}
14546629Szf162725 
14556629Szf162725 
14566629Szf162725 		/* make tx led blink on tx (controlled by ASIC) */
14576629Szf162725 		ural_write(sc, RAL_MAC_CSR20, 1);
14586629Szf162725 
14596629Szf162725 		if (ic->ic_opmode != IEEE80211_M_MONITOR)
14606629Szf162725 			ural_enable_tsf_sync(sc);
14616629Szf162725 
14626629Szf162725 		/* enable automatic rate adaptation in STA mode */
14636629Szf162725 		if (ic->ic_opmode == IEEE80211_M_STA &&
14646629Szf162725 		    ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
14656629Szf162725 			ural_amrr_start(sc, ni);
14666629Szf162725 
14676629Szf162725 		break;
14686629Szf162725 	}
14696629Szf162725 
14706629Szf162725 	RAL_UNLOCK(sc);
14716629Szf162725 
14726629Szf162725 	err = sc->sc_newstate(ic, nstate, arg);
14736629Szf162725 	/*
14746629Szf162725 	 * Finally, start any timers.
14756629Szf162725 	 */
14766629Szf162725 	if (nstate == IEEE80211_S_RUN)
14776629Szf162725 		ieee80211_start_watchdog(ic, 1);
14786629Szf162725 
14796629Szf162725 	return (err);
14806629Szf162725 }
14816629Szf162725 
14826629Szf162725 
14836629Szf162725 
14846629Szf162725 static void
14856629Szf162725 ural_close_pipes(struct ural_softc *sc)
14866629Szf162725 {
14876629Szf162725 	usb_flags_t flags = USB_FLAGS_SLEEP;
14886629Szf162725 
14896629Szf162725 	if (sc->sc_rx_pipeh != NULL) {
14906629Szf162725 		usb_pipe_reset(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0);
14916629Szf162725 		usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0);
14926629Szf162725 		sc->sc_rx_pipeh = NULL;
14936629Szf162725 	}
14946629Szf162725 
14956629Szf162725 	if (sc->sc_tx_pipeh != NULL) {
14966629Szf162725 		usb_pipe_reset(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0);
14976629Szf162725 		usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0);
14986629Szf162725 		sc->sc_tx_pipeh = NULL;
14996629Szf162725 	}
15006629Szf162725 }
15016629Szf162725 
15026629Szf162725 static int
15036629Szf162725 ural_open_pipes(struct ural_softc *sc)
15046629Szf162725 {
15056629Szf162725 	usb_ep_data_t *ep_node;
15066629Szf162725 	usb_pipe_policy_t policy;
15076629Szf162725 	int err;
15086629Szf162725 
15096629Szf162725 	ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0,
15106629Szf162725 	    USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
15116629Szf162725 
15126629Szf162725 	bzero(&policy, sizeof (usb_pipe_policy_t));
15136629Szf162725 	policy.pp_max_async_reqs = RAL_TX_LIST_COUNT;
15146629Szf162725 
15156629Szf162725 	if ((err = usb_pipe_open(sc->sc_dev,
15166629Szf162725 	    &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
15176629Szf162725 	    &sc->sc_tx_pipeh)) != USB_SUCCESS) {
15186629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
15196629Szf162725 		    "ural_open_pipes(): %x failed to open tx pipe\n", err);
15206629Szf162725 		goto fail;
15216629Szf162725 	}
15226629Szf162725 
15236629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "tx pipe opened\n");
15246629Szf162725 
15256629Szf162725 	ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0,
15266629Szf162725 	    USB_EP_ATTR_BULK, USB_EP_DIR_IN);
15276629Szf162725 
15286629Szf162725 	bzero(&policy, sizeof (usb_pipe_policy_t));
15296629Szf162725 	policy.pp_max_async_reqs = RAL_RX_LIST_COUNT + 32;
15306629Szf162725 
15316629Szf162725 	if ((err = usb_pipe_open(sc->sc_dev,
15326629Szf162725 	    &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
15336629Szf162725 	    &sc->sc_rx_pipeh)) != USB_SUCCESS) {
15346629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
15356629Szf162725 		    "ural_open_pipes(): %x failed to open rx pipe\n", err);
15366629Szf162725 		goto fail;
15376629Szf162725 	}
15386629Szf162725 
15396629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "rx pipe opened\n");
15406629Szf162725 
15416629Szf162725 	return (USB_SUCCESS);
15426629Szf162725 
15436629Szf162725 fail:
15446629Szf162725 	if (sc->sc_rx_pipeh != NULL) {
15456629Szf162725 		usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh,
15466629Szf162725 		    USB_FLAGS_SLEEP, NULL, 0);
15476629Szf162725 		sc->sc_rx_pipeh = NULL;
15486629Szf162725 	}
15496629Szf162725 
15506629Szf162725 	if (sc->sc_tx_pipeh != NULL) {
15516629Szf162725 		usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh,
15526629Szf162725 		    USB_FLAGS_SLEEP, NULL, 0);
15536629Szf162725 		sc->sc_tx_pipeh = NULL;
15546629Szf162725 	}
15556629Szf162725 
15566629Szf162725 	return (USB_FAILURE);
15576629Szf162725 }
15586629Szf162725 
15596629Szf162725 static int
15606629Szf162725 ural_tx_trigger(struct ural_softc *sc, mblk_t *mp)
15616629Szf162725 {
15626629Szf162725 	usb_bulk_req_t *req;
15636629Szf162725 	int err;
15646629Szf162725 
15656629Szf162725 	sc->sc_tx_timer = RAL_TX_TIMEOUT;
15666629Szf162725 
15676629Szf162725 	req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP);
15686629Szf162725 	if (req == NULL) {
15696629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
15706629Szf162725 		    "ural_tx_trigger(): failed to allocate req");
15716629Szf162725 		freemsg(mp);
15726629Szf162725 		return (-1);
15736629Szf162725 	}
15746629Szf162725 
15756629Szf162725 	req->bulk_len		= (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
15766629Szf162725 	req->bulk_data		= mp;
15776629Szf162725 	req->bulk_client_private = (usb_opaque_t)sc;
15786629Szf162725 	req->bulk_timeout	= RAL_TX_TIMEOUT;
15796629Szf162725 	req->bulk_attributes	= USB_ATTRS_AUTOCLEARING;
15806629Szf162725 	req->bulk_cb		= ural_txeof;
15816629Szf162725 	req->bulk_exc_cb	= ural_txeof;
15826629Szf162725 	req->bulk_completion_reason = 0;
15836629Szf162725 	req->bulk_cb_flags	= 0;
15846629Szf162725 
15856629Szf162725 	if ((err = usb_pipe_bulk_xfer(sc->sc_tx_pipeh, req, 0))
15866629Szf162725 	    != USB_SUCCESS) {
15876629Szf162725 
15886629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_tx_trigger(): "
15896629Szf162725 		    "failed to do tx xfer, %d", err);
15906629Szf162725 		usb_free_bulk_req(req);
15916629Szf162725 		return (-1);
15926629Szf162725 	}
15936629Szf162725 
15946629Szf162725 	sc->tx_queued++;
15956629Szf162725 
15966629Szf162725 	return (0);
15976629Szf162725 }
15986629Szf162725 
15996629Szf162725 static int
16006629Szf162725 ural_rx_trigger(struct ural_softc *sc)
16016629Szf162725 {
16026629Szf162725 	usb_bulk_req_t *req;
16036629Szf162725 	int err;
16046629Szf162725 
16056629Szf162725 	req = usb_alloc_bulk_req(sc->sc_dev, RAL_RXBUF_SIZE, USB_FLAGS_SLEEP);
16066629Szf162725 	if (req == NULL) {
16076629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
16086629Szf162725 		    "ural_rx_trigger(): failed to allocate req");
16096629Szf162725 		return (-1);
16106629Szf162725 	}
16116629Szf162725 
16126629Szf162725 	req->bulk_len		= RAL_RXBUF_SIZE;
16136629Szf162725 	req->bulk_client_private = (usb_opaque_t)sc;
16146629Szf162725 	req->bulk_timeout	= 0;
16156629Szf162725 	req->bulk_attributes	= USB_ATTRS_SHORT_XFER_OK
16166629Szf162725 	    | USB_ATTRS_AUTOCLEARING;
16176629Szf162725 	req->bulk_cb		= ural_rxeof;
16186629Szf162725 	req->bulk_exc_cb	= ural_rxeof;
16196629Szf162725 	req->bulk_completion_reason = 0;
16206629Szf162725 	req->bulk_cb_flags	= 0;
16216629Szf162725 
16226629Szf162725 	err = usb_pipe_bulk_xfer(sc->sc_rx_pipeh, req, 0);
16236629Szf162725 
16246629Szf162725 	if (err != USB_SUCCESS) {
16256629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_rx_trigger(): "
16266629Szf162725 		    "failed to do rx xfer, %d", err);
16276629Szf162725 		usb_free_bulk_req(req);
16286629Szf162725 
16296629Szf162725 		return (-1);
16306629Szf162725 	}
16316629Szf162725 
16326629Szf162725 	mutex_enter(&sc->rx_lock);
16336629Szf162725 	sc->rx_queued++;
16346629Szf162725 	mutex_exit(&sc->rx_lock);
16356629Szf162725 
16366629Szf162725 	return (0);
16376629Szf162725 }
16386629Szf162725 
16396629Szf162725 static void
16406629Szf162725 ural_init_tx_queue(struct ural_softc *sc)
16416629Szf162725 {
16426629Szf162725 	sc->tx_queued = 0;
16436629Szf162725 }
16446629Szf162725 
16456629Szf162725 static int
16466629Szf162725 ural_init_rx_queue(struct ural_softc *sc)
16476629Szf162725 {
16486629Szf162725 	int	i;
16496629Szf162725 
16506629Szf162725 	sc->rx_queued = 0;
16516629Szf162725 
16526629Szf162725 	for (i = 0; i < RAL_RX_LIST_COUNT; i++) {
16536629Szf162725 		if (ural_rx_trigger(sc) != 0) {
16546629Szf162725 			return (USB_FAILURE);
16556629Szf162725 		}
16566629Szf162725 	}
16576629Szf162725 
16586629Szf162725 	return (USB_SUCCESS);
16596629Szf162725 }
16606629Szf162725 
16616629Szf162725 static void
16626629Szf162725 ural_stop(struct ural_softc *sc)
16636629Szf162725 {
16646629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
16656629Szf162725 
16666629Szf162725 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
16676629Szf162725 	ieee80211_stop_watchdog(ic);	/* stop the watchdog */
16686629Szf162725 
16696629Szf162725 	RAL_LOCK(sc);
16706629Szf162725 
16716629Szf162725 	sc->sc_tx_timer = 0;
16726629Szf162725 	sc->sc_flags &= ~RAL_FLAG_RUNNING;	/* STOP */
16736629Szf162725 
16746629Szf162725 	/* disable Rx */
16756629Szf162725 	ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
16766629Szf162725 
16776629Szf162725 	/* reset ASIC and BBP (but won't reset MAC registers!) */
16786629Szf162725 	ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP);
16796629Szf162725 	ural_write(sc, RAL_MAC_CSR1, 0);
16806629Szf162725 
16816629Szf162725 	ural_close_pipes(sc);
16826629Szf162725 
16836629Szf162725 	RAL_UNLOCK(sc);
16846629Szf162725 }
16856629Szf162725 
16866629Szf162725 static int
16876629Szf162725 ural_init(struct ural_softc *sc)
16886629Szf162725 {
16896629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
16906629Szf162725 	uint16_t tmp;
16916629Szf162725 	int i, ntries;
16926629Szf162725 
16936629Szf162725 	ural_set_testmode(sc);
16946629Szf162725 	ural_write(sc, 0x308, 0x00f0);	/* magic */
16956629Szf162725 
16966629Szf162725 	ural_stop(sc);
16976629Szf162725 
16986629Szf162725 	/* initialize MAC registers to default values */
16996629Szf162725 	for (i = 0; i < URAL_N(ural_def_mac); i++)
17006629Szf162725 		ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val);
17016629Szf162725 
17026629Szf162725 	/* wait for BBP and RF to wake up (this can take a long time!) */
17036629Szf162725 	for (ntries = 0; ntries < 100; ntries++) {
17046629Szf162725 		tmp = ural_read(sc, RAL_MAC_CSR17);
17056629Szf162725 		if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) ==
17066629Szf162725 		    (RAL_BBP_AWAKE | RAL_RF_AWAKE))
17076629Szf162725 			break;
17086629Szf162725 		drv_usecwait(1000);
17096629Szf162725 	}
17106629Szf162725 	if (ntries == 100) {
17116629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
17126629Szf162725 		    "ural_init(): timeout waiting for BBP/RF to wakeup\n");
17136629Szf162725 		goto fail;
17146629Szf162725 	}
17156629Szf162725 
17166629Szf162725 	/* we're ready! */
17176629Szf162725 	ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY);
17186629Szf162725 
17196629Szf162725 	/* set basic rate set (will be updated later) */
17206629Szf162725 	ural_write(sc, RAL_TXRX_CSR11, 0x15f);
17216629Szf162725 
17226629Szf162725 	if (ural_bbp_init(sc) != 0)
17236629Szf162725 		goto fail;
17246629Szf162725 
17256629Szf162725 	/* set default BSS channel */
17266629Szf162725 	ural_set_chan(sc, ic->ic_curchan);
17276629Szf162725 
17286629Szf162725 	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
17296629Szf162725 	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
17306629Szf162725 
17316629Szf162725 	ural_set_txantenna(sc, sc->tx_ant);
17326629Szf162725 	ural_set_rxantenna(sc, sc->rx_ant);
17336629Szf162725 
17346629Szf162725 	ural_set_macaddr(sc, ic->ic_macaddr);
17356629Szf162725 
17366629Szf162725 	if (ural_open_pipes(sc) != USB_SUCCESS) {
17376629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_init(): "
17386629Szf162725 		    "could not open pipes.\n");
17396629Szf162725 		goto fail;
17406629Szf162725 	}
17416629Szf162725 
17426629Szf162725 	ural_init_tx_queue(sc);
17436629Szf162725 
17446629Szf162725 	if (ural_init_rx_queue(sc) != USB_SUCCESS)
17456629Szf162725 		goto fail;
17466629Szf162725 
17476629Szf162725 	/* kick Rx */
17486629Szf162725 	tmp = RAL_DROP_PHY | RAL_DROP_CRC;
17496629Szf162725 	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
17506629Szf162725 		tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
17516629Szf162725 		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
17526629Szf162725 			tmp |= RAL_DROP_TODS;
17536629Szf162725 		if (!(sc->sc_rcr & RAL_RCR_PROMISC))
17546629Szf162725 			tmp |= RAL_DROP_NOT_TO_ME;
17556629Szf162725 	}
17566629Szf162725 	ural_write(sc, RAL_TXRX_CSR2, tmp);
17576629Szf162725 	sc->sc_flags |= RAL_FLAG_RUNNING;	/* RUNNING */
17586629Szf162725 
17596629Szf162725 	return (DDI_SUCCESS);
17606629Szf162725 fail:
17616629Szf162725 	ural_stop(sc);
17626629Szf162725 	return (EIO);
17636629Szf162725 }
17646629Szf162725 
17656629Szf162725 static int
17666629Szf162725 ural_offline(dev_info_t *devinfo)
17676629Szf162725 {
17686629Szf162725 	struct ural_softc *sc;
17696629Szf162725 	struct ieee80211com *ic;
17706629Szf162725 
17716629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_offline()\n");
17726629Szf162725 
17736629Szf162725 	/*
17746629Szf162725 	 * We can't call ural_stop() here, since the hardware is removed,
17756629Szf162725 	 * we can't access the register anymore.
17766629Szf162725 	 */
17776629Szf162725 
17786629Szf162725 	sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
17796629Szf162725 	ic = &sc->sc_ic;
17806629Szf162725 
17816629Szf162725 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
17826629Szf162725 	ieee80211_stop_watchdog(ic);	/* stop the watchdog */
17836629Szf162725 
17846629Szf162725 	RAL_LOCK(sc);
17856629Szf162725 
17866629Szf162725 	sc->sc_tx_timer = 0;
17876629Szf162725 	sc->sc_flags &= ~RAL_FLAG_RUNNING;	/* STOP */
17886629Szf162725 
17896629Szf162725 	ural_close_pipes(sc);
17906629Szf162725 
17916629Szf162725 	RAL_UNLOCK(sc);
17926629Szf162725 
17936629Szf162725 	return (DDI_SUCCESS);
17946629Szf162725 }
17956629Szf162725 
17966629Szf162725 static int
17976629Szf162725 ural_online(dev_info_t *devinfo)
17986629Szf162725 {
17996629Szf162725 	struct ural_softc *sc;
18006629Szf162725 	int err;
18016629Szf162725 
18026629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_online()\n");
18036629Szf162725 
18046629Szf162725 	sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
18056629Szf162725 	err = ural_init(sc);
18066629Szf162725 
18076629Szf162725 	return (err);
18086629Szf162725 }
18096629Szf162725 
18106629Szf162725 #define	URAL_AMRR_MIN_SUCCESS_THRESHOLD	1
18116629Szf162725 #define	URAL_AMRR_MAX_SUCCESS_THRESHOLD	10
18126629Szf162725 
18136629Szf162725 /*
18146629Szf162725  * Naive implementation of the Adaptive Multi Rate Retry algorithm:
18156629Szf162725  * "IEEE 802.11 Rate Adaptation: A Practical Approach"
18166629Szf162725  * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
18176629Szf162725  * INRIA Sophia - Projet Planete
18186629Szf162725  * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
18196629Szf162725  *
18206629Szf162725  * This algorithm is particularly well suited for ural since it does not
18216629Szf162725  * require per-frame retry statistics.  Note however that since h/w does
18226629Szf162725  * not provide per-frame stats, we can't do per-node rate adaptation and
18236629Szf162725  * thus automatic rate adaptation is only enabled in STA operating mode.
18246629Szf162725  */
18256629Szf162725 #define	is_success(amrr)	\
18266629Szf162725 	((amrr)->retrycnt < (amrr)->txcnt / 10)
18276629Szf162725 #define	is_failure(amrr)	\
18286629Szf162725 	((amrr)->retrycnt > (amrr)->txcnt / 3)
18296629Szf162725 #define	is_enough(amrr)		\
18306629Szf162725 	((amrr)->txcnt > 10)
18316629Szf162725 #define	is_min_rate(ni)		\
18326629Szf162725 	((ni)->in_txrate == 0)
18336629Szf162725 #define	is_max_rate(ni)		\
18346629Szf162725 	((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1)
18356629Szf162725 #define	increase_rate(ni)	\
18366629Szf162725 	((ni)->in_txrate++)
18376629Szf162725 #define	decrease_rate(ni)	\
18386629Szf162725 	((ni)->in_txrate--)
18396629Szf162725 #define	reset_cnt(amrr)	do {	\
18406629Szf162725 	(amrr)->txcnt = (amrr)->retrycnt = 0;	\
18416629Szf162725 	_NOTE(CONSTCOND)	\
18426629Szf162725 } while (/* CONSTCOND */0)
18436629Szf162725 
18446629Szf162725 static void
18456629Szf162725 ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni)
18466629Szf162725 {
18476629Szf162725 	int need_change = 0;
18486629Szf162725 
18496629Szf162725 	if (is_success(amrr) && is_enough(amrr)) {
18506629Szf162725 		amrr->success++;
18516629Szf162725 		if (amrr->success >= amrr->success_threshold &&
18526629Szf162725 		    !is_max_rate(ni)) {
18536629Szf162725 			amrr->recovery = 1;
18546629Szf162725 			amrr->success = 0;
18556629Szf162725 			increase_rate(ni);
18566629Szf162725 			need_change = 1;
18576629Szf162725 		} else {
18586629Szf162725 			amrr->recovery = 0;
18596629Szf162725 		}
18606629Szf162725 	} else if (is_failure(amrr)) {
18616629Szf162725 		amrr->success = 0;
18626629Szf162725 		if (!is_min_rate(ni)) {
18636629Szf162725 			if (amrr->recovery) {
18646629Szf162725 				amrr->success_threshold *= 2;
18656629Szf162725 				if (amrr->success_threshold >
18666629Szf162725 				    URAL_AMRR_MAX_SUCCESS_THRESHOLD)
18676629Szf162725 					amrr->success_threshold =
18686629Szf162725 					    URAL_AMRR_MAX_SUCCESS_THRESHOLD;
18696629Szf162725 			} else {
18706629Szf162725 				amrr->success_threshold =
18716629Szf162725 				    URAL_AMRR_MIN_SUCCESS_THRESHOLD;
18726629Szf162725 			}
18736629Szf162725 			decrease_rate(ni);
18746629Szf162725 			need_change = 1;
18756629Szf162725 		}
18766629Szf162725 		amrr->recovery = 0;	/* original paper was incorrect */
18776629Szf162725 	}
18786629Szf162725 
18796629Szf162725 	if (is_enough(amrr) || need_change)
18806629Szf162725 		reset_cnt(amrr);
18816629Szf162725 }
18826629Szf162725 
18836629Szf162725 static void
18846629Szf162725 ural_amrr_timeout(void *arg)
18856629Szf162725 {
18866629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
18876629Szf162725 	struct ural_amrr *amrr = &sc->amrr;
18886629Szf162725 
18896629Szf162725 	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
18906629Szf162725 
18916629Szf162725 	/* count TX retry-fail as Tx errors */
18926629Szf162725 	sc->sc_tx_err += sc->sta[9];
18936629Szf162725 	sc->sc_tx_retries += (sc->sta[7] + sc->sta[8]);
18946629Szf162725 
18956629Szf162725 	amrr->retrycnt =
18966629Szf162725 	    sc->sta[7] +	/* TX one-retry ok count */
18976629Szf162725 	    sc->sta[8] +	/* TX more-retry ok count */
18986629Szf162725 	    sc->sta[9];		/* TX retry-fail count */
18996629Szf162725 
19006629Szf162725 	amrr->txcnt =
19016629Szf162725 	    amrr->retrycnt +
19026629Szf162725 	    sc->sta[6];		/* TX no-retry ok count */
19036629Szf162725 
19046629Szf162725 	ural_ratectl(amrr, sc->sc_ic.ic_bss);
19056629Szf162725 
19066629Szf162725 	sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc,
19076629Szf162725 	    drv_usectohz(1000 * 1000)); /* 1 second */
19086629Szf162725 }
19096629Szf162725 
19106629Szf162725 
19116629Szf162725 static void
19126629Szf162725 ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni)
19136629Szf162725 {
19146629Szf162725 	struct ural_amrr *amrr = &sc->amrr;
19156629Szf162725 	int i;
19166629Szf162725 
19176629Szf162725 	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
19186629Szf162725 	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
19196629Szf162725 
19206629Szf162725 	amrr->success = 0;
19216629Szf162725 	amrr->recovery = 0;
19226629Szf162725 	amrr->txcnt = amrr->retrycnt = 0;
19236629Szf162725 	amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD;
19246629Szf162725 
19256629Szf162725 	/* set rate to some reasonable initial value */
19266629Szf162725 	for (i = ni->in_rates.ir_nrates - 1;
19276629Szf162725 	    i > 0 && (ni->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72;
19286629Szf162725 	    i--) {
19296629Szf162725 	}
19306629Szf162725 
19316629Szf162725 	ni->in_txrate = i;
19326629Szf162725 
19336629Szf162725 	sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc,
19346629Szf162725 	    drv_usectohz(1000 * 1000)); /* 1 second */
19356629Szf162725 }
19366629Szf162725 
19376629Szf162725 void
19386629Szf162725 ural_watchdog(void *arg)
19396629Szf162725 {
19406629Szf162725 	struct ural_softc *sc = arg;
19416629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
19426629Szf162725 	int ntimer = 0;
19436629Szf162725 
19446629Szf162725 	RAL_LOCK(sc);
19456629Szf162725 	ic->ic_watchdog_timer = 0;
19466629Szf162725 
19476629Szf162725 	if (!RAL_IS_RUNNING(sc)) {
19486629Szf162725 		RAL_UNLOCK(sc);
19496629Szf162725 		return;
19506629Szf162725 	}
19516629Szf162725 
19526629Szf162725 	if (sc->sc_tx_timer > 0) {
19536629Szf162725 		if (--sc->sc_tx_timer == 0) {
19546629Szf162725 			RAL_DEBUG(RAL_DBG_ERR, "tx timer timeout\n");
19556629Szf162725 			RAL_UNLOCK(sc);
19566629Szf162725 			(void) ural_init(sc);
19576629Szf162725 			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
19586629Szf162725 			return;
19596629Szf162725 		}
19606629Szf162725 	}
19616629Szf162725 
19626629Szf162725 	if (ic->ic_state == IEEE80211_S_RUN)
19636629Szf162725 		ntimer = 1;
19646629Szf162725 
19656629Szf162725 	RAL_UNLOCK(sc);
19666629Szf162725 
19676629Szf162725 	ieee80211_watchdog(ic);
19686629Szf162725 
19696629Szf162725 	if (ntimer)
19706629Szf162725 		ieee80211_start_watchdog(ic, ntimer);
19716629Szf162725 }
19726629Szf162725 
19736629Szf162725 static int
19746629Szf162725 ural_m_start(void *arg)
19756629Szf162725 {
19766629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
19776629Szf162725 	crypto_mech_type_t type;
19786629Szf162725 	int err;
19796629Szf162725 
19806629Szf162725 
19816629Szf162725 	type = crypto_mech2id(SUN_CKM_RC4); /* load rc4 module into kernel */
19826629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_m_start(%d)\n", type);
19836629Szf162725 
19846629Szf162725 	/*
19856629Szf162725 	 * initialize RT2500USB hardware
19866629Szf162725 	 */
19876629Szf162725 	err = ural_init(sc);
19886629Szf162725 	if (err != DDI_SUCCESS) {
19896629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "device configuration failed\n");
19906629Szf162725 		goto fail;
19916629Szf162725 	}
19926629Szf162725 	sc->sc_flags |= RAL_FLAG_RUNNING;	/* RUNNING */
19936629Szf162725 	return (err);
19946629Szf162725 
19956629Szf162725 fail:
19966629Szf162725 	ural_stop(sc);
19976629Szf162725 	return (err);
19986629Szf162725 }
19996629Szf162725 
20006629Szf162725 static void
20016629Szf162725 ural_m_stop(void *arg)
20026629Szf162725 {
20036629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
20046629Szf162725 
20056629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_m_stop()\n");
20066629Szf162725 
20076629Szf162725 	(void) ural_stop(sc);
20086629Szf162725 	sc->sc_flags &= ~RAL_FLAG_RUNNING;	/* STOP */
20096629Szf162725 }
20106629Szf162725 
20116629Szf162725 static int
20126629Szf162725 ural_m_unicst(void *arg, const uint8_t *macaddr)
20136629Szf162725 {
20146629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
20156629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
20166629Szf162725 
20176629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_m_unicst(): " MACSTR "\n",
20186629Szf162725 	    MAC2STR(macaddr));
20196629Szf162725 
20206629Szf162725 	IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
20216629Szf162725 	(void) ural_set_macaddr(sc, (uint8_t *)macaddr);
20226629Szf162725 	(void) ural_init(sc);
20236629Szf162725 
20246629Szf162725 	return (0);
20256629Szf162725 }
20266629Szf162725 
20276629Szf162725 /*ARGSUSED*/
20286629Szf162725 static int
20296629Szf162725 ural_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
20306629Szf162725 {
20316629Szf162725 	return (0);
20326629Szf162725 }
20336629Szf162725 
20346629Szf162725 static int
20356629Szf162725 ural_m_promisc(void *arg, boolean_t on)
20366629Szf162725 {
20376629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
20386629Szf162725 
20396629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_m_promisc()\n");
20406629Szf162725 
20416629Szf162725 	if (on) {
20426629Szf162725 		sc->sc_rcr |= RAL_RCR_PROMISC;
20436629Szf162725 		sc->sc_rcr |= RAL_RCR_MULTI;
20446629Szf162725 	} else {
20456629Szf162725 		sc->sc_rcr &= ~RAL_RCR_PROMISC;
20466629Szf162725 		sc->sc_rcr &= ~RAL_RCR_PROMISC;
20476629Szf162725 	}
20486629Szf162725 
20496629Szf162725 	ural_update_promisc(sc);
20506629Szf162725 	return (0);
20516629Szf162725 }
20526629Szf162725 
2053*8099SQuaker.Fang@Sun.COM /*
2054*8099SQuaker.Fang@Sun.COM  * callback functions for /get/set properties
2055*8099SQuaker.Fang@Sun.COM  */
2056*8099SQuaker.Fang@Sun.COM static int
2057*8099SQuaker.Fang@Sun.COM ural_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2058*8099SQuaker.Fang@Sun.COM     uint_t wldp_length, const void *wldp_buf)
2059*8099SQuaker.Fang@Sun.COM {
2060*8099SQuaker.Fang@Sun.COM 	struct ural_softc *sc = (struct ural_softc *)arg;
2061*8099SQuaker.Fang@Sun.COM 	struct ieee80211com *ic = &sc->sc_ic;
2062*8099SQuaker.Fang@Sun.COM 	int err;
2063*8099SQuaker.Fang@Sun.COM 
2064*8099SQuaker.Fang@Sun.COM 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
2065*8099SQuaker.Fang@Sun.COM 	    wldp_length, wldp_buf);
2066*8099SQuaker.Fang@Sun.COM 	RAL_LOCK(sc);
2067*8099SQuaker.Fang@Sun.COM 	if (err == ENETRESET) {
2068*8099SQuaker.Fang@Sun.COM 		if (RAL_IS_RUNNING(sc)) {
2069*8099SQuaker.Fang@Sun.COM 			RAL_UNLOCK(sc);
2070*8099SQuaker.Fang@Sun.COM 			(void) ural_init(sc);
2071*8099SQuaker.Fang@Sun.COM 			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2072*8099SQuaker.Fang@Sun.COM 			RAL_LOCK(sc);
2073*8099SQuaker.Fang@Sun.COM 		}
2074*8099SQuaker.Fang@Sun.COM 		err = 0;
2075*8099SQuaker.Fang@Sun.COM 	}
2076*8099SQuaker.Fang@Sun.COM 	RAL_UNLOCK(sc);
2077*8099SQuaker.Fang@Sun.COM 
2078*8099SQuaker.Fang@Sun.COM 	return (err);
2079*8099SQuaker.Fang@Sun.COM }
2080*8099SQuaker.Fang@Sun.COM 
2081*8099SQuaker.Fang@Sun.COM static int
2082*8099SQuaker.Fang@Sun.COM ural_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2083*8099SQuaker.Fang@Sun.COM     uint_t pr_flags, uint_t wldp_length, void *wldp_buf)
2084*8099SQuaker.Fang@Sun.COM {
2085*8099SQuaker.Fang@Sun.COM 	struct ural_softc *sc = (struct ural_softc *)arg;
2086*8099SQuaker.Fang@Sun.COM 	int err;
2087*8099SQuaker.Fang@Sun.COM 
2088*8099SQuaker.Fang@Sun.COM 	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
2089*8099SQuaker.Fang@Sun.COM 	    pr_flags, wldp_length, wldp_buf);
2090*8099SQuaker.Fang@Sun.COM 
2091*8099SQuaker.Fang@Sun.COM 	return (err);
2092*8099SQuaker.Fang@Sun.COM }
2093*8099SQuaker.Fang@Sun.COM 
20946629Szf162725 static void
20956629Szf162725 ural_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
20966629Szf162725 {
20976629Szf162725 	struct ural_softc *sc = (struct ural_softc *)arg;
20986629Szf162725 	struct ieee80211com *ic = &sc->sc_ic;
20996629Szf162725 	int err;
21006629Szf162725 
21016629Szf162725 	err = ieee80211_ioctl(ic, wq, mp);
21026629Szf162725 	RAL_LOCK(sc);
21036629Szf162725 	if (err == ENETRESET) {
21046629Szf162725 		if (RAL_IS_RUNNING(sc)) {
21056629Szf162725 			RAL_UNLOCK(sc);
21066629Szf162725 			(void) ural_init(sc);
21076629Szf162725 			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
21086629Szf162725 			RAL_LOCK(sc);
21096629Szf162725 		}
21106629Szf162725 	}
21116629Szf162725 	RAL_UNLOCK(sc);
21126629Szf162725 }
21136629Szf162725 
21146629Szf162725 static int
21156629Szf162725 ural_m_stat(void *arg, uint_t stat, uint64_t *val)
21166629Szf162725 {
21176629Szf162725 	struct ural_softc *sc  = (struct ural_softc *)arg;
21186629Szf162725 	ieee80211com_t	*ic = &sc->sc_ic;
21196629Szf162725 	ieee80211_node_t *ni = ic->ic_bss;
21206629Szf162725 	struct ieee80211_rateset *rs = &ni->in_rates;
21216629Szf162725 
21226629Szf162725 	RAL_LOCK(sc);
21236629Szf162725 	switch (stat) {
21246629Szf162725 	case MAC_STAT_IFSPEED:
21256629Szf162725 		*val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
21266629Szf162725 		    (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
21276890Sql147931 		    : ic->ic_fixed_rate) / 2 * 1000000;
21286629Szf162725 		break;
21296629Szf162725 	case MAC_STAT_NOXMTBUF:
21306629Szf162725 		*val = sc->sc_tx_nobuf;
21316629Szf162725 		break;
21326629Szf162725 	case MAC_STAT_NORCVBUF:
21336629Szf162725 		*val = sc->sc_rx_nobuf;
21346629Szf162725 		break;
21356629Szf162725 	case MAC_STAT_IERRORS:
21366629Szf162725 		*val = sc->sc_rx_err;
21376629Szf162725 		break;
21386629Szf162725 	case MAC_STAT_RBYTES:
21396629Szf162725 		*val = ic->ic_stats.is_rx_bytes;
21406629Szf162725 		break;
21416629Szf162725 	case MAC_STAT_IPACKETS:
21426629Szf162725 		*val = ic->ic_stats.is_rx_frags;
21436629Szf162725 		break;
21446629Szf162725 	case MAC_STAT_OBYTES:
21456629Szf162725 		*val = ic->ic_stats.is_tx_bytes;
21466629Szf162725 		break;
21476629Szf162725 	case MAC_STAT_OPACKETS:
21486629Szf162725 		*val = ic->ic_stats.is_tx_frags;
21496629Szf162725 		break;
21506629Szf162725 	case MAC_STAT_OERRORS:
21516629Szf162725 	case WIFI_STAT_TX_FAILED:
21526629Szf162725 		*val = sc->sc_tx_err;
21536629Szf162725 		break;
21546629Szf162725 	case WIFI_STAT_TX_RETRANS:
21556629Szf162725 		*val = sc->sc_tx_retries;
21566629Szf162725 		break;
21576629Szf162725 	case WIFI_STAT_FCS_ERRORS:
21586629Szf162725 	case WIFI_STAT_WEP_ERRORS:
21596629Szf162725 	case WIFI_STAT_TX_FRAGS:
21606629Szf162725 	case WIFI_STAT_MCAST_TX:
21616629Szf162725 	case WIFI_STAT_RTS_SUCCESS:
21626629Szf162725 	case WIFI_STAT_RTS_FAILURE:
21636629Szf162725 	case WIFI_STAT_ACK_FAILURE:
21646629Szf162725 	case WIFI_STAT_RX_FRAGS:
21656629Szf162725 	case WIFI_STAT_MCAST_RX:
21666629Szf162725 	case WIFI_STAT_RX_DUPS:
21676629Szf162725 		RAL_UNLOCK(sc);
21686629Szf162725 		return (ieee80211_stat(ic, stat, val));
21696629Szf162725 	default:
21706629Szf162725 		RAL_UNLOCK(sc);
21716629Szf162725 		return (ENOTSUP);
21726629Szf162725 	}
21736629Szf162725 	RAL_UNLOCK(sc);
21746629Szf162725 
21756629Szf162725 	return (0);
21766629Szf162725 }
21776629Szf162725 
21786629Szf162725 
21796629Szf162725 static int
21806629Szf162725 ural_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
21816629Szf162725 {
21826629Szf162725 	struct ural_softc *sc;
21836629Szf162725 	struct ieee80211com *ic;
21846629Szf162725 	int err, i;
21856629Szf162725 	int instance;
21866629Szf162725 
21876629Szf162725 	char strbuf[32];
21886629Szf162725 
21896629Szf162725 	wifi_data_t wd = { 0 };
21906629Szf162725 	mac_register_t *macp;
21916629Szf162725 
21926629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_attach()\n");
21936629Szf162725 
21946629Szf162725 	if (cmd != DDI_ATTACH)
21956629Szf162725 		return (DDI_FAILURE);
21966629Szf162725 
21976629Szf162725 	instance = ddi_get_instance(devinfo);
21986629Szf162725 
21996629Szf162725 	if (ddi_soft_state_zalloc(ural_soft_state_p, instance) != DDI_SUCCESS) {
22006629Szf162725 		RAL_DEBUG(RAL_DBG_MSG, "ural_attach(): "
22016629Szf162725 		    "unable to alloc soft_state_p\n");
22026629Szf162725 		return (DDI_FAILURE);
22036629Szf162725 	}
22046629Szf162725 
22056629Szf162725 	sc = ddi_get_soft_state(ural_soft_state_p, instance);
22066629Szf162725 	ic = (ieee80211com_t *)&sc->sc_ic;
22076629Szf162725 	sc->sc_dev = devinfo;
22086629Szf162725 
22096629Szf162725 	if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) {
22106629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
22116629Szf162725 		    "ural_attach(): usb_client_attach failed\n");
22126629Szf162725 		goto fail1;
22136629Szf162725 	}
22146629Szf162725 
22156629Szf162725 	if (usb_get_dev_data(devinfo, &sc->sc_udev,
22166629Szf162725 	    USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) {
22176629Szf162725 		sc->sc_udev = NULL;
22186629Szf162725 		goto fail2;
22196629Szf162725 	}
22206629Szf162725 
22216629Szf162725 	mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
22226629Szf162725 	mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL);
22236629Szf162725 	mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL);
22246629Szf162725 
22256629Szf162725 	/* retrieve RT2570 rev. no */
22266629Szf162725 	sc->asic_rev = ural_read(sc, RAL_MAC_CSR0);
22276629Szf162725 
22286629Szf162725 	/* retrieve MAC address and various other things from EEPROM */
22296629Szf162725 	ural_read_eeprom(sc);
22306629Szf162725 
22316629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
22326629Szf162725 	    sc->asic_rev, ural_get_rf(sc->rf_rev));
22336629Szf162725 
22346629Szf162725 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
22356629Szf162725 	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
22366629Szf162725 	ic->ic_state = IEEE80211_S_INIT;
22376629Szf162725 
22386629Szf162725 	ic->ic_maxrssi = 63;
22396629Szf162725 	ic->ic_set_shortslot = ural_update_slot;
22406629Szf162725 	ic->ic_xmit = ural_send;
22416629Szf162725 
22426629Szf162725 	/* set device capabilities */
22436629Szf162725 	ic->ic_caps =
22446629Szf162725 	    IEEE80211_C_TXPMGT |	/* tx power management */
22456629Szf162725 	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
22466629Szf162725 	    IEEE80211_C_SHSLOT;		/* short slot time supported */
22476629Szf162725 
22486629Szf162725 	ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
22496629Szf162725 
22506629Szf162725 #define	IEEE80211_CHAN_A	\
22516629Szf162725 	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
22526629Szf162725 
22536629Szf162725 	if (sc->rf_rev == RAL_RF_5222) {
22546629Szf162725 		/* set supported .11a rates */
22556629Szf162725 		ic->ic_sup_rates[IEEE80211_MODE_11A] = ural_rateset_11a;
22566629Szf162725 
22576629Szf162725 		/* set supported .11a channels */
22586629Szf162725 		for (i = 36; i <= 64; i += 4) {
22596629Szf162725 			ic->ic_sup_channels[i].ich_freq =
22606629Szf162725 			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22616629Szf162725 			ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22626629Szf162725 		}
22636629Szf162725 		for (i = 100; i <= 140; i += 4) {
22646629Szf162725 			ic->ic_sup_channels[i].ich_freq =
22656629Szf162725 			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22666629Szf162725 			ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22676629Szf162725 		}
22686629Szf162725 		for (i = 149; i <= 161; i += 4) {
22696629Szf162725 			ic->ic_sup_channels[i].ich_freq =
22706629Szf162725 			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22716629Szf162725 			ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22726629Szf162725 		}
22736629Szf162725 	}
22746629Szf162725 
22756629Szf162725 	/* set supported .11b and .11g rates */
22766629Szf162725 	ic->ic_sup_rates[IEEE80211_MODE_11B] = ural_rateset_11b;
22776629Szf162725 	ic->ic_sup_rates[IEEE80211_MODE_11G] = ural_rateset_11g;
22786629Szf162725 
22796629Szf162725 	/* set supported .11b and .11g channels (1 through 14) */
22806629Szf162725 	for (i = 1; i <= 14; i++) {
22816629Szf162725 		ic->ic_sup_channels[i].ich_freq =
22826629Szf162725 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
22836629Szf162725 		ic->ic_sup_channels[i].ich_flags =
22846629Szf162725 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
22856629Szf162725 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
22866629Szf162725 	}
22876629Szf162725 
22886629Szf162725 	ieee80211_attach(ic);
22896629Szf162725 
22906629Szf162725 	/* register WPA door */
22916629Szf162725 	ieee80211_register_door(ic, ddi_driver_name(devinfo),
22926629Szf162725 	    ddi_get_instance(devinfo));
22936629Szf162725 
22946629Szf162725 	/* override state transition machine */
22956629Szf162725 	sc->sc_newstate = ic->ic_newstate;
22966629Szf162725 	ic->ic_newstate = ural_newstate;
22976629Szf162725 	ic->ic_watchdog = ural_watchdog;
22986629Szf162725 	ieee80211_media_init(ic);
22996629Szf162725 	ic->ic_def_txkey = 0;
23006629Szf162725 
23016629Szf162725 	sc->sc_rcr = 0;
23026629Szf162725 	sc->dwelltime = 300;
23036629Szf162725 	sc->sc_flags &= ~RAL_FLAG_RUNNING;
23046629Szf162725 
23056629Szf162725 	/*
23066629Szf162725 	 * Provide initial settings for the WiFi plugin; whenever this
23076629Szf162725 	 * information changes, we need to call mac_plugindata_update()
23086629Szf162725 	 */
23096629Szf162725 	wd.wd_opmode = ic->ic_opmode;
23106629Szf162725 	wd.wd_secalloc = WIFI_SEC_NONE;
23116629Szf162725 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
23126629Szf162725 
23136629Szf162725 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
23146629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_attach(): "
23156629Szf162725 		    "MAC version mismatch\n");
23166629Szf162725 		goto fail3;
23176629Szf162725 	}
23186629Szf162725 
23196629Szf162725 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
23206629Szf162725 	macp->m_driver		= sc;
23216629Szf162725 	macp->m_dip		= devinfo;
23226629Szf162725 	macp->m_src_addr	= ic->ic_macaddr;
23236629Szf162725 	macp->m_callbacks	= &ural_m_callbacks;
23246629Szf162725 	macp->m_min_sdu		= 0;
23256629Szf162725 	macp->m_max_sdu		= IEEE80211_MTU;
23266629Szf162725 	macp->m_pdata		= &wd;
23276629Szf162725 	macp->m_pdata_size	= sizeof (wd);
23286629Szf162725 
23296629Szf162725 	err = mac_register(macp, &ic->ic_mach);
23306629Szf162725 	mac_free(macp);
23316629Szf162725 	if (err != 0) {
23326629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ural_attach(): "
23336629Szf162725 		    "mac_register() err %x\n", err);
23346629Szf162725 		goto fail3;
23356629Szf162725 	}
23366629Szf162725 
23376629Szf162725 	if (usb_register_hotplug_cbs(devinfo, ural_offline,
23386629Szf162725 	    ural_online) != USB_SUCCESS) {
23396629Szf162725 		RAL_DEBUG(RAL_DBG_ERR,
23406629Szf162725 		    "ural: ural_attach() failed to register events");
23416629Szf162725 		goto fail4;
23426629Szf162725 	}
23436629Szf162725 
23446629Szf162725 	/*
23456629Szf162725 	 * Create minor node of type DDI_NT_NET_WIFI
23466629Szf162725 	 */
23476629Szf162725 	(void) snprintf(strbuf, sizeof (strbuf), "%s%d",
23486629Szf162725 	    "ural", instance);
23496629Szf162725 	err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
23506629Szf162725 	    instance + 1, DDI_NT_NET_WIFI, 0);
23516629Szf162725 
23526629Szf162725 	if (err != DDI_SUCCESS)
23536629Szf162725 		RAL_DEBUG(RAL_DBG_ERR, "ddi_create_minor_node() failed\n");
23546629Szf162725 
23556629Szf162725 	/*
23566629Szf162725 	 * Notify link is down now
23576629Szf162725 	 */
23586629Szf162725 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
23596629Szf162725 
23606629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_attach() done successfully.\n");
23616629Szf162725 	return (DDI_SUCCESS);
23626629Szf162725 fail4:
23636629Szf162725 	(void) mac_unregister(ic->ic_mach);
23646629Szf162725 fail3:
23656629Szf162725 	mutex_destroy(&sc->sc_genlock);
23666629Szf162725 	mutex_destroy(&sc->tx_lock);
23676629Szf162725 	mutex_destroy(&sc->rx_lock);
23686629Szf162725 fail2:
23696629Szf162725 	usb_client_detach(sc->sc_dev, sc->sc_udev);
23706629Szf162725 fail1:
23716629Szf162725 	ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo));
23726629Szf162725 
23736629Szf162725 	return (DDI_FAILURE);
23746629Szf162725 }
23756629Szf162725 
23766629Szf162725 static int
23776629Szf162725 ural_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
23786629Szf162725 {
23796629Szf162725 	struct ural_softc *sc;
23806629Szf162725 
23816629Szf162725 	RAL_DEBUG(RAL_DBG_MSG, "ural_detach()\n");
23826629Szf162725 	sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
23836629Szf162725 
23846629Szf162725 	if (cmd != DDI_DETACH)
23856629Szf162725 		return (DDI_FAILURE);
23866629Szf162725 
23877507SXinghua.Wen@Sun.COM 	if (mac_disable(sc->sc_ic.ic_mach) != 0)
23887507SXinghua.Wen@Sun.COM 		return (DDI_FAILURE);
23897507SXinghua.Wen@Sun.COM 
23906629Szf162725 	ural_stop(sc);
23916629Szf162725 	usb_unregister_hotplug_cbs(devinfo);
23926629Szf162725 
23936629Szf162725 	/*
23946629Szf162725 	 * Unregister from the MAC layer subsystem
23956629Szf162725 	 */
23967507SXinghua.Wen@Sun.COM 	(void) mac_unregister(sc->sc_ic.ic_mach);
23976629Szf162725 
23986629Szf162725 	/*
23996629Szf162725 	 * detach ieee80211 layer
24006629Szf162725 	 */
24016629Szf162725 	ieee80211_detach(&sc->sc_ic);
24026629Szf162725 
24036629Szf162725 	mutex_destroy(&sc->sc_genlock);
24046629Szf162725 	mutex_destroy(&sc->tx_lock);
24056629Szf162725 	mutex_destroy(&sc->rx_lock);
24066629Szf162725 
24076629Szf162725 	/* pipes will be close in ural_stop() */
24086629Szf162725 	usb_client_detach(devinfo, sc->sc_udev);
24096629Szf162725 	sc->sc_udev = NULL;
24106629Szf162725 
24116629Szf162725 	ddi_remove_minor_node(devinfo, NULL);
24126629Szf162725 	ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo));
24136629Szf162725 
24146629Szf162725 	return (DDI_SUCCESS);
24156629Szf162725 }
24166629Szf162725 
24176629Szf162725 int
24186629Szf162725 _info(struct modinfo *modinfop)
24196629Szf162725 {
24206629Szf162725 	return (mod_info(&modlinkage, modinfop));
24216629Szf162725 }
24226629Szf162725 
24236629Szf162725 int
24246629Szf162725 _init(void)
24256629Szf162725 {
24266629Szf162725 	int status;
24276629Szf162725 
24286629Szf162725 	status = ddi_soft_state_init(&ural_soft_state_p,
24296629Szf162725 	    sizeof (struct ural_softc), 1);
24306629Szf162725 	if (status != 0)
24316629Szf162725 		return (status);
24326629Szf162725 
24336629Szf162725 	mac_init_ops(&ural_dev_ops, "ural");
24346629Szf162725 	status = mod_install(&modlinkage);
24356629Szf162725 	if (status != 0) {
24366629Szf162725 		mac_fini_ops(&ural_dev_ops);
24376629Szf162725 		ddi_soft_state_fini(&ural_soft_state_p);
24386629Szf162725 	}
24396629Szf162725 	return (status);
24406629Szf162725 }
24416629Szf162725 
24426629Szf162725 int
24436629Szf162725 _fini(void)
24446629Szf162725 {
24456629Szf162725 	int status;
24466629Szf162725 
24476629Szf162725 	status = mod_remove(&modlinkage);
24486629Szf162725 	if (status == 0) {
24496629Szf162725 		mac_fini_ops(&ural_dev_ops);
24506629Szf162725 		ddi_soft_state_fini(&ural_soft_state_p);
24516629Szf162725 	}
24526629Szf162725 	return (status);
24536629Szf162725 }
2454