xref: /illumos-gate/usr/src/uts/common/io/uath/uath.c (revision d278f1c9)
156f9a274Sfei feng - Sun Microsystems - Beijing China /*
20dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
356f9a274Sfei feng - Sun Microsystems - Beijing China  * Use is subject to license terms.
456f9a274Sfei feng - Sun Microsystems - Beijing China  */
556f9a274Sfei feng - Sun Microsystems - Beijing China 
6d3351b34SJohn Levon /*
7d3351b34SJohn Levon  * Copyright 2019 Joyent, Inc.
8d3351b34SJohn Levon  */
9d3351b34SJohn Levon 
1056f9a274Sfei feng - Sun Microsystems - Beijing China /*
1156f9a274Sfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2006 Sam Leffler, Errno Consulting
1256f9a274Sfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
1356f9a274Sfei feng - Sun Microsystems - Beijing China  * All rights reserved.
1456f9a274Sfei feng - Sun Microsystems - Beijing China  *
1556f9a274Sfei feng - Sun Microsystems - Beijing China  * Redistribution and use in source and binary forms, with or without
1656f9a274Sfei feng - Sun Microsystems - Beijing China  * modification, are permitted provided that the following conditions
1756f9a274Sfei feng - Sun Microsystems - Beijing China  * are met:
1856f9a274Sfei feng - Sun Microsystems - Beijing China  * 1. Redistributions of source code must retain the above copyright
1956f9a274Sfei feng - Sun Microsystems - Beijing China  *    notice, this list of conditions and the following disclaimer,
2056f9a274Sfei feng - Sun Microsystems - Beijing China  *    without modification.
2156f9a274Sfei feng - Sun Microsystems - Beijing China  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
2256f9a274Sfei feng - Sun Microsystems - Beijing China  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
2356f9a274Sfei feng - Sun Microsystems - Beijing China  *    redistribution must be conditioned upon including a substantially
2456f9a274Sfei feng - Sun Microsystems - Beijing China  *    similar Disclaimer requirement for further binary redistribution.
2556f9a274Sfei feng - Sun Microsystems - Beijing China  *
2656f9a274Sfei feng - Sun Microsystems - Beijing China  * NO WARRANTY
2756f9a274Sfei feng - Sun Microsystems - Beijing China  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2856f9a274Sfei feng - Sun Microsystems - Beijing China  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2956f9a274Sfei feng - Sun Microsystems - Beijing China  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
3056f9a274Sfei feng - Sun Microsystems - Beijing China  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
3156f9a274Sfei feng - Sun Microsystems - Beijing China  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
3256f9a274Sfei feng - Sun Microsystems - Beijing China  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3356f9a274Sfei feng - Sun Microsystems - Beijing China  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3456f9a274Sfei feng - Sun Microsystems - Beijing China  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3556f9a274Sfei feng - Sun Microsystems - Beijing China  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3656f9a274Sfei feng - Sun Microsystems - Beijing China  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3756f9a274Sfei feng - Sun Microsystems - Beijing China  * THE POSSIBILITY OF SUCH DAMAGES.
3856f9a274Sfei feng - Sun Microsystems - Beijing China  */
3956f9a274Sfei feng - Sun Microsystems - Beijing China 
4056f9a274Sfei feng - Sun Microsystems - Beijing China /*
4156f9a274Sfei feng - Sun Microsystems - Beijing China  * This driver is distantly derived from a driver of the same name
4256f9a274Sfei feng - Sun Microsystems - Beijing China  * by Damien Bergamini.  The original copyright is included below:
4356f9a274Sfei feng - Sun Microsystems - Beijing China  *
4456f9a274Sfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2006
4556f9a274Sfei feng - Sun Microsystems - Beijing China  *	Damien Bergamini <damien.bergamini@free.fr>
4656f9a274Sfei feng - Sun Microsystems - Beijing China  *
4756f9a274Sfei feng - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and distribute this software for any
4856f9a274Sfei feng - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
4956f9a274Sfei feng - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
5056f9a274Sfei feng - Sun Microsystems - Beijing China  *
5156f9a274Sfei feng - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
5256f9a274Sfei feng - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
5356f9a274Sfei feng - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
5456f9a274Sfei feng - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
5556f9a274Sfei feng - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
5656f9a274Sfei feng - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
5756f9a274Sfei feng - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5856f9a274Sfei feng - Sun Microsystems - Beijing China  */
5956f9a274Sfei feng - Sun Microsystems - Beijing China 
6056f9a274Sfei feng - Sun Microsystems - Beijing China 
6156f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/types.h>
6256f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/cmn_err.h>
6356f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/strsubr.h>
6456f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/strsun.h>
6556f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/modctl.h>
6656f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/devops.h>
670dc2366fSVenugopal Iyer #include <sys/byteorder.h>
6856f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/mac_provider.h>
6956f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/mac_wifi.h>
7056f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/net80211.h>
7156f9a274Sfei feng - Sun Microsystems - Beijing China 
7256f9a274Sfei feng - Sun Microsystems - Beijing China #define	USBDRV_MAJOR_VER	2
7356f9a274Sfei feng - Sun Microsystems - Beijing China #define	USBDRV_MINOR_VER	0
7456f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/usb/usba.h>
7556f9a274Sfei feng - Sun Microsystems - Beijing China #include <sys/usb/usba/usba_types.h>
7656f9a274Sfei feng - Sun Microsystems - Beijing China 
7756f9a274Sfei feng - Sun Microsystems - Beijing China #include "uath_reg.h"
7856f9a274Sfei feng - Sun Microsystems - Beijing China #include "uath_var.h"
7956f9a274Sfei feng - Sun Microsystems - Beijing China 
8056f9a274Sfei feng - Sun Microsystems - Beijing China static void *uath_soft_state_p = NULL;
8156f9a274Sfei feng - Sun Microsystems - Beijing China 
8256f9a274Sfei feng - Sun Microsystems - Beijing China /*
8356f9a274Sfei feng - Sun Microsystems - Beijing China  * Bit flags in the ral_dbg_flags
8456f9a274Sfei feng - Sun Microsystems - Beijing China  */
8556f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_MSG		0x000001
8656f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_ERR		0x000002
8756f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_USB		0x000004
8856f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_TX		0x000008
8956f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_RX		0x000010
9056f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_FW		0x000020
9156f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_TX_CMD		0x000040
9256f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_RX_CMD		0x000080
9356f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DBG_ALL		0x000fff
9456f9a274Sfei feng - Sun Microsystems - Beijing China 
9556f9a274Sfei feng - Sun Microsystems - Beijing China uint32_t uath_dbg_flags = 0;
9656f9a274Sfei feng - Sun Microsystems - Beijing China 
9756f9a274Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
9856f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DEBUG \
9956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_debug
10056f9a274Sfei feng - Sun Microsystems - Beijing China #else
101d3351b34SJohn Levon #define	UATH_DEBUG(...) (void)(0)
10256f9a274Sfei feng - Sun Microsystems - Beijing China #endif
10356f9a274Sfei feng - Sun Microsystems - Beijing China 
10456f9a274Sfei feng - Sun Microsystems - Beijing China /*
10556f9a274Sfei feng - Sun Microsystems - Beijing China  * Various supported device vendors/products.
10656f9a274Sfei feng - Sun Microsystems - Beijing China  * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11b/g
10756f9a274Sfei feng - Sun Microsystems - Beijing China  */
10856f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_FLAG_PRE_FIRMWARE	(1 << 0)
10956f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_FLAG_ABG		(1 << 1)
11056f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_FLAG_ERR		(1 << 2)
11156f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DEV(v, p, f)						\
11256f9a274Sfei feng - Sun Microsystems - Beijing China 	{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) },		\
11356f9a274Sfei feng - Sun Microsystems - Beijing China 	{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p##_NF },		\
11456f9a274Sfei feng - Sun Microsystems - Beijing China 	    (f) | UATH_FLAG_PRE_FIRMWARE }
11556f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DEV_UG(v, p)	UATH_DEV(v, p, 0)
11656f9a274Sfei feng - Sun Microsystems - Beijing China #define	UATH_DEV_UX(v, p)	UATH_DEV(v, p, UATH_FLAG_ABG)
11756f9a274Sfei feng - Sun Microsystems - Beijing China 
11856f9a274Sfei feng - Sun Microsystems - Beijing China struct uath_devno {
11956f9a274Sfei feng - Sun Microsystems - Beijing China 	uint16_t vendor_id;
12056f9a274Sfei feng - Sun Microsystems - Beijing China 	uint16_t product_id;
12156f9a274Sfei feng - Sun Microsystems - Beijing China };
12256f9a274Sfei feng - Sun Microsystems - Beijing China 
12356f9a274Sfei feng - Sun Microsystems - Beijing China static const struct uath_type {
12456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_devno	dev;
12556f9a274Sfei feng - Sun Microsystems - Beijing China 	uint8_t			flags;
12656f9a274Sfei feng - Sun Microsystems - Beijing China } uath_devs[] = {
12756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(ACCTON,		SMCWUSBTG2),
12856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(ATHEROS,		AR5523),
12956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(ATHEROS2,		AR5523_1),
13056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(ATHEROS2,		AR5523_2),
13156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(ATHEROS2,		AR5523_3),
13256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(CONCEPTRONIC,	AR5523_1),
13356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(CONCEPTRONIC,	AR5523_2),
13456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(DLINK,		DWLAG122),
13556f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(DLINK,		DWLAG132),
13656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(DLINK,		DWLG132),
13756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(GIGASET,		AR5523),
13856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(GIGASET,		SMCWUSBTG),
13956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(GLOBALSUN,		AR5523_1),
14056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(GLOBALSUN,		AR5523_2),
14156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(IODATA,		USBWNG54US),
14256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(MELCO,		WLIU2KAMG54),
14356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(NETGEAR,		WG111U),
14456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(NETGEAR3,		WG111T),
14556f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(NETGEAR3,		WPN111),
14656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(PHILIPS,		SNU6500),
14756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(UMEDIA,		AR5523_2),
14856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(UMEDIA,		TEW444UBEU),
14956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(WISTRONNEWEB,	AR5523_1),
15056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UX(WISTRONNEWEB,	AR5523_2),
15156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEV_UG(ZCOM,		AR5523)
15256f9a274Sfei feng - Sun Microsystems - Beijing China };
15356f9a274Sfei feng - Sun Microsystems - Beijing China 
15456f9a274Sfei feng - Sun Microsystems - Beijing China static char uath_fwmod[] = "uathfw";
15556f9a274Sfei feng - Sun Microsystems - Beijing China static char uath_binmod[] = "uathbin";
15656f9a274Sfei feng - Sun Microsystems - Beijing China 
15756f9a274Sfei feng - Sun Microsystems - Beijing China /*
15856f9a274Sfei feng - Sun Microsystems - Beijing China  * Supported rates for 802.11b/g modes (in 500Kbps unit).
15956f9a274Sfei feng - Sun Microsystems - Beijing China  */
16056f9a274Sfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset uath_rateset_11b =
16156f9a274Sfei feng - Sun Microsystems - Beijing China 	{ 4, { 2, 4, 11, 22 } };
16256f9a274Sfei feng - Sun Microsystems - Beijing China 
16356f9a274Sfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset uath_rateset_11g =
16456f9a274Sfei feng - Sun Microsystems - Beijing China 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
16556f9a274Sfei feng - Sun Microsystems - Beijing China 
16656f9a274Sfei feng - Sun Microsystems - Beijing China /*
16756f9a274Sfei feng - Sun Microsystems - Beijing China  * device operations
16856f9a274Sfei feng - Sun Microsystems - Beijing China  */
16956f9a274Sfei feng - Sun Microsystems - Beijing China static int uath_attach(dev_info_t *, ddi_attach_cmd_t);
17056f9a274Sfei feng - Sun Microsystems - Beijing China static int uath_detach(dev_info_t *, ddi_detach_cmd_t);
17156f9a274Sfei feng - Sun Microsystems - Beijing China 
17256f9a274Sfei feng - Sun Microsystems - Beijing China /*
17356f9a274Sfei feng - Sun Microsystems - Beijing China  * Module Loading Data & Entry Points
17456f9a274Sfei feng - Sun Microsystems - Beijing China  */
17556f9a274Sfei feng - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(uath_dev_ops, nulldev, nulldev, uath_attach,
17656f9a274Sfei feng - Sun Microsystems - Beijing China     uath_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
17756f9a274Sfei feng - Sun Microsystems - Beijing China 
17856f9a274Sfei feng - Sun Microsystems - Beijing China static struct modldrv uath_modldrv = {
17956f9a274Sfei feng - Sun Microsystems - Beijing China 	&mod_driverops,		/* Type of module.  This one is a driver */
18056f9a274Sfei feng - Sun Microsystems - Beijing China 	"Atheros AR5523 USB Driver v1.1",	/* short description */
18156f9a274Sfei feng - Sun Microsystems - Beijing China 	&uath_dev_ops		/* driver specific ops */
18256f9a274Sfei feng - Sun Microsystems - Beijing China };
18356f9a274Sfei feng - Sun Microsystems - Beijing China 
18456f9a274Sfei feng - Sun Microsystems - Beijing China static struct modlinkage modlinkage = {
18556f9a274Sfei feng - Sun Microsystems - Beijing China 	MODREV_1,
18656f9a274Sfei feng - Sun Microsystems - Beijing China 	(void *)&uath_modldrv,
18756f9a274Sfei feng - Sun Microsystems - Beijing China 	NULL
18856f9a274Sfei feng - Sun Microsystems - Beijing China };
18956f9a274Sfei feng - Sun Microsystems - Beijing China 
19056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_stat(void *,  uint_t, uint64_t *);
19156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_start(void *);
19256f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_m_stop(void *);
19356f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_promisc(void *, boolean_t);
19456f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_multicst(void *, boolean_t, const uint8_t *);
19556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_unicst(void *, const uint8_t *);
19656f9a274Sfei feng - Sun Microsystems - Beijing China static mblk_t	*uath_m_tx(void *, mblk_t *);
19756f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_m_ioctl(void *, queue_t *, mblk_t *);
19856f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_setprop(void *, const char *, mac_prop_id_t,
19956f9a274Sfei feng - Sun Microsystems - Beijing China 		    uint_t, const void *);
20056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_m_getprop(void *, const char *, mac_prop_id_t,
2010dc2366fSVenugopal Iyer 		    uint_t, void *);
2020dc2366fSVenugopal Iyer static void	uath_m_propinfo(void *, const char *, mac_prop_id_t,
2030dc2366fSVenugopal Iyer 		    mac_prop_info_handle_t);
20456f9a274Sfei feng - Sun Microsystems - Beijing China 
20556f9a274Sfei feng - Sun Microsystems - Beijing China static mac_callbacks_t uath_m_callbacks = {
2060dc2366fSVenugopal Iyer 	MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
20756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_stat,
20856f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_start,
20956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_stop,
21056f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_promisc,
21156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_multicst,
21256f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_unicst,
21356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_tx,
2140dc2366fSVenugopal Iyer 	NULL,
21556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_ioctl,
21656f9a274Sfei feng - Sun Microsystems - Beijing China 	NULL,
21756f9a274Sfei feng - Sun Microsystems - Beijing China 	NULL,
21856f9a274Sfei feng - Sun Microsystems - Beijing China 	NULL,
21956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_m_setprop,
2200dc2366fSVenugopal Iyer 	uath_m_getprop,
2210dc2366fSVenugopal Iyer 	uath_m_propinfo
22256f9a274Sfei feng - Sun Microsystems - Beijing China };
22356f9a274Sfei feng - Sun Microsystems - Beijing China 
22456f9a274Sfei feng - Sun Microsystems - Beijing China static usb_alt_if_data_t *
22556f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_lookup_alt_if(usb_client_dev_data_t *,
22656f9a274Sfei feng - Sun Microsystems - Beijing China 		    uint_t, uint_t, uint_t);
22756f9a274Sfei feng - Sun Microsystems - Beijing China static usb_ep_data_t *
22856f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_lookup_ep_data(dev_info_t *,
22956f9a274Sfei feng - Sun Microsystems - Beijing China 		    usb_client_dev_data_t *, uint_t, uint_t, uint8_t, uint8_t);
23056f9a274Sfei feng - Sun Microsystems - Beijing China static const char *
23156f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_codename(int code);
23256f9a274Sfei feng - Sun Microsystems - Beijing China 
23356f9a274Sfei feng - Sun Microsystems - Beijing China static uint_t	uath_lookup(uint16_t, uint16_t);
23456f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_list_all_eps(usb_alt_if_data_t *);
23556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_open_pipes(struct uath_softc *);
23656f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_close_pipes(struct uath_softc *);
23756f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_fw_send(struct uath_softc *,
23856f9a274Sfei feng - Sun Microsystems - Beijing China 		    usb_pipe_handle_t, const void *, size_t);
23956f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_fw_ack(struct uath_softc *, int);
24056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_loadsym(ddi_modhandle_t, char *, char **, size_t *);
24156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_loadfirmware(struct uath_softc *);
24256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_alloc_cmd_list(struct uath_softc *,
24356f9a274Sfei feng - Sun Microsystems - Beijing China 		    struct uath_cmd *, int, int);
244*d278f1c9SToomas Soome static int	uath_init_cmd_list(struct uath_softc *);
24556f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_free_cmd_list(struct uath_cmd *, int);
24656f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_host_available(struct uath_softc *);
24756f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
24856f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_get_devcap(struct uath_softc *);
249*d278f1c9SToomas Soome static int	uath_get_devstatus(struct uath_softc *,
250*d278f1c9SToomas Soome 		    uint8_t [IEEE80211_ADDR_LEN]);
25156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_get_status(struct uath_softc *, uint32_t, void *, int);
25256f9a274Sfei feng - Sun Microsystems - Beijing China 
25356f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmd_lock_init(struct uath_cmd_lock *);
25456f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmd_lock_destroy(struct uath_cmd_lock *);
25556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_cmd_lock_wait(struct uath_cmd_lock *, clock_t);
25656f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmd_lock_signal(struct uath_cmd_lock *);
25756f9a274Sfei feng - Sun Microsystems - Beijing China 
25856f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_cmd_read(struct uath_softc *, uint32_t, const void *,
25956f9a274Sfei feng - Sun Microsystems - Beijing China 		    int, void *, int, int);
26056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_cmd_write(struct uath_softc *, uint32_t, const void *,
26156f9a274Sfei feng - Sun Microsystems - Beijing China 		    int, int);
26256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_cmdsend(struct uath_softc *, uint32_t,
26356f9a274Sfei feng - Sun Microsystems - Beijing China 		    const void *, int, void *, int, int);
26456f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_rx_cmd_xfer(struct uath_softc *);
26556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_tx_cmd_xfer(struct uath_softc *,
26656f9a274Sfei feng - Sun Microsystems - Beijing China 		    usb_pipe_handle_t, const void *, uint_t);
26756f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmd_txeof(usb_pipe_handle_t, struct usb_bulk_req *);
26856f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmd_rxeof(usb_pipe_handle_t, usb_bulk_req_t *);
26956f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_cmdeof(struct uath_softc *, struct uath_cmd *);
27056f9a274Sfei feng - Sun Microsystems - Beijing China 
27156f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_init_data_queue(struct uath_softc *);
27256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_rx_data_xfer(struct uath_softc *sc);
27356f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_tx_data_xfer(struct uath_softc *, mblk_t *);
27456f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_data_txeof(usb_pipe_handle_t, usb_bulk_req_t *);
27556f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_data_rxeof(usb_pipe_handle_t, usb_bulk_req_t *);
27656f9a274Sfei feng - Sun Microsystems - Beijing China 
27756f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_create_connection(struct uath_softc *, uint32_t);
27856f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_rates(struct uath_softc *,
27956f9a274Sfei feng - Sun Microsystems - Beijing China 		    const struct ieee80211_rateset *);
28056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_write_associd(struct uath_softc *);
28156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_ledsteady(struct uath_softc *, int, int);
28256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_ledblink(struct uath_softc *, int, int, int, int);
28356f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_update_rxstat(struct uath_softc *, uint32_t);
28456f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_send(ieee80211com_t *, mblk_t *, uint8_t);
28556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_reconnect(dev_info_t *);
28656f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_disconnect(dev_info_t *);
28756f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_newstate(struct ieee80211com *, enum ieee80211_state, int);
28856f9a274Sfei feng - Sun Microsystems - Beijing China 
28956f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_dataflush(struct uath_softc *);
29056f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_cmdflush(struct uath_softc *);
29156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_flush(struct uath_softc *);
29256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_ledstate(struct uath_softc *, int);
29356f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
29456f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_reset_tx_queues(struct uath_softc *);
29556f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_wme_init(struct uath_softc *);
29656f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_config_multi(struct uath_softc *,
29756f9a274Sfei feng - Sun Microsystems - Beijing China 		    uint32_t, const void *, int);
29856f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_config(struct uath_softc *, uint32_t, uint32_t);
29956f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_switch_channel(struct uath_softc *,
30056f9a274Sfei feng - Sun Microsystems - Beijing China 		    struct ieee80211_channel *);
30156f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
30256f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_init_locked(void *);
30356f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_stop_locked(void *);
30456f9a274Sfei feng - Sun Microsystems - Beijing China static int	uath_init(struct uath_softc *);
30556f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_stop(struct uath_softc *);
30656f9a274Sfei feng - Sun Microsystems - Beijing China static void	uath_resume(struct uath_softc *);
30756f9a274Sfei feng - Sun Microsystems - Beijing China 
30856f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_debug(uint32_t dbg_flags,const int8_t * fmt,...)30956f9a274Sfei feng - Sun Microsystems - Beijing China uath_debug(uint32_t dbg_flags, const int8_t *fmt, ...)
31056f9a274Sfei feng - Sun Microsystems - Beijing China {
31156f9a274Sfei feng - Sun Microsystems - Beijing China 	va_list args;
31256f9a274Sfei feng - Sun Microsystems - Beijing China 
31356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (dbg_flags & uath_dbg_flags) {
31456f9a274Sfei feng - Sun Microsystems - Beijing China 		va_start(args, fmt);
31556f9a274Sfei feng - Sun Microsystems - Beijing China 		vcmn_err(CE_CONT, fmt, args);
31656f9a274Sfei feng - Sun Microsystems - Beijing China 		va_end(args);
31756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
31856f9a274Sfei feng - Sun Microsystems - Beijing China }
31956f9a274Sfei feng - Sun Microsystems - Beijing China 
32056f9a274Sfei feng - Sun Microsystems - Beijing China static uint_t
uath_lookup(uint16_t vendor_id,uint16_t product_id)32156f9a274Sfei feng - Sun Microsystems - Beijing China uath_lookup(uint16_t vendor_id, uint16_t product_id)
32256f9a274Sfei feng - Sun Microsystems - Beijing China {
32356f9a274Sfei feng - Sun Microsystems - Beijing China 	int i, size;
32456f9a274Sfei feng - Sun Microsystems - Beijing China 
32556f9a274Sfei feng - Sun Microsystems - Beijing China 	size = sizeof (uath_devs) / sizeof (struct uath_type);
32656f9a274Sfei feng - Sun Microsystems - Beijing China 
32756f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < size; i++) {
32856f9a274Sfei feng - Sun Microsystems - Beijing China 		if ((vendor_id == uath_devs[i].dev.vendor_id) &&
32956f9a274Sfei feng - Sun Microsystems - Beijing China 		    (product_id == uath_devs[i].dev.product_id))
33056f9a274Sfei feng - Sun Microsystems - Beijing China 			return (uath_devs[i].flags);
33156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
33256f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_FLAG_ERR);
33356f9a274Sfei feng - Sun Microsystems - Beijing China }
33456f9a274Sfei feng - Sun Microsystems - Beijing China 
33556f9a274Sfei feng - Sun Microsystems - Beijing China /*
33656f9a274Sfei feng - Sun Microsystems - Beijing China  * Return a specific alt_if from the device descriptor tree.
33756f9a274Sfei feng - Sun Microsystems - Beijing China  */
33856f9a274Sfei feng - Sun Microsystems - Beijing China static usb_alt_if_data_t *
uath_lookup_alt_if(usb_client_dev_data_t * dev_data,uint_t config,uint_t interface,uint_t alt)33956f9a274Sfei feng - Sun Microsystems - Beijing China uath_lookup_alt_if(usb_client_dev_data_t *dev_data, uint_t config,
34056f9a274Sfei feng - Sun Microsystems - Beijing China     uint_t interface, uint_t alt)
34156f9a274Sfei feng - Sun Microsystems - Beijing China {
34256f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_cfg_data_t *cfg_data;
34356f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_if_data_t *if_data;
34456f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_alt_if_data_t *if_alt_data;
34556f9a274Sfei feng - Sun Microsystems - Beijing China 
34656f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
34756f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Assume everything is in the tree for now,
34856f9a274Sfei feng - Sun Microsystems - Beijing China 	 * (USB_PARSE_LVL_ALL)
34956f9a274Sfei feng - Sun Microsystems - Beijing China 	 * so we can directly index the array.
35056f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
35156f9a274Sfei feng - Sun Microsystems - Beijing China 
35256f9a274Sfei feng - Sun Microsystems - Beijing China 	/* Descend to configuration, configs are 1-based */
35356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (config < 1 || config > dev_data->dev_n_cfg)
35456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
35556f9a274Sfei feng - Sun Microsystems - Beijing China 	cfg_data = &dev_data->dev_cfg[config - 1];
35656f9a274Sfei feng - Sun Microsystems - Beijing China 
35756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* Descend to interface */
35856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (interface > cfg_data->cfg_n_if - 1)
35956f9a274Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
36056f9a274Sfei feng - Sun Microsystems - Beijing China 	if_data = &cfg_data->cfg_if[interface];
36156f9a274Sfei feng - Sun Microsystems - Beijing China 
36256f9a274Sfei feng - Sun Microsystems - Beijing China 	/* Descend to alt */
36356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (alt > if_data->if_n_alt - 1)
36456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
36556f9a274Sfei feng - Sun Microsystems - Beijing China 	if_alt_data = &if_data->if_alt[alt];
36656f9a274Sfei feng - Sun Microsystems - Beijing China 
36756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (if_alt_data);
36856f9a274Sfei feng - Sun Microsystems - Beijing China }
36956f9a274Sfei feng - Sun Microsystems - Beijing China 
37056f9a274Sfei feng - Sun Microsystems - Beijing China /*
37156f9a274Sfei feng - Sun Microsystems - Beijing China  * Print all endpoints of an alt_if.
37256f9a274Sfei feng - Sun Microsystems - Beijing China  */
37356f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_list_all_eps(usb_alt_if_data_t * ifalt)37456f9a274Sfei feng - Sun Microsystems - Beijing China uath_list_all_eps(usb_alt_if_data_t *ifalt)
37556f9a274Sfei feng - Sun Microsystems - Beijing China {
37656f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_ep_data_t *ep_data;
37756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_ep_descr_t *ep_descr;
37856f9a274Sfei feng - Sun Microsystems - Beijing China 	int i;
37956f9a274Sfei feng - Sun Microsystems - Beijing China 
38056f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < ifalt->altif_n_ep; i++) {
38156f9a274Sfei feng - Sun Microsystems - Beijing China 		ep_data = &ifalt->altif_ep[i];
38256f9a274Sfei feng - Sun Microsystems - Beijing China 		ep_descr = &ep_data->ep_descr;
38356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_USB,
38456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "uath: uath_list_all_endpoint: "
38556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "ep addresa[%x] is %x",
38656f9a274Sfei feng - Sun Microsystems - Beijing China 		    i, ep_descr->bEndpointAddress);
38756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
38856f9a274Sfei feng - Sun Microsystems - Beijing China }
38956f9a274Sfei feng - Sun Microsystems - Beijing China 
39056f9a274Sfei feng - Sun Microsystems - Beijing China static usb_ep_data_t *
uath_lookup_ep_data(dev_info_t * dip,usb_client_dev_data_t * dev_datap,uint_t interface,uint_t alternate,uint8_t address,uint8_t type)39156f9a274Sfei feng - Sun Microsystems - Beijing China uath_lookup_ep_data(dev_info_t *dip,
39256f9a274Sfei feng - Sun Microsystems - Beijing China     usb_client_dev_data_t *dev_datap,
39356f9a274Sfei feng - Sun Microsystems - Beijing China     uint_t interface,
39456f9a274Sfei feng - Sun Microsystems - Beijing China     uint_t alternate,
39556f9a274Sfei feng - Sun Microsystems - Beijing China     uint8_t address,
39656f9a274Sfei feng - Sun Microsystems - Beijing China     uint8_t type)
39756f9a274Sfei feng - Sun Microsystems - Beijing China {
39856f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_alt_if_data_t *altif_data;
39956f9a274Sfei feng - Sun Microsystems - Beijing China 	int i;
40056f9a274Sfei feng - Sun Microsystems - Beijing China 
40156f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((dip == NULL) || (dev_datap == NULL))
40256f9a274Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
40356f9a274Sfei feng - Sun Microsystems - Beijing China 
40456f9a274Sfei feng - Sun Microsystems - Beijing China 	altif_data = &dev_datap->dev_curr_cfg->
40556f9a274Sfei feng - Sun Microsystems - Beijing China 	    cfg_if[interface].if_alt[alternate];
40656f9a274Sfei feng - Sun Microsystems - Beijing China 
40756f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < altif_data->altif_n_ep; i++) {
40856f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_ep_descr_t *ept = &altif_data->altif_ep[i].ep_descr;
40956f9a274Sfei feng - Sun Microsystems - Beijing China 		uint8_t ept_type = ept->bmAttributes & USB_EP_ATTR_MASK;
41056f9a274Sfei feng - Sun Microsystems - Beijing China 		uint8_t ept_address = ept->bEndpointAddress;
41156f9a274Sfei feng - Sun Microsystems - Beijing China 
41256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ept->bLength == 0)
41356f9a274Sfei feng - Sun Microsystems - Beijing China 			continue;
41456f9a274Sfei feng - Sun Microsystems - Beijing China 		if ((ept_type == type) &&
41556f9a274Sfei feng - Sun Microsystems - Beijing China 		    ((type == USB_EP_ATTR_CONTROL) || (address == ept_address)))
41656f9a274Sfei feng - Sun Microsystems - Beijing China 			return (&altif_data->altif_ep[i]);
41756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
41856f9a274Sfei feng - Sun Microsystems - Beijing China 	return (NULL);
41956f9a274Sfei feng - Sun Microsystems - Beijing China }
42056f9a274Sfei feng - Sun Microsystems - Beijing China 
42156f9a274Sfei feng - Sun Microsystems - Beijing China /*
42256f9a274Sfei feng - Sun Microsystems - Beijing China  * Open communication pipes.
42356f9a274Sfei feng - Sun Microsystems - Beijing China  * The following pipes are used by the AR5523:
42456f9a274Sfei feng - Sun Microsystems - Beijing China  * ep0: 0x81 IN  Rx cmd
42556f9a274Sfei feng - Sun Microsystems - Beijing China  * ep1: 0x01 OUT Tx cmd
42656f9a274Sfei feng - Sun Microsystems - Beijing China  * ep2: 0x82 IN  Rx data
42756f9a274Sfei feng - Sun Microsystems - Beijing China  * ep3: 0x02 OUT Tx data
42856f9a274Sfei feng - Sun Microsystems - Beijing China  */
42956f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_open_pipes(struct uath_softc * sc)43056f9a274Sfei feng - Sun Microsystems - Beijing China uath_open_pipes(struct uath_softc *sc)
43156f9a274Sfei feng - Sun Microsystems - Beijing China {
43256f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_ep_data_t *ep_node;
43356f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_ep_descr_t *ep_descr;
43456f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_pipe_policy_t policy;
43556f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
43656f9a274Sfei feng - Sun Microsystems - Beijing China 
43756f9a274Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
43856f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_alt_if_data_t *altif_data;
43956f9a274Sfei feng - Sun Microsystems - Beijing China 
44056f9a274Sfei feng - Sun Microsystems - Beijing China 	altif_data = uath_lookup_alt_if(sc->sc_udev, UATH_CONFIG_NO,
44156f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_IFACE_INDEX, UATH_ALT_IF_INDEX);
44256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (altif_data == NULL) {
44356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "alt_if not found");
44456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (USB_FAILURE);
44556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
44656f9a274Sfei feng - Sun Microsystems - Beijing China 
44756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_list_all_eps(altif_data);
44856f9a274Sfei feng - Sun Microsystems - Beijing China #endif
44956f9a274Sfei feng - Sun Microsystems - Beijing China 
45056f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
45156f9a274Sfei feng - Sun Microsystems - Beijing China 	 * XXX pipes numbers are hardcoded because we don't have any way
45256f9a274Sfei feng - Sun Microsystems - Beijing China 	 * to distinguish the data pipes from the firmware command pipes
45356f9a274Sfei feng - Sun Microsystems - Beijing China 	 * (both are bulk pipes) using the endpoints descriptors.
45456f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
45556f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev,
45656f9a274Sfei feng - Sun Microsystems - Beijing China 	    0, 0, 0x81, USB_EP_ATTR_BULK);
45756f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_descr = &ep_node->ep_descr;
45856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_open_pipes(): "
45956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "find pipe %x\n", ep_descr->bEndpointAddress);
46056f9a274Sfei feng - Sun Microsystems - Beijing China 
46156f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&policy, sizeof (usb_pipe_policy_t));
46256f9a274Sfei feng - Sun Microsystems - Beijing China 	policy.pp_max_async_reqs = UATH_CMD_LIST_COUNT;
46356f9a274Sfei feng - Sun Microsystems - Beijing China 
46456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr,
46556f9a274Sfei feng - Sun Microsystems - Beijing China 	    &policy, USB_FLAGS_SLEEP, &sc->rx_cmd_pipe);
46656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
46756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
46856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to open rx data pipe, err = %x\n",
46956f9a274Sfei feng - Sun Microsystems - Beijing China 		    err);
47056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
47156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
47256f9a274Sfei feng - Sun Microsystems - Beijing China 
47356f9a274Sfei feng - Sun Microsystems - Beijing China 
47456f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev,
47556f9a274Sfei feng - Sun Microsystems - Beijing China 	    0, 0, 0x01, USB_EP_ATTR_BULK);
47656f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_descr = &ep_node->ep_descr;
47756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
47856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "find pipe %x\n",
47956f9a274Sfei feng - Sun Microsystems - Beijing China 	    ep_descr->bEndpointAddress);
48056f9a274Sfei feng - Sun Microsystems - Beijing China 
48156f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&policy, sizeof (usb_pipe_policy_t));
48256f9a274Sfei feng - Sun Microsystems - Beijing China 	policy.pp_max_async_reqs = UATH_CMD_LIST_COUNT;
48356f9a274Sfei feng - Sun Microsystems - Beijing China 
48456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr,
48556f9a274Sfei feng - Sun Microsystems - Beijing China 	    &policy, USB_FLAGS_SLEEP, &sc->tx_cmd_pipe);
48656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
48756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
48856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to open tx command pipe, err = %x\n",
48956f9a274Sfei feng - Sun Microsystems - Beijing China 		    err);
49056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
49156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
49256f9a274Sfei feng - Sun Microsystems - Beijing China 
49356f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev,
49456f9a274Sfei feng - Sun Microsystems - Beijing China 	    0, 0, 0x82, USB_EP_ATTR_BULK);
49556f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_descr = &ep_node->ep_descr;
49656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
49756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "find pipe %x\n",
49856f9a274Sfei feng - Sun Microsystems - Beijing China 	    ep_descr->bEndpointAddress);
49956f9a274Sfei feng - Sun Microsystems - Beijing China 
50056f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&policy, sizeof (usb_pipe_policy_t));
50156f9a274Sfei feng - Sun Microsystems - Beijing China 	policy.pp_max_async_reqs = UATH_RX_DATA_LIST_COUNT;
50256f9a274Sfei feng - Sun Microsystems - Beijing China 
50356f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr,
50456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &policy, USB_FLAGS_SLEEP, &sc->rx_data_pipe);
50556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
50656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
50756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to open tx pipe, err = %x\n",
50856f9a274Sfei feng - Sun Microsystems - Beijing China 		    err);
50956f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
51056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
51156f9a274Sfei feng - Sun Microsystems - Beijing China 
51256f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev,
51356f9a274Sfei feng - Sun Microsystems - Beijing China 	    0, 0, 0x02, USB_EP_ATTR_BULK);
51456f9a274Sfei feng - Sun Microsystems - Beijing China 	ep_descr = &ep_node->ep_descr;
51556f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
51656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "find pipe %x\n",
51756f9a274Sfei feng - Sun Microsystems - Beijing China 	    ep_descr->bEndpointAddress);
51856f9a274Sfei feng - Sun Microsystems - Beijing China 
51956f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&policy, sizeof (usb_pipe_policy_t));
52056f9a274Sfei feng - Sun Microsystems - Beijing China 	policy.pp_max_async_reqs = UATH_TX_DATA_LIST_COUNT;
52156f9a274Sfei feng - Sun Microsystems - Beijing China 
52256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr,
52356f9a274Sfei feng - Sun Microsystems - Beijing China 	    &policy, USB_FLAGS_SLEEP, &sc->tx_data_pipe);
52456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
52556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): "
52656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to open rx command pipe, err = %x\n",
52756f9a274Sfei feng - Sun Microsystems - Beijing China 		    err);
52856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
52956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
53056f9a274Sfei feng - Sun Microsystems - Beijing China 
53156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
53256f9a274Sfei feng - Sun Microsystems - Beijing China fail:
53356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_close_pipes(sc);
53456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
53556f9a274Sfei feng - Sun Microsystems - Beijing China }
53656f9a274Sfei feng - Sun Microsystems - Beijing China 
53756f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_close_pipes(struct uath_softc * sc)53856f9a274Sfei feng - Sun Microsystems - Beijing China uath_close_pipes(struct uath_softc *sc)
53956f9a274Sfei feng - Sun Microsystems - Beijing China {
54056f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_flags_t flags = USB_FLAGS_SLEEP;
54156f9a274Sfei feng - Sun Microsystems - Beijing China 
54256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->rx_cmd_pipe != NULL) {
54356f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_reset(sc->sc_dev, sc->rx_cmd_pipe, flags, NULL, 0);
54456f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_close(sc->sc_dev, sc->rx_cmd_pipe, flags, NULL, 0);
54556f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->rx_cmd_pipe = NULL;
54656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
54756f9a274Sfei feng - Sun Microsystems - Beijing China 
54856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->tx_cmd_pipe != NULL) {
54956f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_reset(sc->sc_dev, sc->tx_cmd_pipe, flags, NULL, 0);
55056f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_close(sc->sc_dev, sc->tx_cmd_pipe, flags, NULL, 0);
55156f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->tx_cmd_pipe = NULL;
55256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
55356f9a274Sfei feng - Sun Microsystems - Beijing China 
55456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->rx_data_pipe != NULL) {
55556f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_reset(sc->sc_dev, sc->rx_data_pipe, flags, NULL, 0);
55656f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_close(sc->sc_dev, sc->rx_data_pipe, flags, NULL, 0);
55756f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->rx_data_pipe = NULL;
55856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
55956f9a274Sfei feng - Sun Microsystems - Beijing China 
56056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->tx_data_pipe != NULL) {
56156f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_reset(sc->sc_dev, sc->tx_data_pipe, flags, NULL, 0);
56256f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_pipe_close(sc->sc_dev, sc->tx_data_pipe, flags, NULL, 0);
56356f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->tx_data_pipe = NULL;
56456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
56556f9a274Sfei feng - Sun Microsystems - Beijing China 
56656f9a274Sfei feng - Sun Microsystems - Beijing China }
56756f9a274Sfei feng - Sun Microsystems - Beijing China 
56856f9a274Sfei feng - Sun Microsystems - Beijing China static const char *
uath_codename(int code)56956f9a274Sfei feng - Sun Microsystems - Beijing China uath_codename(int code)
57056f9a274Sfei feng - Sun Microsystems - Beijing China {
57156f9a274Sfei feng - Sun Microsystems - Beijing China #define	N(a)	(sizeof (a)/sizeof (a[0]))
57256f9a274Sfei feng - Sun Microsystems - Beijing China 	static const char *names[] = {
57356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "0x00",
57456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "HOST_AVAILABLE",
57556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "BIND",
57656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_RESET",
57756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_GET_CAPABILITY",
57856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_SET_CONFIG",
57956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_GET_STATUS",
58056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_GET_STATS",
58156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_START",
58256f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_STOP",
58356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_ENABLE",
58456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "TARGET_DISABLE",
58556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "CREATE_CONNECTION",
58656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "UPDATE_CONNECT_ATTR",
58756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "DELETE_CONNECT",
58856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SEND",
58956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "FLUSH",
59056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "STATS_UPDATE",
59156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "BMISS",
59256f9a274Sfei feng - Sun Microsystems - Beijing China 	    "DEVICE_AVAIL",
59356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SEND_COMPLETE",
59456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "DATA_AVAIL",
59556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_PWR_MODE",
59656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "BMISS_ACK",
59756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_LED_STEADY",
59856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_LED_BLINK",
59956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SETUP_BEACON_DESC",
60056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "BEACON_INIT",
60156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RESET_KEY_CACHE",
60256f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RESET_KEY_CACHE_ENTRY",
60356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_KEY_CACHE_ENTRY",
60456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_DECOMP_MASK",
60556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_REGULATORY_DOMAIN",
60656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_LED_STATE",
60756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "WRITE_ASSOCID",
60856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_STA_BEACON_TIMERS",
60956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "GET_TSF",
61056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RESET_TSF",
61156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_ADHOC_MODE",
61256f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_BASIC_RATE",
61356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "MIB_CONTROL",
61456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "GET_CHANNEL_DATA",
61556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "GET_CUR_RSSI",
61656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_ANTENNA_SWITCH",
61756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "0x2c", "0x2d", "0x2e",
61856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "USE_SHORT_SLOT_TIME",
61956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_POWER_MODE",
62056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SETUP_PSPOLL_DESC",
62156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_RX_MULTICAST_FILTER",
62256f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RX_FILTER",
62356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "PER_CALIBRATION",
62456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RESET",
62556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "DISABLE",
62656f9a274Sfei feng - Sun Microsystems - Beijing China 	    "PHY_DISABLE",
62756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_TX_POWER_LIMIT",
62856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SET_TX_QUEUE_PARAMS",
62956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "SETUP_TX_QUEUE",
63056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "RELEASE_TX_QUEUE",
63156f9a274Sfei feng - Sun Microsystems - Beijing China 	};
63256f9a274Sfei feng - Sun Microsystems - Beijing China 	static char buf[8];
63356f9a274Sfei feng - Sun Microsystems - Beijing China 
63456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (code < N(names))
63556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (names[code]);
63656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (code == WDCMSG_SET_DEFAULT_KEY)
63756f9a274Sfei feng - Sun Microsystems - Beijing China 		return ("SET_DEFAULT_KEY");
63856f9a274Sfei feng - Sun Microsystems - Beijing China 
63956f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) snprintf(buf, sizeof (buf), "0x%02x", code);
64056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (buf);
64156f9a274Sfei feng - Sun Microsystems - Beijing China #undef N
64256f9a274Sfei feng - Sun Microsystems - Beijing China }
64356f9a274Sfei feng - Sun Microsystems - Beijing China 
64456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_fw_send(struct uath_softc * sc,usb_pipe_handle_t pipe,const void * data,size_t len)64556f9a274Sfei feng - Sun Microsystems - Beijing China uath_fw_send(struct uath_softc *sc, usb_pipe_handle_t pipe,
64656f9a274Sfei feng - Sun Microsystems - Beijing China     const void *data, size_t len)
64756f9a274Sfei feng - Sun Microsystems - Beijing China {
64856f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *send_req;
64956f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *mblk;
65056f9a274Sfei feng - Sun Microsystems - Beijing China 	int res;
65156f9a274Sfei feng - Sun Microsystems - Beijing China 
65256f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP);
65356f9a274Sfei feng - Sun Microsystems - Beijing China 
65456f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_len = (int)len;
65556f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
65656f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_timeout = UATH_CMD_TIMEOUT;
65756f9a274Sfei feng - Sun Microsystems - Beijing China 
65856f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk = send_req->bulk_data;
65956f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(data, mblk->b_wptr, len);
66056f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk->b_wptr += len;
66156f9a274Sfei feng - Sun Microsystems - Beijing China 
66256f9a274Sfei feng - Sun Microsystems - Beijing China 	res = usb_pipe_bulk_xfer(pipe, send_req, USB_FLAGS_SLEEP);
66356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
66456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_send(): "
66556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "Error %x writing data to bulk/out pipe", res);
66656f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
66756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
66856f9a274Sfei feng - Sun Microsystems - Beijing China 
66956f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(send_req);
67056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
67156f9a274Sfei feng - Sun Microsystems - Beijing China }
67256f9a274Sfei feng - Sun Microsystems - Beijing China 
67356f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_fw_ack(struct uath_softc * sc,int len)67456f9a274Sfei feng - Sun Microsystems - Beijing China uath_fw_ack(struct uath_softc *sc, int len)
67556f9a274Sfei feng - Sun Microsystems - Beijing China {
67656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_fwblock *rxblock;
67756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *req;
67856f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *mp;
67956f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
68056f9a274Sfei feng - Sun Microsystems - Beijing China 
68156f9a274Sfei feng - Sun Microsystems - Beijing China 	req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP);
68256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req == NULL) {
68356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_FW,
68456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "uath: uath_fw_ack(): "
68556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "uath_rx_transfer(): failed to allocate req");
68656f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
68756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
68856f9a274Sfei feng - Sun Microsystems - Beijing China 
68956f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_len			= len;
69056f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_client_private	= (usb_opaque_t)sc;
69156f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_timeout		= 0;
69256f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_attributes		= USB_ATTRS_SHORT_XFER_OK
69356f9a274Sfei feng - Sun Microsystems - Beijing China 	    | USB_ATTRS_AUTOCLEARING;
69456f9a274Sfei feng - Sun Microsystems - Beijing China 
69556f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_bulk_xfer(sc->rx_cmd_pipe, req, USB_FLAGS_SLEEP);
69656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
69756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_ack(): "
69856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to do rx xfer, %d", err);
69956f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_free_bulk_req(req);
70056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
70156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
70256f9a274Sfei feng - Sun Microsystems - Beijing China 
70356f9a274Sfei feng - Sun Microsystems - Beijing China 	mp = req->bulk_data;
70456f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_data = NULL;
70556f9a274Sfei feng - Sun Microsystems - Beijing China 
70656f9a274Sfei feng - Sun Microsystems - Beijing China 	rxblock = (struct uath_fwblock *)mp->b_rptr;
70756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_ack() "
70856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "rxblock flags=0x%x total=%d\n",
70956f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(rxblock->flags), BE_32(rxblock->rxtotal));
71056f9a274Sfei feng - Sun Microsystems - Beijing China 
71156f9a274Sfei feng - Sun Microsystems - Beijing China 	freemsg(mp);
71256f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
71356f9a274Sfei feng - Sun Microsystems - Beijing China 
71456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
71556f9a274Sfei feng - Sun Microsystems - Beijing China }
71656f9a274Sfei feng - Sun Microsystems - Beijing China 
71756f9a274Sfei feng - Sun Microsystems - Beijing China /*
71856f9a274Sfei feng - Sun Microsystems - Beijing China  * find uath firmware module's "_start" "_end" symbols
71956f9a274Sfei feng - Sun Microsystems - Beijing China  * and get its size.
72056f9a274Sfei feng - Sun Microsystems - Beijing China  */
72156f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_loadsym(ddi_modhandle_t modp,char * sym,char ** start,size_t * len)72256f9a274Sfei feng - Sun Microsystems - Beijing China uath_loadsym(ddi_modhandle_t modp, char *sym, char **start, size_t *len)
72356f9a274Sfei feng - Sun Microsystems - Beijing China {
72456f9a274Sfei feng - Sun Microsystems - Beijing China 	char start_sym[64];
72556f9a274Sfei feng - Sun Microsystems - Beijing China 	char end_sym[64];
72656f9a274Sfei feng - Sun Microsystems - Beijing China 	char *p, *end;
72756f9a274Sfei feng - Sun Microsystems - Beijing China 	int rv;
72856f9a274Sfei feng - Sun Microsystems - Beijing China 	size_t n;
72956f9a274Sfei feng - Sun Microsystems - Beijing China 
73056f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) snprintf(start_sym, sizeof (start_sym), "%s_start", sym);
73156f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) snprintf(end_sym, sizeof (end_sym), "%s_end", sym);
73256f9a274Sfei feng - Sun Microsystems - Beijing China 
73356f9a274Sfei feng - Sun Microsystems - Beijing China 	p = (char *)ddi_modsym(modp, start_sym, &rv);
73456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (p == NULL || rv != 0) {
73556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_loadsym(): "
73656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "mod %s: symbol %s not found\n", uath_fwmod, start_sym);
73756f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
73856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
73956f9a274Sfei feng - Sun Microsystems - Beijing China 
74056f9a274Sfei feng - Sun Microsystems - Beijing China 	end = (char *)ddi_modsym(modp, end_sym, &rv);
74156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (end == NULL || rv != 0) {
74256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_loadsym(): "
74356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "mod %s: symbol %s not found\n", uath_fwmod, end_sym);
74456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
74556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
74656f9a274Sfei feng - Sun Microsystems - Beijing China 
74756f9a274Sfei feng - Sun Microsystems - Beijing China 	n = _PTRDIFF(end, p);
74856f9a274Sfei feng - Sun Microsystems - Beijing China 	*start = p;
74956f9a274Sfei feng - Sun Microsystems - Beijing China 	*len = n;
75056f9a274Sfei feng - Sun Microsystems - Beijing China 
75156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
75256f9a274Sfei feng - Sun Microsystems - Beijing China }
75356f9a274Sfei feng - Sun Microsystems - Beijing China 
75456f9a274Sfei feng - Sun Microsystems - Beijing China /*
75556f9a274Sfei feng - Sun Microsystems - Beijing China  * Load the MIPS R4000 microcode into the device.  Once the image is loaded,
75656f9a274Sfei feng - Sun Microsystems - Beijing China  * the device will detach itself from the bus and reattach later with a new
75756f9a274Sfei feng - Sun Microsystems - Beijing China  * product Id (a la ezusb).  XXX this could also be implemented in userland
75856f9a274Sfei feng - Sun Microsystems - Beijing China  * through /dev/ugen.
75956f9a274Sfei feng - Sun Microsystems - Beijing China  */
76056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_loadfirmware(struct uath_softc * sc)76156f9a274Sfei feng - Sun Microsystems - Beijing China uath_loadfirmware(struct uath_softc *sc)
76256f9a274Sfei feng - Sun Microsystems - Beijing China {
76356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_fwblock txblock;
76456f9a274Sfei feng - Sun Microsystems - Beijing China 	ddi_modhandle_t modp;
76556f9a274Sfei feng - Sun Microsystems - Beijing China 	char *fw_index, *fw_image = NULL;
76656f9a274Sfei feng - Sun Microsystems - Beijing China 	size_t fw_size, len;
76756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err = DDI_SUCCESS, rv = 0;
76856f9a274Sfei feng - Sun Microsystems - Beijing China 
76956f9a274Sfei feng - Sun Microsystems - Beijing China 	modp = ddi_modopen(uath_fwmod, KRTLD_MODE_FIRST, &rv);
77056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (modp == NULL) {
77156f9a274Sfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "uath: uath_loadfirmware(): "
77256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "module %s not found\n", uath_fwmod);
77356f9a274Sfei feng - Sun Microsystems - Beijing China 		goto label;
77456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
77556f9a274Sfei feng - Sun Microsystems - Beijing China 
77656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_loadsym(modp, uath_binmod, &fw_index, &fw_size);
77756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
77856f9a274Sfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "uath: uath_loadfirmware(): "
77956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not get firmware\n");
78056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto label;
78156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
78256f9a274Sfei feng - Sun Microsystems - Beijing China 
78356f9a274Sfei feng - Sun Microsystems - Beijing China 	fw_image = (char *)kmem_alloc(fw_size, KM_SLEEP);
78456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (fw_image == NULL) {
78556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_loadfirmware(): "
78656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc firmware memory\n");
78756f9a274Sfei feng - Sun Microsystems - Beijing China 		err = UATH_FAILURE;
78856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto label;
78956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
79056f9a274Sfei feng - Sun Microsystems - Beijing China 
79156f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) memcpy(fw_image, fw_index, fw_size);
79256f9a274Sfei feng - Sun Microsystems - Beijing China 	fw_index = fw_image;
79356f9a274Sfei feng - Sun Microsystems - Beijing China 	len = fw_size;
79456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "loading firmware size = %lu\n", fw_size);
79556f9a274Sfei feng - Sun Microsystems - Beijing China 
79656f9a274Sfei feng - Sun Microsystems - Beijing China 	/* bzero(txblock, sizeof (struct uath_fwblock)); */
79756f9a274Sfei feng - Sun Microsystems - Beijing China 	txblock.flags = BE_32(UATH_WRITE_BLOCK);
79856f9a274Sfei feng - Sun Microsystems - Beijing China 	txblock.total = BE_32(fw_size);
79956f9a274Sfei feng - Sun Microsystems - Beijing China 
80056f9a274Sfei feng - Sun Microsystems - Beijing China 	while (len > 0) {
80156f9a274Sfei feng - Sun Microsystems - Beijing China 		size_t mlen = min(len, UATH_MAX_FWBLOCK_SIZE);
80256f9a274Sfei feng - Sun Microsystems - Beijing China 
80356f9a274Sfei feng - Sun Microsystems - Beijing China 		txblock.remain = BE_32(len - mlen);
80456f9a274Sfei feng - Sun Microsystems - Beijing China 		txblock.len = BE_32(mlen);
80556f9a274Sfei feng - Sun Microsystems - Beijing China 
80656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): "
80756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "sending firmware block: %d bytes sending\n", mlen);
80856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): "
80956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "sending firmware block: %d bytes remaining\n",
81056f9a274Sfei feng - Sun Microsystems - Beijing China 		    len - mlen);
81156f9a274Sfei feng - Sun Microsystems - Beijing China 
81256f9a274Sfei feng - Sun Microsystems - Beijing China 		/* send firmware block meta-data */
81356f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_fw_send(sc, sc->tx_cmd_pipe, &txblock,
81456f9a274Sfei feng - Sun Microsystems - Beijing China 		    sizeof (struct uath_fwblock));
81556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
81656f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): "
81756f9a274Sfei feng - Sun Microsystems - Beijing China 			    "send block meta-data error");
81856f9a274Sfei feng - Sun Microsystems - Beijing China 			goto label;
81956f9a274Sfei feng - Sun Microsystems - Beijing China 		}
82056f9a274Sfei feng - Sun Microsystems - Beijing China 
82156f9a274Sfei feng - Sun Microsystems - Beijing China 		/* send firmware block data */
82256f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_fw_send(sc, sc->tx_data_pipe, fw_index, mlen);
82356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
82456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware() "
82556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "send block data err");
82656f9a274Sfei feng - Sun Microsystems - Beijing China 			goto label;
82756f9a274Sfei feng - Sun Microsystems - Beijing China 		}
82856f9a274Sfei feng - Sun Microsystems - Beijing China 
82956f9a274Sfei feng - Sun Microsystems - Beijing China 		/* wait for ack from firmware */
83056f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_fw_ack(sc, sizeof (struct uath_fwblock));
83156f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
83256f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware() "
83356f9a274Sfei feng - Sun Microsystems - Beijing China 			    "rx block ack err");
83456f9a274Sfei feng - Sun Microsystems - Beijing China 			goto label;
83556f9a274Sfei feng - Sun Microsystems - Beijing China 		}
83656f9a274Sfei feng - Sun Microsystems - Beijing China 
83756f9a274Sfei feng - Sun Microsystems - Beijing China 		fw_index += mlen;
83856f9a274Sfei feng - Sun Microsystems - Beijing China 		len -= mlen;
83956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
84056f9a274Sfei feng - Sun Microsystems - Beijing China 
84156f9a274Sfei feng - Sun Microsystems - Beijing China label:
84256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (fw_image != NULL)
84356f9a274Sfei feng - Sun Microsystems - Beijing China 		kmem_free(fw_image, fw_size);
84456f9a274Sfei feng - Sun Microsystems - Beijing China 	fw_image = fw_index = NULL;
84556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (modp != NULL)
84656f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_modclose(modp);
84756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
84856f9a274Sfei feng - Sun Microsystems - Beijing China }
84956f9a274Sfei feng - Sun Microsystems - Beijing China 
85056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_alloc_cmd_list(struct uath_softc * sc,struct uath_cmd cmds[],int ncmd,int maxsz)85156f9a274Sfei feng - Sun Microsystems - Beijing China uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
85256f9a274Sfei feng - Sun Microsystems - Beijing China     int ncmd, int maxsz)
85356f9a274Sfei feng - Sun Microsystems - Beijing China {
85456f9a274Sfei feng - Sun Microsystems - Beijing China 	int i, err;
85556f9a274Sfei feng - Sun Microsystems - Beijing China 
85656f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < ncmd; i++) {
85756f9a274Sfei feng - Sun Microsystems - Beijing China 		struct uath_cmd *cmd = &cmds[i];
85856f9a274Sfei feng - Sun Microsystems - Beijing China 
85956f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd->sc = sc;	/* backpointer for callbacks */
86056f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd->msgid = i;
86156f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd->buf = kmem_zalloc(maxsz, KM_NOSLEEP);
86256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (cmd->buf == NULL) {
86356f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_alloc_cmd_list(): "
86456f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not allocate xfer buffer\n");
86556f9a274Sfei feng - Sun Microsystems - Beijing China 			err = DDI_ENOMEM;
86656f9a274Sfei feng - Sun Microsystems - Beijing China 			goto fail;
86756f9a274Sfei feng - Sun Microsystems - Beijing China 		}
86856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
86956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
87056f9a274Sfei feng - Sun Microsystems - Beijing China 
87156f9a274Sfei feng - Sun Microsystems - Beijing China fail:
87256f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_free_cmd_list(cmds, ncmd);
87356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
87456f9a274Sfei feng - Sun Microsystems - Beijing China }
87556f9a274Sfei feng - Sun Microsystems - Beijing China 
87656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_init_cmd_list(struct uath_softc * sc)87756f9a274Sfei feng - Sun Microsystems - Beijing China uath_init_cmd_list(struct uath_softc *sc)
87856f9a274Sfei feng - Sun Microsystems - Beijing China {
87956f9a274Sfei feng - Sun Microsystems - Beijing China 	int i;
88056f9a274Sfei feng - Sun Microsystems - Beijing China 
88156f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_cmdid = sc->rx_cmd_queued = sc->tx_cmd_queued = 0;
88256f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < UATH_CMD_LIST_COUNT; i++) {
88356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_rx_cmd_xfer(sc) != UATH_SUCCESS) {
88456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_cmd_list(): "
88556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "failed to init cmd list %x\n", i);
88656f9a274Sfei feng - Sun Microsystems - Beijing China 			return (UATH_FAILURE);
88756f9a274Sfei feng - Sun Microsystems - Beijing China 		}
88856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
88956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
89056f9a274Sfei feng - Sun Microsystems - Beijing China }
89156f9a274Sfei feng - Sun Microsystems - Beijing China 
89256f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_free_cmd_list(struct uath_cmd cmds[],int ncmd)89356f9a274Sfei feng - Sun Microsystems - Beijing China uath_free_cmd_list(struct uath_cmd cmds[], int ncmd)
89456f9a274Sfei feng - Sun Microsystems - Beijing China {
89556f9a274Sfei feng - Sun Microsystems - Beijing China 	int i;
89656f9a274Sfei feng - Sun Microsystems - Beijing China 
89756f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < ncmd; i++)
89856f9a274Sfei feng - Sun Microsystems - Beijing China 		if (cmds[i].buf != NULL) {
89956f9a274Sfei feng - Sun Microsystems - Beijing China 			kmem_free(cmds[i].buf, UATH_MAX_CMDSZ);
90056f9a274Sfei feng - Sun Microsystems - Beijing China 			cmds[i].buf = NULL;
90156f9a274Sfei feng - Sun Microsystems - Beijing China 		}
90256f9a274Sfei feng - Sun Microsystems - Beijing China }
90356f9a274Sfei feng - Sun Microsystems - Beijing China 
90456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_host_available(struct uath_softc * sc)90556f9a274Sfei feng - Sun Microsystems - Beijing China uath_host_available(struct uath_softc *sc)
90656f9a274Sfei feng - Sun Microsystems - Beijing China {
90756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_host_available setup;
90856f9a274Sfei feng - Sun Microsystems - Beijing China 
90956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* inform target the host is available */
91056f9a274Sfei feng - Sun Microsystems - Beijing China 	setup.sw_ver_major = BE_32(ATH_SW_VER_MAJOR);
91156f9a274Sfei feng - Sun Microsystems - Beijing China 	setup.sw_ver_minor = BE_32(ATH_SW_VER_MINOR);
91256f9a274Sfei feng - Sun Microsystems - Beijing China 	setup.sw_ver_patch = BE_32(ATH_SW_VER_PATCH);
91356f9a274Sfei feng - Sun Microsystems - Beijing China 	setup.sw_ver_build = BE_32(ATH_SW_VER_BUILD);
91456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE,
91556f9a274Sfei feng - Sun Microsystems - Beijing China 	    &setup, sizeof (setup), NULL, 0, 0));
91656f9a274Sfei feng - Sun Microsystems - Beijing China }
91756f9a274Sfei feng - Sun Microsystems - Beijing China 
91856f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_get_capability(struct uath_softc * sc,uint32_t cap,uint32_t * val)91956f9a274Sfei feng - Sun Microsystems - Beijing China uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val)
92056f9a274Sfei feng - Sun Microsystems - Beijing China {
92156f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
92256f9a274Sfei feng - Sun Microsystems - Beijing China 
92356f9a274Sfei feng - Sun Microsystems - Beijing China 	cap = BE_32(cap);
92456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY, &cap,
92556f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (cap), val, sizeof (uint32_t), UATH_CMD_FLAG_MAGIC);
92656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err == UATH_SUCCESS)
92756f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = BE_32(*val);
92856f9a274Sfei feng - Sun Microsystems - Beijing China 	else
92956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_capability(): "
93056f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not read capability %u\n", BE_32(cap));
93156f9a274Sfei feng - Sun Microsystems - Beijing China }
93256f9a274Sfei feng - Sun Microsystems - Beijing China 
93356f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_get_devcap(struct uath_softc * sc)93456f9a274Sfei feng - Sun Microsystems - Beijing China uath_get_devcap(struct uath_softc *sc)
93556f9a274Sfei feng - Sun Microsystems - Beijing China {
93656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_devcap *cap = &sc->sc_devcap;
93756f9a274Sfei feng - Sun Microsystems - Beijing China 
93856f9a274Sfei feng - Sun Microsystems - Beijing China 	/* collect device capabilities */
93956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TARGET_VERSION,
94056f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->targetVersion);
94156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TARGET_REVISION,
94256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->targetRevision);
94356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_MAC_VERSION,
94456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->macVersion);
94556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_MAC_REVISION,
94656f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->macRevision);
94756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_PHY_REVISION,
94856f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->phyRevision);
94956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_ANALOG_5GHz_REVISION,
95056f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->analog5GhzRevision);
95156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_ANALOG_2GHz_REVISION,
95256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->analog2GhzRevision);
95356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_REG_DOMAIN,
95456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->regDomain);
95556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_REG_CAP_BITS,
95656f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->regCapBits);
95756f9a274Sfei feng - Sun Microsystems - Beijing China 
95856f9a274Sfei feng - Sun Microsystems - Beijing China 	/* NB: not supported in rev 1.5 */
95956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* uath_get_capability(sc, CAP_COUNTRY_CODE, cap->countryCode); */
96056f9a274Sfei feng - Sun Microsystems - Beijing China 
96156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_WIRELESS_MODES,
96256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->wirelessModes);
96356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_CHAN_SPREAD_SUPPORT,
96456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->chanSpreadSupport);
96556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_COMPRESS_SUPPORT,
96656f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->compressSupport);
96756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_BURST_SUPPORT,
96856f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->burstSupport);
96956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_FAST_FRAMES_SUPPORT,
97056f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->fastFramesSupport);
97156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_CHAP_TUNING_SUPPORT,
97256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->chapTuningSupport);
97356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TURBOG_SUPPORT,
97456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->turboGSupport);
97556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TURBO_PRIME_SUPPORT,
97656f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->turboPrimeSupport);
97756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_DEVICE_TYPE,
97856f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->deviceType);
97956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_WME_SUPPORT,
98056f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->wmeSupport);
98156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TOTAL_QUEUES,
98256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->numTxQueues);
98356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_CONNECTION_ID_MAX,
98456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->connectionIdMax);
98556f9a274Sfei feng - Sun Microsystems - Beijing China 
98656f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_LOW_5GHZ_CHAN,
98756f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->low5GhzChan);
98856f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_HIGH_5GHZ_CHAN,
98956f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->high5GhzChan);
99056f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_LOW_2GHZ_CHAN,
99156f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->low2GhzChan);
99256f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_HIGH_2GHZ_CHAN,
99356f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->high2GhzChan);
99456f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TWICE_ANTENNAGAIN_5G,
99556f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->twiceAntennaGain5G);
99656f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_TWICE_ANTENNAGAIN_2G,
99756f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->twiceAntennaGain2G);
99856f9a274Sfei feng - Sun Microsystems - Beijing China 
99956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_CIPHER_AES_CCM,
100056f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->supportCipherAES_CCM);
100156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_CIPHER_TKIP,
100256f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->supportCipherTKIP);
100356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_get_capability(sc, CAP_MIC_TKIP,
100456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &cap->supportMicTKIP);
100556f9a274Sfei feng - Sun Microsystems - Beijing China 
100656f9a274Sfei feng - Sun Microsystems - Beijing China 	cap->supportCipherWEP = 1;	/* NB: always available */
100756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
100856f9a274Sfei feng - Sun Microsystems - Beijing China }
100956f9a274Sfei feng - Sun Microsystems - Beijing China 
101056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_get_status(struct uath_softc * sc,uint32_t which,void * odata,int olen)101156f9a274Sfei feng - Sun Microsystems - Beijing China uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen)
101256f9a274Sfei feng - Sun Microsystems - Beijing China {
101356f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
101456f9a274Sfei feng - Sun Microsystems - Beijing China 
101556f9a274Sfei feng - Sun Microsystems - Beijing China 	which = BE_32(which);
101656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS,
101756f9a274Sfei feng - Sun Microsystems - Beijing China 	    &which, sizeof (which), odata, olen, UATH_CMD_FLAG_MAGIC);
101856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS)
101956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_status(): "
102056f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not read EEPROM offset 0x%02x\n", BE_32(which));
102156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
102256f9a274Sfei feng - Sun Microsystems - Beijing China }
102356f9a274Sfei feng - Sun Microsystems - Beijing China 
102456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_get_devstatus(struct uath_softc * sc,uint8_t macaddr[IEEE80211_ADDR_LEN])102556f9a274Sfei feng - Sun Microsystems - Beijing China uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
102656f9a274Sfei feng - Sun Microsystems - Beijing China {
102756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
102856f9a274Sfei feng - Sun Microsystems - Beijing China 
102956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* retrieve MAC address */
103056f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN);
103156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
103256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_devstatus(): "
103356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not read MAC address\n");
103456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (err);
103556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
103656f9a274Sfei feng - Sun Microsystems - Beijing China 
103756f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_get_status(sc, ST_SERIAL_NUMBER,
103856f9a274Sfei feng - Sun Microsystems - Beijing China 	    &sc->sc_serial[0], sizeof (sc->sc_serial));
103956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
104056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_devstatus(): "
104156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not read device serial number\n");
104256f9a274Sfei feng - Sun Microsystems - Beijing China 		return (err);
104356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
104456f9a274Sfei feng - Sun Microsystems - Beijing China 
104556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
104656f9a274Sfei feng - Sun Microsystems - Beijing China }
104756f9a274Sfei feng - Sun Microsystems - Beijing China 
104856f9a274Sfei feng - Sun Microsystems - Beijing China /*
104956f9a274Sfei feng - Sun Microsystems - Beijing China  * uath_cmd_lock: a special signal structure that is used for notification
105056f9a274Sfei feng - Sun Microsystems - Beijing China  * that a callback function has been called.
105156f9a274Sfei feng - Sun Microsystems - Beijing China  */
105256f9a274Sfei feng - Sun Microsystems - Beijing China 
105356f9a274Sfei feng - Sun Microsystems - Beijing China /* Initializes the uath_cmd_lock structure. */
105456f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_cmd_lock_init(struct uath_cmd_lock * lock)105556f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_lock_init(struct uath_cmd_lock *lock)
105656f9a274Sfei feng - Sun Microsystems - Beijing China {
105756f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
105856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&lock->mutex, NULL, MUTEX_DRIVER, NULL);
105956f9a274Sfei feng - Sun Microsystems - Beijing China 	cv_init(&lock->cv, NULL, CV_DRIVER, NULL);
106056f9a274Sfei feng - Sun Microsystems - Beijing China 	lock->done = B_FALSE;
106156f9a274Sfei feng - Sun Microsystems - Beijing China }
106256f9a274Sfei feng - Sun Microsystems - Beijing China 
106356f9a274Sfei feng - Sun Microsystems - Beijing China /* Deinitalizes the uath_cb_lock structure. */
106456f9a274Sfei feng - Sun Microsystems - Beijing China void
uath_cmd_lock_destroy(struct uath_cmd_lock * lock)106556f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_lock_destroy(struct uath_cmd_lock *lock)
106656f9a274Sfei feng - Sun Microsystems - Beijing China {
106756f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
106856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&lock->mutex);
106956f9a274Sfei feng - Sun Microsystems - Beijing China 	cv_destroy(&lock->cv);
107056f9a274Sfei feng - Sun Microsystems - Beijing China }
107156f9a274Sfei feng - Sun Microsystems - Beijing China 
107256f9a274Sfei feng - Sun Microsystems - Beijing China /*
107356f9a274Sfei feng - Sun Microsystems - Beijing China  * Wait on lock until someone calls the "signal" function or the timeout
107456f9a274Sfei feng - Sun Microsystems - Beijing China  * expires. Note: timeout is in microseconds.
107556f9a274Sfei feng - Sun Microsystems - Beijing China  */
107656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_cmd_lock_wait(struct uath_cmd_lock * lock,clock_t timeout)107756f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_lock_wait(struct uath_cmd_lock *lock, clock_t timeout)
107856f9a274Sfei feng - Sun Microsystems - Beijing China {
107956f9a274Sfei feng - Sun Microsystems - Beijing China 	int res, cv_res;
108056f9a274Sfei feng - Sun Microsystems - Beijing China 	clock_t etime;
108156f9a274Sfei feng - Sun Microsystems - Beijing China 
108256f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
108356f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&lock->mutex);
108456f9a274Sfei feng - Sun Microsystems - Beijing China 
108556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (timeout < 0) {
108656f9a274Sfei feng - Sun Microsystems - Beijing China 		/* no timeout - wait as long as needed */
108756f9a274Sfei feng - Sun Microsystems - Beijing China 		while (lock->done == B_FALSE)
108856f9a274Sfei feng - Sun Microsystems - Beijing China 			cv_wait(&lock->cv, &lock->mutex);
108956f9a274Sfei feng - Sun Microsystems - Beijing China 	} else {
109056f9a274Sfei feng - Sun Microsystems - Beijing China 		/* wait with timeout (given in usec) */
109156f9a274Sfei feng - Sun Microsystems - Beijing China 		etime = ddi_get_lbolt() + drv_usectohz(timeout);
109256f9a274Sfei feng - Sun Microsystems - Beijing China 		while (lock->done == B_FALSE) {
109356f9a274Sfei feng - Sun Microsystems - Beijing China 			cv_res = cv_timedwait_sig(&lock->cv,
109456f9a274Sfei feng - Sun Microsystems - Beijing China 			    &lock->mutex, etime);
109556f9a274Sfei feng - Sun Microsystems - Beijing China 			if (cv_res <= 0) break;
109656f9a274Sfei feng - Sun Microsystems - Beijing China 		}
109756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
109856f9a274Sfei feng - Sun Microsystems - Beijing China 
109956f9a274Sfei feng - Sun Microsystems - Beijing China 	res = (lock->done == B_TRUE) ? UATH_SUCCESS : UATH_FAILURE;
110056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&lock->mutex);
110156f9a274Sfei feng - Sun Microsystems - Beijing China 
110256f9a274Sfei feng - Sun Microsystems - Beijing China 	return (res);
110356f9a274Sfei feng - Sun Microsystems - Beijing China }
110456f9a274Sfei feng - Sun Microsystems - Beijing China 
110556f9a274Sfei feng - Sun Microsystems - Beijing China /* Signal that the job (eg. callback) is done and unblock anyone who waits. */
110656f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_cmd_lock_signal(struct uath_cmd_lock * lock)110756f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_lock_signal(struct uath_cmd_lock *lock)
110856f9a274Sfei feng - Sun Microsystems - Beijing China {
110956f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
111056f9a274Sfei feng - Sun Microsystems - Beijing China 
111156f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&lock->mutex);
111256f9a274Sfei feng - Sun Microsystems - Beijing China 	lock->done = B_TRUE;
111356f9a274Sfei feng - Sun Microsystems - Beijing China 	cv_broadcast(&lock->cv);
111456f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&lock->mutex);
111556f9a274Sfei feng - Sun Microsystems - Beijing China }
111656f9a274Sfei feng - Sun Microsystems - Beijing China 
111756f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_cmd_read(struct uath_softc * sc,uint32_t code,const void * idata,int ilen,void * odata,int olen,int flags)111856f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
111956f9a274Sfei feng - Sun Microsystems - Beijing China     int ilen, void *odata, int olen, int flags)
112056f9a274Sfei feng - Sun Microsystems - Beijing China {
112156f9a274Sfei feng - Sun Microsystems - Beijing China 	flags |= UATH_CMD_FLAG_READ;
112256f9a274Sfei feng - Sun Microsystems - Beijing China 	return (uath_cmdsend(sc, code, idata, ilen, odata, olen, flags));
112356f9a274Sfei feng - Sun Microsystems - Beijing China }
112456f9a274Sfei feng - Sun Microsystems - Beijing China 
112556f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_cmd_write(struct uath_softc * sc,uint32_t code,const void * data,int len,int flags)112656f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data,
112756f9a274Sfei feng - Sun Microsystems - Beijing China     int len, int flags)
112856f9a274Sfei feng - Sun Microsystems - Beijing China {
112956f9a274Sfei feng - Sun Microsystems - Beijing China 	flags &= ~UATH_CMD_FLAG_READ;
113056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (uath_cmdsend(sc, code, data, len, NULL, 0, flags));
113156f9a274Sfei feng - Sun Microsystems - Beijing China }
113256f9a274Sfei feng - Sun Microsystems - Beijing China 
113356f9a274Sfei feng - Sun Microsystems - Beijing China /*
113456f9a274Sfei feng - Sun Microsystems - Beijing China  * Low-level function to send read or write commands to the firmware.
113556f9a274Sfei feng - Sun Microsystems - Beijing China  */
113656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_cmdsend(struct uath_softc * sc,uint32_t code,const void * idata,int ilen,void * odata,int olen,int flags)113756f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
113856f9a274Sfei feng - Sun Microsystems - Beijing China     void *odata, int olen, int flags)
113956f9a274Sfei feng - Sun Microsystems - Beijing China {
114056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_hdr *hdr;
114156f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd *cmd;
114256f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
114356f9a274Sfei feng - Sun Microsystems - Beijing China 
114456f9a274Sfei feng - Sun Microsystems - Beijing China 	/* grab a xfer */
114556f9a274Sfei feng - Sun Microsystems - Beijing China 	cmd = &sc->sc_cmd[sc->sc_cmdid];
114656f9a274Sfei feng - Sun Microsystems - Beijing China 
114756f9a274Sfei feng - Sun Microsystems - Beijing China 	cmd->flags = flags;
114856f9a274Sfei feng - Sun Microsystems - Beijing China 	/* always bulk-out a multiple of 4 bytes */
114956f9a274Sfei feng - Sun Microsystems - Beijing China 	cmd->buflen = (sizeof (struct uath_cmd_hdr) + ilen + 3) & ~3;
115056f9a274Sfei feng - Sun Microsystems - Beijing China 
115156f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr = (struct uath_cmd_hdr *)cmd->buf;
115256f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(hdr, sizeof (struct uath_cmd_hdr));
115356f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->len   = BE_32(cmd->buflen);
115456f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->code  = BE_32(code);
115556f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->msgid = cmd->msgid;	/* don't care about endianness */
115656f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->magic = BE_32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
115756f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(idata, (uint8_t *)(hdr + 1), ilen);
115856f9a274Sfei feng - Sun Microsystems - Beijing China 
115956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): "
116056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "queue %x send %s [flags 0x%x] olen %d\n",
116156f9a274Sfei feng - Sun Microsystems - Beijing China 	    cmd->msgid, uath_codename(code), cmd->flags, olen);
116256f9a274Sfei feng - Sun Microsystems - Beijing China 
116356f9a274Sfei feng - Sun Microsystems - Beijing China 	cmd->odata = odata;
116456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (odata == NULL)
116556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): "
116656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "warning - odata is NULL\n");
116756f9a274Sfei feng - Sun Microsystems - Beijing China 	else if (olen < UATH_MAX_CMDSZ - sizeof (*hdr) + sizeof (uint32_t))
116856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): "
116956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "warning - olen %x is short\n, olen");
117056f9a274Sfei feng - Sun Microsystems - Beijing China 	cmd->olen = olen;
117156f9a274Sfei feng - Sun Microsystems - Beijing China 
117256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_tx_cmd_xfer(sc, sc->tx_cmd_pipe, cmd->buf, cmd->buflen);
117356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
117456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): "
117556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "Error writing command\n");
117656f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
117756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
117856f9a274Sfei feng - Sun Microsystems - Beijing China 
117956f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_cmdid = (sc->sc_cmdid + 1) % UATH_CMD_LIST_COUNT;
118056f9a274Sfei feng - Sun Microsystems - Beijing China 
118156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (cmd->flags & UATH_CMD_FLAG_READ) {
118256f9a274Sfei feng - Sun Microsystems - Beijing China 		/* wait at most two seconds for command reply */
118356f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_cmd_lock_init(&sc->rlock);
118456f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_cmd_lock_wait(&sc->rlock, 2000000);
118556f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd->odata = NULL;	/* in case reply comes too late */
118656f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
118756f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): "
118856f9a274Sfei feng - Sun Microsystems - Beijing China 			    "timeout waiting for reply, "
118956f9a274Sfei feng - Sun Microsystems - Beijing China 			    "to cmd 0x%x (%u), queue %x\n",
119056f9a274Sfei feng - Sun Microsystems - Beijing China 			    code, code, cmd->msgid);
119156f9a274Sfei feng - Sun Microsystems - Beijing China 			err = UATH_FAILURE;
119256f9a274Sfei feng - Sun Microsystems - Beijing China 		} else if (cmd->olen != olen) {
119356f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): "
119456f9a274Sfei feng - Sun Microsystems - Beijing China 			    "unexpected reply data count "
119556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "to cmd 0x%x (%x), got %u, expected %u\n",
119656f9a274Sfei feng - Sun Microsystems - Beijing China 			    code, cmd->msgid, cmd->olen, olen);
119756f9a274Sfei feng - Sun Microsystems - Beijing China 			err = UATH_FAILURE;
119856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
119956f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_cmd_lock_destroy(&sc->rlock);
120056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (err);
120156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
120256f9a274Sfei feng - Sun Microsystems - Beijing China 
120356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
120456f9a274Sfei feng - Sun Microsystems - Beijing China }
120556f9a274Sfei feng - Sun Microsystems - Beijing China 
120656f9a274Sfei feng - Sun Microsystems - Beijing China /* ARGSUSED */
120756f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_cmd_txeof(usb_pipe_handle_t pipe,struct usb_bulk_req * req)120856f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_txeof(usb_pipe_handle_t pipe, struct usb_bulk_req *req)
120956f9a274Sfei feng - Sun Microsystems - Beijing China {
121056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private;
121156f9a274Sfei feng - Sun Microsystems - Beijing China 
121256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmd_txeof(): "
121356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "cr:%s(%d), flags:0x%x, tx queued %d\n",
121456f9a274Sfei feng - Sun Microsystems - Beijing China 	    usb_str_cr(req->bulk_completion_reason),
121556f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_completion_reason,
121656f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_cb_flags,
121756f9a274Sfei feng - Sun Microsystems - Beijing China 	    sc->tx_cmd_queued);
121856f9a274Sfei feng - Sun Microsystems - Beijing China 
121956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req->bulk_completion_reason != USB_CR_OK)
122056f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_err++;
122156f9a274Sfei feng - Sun Microsystems - Beijing China 
122256f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_txlock_cmd);
122356f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->tx_cmd_queued--;
122456f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_txlock_cmd);
122556f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
122656f9a274Sfei feng - Sun Microsystems - Beijing China }
122756f9a274Sfei feng - Sun Microsystems - Beijing China 
122856f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_tx_cmd_xfer(struct uath_softc * sc,usb_pipe_handle_t pipe,const void * data,uint_t len)122956f9a274Sfei feng - Sun Microsystems - Beijing China uath_tx_cmd_xfer(struct uath_softc *sc,
123056f9a274Sfei feng - Sun Microsystems - Beijing China     usb_pipe_handle_t pipe, const void *data, uint_t len)
123156f9a274Sfei feng - Sun Microsystems - Beijing China {
123256f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *send_req;
123356f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *mblk;
123456f9a274Sfei feng - Sun Microsystems - Beijing China 	int res;
123556f9a274Sfei feng - Sun Microsystems - Beijing China 
123656f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP);
123756f9a274Sfei feng - Sun Microsystems - Beijing China 
123856f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_client_private		= (usb_opaque_t)sc;
123956f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_len			= (int)len;
124056f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_attributes		= USB_ATTRS_AUTOCLEARING;
124156f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_timeout			= UATH_CMD_TIMEOUT;
124256f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_cb			= uath_cmd_txeof;
124356f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_exc_cb			= uath_cmd_txeof;
124456f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_completion_reason	= 0;
124556f9a274Sfei feng - Sun Microsystems - Beijing China 	send_req->bulk_cb_flags			= 0;
124656f9a274Sfei feng - Sun Microsystems - Beijing China 
124756f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk = send_req->bulk_data;
124856f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(data, mblk->b_rptr, len);
124956f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk->b_wptr += len;
125056f9a274Sfei feng - Sun Microsystems - Beijing China 
125156f9a274Sfei feng - Sun Microsystems - Beijing China 	res = usb_pipe_bulk_xfer(pipe, send_req, USB_FLAGS_NOSLEEP);
125256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (res != UATH_SUCCESS) {
125356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_tx_cmd_xfer(): "
125456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "Error %x writing cmd to bulk/out pipe", res);
125556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
125656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
125756f9a274Sfei feng - Sun Microsystems - Beijing China 
125856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_txlock_cmd);
125956f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->tx_cmd_queued++;
126056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_txlock_cmd);
126156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
126256f9a274Sfei feng - Sun Microsystems - Beijing China }
126356f9a274Sfei feng - Sun Microsystems - Beijing China 
126456f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_cmdeof(struct uath_softc * sc,struct uath_cmd * cmd)126556f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
126656f9a274Sfei feng - Sun Microsystems - Beijing China {
126756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_hdr *hdr;
126856f9a274Sfei feng - Sun Microsystems - Beijing China 	int dlen;
126956f9a274Sfei feng - Sun Microsystems - Beijing China 
127056f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr = (struct uath_cmd_hdr *)cmd->buf;
127156f9a274Sfei feng - Sun Microsystems - Beijing China 
127256f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->code = BE_32(hdr->code);
127356f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->len = BE_32(hdr->len);
127456f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr->magic = BE_32(hdr->magic);	/* target status on return */
127556f9a274Sfei feng - Sun Microsystems - Beijing China 
127656f9a274Sfei feng - Sun Microsystems - Beijing China 	/* NB: msgid is passed thru w/o byte swapping */
127756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): "
127856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "%s: [ix %x] len=%x status %x\n",
127956f9a274Sfei feng - Sun Microsystems - Beijing China 	    uath_codename(hdr->code),
128056f9a274Sfei feng - Sun Microsystems - Beijing China 	    hdr->msgid,
128156f9a274Sfei feng - Sun Microsystems - Beijing China 	    hdr->len,
128256f9a274Sfei feng - Sun Microsystems - Beijing China 	    hdr->magic);
128356f9a274Sfei feng - Sun Microsystems - Beijing China 
128456f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (hdr->code & 0xff) {
128556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* reply to a read command */
128656f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
128756f9a274Sfei feng - Sun Microsystems - Beijing China 		dlen = hdr->len - sizeof (*hdr);
128856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): "
128956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "code %x data len %u\n",
129056f9a274Sfei feng - Sun Microsystems - Beijing China 		    hdr->code & 0xff, dlen);
129156f9a274Sfei feng - Sun Microsystems - Beijing China 
129256f9a274Sfei feng - Sun Microsystems - Beijing China 		/*
129356f9a274Sfei feng - Sun Microsystems - Beijing China 		 * The first response from the target after the
129456f9a274Sfei feng - Sun Microsystems - Beijing China 		 * HOST_AVAILABLE has an invalid msgid so we must
129556f9a274Sfei feng - Sun Microsystems - Beijing China 		 * treat it specially.
129656f9a274Sfei feng - Sun Microsystems - Beijing China 		 */
129756f9a274Sfei feng - Sun Microsystems - Beijing China 		if ((hdr->msgid < UATH_CMD_LIST_COUNT) && (hdr->code != 0x13)) {
129856f9a274Sfei feng - Sun Microsystems - Beijing China 			uint32_t *rp = (uint32_t *)(hdr + 1);
129956f9a274Sfei feng - Sun Microsystems - Beijing China 			uint_t olen;
130056f9a274Sfei feng - Sun Microsystems - Beijing China 
130156f9a274Sfei feng - Sun Microsystems - Beijing China 			if (!(sizeof (*hdr) <= hdr->len &&
130256f9a274Sfei feng - Sun Microsystems - Beijing China 			    hdr->len < UATH_MAX_CMDSZ)) {
130356f9a274Sfei feng - Sun Microsystems - Beijing China 				UATH_DEBUG(UATH_DBG_RX_CMD,
130456f9a274Sfei feng - Sun Microsystems - Beijing China 				    "uath: uath_cmdeof(): "
130556f9a274Sfei feng - Sun Microsystems - Beijing China 				    "invalid WDC msg length %u; "
130656f9a274Sfei feng - Sun Microsystems - Beijing China 				    "msg ignored\n",
130756f9a274Sfei feng - Sun Microsystems - Beijing China 				    hdr->len);
130856f9a274Sfei feng - Sun Microsystems - Beijing China 				return;
130956f9a274Sfei feng - Sun Microsystems - Beijing China 			}
131056f9a274Sfei feng - Sun Microsystems - Beijing China 
131156f9a274Sfei feng - Sun Microsystems - Beijing China 			/*
131256f9a274Sfei feng - Sun Microsystems - Beijing China 			 * Calculate return/receive payload size; the
131356f9a274Sfei feng - Sun Microsystems - Beijing China 			 * first word, if present, always gives the
131456f9a274Sfei feng - Sun Microsystems - Beijing China 			 * number of bytes--unless it's 0 in which
131556f9a274Sfei feng - Sun Microsystems - Beijing China 			 * case a single 32-bit word should be present.
131656f9a274Sfei feng - Sun Microsystems - Beijing China 			 */
131756f9a274Sfei feng - Sun Microsystems - Beijing China 			if (dlen >= sizeof (uint32_t)) {
131856f9a274Sfei feng - Sun Microsystems - Beijing China 				olen = BE_32(rp[0]);
131956f9a274Sfei feng - Sun Microsystems - Beijing China 				dlen -= sizeof (uint32_t);
132056f9a274Sfei feng - Sun Microsystems - Beijing China 				if (olen == 0) {
132156f9a274Sfei feng - Sun Microsystems - Beijing China 					/* convention is 0 =>'s one word */
132256f9a274Sfei feng - Sun Microsystems - Beijing China 					olen = sizeof (uint32_t);
132356f9a274Sfei feng - Sun Microsystems - Beijing China 					/* XXX KASSERT(olen == dlen ) */
132456f9a274Sfei feng - Sun Microsystems - Beijing China 				}
132556f9a274Sfei feng - Sun Microsystems - Beijing China 			} else
132656f9a274Sfei feng - Sun Microsystems - Beijing China 				olen = 0;
132756f9a274Sfei feng - Sun Microsystems - Beijing China 
132856f9a274Sfei feng - Sun Microsystems - Beijing China 			if (cmd->odata != NULL) {
132956f9a274Sfei feng - Sun Microsystems - Beijing China 				/* NB: cmd->olen validated in uath_cmd */
133056f9a274Sfei feng - Sun Microsystems - Beijing China 				if (olen > cmd->olen) {
133156f9a274Sfei feng - Sun Microsystems - Beijing China 					/* XXX complain? */
133256f9a274Sfei feng - Sun Microsystems - Beijing China 					UATH_DEBUG(UATH_DBG_RX_CMD,
133356f9a274Sfei feng - Sun Microsystems - Beijing China 					    "uath: uath_cmdeof(): "
133456f9a274Sfei feng - Sun Microsystems - Beijing China 					    "cmd 0x%x olen %u cmd olen %u\n",
133556f9a274Sfei feng - Sun Microsystems - Beijing China 					    hdr->code, olen, cmd->olen);
133656f9a274Sfei feng - Sun Microsystems - Beijing China 					olen = cmd->olen;
133756f9a274Sfei feng - Sun Microsystems - Beijing China 				}
133856f9a274Sfei feng - Sun Microsystems - Beijing China 				if (olen > dlen) {
133956f9a274Sfei feng - Sun Microsystems - Beijing China 					/* XXX complain, shouldn't happen */
134056f9a274Sfei feng - Sun Microsystems - Beijing China 					UATH_DEBUG(UATH_DBG_RX_CMD,
134156f9a274Sfei feng - Sun Microsystems - Beijing China 					    "uath: uath_cmdeof(): "
134256f9a274Sfei feng - Sun Microsystems - Beijing China 					    "cmd 0x%x olen %u dlen %u\n",
134356f9a274Sfei feng - Sun Microsystems - Beijing China 					    hdr->code, olen, dlen);
134456f9a274Sfei feng - Sun Microsystems - Beijing China 					olen = dlen;
134556f9a274Sfei feng - Sun Microsystems - Beijing China 				}
134656f9a274Sfei feng - Sun Microsystems - Beijing China 				/* XXX have submitter do this */
134756f9a274Sfei feng - Sun Microsystems - Beijing China 				/* copy answer into caller's supplied buffer */
134856f9a274Sfei feng - Sun Microsystems - Beijing China 				bcopy(&rp[1], cmd->odata, olen);
134956f9a274Sfei feng - Sun Microsystems - Beijing China 				cmd->olen = olen;
135056f9a274Sfei feng - Sun Microsystems - Beijing China 			}
135156f9a274Sfei feng - Sun Microsystems - Beijing China 		}
135256f9a274Sfei feng - Sun Microsystems - Beijing China 
135356f9a274Sfei feng - Sun Microsystems - Beijing China 		/* Just signal that something happened */
135456f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_cmd_lock_signal(&sc->rlock);
135556f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
135656f9a274Sfei feng - Sun Microsystems - Beijing China 
135756f9a274Sfei feng - Sun Microsystems - Beijing China 	case WDCMSG_TARGET_START:
135856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): "
135956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "receive TARGET STAERT\n");
136056f9a274Sfei feng - Sun Microsystems - Beijing China 
136156f9a274Sfei feng - Sun Microsystems - Beijing China 		if (hdr->msgid >= UATH_CMD_LIST_COUNT) {
136256f9a274Sfei feng - Sun Microsystems - Beijing China 			/* XXX */
136356f9a274Sfei feng - Sun Microsystems - Beijing China 			return;
136456f9a274Sfei feng - Sun Microsystems - Beijing China 		}
136556f9a274Sfei feng - Sun Microsystems - Beijing China 		dlen = hdr->len - sizeof (*hdr);
136656f9a274Sfei feng - Sun Microsystems - Beijing China 		if (dlen != sizeof (uint32_t)) {
136756f9a274Sfei feng - Sun Microsystems - Beijing China 			/* XXX something wrong */
136856f9a274Sfei feng - Sun Microsystems - Beijing China 			return;
136956f9a274Sfei feng - Sun Microsystems - Beijing China 		}
137056f9a274Sfei feng - Sun Microsystems - Beijing China 		/* XXX have submitter do this */
137156f9a274Sfei feng - Sun Microsystems - Beijing China 		/* copy answer into caller's supplied buffer */
137256f9a274Sfei feng - Sun Microsystems - Beijing China 		bcopy(hdr + 1, cmd->odata, sizeof (uint32_t));
137356f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd->olen = sizeof (uint32_t);
137456f9a274Sfei feng - Sun Microsystems - Beijing China 
137556f9a274Sfei feng - Sun Microsystems - Beijing China 		/* wake up caller */
137656f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_cmd_lock_signal(&sc->rlock);
137756f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
137856f9a274Sfei feng - Sun Microsystems - Beijing China 
137956f9a274Sfei feng - Sun Microsystems - Beijing China 	case WDCMSG_SEND_COMPLETE:
138056f9a274Sfei feng - Sun Microsystems - Beijing China 		/* this notification is sent when UATH_TX_NOTIFY is set */
138156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): "
138256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "receive Tx notification\n");
138356f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
138456f9a274Sfei feng - Sun Microsystems - Beijing China 
138556f9a274Sfei feng - Sun Microsystems - Beijing China 	case WDCMSG_TARGET_GET_STATS:
138656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): "
138756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "received device statistics\n");
138856f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
138956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
139056f9a274Sfei feng - Sun Microsystems - Beijing China }
139156f9a274Sfei feng - Sun Microsystems - Beijing China 
139256f9a274Sfei feng - Sun Microsystems - Beijing China /* ARGSUSED */
139356f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_cmd_rxeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)139456f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmd_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
139556f9a274Sfei feng - Sun Microsystems - Beijing China {
139656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private;
139756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_hdr *hdr;
139856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd *cmd;
139956f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *mp;
140056f9a274Sfei feng - Sun Microsystems - Beijing China 	int len;
140156f9a274Sfei feng - Sun Microsystems - Beijing China 
140256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmd_rxeof(): "
140356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "cr:%s(%d), flags:0x%x, rx queued %d\n",
140456f9a274Sfei feng - Sun Microsystems - Beijing China 	    usb_str_cr(req->bulk_completion_reason),
140556f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_completion_reason,
140656f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_cb_flags,
140756f9a274Sfei feng - Sun Microsystems - Beijing China 	    sc->rx_cmd_queued);
140856f9a274Sfei feng - Sun Microsystems - Beijing China 
140956f9a274Sfei feng - Sun Microsystems - Beijing China 	m = req->bulk_data;
141056f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_data = NULL;
141156f9a274Sfei feng - Sun Microsystems - Beijing China 
141256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req->bulk_completion_reason != USB_CR_OK) {
141356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmd_rxeof(): "
141456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "USB CR is not OK\n");
141556f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
141656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
141756f9a274Sfei feng - Sun Microsystems - Beijing China 
141856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (m->b_cont != NULL) {
141956f9a274Sfei feng - Sun Microsystems - Beijing China 		/* Fragmented message, concatenate */
142056f9a274Sfei feng - Sun Microsystems - Beijing China 		mp = msgpullup(m, -1);
142156f9a274Sfei feng - Sun Microsystems - Beijing China 		freemsg(m);
142256f9a274Sfei feng - Sun Microsystems - Beijing China 		m = mp;
142356f9a274Sfei feng - Sun Microsystems - Beijing China 		mp = NULL;
142456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
142556f9a274Sfei feng - Sun Microsystems - Beijing China 
142656f9a274Sfei feng - Sun Microsystems - Beijing China 	len = msgdsize(m);
142756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (len < sizeof (struct uath_cmd_hdr)) {
142856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_rx_cmdeof(): "
142956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "short xfer error\n");
143056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
143156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
143256f9a274Sfei feng - Sun Microsystems - Beijing China 
143356f9a274Sfei feng - Sun Microsystems - Beijing China 	hdr = (struct uath_cmd_hdr *)m->b_rptr;
143456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (BE_32(hdr->code) == 0x13)
143556f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd = &sc->sc_cmd[0];
143656f9a274Sfei feng - Sun Microsystems - Beijing China 	else
143756f9a274Sfei feng - Sun Microsystems - Beijing China 		cmd = &sc->sc_cmd[hdr->msgid];
143856f9a274Sfei feng - Sun Microsystems - Beijing China 
143956f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(m->b_rptr, cmd->buf, len);
144056f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_cmdeof(sc, cmd);
144156f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_rx_cmd_xfer(sc);
144256f9a274Sfei feng - Sun Microsystems - Beijing China fail:
144356f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_rxlock_cmd);
144456f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->rx_cmd_queued--;
144556f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_rxlock_cmd);
144656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (m) freemsg(m);
144756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
144856f9a274Sfei feng - Sun Microsystems - Beijing China }
144956f9a274Sfei feng - Sun Microsystems - Beijing China 
145056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_rx_cmd_xfer(struct uath_softc * sc)145156f9a274Sfei feng - Sun Microsystems - Beijing China uath_rx_cmd_xfer(struct uath_softc *sc)
145256f9a274Sfei feng - Sun Microsystems - Beijing China {
145356f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *req;
145456f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
145556f9a274Sfei feng - Sun Microsystems - Beijing China 
145656f9a274Sfei feng - Sun Microsystems - Beijing China 	req = usb_alloc_bulk_req(sc->sc_dev, UATH_MAX_CMDSZ, USB_FLAGS_SLEEP);
145756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req == NULL) {
145856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_rx_cmd_xfer(): "
145956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to allocate req");
146056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
146156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
146256f9a274Sfei feng - Sun Microsystems - Beijing China 
146356f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_len			= UATH_MAX_CMDSZ;
146456f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_client_private	= (usb_opaque_t)sc;
146556f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb			= uath_cmd_rxeof;
146656f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_exc_cb		= uath_cmd_rxeof;
146756f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_timeout		= 0;
146856f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_completion_reason	= 0;
146956f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb_flags		= 0;
147056f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_attributes		= USB_ATTRS_SHORT_XFER_OK
147156f9a274Sfei feng - Sun Microsystems - Beijing China 	    | USB_ATTRS_AUTOCLEARING;
147256f9a274Sfei feng - Sun Microsystems - Beijing China 
147356f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_bulk_xfer(sc->rx_cmd_pipe, req, USB_FLAGS_NOSLEEP);
147456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
147556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_rx_cmd_xfer(): "
147656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to do rx xfer, %d", err);
147756f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_free_bulk_req(req);
147856f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
147956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
148056f9a274Sfei feng - Sun Microsystems - Beijing China 
148156f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_rxlock_cmd);
148256f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->rx_cmd_queued++;
148356f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_rxlock_cmd);
148456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
148556f9a274Sfei feng - Sun Microsystems - Beijing China }
148656f9a274Sfei feng - Sun Microsystems - Beijing China 
148756f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_init_data_queue(struct uath_softc * sc)148856f9a274Sfei feng - Sun Microsystems - Beijing China uath_init_data_queue(struct uath_softc *sc)
148956f9a274Sfei feng - Sun Microsystems - Beijing China {
149056f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->tx_data_queued = sc->rx_data_queued = 0;
149156f9a274Sfei feng - Sun Microsystems - Beijing China }
149256f9a274Sfei feng - Sun Microsystems - Beijing China 
149356f9a274Sfei feng - Sun Microsystems - Beijing China /* ARGSUSED */
149456f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_data_txeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)149556f9a274Sfei feng - Sun Microsystems - Beijing China uath_data_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
149656f9a274Sfei feng - Sun Microsystems - Beijing China {
149756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private;
149856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
149956f9a274Sfei feng - Sun Microsystems - Beijing China 
150056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_TX, "uath: uath_data_txeof(): "
150156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "uath_txeof(): cr:%s(%d), flags:0x%x, tx_data_queued %d\n",
150256f9a274Sfei feng - Sun Microsystems - Beijing China 	    usb_str_cr(req->bulk_completion_reason),
150356f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_completion_reason,
150456f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_cb_flags,
150556f9a274Sfei feng - Sun Microsystems - Beijing China 	    sc->tx_data_queued);
150656f9a274Sfei feng - Sun Microsystems - Beijing China 
150756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req->bulk_completion_reason != USB_CR_OK)
150856f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_err++;
150956f9a274Sfei feng - Sun Microsystems - Beijing China 
151056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_txlock_data);
151156f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->tx_data_queued--;
151256f9a274Sfei feng - Sun Microsystems - Beijing China 
151356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_need_sched) {
151456f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_need_sched = 0;
151556f9a274Sfei feng - Sun Microsystems - Beijing China 		mac_tx_update(ic->ic_mach);
151656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
151756f9a274Sfei feng - Sun Microsystems - Beijing China 
151856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_txlock_data);
151956f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
152056f9a274Sfei feng - Sun Microsystems - Beijing China }
152156f9a274Sfei feng - Sun Microsystems - Beijing China 
152256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_tx_data_xfer(struct uath_softc * sc,mblk_t * mp)152356f9a274Sfei feng - Sun Microsystems - Beijing China uath_tx_data_xfer(struct uath_softc *sc, mblk_t *mp)
152456f9a274Sfei feng - Sun Microsystems - Beijing China {
152556f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *req;
152656f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
152756f9a274Sfei feng - Sun Microsystems - Beijing China 
152856f9a274Sfei feng - Sun Microsystems - Beijing China 	req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP);
152956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req == NULL) {
153056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX, "uath: uath_tx_data_xfer(): "
153156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "uath_tx_data_xfer(): failed to allocate req");
153256f9a274Sfei feng - Sun Microsystems - Beijing China 		freemsg(mp);
153356f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
153456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
153556f9a274Sfei feng - Sun Microsystems - Beijing China 
153656f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_len			= msgdsize(mp);
153756f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_data			= mp;
1538*d278f1c9SToomas Soome 	req->bulk_client_private	= (usb_opaque_t)sc;
153956f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_timeout		= UATH_DATA_TIMEOUT;
154056f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_attributes		= USB_ATTRS_AUTOCLEARING;
154156f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb			= uath_data_txeof;
154256f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_exc_cb		= uath_data_txeof;
1543*d278f1c9SToomas Soome 	req->bulk_completion_reason	= 0;
154456f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb_flags		= 0;
154556f9a274Sfei feng - Sun Microsystems - Beijing China 
154656f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((err = usb_pipe_bulk_xfer(sc->tx_data_pipe, req, 0)) !=
154756f9a274Sfei feng - Sun Microsystems - Beijing China 	    USB_SUCCESS) {
154856f9a274Sfei feng - Sun Microsystems - Beijing China 
154956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX, "uath: uath_tx_data_xfer(): "
155056f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to do tx xfer, %d", err);
155156f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_free_bulk_req(req);
155256f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
155356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
155456f9a274Sfei feng - Sun Microsystems - Beijing China 
155556f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->tx_data_queued++;
155656f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
155756f9a274Sfei feng - Sun Microsystems - Beijing China }
155856f9a274Sfei feng - Sun Microsystems - Beijing China 
155956f9a274Sfei feng - Sun Microsystems - Beijing China /* ARGSUSED */
156056f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_data_rxeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)156156f9a274Sfei feng - Sun Microsystems - Beijing China uath_data_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
156256f9a274Sfei feng - Sun Microsystems - Beijing China {
156356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private;
156456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
156556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_chunk *chunk;
156656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_rx_desc *desc;
156756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
156856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni;
156956f9a274Sfei feng - Sun Microsystems - Beijing China 
157056f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *mp;
157156f9a274Sfei feng - Sun Microsystems - Beijing China 	uint8_t *rxbuf;
157256f9a274Sfei feng - Sun Microsystems - Beijing China 	int actlen, pktlen;
157356f9a274Sfei feng - Sun Microsystems - Beijing China 
157456f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_rxlock_data);
157556f9a274Sfei feng - Sun Microsystems - Beijing China 
157656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
157756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "cr:%s(%d), flags:0x%x, rx_data_queued %d\n",
157856f9a274Sfei feng - Sun Microsystems - Beijing China 	    usb_str_cr(req->bulk_completion_reason),
157956f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_completion_reason,
158056f9a274Sfei feng - Sun Microsystems - Beijing China 	    req->bulk_cb_flags,
158156f9a274Sfei feng - Sun Microsystems - Beijing China 	    sc->rx_data_queued);
158256f9a274Sfei feng - Sun Microsystems - Beijing China 
158356f9a274Sfei feng - Sun Microsystems - Beijing China 	mp = req->bulk_data;
158456f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_data = NULL;
158556f9a274Sfei feng - Sun Microsystems - Beijing China 
158656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req->bulk_completion_reason != USB_CR_OK) {
158756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
158856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "USB CR is not OK\n");
158956f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_err++;
159056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
159156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
159256f9a274Sfei feng - Sun Microsystems - Beijing China 
159356f9a274Sfei feng - Sun Microsystems - Beijing China 	rxbuf = (uint8_t *)mp->b_rptr;
159456f9a274Sfei feng - Sun Microsystems - Beijing China 	actlen = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
159556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (actlen < UATH_MIN_RXBUFSZ) {
159656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath_data_rxeof(): "
159756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "wrong recv size %d\n", actlen);
159856f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_err++;
159956f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
160056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
160156f9a274Sfei feng - Sun Microsystems - Beijing China 
160256f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk = (struct uath_chunk *)rxbuf;
160356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
160456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
160556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "strange response\n");
160656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_RESET_INTRX(sc);
160756f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_err++;
160856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
160956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
161056f9a274Sfei feng - Sun Microsystems - Beijing China 
161156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (chunk->seqnum != sc->sc_intrx_nextnum) {
161256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
161356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "invalid seqnum %d, expected %d\n",
161456f9a274Sfei feng - Sun Microsystems - Beijing China 		    chunk->seqnum, sc->sc_intrx_nextnum);
161556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_badchunkseqnum);
161656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_RESET_INTRX(sc);
161756f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_err++;
161856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
161956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
162056f9a274Sfei feng - Sun Microsystems - Beijing China 
162156f9a274Sfei feng - Sun Microsystems - Beijing China 	/* check multi-chunk frames  */
162256f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) ||
162356f9a274Sfei feng - Sun Microsystems - Beijing China 	    (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) ||
162456f9a274Sfei feng - Sun Microsystems - Beijing China 	    chunk->flags & UATH_CFLAGS_RXMSG) {
162556f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
162656f9a274Sfei feng - Sun Microsystems - Beijing China 		    "receive multi-chunk frames "
162756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "chunk seqnum %x, flags %x, length %u\n",
162856f9a274Sfei feng - Sun Microsystems - Beijing China 		    chunk->seqnum, chunk->flags, BE_16(chunk->length));
162956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_multichunk);
163056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
163156f9a274Sfei feng - Sun Microsystems - Beijing China 
163256f9a274Sfei feng - Sun Microsystems - Beijing China 
163356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* if the frame is not final continue the transfer  */
163456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (!(chunk->flags & UATH_CFLAGS_FINAL))
163556f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_intrx_nextnum++;
163656f9a274Sfei feng - Sun Microsystems - Beijing China 
163756f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
163856f9a274Sfei feng - Sun Microsystems - Beijing China 	 * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is
163956f9a274Sfei feng - Sun Microsystems - Beijing China 	 * located at the end, 32-bit aligned
164056f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
164156f9a274Sfei feng - Sun Microsystems - Beijing China 	desc = (chunk->flags & UATH_CFLAGS_RXMSG) ?
164256f9a274Sfei feng - Sun Microsystems - Beijing China 	    (struct uath_rx_desc *)(chunk + 1) :
164356f9a274Sfei feng - Sun Microsystems - Beijing China 	    (struct uath_rx_desc *)(((uint8_t *)chunk) +
164456f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (struct uath_chunk) + BE_16(chunk->length) -
164556f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (struct uath_rx_desc));
164656f9a274Sfei feng - Sun Microsystems - Beijing China 
164756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
164856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "frame len %u code %u status %u rate %u antenna %u "
164956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "rssi %d channel %u phyerror %u connix %u "
165056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "decrypterror %u keycachemiss %u\n",
165156f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(desc->framelen), BE_32(desc->code), BE_32(desc->status),
165256f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(desc->rate), BE_32(desc->antenna), BE_32(desc->rssi),
165356f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(desc->channel), BE_32(desc->phyerror), BE_32(desc->connix),
165456f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(desc->decrypterror), BE_32(desc->keycachemiss));
165556f9a274Sfei feng - Sun Microsystems - Beijing China 
165656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (BE_32(desc->len) > IEEE80211_MAX_LEN) {
165756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
165856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "bad descriptor (len=%d)\n", BE_32(desc->len));
165956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_toobigrxpkt);
166056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
166156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
166256f9a274Sfei feng - Sun Microsystems - Beijing China 
166356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_update_rxstat(sc, BE_32(desc->status));
166456f9a274Sfei feng - Sun Microsystems - Beijing China 
166556f9a274Sfei feng - Sun Microsystems - Beijing China 	pktlen = BE_32(desc->framelen) - UATH_RX_DUMMYSIZE;
166656f9a274Sfei feng - Sun Microsystems - Beijing China 
166756f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((m = allocb(pktlen, BPRI_MED)) == NULL) {
166856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): "
166956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "allocate mblk failed.\n");
167056f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_nobuf++;
167156f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
167256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
167356f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy((rxbuf + sizeof (struct uath_chunk)), m->b_rptr, pktlen);
167456f9a274Sfei feng - Sun Microsystems - Beijing China 
167556f9a274Sfei feng - Sun Microsystems - Beijing China 	m->b_wptr = m->b_rptr + pktlen;
167656f9a274Sfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
167756f9a274Sfei feng - Sun Microsystems - Beijing China 	ni = ieee80211_find_rxnode(ic, wh);
167856f9a274Sfei feng - Sun Microsystems - Beijing China 
167956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* send the frame to the 802.11 layer */
168056f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) ieee80211_input(ic, m, ni, (int)BE_32(desc->rssi), 0);
168156f9a274Sfei feng - Sun Microsystems - Beijing China 
168256f9a274Sfei feng - Sun Microsystems - Beijing China 	/* node is no longer needed */
168356f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_free_node(ni);
168456f9a274Sfei feng - Sun Microsystems - Beijing China fail:
168556f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->rx_data_queued--;
168656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (mp) freemsg(mp);
168756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
168856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_rxlock_data);
168956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_RUNNING(sc) && !UATH_IS_SUSPEND(sc)) {
169056f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) uath_rx_data_xfer(sc);
169156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
169256f9a274Sfei feng - Sun Microsystems - Beijing China }
169356f9a274Sfei feng - Sun Microsystems - Beijing China 
169456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_rx_data_xfer(struct uath_softc * sc)169556f9a274Sfei feng - Sun Microsystems - Beijing China uath_rx_data_xfer(struct uath_softc *sc)
169656f9a274Sfei feng - Sun Microsystems - Beijing China {
169756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_bulk_req_t *req;
169856f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
169956f9a274Sfei feng - Sun Microsystems - Beijing China 
170056f9a274Sfei feng - Sun Microsystems - Beijing China 	req = usb_alloc_bulk_req(sc->sc_dev,
170156f9a274Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_MAX_LEN, USB_FLAGS_SLEEP);
170256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (req == NULL) {
170356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_rx_data_xfer(): "
170456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to allocate req");
170556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_SUCCESS);
170656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
170756f9a274Sfei feng - Sun Microsystems - Beijing China 
170856f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_len			= IEEE80211_MAX_LEN;
170956f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb			= uath_data_rxeof;
171056f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_exc_cb		= uath_data_rxeof;
171156f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_client_private	= (usb_opaque_t)sc;
171256f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_timeout		= 0;
171356f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_completion_reason	= 0;
171456f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_cb_flags		= 0;
171556f9a274Sfei feng - Sun Microsystems - Beijing China 	req->bulk_attributes		= USB_ATTRS_SHORT_XFER_OK
171656f9a274Sfei feng - Sun Microsystems - Beijing China 	    | USB_ATTRS_AUTOCLEARING;
171756f9a274Sfei feng - Sun Microsystems - Beijing China 
171856f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_pipe_bulk_xfer(sc->rx_data_pipe, req, 0);
171956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
172056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_rx_data_xfer(): "
172156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to do rx xfer, %d", err);
172256f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_free_bulk_req(req);
172356f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
172456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
172556f9a274Sfei feng - Sun Microsystems - Beijing China 
172656f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_rxlock_data);
172756f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->rx_data_queued++;
172856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_rxlock_data);
172956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
173056f9a274Sfei feng - Sun Microsystems - Beijing China }
173156f9a274Sfei feng - Sun Microsystems - Beijing China 
173256f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_update_rxstat(struct uath_softc * sc,uint32_t status)173356f9a274Sfei feng - Sun Microsystems - Beijing China uath_update_rxstat(struct uath_softc *sc, uint32_t status)
173456f9a274Sfei feng - Sun Microsystems - Beijing China {
173556f9a274Sfei feng - Sun Microsystems - Beijing China 
173656f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (status) {
173756f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_STOP_IN_PROGRESS:
173856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_stopinprogress);
173956f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
174056f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_CRC_ERR:
174156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_crcerr);
174256f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
174356f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_PHY_ERR:
174456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_phyerr);
174556f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
174656f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_DECRYPT_CRC_ERR:
174756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_decrypt_crcerr);
174856f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
174956f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_DECRYPT_MIC_ERR:
175056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_decrypt_micerr);
175156f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
175256f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_DECOMP_ERR:
175356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_decomperr);
175456f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
175556f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_KEY_ERR:
175656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_keyerr);
175756f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
175856f9a274Sfei feng - Sun Microsystems - Beijing China 	case UATH_STATUS_ERR:
175956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_STAT_INC(sc, st_err);
176056f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
176156f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
176256f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
176356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
176456f9a274Sfei feng - Sun Microsystems - Beijing China }
176556f9a274Sfei feng - Sun Microsystems - Beijing China 
176656f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_next_scan(void * arg)176756f9a274Sfei feng - Sun Microsystems - Beijing China uath_next_scan(void *arg)
176856f9a274Sfei feng - Sun Microsystems - Beijing China {
176956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc	*sc = arg;
177056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com	*ic = &sc->sc_ic;
177156f9a274Sfei feng - Sun Microsystems - Beijing China 
177256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_state == IEEE80211_S_SCAN)
177356f9a274Sfei feng - Sun Microsystems - Beijing China 		ieee80211_next_scan(ic);
177456f9a274Sfei feng - Sun Microsystems - Beijing China 
177556f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_scan_id = 0;
177656f9a274Sfei feng - Sun Microsystems - Beijing China }
177756f9a274Sfei feng - Sun Microsystems - Beijing China 
177856f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_create_connection(struct uath_softc * sc,uint32_t connid)177956f9a274Sfei feng - Sun Microsystems - Beijing China uath_create_connection(struct uath_softc *sc, uint32_t connid)
178056f9a274Sfei feng - Sun Microsystems - Beijing China {
178156f9a274Sfei feng - Sun Microsystems - Beijing China 	const struct ieee80211_rateset *rs;
178256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
178356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = ic->ic_bss;
178456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_create_connection create;
178556f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
178656f9a274Sfei feng - Sun Microsystems - Beijing China 
178756f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&create, sizeof (create));
178856f9a274Sfei feng - Sun Microsystems - Beijing China 	create.connid = BE_32(connid);
178956f9a274Sfei feng - Sun Microsystems - Beijing China 	create.bssid = BE_32(0);
179056f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX packed or not?  */
179156f9a274Sfei feng - Sun Microsystems - Beijing China 	create.size = BE_32(sizeof (struct uath_cmd_rateset));
179256f9a274Sfei feng - Sun Microsystems - Beijing China 
179356f9a274Sfei feng - Sun Microsystems - Beijing China 	rs = &ni->in_rates;
179456f9a274Sfei feng - Sun Microsystems - Beijing China 	create.connattr.rateset.length = rs->ir_nrates;
179556f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(rs->ir_rates, &create.connattr.rateset.set[0],
179656f9a274Sfei feng - Sun Microsystems - Beijing China 	    rs->ir_nrates);
179756f9a274Sfei feng - Sun Microsystems - Beijing China 
179856f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX turbo */
179956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_CHAN_A(ni->in_chan))
180056f9a274Sfei feng - Sun Microsystems - Beijing China 		create.connattr.wlanmode = BE_32(WLAN_MODE_11a);
180156f9a274Sfei feng - Sun Microsystems - Beijing China 	else if (UATH_IS_CHAN_ANYG(ni->in_chan))
180256f9a274Sfei feng - Sun Microsystems - Beijing China 		create.connattr.wlanmode = BE_32(WLAN_MODE_11g);
180356f9a274Sfei feng - Sun Microsystems - Beijing China 	else
180456f9a274Sfei feng - Sun Microsystems - Beijing China 		create.connattr.wlanmode = BE_32(WLAN_MODE_11b);
180556f9a274Sfei feng - Sun Microsystems - Beijing China 
180656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create,
180756f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (create), 0);
180856f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
180956f9a274Sfei feng - Sun Microsystems - Beijing China }
181056f9a274Sfei feng - Sun Microsystems - Beijing China 
181156f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_rates(struct uath_softc * sc,const struct ieee80211_rateset * rs)181256f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
181356f9a274Sfei feng - Sun Microsystems - Beijing China {
181456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_rates rates;
181556f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
181656f9a274Sfei feng - Sun Microsystems - Beijing China 
181756f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&rates, sizeof (rates));
181856f9a274Sfei feng - Sun Microsystems - Beijing China 	rates.connid = BE_32(UATH_ID_BSS);		/* XXX */
181956f9a274Sfei feng - Sun Microsystems - Beijing China 	rates.size   = BE_32(sizeof (struct uath_cmd_rateset));
182056f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX bounds check rs->rs_nrates */
182156f9a274Sfei feng - Sun Microsystems - Beijing China 	rates.rateset.length = rs->ir_nrates;
182256f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(rs->ir_rates, &rates.rateset.set[0], rs->ir_nrates);
182356f9a274Sfei feng - Sun Microsystems - Beijing China 
182456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_rates(): "
182556f9a274Sfei feng - Sun Microsystems - Beijing China 	    "setting supported rates nrates=%d\n", rs->ir_nrates);
182656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE,
182756f9a274Sfei feng - Sun Microsystems - Beijing China 	    &rates, sizeof (rates), 0);
182856f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
182956f9a274Sfei feng - Sun Microsystems - Beijing China }
183056f9a274Sfei feng - Sun Microsystems - Beijing China 
183156f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_write_associd(struct uath_softc * sc)183256f9a274Sfei feng - Sun Microsystems - Beijing China uath_write_associd(struct uath_softc *sc)
183356f9a274Sfei feng - Sun Microsystems - Beijing China {
183456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
183556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = ic->ic_bss;
183656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_set_associd associd;
183756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
183856f9a274Sfei feng - Sun Microsystems - Beijing China 
183956f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&associd, sizeof (associd));
184056f9a274Sfei feng - Sun Microsystems - Beijing China 	associd.defaultrateix = BE_32(1);	/* XXX */
184156f9a274Sfei feng - Sun Microsystems - Beijing China 	associd.associd = BE_32(ni->in_associd);
184256f9a274Sfei feng - Sun Microsystems - Beijing China 	associd.timoffset = BE_32(0x3b);	/* XXX */
184356f9a274Sfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(associd.bssid, ni->in_bssid);
184456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd,
184556f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (associd), 0);
184656f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
184756f9a274Sfei feng - Sun Microsystems - Beijing China }
184856f9a274Sfei feng - Sun Microsystems - Beijing China 
184956f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_ledsteady(struct uath_softc * sc,int lednum,int ledmode)185056f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode)
185156f9a274Sfei feng - Sun Microsystems - Beijing China {
185256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_ledsteady led;
185356f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
185456f9a274Sfei feng - Sun Microsystems - Beijing China 
185556f9a274Sfei feng - Sun Microsystems - Beijing China 	led.lednum = BE_32(lednum);
185656f9a274Sfei feng - Sun Microsystems - Beijing China 	led.ledmode = BE_32(ledmode);
185756f9a274Sfei feng - Sun Microsystems - Beijing China 
185856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledsteady(): "
185956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "set %s led %s (steady)\n",
186056f9a274Sfei feng - Sun Microsystems - Beijing China 	    (lednum == UATH_LED_LINK) ? "link" : "activity",
186156f9a274Sfei feng - Sun Microsystems - Beijing China 	    ledmode ? "on" : "off");
186256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof (led), 0);
186356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
186456f9a274Sfei feng - Sun Microsystems - Beijing China }
186556f9a274Sfei feng - Sun Microsystems - Beijing China 
186656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_ledblink(struct uath_softc * sc,int lednum,int ledmode,int blinkrate,int slowmode)186756f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode,
186856f9a274Sfei feng - Sun Microsystems - Beijing China     int blinkrate, int slowmode)
186956f9a274Sfei feng - Sun Microsystems - Beijing China {
187056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_ledblink led;
187156f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
187256f9a274Sfei feng - Sun Microsystems - Beijing China 
187356f9a274Sfei feng - Sun Microsystems - Beijing China 	led.lednum = BE_32(lednum);
187456f9a274Sfei feng - Sun Microsystems - Beijing China 	led.ledmode = BE_32(ledmode);
187556f9a274Sfei feng - Sun Microsystems - Beijing China 	led.blinkrate = BE_32(blinkrate);
187656f9a274Sfei feng - Sun Microsystems - Beijing China 	led.slowmode = BE_32(slowmode);
187756f9a274Sfei feng - Sun Microsystems - Beijing China 
187856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledblink(): "
187956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "set %s led %s (blink)\n",
188056f9a274Sfei feng - Sun Microsystems - Beijing China 	    (lednum == UATH_LED_LINK) ? "link" : "activity",
188156f9a274Sfei feng - Sun Microsystems - Beijing China 	    ledmode ? "on" : "off");
188256f9a274Sfei feng - Sun Microsystems - Beijing China 
188356f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_SET_LED_BLINK,
188456f9a274Sfei feng - Sun Microsystems - Beijing China 	    &led, sizeof (led), 0);
188556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
188656f9a274Sfei feng - Sun Microsystems - Beijing China }
188756f9a274Sfei feng - Sun Microsystems - Beijing China 
188856f9a274Sfei feng - Sun Microsystems - Beijing China 
188956f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)189056f9a274Sfei feng - Sun Microsystems - Beijing China uath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
189156f9a274Sfei feng - Sun Microsystems - Beijing China {
189256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)ic;
189356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = ic->ic_bss;
189456f9a274Sfei feng - Sun Microsystems - Beijing China 	enum ieee80211_state ostate;
189556f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
189656f9a274Sfei feng - Sun Microsystems - Beijing China 
189756f9a274Sfei feng - Sun Microsystems - Beijing China 	ostate = ic->ic_state;
189856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_newstate(): "
189956f9a274Sfei feng - Sun Microsystems - Beijing China 	    "%d -> %d\n", ostate, nstate);
190056f9a274Sfei feng - Sun Microsystems - Beijing China 
190156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_scan_id != 0) {
190256f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) untimeout(sc->sc_scan_id);
190356f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_scan_id = 0;
190456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
190556f9a274Sfei feng - Sun Microsystems - Beijing China 
190656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
190756f9a274Sfei feng - Sun Microsystems - Beijing China 
190856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_DISCONNECT(sc) && (nstate != IEEE80211_S_INIT)) {
190956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
191056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
191156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
191256f9a274Sfei feng - Sun Microsystems - Beijing China 
191356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_SUSPEND(sc) && (nstate != IEEE80211_S_INIT)) {
191456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
191556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
191656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
191756f9a274Sfei feng - Sun Microsystems - Beijing China 
191856f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (nstate) {
191956f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_INIT:
192056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_RUN) {
192156f9a274Sfei feng - Sun Microsystems - Beijing China 			/* turn link and activity LEDs off */
192256f9a274Sfei feng - Sun Microsystems - Beijing China 			(void) uath_set_ledstate(sc, 0);
192356f9a274Sfei feng - Sun Microsystems - Beijing China 		}
192456f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
192556f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_SCAN:
192656f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_switch_channel(sc, ic->ic_curchan) != UATH_SUCCESS) {
192756f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): "
192856f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not switch channel\n");
192956f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
193056f9a274Sfei feng - Sun Microsystems - Beijing China 		}
193156f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_scan_id = timeout(uath_next_scan, (void *)sc,
193256f9a274Sfei feng - Sun Microsystems - Beijing China 		    drv_usectohz(250000));
193356f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
193456f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_AUTH:
193556f9a274Sfei feng - Sun Microsystems - Beijing China 		/* XXX good place?  set RTS threshold  */
193656f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_config(sc, CFG_USER_RTS_THRESHOLD, ic->ic_rtsthreshold);
193756f9a274Sfei feng - Sun Microsystems - Beijing China 
193856f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_switch_channel(sc, ni->in_chan) != 0) {
193956f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): "
194056f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not switch channel\n");
194156f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
194256f9a274Sfei feng - Sun Microsystems - Beijing China 		}
194356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_create_connection(sc, UATH_ID_BSS) != 0) {
194456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): "
194556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not create connection\n");
194656f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
194756f9a274Sfei feng - Sun Microsystems - Beijing China 		}
194856f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
194956f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_ASSOC:
195056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_set_rates(sc, &ni->in_rates) != 0) {
195156f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): "
195256f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not set negotiated rate set\n");
195356f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
195456f9a274Sfei feng - Sun Microsystems - Beijing China 		}
195556f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
195656f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_RUN:
195756f9a274Sfei feng - Sun Microsystems - Beijing China 		/* XXX monitor mode doesn't be supported  */
195856f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
195956f9a274Sfei feng - Sun Microsystems - Beijing China 			(void) uath_set_ledstate(sc, 1);
196056f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
196156f9a274Sfei feng - Sun Microsystems - Beijing China 		}
196256f9a274Sfei feng - Sun Microsystems - Beijing China 
196356f9a274Sfei feng - Sun Microsystems - Beijing China 		/*
196456f9a274Sfei feng - Sun Microsystems - Beijing China 		 * Tx rate is controlled by firmware, report the maximum
196556f9a274Sfei feng - Sun Microsystems - Beijing China 		 * negotiated rate in ifconfig output.
196656f9a274Sfei feng - Sun Microsystems - Beijing China 		 */
196756f9a274Sfei feng - Sun Microsystems - Beijing China 		ni->in_txrate = ni->in_rates.ir_nrates - 1;
196856f9a274Sfei feng - Sun Microsystems - Beijing China 
196956f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_write_associd(sc) != 0) {
197056f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): "
197156f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not write association id\n");
197256f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
197356f9a274Sfei feng - Sun Microsystems - Beijing China 		}
197456f9a274Sfei feng - Sun Microsystems - Beijing China 		/* turn link LED on */
197556f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON);
197656f9a274Sfei feng - Sun Microsystems - Beijing China 		/* make activity LED blink */
197756f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) uath_set_ledblink(sc, UATH_LED_ACTIVITY,
197856f9a274Sfei feng - Sun Microsystems - Beijing China 		    UATH_LED_ON, 1, 2);
197956f9a274Sfei feng - Sun Microsystems - Beijing China 		/* set state to associated */
198056f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) uath_set_ledstate(sc, 1);
198156f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
198256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
198356f9a274Sfei feng - Sun Microsystems - Beijing China 
198456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
198556f9a274Sfei feng - Sun Microsystems - Beijing China 
198656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = sc->sc_newstate(ic, nstate, arg);
198756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
198856f9a274Sfei feng - Sun Microsystems - Beijing China }
198956f9a274Sfei feng - Sun Microsystems - Beijing China 
199056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)199156f9a274Sfei feng - Sun Microsystems - Beijing China uath_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
199256f9a274Sfei feng - Sun Microsystems - Beijing China {
199356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)ic;
199456f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_chunk *chunk;
199556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_tx_desc *desc;
199656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
199756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = NULL;
199856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_key *k;
199956f9a274Sfei feng - Sun Microsystems - Beijing China 
200056f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *m0;
200156f9a274Sfei feng - Sun Microsystems - Beijing China 	int err, off, mblen;
200256f9a274Sfei feng - Sun Microsystems - Beijing China 	int pktlen, framelen, msglen;
200356f9a274Sfei feng - Sun Microsystems - Beijing China 
200456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = UATH_SUCCESS;
200556f9a274Sfei feng - Sun Microsystems - Beijing China 
200656f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_txlock_data);
200756f9a274Sfei feng - Sun Microsystems - Beijing China 
200856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_SUSPEND(sc)) {
200956f9a274Sfei feng - Sun Microsystems - Beijing China 		err = 0;
201056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
201156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
201256f9a274Sfei feng - Sun Microsystems - Beijing China 
201356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->tx_data_queued > UATH_TX_DATA_LIST_COUNT) {
201456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): "
201556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "no TX buffer available!\n");
201656f9a274Sfei feng - Sun Microsystems - Beijing China 		if ((type & IEEE80211_FC0_TYPE_MASK) ==
201756f9a274Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_FC0_TYPE_DATA) {
201856f9a274Sfei feng - Sun Microsystems - Beijing China 			sc->sc_need_sched = 1;
201956f9a274Sfei feng - Sun Microsystems - Beijing China 		}
202056f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_nobuf++;
202156f9a274Sfei feng - Sun Microsystems - Beijing China 		err = ENOMEM;
202256f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
202356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
202456f9a274Sfei feng - Sun Microsystems - Beijing China 
202556f9a274Sfei feng - Sun Microsystems - Beijing China 	m = allocb(UATH_MAX_TXBUFSZ, BPRI_MED);
202656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (m == NULL) {
202756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): "
202856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "can't alloc mblk.\n");
202956f9a274Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
203056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
203156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
203256f9a274Sfei feng - Sun Microsystems - Beijing China 
203356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* skip TX descriptor */
203456f9a274Sfei feng - Sun Microsystems - Beijing China 	m->b_rptr += sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc);
203556f9a274Sfei feng - Sun Microsystems - Beijing China 	m->b_wptr += sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc);
203656f9a274Sfei feng - Sun Microsystems - Beijing China 
203756f9a274Sfei feng - Sun Microsystems - Beijing China 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
203856f9a274Sfei feng - Sun Microsystems - Beijing China 		mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr;
203956f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
204056f9a274Sfei feng - Sun Microsystems - Beijing China 		off += mblen;
204156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
204256f9a274Sfei feng - Sun Microsystems - Beijing China 	m->b_wptr += off;
204356f9a274Sfei feng - Sun Microsystems - Beijing China 
204456f9a274Sfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
204556f9a274Sfei feng - Sun Microsystems - Beijing China 
204656f9a274Sfei feng - Sun Microsystems - Beijing China 	ni = ieee80211_find_txnode(ic, wh->i_addr1);
204756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (ni == NULL) {
204856f9a274Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
204956f9a274Sfei feng - Sun Microsystems - Beijing China 		freemsg(m);
205056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
205156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
205256f9a274Sfei feng - Sun Microsystems - Beijing China 
205356f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((type & IEEE80211_FC0_TYPE_MASK) ==
205456f9a274Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_FC0_TYPE_DATA) {
205556f9a274Sfei feng - Sun Microsystems - Beijing China 		(void) ieee80211_encap(ic, m, ni);
205656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
205756f9a274Sfei feng - Sun Microsystems - Beijing China 
205856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
205956f9a274Sfei feng - Sun Microsystems - Beijing China 		k = ieee80211_crypto_encap(ic, m);
206056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (k == NULL) {
206156f9a274Sfei feng - Sun Microsystems - Beijing China 			freemsg(m);
206256f9a274Sfei feng - Sun Microsystems - Beijing China 			err = DDI_FAILURE;
206356f9a274Sfei feng - Sun Microsystems - Beijing China 			goto fail;
206456f9a274Sfei feng - Sun Microsystems - Beijing China 		}
206556f9a274Sfei feng - Sun Microsystems - Beijing China 		/* packet header may have moved, reset our local pointer */
206656f9a274Sfei feng - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
206756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
206856f9a274Sfei feng - Sun Microsystems - Beijing China 
206956f9a274Sfei feng - Sun Microsystems - Beijing China 	pktlen = (uintptr_t)m->b_wptr - (uintptr_t)m->b_rptr;
207056f9a274Sfei feng - Sun Microsystems - Beijing China 	framelen = pktlen + IEEE80211_CRC_LEN;
207156f9a274Sfei feng - Sun Microsystems - Beijing China 	msglen = framelen + sizeof (struct uath_tx_desc);
207256f9a274Sfei feng - Sun Microsystems - Beijing China 
207356f9a274Sfei feng - Sun Microsystems - Beijing China 	m->b_rptr -= sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc);
207456f9a274Sfei feng - Sun Microsystems - Beijing China 
207556f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk = (struct uath_chunk *)m->b_rptr;
207656f9a274Sfei feng - Sun Microsystems - Beijing China 	desc = (struct uath_tx_desc *)(chunk + 1);
207756f9a274Sfei feng - Sun Microsystems - Beijing China 
207856f9a274Sfei feng - Sun Microsystems - Beijing China 	/* one chunk only for now */
207956f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->seqnum = 0;
208056f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->flags = UATH_CFLAGS_FINAL;
208156f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->length = BE_16(msglen);
208256f9a274Sfei feng - Sun Microsystems - Beijing China 
208356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* fill Tx descriptor */
208456f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->msglen = BE_32(msglen);
208556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0  */
208656f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->msgid  = sc->sc_msgid; /* don't care about endianness */
208756f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->type   = BE_32(WDCMSG_SEND);
208856f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
208956f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_FC0_TYPE_CTL:
209056f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_FC0_TYPE_MGT:
209156f9a274Sfei feng - Sun Microsystems - Beijing China 		/* NB: force all management frames to highest queue */
209256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ni->in_flags & UATH_NODE_QOS) {
209356f9a274Sfei feng - Sun Microsystems - Beijing China 			/* NB: force all management frames to highest queue */
209456f9a274Sfei feng - Sun Microsystems - Beijing China 			desc->txqid = BE_32(WME_AC_VO | UATH_TXQID_MINRATE);
209556f9a274Sfei feng - Sun Microsystems - Beijing China 		} else
209656f9a274Sfei feng - Sun Microsystems - Beijing China 			desc->txqid = BE_32(WME_AC_BE | UATH_TXQID_MINRATE);
209756f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
209856f9a274Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_FC0_TYPE_DATA:
209956f9a274Sfei feng - Sun Microsystems - Beijing China 		/* XXX multicast frames should honor mcastrate */
210056f9a274Sfei feng - Sun Microsystems - Beijing China 		desc->txqid = BE_32(WME_AC_BE);
210156f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
210256f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
210356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): "
210456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "bogus frame type 0x%x (%s)\n",
210556f9a274Sfei feng - Sun Microsystems - Beijing China 		    wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
210656f9a274Sfei feng - Sun Microsystems - Beijing China 		err = EIO;
210756f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
210856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
210956f9a274Sfei feng - Sun Microsystems - Beijing China 
211056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_state == IEEE80211_S_AUTH ||
211156f9a274Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_state == IEEE80211_S_ASSOC ||
211256f9a274Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_state == IEEE80211_S_RUN)
211356f9a274Sfei feng - Sun Microsystems - Beijing China 		desc->connid = BE_32(UATH_ID_BSS);
211456f9a274Sfei feng - Sun Microsystems - Beijing China 	else
211556f9a274Sfei feng - Sun Microsystems - Beijing China 		desc->connid = BE_32(UATH_ID_INVALID);
211656f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->flags  = BE_32(0 /* no UATH_TX_NOTIFY */);
211756f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->buflen = BE_32(pktlen);
211856f9a274Sfei feng - Sun Microsystems - Beijing China 
211956f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_tx_data_xfer(sc, m);
212056f9a274Sfei feng - Sun Microsystems - Beijing China 
212156f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_msgid = (sc->sc_msgid + 1) % UATH_TX_DATA_LIST_COUNT;
212256f9a274Sfei feng - Sun Microsystems - Beijing China 
212356f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_frags++;
212456f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_bytes += pktlen;
212556f9a274Sfei feng - Sun Microsystems - Beijing China 
212656f9a274Sfei feng - Sun Microsystems - Beijing China fail:
212756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (ni != NULL)
212856f9a274Sfei feng - Sun Microsystems - Beijing China 		ieee80211_free_node(ni);
212956f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((mp) &&
213056f9a274Sfei feng - Sun Microsystems - Beijing China 	    ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
213156f9a274Sfei feng - Sun Microsystems - Beijing China 	    err == 0)) {
213256f9a274Sfei feng - Sun Microsystems - Beijing China 		freemsg(mp);
213356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
213456f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_txlock_data);
213556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
213656f9a274Sfei feng - Sun Microsystems - Beijing China }
213756f9a274Sfei feng - Sun Microsystems - Beijing China 
213856f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_reconnect(dev_info_t * devinfo)213956f9a274Sfei feng - Sun Microsystems - Beijing China uath_reconnect(dev_info_t *devinfo)
214056f9a274Sfei feng - Sun Microsystems - Beijing China {
214156f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc;
214256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic;
214356f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
214456f9a274Sfei feng - Sun Microsystems - Beijing China 	uint16_t vendor_id, product_id;
214556f9a274Sfei feng - Sun Microsystems - Beijing China 
214656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_reconnect(): "
214756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "uath online\n");
214856f9a274Sfei feng - Sun Microsystems - Beijing China 
214956f9a274Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo));
215056f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
215156f9a274Sfei feng - Sun Microsystems - Beijing China 	ic = (struct ieee80211com *)&sc->sc_ic;
215256f9a274Sfei feng - Sun Microsystems - Beijing China 
215356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (!UATH_IS_RECONNECT(sc)) {
215456f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_open_pipes(sc);
215556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
215656f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
215756f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not open pipes\n");
215856f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
215956f9a274Sfei feng - Sun Microsystems - Beijing China 		}
216056f9a274Sfei feng - Sun Microsystems - Beijing China 
216156f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_loadfirmware(sc);
216256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
216356f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
216456f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not download firmware\n");
216556f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
216656f9a274Sfei feng - Sun Microsystems - Beijing China 		}
216756f9a274Sfei feng - Sun Microsystems - Beijing China 
216856f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_close_pipes(sc);
216956f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_client_detach(sc->sc_dev, sc->sc_udev);
217056f9a274Sfei feng - Sun Microsystems - Beijing China 
217156f9a274Sfei feng - Sun Microsystems - Beijing China 		/* reset device */
217256f9a274Sfei feng - Sun Microsystems - Beijing China 		err = usb_reset_device(sc->sc_dev, USB_RESET_LVL_DEFAULT);
217356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != USB_SUCCESS) {
217456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
217556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not reset device %x\n", err);
217656f9a274Sfei feng - Sun Microsystems - Beijing China 		}
217756f9a274Sfei feng - Sun Microsystems - Beijing China 
217856f9a274Sfei feng - Sun Microsystems - Beijing China 		err = usb_client_attach(devinfo, USBDRV_VERSION, 0);
217956f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != USB_SUCCESS) {
218056f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
218156f9a274Sfei feng - Sun Microsystems - Beijing China 			    "usb_client_attach failed\n");
218256f9a274Sfei feng - Sun Microsystems - Beijing China 		}
218356f9a274Sfei feng - Sun Microsystems - Beijing China 
218456f9a274Sfei feng - Sun Microsystems - Beijing China 		err = usb_get_dev_data(devinfo, &sc->sc_udev,
218556f9a274Sfei feng - Sun Microsystems - Beijing China 		    USB_PARSE_LVL_ALL, 0);
218656f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != USB_SUCCESS) {
218756f9a274Sfei feng - Sun Microsystems - Beijing China 			sc->sc_udev = NULL;
218856f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
218956f9a274Sfei feng - Sun Microsystems - Beijing China 			    "usb_get_dev_data failed\n");
219056f9a274Sfei feng - Sun Microsystems - Beijing China 		}
219156f9a274Sfei feng - Sun Microsystems - Beijing China 
219256f9a274Sfei feng - Sun Microsystems - Beijing China 		vendor_id = sc->sc_udev->dev_descr->idVendor;
219356f9a274Sfei feng - Sun Microsystems - Beijing China 		product_id = sc->sc_udev->dev_descr->idProduct;
219456f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->dev_flags = uath_lookup(vendor_id, product_id);
219556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (sc->dev_flags == UATH_FLAG_ERR) {
219656f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
219756f9a274Sfei feng - Sun Microsystems - Beijing China 			    "HW does not match\n");
219856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
219956f9a274Sfei feng - Sun Microsystems - Beijing China 
220056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_reconnect(): "
220156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "vendorId = %x,deviceID = %x, flags = %x\n",
220256f9a274Sfei feng - Sun Microsystems - Beijing China 		    vendor_id, product_id, sc->dev_flags);
220356f9a274Sfei feng - Sun Microsystems - Beijing China 
220456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_LOCK(sc);
220556f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags |= UATH_FLAG_RECONNECT;
220656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
220756f9a274Sfei feng - Sun Microsystems - Beijing China 
220856f9a274Sfei feng - Sun Microsystems - Beijing China 	} else {
220956f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_open_pipes(sc);
221056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
221156f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
221256f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not open pipes\n");
221356f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
221456f9a274Sfei feng - Sun Microsystems - Beijing China 		}
221556f9a274Sfei feng - Sun Microsystems - Beijing China 
221656f9a274Sfei feng - Sun Microsystems - Beijing China 		/*
221756f9a274Sfei feng - Sun Microsystems - Beijing China 		 * Allocate xfers for firmware commands.
221856f9a274Sfei feng - Sun Microsystems - Beijing China 		 */
221956f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
222056f9a274Sfei feng - Sun Microsystems - Beijing China 		    UATH_MAX_CMDSZ);
222156f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
222256f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
222356f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not allocate Tx command list\n");
222456f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
222556f9a274Sfei feng - Sun Microsystems - Beijing China 		}
222656f9a274Sfei feng - Sun Microsystems - Beijing China 
222756f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_init_cmd_list(sc);
222856f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
222956f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
223056f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not init RX command list\n");
223156f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
223256f9a274Sfei feng - Sun Microsystems - Beijing China 		}
223356f9a274Sfei feng - Sun Microsystems - Beijing China 
223456f9a274Sfei feng - Sun Microsystems - Beijing China 		/*
223556f9a274Sfei feng - Sun Microsystems - Beijing China 		 * We're now ready to send+receive firmware commands.
223656f9a274Sfei feng - Sun Microsystems - Beijing China 		 */
223756f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_host_available(sc);
223856f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
223956f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
224056f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not initialize adapter\n");
224156f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
224256f9a274Sfei feng - Sun Microsystems - Beijing China 		}
224356f9a274Sfei feng - Sun Microsystems - Beijing China 
224456f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_get_devcap(sc);
224556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
224656f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
224756f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not get device capabilities\n");
224856f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
224956f9a274Sfei feng - Sun Microsystems - Beijing China 		}
225056f9a274Sfei feng - Sun Microsystems - Beijing China 
225156f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_get_devstatus(sc, ic->ic_macaddr);
225256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
225356f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
225456f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not get dev status\n");
225556f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
225656f9a274Sfei feng - Sun Microsystems - Beijing China 		}
225756f9a274Sfei feng - Sun Microsystems - Beijing China 
225856f9a274Sfei feng - Sun Microsystems - Beijing China 		err = usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1,
225956f9a274Sfei feng - Sun Microsystems - Beijing China 		    USB_CHK_BASIC, NULL);
226056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != USB_SUCCESS) {
226156f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
226256f9a274Sfei feng - Sun Microsystems - Beijing China 			    "different device connected %x\n", err);
226356f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
226456f9a274Sfei feng - Sun Microsystems - Beijing China 		}
226556f9a274Sfei feng - Sun Microsystems - Beijing China 
226656f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_init(sc);
226756f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
226856f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): "
226956f9a274Sfei feng - Sun Microsystems - Beijing China 			    "device re-connect failed\n");
227056f9a274Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
227156f9a274Sfei feng - Sun Microsystems - Beijing China 		}
227256f9a274Sfei feng - Sun Microsystems - Beijing China 
227356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_LOCK(sc);
227456f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags &= ~UATH_FLAG_RECONNECT;
227556f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags &= ~UATH_FLAG_DISCONNECT;
227656f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags |= UATH_FLAG_RUNNING;
227756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
227856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
227956f9a274Sfei feng - Sun Microsystems - Beijing China 
228056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
228156f9a274Sfei feng - Sun Microsystems - Beijing China }
228256f9a274Sfei feng - Sun Microsystems - Beijing China 
228356f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_disconnect(dev_info_t * devinfo)228456f9a274Sfei feng - Sun Microsystems - Beijing China uath_disconnect(dev_info_t *devinfo)
228556f9a274Sfei feng - Sun Microsystems - Beijing China {
228656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc;
228756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic;
228856f9a274Sfei feng - Sun Microsystems - Beijing China 
228956f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
229056f9a274Sfei feng - Sun Microsystems - Beijing China 	 * We can't call uath_stop() here, since the hardware is removed,
229156f9a274Sfei feng - Sun Microsystems - Beijing China 	 * we can't access the register anymore.
229256f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
229356f9a274Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo));
229456f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
229556f9a274Sfei feng - Sun Microsystems - Beijing China 
229656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_flags & UATH_FLAG_RECONNECT) {
229756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_disconnect(): "
229856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "stage 0 in re-connect\n");
229956f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_close_pipes(sc);
230056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
230156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
230256f9a274Sfei feng - Sun Microsystems - Beijing China 
230356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
230456f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= UATH_FLAG_DISCONNECT;
230556f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
230656f9a274Sfei feng - Sun Microsystems - Beijing China 
230756f9a274Sfei feng - Sun Microsystems - Beijing China 	ic = (struct ieee80211com *)&sc->sc_ic;
230856f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
230956f9a274Sfei feng - Sun Microsystems - Beijing China 
231056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
231156f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags &= ~UATH_FLAG_RUNNING;	/* STOP */
231256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
231356f9a274Sfei feng - Sun Microsystems - Beijing China 
231456f9a274Sfei feng - Sun Microsystems - Beijing China 	/* abort and free xfers */
231556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT);
231656f9a274Sfei feng - Sun Microsystems - Beijing China 
231756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* close Tx/Rx pipes */
231856f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_close_pipes(sc);
231956f9a274Sfei feng - Sun Microsystems - Beijing China 
232056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_disconnect(): "
232156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "offline success\n");
232256f9a274Sfei feng - Sun Microsystems - Beijing China 
232356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
232456f9a274Sfei feng - Sun Microsystems - Beijing China }
232556f9a274Sfei feng - Sun Microsystems - Beijing China 
232656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_dataflush(struct uath_softc * sc)232756f9a274Sfei feng - Sun Microsystems - Beijing China uath_dataflush(struct uath_softc *sc)
232856f9a274Sfei feng - Sun Microsystems - Beijing China {
232956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_chunk *chunk;
233056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_tx_desc *desc;
233156f9a274Sfei feng - Sun Microsystems - Beijing China 	uint8_t *buf;
233256f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
233356f9a274Sfei feng - Sun Microsystems - Beijing China 
233456f9a274Sfei feng - Sun Microsystems - Beijing China 	buf = kmem_alloc(UATH_MAX_TXBUFSZ, KM_NOSLEEP);
233556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (buf == NULL) {
233656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_dataflush(): "
233756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "no bufs\n");
233856f9a274Sfei feng - Sun Microsystems - Beijing China 		return (ENOBUFS);
233956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
234056f9a274Sfei feng - Sun Microsystems - Beijing China 
234156f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk = (struct uath_chunk *)buf;
234256f9a274Sfei feng - Sun Microsystems - Beijing China 	desc = (struct uath_tx_desc *)(chunk + 1);
234356f9a274Sfei feng - Sun Microsystems - Beijing China 
234456f9a274Sfei feng - Sun Microsystems - Beijing China 	/* one chunk only */
234556f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->seqnum = 0;
234656f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->flags = UATH_CFLAGS_FINAL;
234756f9a274Sfei feng - Sun Microsystems - Beijing China 	chunk->length = BE_16(sizeof (struct uath_tx_desc));
234856f9a274Sfei feng - Sun Microsystems - Beijing China 
234956f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(desc, sizeof (struct uath_tx_desc));
235056f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->msglen = BE_32(sizeof (struct uath_tx_desc));
235156f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->msgid  = sc->sc_msgid; /* don't care about endianness */
235256f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->type   = BE_32(WDCMSG_FLUSH);
235356f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->txqid  = BE_32(0);
235456f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->connid = BE_32(0);
235556f9a274Sfei feng - Sun Microsystems - Beijing China 	desc->flags  = BE_32(0);
235656f9a274Sfei feng - Sun Microsystems - Beijing China 
235756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_dataflush(): "
235856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "send flush ix %d\n", desc->msgid);
235956f9a274Sfei feng - Sun Microsystems - Beijing China 
236056f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_fw_send(sc, sc->tx_data_pipe, buf,
236156f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc));
236256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
236356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_dataflush(): "
236456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "data flush error");
236556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (UATH_FAILURE);
236656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
236756f9a274Sfei feng - Sun Microsystems - Beijing China 
236856f9a274Sfei feng - Sun Microsystems - Beijing China 	kmem_free(buf, UATH_MAX_TXBUFSZ);
236956f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_msgid = (sc->sc_msgid + 1) % UATH_TX_DATA_LIST_COUNT;
237056f9a274Sfei feng - Sun Microsystems - Beijing China 
237156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
237256f9a274Sfei feng - Sun Microsystems - Beijing China }
237356f9a274Sfei feng - Sun Microsystems - Beijing China 
237456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_cmdflush(struct uath_softc * sc)237556f9a274Sfei feng - Sun Microsystems - Beijing China uath_cmdflush(struct uath_softc *sc)
237656f9a274Sfei feng - Sun Microsystems - Beijing China {
237756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0));
237856f9a274Sfei feng - Sun Microsystems - Beijing China }
237956f9a274Sfei feng - Sun Microsystems - Beijing China 
238056f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_flush(struct uath_softc * sc)238156f9a274Sfei feng - Sun Microsystems - Beijing China uath_flush(struct uath_softc *sc)
238256f9a274Sfei feng - Sun Microsystems - Beijing China {
238356f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
238456f9a274Sfei feng - Sun Microsystems - Beijing China 
238556f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_dataflush(sc);
238656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS)
238756f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
238856f9a274Sfei feng - Sun Microsystems - Beijing China 
238956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmdflush(sc);
239056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS)
239156f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
239256f9a274Sfei feng - Sun Microsystems - Beijing China 
239356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
239456f9a274Sfei feng - Sun Microsystems - Beijing China failed:
239556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
239656f9a274Sfei feng - Sun Microsystems - Beijing China }
239756f9a274Sfei feng - Sun Microsystems - Beijing China 
239856f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_ledstate(struct uath_softc * sc,int connected)239956f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_ledstate(struct uath_softc *sc, int connected)
240056f9a274Sfei feng - Sun Microsystems - Beijing China {
240156f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
240256f9a274Sfei feng - Sun Microsystems - Beijing China 
240356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledstate(): "
240456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "set led state %sconnected\n", connected ? "" : "!");
240556f9a274Sfei feng - Sun Microsystems - Beijing China 
240656f9a274Sfei feng - Sun Microsystems - Beijing China 	connected = BE_32(connected);
240756f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_SET_LED_STATE,
240856f9a274Sfei feng - Sun Microsystems - Beijing China 	    &connected, sizeof (connected), 0);
240956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
241056f9a274Sfei feng - Sun Microsystems - Beijing China }
241156f9a274Sfei feng - Sun Microsystems - Beijing China 
241256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_config_multi(struct uath_softc * sc,uint32_t reg,const void * data,int len)241356f9a274Sfei feng - Sun Microsystems - Beijing China uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data,
241456f9a274Sfei feng - Sun Microsystems - Beijing China     int len)
241556f9a274Sfei feng - Sun Microsystems - Beijing China {
241656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_write_mac write;
241756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
241856f9a274Sfei feng - Sun Microsystems - Beijing China 
241956f9a274Sfei feng - Sun Microsystems - Beijing China 	write.reg = BE_32(reg);
242056f9a274Sfei feng - Sun Microsystems - Beijing China 	write.len = BE_32(len);
242156f9a274Sfei feng - Sun Microsystems - Beijing China 	bcopy(data, write.data, len);
242256f9a274Sfei feng - Sun Microsystems - Beijing China 
242356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* properly handle the case where len is zero (reset) */
242456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
242556f9a274Sfei feng - Sun Microsystems - Beijing China 	    (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
242656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
242756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_config_multi(): "
242856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not write %d bytes to register 0x%02x\n", len, reg);
242956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
243056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
243156f9a274Sfei feng - Sun Microsystems - Beijing China }
243256f9a274Sfei feng - Sun Microsystems - Beijing China 
243356f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_config(struct uath_softc * sc,uint32_t reg,uint32_t val)243456f9a274Sfei feng - Sun Microsystems - Beijing China uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
243556f9a274Sfei feng - Sun Microsystems - Beijing China {
243656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_write_mac write;
243756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
243856f9a274Sfei feng - Sun Microsystems - Beijing China 
243956f9a274Sfei feng - Sun Microsystems - Beijing China 	write.reg = BE_32(reg);
244056f9a274Sfei feng - Sun Microsystems - Beijing China 	write.len = BE_32(0);	/* 0 = single write */
244156f9a274Sfei feng - Sun Microsystems - Beijing China 	*(uint32_t *)write.data = BE_32(val);
244256f9a274Sfei feng - Sun Microsystems - Beijing China 
244356f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
244456f9a274Sfei feng - Sun Microsystems - Beijing China 	    3 * sizeof (uint32_t), 0);
244556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
244656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_config(): "
244756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not write register 0x%02x\n",
244856f9a274Sfei feng - Sun Microsystems - Beijing China 		    reg);
244956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
245056f9a274Sfei feng - Sun Microsystems - Beijing China }
245156f9a274Sfei feng - Sun Microsystems - Beijing China 
245256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_switch_channel(struct uath_softc * sc,struct ieee80211_channel * c)245356f9a274Sfei feng - Sun Microsystems - Beijing China uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
245456f9a274Sfei feng - Sun Microsystems - Beijing China {
245556f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
245656f9a274Sfei feng - Sun Microsystems - Beijing China 
245756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set radio frequency */
245856f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_set_chan(sc, c);
245956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
246056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): "
246156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not set channel\n");
246256f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
246356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
246456f9a274Sfei feng - Sun Microsystems - Beijing China 
246556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* reset Tx rings */
246656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_reset_tx_queues(sc);
246756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
246856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): "
246956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not reset Tx queues\n");
247056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
247156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
247256f9a274Sfei feng - Sun Microsystems - Beijing China 
247356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set Tx rings WME properties */
247456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_wme_init(sc);
247556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
247656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): "
247756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not init Tx queues\n");
247856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
247956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
248056f9a274Sfei feng - Sun Microsystems - Beijing China 
248156f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_set_ledstate(sc, 0);
248256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
248356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): "
248456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not set led state\n");
248556f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
248656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
248756f9a274Sfei feng - Sun Microsystems - Beijing China 
248856f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_flush(sc);
248956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
249056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): "
249156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not flush pipes\n");
249256f9a274Sfei feng - Sun Microsystems - Beijing China 		goto failed;
249356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
249456f9a274Sfei feng - Sun Microsystems - Beijing China 
249556f9a274Sfei feng - Sun Microsystems - Beijing China failed:
249656f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
249756f9a274Sfei feng - Sun Microsystems - Beijing China }
249856f9a274Sfei feng - Sun Microsystems - Beijing China 
249956f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_rxfilter(struct uath_softc * sc,uint32_t bits,uint32_t op)250056f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op)
250156f9a274Sfei feng - Sun Microsystems - Beijing China {
250256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_rx_filter rxfilter;
250356f9a274Sfei feng - Sun Microsystems - Beijing China 
250456f9a274Sfei feng - Sun Microsystems - Beijing China 	rxfilter.bits = BE_32(bits);
250556f9a274Sfei feng - Sun Microsystems - Beijing China 	rxfilter.op = BE_32(op);
250656f9a274Sfei feng - Sun Microsystems - Beijing China 
250756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_rxfilter(): "
250856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "setting Rx filter=0x%x flags=0x%x\n", bits, op);
250956f9a274Sfei feng - Sun Microsystems - Beijing China 
251056f9a274Sfei feng - Sun Microsystems - Beijing China 	return ((uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter,
251156f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (rxfilter), 0)));
251256f9a274Sfei feng - Sun Microsystems - Beijing China }
251356f9a274Sfei feng - Sun Microsystems - Beijing China 
251456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_set_chan(struct uath_softc * sc,struct ieee80211_channel * c)251556f9a274Sfei feng - Sun Microsystems - Beijing China uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
251656f9a274Sfei feng - Sun Microsystems - Beijing China {
251756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
251856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_reset reset;
251956f9a274Sfei feng - Sun Microsystems - Beijing China 
252056f9a274Sfei feng - Sun Microsystems - Beijing China 	bzero(&reset, sizeof (reset));
252156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_2GHZ(c))
252256f9a274Sfei feng - Sun Microsystems - Beijing China 		reset.flags |= BE_32(UATH_CHAN_2GHZ);
252356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_5GHZ(c))
252456f9a274Sfei feng - Sun Microsystems - Beijing China 		reset.flags |= BE_32(UATH_CHAN_5GHZ);
252556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* NB: 11g =>'s 11b so don't specify both OFDM and CCK */
252656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_CHAN_OFDM(c))
252756f9a274Sfei feng - Sun Microsystems - Beijing China 		reset.flags |= BE_32(UATH_CHAN_OFDM);
252856f9a274Sfei feng - Sun Microsystems - Beijing China 	else if (UATH_IS_CHAN_CCK(c))
252956f9a274Sfei feng - Sun Microsystems - Beijing China 		reset.flags |= BE_32(UATH_CHAN_CCK);
253056f9a274Sfei feng - Sun Microsystems - Beijing China 	/* turbo can be used in either 2GHz or 5GHz */
253156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (c->ich_flags & IEEE80211_CHAN_TURBO)
253256f9a274Sfei feng - Sun Microsystems - Beijing China 		reset.flags |= BE_32(UATH_CHAN_TURBO);
253356f9a274Sfei feng - Sun Microsystems - Beijing China 
253456f9a274Sfei feng - Sun Microsystems - Beijing China 	reset.freq = BE_32(c->ich_freq);
253556f9a274Sfei feng - Sun Microsystems - Beijing China 	reset.maxrdpower = BE_32(50);	/* XXX */
253656f9a274Sfei feng - Sun Microsystems - Beijing China 	reset.channelchange = BE_32(1);
253756f9a274Sfei feng - Sun Microsystems - Beijing China 	reset.keeprccontent = BE_32(0);
253856f9a274Sfei feng - Sun Microsystems - Beijing China 
253956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_chan(): "
254056f9a274Sfei feng - Sun Microsystems - Beijing China 	    "set channel %d, flags 0x%x freq %u\n",
254156f9a274Sfei feng - Sun Microsystems - Beijing China 	    ieee80211_chan2ieee(ic, c),
254256f9a274Sfei feng - Sun Microsystems - Beijing China 	    BE_32(reset.flags), BE_32(reset.freq));
254356f9a274Sfei feng - Sun Microsystems - Beijing China 
254456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof (reset), 0));
254556f9a274Sfei feng - Sun Microsystems - Beijing China }
254656f9a274Sfei feng - Sun Microsystems - Beijing China 
254756f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_reset_tx_queues(struct uath_softc * sc)254856f9a274Sfei feng - Sun Microsystems - Beijing China uath_reset_tx_queues(struct uath_softc *sc)
254956f9a274Sfei feng - Sun Microsystems - Beijing China {
255056f9a274Sfei feng - Sun Microsystems - Beijing China 	int ac, err;
255156f9a274Sfei feng - Sun Microsystems - Beijing China 
255256f9a274Sfei feng - Sun Microsystems - Beijing China 	for (ac = 0; ac < 4; ac++) {
255356f9a274Sfei feng - Sun Microsystems - Beijing China 		const uint32_t qid = BE_32(ac);
255456f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid,
255556f9a274Sfei feng - Sun Microsystems - Beijing China 		    sizeof (qid), 0);
255656f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS)
255756f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
255856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
255956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
256056f9a274Sfei feng - Sun Microsystems - Beijing China }
256156f9a274Sfei feng - Sun Microsystems - Beijing China 
256256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_wme_init(struct uath_softc * sc)256356f9a274Sfei feng - Sun Microsystems - Beijing China uath_wme_init(struct uath_softc *sc)
256456f9a274Sfei feng - Sun Microsystems - Beijing China {
256556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX get from net80211 */
256656f9a274Sfei feng - Sun Microsystems - Beijing China 	static const struct uath_wme_settings uath_wme_11g[4] = {
256756f9a274Sfei feng - Sun Microsystems - Beijing China 		{ 7, 4, 10,  0, 0 },	/* Background */
256856f9a274Sfei feng - Sun Microsystems - Beijing China 		{ 3, 4, 10,  0, 0 },	/* Best-Effort */
256956f9a274Sfei feng - Sun Microsystems - Beijing China 		{ 3, 3,  4, 26, 0 },	/* Video */
257056f9a274Sfei feng - Sun Microsystems - Beijing China 		{ 2, 2,  3, 47, 0 }	/* Voice */
257156f9a274Sfei feng - Sun Microsystems - Beijing China 	};
257256f9a274Sfei feng - Sun Microsystems - Beijing China 
257356f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_cmd_txq_setup qinfo;
257456f9a274Sfei feng - Sun Microsystems - Beijing China 	int ac, err;
257556f9a274Sfei feng - Sun Microsystems - Beijing China 
257656f9a274Sfei feng - Sun Microsystems - Beijing China 	for (ac = 0; ac < 4; ac++) {
257756f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.qid		= BE_32(ac);
257856f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.len		= BE_32(sizeof (qinfo.attr));
257956f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.priority	= BE_32(ac);	/* XXX */
258056f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.aifs		= BE_32(uath_wme_11g[ac].aifsn);
258156f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.logcwmin	= BE_32(uath_wme_11g[ac].logcwmin);
258256f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.logcwmax	= BE_32(uath_wme_11g[ac].logcwmax);
258356f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.mode		= BE_32(uath_wme_11g[ac].acm);
258456f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.qflags	= BE_32(1);
258556f9a274Sfei feng - Sun Microsystems - Beijing China 		qinfo.attr.bursttime	=
258656f9a274Sfei feng - Sun Microsystems - Beijing China 		    BE_32(UATH_TXOP_TO_US(uath_wme_11g[ac].txop));
258756f9a274Sfei feng - Sun Microsystems - Beijing China 
258856f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo,
258956f9a274Sfei feng - Sun Microsystems - Beijing China 		    sizeof (qinfo), 0);
259056f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS)
259156f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
259256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
259356f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
259456f9a274Sfei feng - Sun Microsystems - Beijing China }
259556f9a274Sfei feng - Sun Microsystems - Beijing China 
259656f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_stop_locked(void * arg)259756f9a274Sfei feng - Sun Microsystems - Beijing China uath_stop_locked(void *arg)
259856f9a274Sfei feng - Sun Microsystems - Beijing China {
259956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
260056f9a274Sfei feng - Sun Microsystems - Beijing China 
260156f9a274Sfei feng - Sun Microsystems - Beijing China 	/* flush data & control requests into the target  */
260256f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_flush(sc);
260356f9a274Sfei feng - Sun Microsystems - Beijing China 
260456f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set a LED status to the disconnected.  */
260556f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_set_ledstate(sc, 0);
260656f9a274Sfei feng - Sun Microsystems - Beijing China 
260756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* stop the target  */
260856f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
260956f9a274Sfei feng - Sun Microsystems - Beijing China 
261056f9a274Sfei feng - Sun Microsystems - Beijing China 	/* abort any pending transfers */
261156f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_pipe_reset(sc->sc_dev, sc->rx_data_pipe, USB_FLAGS_SLEEP, NULL, 0);
261256f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_pipe_reset(sc->sc_dev, sc->tx_data_pipe, USB_FLAGS_SLEEP, NULL, 0);
261356f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_pipe_reset(sc->sc_dev, sc->tx_cmd_pipe, USB_FLAGS_SLEEP, NULL, 0);
261456f9a274Sfei feng - Sun Microsystems - Beijing China }
261556f9a274Sfei feng - Sun Microsystems - Beijing China 
261656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_init_locked(void * arg)261756f9a274Sfei feng - Sun Microsystems - Beijing China uath_init_locked(void *arg)
261856f9a274Sfei feng - Sun Microsystems - Beijing China {
261956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = arg;
262056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
262156f9a274Sfei feng - Sun Microsystems - Beijing China 	uint32_t val;
262256f9a274Sfei feng - Sun Microsystems - Beijing China 	int i, err;
262356f9a274Sfei feng - Sun Microsystems - Beijing China 
262456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (UATH_IS_RUNNING(sc))
262556f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_stop_locked(sc);
262656f9a274Sfei feng - Sun Microsystems - Beijing China 
262756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_init_data_queue(sc);
262856f9a274Sfei feng - Sun Microsystems - Beijing China 
262956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* reset variables */
263056f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_intrx_nextnum = sc->sc_msgid = 0;
263156f9a274Sfei feng - Sun Microsystems - Beijing China 
263256f9a274Sfei feng - Sun Microsystems - Beijing China 	val = BE_32(0);
263356f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof (val), 0);
263456f9a274Sfei feng - Sun Microsystems - Beijing China 
263556f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set MAC address */
263656f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_config_multi(sc, CFG_MAC_ADDR,
263756f9a274Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr, IEEE80211_ADDR_LEN);
263856f9a274Sfei feng - Sun Microsystems - Beijing China 
263956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX honor net80211 state */
264056f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
264156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001);
264256f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_ABOLT, 0x0000003f);
264356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_WME_ENABLED, 0x00000001);
264456f9a274Sfei feng - Sun Microsystems - Beijing China 
264556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_SERVICE_TYPE, 1);
264656f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_TP_SCALE, 0x00000000);
264756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c);
264856f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c);
264956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000);
265056f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000);
265156f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
265256f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000);
265356f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_config(sc, CFG_MODE_CTS, 0x00000002);
265456f9a274Sfei feng - Sun Microsystems - Beijing China 
265556f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0,
265656f9a274Sfei feng - Sun Microsystems - Beijing China 	    &val, sizeof (val), UATH_CMD_FLAG_MAGIC);
265756f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
265856f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): "
265956f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not start target\n");
266056f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
266156f9a274Sfei feng - Sun Microsystems - Beijing China 	}
266256f9a274Sfei feng - Sun Microsystems - Beijing China 
266356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_init_locked(): "
266456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "%s returns handle: 0x%x\n",
266556f9a274Sfei feng - Sun Microsystems - Beijing China 	    uath_codename(WDCMSG_TARGET_START), BE_32(val));
266656f9a274Sfei feng - Sun Microsystems - Beijing China 
266756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set default channel */
266856f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_switch_channel(sc, ic->ic_curchan);
266956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err) {
267056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): "
267156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not switch channel, error %d\n", err);
267256f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail;
267356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
267456f9a274Sfei feng - Sun Microsystems - Beijing China 
267556f9a274Sfei feng - Sun Microsystems - Beijing China 	val = BE_32(TARGET_DEVICE_AWAKE);
267656f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof (val), 0);
267756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* XXX? check */
267856f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
267956f9a274Sfei feng - Sun Microsystems - Beijing China 
268056f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
268156f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_rx_data_xfer(sc);
268256f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != UATH_SUCCESS) {
268356f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): "
268456f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not alloc rx xfer %x\n", i);
268556f9a274Sfei feng - Sun Microsystems - Beijing China 			goto fail;
268656f9a274Sfei feng - Sun Microsystems - Beijing China 		}
268756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
268856f9a274Sfei feng - Sun Microsystems - Beijing China 
268956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* enable Rx */
269056f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT);
269156f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) uath_set_rxfilter(sc,
269256f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
269356f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
269456f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_FILTER_OP_SET);
269556f9a274Sfei feng - Sun Microsystems - Beijing China 
269656f9a274Sfei feng - Sun Microsystems - Beijing China 	return (UATH_SUCCESS);
269756f9a274Sfei feng - Sun Microsystems - Beijing China 
269856f9a274Sfei feng - Sun Microsystems - Beijing China fail:
269956f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_stop_locked(sc);
270056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
270156f9a274Sfei feng - Sun Microsystems - Beijing China }
270256f9a274Sfei feng - Sun Microsystems - Beijing China 
270356f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_init(struct uath_softc * sc)270456f9a274Sfei feng - Sun Microsystems - Beijing China uath_init(struct uath_softc *sc)
270556f9a274Sfei feng - Sun Microsystems - Beijing China {
270656f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
270756f9a274Sfei feng - Sun Microsystems - Beijing China 
270856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
270956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_init_locked(sc);
271056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
271156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init(): "
271256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to initialize uath hardware\n");
271356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
271456f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
271556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
271656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
271756f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
271856f9a274Sfei feng - Sun Microsystems - Beijing China }
271956f9a274Sfei feng - Sun Microsystems - Beijing China 
272056f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_stop(struct uath_softc * sc)272156f9a274Sfei feng - Sun Microsystems - Beijing China uath_stop(struct uath_softc *sc)
272256f9a274Sfei feng - Sun Microsystems - Beijing China {
272356f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_stop(): "
272456f9a274Sfei feng - Sun Microsystems - Beijing China 	    "uath stop now\n");
272556f9a274Sfei feng - Sun Microsystems - Beijing China 
272656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
272756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_stop_locked(sc);
272856f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
272956f9a274Sfei feng - Sun Microsystems - Beijing China }
273056f9a274Sfei feng - Sun Microsystems - Beijing China 
273156f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_resume(struct uath_softc * sc)273256f9a274Sfei feng - Sun Microsystems - Beijing China uath_resume(struct uath_softc *sc)
273356f9a274Sfei feng - Sun Microsystems - Beijing China {
273456f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
273556f9a274Sfei feng - Sun Microsystems - Beijing China 
273656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): "
273756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "uath resume now\n");
273856f9a274Sfei feng - Sun Microsystems - Beijing China 
273956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* check device changes after suspend */
274056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1,
274156f9a274Sfei feng - Sun Microsystems - Beijing China 	    USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
274256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume: "
274356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "no or different device connected\n");
274456f9a274Sfei feng - Sun Microsystems - Beijing China 		return;
274556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
274656f9a274Sfei feng - Sun Microsystems - Beijing China 
274756f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
274856f9a274Sfei feng - Sun Microsystems - Beijing China 	 * initialize hardware
274956f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
275056f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_init_cmd_list(sc);
275156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
275256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): "
275356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not init RX command list\n");
275456f9a274Sfei feng - Sun Microsystems - Beijing China 		return;
275556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
275656f9a274Sfei feng - Sun Microsystems - Beijing China 
275756f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_init(sc);
275856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
275956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): "
276056f9a274Sfei feng - Sun Microsystems - Beijing China 		    "hardware init failed\n");
276156f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_stop(sc);
276256f9a274Sfei feng - Sun Microsystems - Beijing China 		return;
276356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
276456f9a274Sfei feng - Sun Microsystems - Beijing China 
276556f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
276656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
276756f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags &= ~UATH_FLAG_SUSPEND;
276856f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= UATH_FLAG_RUNNING;
276956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
277056f9a274Sfei feng - Sun Microsystems - Beijing China }
277156f9a274Sfei feng - Sun Microsystems - Beijing China 
277256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_start(void * arg)277356f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_start(void *arg)
277456f9a274Sfei feng - Sun Microsystems - Beijing China {
277556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
277656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
277756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
277856f9a274Sfei feng - Sun Microsystems - Beijing China 
277956f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
278056f9a274Sfei feng - Sun Microsystems - Beijing China 	 * initialize hardware
278156f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
278256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_init(sc);
278356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
278456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_m_start(): "
278556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "device configuration failed\n");
278656f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_stop(sc);
278756f9a274Sfei feng - Sun Microsystems - Beijing China 		return (err);
278856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
278956f9a274Sfei feng - Sun Microsystems - Beijing China 
279056f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
279156f9a274Sfei feng - Sun Microsystems - Beijing China 
279256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
279356f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= UATH_FLAG_RUNNING;
279456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
279556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
279656f9a274Sfei feng - Sun Microsystems - Beijing China }
279756f9a274Sfei feng - Sun Microsystems - Beijing China 
279856f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_m_stop(void * arg)279956f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_stop(void *arg)
280056f9a274Sfei feng - Sun Microsystems - Beijing China {
280156f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
280256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
280356f9a274Sfei feng - Sun Microsystems - Beijing China 
280456f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
280556f9a274Sfei feng - Sun Microsystems - Beijing China 
280656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (!UATH_IS_DISCONNECT(sc))
280756f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_stop(sc);
280856f9a274Sfei feng - Sun Microsystems - Beijing China 
280956f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
281056f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags &= ~UATH_FLAG_RUNNING;
281156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
281256f9a274Sfei feng - Sun Microsystems - Beijing China }
281356f9a274Sfei feng - Sun Microsystems - Beijing China 
281456f9a274Sfei feng - Sun Microsystems - Beijing China static void
uath_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)281556f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
281656f9a274Sfei feng - Sun Microsystems - Beijing China {
281756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
281856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
281956f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
282056f9a274Sfei feng - Sun Microsystems - Beijing China 
282156f9a274Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_ioctl(ic, wq, mp);
282256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
282356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
282456f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
282556f9a274Sfei feng - Sun Microsystems - Beijing China 			if (UATH_IS_RUNNING(sc)) {
282656f9a274Sfei feng - Sun Microsystems - Beijing China 				UATH_UNLOCK(sc);
282756f9a274Sfei feng - Sun Microsystems - Beijing China 				(void) uath_init(sc);
282856f9a274Sfei feng - Sun Microsystems - Beijing China 				(void) ieee80211_new_state(ic,
282956f9a274Sfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_SCAN, -1);
283056f9a274Sfei feng - Sun Microsystems - Beijing China 				UATH_LOCK(sc);
283156f9a274Sfei feng - Sun Microsystems - Beijing China 			}
283256f9a274Sfei feng - Sun Microsystems - Beijing China 		}
283356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
283456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
283556f9a274Sfei feng - Sun Microsystems - Beijing China }
283656f9a274Sfei feng - Sun Microsystems - Beijing China 
283756f9a274Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
283856f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_unicst(void * arg,const uint8_t * macaddr)283956f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_unicst(void *arg, const uint8_t *macaddr)
284056f9a274Sfei feng - Sun Microsystems - Beijing China {
284156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (0);
284256f9a274Sfei feng - Sun Microsystems - Beijing China }
284356f9a274Sfei feng - Sun Microsystems - Beijing China 
284456f9a274Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
284556f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_multicst(void * arg,boolean_t add,const uint8_t * mca)284656f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
284756f9a274Sfei feng - Sun Microsystems - Beijing China {
284856f9a274Sfei feng - Sun Microsystems - Beijing China 	return (0);
284956f9a274Sfei feng - Sun Microsystems - Beijing China }
285056f9a274Sfei feng - Sun Microsystems - Beijing China 
285156f9a274Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
285256f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_promisc(void * arg,boolean_t on)285356f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_promisc(void *arg, boolean_t on)
285456f9a274Sfei feng - Sun Microsystems - Beijing China {
285556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (0);
285656f9a274Sfei feng - Sun Microsystems - Beijing China }
285756f9a274Sfei feng - Sun Microsystems - Beijing China 
285856f9a274Sfei feng - Sun Microsystems - Beijing China /*
285956f9a274Sfei feng - Sun Microsystems - Beijing China  * callback functions for /get/set properties
286056f9a274Sfei feng - Sun Microsystems - Beijing China  */
286156f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)286256f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
286356f9a274Sfei feng - Sun Microsystems - Beijing China     uint_t wldp_length, const void *wldp_buf)
286456f9a274Sfei feng - Sun Microsystems - Beijing China {
286556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
286656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
286756f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
286856f9a274Sfei feng - Sun Microsystems - Beijing China 
286956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
287056f9a274Sfei feng - Sun Microsystems - Beijing China 	    wldp_length, wldp_buf);
287156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
287256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
287356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen && UATH_IS_RUNNING(sc)) {
287456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_UNLOCK(sc);
287556f9a274Sfei feng - Sun Microsystems - Beijing China 			(void) uath_init(sc);
287656f9a274Sfei feng - Sun Microsystems - Beijing China 			(void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
287756f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_LOCK(sc);
287856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
287956f9a274Sfei feng - Sun Microsystems - Beijing China 		err = 0;
288056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
288156f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
288256f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
288356f9a274Sfei feng - Sun Microsystems - Beijing China }
288456f9a274Sfei feng - Sun Microsystems - Beijing China 
288556f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)288656f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
28870dc2366fSVenugopal Iyer     uint_t wldp_length, void *wldp_buf)
288856f9a274Sfei feng - Sun Microsystems - Beijing China {
288956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
289056f9a274Sfei feng - Sun Microsystems - Beijing China 	int err;
289156f9a274Sfei feng - Sun Microsystems - Beijing China 
289256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
28930dc2366fSVenugopal Iyer 	    wldp_length, wldp_buf);
289456f9a274Sfei feng - Sun Microsystems - Beijing China 	return (err);
289556f9a274Sfei feng - Sun Microsystems - Beijing China }
289656f9a274Sfei feng - Sun Microsystems - Beijing China 
28970dc2366fSVenugopal Iyer static void
uath_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t prh)28980dc2366fSVenugopal Iyer uath_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
28990dc2366fSVenugopal Iyer     mac_prop_info_handle_t prh)
29000dc2366fSVenugopal Iyer {
29010dc2366fSVenugopal Iyer 	struct uath_softc *sc = (struct uath_softc *)arg;
29020dc2366fSVenugopal Iyer 
29030dc2366fSVenugopal Iyer 	ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, prh);
29040dc2366fSVenugopal Iyer }
29050dc2366fSVenugopal Iyer 
290656f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_m_stat(void * arg,uint_t stat,uint64_t * val)290756f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_stat(void *arg, uint_t stat, uint64_t *val)
290856f9a274Sfei feng - Sun Microsystems - Beijing China {
290956f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc  = (struct uath_softc *)arg;
291056f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
291156f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = NULL;
291256f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_rateset *rs = NULL;
291356f9a274Sfei feng - Sun Microsystems - Beijing China 
291456f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_LOCK(sc);
291556f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (stat) {
291656f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IFSPEED:
291756f9a274Sfei feng - Sun Microsystems - Beijing China 		ni = ic->ic_bss;
291856f9a274Sfei feng - Sun Microsystems - Beijing China 		rs = &ni->in_rates;
291956f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
292056f9a274Sfei feng - Sun Microsystems - Beijing China 		    (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
292156f9a274Sfei feng - Sun Microsystems - Beijing China 		    : ic->ic_fixed_rate) * 5000000ull;
292256f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
292356f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NOXMTBUF:
292456f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_nobuf;
292556f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
292656f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NORCVBUF:
292756f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_nobuf;
292856f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
292956f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IERRORS:
293056f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_err;
293156f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
293256f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_RBYTES:
293356f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_bytes;
293456f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
293556f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IPACKETS:
293656f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_frags;
293756f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
293856f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OBYTES:
293956f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_bytes;
294056f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
294156f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OPACKETS:
294256f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_frags;
294356f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
294456f9a274Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OERRORS:
294556f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FAILED:
294656f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_err;
294756f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
294856f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_RETRANS:
294956f9a274Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_retries;
295056f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
295156f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_FCS_ERRORS:
295256f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_WEP_ERRORS:
295356f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FRAGS:
295456f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_TX:
295556f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_SUCCESS:
295656f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_FAILURE:
295756f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_ACK_FAILURE:
295856f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_FRAGS:
295956f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_RX:
296056f9a274Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_DUPS:
296156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
296256f9a274Sfei feng - Sun Microsystems - Beijing China 		return (ieee80211_stat(ic, stat, val));
296356f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
296456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
296556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (ENOTSUP);
296656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
296756f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_UNLOCK(sc);
296856f9a274Sfei feng - Sun Microsystems - Beijing China 
296956f9a274Sfei feng - Sun Microsystems - Beijing China 	return (0);
297056f9a274Sfei feng - Sun Microsystems - Beijing China }
297156f9a274Sfei feng - Sun Microsystems - Beijing China 
297256f9a274Sfei feng - Sun Microsystems - Beijing China static mblk_t *
uath_m_tx(void * arg,mblk_t * mp)297356f9a274Sfei feng - Sun Microsystems - Beijing China uath_m_tx(void *arg, mblk_t *mp)
297456f9a274Sfei feng - Sun Microsystems - Beijing China {
297556f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc = (struct uath_softc *)arg;
297656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
297756f9a274Sfei feng - Sun Microsystems - Beijing China 	mblk_t *next;
297856f9a274Sfei feng - Sun Microsystems - Beijing China 
297956f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
298056f9a274Sfei feng - Sun Microsystems - Beijing China 	 * No data frames go out unless we're associated; this
298156f9a274Sfei feng - Sun Microsystems - Beijing China 	 * should not happen as the 802.11 layer does not enable
298256f9a274Sfei feng - Sun Microsystems - Beijing China 	 * the xmit queue until we enter the RUN state.
298356f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
298456f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((ic->ic_state != IEEE80211_S_RUN) ||
298556f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_IS_SUSPEND(sc)) {
298656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_MSG, "uath: uath_m_tx(): "
298756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "discard, state %u\n", ic->ic_state);
298856f9a274Sfei feng - Sun Microsystems - Beijing China 		freemsgchain(mp);
298956f9a274Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
299056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
299156f9a274Sfei feng - Sun Microsystems - Beijing China 
299256f9a274Sfei feng - Sun Microsystems - Beijing China 	while (mp != NULL) {
299356f9a274Sfei feng - Sun Microsystems - Beijing China 		next = mp->b_next;
299456f9a274Sfei feng - Sun Microsystems - Beijing China 		mp->b_next = NULL;
299556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (uath_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) {
299656f9a274Sfei feng - Sun Microsystems - Beijing China 			mp->b_next = next;
299756f9a274Sfei feng - Sun Microsystems - Beijing China 			break;
299856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
299956f9a274Sfei feng - Sun Microsystems - Beijing China 		mp = next;
300056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
300156f9a274Sfei feng - Sun Microsystems - Beijing China 	return (mp);
300256f9a274Sfei feng - Sun Microsystems - Beijing China }
300356f9a274Sfei feng - Sun Microsystems - Beijing China 
300456f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)300556f9a274Sfei feng - Sun Microsystems - Beijing China uath_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
300656f9a274Sfei feng - Sun Microsystems - Beijing China {
300756f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc;
300856f9a274Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic;
300956f9a274Sfei feng - Sun Microsystems - Beijing China 
301056f9a274Sfei feng - Sun Microsystems - Beijing China 	int i, err, instance;
301156f9a274Sfei feng - Sun Microsystems - Beijing China 	char strbuf[32];
301256f9a274Sfei feng - Sun Microsystems - Beijing China 	uint16_t vendor_id, product_id;
301356f9a274Sfei feng - Sun Microsystems - Beijing China 
301456f9a274Sfei feng - Sun Microsystems - Beijing China 	wifi_data_t wd = { 0 };
301556f9a274Sfei feng - Sun Microsystems - Beijing China 	mac_register_t *macp;
301656f9a274Sfei feng - Sun Microsystems - Beijing China 
301756f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
301856f9a274Sfei feng - Sun Microsystems - Beijing China 	case DDI_ATTACH:
301956f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
302056f9a274Sfei feng - Sun Microsystems - Beijing China 	case DDI_RESUME:
302156f9a274Sfei feng - Sun Microsystems - Beijing China 		sc = ddi_get_soft_state(uath_soft_state_p,
302256f9a274Sfei feng - Sun Microsystems - Beijing China 		    ddi_get_instance(devinfo));
302356f9a274Sfei feng - Sun Microsystems - Beijing China 		ASSERT(sc != NULL);
302456f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_resume(sc);
302556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
302656f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
302756f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
302856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
302956f9a274Sfei feng - Sun Microsystems - Beijing China 
303056f9a274Sfei feng - Sun Microsystems - Beijing China 	instance = ddi_get_instance(devinfo);
303156f9a274Sfei feng - Sun Microsystems - Beijing China 	err = ddi_soft_state_zalloc(uath_soft_state_p, instance);
303256f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
303356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
303456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "ddi_soft_state_zalloc failed\n");
303556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
303656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
303756f9a274Sfei feng - Sun Microsystems - Beijing China 
303856f9a274Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(uath_soft_state_p, instance);
303956f9a274Sfei feng - Sun Microsystems - Beijing China 	ic = (ieee80211com_t *)&sc->sc_ic;
304056f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_dev = devinfo;
304156f9a274Sfei feng - Sun Microsystems - Beijing China 
304256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_client_attach(devinfo, USBDRV_VERSION, 0);
304356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
304456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
304556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "usb_client_attach failed\n");
304656f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
304756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
304856f9a274Sfei feng - Sun Microsystems - Beijing China 
304956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_get_dev_data(devinfo, &sc->sc_udev, USB_PARSE_LVL_ALL, 0);
305056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
305156f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_udev = NULL;
305256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
305356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "usb_get_dev_data failed\n");
305456f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
305556f9a274Sfei feng - Sun Microsystems - Beijing China 	}
305656f9a274Sfei feng - Sun Microsystems - Beijing China 
305756f9a274Sfei feng - Sun Microsystems - Beijing China 	vendor_id = sc->sc_udev->dev_descr->idVendor;
305856f9a274Sfei feng - Sun Microsystems - Beijing China 	product_id = sc->sc_udev->dev_descr->idProduct;
305956f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->dev_flags = uath_lookup(vendor_id, product_id);
306056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->dev_flags == UATH_FLAG_ERR) {
306156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
306256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "HW does not match\n");
306356f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
306456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
306556f9a274Sfei feng - Sun Microsystems - Beijing China 
306656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): "
306756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "vendorId = %x,deviceID = %x, flags = %x\n",
306856f9a274Sfei feng - Sun Microsystems - Beijing China 	    vendor_id, product_id, sc->dev_flags);
306956f9a274Sfei feng - Sun Microsystems - Beijing China 
307056f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
307156f9a274Sfei feng - Sun Microsystems - Beijing China 	 * We must open the pipes early because they're used to upload the
307256f9a274Sfei feng - Sun Microsystems - Beijing China 	 * firmware (pre-firmware devices) or to send firmware commands.
307356f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
307456f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_open_pipes(sc);
307556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
307656f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
307756f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not open pipes\n");
307856f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail3;
307956f9a274Sfei feng - Sun Microsystems - Beijing China 	}
308056f9a274Sfei feng - Sun Microsystems - Beijing China 
308156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->dev_flags & UATH_FLAG_PRE_FIRMWARE) {
308256f9a274Sfei feng - Sun Microsystems - Beijing China 		err = uath_loadfirmware(sc);
308356f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
308456f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
308556f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not read firmware %s, err %d\n",
308656f9a274Sfei feng - Sun Microsystems - Beijing China 			    "uath-ar5523", err);
308756f9a274Sfei feng - Sun Microsystems - Beijing China 			goto fail3;
308856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
308956f9a274Sfei feng - Sun Microsystems - Beijing China 
309056f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_close_pipes(sc);
309156f9a274Sfei feng - Sun Microsystems - Beijing China 		usb_client_detach(sc->sc_dev, sc->sc_udev);
309256f9a274Sfei feng - Sun Microsystems - Beijing China 
309356f9a274Sfei feng - Sun Microsystems - Beijing China 		err = usb_reset_device(devinfo, USB_RESET_LVL_REATTACH);
309456f9a274Sfei feng - Sun Microsystems - Beijing China 		if (err != USB_SUCCESS) {
309556f9a274Sfei feng - Sun Microsystems - Beijing China 			UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
309656f9a274Sfei feng - Sun Microsystems - Beijing China 			    "could not re-attach, err %d\n", err);
309756f9a274Sfei feng - Sun Microsystems - Beijing China 			goto fail1;
309856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
309956f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
310056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
310156f9a274Sfei feng - Sun Microsystems - Beijing China 
310256f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): "
310356f9a274Sfei feng - Sun Microsystems - Beijing China 	    "firmware download and re-attach successfully\n");
310456f9a274Sfei feng - Sun Microsystems - Beijing China 
310556f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
310656f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Only post-firmware devices here.
310756f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
310856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
310956f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_rxlock_cmd, NULL, MUTEX_DRIVER, NULL);
311056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_txlock_cmd, NULL, MUTEX_DRIVER, NULL);
311156f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_rxlock_data, NULL, MUTEX_DRIVER, NULL);
311256f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_txlock_data, NULL, MUTEX_DRIVER, NULL);
311356f9a274Sfei feng - Sun Microsystems - Beijing China 
311456f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
311556f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Allocate xfers for firmware commands.
311656f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
311756f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
311856f9a274Sfei feng - Sun Microsystems - Beijing China 	    UATH_MAX_CMDSZ);
311956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
312056f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
312156f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not allocate Tx command list\n");
312256f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail4;
312356f9a274Sfei feng - Sun Microsystems - Beijing China 	}
312456f9a274Sfei feng - Sun Microsystems - Beijing China 
312556f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_init_cmd_list(sc);
312656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
312756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
312856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not init RX command list\n");
312956f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
313056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
313156f9a274Sfei feng - Sun Microsystems - Beijing China 
313256f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
313356f9a274Sfei feng - Sun Microsystems - Beijing China 	 * We're now ready to send+receive firmware commands.
313456f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
313556f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_host_available(sc);
313656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
313756f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
313856f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not initialize adapter\n");
313956f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
314056f9a274Sfei feng - Sun Microsystems - Beijing China 	}
314156f9a274Sfei feng - Sun Microsystems - Beijing China 
314256f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_get_devcap(sc);
314356f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
314456f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
314556f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not get device capabilities\n");
314656f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
314756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
314856f9a274Sfei feng - Sun Microsystems - Beijing China 
314956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = uath_get_devstatus(sc, ic->ic_macaddr);
315056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != UATH_SUCCESS) {
315156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
315256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "could not get dev status\n");
315356f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
315456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
315556f9a274Sfei feng - Sun Microsystems - Beijing China 
315656f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): "
315756f9a274Sfei feng - Sun Microsystems - Beijing China 	    "MAC address is: %x:%x:%x:%x:%x:%x\n",
315856f9a274Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
315956f9a274Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]);
316056f9a274Sfei feng - Sun Microsystems - Beijing China 
316156f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
316256f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
316356f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_state = IEEE80211_S_INIT;
316456f9a274Sfei feng - Sun Microsystems - Beijing China 
316556f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_maxrssi = 40;
316656f9a274Sfei feng - Sun Microsystems - Beijing China 
316756f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_xmit = uath_send;
316856f9a274Sfei feng - Sun Microsystems - Beijing China 
316956f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set device capabilities */
317056f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_caps =
317156f9a274Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_TXPMGT |	/* tx power management */
317256f9a274Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
317356f9a274Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_SHSLOT;		/* short slot time supported */
317456f9a274Sfei feng - Sun Microsystems - Beijing China 
317556f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_caps |= IEEE80211_C_WPA;  /* Support WPA/WPA2 */
317656f9a274Sfei feng - Sun Microsystems - Beijing China 
317756f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set supported .11b and .11g rates */
317856f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11B] = uath_rateset_11b;
317956f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11G] = uath_rateset_11g;
318056f9a274Sfei feng - Sun Microsystems - Beijing China 
318156f9a274Sfei feng - Sun Microsystems - Beijing China 	/* set supported .11b and .11g channels (1 through 11) */
318256f9a274Sfei feng - Sun Microsystems - Beijing China 	for (i = 1; i <= 11; i++) {
318356f9a274Sfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_freq =
318456f9a274Sfei feng - Sun Microsystems - Beijing China 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
318556f9a274Sfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_flags =
318656f9a274Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
318756f9a274Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
318856f9a274Sfei feng - Sun Microsystems - Beijing China 	}
318956f9a274Sfei feng - Sun Microsystems - Beijing China 
319056f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_attach(ic);
319156f9a274Sfei feng - Sun Microsystems - Beijing China 
319256f9a274Sfei feng - Sun Microsystems - Beijing China 	/* register WPA door */
319356f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_register_door(ic, ddi_driver_name(devinfo),
319456f9a274Sfei feng - Sun Microsystems - Beijing China 	    ddi_get_instance(devinfo));
319556f9a274Sfei feng - Sun Microsystems - Beijing China 
319656f9a274Sfei feng - Sun Microsystems - Beijing China 	/* override state transition machine */
319756f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_newstate = ic->ic_newstate;
319856f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_newstate = uath_newstate;
319956f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_media_init(ic);
320056f9a274Sfei feng - Sun Microsystems - Beijing China 	ic->ic_def_txkey = 0;
320156f9a274Sfei feng - Sun Microsystems - Beijing China 
320256f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags = 0;
320356f9a274Sfei feng - Sun Microsystems - Beijing China 
320456f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
320556f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Provide initial settings for the WiFi plugin; whenever this
320656f9a274Sfei feng - Sun Microsystems - Beijing China 	 * information changes, we need to call mac_plugindata_update()
320756f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
320856f9a274Sfei feng - Sun Microsystems - Beijing China 	wd.wd_opmode = ic->ic_opmode;
320956f9a274Sfei feng - Sun Microsystems - Beijing China 	wd.wd_secalloc = WIFI_SEC_NONE;
321056f9a274Sfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
321156f9a274Sfei feng - Sun Microsystems - Beijing China 
321256f9a274Sfei feng - Sun Microsystems - Beijing China 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
321356f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath_attach(): "
321456f9a274Sfei feng - Sun Microsystems - Beijing China 		    "MAC version mismatch\n");
321556f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
321656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
321756f9a274Sfei feng - Sun Microsystems - Beijing China 
321856f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
321956f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_driver		= sc;
322056f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_dip		= devinfo;
322156f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_src_addr	= ic->ic_macaddr;
322256f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_callbacks	= &uath_m_callbacks;
322356f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_min_sdu		= 0;
322456f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_max_sdu		= IEEE80211_MTU;
322556f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_pdata		= &wd;
322656f9a274Sfei feng - Sun Microsystems - Beijing China 	macp->m_pdata_size	= sizeof (wd);
322756f9a274Sfei feng - Sun Microsystems - Beijing China 
322856f9a274Sfei feng - Sun Microsystems - Beijing China 	err = mac_register(macp, &ic->ic_mach);
322956f9a274Sfei feng - Sun Microsystems - Beijing China 	mac_free(macp);
323056f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != 0) {
323156f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath_attach(): "
323256f9a274Sfei feng - Sun Microsystems - Beijing China 		    "mac_register() error %x\n", err);
323356f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
323456f9a274Sfei feng - Sun Microsystems - Beijing China 	};
323556f9a274Sfei feng - Sun Microsystems - Beijing China 
323656f9a274Sfei feng - Sun Microsystems - Beijing China 	err = usb_register_hotplug_cbs(devinfo,
323756f9a274Sfei feng - Sun Microsystems - Beijing China 	    uath_disconnect, uath_reconnect);
323856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
323956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
324056f9a274Sfei feng - Sun Microsystems - Beijing China 		    "failed to register events\n");
324156f9a274Sfei feng - Sun Microsystems - Beijing China 		goto fail6;
324256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
324356f9a274Sfei feng - Sun Microsystems - Beijing China 
324456f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
324556f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Create minor node of type DDI_NT_NET_WIFI
324656f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
324756f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) snprintf(strbuf, sizeof (strbuf), "%s%d",
324856f9a274Sfei feng - Sun Microsystems - Beijing China 	    "uath", instance);
324956f9a274Sfei feng - Sun Microsystems - Beijing China 	err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
325056f9a274Sfei feng - Sun Microsystems - Beijing China 	    instance + 1, DDI_NT_NET_WIFI, 0);
325156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
325256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): "
325356f9a274Sfei feng - Sun Microsystems - Beijing China 		    "ddi_create_minor_node() failed\n");
325456f9a274Sfei feng - Sun Microsystems - Beijing China 
325556f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
325656f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Notify link is down now
325756f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
325856f9a274Sfei feng - Sun Microsystems - Beijing China 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
325956f9a274Sfei feng - Sun Microsystems - Beijing China 
326056f9a274Sfei feng - Sun Microsystems - Beijing China 	UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): "
326156f9a274Sfei feng - Sun Microsystems - Beijing China 	    "attach success\n");
326256f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
326356f9a274Sfei feng - Sun Microsystems - Beijing China 
326456f9a274Sfei feng - Sun Microsystems - Beijing China fail6:
326556f9a274Sfei feng - Sun Microsystems - Beijing China 	(void) mac_unregister(ic->ic_mach);
326656f9a274Sfei feng - Sun Microsystems - Beijing China fail5:
326756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT);
326856f9a274Sfei feng - Sun Microsystems - Beijing China fail4:
326956f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_genlock);
327056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock_cmd);
327156f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock_data);
327256f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock_cmd);
327356f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock_data);
327456f9a274Sfei feng - Sun Microsystems - Beijing China fail3:
327556f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_close_pipes(sc);
327656f9a274Sfei feng - Sun Microsystems - Beijing China fail2:
327756f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_client_detach(sc->sc_dev, sc->sc_udev);
327856f9a274Sfei feng - Sun Microsystems - Beijing China fail1:
327956f9a274Sfei feng - Sun Microsystems - Beijing China 	ddi_soft_state_free(uath_soft_state_p, ddi_get_instance(devinfo));
328056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
328156f9a274Sfei feng - Sun Microsystems - Beijing China }
328256f9a274Sfei feng - Sun Microsystems - Beijing China 
328356f9a274Sfei feng - Sun Microsystems - Beijing China static int
uath_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)328456f9a274Sfei feng - Sun Microsystems - Beijing China uath_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
328556f9a274Sfei feng - Sun Microsystems - Beijing China {
328656f9a274Sfei feng - Sun Microsystems - Beijing China 	struct uath_softc *sc;
328756f9a274Sfei feng - Sun Microsystems - Beijing China 
328856f9a274Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo));
328956f9a274Sfei feng - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
329056f9a274Sfei feng - Sun Microsystems - Beijing China 
329156f9a274Sfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
329256f9a274Sfei feng - Sun Microsystems - Beijing China 	case DDI_DETACH:
329356f9a274Sfei feng - Sun Microsystems - Beijing China 		break;
329456f9a274Sfei feng - Sun Microsystems - Beijing China 	case DDI_SUSPEND:
329556f9a274Sfei feng - Sun Microsystems - Beijing China 		if (UATH_IS_RUNNING(sc)) {
329656f9a274Sfei feng - Sun Microsystems - Beijing China 			ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
329756f9a274Sfei feng - Sun Microsystems - Beijing China 			uath_stop(sc);
329856f9a274Sfei feng - Sun Microsystems - Beijing China 		}
329956f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_LOCK(sc);
330056f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags &= ~UATH_FLAG_RUNNING;
330156f9a274Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags |= UATH_FLAG_SUSPEND;
330256f9a274Sfei feng - Sun Microsystems - Beijing China 		UATH_UNLOCK(sc);
330356f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
330456f9a274Sfei feng - Sun Microsystems - Beijing China 	default:
330556f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
330656f9a274Sfei feng - Sun Microsystems - Beijing China 	}
330756f9a274Sfei feng - Sun Microsystems - Beijing China 
330856f9a274Sfei feng - Sun Microsystems - Beijing China 	if (sc->dev_flags & UATH_FLAG_PRE_FIRMWARE) {
330956f9a274Sfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_free(uath_soft_state_p,
331056f9a274Sfei feng - Sun Microsystems - Beijing China 		    ddi_get_instance(devinfo));
331156f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
331256f9a274Sfei feng - Sun Microsystems - Beijing China 	}
331356f9a274Sfei feng - Sun Microsystems - Beijing China 
331456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (!UATH_IS_DISCONNECT(sc) && UATH_IS_RUNNING(sc))
331556f9a274Sfei feng - Sun Microsystems - Beijing China 		uath_stop(sc);
331656f9a274Sfei feng - Sun Microsystems - Beijing China 
331756f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT);
331856f9a274Sfei feng - Sun Microsystems - Beijing China 
331956f9a274Sfei feng - Sun Microsystems - Beijing China 	if (mac_disable(sc->sc_ic.ic_mach) != 0)
332056f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
332156f9a274Sfei feng - Sun Microsystems - Beijing China 
332256f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
332356f9a274Sfei feng - Sun Microsystems - Beijing China 	 * Unregister from the MAC layer subsystem
332456f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
332556f9a274Sfei feng - Sun Microsystems - Beijing China 	if (mac_unregister(sc->sc_ic.ic_mach) != 0)
332656f9a274Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
332756f9a274Sfei feng - Sun Microsystems - Beijing China 
332856f9a274Sfei feng - Sun Microsystems - Beijing China 	/*
332956f9a274Sfei feng - Sun Microsystems - Beijing China 	 * detach ieee80211 layer
333056f9a274Sfei feng - Sun Microsystems - Beijing China 	 */
333156f9a274Sfei feng - Sun Microsystems - Beijing China 	ieee80211_detach(&sc->sc_ic);
333256f9a274Sfei feng - Sun Microsystems - Beijing China 
333356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* close Tx/Rx pipes */
333456f9a274Sfei feng - Sun Microsystems - Beijing China 	uath_close_pipes(sc);
333556f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_unregister_hotplug_cbs(devinfo);
333656f9a274Sfei feng - Sun Microsystems - Beijing China 
333756f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_genlock);
333856f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock_cmd);
333956f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock_data);
334056f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock_cmd);
334156f9a274Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock_data);
334256f9a274Sfei feng - Sun Microsystems - Beijing China 
334356f9a274Sfei feng - Sun Microsystems - Beijing China 	/* pipes will be close in uath_stop() */
334456f9a274Sfei feng - Sun Microsystems - Beijing China 	usb_client_detach(devinfo, sc->sc_udev);
334556f9a274Sfei feng - Sun Microsystems - Beijing China 	sc->sc_udev = NULL;
334656f9a274Sfei feng - Sun Microsystems - Beijing China 
334756f9a274Sfei feng - Sun Microsystems - Beijing China 	ddi_remove_minor_node(devinfo, NULL);
334856f9a274Sfei feng - Sun Microsystems - Beijing China 	ddi_soft_state_free(uath_soft_state_p, ddi_get_instance(devinfo));
334956f9a274Sfei feng - Sun Microsystems - Beijing China 
335056f9a274Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
335156f9a274Sfei feng - Sun Microsystems - Beijing China }
335256f9a274Sfei feng - Sun Microsystems - Beijing China 
335356f9a274Sfei feng - Sun Microsystems - Beijing China int
_info(struct modinfo * modinfop)335456f9a274Sfei feng - Sun Microsystems - Beijing China _info(struct modinfo *modinfop)
335556f9a274Sfei feng - Sun Microsystems - Beijing China {
335656f9a274Sfei feng - Sun Microsystems - Beijing China 	return (mod_info(&modlinkage, modinfop));
335756f9a274Sfei feng - Sun Microsystems - Beijing China }
335856f9a274Sfei feng - Sun Microsystems - Beijing China 
335956f9a274Sfei feng - Sun Microsystems - Beijing China int
_init(void)336056f9a274Sfei feng - Sun Microsystems - Beijing China _init(void)
336156f9a274Sfei feng - Sun Microsystems - Beijing China {
336256f9a274Sfei feng - Sun Microsystems - Beijing China 	int status;
336356f9a274Sfei feng - Sun Microsystems - Beijing China 
336456f9a274Sfei feng - Sun Microsystems - Beijing China 	status = ddi_soft_state_init(&uath_soft_state_p,
336556f9a274Sfei feng - Sun Microsystems - Beijing China 	    sizeof (struct uath_softc), 1);
336656f9a274Sfei feng - Sun Microsystems - Beijing China 	if (status != 0)
336756f9a274Sfei feng - Sun Microsystems - Beijing China 		return (status);
336856f9a274Sfei feng - Sun Microsystems - Beijing China 
336956f9a274Sfei feng - Sun Microsystems - Beijing China 	mac_init_ops(&uath_dev_ops, "uath");
337056f9a274Sfei feng - Sun Microsystems - Beijing China 	status = mod_install(&modlinkage);
337156f9a274Sfei feng - Sun Microsystems - Beijing China 	if (status != 0) {
337256f9a274Sfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&uath_dev_ops);
337356f9a274Sfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&uath_soft_state_p);
337456f9a274Sfei feng - Sun Microsystems - Beijing China 	}
337556f9a274Sfei feng - Sun Microsystems - Beijing China 	return (status);
337656f9a274Sfei feng - Sun Microsystems - Beijing China }
337756f9a274Sfei feng - Sun Microsystems - Beijing China 
337856f9a274Sfei feng - Sun Microsystems - Beijing China int
_fini(void)337956f9a274Sfei feng - Sun Microsystems - Beijing China _fini(void)
338056f9a274Sfei feng - Sun Microsystems - Beijing China {
338156f9a274Sfei feng - Sun Microsystems - Beijing China 	int status;
338256f9a274Sfei feng - Sun Microsystems - Beijing China 
338356f9a274Sfei feng - Sun Microsystems - Beijing China 	status = mod_remove(&modlinkage);
338456f9a274Sfei feng - Sun Microsystems - Beijing China 	if (status == 0) {
338556f9a274Sfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&uath_dev_ops);
338656f9a274Sfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&uath_soft_state_p);
338756f9a274Sfei feng - Sun Microsystems - Beijing China 	}
338856f9a274Sfei feng - Sun Microsystems - Beijing China 	return (status);
338956f9a274Sfei feng - Sun Microsystems - Beijing China }
3390