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