19485SMikore.Li@Sun.COM /* 29485SMikore.Li@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 39485SMikore.Li@Sun.COM * Use is subject to license terms. 49485SMikore.Li@Sun.COM */ 59485SMikore.Li@Sun.COM 69485SMikore.Li@Sun.COM /* 79485SMikore.Li@Sun.COM * Copyright (c) 2008 Weongyo Jeong 89485SMikore.Li@Sun.COM * All rights reserved. 99485SMikore.Li@Sun.COM * 109485SMikore.Li@Sun.COM * Redistribution and use in source and binary forms, with or without 119485SMikore.Li@Sun.COM * modification, are permitted provided that the following conditions 129485SMikore.Li@Sun.COM * are met: 139485SMikore.Li@Sun.COM * 1. Redistributions of source code must retain the above copyright 149485SMikore.Li@Sun.COM * notice, this list of conditions and the following disclaimer, 159485SMikore.Li@Sun.COM * without modification. 169485SMikore.Li@Sun.COM * 2. Redistributions in binary form must reproduce at minimum a disclaimer 179485SMikore.Li@Sun.COM * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 189485SMikore.Li@Sun.COM * redistribution must be conditioned upon including a substantially 199485SMikore.Li@Sun.COM * similar Disclaimer requirement for further binary redistribution. 209485SMikore.Li@Sun.COM * 219485SMikore.Li@Sun.COM * NO WARRANTY 229485SMikore.Li@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 239485SMikore.Li@Sun.COM * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 249485SMikore.Li@Sun.COM * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 259485SMikore.Li@Sun.COM * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 269485SMikore.Li@Sun.COM * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 279485SMikore.Li@Sun.COM * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 289485SMikore.Li@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 299485SMikore.Li@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 309485SMikore.Li@Sun.COM * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 319485SMikore.Li@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 329485SMikore.Li@Sun.COM * THE POSSIBILITY OF SUCH DAMAGES. 339485SMikore.Li@Sun.COM */ 349485SMikore.Li@Sun.COM #include <sys/sysmacros.h> 359485SMikore.Li@Sun.COM #include <sys/strsubr.h> 369485SMikore.Li@Sun.COM #include <sys/strsun.h> 379485SMikore.Li@Sun.COM #include <sys/mac_provider.h> 389485SMikore.Li@Sun.COM #include <sys/mac_wifi.h> 399485SMikore.Li@Sun.COM #include <sys/net80211.h> 409485SMikore.Li@Sun.COM #define USBDRV_MAJOR_VER 2 419485SMikore.Li@Sun.COM #define USBDRV_MINOR_VER 0 429485SMikore.Li@Sun.COM #include <sys/usb/usba.h> 439485SMikore.Li@Sun.COM #include <sys/usb/usba/usba_types.h> 449485SMikore.Li@Sun.COM 459485SMikore.Li@Sun.COM #include "urtw_reg.h" 469485SMikore.Li@Sun.COM #include "urtw_var.h" 479485SMikore.Li@Sun.COM 489485SMikore.Li@Sun.COM static void *urtw_soft_state_p = NULL; 499485SMikore.Li@Sun.COM 509485SMikore.Li@Sun.COM #define URTW_TXBUF_SIZE (IEEE80211_MAX_LEN) 519485SMikore.Li@Sun.COM #define URTW_RXBUF_SIZE (URTW_TXBUF_SIZE) 529485SMikore.Li@Sun.COM /* 539485SMikore.Li@Sun.COM * device operations 549485SMikore.Li@Sun.COM */ 559485SMikore.Li@Sun.COM static int urtw_attach(dev_info_t *, ddi_attach_cmd_t); 569485SMikore.Li@Sun.COM static int urtw_detach(dev_info_t *, ddi_detach_cmd_t); 579485SMikore.Li@Sun.COM 589485SMikore.Li@Sun.COM /* 599485SMikore.Li@Sun.COM * Module Loading Data & Entry Points 609485SMikore.Li@Sun.COM */ 619485SMikore.Li@Sun.COM DDI_DEFINE_STREAM_OPS(urtw_dev_ops, nulldev, nulldev, urtw_attach, 629485SMikore.Li@Sun.COM urtw_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 639485SMikore.Li@Sun.COM 649485SMikore.Li@Sun.COM static struct modldrv urtw_modldrv = { 659485SMikore.Li@Sun.COM &mod_driverops, /* Type of module. This one is a driver */ 66*10364SMikore.Li@Sun.COM "RTL8187L/B driver v1.2", /* short description */ 679485SMikore.Li@Sun.COM &urtw_dev_ops /* driver specific ops */ 689485SMikore.Li@Sun.COM }; 699485SMikore.Li@Sun.COM 709485SMikore.Li@Sun.COM static struct modlinkage modlinkage = { 719485SMikore.Li@Sun.COM MODREV_1, 729485SMikore.Li@Sun.COM (void *)&urtw_modldrv, 739485SMikore.Li@Sun.COM NULL 749485SMikore.Li@Sun.COM }; 759485SMikore.Li@Sun.COM 769485SMikore.Li@Sun.COM static int urtw_m_stat(void *, uint_t, uint64_t *); 779485SMikore.Li@Sun.COM static int urtw_m_start(void *); 789485SMikore.Li@Sun.COM static void urtw_m_stop(void *); 799485SMikore.Li@Sun.COM static int urtw_m_promisc(void *, boolean_t); 809485SMikore.Li@Sun.COM static int urtw_m_multicst(void *, boolean_t, const uint8_t *); 819485SMikore.Li@Sun.COM static int urtw_m_unicst(void *, const uint8_t *); 829485SMikore.Li@Sun.COM static mblk_t *urtw_m_tx(void *, mblk_t *); 839485SMikore.Li@Sun.COM static void urtw_m_ioctl(void *, queue_t *, mblk_t *); 849485SMikore.Li@Sun.COM static int urtw_m_setprop(void *, const char *, mac_prop_id_t, 859485SMikore.Li@Sun.COM uint_t, const void *); 86*10364SMikore.Li@Sun.COM static int urtw_m_getprop(void *, const char *, mac_prop_id_t, 87*10364SMikore.Li@Sun.COM uint_t, uint_t, void *, uint_t *); 889485SMikore.Li@Sun.COM 899485SMikore.Li@Sun.COM static mac_callbacks_t urtw_m_callbacks = { 909485SMikore.Li@Sun.COM MC_IOCTL | MC_SETPROP | MC_GETPROP, 919485SMikore.Li@Sun.COM urtw_m_stat, 929485SMikore.Li@Sun.COM urtw_m_start, 939485SMikore.Li@Sun.COM urtw_m_stop, 949485SMikore.Li@Sun.COM urtw_m_promisc, 959485SMikore.Li@Sun.COM urtw_m_multicst, 969485SMikore.Li@Sun.COM urtw_m_unicst, 979485SMikore.Li@Sun.COM urtw_m_tx, 989485SMikore.Li@Sun.COM urtw_m_ioctl, 999485SMikore.Li@Sun.COM NULL, 1009485SMikore.Li@Sun.COM NULL, 1019485SMikore.Li@Sun.COM NULL, 1029485SMikore.Li@Sun.COM urtw_m_setprop, 103*10364SMikore.Li@Sun.COM urtw_m_getprop 1049485SMikore.Li@Sun.COM }; 1059485SMikore.Li@Sun.COM 1069485SMikore.Li@Sun.COM static int urtw_tx_start(struct urtw_softc *, mblk_t *, int); 1079485SMikore.Li@Sun.COM static int urtw_rx_start(struct urtw_softc *); 1089485SMikore.Li@Sun.COM 1099485SMikore.Li@Sun.COM 1109485SMikore.Li@Sun.COM /* 111*10364SMikore.Li@Sun.COM * Supported rates for 802.11b/g modes (in 500Kbps unit). 1129485SMikore.Li@Sun.COM */ 1139485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11b = 1149485SMikore.Li@Sun.COM { 4, { 2, 4, 11, 22 } }; 1159485SMikore.Li@Sun.COM 1169485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11g = 1179485SMikore.Li@Sun.COM { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 1189485SMikore.Li@Sun.COM 119*10364SMikore.Li@Sun.COM #define USB_VENDOR_DICKSMITH 0x1371 /* Dick Smith Electronics */ 120*10364SMikore.Li@Sun.COM #define USB_VENDOR_LOGITEC 0x0789 /* Logitec */ 121*10364SMikore.Li@Sun.COM #define USB_VENDOR_NETGEAR 0x0846 /* BayNETGEAR */ 122*10364SMikore.Li@Sun.COM #define USB_VENDOR_REALTEK 0x0bda /* Realtek */ 123*10364SMikore.Li@Sun.COM #define USB_VENDOR_SPHAIRON 0x114b /* Sphairon Access Systems */ 124*10364SMikore.Li@Sun.COM #define USB_VENDOR_SURECOM 0x0769 /* Surecom Technology */ 125*10364SMikore.Li@Sun.COM #define USB_VENDOR_BELKIN 0x050d /* Belkin Components */ 126*10364SMikore.Li@Sun.COM #define USB_VENDOR_SITECOMEU 0x0df6 /* Sitecom Europe */ 127*10364SMikore.Li@Sun.COM 128*10364SMikore.Li@Sun.COM #define USB_PRODUCT_SPHAIRON_RTL8187 0x0150 /* RTL8187 */ 129*10364SMikore.Li@Sun.COM #define USB_PRODUCT_DICKSMITH_RTL8187 0x9401 /* RTL8187 */ 130*10364SMikore.Li@Sun.COM #define USB_PRODUCT_LOGITEC_RTL8187 0x010c /* RTL8187 */ 131*10364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187 0x8187 /* RTL8187 */ 132*10364SMikore.Li@Sun.COM #define USB_PRODUCT_NETGEAR_WG111V2 0x6a00 /* WG111v2 */ 133*10364SMikore.Li@Sun.COM #define USB_PRODUCT_SURECOM_EP9001G2A 0x11f2 /* EP-9001-G rev 2A */ 134*10364SMikore.Li@Sun.COM #define USB_PRODUCT_BELKIN_F5D7050E 0x705e /* F5D705E 54g */ 135*10364SMikore.Li@Sun.COM #define USB_PRODUCT_NETGEAR_WG111V3 0x4260 /* WG111v3 */ 136*10364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_0 0x8189 /* RTL8187B */ 137*10364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_1 0x8197 /* RTL8187B */ 138*10364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_2 0x8198 /* RTL8187B */ 139*10364SMikore.Li@Sun.COM #define USB_PRODUCT_SITECOMEU_WL168 0x0028 /* WL-168 */ 140*10364SMikore.Li@Sun.COM 141*10364SMikore.Li@Sun.COM #define USB_PRODUCT_ANY 0xffff 142*10364SMikore.Li@Sun.COM 143*10364SMikore.Li@Sun.COM struct usb_devno { 144*10364SMikore.Li@Sun.COM uint16_t v; 145*10364SMikore.Li@Sun.COM uint16_t p; 146*10364SMikore.Li@Sun.COM }; 147*10364SMikore.Li@Sun.COM 148*10364SMikore.Li@Sun.COM /* 149*10364SMikore.Li@Sun.COM * Recognized device vendors/products. 150*10364SMikore.Li@Sun.COM */ 151*10364SMikore.Li@Sun.COM static struct urtw_type { 152*10364SMikore.Li@Sun.COM struct usb_devno dev; 153*10364SMikore.Li@Sun.COM uint8_t rev; 154*10364SMikore.Li@Sun.COM } urtw_devs[] = { 155*10364SMikore.Li@Sun.COM #define URTW_DEV_RTL8187(v, p) \ 156*10364SMikore.Li@Sun.COM { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187 } 157*10364SMikore.Li@Sun.COM #define URTW_DEV_RTL8187B(v, p) \ 158*10364SMikore.Li@Sun.COM { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187B } 159*10364SMikore.Li@Sun.COM /* Realtek RTL8187 devices. */ 160*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(DICKSMITH, RTL8187), 161*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(LOGITEC, RTL8187), 162*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(NETGEAR, WG111V2), 163*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(REALTEK, RTL8187), 164*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(SPHAIRON, RTL8187), 165*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187(SURECOM, EP9001G2A), 166*10364SMikore.Li@Sun.COM /* Realtek RTL8187B devices. */ 167*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(BELKIN, F5D7050E), 168*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(NETGEAR, WG111V3), 169*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_0), 170*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_1), 171*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_2), 172*10364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(SITECOMEU, WL168) 173*10364SMikore.Li@Sun.COM #undef URTW_DEV_RTL8187 174*10364SMikore.Li@Sun.COM #undef URTW_DEV_RTL8187B 175*10364SMikore.Li@Sun.COM }; 176*10364SMikore.Li@Sun.COM 177*10364SMikore.Li@Sun.COM /* 178*10364SMikore.Li@Sun.COM * Search for a vendor/product pair in an array. The item size is 179*10364SMikore.Li@Sun.COM * given as an argument. 180*10364SMikore.Li@Sun.COM */ 181*10364SMikore.Li@Sun.COM struct urtw_type * 182*10364SMikore.Li@Sun.COM usb_match_device(struct urtw_type *tbl, uint32_t nentries, 183*10364SMikore.Li@Sun.COM uint16_t vendor, uint16_t product) 184*10364SMikore.Li@Sun.COM { 185*10364SMikore.Li@Sun.COM while (nentries-- > 0) { 186*10364SMikore.Li@Sun.COM uint16_t tproduct = tbl[nentries].dev.p; 187*10364SMikore.Li@Sun.COM if (tbl[nentries].dev.v == vendor && 188*10364SMikore.Li@Sun.COM (tproduct == product || tproduct == USB_PRODUCT_ANY)) 189*10364SMikore.Li@Sun.COM return (&tbl[nentries]); 190*10364SMikore.Li@Sun.COM } 191*10364SMikore.Li@Sun.COM return (NULL); 192*10364SMikore.Li@Sun.COM } 193*10364SMikore.Li@Sun.COM 194*10364SMikore.Li@Sun.COM #define usb_lookup(tbl, vendor, product) \ 195*10364SMikore.Li@Sun.COM usb_match_device(tbl, sizeof (tbl) / sizeof ((tbl)[0]), \ 196*10364SMikore.Li@Sun.COM (vendor), (product)) 197*10364SMikore.Li@Sun.COM 198*10364SMikore.Li@Sun.COM #define urtw_lookup(v, p) (usb_lookup(urtw_devs, v, p)) 1999485SMikore.Li@Sun.COM 2009485SMikore.Li@Sun.COM struct urtw_pair { 2019485SMikore.Li@Sun.COM uint32_t reg; 2029485SMikore.Li@Sun.COM uint32_t val; 2039485SMikore.Li@Sun.COM }; 2049485SMikore.Li@Sun.COM 205*10364SMikore.Li@Sun.COM struct urtw_pair_idx { 206*10364SMikore.Li@Sun.COM uint8_t reg; 207*10364SMikore.Li@Sun.COM uint8_t val; 208*10364SMikore.Li@Sun.COM uint8_t idx; 209*10364SMikore.Li@Sun.COM }; 210*10364SMikore.Li@Sun.COM 211*10364SMikore.Li@Sun.COM static struct urtw_pair_idx urtw_8187b_regtbl[] = { 212*10364SMikore.Li@Sun.COM { 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 }, 213*10364SMikore.Li@Sun.COM { 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 }, 214*10364SMikore.Li@Sun.COM { 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 }, 215*10364SMikore.Li@Sun.COM { 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 }, 216*10364SMikore.Li@Sun.COM { 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 }, 217*10364SMikore.Li@Sun.COM { 0xff, 0x00, 0 }, 218*10364SMikore.Li@Sun.COM 219*10364SMikore.Li@Sun.COM { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, { 0x5a, 0x4b, 1 }, 220*10364SMikore.Li@Sun.COM { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, { 0x61, 0x09, 1 }, 221*10364SMikore.Li@Sun.COM { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, { 0xce, 0x0f, 1 }, 222*10364SMikore.Li@Sun.COM { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, { 0xe1, 0x0f, 1 }, 223*10364SMikore.Li@Sun.COM { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, { 0xf1, 0x01, 1 }, 224*10364SMikore.Li@Sun.COM { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, { 0xf4, 0x04, 1 }, 225*10364SMikore.Li@Sun.COM { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, { 0xf7, 0x07, 1 }, 226*10364SMikore.Li@Sun.COM { 0xf8, 0x08, 1 }, 227*10364SMikore.Li@Sun.COM 228*10364SMikore.Li@Sun.COM { 0x4e, 0x00, 2 }, { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, 229*10364SMikore.Li@Sun.COM { 0x22, 0x68, 2 }, { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, 230*10364SMikore.Li@Sun.COM { 0x25, 0x7d, 2 }, { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, 231*10364SMikore.Li@Sun.COM { 0x4d, 0x08, 2 }, { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, 232*10364SMikore.Li@Sun.COM { 0x52, 0x04, 2 }, { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, 233*10364SMikore.Li@Sun.COM { 0x55, 0x23, 2 }, { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, 234*10364SMikore.Li@Sun.COM { 0x58, 0x08, 2 }, { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, 235*10364SMikore.Li@Sun.COM { 0x5b, 0x08, 2 }, { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, 236*10364SMikore.Li@Sun.COM { 0x62, 0x08, 2 }, { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, 237*10364SMikore.Li@Sun.COM { 0x72, 0x56, 2 }, { 0x73, 0x9a, 2 }, 238*10364SMikore.Li@Sun.COM 239*10364SMikore.Li@Sun.COM { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, { 0x5b, 0x40, 0 }, 240*10364SMikore.Li@Sun.COM { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, { 0x88, 0x54, 0 }, 241*10364SMikore.Li@Sun.COM { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, { 0x8d, 0x00, 0 }, 242*10364SMikore.Li@Sun.COM { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, { 0x96, 0x00, 0 }, 243*10364SMikore.Li@Sun.COM { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, { 0x9f, 0x10, 0 }, 244*10364SMikore.Li@Sun.COM { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, { 0xdb, 0x00, 0 }, 245*10364SMikore.Li@Sun.COM { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 }, 246*10364SMikore.Li@Sun.COM 247*10364SMikore.Li@Sun.COM { 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 }, 248*10364SMikore.Li@Sun.COM { 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 } 249*10364SMikore.Li@Sun.COM }; 250*10364SMikore.Li@Sun.COM 2519485SMikore.Li@Sun.COM static uint8_t urtw_8225_agc[] = { 2529485SMikore.Li@Sun.COM 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, 2539485SMikore.Li@Sun.COM 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 2549485SMikore.Li@Sun.COM 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 2559485SMikore.Li@Sun.COM 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 2569485SMikore.Li@Sun.COM 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 2579485SMikore.Li@Sun.COM 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 2589485SMikore.Li@Sun.COM 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 2599485SMikore.Li@Sun.COM 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 2609485SMikore.Li@Sun.COM 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 2619485SMikore.Li@Sun.COM 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 2629485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 2639485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 2649485SMikore.Li@Sun.COM }; 2659485SMikore.Li@Sun.COM 266*10364SMikore.Li@Sun.COM static uint8_t urtw_8225v2_agc[] = { 267*10364SMikore.Li@Sun.COM 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 268*10364SMikore.Li@Sun.COM 0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47, 269*10364SMikore.Li@Sun.COM 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, 270*10364SMikore.Li@Sun.COM 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 271*10364SMikore.Li@Sun.COM 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 272*10364SMikore.Li@Sun.COM 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, 273*10364SMikore.Li@Sun.COM 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 274*10364SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 275*10364SMikore.Li@Sun.COM 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 276*10364SMikore.Li@Sun.COM 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 277*10364SMikore.Li@Sun.COM 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a, 278*10364SMikore.Li@Sun.COM 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 279*10364SMikore.Li@Sun.COM 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 280*10364SMikore.Li@Sun.COM 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 281*10364SMikore.Li@Sun.COM 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 282*10364SMikore.Li@Sun.COM 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 283*10364SMikore.Li@Sun.COM }; 284*10364SMikore.Li@Sun.COM 285*10364SMikore.Li@Sun.COM static uint8_t urtw_8225v2_ofdm[] = { 286*10364SMikore.Li@Sun.COM 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, 287*10364SMikore.Li@Sun.COM 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 288*10364SMikore.Li@Sun.COM 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, 289*10364SMikore.Li@Sun.COM 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, 290*10364SMikore.Li@Sun.COM 0x0a, 0xe1, 0x2c, 0x8a, 0x86, 0x83, 0x34, 0x0f, 291*10364SMikore.Li@Sun.COM 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, 292*10364SMikore.Li@Sun.COM 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, 293*10364SMikore.Li@Sun.COM 0x6d, 0x3c, 0xfb, 0x07 294*10364SMikore.Li@Sun.COM }; 295*10364SMikore.Li@Sun.COM 2969485SMikore.Li@Sun.COM static uint32_t urtw_8225_channel[] = { 2979485SMikore.Li@Sun.COM 0x0000, /* dummy channel 0 */ 2989485SMikore.Li@Sun.COM 0x085c, /* 1 */ 2999485SMikore.Li@Sun.COM 0x08dc, /* 2 */ 3009485SMikore.Li@Sun.COM 0x095c, /* 3 */ 3019485SMikore.Li@Sun.COM 0x09dc, /* 4 */ 3029485SMikore.Li@Sun.COM 0x0a5c, /* 5 */ 3039485SMikore.Li@Sun.COM 0x0adc, /* 6 */ 3049485SMikore.Li@Sun.COM 0x0b5c, /* 7 */ 3059485SMikore.Li@Sun.COM 0x0bdc, /* 8 */ 3069485SMikore.Li@Sun.COM 0x0c5c, /* 9 */ 3079485SMikore.Li@Sun.COM 0x0cdc, /* 10 */ 3089485SMikore.Li@Sun.COM 0x0d5c, /* 11 */ 3099485SMikore.Li@Sun.COM 0x0ddc, /* 12 */ 3109485SMikore.Li@Sun.COM 0x0e5c, /* 13 */ 3119485SMikore.Li@Sun.COM 0x0f72, /* 14 */ 3129485SMikore.Li@Sun.COM }; 3139485SMikore.Li@Sun.COM 3149485SMikore.Li@Sun.COM static uint8_t urtw_8225_gain[] = { 3159485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ 3169485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ 3179485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ 3189485SMikore.Li@Sun.COM 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ 3199485SMikore.Li@Sun.COM 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ 3209485SMikore.Li@Sun.COM 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ 3219485SMikore.Li@Sun.COM 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ 3229485SMikore.Li@Sun.COM }; 3239485SMikore.Li@Sun.COM 3249485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part1[] = { 3259485SMikore.Li@Sun.COM { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 3269485SMikore.Li@Sun.COM { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a }, 3279485SMikore.Li@Sun.COM { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 }, 3289485SMikore.Li@Sun.COM { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }, 3299485SMikore.Li@Sun.COM }; 3309485SMikore.Li@Sun.COM 3319485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part2[] = { 3329485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 3339485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 3349485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 }, 3359485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 }, 3369485SMikore.Li@Sun.COM { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 }, 3379485SMikore.Li@Sun.COM { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef }, 3389485SMikore.Li@Sun.COM { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 }, 3399485SMikore.Li@Sun.COM { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 }, 3409485SMikore.Li@Sun.COM { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 }, 3419485SMikore.Li@Sun.COM { 0x27, 0x88 } 3429485SMikore.Li@Sun.COM }; 3439485SMikore.Li@Sun.COM 3449485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part3[] = { 3459485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 3469485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b }, 3479485SMikore.Li@Sun.COM { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, 3489485SMikore.Li@Sun.COM { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d }, 3499485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e }, 3509485SMikore.Li@Sun.COM { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a }, 3519485SMikore.Li@Sun.COM { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 } 3529485SMikore.Li@Sun.COM }; 3539485SMikore.Li@Sun.COM 3549485SMikore.Li@Sun.COM static uint16_t urtw_8225_rxgain[] = { 3559485SMikore.Li@Sun.COM 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 3569485SMikore.Li@Sun.COM 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, 3579485SMikore.Li@Sun.COM 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, 3589485SMikore.Li@Sun.COM 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, 3599485SMikore.Li@Sun.COM 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, 3609485SMikore.Li@Sun.COM 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, 3619485SMikore.Li@Sun.COM 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, 3629485SMikore.Li@Sun.COM 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, 3639485SMikore.Li@Sun.COM 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 3649485SMikore.Li@Sun.COM 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 3659485SMikore.Li@Sun.COM 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, 3669485SMikore.Li@Sun.COM 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb 3679485SMikore.Li@Sun.COM }; 3689485SMikore.Li@Sun.COM 3699485SMikore.Li@Sun.COM static uint8_t urtw_8225_threshold[] = { 3709485SMikore.Li@Sun.COM 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, 3719485SMikore.Li@Sun.COM }; 3729485SMikore.Li@Sun.COM 3739485SMikore.Li@Sun.COM static uint8_t urtw_8225_tx_gain_cck_ofdm[] = { 3749485SMikore.Li@Sun.COM 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e 3759485SMikore.Li@Sun.COM }; 3769485SMikore.Li@Sun.COM 3779485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck[] = { 3789485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, 3799485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, 3809485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, 3819485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, 3829485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, 3839485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 3849485SMikore.Li@Sun.COM }; 3859485SMikore.Li@Sun.COM 3869485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck_ch14[] = { 3879485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, 3889485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, 3899485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, 3909485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 3919485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 3929485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 3939485SMikore.Li@Sun.COM }; 3949485SMikore.Li@Sun.COM 3959485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_ofdm[] = { 3969485SMikore.Li@Sun.COM 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 3979485SMikore.Li@Sun.COM }; 3989485SMikore.Li@Sun.COM 3999485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_gain_bg[] = { 4009485SMikore.Li@Sun.COM 0x23, 0x15, 0xa5, /* -82-1dbm */ 4019485SMikore.Li@Sun.COM 0x23, 0x15, 0xb5, /* -82-2dbm */ 4029485SMikore.Li@Sun.COM 0x23, 0x15, 0xc5, /* -82-3dbm */ 4039485SMikore.Li@Sun.COM 0x33, 0x15, 0xc5, /* -78dbm */ 4049485SMikore.Li@Sun.COM 0x43, 0x15, 0xc5, /* -74dbm */ 4059485SMikore.Li@Sun.COM 0x53, 0x15, 0xc5, /* -70dbm */ 4069485SMikore.Li@Sun.COM 0x63, 0x15, 0xc5, /* -66dbm */ 4079485SMikore.Li@Sun.COM }; 4089485SMikore.Li@Sun.COM 4099485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part1[] = { 4109485SMikore.Li@Sun.COM { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 4119485SMikore.Li@Sun.COM { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, 4129485SMikore.Li@Sun.COM { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, 4139485SMikore.Li@Sun.COM { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } 4149485SMikore.Li@Sun.COM }; 4159485SMikore.Li@Sun.COM 4169485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part2[] = { 4179485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 4189485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 4199485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 }, 4209485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, 4219485SMikore.Li@Sun.COM { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 }, 4229485SMikore.Li@Sun.COM { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, 4239485SMikore.Li@Sun.COM { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 }, 4249485SMikore.Li@Sun.COM { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 }, 4259485SMikore.Li@Sun.COM { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 }, 4269485SMikore.Li@Sun.COM { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 } 4279485SMikore.Li@Sun.COM }; 4289485SMikore.Li@Sun.COM 4299485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part3[] = { 4309485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 4319485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 }, 4329485SMikore.Li@Sun.COM { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 }, 4339485SMikore.Li@Sun.COM { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 }, 4349485SMikore.Li@Sun.COM { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d }, 4359485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 }, 4369485SMikore.Li@Sun.COM { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 }, 4379485SMikore.Li@Sun.COM { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 } 4389485SMikore.Li@Sun.COM }; 4399485SMikore.Li@Sun.COM 4409485SMikore.Li@Sun.COM static uint16_t urtw_8225v2_rxgain[] = { 441*10364SMikore.Li@Sun.COM 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 442*10364SMikore.Li@Sun.COM 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, 443*10364SMikore.Li@Sun.COM 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, 444*10364SMikore.Li@Sun.COM 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, 445*10364SMikore.Li@Sun.COM 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, 446*10364SMikore.Li@Sun.COM 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, 447*10364SMikore.Li@Sun.COM 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, 448*10364SMikore.Li@Sun.COM 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, 449*10364SMikore.Li@Sun.COM 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 450*10364SMikore.Li@Sun.COM 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 4519485SMikore.Li@Sun.COM 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 4529485SMikore.Li@Sun.COM 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb 4539485SMikore.Li@Sun.COM }; 4549485SMikore.Li@Sun.COM 4559485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { 4569485SMikore.Li@Sun.COM 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 4579485SMikore.Li@Sun.COM 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 4589485SMikore.Li@Sun.COM 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 4599485SMikore.Li@Sun.COM 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 4609485SMikore.Li@Sun.COM 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 4619485SMikore.Li@Sun.COM 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 4629485SMikore.Li@Sun.COM }; 4639485SMikore.Li@Sun.COM 4649485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck[] = { 465*10364SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, 466*10364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, 467*10364SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, 468*10364SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 4699485SMikore.Li@Sun.COM }; 4709485SMikore.Li@Sun.COM 4719485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck_ch14[] = { 472*10364SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, 473*10364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, 474*10364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, 475*10364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 476*10364SMikore.Li@Sun.COM }; 477*10364SMikore.Li@Sun.COM 478*10364SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_b_rf[] = { 479*10364SMikore.Li@Sun.COM { 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 480*10364SMikore.Li@Sun.COM { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, 481*10364SMikore.Li@Sun.COM { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, 482*10364SMikore.Li@Sun.COM { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 }, 483*10364SMikore.Li@Sun.COM { 0x00, 0x01b7 } 4849485SMikore.Li@Sun.COM }; 4859485SMikore.Li@Sun.COM 4869485SMikore.Li@Sun.COM static struct urtw_pair urtw_ratetable[] = { 4879485SMikore.Li@Sun.COM { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 }, 4889485SMikore.Li@Sun.COM { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 }, 4899485SMikore.Li@Sun.COM { 96, 10 }, { 108, 11 } 4909485SMikore.Li@Sun.COM }; 4919485SMikore.Li@Sun.COM 492*10364SMikore.Li@Sun.COM static int urtw_8187_init(void *); 4939485SMikore.Li@Sun.COM static void urtw_stop(struct urtw_softc *); 4949485SMikore.Li@Sun.COM static int urtw_set_channel(struct urtw_softc *); 4959485SMikore.Li@Sun.COM static void 4969485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t, usb_bulk_req_t *); 4979485SMikore.Li@Sun.COM static int 4989485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *, enum ieee80211_state, int); 499*10364SMikore.Li@Sun.COM static usbd_status 500*10364SMikore.Li@Sun.COM urtw_read8_c(struct urtw_softc *, int, uint8_t *, uint8_t); 501*10364SMikore.Li@Sun.COM static usbd_status 502*10364SMikore.Li@Sun.COM urtw_read16_c(struct urtw_softc *, int, uint16_t *, uint8_t); 503*10364SMikore.Li@Sun.COM static usbd_status 504*10364SMikore.Li@Sun.COM urtw_read32_c(struct urtw_softc *, int, uint32_t *, uint8_t); 505*10364SMikore.Li@Sun.COM static usbd_status 506*10364SMikore.Li@Sun.COM urtw_write8_c(struct urtw_softc *, int, uint8_t, uint8_t); 507*10364SMikore.Li@Sun.COM static usbd_status 508*10364SMikore.Li@Sun.COM urtw_write16_c(struct urtw_softc *, int, uint16_t, uint8_t); 509*10364SMikore.Li@Sun.COM static usbd_status 510*10364SMikore.Li@Sun.COM urtw_write32_c(struct urtw_softc *, int, uint32_t, uint8_t); 5119485SMikore.Li@Sun.COM static usbd_status urtw_eprom_cs(struct urtw_softc *, int); 5129485SMikore.Li@Sun.COM static usbd_status urtw_eprom_ck(struct urtw_softc *); 5139485SMikore.Li@Sun.COM static usbd_status urtw_eprom_sendbits(struct urtw_softc *, int16_t *, 5149485SMikore.Li@Sun.COM int); 5159485SMikore.Li@Sun.COM static usbd_status urtw_eprom_read32(struct urtw_softc *, uint32_t, 5169485SMikore.Li@Sun.COM uint32_t *); 5179485SMikore.Li@Sun.COM static usbd_status urtw_eprom_readbit(struct urtw_softc *, int16_t *); 5189485SMikore.Li@Sun.COM static usbd_status urtw_eprom_writebit(struct urtw_softc *, int16_t); 5199485SMikore.Li@Sun.COM static usbd_status urtw_get_macaddr(struct urtw_softc *); 5209485SMikore.Li@Sun.COM static usbd_status urtw_get_txpwr(struct urtw_softc *); 5219485SMikore.Li@Sun.COM static usbd_status urtw_get_rfchip(struct urtw_softc *); 5229485SMikore.Li@Sun.COM static usbd_status urtw_led_init(struct urtw_softc *); 5239485SMikore.Li@Sun.COM static usbd_status 5249485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *, uint8_t, uint32_t *); 525*10364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_init(struct urtw_rf *); 526*10364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_chan(struct urtw_rf *, int); 527*10364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_sens(struct urtw_rf *); 528*10364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_init(struct urtw_rf *); 529*10364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_set_chan(struct urtw_rf *, int); 5309485SMikore.Li@Sun.COM static usbd_status urtw_open_pipes(struct urtw_softc *); 5319485SMikore.Li@Sun.COM static void urtw_close_pipes(struct urtw_softc *); 5329485SMikore.Li@Sun.COM static void urtw_led_launch(void *); 5339485SMikore.Li@Sun.COM 534*10364SMikore.Li@Sun.COM static void urtw_8187b_update_wmm(struct urtw_softc *); 535*10364SMikore.Li@Sun.COM static usbd_status urtw_8187b_reset(struct urtw_softc *); 536*10364SMikore.Li@Sun.COM static int urtw_8187b_init(void *); 537*10364SMikore.Li@Sun.COM static void urtw_8225v2_b_config_mac(struct urtw_softc *); 538*10364SMikore.Li@Sun.COM static void urtw_8225v2_b_init_rfe(struct urtw_softc *); 539*10364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_update_chan(struct urtw_softc *); 540*10364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_rf_init(struct urtw_rf *); 541*10364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_rf_set_chan(struct urtw_rf *, int); 542*10364SMikore.Li@Sun.COM static void urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *, int); 543*10364SMikore.Li@Sun.COM 5449485SMikore.Li@Sun.COM #ifdef DEBUG 5459485SMikore.Li@Sun.COM 5469485SMikore.Li@Sun.COM #define URTW_DEBUG_XMIT 0x00000001 5479485SMikore.Li@Sun.COM #define URTW_DEBUG_RECV 0x00000002 5489485SMikore.Li@Sun.COM #define URTW_DEBUG_LED 0x00000004 5499485SMikore.Li@Sun.COM #define URTW_DEBUG_GLD 0x00000008 5509485SMikore.Li@Sun.COM #define URTW_DEBUG_RF 0x00000010 5519485SMikore.Li@Sun.COM #define URTW_DEBUG_ATTACH 0x00000020 5529485SMikore.Li@Sun.COM #define URTW_DEBUG_ACTIVE 0x00000040 5539485SMikore.Li@Sun.COM #define URTW_DEBUG_HWTYPE 0x00000080 554*10364SMikore.Li@Sun.COM #define URTW_DEBUG_DEVREQ 0x00000100 5559485SMikore.Li@Sun.COM #define URTW_DEBUG_HOTPLUG 0x00000200 556*10364SMikore.Li@Sun.COM #define URTW_DEBUG_STATE 0x00000400 5579485SMikore.Li@Sun.COM #define URTW_DEBUG_TX_PROC 0x00000800 5589485SMikore.Li@Sun.COM #define URTW_DEBUG_RX_PROC 0x00001000 5599485SMikore.Li@Sun.COM #define URTW_DEBUG_EEPROM 0x00002000 5609485SMikore.Li@Sun.COM #define URTW_DEBUG_RESET 0x00004000 5619485SMikore.Li@Sun.COM #define URTW_DEBUG_ANY 0xffffffff 5629485SMikore.Li@Sun.COM 5639485SMikore.Li@Sun.COM uint32_t urtw8187_dbg_flags = 0; 5649485SMikore.Li@Sun.COM static void 5659485SMikore.Li@Sun.COM urtw8187_dbg(dev_info_t *dip, int level, const char *fmt, ...) 5669485SMikore.Li@Sun.COM { 5679485SMikore.Li@Sun.COM char msg_buffer[255]; 5689485SMikore.Li@Sun.COM va_list ap; 5699485SMikore.Li@Sun.COM 5709485SMikore.Li@Sun.COM if (dip == NULL) { 5719485SMikore.Li@Sun.COM return; 5729485SMikore.Li@Sun.COM } 5739485SMikore.Li@Sun.COM 5749485SMikore.Li@Sun.COM va_start(ap, fmt); 5759485SMikore.Li@Sun.COM (void) vsprintf(msg_buffer, fmt, ap); 5769485SMikore.Li@Sun.COM cmn_err(level, "%s%d: %s", ddi_get_name(dip), 5779485SMikore.Li@Sun.COM ddi_get_instance(dip), msg_buffer); 5789485SMikore.Li@Sun.COM va_end(ap); 5799485SMikore.Li@Sun.COM } 5809485SMikore.Li@Sun.COM 5819485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x) do {\ 5829485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \ 5839485SMikore.Li@Sun.COM if ((l) & urtw8187_dbg_flags) \ 5849485SMikore.Li@Sun.COM urtw8187_dbg x;\ 5859485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \ 5869485SMikore.Li@Sun.COM } while (0) 5879485SMikore.Li@Sun.COM #else 5889485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x) 5899485SMikore.Li@Sun.COM #endif 5909485SMikore.Li@Sun.COM 5919485SMikore.Li@Sun.COM static usbd_status 5929485SMikore.Li@Sun.COM urtw_led_init(struct urtw_softc *sc) 5939485SMikore.Li@Sun.COM { 5949485SMikore.Li@Sun.COM uint32_t rev; 5959485SMikore.Li@Sun.COM usbd_status error; 5969485SMikore.Li@Sun.COM 597*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_PSR, &sc->sc_psr, 0)) 5989485SMikore.Li@Sun.COM goto fail; 5999485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev); 6009485SMikore.Li@Sun.COM if (error != 0) 6019485SMikore.Li@Sun.COM goto fail; 6029485SMikore.Li@Sun.COM 6039485SMikore.Li@Sun.COM switch (rev & URTW_EPROM_CID_MASK) { 6049485SMikore.Li@Sun.COM case URTW_EPROM_CID_ALPHA0: 6059485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE1; 6069485SMikore.Li@Sun.COM break; 6079485SMikore.Li@Sun.COM case URTW_EPROM_CID_SERCOMM_PS: 6089485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE3; 6099485SMikore.Li@Sun.COM break; 6109485SMikore.Li@Sun.COM case URTW_EPROM_CID_HW_LED: 6119485SMikore.Li@Sun.COM sc->sc_strategy = URTW_HW_LED; 6129485SMikore.Li@Sun.COM break; 6139485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD0: 6149485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD1: 6159485SMikore.Li@Sun.COM default: 6169485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE0; 6179485SMikore.Li@Sun.COM break; 6189485SMikore.Li@Sun.COM } 6199485SMikore.Li@Sun.COM 6209485SMikore.Li@Sun.COM sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0; 6219485SMikore.Li@Sun.COM 6229485SMikore.Li@Sun.COM fail: 6239485SMikore.Li@Sun.COM return (error); 6249485SMikore.Li@Sun.COM } 6259485SMikore.Li@Sun.COM 6269485SMikore.Li@Sun.COM static usbd_status 6279485SMikore.Li@Sun.COM urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index, 6289485SMikore.Li@Sun.COM uint16_t *data) 6299485SMikore.Li@Sun.COM { 6309485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 6319485SMikore.Li@Sun.COM usb_cr_t cr; 6329485SMikore.Li@Sun.COM usb_cb_flags_t cf; 6339485SMikore.Li@Sun.COM mblk_t *mp = 0; 6349485SMikore.Li@Sun.COM uint16_t data16; 6359485SMikore.Li@Sun.COM usbd_status error; 6369485SMikore.Li@Sun.COM 6379485SMikore.Li@Sun.COM data16 = *data; 6389485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 6399485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 6409485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 6419485SMikore.Li@Sun.COM req.wValue = addr; 6429485SMikore.Li@Sun.COM req.wIndex = (uint16_t)index; 6439485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 6449485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 6459485SMikore.Li@Sun.COM 6469485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED); 6479485SMikore.Li@Sun.COM if (mp == 0) { 6489485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_8225_write_s16: allocb failed\n"); 6499485SMikore.Li@Sun.COM return (-1); 6509485SMikore.Li@Sun.COM } 6519485SMikore.Li@Sun.COM *(mp->b_rptr) = (data16 & 0x00ff); 6529485SMikore.Li@Sun.COM *(mp->b_rptr + 1) = (data16 & 0xff00) >> 8; 6539485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t); 6549485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 6559485SMikore.Li@Sun.COM &cr, &cf, 0); 6569485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 6579485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 6589485SMikore.Li@Sun.COM "urtw_8225_write_s16: could not set regs:" 6599485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 6609485SMikore.Li@Sun.COM } 6619485SMikore.Li@Sun.COM if (mp) 6629485SMikore.Li@Sun.COM freemsg(mp); 6639485SMikore.Li@Sun.COM return (error); 6649485SMikore.Li@Sun.COM 6659485SMikore.Li@Sun.COM } 6669485SMikore.Li@Sun.COM 6679485SMikore.Li@Sun.COM static usbd_status 6689485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data) 6699485SMikore.Li@Sun.COM { 6709485SMikore.Li@Sun.COM int i; 6719485SMikore.Li@Sun.COM int16_t bit; 6729485SMikore.Li@Sun.COM uint8_t rlen = 12, wlen = 6; 6739485SMikore.Li@Sun.COM uint16_t o1, o2, o3, tmp; 6749485SMikore.Li@Sun.COM uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27; 6759485SMikore.Li@Sun.COM uint32_t mask = 0x80000000, value = 0; 6769485SMikore.Li@Sun.COM usbd_status error; 6779485SMikore.Li@Sun.COM 678*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &o1, 0)) 6799485SMikore.Li@Sun.COM goto fail; 680*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &o2, 0)) 6819485SMikore.Li@Sun.COM goto fail; 682*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &o3, 0)) 6839485SMikore.Li@Sun.COM goto fail; 684*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2 | 0xf, 0)) 6859485SMikore.Li@Sun.COM goto fail; 686*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3 | 0xf, 0)) 6879485SMikore.Li@Sun.COM goto fail; 6889485SMikore.Li@Sun.COM o1 &= ~0xf; 6899485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 690*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN, 0)) 6919485SMikore.Li@Sun.COM goto fail; 6929485SMikore.Li@Sun.COM DELAY(5); 693*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, o1, 0)) 6949485SMikore.Li@Sun.COM goto fail; 6959485SMikore.Li@Sun.COM DELAY(5); 6969485SMikore.Li@Sun.COM 6979485SMikore.Li@Sun.COM for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) { 6989485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0; 6999485SMikore.Li@Sun.COM 700*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 701*10364SMikore.Li@Sun.COM bit | o1, 0)) 7029485SMikore.Li@Sun.COM goto fail; 7039485SMikore.Li@Sun.COM DELAY(2); 704*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 705*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0)) 7069485SMikore.Li@Sun.COM goto fail; 7079485SMikore.Li@Sun.COM DELAY(2); 708*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 709*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0)) 7109485SMikore.Li@Sun.COM goto fail; 7119485SMikore.Li@Sun.COM DELAY(2); 7129485SMikore.Li@Sun.COM mask = mask >> 1; 7139485SMikore.Li@Sun.COM if (i == 2) 7149485SMikore.Li@Sun.COM break; 7159485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0; 716*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 717*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0)) 7189485SMikore.Li@Sun.COM goto fail; 7199485SMikore.Li@Sun.COM DELAY(2); 720*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 721*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0)) 7229485SMikore.Li@Sun.COM goto fail; 7239485SMikore.Li@Sun.COM DELAY(2); 724*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 725*10364SMikore.Li@Sun.COM bit | o1, 0)) 7269485SMikore.Li@Sun.COM goto fail; 7279485SMikore.Li@Sun.COM DELAY(1); 7289485SMikore.Li@Sun.COM } 7299485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 730*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0)) 7319485SMikore.Li@Sun.COM goto fail; 7329485SMikore.Li@Sun.COM DELAY(2); 7339485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 734*10364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW, 0)) 7359485SMikore.Li@Sun.COM goto fail; 7369485SMikore.Li@Sun.COM DELAY(2); 7379485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 738*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0)) 7399485SMikore.Li@Sun.COM goto fail; 7409485SMikore.Li@Sun.COM DELAY(2); 7419485SMikore.Li@Sun.COM 7429485SMikore.Li@Sun.COM mask = 0x800; 7439485SMikore.Li@Sun.COM for (i = 0; i < rlen; i++, mask = mask >> 1) { 7449485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 745*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0)) 7469485SMikore.Li@Sun.COM goto fail; 7479485SMikore.Li@Sun.COM DELAY(2); 7489485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 749*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0)) 7509485SMikore.Li@Sun.COM goto fail; 7519485SMikore.Li@Sun.COM DELAY(2); 7529485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 753*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0)) 7549485SMikore.Li@Sun.COM goto fail; 7559485SMikore.Li@Sun.COM DELAY(2); 7569485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 757*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0)) 7589485SMikore.Li@Sun.COM goto fail; 7599485SMikore.Li@Sun.COM DELAY(2); 7609485SMikore.Li@Sun.COM 761*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_INPUT, &tmp, 0)) 7629485SMikore.Li@Sun.COM goto fail; 7639485SMikore.Li@Sun.COM value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0); 7649485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 765*10364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0)) 7669485SMikore.Li@Sun.COM goto fail; 7679485SMikore.Li@Sun.COM DELAY(2); 7689485SMikore.Li@Sun.COM } 7699485SMikore.Li@Sun.COM 7709485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 7719485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN | 772*10364SMikore.Li@Sun.COM URTW_BB_HOST_BANG_RW, 0)) 7739485SMikore.Li@Sun.COM goto fail; 7749485SMikore.Li@Sun.COM DELAY(2); 7759485SMikore.Li@Sun.COM 776*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2, 0)) 7779485SMikore.Li@Sun.COM goto fail; 778*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3, 0)) 7799485SMikore.Li@Sun.COM goto fail; 780*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x3a0, 0); 7819485SMikore.Li@Sun.COM 7829485SMikore.Li@Sun.COM if (data != NULL) 7839485SMikore.Li@Sun.COM *data = value; 7849485SMikore.Li@Sun.COM fail: 7859485SMikore.Li@Sun.COM return (error); 7869485SMikore.Li@Sun.COM } 7879485SMikore.Li@Sun.COM 7889485SMikore.Li@Sun.COM static void 7899485SMikore.Li@Sun.COM urtw_delay_ms(int t) 7909485SMikore.Li@Sun.COM { 7919485SMikore.Li@Sun.COM DELAY(t * 1000); 7929485SMikore.Li@Sun.COM } 7939485SMikore.Li@Sun.COM 7949485SMikore.Li@Sun.COM static usbd_status 7959485SMikore.Li@Sun.COM urtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data) 7969485SMikore.Li@Sun.COM { 7979485SMikore.Li@Sun.COM uint16_t d80, d82, d84; 7989485SMikore.Li@Sun.COM usbd_status error; 7999485SMikore.Li@Sun.COM 800*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &d80, 0)) 8019485SMikore.Li@Sun.COM goto fail; 8029485SMikore.Li@Sun.COM d80 &= 0xfff3; 803*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &d82, 0)) 8049485SMikore.Li@Sun.COM goto fail; 805*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &d84, 0)) 8069485SMikore.Li@Sun.COM goto fail; 8079485SMikore.Li@Sun.COM d84 &= 0xfff0; 8089485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 809*10364SMikore.Li@Sun.COM d82 | 0x0007, 0)) 8109485SMikore.Li@Sun.COM goto fail; 8119485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 812*10364SMikore.Li@Sun.COM d84 | 0x0007, 0)) 8139485SMikore.Li@Sun.COM goto fail; 8149485SMikore.Li@Sun.COM 8159485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 816*10364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0)) 8179485SMikore.Li@Sun.COM goto fail; 818*10364SMikore.Li@Sun.COM urtw_delay_ms(2); 819*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, d80, 0)) 8209485SMikore.Li@Sun.COM goto fail; 8219485SMikore.Li@Sun.COM 8229485SMikore.Li@Sun.COM error = urtw_8225_write_s16(sc, addr, 0x8225, &data); 8239485SMikore.Li@Sun.COM if (error != 0) 8249485SMikore.Li@Sun.COM goto fail; 8259485SMikore.Li@Sun.COM 8269485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 827*10364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0)) 8289485SMikore.Li@Sun.COM goto fail; 8299485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 830*10364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0)) 8319485SMikore.Li@Sun.COM goto fail; 832*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, d84, 0); 8339485SMikore.Li@Sun.COM urtw_delay_ms(2); 8349485SMikore.Li@Sun.COM fail: 8359485SMikore.Li@Sun.COM return (error); 8369485SMikore.Li@Sun.COM } 8379485SMikore.Li@Sun.COM 8389485SMikore.Li@Sun.COM static usbd_status 8399485SMikore.Li@Sun.COM urtw_8225_isv2(struct urtw_softc *sc, int *ret) 8409485SMikore.Li@Sun.COM { 8419485SMikore.Li@Sun.COM uint32_t data; 8429485SMikore.Li@Sun.COM usbd_status error; 8439485SMikore.Li@Sun.COM 8449485SMikore.Li@Sun.COM *ret = 1; 8459485SMikore.Li@Sun.COM 846*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0080, 0)) 8479485SMikore.Li@Sun.COM goto fail; 848*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x0080, 0)) 8499485SMikore.Li@Sun.COM goto fail; 850*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x0080, 0)) 8519485SMikore.Li@Sun.COM goto fail; 8529485SMikore.Li@Sun.COM urtw_delay_ms(300); 8539485SMikore.Li@Sun.COM 8549485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7)) 8559485SMikore.Li@Sun.COM goto fail; 8569485SMikore.Li@Sun.COM 8579485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x8, &data); 8589485SMikore.Li@Sun.COM if (error != 0) 8599485SMikore.Li@Sun.COM goto fail; 8609485SMikore.Li@Sun.COM if (data != 0x588) 8619485SMikore.Li@Sun.COM *ret = 0; 8629485SMikore.Li@Sun.COM else { 8639485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x9, &data); 8649485SMikore.Li@Sun.COM if (error != 0) 8659485SMikore.Li@Sun.COM goto fail; 8669485SMikore.Li@Sun.COM if (data != 0x700) 8679485SMikore.Li@Sun.COM *ret = 0; 8689485SMikore.Li@Sun.COM } 8699485SMikore.Li@Sun.COM 8709485SMikore.Li@Sun.COM error = urtw_8225_write_c(sc, 0x0, 0xb7); 8719485SMikore.Li@Sun.COM fail: 8729485SMikore.Li@Sun.COM return (error); 8739485SMikore.Li@Sun.COM } 8749485SMikore.Li@Sun.COM 8759485SMikore.Li@Sun.COM static usbd_status 8769485SMikore.Li@Sun.COM urtw_get_rfchip(struct urtw_softc *sc) 8779485SMikore.Li@Sun.COM { 878*10364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf; 8799485SMikore.Li@Sun.COM int ret; 8809485SMikore.Li@Sun.COM uint32_t data; 8819485SMikore.Li@Sun.COM usbd_status error; 8829485SMikore.Li@Sun.COM 883*10364SMikore.Li@Sun.COM rf->rf_sc = sc; 884*10364SMikore.Li@Sun.COM 885*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 886*10364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); 887*10364SMikore.Li@Sun.COM if (error != 0) { 888*10364SMikore.Li@Sun.COM cmn_err(CE_WARN, "RF ID read failed\n"); 889*10364SMikore.Li@Sun.COM return (-1); 890*10364SMikore.Li@Sun.COM } 891*10364SMikore.Li@Sun.COM switch (data & 0xff) { 892*10364SMikore.Li@Sun.COM case URTW_EPROM_RFCHIPID_RTL8225U: 893*10364SMikore.Li@Sun.COM error = urtw_8225_isv2(sc, &ret); 894*10364SMikore.Li@Sun.COM if (error != 0) { 895*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 896*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 897*10364SMikore.Li@Sun.COM "8225 version check failed\n")); 898*10364SMikore.Li@Sun.COM goto fail; 899*10364SMikore.Li@Sun.COM } 900*10364SMikore.Li@Sun.COM if (ret == 0) { 901*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 902*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 903*10364SMikore.Li@Sun.COM "8225 detected\n")); 904*10364SMikore.Li@Sun.COM rf->init = urtw_8225_rf_init; 905*10364SMikore.Li@Sun.COM rf->set_chan = urtw_8225_rf_set_chan; 906*10364SMikore.Li@Sun.COM rf->set_sens = urtw_8225_rf_set_sens; 907*10364SMikore.Li@Sun.COM } else { 908*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 909*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 910*10364SMikore.Li@Sun.COM "8225 v2 detected\n")); 911*10364SMikore.Li@Sun.COM rf->init = urtw_8225v2_rf_init; 912*10364SMikore.Li@Sun.COM rf->set_chan = urtw_8225v2_rf_set_chan; 913*10364SMikore.Li@Sun.COM rf->set_sens = NULL; 914*10364SMikore.Li@Sun.COM } 915*10364SMikore.Li@Sun.COM break; 916*10364SMikore.Li@Sun.COM default: 9179485SMikore.Li@Sun.COM goto fail; 9189485SMikore.Li@Sun.COM } 919*10364SMikore.Li@Sun.COM } else { 920*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 921*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 922*10364SMikore.Li@Sun.COM "8225 v2 [b] detected\n")); 923*10364SMikore.Li@Sun.COM rf->init = urtw_8225v2_b_rf_init; 924*10364SMikore.Li@Sun.COM rf->set_chan = urtw_8225v2_b_rf_set_chan; 925*10364SMikore.Li@Sun.COM rf->set_sens = NULL; 9269485SMikore.Li@Sun.COM } 9279485SMikore.Li@Sun.COM 928*10364SMikore.Li@Sun.COM rf->max_sens = URTW_8225_RF_MAX_SENS; 929*10364SMikore.Li@Sun.COM rf->sens = URTW_8225_RF_DEF_SENS; 930*10364SMikore.Li@Sun.COM 931*10364SMikore.Li@Sun.COM return (0); 932*10364SMikore.Li@Sun.COM 9339485SMikore.Li@Sun.COM fail: 934*10364SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported RF chip %d\n", data & 0xff); 935*10364SMikore.Li@Sun.COM return (-1); 9369485SMikore.Li@Sun.COM } 9379485SMikore.Li@Sun.COM 9389485SMikore.Li@Sun.COM static usbd_status 9399485SMikore.Li@Sun.COM urtw_get_txpwr(struct urtw_softc *sc) 9409485SMikore.Li@Sun.COM { 9419485SMikore.Li@Sun.COM int i, j; 9429485SMikore.Li@Sun.COM uint32_t data; 9439485SMikore.Li@Sun.COM usbd_status error; 9449485SMikore.Li@Sun.COM 9459485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data); 9469485SMikore.Li@Sun.COM if (error != 0) 9479485SMikore.Li@Sun.COM goto fail; 9489485SMikore.Li@Sun.COM sc->sc_txpwr_cck_base = data & 0xf; 9499485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf; 9509485SMikore.Li@Sun.COM 9519485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 6; i += 2, j++) { 9529485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data); 9539485SMikore.Li@Sun.COM if (error != 0) 9549485SMikore.Li@Sun.COM goto fail; 9559485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i] = data & 0xf; 9569485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8; 9579485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4; 9589485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12; 9599485SMikore.Li@Sun.COM } 9609485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) { 9619485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data); 9629485SMikore.Li@Sun.COM if (error != 0) 9639485SMikore.Li@Sun.COM goto fail; 9649485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6] = data & 0xf; 9659485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8; 9669485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; 9679485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; 9689485SMikore.Li@Sun.COM } 969*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 970*10364SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) { 971*10364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, 972*10364SMikore.Li@Sun.COM &data); 973*10364SMikore.Li@Sun.COM if (error != 0) 974*10364SMikore.Li@Sun.COM goto fail; 975*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; 976*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; 977*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; 978*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = 979*10364SMikore.Li@Sun.COM (data & 0xf000) >> 12; 980*10364SMikore.Li@Sun.COM } 981*10364SMikore.Li@Sun.COM } else { 982*10364SMikore.Li@Sun.COM /* Channel 11. */ 983*10364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0x1b, &data); 9849485SMikore.Li@Sun.COM if (error != 0) 9859485SMikore.Li@Sun.COM goto fail; 986*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[11] = data & 0xf; 987*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[11] = (data & 0xf0) >> 4; 988*10364SMikore.Li@Sun.COM 989*10364SMikore.Li@Sun.COM /* Channel 12. */ 990*10364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0xa, &data); 991*10364SMikore.Li@Sun.COM if (error != 0) 992*10364SMikore.Li@Sun.COM goto fail; 993*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[12] = data & 0xf; 994*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[12] = (data & 0xf0) >> 4; 995*10364SMikore.Li@Sun.COM 996*10364SMikore.Li@Sun.COM /* Channel 13, 14. */ 997*10364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0x1c, &data); 998*10364SMikore.Li@Sun.COM if (error != 0) 999*10364SMikore.Li@Sun.COM goto fail; 1000*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[13] = data & 0xf; 1001*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[13] = (data & 0xf0) >> 4; 1002*10364SMikore.Li@Sun.COM sc->sc_txpwr_cck[14] = (data & 0xf00) >> 8; 1003*10364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[14] = (data & 0xf000) >> 12; 10049485SMikore.Li@Sun.COM } 10059485SMikore.Li@Sun.COM fail: 10069485SMikore.Li@Sun.COM return (error); 10079485SMikore.Li@Sun.COM } 10089485SMikore.Li@Sun.COM 1009*10364SMikore.Li@Sun.COM 10109485SMikore.Li@Sun.COM static usbd_status 10119485SMikore.Li@Sun.COM urtw_get_macaddr(struct urtw_softc *sc) 10129485SMikore.Li@Sun.COM { 10139485SMikore.Li@Sun.COM uint32_t data; 10149485SMikore.Li@Sun.COM usbd_status error; 10159485SMikore.Li@Sun.COM uint8_t *m = 0; 10169485SMikore.Li@Sun.COM 10179485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); 10189485SMikore.Li@Sun.COM if (error != 0) 10199485SMikore.Li@Sun.COM goto fail; 10209485SMikore.Li@Sun.COM sc->sc_bssid[0] = data & 0xff; 10219485SMikore.Li@Sun.COM sc->sc_bssid[1] = (data & 0xff00) >> 8; 10229485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); 10239485SMikore.Li@Sun.COM if (error != 0) 10249485SMikore.Li@Sun.COM goto fail; 10259485SMikore.Li@Sun.COM sc->sc_bssid[2] = data & 0xff; 10269485SMikore.Li@Sun.COM sc->sc_bssid[3] = (data & 0xff00) >> 8; 10279485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); 10289485SMikore.Li@Sun.COM if (error != 0) 10299485SMikore.Li@Sun.COM goto fail; 10309485SMikore.Li@Sun.COM sc->sc_bssid[4] = data & 0xff; 10319485SMikore.Li@Sun.COM sc->sc_bssid[5] = (data & 0xff00) >> 8; 10329485SMikore.Li@Sun.COM bcopy(sc->sc_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN); 10339485SMikore.Li@Sun.COM m = sc->sc_bssid; 10349485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 10359485SMikore.Li@Sun.COM "MAC: %x:%x:%x:%x:%x:%x\n", 10369485SMikore.Li@Sun.COM m[0], m[1], m[2], m[3], m[4], m[5])); 10379485SMikore.Li@Sun.COM fail: 10389485SMikore.Li@Sun.COM return (error); 10399485SMikore.Li@Sun.COM } 10409485SMikore.Li@Sun.COM 10419485SMikore.Li@Sun.COM static usbd_status 10429485SMikore.Li@Sun.COM urtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data) 10439485SMikore.Li@Sun.COM { 10449485SMikore.Li@Sun.COM #define URTW_READCMD_LEN 3 10459485SMikore.Li@Sun.COM int addrlen, i; 10469485SMikore.Li@Sun.COM int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 }; 10479485SMikore.Li@Sun.COM usbd_status error; 10489485SMikore.Li@Sun.COM 10499485SMikore.Li@Sun.COM /* NB: make sure the buffer is initialized */ 10509485SMikore.Li@Sun.COM *data = 0; 10519485SMikore.Li@Sun.COM 10529485SMikore.Li@Sun.COM /* enable EPROM programming */ 10539485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD, 1054*10364SMikore.Li@Sun.COM URTW_EPROM_CMD_PROGRAM_MODE, 0)) 10559485SMikore.Li@Sun.COM goto fail; 10569485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 10579485SMikore.Li@Sun.COM 10589485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE); 10599485SMikore.Li@Sun.COM if (error != 0) 10609485SMikore.Li@Sun.COM goto fail; 10619485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 10629485SMikore.Li@Sun.COM if (error != 0) 10639485SMikore.Li@Sun.COM goto fail; 10649485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN); 10659485SMikore.Li@Sun.COM if (error != 0) 10669485SMikore.Li@Sun.COM goto fail; 10679485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56) { 10689485SMikore.Li@Sun.COM addrlen = 8; 10699485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 7); 10709485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 6); 10719485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 5); 10729485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 4); 10739485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 3); 10749485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 2); 10759485SMikore.Li@Sun.COM addrstr[6] = addr & (1 << 1); 10769485SMikore.Li@Sun.COM addrstr[7] = addr & (1 << 0); 10779485SMikore.Li@Sun.COM } else { 10789485SMikore.Li@Sun.COM addrlen = 6; 10799485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 5); 10809485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 4); 10819485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 3); 10829485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 2); 10839485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 1); 10849485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 0); 10859485SMikore.Li@Sun.COM } 10869485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, addrstr, addrlen); 10879485SMikore.Li@Sun.COM if (error != 0) 10889485SMikore.Li@Sun.COM goto fail; 10899485SMikore.Li@Sun.COM 10909485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, 0); 10919485SMikore.Li@Sun.COM if (error != 0) 10929485SMikore.Li@Sun.COM goto fail; 10939485SMikore.Li@Sun.COM 10949485SMikore.Li@Sun.COM for (i = 0; i < 16; i++) { 10959485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 10969485SMikore.Li@Sun.COM if (error != 0) 10979485SMikore.Li@Sun.COM goto fail; 10989485SMikore.Li@Sun.COM error = urtw_eprom_readbit(sc, &data16); 10999485SMikore.Li@Sun.COM if (error != 0) 11009485SMikore.Li@Sun.COM goto fail; 11019485SMikore.Li@Sun.COM 11029485SMikore.Li@Sun.COM (*data) |= (data16 << (15 - i)); 11039485SMikore.Li@Sun.COM } 11049485SMikore.Li@Sun.COM 11059485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE); 11069485SMikore.Li@Sun.COM if (error != 0) 11079485SMikore.Li@Sun.COM goto fail; 11089485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 11099485SMikore.Li@Sun.COM if (error != 0) 11109485SMikore.Li@Sun.COM goto fail; 11119485SMikore.Li@Sun.COM 11129485SMikore.Li@Sun.COM /* now disable EPROM programming */ 1113*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 1114*10364SMikore.Li@Sun.COM URTW_EPROM_CMD_NORMAL_MODE, 0); 11159485SMikore.Li@Sun.COM fail: 11169485SMikore.Li@Sun.COM return (error); 11179485SMikore.Li@Sun.COM #undef URTW_READCMD_LEN 11189485SMikore.Li@Sun.COM } 11199485SMikore.Li@Sun.COM 11209485SMikore.Li@Sun.COM static usbd_status 11219485SMikore.Li@Sun.COM urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data) 11229485SMikore.Li@Sun.COM { 11239485SMikore.Li@Sun.COM uint8_t data8; 11249485SMikore.Li@Sun.COM usbd_status error; 11259485SMikore.Li@Sun.COM 1126*10364SMikore.Li@Sun.COM error = urtw_read8_c(sc, URTW_EPROM_CMD, &data8, 0); 11279485SMikore.Li@Sun.COM *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0; 11289485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 11299485SMikore.Li@Sun.COM return (error); 11309485SMikore.Li@Sun.COM } 11319485SMikore.Li@Sun.COM 11329485SMikore.Li@Sun.COM static usbd_status 11339485SMikore.Li@Sun.COM urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen) 11349485SMikore.Li@Sun.COM { 11359485SMikore.Li@Sun.COM int i = 0; 11369485SMikore.Li@Sun.COM usbd_status error; 11379485SMikore.Li@Sun.COM 11389485SMikore.Li@Sun.COM for (i = 0; i < buflen; i++) { 11399485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, buf[i]); 11409485SMikore.Li@Sun.COM if (error != 0) 11419485SMikore.Li@Sun.COM goto fail; 11429485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 11439485SMikore.Li@Sun.COM if (error != 0) 11449485SMikore.Li@Sun.COM goto fail; 11459485SMikore.Li@Sun.COM } 11469485SMikore.Li@Sun.COM fail: 11479485SMikore.Li@Sun.COM return (error); 11489485SMikore.Li@Sun.COM } 11499485SMikore.Li@Sun.COM 11509485SMikore.Li@Sun.COM static usbd_status 11519485SMikore.Li@Sun.COM urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit) 11529485SMikore.Li@Sun.COM { 11539485SMikore.Li@Sun.COM uint8_t data; 11549485SMikore.Li@Sun.COM usbd_status error; 11559485SMikore.Li@Sun.COM 1156*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0)) 11579485SMikore.Li@Sun.COM goto fail; 11589485SMikore.Li@Sun.COM if (bit != 0) 11599485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 1160*10364SMikore.Li@Sun.COM data | URTW_EPROM_WRITEBIT, 0); 11619485SMikore.Li@Sun.COM else 11629485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 1163*10364SMikore.Li@Sun.COM data & ~URTW_EPROM_WRITEBIT, 0); 11649485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 11659485SMikore.Li@Sun.COM fail: 11669485SMikore.Li@Sun.COM return (error); 11679485SMikore.Li@Sun.COM } 11689485SMikore.Li@Sun.COM 11699485SMikore.Li@Sun.COM static usbd_status 11709485SMikore.Li@Sun.COM urtw_eprom_ck(struct urtw_softc *sc) 11719485SMikore.Li@Sun.COM { 11729485SMikore.Li@Sun.COM uint8_t data; 11739485SMikore.Li@Sun.COM usbd_status error; 11749485SMikore.Li@Sun.COM 11759485SMikore.Li@Sun.COM /* masking */ 1176*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0)) 11779485SMikore.Li@Sun.COM goto fail; 1178*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK, 0)) 11799485SMikore.Li@Sun.COM goto fail; 11809485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 11819485SMikore.Li@Sun.COM /* unmasking */ 1182*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0)) 11839485SMikore.Li@Sun.COM goto fail; 1184*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK, 0); 11859485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 11869485SMikore.Li@Sun.COM fail: 11879485SMikore.Li@Sun.COM return (error); 11889485SMikore.Li@Sun.COM } 11899485SMikore.Li@Sun.COM 11909485SMikore.Li@Sun.COM static usbd_status 11919485SMikore.Li@Sun.COM urtw_eprom_cs(struct urtw_softc *sc, int able) 11929485SMikore.Li@Sun.COM { 11939485SMikore.Li@Sun.COM uint8_t data; 11949485SMikore.Li@Sun.COM usbd_status error; 11959485SMikore.Li@Sun.COM 1196*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0)) 11979485SMikore.Li@Sun.COM goto fail; 11989485SMikore.Li@Sun.COM if (able == URTW_EPROM_ENABLE) 11999485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 1200*10364SMikore.Li@Sun.COM data | URTW_EPROM_CS, 0); 12019485SMikore.Li@Sun.COM else 12029485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 1203*10364SMikore.Li@Sun.COM data & ~URTW_EPROM_CS, 0); 12049485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 12059485SMikore.Li@Sun.COM fail: 12069485SMikore.Li@Sun.COM return (error); 12079485SMikore.Li@Sun.COM } 12089485SMikore.Li@Sun.COM 12099485SMikore.Li@Sun.COM static usbd_status 1210*10364SMikore.Li@Sun.COM urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data, uint8_t idx) 12119485SMikore.Li@Sun.COM { 12129485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 12139485SMikore.Li@Sun.COM usb_cr_t cr; 12149485SMikore.Li@Sun.COM usb_cb_flags_t cf; 12159485SMikore.Li@Sun.COM mblk_t *mp = NULL; 12169485SMikore.Li@Sun.COM usbd_status error; 12179485SMikore.Li@Sun.COM 12189485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 12199485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 12209485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 12219485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1222*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 12239485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 12249485SMikore.Li@Sun.COM 12259485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 12269485SMikore.Li@Sun.COM &cr, &cf, 0); 12279485SMikore.Li@Sun.COM 12289485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 12299485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 12309485SMikore.Li@Sun.COM "urtw_read8_c: get regs req failed :" 12319485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 12329485SMikore.Li@Sun.COM return (error); 12339485SMikore.Li@Sun.COM } 12349485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t)); 12359485SMikore.Li@Sun.COM if (mp) 12369485SMikore.Li@Sun.COM freemsg(mp); 12379485SMikore.Li@Sun.COM return (error); 12389485SMikore.Li@Sun.COM } 12399485SMikore.Li@Sun.COM 12409485SMikore.Li@Sun.COM static usbd_status 12419485SMikore.Li@Sun.COM urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data) 12429485SMikore.Li@Sun.COM { 12439485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 12449485SMikore.Li@Sun.COM usb_cr_t cr; 12459485SMikore.Li@Sun.COM usb_cb_flags_t cf; 12469485SMikore.Li@Sun.COM mblk_t *mp = NULL; 12479485SMikore.Li@Sun.COM usbd_status error; 12489485SMikore.Li@Sun.COM 12499485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 12509485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 12519485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 12529485SMikore.Li@Sun.COM req.wValue = val | 0xfe00; 12539485SMikore.Li@Sun.COM req.wIndex = 0; 12549485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 12559485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 12569485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 12579485SMikore.Li@Sun.COM &cr, &cf, 0); 12589485SMikore.Li@Sun.COM 12599485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 12609485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 12619485SMikore.Li@Sun.COM "urtw_read8e: get regs req failed :" 12629485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 12639485SMikore.Li@Sun.COM return (error); 12649485SMikore.Li@Sun.COM } 12659485SMikore.Li@Sun.COM 12669485SMikore.Li@Sun.COM if (mp) { 12679485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t)); 12689485SMikore.Li@Sun.COM freemsg(mp); 12699485SMikore.Li@Sun.COM } 12709485SMikore.Li@Sun.COM return (error); 12719485SMikore.Li@Sun.COM } 12729485SMikore.Li@Sun.COM 12739485SMikore.Li@Sun.COM static usbd_status 1274*10364SMikore.Li@Sun.COM urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data, uint8_t idx) 12759485SMikore.Li@Sun.COM { 12769485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 12779485SMikore.Li@Sun.COM usb_cr_t cr; 12789485SMikore.Li@Sun.COM usb_cb_flags_t cf; 12799485SMikore.Li@Sun.COM mblk_t *mp = NULL; 12809485SMikore.Li@Sun.COM usbd_status error; 12819485SMikore.Li@Sun.COM 12829485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 12839485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 12849485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 12859485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1286*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 12879485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 12889485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 12899485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 12909485SMikore.Li@Sun.COM &cr, &cf, 0); 12919485SMikore.Li@Sun.COM 12929485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 12939485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 12949485SMikore.Li@Sun.COM "urtw_read16_c: get regs req failed :" 12959485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", 12969485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 12979485SMikore.Li@Sun.COM return (error); 12989485SMikore.Li@Sun.COM } 12999485SMikore.Li@Sun.COM if (mp) { 13009485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint16_t)); 13019485SMikore.Li@Sun.COM freemsg(mp); 13029485SMikore.Li@Sun.COM } 13039485SMikore.Li@Sun.COM return (error); 13049485SMikore.Li@Sun.COM } 13059485SMikore.Li@Sun.COM 13069485SMikore.Li@Sun.COM static usbd_status 1307*10364SMikore.Li@Sun.COM urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data, uint8_t idx) 13089485SMikore.Li@Sun.COM { 13099485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 13109485SMikore.Li@Sun.COM usb_cr_t cr; 13119485SMikore.Li@Sun.COM usb_cb_flags_t cf; 13129485SMikore.Li@Sun.COM mblk_t *mp = NULL; 13139485SMikore.Li@Sun.COM usbd_status error; 13149485SMikore.Li@Sun.COM 13159485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 13169485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 13179485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 13189485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1319*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 13209485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t); 13219485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 13229485SMikore.Li@Sun.COM 13239485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 13249485SMikore.Li@Sun.COM &cr, &cf, 0); 13259485SMikore.Li@Sun.COM 13269485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 13279485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 13289485SMikore.Li@Sun.COM "urtw_read32_c: get regs req failed :" 13299485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 13309485SMikore.Li@Sun.COM return (error); 13319485SMikore.Li@Sun.COM } 13329485SMikore.Li@Sun.COM 13339485SMikore.Li@Sun.COM if (mp) { 13349485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint32_t)); 13359485SMikore.Li@Sun.COM freemsg(mp); 13369485SMikore.Li@Sun.COM } 13379485SMikore.Li@Sun.COM return (error); 13389485SMikore.Li@Sun.COM } 13399485SMikore.Li@Sun.COM 13409485SMikore.Li@Sun.COM static usbd_status 1341*10364SMikore.Li@Sun.COM urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data, uint8_t idx) 13429485SMikore.Li@Sun.COM { 13439485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 13449485SMikore.Li@Sun.COM usb_cr_t cr; 13459485SMikore.Li@Sun.COM usb_cb_flags_t cf; 13469485SMikore.Li@Sun.COM mblk_t *mp = 0; 13479485SMikore.Li@Sun.COM int error; 13489485SMikore.Li@Sun.COM 13499485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 13509485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 13519485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 13529485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1353*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 13549485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 13559485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 13569485SMikore.Li@Sun.COM 13579485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED); 13589485SMikore.Li@Sun.COM if (mp == NULL) { 13599485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8_c: failed alloc mblk."); 13609485SMikore.Li@Sun.COM return (-1); 13619485SMikore.Li@Sun.COM } 13629485SMikore.Li@Sun.COM *(uint8_t *)(mp->b_rptr) = data; 13639485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t); 13649485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 13659485SMikore.Li@Sun.COM &cr, &cf, 0); 13669485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 13679485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 13689485SMikore.Li@Sun.COM "urtw_write8_c: could not set regs:" 13699485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 13709485SMikore.Li@Sun.COM } 13719485SMikore.Li@Sun.COM if (mp) 13729485SMikore.Li@Sun.COM freemsg(mp); 13739485SMikore.Li@Sun.COM return (error); 13749485SMikore.Li@Sun.COM } 13759485SMikore.Li@Sun.COM 13769485SMikore.Li@Sun.COM static usbd_status 13779485SMikore.Li@Sun.COM urtw_write8e(struct urtw_softc *sc, int val, uint8_t data) 13789485SMikore.Li@Sun.COM { 13799485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 13809485SMikore.Li@Sun.COM usb_cr_t cr; 13819485SMikore.Li@Sun.COM usb_cb_flags_t cf; 13829485SMikore.Li@Sun.COM mblk_t *mp = 0; 13839485SMikore.Li@Sun.COM int error; 13849485SMikore.Li@Sun.COM 13859485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 13869485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 13879485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 13889485SMikore.Li@Sun.COM req.wValue = val | 0xfe00; 13899485SMikore.Li@Sun.COM req.wIndex = 0; 13909485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 13919485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 13929485SMikore.Li@Sun.COM 13939485SMikore.Li@Sun.COM mp = allocb(sizeof (uint8_t), BPRI_MED); 13949485SMikore.Li@Sun.COM if (mp == NULL) { 13959485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8e: failed alloc mblk."); 13969485SMikore.Li@Sun.COM return (-1); 13979485SMikore.Li@Sun.COM } 13989485SMikore.Li@Sun.COM *(mp->b_rptr) = data; 13999485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t); 14009485SMikore.Li@Sun.COM 14019485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 14029485SMikore.Li@Sun.COM &cr, &cf, 0); 14039485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 14049485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 14059485SMikore.Li@Sun.COM "urtw_write8e: could not set regs:" 14069485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 14079485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 14089485SMikore.Li@Sun.COM } 14099485SMikore.Li@Sun.COM if (mp) 14109485SMikore.Li@Sun.COM freemsg(mp); 14119485SMikore.Li@Sun.COM return (error); 14129485SMikore.Li@Sun.COM } 14139485SMikore.Li@Sun.COM 14149485SMikore.Li@Sun.COM static usbd_status 1415*10364SMikore.Li@Sun.COM urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data, uint8_t idx) 14169485SMikore.Li@Sun.COM { 14179485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 14189485SMikore.Li@Sun.COM usb_cr_t cr; 14199485SMikore.Li@Sun.COM usb_cb_flags_t cf; 14209485SMikore.Li@Sun.COM mblk_t *mp = 0; 14219485SMikore.Li@Sun.COM int error; 14229485SMikore.Li@Sun.COM 14239485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 14249485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 14259485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 14269485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1427*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 14289485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 14299485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 14309485SMikore.Li@Sun.COM 14319485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED); 14329485SMikore.Li@Sun.COM if (mp == NULL) { 14339485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write16_c: failed alloc mblk."); 14349485SMikore.Li@Sun.COM return (-1); 14359485SMikore.Li@Sun.COM } 14369485SMikore.Li@Sun.COM *(uint16_t *)(uintptr_t)(mp->b_rptr) = data; 14379485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t); 14389485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 14399485SMikore.Li@Sun.COM &cr, &cf, 0); 14409485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 14419485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 14429485SMikore.Li@Sun.COM "urtw_write16_c: could not set regs:" 14439485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 14449485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 14459485SMikore.Li@Sun.COM } 14469485SMikore.Li@Sun.COM if (mp) 14479485SMikore.Li@Sun.COM freemsg(mp); 14489485SMikore.Li@Sun.COM return (error); 14499485SMikore.Li@Sun.COM } 14509485SMikore.Li@Sun.COM 14519485SMikore.Li@Sun.COM static usbd_status 1452*10364SMikore.Li@Sun.COM urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data, uint8_t idx) 14539485SMikore.Li@Sun.COM { 14549485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 14559485SMikore.Li@Sun.COM usb_cr_t cr; 14569485SMikore.Li@Sun.COM usb_cb_flags_t cf; 14579485SMikore.Li@Sun.COM mblk_t *mp = 0; 14589485SMikore.Li@Sun.COM int error; 14599485SMikore.Li@Sun.COM 14609485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 14619485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 14629485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 14639485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1464*10364SMikore.Li@Sun.COM req.wIndex = idx & 0x03; 14659485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t); 14669485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 14679485SMikore.Li@Sun.COM 14689485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED); 14699485SMikore.Li@Sun.COM if (mp == NULL) { 14709485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write32_c: failed alloc mblk."); 14719485SMikore.Li@Sun.COM return (-1); 14729485SMikore.Li@Sun.COM } 14739485SMikore.Li@Sun.COM *(uint32_t *)(uintptr_t)(mp->b_rptr) = data; 14749485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint32_t); 14759485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 14769485SMikore.Li@Sun.COM &cr, &cf, 0); 14779485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 14789485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 14799485SMikore.Li@Sun.COM "urtw_write32_c: could not set regs:" 14809485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 14819485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 14829485SMikore.Li@Sun.COM } 14839485SMikore.Li@Sun.COM 14849485SMikore.Li@Sun.COM if (mp) 14859485SMikore.Li@Sun.COM freemsg(mp); 14869485SMikore.Li@Sun.COM return (error); 14879485SMikore.Li@Sun.COM } 14889485SMikore.Li@Sun.COM 14899485SMikore.Li@Sun.COM static usbd_status 14909485SMikore.Li@Sun.COM urtw_set_mode(struct urtw_softc *sc, uint32_t mode) 14919485SMikore.Li@Sun.COM { 14929485SMikore.Li@Sun.COM uint8_t data; 14939485SMikore.Li@Sun.COM usbd_status error; 14949485SMikore.Li@Sun.COM 1495*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0)) 14969485SMikore.Li@Sun.COM goto fail; 14979485SMikore.Li@Sun.COM data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT); 14989485SMikore.Li@Sun.COM data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK); 1499*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data, 0); 15009485SMikore.Li@Sun.COM fail: 15019485SMikore.Li@Sun.COM return (error); 15029485SMikore.Li@Sun.COM } 15039485SMikore.Li@Sun.COM 15049485SMikore.Li@Sun.COM static usbd_status 15059485SMikore.Li@Sun.COM urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val) 15069485SMikore.Li@Sun.COM { 15079485SMikore.Li@Sun.COM uint8_t data; 15089485SMikore.Li@Sun.COM usbd_status error; 15099485SMikore.Li@Sun.COM 15109485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 15119485SMikore.Li@Sun.COM if (error) 15129485SMikore.Li@Sun.COM goto fail; 15139485SMikore.Li@Sun.COM 1514*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0)) 15159485SMikore.Li@Sun.COM goto fail; 15169485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1517*10364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0)) 15189485SMikore.Li@Sun.COM goto fail; 1519*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM, val, 0)) 15209485SMikore.Li@Sun.COM goto fail; 1521*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0)) 15229485SMikore.Li@Sun.COM goto fail; 15239485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1524*10364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0)) 15259485SMikore.Li@Sun.COM goto fail; 15269485SMikore.Li@Sun.COM 15279485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 15289485SMikore.Li@Sun.COM if (error) 15299485SMikore.Li@Sun.COM goto fail; 15309485SMikore.Li@Sun.COM fail: 15319485SMikore.Li@Sun.COM return (error); 15329485SMikore.Li@Sun.COM } 15339485SMikore.Li@Sun.COM 15349485SMikore.Li@Sun.COM static usbd_status 15359485SMikore.Li@Sun.COM urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val) 15369485SMikore.Li@Sun.COM { 15379485SMikore.Li@Sun.COM uint8_t data; 15389485SMikore.Li@Sun.COM usbd_status error; 15399485SMikore.Li@Sun.COM 15409485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 15419485SMikore.Li@Sun.COM if (error) 15429485SMikore.Li@Sun.COM goto fail; 15439485SMikore.Li@Sun.COM 1544*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0)) 15459485SMikore.Li@Sun.COM goto fail; 15469485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1547*10364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0)) 15489485SMikore.Li@Sun.COM goto fail; 1549*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM2, val, 0)) 15509485SMikore.Li@Sun.COM goto fail; 1551*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0)) 15529485SMikore.Li@Sun.COM goto fail; 15539485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1554*10364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0)) 15559485SMikore.Li@Sun.COM goto fail; 15569485SMikore.Li@Sun.COM 15579485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 15589485SMikore.Li@Sun.COM if (error) 15599485SMikore.Li@Sun.COM goto fail; 15609485SMikore.Li@Sun.COM fail: 15619485SMikore.Li@Sun.COM return (error); 15629485SMikore.Li@Sun.COM } 15639485SMikore.Li@Sun.COM 15649485SMikore.Li@Sun.COM static usbd_status 15659485SMikore.Li@Sun.COM urtw_intr_disable(struct urtw_softc *sc) 15669485SMikore.Li@Sun.COM { 15679485SMikore.Li@Sun.COM usbd_status error; 15689485SMikore.Li@Sun.COM 1569*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0, 0); 15709485SMikore.Li@Sun.COM return (error); 15719485SMikore.Li@Sun.COM } 15729485SMikore.Li@Sun.COM 15739485SMikore.Li@Sun.COM static usbd_status 1574*10364SMikore.Li@Sun.COM urtw_8187_reset(struct urtw_softc *sc) 15759485SMikore.Li@Sun.COM { 15769485SMikore.Li@Sun.COM uint8_t data; 15779485SMikore.Li@Sun.COM usbd_status error; 15789485SMikore.Li@Sun.COM 1579*10364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON); 15809485SMikore.Li@Sun.COM if (error) 15819485SMikore.Li@Sun.COM goto fail; 1582*10364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON); 15839485SMikore.Li@Sun.COM if (error) 15849485SMikore.Li@Sun.COM goto fail; 15859485SMikore.Li@Sun.COM 15869485SMikore.Li@Sun.COM error = urtw_intr_disable(sc); 15879485SMikore.Li@Sun.COM if (error) 15889485SMikore.Li@Sun.COM goto fail; 15899485SMikore.Li@Sun.COM urtw_delay_ms(50); 15909485SMikore.Li@Sun.COM 15919485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x10); 15929485SMikore.Li@Sun.COM if (error != 0) 15939485SMikore.Li@Sun.COM goto fail; 15949485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x11); 15959485SMikore.Li@Sun.COM if (error != 0) 15969485SMikore.Li@Sun.COM goto fail; 15979485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x00); 15989485SMikore.Li@Sun.COM if (error != 0) 15999485SMikore.Li@Sun.COM goto fail; 16009485SMikore.Li@Sun.COM urtw_delay_ms(50); 16019485SMikore.Li@Sun.COM 1602*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0)) 16039485SMikore.Li@Sun.COM goto fail; 16049485SMikore.Li@Sun.COM data = (data & 2) | URTW_CMD_RST; 1605*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CMD, data, 0)) 16069485SMikore.Li@Sun.COM goto fail; 16079485SMikore.Li@Sun.COM urtw_delay_ms(50); 16089485SMikore.Li@Sun.COM 1609*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0)) 16109485SMikore.Li@Sun.COM goto fail; 16119485SMikore.Li@Sun.COM if (data & URTW_CMD_RST) { 16129485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw reset timeout\n"); 16139485SMikore.Li@Sun.COM goto fail; 16149485SMikore.Li@Sun.COM } 16159485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD); 16169485SMikore.Li@Sun.COM if (error) 16179485SMikore.Li@Sun.COM goto fail; 16189485SMikore.Li@Sun.COM urtw_delay_ms(50); 16199485SMikore.Li@Sun.COM 1620*10364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON); 16219485SMikore.Li@Sun.COM if (error) 16229485SMikore.Li@Sun.COM goto fail; 1623*10364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON); 16249485SMikore.Li@Sun.COM if (error) 16259485SMikore.Li@Sun.COM goto fail; 16269485SMikore.Li@Sun.COM fail: 16279485SMikore.Li@Sun.COM return (error); 16289485SMikore.Li@Sun.COM } 16299485SMikore.Li@Sun.COM 16309485SMikore.Li@Sun.COM static usbd_status 16319485SMikore.Li@Sun.COM urtw_led_on(struct urtw_softc *sc, int type) 16329485SMikore.Li@Sun.COM { 16339485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) { 16349485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) { 16359485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0: 1636*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0); 1637*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x00, 0); 16389485SMikore.Li@Sun.COM break; 16399485SMikore.Li@Sun.COM default: 16409485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x", 16419485SMikore.Li@Sun.COM sc->sc_gpio_ledpin); 16429485SMikore.Li@Sun.COM /* never reach */ 16439485SMikore.Li@Sun.COM } 16449485SMikore.Li@Sun.COM } else { 16459485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type); 16469485SMikore.Li@Sun.COM /* never reach */ 16479485SMikore.Li@Sun.COM } 16489485SMikore.Li@Sun.COM 16499485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 1; 16509485SMikore.Li@Sun.COM return (0); 16519485SMikore.Li@Sun.COM } 16529485SMikore.Li@Sun.COM 16539485SMikore.Li@Sun.COM static usbd_status 16549485SMikore.Li@Sun.COM urtw_led_off(struct urtw_softc *sc, int type) 16559485SMikore.Li@Sun.COM { 16569485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) { 16579485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) { 16589485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0: 1659*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0); 1660*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x01, 0); 16619485SMikore.Li@Sun.COM break; 16629485SMikore.Li@Sun.COM default: 16639485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x", 16649485SMikore.Li@Sun.COM sc->sc_gpio_ledpin); 16659485SMikore.Li@Sun.COM /* never reach */ 16669485SMikore.Li@Sun.COM } 16679485SMikore.Li@Sun.COM } else { 16689485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type); 16699485SMikore.Li@Sun.COM /* never reach */ 16709485SMikore.Li@Sun.COM } 16719485SMikore.Li@Sun.COM 16729485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 0; 16739485SMikore.Li@Sun.COM return (0); 16749485SMikore.Li@Sun.COM } 16759485SMikore.Li@Sun.COM 16769485SMikore.Li@Sun.COM static usbd_status 16779485SMikore.Li@Sun.COM urtw_led_mode0(struct urtw_softc *sc, int mode) 16789485SMikore.Li@Sun.COM { 16799485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 16809485SMikore.Li@Sun.COM "urtw_led_mode0: mode = %d\n", mode)); 16819485SMikore.Li@Sun.COM switch (mode) { 16829485SMikore.Li@Sun.COM case URTW_LED_CTL_POWER_ON: 16839485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK; 16849485SMikore.Li@Sun.COM break; 16859485SMikore.Li@Sun.COM case URTW_LED_CTL_TX: 16869485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress == 1) 16879485SMikore.Li@Sun.COM return (0); 16889485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL; 16899485SMikore.Li@Sun.COM sc->sc_gpio_blinktime = 16909485SMikore.Li@Sun.COM (sc->sc_ic.ic_state == IEEE80211_S_RUN ? 4:2); 16919485SMikore.Li@Sun.COM break; 16929485SMikore.Li@Sun.COM case URTW_LED_CTL_LINK: 16939485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_ON; 16949485SMikore.Li@Sun.COM break; 16959485SMikore.Li@Sun.COM default: 16969485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode 0x%x", mode); 16979485SMikore.Li@Sun.COM /* never reach */ 16989485SMikore.Li@Sun.COM } 16999485SMikore.Li@Sun.COM 17009485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) { 17019485SMikore.Li@Sun.COM case URTW_LED_ON: 17029485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0) 17039485SMikore.Li@Sun.COM break; 17049485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 17059485SMikore.Li@Sun.COM break; 17069485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL: 17079485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0) 17089485SMikore.Li@Sun.COM break; 17099485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 1; 17109485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ? 17119485SMikore.Li@Sun.COM URTW_LED_OFF : URTW_LED_ON; 17129485SMikore.Li@Sun.COM URTW_LEDLOCK(sc); 17139485SMikore.Li@Sun.COM if (sc->sc_led_ch == 0) { 17149485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 17159485SMikore.Li@Sun.COM "urtw_led_mode0: restart led timer\n")); 17169485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch, 17179485SMikore.Li@Sun.COM (void *)sc, 17189485SMikore.Li@Sun.COM drv_usectohz((sc->sc_ic.ic_state == 17199485SMikore.Li@Sun.COM IEEE80211_S_RUN) ? 17209485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK : 17219485SMikore.Li@Sun.COM URTW_LED_LINKOFF_BLINK)); 17229485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 17239485SMikore.Li@Sun.COM } 17249485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 17259485SMikore.Li@Sun.COM break; 17269485SMikore.Li@Sun.COM case URTW_LED_POWER_ON_BLINK: 17279485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 17289485SMikore.Li@Sun.COM urtw_delay_ms(100); 17299485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 17309485SMikore.Li@Sun.COM break; 17319485SMikore.Li@Sun.COM default: 17329485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 17339485SMikore.Li@Sun.COM "urtw_led_mode0: unknown LED status 0x%x", 17349485SMikore.Li@Sun.COM sc->sc_gpio_ledstate)); 17359485SMikore.Li@Sun.COM } 17369485SMikore.Li@Sun.COM return (0); 17379485SMikore.Li@Sun.COM } 17389485SMikore.Li@Sun.COM 17399485SMikore.Li@Sun.COM static usbd_status 17409485SMikore.Li@Sun.COM urtw_led_mode1(struct urtw_softc *sc, int mode) 17419485SMikore.Li@Sun.COM { 17429485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 17439485SMikore.Li@Sun.COM return (USBD_INVAL); 17449485SMikore.Li@Sun.COM } 17459485SMikore.Li@Sun.COM 17469485SMikore.Li@Sun.COM static usbd_status 17479485SMikore.Li@Sun.COM urtw_led_mode2(struct urtw_softc *sc, int mode) 17489485SMikore.Li@Sun.COM { 17499485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 17509485SMikore.Li@Sun.COM return (USBD_INVAL); 17519485SMikore.Li@Sun.COM } 17529485SMikore.Li@Sun.COM 17539485SMikore.Li@Sun.COM static usbd_status 17549485SMikore.Li@Sun.COM urtw_led_mode3(struct urtw_softc *sc, int mode) 17559485SMikore.Li@Sun.COM { 17569485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 17579485SMikore.Li@Sun.COM return (USBD_INVAL); 17589485SMikore.Li@Sun.COM } 17599485SMikore.Li@Sun.COM 17609485SMikore.Li@Sun.COM static usbd_status 17619485SMikore.Li@Sun.COM urtw_led_blink(struct urtw_softc *sc) 17629485SMikore.Li@Sun.COM { 17639485SMikore.Li@Sun.COM uint8_t ing = 0; 17649485SMikore.Li@Sun.COM 17659485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 17669485SMikore.Li@Sun.COM "urtw_led_blink: gpio_blinkstate %d\n", 17679485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate)); 17689485SMikore.Li@Sun.COM if (sc->sc_gpio_blinkstate == URTW_LED_ON) 17699485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 17709485SMikore.Li@Sun.COM else 17719485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 17729485SMikore.Li@Sun.COM sc->sc_gpio_blinktime--; 17739485SMikore.Li@Sun.COM if (sc->sc_gpio_blinktime == 0) 17749485SMikore.Li@Sun.COM ing = 1; 17759485SMikore.Li@Sun.COM else { 17769485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL && 17779485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY && 17789485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3) 17799485SMikore.Li@Sun.COM ing = 1; 17809485SMikore.Li@Sun.COM } 17819485SMikore.Li@Sun.COM if (ing == 1) { 17829485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate == URTW_LED_ON && 17839485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 0) 17849485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 17859485SMikore.Li@Sun.COM else if (sc->sc_gpio_ledstate == URTW_LED_OFF && 17869485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 1) 17879485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 17889485SMikore.Li@Sun.COM 17899485SMikore.Li@Sun.COM sc->sc_gpio_blinktime = 0; 17909485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 17919485SMikore.Li@Sun.COM return (0); 17929485SMikore.Li@Sun.COM } 17939485SMikore.Li@Sun.COM 17949485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ? 17959485SMikore.Li@Sun.COM URTW_LED_ON : URTW_LED_OFF; 17969485SMikore.Li@Sun.COM 17979485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) { 17989485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL: 17999485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 18009485SMikore.Li@Sun.COM "URTW_LED_BLINK_NORMAL\n")); 18019485SMikore.Li@Sun.COM return (1); 18029485SMikore.Li@Sun.COM default: 18039485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 18049485SMikore.Li@Sun.COM "unknown LED status 0x%x", sc->sc_gpio_ledstate)); 18059485SMikore.Li@Sun.COM } 18069485SMikore.Li@Sun.COM return (0); 18079485SMikore.Li@Sun.COM } 18089485SMikore.Li@Sun.COM 18099485SMikore.Li@Sun.COM static usbd_status 18109485SMikore.Li@Sun.COM urtw_led_ctl(struct urtw_softc *sc, int mode) 18119485SMikore.Li@Sun.COM { 18129485SMikore.Li@Sun.COM usbd_status error = 0; 18139485SMikore.Li@Sun.COM 18149485SMikore.Li@Sun.COM switch (sc->sc_strategy) { 18159485SMikore.Li@Sun.COM case URTW_SW_LED_MODE0: 18169485SMikore.Li@Sun.COM error = urtw_led_mode0(sc, mode); 18179485SMikore.Li@Sun.COM break; 18189485SMikore.Li@Sun.COM case URTW_SW_LED_MODE1: 18199485SMikore.Li@Sun.COM error = urtw_led_mode1(sc, mode); 18209485SMikore.Li@Sun.COM break; 18219485SMikore.Li@Sun.COM case URTW_SW_LED_MODE2: 18229485SMikore.Li@Sun.COM error = urtw_led_mode2(sc, mode); 18239485SMikore.Li@Sun.COM break; 18249485SMikore.Li@Sun.COM case URTW_SW_LED_MODE3: 18259485SMikore.Li@Sun.COM error = urtw_led_mode3(sc, mode); 18269485SMikore.Li@Sun.COM break; 18279485SMikore.Li@Sun.COM default: 18289485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode %d\n", sc->sc_strategy); 18299485SMikore.Li@Sun.COM /* never reach */ 18309485SMikore.Li@Sun.COM return (-1); 18319485SMikore.Li@Sun.COM } 18329485SMikore.Li@Sun.COM 18339485SMikore.Li@Sun.COM return (error); 18349485SMikore.Li@Sun.COM } 18359485SMikore.Li@Sun.COM 18369485SMikore.Li@Sun.COM static usbd_status 18379485SMikore.Li@Sun.COM urtw_update_msr(struct urtw_softc *sc, int nstate) 18389485SMikore.Li@Sun.COM { 18399485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 18409485SMikore.Li@Sun.COM uint8_t data; 18419485SMikore.Li@Sun.COM usbd_status error; 18429485SMikore.Li@Sun.COM 1843*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_MSR, &data, 0)) 18449485SMikore.Li@Sun.COM goto fail; 18459485SMikore.Li@Sun.COM data &= ~URTW_MSR_LINK_MASK; 18469485SMikore.Li@Sun.COM 1847*10364SMikore.Li@Sun.COM /* Should always be set. */ 1848*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B) 1849*10364SMikore.Li@Sun.COM data |= URTW_MSR_LINK_ENEDCA; 1850*10364SMikore.Li@Sun.COM 18519485SMikore.Li@Sun.COM if (nstate == IEEE80211_S_RUN) { 18529485SMikore.Li@Sun.COM switch (ic->ic_opmode) { 18539485SMikore.Li@Sun.COM case IEEE80211_M_STA: 18549485SMikore.Li@Sun.COM case IEEE80211_M_MONITOR: 18559485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_STA; 18569485SMikore.Li@Sun.COM break; 18579485SMikore.Li@Sun.COM case IEEE80211_M_IBSS: 18589485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_ADHOC; 18599485SMikore.Li@Sun.COM break; 18609485SMikore.Li@Sun.COM case IEEE80211_M_HOSTAP: 18619485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_HOSTAP; 18629485SMikore.Li@Sun.COM break; 18639485SMikore.Li@Sun.COM default: 18649485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported operation mode 0x%x\n", 18659485SMikore.Li@Sun.COM ic->ic_opmode); 18669485SMikore.Li@Sun.COM return (-1); 18679485SMikore.Li@Sun.COM } 18689485SMikore.Li@Sun.COM } else 18699485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_NONE; 18709485SMikore.Li@Sun.COM 1871*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_MSR, data, 0); 18729485SMikore.Li@Sun.COM fail: 18739485SMikore.Li@Sun.COM return (error); 18749485SMikore.Li@Sun.COM } 18759485SMikore.Li@Sun.COM 18769485SMikore.Li@Sun.COM static uint16_t 18779485SMikore.Li@Sun.COM urtw_rate2rtl(int rate) 18789485SMikore.Li@Sun.COM { 18799485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 18809485SMikore.Li@Sun.COM int i; 18819485SMikore.Li@Sun.COM 18829485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) { 18839485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].reg) 18849485SMikore.Li@Sun.COM return (urtw_ratetable[i].val); 18859485SMikore.Li@Sun.COM } 18869485SMikore.Li@Sun.COM return (3); 18879485SMikore.Li@Sun.COM #undef N 18889485SMikore.Li@Sun.COM } 18899485SMikore.Li@Sun.COM 18909485SMikore.Li@Sun.COM static uint16_t 18919485SMikore.Li@Sun.COM urtw_rtl2rate(int rate) 18929485SMikore.Li@Sun.COM { 18939485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 18949485SMikore.Li@Sun.COM int i; 18959485SMikore.Li@Sun.COM 18969485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) { 18979485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].val) 18989485SMikore.Li@Sun.COM return (urtw_ratetable[i].reg); 18999485SMikore.Li@Sun.COM } 19009485SMikore.Li@Sun.COM 19019485SMikore.Li@Sun.COM return (0); 19029485SMikore.Li@Sun.COM #undef N 19039485SMikore.Li@Sun.COM } 19049485SMikore.Li@Sun.COM 19059485SMikore.Li@Sun.COM static usbd_status 19069485SMikore.Li@Sun.COM urtw_set_rate(struct urtw_softc *sc) 19079485SMikore.Li@Sun.COM { 19089485SMikore.Li@Sun.COM int i, basic_rate, min_rr_rate, max_rr_rate; 19099485SMikore.Li@Sun.COM uint16_t data; 19109485SMikore.Li@Sun.COM usbd_status error; 19119485SMikore.Li@Sun.COM 19129485SMikore.Li@Sun.COM basic_rate = urtw_rate2rtl(48); 19139485SMikore.Li@Sun.COM min_rr_rate = urtw_rate2rtl(12); 19149485SMikore.Li@Sun.COM max_rr_rate = urtw_rate2rtl(48); 19159485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RESP_RATE, 19169485SMikore.Li@Sun.COM max_rr_rate << URTW_RESP_MAX_RATE_SHIFT | 1917*10364SMikore.Li@Sun.COM min_rr_rate << URTW_RESP_MIN_RATE_SHIFT, 0)) 19189485SMikore.Li@Sun.COM goto fail; 19199485SMikore.Li@Sun.COM 1920*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0)) 19219485SMikore.Li@Sun.COM goto fail; 19229485SMikore.Li@Sun.COM data &= ~URTW_BRSR_MBR_8185; 19239485SMikore.Li@Sun.COM 19249485SMikore.Li@Sun.COM for (i = 0; i <= basic_rate; i++) 19259485SMikore.Li@Sun.COM data |= (1 << i); 19269485SMikore.Li@Sun.COM 1927*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_BRSR, data, 0); 19289485SMikore.Li@Sun.COM fail: 19299485SMikore.Li@Sun.COM return (error); 19309485SMikore.Li@Sun.COM } 19319485SMikore.Li@Sun.COM 19329485SMikore.Li@Sun.COM static usbd_status 19339485SMikore.Li@Sun.COM urtw_intr_enable(struct urtw_softc *sc) 19349485SMikore.Li@Sun.COM { 19359485SMikore.Li@Sun.COM usbd_status error; 19369485SMikore.Li@Sun.COM 1937*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0xffff, 0); 19389485SMikore.Li@Sun.COM return (error); 19399485SMikore.Li@Sun.COM } 19409485SMikore.Li@Sun.COM 19419485SMikore.Li@Sun.COM static usbd_status 19429485SMikore.Li@Sun.COM urtw_rx_setconf(struct urtw_softc *sc) 19439485SMikore.Li@Sun.COM { 19449485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 19459485SMikore.Li@Sun.COM uint32_t data, a, b; 19469485SMikore.Li@Sun.COM usbd_status error; 19479485SMikore.Li@Sun.COM 1948*10364SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data, 0)) 19499485SMikore.Li@Sun.COM goto fail; 19509485SMikore.Li@Sun.COM data = data &~ URTW_RX_FILTER_MASK; 19519485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA; 19529485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST; 19539485SMikore.Li@Sun.COM 19549485SMikore.Li@Sun.COM if (ic->ic_opmode == IEEE80211_M_MONITOR) { 19559485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_ICVERR; 19569485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_PWR; 19579485SMikore.Li@Sun.COM } 19589485SMikore.Li@Sun.COM if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) 19599485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_CRCERR; 19609485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_NICMAC; 19619485SMikore.Li@Sun.COM data = data | URTW_RX_CHECK_BSSID; 19629485SMikore.Li@Sun.COM data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; 19639485SMikore.Li@Sun.COM data = data | URTW_RX_FIFO_THRESHOLD_NONE | URTW_RX_AUTORESETPHY; 19649485SMikore.Li@Sun.COM data = data &~ URTW_MAX_RX_DMA_MASK; 19659485SMikore.Li@Sun.COM a = URTW_MAX_RX_DMA_2048; 19669485SMikore.Li@Sun.COM b = 0x80000000; 19679485SMikore.Li@Sun.COM data = data | a | b; 19689485SMikore.Li@Sun.COM 1969*10364SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_RX, data, 0); 19709485SMikore.Li@Sun.COM fail: 19719485SMikore.Li@Sun.COM return (error); 19729485SMikore.Li@Sun.COM } 19739485SMikore.Li@Sun.COM 19749485SMikore.Li@Sun.COM static usbd_status 19759485SMikore.Li@Sun.COM urtw_rx_enable(struct urtw_softc *sc) 19769485SMikore.Li@Sun.COM { 19779485SMikore.Li@Sun.COM int i; 19789485SMikore.Li@Sun.COM usbd_status error; 19799485SMikore.Li@Sun.COM uint8_t data; 19809485SMikore.Li@Sun.COM 19819485SMikore.Li@Sun.COM sc->rx_queued = 0; 19829485SMikore.Li@Sun.COM for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) { 19839485SMikore.Li@Sun.COM if (urtw_rx_start(sc) != 0) { 19849485SMikore.Li@Sun.COM return (USB_FAILURE); 19859485SMikore.Li@Sun.COM } 19869485SMikore.Li@Sun.COM } 19879485SMikore.Li@Sun.COM 19889485SMikore.Li@Sun.COM error = urtw_rx_setconf(sc); 19899485SMikore.Li@Sun.COM if (error != 0) 19909485SMikore.Li@Sun.COM goto fail; 19919485SMikore.Li@Sun.COM 1992*10364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0)) 19939485SMikore.Li@Sun.COM goto fail; 1994*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE, 0); 19959485SMikore.Li@Sun.COM fail: 19969485SMikore.Li@Sun.COM return (error); 19979485SMikore.Li@Sun.COM } 19989485SMikore.Li@Sun.COM 1999*10364SMikore.Li@Sun.COM void 20009485SMikore.Li@Sun.COM urtw_tx_enable(struct urtw_softc *sc) 20019485SMikore.Li@Sun.COM { 20029485SMikore.Li@Sun.COM uint8_t data8; 20039485SMikore.Li@Sun.COM uint32_t data; 2004*10364SMikore.Li@Sun.COM 2005*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 2006*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CW_CONF, &data8, 0); 2007*10364SMikore.Li@Sun.COM data8 &= ~(URTW_CW_CONF_PERPACKET_CW | 2008*10364SMikore.Li@Sun.COM URTW_CW_CONF_PERPACKET_RETRY); 2009*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CW_CONF, data8, 0); 2010*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data8, 0); 2011*10364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; 2012*10364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; 2013*10364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; 2014*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data8, 0); 2015*10364SMikore.Li@Sun.COM 2016*10364SMikore.Li@Sun.COM (void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0); 2017*10364SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK; 2018*10364SMikore.Li@Sun.COM data |= URTW_TX_LOOPBACK_NONE; 2019*10364SMikore.Li@Sun.COM data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); 2020*10364SMikore.Li@Sun.COM data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; 2021*10364SMikore.Li@Sun.COM data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; 2022*10364SMikore.Li@Sun.COM data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); 2023*10364SMikore.Li@Sun.COM data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; 2024*10364SMikore.Li@Sun.COM data &= ~URTW_TX_SWPLCPLEN; 2025*10364SMikore.Li@Sun.COM data |= URTW_TX_NOICV; 2026*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_TX_CONF, data, 0); 2027*10364SMikore.Li@Sun.COM } else { 2028*10364SMikore.Li@Sun.COM data = URTW_TX_DURPROCMODE | URTW_TX_DISREQQSIZE | 2029*10364SMikore.Li@Sun.COM URTW_TX_MXDMA_2048 | URTW_TX_SHORTRETRY | 2030*10364SMikore.Li@Sun.COM URTW_TX_LONGRETRY; 2031*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_TX_CONF, data, 0); 2032*10364SMikore.Li@Sun.COM } 2033*10364SMikore.Li@Sun.COM 2034*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data8, 0); 2035*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE, 0); 20369485SMikore.Li@Sun.COM } 20379485SMikore.Li@Sun.COM 20389485SMikore.Li@Sun.COM static int 2039*10364SMikore.Li@Sun.COM urtw_8187_init(void *arg) 20409485SMikore.Li@Sun.COM { 20419485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 20429485SMikore.Li@Sun.COM usbd_status error; 2043*10364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf; 2044*10364SMikore.Li@Sun.COM int i; 20459485SMikore.Li@Sun.COM 20469485SMikore.Li@Sun.COM urtw_stop(sc); 20479485SMikore.Li@Sun.COM URTW_LOCK(sc); 2048*10364SMikore.Li@Sun.COM error = urtw_8187_reset(sc); 2049*10364SMikore.Li@Sun.COM if (error) 2050*10364SMikore.Li@Sun.COM goto fail; 2051*10364SMikore.Li@Sun.COM 2052*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 0, 0); 2053*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0, 0); 2054*10364SMikore.Li@Sun.COM 2055*10364SMikore.Li@Sun.COM /* for led */ 2056*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 4, 0); 2057*10364SMikore.Li@Sun.COM error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON); 20589485SMikore.Li@Sun.COM if (error != 0) 20599485SMikore.Li@Sun.COM goto fail; 2060*10364SMikore.Li@Sun.COM 2061*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 2062*10364SMikore.Li@Sun.COM if (error) 2063*10364SMikore.Li@Sun.COM goto fail; 2064*10364SMikore.Li@Sun.COM 2065*10364SMikore.Li@Sun.COM /* applying MAC address again. */ 2066*10364SMikore.Li@Sun.COM for (i = 0; i < IEEE80211_ADDR_LEN; i++) 2067*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_MAC0 + i, 2068*10364SMikore.Li@Sun.COM sc->sc_ic.ic_macaddr[i], 0); 2069*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 2070*10364SMikore.Li@Sun.COM if (error) 2071*10364SMikore.Li@Sun.COM goto fail; 2072*10364SMikore.Li@Sun.COM 2073*10364SMikore.Li@Sun.COM error = urtw_update_msr(sc, IEEE80211_S_INIT); 2074*10364SMikore.Li@Sun.COM if (error) 2075*10364SMikore.Li@Sun.COM goto fail; 2076*10364SMikore.Li@Sun.COM 2077*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_INT_TIMEOUT, 0, 0); 2078*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0); 2079*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_RATE_FALLBACK, 0x81, 0); 2080*10364SMikore.Li@Sun.COM error = urtw_set_rate(sc); 2081*10364SMikore.Li@Sun.COM if (error != 0) 2082*10364SMikore.Li@Sun.COM goto fail; 2083*10364SMikore.Li@Sun.COM 2084*10364SMikore.Li@Sun.COM error = rf->init(rf); 2085*10364SMikore.Li@Sun.COM if (error != 0) 2086*10364SMikore.Li@Sun.COM goto fail; 2087*10364SMikore.Li@Sun.COM if (rf->set_sens != NULL) 2088*10364SMikore.Li@Sun.COM rf->set_sens(rf); 2089*10364SMikore.Li@Sun.COM 2090*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x5e, 1, 0); 2091*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0xfe, 0x10, 0); 2092*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TALLY_SEL, 0x80, 0); 2093*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xff, 0x60, 0); 2094*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x5e, 0, 0); 2095*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 4, 0); 2096*10364SMikore.Li@Sun.COM 2097*10364SMikore.Li@Sun.COM error = urtw_intr_enable(sc); 2098*10364SMikore.Li@Sun.COM if (error != 0) 2099*10364SMikore.Li@Sun.COM goto fail; 2100*10364SMikore.Li@Sun.COM 2101*10364SMikore.Li@Sun.COM error = urtw_open_pipes(sc); 21029485SMikore.Li@Sun.COM if (error != 0) 21039485SMikore.Li@Sun.COM goto fail; 21049485SMikore.Li@Sun.COM sc->sc_tx_low_queued = 0; 21059485SMikore.Li@Sun.COM sc->sc_tx_normal_queued = 0; 21069485SMikore.Li@Sun.COM error = urtw_rx_enable(sc); 21079485SMikore.Li@Sun.COM if (error != 0) 21089485SMikore.Li@Sun.COM goto fail; 2109*10364SMikore.Li@Sun.COM urtw_tx_enable(sc); 21109485SMikore.Li@Sun.COM 21119485SMikore.Li@Sun.COM if (error == 0) { 21129485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, 2113*10364SMikore.Li@Sun.COM CE_CONT, "urtw_8187_init: succesfully done\n")); 21149485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_RUNNING; 21159485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 21169485SMikore.Li@Sun.COM return (error); 21179485SMikore.Li@Sun.COM } 21189485SMikore.Li@Sun.COM 21199485SMikore.Li@Sun.COM fail: 21209485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 21219485SMikore.Li@Sun.COM urtw_stop(sc); 2122*10364SMikore.Li@Sun.COM return (EIO); 21239485SMikore.Li@Sun.COM } 21249485SMikore.Li@Sun.COM 21259485SMikore.Li@Sun.COM 21269485SMikore.Li@Sun.COM static usbd_status 21279485SMikore.Li@Sun.COM urtw_8225_usb_init(struct urtw_softc *sc) 21289485SMikore.Li@Sun.COM { 21299485SMikore.Li@Sun.COM uint8_t data; 21309485SMikore.Li@Sun.COM usbd_status error; 21319485SMikore.Li@Sun.COM 2132*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 0, 0)) 21339485SMikore.Li@Sun.COM goto fail; 2134*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0, 0)) 21359485SMikore.Li@Sun.COM goto fail; 21369485SMikore.Li@Sun.COM if (error = urtw_read8e(sc, 0x53, &data)) 21379485SMikore.Li@Sun.COM goto fail; 21389485SMikore.Li@Sun.COM if (error = urtw_write8e(sc, 0x53, data | (1 << 7))) 21399485SMikore.Li@Sun.COM goto fail; 2140*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 4, 0)) 21419485SMikore.Li@Sun.COM goto fail; 2142*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0x20, 0)) 21439485SMikore.Li@Sun.COM goto fail; 2144*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GP_ENABLE, 0, 0)) 21459485SMikore.Li@Sun.COM goto fail; 2146*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x80, 0)) 21479485SMikore.Li@Sun.COM goto fail; 2148*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x80, 0)) 21499485SMikore.Li@Sun.COM goto fail; 2150*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x80, 0); 21519485SMikore.Li@Sun.COM 21529485SMikore.Li@Sun.COM urtw_delay_ms(100); 21539485SMikore.Li@Sun.COM fail: 21549485SMikore.Li@Sun.COM return (error); 21559485SMikore.Li@Sun.COM } 21569485SMikore.Li@Sun.COM 21579485SMikore.Li@Sun.COM static usbd_status 21589485SMikore.Li@Sun.COM urtw_8185_rf_pins_enable(struct urtw_softc *sc) 21599485SMikore.Li@Sun.COM { 21609485SMikore.Li@Sun.COM usbd_status error = 0; 21619485SMikore.Li@Sun.COM 2162*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1ff7, 0); 21639485SMikore.Li@Sun.COM return (error); 21649485SMikore.Li@Sun.COM } 21659485SMikore.Li@Sun.COM 21669485SMikore.Li@Sun.COM static usbd_status 21679485SMikore.Li@Sun.COM urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) 21689485SMikore.Li@Sun.COM { 21699485SMikore.Li@Sun.COM uint32_t phyw; 21709485SMikore.Li@Sun.COM usbd_status error; 21719485SMikore.Li@Sun.COM 21729485SMikore.Li@Sun.COM phyw = ((data << 8) | (addr | 0x80)); 2173*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7f, ((phyw & 0xff000000) >> 24), 0)) 21749485SMikore.Li@Sun.COM goto fail; 2175*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7e, ((phyw & 0x00ff0000) >> 16), 0)) 2176*10364SMikore.Li@Sun.COM goto fail; 2177*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7d, ((phyw & 0x0000ff00) >> 8), 0)) 21789485SMikore.Li@Sun.COM goto fail; 2179*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, 0x7c, (phyw & 0x000000ff), 0); 2180*10364SMikore.Li@Sun.COM /* 2181*10364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187. 2182*10364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1); 2183*10364SMikore.Li@Sun.COM */ 21849485SMikore.Li@Sun.COM fail: 21859485SMikore.Li@Sun.COM return (error); 21869485SMikore.Li@Sun.COM } 21879485SMikore.Li@Sun.COM 21889485SMikore.Li@Sun.COM static usbd_status 21899485SMikore.Li@Sun.COM urtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 21909485SMikore.Li@Sun.COM { 21919485SMikore.Li@Sun.COM data = data & 0xff; 21929485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, data)); 21939485SMikore.Li@Sun.COM } 21949485SMikore.Li@Sun.COM 21959485SMikore.Li@Sun.COM static usbd_status 21969485SMikore.Li@Sun.COM urtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 21979485SMikore.Li@Sun.COM { 21989485SMikore.Li@Sun.COM data = data & 0xff; 21999485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, (data | 0x10000))); 22009485SMikore.Li@Sun.COM } 22019485SMikore.Li@Sun.COM 22029485SMikore.Li@Sun.COM static usbd_status 22039485SMikore.Li@Sun.COM urtw_8225_setgain(struct urtw_softc *sc, int16_t gain) 22049485SMikore.Li@Sun.COM { 22059485SMikore.Li@Sun.COM usbd_status error; 22069485SMikore.Li@Sun.COM 22079485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d, 22089485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4])) 22099485SMikore.Li@Sun.COM goto fail; 22109485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b, 22119485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 2])) 22129485SMikore.Li@Sun.COM goto fail; 22139485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d, 22149485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 3])) 22159485SMikore.Li@Sun.COM goto fail; 22169485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x23, 22179485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 1]); 22189485SMikore.Li@Sun.COM fail: 22199485SMikore.Li@Sun.COM return (error); 22209485SMikore.Li@Sun.COM } 22219485SMikore.Li@Sun.COM 22229485SMikore.Li@Sun.COM static usbd_status 22239485SMikore.Li@Sun.COM urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan) 22249485SMikore.Li@Sun.COM { 22259485SMikore.Li@Sun.COM int i, idx, set; 22269485SMikore.Li@Sun.COM uint8_t *cck_pwltable; 22279485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max; 22289485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 22299485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 22309485SMikore.Li@Sun.COM usbd_status error; 22319485SMikore.Li@Sun.COM 22329485SMikore.Li@Sun.COM cck_pwrlvl_max = 11; 22339485SMikore.Li@Sun.COM ofdm_pwrlvl_max = 25; /* 12 -> 25 */ 22349485SMikore.Li@Sun.COM ofdm_pwrlvl_min = 10; 22359485SMikore.Li@Sun.COM 22369485SMikore.Li@Sun.COM /* CCK power setting */ 22379485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? 22389485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl; 22399485SMikore.Li@Sun.COM idx = cck_pwrlvl % 6; 22409485SMikore.Li@Sun.COM set = cck_pwrlvl / 6; 22419485SMikore.Li@Sun.COM cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 : 22429485SMikore.Li@Sun.COM urtw_8225_txpwr_cck; 22439485SMikore.Li@Sun.COM 22449485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK, 2245*10364SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0)) 22469485SMikore.Li@Sun.COM goto fail; 22479485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) { 22489485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i, 22499485SMikore.Li@Sun.COM cck_pwltable[idx * 8 + i])) 22509485SMikore.Li@Sun.COM goto fail; 22519485SMikore.Li@Sun.COM } 22529485SMikore.Li@Sun.COM urtw_delay_ms(1); 22539485SMikore.Li@Sun.COM /* OFDM power setting */ 22549485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 22559485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 22569485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 22579485SMikore.Li@Sun.COM idx = ofdm_pwrlvl % 6; 22589485SMikore.Li@Sun.COM set = ofdm_pwrlvl / 6; 22599485SMikore.Li@Sun.COM 2260*10364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON); 22619485SMikore.Li@Sun.COM if (error) 22629485SMikore.Li@Sun.COM goto fail; 22639485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42)) 22649485SMikore.Li@Sun.COM goto fail; 22659485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0)) 22669485SMikore.Li@Sun.COM goto fail; 22679485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0)) 22689485SMikore.Li@Sun.COM goto fail; 22699485SMikore.Li@Sun.COM 22709485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 2271*10364SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0)) 22729485SMikore.Li@Sun.COM goto fail; 22739485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x5, 22749485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx])) 22759485SMikore.Li@Sun.COM goto fail; 22769485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x7, 22779485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx]); 22789485SMikore.Li@Sun.COM urtw_delay_ms(1); 22799485SMikore.Li@Sun.COM fail: 22809485SMikore.Li@Sun.COM return (error); 22819485SMikore.Li@Sun.COM } 22829485SMikore.Li@Sun.COM 22839485SMikore.Li@Sun.COM static usbd_status 22849485SMikore.Li@Sun.COM urtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant) 22859485SMikore.Li@Sun.COM { 22869485SMikore.Li@Sun.COM usbd_status error; 22879485SMikore.Li@Sun.COM 2288*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_ANTENNA, ant, 0); 22899485SMikore.Li@Sun.COM urtw_delay_ms(1); 22909485SMikore.Li@Sun.COM return (error); 22919485SMikore.Li@Sun.COM } 22929485SMikore.Li@Sun.COM 22939485SMikore.Li@Sun.COM static usbd_status 2294*10364SMikore.Li@Sun.COM urtw_8225_rf_init(struct urtw_rf *rf) 22959485SMikore.Li@Sun.COM { 22969485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 22979485SMikore.Li@Sun.COM int i; 22989485SMikore.Li@Sun.COM uint16_t data; 22999485SMikore.Li@Sun.COM usbd_status error; 2300*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 2301*10364SMikore.Li@Sun.COM 2302*10364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON); 23039485SMikore.Li@Sun.COM if (error) 23049485SMikore.Li@Sun.COM goto fail; 23059485SMikore.Li@Sun.COM 23069485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc)) 23079485SMikore.Li@Sun.COM goto fail; 2308*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0)) 23099485SMikore.Li@Sun.COM goto fail; 2310*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0)) 23119485SMikore.Li@Sun.COM goto fail; 2312*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0)) 23139485SMikore.Li@Sun.COM goto fail; 2314*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0)) 23159485SMikore.Li@Sun.COM goto fail; 23169485SMikore.Li@Sun.COM 23179485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG)) 23189485SMikore.Li@Sun.COM goto fail; 2319*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0)) 23209485SMikore.Li@Sun.COM goto fail; 23219485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL)) 23229485SMikore.Li@Sun.COM goto fail; 23239485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc)) 23249485SMikore.Li@Sun.COM goto fail; 23259485SMikore.Li@Sun.COM urtw_delay_ms(100); 23269485SMikore.Li@Sun.COM 23279485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part1); i++) { 23289485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225_rf_part1[i].reg, 23299485SMikore.Li@Sun.COM urtw_8225_rf_part1[i].val)) 23309485SMikore.Li@Sun.COM goto fail; 23319485SMikore.Li@Sun.COM urtw_delay_ms(1); 23329485SMikore.Li@Sun.COM } 23339485SMikore.Li@Sun.COM urtw_delay_ms(50); 23349485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d)) 23359485SMikore.Li@Sun.COM goto fail; 23369485SMikore.Li@Sun.COM urtw_delay_ms(50); 23379485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d)) 23389485SMikore.Li@Sun.COM goto fail; 23399485SMikore.Li@Sun.COM urtw_delay_ms(50); 23409485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x127)) 23419485SMikore.Li@Sun.COM goto fail; 23429485SMikore.Li@Sun.COM 23439485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) { 23449485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1))) 23459485SMikore.Li@Sun.COM goto fail; 23469485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225_rxgain[i])) 23479485SMikore.Li@Sun.COM goto fail; 23489485SMikore.Li@Sun.COM } 23499485SMikore.Li@Sun.COM 23509485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x27)) 23519485SMikore.Li@Sun.COM goto fail; 23529485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x22f)) 23539485SMikore.Li@Sun.COM goto fail; 23549485SMikore.Li@Sun.COM 23559485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) { 23569485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb, 23579485SMikore.Li@Sun.COM urtw_8225_agc[i])) 23589485SMikore.Li@Sun.COM goto fail; 23599485SMikore.Li@Sun.COM urtw_delay_ms(1); 23609485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa, 23619485SMikore.Li@Sun.COM (uint8_t)i + 0x80)) 23629485SMikore.Li@Sun.COM goto fail; 23639485SMikore.Li@Sun.COM urtw_delay_ms(1); 23649485SMikore.Li@Sun.COM } 23659485SMikore.Li@Sun.COM 23669485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part2); i++) { 23679485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 23689485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].reg, 23699485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].val)) 23709485SMikore.Li@Sun.COM goto fail; 23719485SMikore.Li@Sun.COM urtw_delay_ms(1); 23729485SMikore.Li@Sun.COM } 23739485SMikore.Li@Sun.COM error = urtw_8225_setgain(sc, 4); 23749485SMikore.Li@Sun.COM if (error) 23759485SMikore.Li@Sun.COM goto fail; 23769485SMikore.Li@Sun.COM 23779485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part3); i++) { 23789485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 23799485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].reg, 23809485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].val)) 23819485SMikore.Li@Sun.COM goto fail; 23829485SMikore.Li@Sun.COM urtw_delay_ms(1); 23839485SMikore.Li@Sun.COM } 23849485SMikore.Li@Sun.COM 2385*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0)) 23869485SMikore.Li@Sun.COM goto fail; 23879485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, 1)) 23889485SMikore.Li@Sun.COM goto fail; 23899485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b)) 23909485SMikore.Li@Sun.COM goto fail; 23919485SMikore.Li@Sun.COM urtw_delay_ms(1); 23929485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90)) 23939485SMikore.Li@Sun.COM goto fail; 23949485SMikore.Li@Sun.COM urtw_delay_ms(1); 23959485SMikore.Li@Sun.COM 23969485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */ 23979485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3)) 23989485SMikore.Li@Sun.COM goto fail; 2399*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0)) 24009485SMikore.Li@Sun.COM goto fail; 24019485SMikore.Li@Sun.COM 2402*10364SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(rf, 2403*10364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan)); 24049485SMikore.Li@Sun.COM fail: 24059485SMikore.Li@Sun.COM return (error); 24069485SMikore.Li@Sun.COM #undef N 24079485SMikore.Li@Sun.COM } 24089485SMikore.Li@Sun.COM 24099485SMikore.Li@Sun.COM static usbd_status 2410*10364SMikore.Li@Sun.COM urtw_8225_rf_set_chan(struct urtw_rf *rf, int chan) 24119485SMikore.Li@Sun.COM { 24129485SMikore.Li@Sun.COM #define IEEE80211_CHAN_G \ 24139485SMikore.Li@Sun.COM (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 24149485SMikore.Li@Sun.COM #define IEEE80211_IS_CHAN_G(_c) \ 24159485SMikore.Li@Sun.COM (((_c)->ich_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 24169485SMikore.Li@Sun.COM 2417*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 24189485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 24199485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 24209485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0; 24219485SMikore.Li@Sun.COM usbd_status error; 24229485SMikore.Li@Sun.COM 24239485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, chan)) 24249485SMikore.Li@Sun.COM goto fail; 24259485SMikore.Li@Sun.COM if (urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan])) 24269485SMikore.Li@Sun.COM goto fail; 24279485SMikore.Li@Sun.COM urtw_delay_ms(10); 24289485SMikore.Li@Sun.COM 2429*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0)) 24309485SMikore.Li@Sun.COM goto fail; 24319485SMikore.Li@Sun.COM 24329485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC && 24339485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT) 2434*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0)) 24359485SMikore.Li@Sun.COM goto fail; 24369485SMikore.Li@Sun.COM else 2437*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0)) 24389485SMikore.Li@Sun.COM goto fail; 24399485SMikore.Li@Sun.COM if (gset) { 24409485SMikore.Li@Sun.COM /* for G */ 2441*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0)) 24429485SMikore.Li@Sun.COM goto fail; 2443*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0)) 24449485SMikore.Li@Sun.COM goto fail; 2445*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0); 24469485SMikore.Li@Sun.COM } else { 24479485SMikore.Li@Sun.COM /* for B */ 2448*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0)) 24499485SMikore.Li@Sun.COM goto fail; 2450*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0)) 24519485SMikore.Li@Sun.COM goto fail; 2452*10364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0); 24539485SMikore.Li@Sun.COM } 24549485SMikore.Li@Sun.COM 24559485SMikore.Li@Sun.COM fail: 24569485SMikore.Li@Sun.COM return (error); 24579485SMikore.Li@Sun.COM } 24589485SMikore.Li@Sun.COM 24599485SMikore.Li@Sun.COM static usbd_status 2460*10364SMikore.Li@Sun.COM urtw_8225_rf_set_sens(struct urtw_rf *rf) 24619485SMikore.Li@Sun.COM { 24629485SMikore.Li@Sun.COM usbd_status error; 2463*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 2464*10364SMikore.Li@Sun.COM 2465*10364SMikore.Li@Sun.COM if (rf->sens < 0 || rf->sens > 6) 24669485SMikore.Li@Sun.COM return (-1); 24679485SMikore.Li@Sun.COM 2468*10364SMikore.Li@Sun.COM if (rf->sens > 4) 24699485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x850)) 24709485SMikore.Li@Sun.COM goto fail; 24719485SMikore.Li@Sun.COM else 24729485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x50)) 24739485SMikore.Li@Sun.COM goto fail; 24749485SMikore.Li@Sun.COM 2475*10364SMikore.Li@Sun.COM rf->sens = 6 - rf->sens; 2476*10364SMikore.Li@Sun.COM if (error = urtw_8225_setgain(sc, rf->sens)) 24779485SMikore.Li@Sun.COM goto fail; 2478*10364SMikore.Li@Sun.COM error = urtw_8187_write_phy_cck_c(sc, 0x41, 2479*10364SMikore.Li@Sun.COM urtw_8225_threshold[rf->sens]); 24809485SMikore.Li@Sun.COM fail: 24819485SMikore.Li@Sun.COM return (error); 24829485SMikore.Li@Sun.COM } 24839485SMikore.Li@Sun.COM 24849485SMikore.Li@Sun.COM static void 24859485SMikore.Li@Sun.COM urtw_stop(struct urtw_softc *sc) 24869485SMikore.Li@Sun.COM { 24879485SMikore.Li@Sun.COM URTW_LOCK(sc); 24889485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_RUNNING; 24899485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 24909485SMikore.Li@Sun.COM urtw_close_pipes(sc); 24919485SMikore.Li@Sun.COM } 24929485SMikore.Li@Sun.COM 24939485SMikore.Li@Sun.COM static int 24949485SMikore.Li@Sun.COM urtw_isbmode(uint16_t rate) 24959485SMikore.Li@Sun.COM { 24969485SMikore.Li@Sun.COM 24979485SMikore.Li@Sun.COM rate = urtw_rtl2rate(rate); 24989485SMikore.Li@Sun.COM 24999485SMikore.Li@Sun.COM return ((rate <= 22 && rate != 12 && rate != 18)?(1) : (0)); 25009485SMikore.Li@Sun.COM } 25019485SMikore.Li@Sun.COM 25029485SMikore.Li@Sun.COM /* ARGSUSED */ 25039485SMikore.Li@Sun.COM static void 25049485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 25059485SMikore.Li@Sun.COM { 25069485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 25079485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 25089485SMikore.Li@Sun.COM int actlen, len, flen, rssi; 25099485SMikore.Li@Sun.COM uint8_t *desc, rate; 25109485SMikore.Li@Sun.COM struct ieee80211_frame *wh; 25119485SMikore.Li@Sun.COM struct ieee80211_node *ni = 0; 25129485SMikore.Li@Sun.COM mblk_t *mp = 0; 25139485SMikore.Li@Sun.COM uint8_t *rxbuf; 25149485SMikore.Li@Sun.COM 25159485SMikore.Li@Sun.COM mp = req->bulk_data; 25169485SMikore.Li@Sun.COM req->bulk_data = NULL; 25179485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK || 25189485SMikore.Li@Sun.COM mp == NULL) { 25199485SMikore.Li@Sun.COM sc->sc_rx_err++; 25209485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 2521*10364SMikore.Li@Sun.COM "urtw_rxeof failed! %d, mp %p\n", 2522*10364SMikore.Li@Sun.COM req->bulk_completion_reason, mp)); 25239485SMikore.Li@Sun.COM req->bulk_data = mp; 25249485SMikore.Li@Sun.COM goto fail; 25259485SMikore.Li@Sun.COM } 25269485SMikore.Li@Sun.COM 25279485SMikore.Li@Sun.COM actlen = MBLKL(mp); 25289485SMikore.Li@Sun.COM rxbuf = (uint8_t *)mp->b_rptr; 25299485SMikore.Li@Sun.COM 2530*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) 2531*10364SMikore.Li@Sun.COM /* 4 dword and 4 byte CRC */ 2532*10364SMikore.Li@Sun.COM len = actlen - (4 * 4); 2533*10364SMikore.Li@Sun.COM else 2534*10364SMikore.Li@Sun.COM /* 5 dword and 4 byte CRC */ 2535*10364SMikore.Li@Sun.COM len = actlen - (4 * 5); 2536*10364SMikore.Li@Sun.COM 25379485SMikore.Li@Sun.COM desc = rxbuf + len; 25389485SMikore.Li@Sun.COM flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff); 25399485SMikore.Li@Sun.COM if (flen > actlen) { 25409485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_rxeof: impossible: flen %d, actlen %d\n", 25419485SMikore.Li@Sun.COM flen, actlen); 25429485SMikore.Li@Sun.COM sc->sc_rx_err++; 25439485SMikore.Li@Sun.COM req->bulk_data = mp; 25449485SMikore.Li@Sun.COM goto fail; 25459485SMikore.Li@Sun.COM } 25469485SMikore.Li@Sun.COM 25479485SMikore.Li@Sun.COM rate = (desc[2] & 0xf0) >> 4; 2548*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 2549*10364SMikore.Li@Sun.COM rssi = (desc[6] & 0xfe) >> 1; 2550*10364SMikore.Li@Sun.COM 2551*10364SMikore.Li@Sun.COM /* XXX correct? */ 2552*10364SMikore.Li@Sun.COM if (!urtw_isbmode(rate)) { 2553*10364SMikore.Li@Sun.COM rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi); 2554*10364SMikore.Li@Sun.COM rssi = ((90 - rssi) * 100) / 65; 2555*10364SMikore.Li@Sun.COM } else { 2556*10364SMikore.Li@Sun.COM rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi); 2557*10364SMikore.Li@Sun.COM rssi = ((95 - rssi) * 100) / 65; 2558*10364SMikore.Li@Sun.COM } 25599485SMikore.Li@Sun.COM } else { 2560*10364SMikore.Li@Sun.COM rssi = 14 + desc[13]/2; 2561*10364SMikore.Li@Sun.COM if (rssi >= 95) 2562*10364SMikore.Li@Sun.COM rssi = 95; 2563*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 2564*10364SMikore.Li@Sun.COM "urtw_rxeof: rssi %u\n", rssi)); 25659485SMikore.Li@Sun.COM } 25669485SMikore.Li@Sun.COM 25679485SMikore.Li@Sun.COM mp->b_wptr = mp->b_rptr + flen - 4; 25689485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)mp->b_rptr; 25699485SMikore.Li@Sun.COM if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) 25709485SMikore.Li@Sun.COM == IEEE80211_FC0_TYPE_DATA) { 25719485SMikore.Li@Sun.COM sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; 25729485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 25739485SMikore.Li@Sun.COM "urtw_rxeof: update sc_currate to %u\n", 25749485SMikore.Li@Sun.COM sc->sc_currate)); 25759485SMikore.Li@Sun.COM } 25769485SMikore.Li@Sun.COM ni = ieee80211_find_rxnode(ic, wh); 25779485SMikore.Li@Sun.COM 25789485SMikore.Li@Sun.COM /* send the frame to the 802.11 layer */ 25799485SMikore.Li@Sun.COM (void) ieee80211_input(ic, mp, ni, rssi, 0); 25809485SMikore.Li@Sun.COM 25819485SMikore.Li@Sun.COM /* node is no longer needed */ 25829485SMikore.Li@Sun.COM ieee80211_free_node(ni); 25839485SMikore.Li@Sun.COM fail: 25849485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock); 25859485SMikore.Li@Sun.COM sc->rx_queued--; 25869485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock); 25879485SMikore.Li@Sun.COM usb_free_bulk_req(req); 25889485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && !URTW_IS_SUSPENDING(sc)) 25899485SMikore.Li@Sun.COM (void) urtw_rx_start(sc); 25909485SMikore.Li@Sun.COM } 25919485SMikore.Li@Sun.COM 25929485SMikore.Li@Sun.COM static usbd_status 25939485SMikore.Li@Sun.COM urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain) 25949485SMikore.Li@Sun.COM { 25959485SMikore.Li@Sun.COM uint8_t *gainp; 25969485SMikore.Li@Sun.COM usbd_status error; 25979485SMikore.Li@Sun.COM 25989485SMikore.Li@Sun.COM /* XXX for A? */ 25999485SMikore.Li@Sun.COM gainp = urtw_8225v2_gain_bg; 26009485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d, gainp[gain * 3])) 26019485SMikore.Li@Sun.COM goto fail; 26029485SMikore.Li@Sun.COM urtw_delay_ms(1); 26039485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b, gainp[gain * 3 + 1])) 26049485SMikore.Li@Sun.COM urtw_delay_ms(1); 26059485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d, gainp[gain * 3 + 2])) 26069485SMikore.Li@Sun.COM goto fail; 26079485SMikore.Li@Sun.COM urtw_delay_ms(1); 26089485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x21, 0x17)) 26099485SMikore.Li@Sun.COM goto fail; 26109485SMikore.Li@Sun.COM urtw_delay_ms(1); 26119485SMikore.Li@Sun.COM fail: 26129485SMikore.Li@Sun.COM return (error); 26139485SMikore.Li@Sun.COM } 26149485SMikore.Li@Sun.COM 26159485SMikore.Li@Sun.COM static usbd_status 26169485SMikore.Li@Sun.COM urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan) 26179485SMikore.Li@Sun.COM { 26189485SMikore.Li@Sun.COM int i; 26199485SMikore.Li@Sun.COM uint8_t *cck_pwrtable; 26209485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10; 26219485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 26229485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 26239485SMikore.Li@Sun.COM usbd_status error; 26249485SMikore.Li@Sun.COM 26259485SMikore.Li@Sun.COM /* CCK power setting */ 26269485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? 26279485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl; 26289485SMikore.Li@Sun.COM cck_pwrlvl += sc->sc_txpwr_cck_base; 26299485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; 26309485SMikore.Li@Sun.COM cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : 26319485SMikore.Li@Sun.COM urtw_8225v2_txpwr_cck; 26329485SMikore.Li@Sun.COM 26339485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) { 26349485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i, 26359485SMikore.Li@Sun.COM cck_pwrtable[i])) 26369485SMikore.Li@Sun.COM goto fail; 26379485SMikore.Li@Sun.COM } 26389485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK, 2639*10364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl], 0)) 26409485SMikore.Li@Sun.COM goto fail; 26419485SMikore.Li@Sun.COM urtw_delay_ms(1); 26429485SMikore.Li@Sun.COM 26439485SMikore.Li@Sun.COM /* OFDM power setting */ 26449485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 26459485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 26469485SMikore.Li@Sun.COM ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; 26479485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 26489485SMikore.Li@Sun.COM 2649*10364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON); 26509485SMikore.Li@Sun.COM if (error) 26519485SMikore.Li@Sun.COM goto fail; 26529485SMikore.Li@Sun.COM 26539485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42)) 26549485SMikore.Li@Sun.COM goto fail; 26559485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 5, 0x0)) 26569485SMikore.Li@Sun.COM goto fail; 26579485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0x40)) 26589485SMikore.Li@Sun.COM goto fail; 26599485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 7, 0x0)) 26609485SMikore.Li@Sun.COM goto fail; 26619485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0x40)) 26629485SMikore.Li@Sun.COM goto fail; 26639485SMikore.Li@Sun.COM 26649485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 2665*10364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl], 0); 26669485SMikore.Li@Sun.COM urtw_delay_ms(1); 26679485SMikore.Li@Sun.COM fail: 26689485SMikore.Li@Sun.COM return (error); 26699485SMikore.Li@Sun.COM } 26709485SMikore.Li@Sun.COM 26719485SMikore.Li@Sun.COM static usbd_status 2672*10364SMikore.Li@Sun.COM urtw_8225v2_rf_init(struct urtw_rf *rf) 26739485SMikore.Li@Sun.COM { 26749485SMikore.Li@Sun.COM #define N(a) (sizeof (a)/ sizeof ((a)[0])) 26759485SMikore.Li@Sun.COM int i; 26769485SMikore.Li@Sun.COM uint16_t data; 26779485SMikore.Li@Sun.COM uint32_t data32; 26789485SMikore.Li@Sun.COM usbd_status error; 2679*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 2680*10364SMikore.Li@Sun.COM 2681*10364SMikore.Li@Sun.COM if (error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON)) 26829485SMikore.Li@Sun.COM goto fail; 26839485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc)) 26849485SMikore.Li@Sun.COM goto fail; 2685*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0)) 26869485SMikore.Li@Sun.COM goto fail; 2687*10364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0)) 26889485SMikore.Li@Sun.COM goto fail; 2689*10364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0)) 26909485SMikore.Li@Sun.COM goto fail; 2691*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0)) 26929485SMikore.Li@Sun.COM goto fail; 26939485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG)) 26949485SMikore.Li@Sun.COM goto fail; 2695*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0)) 26969485SMikore.Li@Sun.COM goto fail; 26979485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL)) 26989485SMikore.Li@Sun.COM goto fail; 26999485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc)) 27009485SMikore.Li@Sun.COM goto fail; 27019485SMikore.Li@Sun.COM 27029485SMikore.Li@Sun.COM urtw_delay_ms(500); 27039485SMikore.Li@Sun.COM 27049485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part1); i++) { 27059485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225v2_rf_part1[i].reg, 27069485SMikore.Li@Sun.COM urtw_8225v2_rf_part1[i].val)) 27079485SMikore.Li@Sun.COM goto fail; 27089485SMikore.Li@Sun.COM urtw_delay_ms(1); 27099485SMikore.Li@Sun.COM } 27109485SMikore.Li@Sun.COM urtw_delay_ms(100); 27119485SMikore.Li@Sun.COM 27129485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7)) 27139485SMikore.Li@Sun.COM goto fail; 27149485SMikore.Li@Sun.COM 27159485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) { 27169485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1))) 27179485SMikore.Li@Sun.COM goto fail; 27189485SMikore.Li@Sun.COM urtw_delay_ms(1); 27199485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i])) 27209485SMikore.Li@Sun.COM goto fail; 27219485SMikore.Li@Sun.COM urtw_delay_ms(1); 27229485SMikore.Li@Sun.COM } 27239485SMikore.Li@Sun.COM 27249485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x3, 0x2)) 27259485SMikore.Li@Sun.COM goto fail; 27269485SMikore.Li@Sun.COM urtw_delay_ms(1); 27279485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x5, 0x4)) 27289485SMikore.Li@Sun.COM goto fail; 27299485SMikore.Li@Sun.COM urtw_delay_ms(1); 27309485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0xb7)) 27319485SMikore.Li@Sun.COM goto fail; 27329485SMikore.Li@Sun.COM urtw_delay_ms(1); 27339485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d)) 27349485SMikore.Li@Sun.COM goto fail; 27359485SMikore.Li@Sun.COM urtw_delay_ms(100); 27369485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d)) 27379485SMikore.Li@Sun.COM goto fail; 27389485SMikore.Li@Sun.COM urtw_delay_ms(100); 27399485SMikore.Li@Sun.COM 27409485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32)) 27419485SMikore.Li@Sun.COM goto fail; 27429485SMikore.Li@Sun.COM if (data32 != 0xe6) { 27439485SMikore.Li@Sun.COM error = (-1); 27449485SMikore.Li@Sun.COM cmn_err(CE_WARN, "expect 0xe6!! (0x%x)\n", data32); 27459485SMikore.Li@Sun.COM goto fail; 27469485SMikore.Li@Sun.COM } 27479485SMikore.Li@Sun.COM if (!(data32 & 0x80)) { 27489485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x0c4d)) 27499485SMikore.Li@Sun.COM goto fail; 27509485SMikore.Li@Sun.COM urtw_delay_ms(200); 27519485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x044d)) 27529485SMikore.Li@Sun.COM goto fail; 27539485SMikore.Li@Sun.COM urtw_delay_ms(100); 27549485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32)) 27559485SMikore.Li@Sun.COM goto fail; 27569485SMikore.Li@Sun.COM if (!(data32 & 0x80)) 27579485SMikore.Li@Sun.COM cmn_err(CE_CONT, "RF calibration failed\n"); 27589485SMikore.Li@Sun.COM } 27599485SMikore.Li@Sun.COM urtw_delay_ms(200); 27609485SMikore.Li@Sun.COM 27619485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x2bf)) 27629485SMikore.Li@Sun.COM goto fail; 27639485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) { 27649485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb, 27659485SMikore.Li@Sun.COM urtw_8225_agc[i])) 27669485SMikore.Li@Sun.COM goto fail; 27679485SMikore.Li@Sun.COM urtw_delay_ms(1); 27689485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa, 27699485SMikore.Li@Sun.COM (uint8_t)i + 0x80)) 27709485SMikore.Li@Sun.COM goto fail; 27719485SMikore.Li@Sun.COM urtw_delay_ms(1); 27729485SMikore.Li@Sun.COM } 27739485SMikore.Li@Sun.COM urtw_delay_ms(1); 27749485SMikore.Li@Sun.COM 27759485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part2); i++) { 27769485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 27779485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].reg, 27789485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].val)) 27799485SMikore.Li@Sun.COM goto fail; 27809485SMikore.Li@Sun.COM urtw_delay_ms(1); 27819485SMikore.Li@Sun.COM } 27829485SMikore.Li@Sun.COM error = urtw_8225v2_setgain(sc, 4); 27839485SMikore.Li@Sun.COM if (error) 27849485SMikore.Li@Sun.COM goto fail; 27859485SMikore.Li@Sun.COM 27869485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part3); i++) { 27879485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 27889485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].reg, 27899485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].val)) 27909485SMikore.Li@Sun.COM goto fail; 27919485SMikore.Li@Sun.COM urtw_delay_ms(1); 27929485SMikore.Li@Sun.COM } 27939485SMikore.Li@Sun.COM 2794*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0)) 27959485SMikore.Li@Sun.COM goto fail; 27969485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, 1)) 27979485SMikore.Li@Sun.COM goto fail; 27989485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b)) 27999485SMikore.Li@Sun.COM goto fail; 28009485SMikore.Li@Sun.COM urtw_delay_ms(1); 28019485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90)) 28029485SMikore.Li@Sun.COM goto fail; 28039485SMikore.Li@Sun.COM urtw_delay_ms(1); 28049485SMikore.Li@Sun.COM 28059485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */ 28069485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3)) 28079485SMikore.Li@Sun.COM goto fail; 2808*10364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0)) 28099485SMikore.Li@Sun.COM goto fail; 28109485SMikore.Li@Sun.COM 2811*10364SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(rf, 2812*10364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan)); 28139485SMikore.Li@Sun.COM fail: 28149485SMikore.Li@Sun.COM return (error); 28159485SMikore.Li@Sun.COM #undef N 28169485SMikore.Li@Sun.COM } 28179485SMikore.Li@Sun.COM 28189485SMikore.Li@Sun.COM static usbd_status 2819*10364SMikore.Li@Sun.COM urtw_8225v2_rf_set_chan(struct urtw_rf *rf, int chan) 28209485SMikore.Li@Sun.COM { 2821*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 28229485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 28239485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 28249485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0; 28259485SMikore.Li@Sun.COM usbd_status error; 28269485SMikore.Li@Sun.COM 28279485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, chan)) 28289485SMikore.Li@Sun.COM goto fail; 28299485SMikore.Li@Sun.COM 28309485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan])) 28319485SMikore.Li@Sun.COM goto fail; 28329485SMikore.Li@Sun.COM 28339485SMikore.Li@Sun.COM urtw_delay_ms(10); 28349485SMikore.Li@Sun.COM 2835*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0)) 28369485SMikore.Li@Sun.COM goto fail; 28379485SMikore.Li@Sun.COM 28389485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC && 28399485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT) { 2840*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0)) 28419485SMikore.Li@Sun.COM goto fail; 28429485SMikore.Li@Sun.COM } else 2843*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0)) 28449485SMikore.Li@Sun.COM goto fail; 28459485SMikore.Li@Sun.COM if (gset) { 28469485SMikore.Li@Sun.COM /* for G */ 2847*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0)) 28489485SMikore.Li@Sun.COM goto fail; 2849*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0)) 28509485SMikore.Li@Sun.COM goto fail; 2851*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0)) 28529485SMikore.Li@Sun.COM goto fail; 28539485SMikore.Li@Sun.COM } else { 28549485SMikore.Li@Sun.COM /* for B */ 2855*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0)) 28569485SMikore.Li@Sun.COM goto fail; 2857*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0)) 28589485SMikore.Li@Sun.COM goto fail; 2859*10364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0)) 28609485SMikore.Li@Sun.COM goto fail; 28619485SMikore.Li@Sun.COM } 28629485SMikore.Li@Sun.COM 28639485SMikore.Li@Sun.COM fail: 28649485SMikore.Li@Sun.COM return (error); 28659485SMikore.Li@Sun.COM } 28669485SMikore.Li@Sun.COM 28679485SMikore.Li@Sun.COM static int 28689485SMikore.Li@Sun.COM urtw_set_channel(struct urtw_softc *sc) 28699485SMikore.Li@Sun.COM { 28709485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2871*10364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf; 28729485SMikore.Li@Sun.COM uint32_t data; 28739485SMikore.Li@Sun.COM usbd_status error; 28749485SMikore.Li@Sun.COM 2875*10364SMikore.Li@Sun.COM if (error = urtw_read32_c(sc, URTW_TX_CONF, &data, 0)) 28769485SMikore.Li@Sun.COM goto fail; 28779485SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK; 28789485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_TX_CONF, 2879*10364SMikore.Li@Sun.COM data | URTW_TX_LOOPBACK_MAC, 0)) 28809485SMikore.Li@Sun.COM goto fail; 2881*10364SMikore.Li@Sun.COM error = rf->set_chan(rf, ieee80211_chan2ieee(ic, ic->ic_curchan)); 28829485SMikore.Li@Sun.COM if (error) 28839485SMikore.Li@Sun.COM goto fail; 2884*10364SMikore.Li@Sun.COM urtw_delay_ms(20); 2885*10364SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_TX_CONF, 2886*10364SMikore.Li@Sun.COM data | URTW_TX_LOOPBACK_NONE, 0); 28879485SMikore.Li@Sun.COM fail: 28889485SMikore.Li@Sun.COM return (error); 28899485SMikore.Li@Sun.COM } 28909485SMikore.Li@Sun.COM 28919485SMikore.Li@Sun.COM /* ARGSUSED */ 28929485SMikore.Li@Sun.COM static void 28939485SMikore.Li@Sun.COM urtw_txeof_low(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 28949485SMikore.Li@Sun.COM { 28959485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 28969485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 28979485SMikore.Li@Sun.COM 28989485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 28999485SMikore.Li@Sun.COM "urtw_txeof_low(): cr:%s(%d), flags:0x%x, tx_queued:%d", 29009485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason), 29019485SMikore.Li@Sun.COM req->bulk_completion_reason, 29029485SMikore.Li@Sun.COM req->bulk_cb_flags, 29039485SMikore.Li@Sun.COM sc->sc_tx_low_queued)); 29049485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 29059485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) { 29069485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 29079485SMikore.Li@Sun.COM goto fail; 29089485SMikore.Li@Sun.COM } 29099485SMikore.Li@Sun.COM 29109485SMikore.Li@Sun.COM if (sc->sc_need_sched) { 29119485SMikore.Li@Sun.COM sc->sc_need_sched = 0; 29129485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach); 29139485SMikore.Li@Sun.COM } 29149485SMikore.Li@Sun.COM fail: 29159485SMikore.Li@Sun.COM sc->sc_tx_low_queued--; 29169485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 29179485SMikore.Li@Sun.COM usb_free_bulk_req(req); 29189485SMikore.Li@Sun.COM } 29199485SMikore.Li@Sun.COM 29209485SMikore.Li@Sun.COM /* ARGSUSED */ 29219485SMikore.Li@Sun.COM static void 29229485SMikore.Li@Sun.COM urtw_txeof_normal(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 29239485SMikore.Li@Sun.COM { 29249485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 29259485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 29269485SMikore.Li@Sun.COM 29279485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 29289485SMikore.Li@Sun.COM "urtw_txeof_normal(): cr:%s(%d), flags:0x%x, tx_queued:%d", 29299485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason), 29309485SMikore.Li@Sun.COM req->bulk_completion_reason, 29319485SMikore.Li@Sun.COM req->bulk_cb_flags, 29329485SMikore.Li@Sun.COM sc->sc_tx_normal_queued)); 29339485SMikore.Li@Sun.COM 29349485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 29359485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) { 29369485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 29379485SMikore.Li@Sun.COM goto fail; 29389485SMikore.Li@Sun.COM } 29399485SMikore.Li@Sun.COM 29409485SMikore.Li@Sun.COM if (sc->sc_need_sched) { 29419485SMikore.Li@Sun.COM sc->sc_need_sched = 0; 29429485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach); 29439485SMikore.Li@Sun.COM } 29449485SMikore.Li@Sun.COM fail: 29459485SMikore.Li@Sun.COM sc->sc_tx_normal_queued--; 29469485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 29479485SMikore.Li@Sun.COM usb_free_bulk_req(req); 29489485SMikore.Li@Sun.COM } 29499485SMikore.Li@Sun.COM 29509485SMikore.Li@Sun.COM 29519485SMikore.Li@Sun.COM static int 29529485SMikore.Li@Sun.COM urtw_get_rate(struct ieee80211com *ic) 29539485SMikore.Li@Sun.COM { 29549485SMikore.Li@Sun.COM uint8_t (*rates)[IEEE80211_RATE_MAXSIZE]; 29559485SMikore.Li@Sun.COM int rate; 29569485SMikore.Li@Sun.COM 29579485SMikore.Li@Sun.COM rates = &ic->ic_bss->in_rates.ir_rates; 29589485SMikore.Li@Sun.COM 29599485SMikore.Li@Sun.COM if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 29609485SMikore.Li@Sun.COM rate = ic->ic_fixed_rate; 29619485SMikore.Li@Sun.COM else if (ic->ic_state == IEEE80211_S_RUN) 29629485SMikore.Li@Sun.COM rate = (*rates)[ic->ic_bss->in_txrate]; 29639485SMikore.Li@Sun.COM else 29649485SMikore.Li@Sun.COM rate = 0; 29659485SMikore.Li@Sun.COM return (rate & IEEE80211_RATE_VAL); 29669485SMikore.Li@Sun.COM } 29679485SMikore.Li@Sun.COM 2968*10364SMikore.Li@Sun.COM void 2969*10364SMikore.Li@Sun.COM urtw_8187b_update_wmm(struct urtw_softc *sc) 2970*10364SMikore.Li@Sun.COM { 2971*10364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2972*10364SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 2973*10364SMikore.Li@Sun.COM uint32_t data; 2974*10364SMikore.Li@Sun.COM uint8_t aifs, sifs, slot, ecwmin, ecwmax; 2975*10364SMikore.Li@Sun.COM 2976*10364SMikore.Li@Sun.COM sifs = 0xa; 2977*10364SMikore.Li@Sun.COM if (IEEE80211_IS_CHAN_G(c)) 2978*10364SMikore.Li@Sun.COM slot = 0x9; 2979*10364SMikore.Li@Sun.COM else 2980*10364SMikore.Li@Sun.COM slot = 0x14; 2981*10364SMikore.Li@Sun.COM 2982*10364SMikore.Li@Sun.COM aifs = (2 * slot) + sifs; 2983*10364SMikore.Li@Sun.COM ecwmin = 3; 2984*10364SMikore.Li@Sun.COM ecwmax = 7; 2985*10364SMikore.Li@Sun.COM 2986*10364SMikore.Li@Sun.COM data = ((uint32_t)aifs << 0) | /* AIFS, offset 0 */ 2987*10364SMikore.Li@Sun.COM ((uint32_t)ecwmin << 8) | /* ECW minimum, offset 8 */ 2988*10364SMikore.Li@Sun.COM ((uint32_t)ecwmax << 12); /* ECW maximum, offset 16 */ 2989*10364SMikore.Li@Sun.COM 2990*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_VO, data, 0); 2991*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_VI, data, 0); 2992*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_BE, data, 0); 2993*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_BK, data, 0); 2994*10364SMikore.Li@Sun.COM } 2995*10364SMikore.Li@Sun.COM 2996*10364SMikore.Li@Sun.COM usbd_status 2997*10364SMikore.Li@Sun.COM urtw_8187b_reset(struct urtw_softc *sc) 2998*10364SMikore.Li@Sun.COM { 2999*10364SMikore.Li@Sun.COM uint8_t data; 3000*10364SMikore.Li@Sun.COM usbd_status error; 3001*10364SMikore.Li@Sun.COM 3002*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3003*10364SMikore.Li@Sun.COM if (error) 3004*10364SMikore.Li@Sun.COM goto fail; 3005*10364SMikore.Li@Sun.COM 3006*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0); 3007*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3, 3008*10364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE | 3009*10364SMikore.Li@Sun.COM URTW_CONFIG3_GNT_SELECT, 0); 3010*10364SMikore.Li@Sun.COM 3011*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_ANAPARAM2, 3012*10364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM2_ON, 0); 3013*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_ANAPARAM, 3014*10364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM_ON, 0); 3015*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_ANAPARAM3, 3016*10364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM3_ON, 0); 3017*10364SMikore.Li@Sun.COM 3018*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x61, 0x10, 0); 3019*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, 0x62, &data, 0); 3020*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x62, data & ~(1 << 5), 0); 3021*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x62, data | (1 << 5), 0); 3022*10364SMikore.Li@Sun.COM 3023*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0); 3024*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3, 3025*10364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0); 3026*10364SMikore.Li@Sun.COM 3027*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3028*10364SMikore.Li@Sun.COM if (error) 3029*10364SMikore.Li@Sun.COM goto fail; 3030*10364SMikore.Li@Sun.COM 3031*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data, 0); 3032*10364SMikore.Li@Sun.COM data = (data & 2) | URTW_CMD_RST; 3033*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CMD, data, 0); 3034*10364SMikore.Li@Sun.COM urtw_delay_ms(100); 3035*10364SMikore.Li@Sun.COM 3036*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data, 0); 3037*10364SMikore.Li@Sun.COM if (data & URTW_CMD_RST) { 3038*10364SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw: 8187b reset timeout\n"); 3039*10364SMikore.Li@Sun.COM goto fail; 3040*10364SMikore.Li@Sun.COM } 3041*10364SMikore.Li@Sun.COM 3042*10364SMikore.Li@Sun.COM fail: 3043*10364SMikore.Li@Sun.COM return (error); 3044*10364SMikore.Li@Sun.COM } 3045*10364SMikore.Li@Sun.COM 3046*10364SMikore.Li@Sun.COM static int 3047*10364SMikore.Li@Sun.COM urtw_8187b_init(void *arg) 3048*10364SMikore.Li@Sun.COM { 3049*10364SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 3050*10364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf; 3051*10364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3052*10364SMikore.Li@Sun.COM int i; 3053*10364SMikore.Li@Sun.COM uint8_t data; 3054*10364SMikore.Li@Sun.COM usbd_status error; 3055*10364SMikore.Li@Sun.COM 3056*10364SMikore.Li@Sun.COM urtw_stop(sc); 3057*10364SMikore.Li@Sun.COM URTW_LOCK(sc); 3058*10364SMikore.Li@Sun.COM urtw_8187b_update_wmm(sc); 3059*10364SMikore.Li@Sun.COM error = urtw_8187b_reset(sc); 3060*10364SMikore.Li@Sun.COM if (error) 3061*10364SMikore.Li@Sun.COM goto fail; 3062*10364SMikore.Li@Sun.COM 3063*10364SMikore.Li@Sun.COM error = urtw_open_pipes(sc); 3064*10364SMikore.Li@Sun.COM if (error != 0) 3065*10364SMikore.Li@Sun.COM goto fail; 3066*10364SMikore.Li@Sun.COM /* Applying MAC address again. */ 3067*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3068*10364SMikore.Li@Sun.COM if (error) 3069*10364SMikore.Li@Sun.COM goto fail; 3070*10364SMikore.Li@Sun.COM for (i = 0; i < IEEE80211_ADDR_LEN; i++) 3071*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_MAC0 + i, 3072*10364SMikore.Li@Sun.COM ic->ic_macaddr[i], 0); 3073*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3074*10364SMikore.Li@Sun.COM if (error) 3075*10364SMikore.Li@Sun.COM goto fail; 3076*10364SMikore.Li@Sun.COM 3077*10364SMikore.Li@Sun.COM error = urtw_update_msr(sc, IEEE80211_S_INIT); 3078*10364SMikore.Li@Sun.COM if (error) 3079*10364SMikore.Li@Sun.COM goto fail; 3080*10364SMikore.Li@Sun.COM 3081*10364SMikore.Li@Sun.COM error = rf->init(rf); 3082*10364SMikore.Li@Sun.COM if (error != 0) 3083*10364SMikore.Li@Sun.COM goto fail; 3084*10364SMikore.Li@Sun.COM error = urtw_intr_enable(sc); 3085*10364SMikore.Li@Sun.COM if (error != 0) 3086*10364SMikore.Li@Sun.COM goto fail; 3087*10364SMikore.Li@Sun.COM 3088*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x41, 0xf4); 3089*10364SMikore.Li@Sun.COM if (error != 0) 3090*10364SMikore.Li@Sun.COM goto fail; 3091*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x40, 0x00); 3092*10364SMikore.Li@Sun.COM if (error != 0) 3093*10364SMikore.Li@Sun.COM goto fail; 3094*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x00); 3095*10364SMikore.Li@Sun.COM if (error != 0) 3096*10364SMikore.Li@Sun.COM goto fail; 3097*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x01); 3098*10364SMikore.Li@Sun.COM if (error != 0) 3099*10364SMikore.Li@Sun.COM goto fail; 3100*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x40, 0x0f); 3101*10364SMikore.Li@Sun.COM if (error != 0) 3102*10364SMikore.Li@Sun.COM goto fail; 3103*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x00); 3104*10364SMikore.Li@Sun.COM if (error != 0) 3105*10364SMikore.Li@Sun.COM goto fail; 3106*10364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x01); 3107*10364SMikore.Li@Sun.COM if (error != 0) 3108*10364SMikore.Li@Sun.COM goto fail; 3109*10364SMikore.Li@Sun.COM 3110*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, 0xdb, &data, 0); 3111*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xdb, data | (1 << 2), 0); 3112*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x72, 0x59fa, 3); 3113*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x74, 0x59d2, 3); 3114*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x76, 0x59d2, 3); 3115*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x78, 0x19fa, 3); 3116*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x7a, 0x19fa, 3); 3117*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x7c, 0x00d0, 3); 3118*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x61, 0, 0); 3119*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x80, 0x0f, 1); 3120*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x83, 0x03, 1); 3121*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xda, 0x10, 0); 3122*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x4d, 0x08, 2); 3123*10364SMikore.Li@Sun.COM 3124*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_HSSI_PARA, 0x0600321b, 0); 3125*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0xec, 0x0800, 1); 3126*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_ACM_CONTROL, 0, 0); 3127*10364SMikore.Li@Sun.COM 3128*10364SMikore.Li@Sun.COM sc->sc_tx_low_queued = 0; 3129*10364SMikore.Li@Sun.COM sc->sc_tx_normal_queued = 0; 3130*10364SMikore.Li@Sun.COM error = urtw_rx_enable(sc); 3131*10364SMikore.Li@Sun.COM if (error != 0) 3132*10364SMikore.Li@Sun.COM goto fail; 3133*10364SMikore.Li@Sun.COM urtw_tx_enable(sc); 3134*10364SMikore.Li@Sun.COM 3135*10364SMikore.Li@Sun.COM if (error == 0) { 3136*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, 3137*10364SMikore.Li@Sun.COM CE_CONT, "urtw_8187b_init: done\n")); 3138*10364SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_RUNNING; 3139*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3140*10364SMikore.Li@Sun.COM return (error); 3141*10364SMikore.Li@Sun.COM } 3142*10364SMikore.Li@Sun.COM 3143*10364SMikore.Li@Sun.COM fail: 3144*10364SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_8187b_init failed\n"); 3145*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3146*10364SMikore.Li@Sun.COM urtw_stop(sc); 3147*10364SMikore.Li@Sun.COM return (EIO); 3148*10364SMikore.Li@Sun.COM } 3149*10364SMikore.Li@Sun.COM 3150*10364SMikore.Li@Sun.COM void 3151*10364SMikore.Li@Sun.COM urtw_8225v2_b_config_mac(struct urtw_softc *sc) 3152*10364SMikore.Li@Sun.COM { 3153*10364SMikore.Li@Sun.COM int i; 3154*10364SMikore.Li@Sun.COM int nitems = sizeof (urtw_8187b_regtbl) 3155*10364SMikore.Li@Sun.COM / sizeof ((urtw_8187b_regtbl)[0]); 3156*10364SMikore.Li@Sun.COM 3157*10364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) { 3158*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, urtw_8187b_regtbl[i].reg, 3159*10364SMikore.Li@Sun.COM urtw_8187b_regtbl[i].val, urtw_8187b_regtbl[i].idx); 3160*10364SMikore.Li@Sun.COM } 3161*10364SMikore.Li@Sun.COM 3162*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_TID_AC_MAP, 0xfa50, 0); 3163*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_INT_MIG, 0, 0); 3164*10364SMikore.Li@Sun.COM 3165*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, 0xf0, 0, 1); 3166*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, 0xf4, 0, 1); 3167*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xf8, 0, 1); 3168*10364SMikore.Li@Sun.COM 3169*10364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_RF_TIMING, 0x00004001, 0); 3170*10364SMikore.Li@Sun.COM } 3171*10364SMikore.Li@Sun.COM 3172*10364SMikore.Li@Sun.COM void 3173*10364SMikore.Li@Sun.COM urtw_8225v2_b_init_rfe(struct urtw_softc *sc) 3174*10364SMikore.Li@Sun.COM { 3175*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0480, 0); 3176*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x2488, 0); 3177*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1fff, 0); 3178*10364SMikore.Li@Sun.COM urtw_delay_ms(100); 3179*10364SMikore.Li@Sun.COM } 3180*10364SMikore.Li@Sun.COM 3181*10364SMikore.Li@Sun.COM usbd_status 3182*10364SMikore.Li@Sun.COM urtw_8225v2_b_update_chan(struct urtw_softc *sc) 3183*10364SMikore.Li@Sun.COM { 3184*10364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3185*10364SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 3186*10364SMikore.Li@Sun.COM uint8_t aifs, difs, eifs, sifs, slot; 3187*10364SMikore.Li@Sun.COM 3188*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_SIFS, 0x22, 0); 3189*10364SMikore.Li@Sun.COM 3190*10364SMikore.Li@Sun.COM sifs = 0xa; 3191*10364SMikore.Li@Sun.COM if (IEEE80211_IS_CHAN_G(c)) { 3192*10364SMikore.Li@Sun.COM slot = 0x9; 3193*10364SMikore.Li@Sun.COM difs = 0x1c; 3194*10364SMikore.Li@Sun.COM eifs = 0x5b; 3195*10364SMikore.Li@Sun.COM } else { 3196*10364SMikore.Li@Sun.COM slot = 0x14; 3197*10364SMikore.Li@Sun.COM difs = 0x32; 3198*10364SMikore.Li@Sun.COM eifs = 0x5b; 3199*10364SMikore.Li@Sun.COM } 3200*10364SMikore.Li@Sun.COM aifs = (2 * slot) + sifs; 3201*10364SMikore.Li@Sun.COM 3202*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_SLOT, slot, 0); 3203*10364SMikore.Li@Sun.COM 3204*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_VO, aifs, 0); 3205*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_VI, aifs, 0); 3206*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_BE, aifs, 0); 3207*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_BK, aifs, 0); 3208*10364SMikore.Li@Sun.COM 3209*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_DIFS, difs, 0); 3210*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_8187B_EIFS, eifs, 0); 3211*10364SMikore.Li@Sun.COM return (0); 3212*10364SMikore.Li@Sun.COM } 3213*10364SMikore.Li@Sun.COM 3214*10364SMikore.Li@Sun.COM usbd_status 3215*10364SMikore.Li@Sun.COM urtw_8225v2_b_rf_init(struct urtw_rf *rf) 3216*10364SMikore.Li@Sun.COM { 3217*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 3218*10364SMikore.Li@Sun.COM int i, nitems; 3219*10364SMikore.Li@Sun.COM uint8_t data; 3220*10364SMikore.Li@Sun.COM usbd_status error; 3221*10364SMikore.Li@Sun.COM 3222*10364SMikore.Li@Sun.COM /* Set up ACK rate, retry limit, TX AGC, TX antenna. */ 3223*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_8187B_BRSR, 0x0fff, 0); 3224*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CW_CONF, &data, 0); 3225*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CW_CONF, data | 3226*10364SMikore.Li@Sun.COM URTW_CW_CONF_PERPACKET_RETRY, 0); 3227*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data, 0); 3228*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data | 3229*10364SMikore.Li@Sun.COM URTW_TX_AGC_CTL_PERPACKET_GAIN | 3230*10364SMikore.Li@Sun.COM URTW_TX_AGC_CTL_PERPACKET_ANTSEL, 0); 3231*10364SMikore.Li@Sun.COM 3232*10364SMikore.Li@Sun.COM /* Auto rate fallback control. */ 3233*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_ARFR, 0x0fff, 1); /* 1M ~ 54M */ 3234*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_RATE_FALLBACK, &data, 0); 3235*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_RATE_FALLBACK, data | 3236*10364SMikore.Li@Sun.COM URTW_RATE_FALLBACK_ENABLE, 0); 3237*10364SMikore.Li@Sun.COM 3238*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_BEACON_INTERVAL, 0x3ff, 0); 3239*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_ATIM_WND, 2, 0); 3240*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_FEMR, 0xffff, 1); 3241*10364SMikore.Li@Sun.COM 3242*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3243*10364SMikore.Li@Sun.COM if (error) 3244*10364SMikore.Li@Sun.COM goto fail; 3245*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG1, &data, 0); 3246*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG1, (data & 0x3f) | 0x80, 0); 3247*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3248*10364SMikore.Li@Sun.COM if (error) 3249*10364SMikore.Li@Sun.COM goto fail; 3250*10364SMikore.Li@Sun.COM 3251*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0); 3252*10364SMikore.Li@Sun.COM urtw_8225v2_b_config_mac(sc); 3253*10364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RFSW_CTRL, 0x569a, 2); 3254*10364SMikore.Li@Sun.COM 3255*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3256*10364SMikore.Li@Sun.COM if (error) 3257*10364SMikore.Li@Sun.COM goto fail; 3258*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0); 3259*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3, 3260*10364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0); 3261*10364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3262*10364SMikore.Li@Sun.COM if (error) 3263*10364SMikore.Li@Sun.COM goto fail; 3264*10364SMikore.Li@Sun.COM 3265*10364SMikore.Li@Sun.COM urtw_8225v2_b_init_rfe(sc); 3266*10364SMikore.Li@Sun.COM 3267*10364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_b_rf) / sizeof ((urtw_8225v2_b_rf)[0]); 3268*10364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) { 3269*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, urtw_8225v2_b_rf[i].reg, 3270*10364SMikore.Li@Sun.COM urtw_8225v2_b_rf[i].val); 3271*10364SMikore.Li@Sun.COM } 3272*10364SMikore.Li@Sun.COM 3273*10364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_rxgain) / sizeof ((urtw_8225v2_rxgain)[0]); 3274*10364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) { 3275*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1)); 3276*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i]); 3277*10364SMikore.Li@Sun.COM } 3278*10364SMikore.Li@Sun.COM 3279*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x03, 0x080); 3280*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x05, 0x004); 3281*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x00, 0x0b7); 3282*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x02, 0xc4d); 3283*10364SMikore.Li@Sun.COM urtw_delay_ms(10); 3284*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x02, 0x44d); 3285*10364SMikore.Li@Sun.COM urtw_delay_ms(10); 3286*10364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x00, 0x2bf); 3287*10364SMikore.Li@Sun.COM urtw_delay_ms(10); 3288*10364SMikore.Li@Sun.COM 3289*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_CCK, 0x03, 0); 3290*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 0x07, 0); 3291*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_ANTENNA, 0x03, 0); 3292*10364SMikore.Li@Sun.COM 3293*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x12); 3294*10364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_agc) / sizeof ((urtw_8225v2_agc)[0]); 3295*10364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) { 3296*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0f, urtw_8225v2_agc[i]); 3297*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, (uint8_t)i + 0x80); 3298*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, 0); 3299*10364SMikore.Li@Sun.COM } 3300*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x10); 3301*10364SMikore.Li@Sun.COM 3302*10364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_ofdm) / sizeof ((urtw_8225v2_ofdm)[0]); 3303*10364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) { 3304*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, i, urtw_8225v2_ofdm[i]); 3305*10364SMikore.Li@Sun.COM } 3306*10364SMikore.Li@Sun.COM (void) urtw_8225v2_b_update_chan(sc); 3307*10364SMikore.Li@Sun.COM 3308*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x97, 0x46); 3309*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0xa4, 0xb6); 3310*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x85, 0xfc); 3311*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_cck_c(sc, 0xc1, 0x88); 3312*10364SMikore.Li@Sun.COM 3313*10364SMikore.Li@Sun.COM error = urtw_8225v2_b_rf_set_chan(rf, 3314*10364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan)); 3315*10364SMikore.Li@Sun.COM fail: 3316*10364SMikore.Li@Sun.COM return (error); 3317*10364SMikore.Li@Sun.COM } 3318*10364SMikore.Li@Sun.COM 3319*10364SMikore.Li@Sun.COM static usbd_status 3320*10364SMikore.Li@Sun.COM urtw_8225v2_b_rf_set_chan(struct urtw_rf *rf, int chan) 3321*10364SMikore.Li@Sun.COM { 3322*10364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc; 3323*10364SMikore.Li@Sun.COM int error = 0; 3324*10364SMikore.Li@Sun.COM 3325*10364SMikore.Li@Sun.COM urtw_8225v2_b_set_txpwrlvl(sc, chan); 3326*10364SMikore.Li@Sun.COM error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan]); 3327*10364SMikore.Li@Sun.COM if (error) 3328*10364SMikore.Li@Sun.COM goto fail; 3329*10364SMikore.Li@Sun.COM /* 3330*10364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187. 3331*10364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 10); 3332*10364SMikore.Li@Sun.COM */ 3333*10364SMikore.Li@Sun.COM 3334*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_VO, 0x5114, 0); 3335*10364SMikore.Li@Sun.COM if (error) 3336*10364SMikore.Li@Sun.COM goto fail; 3337*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_VI, 0x5114, 0); 3338*10364SMikore.Li@Sun.COM if (error) 3339*10364SMikore.Li@Sun.COM goto fail; 3340*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_BE, 0x5114, 0); 3341*10364SMikore.Li@Sun.COM if (error) 3342*10364SMikore.Li@Sun.COM goto fail; 3343*10364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_BK, 0x5114, 0); 3344*10364SMikore.Li@Sun.COM fail: 3345*10364SMikore.Li@Sun.COM return (error); 3346*10364SMikore.Li@Sun.COM } 3347*10364SMikore.Li@Sun.COM 3348*10364SMikore.Li@Sun.COM void 3349*10364SMikore.Li@Sun.COM urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *sc, int chan) 3350*10364SMikore.Li@Sun.COM { 3351*10364SMikore.Li@Sun.COM int i; 3352*10364SMikore.Li@Sun.COM uint8_t *cck_pwrtable; 3353*10364SMikore.Li@Sun.COM uint8_t cck_pwrlvl_min, cck_pwrlvl_max, ofdm_pwrlvl_min, 3354*10364SMikore.Li@Sun.COM ofdm_pwrlvl_max; 3355*10364SMikore.Li@Sun.COM int8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 3356*10364SMikore.Li@Sun.COM int8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 3357*10364SMikore.Li@Sun.COM 3358*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) { 3359*10364SMikore.Li@Sun.COM cck_pwrlvl_min = 0; 3360*10364SMikore.Li@Sun.COM cck_pwrlvl_max = 15; 3361*10364SMikore.Li@Sun.COM ofdm_pwrlvl_min = 2; 3362*10364SMikore.Li@Sun.COM ofdm_pwrlvl_max = 17; 3363*10364SMikore.Li@Sun.COM } else { 3364*10364SMikore.Li@Sun.COM cck_pwrlvl_min = 7; 3365*10364SMikore.Li@Sun.COM cck_pwrlvl_max = 22; 3366*10364SMikore.Li@Sun.COM ofdm_pwrlvl_min = 10; 3367*10364SMikore.Li@Sun.COM ofdm_pwrlvl_max = 25; 3368*10364SMikore.Li@Sun.COM } 3369*10364SMikore.Li@Sun.COM 3370*10364SMikore.Li@Sun.COM /* CCK power setting */ 3371*10364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > (cck_pwrlvl_max - cck_pwrlvl_min)) ? 3372*10364SMikore.Li@Sun.COM cck_pwrlvl_max : (cck_pwrlvl + cck_pwrlvl_min); 3373*10364SMikore.Li@Sun.COM 3374*10364SMikore.Li@Sun.COM cck_pwrlvl += sc->sc_txpwr_cck_base; 3375*10364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; 3376*10364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl < 0) ? 0 : cck_pwrlvl; 3377*10364SMikore.Li@Sun.COM 3378*10364SMikore.Li@Sun.COM cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : 3379*10364SMikore.Li@Sun.COM urtw_8225v2_txpwr_cck; 3380*10364SMikore.Li@Sun.COM 3381*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) { 3382*10364SMikore.Li@Sun.COM if (cck_pwrlvl > 7 && cck_pwrlvl <= 11) 3383*10364SMikore.Li@Sun.COM cck_pwrtable += 8; 3384*10364SMikore.Li@Sun.COM if (cck_pwrlvl > 11) 3385*10364SMikore.Li@Sun.COM cck_pwrtable += 16; 3386*10364SMikore.Li@Sun.COM } else { 3387*10364SMikore.Li@Sun.COM if (cck_pwrlvl > 5 && cck_pwrlvl <= 11) 3388*10364SMikore.Li@Sun.COM cck_pwrtable += 8; 3389*10364SMikore.Li@Sun.COM if (cck_pwrlvl > 12 && cck_pwrlvl <= 17) 3390*10364SMikore.Li@Sun.COM cck_pwrtable += 16; 3391*10364SMikore.Li@Sun.COM if (cck_pwrlvl > 17) 3392*10364SMikore.Li@Sun.COM cck_pwrtable += 24; 3393*10364SMikore.Li@Sun.COM } 3394*10364SMikore.Li@Sun.COM 3395*10364SMikore.Li@Sun.COM for (i = 0; i < 8; i++) { 3396*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_cck_c(sc, 0x44 + i, cck_pwrtable[i]); 3397*10364SMikore.Li@Sun.COM } 3398*10364SMikore.Li@Sun.COM 3399*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_CCK, 3400*10364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1, 0); 3401*10364SMikore.Li@Sun.COM /* 3402*10364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187. 3403*10364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1); 3404*10364SMikore.Li@Sun.COM */ 3405*10364SMikore.Li@Sun.COM 3406*10364SMikore.Li@Sun.COM /* OFDM power setting */ 3407*10364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 3408*10364SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 3409*10364SMikore.Li@Sun.COM 3410*10364SMikore.Li@Sun.COM ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; 3411*10364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 3412*10364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl < 0) ? 0 : ofdm_pwrlvl; 3413*10364SMikore.Li@Sun.COM 3414*10364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 3415*10364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1, 0); 3416*10364SMikore.Li@Sun.COM 3417*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) { 3418*10364SMikore.Li@Sun.COM if (ofdm_pwrlvl <= 11) { 3419*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x60); 3420*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x60); 3421*10364SMikore.Li@Sun.COM } else { 3422*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c); 3423*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c); 3424*10364SMikore.Li@Sun.COM } 3425*10364SMikore.Li@Sun.COM } else { 3426*10364SMikore.Li@Sun.COM if (ofdm_pwrlvl <= 11) { 3427*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c); 3428*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c); 3429*10364SMikore.Li@Sun.COM } else if (ofdm_pwrlvl <= 17) { 3430*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x54); 3431*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x54); 3432*10364SMikore.Li@Sun.COM } else { 3433*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x50); 3434*10364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x50); 3435*10364SMikore.Li@Sun.COM } 3436*10364SMikore.Li@Sun.COM } 3437*10364SMikore.Li@Sun.COM 3438*10364SMikore.Li@Sun.COM /* 3439*10364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187. 3440*10364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1); 3441*10364SMikore.Li@Sun.COM */ 3442*10364SMikore.Li@Sun.COM } 3443*10364SMikore.Li@Sun.COM 3444*10364SMikore.Li@Sun.COM 34459485SMikore.Li@Sun.COM static int 34469485SMikore.Li@Sun.COM urtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 34479485SMikore.Li@Sun.COM { 34489485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic; 34499485SMikore.Li@Sun.COM struct ieee80211_frame *wh; 34509485SMikore.Li@Sun.COM struct ieee80211_key *k; 34519485SMikore.Li@Sun.COM struct ieee80211_node *ni = NULL; 34529485SMikore.Li@Sun.COM uint8_t *buf; 34539485SMikore.Li@Sun.COM mblk_t *m = 0, *m0, *mtx; 34549485SMikore.Li@Sun.COM int off, mblen, xferlen, err = 0, priority = 0; 34559485SMikore.Li@Sun.COM 34569485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 34579485SMikore.Li@Sun.COM priority = (type == IEEE80211_FC0_TYPE_DATA) ? 34589485SMikore.Li@Sun.COM LOW_PRIORITY_PIPE: NORMAL_PRIORITY_PIPE; 34599485SMikore.Li@Sun.COM 34609485SMikore.Li@Sun.COM if (URTW_IS_SUSPENDING(sc)) { 34619485SMikore.Li@Sun.COM err = 0; 34629485SMikore.Li@Sun.COM goto failed; 34639485SMikore.Li@Sun.COM } 34649485SMikore.Li@Sun.COM 34659485SMikore.Li@Sun.COM if (((priority)? sc->sc_tx_normal_queued : sc->sc_tx_low_queued) >= 34669485SMikore.Li@Sun.COM URTW_TX_DATA_LIST_COUNT) { 34679485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT, 34689485SMikore.Li@Sun.COM "urtw_send(): no TX buffer!\n")); 34699485SMikore.Li@Sun.COM sc->sc_tx_nobuf++; 34709485SMikore.Li@Sun.COM err = ENOMEM; 34719485SMikore.Li@Sun.COM goto failed; 34729485SMikore.Li@Sun.COM } 34739485SMikore.Li@Sun.COM 34749485SMikore.Li@Sun.COM m = allocb(URTW_TXBUF_SIZE, BPRI_MED); 34759485SMikore.Li@Sun.COM if (m == NULL) { 34769485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_send(): can't alloc mblk.\n"); 34779485SMikore.Li@Sun.COM err = ENOMEM; 34789485SMikore.Li@Sun.COM goto failed; 34799485SMikore.Li@Sun.COM } 34809485SMikore.Li@Sun.COM 34819485SMikore.Li@Sun.COM for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 34829485SMikore.Li@Sun.COM mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr; 34839485SMikore.Li@Sun.COM (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen); 34849485SMikore.Li@Sun.COM off += mblen; 34859485SMikore.Li@Sun.COM } 34869485SMikore.Li@Sun.COM m->b_wptr += off; 34879485SMikore.Li@Sun.COM 34889485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr; 34899485SMikore.Li@Sun.COM 34909485SMikore.Li@Sun.COM ni = ieee80211_find_txnode(ic, wh->i_addr1); 34919485SMikore.Li@Sun.COM if (ni == NULL) { 34929485SMikore.Li@Sun.COM err = ENXIO; 34939485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 34949485SMikore.Li@Sun.COM goto failed; 34959485SMikore.Li@Sun.COM } 34969485SMikore.Li@Sun.COM 34979485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) == 34989485SMikore.Li@Sun.COM IEEE80211_FC0_TYPE_DATA) { 34999485SMikore.Li@Sun.COM (void) ieee80211_encap(ic, m, ni); 35009485SMikore.Li@Sun.COM } 35019485SMikore.Li@Sun.COM 35029485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 35039485SMikore.Li@Sun.COM k = ieee80211_crypto_encap(ic, m); 35049485SMikore.Li@Sun.COM if (k == NULL) { 35059485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 35069485SMikore.Li@Sun.COM err = ENXIO; 35079485SMikore.Li@Sun.COM goto failed; 35089485SMikore.Li@Sun.COM } 35099485SMikore.Li@Sun.COM /* packet header may have moved, reset our local pointer */ 35109485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr; 35119485SMikore.Li@Sun.COM } 35129485SMikore.Li@Sun.COM 3513*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) 3514*10364SMikore.Li@Sun.COM xferlen = MBLKL(m) + 4 * 3; 3515*10364SMikore.Li@Sun.COM else 3516*10364SMikore.Li@Sun.COM xferlen = MBLKL(m) + 4 * 8; 3517*10364SMikore.Li@Sun.COM 35189485SMikore.Li@Sun.COM if ((0 == xferlen % 64) || (0 == xferlen % 512)) 35199485SMikore.Li@Sun.COM xferlen += 1; 35209485SMikore.Li@Sun.COM 35219485SMikore.Li@Sun.COM mtx = allocb(xferlen, BPRI_MED); 35229485SMikore.Li@Sun.COM buf = mtx->b_rptr; 35239485SMikore.Li@Sun.COM 35249485SMikore.Li@Sun.COM bzero(buf, xferlen); 35259485SMikore.Li@Sun.COM buf[0] = MBLKL(m) & 0xff; 35269485SMikore.Li@Sun.COM buf[1] = (MBLKL(m) & 0x0f00) >> 8; 35279485SMikore.Li@Sun.COM buf[1] |= (1 << 7); 35289485SMikore.Li@Sun.COM 35299485SMikore.Li@Sun.COM /* XXX sc_preamble_mode is always 2. */ 35309485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) 35319485SMikore.Li@Sun.COM buf[2] |= (1 << 1); 35329485SMikore.Li@Sun.COM /* RTS rate - 10 means we use a basic rate. */ 35339485SMikore.Li@Sun.COM buf[2] |= (urtw_rate2rtl(2) << 3); 35349485SMikore.Li@Sun.COM /* 35359485SMikore.Li@Sun.COM * XXX currently TX rate control depends on the rate value of 35369485SMikore.Li@Sun.COM * RX descriptor because I don't know how to we can control TX rate 35379485SMikore.Li@Sun.COM * in more smart way. Please fix me you find a thing. 35389485SMikore.Li@Sun.COM */ 35399485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { 35409485SMikore.Li@Sun.COM buf[3] = urtw_rate2rtl(MAX(2, urtw_get_rate(ic))); 35419485SMikore.Li@Sun.COM } else 35429485SMikore.Li@Sun.COM buf[3] = sc->sc_currate; 3543*10364SMikore.Li@Sun.COM 3544*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 3545*10364SMikore.Li@Sun.COM buf[8] = 3; /* CW minimum */ 3546*10364SMikore.Li@Sun.COM buf[8] |= (7 << 4); /* CW maximum */ 3547*10364SMikore.Li@Sun.COM buf[9] |= 11; /* retry limitation */ 3548*10364SMikore.Li@Sun.COM bcopy(m->b_rptr, &buf[12], MBLKL(m)); 3549*10364SMikore.Li@Sun.COM } else { 3550*10364SMikore.Li@Sun.COM buf[21] |= 11; /* retry limitation */ 3551*10364SMikore.Li@Sun.COM bcopy(m->b_rptr, &buf[32], MBLKL(m)); 3552*10364SMikore.Li@Sun.COM } 35539485SMikore.Li@Sun.COM 35549485SMikore.Li@Sun.COM (void) urtw_led_ctl(sc, URTW_LED_CTL_TX); 35559485SMikore.Li@Sun.COM mtx->b_wptr = mtx->b_rptr + xferlen; 35569485SMikore.Li@Sun.COM 35579485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT, 3558*10364SMikore.Li@Sun.COM "sending frame len=%u rate=%u xfer len=%u\n", 35599485SMikore.Li@Sun.COM MBLKL(m), buf[3], xferlen)); 35609485SMikore.Li@Sun.COM 35619485SMikore.Li@Sun.COM err = urtw_tx_start(sc, mtx, priority); 35629485SMikore.Li@Sun.COM if (!err) { 35639485SMikore.Li@Sun.COM ic->ic_stats.is_tx_frags++; 35649485SMikore.Li@Sun.COM ic->ic_stats.is_tx_bytes += MBLKL(m); 35659485SMikore.Li@Sun.COM } else { 35669485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 35679485SMikore.Li@Sun.COM } 35689485SMikore.Li@Sun.COM 35699485SMikore.Li@Sun.COM failed: 35709485SMikore.Li@Sun.COM if (ni != NULL) 35719485SMikore.Li@Sun.COM ieee80211_free_node(ni); 35729485SMikore.Li@Sun.COM 35739485SMikore.Li@Sun.COM if ((mp) && 35749485SMikore.Li@Sun.COM ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 35759485SMikore.Li@Sun.COM err == DDI_SUCCESS)) { 35769485SMikore.Li@Sun.COM freemsg(mp); 35779485SMikore.Li@Sun.COM } 35789485SMikore.Li@Sun.COM if (m) freemsg(m); 35799485SMikore.Li@Sun.COM 35809485SMikore.Li@Sun.COM if (((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) && 35819485SMikore.Li@Sun.COM (err != 0)) { 35829485SMikore.Li@Sun.COM sc->sc_need_sched = 1; 35839485SMikore.Li@Sun.COM } 35849485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 35859485SMikore.Li@Sun.COM return (err); 35869485SMikore.Li@Sun.COM } 35879485SMikore.Li@Sun.COM 35889485SMikore.Li@Sun.COM static void 35899485SMikore.Li@Sun.COM urtw_next_scan(void *arg) 35909485SMikore.Li@Sun.COM { 35919485SMikore.Li@Sun.COM ieee80211com_t *ic = arg; 35929485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 35939485SMikore.Li@Sun.COM 35949485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) { 35959485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 35969485SMikore.Li@Sun.COM return; 35979485SMikore.Li@Sun.COM } 35989485SMikore.Li@Sun.COM 35999485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_SCAN) { 36009485SMikore.Li@Sun.COM (void) ieee80211_next_scan(ic); 36019485SMikore.Li@Sun.COM } 36029485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 36039485SMikore.Li@Sun.COM } 36049485SMikore.Li@Sun.COM 36059485SMikore.Li@Sun.COM static void 36069485SMikore.Li@Sun.COM urtw_led_launch(void *arg) 36079485SMikore.Li@Sun.COM { 36089485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 36099485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic; 36109485SMikore.Li@Sun.COM int error = 0; 36119485SMikore.Li@Sun.COM 36129485SMikore.Li@Sun.COM URTW_LEDLOCK(sc); 36139485SMikore.Li@Sun.COM if ((sc->sc_strategy != URTW_SW_LED_MODE0) || 36149485SMikore.Li@Sun.COM URTW_IS_NOT_RUNNING(sc) || 36159485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) { 36169485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 36179485SMikore.Li@Sun.COM "failed process LED strategy 0x%x, run?%d", 36189485SMikore.Li@Sun.COM sc->sc_strategy, 36199485SMikore.Li@Sun.COM sc->sc_flags)); 36209485SMikore.Li@Sun.COM sc->sc_led_ch = 0; 36219485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 36229485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 36239485SMikore.Li@Sun.COM return; 36249485SMikore.Li@Sun.COM } 36259485SMikore.Li@Sun.COM error = urtw_led_blink(sc); 36269485SMikore.Li@Sun.COM if (error) { 36279485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch, (void *)sc, 36289485SMikore.Li@Sun.COM drv_usectohz((ic->ic_state == IEEE80211_S_RUN) ? 36299485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK: URTW_LED_LINKOFF_BLINK)); 36309485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 36319485SMikore.Li@Sun.COM "try again led launch")); 36329485SMikore.Li@Sun.COM } else { 36339485SMikore.Li@Sun.COM sc->sc_led_ch = 0; 36349485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 36359485SMikore.Li@Sun.COM "exit led launch")); 36369485SMikore.Li@Sun.COM } 36379485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 36389485SMikore.Li@Sun.COM } 36399485SMikore.Li@Sun.COM 36409485SMikore.Li@Sun.COM static int 36419485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 36429485SMikore.Li@Sun.COM { 36439485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic; 36449485SMikore.Li@Sun.COM struct ieee80211_node *ni; 36459485SMikore.Li@Sun.COM int error = 0; 36469485SMikore.Li@Sun.COM 36479485SMikore.Li@Sun.COM if (sc->sc_scan_id != 0) { 36489485SMikore.Li@Sun.COM (void) untimeout(sc->sc_scan_id); 36499485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 36509485SMikore.Li@Sun.COM } 36519485SMikore.Li@Sun.COM URTW_LOCK(sc); 36529485SMikore.Li@Sun.COM switch (nstate) { 36539485SMikore.Li@Sun.COM case IEEE80211_S_INIT: 36549485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 36559485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "-> IEEE80211_S_INIT...arg(%d)\n", 36569485SMikore.Li@Sun.COM arg)); 3657*10364SMikore.Li@Sun.COM if (sc->sc_flags & URTW_FLAG_HP) 3658*10364SMikore.Li@Sun.COM break; 36599485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate); 36609485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 36619485SMikore.Li@Sun.COM break; 36629485SMikore.Li@Sun.COM 36639485SMikore.Li@Sun.COM case IEEE80211_S_SCAN: 36649485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 36659485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 36669485SMikore.Li@Sun.COM "-> IEEE80211_S_SCAN...arg(%d)...[%d]\n", 36679485SMikore.Li@Sun.COM arg, ieee80211_chan2ieee(ic, ic->ic_curchan))); 36689485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 36699485SMikore.Li@Sun.COM if (error) { 36709485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 36719485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "scan setchan failed")); 36729485SMikore.Li@Sun.COM break; 36739485SMikore.Li@Sun.COM } 36749485SMikore.Li@Sun.COM sc->sc_scan_id = timeout(urtw_next_scan, (void *)sc, 36759485SMikore.Li@Sun.COM drv_usectohz(sc->dwelltime * 1000)); 36769485SMikore.Li@Sun.COM break; 36779485SMikore.Li@Sun.COM 36789485SMikore.Li@Sun.COM case IEEE80211_S_AUTH: 36799485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT, 3680*10364SMikore.Li@Sun.COM "-> IEEE80211_S_AUTH ...arg(%d), chan (%d)\n", arg, 3681*10364SMikore.Li@Sun.COM ieee80211_chan2ieee(ic, ic->ic_curchan))); 36829485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 36839485SMikore.Li@Sun.COM if (error) { 36849485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 36859485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "auth setchan failed")); 36869485SMikore.Li@Sun.COM } 36879485SMikore.Li@Sun.COM break; 36889485SMikore.Li@Sun.COM 36899485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC: 36909485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT, 3691*10364SMikore.Li@Sun.COM "-> IEEE80211_S_ASSOC ...arg(%d), chan (%d)\n", arg, 3692*10364SMikore.Li@Sun.COM ieee80211_chan2ieee(ic, ic->ic_curchan))); 36939485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 36949485SMikore.Li@Sun.COM if (error) { 36959485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 36969485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "assoc setchan failed")); 36979485SMikore.Li@Sun.COM } 36989485SMikore.Li@Sun.COM break; 36999485SMikore.Li@Sun.COM 37009485SMikore.Li@Sun.COM case IEEE80211_S_RUN: 37019485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 3702*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 3703*10364SMikore.Li@Sun.COM "-> IEEE80211_S_RUN ...arg(%d), chan (%d)\n", 3704*10364SMikore.Li@Sun.COM arg, ieee80211_chan2ieee(ic, ic->ic_curchan))); 37059485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 37069485SMikore.Li@Sun.COM if (error) { 37079485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 37089485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "run setchan failed")); 37099485SMikore.Li@Sun.COM goto fail; 37109485SMikore.Li@Sun.COM } 37119485SMikore.Li@Sun.COM ni = ic->ic_bss; 37129485SMikore.Li@Sun.COM /* setting bssid. */ 37139485SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_BSSID, 3714*10364SMikore.Li@Sun.COM ((uint32_t *)(uintptr_t)ni->in_bssid)[0], 0); 37159485SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_BSSID + 4, 3716*10364SMikore.Li@Sun.COM ((uint16_t *)(uintptr_t)ni->in_bssid)[2], 0); 37179485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate); 37189485SMikore.Li@Sun.COM 37199485SMikore.Li@Sun.COM ni->in_txrate = ni->in_rates.ir_nrates - 1; 37209485SMikore.Li@Sun.COM break; 37219485SMikore.Li@Sun.COM } 37229485SMikore.Li@Sun.COM fail: 37239485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 37249485SMikore.Li@Sun.COM 3725*10364SMikore.Li@Sun.COM if (error) { 3726*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT, 3727*10364SMikore.Li@Sun.COM "-> newstate error...arg(%d)\n", error)); 37289485SMikore.Li@Sun.COM return (EIO); 3729*10364SMikore.Li@Sun.COM } 37309485SMikore.Li@Sun.COM error = sc->sc_newstate(ic, nstate, arg); 37319485SMikore.Li@Sun.COM return (error); 37329485SMikore.Li@Sun.COM } 37339485SMikore.Li@Sun.COM 37349485SMikore.Li@Sun.COM static void 37359485SMikore.Li@Sun.COM urtw_close_pipes(struct urtw_softc *sc) 37369485SMikore.Li@Sun.COM { 37379485SMikore.Li@Sun.COM usb_flags_t flags = USB_FLAGS_SLEEP; 37389485SMikore.Li@Sun.COM 37399485SMikore.Li@Sun.COM if (sc->sc_rxpipe != NULL) { 37409485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 37419485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0); 37429485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 37439485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0); 37449485SMikore.Li@Sun.COM sc->sc_rxpipe = NULL; 37459485SMikore.Li@Sun.COM } 37469485SMikore.Li@Sun.COM 37479485SMikore.Li@Sun.COM if (sc->sc_txpipe_low != NULL) { 37489485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 37499485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0); 37509485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 37519485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0); 37529485SMikore.Li@Sun.COM sc->sc_txpipe_low = NULL; 37539485SMikore.Li@Sun.COM } 37549485SMikore.Li@Sun.COM 37559485SMikore.Li@Sun.COM if (sc->sc_txpipe_normal != NULL) { 37569485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 37579485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0); 37589485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 37599485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0); 37609485SMikore.Li@Sun.COM sc->sc_txpipe_normal = NULL; 37619485SMikore.Li@Sun.COM } 37629485SMikore.Li@Sun.COM } 37639485SMikore.Li@Sun.COM 37649485SMikore.Li@Sun.COM static int 37659485SMikore.Li@Sun.COM urtw_open_pipes(struct urtw_softc *sc) 37669485SMikore.Li@Sun.COM { 37679485SMikore.Li@Sun.COM usb_ep_data_t *ep_node; 37689485SMikore.Li@Sun.COM usb_pipe_policy_t policy; 37699485SMikore.Li@Sun.COM int err; 3770*10364SMikore.Li@Sun.COM uint_t skip = 0; 37719485SMikore.Li@Sun.COM 37729485SMikore.Li@Sun.COM if (sc->sc_rxpipe || sc->sc_txpipe_low || sc->sc_txpipe_normal) 37739485SMikore.Li@Sun.COM return (USB_SUCCESS); 37749485SMikore.Li@Sun.COM 3775*10364SMikore.Li@Sun.COM if ((sc->sc_hwrev & URTW_HWREV_8187) == 0) { 3776*10364SMikore.Li@Sun.COM skip = 2; 3777*10364SMikore.Li@Sun.COM } 37789485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 3779*10364SMikore.Li@Sun.COM LOW_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 37809485SMikore.Li@Sun.COM 37819485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 37829485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT; 37839485SMikore.Li@Sun.COM 37849485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 37859485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 37869485SMikore.Li@Sun.COM &sc->sc_txpipe_low)) != USB_SUCCESS) { 37879485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 37889485SMikore.Li@Sun.COM "urtw_open_pipes(): %x low priority pipe open failed\n", 37899485SMikore.Li@Sun.COM err)); 37909485SMikore.Li@Sun.COM goto fail; 37919485SMikore.Li@Sun.COM } 37929485SMikore.Li@Sun.COM 37939485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 3794*10364SMikore.Li@Sun.COM NORMAL_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 37959485SMikore.Li@Sun.COM 37969485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 37979485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT; 37989485SMikore.Li@Sun.COM 37999485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 38009485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 38019485SMikore.Li@Sun.COM &sc->sc_txpipe_normal)) != USB_SUCCESS) { 38029485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 38039485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open high tx pipe\n", 38049485SMikore.Li@Sun.COM err)); 38059485SMikore.Li@Sun.COM goto fail; 38069485SMikore.Li@Sun.COM } 38079485SMikore.Li@Sun.COM 38089485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0, 38099485SMikore.Li@Sun.COM USB_EP_ATTR_BULK, USB_EP_DIR_IN); 38109485SMikore.Li@Sun.COM 38119485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 38129485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_RX_DATA_LIST_COUNT; 38139485SMikore.Li@Sun.COM 38149485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 38159485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 38169485SMikore.Li@Sun.COM &sc->sc_rxpipe)) != USB_SUCCESS) { 38179485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 38189485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open rx pipe\n", err)); 38199485SMikore.Li@Sun.COM goto fail; 38209485SMikore.Li@Sun.COM } 38219485SMikore.Li@Sun.COM 38229485SMikore.Li@Sun.COM return (USB_SUCCESS); 38239485SMikore.Li@Sun.COM 38249485SMikore.Li@Sun.COM fail: 38259485SMikore.Li@Sun.COM urtw_close_pipes(sc); 38269485SMikore.Li@Sun.COM return (USB_FAILURE); 38279485SMikore.Li@Sun.COM } 38289485SMikore.Li@Sun.COM 38299485SMikore.Li@Sun.COM static int 38309485SMikore.Li@Sun.COM urtw_tx_start(struct urtw_softc *sc, mblk_t *mp, int priority) 38319485SMikore.Li@Sun.COM { 38329485SMikore.Li@Sun.COM usb_bulk_req_t *req; 38339485SMikore.Li@Sun.COM int err; 38349485SMikore.Li@Sun.COM 38359485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP); 38369485SMikore.Li@Sun.COM if (req == NULL) { 38379485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 38389485SMikore.Li@Sun.COM "urtw_tx_start(): failed to allocate req")); 38399485SMikore.Li@Sun.COM freemsg(mp); 38409485SMikore.Li@Sun.COM return (-1); 38419485SMikore.Li@Sun.COM } 38429485SMikore.Li@Sun.COM 38439485SMikore.Li@Sun.COM req->bulk_len = MBLKL(mp); 38449485SMikore.Li@Sun.COM req->bulk_data = mp; 38459485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc; 38469485SMikore.Li@Sun.COM req->bulk_timeout = URTW_TX_TIMEOUT; 38479485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 38489485SMikore.Li@Sun.COM req->bulk_cb = (priority)?urtw_txeof_normal : urtw_txeof_low; 38499485SMikore.Li@Sun.COM req->bulk_exc_cb = (priority)?urtw_txeof_normal: urtw_txeof_low; 38509485SMikore.Li@Sun.COM req->bulk_completion_reason = 0; 38519485SMikore.Li@Sun.COM req->bulk_cb_flags = 0; 38529485SMikore.Li@Sun.COM 38539485SMikore.Li@Sun.COM if ((err = usb_pipe_bulk_xfer( 38549485SMikore.Li@Sun.COM (priority)?sc->sc_txpipe_normal:sc->sc_txpipe_low, req, 0)) 38559485SMikore.Li@Sun.COM != USB_SUCCESS) { 38569485SMikore.Li@Sun.COM sc->sc_ic.ic_stats.is_tx_failed++; 38579485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 38589485SMikore.Li@Sun.COM "urtw_tx_start: failed to do tx xfer, %d", err)); 38599485SMikore.Li@Sun.COM usb_free_bulk_req(req); 38609485SMikore.Li@Sun.COM return (EIO); 38619485SMikore.Li@Sun.COM } 38629485SMikore.Li@Sun.COM 38639485SMikore.Li@Sun.COM if (priority) { 38649485SMikore.Li@Sun.COM sc->sc_tx_normal_queued++; 38659485SMikore.Li@Sun.COM } else { 38669485SMikore.Li@Sun.COM sc->sc_tx_low_queued++; 38679485SMikore.Li@Sun.COM } 38689485SMikore.Li@Sun.COM 38699485SMikore.Li@Sun.COM return (0); 38709485SMikore.Li@Sun.COM } 38719485SMikore.Li@Sun.COM 38729485SMikore.Li@Sun.COM static int 38739485SMikore.Li@Sun.COM urtw_rx_start(struct urtw_softc *sc) 38749485SMikore.Li@Sun.COM { 38759485SMikore.Li@Sun.COM usb_bulk_req_t *req; 38769485SMikore.Li@Sun.COM int err; 38779485SMikore.Li@Sun.COM 38789485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, URTW_RXBUF_SIZE, USB_FLAGS_SLEEP); 38799485SMikore.Li@Sun.COM if (req == NULL) { 38809485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT, 38819485SMikore.Li@Sun.COM "urtw_rx_start(): failed to allocate req")); 38829485SMikore.Li@Sun.COM return (-1); 38839485SMikore.Li@Sun.COM } 38849485SMikore.Li@Sun.COM 38859485SMikore.Li@Sun.COM req->bulk_len = URTW_RXBUF_SIZE; 38869485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc; 38879485SMikore.Li@Sun.COM req->bulk_timeout = 0; 38889485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | 38899485SMikore.Li@Sun.COM USB_ATTRS_AUTOCLEARING; 38909485SMikore.Li@Sun.COM req->bulk_cb = urtw_rxeof; 38919485SMikore.Li@Sun.COM req->bulk_exc_cb = urtw_rxeof; 38929485SMikore.Li@Sun.COM req->bulk_completion_reason = 0; 38939485SMikore.Li@Sun.COM req->bulk_cb_flags = 0; 38949485SMikore.Li@Sun.COM 38959485SMikore.Li@Sun.COM err = usb_pipe_bulk_xfer(sc->sc_rxpipe, req, 0); 38969485SMikore.Li@Sun.COM 38979485SMikore.Li@Sun.COM if (err != USB_SUCCESS) { 38989485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT, 38999485SMikore.Li@Sun.COM "urtw_rx_start: failed to do rx xfer, %d", err)); 39009485SMikore.Li@Sun.COM usb_free_bulk_req(req); 39019485SMikore.Li@Sun.COM return (-1); 39029485SMikore.Li@Sun.COM } 39039485SMikore.Li@Sun.COM 39049485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock); 39059485SMikore.Li@Sun.COM sc->rx_queued++; 39069485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock); 39079485SMikore.Li@Sun.COM 39089485SMikore.Li@Sun.COM return (0); 39099485SMikore.Li@Sun.COM } 39109485SMikore.Li@Sun.COM 39119485SMikore.Li@Sun.COM static int 39129485SMikore.Li@Sun.COM urtw_disconnect(dev_info_t *devinfo) 39139485SMikore.Li@Sun.COM { 39149485SMikore.Li@Sun.COM struct urtw_softc *sc; 39159485SMikore.Li@Sun.COM 39169485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 39179485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG, 39189485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_offline()\n")); 39199485SMikore.Li@Sun.COM 39209485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) { 39219485SMikore.Li@Sun.COM urtw_stop(sc); 39229485SMikore.Li@Sun.COM URTW_LOCK(sc); 39239485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE; 39249485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 39259485SMikore.Li@Sun.COM } 3926*10364SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_HP; 3927*10364SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3928*10364SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 39299485SMikore.Li@Sun.COM return (DDI_SUCCESS); 39309485SMikore.Li@Sun.COM } 39319485SMikore.Li@Sun.COM 39329485SMikore.Li@Sun.COM static int 39339485SMikore.Li@Sun.COM urtw_reconnect(dev_info_t *devinfo) 39349485SMikore.Li@Sun.COM { 39359485SMikore.Li@Sun.COM struct urtw_softc *sc; 39369485SMikore.Li@Sun.COM int error = 0; 39379485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 39389485SMikore.Li@Sun.COM if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 39399485SMikore.Li@Sun.COM USB_CHK_ALL, NULL) != USB_SUCCESS) 39409485SMikore.Li@Sun.COM return (DDI_FAILURE); 39419485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG, (sc->sc_dev, CE_CONT, 39429485SMikore.Li@Sun.COM "urtw_online()\n")); 3943*10364SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_HP; 39449485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) { 3945*10364SMikore.Li@Sun.COM error = sc->urtw_init(sc); 39469485SMikore.Li@Sun.COM if (!error) { 39479485SMikore.Li@Sun.COM URTW_LOCK(sc); 39489485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE; 39499485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 39509485SMikore.Li@Sun.COM } 39519485SMikore.Li@Sun.COM } 3952*10364SMikore.Li@Sun.COM return (error? DDI_FAILURE: DDI_SUCCESS); 39539485SMikore.Li@Sun.COM } 39549485SMikore.Li@Sun.COM 39559485SMikore.Li@Sun.COM static mblk_t * 39569485SMikore.Li@Sun.COM urtw_m_tx(void *arg, mblk_t *mp) 39579485SMikore.Li@Sun.COM { 39589485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 39599485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 39609485SMikore.Li@Sun.COM mblk_t *next; 39619485SMikore.Li@Sun.COM 39629485SMikore.Li@Sun.COM if ((ic->ic_state != IEEE80211_S_RUN) || 39639485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) { 39649485SMikore.Li@Sun.COM freemsgchain(mp); 39659485SMikore.Li@Sun.COM return (NULL); 39669485SMikore.Li@Sun.COM } 39679485SMikore.Li@Sun.COM 39689485SMikore.Li@Sun.COM while (mp != NULL) { 39699485SMikore.Li@Sun.COM next = mp->b_next; 39709485SMikore.Li@Sun.COM mp->b_next = NULL; 39719485SMikore.Li@Sun.COM if (urtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) { 39729485SMikore.Li@Sun.COM mp->b_next = next; 39739485SMikore.Li@Sun.COM break; 39749485SMikore.Li@Sun.COM } 39759485SMikore.Li@Sun.COM mp = next; 39769485SMikore.Li@Sun.COM } 39779485SMikore.Li@Sun.COM return (mp); 39789485SMikore.Li@Sun.COM } 39799485SMikore.Li@Sun.COM 39809485SMikore.Li@Sun.COM static int 39819485SMikore.Li@Sun.COM urtw_m_start(void *arg) 39829485SMikore.Li@Sun.COM { 39839485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 39849485SMikore.Li@Sun.COM int error = 0; 39859485SMikore.Li@Sun.COM 39869485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 3987*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_m_start\n")); 3988*10364SMikore.Li@Sun.COM error = sc->urtw_init(sc); 39899485SMikore.Li@Sun.COM return (error); 39909485SMikore.Li@Sun.COM } 39919485SMikore.Li@Sun.COM 39929485SMikore.Li@Sun.COM static void 39939485SMikore.Li@Sun.COM urtw_m_stop(void *arg) 39949485SMikore.Li@Sun.COM { 39959485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 39969485SMikore.Li@Sun.COM 39979485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 39989485SMikore.Li@Sun.COM "urtw_m_stop()\n")); 39999485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 40009485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 40019485SMikore.Li@Sun.COM (void) urtw_stop(sc); 40029485SMikore.Li@Sun.COM } 40039485SMikore.Li@Sun.COM 40049485SMikore.Li@Sun.COM /*ARGSUSED*/ 40059485SMikore.Li@Sun.COM static int 40069485SMikore.Li@Sun.COM urtw_m_unicst(void *arg, const uint8_t *macaddr) 40079485SMikore.Li@Sun.COM { 40089485SMikore.Li@Sun.COM return (ENOTSUP); 40099485SMikore.Li@Sun.COM } 40109485SMikore.Li@Sun.COM 40119485SMikore.Li@Sun.COM /*ARGSUSED*/ 40129485SMikore.Li@Sun.COM static int 40139485SMikore.Li@Sun.COM urtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 40149485SMikore.Li@Sun.COM { 40159485SMikore.Li@Sun.COM return (ENOTSUP); 40169485SMikore.Li@Sun.COM } 40179485SMikore.Li@Sun.COM 40189485SMikore.Li@Sun.COM /*ARGSUSED*/ 40199485SMikore.Li@Sun.COM static int 40209485SMikore.Li@Sun.COM urtw_m_promisc(void *arg, boolean_t on) 40219485SMikore.Li@Sun.COM { 40229485SMikore.Li@Sun.COM return (0); 40239485SMikore.Li@Sun.COM } 40249485SMikore.Li@Sun.COM 40259485SMikore.Li@Sun.COM static int 4026*10364SMikore.Li@Sun.COM urtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 4027*10364SMikore.Li@Sun.COM uint_t pr_flags, uint_t wldp_length, void *wldp_buf, uint_t *perm) 4028*10364SMikore.Li@Sun.COM { 4029*10364SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 4030*10364SMikore.Li@Sun.COM int err = 0; 4031*10364SMikore.Li@Sun.COM 4032*10364SMikore.Li@Sun.COM err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 4033*10364SMikore.Li@Sun.COM pr_flags, wldp_length, wldp_buf, perm); 4034*10364SMikore.Li@Sun.COM return (err); 4035*10364SMikore.Li@Sun.COM } 4036*10364SMikore.Li@Sun.COM 4037*10364SMikore.Li@Sun.COM static int 40389485SMikore.Li@Sun.COM urtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 40399485SMikore.Li@Sun.COM uint_t wldp_length, const void *wldp_buf) 40409485SMikore.Li@Sun.COM { 40419485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 40429485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 40439485SMikore.Li@Sun.COM int err; 40449485SMikore.Li@Sun.COM 40459485SMikore.Li@Sun.COM err = ieee80211_setprop(ic, pr_name, wldp_pr_num, 40469485SMikore.Li@Sun.COM wldp_length, wldp_buf); 4047*10364SMikore.Li@Sun.COM URTW_LOCK(sc); 40489485SMikore.Li@Sun.COM if (err == ENETRESET) { 4049*10364SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) { 4050*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 4051*10364SMikore.Li@Sun.COM err = sc->urtw_init(sc); 4052*10364SMikore.Li@Sun.COM if (err) { 4053*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 4054*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 4055*10364SMikore.Li@Sun.COM "urtw: setprop failed\n")); 4056*10364SMikore.Li@Sun.COM return (err); 4057*10364SMikore.Li@Sun.COM } 40589485SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 4059*10364SMikore.Li@Sun.COM URTW_LOCK(sc); 40609485SMikore.Li@Sun.COM } 40619485SMikore.Li@Sun.COM err = 0; 40629485SMikore.Li@Sun.COM } 4063*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 40649485SMikore.Li@Sun.COM return (err); 40659485SMikore.Li@Sun.COM } 40669485SMikore.Li@Sun.COM 40679485SMikore.Li@Sun.COM static void 40689485SMikore.Li@Sun.COM urtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 40699485SMikore.Li@Sun.COM { 40709485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 40719485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 40729485SMikore.Li@Sun.COM int err; 40739485SMikore.Li@Sun.COM 40749485SMikore.Li@Sun.COM err = ieee80211_ioctl(ic, wq, mp); 4075*10364SMikore.Li@Sun.COM URTW_LOCK(sc); 40769485SMikore.Li@Sun.COM if (err == ENETRESET) { 4077*10364SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) { 4078*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 4079*10364SMikore.Li@Sun.COM err = sc->urtw_init(sc); 4080*10364SMikore.Li@Sun.COM if (err) { 4081*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 4082*10364SMikore.Li@Sun.COM (sc->sc_dev, 4083*10364SMikore.Li@Sun.COM CE_CONT, "urtw: dev init failed\n")); 4084*10364SMikore.Li@Sun.COM return; 4085*10364SMikore.Li@Sun.COM } 4086*10364SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 4087*10364SMikore.Li@Sun.COM URTW_LOCK(sc); 40889485SMikore.Li@Sun.COM } 40899485SMikore.Li@Sun.COM } 4090*10364SMikore.Li@Sun.COM URTW_UNLOCK(sc); 40919485SMikore.Li@Sun.COM } 40929485SMikore.Li@Sun.COM 40939485SMikore.Li@Sun.COM static int 40949485SMikore.Li@Sun.COM urtw_m_stat(void *arg, uint_t stat, uint64_t *val) 40959485SMikore.Li@Sun.COM { 40969485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 40979485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic; 40989485SMikore.Li@Sun.COM ieee80211_node_t *ni = 0; 40999485SMikore.Li@Sun.COM struct ieee80211_rateset *rs = 0; 41009485SMikore.Li@Sun.COM 41019485SMikore.Li@Sun.COM URTW_LOCK(sc); 41029485SMikore.Li@Sun.COM switch (stat) { 41039485SMikore.Li@Sun.COM case MAC_STAT_IFSPEED: 41049485SMikore.Li@Sun.COM ni = ic->ic_bss; 41059485SMikore.Li@Sun.COM rs = &ni->in_rates; 41069485SMikore.Li@Sun.COM *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 41079485SMikore.Li@Sun.COM (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 41089485SMikore.Li@Sun.COM : ic->ic_fixed_rate) / 2 * 1000000; 41099485SMikore.Li@Sun.COM break; 41109485SMikore.Li@Sun.COM case MAC_STAT_NOXMTBUF: 41119485SMikore.Li@Sun.COM *val = sc->sc_tx_nobuf; 41129485SMikore.Li@Sun.COM break; 41139485SMikore.Li@Sun.COM case MAC_STAT_NORCVBUF: 41149485SMikore.Li@Sun.COM *val = sc->sc_rx_nobuf; 41159485SMikore.Li@Sun.COM break; 41169485SMikore.Li@Sun.COM case MAC_STAT_IERRORS: 41179485SMikore.Li@Sun.COM *val = sc->sc_rx_err; 41189485SMikore.Li@Sun.COM break; 41199485SMikore.Li@Sun.COM case MAC_STAT_RBYTES: 41209485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_bytes; 41219485SMikore.Li@Sun.COM break; 41229485SMikore.Li@Sun.COM case MAC_STAT_IPACKETS: 41239485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_frags; 41249485SMikore.Li@Sun.COM break; 41259485SMikore.Li@Sun.COM case MAC_STAT_OBYTES: 41269485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_bytes; 41279485SMikore.Li@Sun.COM break; 41289485SMikore.Li@Sun.COM case MAC_STAT_OPACKETS: 41299485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_frags; 41309485SMikore.Li@Sun.COM break; 41319485SMikore.Li@Sun.COM case MAC_STAT_OERRORS: 41329485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_failed; 41339485SMikore.Li@Sun.COM break; 41349485SMikore.Li@Sun.COM case WIFI_STAT_TX_FRAGS: 41359485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_TX: 41369485SMikore.Li@Sun.COM case WIFI_STAT_TX_FAILED: 41379485SMikore.Li@Sun.COM case WIFI_STAT_TX_RETRANS: 41389485SMikore.Li@Sun.COM case WIFI_STAT_RTS_SUCCESS: 41399485SMikore.Li@Sun.COM case WIFI_STAT_RTS_FAILURE: 41409485SMikore.Li@Sun.COM case WIFI_STAT_ACK_FAILURE: 41419485SMikore.Li@Sun.COM case WIFI_STAT_RX_FRAGS: 41429485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_RX: 41439485SMikore.Li@Sun.COM case WIFI_STAT_FCS_ERRORS: 41449485SMikore.Li@Sun.COM case WIFI_STAT_WEP_ERRORS: 41459485SMikore.Li@Sun.COM case WIFI_STAT_RX_DUPS: 41469485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 41479485SMikore.Li@Sun.COM return (ieee80211_stat(ic, stat, val)); 41489485SMikore.Li@Sun.COM default: 41499485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 41509485SMikore.Li@Sun.COM return (ENOTSUP); 41519485SMikore.Li@Sun.COM } 41529485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 41539485SMikore.Li@Sun.COM 41549485SMikore.Li@Sun.COM return (0); 41559485SMikore.Li@Sun.COM } 41569485SMikore.Li@Sun.COM 41579485SMikore.Li@Sun.COM static void 41589485SMikore.Li@Sun.COM urtw_watchdog(void *arg) 41599485SMikore.Li@Sun.COM { 41609485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 41619485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 41629485SMikore.Li@Sun.COM 41639485SMikore.Li@Sun.COM ieee80211_stop_watchdog(ic); 41649485SMikore.Li@Sun.COM 41659485SMikore.Li@Sun.COM URTW_LOCK(sc); 41669485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) { 41679485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 41689485SMikore.Li@Sun.COM return; 41699485SMikore.Li@Sun.COM } 41709485SMikore.Li@Sun.COM 41719485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 41729485SMikore.Li@Sun.COM switch (ic->ic_state) { 41739485SMikore.Li@Sun.COM case IEEE80211_S_AUTH: 41749485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC: 4175*10364SMikore.Li@Sun.COM if (ic->ic_bss->in_fails > 0) { 41769485SMikore.Li@Sun.COM ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 4177*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 4178*10364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 4179*10364SMikore.Li@Sun.COM "urtw: watchdog begin\n")); 4180*10364SMikore.Li@Sun.COM } else 41819485SMikore.Li@Sun.COM ieee80211_watchdog(ic); 41829485SMikore.Li@Sun.COM break; 41839485SMikore.Li@Sun.COM } 41849485SMikore.Li@Sun.COM } 41859485SMikore.Li@Sun.COM 41869485SMikore.Li@Sun.COM 41879485SMikore.Li@Sun.COM static int 41889485SMikore.Li@Sun.COM urtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 41899485SMikore.Li@Sun.COM { 41909485SMikore.Li@Sun.COM struct urtw_softc *sc; 41919485SMikore.Li@Sun.COM struct ieee80211com *ic; 41929485SMikore.Li@Sun.COM int error, i, instance; 41939485SMikore.Li@Sun.COM uint32_t data = 0; 4194*10364SMikore.Li@Sun.COM uint8_t data8 = 0; 41959485SMikore.Li@Sun.COM char strbuf[32]; 41969485SMikore.Li@Sun.COM wifi_data_t wd = { 0 }; 41979485SMikore.Li@Sun.COM mac_register_t *macp; 4198*10364SMikore.Li@Sun.COM struct urtw_type *e = 0; 4199*10364SMikore.Li@Sun.COM char *urtw_name = NULL; 42009485SMikore.Li@Sun.COM 42019485SMikore.Li@Sun.COM switch (cmd) { 42029485SMikore.Li@Sun.COM case DDI_ATTACH: 42039485SMikore.Li@Sun.COM break; 42049485SMikore.Li@Sun.COM case DDI_RESUME: 42059485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, 42069485SMikore.Li@Sun.COM ddi_get_instance(devinfo)); 42079485SMikore.Li@Sun.COM ASSERT(sc != NULL); 42089485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 42099485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: resume\n")); 42109485SMikore.Li@Sun.COM URTW_LOCK(sc); 42119485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_SUSPEND; 42129485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 42139485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) { 4214*10364SMikore.Li@Sun.COM error = sc->urtw_init(sc); 42159485SMikore.Li@Sun.COM if (error == 0) { 42169485SMikore.Li@Sun.COM URTW_LOCK(sc); 42179485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE; 42189485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 42199485SMikore.Li@Sun.COM } 42209485SMikore.Li@Sun.COM } 42219485SMikore.Li@Sun.COM return (DDI_SUCCESS); 42229485SMikore.Li@Sun.COM default: 42239485SMikore.Li@Sun.COM return (DDI_FAILURE); 42249485SMikore.Li@Sun.COM } 42259485SMikore.Li@Sun.COM 42269485SMikore.Li@Sun.COM instance = ddi_get_instance(devinfo); 42279485SMikore.Li@Sun.COM 42289485SMikore.Li@Sun.COM if (ddi_soft_state_zalloc(urtw_soft_state_p, instance) != DDI_SUCCESS) { 42299485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach:unable to alloc soft_state_p\n"); 42309485SMikore.Li@Sun.COM return (DDI_FAILURE); 42319485SMikore.Li@Sun.COM } 42329485SMikore.Li@Sun.COM 42339485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, instance); 42349485SMikore.Li@Sun.COM ic = (ieee80211com_t *)&sc->sc_ic; 42359485SMikore.Li@Sun.COM sc->sc_dev = devinfo; 42369485SMikore.Li@Sun.COM 42379485SMikore.Li@Sun.COM if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) { 42389485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: usb_client_attach failed\n"); 42399485SMikore.Li@Sun.COM goto fail1; 42409485SMikore.Li@Sun.COM } 42419485SMikore.Li@Sun.COM 42429485SMikore.Li@Sun.COM if (usb_get_dev_data(devinfo, &sc->sc_udev, 42439485SMikore.Li@Sun.COM USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) { 42449485SMikore.Li@Sun.COM sc->sc_udev = NULL; 42459485SMikore.Li@Sun.COM goto fail2; 42469485SMikore.Li@Sun.COM } 42479485SMikore.Li@Sun.COM 42489485SMikore.Li@Sun.COM mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 42499485SMikore.Li@Sun.COM mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL); 42509485SMikore.Li@Sun.COM mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL); 42519485SMikore.Li@Sun.COM mutex_init(&sc->sc_ledlock, NULL, MUTEX_DRIVER, NULL); 42529485SMikore.Li@Sun.COM 4253*10364SMikore.Li@Sun.COM e = urtw_lookup(sc->sc_udev->dev_descr->idVendor, 4254*10364SMikore.Li@Sun.COM sc->sc_udev->dev_descr->idProduct); 4255*10364SMikore.Li@Sun.COM if (e == NULL) { 4256*10364SMikore.Li@Sun.COM cmn_err(CE_WARN, "(urtw) unknown device\n"); 4257*10364SMikore.Li@Sun.COM goto fail2; 4258*10364SMikore.Li@Sun.COM } 4259*10364SMikore.Li@Sun.COM sc->sc_hwrev = e->rev; 4260*10364SMikore.Li@Sun.COM 4261*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 4262*10364SMikore.Li@Sun.COM (void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0); 4263*10364SMikore.Li@Sun.COM data &= URTW_TX_HWREV_MASK; 4264*10364SMikore.Li@Sun.COM switch (data) { 4265*10364SMikore.Li@Sun.COM case URTW_TX_HWREV_8187_D: 4266*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187_D; 4267*10364SMikore.Li@Sun.COM urtw_name = "RTL8187 rev. D"; 4268*10364SMikore.Li@Sun.COM break; 4269*10364SMikore.Li@Sun.COM case URTW_TX_HWREV_8187B_D: 4270*10364SMikore.Li@Sun.COM /* 4271*10364SMikore.Li@Sun.COM * Detect Realtek RTL8187B devices that use 4272*10364SMikore.Li@Sun.COM * USB IDs of RTL8187. 4273*10364SMikore.Li@Sun.COM */ 4274*10364SMikore.Li@Sun.COM sc->sc_hwrev = URTW_HWREV_8187B | URTW_HWREV_8187B_B; 4275*10364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B (early)"; 4276*10364SMikore.Li@Sun.COM break; 4277*10364SMikore.Li@Sun.COM default: 4278*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187_B; 4279*10364SMikore.Li@Sun.COM urtw_name = "RTL8187 rev. B (default)"; 4280*10364SMikore.Li@Sun.COM break; 4281*10364SMikore.Li@Sun.COM } 4282*10364SMikore.Li@Sun.COM } else { 4283*10364SMikore.Li@Sun.COM /* RTL8187B hwrev register. */ 4284*10364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_8187B_HWREV, &data8, 0); 4285*10364SMikore.Li@Sun.COM switch (data8) { 4286*10364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_B: 4287*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_B; 4288*10364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B"; 4289*10364SMikore.Li@Sun.COM break; 4290*10364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_D: 4291*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_D; 4292*10364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. D"; 4293*10364SMikore.Li@Sun.COM break; 4294*10364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_E: 4295*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_E; 4296*10364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. E"; 4297*10364SMikore.Li@Sun.COM break; 4298*10364SMikore.Li@Sun.COM default: 4299*10364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_B; 4300*10364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B (default)"; 4301*10364SMikore.Li@Sun.COM break; 4302*10364SMikore.Li@Sun.COM } 4303*10364SMikore.Li@Sun.COM } 4304*10364SMikore.Li@Sun.COM 4305*10364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 4306*10364SMikore.Li@Sun.COM "urtw_attach: actual device is %s\n", urtw_name)); 4307*10364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) { 4308*10364SMikore.Li@Sun.COM sc->urtw_init = urtw_8187_init; 4309*10364SMikore.Li@Sun.COM } else { 4310*10364SMikore.Li@Sun.COM sc->urtw_init = urtw_8187b_init; 4311*10364SMikore.Li@Sun.COM } 4312*10364SMikore.Li@Sun.COM 4313*10364SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data, 0)) 43149485SMikore.Li@Sun.COM goto fail3; 43159485SMikore.Li@Sun.COM sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 : 43169485SMikore.Li@Sun.COM URTW_EEPROM_93C46; 43179485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56) 43189485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 43199485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C56\n")); 43209485SMikore.Li@Sun.COM else 43219485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 43229485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C46\n")); 43239485SMikore.Li@Sun.COM error = urtw_get_rfchip(sc); 43249485SMikore.Li@Sun.COM if (error != 0) 43259485SMikore.Li@Sun.COM goto fail3; 43269485SMikore.Li@Sun.COM error = urtw_get_macaddr(sc); 43279485SMikore.Li@Sun.COM if (error != 0) 43289485SMikore.Li@Sun.COM goto fail3; 43299485SMikore.Li@Sun.COM error = urtw_get_txpwr(sc); 43309485SMikore.Li@Sun.COM if (error != 0) 43319485SMikore.Li@Sun.COM goto fail3; 43329485SMikore.Li@Sun.COM error = urtw_led_init(sc); /* XXX incompleted */ 43339485SMikore.Li@Sun.COM if (error != 0) 43349485SMikore.Li@Sun.COM goto fail3; 43359485SMikore.Li@Sun.COM 43369485SMikore.Li@Sun.COM sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY; 43379485SMikore.Li@Sun.COM sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY; 43389485SMikore.Li@Sun.COM sc->sc_currate = 3; 43399485SMikore.Li@Sun.COM /* XXX for what? */ 43409485SMikore.Li@Sun.COM sc->sc_preamble_mode = 2; 43419485SMikore.Li@Sun.COM 43429485SMikore.Li@Sun.COM ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 43439485SMikore.Li@Sun.COM ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 43449485SMikore.Li@Sun.COM ic->ic_state = IEEE80211_S_INIT; 43459485SMikore.Li@Sun.COM 43469485SMikore.Li@Sun.COM ic->ic_maxrssi = 95; 43479485SMikore.Li@Sun.COM ic->ic_xmit = urtw_send; 43489485SMikore.Li@Sun.COM 43499485SMikore.Li@Sun.COM ic->ic_caps |= IEEE80211_C_WPA | /* Support WPA/WPA2 */ 43509485SMikore.Li@Sun.COM IEEE80211_C_TXPMGT | /* tx power management */ 43519485SMikore.Li@Sun.COM IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 43529485SMikore.Li@Sun.COM IEEE80211_C_SHSLOT; /* short slot time supported */ 43539485SMikore.Li@Sun.COM /* set supported .11b and .11g rates */ 43549485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11B] = urtw_rateset_11b; 43559485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11G] = urtw_rateset_11g; 43569485SMikore.Li@Sun.COM 43579485SMikore.Li@Sun.COM /* set supported .11b and .11g channels (1 through 11) */ 43589485SMikore.Li@Sun.COM for (i = 1; i <= 11; i++) { 43599485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_freq = 43609485SMikore.Li@Sun.COM ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 43619485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_flags = 43629485SMikore.Li@Sun.COM IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN | 43639485SMikore.Li@Sun.COM IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM; 43649485SMikore.Li@Sun.COM } 43659485SMikore.Li@Sun.COM 43669485SMikore.Li@Sun.COM ieee80211_attach(ic); 4367*10364SMikore.Li@Sun.COM ic->ic_ibss_chan = &ic->ic_sup_channels[1]; 4368*10364SMikore.Li@Sun.COM ic->ic_curchan = ic->ic_ibss_chan; 43699485SMikore.Li@Sun.COM 43709485SMikore.Li@Sun.COM /* register WPA door */ 43719485SMikore.Li@Sun.COM ieee80211_register_door(ic, ddi_driver_name(devinfo), 43729485SMikore.Li@Sun.COM ddi_get_instance(devinfo)); 43739485SMikore.Li@Sun.COM 43749485SMikore.Li@Sun.COM /* override state transition machine */ 43759485SMikore.Li@Sun.COM sc->sc_newstate = ic->ic_newstate; 43769485SMikore.Li@Sun.COM ic->ic_newstate = urtw_newstate; 43779485SMikore.Li@Sun.COM ic->ic_watchdog = urtw_watchdog; 43789485SMikore.Li@Sun.COM ieee80211_media_init(ic); 43799485SMikore.Li@Sun.COM ic->ic_def_txkey = 0; 43809485SMikore.Li@Sun.COM 4381*10364SMikore.Li@Sun.COM sc->dwelltime = 250; 43829485SMikore.Li@Sun.COM sc->sc_flags = 0; 43839485SMikore.Li@Sun.COM 43849485SMikore.Li@Sun.COM /* 43859485SMikore.Li@Sun.COM * Provide initial settings for the WiFi plugin; whenever this 43869485SMikore.Li@Sun.COM * information changes, we need to call mac_plugindata_update() 43879485SMikore.Li@Sun.COM */ 43889485SMikore.Li@Sun.COM wd.wd_opmode = ic->ic_opmode; 43899485SMikore.Li@Sun.COM wd.wd_secalloc = WIFI_SEC_NONE; 43909485SMikore.Li@Sun.COM IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 43919485SMikore.Li@Sun.COM 43929485SMikore.Li@Sun.COM if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 43939485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT, 43949485SMikore.Li@Sun.COM "MAC version alloc failed\n")); 43959485SMikore.Li@Sun.COM goto fail4; 43969485SMikore.Li@Sun.COM } 43979485SMikore.Li@Sun.COM 43989485SMikore.Li@Sun.COM macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 43999485SMikore.Li@Sun.COM macp->m_driver = sc; 44009485SMikore.Li@Sun.COM macp->m_dip = devinfo; 44019485SMikore.Li@Sun.COM macp->m_src_addr = ic->ic_macaddr; 44029485SMikore.Li@Sun.COM macp->m_callbacks = &urtw_m_callbacks; 44039485SMikore.Li@Sun.COM macp->m_min_sdu = 0; 44049485SMikore.Li@Sun.COM macp->m_max_sdu = IEEE80211_MTU; 44059485SMikore.Li@Sun.COM macp->m_pdata = &wd; 44069485SMikore.Li@Sun.COM macp->m_pdata_size = sizeof (wd); 44079485SMikore.Li@Sun.COM 44089485SMikore.Li@Sun.COM error = mac_register(macp, &ic->ic_mach); 44099485SMikore.Li@Sun.COM mac_free(macp); 44109485SMikore.Li@Sun.COM if (error != 0) { 44119485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: mac_register() err %x\n", error); 44129485SMikore.Li@Sun.COM goto fail4; 44139485SMikore.Li@Sun.COM } 44149485SMikore.Li@Sun.COM 44159485SMikore.Li@Sun.COM if (usb_register_hotplug_cbs(devinfo, urtw_disconnect, 44169485SMikore.Li@Sun.COM urtw_reconnect) != USB_SUCCESS) { 44179485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: failed to register events"); 44189485SMikore.Li@Sun.COM goto fail5; 44199485SMikore.Li@Sun.COM } 44209485SMikore.Li@Sun.COM 44219485SMikore.Li@Sun.COM /* 44229485SMikore.Li@Sun.COM * Create minor node of type DDI_NT_NET_WIFI 44239485SMikore.Li@Sun.COM */ 44249485SMikore.Li@Sun.COM (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 44259485SMikore.Li@Sun.COM "urtw", instance); 44269485SMikore.Li@Sun.COM error = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 44279485SMikore.Li@Sun.COM instance + 1, DDI_NT_NET_WIFI, 0); 44289485SMikore.Li@Sun.COM 44299485SMikore.Li@Sun.COM if (error != DDI_SUCCESS) 44309485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw: ddi_create_minor_node() failed\n"); 44319485SMikore.Li@Sun.COM /* 44329485SMikore.Li@Sun.COM * Notify link is down now 44339485SMikore.Li@Sun.COM */ 44349485SMikore.Li@Sun.COM mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 44359485SMikore.Li@Sun.COM 44369485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT, 44379485SMikore.Li@Sun.COM "urtw_attach: successfully.\n")); 44389485SMikore.Li@Sun.COM return (DDI_SUCCESS); 44399485SMikore.Li@Sun.COM fail5: 4440*10364SMikore.Li@Sun.COM (void) mac_disable(ic->ic_mach); 44419485SMikore.Li@Sun.COM (void) mac_unregister(ic->ic_mach); 44429485SMikore.Li@Sun.COM fail4: 44439485SMikore.Li@Sun.COM ieee80211_detach(ic); 44449485SMikore.Li@Sun.COM fail3: 44459485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock); 44469485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock); 44479485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock); 44489485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock); 44499485SMikore.Li@Sun.COM fail2: 44509485SMikore.Li@Sun.COM usb_client_detach(sc->sc_dev, sc->sc_udev); 44519485SMikore.Li@Sun.COM fail1: 44529485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo)); 44539485SMikore.Li@Sun.COM 44549485SMikore.Li@Sun.COM return (DDI_FAILURE); 44559485SMikore.Li@Sun.COM } 44569485SMikore.Li@Sun.COM 44579485SMikore.Li@Sun.COM static int 44589485SMikore.Li@Sun.COM urtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 44599485SMikore.Li@Sun.COM { 44609485SMikore.Li@Sun.COM struct urtw_softc *sc; 44619485SMikore.Li@Sun.COM 44629485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 44639485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, 44649485SMikore.Li@Sun.COM CE_CONT, "urtw_detach()\n")); 44659485SMikore.Li@Sun.COM 44669485SMikore.Li@Sun.COM switch (cmd) { 44679485SMikore.Li@Sun.COM case DDI_DETACH: 44689485SMikore.Li@Sun.COM break; 44699485SMikore.Li@Sun.COM case DDI_SUSPEND: 44709485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, 44719485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: suspend\n")); 44729485SMikore.Li@Sun.COM 44739485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 44749485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 44759485SMikore.Li@Sun.COM 44769485SMikore.Li@Sun.COM URTW_LOCK(sc); 44779485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_SUSPEND; 44789485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 44799485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) { 44809485SMikore.Li@Sun.COM urtw_stop(sc); 44819485SMikore.Li@Sun.COM URTW_LOCK(sc); 44829485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE; 44839485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 44849485SMikore.Li@Sun.COM } 44859485SMikore.Li@Sun.COM return (DDI_SUCCESS); 44869485SMikore.Li@Sun.COM default: 44879485SMikore.Li@Sun.COM return (DDI_FAILURE); 44889485SMikore.Li@Sun.COM } 44899485SMikore.Li@Sun.COM 44909485SMikore.Li@Sun.COM if (mac_disable(sc->sc_ic.ic_mach) != 0) 44919485SMikore.Li@Sun.COM return (DDI_FAILURE); 44929485SMikore.Li@Sun.COM urtw_stop(sc); 44939485SMikore.Li@Sun.COM /* 44949485SMikore.Li@Sun.COM * Unregister from the MAC layer subsystem 44959485SMikore.Li@Sun.COM */ 44969485SMikore.Li@Sun.COM (void) mac_unregister(sc->sc_ic.ic_mach); 44979485SMikore.Li@Sun.COM 44989485SMikore.Li@Sun.COM ieee80211_detach(&sc->sc_ic); 44999485SMikore.Li@Sun.COM usb_unregister_hotplug_cbs(devinfo); 45009485SMikore.Li@Sun.COM usb_client_detach(devinfo, sc->sc_udev); 45019485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock); 45029485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock); 45039485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock); 45049485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock); 45059485SMikore.Li@Sun.COM sc->sc_udev = NULL; 45069485SMikore.Li@Sun.COM 45079485SMikore.Li@Sun.COM ddi_remove_minor_node(devinfo, NULL); 45089485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo)); 45099485SMikore.Li@Sun.COM 45109485SMikore.Li@Sun.COM return (DDI_SUCCESS); 45119485SMikore.Li@Sun.COM } 45129485SMikore.Li@Sun.COM 45139485SMikore.Li@Sun.COM int 45149485SMikore.Li@Sun.COM _info(struct modinfo *modinfop) 45159485SMikore.Li@Sun.COM { 45169485SMikore.Li@Sun.COM return (mod_info(&modlinkage, modinfop)); 45179485SMikore.Li@Sun.COM } 45189485SMikore.Li@Sun.COM 45199485SMikore.Li@Sun.COM int 45209485SMikore.Li@Sun.COM _init(void) 45219485SMikore.Li@Sun.COM { 45229485SMikore.Li@Sun.COM int status; 45239485SMikore.Li@Sun.COM 45249485SMikore.Li@Sun.COM status = ddi_soft_state_init(&urtw_soft_state_p, 45259485SMikore.Li@Sun.COM sizeof (struct urtw_softc), 1); 45269485SMikore.Li@Sun.COM if (status != 0) 45279485SMikore.Li@Sun.COM return (status); 45289485SMikore.Li@Sun.COM 45299485SMikore.Li@Sun.COM mac_init_ops(&urtw_dev_ops, "urtw"); 45309485SMikore.Li@Sun.COM status = mod_install(&modlinkage); 45319485SMikore.Li@Sun.COM if (status != 0) { 45329485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops); 45339485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p); 45349485SMikore.Li@Sun.COM } 45359485SMikore.Li@Sun.COM return (status); 45369485SMikore.Li@Sun.COM } 45379485SMikore.Li@Sun.COM 45389485SMikore.Li@Sun.COM int 45399485SMikore.Li@Sun.COM _fini(void) 45409485SMikore.Li@Sun.COM { 45419485SMikore.Li@Sun.COM int status; 45429485SMikore.Li@Sun.COM 45439485SMikore.Li@Sun.COM status = mod_remove(&modlinkage); 45449485SMikore.Li@Sun.COM if (status == 0) { 45459485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops); 45469485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p); 45479485SMikore.Li@Sun.COM } 45489485SMikore.Li@Sun.COM return (status); 45499485SMikore.Li@Sun.COM } 4550