1*9485SMikore.Li@Sun.COM /* 2*9485SMikore.Li@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3*9485SMikore.Li@Sun.COM * Use is subject to license terms. 4*9485SMikore.Li@Sun.COM */ 5*9485SMikore.Li@Sun.COM 6*9485SMikore.Li@Sun.COM /* 7*9485SMikore.Li@Sun.COM * Copyright (c) 2008 Weongyo Jeong 8*9485SMikore.Li@Sun.COM * All rights reserved. 9*9485SMikore.Li@Sun.COM * 10*9485SMikore.Li@Sun.COM * Redistribution and use in source and binary forms, with or without 11*9485SMikore.Li@Sun.COM * modification, are permitted provided that the following conditions 12*9485SMikore.Li@Sun.COM * are met: 13*9485SMikore.Li@Sun.COM * 1. Redistributions of source code must retain the above copyright 14*9485SMikore.Li@Sun.COM * notice, this list of conditions and the following disclaimer, 15*9485SMikore.Li@Sun.COM * without modification. 16*9485SMikore.Li@Sun.COM * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17*9485SMikore.Li@Sun.COM * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 18*9485SMikore.Li@Sun.COM * redistribution must be conditioned upon including a substantially 19*9485SMikore.Li@Sun.COM * similar Disclaimer requirement for further binary redistribution. 20*9485SMikore.Li@Sun.COM * 21*9485SMikore.Li@Sun.COM * NO WARRANTY 22*9485SMikore.Li@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23*9485SMikore.Li@Sun.COM * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24*9485SMikore.Li@Sun.COM * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 25*9485SMikore.Li@Sun.COM * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26*9485SMikore.Li@Sun.COM * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 27*9485SMikore.Li@Sun.COM * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28*9485SMikore.Li@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29*9485SMikore.Li@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 30*9485SMikore.Li@Sun.COM * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31*9485SMikore.Li@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32*9485SMikore.Li@Sun.COM * THE POSSIBILITY OF SUCH DAMAGES. 33*9485SMikore.Li@Sun.COM */ 34*9485SMikore.Li@Sun.COM #include <sys/sysmacros.h> 35*9485SMikore.Li@Sun.COM #include <sys/strsubr.h> 36*9485SMikore.Li@Sun.COM #include <sys/strsun.h> 37*9485SMikore.Li@Sun.COM #include <sys/mac_provider.h> 38*9485SMikore.Li@Sun.COM #include <sys/mac_wifi.h> 39*9485SMikore.Li@Sun.COM #include <sys/net80211.h> 40*9485SMikore.Li@Sun.COM #define USBDRV_MAJOR_VER 2 41*9485SMikore.Li@Sun.COM #define USBDRV_MINOR_VER 0 42*9485SMikore.Li@Sun.COM #include <sys/usb/usba.h> 43*9485SMikore.Li@Sun.COM #include <sys/usb/usba/usba_types.h> 44*9485SMikore.Li@Sun.COM 45*9485SMikore.Li@Sun.COM #include "urtw_reg.h" 46*9485SMikore.Li@Sun.COM #include "urtw_var.h" 47*9485SMikore.Li@Sun.COM 48*9485SMikore.Li@Sun.COM static void *urtw_soft_state_p = NULL; 49*9485SMikore.Li@Sun.COM 50*9485SMikore.Li@Sun.COM #define URTW_TXBUF_SIZE (IEEE80211_MAX_LEN) 51*9485SMikore.Li@Sun.COM #define URTW_RXBUF_SIZE (URTW_TXBUF_SIZE) 52*9485SMikore.Li@Sun.COM /* 53*9485SMikore.Li@Sun.COM * device operations 54*9485SMikore.Li@Sun.COM */ 55*9485SMikore.Li@Sun.COM static int urtw_attach(dev_info_t *, ddi_attach_cmd_t); 56*9485SMikore.Li@Sun.COM static int urtw_detach(dev_info_t *, ddi_detach_cmd_t); 57*9485SMikore.Li@Sun.COM 58*9485SMikore.Li@Sun.COM /* 59*9485SMikore.Li@Sun.COM * Module Loading Data & Entry Points 60*9485SMikore.Li@Sun.COM */ 61*9485SMikore.Li@Sun.COM DDI_DEFINE_STREAM_OPS(urtw_dev_ops, nulldev, nulldev, urtw_attach, 62*9485SMikore.Li@Sun.COM urtw_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 63*9485SMikore.Li@Sun.COM 64*9485SMikore.Li@Sun.COM static struct modldrv urtw_modldrv = { 65*9485SMikore.Li@Sun.COM &mod_driverops, /* Type of module. This one is a driver */ 66*9485SMikore.Li@Sun.COM "RTL8187L driver v1.1", /* short description */ 67*9485SMikore.Li@Sun.COM &urtw_dev_ops /* driver specific ops */ 68*9485SMikore.Li@Sun.COM }; 69*9485SMikore.Li@Sun.COM 70*9485SMikore.Li@Sun.COM static struct modlinkage modlinkage = { 71*9485SMikore.Li@Sun.COM MODREV_1, 72*9485SMikore.Li@Sun.COM (void *)&urtw_modldrv, 73*9485SMikore.Li@Sun.COM NULL 74*9485SMikore.Li@Sun.COM }; 75*9485SMikore.Li@Sun.COM 76*9485SMikore.Li@Sun.COM static int urtw_m_stat(void *, uint_t, uint64_t *); 77*9485SMikore.Li@Sun.COM static int urtw_m_start(void *); 78*9485SMikore.Li@Sun.COM static void urtw_m_stop(void *); 79*9485SMikore.Li@Sun.COM static int urtw_m_promisc(void *, boolean_t); 80*9485SMikore.Li@Sun.COM static int urtw_m_multicst(void *, boolean_t, const uint8_t *); 81*9485SMikore.Li@Sun.COM static int urtw_m_unicst(void *, const uint8_t *); 82*9485SMikore.Li@Sun.COM static mblk_t *urtw_m_tx(void *, mblk_t *); 83*9485SMikore.Li@Sun.COM static void urtw_m_ioctl(void *, queue_t *, mblk_t *); 84*9485SMikore.Li@Sun.COM static int urtw_m_setprop(void *, const char *, mac_prop_id_t, 85*9485SMikore.Li@Sun.COM uint_t, const void *); 86*9485SMikore.Li@Sun.COM 87*9485SMikore.Li@Sun.COM static mac_callbacks_t urtw_m_callbacks = { 88*9485SMikore.Li@Sun.COM MC_IOCTL | MC_SETPROP | MC_GETPROP, 89*9485SMikore.Li@Sun.COM urtw_m_stat, 90*9485SMikore.Li@Sun.COM urtw_m_start, 91*9485SMikore.Li@Sun.COM urtw_m_stop, 92*9485SMikore.Li@Sun.COM urtw_m_promisc, 93*9485SMikore.Li@Sun.COM urtw_m_multicst, 94*9485SMikore.Li@Sun.COM urtw_m_unicst, 95*9485SMikore.Li@Sun.COM urtw_m_tx, 96*9485SMikore.Li@Sun.COM urtw_m_ioctl, 97*9485SMikore.Li@Sun.COM NULL, 98*9485SMikore.Li@Sun.COM NULL, 99*9485SMikore.Li@Sun.COM NULL, 100*9485SMikore.Li@Sun.COM urtw_m_setprop, 101*9485SMikore.Li@Sun.COM ieee80211_getprop 102*9485SMikore.Li@Sun.COM }; 103*9485SMikore.Li@Sun.COM 104*9485SMikore.Li@Sun.COM static int urtw_tx_start(struct urtw_softc *, mblk_t *, int); 105*9485SMikore.Li@Sun.COM static int urtw_rx_start(struct urtw_softc *); 106*9485SMikore.Li@Sun.COM 107*9485SMikore.Li@Sun.COM 108*9485SMikore.Li@Sun.COM /* 109*9485SMikore.Li@Sun.COM * Supported rates for 802.11a/b/g modes (in 500Kbps unit). 110*9485SMikore.Li@Sun.COM */ 111*9485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11b = 112*9485SMikore.Li@Sun.COM { 4, { 2, 4, 11, 22 } }; 113*9485SMikore.Li@Sun.COM 114*9485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11g = 115*9485SMikore.Li@Sun.COM { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 116*9485SMikore.Li@Sun.COM 117*9485SMikore.Li@Sun.COM 118*9485SMikore.Li@Sun.COM struct urtw_pair { 119*9485SMikore.Li@Sun.COM uint32_t reg; 120*9485SMikore.Li@Sun.COM uint32_t val; 121*9485SMikore.Li@Sun.COM }; 122*9485SMikore.Li@Sun.COM 123*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_agc[] = { 124*9485SMikore.Li@Sun.COM 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, 125*9485SMikore.Li@Sun.COM 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 126*9485SMikore.Li@Sun.COM 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 127*9485SMikore.Li@Sun.COM 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 128*9485SMikore.Li@Sun.COM 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 129*9485SMikore.Li@Sun.COM 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 130*9485SMikore.Li@Sun.COM 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 131*9485SMikore.Li@Sun.COM 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 132*9485SMikore.Li@Sun.COM 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 133*9485SMikore.Li@Sun.COM 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 134*9485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 135*9485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 136*9485SMikore.Li@Sun.COM }; 137*9485SMikore.Li@Sun.COM 138*9485SMikore.Li@Sun.COM static uint32_t urtw_8225_channel[] = { 139*9485SMikore.Li@Sun.COM 0x0000, /* dummy channel 0 */ 140*9485SMikore.Li@Sun.COM 0x085c, /* 1 */ 141*9485SMikore.Li@Sun.COM 0x08dc, /* 2 */ 142*9485SMikore.Li@Sun.COM 0x095c, /* 3 */ 143*9485SMikore.Li@Sun.COM 0x09dc, /* 4 */ 144*9485SMikore.Li@Sun.COM 0x0a5c, /* 5 */ 145*9485SMikore.Li@Sun.COM 0x0adc, /* 6 */ 146*9485SMikore.Li@Sun.COM 0x0b5c, /* 7 */ 147*9485SMikore.Li@Sun.COM 0x0bdc, /* 8 */ 148*9485SMikore.Li@Sun.COM 0x0c5c, /* 9 */ 149*9485SMikore.Li@Sun.COM 0x0cdc, /* 10 */ 150*9485SMikore.Li@Sun.COM 0x0d5c, /* 11 */ 151*9485SMikore.Li@Sun.COM 0x0ddc, /* 12 */ 152*9485SMikore.Li@Sun.COM 0x0e5c, /* 13 */ 153*9485SMikore.Li@Sun.COM 0x0f72, /* 14 */ 154*9485SMikore.Li@Sun.COM }; 155*9485SMikore.Li@Sun.COM 156*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_gain[] = { 157*9485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ 158*9485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ 159*9485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ 160*9485SMikore.Li@Sun.COM 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ 161*9485SMikore.Li@Sun.COM 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ 162*9485SMikore.Li@Sun.COM 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ 163*9485SMikore.Li@Sun.COM 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ 164*9485SMikore.Li@Sun.COM }; 165*9485SMikore.Li@Sun.COM 166*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part1[] = { 167*9485SMikore.Li@Sun.COM { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 168*9485SMikore.Li@Sun.COM { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a }, 169*9485SMikore.Li@Sun.COM { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 }, 170*9485SMikore.Li@Sun.COM { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }, 171*9485SMikore.Li@Sun.COM }; 172*9485SMikore.Li@Sun.COM 173*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part2[] = { 174*9485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 175*9485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 176*9485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 }, 177*9485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 }, 178*9485SMikore.Li@Sun.COM { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 }, 179*9485SMikore.Li@Sun.COM { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef }, 180*9485SMikore.Li@Sun.COM { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 }, 181*9485SMikore.Li@Sun.COM { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 }, 182*9485SMikore.Li@Sun.COM { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 }, 183*9485SMikore.Li@Sun.COM { 0x27, 0x88 } 184*9485SMikore.Li@Sun.COM }; 185*9485SMikore.Li@Sun.COM 186*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part3[] = { 187*9485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 188*9485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b }, 189*9485SMikore.Li@Sun.COM { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, 190*9485SMikore.Li@Sun.COM { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d }, 191*9485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e }, 192*9485SMikore.Li@Sun.COM { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a }, 193*9485SMikore.Li@Sun.COM { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 } 194*9485SMikore.Li@Sun.COM }; 195*9485SMikore.Li@Sun.COM 196*9485SMikore.Li@Sun.COM static uint16_t urtw_8225_rxgain[] = { 197*9485SMikore.Li@Sun.COM 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 198*9485SMikore.Li@Sun.COM 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, 199*9485SMikore.Li@Sun.COM 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, 200*9485SMikore.Li@Sun.COM 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, 201*9485SMikore.Li@Sun.COM 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, 202*9485SMikore.Li@Sun.COM 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, 203*9485SMikore.Li@Sun.COM 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, 204*9485SMikore.Li@Sun.COM 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, 205*9485SMikore.Li@Sun.COM 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 206*9485SMikore.Li@Sun.COM 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 207*9485SMikore.Li@Sun.COM 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, 208*9485SMikore.Li@Sun.COM 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb 209*9485SMikore.Li@Sun.COM }; 210*9485SMikore.Li@Sun.COM 211*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_threshold[] = { 212*9485SMikore.Li@Sun.COM 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, 213*9485SMikore.Li@Sun.COM }; 214*9485SMikore.Li@Sun.COM 215*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_tx_gain_cck_ofdm[] = { 216*9485SMikore.Li@Sun.COM 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e 217*9485SMikore.Li@Sun.COM }; 218*9485SMikore.Li@Sun.COM 219*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck[] = { 220*9485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, 221*9485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, 222*9485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, 223*9485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, 224*9485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, 225*9485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 226*9485SMikore.Li@Sun.COM }; 227*9485SMikore.Li@Sun.COM 228*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck_ch14[] = { 229*9485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, 230*9485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, 231*9485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, 232*9485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 233*9485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 234*9485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 235*9485SMikore.Li@Sun.COM }; 236*9485SMikore.Li@Sun.COM 237*9485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_ofdm[] = { 238*9485SMikore.Li@Sun.COM 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 239*9485SMikore.Li@Sun.COM }; 240*9485SMikore.Li@Sun.COM 241*9485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_gain_bg[] = { 242*9485SMikore.Li@Sun.COM 0x23, 0x15, 0xa5, /* -82-1dbm */ 243*9485SMikore.Li@Sun.COM 0x23, 0x15, 0xb5, /* -82-2dbm */ 244*9485SMikore.Li@Sun.COM 0x23, 0x15, 0xc5, /* -82-3dbm */ 245*9485SMikore.Li@Sun.COM 0x33, 0x15, 0xc5, /* -78dbm */ 246*9485SMikore.Li@Sun.COM 0x43, 0x15, 0xc5, /* -74dbm */ 247*9485SMikore.Li@Sun.COM 0x53, 0x15, 0xc5, /* -70dbm */ 248*9485SMikore.Li@Sun.COM 0x63, 0x15, 0xc5, /* -66dbm */ 249*9485SMikore.Li@Sun.COM }; 250*9485SMikore.Li@Sun.COM 251*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part1[] = { 252*9485SMikore.Li@Sun.COM { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 253*9485SMikore.Li@Sun.COM { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, 254*9485SMikore.Li@Sun.COM { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, 255*9485SMikore.Li@Sun.COM { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } 256*9485SMikore.Li@Sun.COM }; 257*9485SMikore.Li@Sun.COM 258*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part2[] = { 259*9485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 260*9485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 261*9485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 }, 262*9485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, 263*9485SMikore.Li@Sun.COM { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 }, 264*9485SMikore.Li@Sun.COM { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, 265*9485SMikore.Li@Sun.COM { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 }, 266*9485SMikore.Li@Sun.COM { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 }, 267*9485SMikore.Li@Sun.COM { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 }, 268*9485SMikore.Li@Sun.COM { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 } 269*9485SMikore.Li@Sun.COM }; 270*9485SMikore.Li@Sun.COM 271*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part3[] = { 272*9485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 273*9485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 }, 274*9485SMikore.Li@Sun.COM { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 }, 275*9485SMikore.Li@Sun.COM { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 }, 276*9485SMikore.Li@Sun.COM { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d }, 277*9485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 }, 278*9485SMikore.Li@Sun.COM { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 }, 279*9485SMikore.Li@Sun.COM { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 } 280*9485SMikore.Li@Sun.COM }; 281*9485SMikore.Li@Sun.COM 282*9485SMikore.Li@Sun.COM static uint16_t urtw_8225v2_rxgain[] = { 283*9485SMikore.Li@Sun.COM 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, 284*9485SMikore.Li@Sun.COM 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, 285*9485SMikore.Li@Sun.COM 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, 286*9485SMikore.Li@Sun.COM 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, 287*9485SMikore.Li@Sun.COM 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, 288*9485SMikore.Li@Sun.COM 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, 289*9485SMikore.Li@Sun.COM 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, 290*9485SMikore.Li@Sun.COM 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, 291*9485SMikore.Li@Sun.COM 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 292*9485SMikore.Li@Sun.COM 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, 293*9485SMikore.Li@Sun.COM 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 294*9485SMikore.Li@Sun.COM 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb 295*9485SMikore.Li@Sun.COM }; 296*9485SMikore.Li@Sun.COM 297*9485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { 298*9485SMikore.Li@Sun.COM 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 299*9485SMikore.Li@Sun.COM 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 300*9485SMikore.Li@Sun.COM 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 301*9485SMikore.Li@Sun.COM 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 302*9485SMikore.Li@Sun.COM 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 303*9485SMikore.Li@Sun.COM 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 304*9485SMikore.Li@Sun.COM }; 305*9485SMikore.Li@Sun.COM 306*9485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck[] = { 307*9485SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 308*9485SMikore.Li@Sun.COM }; 309*9485SMikore.Li@Sun.COM 310*9485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck_ch14[] = { 311*9485SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 312*9485SMikore.Li@Sun.COM }; 313*9485SMikore.Li@Sun.COM 314*9485SMikore.Li@Sun.COM static struct urtw_pair urtw_ratetable[] = { 315*9485SMikore.Li@Sun.COM { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 }, 316*9485SMikore.Li@Sun.COM { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 }, 317*9485SMikore.Li@Sun.COM { 96, 10 }, { 108, 11 } 318*9485SMikore.Li@Sun.COM }; 319*9485SMikore.Li@Sun.COM 320*9485SMikore.Li@Sun.COM static int urtw_init(void *); 321*9485SMikore.Li@Sun.COM static void urtw_stop(struct urtw_softc *); 322*9485SMikore.Li@Sun.COM static int urtw_set_channel(struct urtw_softc *); 323*9485SMikore.Li@Sun.COM static void 324*9485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t, usb_bulk_req_t *); 325*9485SMikore.Li@Sun.COM static int 326*9485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *, enum ieee80211_state, int); 327*9485SMikore.Li@Sun.COM static usbd_status urtw_read8_c(struct urtw_softc *, int, uint8_t *); 328*9485SMikore.Li@Sun.COM static usbd_status urtw_read16_c(struct urtw_softc *, int, uint16_t *); 329*9485SMikore.Li@Sun.COM static usbd_status urtw_read32_c(struct urtw_softc *, int, uint32_t *); 330*9485SMikore.Li@Sun.COM static usbd_status urtw_write8_c(struct urtw_softc *, int, uint8_t); 331*9485SMikore.Li@Sun.COM static usbd_status urtw_write16_c(struct urtw_softc *, int, uint16_t); 332*9485SMikore.Li@Sun.COM static usbd_status urtw_write32_c(struct urtw_softc *, int, uint32_t); 333*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_cs(struct urtw_softc *, int); 334*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_ck(struct urtw_softc *); 335*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_sendbits(struct urtw_softc *, int16_t *, 336*9485SMikore.Li@Sun.COM int); 337*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_read32(struct urtw_softc *, uint32_t, 338*9485SMikore.Li@Sun.COM uint32_t *); 339*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_readbit(struct urtw_softc *, int16_t *); 340*9485SMikore.Li@Sun.COM static usbd_status urtw_eprom_writebit(struct urtw_softc *, int16_t); 341*9485SMikore.Li@Sun.COM static usbd_status urtw_get_macaddr(struct urtw_softc *); 342*9485SMikore.Li@Sun.COM static usbd_status urtw_get_txpwr(struct urtw_softc *); 343*9485SMikore.Li@Sun.COM static usbd_status urtw_get_rfchip(struct urtw_softc *); 344*9485SMikore.Li@Sun.COM static usbd_status urtw_led_init(struct urtw_softc *); 345*9485SMikore.Li@Sun.COM static usbd_status 346*9485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *, uint8_t, uint32_t *); 347*9485SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_init(struct urtw_softc *); 348*9485SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_chan(struct urtw_softc *, int); 349*9485SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_sens(struct urtw_softc *, int); 350*9485SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_init(struct urtw_softc *); 351*9485SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_set_chan(struct urtw_softc *, int); 352*9485SMikore.Li@Sun.COM static usbd_status urtw_open_pipes(struct urtw_softc *); 353*9485SMikore.Li@Sun.COM static void urtw_close_pipes(struct urtw_softc *); 354*9485SMikore.Li@Sun.COM static void urtw_led_launch(void *); 355*9485SMikore.Li@Sun.COM 356*9485SMikore.Li@Sun.COM #ifdef DEBUG 357*9485SMikore.Li@Sun.COM 358*9485SMikore.Li@Sun.COM #define URTW_DEBUG_XMIT 0x00000001 359*9485SMikore.Li@Sun.COM #define URTW_DEBUG_RECV 0x00000002 360*9485SMikore.Li@Sun.COM #define URTW_DEBUG_LED 0x00000004 361*9485SMikore.Li@Sun.COM #define URTW_DEBUG_GLD 0x00000008 362*9485SMikore.Li@Sun.COM #define URTW_DEBUG_RF 0x00000010 363*9485SMikore.Li@Sun.COM #define URTW_DEBUG_ATTACH 0x00000020 364*9485SMikore.Li@Sun.COM #define URTW_DEBUG_ACTIVE 0x00000040 365*9485SMikore.Li@Sun.COM #define URTW_DEBUG_HWTYPE 0x00000080 366*9485SMikore.Li@Sun.COM #define URTW_DEBUG_STATE 0x00000100 367*9485SMikore.Li@Sun.COM #define URTW_DEBUG_HOTPLUG 0x00000200 368*9485SMikore.Li@Sun.COM #define URTW_DEBUG_STAT 0x00000400 369*9485SMikore.Li@Sun.COM #define URTW_DEBUG_TX_PROC 0x00000800 370*9485SMikore.Li@Sun.COM #define URTW_DEBUG_RX_PROC 0x00001000 371*9485SMikore.Li@Sun.COM #define URTW_DEBUG_EEPROM 0x00002000 372*9485SMikore.Li@Sun.COM #define URTW_DEBUG_RESET 0x00004000 373*9485SMikore.Li@Sun.COM #define URTW_DEBUG_DEVREQ 0x00010000 374*9485SMikore.Li@Sun.COM #define URTW_DEBUG_ANY 0xffffffff 375*9485SMikore.Li@Sun.COM 376*9485SMikore.Li@Sun.COM uint32_t urtw8187_dbg_flags = 0; 377*9485SMikore.Li@Sun.COM static void 378*9485SMikore.Li@Sun.COM urtw8187_dbg(dev_info_t *dip, int level, const char *fmt, ...) 379*9485SMikore.Li@Sun.COM { 380*9485SMikore.Li@Sun.COM char msg_buffer[255]; 381*9485SMikore.Li@Sun.COM va_list ap; 382*9485SMikore.Li@Sun.COM 383*9485SMikore.Li@Sun.COM if (dip == NULL) { 384*9485SMikore.Li@Sun.COM return; 385*9485SMikore.Li@Sun.COM } 386*9485SMikore.Li@Sun.COM 387*9485SMikore.Li@Sun.COM va_start(ap, fmt); 388*9485SMikore.Li@Sun.COM (void) vsprintf(msg_buffer, fmt, ap); 389*9485SMikore.Li@Sun.COM cmn_err(level, "%s%d: %s", ddi_get_name(dip), 390*9485SMikore.Li@Sun.COM ddi_get_instance(dip), msg_buffer); 391*9485SMikore.Li@Sun.COM va_end(ap); 392*9485SMikore.Li@Sun.COM } 393*9485SMikore.Li@Sun.COM 394*9485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x) do {\ 395*9485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \ 396*9485SMikore.Li@Sun.COM if ((l) & urtw8187_dbg_flags) \ 397*9485SMikore.Li@Sun.COM urtw8187_dbg x;\ 398*9485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \ 399*9485SMikore.Li@Sun.COM } while (0) 400*9485SMikore.Li@Sun.COM #else 401*9485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x) 402*9485SMikore.Li@Sun.COM #endif 403*9485SMikore.Li@Sun.COM 404*9485SMikore.Li@Sun.COM static usbd_status 405*9485SMikore.Li@Sun.COM urtw_led_init(struct urtw_softc *sc) 406*9485SMikore.Li@Sun.COM { 407*9485SMikore.Li@Sun.COM uint32_t rev; 408*9485SMikore.Li@Sun.COM usbd_status error; 409*9485SMikore.Li@Sun.COM 410*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_PSR, &sc->sc_psr)) 411*9485SMikore.Li@Sun.COM goto fail; 412*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev); 413*9485SMikore.Li@Sun.COM if (error != 0) 414*9485SMikore.Li@Sun.COM goto fail; 415*9485SMikore.Li@Sun.COM 416*9485SMikore.Li@Sun.COM switch (rev & URTW_EPROM_CID_MASK) { 417*9485SMikore.Li@Sun.COM case URTW_EPROM_CID_ALPHA0: 418*9485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE1; 419*9485SMikore.Li@Sun.COM break; 420*9485SMikore.Li@Sun.COM case URTW_EPROM_CID_SERCOMM_PS: 421*9485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE3; 422*9485SMikore.Li@Sun.COM break; 423*9485SMikore.Li@Sun.COM case URTW_EPROM_CID_HW_LED: 424*9485SMikore.Li@Sun.COM sc->sc_strategy = URTW_HW_LED; 425*9485SMikore.Li@Sun.COM break; 426*9485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD0: 427*9485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD1: 428*9485SMikore.Li@Sun.COM default: 429*9485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE0; 430*9485SMikore.Li@Sun.COM break; 431*9485SMikore.Li@Sun.COM } 432*9485SMikore.Li@Sun.COM 433*9485SMikore.Li@Sun.COM sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0; 434*9485SMikore.Li@Sun.COM 435*9485SMikore.Li@Sun.COM fail: 436*9485SMikore.Li@Sun.COM return (error); 437*9485SMikore.Li@Sun.COM } 438*9485SMikore.Li@Sun.COM 439*9485SMikore.Li@Sun.COM static usbd_status 440*9485SMikore.Li@Sun.COM urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index, 441*9485SMikore.Li@Sun.COM uint16_t *data) 442*9485SMikore.Li@Sun.COM { 443*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 444*9485SMikore.Li@Sun.COM usb_cr_t cr; 445*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 446*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 447*9485SMikore.Li@Sun.COM uint16_t data16; 448*9485SMikore.Li@Sun.COM usbd_status error; 449*9485SMikore.Li@Sun.COM 450*9485SMikore.Li@Sun.COM data16 = *data; 451*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 452*9485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 453*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 454*9485SMikore.Li@Sun.COM req.wValue = addr; 455*9485SMikore.Li@Sun.COM req.wIndex = (uint16_t)index; 456*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 457*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 458*9485SMikore.Li@Sun.COM 459*9485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED); 460*9485SMikore.Li@Sun.COM if (mp == 0) { 461*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_8225_write_s16: allocb failed\n"); 462*9485SMikore.Li@Sun.COM return (-1); 463*9485SMikore.Li@Sun.COM } 464*9485SMikore.Li@Sun.COM *(mp->b_rptr) = (data16 & 0x00ff); 465*9485SMikore.Li@Sun.COM *(mp->b_rptr + 1) = (data16 & 0xff00) >> 8; 466*9485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t); 467*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 468*9485SMikore.Li@Sun.COM &cr, &cf, 0); 469*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 470*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 471*9485SMikore.Li@Sun.COM "urtw_8225_write_s16: could not set regs:" 472*9485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 473*9485SMikore.Li@Sun.COM } 474*9485SMikore.Li@Sun.COM if (mp) 475*9485SMikore.Li@Sun.COM freemsg(mp); 476*9485SMikore.Li@Sun.COM return (error); 477*9485SMikore.Li@Sun.COM 478*9485SMikore.Li@Sun.COM } 479*9485SMikore.Li@Sun.COM 480*9485SMikore.Li@Sun.COM static usbd_status 481*9485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data) 482*9485SMikore.Li@Sun.COM { 483*9485SMikore.Li@Sun.COM int i; 484*9485SMikore.Li@Sun.COM int16_t bit; 485*9485SMikore.Li@Sun.COM uint8_t rlen = 12, wlen = 6; 486*9485SMikore.Li@Sun.COM uint16_t o1, o2, o3, tmp; 487*9485SMikore.Li@Sun.COM uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27; 488*9485SMikore.Li@Sun.COM uint32_t mask = 0x80000000, value = 0; 489*9485SMikore.Li@Sun.COM usbd_status error; 490*9485SMikore.Li@Sun.COM 491*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &o1)) 492*9485SMikore.Li@Sun.COM goto fail; 493*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &o2)) 494*9485SMikore.Li@Sun.COM goto fail; 495*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &o3)) 496*9485SMikore.Li@Sun.COM goto fail; 497*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2 | 0xf)) 498*9485SMikore.Li@Sun.COM goto fail; 499*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3 | 0xf)) 500*9485SMikore.Li@Sun.COM goto fail; 501*9485SMikore.Li@Sun.COM o1 &= ~0xf; 502*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 503*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN)) 504*9485SMikore.Li@Sun.COM goto fail; 505*9485SMikore.Li@Sun.COM DELAY(5); 506*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, o1)) 507*9485SMikore.Li@Sun.COM goto fail; 508*9485SMikore.Li@Sun.COM DELAY(5); 509*9485SMikore.Li@Sun.COM 510*9485SMikore.Li@Sun.COM for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) { 511*9485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0; 512*9485SMikore.Li@Sun.COM 513*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1)) 514*9485SMikore.Li@Sun.COM goto fail; 515*9485SMikore.Li@Sun.COM DELAY(2); 516*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 517*9485SMikore.Li@Sun.COM URTW_BB_HOST_BANG_CLK)) 518*9485SMikore.Li@Sun.COM goto fail; 519*9485SMikore.Li@Sun.COM DELAY(2); 520*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 521*9485SMikore.Li@Sun.COM URTW_BB_HOST_BANG_CLK)) 522*9485SMikore.Li@Sun.COM goto fail; 523*9485SMikore.Li@Sun.COM DELAY(2); 524*9485SMikore.Li@Sun.COM mask = mask >> 1; 525*9485SMikore.Li@Sun.COM if (i == 2) 526*9485SMikore.Li@Sun.COM break; 527*9485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0; 528*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 529*9485SMikore.Li@Sun.COM URTW_BB_HOST_BANG_CLK)) 530*9485SMikore.Li@Sun.COM goto fail; 531*9485SMikore.Li@Sun.COM DELAY(2); 532*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 533*9485SMikore.Li@Sun.COM URTW_BB_HOST_BANG_CLK)) 534*9485SMikore.Li@Sun.COM goto fail; 535*9485SMikore.Li@Sun.COM DELAY(2); 536*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, bit | o1)) 537*9485SMikore.Li@Sun.COM goto fail; 538*9485SMikore.Li@Sun.COM DELAY(1); 539*9485SMikore.Li@Sun.COM } 540*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 541*9485SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK)) 542*9485SMikore.Li@Sun.COM goto fail; 543*9485SMikore.Li@Sun.COM DELAY(2); 544*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 545*9485SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW)) 546*9485SMikore.Li@Sun.COM goto fail; 547*9485SMikore.Li@Sun.COM DELAY(2); 548*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 549*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW)) 550*9485SMikore.Li@Sun.COM goto fail; 551*9485SMikore.Li@Sun.COM DELAY(2); 552*9485SMikore.Li@Sun.COM 553*9485SMikore.Li@Sun.COM mask = 0x800; 554*9485SMikore.Li@Sun.COM for (i = 0; i < rlen; i++, mask = mask >> 1) { 555*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 556*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW)) 557*9485SMikore.Li@Sun.COM goto fail; 558*9485SMikore.Li@Sun.COM DELAY(2); 559*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 560*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK)) 561*9485SMikore.Li@Sun.COM goto fail; 562*9485SMikore.Li@Sun.COM DELAY(2); 563*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 564*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK)) 565*9485SMikore.Li@Sun.COM goto fail; 566*9485SMikore.Li@Sun.COM DELAY(2); 567*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 568*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK)) 569*9485SMikore.Li@Sun.COM goto fail; 570*9485SMikore.Li@Sun.COM DELAY(2); 571*9485SMikore.Li@Sun.COM 572*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_INPUT, &tmp)) 573*9485SMikore.Li@Sun.COM goto fail; 574*9485SMikore.Li@Sun.COM value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0); 575*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 576*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW)) 577*9485SMikore.Li@Sun.COM goto fail; 578*9485SMikore.Li@Sun.COM DELAY(2); 579*9485SMikore.Li@Sun.COM } 580*9485SMikore.Li@Sun.COM 581*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 582*9485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN | 583*9485SMikore.Li@Sun.COM URTW_BB_HOST_BANG_RW)) 584*9485SMikore.Li@Sun.COM goto fail; 585*9485SMikore.Li@Sun.COM DELAY(2); 586*9485SMikore.Li@Sun.COM 587*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2)) 588*9485SMikore.Li@Sun.COM goto fail; 589*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3)) 590*9485SMikore.Li@Sun.COM goto fail; 591*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x3a0); 592*9485SMikore.Li@Sun.COM 593*9485SMikore.Li@Sun.COM if (data != NULL) 594*9485SMikore.Li@Sun.COM *data = value; 595*9485SMikore.Li@Sun.COM fail: 596*9485SMikore.Li@Sun.COM return (error); 597*9485SMikore.Li@Sun.COM } 598*9485SMikore.Li@Sun.COM 599*9485SMikore.Li@Sun.COM static void 600*9485SMikore.Li@Sun.COM urtw_delay_ms(int t) 601*9485SMikore.Li@Sun.COM { 602*9485SMikore.Li@Sun.COM DELAY(t * 1000); 603*9485SMikore.Li@Sun.COM } 604*9485SMikore.Li@Sun.COM 605*9485SMikore.Li@Sun.COM static usbd_status 606*9485SMikore.Li@Sun.COM urtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data) 607*9485SMikore.Li@Sun.COM { 608*9485SMikore.Li@Sun.COM uint16_t d80, d82, d84; 609*9485SMikore.Li@Sun.COM usbd_status error; 610*9485SMikore.Li@Sun.COM 611*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &d80)) 612*9485SMikore.Li@Sun.COM goto fail; 613*9485SMikore.Li@Sun.COM d80 &= 0xfff3; 614*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &d82)) 615*9485SMikore.Li@Sun.COM goto fail; 616*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &d84)) 617*9485SMikore.Li@Sun.COM goto fail; 618*9485SMikore.Li@Sun.COM d84 &= 0xfff0; 619*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 620*9485SMikore.Li@Sun.COM d82 | 0x0007)) 621*9485SMikore.Li@Sun.COM goto fail; 622*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 623*9485SMikore.Li@Sun.COM d84 | 0x0007)) 624*9485SMikore.Li@Sun.COM goto fail; 625*9485SMikore.Li@Sun.COM DELAY(10); 626*9485SMikore.Li@Sun.COM 627*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 628*9485SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN)) 629*9485SMikore.Li@Sun.COM goto fail; 630*9485SMikore.Li@Sun.COM DELAY(2); 631*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, d80)) 632*9485SMikore.Li@Sun.COM goto fail; 633*9485SMikore.Li@Sun.COM DELAY(10); 634*9485SMikore.Li@Sun.COM 635*9485SMikore.Li@Sun.COM error = urtw_8225_write_s16(sc, addr, 0x8225, &data); 636*9485SMikore.Li@Sun.COM if (error != 0) 637*9485SMikore.Li@Sun.COM goto fail; 638*9485SMikore.Li@Sun.COM 639*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 640*9485SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN)) 641*9485SMikore.Li@Sun.COM goto fail; 642*9485SMikore.Li@Sun.COM DELAY(10); 643*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 644*9485SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN)) 645*9485SMikore.Li@Sun.COM goto fail; 646*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, d84); 647*9485SMikore.Li@Sun.COM urtw_delay_ms(2); 648*9485SMikore.Li@Sun.COM fail: 649*9485SMikore.Li@Sun.COM return (error); 650*9485SMikore.Li@Sun.COM } 651*9485SMikore.Li@Sun.COM 652*9485SMikore.Li@Sun.COM static usbd_status 653*9485SMikore.Li@Sun.COM urtw_8225_isv2(struct urtw_softc *sc, int *ret) 654*9485SMikore.Li@Sun.COM { 655*9485SMikore.Li@Sun.COM uint32_t data; 656*9485SMikore.Li@Sun.COM usbd_status error; 657*9485SMikore.Li@Sun.COM 658*9485SMikore.Li@Sun.COM *ret = 1; 659*9485SMikore.Li@Sun.COM 660*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0080)) 661*9485SMikore.Li@Sun.COM goto fail; 662*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x0080)) 663*9485SMikore.Li@Sun.COM goto fail; 664*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x0080)) 665*9485SMikore.Li@Sun.COM goto fail; 666*9485SMikore.Li@Sun.COM urtw_delay_ms(300); 667*9485SMikore.Li@Sun.COM 668*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7)) 669*9485SMikore.Li@Sun.COM goto fail; 670*9485SMikore.Li@Sun.COM 671*9485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x8, &data); 672*9485SMikore.Li@Sun.COM if (error != 0) 673*9485SMikore.Li@Sun.COM goto fail; 674*9485SMikore.Li@Sun.COM if (data != 0x588) 675*9485SMikore.Li@Sun.COM *ret = 0; 676*9485SMikore.Li@Sun.COM else { 677*9485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x9, &data); 678*9485SMikore.Li@Sun.COM if (error != 0) 679*9485SMikore.Li@Sun.COM goto fail; 680*9485SMikore.Li@Sun.COM if (data != 0x700) 681*9485SMikore.Li@Sun.COM *ret = 0; 682*9485SMikore.Li@Sun.COM } 683*9485SMikore.Li@Sun.COM 684*9485SMikore.Li@Sun.COM error = urtw_8225_write_c(sc, 0x0, 0xb7); 685*9485SMikore.Li@Sun.COM fail: 686*9485SMikore.Li@Sun.COM return (error); 687*9485SMikore.Li@Sun.COM } 688*9485SMikore.Li@Sun.COM 689*9485SMikore.Li@Sun.COM static usbd_status 690*9485SMikore.Li@Sun.COM urtw_get_rfchip(struct urtw_softc *sc) 691*9485SMikore.Li@Sun.COM { 692*9485SMikore.Li@Sun.COM int ret; 693*9485SMikore.Li@Sun.COM uint32_t data; 694*9485SMikore.Li@Sun.COM usbd_status error; 695*9485SMikore.Li@Sun.COM 696*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); 697*9485SMikore.Li@Sun.COM if (error != 0) 698*9485SMikore.Li@Sun.COM goto fail; 699*9485SMikore.Li@Sun.COM switch (data & 0xff) { 700*9485SMikore.Li@Sun.COM case URTW_EPROM_RFCHIPID_RTL8225U: 701*9485SMikore.Li@Sun.COM error = urtw_8225_isv2(sc, &ret); 702*9485SMikore.Li@Sun.COM if (error != 0) 703*9485SMikore.Li@Sun.COM goto fail; 704*9485SMikore.Li@Sun.COM if (ret == 0) { 705*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 706*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "8225 RF chip detected\n")); 707*9485SMikore.Li@Sun.COM sc->sc_rf_init = urtw_8225_rf_init; 708*9485SMikore.Li@Sun.COM sc->sc_rf_set_sens = urtw_8225_rf_set_sens; 709*9485SMikore.Li@Sun.COM sc->sc_rf_set_chan = urtw_8225_rf_set_chan; 710*9485SMikore.Li@Sun.COM } else { 711*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, 712*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 713*9485SMikore.Li@Sun.COM "8225 v2 RF chip detected\n")); 714*9485SMikore.Li@Sun.COM sc->sc_rf_init = urtw_8225v2_rf_init; 715*9485SMikore.Li@Sun.COM sc->sc_rf_set_chan = urtw_8225v2_rf_set_chan; 716*9485SMikore.Li@Sun.COM } 717*9485SMikore.Li@Sun.COM sc->sc_max_sens = URTW_8225_RF_MAX_SENS; 718*9485SMikore.Li@Sun.COM sc->sc_sens = URTW_8225_RF_DEF_SENS; 719*9485SMikore.Li@Sun.COM break; 720*9485SMikore.Li@Sun.COM default: 721*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported RF chip %d\n", data & 0xff); 722*9485SMikore.Li@Sun.COM error = -1; 723*9485SMikore.Li@Sun.COM } 724*9485SMikore.Li@Sun.COM 725*9485SMikore.Li@Sun.COM fail: 726*9485SMikore.Li@Sun.COM return (error); 727*9485SMikore.Li@Sun.COM } 728*9485SMikore.Li@Sun.COM 729*9485SMikore.Li@Sun.COM static usbd_status 730*9485SMikore.Li@Sun.COM urtw_get_txpwr(struct urtw_softc *sc) 731*9485SMikore.Li@Sun.COM { 732*9485SMikore.Li@Sun.COM int i, j; 733*9485SMikore.Li@Sun.COM uint32_t data; 734*9485SMikore.Li@Sun.COM usbd_status error; 735*9485SMikore.Li@Sun.COM 736*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data); 737*9485SMikore.Li@Sun.COM if (error != 0) 738*9485SMikore.Li@Sun.COM goto fail; 739*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck_base = data & 0xf; 740*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf; 741*9485SMikore.Li@Sun.COM 742*9485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 6; i += 2, j++) { 743*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data); 744*9485SMikore.Li@Sun.COM if (error != 0) 745*9485SMikore.Li@Sun.COM goto fail; 746*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i] = data & 0xf; 747*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8; 748*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4; 749*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12; 750*9485SMikore.Li@Sun.COM } 751*9485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) { 752*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data); 753*9485SMikore.Li@Sun.COM if (error != 0) 754*9485SMikore.Li@Sun.COM goto fail; 755*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6] = data & 0xf; 756*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8; 757*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; 758*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; 759*9485SMikore.Li@Sun.COM } 760*9485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) { 761*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, &data); 762*9485SMikore.Li@Sun.COM if (error != 0) 763*9485SMikore.Li@Sun.COM goto fail; 764*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; 765*9485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; 766*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; 767*9485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12; 768*9485SMikore.Li@Sun.COM } 769*9485SMikore.Li@Sun.COM fail: 770*9485SMikore.Li@Sun.COM return (error); 771*9485SMikore.Li@Sun.COM } 772*9485SMikore.Li@Sun.COM 773*9485SMikore.Li@Sun.COM static usbd_status 774*9485SMikore.Li@Sun.COM urtw_get_macaddr(struct urtw_softc *sc) 775*9485SMikore.Li@Sun.COM { 776*9485SMikore.Li@Sun.COM uint32_t data; 777*9485SMikore.Li@Sun.COM usbd_status error; 778*9485SMikore.Li@Sun.COM uint8_t *m = 0; 779*9485SMikore.Li@Sun.COM 780*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); 781*9485SMikore.Li@Sun.COM if (error != 0) 782*9485SMikore.Li@Sun.COM goto fail; 783*9485SMikore.Li@Sun.COM sc->sc_bssid[0] = data & 0xff; 784*9485SMikore.Li@Sun.COM sc->sc_bssid[1] = (data & 0xff00) >> 8; 785*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); 786*9485SMikore.Li@Sun.COM if (error != 0) 787*9485SMikore.Li@Sun.COM goto fail; 788*9485SMikore.Li@Sun.COM sc->sc_bssid[2] = data & 0xff; 789*9485SMikore.Li@Sun.COM sc->sc_bssid[3] = (data & 0xff00) >> 8; 790*9485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); 791*9485SMikore.Li@Sun.COM if (error != 0) 792*9485SMikore.Li@Sun.COM goto fail; 793*9485SMikore.Li@Sun.COM sc->sc_bssid[4] = data & 0xff; 794*9485SMikore.Li@Sun.COM sc->sc_bssid[5] = (data & 0xff00) >> 8; 795*9485SMikore.Li@Sun.COM bcopy(sc->sc_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN); 796*9485SMikore.Li@Sun.COM m = sc->sc_bssid; 797*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 798*9485SMikore.Li@Sun.COM "MAC: %x:%x:%x:%x:%x:%x\n", 799*9485SMikore.Li@Sun.COM m[0], m[1], m[2], m[3], m[4], m[5])); 800*9485SMikore.Li@Sun.COM fail: 801*9485SMikore.Li@Sun.COM return (error); 802*9485SMikore.Li@Sun.COM } 803*9485SMikore.Li@Sun.COM 804*9485SMikore.Li@Sun.COM static usbd_status 805*9485SMikore.Li@Sun.COM urtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data) 806*9485SMikore.Li@Sun.COM { 807*9485SMikore.Li@Sun.COM #define URTW_READCMD_LEN 3 808*9485SMikore.Li@Sun.COM int addrlen, i; 809*9485SMikore.Li@Sun.COM int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 }; 810*9485SMikore.Li@Sun.COM usbd_status error; 811*9485SMikore.Li@Sun.COM 812*9485SMikore.Li@Sun.COM /* NB: make sure the buffer is initialized */ 813*9485SMikore.Li@Sun.COM *data = 0; 814*9485SMikore.Li@Sun.COM 815*9485SMikore.Li@Sun.COM /* enable EPROM programming */ 816*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD, 817*9485SMikore.Li@Sun.COM URTW_EPROM_CMD_PROGRAM_MODE)) 818*9485SMikore.Li@Sun.COM goto fail; 819*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 820*9485SMikore.Li@Sun.COM 821*9485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE); 822*9485SMikore.Li@Sun.COM if (error != 0) 823*9485SMikore.Li@Sun.COM goto fail; 824*9485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 825*9485SMikore.Li@Sun.COM if (error != 0) 826*9485SMikore.Li@Sun.COM goto fail; 827*9485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN); 828*9485SMikore.Li@Sun.COM if (error != 0) 829*9485SMikore.Li@Sun.COM goto fail; 830*9485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56) { 831*9485SMikore.Li@Sun.COM addrlen = 8; 832*9485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 7); 833*9485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 6); 834*9485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 5); 835*9485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 4); 836*9485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 3); 837*9485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 2); 838*9485SMikore.Li@Sun.COM addrstr[6] = addr & (1 << 1); 839*9485SMikore.Li@Sun.COM addrstr[7] = addr & (1 << 0); 840*9485SMikore.Li@Sun.COM } else { 841*9485SMikore.Li@Sun.COM addrlen = 6; 842*9485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 5); 843*9485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 4); 844*9485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 3); 845*9485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 2); 846*9485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 1); 847*9485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 0); 848*9485SMikore.Li@Sun.COM } 849*9485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, addrstr, addrlen); 850*9485SMikore.Li@Sun.COM if (error != 0) 851*9485SMikore.Li@Sun.COM goto fail; 852*9485SMikore.Li@Sun.COM 853*9485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, 0); 854*9485SMikore.Li@Sun.COM if (error != 0) 855*9485SMikore.Li@Sun.COM goto fail; 856*9485SMikore.Li@Sun.COM 857*9485SMikore.Li@Sun.COM for (i = 0; i < 16; i++) { 858*9485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 859*9485SMikore.Li@Sun.COM if (error != 0) 860*9485SMikore.Li@Sun.COM goto fail; 861*9485SMikore.Li@Sun.COM error = urtw_eprom_readbit(sc, &data16); 862*9485SMikore.Li@Sun.COM if (error != 0) 863*9485SMikore.Li@Sun.COM goto fail; 864*9485SMikore.Li@Sun.COM 865*9485SMikore.Li@Sun.COM (*data) |= (data16 << (15 - i)); 866*9485SMikore.Li@Sun.COM } 867*9485SMikore.Li@Sun.COM 868*9485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE); 869*9485SMikore.Li@Sun.COM if (error != 0) 870*9485SMikore.Li@Sun.COM goto fail; 871*9485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 872*9485SMikore.Li@Sun.COM if (error != 0) 873*9485SMikore.Li@Sun.COM goto fail; 874*9485SMikore.Li@Sun.COM 875*9485SMikore.Li@Sun.COM /* now disable EPROM programming */ 876*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_NORMAL_MODE); 877*9485SMikore.Li@Sun.COM fail: 878*9485SMikore.Li@Sun.COM return (error); 879*9485SMikore.Li@Sun.COM #undef URTW_READCMD_LEN 880*9485SMikore.Li@Sun.COM } 881*9485SMikore.Li@Sun.COM 882*9485SMikore.Li@Sun.COM static usbd_status 883*9485SMikore.Li@Sun.COM urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data) 884*9485SMikore.Li@Sun.COM { 885*9485SMikore.Li@Sun.COM uint8_t data8; 886*9485SMikore.Li@Sun.COM usbd_status error; 887*9485SMikore.Li@Sun.COM 888*9485SMikore.Li@Sun.COM error = urtw_read8_c(sc, URTW_EPROM_CMD, &data8); 889*9485SMikore.Li@Sun.COM *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0; 890*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 891*9485SMikore.Li@Sun.COM return (error); 892*9485SMikore.Li@Sun.COM } 893*9485SMikore.Li@Sun.COM 894*9485SMikore.Li@Sun.COM static usbd_status 895*9485SMikore.Li@Sun.COM urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen) 896*9485SMikore.Li@Sun.COM { 897*9485SMikore.Li@Sun.COM int i = 0; 898*9485SMikore.Li@Sun.COM usbd_status error; 899*9485SMikore.Li@Sun.COM 900*9485SMikore.Li@Sun.COM for (i = 0; i < buflen; i++) { 901*9485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, buf[i]); 902*9485SMikore.Li@Sun.COM if (error != 0) 903*9485SMikore.Li@Sun.COM goto fail; 904*9485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc); 905*9485SMikore.Li@Sun.COM if (error != 0) 906*9485SMikore.Li@Sun.COM goto fail; 907*9485SMikore.Li@Sun.COM } 908*9485SMikore.Li@Sun.COM fail: 909*9485SMikore.Li@Sun.COM return (error); 910*9485SMikore.Li@Sun.COM } 911*9485SMikore.Li@Sun.COM 912*9485SMikore.Li@Sun.COM static usbd_status 913*9485SMikore.Li@Sun.COM urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit) 914*9485SMikore.Li@Sun.COM { 915*9485SMikore.Li@Sun.COM uint8_t data; 916*9485SMikore.Li@Sun.COM usbd_status error; 917*9485SMikore.Li@Sun.COM 918*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data)) 919*9485SMikore.Li@Sun.COM goto fail; 920*9485SMikore.Li@Sun.COM if (bit != 0) 921*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 922*9485SMikore.Li@Sun.COM data | URTW_EPROM_WRITEBIT); 923*9485SMikore.Li@Sun.COM else 924*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 925*9485SMikore.Li@Sun.COM data & ~URTW_EPROM_WRITEBIT); 926*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 927*9485SMikore.Li@Sun.COM fail: 928*9485SMikore.Li@Sun.COM return (error); 929*9485SMikore.Li@Sun.COM } 930*9485SMikore.Li@Sun.COM 931*9485SMikore.Li@Sun.COM static usbd_status 932*9485SMikore.Li@Sun.COM urtw_eprom_ck(struct urtw_softc *sc) 933*9485SMikore.Li@Sun.COM { 934*9485SMikore.Li@Sun.COM uint8_t data; 935*9485SMikore.Li@Sun.COM usbd_status error; 936*9485SMikore.Li@Sun.COM 937*9485SMikore.Li@Sun.COM /* masking */ 938*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data)) 939*9485SMikore.Li@Sun.COM goto fail; 940*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK)) 941*9485SMikore.Li@Sun.COM goto fail; 942*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 943*9485SMikore.Li@Sun.COM /* unmasking */ 944*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data)) 945*9485SMikore.Li@Sun.COM goto fail; 946*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK); 947*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 948*9485SMikore.Li@Sun.COM fail: 949*9485SMikore.Li@Sun.COM return (error); 950*9485SMikore.Li@Sun.COM } 951*9485SMikore.Li@Sun.COM 952*9485SMikore.Li@Sun.COM static usbd_status 953*9485SMikore.Li@Sun.COM urtw_eprom_cs(struct urtw_softc *sc, int able) 954*9485SMikore.Li@Sun.COM { 955*9485SMikore.Li@Sun.COM uint8_t data; 956*9485SMikore.Li@Sun.COM usbd_status error; 957*9485SMikore.Li@Sun.COM 958*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data)) 959*9485SMikore.Li@Sun.COM goto fail; 960*9485SMikore.Li@Sun.COM if (able == URTW_EPROM_ENABLE) 961*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 962*9485SMikore.Li@Sun.COM data | URTW_EPROM_CS); 963*9485SMikore.Li@Sun.COM else 964*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, 965*9485SMikore.Li@Sun.COM data & ~URTW_EPROM_CS); 966*9485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY); 967*9485SMikore.Li@Sun.COM fail: 968*9485SMikore.Li@Sun.COM return (error); 969*9485SMikore.Li@Sun.COM } 970*9485SMikore.Li@Sun.COM 971*9485SMikore.Li@Sun.COM static usbd_status 972*9485SMikore.Li@Sun.COM urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data) 973*9485SMikore.Li@Sun.COM { 974*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 975*9485SMikore.Li@Sun.COM usb_cr_t cr; 976*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 977*9485SMikore.Li@Sun.COM mblk_t *mp = NULL; 978*9485SMikore.Li@Sun.COM usbd_status error; 979*9485SMikore.Li@Sun.COM 980*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 981*9485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 982*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 983*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 984*9485SMikore.Li@Sun.COM req.wIndex = 0; 985*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 986*9485SMikore.Li@Sun.COM 987*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 988*9485SMikore.Li@Sun.COM &cr, &cf, 0); 989*9485SMikore.Li@Sun.COM 990*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 991*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 992*9485SMikore.Li@Sun.COM "urtw_read8_c: get regs req failed :" 993*9485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 994*9485SMikore.Li@Sun.COM return (error); 995*9485SMikore.Li@Sun.COM } 996*9485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t)); 997*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 998*9485SMikore.Li@Sun.COM "urtw_read8_c: get regs data1 ok :0x%x", *data)); 999*9485SMikore.Li@Sun.COM if (mp) 1000*9485SMikore.Li@Sun.COM freemsg(mp); 1001*9485SMikore.Li@Sun.COM return (error); 1002*9485SMikore.Li@Sun.COM } 1003*9485SMikore.Li@Sun.COM 1004*9485SMikore.Li@Sun.COM static usbd_status 1005*9485SMikore.Li@Sun.COM urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data) 1006*9485SMikore.Li@Sun.COM { 1007*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1008*9485SMikore.Li@Sun.COM usb_cr_t cr; 1009*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1010*9485SMikore.Li@Sun.COM mblk_t *mp = NULL; 1011*9485SMikore.Li@Sun.COM usbd_status error; 1012*9485SMikore.Li@Sun.COM 1013*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1014*9485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 1015*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 1016*9485SMikore.Li@Sun.COM req.wValue = val | 0xfe00; 1017*9485SMikore.Li@Sun.COM req.wIndex = 0; 1018*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 1019*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 1020*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1021*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1022*9485SMikore.Li@Sun.COM 1023*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1024*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1025*9485SMikore.Li@Sun.COM "urtw_read8e: get regs req failed :" 1026*9485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 1027*9485SMikore.Li@Sun.COM return (error); 1028*9485SMikore.Li@Sun.COM } 1029*9485SMikore.Li@Sun.COM 1030*9485SMikore.Li@Sun.COM if (mp) { 1031*9485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t)); 1032*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1033*9485SMikore.Li@Sun.COM "urtw_read8e: get regs data1 ok :0x%x", *data)); 1034*9485SMikore.Li@Sun.COM freemsg(mp); 1035*9485SMikore.Li@Sun.COM } 1036*9485SMikore.Li@Sun.COM return (error); 1037*9485SMikore.Li@Sun.COM } 1038*9485SMikore.Li@Sun.COM 1039*9485SMikore.Li@Sun.COM static usbd_status 1040*9485SMikore.Li@Sun.COM urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data) 1041*9485SMikore.Li@Sun.COM { 1042*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1043*9485SMikore.Li@Sun.COM usb_cr_t cr; 1044*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1045*9485SMikore.Li@Sun.COM mblk_t *mp = NULL; 1046*9485SMikore.Li@Sun.COM usbd_status error; 1047*9485SMikore.Li@Sun.COM 1048*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1049*9485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 1050*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 1051*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1052*9485SMikore.Li@Sun.COM req.wIndex = 0; 1053*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 1054*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 1055*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1056*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1057*9485SMikore.Li@Sun.COM 1058*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1059*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1060*9485SMikore.Li@Sun.COM "urtw_read16_c: get regs req failed :" 1061*9485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", 1062*9485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 1063*9485SMikore.Li@Sun.COM return (error); 1064*9485SMikore.Li@Sun.COM } 1065*9485SMikore.Li@Sun.COM if (mp) { 1066*9485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint16_t)); 1067*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1068*9485SMikore.Li@Sun.COM "urtw_read16_c: get regs data2 ok :0x%x", *data)); 1069*9485SMikore.Li@Sun.COM freemsg(mp); 1070*9485SMikore.Li@Sun.COM } 1071*9485SMikore.Li@Sun.COM return (error); 1072*9485SMikore.Li@Sun.COM } 1073*9485SMikore.Li@Sun.COM 1074*9485SMikore.Li@Sun.COM static usbd_status 1075*9485SMikore.Li@Sun.COM urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data) 1076*9485SMikore.Li@Sun.COM { 1077*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1078*9485SMikore.Li@Sun.COM usb_cr_t cr; 1079*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1080*9485SMikore.Li@Sun.COM mblk_t *mp = NULL; 1081*9485SMikore.Li@Sun.COM usbd_status error; 1082*9485SMikore.Li@Sun.COM 1083*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1084*9485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE; 1085*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ; 1086*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1087*9485SMikore.Li@Sun.COM req.wIndex = 0; 1088*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t); 1089*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING; 1090*9485SMikore.Li@Sun.COM 1091*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1092*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1093*9485SMikore.Li@Sun.COM 1094*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1095*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1096*9485SMikore.Li@Sun.COM "urtw_read32_c: get regs req failed :" 1097*9485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 1098*9485SMikore.Li@Sun.COM return (error); 1099*9485SMikore.Li@Sun.COM } 1100*9485SMikore.Li@Sun.COM 1101*9485SMikore.Li@Sun.COM if (mp) { 1102*9485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint32_t)); 1103*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1104*9485SMikore.Li@Sun.COM "urtw_read32_c: get regs data4 ok :0x%x", *data)); 1105*9485SMikore.Li@Sun.COM freemsg(mp); 1106*9485SMikore.Li@Sun.COM } 1107*9485SMikore.Li@Sun.COM return (error); 1108*9485SMikore.Li@Sun.COM } 1109*9485SMikore.Li@Sun.COM 1110*9485SMikore.Li@Sun.COM static usbd_status 1111*9485SMikore.Li@Sun.COM urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data) 1112*9485SMikore.Li@Sun.COM { 1113*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1114*9485SMikore.Li@Sun.COM usb_cr_t cr; 1115*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1116*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 1117*9485SMikore.Li@Sun.COM int error; 1118*9485SMikore.Li@Sun.COM 1119*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1120*9485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1121*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 1122*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1123*9485SMikore.Li@Sun.COM req.wIndex = 0; 1124*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 1125*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 1126*9485SMikore.Li@Sun.COM 1127*9485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED); 1128*9485SMikore.Li@Sun.COM if (mp == NULL) { 1129*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8_c: failed alloc mblk."); 1130*9485SMikore.Li@Sun.COM return (-1); 1131*9485SMikore.Li@Sun.COM } 1132*9485SMikore.Li@Sun.COM *(uint8_t *)(mp->b_rptr) = data; 1133*9485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t); 1134*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1135*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1136*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1137*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1138*9485SMikore.Li@Sun.COM "urtw_write8_c: could not set regs:" 1139*9485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf)); 1140*9485SMikore.Li@Sun.COM } 1141*9485SMikore.Li@Sun.COM if (mp) 1142*9485SMikore.Li@Sun.COM freemsg(mp); 1143*9485SMikore.Li@Sun.COM return (error); 1144*9485SMikore.Li@Sun.COM } 1145*9485SMikore.Li@Sun.COM 1146*9485SMikore.Li@Sun.COM static usbd_status 1147*9485SMikore.Li@Sun.COM urtw_write8e(struct urtw_softc *sc, int val, uint8_t data) 1148*9485SMikore.Li@Sun.COM { 1149*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1150*9485SMikore.Li@Sun.COM usb_cr_t cr; 1151*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1152*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 1153*9485SMikore.Li@Sun.COM int error; 1154*9485SMikore.Li@Sun.COM 1155*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1156*9485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1157*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 1158*9485SMikore.Li@Sun.COM req.wValue = val | 0xfe00; 1159*9485SMikore.Li@Sun.COM req.wIndex = 0; 1160*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t); 1161*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 1162*9485SMikore.Li@Sun.COM 1163*9485SMikore.Li@Sun.COM mp = allocb(sizeof (uint8_t), BPRI_MED); 1164*9485SMikore.Li@Sun.COM if (mp == NULL) { 1165*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8e: failed alloc mblk."); 1166*9485SMikore.Li@Sun.COM return (-1); 1167*9485SMikore.Li@Sun.COM } 1168*9485SMikore.Li@Sun.COM *(mp->b_rptr) = data; 1169*9485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t); 1170*9485SMikore.Li@Sun.COM 1171*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1172*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1173*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1174*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1175*9485SMikore.Li@Sun.COM "urtw_write8e: could not set regs:" 1176*9485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 1177*9485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 1178*9485SMikore.Li@Sun.COM } 1179*9485SMikore.Li@Sun.COM if (mp) 1180*9485SMikore.Li@Sun.COM freemsg(mp); 1181*9485SMikore.Li@Sun.COM return (error); 1182*9485SMikore.Li@Sun.COM } 1183*9485SMikore.Li@Sun.COM 1184*9485SMikore.Li@Sun.COM static usbd_status 1185*9485SMikore.Li@Sun.COM urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data) 1186*9485SMikore.Li@Sun.COM { 1187*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1188*9485SMikore.Li@Sun.COM usb_cr_t cr; 1189*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1190*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 1191*9485SMikore.Li@Sun.COM int error; 1192*9485SMikore.Li@Sun.COM 1193*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1194*9485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1195*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 1196*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1197*9485SMikore.Li@Sun.COM req.wIndex = 0; 1198*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t); 1199*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 1200*9485SMikore.Li@Sun.COM 1201*9485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED); 1202*9485SMikore.Li@Sun.COM if (mp == NULL) { 1203*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write16_c: failed alloc mblk."); 1204*9485SMikore.Li@Sun.COM return (-1); 1205*9485SMikore.Li@Sun.COM } 1206*9485SMikore.Li@Sun.COM *(uint16_t *)(uintptr_t)(mp->b_rptr) = data; 1207*9485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t); 1208*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1209*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1210*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1211*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1212*9485SMikore.Li@Sun.COM "urtw_write16_c: could not set regs:" 1213*9485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 1214*9485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 1215*9485SMikore.Li@Sun.COM } 1216*9485SMikore.Li@Sun.COM if (mp) 1217*9485SMikore.Li@Sun.COM freemsg(mp); 1218*9485SMikore.Li@Sun.COM return (error); 1219*9485SMikore.Li@Sun.COM } 1220*9485SMikore.Li@Sun.COM 1221*9485SMikore.Li@Sun.COM static usbd_status 1222*9485SMikore.Li@Sun.COM urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data) 1223*9485SMikore.Li@Sun.COM { 1224*9485SMikore.Li@Sun.COM usb_ctrl_setup_t req; 1225*9485SMikore.Li@Sun.COM usb_cr_t cr; 1226*9485SMikore.Li@Sun.COM usb_cb_flags_t cf; 1227*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 1228*9485SMikore.Li@Sun.COM int error; 1229*9485SMikore.Li@Sun.COM 1230*9485SMikore.Li@Sun.COM bzero(&req, sizeof (req)); 1231*9485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1232*9485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ; 1233*9485SMikore.Li@Sun.COM req.wValue = val | 0xff00; 1234*9485SMikore.Li@Sun.COM req.wIndex = 0; 1235*9485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t); 1236*9485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE; 1237*9485SMikore.Li@Sun.COM 1238*9485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED); 1239*9485SMikore.Li@Sun.COM if (mp == NULL) { 1240*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write32_c: failed alloc mblk."); 1241*9485SMikore.Li@Sun.COM return (-1); 1242*9485SMikore.Li@Sun.COM } 1243*9485SMikore.Li@Sun.COM *(uint32_t *)(uintptr_t)(mp->b_rptr) = data; 1244*9485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint32_t); 1245*9485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 1246*9485SMikore.Li@Sun.COM &cr, &cf, 0); 1247*9485SMikore.Li@Sun.COM if (error != USB_SUCCESS) { 1248*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT, 1249*9485SMikore.Li@Sun.COM "urtw_write32_c: could not set regs:" 1250*9485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", 1251*9485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf)); 1252*9485SMikore.Li@Sun.COM } 1253*9485SMikore.Li@Sun.COM 1254*9485SMikore.Li@Sun.COM if (mp) 1255*9485SMikore.Li@Sun.COM freemsg(mp); 1256*9485SMikore.Li@Sun.COM return (error); 1257*9485SMikore.Li@Sun.COM } 1258*9485SMikore.Li@Sun.COM 1259*9485SMikore.Li@Sun.COM static usbd_status 1260*9485SMikore.Li@Sun.COM urtw_set_mode(struct urtw_softc *sc, uint32_t mode) 1261*9485SMikore.Li@Sun.COM { 1262*9485SMikore.Li@Sun.COM uint8_t data; 1263*9485SMikore.Li@Sun.COM usbd_status error; 1264*9485SMikore.Li@Sun.COM 1265*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data)) 1266*9485SMikore.Li@Sun.COM goto fail; 1267*9485SMikore.Li@Sun.COM data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT); 1268*9485SMikore.Li@Sun.COM data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK); 1269*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data); 1270*9485SMikore.Li@Sun.COM fail: 1271*9485SMikore.Li@Sun.COM return (error); 1272*9485SMikore.Li@Sun.COM } 1273*9485SMikore.Li@Sun.COM 1274*9485SMikore.Li@Sun.COM static usbd_status 1275*9485SMikore.Li@Sun.COM urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val) 1276*9485SMikore.Li@Sun.COM { 1277*9485SMikore.Li@Sun.COM uint8_t data; 1278*9485SMikore.Li@Sun.COM usbd_status error; 1279*9485SMikore.Li@Sun.COM 1280*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 1281*9485SMikore.Li@Sun.COM if (error) 1282*9485SMikore.Li@Sun.COM goto fail; 1283*9485SMikore.Li@Sun.COM 1284*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data)) 1285*9485SMikore.Li@Sun.COM goto fail; 1286*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1287*9485SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE)) 1288*9485SMikore.Li@Sun.COM goto fail; 1289*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM, val)) 1290*9485SMikore.Li@Sun.COM goto fail; 1291*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data)) 1292*9485SMikore.Li@Sun.COM goto fail; 1293*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1294*9485SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE)) 1295*9485SMikore.Li@Sun.COM goto fail; 1296*9485SMikore.Li@Sun.COM 1297*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 1298*9485SMikore.Li@Sun.COM if (error) 1299*9485SMikore.Li@Sun.COM goto fail; 1300*9485SMikore.Li@Sun.COM fail: 1301*9485SMikore.Li@Sun.COM return (error); 1302*9485SMikore.Li@Sun.COM } 1303*9485SMikore.Li@Sun.COM 1304*9485SMikore.Li@Sun.COM static usbd_status 1305*9485SMikore.Li@Sun.COM urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val) 1306*9485SMikore.Li@Sun.COM { 1307*9485SMikore.Li@Sun.COM uint8_t data; 1308*9485SMikore.Li@Sun.COM usbd_status error; 1309*9485SMikore.Li@Sun.COM 1310*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 1311*9485SMikore.Li@Sun.COM if (error) 1312*9485SMikore.Li@Sun.COM goto fail; 1313*9485SMikore.Li@Sun.COM 1314*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data)) 1315*9485SMikore.Li@Sun.COM goto fail; 1316*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1317*9485SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE)) 1318*9485SMikore.Li@Sun.COM goto fail; 1319*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM2, val)) 1320*9485SMikore.Li@Sun.COM goto fail; 1321*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data)) 1322*9485SMikore.Li@Sun.COM goto fail; 1323*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 1324*9485SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE)) 1325*9485SMikore.Li@Sun.COM goto fail; 1326*9485SMikore.Li@Sun.COM 1327*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 1328*9485SMikore.Li@Sun.COM if (error) 1329*9485SMikore.Li@Sun.COM goto fail; 1330*9485SMikore.Li@Sun.COM fail: 1331*9485SMikore.Li@Sun.COM return (error); 1332*9485SMikore.Li@Sun.COM } 1333*9485SMikore.Li@Sun.COM 1334*9485SMikore.Li@Sun.COM static usbd_status 1335*9485SMikore.Li@Sun.COM urtw_intr_disable(struct urtw_softc *sc) 1336*9485SMikore.Li@Sun.COM { 1337*9485SMikore.Li@Sun.COM usbd_status error; 1338*9485SMikore.Li@Sun.COM 1339*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0); 1340*9485SMikore.Li@Sun.COM return (error); 1341*9485SMikore.Li@Sun.COM } 1342*9485SMikore.Li@Sun.COM 1343*9485SMikore.Li@Sun.COM static usbd_status 1344*9485SMikore.Li@Sun.COM urtw_reset(struct urtw_softc *sc) 1345*9485SMikore.Li@Sun.COM { 1346*9485SMikore.Li@Sun.COM uint8_t data; 1347*9485SMikore.Li@Sun.COM usbd_status error; 1348*9485SMikore.Li@Sun.COM 1349*9485SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 1350*9485SMikore.Li@Sun.COM if (error) 1351*9485SMikore.Li@Sun.COM goto fail; 1352*9485SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 1353*9485SMikore.Li@Sun.COM if (error) 1354*9485SMikore.Li@Sun.COM goto fail; 1355*9485SMikore.Li@Sun.COM 1356*9485SMikore.Li@Sun.COM error = urtw_intr_disable(sc); 1357*9485SMikore.Li@Sun.COM if (error) 1358*9485SMikore.Li@Sun.COM goto fail; 1359*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 1360*9485SMikore.Li@Sun.COM 1361*9485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x10); 1362*9485SMikore.Li@Sun.COM if (error != 0) 1363*9485SMikore.Li@Sun.COM goto fail; 1364*9485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x11); 1365*9485SMikore.Li@Sun.COM if (error != 0) 1366*9485SMikore.Li@Sun.COM goto fail; 1367*9485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x00); 1368*9485SMikore.Li@Sun.COM if (error != 0) 1369*9485SMikore.Li@Sun.COM goto fail; 1370*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 1371*9485SMikore.Li@Sun.COM 1372*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data)) 1373*9485SMikore.Li@Sun.COM goto fail; 1374*9485SMikore.Li@Sun.COM data = (data & 2) | URTW_CMD_RST; 1375*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CMD, data)) 1376*9485SMikore.Li@Sun.COM goto fail; 1377*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 1378*9485SMikore.Li@Sun.COM 1379*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data)) 1380*9485SMikore.Li@Sun.COM goto fail; 1381*9485SMikore.Li@Sun.COM if (data & URTW_CMD_RST) { 1382*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw reset timeout\n"); 1383*9485SMikore.Li@Sun.COM goto fail; 1384*9485SMikore.Li@Sun.COM } 1385*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD); 1386*9485SMikore.Li@Sun.COM if (error) 1387*9485SMikore.Li@Sun.COM goto fail; 1388*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 1389*9485SMikore.Li@Sun.COM 1390*9485SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 1391*9485SMikore.Li@Sun.COM if (error) 1392*9485SMikore.Li@Sun.COM goto fail; 1393*9485SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 1394*9485SMikore.Li@Sun.COM if (error) 1395*9485SMikore.Li@Sun.COM goto fail; 1396*9485SMikore.Li@Sun.COM fail: 1397*9485SMikore.Li@Sun.COM return (error); 1398*9485SMikore.Li@Sun.COM } 1399*9485SMikore.Li@Sun.COM 1400*9485SMikore.Li@Sun.COM static usbd_status 1401*9485SMikore.Li@Sun.COM urtw_led_on(struct urtw_softc *sc, int type) 1402*9485SMikore.Li@Sun.COM { 1403*9485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) { 1404*9485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) { 1405*9485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0: 1406*9485SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01); 1407*9485SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x00); 1408*9485SMikore.Li@Sun.COM break; 1409*9485SMikore.Li@Sun.COM default: 1410*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x", 1411*9485SMikore.Li@Sun.COM sc->sc_gpio_ledpin); 1412*9485SMikore.Li@Sun.COM /* never reach */ 1413*9485SMikore.Li@Sun.COM } 1414*9485SMikore.Li@Sun.COM } else { 1415*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type); 1416*9485SMikore.Li@Sun.COM /* never reach */ 1417*9485SMikore.Li@Sun.COM } 1418*9485SMikore.Li@Sun.COM 1419*9485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 1; 1420*9485SMikore.Li@Sun.COM return (0); 1421*9485SMikore.Li@Sun.COM } 1422*9485SMikore.Li@Sun.COM 1423*9485SMikore.Li@Sun.COM static usbd_status 1424*9485SMikore.Li@Sun.COM urtw_led_off(struct urtw_softc *sc, int type) 1425*9485SMikore.Li@Sun.COM { 1426*9485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) { 1427*9485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) { 1428*9485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0: 1429*9485SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01); 1430*9485SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x01); 1431*9485SMikore.Li@Sun.COM break; 1432*9485SMikore.Li@Sun.COM default: 1433*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x", 1434*9485SMikore.Li@Sun.COM sc->sc_gpio_ledpin); 1435*9485SMikore.Li@Sun.COM /* never reach */ 1436*9485SMikore.Li@Sun.COM } 1437*9485SMikore.Li@Sun.COM } else { 1438*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type); 1439*9485SMikore.Li@Sun.COM /* never reach */ 1440*9485SMikore.Li@Sun.COM } 1441*9485SMikore.Li@Sun.COM 1442*9485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 0; 1443*9485SMikore.Li@Sun.COM return (0); 1444*9485SMikore.Li@Sun.COM } 1445*9485SMikore.Li@Sun.COM 1446*9485SMikore.Li@Sun.COM static usbd_status 1447*9485SMikore.Li@Sun.COM urtw_led_mode0(struct urtw_softc *sc, int mode) 1448*9485SMikore.Li@Sun.COM { 1449*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1450*9485SMikore.Li@Sun.COM "urtw_led_mode0: mode = %d\n", mode)); 1451*9485SMikore.Li@Sun.COM switch (mode) { 1452*9485SMikore.Li@Sun.COM case URTW_LED_CTL_POWER_ON: 1453*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK; 1454*9485SMikore.Li@Sun.COM break; 1455*9485SMikore.Li@Sun.COM case URTW_LED_CTL_TX: 1456*9485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress == 1) 1457*9485SMikore.Li@Sun.COM return (0); 1458*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL; 1459*9485SMikore.Li@Sun.COM sc->sc_gpio_blinktime = 1460*9485SMikore.Li@Sun.COM (sc->sc_ic.ic_state == IEEE80211_S_RUN ? 4:2); 1461*9485SMikore.Li@Sun.COM break; 1462*9485SMikore.Li@Sun.COM case URTW_LED_CTL_LINK: 1463*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_ON; 1464*9485SMikore.Li@Sun.COM break; 1465*9485SMikore.Li@Sun.COM default: 1466*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode 0x%x", mode); 1467*9485SMikore.Li@Sun.COM /* never reach */ 1468*9485SMikore.Li@Sun.COM } 1469*9485SMikore.Li@Sun.COM 1470*9485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) { 1471*9485SMikore.Li@Sun.COM case URTW_LED_ON: 1472*9485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0) 1473*9485SMikore.Li@Sun.COM break; 1474*9485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 1475*9485SMikore.Li@Sun.COM break; 1476*9485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL: 1477*9485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0) 1478*9485SMikore.Li@Sun.COM break; 1479*9485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 1; 1480*9485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ? 1481*9485SMikore.Li@Sun.COM URTW_LED_OFF : URTW_LED_ON; 1482*9485SMikore.Li@Sun.COM URTW_LEDLOCK(sc); 1483*9485SMikore.Li@Sun.COM if (sc->sc_led_ch == 0) { 1484*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1485*9485SMikore.Li@Sun.COM "urtw_led_mode0: restart led timer\n")); 1486*9485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch, 1487*9485SMikore.Li@Sun.COM (void *)sc, 1488*9485SMikore.Li@Sun.COM drv_usectohz((sc->sc_ic.ic_state == 1489*9485SMikore.Li@Sun.COM IEEE80211_S_RUN) ? 1490*9485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK : 1491*9485SMikore.Li@Sun.COM URTW_LED_LINKOFF_BLINK)); 1492*9485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 1493*9485SMikore.Li@Sun.COM } 1494*9485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 1495*9485SMikore.Li@Sun.COM break; 1496*9485SMikore.Li@Sun.COM case URTW_LED_POWER_ON_BLINK: 1497*9485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 1498*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 1499*9485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 1500*9485SMikore.Li@Sun.COM break; 1501*9485SMikore.Li@Sun.COM default: 1502*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1503*9485SMikore.Li@Sun.COM "urtw_led_mode0: unknown LED status 0x%x", 1504*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate)); 1505*9485SMikore.Li@Sun.COM } 1506*9485SMikore.Li@Sun.COM return (0); 1507*9485SMikore.Li@Sun.COM } 1508*9485SMikore.Li@Sun.COM 1509*9485SMikore.Li@Sun.COM static usbd_status 1510*9485SMikore.Li@Sun.COM urtw_led_mode1(struct urtw_softc *sc, int mode) 1511*9485SMikore.Li@Sun.COM { 1512*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 1513*9485SMikore.Li@Sun.COM return (USBD_INVAL); 1514*9485SMikore.Li@Sun.COM } 1515*9485SMikore.Li@Sun.COM 1516*9485SMikore.Li@Sun.COM static usbd_status 1517*9485SMikore.Li@Sun.COM urtw_led_mode2(struct urtw_softc *sc, int mode) 1518*9485SMikore.Li@Sun.COM { 1519*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 1520*9485SMikore.Li@Sun.COM return (USBD_INVAL); 1521*9485SMikore.Li@Sun.COM } 1522*9485SMikore.Li@Sun.COM 1523*9485SMikore.Li@Sun.COM static usbd_status 1524*9485SMikore.Li@Sun.COM urtw_led_mode3(struct urtw_softc *sc, int mode) 1525*9485SMikore.Li@Sun.COM { 1526*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode); 1527*9485SMikore.Li@Sun.COM return (USBD_INVAL); 1528*9485SMikore.Li@Sun.COM } 1529*9485SMikore.Li@Sun.COM 1530*9485SMikore.Li@Sun.COM static usbd_status 1531*9485SMikore.Li@Sun.COM urtw_led_blink(struct urtw_softc *sc) 1532*9485SMikore.Li@Sun.COM { 1533*9485SMikore.Li@Sun.COM uint8_t ing = 0; 1534*9485SMikore.Li@Sun.COM 1535*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1536*9485SMikore.Li@Sun.COM "urtw_led_blink: gpio_blinkstate %d\n", 1537*9485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate)); 1538*9485SMikore.Li@Sun.COM if (sc->sc_gpio_blinkstate == URTW_LED_ON) 1539*9485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 1540*9485SMikore.Li@Sun.COM else 1541*9485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 1542*9485SMikore.Li@Sun.COM sc->sc_gpio_blinktime--; 1543*9485SMikore.Li@Sun.COM if (sc->sc_gpio_blinktime == 0) 1544*9485SMikore.Li@Sun.COM ing = 1; 1545*9485SMikore.Li@Sun.COM else { 1546*9485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL && 1547*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY && 1548*9485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3) 1549*9485SMikore.Li@Sun.COM ing = 1; 1550*9485SMikore.Li@Sun.COM } 1551*9485SMikore.Li@Sun.COM if (ing == 1) { 1552*9485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate == URTW_LED_ON && 1553*9485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 0) 1554*9485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO); 1555*9485SMikore.Li@Sun.COM else if (sc->sc_gpio_ledstate == URTW_LED_OFF && 1556*9485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 1) 1557*9485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 1558*9485SMikore.Li@Sun.COM 1559*9485SMikore.Li@Sun.COM sc->sc_gpio_blinktime = 0; 1560*9485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 1561*9485SMikore.Li@Sun.COM return (0); 1562*9485SMikore.Li@Sun.COM } 1563*9485SMikore.Li@Sun.COM 1564*9485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ? 1565*9485SMikore.Li@Sun.COM URTW_LED_ON : URTW_LED_OFF; 1566*9485SMikore.Li@Sun.COM 1567*9485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) { 1568*9485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL: 1569*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1570*9485SMikore.Li@Sun.COM "URTW_LED_BLINK_NORMAL\n")); 1571*9485SMikore.Li@Sun.COM return (1); 1572*9485SMikore.Li@Sun.COM default: 1573*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 1574*9485SMikore.Li@Sun.COM "unknown LED status 0x%x", sc->sc_gpio_ledstate)); 1575*9485SMikore.Li@Sun.COM } 1576*9485SMikore.Li@Sun.COM return (0); 1577*9485SMikore.Li@Sun.COM } 1578*9485SMikore.Li@Sun.COM 1579*9485SMikore.Li@Sun.COM static usbd_status 1580*9485SMikore.Li@Sun.COM urtw_led_ctl(struct urtw_softc *sc, int mode) 1581*9485SMikore.Li@Sun.COM { 1582*9485SMikore.Li@Sun.COM usbd_status error = 0; 1583*9485SMikore.Li@Sun.COM 1584*9485SMikore.Li@Sun.COM switch (sc->sc_strategy) { 1585*9485SMikore.Li@Sun.COM case URTW_SW_LED_MODE0: 1586*9485SMikore.Li@Sun.COM error = urtw_led_mode0(sc, mode); 1587*9485SMikore.Li@Sun.COM break; 1588*9485SMikore.Li@Sun.COM case URTW_SW_LED_MODE1: 1589*9485SMikore.Li@Sun.COM error = urtw_led_mode1(sc, mode); 1590*9485SMikore.Li@Sun.COM break; 1591*9485SMikore.Li@Sun.COM case URTW_SW_LED_MODE2: 1592*9485SMikore.Li@Sun.COM error = urtw_led_mode2(sc, mode); 1593*9485SMikore.Li@Sun.COM break; 1594*9485SMikore.Li@Sun.COM case URTW_SW_LED_MODE3: 1595*9485SMikore.Li@Sun.COM error = urtw_led_mode3(sc, mode); 1596*9485SMikore.Li@Sun.COM break; 1597*9485SMikore.Li@Sun.COM default: 1598*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode %d\n", sc->sc_strategy); 1599*9485SMikore.Li@Sun.COM /* never reach */ 1600*9485SMikore.Li@Sun.COM return (-1); 1601*9485SMikore.Li@Sun.COM } 1602*9485SMikore.Li@Sun.COM 1603*9485SMikore.Li@Sun.COM return (error); 1604*9485SMikore.Li@Sun.COM } 1605*9485SMikore.Li@Sun.COM 1606*9485SMikore.Li@Sun.COM static usbd_status 1607*9485SMikore.Li@Sun.COM urtw_update_msr(struct urtw_softc *sc, int nstate) 1608*9485SMikore.Li@Sun.COM { 1609*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 1610*9485SMikore.Li@Sun.COM uint8_t data; 1611*9485SMikore.Li@Sun.COM usbd_status error; 1612*9485SMikore.Li@Sun.COM 1613*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_MSR, &data)) 1614*9485SMikore.Li@Sun.COM goto fail; 1615*9485SMikore.Li@Sun.COM data &= ~URTW_MSR_LINK_MASK; 1616*9485SMikore.Li@Sun.COM 1617*9485SMikore.Li@Sun.COM if (nstate == IEEE80211_S_RUN) { 1618*9485SMikore.Li@Sun.COM switch (ic->ic_opmode) { 1619*9485SMikore.Li@Sun.COM case IEEE80211_M_STA: 1620*9485SMikore.Li@Sun.COM case IEEE80211_M_MONITOR: 1621*9485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_STA; 1622*9485SMikore.Li@Sun.COM break; 1623*9485SMikore.Li@Sun.COM case IEEE80211_M_IBSS: 1624*9485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_ADHOC; 1625*9485SMikore.Li@Sun.COM break; 1626*9485SMikore.Li@Sun.COM case IEEE80211_M_HOSTAP: 1627*9485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_HOSTAP; 1628*9485SMikore.Li@Sun.COM break; 1629*9485SMikore.Li@Sun.COM default: 1630*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported operation mode 0x%x\n", 1631*9485SMikore.Li@Sun.COM ic->ic_opmode); 1632*9485SMikore.Li@Sun.COM return (-1); 1633*9485SMikore.Li@Sun.COM } 1634*9485SMikore.Li@Sun.COM } else 1635*9485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_NONE; 1636*9485SMikore.Li@Sun.COM 1637*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_MSR, data); 1638*9485SMikore.Li@Sun.COM drv_usecwait(10000); 1639*9485SMikore.Li@Sun.COM fail: 1640*9485SMikore.Li@Sun.COM return (error); 1641*9485SMikore.Li@Sun.COM } 1642*9485SMikore.Li@Sun.COM 1643*9485SMikore.Li@Sun.COM static uint16_t 1644*9485SMikore.Li@Sun.COM urtw_rate2rtl(int rate) 1645*9485SMikore.Li@Sun.COM { 1646*9485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 1647*9485SMikore.Li@Sun.COM int i; 1648*9485SMikore.Li@Sun.COM 1649*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) { 1650*9485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].reg) 1651*9485SMikore.Li@Sun.COM return (urtw_ratetable[i].val); 1652*9485SMikore.Li@Sun.COM } 1653*9485SMikore.Li@Sun.COM return (3); 1654*9485SMikore.Li@Sun.COM #undef N 1655*9485SMikore.Li@Sun.COM } 1656*9485SMikore.Li@Sun.COM 1657*9485SMikore.Li@Sun.COM static uint16_t 1658*9485SMikore.Li@Sun.COM urtw_rtl2rate(int rate) 1659*9485SMikore.Li@Sun.COM { 1660*9485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 1661*9485SMikore.Li@Sun.COM int i; 1662*9485SMikore.Li@Sun.COM 1663*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) { 1664*9485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].val) 1665*9485SMikore.Li@Sun.COM return (urtw_ratetable[i].reg); 1666*9485SMikore.Li@Sun.COM } 1667*9485SMikore.Li@Sun.COM 1668*9485SMikore.Li@Sun.COM return (0); 1669*9485SMikore.Li@Sun.COM #undef N 1670*9485SMikore.Li@Sun.COM } 1671*9485SMikore.Li@Sun.COM 1672*9485SMikore.Li@Sun.COM static usbd_status 1673*9485SMikore.Li@Sun.COM urtw_set_rate(struct urtw_softc *sc) 1674*9485SMikore.Li@Sun.COM { 1675*9485SMikore.Li@Sun.COM int i, basic_rate, min_rr_rate, max_rr_rate; 1676*9485SMikore.Li@Sun.COM uint16_t data; 1677*9485SMikore.Li@Sun.COM usbd_status error; 1678*9485SMikore.Li@Sun.COM 1679*9485SMikore.Li@Sun.COM basic_rate = urtw_rate2rtl(48); 1680*9485SMikore.Li@Sun.COM min_rr_rate = urtw_rate2rtl(12); 1681*9485SMikore.Li@Sun.COM max_rr_rate = urtw_rate2rtl(48); 1682*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RESP_RATE, 1683*9485SMikore.Li@Sun.COM max_rr_rate << URTW_RESP_MAX_RATE_SHIFT | 1684*9485SMikore.Li@Sun.COM min_rr_rate << URTW_RESP_MIN_RATE_SHIFT)) 1685*9485SMikore.Li@Sun.COM goto fail; 1686*9485SMikore.Li@Sun.COM 1687*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data)) 1688*9485SMikore.Li@Sun.COM goto fail; 1689*9485SMikore.Li@Sun.COM data &= ~URTW_BRSR_MBR_8185; 1690*9485SMikore.Li@Sun.COM 1691*9485SMikore.Li@Sun.COM for (i = 0; i <= basic_rate; i++) 1692*9485SMikore.Li@Sun.COM data |= (1 << i); 1693*9485SMikore.Li@Sun.COM 1694*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_BRSR, data); 1695*9485SMikore.Li@Sun.COM fail: 1696*9485SMikore.Li@Sun.COM return (error); 1697*9485SMikore.Li@Sun.COM } 1698*9485SMikore.Li@Sun.COM 1699*9485SMikore.Li@Sun.COM static usbd_status 1700*9485SMikore.Li@Sun.COM urtw_intr_enable(struct urtw_softc *sc) 1701*9485SMikore.Li@Sun.COM { 1702*9485SMikore.Li@Sun.COM usbd_status error; 1703*9485SMikore.Li@Sun.COM 1704*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0xffff); 1705*9485SMikore.Li@Sun.COM return (error); 1706*9485SMikore.Li@Sun.COM } 1707*9485SMikore.Li@Sun.COM 1708*9485SMikore.Li@Sun.COM static usbd_status 1709*9485SMikore.Li@Sun.COM urtw_adapter_start(struct urtw_softc *sc) 1710*9485SMikore.Li@Sun.COM { 1711*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 1712*9485SMikore.Li@Sun.COM usbd_status error; 1713*9485SMikore.Li@Sun.COM int i = 0; 1714*9485SMikore.Li@Sun.COM 1715*9485SMikore.Li@Sun.COM error = urtw_reset(sc); 1716*9485SMikore.Li@Sun.COM if (error) 1717*9485SMikore.Li@Sun.COM goto fail; 1718*9485SMikore.Li@Sun.COM 1719*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x85, 0)) 1720*9485SMikore.Li@Sun.COM goto fail; 1721*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0)) 1722*9485SMikore.Li@Sun.COM goto fail; 1723*9485SMikore.Li@Sun.COM 1724*9485SMikore.Li@Sun.COM /* for led */ 1725*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x85, 4)) 1726*9485SMikore.Li@Sun.COM goto fail; 1727*9485SMikore.Li@Sun.COM error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON); 1728*9485SMikore.Li@Sun.COM if (error != 0) 1729*9485SMikore.Li@Sun.COM goto fail; 1730*9485SMikore.Li@Sun.COM 1731*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 1732*9485SMikore.Li@Sun.COM if (error) 1733*9485SMikore.Li@Sun.COM goto fail; 1734*9485SMikore.Li@Sun.COM /* applying MAC address again. */ 1735*9485SMikore.Li@Sun.COM for (i = 0; i < IEEE80211_ADDR_LEN; i++) 1736*9485SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_MAC0 + i, 1737*9485SMikore.Li@Sun.COM ic->ic_macaddr[i]); 1738*9485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 1739*9485SMikore.Li@Sun.COM if (error) 1740*9485SMikore.Li@Sun.COM goto fail; 1741*9485SMikore.Li@Sun.COM 1742*9485SMikore.Li@Sun.COM error = urtw_update_msr(sc, IEEE80211_S_INIT); 1743*9485SMikore.Li@Sun.COM if (error) 1744*9485SMikore.Li@Sun.COM goto fail; 1745*9485SMikore.Li@Sun.COM 1746*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_INT_TIMEOUT, 0)) 1747*9485SMikore.Li@Sun.COM goto fail; 1748*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_WPA_CONFIG, 0)) 1749*9485SMikore.Li@Sun.COM goto fail; 1750*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RATE_FALLBACK, 0x81)) 1751*9485SMikore.Li@Sun.COM goto fail; 1752*9485SMikore.Li@Sun.COM error = urtw_set_rate(sc); 1753*9485SMikore.Li@Sun.COM if (error != 0) 1754*9485SMikore.Li@Sun.COM goto fail; 1755*9485SMikore.Li@Sun.COM 1756*9485SMikore.Li@Sun.COM error = sc->sc_rf_init(sc); 1757*9485SMikore.Li@Sun.COM if (error != 0) 1758*9485SMikore.Li@Sun.COM goto fail; 1759*9485SMikore.Li@Sun.COM if (sc->sc_rf_set_sens != NULL) 1760*9485SMikore.Li@Sun.COM sc->sc_rf_set_sens(sc, sc->sc_sens); 1761*9485SMikore.Li@Sun.COM 1762*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, 0x5e, 1)) 1763*9485SMikore.Li@Sun.COM goto fail; 1764*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, 0xfe, 0x10)) 1765*9485SMikore.Li@Sun.COM goto fail; 1766*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TALLY_SEL, 0x80)) 1767*9485SMikore.Li@Sun.COM goto fail; 1768*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0xff, 0x60)) 1769*9485SMikore.Li@Sun.COM goto fail; 1770*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, 0x5e, 0)) 1771*9485SMikore.Li@Sun.COM goto fail; 1772*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x85, 4)) 1773*9485SMikore.Li@Sun.COM goto fail; 1774*9485SMikore.Li@Sun.COM ic->ic_curchan = &ic->ic_sup_channels[1]; 1775*9485SMikore.Li@Sun.COM error = urtw_intr_enable(sc); 1776*9485SMikore.Li@Sun.COM if (error != 0) 1777*9485SMikore.Li@Sun.COM goto fail; 1778*9485SMikore.Li@Sun.COM 1779*9485SMikore.Li@Sun.COM fail: 1780*9485SMikore.Li@Sun.COM return (error); 1781*9485SMikore.Li@Sun.COM } 1782*9485SMikore.Li@Sun.COM 1783*9485SMikore.Li@Sun.COM static usbd_status 1784*9485SMikore.Li@Sun.COM urtw_rx_setconf(struct urtw_softc *sc) 1785*9485SMikore.Li@Sun.COM { 1786*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 1787*9485SMikore.Li@Sun.COM uint32_t data, a, b; 1788*9485SMikore.Li@Sun.COM usbd_status error; 1789*9485SMikore.Li@Sun.COM 1790*9485SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data)) 1791*9485SMikore.Li@Sun.COM goto fail; 1792*9485SMikore.Li@Sun.COM data = data &~ URTW_RX_FILTER_MASK; 1793*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA; 1794*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST; 1795*9485SMikore.Li@Sun.COM 1796*9485SMikore.Li@Sun.COM if (ic->ic_opmode == IEEE80211_M_MONITOR) { 1797*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_ICVERR; 1798*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_PWR; 1799*9485SMikore.Li@Sun.COM } 1800*9485SMikore.Li@Sun.COM if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) 1801*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_CRCERR; 1802*9485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_NICMAC; 1803*9485SMikore.Li@Sun.COM data = data | URTW_RX_CHECK_BSSID; 1804*9485SMikore.Li@Sun.COM data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; 1805*9485SMikore.Li@Sun.COM data = data | URTW_RX_FIFO_THRESHOLD_NONE | URTW_RX_AUTORESETPHY; 1806*9485SMikore.Li@Sun.COM data = data &~ URTW_MAX_RX_DMA_MASK; 1807*9485SMikore.Li@Sun.COM a = URTW_MAX_RX_DMA_2048; 1808*9485SMikore.Li@Sun.COM b = 0x80000000; 1809*9485SMikore.Li@Sun.COM data = data | a | b; 1810*9485SMikore.Li@Sun.COM 1811*9485SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_RX, data); 1812*9485SMikore.Li@Sun.COM fail: 1813*9485SMikore.Li@Sun.COM return (error); 1814*9485SMikore.Li@Sun.COM } 1815*9485SMikore.Li@Sun.COM 1816*9485SMikore.Li@Sun.COM static usbd_status 1817*9485SMikore.Li@Sun.COM urtw_rx_enable(struct urtw_softc *sc) 1818*9485SMikore.Li@Sun.COM { 1819*9485SMikore.Li@Sun.COM int i; 1820*9485SMikore.Li@Sun.COM usbd_status error; 1821*9485SMikore.Li@Sun.COM uint8_t data; 1822*9485SMikore.Li@Sun.COM 1823*9485SMikore.Li@Sun.COM sc->rx_queued = 0; 1824*9485SMikore.Li@Sun.COM for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) { 1825*9485SMikore.Li@Sun.COM if (urtw_rx_start(sc) != 0) { 1826*9485SMikore.Li@Sun.COM return (USB_FAILURE); 1827*9485SMikore.Li@Sun.COM } 1828*9485SMikore.Li@Sun.COM } 1829*9485SMikore.Li@Sun.COM 1830*9485SMikore.Li@Sun.COM error = urtw_rx_setconf(sc); 1831*9485SMikore.Li@Sun.COM if (error != 0) 1832*9485SMikore.Li@Sun.COM goto fail; 1833*9485SMikore.Li@Sun.COM 1834*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data)) 1835*9485SMikore.Li@Sun.COM goto fail; 1836*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE); 1837*9485SMikore.Li@Sun.COM fail: 1838*9485SMikore.Li@Sun.COM return (error); 1839*9485SMikore.Li@Sun.COM } 1840*9485SMikore.Li@Sun.COM 1841*9485SMikore.Li@Sun.COM static usbd_status 1842*9485SMikore.Li@Sun.COM urtw_tx_enable(struct urtw_softc *sc) 1843*9485SMikore.Li@Sun.COM { 1844*9485SMikore.Li@Sun.COM uint8_t data8; 1845*9485SMikore.Li@Sun.COM uint32_t data; 1846*9485SMikore.Li@Sun.COM usbd_status error; 1847*9485SMikore.Li@Sun.COM 1848*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CW_CONF, &data8)) 1849*9485SMikore.Li@Sun.COM goto fail; 1850*9485SMikore.Li@Sun.COM data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY); 1851*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_CONF, data8)) 1852*9485SMikore.Li@Sun.COM goto fail; 1853*9485SMikore.Li@Sun.COM 1854*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_TX_AGC_CTL, &data8)) 1855*9485SMikore.Li@Sun.COM goto fail; 1856*9485SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; 1857*9485SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; 1858*9485SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; 1859*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_AGC_CTL, data8)) 1860*9485SMikore.Li@Sun.COM goto fail; 1861*9485SMikore.Li@Sun.COM 1862*9485SMikore.Li@Sun.COM if (error = urtw_read32_c(sc, URTW_TX_CONF, &data)) 1863*9485SMikore.Li@Sun.COM goto fail; 1864*9485SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK; 1865*9485SMikore.Li@Sun.COM data |= URTW_TX_LOOPBACK_NONE; 1866*9485SMikore.Li@Sun.COM data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); 1867*9485SMikore.Li@Sun.COM data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; 1868*9485SMikore.Li@Sun.COM data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; 1869*9485SMikore.Li@Sun.COM data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); 1870*9485SMikore.Li@Sun.COM data |= URTW_TX_MXDMA_2048 | 0x80000000 | URTW_TX_DISCW; 1871*9485SMikore.Li@Sun.COM data &= ~URTW_TX_SWPLCPLEN; 1872*9485SMikore.Li@Sun.COM data |= URTW_TX_NOICV; 1873*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_TX_CONF, data)) 1874*9485SMikore.Li@Sun.COM goto fail; 1875*9485SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data8)) 1876*9485SMikore.Li@Sun.COM goto fail; 1877*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE); 1878*9485SMikore.Li@Sun.COM fail: 1879*9485SMikore.Li@Sun.COM return (error); 1880*9485SMikore.Li@Sun.COM } 1881*9485SMikore.Li@Sun.COM 1882*9485SMikore.Li@Sun.COM static int 1883*9485SMikore.Li@Sun.COM urtw_init(void *arg) 1884*9485SMikore.Li@Sun.COM { 1885*9485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 1886*9485SMikore.Li@Sun.COM usbd_status error; 1887*9485SMikore.Li@Sun.COM 1888*9485SMikore.Li@Sun.COM urtw_stop(sc); 1889*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 1890*9485SMikore.Li@Sun.COM error = urtw_open_pipes(sc); 1891*9485SMikore.Li@Sun.COM if (error != 0) 1892*9485SMikore.Li@Sun.COM goto fail; 1893*9485SMikore.Li@Sun.COM error = urtw_adapter_start(sc); 1894*9485SMikore.Li@Sun.COM if (error != 0) 1895*9485SMikore.Li@Sun.COM goto fail; 1896*9485SMikore.Li@Sun.COM sc->sc_tx_low_queued = 0; 1897*9485SMikore.Li@Sun.COM sc->sc_tx_normal_queued = 0; 1898*9485SMikore.Li@Sun.COM error = urtw_rx_enable(sc); 1899*9485SMikore.Li@Sun.COM if (error != 0) 1900*9485SMikore.Li@Sun.COM goto fail; 1901*9485SMikore.Li@Sun.COM error = urtw_tx_enable(sc); 1902*9485SMikore.Li@Sun.COM if (error != 0) 1903*9485SMikore.Li@Sun.COM goto fail; 1904*9485SMikore.Li@Sun.COM 1905*9485SMikore.Li@Sun.COM if (error == 0) { 1906*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, 1907*9485SMikore.Li@Sun.COM CE_CONT, "urtw_init: succesfully done\n")); 1908*9485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_RUNNING; 1909*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 1910*9485SMikore.Li@Sun.COM return (error); 1911*9485SMikore.Li@Sun.COM } 1912*9485SMikore.Li@Sun.COM 1913*9485SMikore.Li@Sun.COM fail: 1914*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 1915*9485SMikore.Li@Sun.COM urtw_stop(sc); 1916*9485SMikore.Li@Sun.COM return (error); 1917*9485SMikore.Li@Sun.COM } 1918*9485SMikore.Li@Sun.COM 1919*9485SMikore.Li@Sun.COM 1920*9485SMikore.Li@Sun.COM static usbd_status 1921*9485SMikore.Li@Sun.COM urtw_8225_usb_init(struct urtw_softc *sc) 1922*9485SMikore.Li@Sun.COM { 1923*9485SMikore.Li@Sun.COM uint8_t data; 1924*9485SMikore.Li@Sun.COM usbd_status error; 1925*9485SMikore.Li@Sun.COM 1926*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 0)) 1927*9485SMikore.Li@Sun.COM goto fail; 1928*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0)) 1929*9485SMikore.Li@Sun.COM goto fail; 1930*9485SMikore.Li@Sun.COM if (error = urtw_read8e(sc, 0x53, &data)) 1931*9485SMikore.Li@Sun.COM goto fail; 1932*9485SMikore.Li@Sun.COM if (error = urtw_write8e(sc, 0x53, data | (1 << 7))) 1933*9485SMikore.Li@Sun.COM goto fail; 1934*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 4)) 1935*9485SMikore.Li@Sun.COM goto fail; 1936*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0x20)) 1937*9485SMikore.Li@Sun.COM goto fail; 1938*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GP_ENABLE, 0)) 1939*9485SMikore.Li@Sun.COM goto fail; 1940*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x80)) 1941*9485SMikore.Li@Sun.COM goto fail; 1942*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x80)) 1943*9485SMikore.Li@Sun.COM goto fail; 1944*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x80); 1945*9485SMikore.Li@Sun.COM 1946*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 1947*9485SMikore.Li@Sun.COM fail: 1948*9485SMikore.Li@Sun.COM return (error); 1949*9485SMikore.Li@Sun.COM } 1950*9485SMikore.Li@Sun.COM 1951*9485SMikore.Li@Sun.COM static usbd_status 1952*9485SMikore.Li@Sun.COM urtw_8185_rf_pins_enable(struct urtw_softc *sc) 1953*9485SMikore.Li@Sun.COM { 1954*9485SMikore.Li@Sun.COM usbd_status error = 0; 1955*9485SMikore.Li@Sun.COM 1956*9485SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1ff7); 1957*9485SMikore.Li@Sun.COM return (error); 1958*9485SMikore.Li@Sun.COM } 1959*9485SMikore.Li@Sun.COM 1960*9485SMikore.Li@Sun.COM static usbd_status 1961*9485SMikore.Li@Sun.COM urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) 1962*9485SMikore.Li@Sun.COM { 1963*9485SMikore.Li@Sun.COM uint32_t phyw; 1964*9485SMikore.Li@Sun.COM usbd_status error; 1965*9485SMikore.Li@Sun.COM 1966*9485SMikore.Li@Sun.COM phyw = ((data << 8) | (addr | 0x80)); 1967*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7f, ((phyw & 0xff000000) >> 24))) 1968*9485SMikore.Li@Sun.COM goto fail; 1969*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7e, ((phyw & 0x00ff0000) >> 16))) 1970*9485SMikore.Li@Sun.COM goto fail; 1971*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7d, ((phyw & 0x0000ff00) >> 8))) 1972*9485SMikore.Li@Sun.COM goto fail; 1973*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, 0x7c, ((phyw & 0x000000ff))); 1974*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 1975*9485SMikore.Li@Sun.COM fail: 1976*9485SMikore.Li@Sun.COM return (error); 1977*9485SMikore.Li@Sun.COM } 1978*9485SMikore.Li@Sun.COM 1979*9485SMikore.Li@Sun.COM static usbd_status 1980*9485SMikore.Li@Sun.COM urtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 1981*9485SMikore.Li@Sun.COM { 1982*9485SMikore.Li@Sun.COM data = data & 0xff; 1983*9485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, data)); 1984*9485SMikore.Li@Sun.COM } 1985*9485SMikore.Li@Sun.COM 1986*9485SMikore.Li@Sun.COM static usbd_status 1987*9485SMikore.Li@Sun.COM urtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 1988*9485SMikore.Li@Sun.COM { 1989*9485SMikore.Li@Sun.COM data = data & 0xff; 1990*9485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, (data | 0x10000))); 1991*9485SMikore.Li@Sun.COM } 1992*9485SMikore.Li@Sun.COM 1993*9485SMikore.Li@Sun.COM static usbd_status 1994*9485SMikore.Li@Sun.COM urtw_8225_setgain(struct urtw_softc *sc, int16_t gain) 1995*9485SMikore.Li@Sun.COM { 1996*9485SMikore.Li@Sun.COM usbd_status error; 1997*9485SMikore.Li@Sun.COM 1998*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d, 1999*9485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4])) 2000*9485SMikore.Li@Sun.COM goto fail; 2001*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b, 2002*9485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 2])) 2003*9485SMikore.Li@Sun.COM goto fail; 2004*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d, 2005*9485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 3])) 2006*9485SMikore.Li@Sun.COM goto fail; 2007*9485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x23, 2008*9485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 1]); 2009*9485SMikore.Li@Sun.COM fail: 2010*9485SMikore.Li@Sun.COM return (error); 2011*9485SMikore.Li@Sun.COM } 2012*9485SMikore.Li@Sun.COM 2013*9485SMikore.Li@Sun.COM static usbd_status 2014*9485SMikore.Li@Sun.COM urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan) 2015*9485SMikore.Li@Sun.COM { 2016*9485SMikore.Li@Sun.COM int i, idx, set; 2017*9485SMikore.Li@Sun.COM uint8_t *cck_pwltable; 2018*9485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max; 2019*9485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 2020*9485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 2021*9485SMikore.Li@Sun.COM usbd_status error; 2022*9485SMikore.Li@Sun.COM 2023*9485SMikore.Li@Sun.COM cck_pwrlvl_max = 11; 2024*9485SMikore.Li@Sun.COM ofdm_pwrlvl_max = 25; /* 12 -> 25 */ 2025*9485SMikore.Li@Sun.COM ofdm_pwrlvl_min = 10; 2026*9485SMikore.Li@Sun.COM 2027*9485SMikore.Li@Sun.COM /* CCK power setting */ 2028*9485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? 2029*9485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl; 2030*9485SMikore.Li@Sun.COM idx = cck_pwrlvl % 6; 2031*9485SMikore.Li@Sun.COM set = cck_pwrlvl / 6; 2032*9485SMikore.Li@Sun.COM cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 : 2033*9485SMikore.Li@Sun.COM urtw_8225_txpwr_cck; 2034*9485SMikore.Li@Sun.COM 2035*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK, 2036*9485SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1)) 2037*9485SMikore.Li@Sun.COM goto fail; 2038*9485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) { 2039*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i, 2040*9485SMikore.Li@Sun.COM cck_pwltable[idx * 8 + i])) 2041*9485SMikore.Li@Sun.COM goto fail; 2042*9485SMikore.Li@Sun.COM } 2043*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2044*9485SMikore.Li@Sun.COM /* OFDM power setting */ 2045*9485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 2046*9485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 2047*9485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 2048*9485SMikore.Li@Sun.COM idx = ofdm_pwrlvl % 6; 2049*9485SMikore.Li@Sun.COM set = ofdm_pwrlvl / 6; 2050*9485SMikore.Li@Sun.COM 2051*9485SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 2052*9485SMikore.Li@Sun.COM if (error) 2053*9485SMikore.Li@Sun.COM goto fail; 2054*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42)) 2055*9485SMikore.Li@Sun.COM goto fail; 2056*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0)) 2057*9485SMikore.Li@Sun.COM goto fail; 2058*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0)) 2059*9485SMikore.Li@Sun.COM goto fail; 2060*9485SMikore.Li@Sun.COM 2061*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 2062*9485SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1)) 2063*9485SMikore.Li@Sun.COM goto fail; 2064*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x5, 2065*9485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx])) 2066*9485SMikore.Li@Sun.COM goto fail; 2067*9485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x7, 2068*9485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx]); 2069*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2070*9485SMikore.Li@Sun.COM fail: 2071*9485SMikore.Li@Sun.COM return (error); 2072*9485SMikore.Li@Sun.COM } 2073*9485SMikore.Li@Sun.COM 2074*9485SMikore.Li@Sun.COM static usbd_status 2075*9485SMikore.Li@Sun.COM urtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant) 2076*9485SMikore.Li@Sun.COM { 2077*9485SMikore.Li@Sun.COM usbd_status error; 2078*9485SMikore.Li@Sun.COM 2079*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_ANTENNA, ant); 2080*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2081*9485SMikore.Li@Sun.COM return (error); 2082*9485SMikore.Li@Sun.COM } 2083*9485SMikore.Li@Sun.COM 2084*9485SMikore.Li@Sun.COM static usbd_status 2085*9485SMikore.Li@Sun.COM urtw_8225_rf_init(struct urtw_softc *sc) 2086*9485SMikore.Li@Sun.COM { 2087*9485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0])) 2088*9485SMikore.Li@Sun.COM int i; 2089*9485SMikore.Li@Sun.COM uint16_t data; 2090*9485SMikore.Li@Sun.COM usbd_status error; 2091*9485SMikore.Li@Sun.COM 2092*9485SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 2093*9485SMikore.Li@Sun.COM if (error) 2094*9485SMikore.Li@Sun.COM goto fail; 2095*9485SMikore.Li@Sun.COM 2096*9485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc)) 2097*9485SMikore.Li@Sun.COM goto fail; 2098*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008)) 2099*9485SMikore.Li@Sun.COM goto fail; 2100*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data)) 2101*9485SMikore.Li@Sun.COM goto fail; 2102*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff)) 2103*9485SMikore.Li@Sun.COM goto fail; 2104*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044)) 2105*9485SMikore.Li@Sun.COM goto fail; 2106*9485SMikore.Li@Sun.COM 2107*9485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG)) 2108*9485SMikore.Li@Sun.COM goto fail; 2109*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44)) 2110*9485SMikore.Li@Sun.COM goto fail; 2111*9485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL)) 2112*9485SMikore.Li@Sun.COM goto fail; 2113*9485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc)) 2114*9485SMikore.Li@Sun.COM goto fail; 2115*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 2116*9485SMikore.Li@Sun.COM 2117*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part1); i++) { 2118*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225_rf_part1[i].reg, 2119*9485SMikore.Li@Sun.COM urtw_8225_rf_part1[i].val)) 2120*9485SMikore.Li@Sun.COM goto fail; 2121*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2122*9485SMikore.Li@Sun.COM } 2123*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 2124*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d)) 2125*9485SMikore.Li@Sun.COM goto fail; 2126*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 2127*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d)) 2128*9485SMikore.Li@Sun.COM goto fail; 2129*9485SMikore.Li@Sun.COM urtw_delay_ms(50); 2130*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x127)) 2131*9485SMikore.Li@Sun.COM goto fail; 2132*9485SMikore.Li@Sun.COM 2133*9485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) { 2134*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1))) 2135*9485SMikore.Li@Sun.COM goto fail; 2136*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225_rxgain[i])) 2137*9485SMikore.Li@Sun.COM goto fail; 2138*9485SMikore.Li@Sun.COM } 2139*9485SMikore.Li@Sun.COM 2140*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x27)) 2141*9485SMikore.Li@Sun.COM goto fail; 2142*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x22f)) 2143*9485SMikore.Li@Sun.COM goto fail; 2144*9485SMikore.Li@Sun.COM 2145*9485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) { 2146*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb, 2147*9485SMikore.Li@Sun.COM urtw_8225_agc[i])) 2148*9485SMikore.Li@Sun.COM goto fail; 2149*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2150*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa, 2151*9485SMikore.Li@Sun.COM (uint8_t)i + 0x80)) 2152*9485SMikore.Li@Sun.COM goto fail; 2153*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2154*9485SMikore.Li@Sun.COM } 2155*9485SMikore.Li@Sun.COM 2156*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part2); i++) { 2157*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2158*9485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].reg, 2159*9485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].val)) 2160*9485SMikore.Li@Sun.COM goto fail; 2161*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2162*9485SMikore.Li@Sun.COM } 2163*9485SMikore.Li@Sun.COM error = urtw_8225_setgain(sc, 4); 2164*9485SMikore.Li@Sun.COM if (error) 2165*9485SMikore.Li@Sun.COM goto fail; 2166*9485SMikore.Li@Sun.COM 2167*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part3); i++) { 2168*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 2169*9485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].reg, 2170*9485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].val)) 2171*9485SMikore.Li@Sun.COM goto fail; 2172*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2173*9485SMikore.Li@Sun.COM } 2174*9485SMikore.Li@Sun.COM 2175*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d)) 2176*9485SMikore.Li@Sun.COM goto fail; 2177*9485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, 1)) 2178*9485SMikore.Li@Sun.COM goto fail; 2179*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b)) 2180*9485SMikore.Li@Sun.COM goto fail; 2181*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2182*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90)) 2183*9485SMikore.Li@Sun.COM goto fail; 2184*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2185*9485SMikore.Li@Sun.COM 2186*9485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */ 2187*9485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3)) 2188*9485SMikore.Li@Sun.COM goto fail; 2189*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002)) 2190*9485SMikore.Li@Sun.COM goto fail; 2191*9485SMikore.Li@Sun.COM 2192*9485SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(sc, 1); 2193*9485SMikore.Li@Sun.COM fail: 2194*9485SMikore.Li@Sun.COM return (error); 2195*9485SMikore.Li@Sun.COM #undef N 2196*9485SMikore.Li@Sun.COM } 2197*9485SMikore.Li@Sun.COM 2198*9485SMikore.Li@Sun.COM static usbd_status 2199*9485SMikore.Li@Sun.COM urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan) 2200*9485SMikore.Li@Sun.COM { 2201*9485SMikore.Li@Sun.COM #define IEEE80211_CHAN_G \ 2202*9485SMikore.Li@Sun.COM (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2203*9485SMikore.Li@Sun.COM #define IEEE80211_IS_CHAN_G(_c) \ 2204*9485SMikore.Li@Sun.COM (((_c)->ich_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 2205*9485SMikore.Li@Sun.COM 2206*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2207*9485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 2208*9485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0; 2209*9485SMikore.Li@Sun.COM usbd_status error; 2210*9485SMikore.Li@Sun.COM 2211*9485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, chan)) 2212*9485SMikore.Li@Sun.COM goto fail; 2213*9485SMikore.Li@Sun.COM if (urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan])) 2214*9485SMikore.Li@Sun.COM goto fail; 2215*9485SMikore.Li@Sun.COM urtw_delay_ms(10); 2216*9485SMikore.Li@Sun.COM 2217*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22)) 2218*9485SMikore.Li@Sun.COM goto fail; 2219*9485SMikore.Li@Sun.COM 2220*9485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC && 2221*9485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT) 2222*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9)) 2223*9485SMikore.Li@Sun.COM goto fail; 2224*9485SMikore.Li@Sun.COM else 2225*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14)) 2226*9485SMikore.Li@Sun.COM goto fail; 2227*9485SMikore.Li@Sun.COM if (gset) { 2228*9485SMikore.Li@Sun.COM /* for G */ 2229*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14)) 2230*9485SMikore.Li@Sun.COM goto fail; 2231*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14)) 2232*9485SMikore.Li@Sun.COM goto fail; 2233*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0x73); 2234*9485SMikore.Li@Sun.COM } else { 2235*9485SMikore.Li@Sun.COM /* for B */ 2236*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24)) 2237*9485SMikore.Li@Sun.COM goto fail; 2238*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24)) 2239*9485SMikore.Li@Sun.COM goto fail; 2240*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5); 2241*9485SMikore.Li@Sun.COM } 2242*9485SMikore.Li@Sun.COM 2243*9485SMikore.Li@Sun.COM fail: 2244*9485SMikore.Li@Sun.COM return (error); 2245*9485SMikore.Li@Sun.COM } 2246*9485SMikore.Li@Sun.COM 2247*9485SMikore.Li@Sun.COM static usbd_status 2248*9485SMikore.Li@Sun.COM urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens) 2249*9485SMikore.Li@Sun.COM { 2250*9485SMikore.Li@Sun.COM usbd_status error; 2251*9485SMikore.Li@Sun.COM 2252*9485SMikore.Li@Sun.COM if (sens < 0 || sens > 6) 2253*9485SMikore.Li@Sun.COM return (-1); 2254*9485SMikore.Li@Sun.COM 2255*9485SMikore.Li@Sun.COM if (sens > 4) 2256*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x850)) 2257*9485SMikore.Li@Sun.COM goto fail; 2258*9485SMikore.Li@Sun.COM else 2259*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x50)) 2260*9485SMikore.Li@Sun.COM goto fail; 2261*9485SMikore.Li@Sun.COM 2262*9485SMikore.Li@Sun.COM sens = 6 - sens; 2263*9485SMikore.Li@Sun.COM if (error = urtw_8225_setgain(sc, sens)) 2264*9485SMikore.Li@Sun.COM goto fail; 2265*9485SMikore.Li@Sun.COM error = urtw_8187_write_phy_cck_c(sc, 0x41, urtw_8225_threshold[sens]); 2266*9485SMikore.Li@Sun.COM fail: 2267*9485SMikore.Li@Sun.COM return (error); 2268*9485SMikore.Li@Sun.COM } 2269*9485SMikore.Li@Sun.COM 2270*9485SMikore.Li@Sun.COM static void 2271*9485SMikore.Li@Sun.COM urtw_stop(struct urtw_softc *sc) 2272*9485SMikore.Li@Sun.COM { 2273*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 2274*9485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_RUNNING; 2275*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 2276*9485SMikore.Li@Sun.COM urtw_close_pipes(sc); 2277*9485SMikore.Li@Sun.COM } 2278*9485SMikore.Li@Sun.COM 2279*9485SMikore.Li@Sun.COM static int 2280*9485SMikore.Li@Sun.COM urtw_isbmode(uint16_t rate) 2281*9485SMikore.Li@Sun.COM { 2282*9485SMikore.Li@Sun.COM 2283*9485SMikore.Li@Sun.COM rate = urtw_rtl2rate(rate); 2284*9485SMikore.Li@Sun.COM 2285*9485SMikore.Li@Sun.COM return ((rate <= 22 && rate != 12 && rate != 18)?(1) : (0)); 2286*9485SMikore.Li@Sun.COM } 2287*9485SMikore.Li@Sun.COM 2288*9485SMikore.Li@Sun.COM /* ARGSUSED */ 2289*9485SMikore.Li@Sun.COM static void 2290*9485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 2291*9485SMikore.Li@Sun.COM { 2292*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 2293*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2294*9485SMikore.Li@Sun.COM int actlen, len, flen, rssi; 2295*9485SMikore.Li@Sun.COM uint8_t *desc, rate; 2296*9485SMikore.Li@Sun.COM struct ieee80211_frame *wh; 2297*9485SMikore.Li@Sun.COM struct ieee80211_node *ni = 0; 2298*9485SMikore.Li@Sun.COM mblk_t *mp = 0; 2299*9485SMikore.Li@Sun.COM uint8_t *rxbuf; 2300*9485SMikore.Li@Sun.COM 2301*9485SMikore.Li@Sun.COM mp = req->bulk_data; 2302*9485SMikore.Li@Sun.COM req->bulk_data = NULL; 2303*9485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK || 2304*9485SMikore.Li@Sun.COM mp == NULL) { 2305*9485SMikore.Li@Sun.COM sc->sc_rx_err++; 2306*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 2307*9485SMikore.Li@Sun.COM "urtw_rxeof failed! %d\n", 2308*9485SMikore.Li@Sun.COM req->bulk_completion_reason)); 2309*9485SMikore.Li@Sun.COM req->bulk_data = mp; 2310*9485SMikore.Li@Sun.COM goto fail; 2311*9485SMikore.Li@Sun.COM } 2312*9485SMikore.Li@Sun.COM 2313*9485SMikore.Li@Sun.COM actlen = MBLKL(mp); 2314*9485SMikore.Li@Sun.COM rxbuf = (uint8_t *)mp->b_rptr; 2315*9485SMikore.Li@Sun.COM 2316*9485SMikore.Li@Sun.COM /* 4 dword and 4 byte CRC */ 2317*9485SMikore.Li@Sun.COM len = actlen - (4 * 4); 2318*9485SMikore.Li@Sun.COM desc = rxbuf + len; 2319*9485SMikore.Li@Sun.COM flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff); 2320*9485SMikore.Li@Sun.COM if (flen > actlen) { 2321*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_rxeof: impossible: flen %d, actlen %d\n", 2322*9485SMikore.Li@Sun.COM flen, actlen); 2323*9485SMikore.Li@Sun.COM sc->sc_rx_err++; 2324*9485SMikore.Li@Sun.COM req->bulk_data = mp; 2325*9485SMikore.Li@Sun.COM goto fail; 2326*9485SMikore.Li@Sun.COM } 2327*9485SMikore.Li@Sun.COM 2328*9485SMikore.Li@Sun.COM rate = (desc[2] & 0xf0) >> 4; 2329*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 2330*9485SMikore.Li@Sun.COM "urtw_rxeof: rate is %u\n", rate)); 2331*9485SMikore.Li@Sun.COM /* XXX correct? */ 2332*9485SMikore.Li@Sun.COM rssi = (desc[6] & 0xfe) >> 1; 2333*9485SMikore.Li@Sun.COM if (!urtw_isbmode(rate)) { 2334*9485SMikore.Li@Sun.COM rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi); 2335*9485SMikore.Li@Sun.COM rssi = ((90 - rssi) * 100) / 65; 2336*9485SMikore.Li@Sun.COM } else { 2337*9485SMikore.Li@Sun.COM rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi); 2338*9485SMikore.Li@Sun.COM rssi = ((95 - rssi) * 100) / 65; 2339*9485SMikore.Li@Sun.COM } 2340*9485SMikore.Li@Sun.COM 2341*9485SMikore.Li@Sun.COM mp->b_wptr = mp->b_rptr + flen - 4; 2342*9485SMikore.Li@Sun.COM 2343*9485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)mp->b_rptr; 2344*9485SMikore.Li@Sun.COM if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) 2345*9485SMikore.Li@Sun.COM == IEEE80211_FC0_TYPE_DATA) { 2346*9485SMikore.Li@Sun.COM sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; 2347*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT, 2348*9485SMikore.Li@Sun.COM "urtw_rxeof: update sc_currate to %u\n", 2349*9485SMikore.Li@Sun.COM sc->sc_currate)); 2350*9485SMikore.Li@Sun.COM } 2351*9485SMikore.Li@Sun.COM ni = ieee80211_find_rxnode(ic, wh); 2352*9485SMikore.Li@Sun.COM 2353*9485SMikore.Li@Sun.COM /* send the frame to the 802.11 layer */ 2354*9485SMikore.Li@Sun.COM (void) ieee80211_input(ic, mp, ni, rssi, 0); 2355*9485SMikore.Li@Sun.COM 2356*9485SMikore.Li@Sun.COM /* node is no longer needed */ 2357*9485SMikore.Li@Sun.COM ieee80211_free_node(ni); 2358*9485SMikore.Li@Sun.COM fail: 2359*9485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock); 2360*9485SMikore.Li@Sun.COM sc->rx_queued--; 2361*9485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock); 2362*9485SMikore.Li@Sun.COM usb_free_bulk_req(req); 2363*9485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && !URTW_IS_SUSPENDING(sc)) 2364*9485SMikore.Li@Sun.COM (void) urtw_rx_start(sc); 2365*9485SMikore.Li@Sun.COM } 2366*9485SMikore.Li@Sun.COM 2367*9485SMikore.Li@Sun.COM static usbd_status 2368*9485SMikore.Li@Sun.COM urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain) 2369*9485SMikore.Li@Sun.COM { 2370*9485SMikore.Li@Sun.COM uint8_t *gainp; 2371*9485SMikore.Li@Sun.COM usbd_status error; 2372*9485SMikore.Li@Sun.COM 2373*9485SMikore.Li@Sun.COM /* XXX for A? */ 2374*9485SMikore.Li@Sun.COM gainp = urtw_8225v2_gain_bg; 2375*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d, gainp[gain * 3])) 2376*9485SMikore.Li@Sun.COM goto fail; 2377*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2378*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b, gainp[gain * 3 + 1])) 2379*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2380*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d, gainp[gain * 3 + 2])) 2381*9485SMikore.Li@Sun.COM goto fail; 2382*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2383*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x21, 0x17)) 2384*9485SMikore.Li@Sun.COM goto fail; 2385*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2386*9485SMikore.Li@Sun.COM fail: 2387*9485SMikore.Li@Sun.COM return (error); 2388*9485SMikore.Li@Sun.COM } 2389*9485SMikore.Li@Sun.COM 2390*9485SMikore.Li@Sun.COM static usbd_status 2391*9485SMikore.Li@Sun.COM urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan) 2392*9485SMikore.Li@Sun.COM { 2393*9485SMikore.Li@Sun.COM int i; 2394*9485SMikore.Li@Sun.COM uint8_t *cck_pwrtable; 2395*9485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10; 2396*9485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 2397*9485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 2398*9485SMikore.Li@Sun.COM usbd_status error; 2399*9485SMikore.Li@Sun.COM 2400*9485SMikore.Li@Sun.COM /* CCK power setting */ 2401*9485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? 2402*9485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl; 2403*9485SMikore.Li@Sun.COM cck_pwrlvl += sc->sc_txpwr_cck_base; 2404*9485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; 2405*9485SMikore.Li@Sun.COM cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : 2406*9485SMikore.Li@Sun.COM urtw_8225v2_txpwr_cck; 2407*9485SMikore.Li@Sun.COM 2408*9485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) { 2409*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i, 2410*9485SMikore.Li@Sun.COM cck_pwrtable[i])) 2411*9485SMikore.Li@Sun.COM goto fail; 2412*9485SMikore.Li@Sun.COM } 2413*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK, 2414*9485SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl])) 2415*9485SMikore.Li@Sun.COM goto fail; 2416*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2417*9485SMikore.Li@Sun.COM 2418*9485SMikore.Li@Sun.COM /* OFDM power setting */ 2419*9485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 2420*9485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 2421*9485SMikore.Li@Sun.COM ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; 2422*9485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 2423*9485SMikore.Li@Sun.COM 2424*9485SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 2425*9485SMikore.Li@Sun.COM if (error) 2426*9485SMikore.Li@Sun.COM goto fail; 2427*9485SMikore.Li@Sun.COM 2428*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42)) 2429*9485SMikore.Li@Sun.COM goto fail; 2430*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 5, 0x0)) 2431*9485SMikore.Li@Sun.COM goto fail; 2432*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0x40)) 2433*9485SMikore.Li@Sun.COM goto fail; 2434*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 7, 0x0)) 2435*9485SMikore.Li@Sun.COM goto fail; 2436*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0x40)) 2437*9485SMikore.Li@Sun.COM goto fail; 2438*9485SMikore.Li@Sun.COM 2439*9485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 2440*9485SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]); 2441*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2442*9485SMikore.Li@Sun.COM fail: 2443*9485SMikore.Li@Sun.COM return (error); 2444*9485SMikore.Li@Sun.COM } 2445*9485SMikore.Li@Sun.COM 2446*9485SMikore.Li@Sun.COM static usbd_status 2447*9485SMikore.Li@Sun.COM urtw_8225v2_rf_init(struct urtw_softc *sc) 2448*9485SMikore.Li@Sun.COM { 2449*9485SMikore.Li@Sun.COM #define N(a) (sizeof (a)/ sizeof ((a)[0])) 2450*9485SMikore.Li@Sun.COM int i; 2451*9485SMikore.Li@Sun.COM uint16_t data; 2452*9485SMikore.Li@Sun.COM uint32_t data32; 2453*9485SMikore.Li@Sun.COM usbd_status error; 2454*9485SMikore.Li@Sun.COM 2455*9485SMikore.Li@Sun.COM if (error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON)) 2456*9485SMikore.Li@Sun.COM goto fail; 2457*9485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc)) 2458*9485SMikore.Li@Sun.COM goto fail; 2459*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008)) 2460*9485SMikore.Li@Sun.COM goto fail; 2461*9485SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data)) 2462*9485SMikore.Li@Sun.COM goto fail; 2463*9485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff)) 2464*9485SMikore.Li@Sun.COM goto fail; 2465*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044)) 2466*9485SMikore.Li@Sun.COM goto fail; 2467*9485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG)) 2468*9485SMikore.Li@Sun.COM goto fail; 2469*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44)) 2470*9485SMikore.Li@Sun.COM goto fail; 2471*9485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL)) 2472*9485SMikore.Li@Sun.COM goto fail; 2473*9485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc)) 2474*9485SMikore.Li@Sun.COM goto fail; 2475*9485SMikore.Li@Sun.COM 2476*9485SMikore.Li@Sun.COM urtw_delay_ms(500); 2477*9485SMikore.Li@Sun.COM 2478*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part1); i++) { 2479*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225v2_rf_part1[i].reg, 2480*9485SMikore.Li@Sun.COM urtw_8225v2_rf_part1[i].val)) 2481*9485SMikore.Li@Sun.COM goto fail; 2482*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2483*9485SMikore.Li@Sun.COM } 2484*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 2485*9485SMikore.Li@Sun.COM 2486*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7)) 2487*9485SMikore.Li@Sun.COM goto fail; 2488*9485SMikore.Li@Sun.COM 2489*9485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) { 2490*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1))) 2491*9485SMikore.Li@Sun.COM goto fail; 2492*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2493*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i])) 2494*9485SMikore.Li@Sun.COM goto fail; 2495*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2496*9485SMikore.Li@Sun.COM } 2497*9485SMikore.Li@Sun.COM 2498*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x3, 0x2)) 2499*9485SMikore.Li@Sun.COM goto fail; 2500*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2501*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x5, 0x4)) 2502*9485SMikore.Li@Sun.COM goto fail; 2503*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2504*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0xb7)) 2505*9485SMikore.Li@Sun.COM goto fail; 2506*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2507*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d)) 2508*9485SMikore.Li@Sun.COM goto fail; 2509*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 2510*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d)) 2511*9485SMikore.Li@Sun.COM goto fail; 2512*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 2513*9485SMikore.Li@Sun.COM 2514*9485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32)) 2515*9485SMikore.Li@Sun.COM goto fail; 2516*9485SMikore.Li@Sun.COM if (data32 != 0xe6) { 2517*9485SMikore.Li@Sun.COM error = (-1); 2518*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "expect 0xe6!! (0x%x)\n", data32); 2519*9485SMikore.Li@Sun.COM goto fail; 2520*9485SMikore.Li@Sun.COM } 2521*9485SMikore.Li@Sun.COM if (!(data32 & 0x80)) { 2522*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x0c4d)) 2523*9485SMikore.Li@Sun.COM goto fail; 2524*9485SMikore.Li@Sun.COM urtw_delay_ms(200); 2525*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x044d)) 2526*9485SMikore.Li@Sun.COM goto fail; 2527*9485SMikore.Li@Sun.COM urtw_delay_ms(100); 2528*9485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32)) 2529*9485SMikore.Li@Sun.COM goto fail; 2530*9485SMikore.Li@Sun.COM if (!(data32 & 0x80)) 2531*9485SMikore.Li@Sun.COM cmn_err(CE_CONT, "RF calibration failed\n"); 2532*9485SMikore.Li@Sun.COM } 2533*9485SMikore.Li@Sun.COM urtw_delay_ms(200); 2534*9485SMikore.Li@Sun.COM 2535*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x2bf)) 2536*9485SMikore.Li@Sun.COM goto fail; 2537*9485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) { 2538*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb, 2539*9485SMikore.Li@Sun.COM urtw_8225_agc[i])) 2540*9485SMikore.Li@Sun.COM goto fail; 2541*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2542*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa, 2543*9485SMikore.Li@Sun.COM (uint8_t)i + 0x80)) 2544*9485SMikore.Li@Sun.COM goto fail; 2545*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2546*9485SMikore.Li@Sun.COM } 2547*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2548*9485SMikore.Li@Sun.COM 2549*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part2); i++) { 2550*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2551*9485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].reg, 2552*9485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].val)) 2553*9485SMikore.Li@Sun.COM goto fail; 2554*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2555*9485SMikore.Li@Sun.COM } 2556*9485SMikore.Li@Sun.COM error = urtw_8225v2_setgain(sc, 4); 2557*9485SMikore.Li@Sun.COM if (error) 2558*9485SMikore.Li@Sun.COM goto fail; 2559*9485SMikore.Li@Sun.COM 2560*9485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part3); i++) { 2561*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 2562*9485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].reg, 2563*9485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].val)) 2564*9485SMikore.Li@Sun.COM goto fail; 2565*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2566*9485SMikore.Li@Sun.COM } 2567*9485SMikore.Li@Sun.COM 2568*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d)) 2569*9485SMikore.Li@Sun.COM goto fail; 2570*9485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, 1)) 2571*9485SMikore.Li@Sun.COM goto fail; 2572*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b)) 2573*9485SMikore.Li@Sun.COM goto fail; 2574*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2575*9485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90)) 2576*9485SMikore.Li@Sun.COM goto fail; 2577*9485SMikore.Li@Sun.COM urtw_delay_ms(1); 2578*9485SMikore.Li@Sun.COM 2579*9485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */ 2580*9485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3)) 2581*9485SMikore.Li@Sun.COM goto fail; 2582*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002)) 2583*9485SMikore.Li@Sun.COM goto fail; 2584*9485SMikore.Li@Sun.COM 2585*9485SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(sc, 1); 2586*9485SMikore.Li@Sun.COM fail: 2587*9485SMikore.Li@Sun.COM return (error); 2588*9485SMikore.Li@Sun.COM #undef N 2589*9485SMikore.Li@Sun.COM } 2590*9485SMikore.Li@Sun.COM 2591*9485SMikore.Li@Sun.COM static usbd_status 2592*9485SMikore.Li@Sun.COM urtw_8225v2_rf_set_chan(struct urtw_softc *sc, int chan) 2593*9485SMikore.Li@Sun.COM { 2594*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2595*9485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan; 2596*9485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0; 2597*9485SMikore.Li@Sun.COM usbd_status error; 2598*9485SMikore.Li@Sun.COM 2599*9485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, chan)) 2600*9485SMikore.Li@Sun.COM goto fail; 2601*9485SMikore.Li@Sun.COM 2602*9485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan])) 2603*9485SMikore.Li@Sun.COM goto fail; 2604*9485SMikore.Li@Sun.COM 2605*9485SMikore.Li@Sun.COM urtw_delay_ms(10); 2606*9485SMikore.Li@Sun.COM 2607*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22)) 2608*9485SMikore.Li@Sun.COM goto fail; 2609*9485SMikore.Li@Sun.COM 2610*9485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC && 2611*9485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT) { 2612*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9)) 2613*9485SMikore.Li@Sun.COM goto fail; 2614*9485SMikore.Li@Sun.COM } else 2615*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14)) 2616*9485SMikore.Li@Sun.COM goto fail; 2617*9485SMikore.Li@Sun.COM if (gset) { 2618*9485SMikore.Li@Sun.COM /* for G */ 2619*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14)) 2620*9485SMikore.Li@Sun.COM goto fail; 2621*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14)) 2622*9485SMikore.Li@Sun.COM goto fail; 2623*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0x73)) 2624*9485SMikore.Li@Sun.COM goto fail; 2625*9485SMikore.Li@Sun.COM } else { 2626*9485SMikore.Li@Sun.COM /* for B */ 2627*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24)) 2628*9485SMikore.Li@Sun.COM goto fail; 2629*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24)) 2630*9485SMikore.Li@Sun.COM goto fail; 2631*9485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5)) 2632*9485SMikore.Li@Sun.COM goto fail; 2633*9485SMikore.Li@Sun.COM } 2634*9485SMikore.Li@Sun.COM 2635*9485SMikore.Li@Sun.COM fail: 2636*9485SMikore.Li@Sun.COM return (error); 2637*9485SMikore.Li@Sun.COM } 2638*9485SMikore.Li@Sun.COM 2639*9485SMikore.Li@Sun.COM static int 2640*9485SMikore.Li@Sun.COM urtw_set_channel(struct urtw_softc *sc) 2641*9485SMikore.Li@Sun.COM { 2642*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2643*9485SMikore.Li@Sun.COM uint32_t data; 2644*9485SMikore.Li@Sun.COM usbd_status error; 2645*9485SMikore.Li@Sun.COM 2646*9485SMikore.Li@Sun.COM if (error = urtw_read32_c(sc, URTW_TX_CONF, &data)) 2647*9485SMikore.Li@Sun.COM goto fail; 2648*9485SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK; 2649*9485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_TX_CONF, 2650*9485SMikore.Li@Sun.COM data | URTW_TX_LOOPBACK_MAC)) 2651*9485SMikore.Li@Sun.COM goto fail; 2652*9485SMikore.Li@Sun.COM error = sc->sc_rf_set_chan(sc, 2653*9485SMikore.Li@Sun.COM ieee80211_chan2ieee(ic, ic->ic_curchan)); 2654*9485SMikore.Li@Sun.COM if (error) 2655*9485SMikore.Li@Sun.COM goto fail; 2656*9485SMikore.Li@Sun.COM urtw_delay_ms(10); 2657*9485SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_NONE); 2658*9485SMikore.Li@Sun.COM fail: 2659*9485SMikore.Li@Sun.COM return (error); 2660*9485SMikore.Li@Sun.COM } 2661*9485SMikore.Li@Sun.COM 2662*9485SMikore.Li@Sun.COM /* ARGSUSED */ 2663*9485SMikore.Li@Sun.COM static void 2664*9485SMikore.Li@Sun.COM urtw_txeof_low(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 2665*9485SMikore.Li@Sun.COM { 2666*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 2667*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2668*9485SMikore.Li@Sun.COM 2669*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 2670*9485SMikore.Li@Sun.COM "urtw_txeof_low(): cr:%s(%d), flags:0x%x, tx_queued:%d", 2671*9485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason), 2672*9485SMikore.Li@Sun.COM req->bulk_completion_reason, 2673*9485SMikore.Li@Sun.COM req->bulk_cb_flags, 2674*9485SMikore.Li@Sun.COM sc->sc_tx_low_queued)); 2675*9485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 2676*9485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) { 2677*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 2678*9485SMikore.Li@Sun.COM goto fail; 2679*9485SMikore.Li@Sun.COM } 2680*9485SMikore.Li@Sun.COM 2681*9485SMikore.Li@Sun.COM if (sc->sc_need_sched) { 2682*9485SMikore.Li@Sun.COM sc->sc_need_sched = 0; 2683*9485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach); 2684*9485SMikore.Li@Sun.COM } 2685*9485SMikore.Li@Sun.COM fail: 2686*9485SMikore.Li@Sun.COM sc->sc_tx_low_queued--; 2687*9485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 2688*9485SMikore.Li@Sun.COM usb_free_bulk_req(req); 2689*9485SMikore.Li@Sun.COM } 2690*9485SMikore.Li@Sun.COM 2691*9485SMikore.Li@Sun.COM /* ARGSUSED */ 2692*9485SMikore.Li@Sun.COM static void 2693*9485SMikore.Li@Sun.COM urtw_txeof_normal(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 2694*9485SMikore.Li@Sun.COM { 2695*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private; 2696*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 2697*9485SMikore.Li@Sun.COM 2698*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 2699*9485SMikore.Li@Sun.COM "urtw_txeof_normal(): cr:%s(%d), flags:0x%x, tx_queued:%d", 2700*9485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason), 2701*9485SMikore.Li@Sun.COM req->bulk_completion_reason, 2702*9485SMikore.Li@Sun.COM req->bulk_cb_flags, 2703*9485SMikore.Li@Sun.COM sc->sc_tx_normal_queued)); 2704*9485SMikore.Li@Sun.COM 2705*9485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 2706*9485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) { 2707*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 2708*9485SMikore.Li@Sun.COM goto fail; 2709*9485SMikore.Li@Sun.COM } 2710*9485SMikore.Li@Sun.COM 2711*9485SMikore.Li@Sun.COM if (sc->sc_need_sched) { 2712*9485SMikore.Li@Sun.COM sc->sc_need_sched = 0; 2713*9485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach); 2714*9485SMikore.Li@Sun.COM } 2715*9485SMikore.Li@Sun.COM fail: 2716*9485SMikore.Li@Sun.COM sc->sc_tx_normal_queued--; 2717*9485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 2718*9485SMikore.Li@Sun.COM usb_free_bulk_req(req); 2719*9485SMikore.Li@Sun.COM } 2720*9485SMikore.Li@Sun.COM 2721*9485SMikore.Li@Sun.COM 2722*9485SMikore.Li@Sun.COM static int 2723*9485SMikore.Li@Sun.COM urtw_get_rate(struct ieee80211com *ic) 2724*9485SMikore.Li@Sun.COM { 2725*9485SMikore.Li@Sun.COM uint8_t (*rates)[IEEE80211_RATE_MAXSIZE]; 2726*9485SMikore.Li@Sun.COM int rate; 2727*9485SMikore.Li@Sun.COM 2728*9485SMikore.Li@Sun.COM rates = &ic->ic_bss->in_rates.ir_rates; 2729*9485SMikore.Li@Sun.COM 2730*9485SMikore.Li@Sun.COM if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 2731*9485SMikore.Li@Sun.COM rate = ic->ic_fixed_rate; 2732*9485SMikore.Li@Sun.COM else if (ic->ic_state == IEEE80211_S_RUN) 2733*9485SMikore.Li@Sun.COM rate = (*rates)[ic->ic_bss->in_txrate]; 2734*9485SMikore.Li@Sun.COM else 2735*9485SMikore.Li@Sun.COM rate = 0; 2736*9485SMikore.Li@Sun.COM return (rate & IEEE80211_RATE_VAL); 2737*9485SMikore.Li@Sun.COM } 2738*9485SMikore.Li@Sun.COM 2739*9485SMikore.Li@Sun.COM static int 2740*9485SMikore.Li@Sun.COM urtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2741*9485SMikore.Li@Sun.COM { 2742*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic; 2743*9485SMikore.Li@Sun.COM struct ieee80211_frame *wh; 2744*9485SMikore.Li@Sun.COM struct ieee80211_key *k; 2745*9485SMikore.Li@Sun.COM struct ieee80211_node *ni = NULL; 2746*9485SMikore.Li@Sun.COM uint8_t *buf; 2747*9485SMikore.Li@Sun.COM mblk_t *m = 0, *m0, *mtx; 2748*9485SMikore.Li@Sun.COM int off, mblen, xferlen, err = 0, priority = 0; 2749*9485SMikore.Li@Sun.COM 2750*9485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock); 2751*9485SMikore.Li@Sun.COM priority = (type == IEEE80211_FC0_TYPE_DATA) ? 2752*9485SMikore.Li@Sun.COM LOW_PRIORITY_PIPE: NORMAL_PRIORITY_PIPE; 2753*9485SMikore.Li@Sun.COM 2754*9485SMikore.Li@Sun.COM if (URTW_IS_SUSPENDING(sc)) { 2755*9485SMikore.Li@Sun.COM err = 0; 2756*9485SMikore.Li@Sun.COM goto failed; 2757*9485SMikore.Li@Sun.COM } 2758*9485SMikore.Li@Sun.COM 2759*9485SMikore.Li@Sun.COM if (((priority)? sc->sc_tx_normal_queued : sc->sc_tx_low_queued) >= 2760*9485SMikore.Li@Sun.COM URTW_TX_DATA_LIST_COUNT) { 2761*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT, 2762*9485SMikore.Li@Sun.COM "urtw_send(): no TX buffer!\n")); 2763*9485SMikore.Li@Sun.COM sc->sc_tx_nobuf++; 2764*9485SMikore.Li@Sun.COM err = ENOMEM; 2765*9485SMikore.Li@Sun.COM goto failed; 2766*9485SMikore.Li@Sun.COM } 2767*9485SMikore.Li@Sun.COM 2768*9485SMikore.Li@Sun.COM m = allocb(URTW_TXBUF_SIZE, BPRI_MED); 2769*9485SMikore.Li@Sun.COM if (m == NULL) { 2770*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_send(): can't alloc mblk.\n"); 2771*9485SMikore.Li@Sun.COM err = ENOMEM; 2772*9485SMikore.Li@Sun.COM goto failed; 2773*9485SMikore.Li@Sun.COM } 2774*9485SMikore.Li@Sun.COM 2775*9485SMikore.Li@Sun.COM for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2776*9485SMikore.Li@Sun.COM mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr; 2777*9485SMikore.Li@Sun.COM (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen); 2778*9485SMikore.Li@Sun.COM off += mblen; 2779*9485SMikore.Li@Sun.COM } 2780*9485SMikore.Li@Sun.COM m->b_wptr += off; 2781*9485SMikore.Li@Sun.COM 2782*9485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr; 2783*9485SMikore.Li@Sun.COM 2784*9485SMikore.Li@Sun.COM ni = ieee80211_find_txnode(ic, wh->i_addr1); 2785*9485SMikore.Li@Sun.COM if (ni == NULL) { 2786*9485SMikore.Li@Sun.COM err = ENXIO; 2787*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 2788*9485SMikore.Li@Sun.COM goto failed; 2789*9485SMikore.Li@Sun.COM } 2790*9485SMikore.Li@Sun.COM 2791*9485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) == 2792*9485SMikore.Li@Sun.COM IEEE80211_FC0_TYPE_DATA) { 2793*9485SMikore.Li@Sun.COM (void) ieee80211_encap(ic, m, ni); 2794*9485SMikore.Li@Sun.COM } 2795*9485SMikore.Li@Sun.COM 2796*9485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2797*9485SMikore.Li@Sun.COM k = ieee80211_crypto_encap(ic, m); 2798*9485SMikore.Li@Sun.COM if (k == NULL) { 2799*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 2800*9485SMikore.Li@Sun.COM err = ENXIO; 2801*9485SMikore.Li@Sun.COM goto failed; 2802*9485SMikore.Li@Sun.COM } 2803*9485SMikore.Li@Sun.COM /* packet header may have moved, reset our local pointer */ 2804*9485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr; 2805*9485SMikore.Li@Sun.COM } 2806*9485SMikore.Li@Sun.COM 2807*9485SMikore.Li@Sun.COM xferlen = MBLKL(m) + 4 * 3; 2808*9485SMikore.Li@Sun.COM if ((0 == xferlen % 64) || (0 == xferlen % 512)) 2809*9485SMikore.Li@Sun.COM xferlen += 1; 2810*9485SMikore.Li@Sun.COM 2811*9485SMikore.Li@Sun.COM mtx = allocb(xferlen, BPRI_MED); 2812*9485SMikore.Li@Sun.COM buf = mtx->b_rptr; 2813*9485SMikore.Li@Sun.COM 2814*9485SMikore.Li@Sun.COM bzero(buf, xferlen); 2815*9485SMikore.Li@Sun.COM buf[0] = MBLKL(m) & 0xff; 2816*9485SMikore.Li@Sun.COM buf[1] = (MBLKL(m) & 0x0f00) >> 8; 2817*9485SMikore.Li@Sun.COM buf[1] |= (1 << 7); 2818*9485SMikore.Li@Sun.COM 2819*9485SMikore.Li@Sun.COM /* XXX sc_preamble_mode is always 2. */ 2820*9485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) 2821*9485SMikore.Li@Sun.COM buf[2] |= (1 << 1); 2822*9485SMikore.Li@Sun.COM /* RTS rate - 10 means we use a basic rate. */ 2823*9485SMikore.Li@Sun.COM buf[2] |= (urtw_rate2rtl(2) << 3); 2824*9485SMikore.Li@Sun.COM /* 2825*9485SMikore.Li@Sun.COM * XXX currently TX rate control depends on the rate value of 2826*9485SMikore.Li@Sun.COM * RX descriptor because I don't know how to we can control TX rate 2827*9485SMikore.Li@Sun.COM * in more smart way. Please fix me you find a thing. 2828*9485SMikore.Li@Sun.COM */ 2829*9485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { 2830*9485SMikore.Li@Sun.COM buf[3] = urtw_rate2rtl(MAX(2, urtw_get_rate(ic))); 2831*9485SMikore.Li@Sun.COM } else 2832*9485SMikore.Li@Sun.COM buf[3] = sc->sc_currate; 2833*9485SMikore.Li@Sun.COM buf[8] = 3; /* CW minimum */ 2834*9485SMikore.Li@Sun.COM buf[8] |= (7 << 4); /* CW maximum */ 2835*9485SMikore.Li@Sun.COM buf[9] |= 11; /* retry limitation */ 2836*9485SMikore.Li@Sun.COM 2837*9485SMikore.Li@Sun.COM bcopy(m->b_rptr, &buf[12], MBLKL(m)); 2838*9485SMikore.Li@Sun.COM 2839*9485SMikore.Li@Sun.COM (void) urtw_led_ctl(sc, URTW_LED_CTL_TX); 2840*9485SMikore.Li@Sun.COM mtx->b_wptr = mtx->b_rptr + xferlen; 2841*9485SMikore.Li@Sun.COM 2842*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT, 2843*9485SMikore.Li@Sun.COM "sending data frame len=%u rate=%u xfer len=%u\n", 2844*9485SMikore.Li@Sun.COM MBLKL(m), buf[3], xferlen)); 2845*9485SMikore.Li@Sun.COM 2846*9485SMikore.Li@Sun.COM err = urtw_tx_start(sc, mtx, priority); 2847*9485SMikore.Li@Sun.COM if (!err) { 2848*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_frags++; 2849*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_bytes += MBLKL(m); 2850*9485SMikore.Li@Sun.COM } else { 2851*9485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++; 2852*9485SMikore.Li@Sun.COM } 2853*9485SMikore.Li@Sun.COM 2854*9485SMikore.Li@Sun.COM failed: 2855*9485SMikore.Li@Sun.COM if (ni != NULL) 2856*9485SMikore.Li@Sun.COM ieee80211_free_node(ni); 2857*9485SMikore.Li@Sun.COM 2858*9485SMikore.Li@Sun.COM if ((mp) && 2859*9485SMikore.Li@Sun.COM ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 2860*9485SMikore.Li@Sun.COM err == DDI_SUCCESS)) { 2861*9485SMikore.Li@Sun.COM freemsg(mp); 2862*9485SMikore.Li@Sun.COM } 2863*9485SMikore.Li@Sun.COM if (m) freemsg(m); 2864*9485SMikore.Li@Sun.COM 2865*9485SMikore.Li@Sun.COM if (((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) && 2866*9485SMikore.Li@Sun.COM (err != 0)) { 2867*9485SMikore.Li@Sun.COM sc->sc_need_sched = 1; 2868*9485SMikore.Li@Sun.COM } 2869*9485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock); 2870*9485SMikore.Li@Sun.COM return (err); 2871*9485SMikore.Li@Sun.COM } 2872*9485SMikore.Li@Sun.COM 2873*9485SMikore.Li@Sun.COM static void 2874*9485SMikore.Li@Sun.COM urtw_next_scan(void *arg) 2875*9485SMikore.Li@Sun.COM { 2876*9485SMikore.Li@Sun.COM ieee80211com_t *ic = arg; 2877*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 2878*9485SMikore.Li@Sun.COM 2879*9485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) { 2880*9485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 2881*9485SMikore.Li@Sun.COM return; 2882*9485SMikore.Li@Sun.COM } 2883*9485SMikore.Li@Sun.COM 2884*9485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_SCAN) { 2885*9485SMikore.Li@Sun.COM (void) ieee80211_next_scan(ic); 2886*9485SMikore.Li@Sun.COM } 2887*9485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 2888*9485SMikore.Li@Sun.COM } 2889*9485SMikore.Li@Sun.COM 2890*9485SMikore.Li@Sun.COM static void 2891*9485SMikore.Li@Sun.COM urtw_led_launch(void *arg) 2892*9485SMikore.Li@Sun.COM { 2893*9485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 2894*9485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic; 2895*9485SMikore.Li@Sun.COM int error = 0; 2896*9485SMikore.Li@Sun.COM 2897*9485SMikore.Li@Sun.COM URTW_LEDLOCK(sc); 2898*9485SMikore.Li@Sun.COM if ((sc->sc_strategy != URTW_SW_LED_MODE0) || 2899*9485SMikore.Li@Sun.COM URTW_IS_NOT_RUNNING(sc) || 2900*9485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) { 2901*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 2902*9485SMikore.Li@Sun.COM "failed process LED strategy 0x%x, run?%d", 2903*9485SMikore.Li@Sun.COM sc->sc_strategy, 2904*9485SMikore.Li@Sun.COM sc->sc_flags)); 2905*9485SMikore.Li@Sun.COM sc->sc_led_ch = 0; 2906*9485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0; 2907*9485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 2908*9485SMikore.Li@Sun.COM return; 2909*9485SMikore.Li@Sun.COM } 2910*9485SMikore.Li@Sun.COM error = urtw_led_blink(sc); 2911*9485SMikore.Li@Sun.COM if (error) { 2912*9485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch, (void *)sc, 2913*9485SMikore.Li@Sun.COM drv_usectohz((ic->ic_state == IEEE80211_S_RUN) ? 2914*9485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK: URTW_LED_LINKOFF_BLINK)); 2915*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 2916*9485SMikore.Li@Sun.COM "try again led launch")); 2917*9485SMikore.Li@Sun.COM } else { 2918*9485SMikore.Li@Sun.COM sc->sc_led_ch = 0; 2919*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT, 2920*9485SMikore.Li@Sun.COM "exit led launch")); 2921*9485SMikore.Li@Sun.COM } 2922*9485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc); 2923*9485SMikore.Li@Sun.COM } 2924*9485SMikore.Li@Sun.COM 2925*9485SMikore.Li@Sun.COM static int 2926*9485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 2927*9485SMikore.Li@Sun.COM { 2928*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic; 2929*9485SMikore.Li@Sun.COM struct ieee80211_node *ni; 2930*9485SMikore.Li@Sun.COM int error = 0; 2931*9485SMikore.Li@Sun.COM 2932*9485SMikore.Li@Sun.COM if (sc->sc_scan_id != 0) { 2933*9485SMikore.Li@Sun.COM (void) untimeout(sc->sc_scan_id); 2934*9485SMikore.Li@Sun.COM sc->sc_scan_id = 0; 2935*9485SMikore.Li@Sun.COM } 2936*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 2937*9485SMikore.Li@Sun.COM switch (nstate) { 2938*9485SMikore.Li@Sun.COM case IEEE80211_S_INIT: 2939*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2940*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "-> IEEE80211_S_INIT...arg(%d)\n", 2941*9485SMikore.Li@Sun.COM arg)); 2942*9485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate); 2943*9485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO); 2944*9485SMikore.Li@Sun.COM break; 2945*9485SMikore.Li@Sun.COM 2946*9485SMikore.Li@Sun.COM case IEEE80211_S_SCAN: 2947*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2948*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, 2949*9485SMikore.Li@Sun.COM "-> IEEE80211_S_SCAN...arg(%d)...[%d]\n", 2950*9485SMikore.Li@Sun.COM arg, ieee80211_chan2ieee(ic, ic->ic_curchan))); 2951*9485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 2952*9485SMikore.Li@Sun.COM if (error) { 2953*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2954*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "scan setchan failed")); 2955*9485SMikore.Li@Sun.COM break; 2956*9485SMikore.Li@Sun.COM } 2957*9485SMikore.Li@Sun.COM sc->sc_scan_id = timeout(urtw_next_scan, (void *)sc, 2958*9485SMikore.Li@Sun.COM drv_usectohz(sc->dwelltime * 1000)); 2959*9485SMikore.Li@Sun.COM break; 2960*9485SMikore.Li@Sun.COM 2961*9485SMikore.Li@Sun.COM case IEEE80211_S_AUTH: 2962*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT, 2963*9485SMikore.Li@Sun.COM "-> IEEE80211_S_AUTH ...arg(%d)\n", arg)); 2964*9485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 2965*9485SMikore.Li@Sun.COM if (error) { 2966*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2967*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "auth setchan failed")); 2968*9485SMikore.Li@Sun.COM } 2969*9485SMikore.Li@Sun.COM break; 2970*9485SMikore.Li@Sun.COM 2971*9485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC: 2972*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT, 2973*9485SMikore.Li@Sun.COM "-> IEEE80211_S_ASSOC ...arg(%d)\n", arg)); 2974*9485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 2975*9485SMikore.Li@Sun.COM if (error) { 2976*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2977*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "assoc setchan failed")); 2978*9485SMikore.Li@Sun.COM } 2979*9485SMikore.Li@Sun.COM break; 2980*9485SMikore.Li@Sun.COM 2981*9485SMikore.Li@Sun.COM case IEEE80211_S_RUN: 2982*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2983*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "-> IEEE80211_S_RUN ...arg(%d)\n", 2984*9485SMikore.Li@Sun.COM arg)); 2985*9485SMikore.Li@Sun.COM error = urtw_set_channel(sc); 2986*9485SMikore.Li@Sun.COM if (error) { 2987*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, 2988*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "run setchan failed")); 2989*9485SMikore.Li@Sun.COM goto fail; 2990*9485SMikore.Li@Sun.COM } 2991*9485SMikore.Li@Sun.COM ni = ic->ic_bss; 2992*9485SMikore.Li@Sun.COM /* setting bssid. */ 2993*9485SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_BSSID, 2994*9485SMikore.Li@Sun.COM ((uint32_t *)(uintptr_t)ni->in_bssid)[0]); 2995*9485SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_BSSID + 4, 2996*9485SMikore.Li@Sun.COM ((uint16_t *)(uintptr_t)ni->in_bssid)[2]); 2997*9485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate); 2998*9485SMikore.Li@Sun.COM 2999*9485SMikore.Li@Sun.COM ni->in_txrate = ni->in_rates.ir_nrates - 1; 3000*9485SMikore.Li@Sun.COM break; 3001*9485SMikore.Li@Sun.COM } 3002*9485SMikore.Li@Sun.COM fail: 3003*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3004*9485SMikore.Li@Sun.COM 3005*9485SMikore.Li@Sun.COM if (error) 3006*9485SMikore.Li@Sun.COM return (EIO); 3007*9485SMikore.Li@Sun.COM error = sc->sc_newstate(ic, nstate, arg); 3008*9485SMikore.Li@Sun.COM return (error); 3009*9485SMikore.Li@Sun.COM } 3010*9485SMikore.Li@Sun.COM 3011*9485SMikore.Li@Sun.COM static void 3012*9485SMikore.Li@Sun.COM urtw_close_pipes(struct urtw_softc *sc) 3013*9485SMikore.Li@Sun.COM { 3014*9485SMikore.Li@Sun.COM usb_flags_t flags = USB_FLAGS_SLEEP; 3015*9485SMikore.Li@Sun.COM 3016*9485SMikore.Li@Sun.COM if (sc->sc_rxpipe != NULL) { 3017*9485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 3018*9485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0); 3019*9485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 3020*9485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0); 3021*9485SMikore.Li@Sun.COM sc->sc_rxpipe = NULL; 3022*9485SMikore.Li@Sun.COM } 3023*9485SMikore.Li@Sun.COM 3024*9485SMikore.Li@Sun.COM if (sc->sc_txpipe_low != NULL) { 3025*9485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 3026*9485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0); 3027*9485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 3028*9485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0); 3029*9485SMikore.Li@Sun.COM sc->sc_txpipe_low = NULL; 3030*9485SMikore.Li@Sun.COM } 3031*9485SMikore.Li@Sun.COM 3032*9485SMikore.Li@Sun.COM if (sc->sc_txpipe_normal != NULL) { 3033*9485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev, 3034*9485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0); 3035*9485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev, 3036*9485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0); 3037*9485SMikore.Li@Sun.COM sc->sc_txpipe_normal = NULL; 3038*9485SMikore.Li@Sun.COM } 3039*9485SMikore.Li@Sun.COM } 3040*9485SMikore.Li@Sun.COM 3041*9485SMikore.Li@Sun.COM static int 3042*9485SMikore.Li@Sun.COM urtw_open_pipes(struct urtw_softc *sc) 3043*9485SMikore.Li@Sun.COM { 3044*9485SMikore.Li@Sun.COM usb_ep_data_t *ep_node; 3045*9485SMikore.Li@Sun.COM usb_pipe_policy_t policy; 3046*9485SMikore.Li@Sun.COM int err; 3047*9485SMikore.Li@Sun.COM 3048*9485SMikore.Li@Sun.COM if (sc->sc_rxpipe || sc->sc_txpipe_low || sc->sc_txpipe_normal) 3049*9485SMikore.Li@Sun.COM return (USB_SUCCESS); 3050*9485SMikore.Li@Sun.COM 3051*9485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 3052*9485SMikore.Li@Sun.COM LOW_PRIORITY_PIPE, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 3053*9485SMikore.Li@Sun.COM 3054*9485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 3055*9485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT; 3056*9485SMikore.Li@Sun.COM 3057*9485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 3058*9485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 3059*9485SMikore.Li@Sun.COM &sc->sc_txpipe_low)) != USB_SUCCESS) { 3060*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 3061*9485SMikore.Li@Sun.COM "urtw_open_pipes(): %x low priority pipe open failed\n", 3062*9485SMikore.Li@Sun.COM err)); 3063*9485SMikore.Li@Sun.COM goto fail; 3064*9485SMikore.Li@Sun.COM } 3065*9485SMikore.Li@Sun.COM 3066*9485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 3067*9485SMikore.Li@Sun.COM NORMAL_PRIORITY_PIPE, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 3068*9485SMikore.Li@Sun.COM 3069*9485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 3070*9485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT; 3071*9485SMikore.Li@Sun.COM 3072*9485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 3073*9485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 3074*9485SMikore.Li@Sun.COM &sc->sc_txpipe_normal)) != USB_SUCCESS) { 3075*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 3076*9485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open high tx pipe\n", 3077*9485SMikore.Li@Sun.COM err)); 3078*9485SMikore.Li@Sun.COM goto fail; 3079*9485SMikore.Li@Sun.COM } 3080*9485SMikore.Li@Sun.COM 3081*9485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0, 3082*9485SMikore.Li@Sun.COM USB_EP_ATTR_BULK, USB_EP_DIR_IN); 3083*9485SMikore.Li@Sun.COM 3084*9485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t)); 3085*9485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_RX_DATA_LIST_COUNT; 3086*9485SMikore.Li@Sun.COM 3087*9485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev, 3088*9485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 3089*9485SMikore.Li@Sun.COM &sc->sc_rxpipe)) != USB_SUCCESS) { 3090*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 3091*9485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open rx pipe\n", err)); 3092*9485SMikore.Li@Sun.COM goto fail; 3093*9485SMikore.Li@Sun.COM } 3094*9485SMikore.Li@Sun.COM 3095*9485SMikore.Li@Sun.COM return (USB_SUCCESS); 3096*9485SMikore.Li@Sun.COM 3097*9485SMikore.Li@Sun.COM fail: 3098*9485SMikore.Li@Sun.COM urtw_close_pipes(sc); 3099*9485SMikore.Li@Sun.COM return (USB_FAILURE); 3100*9485SMikore.Li@Sun.COM } 3101*9485SMikore.Li@Sun.COM 3102*9485SMikore.Li@Sun.COM static int 3103*9485SMikore.Li@Sun.COM urtw_tx_start(struct urtw_softc *sc, mblk_t *mp, int priority) 3104*9485SMikore.Li@Sun.COM { 3105*9485SMikore.Li@Sun.COM usb_bulk_req_t *req; 3106*9485SMikore.Li@Sun.COM int err; 3107*9485SMikore.Li@Sun.COM 3108*9485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP); 3109*9485SMikore.Li@Sun.COM if (req == NULL) { 3110*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 3111*9485SMikore.Li@Sun.COM "urtw_tx_start(): failed to allocate req")); 3112*9485SMikore.Li@Sun.COM freemsg(mp); 3113*9485SMikore.Li@Sun.COM return (-1); 3114*9485SMikore.Li@Sun.COM } 3115*9485SMikore.Li@Sun.COM 3116*9485SMikore.Li@Sun.COM req->bulk_len = MBLKL(mp); 3117*9485SMikore.Li@Sun.COM req->bulk_data = mp; 3118*9485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc; 3119*9485SMikore.Li@Sun.COM req->bulk_timeout = URTW_TX_TIMEOUT; 3120*9485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 3121*9485SMikore.Li@Sun.COM req->bulk_cb = (priority)?urtw_txeof_normal : urtw_txeof_low; 3122*9485SMikore.Li@Sun.COM req->bulk_exc_cb = (priority)?urtw_txeof_normal: urtw_txeof_low; 3123*9485SMikore.Li@Sun.COM req->bulk_completion_reason = 0; 3124*9485SMikore.Li@Sun.COM req->bulk_cb_flags = 0; 3125*9485SMikore.Li@Sun.COM 3126*9485SMikore.Li@Sun.COM if ((err = usb_pipe_bulk_xfer( 3127*9485SMikore.Li@Sun.COM (priority)?sc->sc_txpipe_normal:sc->sc_txpipe_low, req, 0)) 3128*9485SMikore.Li@Sun.COM != USB_SUCCESS) { 3129*9485SMikore.Li@Sun.COM sc->sc_ic.ic_stats.is_tx_failed++; 3130*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT, 3131*9485SMikore.Li@Sun.COM "urtw_tx_start: failed to do tx xfer, %d", err)); 3132*9485SMikore.Li@Sun.COM usb_free_bulk_req(req); 3133*9485SMikore.Li@Sun.COM return (EIO); 3134*9485SMikore.Li@Sun.COM } 3135*9485SMikore.Li@Sun.COM 3136*9485SMikore.Li@Sun.COM if (priority) { 3137*9485SMikore.Li@Sun.COM sc->sc_tx_normal_queued++; 3138*9485SMikore.Li@Sun.COM } else { 3139*9485SMikore.Li@Sun.COM sc->sc_tx_low_queued++; 3140*9485SMikore.Li@Sun.COM } 3141*9485SMikore.Li@Sun.COM 3142*9485SMikore.Li@Sun.COM return (0); 3143*9485SMikore.Li@Sun.COM } 3144*9485SMikore.Li@Sun.COM 3145*9485SMikore.Li@Sun.COM static int 3146*9485SMikore.Li@Sun.COM urtw_rx_start(struct urtw_softc *sc) 3147*9485SMikore.Li@Sun.COM { 3148*9485SMikore.Li@Sun.COM usb_bulk_req_t *req; 3149*9485SMikore.Li@Sun.COM int err; 3150*9485SMikore.Li@Sun.COM 3151*9485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, URTW_RXBUF_SIZE, USB_FLAGS_SLEEP); 3152*9485SMikore.Li@Sun.COM if (req == NULL) { 3153*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT, 3154*9485SMikore.Li@Sun.COM "urtw_rx_start(): failed to allocate req")); 3155*9485SMikore.Li@Sun.COM return (-1); 3156*9485SMikore.Li@Sun.COM } 3157*9485SMikore.Li@Sun.COM 3158*9485SMikore.Li@Sun.COM req->bulk_len = URTW_RXBUF_SIZE; 3159*9485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc; 3160*9485SMikore.Li@Sun.COM req->bulk_timeout = 0; 3161*9485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | 3162*9485SMikore.Li@Sun.COM USB_ATTRS_AUTOCLEARING; 3163*9485SMikore.Li@Sun.COM req->bulk_cb = urtw_rxeof; 3164*9485SMikore.Li@Sun.COM req->bulk_exc_cb = urtw_rxeof; 3165*9485SMikore.Li@Sun.COM req->bulk_completion_reason = 0; 3166*9485SMikore.Li@Sun.COM req->bulk_cb_flags = 0; 3167*9485SMikore.Li@Sun.COM 3168*9485SMikore.Li@Sun.COM err = usb_pipe_bulk_xfer(sc->sc_rxpipe, req, 0); 3169*9485SMikore.Li@Sun.COM 3170*9485SMikore.Li@Sun.COM if (err != USB_SUCCESS) { 3171*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT, 3172*9485SMikore.Li@Sun.COM "urtw_rx_start: failed to do rx xfer, %d", err)); 3173*9485SMikore.Li@Sun.COM usb_free_bulk_req(req); 3174*9485SMikore.Li@Sun.COM return (-1); 3175*9485SMikore.Li@Sun.COM } 3176*9485SMikore.Li@Sun.COM 3177*9485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock); 3178*9485SMikore.Li@Sun.COM sc->rx_queued++; 3179*9485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock); 3180*9485SMikore.Li@Sun.COM 3181*9485SMikore.Li@Sun.COM return (0); 3182*9485SMikore.Li@Sun.COM } 3183*9485SMikore.Li@Sun.COM 3184*9485SMikore.Li@Sun.COM static int 3185*9485SMikore.Li@Sun.COM urtw_disconnect(dev_info_t *devinfo) 3186*9485SMikore.Li@Sun.COM { 3187*9485SMikore.Li@Sun.COM struct urtw_softc *sc; 3188*9485SMikore.Li@Sun.COM 3189*9485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 3190*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG, 3191*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_offline()\n")); 3192*9485SMikore.Li@Sun.COM 3193*9485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3194*9485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 3195*9485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) { 3196*9485SMikore.Li@Sun.COM urtw_stop(sc); 3197*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3198*9485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE; 3199*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3200*9485SMikore.Li@Sun.COM } 3201*9485SMikore.Li@Sun.COM return (DDI_SUCCESS); 3202*9485SMikore.Li@Sun.COM } 3203*9485SMikore.Li@Sun.COM 3204*9485SMikore.Li@Sun.COM static int 3205*9485SMikore.Li@Sun.COM urtw_reconnect(dev_info_t *devinfo) 3206*9485SMikore.Li@Sun.COM { 3207*9485SMikore.Li@Sun.COM struct urtw_softc *sc; 3208*9485SMikore.Li@Sun.COM int error = 0; 3209*9485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 3210*9485SMikore.Li@Sun.COM if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 3211*9485SMikore.Li@Sun.COM USB_CHK_ALL, NULL) != USB_SUCCESS) 3212*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3213*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG, (sc->sc_dev, CE_CONT, 3214*9485SMikore.Li@Sun.COM "urtw_online()\n")); 3215*9485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) { 3216*9485SMikore.Li@Sun.COM error = urtw_init(sc); 3217*9485SMikore.Li@Sun.COM if (!error) { 3218*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3219*9485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE; 3220*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3221*9485SMikore.Li@Sun.COM } 3222*9485SMikore.Li@Sun.COM } 3223*9485SMikore.Li@Sun.COM return (error); 3224*9485SMikore.Li@Sun.COM } 3225*9485SMikore.Li@Sun.COM 3226*9485SMikore.Li@Sun.COM static mblk_t * 3227*9485SMikore.Li@Sun.COM urtw_m_tx(void *arg, mblk_t *mp) 3228*9485SMikore.Li@Sun.COM { 3229*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3230*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3231*9485SMikore.Li@Sun.COM mblk_t *next; 3232*9485SMikore.Li@Sun.COM 3233*9485SMikore.Li@Sun.COM if ((ic->ic_state != IEEE80211_S_RUN) || 3234*9485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) { 3235*9485SMikore.Li@Sun.COM freemsgchain(mp); 3236*9485SMikore.Li@Sun.COM return (NULL); 3237*9485SMikore.Li@Sun.COM } 3238*9485SMikore.Li@Sun.COM 3239*9485SMikore.Li@Sun.COM while (mp != NULL) { 3240*9485SMikore.Li@Sun.COM next = mp->b_next; 3241*9485SMikore.Li@Sun.COM mp->b_next = NULL; 3242*9485SMikore.Li@Sun.COM if (urtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) { 3243*9485SMikore.Li@Sun.COM mp->b_next = next; 3244*9485SMikore.Li@Sun.COM break; 3245*9485SMikore.Li@Sun.COM } 3246*9485SMikore.Li@Sun.COM mp = next; 3247*9485SMikore.Li@Sun.COM } 3248*9485SMikore.Li@Sun.COM return (mp); 3249*9485SMikore.Li@Sun.COM } 3250*9485SMikore.Li@Sun.COM 3251*9485SMikore.Li@Sun.COM static int 3252*9485SMikore.Li@Sun.COM urtw_m_start(void *arg) 3253*9485SMikore.Li@Sun.COM { 3254*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3255*9485SMikore.Li@Sun.COM int error = 0; 3256*9485SMikore.Li@Sun.COM 3257*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 3258*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_m_start)\n")); 3259*9485SMikore.Li@Sun.COM error = urtw_init(sc); 3260*9485SMikore.Li@Sun.COM return (error); 3261*9485SMikore.Li@Sun.COM } 3262*9485SMikore.Li@Sun.COM 3263*9485SMikore.Li@Sun.COM static void 3264*9485SMikore.Li@Sun.COM urtw_m_stop(void *arg) 3265*9485SMikore.Li@Sun.COM { 3266*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3267*9485SMikore.Li@Sun.COM 3268*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT, 3269*9485SMikore.Li@Sun.COM "urtw_m_stop()\n")); 3270*9485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3271*9485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 3272*9485SMikore.Li@Sun.COM (void) urtw_stop(sc); 3273*9485SMikore.Li@Sun.COM } 3274*9485SMikore.Li@Sun.COM 3275*9485SMikore.Li@Sun.COM /*ARGSUSED*/ 3276*9485SMikore.Li@Sun.COM static int 3277*9485SMikore.Li@Sun.COM urtw_m_unicst(void *arg, const uint8_t *macaddr) 3278*9485SMikore.Li@Sun.COM { 3279*9485SMikore.Li@Sun.COM return (ENOTSUP); 3280*9485SMikore.Li@Sun.COM } 3281*9485SMikore.Li@Sun.COM 3282*9485SMikore.Li@Sun.COM /*ARGSUSED*/ 3283*9485SMikore.Li@Sun.COM static int 3284*9485SMikore.Li@Sun.COM urtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 3285*9485SMikore.Li@Sun.COM { 3286*9485SMikore.Li@Sun.COM return (ENOTSUP); 3287*9485SMikore.Li@Sun.COM } 3288*9485SMikore.Li@Sun.COM 3289*9485SMikore.Li@Sun.COM /*ARGSUSED*/ 3290*9485SMikore.Li@Sun.COM static int 3291*9485SMikore.Li@Sun.COM urtw_m_promisc(void *arg, boolean_t on) 3292*9485SMikore.Li@Sun.COM { 3293*9485SMikore.Li@Sun.COM return (0); 3294*9485SMikore.Li@Sun.COM } 3295*9485SMikore.Li@Sun.COM 3296*9485SMikore.Li@Sun.COM static int 3297*9485SMikore.Li@Sun.COM urtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3298*9485SMikore.Li@Sun.COM uint_t wldp_length, const void *wldp_buf) 3299*9485SMikore.Li@Sun.COM { 3300*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3301*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3302*9485SMikore.Li@Sun.COM int err; 3303*9485SMikore.Li@Sun.COM 3304*9485SMikore.Li@Sun.COM err = ieee80211_setprop(ic, pr_name, wldp_pr_num, 3305*9485SMikore.Li@Sun.COM wldp_length, wldp_buf); 3306*9485SMikore.Li@Sun.COM if (err == ENETRESET) { 3307*9485SMikore.Li@Sun.COM if (ic->ic_des_esslen && URTW_IS_RUNNING(sc)) { 3308*9485SMikore.Li@Sun.COM (void) urtw_init(sc); 3309*9485SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 3310*9485SMikore.Li@Sun.COM } 3311*9485SMikore.Li@Sun.COM err = 0; 3312*9485SMikore.Li@Sun.COM } 3313*9485SMikore.Li@Sun.COM return (err); 3314*9485SMikore.Li@Sun.COM } 3315*9485SMikore.Li@Sun.COM 3316*9485SMikore.Li@Sun.COM static void 3317*9485SMikore.Li@Sun.COM urtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 3318*9485SMikore.Li@Sun.COM { 3319*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3320*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3321*9485SMikore.Li@Sun.COM int err; 3322*9485SMikore.Li@Sun.COM 3323*9485SMikore.Li@Sun.COM err = ieee80211_ioctl(ic, wq, mp); 3324*9485SMikore.Li@Sun.COM if (err == ENETRESET) { 3325*9485SMikore.Li@Sun.COM if (ic->ic_des_esslen && URTW_IS_RUNNING(sc)) { 3326*9485SMikore.Li@Sun.COM (void) urtw_init(sc); 3327*9485SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, 3328*9485SMikore.Li@Sun.COM IEEE80211_S_SCAN, -1); 3329*9485SMikore.Li@Sun.COM } 3330*9485SMikore.Li@Sun.COM } 3331*9485SMikore.Li@Sun.COM } 3332*9485SMikore.Li@Sun.COM 3333*9485SMikore.Li@Sun.COM static int 3334*9485SMikore.Li@Sun.COM urtw_m_stat(void *arg, uint_t stat, uint64_t *val) 3335*9485SMikore.Li@Sun.COM { 3336*9485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg; 3337*9485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic; 3338*9485SMikore.Li@Sun.COM ieee80211_node_t *ni = 0; 3339*9485SMikore.Li@Sun.COM struct ieee80211_rateset *rs = 0; 3340*9485SMikore.Li@Sun.COM 3341*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3342*9485SMikore.Li@Sun.COM switch (stat) { 3343*9485SMikore.Li@Sun.COM case MAC_STAT_IFSPEED: 3344*9485SMikore.Li@Sun.COM ni = ic->ic_bss; 3345*9485SMikore.Li@Sun.COM rs = &ni->in_rates; 3346*9485SMikore.Li@Sun.COM *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 3347*9485SMikore.Li@Sun.COM (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 3348*9485SMikore.Li@Sun.COM : ic->ic_fixed_rate) / 2 * 1000000; 3349*9485SMikore.Li@Sun.COM break; 3350*9485SMikore.Li@Sun.COM case MAC_STAT_NOXMTBUF: 3351*9485SMikore.Li@Sun.COM *val = sc->sc_tx_nobuf; 3352*9485SMikore.Li@Sun.COM break; 3353*9485SMikore.Li@Sun.COM case MAC_STAT_NORCVBUF: 3354*9485SMikore.Li@Sun.COM *val = sc->sc_rx_nobuf; 3355*9485SMikore.Li@Sun.COM break; 3356*9485SMikore.Li@Sun.COM case MAC_STAT_IERRORS: 3357*9485SMikore.Li@Sun.COM *val = sc->sc_rx_err; 3358*9485SMikore.Li@Sun.COM break; 3359*9485SMikore.Li@Sun.COM case MAC_STAT_RBYTES: 3360*9485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_bytes; 3361*9485SMikore.Li@Sun.COM break; 3362*9485SMikore.Li@Sun.COM case MAC_STAT_IPACKETS: 3363*9485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_frags; 3364*9485SMikore.Li@Sun.COM break; 3365*9485SMikore.Li@Sun.COM case MAC_STAT_OBYTES: 3366*9485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_bytes; 3367*9485SMikore.Li@Sun.COM break; 3368*9485SMikore.Li@Sun.COM case MAC_STAT_OPACKETS: 3369*9485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_frags; 3370*9485SMikore.Li@Sun.COM break; 3371*9485SMikore.Li@Sun.COM case MAC_STAT_OERRORS: 3372*9485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_failed; 3373*9485SMikore.Li@Sun.COM break; 3374*9485SMikore.Li@Sun.COM case WIFI_STAT_TX_FRAGS: 3375*9485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_TX: 3376*9485SMikore.Li@Sun.COM case WIFI_STAT_TX_FAILED: 3377*9485SMikore.Li@Sun.COM case WIFI_STAT_TX_RETRANS: 3378*9485SMikore.Li@Sun.COM case WIFI_STAT_RTS_SUCCESS: 3379*9485SMikore.Li@Sun.COM case WIFI_STAT_RTS_FAILURE: 3380*9485SMikore.Li@Sun.COM case WIFI_STAT_ACK_FAILURE: 3381*9485SMikore.Li@Sun.COM case WIFI_STAT_RX_FRAGS: 3382*9485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_RX: 3383*9485SMikore.Li@Sun.COM case WIFI_STAT_FCS_ERRORS: 3384*9485SMikore.Li@Sun.COM case WIFI_STAT_WEP_ERRORS: 3385*9485SMikore.Li@Sun.COM case WIFI_STAT_RX_DUPS: 3386*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3387*9485SMikore.Li@Sun.COM return (ieee80211_stat(ic, stat, val)); 3388*9485SMikore.Li@Sun.COM default: 3389*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3390*9485SMikore.Li@Sun.COM return (ENOTSUP); 3391*9485SMikore.Li@Sun.COM } 3392*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3393*9485SMikore.Li@Sun.COM 3394*9485SMikore.Li@Sun.COM return (0); 3395*9485SMikore.Li@Sun.COM } 3396*9485SMikore.Li@Sun.COM 3397*9485SMikore.Li@Sun.COM static void 3398*9485SMikore.Li@Sun.COM urtw_watchdog(void *arg) 3399*9485SMikore.Li@Sun.COM { 3400*9485SMikore.Li@Sun.COM struct urtw_softc *sc = arg; 3401*9485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic; 3402*9485SMikore.Li@Sun.COM 3403*9485SMikore.Li@Sun.COM ieee80211_stop_watchdog(ic); 3404*9485SMikore.Li@Sun.COM 3405*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3406*9485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) { 3407*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3408*9485SMikore.Li@Sun.COM return; 3409*9485SMikore.Li@Sun.COM } 3410*9485SMikore.Li@Sun.COM 3411*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3412*9485SMikore.Li@Sun.COM switch (ic->ic_state) { 3413*9485SMikore.Li@Sun.COM case IEEE80211_S_AUTH: 3414*9485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC: 3415*9485SMikore.Li@Sun.COM if (ic->ic_bss->in_fails > 0) 3416*9485SMikore.Li@Sun.COM ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3417*9485SMikore.Li@Sun.COM else 3418*9485SMikore.Li@Sun.COM ieee80211_watchdog(ic); 3419*9485SMikore.Li@Sun.COM break; 3420*9485SMikore.Li@Sun.COM } 3421*9485SMikore.Li@Sun.COM } 3422*9485SMikore.Li@Sun.COM 3423*9485SMikore.Li@Sun.COM 3424*9485SMikore.Li@Sun.COM static int 3425*9485SMikore.Li@Sun.COM urtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 3426*9485SMikore.Li@Sun.COM { 3427*9485SMikore.Li@Sun.COM struct urtw_softc *sc; 3428*9485SMikore.Li@Sun.COM struct ieee80211com *ic; 3429*9485SMikore.Li@Sun.COM int error, i, instance; 3430*9485SMikore.Li@Sun.COM uint32_t data = 0; 3431*9485SMikore.Li@Sun.COM char strbuf[32]; 3432*9485SMikore.Li@Sun.COM wifi_data_t wd = { 0 }; 3433*9485SMikore.Li@Sun.COM mac_register_t *macp; 3434*9485SMikore.Li@Sun.COM 3435*9485SMikore.Li@Sun.COM switch (cmd) { 3436*9485SMikore.Li@Sun.COM case DDI_ATTACH: 3437*9485SMikore.Li@Sun.COM break; 3438*9485SMikore.Li@Sun.COM case DDI_RESUME: 3439*9485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, 3440*9485SMikore.Li@Sun.COM ddi_get_instance(devinfo)); 3441*9485SMikore.Li@Sun.COM ASSERT(sc != NULL); 3442*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, 3443*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: resume\n")); 3444*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3445*9485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_SUSPEND; 3446*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3447*9485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) { 3448*9485SMikore.Li@Sun.COM error = urtw_init(sc); 3449*9485SMikore.Li@Sun.COM if (error == 0) { 3450*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3451*9485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE; 3452*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3453*9485SMikore.Li@Sun.COM } 3454*9485SMikore.Li@Sun.COM } 3455*9485SMikore.Li@Sun.COM return (DDI_SUCCESS); 3456*9485SMikore.Li@Sun.COM default: 3457*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3458*9485SMikore.Li@Sun.COM } 3459*9485SMikore.Li@Sun.COM 3460*9485SMikore.Li@Sun.COM instance = ddi_get_instance(devinfo); 3461*9485SMikore.Li@Sun.COM 3462*9485SMikore.Li@Sun.COM if (ddi_soft_state_zalloc(urtw_soft_state_p, instance) != DDI_SUCCESS) { 3463*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach:unable to alloc soft_state_p\n"); 3464*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3465*9485SMikore.Li@Sun.COM } 3466*9485SMikore.Li@Sun.COM 3467*9485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, instance); 3468*9485SMikore.Li@Sun.COM ic = (ieee80211com_t *)&sc->sc_ic; 3469*9485SMikore.Li@Sun.COM sc->sc_dev = devinfo; 3470*9485SMikore.Li@Sun.COM 3471*9485SMikore.Li@Sun.COM if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) { 3472*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: usb_client_attach failed\n"); 3473*9485SMikore.Li@Sun.COM goto fail1; 3474*9485SMikore.Li@Sun.COM } 3475*9485SMikore.Li@Sun.COM 3476*9485SMikore.Li@Sun.COM if (usb_get_dev_data(devinfo, &sc->sc_udev, 3477*9485SMikore.Li@Sun.COM USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) { 3478*9485SMikore.Li@Sun.COM sc->sc_udev = NULL; 3479*9485SMikore.Li@Sun.COM goto fail2; 3480*9485SMikore.Li@Sun.COM } 3481*9485SMikore.Li@Sun.COM 3482*9485SMikore.Li@Sun.COM mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 3483*9485SMikore.Li@Sun.COM mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL); 3484*9485SMikore.Li@Sun.COM mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL); 3485*9485SMikore.Li@Sun.COM mutex_init(&sc->sc_ledlock, NULL, MUTEX_DRIVER, NULL); 3486*9485SMikore.Li@Sun.COM 3487*9485SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data)) 3488*9485SMikore.Li@Sun.COM goto fail3; 3489*9485SMikore.Li@Sun.COM sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 : 3490*9485SMikore.Li@Sun.COM URTW_EEPROM_93C46; 3491*9485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56) 3492*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 3493*9485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C56\n")); 3494*9485SMikore.Li@Sun.COM else 3495*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT, 3496*9485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C46\n")); 3497*9485SMikore.Li@Sun.COM error = urtw_get_rfchip(sc); 3498*9485SMikore.Li@Sun.COM if (error != 0) 3499*9485SMikore.Li@Sun.COM goto fail3; 3500*9485SMikore.Li@Sun.COM error = urtw_get_macaddr(sc); 3501*9485SMikore.Li@Sun.COM if (error != 0) 3502*9485SMikore.Li@Sun.COM goto fail3; 3503*9485SMikore.Li@Sun.COM error = urtw_get_txpwr(sc); 3504*9485SMikore.Li@Sun.COM if (error != 0) 3505*9485SMikore.Li@Sun.COM goto fail3; 3506*9485SMikore.Li@Sun.COM error = urtw_led_init(sc); /* XXX incompleted */ 3507*9485SMikore.Li@Sun.COM if (error != 0) 3508*9485SMikore.Li@Sun.COM goto fail3; 3509*9485SMikore.Li@Sun.COM 3510*9485SMikore.Li@Sun.COM sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY; 3511*9485SMikore.Li@Sun.COM sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY; 3512*9485SMikore.Li@Sun.COM sc->sc_currate = 3; 3513*9485SMikore.Li@Sun.COM /* XXX for what? */ 3514*9485SMikore.Li@Sun.COM sc->sc_preamble_mode = 2; 3515*9485SMikore.Li@Sun.COM 3516*9485SMikore.Li@Sun.COM ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 3517*9485SMikore.Li@Sun.COM ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 3518*9485SMikore.Li@Sun.COM ic->ic_state = IEEE80211_S_INIT; 3519*9485SMikore.Li@Sun.COM 3520*9485SMikore.Li@Sun.COM ic->ic_maxrssi = 95; 3521*9485SMikore.Li@Sun.COM ic->ic_xmit = urtw_send; 3522*9485SMikore.Li@Sun.COM 3523*9485SMikore.Li@Sun.COM ic->ic_caps |= IEEE80211_C_WPA | /* Support WPA/WPA2 */ 3524*9485SMikore.Li@Sun.COM IEEE80211_C_TXPMGT | /* tx power management */ 3525*9485SMikore.Li@Sun.COM IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 3526*9485SMikore.Li@Sun.COM IEEE80211_C_SHSLOT; /* short slot time supported */ 3527*9485SMikore.Li@Sun.COM /* set supported .11b and .11g rates */ 3528*9485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11B] = urtw_rateset_11b; 3529*9485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11G] = urtw_rateset_11g; 3530*9485SMikore.Li@Sun.COM 3531*9485SMikore.Li@Sun.COM /* set supported .11b and .11g channels (1 through 11) */ 3532*9485SMikore.Li@Sun.COM for (i = 1; i <= 11; i++) { 3533*9485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_freq = 3534*9485SMikore.Li@Sun.COM ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 3535*9485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_flags = 3536*9485SMikore.Li@Sun.COM IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN | 3537*9485SMikore.Li@Sun.COM IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM; 3538*9485SMikore.Li@Sun.COM } 3539*9485SMikore.Li@Sun.COM 3540*9485SMikore.Li@Sun.COM ieee80211_attach(ic); 3541*9485SMikore.Li@Sun.COM 3542*9485SMikore.Li@Sun.COM /* register WPA door */ 3543*9485SMikore.Li@Sun.COM ieee80211_register_door(ic, ddi_driver_name(devinfo), 3544*9485SMikore.Li@Sun.COM ddi_get_instance(devinfo)); 3545*9485SMikore.Li@Sun.COM 3546*9485SMikore.Li@Sun.COM /* override state transition machine */ 3547*9485SMikore.Li@Sun.COM sc->sc_newstate = ic->ic_newstate; 3548*9485SMikore.Li@Sun.COM ic->ic_newstate = urtw_newstate; 3549*9485SMikore.Li@Sun.COM ic->ic_watchdog = urtw_watchdog; 3550*9485SMikore.Li@Sun.COM ieee80211_media_init(ic); 3551*9485SMikore.Li@Sun.COM ic->ic_def_txkey = 0; 3552*9485SMikore.Li@Sun.COM 3553*9485SMikore.Li@Sun.COM sc->dwelltime = 400; 3554*9485SMikore.Li@Sun.COM sc->sc_flags = 0; 3555*9485SMikore.Li@Sun.COM 3556*9485SMikore.Li@Sun.COM /* 3557*9485SMikore.Li@Sun.COM * Provide initial settings for the WiFi plugin; whenever this 3558*9485SMikore.Li@Sun.COM * information changes, we need to call mac_plugindata_update() 3559*9485SMikore.Li@Sun.COM */ 3560*9485SMikore.Li@Sun.COM wd.wd_opmode = ic->ic_opmode; 3561*9485SMikore.Li@Sun.COM wd.wd_secalloc = WIFI_SEC_NONE; 3562*9485SMikore.Li@Sun.COM IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 3563*9485SMikore.Li@Sun.COM 3564*9485SMikore.Li@Sun.COM if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 3565*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT, 3566*9485SMikore.Li@Sun.COM "MAC version alloc failed\n")); 3567*9485SMikore.Li@Sun.COM goto fail4; 3568*9485SMikore.Li@Sun.COM } 3569*9485SMikore.Li@Sun.COM 3570*9485SMikore.Li@Sun.COM macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 3571*9485SMikore.Li@Sun.COM macp->m_driver = sc; 3572*9485SMikore.Li@Sun.COM macp->m_dip = devinfo; 3573*9485SMikore.Li@Sun.COM macp->m_src_addr = ic->ic_macaddr; 3574*9485SMikore.Li@Sun.COM macp->m_callbacks = &urtw_m_callbacks; 3575*9485SMikore.Li@Sun.COM macp->m_min_sdu = 0; 3576*9485SMikore.Li@Sun.COM macp->m_max_sdu = IEEE80211_MTU; 3577*9485SMikore.Li@Sun.COM macp->m_pdata = &wd; 3578*9485SMikore.Li@Sun.COM macp->m_pdata_size = sizeof (wd); 3579*9485SMikore.Li@Sun.COM 3580*9485SMikore.Li@Sun.COM error = mac_register(macp, &ic->ic_mach); 3581*9485SMikore.Li@Sun.COM mac_free(macp); 3582*9485SMikore.Li@Sun.COM if (error != 0) { 3583*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: mac_register() err %x\n", error); 3584*9485SMikore.Li@Sun.COM goto fail4; 3585*9485SMikore.Li@Sun.COM } 3586*9485SMikore.Li@Sun.COM 3587*9485SMikore.Li@Sun.COM if (usb_register_hotplug_cbs(devinfo, urtw_disconnect, 3588*9485SMikore.Li@Sun.COM urtw_reconnect) != USB_SUCCESS) { 3589*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: failed to register events"); 3590*9485SMikore.Li@Sun.COM goto fail5; 3591*9485SMikore.Li@Sun.COM } 3592*9485SMikore.Li@Sun.COM 3593*9485SMikore.Li@Sun.COM /* 3594*9485SMikore.Li@Sun.COM * Create minor node of type DDI_NT_NET_WIFI 3595*9485SMikore.Li@Sun.COM */ 3596*9485SMikore.Li@Sun.COM (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 3597*9485SMikore.Li@Sun.COM "urtw", instance); 3598*9485SMikore.Li@Sun.COM error = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 3599*9485SMikore.Li@Sun.COM instance + 1, DDI_NT_NET_WIFI, 0); 3600*9485SMikore.Li@Sun.COM 3601*9485SMikore.Li@Sun.COM if (error != DDI_SUCCESS) 3602*9485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw: ddi_create_minor_node() failed\n"); 3603*9485SMikore.Li@Sun.COM 3604*9485SMikore.Li@Sun.COM /* 3605*9485SMikore.Li@Sun.COM * Notify link is down now 3606*9485SMikore.Li@Sun.COM */ 3607*9485SMikore.Li@Sun.COM mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 3608*9485SMikore.Li@Sun.COM 3609*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT, 3610*9485SMikore.Li@Sun.COM "urtw_attach: successfully.\n")); 3611*9485SMikore.Li@Sun.COM return (DDI_SUCCESS); 3612*9485SMikore.Li@Sun.COM fail5: 3613*9485SMikore.Li@Sun.COM (void) mac_unregister(ic->ic_mach); 3614*9485SMikore.Li@Sun.COM fail4: 3615*9485SMikore.Li@Sun.COM ieee80211_detach(ic); 3616*9485SMikore.Li@Sun.COM fail3: 3617*9485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock); 3618*9485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock); 3619*9485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock); 3620*9485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock); 3621*9485SMikore.Li@Sun.COM fail2: 3622*9485SMikore.Li@Sun.COM usb_client_detach(sc->sc_dev, sc->sc_udev); 3623*9485SMikore.Li@Sun.COM fail1: 3624*9485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo)); 3625*9485SMikore.Li@Sun.COM 3626*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3627*9485SMikore.Li@Sun.COM } 3628*9485SMikore.Li@Sun.COM 3629*9485SMikore.Li@Sun.COM static int 3630*9485SMikore.Li@Sun.COM urtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 3631*9485SMikore.Li@Sun.COM { 3632*9485SMikore.Li@Sun.COM struct urtw_softc *sc; 3633*9485SMikore.Li@Sun.COM 3634*9485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo)); 3635*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, 3636*9485SMikore.Li@Sun.COM CE_CONT, "urtw_detach()\n")); 3637*9485SMikore.Li@Sun.COM 3638*9485SMikore.Li@Sun.COM switch (cmd) { 3639*9485SMikore.Li@Sun.COM case DDI_DETACH: 3640*9485SMikore.Li@Sun.COM break; 3641*9485SMikore.Li@Sun.COM case DDI_SUSPEND: 3642*9485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, 3643*9485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: suspend\n")); 3644*9485SMikore.Li@Sun.COM 3645*9485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3646*9485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic); 3647*9485SMikore.Li@Sun.COM 3648*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3649*9485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_SUSPEND; 3650*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3651*9485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) { 3652*9485SMikore.Li@Sun.COM urtw_stop(sc); 3653*9485SMikore.Li@Sun.COM URTW_LOCK(sc); 3654*9485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE; 3655*9485SMikore.Li@Sun.COM URTW_UNLOCK(sc); 3656*9485SMikore.Li@Sun.COM } 3657*9485SMikore.Li@Sun.COM return (DDI_SUCCESS); 3658*9485SMikore.Li@Sun.COM default: 3659*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3660*9485SMikore.Li@Sun.COM } 3661*9485SMikore.Li@Sun.COM 3662*9485SMikore.Li@Sun.COM if (mac_disable(sc->sc_ic.ic_mach) != 0) 3663*9485SMikore.Li@Sun.COM return (DDI_FAILURE); 3664*9485SMikore.Li@Sun.COM urtw_stop(sc); 3665*9485SMikore.Li@Sun.COM /* 3666*9485SMikore.Li@Sun.COM * Unregister from the MAC layer subsystem 3667*9485SMikore.Li@Sun.COM */ 3668*9485SMikore.Li@Sun.COM (void) mac_unregister(sc->sc_ic.ic_mach); 3669*9485SMikore.Li@Sun.COM 3670*9485SMikore.Li@Sun.COM ieee80211_detach(&sc->sc_ic); 3671*9485SMikore.Li@Sun.COM usb_unregister_hotplug_cbs(devinfo); 3672*9485SMikore.Li@Sun.COM usb_client_detach(devinfo, sc->sc_udev); 3673*9485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock); 3674*9485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock); 3675*9485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock); 3676*9485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock); 3677*9485SMikore.Li@Sun.COM sc->sc_udev = NULL; 3678*9485SMikore.Li@Sun.COM 3679*9485SMikore.Li@Sun.COM ddi_remove_minor_node(devinfo, NULL); 3680*9485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo)); 3681*9485SMikore.Li@Sun.COM 3682*9485SMikore.Li@Sun.COM return (DDI_SUCCESS); 3683*9485SMikore.Li@Sun.COM } 3684*9485SMikore.Li@Sun.COM 3685*9485SMikore.Li@Sun.COM int 3686*9485SMikore.Li@Sun.COM _info(struct modinfo *modinfop) 3687*9485SMikore.Li@Sun.COM { 3688*9485SMikore.Li@Sun.COM return (mod_info(&modlinkage, modinfop)); 3689*9485SMikore.Li@Sun.COM } 3690*9485SMikore.Li@Sun.COM 3691*9485SMikore.Li@Sun.COM int 3692*9485SMikore.Li@Sun.COM _init(void) 3693*9485SMikore.Li@Sun.COM { 3694*9485SMikore.Li@Sun.COM int status; 3695*9485SMikore.Li@Sun.COM 3696*9485SMikore.Li@Sun.COM status = ddi_soft_state_init(&urtw_soft_state_p, 3697*9485SMikore.Li@Sun.COM sizeof (struct urtw_softc), 1); 3698*9485SMikore.Li@Sun.COM if (status != 0) 3699*9485SMikore.Li@Sun.COM return (status); 3700*9485SMikore.Li@Sun.COM 3701*9485SMikore.Li@Sun.COM mac_init_ops(&urtw_dev_ops, "urtw"); 3702*9485SMikore.Li@Sun.COM status = mod_install(&modlinkage); 3703*9485SMikore.Li@Sun.COM if (status != 0) { 3704*9485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops); 3705*9485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p); 3706*9485SMikore.Li@Sun.COM } 3707*9485SMikore.Li@Sun.COM return (status); 3708*9485SMikore.Li@Sun.COM } 3709*9485SMikore.Li@Sun.COM 3710*9485SMikore.Li@Sun.COM int 3711*9485SMikore.Li@Sun.COM _fini(void) 3712*9485SMikore.Li@Sun.COM { 3713*9485SMikore.Li@Sun.COM int status; 3714*9485SMikore.Li@Sun.COM 3715*9485SMikore.Li@Sun.COM status = mod_remove(&modlinkage); 3716*9485SMikore.Li@Sun.COM if (status == 0) { 3717*9485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops); 3718*9485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p); 3719*9485SMikore.Li@Sun.COM } 3720*9485SMikore.Li@Sun.COM return (status); 3721*9485SMikore.Li@Sun.COM } 3722