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 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 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 * 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 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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