1*4609Szf162725 /* 2*4609Szf162725 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3*4609Szf162725 * Use is subject to license terms. 4*4609Szf162725 */ 5*4609Szf162725 6*4609Szf162725 /* 7*4609Szf162725 * Copyright (c) 2005, 2006 8*4609Szf162725 * Damien Bergamini <damien.bergamini@free.fr> 9*4609Szf162725 * 10*4609Szf162725 * Permission to use, copy, modify, and distribute this software for any 11*4609Szf162725 * purpose with or without fee is hereby granted, provided that the above 12*4609Szf162725 * copyright notice and this permission notice appear in all copies. 13*4609Szf162725 * 14*4609Szf162725 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15*4609Szf162725 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16*4609Szf162725 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17*4609Szf162725 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18*4609Szf162725 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19*4609Szf162725 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20*4609Szf162725 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21*4609Szf162725 */ 22*4609Szf162725 23*4609Szf162725 /* 24*4609Szf162725 * Ralink Technology RT2560 chipset driver 25*4609Szf162725 * http://www.ralinktech.com/ 26*4609Szf162725 */ 27*4609Szf162725 28*4609Szf162725 #pragma ident "%Z%%M% %I% %E% SMI" 29*4609Szf162725 30*4609Szf162725 #include <sys/types.h> 31*4609Szf162725 #include <sys/byteorder.h> 32*4609Szf162725 #include <sys/conf.h> 33*4609Szf162725 #include <sys/cmn_err.h> 34*4609Szf162725 #include <sys/stat.h> 35*4609Szf162725 #include <sys/ddi.h> 36*4609Szf162725 #include <sys/sunddi.h> 37*4609Szf162725 #include <sys/strsubr.h> 38*4609Szf162725 #include <sys/ethernet.h> 39*4609Szf162725 #include <inet/common.h> 40*4609Szf162725 #include <inet/nd.h> 41*4609Szf162725 #include <inet/mi.h> 42*4609Szf162725 #include <sys/note.h> 43*4609Szf162725 #include <sys/stream.h> 44*4609Szf162725 #include <sys/strsun.h> 45*4609Szf162725 #include <sys/modctl.h> 46*4609Szf162725 #include <sys/devops.h> 47*4609Szf162725 #include <sys/dlpi.h> 48*4609Szf162725 #include <sys/mac.h> 49*4609Szf162725 #include <sys/mac_wifi.h> 50*4609Szf162725 #include <sys/net80211.h> 51*4609Szf162725 #include <sys/net80211_proto.h> 52*4609Szf162725 #include <sys/varargs.h> 53*4609Szf162725 #include <sys/policy.h> 54*4609Szf162725 #include <sys/pci.h> 55*4609Szf162725 #include <sys/crypto/common.h> 56*4609Szf162725 #include <sys/crypto/api.h> 57*4609Szf162725 #include <inet/wifi_ioctl.h> 58*4609Szf162725 59*4609Szf162725 #include "ral_rate.h" 60*4609Szf162725 #include "rt2560_reg.h" 61*4609Szf162725 #include "rt2560_var.h" 62*4609Szf162725 63*4609Szf162725 64*4609Szf162725 static void *ral_soft_state_p = NULL; 65*4609Szf162725 66*4609Szf162725 #define RAL_TXBUF_SIZE (IEEE80211_MAX_LEN) 67*4609Szf162725 #define RAL_RXBUF_SIZE (IEEE80211_MAX_LEN) 68*4609Szf162725 69*4609Szf162725 /* quickly determine if a given rate is CCK or OFDM */ 70*4609Szf162725 #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) 71*4609Szf162725 #define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */ 72*4609Szf162725 #define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */ 73*4609Szf162725 #define RAL_SIFS 10 /* us */ 74*4609Szf162725 #define RT2560_TXRX_TURNAROUND 10 /* us */ 75*4609Szf162725 76*4609Szf162725 /* 77*4609Szf162725 * Supported rates for 802.11a/b/g modes (in 500Kbps unit). 78*4609Szf162725 */ 79*4609Szf162725 static const struct ieee80211_rateset rt2560_rateset_11a = 80*4609Szf162725 { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } }; 81*4609Szf162725 82*4609Szf162725 static const struct ieee80211_rateset rt2560_rateset_11b = 83*4609Szf162725 { 4, { 2, 4, 11, 22 } }; 84*4609Szf162725 85*4609Szf162725 static const struct ieee80211_rateset rt2560_rateset_11g = 86*4609Szf162725 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 87*4609Szf162725 88*4609Szf162725 static const struct { 89*4609Szf162725 uint32_t reg; 90*4609Szf162725 uint32_t val; 91*4609Szf162725 } rt2560_def_mac[] = { 92*4609Szf162725 RT2560_DEF_MAC 93*4609Szf162725 }; 94*4609Szf162725 95*4609Szf162725 static const struct { 96*4609Szf162725 uint8_t reg; 97*4609Szf162725 uint8_t val; 98*4609Szf162725 } rt2560_def_bbp[] = { 99*4609Szf162725 RT2560_DEF_BBP 100*4609Szf162725 }; 101*4609Szf162725 102*4609Szf162725 static const uint32_t rt2560_rf2522_r2[] = RT2560_RF2522_R2; 103*4609Szf162725 static const uint32_t rt2560_rf2523_r2[] = RT2560_RF2523_R2; 104*4609Szf162725 static const uint32_t rt2560_rf2524_r2[] = RT2560_RF2524_R2; 105*4609Szf162725 static const uint32_t rt2560_rf2525_r2[] = RT2560_RF2525_R2; 106*4609Szf162725 static const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2; 107*4609Szf162725 static const uint32_t rt2560_rf2525e_r2[] = RT2560_RF2525E_R2; 108*4609Szf162725 static const uint32_t rt2560_rf2526_r2[] = RT2560_RF2526_R2; 109*4609Szf162725 static const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2; 110*4609Szf162725 111*4609Szf162725 static const struct { 112*4609Szf162725 uint8_t chan; 113*4609Szf162725 uint32_t r1, r2, r4; 114*4609Szf162725 } rt2560_rf5222[] = { 115*4609Szf162725 RT2560_RF5222 116*4609Szf162725 }; 117*4609Szf162725 118*4609Szf162725 /* 119*4609Szf162725 * PIO access attributes for registers 120*4609Szf162725 */ 121*4609Szf162725 static ddi_device_acc_attr_t ral_csr_accattr = { 122*4609Szf162725 DDI_DEVICE_ATTR_V0, 123*4609Szf162725 DDI_STRUCTURE_LE_ACC, 124*4609Szf162725 DDI_STRICTORDER_ACC 125*4609Szf162725 }; 126*4609Szf162725 127*4609Szf162725 /* 128*4609Szf162725 * DMA access attributes for descriptors: NOT to be byte swapped. 129*4609Szf162725 */ 130*4609Szf162725 static ddi_device_acc_attr_t ral_desc_accattr = { 131*4609Szf162725 DDI_DEVICE_ATTR_V0, 132*4609Szf162725 DDI_STRUCTURE_LE_ACC, 133*4609Szf162725 DDI_STRICTORDER_ACC 134*4609Szf162725 }; 135*4609Szf162725 136*4609Szf162725 /* 137*4609Szf162725 * Describes the chip's DMA engine 138*4609Szf162725 */ 139*4609Szf162725 static ddi_dma_attr_t ral_dma_attr = { 140*4609Szf162725 DMA_ATTR_V0, /* dma_attr version */ 141*4609Szf162725 0x0000000000000000ull, /* dma_attr_addr_lo */ 142*4609Szf162725 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */ 143*4609Szf162725 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 144*4609Szf162725 0x0000000000000001ull, /* dma_attr_align */ 145*4609Szf162725 0x00000FFF, /* dma_attr_burstsizes */ 146*4609Szf162725 0x00000001, /* dma_attr_minxfer */ 147*4609Szf162725 0x000000000000FFFFull, /* dma_attr_maxxfer */ 148*4609Szf162725 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 149*4609Szf162725 1, /* dma_attr_sgllen */ 150*4609Szf162725 0x00000001, /* dma_attr_granular */ 151*4609Szf162725 0 /* dma_attr_flags */ 152*4609Szf162725 }; 153*4609Szf162725 154*4609Szf162725 /* 155*4609Szf162725 * device operations 156*4609Szf162725 */ 157*4609Szf162725 static int rt2560_attach(dev_info_t *, ddi_attach_cmd_t); 158*4609Szf162725 static int rt2560_detach(dev_info_t *, ddi_detach_cmd_t); 159*4609Szf162725 static int rt2560_reset(dev_info_t *, ddi_reset_cmd_t); 160*4609Szf162725 161*4609Szf162725 /* 162*4609Szf162725 * Module Loading Data & Entry Points 163*4609Szf162725 */ 164*4609Szf162725 DDI_DEFINE_STREAM_OPS(ral_dev_ops, nulldev, nulldev, rt2560_attach, 165*4609Szf162725 rt2560_detach, rt2560_reset, NULL, D_MP, NULL); 166*4609Szf162725 167*4609Szf162725 static struct modldrv ral_modldrv = { 168*4609Szf162725 &mod_driverops, /* Type of module. This one is a driver */ 169*4609Szf162725 "Ralink RT2500 driver v%I%", /* short description */ 170*4609Szf162725 &ral_dev_ops /* driver specific ops */ 171*4609Szf162725 }; 172*4609Szf162725 173*4609Szf162725 static struct modlinkage modlinkage = { 174*4609Szf162725 MODREV_1, 175*4609Szf162725 (void *)&ral_modldrv, 176*4609Szf162725 NULL 177*4609Szf162725 }; 178*4609Szf162725 179*4609Szf162725 static int rt2560_m_stat(void *, uint_t, uint64_t *); 180*4609Szf162725 static int rt2560_m_start(void *); 181*4609Szf162725 static void rt2560_m_stop(void *); 182*4609Szf162725 static int rt2560_m_promisc(void *, boolean_t); 183*4609Szf162725 static int rt2560_m_multicst(void *, boolean_t, const uint8_t *); 184*4609Szf162725 static int rt2560_m_unicst(void *, const uint8_t *); 185*4609Szf162725 static mblk_t *rt2560_m_tx(void *, mblk_t *); 186*4609Szf162725 static void rt2560_m_ioctl(void *, queue_t *, mblk_t *); 187*4609Szf162725 188*4609Szf162725 static mac_callbacks_t rt2560_m_callbacks = { 189*4609Szf162725 MC_IOCTL, 190*4609Szf162725 rt2560_m_stat, 191*4609Szf162725 rt2560_m_start, 192*4609Szf162725 rt2560_m_stop, 193*4609Szf162725 rt2560_m_promisc, 194*4609Szf162725 rt2560_m_multicst, 195*4609Szf162725 rt2560_m_unicst, 196*4609Szf162725 rt2560_m_tx, 197*4609Szf162725 NULL, /* mc_resources; */ 198*4609Szf162725 rt2560_m_ioctl, 199*4609Szf162725 NULL /* mc_getcapab */ 200*4609Szf162725 }; 201*4609Szf162725 202*4609Szf162725 uint32_t ral_dbg_flags = 0; 203*4609Szf162725 204*4609Szf162725 void 205*4609Szf162725 ral_debug(uint32_t dbg_flags, const int8_t *fmt, ...) 206*4609Szf162725 { 207*4609Szf162725 va_list args; 208*4609Szf162725 209*4609Szf162725 if (dbg_flags & ral_dbg_flags) { 210*4609Szf162725 va_start(args, fmt); 211*4609Szf162725 vcmn_err(CE_CONT, fmt, args); 212*4609Szf162725 va_end(args); 213*4609Szf162725 } 214*4609Szf162725 } 215*4609Szf162725 216*4609Szf162725 static void 217*4609Szf162725 rt2560_set_basicrates(struct rt2560_softc *sc) 218*4609Szf162725 { 219*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 220*4609Szf162725 221*4609Szf162725 /* update basic rate set */ 222*4609Szf162725 if (ic->ic_curmode == IEEE80211_MODE_11B) { 223*4609Szf162725 /* 11b basic rates: 1, 2Mbps */ 224*4609Szf162725 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x3); 225*4609Szf162725 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) { 226*4609Szf162725 /* 11a basic rates: 6, 12, 24Mbps */ 227*4609Szf162725 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x150); 228*4609Szf162725 } else { 229*4609Szf162725 /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ 230*4609Szf162725 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x15f); 231*4609Szf162725 } 232*4609Szf162725 } 233*4609Szf162725 234*4609Szf162725 static void 235*4609Szf162725 rt2560_update_led(struct rt2560_softc *sc, int led1, int led2) 236*4609Szf162725 { 237*4609Szf162725 uint32_t tmp; 238*4609Szf162725 239*4609Szf162725 /* set ON period to 70ms and OFF period to 30ms */ 240*4609Szf162725 tmp = led1 << 16 | led2 << 17 | 70 << 8 | 30; 241*4609Szf162725 RAL_WRITE(sc, RT2560_LEDCSR, tmp); 242*4609Szf162725 } 243*4609Szf162725 244*4609Szf162725 static void 245*4609Szf162725 rt2560_set_bssid(struct rt2560_softc *sc, uint8_t *bssid) 246*4609Szf162725 { 247*4609Szf162725 uint32_t tmp; 248*4609Szf162725 249*4609Szf162725 tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24; 250*4609Szf162725 RAL_WRITE(sc, RT2560_CSR5, tmp); 251*4609Szf162725 252*4609Szf162725 tmp = bssid[4] | bssid[5] << 8; 253*4609Szf162725 RAL_WRITE(sc, RT2560_CSR6, tmp); 254*4609Szf162725 255*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "setting BSSID to " MACSTR "\n", MAC2STR(bssid)); 256*4609Szf162725 } 257*4609Szf162725 258*4609Szf162725 259*4609Szf162725 static void 260*4609Szf162725 rt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val) 261*4609Szf162725 { 262*4609Szf162725 uint32_t tmp; 263*4609Szf162725 int ntries; 264*4609Szf162725 265*4609Szf162725 for (ntries = 0; ntries < 100; ntries++) { 266*4609Szf162725 if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY)) 267*4609Szf162725 break; 268*4609Szf162725 drv_usecwait(1); 269*4609Szf162725 } 270*4609Szf162725 if (ntries == 100) { 271*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "could not write to BBP\n"); 272*4609Szf162725 return; 273*4609Szf162725 } 274*4609Szf162725 275*4609Szf162725 tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val; 276*4609Szf162725 RAL_WRITE(sc, RT2560_BBPCSR, tmp); 277*4609Szf162725 278*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "BBP R%u <- 0x%02x\n", reg, val); 279*4609Szf162725 } 280*4609Szf162725 281*4609Szf162725 static uint8_t 282*4609Szf162725 rt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg) 283*4609Szf162725 { 284*4609Szf162725 uint32_t val; 285*4609Szf162725 int ntries; 286*4609Szf162725 287*4609Szf162725 val = RT2560_BBP_BUSY | reg << 8; 288*4609Szf162725 RAL_WRITE(sc, RT2560_BBPCSR, val); 289*4609Szf162725 290*4609Szf162725 for (ntries = 0; ntries < 100; ntries++) { 291*4609Szf162725 val = RAL_READ(sc, RT2560_BBPCSR); 292*4609Szf162725 if (!(val & RT2560_BBP_BUSY)) 293*4609Szf162725 return (val & 0xff); 294*4609Szf162725 drv_usecwait(1); 295*4609Szf162725 } 296*4609Szf162725 297*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "could not read from BBP\n"); 298*4609Szf162725 return (0); 299*4609Szf162725 } 300*4609Szf162725 301*4609Szf162725 static void 302*4609Szf162725 rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val) 303*4609Szf162725 { 304*4609Szf162725 uint32_t tmp; 305*4609Szf162725 int ntries; 306*4609Szf162725 307*4609Szf162725 for (ntries = 0; ntries < 100; ntries++) { 308*4609Szf162725 if (!(RAL_READ(sc, RT2560_RFCSR) & RT2560_RF_BUSY)) 309*4609Szf162725 break; 310*4609Szf162725 drv_usecwait(1); 311*4609Szf162725 } 312*4609Szf162725 if (ntries == 100) { 313*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "could not write to RF\n"); 314*4609Szf162725 return; 315*4609Szf162725 } 316*4609Szf162725 317*4609Szf162725 tmp = RT2560_RF_BUSY | RT2560_RF_20BIT | (val & 0xfffff) << 2 | 318*4609Szf162725 (reg & 0x3); 319*4609Szf162725 RAL_WRITE(sc, RT2560_RFCSR, tmp); 320*4609Szf162725 321*4609Szf162725 /* remember last written value in sc */ 322*4609Szf162725 sc->rf_regs[reg] = val; 323*4609Szf162725 324*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); 325*4609Szf162725 } 326*4609Szf162725 327*4609Szf162725 static void 328*4609Szf162725 rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) 329*4609Szf162725 { 330*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 331*4609Szf162725 uint8_t power, tmp; 332*4609Szf162725 uint_t i, chan; 333*4609Szf162725 334*4609Szf162725 chan = ieee80211_chan2ieee(ic, c); 335*4609Szf162725 if (chan == 0 || chan == IEEE80211_CHAN_ANY) 336*4609Szf162725 return; 337*4609Szf162725 338*4609Szf162725 if (IEEE80211_IS_CHAN_2GHZ(c)) 339*4609Szf162725 power = min(sc->txpow[chan - 1], 31); 340*4609Szf162725 else 341*4609Szf162725 power = 31; 342*4609Szf162725 343*4609Szf162725 /* adjust txpower using ifconfig settings */ 344*4609Szf162725 power -= (100 - ic->ic_txpowlimit) / 8; 345*4609Szf162725 346*4609Szf162725 RAL_DEBUG(RAL_DBG_CHAN, "setting channel to %u, txpower to %u\n", 347*4609Szf162725 chan, power); 348*4609Szf162725 349*4609Szf162725 switch (sc->rf_rev) { 350*4609Szf162725 case RT2560_RF_2522: 351*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x00814); 352*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2522_r2[chan - 1]); 353*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 354*4609Szf162725 break; 355*4609Szf162725 356*4609Szf162725 case RT2560_RF_2523: 357*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x08804); 358*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2523_r2[chan - 1]); 359*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x38044); 360*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 361*4609Szf162725 break; 362*4609Szf162725 363*4609Szf162725 case RT2560_RF_2524: 364*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x0c808); 365*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2524_r2[chan - 1]); 366*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 367*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 368*4609Szf162725 break; 369*4609Szf162725 370*4609Szf162725 case RT2560_RF_2525: 371*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x08808); 372*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_hi_r2[chan - 1]); 373*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 374*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 375*4609Szf162725 376*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x08808); 377*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_r2[chan - 1]); 378*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 379*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 380*4609Szf162725 break; 381*4609Szf162725 382*4609Szf162725 case RT2560_RF_2525E: 383*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x08808); 384*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525e_r2[chan - 1]); 385*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 386*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); 387*4609Szf162725 break; 388*4609Szf162725 389*4609Szf162725 case RT2560_RF_2526: 390*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_hi_r2[chan - 1]); 391*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 392*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, 0x08804); 393*4609Szf162725 394*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_r2[chan - 1]); 395*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 396*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 397*4609Szf162725 break; 398*4609Szf162725 399*4609Szf162725 /* dual-band RF */ 400*4609Szf162725 case RT2560_RF_5222: 401*4609Szf162725 for (i = 0; rt2560_rf5222[i].chan != chan; i++) { 402*4609Szf162725 } 403*4609Szf162725 404*4609Szf162725 rt2560_rf_write(sc, RAL_RF1, rt2560_rf5222[i].r1); 405*4609Szf162725 rt2560_rf_write(sc, RAL_RF2, rt2560_rf5222[i].r2); 406*4609Szf162725 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 407*4609Szf162725 rt2560_rf_write(sc, RAL_RF4, rt2560_rf5222[i].r4); 408*4609Szf162725 break; 409*4609Szf162725 } 410*4609Szf162725 411*4609Szf162725 if (ic->ic_state != IEEE80211_S_SCAN) { 412*4609Szf162725 /* set Japan filter bit for channel 14 */ 413*4609Szf162725 tmp = rt2560_bbp_read(sc, 70); 414*4609Szf162725 415*4609Szf162725 tmp &= ~RT2560_JAPAN_FILTER; 416*4609Szf162725 if (chan == 14) 417*4609Szf162725 tmp |= RT2560_JAPAN_FILTER; 418*4609Szf162725 419*4609Szf162725 rt2560_bbp_write(sc, 70, tmp); 420*4609Szf162725 421*4609Szf162725 /* clear CRC errors */ 422*4609Szf162725 (void) RAL_READ(sc, RT2560_CNT0); 423*4609Szf162725 } 424*4609Szf162725 } 425*4609Szf162725 426*4609Szf162725 /* 427*4609Szf162725 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF 428*4609Szf162725 * synchronization. 429*4609Szf162725 */ 430*4609Szf162725 static void 431*4609Szf162725 rt2560_enable_tsf_sync(struct rt2560_softc *sc) 432*4609Szf162725 { 433*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 434*4609Szf162725 uint16_t logcwmin, preload; 435*4609Szf162725 uint32_t tmp; 436*4609Szf162725 437*4609Szf162725 /* first, disable TSF synchronization */ 438*4609Szf162725 RAL_WRITE(sc, RT2560_CSR14, 0); 439*4609Szf162725 440*4609Szf162725 tmp = 16 * ic->ic_bss->in_intval; 441*4609Szf162725 RAL_WRITE(sc, RT2560_CSR12, tmp); 442*4609Szf162725 443*4609Szf162725 RAL_WRITE(sc, RT2560_CSR13, 0); 444*4609Szf162725 445*4609Szf162725 logcwmin = 5; 446*4609Szf162725 preload = (ic->ic_opmode == IEEE80211_M_STA) ? 384 : 1024; 447*4609Szf162725 tmp = logcwmin << 16 | preload; 448*4609Szf162725 RAL_WRITE(sc, RT2560_BCNOCSR, tmp); 449*4609Szf162725 450*4609Szf162725 /* finally, enable TSF synchronization */ 451*4609Szf162725 tmp = RT2560_ENABLE_TSF | RT2560_ENABLE_TBCN; 452*4609Szf162725 if (ic->ic_opmode == IEEE80211_M_STA) 453*4609Szf162725 tmp |= RT2560_ENABLE_TSF_SYNC(1); 454*4609Szf162725 else 455*4609Szf162725 tmp |= RT2560_ENABLE_TSF_SYNC(2) | 456*4609Szf162725 RT2560_ENABLE_BEACON_GENERATOR; 457*4609Szf162725 RAL_WRITE(sc, RT2560_CSR14, tmp); 458*4609Szf162725 459*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "enabling TSF synchronization\n"); 460*4609Szf162725 } 461*4609Szf162725 462*4609Szf162725 static void 463*4609Szf162725 rt2560_update_plcp(struct rt2560_softc *sc) 464*4609Szf162725 { 465*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 466*4609Szf162725 467*4609Szf162725 /* no short preamble for 1Mbps */ 468*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400); 469*4609Szf162725 470*4609Szf162725 if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) { 471*4609Szf162725 /* values taken from the reference driver */ 472*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380401); 473*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x00150402); 474*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b8403); 475*4609Szf162725 } else { 476*4609Szf162725 /* same values as above or'ed 0x8 */ 477*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380409); 478*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x0015040a); 479*4609Szf162725 RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b840b); 480*4609Szf162725 } 481*4609Szf162725 482*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "updating PLCP for %s preamble\n", 483*4609Szf162725 (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long"); 484*4609Szf162725 } 485*4609Szf162725 486*4609Szf162725 /* 487*4609Szf162725 * This function can be called by ieee80211_set_shortslottime(). Refer to 488*4609Szf162725 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed. 489*4609Szf162725 */ 490*4609Szf162725 void 491*4609Szf162725 rt2560_update_slot(struct ieee80211com *ic, int onoff) 492*4609Szf162725 { 493*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)ic; 494*4609Szf162725 uint8_t slottime; 495*4609Szf162725 uint16_t tx_sifs, tx_pifs, tx_difs, eifs; 496*4609Szf162725 uint32_t tmp; 497*4609Szf162725 498*4609Szf162725 /* slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; */ 499*4609Szf162725 slottime = (onoff ? 9 : 20); 500*4609Szf162725 501*4609Szf162725 /* update the MAC slot boundaries */ 502*4609Szf162725 tx_sifs = RAL_SIFS - RT2560_TXRX_TURNAROUND; 503*4609Szf162725 tx_pifs = tx_sifs + slottime; 504*4609Szf162725 tx_difs = tx_sifs + 2 * slottime; 505*4609Szf162725 eifs = (ic->ic_curmode == IEEE80211_MODE_11B) ? 364 : 60; 506*4609Szf162725 507*4609Szf162725 tmp = RAL_READ(sc, RT2560_CSR11); 508*4609Szf162725 tmp = (tmp & ~0x1f00) | slottime << 8; 509*4609Szf162725 RAL_WRITE(sc, RT2560_CSR11, tmp); 510*4609Szf162725 511*4609Szf162725 tmp = tx_pifs << 16 | tx_sifs; 512*4609Szf162725 RAL_WRITE(sc, RT2560_CSR18, tmp); 513*4609Szf162725 514*4609Szf162725 tmp = eifs << 16 | tx_difs; 515*4609Szf162725 RAL_WRITE(sc, RT2560_CSR19, tmp); 516*4609Szf162725 517*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "setting slottime to %uus\n", slottime); 518*4609Szf162725 } 519*4609Szf162725 520*4609Szf162725 int 521*4609Szf162725 ral_dma_region_alloc(struct rt2560_softc *sc, struct dma_region *dr, 522*4609Szf162725 size_t size, uint_t alloc_flags, uint_t bind_flags) 523*4609Szf162725 { 524*4609Szf162725 dev_info_t *dip = sc->sc_dev; 525*4609Szf162725 int err; 526*4609Szf162725 527*4609Szf162725 RAL_DEBUG(RAL_DBG_DMA, "ral_dma_region_alloc() size=%u\n", size); 528*4609Szf162725 529*4609Szf162725 err = ddi_dma_alloc_handle(dip, &ral_dma_attr, DDI_DMA_SLEEP, NULL, 530*4609Szf162725 &dr->dr_hnd); 531*4609Szf162725 if (err != DDI_SUCCESS) 532*4609Szf162725 goto fail1; 533*4609Szf162725 534*4609Szf162725 err = ddi_dma_mem_alloc(dr->dr_hnd, size, &ral_desc_accattr, 535*4609Szf162725 alloc_flags, DDI_DMA_SLEEP, NULL, 536*4609Szf162725 &dr->dr_base, &dr->dr_size, &dr->dr_acc); 537*4609Szf162725 if (err != DDI_SUCCESS) 538*4609Szf162725 goto fail2; 539*4609Szf162725 540*4609Szf162725 err = ddi_dma_addr_bind_handle(dr->dr_hnd, NULL, 541*4609Szf162725 dr->dr_base, dr->dr_size, 542*4609Szf162725 bind_flags, DDI_DMA_SLEEP, NULL, &dr->dr_cookie, &dr->dr_ccnt); 543*4609Szf162725 if (err != DDI_SUCCESS) 544*4609Szf162725 goto fail3; 545*4609Szf162725 546*4609Szf162725 if (dr->dr_ccnt != 1) { 547*4609Szf162725 err = DDI_FAILURE; 548*4609Szf162725 goto fail4; 549*4609Szf162725 } 550*4609Szf162725 551*4609Szf162725 dr->dr_pbase = dr->dr_cookie.dmac_address; 552*4609Szf162725 RAL_DEBUG(RAL_DBG_DMA, "get physical-base=0x%08x\n", dr->dr_pbase); 553*4609Szf162725 554*4609Szf162725 return (DDI_SUCCESS); 555*4609Szf162725 556*4609Szf162725 fail4: 557*4609Szf162725 (void) ddi_dma_unbind_handle(dr->dr_hnd); 558*4609Szf162725 fail3: 559*4609Szf162725 ddi_dma_mem_free(&dr->dr_acc); 560*4609Szf162725 fail2: 561*4609Szf162725 ddi_dma_free_handle(&dr->dr_hnd); 562*4609Szf162725 fail1: 563*4609Szf162725 return (err); 564*4609Szf162725 } 565*4609Szf162725 566*4609Szf162725 /* ARGSUSED */ 567*4609Szf162725 void 568*4609Szf162725 ral_dma_region_free(struct rt2560_softc *sc, struct dma_region *dr) 569*4609Szf162725 { 570*4609Szf162725 (void) ddi_dma_unbind_handle(dr->dr_hnd); 571*4609Szf162725 ddi_dma_mem_free(&dr->dr_acc); 572*4609Szf162725 ddi_dma_free_handle(&dr->dr_hnd); 573*4609Szf162725 } 574*4609Szf162725 575*4609Szf162725 int 576*4609Szf162725 rt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring, 577*4609Szf162725 int count) 578*4609Szf162725 { 579*4609Szf162725 int i, err; 580*4609Szf162725 int size; 581*4609Szf162725 582*4609Szf162725 ring->count = count; 583*4609Szf162725 ring->queued = 0; 584*4609Szf162725 ring->cur = ring->next = 0; 585*4609Szf162725 ring->cur_encrypt = ring->next_encrypt = 0; 586*4609Szf162725 587*4609Szf162725 ring->data = kmem_zalloc(count * (sizeof (struct rt2560_tx_data)), 588*4609Szf162725 KM_SLEEP); 589*4609Szf162725 ring->dr_txbuf = kmem_zalloc(count * (sizeof (struct dma_region)), 590*4609Szf162725 KM_SLEEP); 591*4609Szf162725 592*4609Szf162725 err = ral_dma_region_alloc(sc, &ring->dr_desc, 593*4609Szf162725 count * (sizeof (struct rt2560_tx_desc)), 594*4609Szf162725 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT); 595*4609Szf162725 596*4609Szf162725 if (err != DDI_SUCCESS) 597*4609Szf162725 goto fail1; 598*4609Szf162725 599*4609Szf162725 size = roundup(RAL_TXBUF_SIZE, sc->sc_cachelsz); 600*4609Szf162725 for (i = 0; i < count; i++) { 601*4609Szf162725 err = ral_dma_region_alloc(sc, &ring->dr_txbuf[i], size, 602*4609Szf162725 DDI_DMA_STREAMING, DDI_DMA_WRITE | DDI_DMA_STREAMING); 603*4609Szf162725 if (err != DDI_SUCCESS) { 604*4609Szf162725 while (i >= 0) { 605*4609Szf162725 ral_dma_region_free(sc, &ring->dr_txbuf[i]); 606*4609Szf162725 i--; 607*4609Szf162725 } 608*4609Szf162725 goto fail2; 609*4609Szf162725 } 610*4609Szf162725 } 611*4609Szf162725 612*4609Szf162725 ring->physaddr = LE_32(ring->dr_desc.dr_pbase); 613*4609Szf162725 ring->desc = (struct rt2560_tx_desc *)ring->dr_desc.dr_base; 614*4609Szf162725 615*4609Szf162725 for (i = 0; i < count; i++) { 616*4609Szf162725 ring->desc[i].physaddr = LE_32(ring->dr_txbuf[i].dr_pbase); 617*4609Szf162725 ring->data[i].buf = ring->dr_txbuf[i].dr_base; 618*4609Szf162725 } 619*4609Szf162725 620*4609Szf162725 return (DDI_SUCCESS); 621*4609Szf162725 fail2: 622*4609Szf162725 ral_dma_region_free(sc, &ring->dr_desc); 623*4609Szf162725 fail1: 624*4609Szf162725 return (err); 625*4609Szf162725 } 626*4609Szf162725 627*4609Szf162725 /* ARGSUSED */ 628*4609Szf162725 void 629*4609Szf162725 rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) 630*4609Szf162725 { 631*4609Szf162725 struct rt2560_tx_desc *desc; 632*4609Szf162725 struct rt2560_tx_data *data; 633*4609Szf162725 int i; 634*4609Szf162725 635*4609Szf162725 for (i = 0; i < ring->count; i++) { 636*4609Szf162725 desc = &ring->desc[i]; 637*4609Szf162725 data = &ring->data[i]; 638*4609Szf162725 639*4609Szf162725 if (data->ni != NULL) { 640*4609Szf162725 ieee80211_free_node(data->ni); 641*4609Szf162725 data->ni = NULL; 642*4609Szf162725 } 643*4609Szf162725 644*4609Szf162725 desc->flags = 0; 645*4609Szf162725 } 646*4609Szf162725 647*4609Szf162725 (void) ddi_dma_sync(ring->dr_desc.dr_hnd, 0, 648*4609Szf162725 ring->count * sizeof (struct rt2560_tx_desc), DDI_DMA_SYNC_FORDEV); 649*4609Szf162725 650*4609Szf162725 ring->queued = 0; 651*4609Szf162725 ring->cur = ring->next = 0; 652*4609Szf162725 ring->cur_encrypt = ring->next_encrypt = 0; 653*4609Szf162725 } 654*4609Szf162725 655*4609Szf162725 void 656*4609Szf162725 rt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) 657*4609Szf162725 { 658*4609Szf162725 struct rt2560_tx_data *data; 659*4609Szf162725 int i; 660*4609Szf162725 661*4609Szf162725 ral_dma_region_free(sc, &ring->dr_desc); 662*4609Szf162725 /* tx buf */ 663*4609Szf162725 for (i = 0; i < ring->count; i++) { 664*4609Szf162725 data = &ring->data[i]; 665*4609Szf162725 if (data->ni != NULL) { 666*4609Szf162725 ieee80211_free_node(data->ni); 667*4609Szf162725 data->ni = NULL; 668*4609Szf162725 } 669*4609Szf162725 670*4609Szf162725 ral_dma_region_free(sc, &ring->dr_txbuf[i]); 671*4609Szf162725 } 672*4609Szf162725 673*4609Szf162725 kmem_free(ring->data, ring->count * (sizeof (struct rt2560_tx_data))); 674*4609Szf162725 kmem_free(ring->dr_txbuf, ring->count * (sizeof (struct dma_region))); 675*4609Szf162725 } 676*4609Szf162725 677*4609Szf162725 void 678*4609Szf162725 rt2560_ring_hwsetup(struct rt2560_softc *sc) 679*4609Szf162725 { 680*4609Szf162725 uint32_t tmp; 681*4609Szf162725 682*4609Szf162725 /* setup tx rings */ 683*4609Szf162725 tmp = ((uint32_t)RT2560_PRIO_RING_COUNT << 24) | 684*4609Szf162725 RT2560_ATIM_RING_COUNT << 16 | 685*4609Szf162725 RT2560_TX_RING_COUNT << 8 | 686*4609Szf162725 RT2560_TX_DESC_SIZE; 687*4609Szf162725 688*4609Szf162725 /* rings must be initialized in this exact order */ 689*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR2, tmp); 690*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR3, sc->txq.physaddr); 691*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR5, sc->prioq.physaddr); 692*4609Szf162725 693*4609Szf162725 /* setup rx ring */ 694*4609Szf162725 tmp = RT2560_RX_RING_COUNT << 8 | RT2560_RX_DESC_SIZE; 695*4609Szf162725 696*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR1, tmp); 697*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR2, sc->rxq.physaddr); 698*4609Szf162725 } 699*4609Szf162725 700*4609Szf162725 int 701*4609Szf162725 rt2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring, 702*4609Szf162725 int count) 703*4609Szf162725 { 704*4609Szf162725 struct rt2560_rx_desc *desc; 705*4609Szf162725 struct rt2560_rx_data *data; 706*4609Szf162725 int i, err; 707*4609Szf162725 int size; 708*4609Szf162725 709*4609Szf162725 ring->count = count; 710*4609Szf162725 ring->cur = ring->next = 0; 711*4609Szf162725 ring->cur_decrypt = 0; 712*4609Szf162725 713*4609Szf162725 ring->data = kmem_zalloc(count * (sizeof (struct rt2560_rx_data)), 714*4609Szf162725 KM_SLEEP); 715*4609Szf162725 ring->dr_rxbuf = kmem_zalloc(count * (sizeof (struct dma_region)), 716*4609Szf162725 KM_SLEEP); 717*4609Szf162725 718*4609Szf162725 err = ral_dma_region_alloc(sc, &ring->dr_desc, 719*4609Szf162725 count * (sizeof (struct rt2560_rx_desc)), 720*4609Szf162725 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT); 721*4609Szf162725 722*4609Szf162725 if (err != DDI_SUCCESS) 723*4609Szf162725 goto fail1; 724*4609Szf162725 725*4609Szf162725 size = roundup(RAL_RXBUF_SIZE, sc->sc_cachelsz); 726*4609Szf162725 for (i = 0; i < count; i++) { 727*4609Szf162725 err = ral_dma_region_alloc(sc, &ring->dr_rxbuf[i], size, 728*4609Szf162725 DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING); 729*4609Szf162725 if (err != DDI_SUCCESS) { 730*4609Szf162725 while (i >= 0) { 731*4609Szf162725 ral_dma_region_free(sc, &ring->dr_rxbuf[i]); 732*4609Szf162725 i--; 733*4609Szf162725 } 734*4609Szf162725 goto fail2; 735*4609Szf162725 } 736*4609Szf162725 } 737*4609Szf162725 738*4609Szf162725 ring->physaddr = ring->dr_desc.dr_pbase; 739*4609Szf162725 ring->desc = (struct rt2560_rx_desc *)ring->dr_desc.dr_base; 740*4609Szf162725 741*4609Szf162725 for (i = 0; i < count; i++) { 742*4609Szf162725 desc = &ring->desc[i]; 743*4609Szf162725 data = &ring->data[i]; 744*4609Szf162725 745*4609Szf162725 desc->physaddr = LE_32(ring->dr_rxbuf[i].dr_pbase); 746*4609Szf162725 desc->flags = LE_32(RT2560_RX_BUSY); 747*4609Szf162725 748*4609Szf162725 data->buf = ring->dr_rxbuf[i].dr_base; 749*4609Szf162725 } 750*4609Szf162725 751*4609Szf162725 return (DDI_SUCCESS); 752*4609Szf162725 fail2: 753*4609Szf162725 ral_dma_region_free(sc, &ring->dr_desc); 754*4609Szf162725 fail1: 755*4609Szf162725 return (err); 756*4609Szf162725 } 757*4609Szf162725 758*4609Szf162725 /* ARGSUSED */ 759*4609Szf162725 static void 760*4609Szf162725 rt2560_reset_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) 761*4609Szf162725 { 762*4609Szf162725 int i; 763*4609Szf162725 764*4609Szf162725 for (i = 0; i < ring->count; i++) { 765*4609Szf162725 ring->desc[i].flags = LE_32(RT2560_RX_BUSY); 766*4609Szf162725 ring->data[i].drop = 0; 767*4609Szf162725 } 768*4609Szf162725 769*4609Szf162725 (void) ddi_dma_sync(ring->dr_desc.dr_hnd, 0, 770*4609Szf162725 ring->count * sizeof (struct rt2560_rx_desc), 771*4609Szf162725 DDI_DMA_SYNC_FORKERNEL); 772*4609Szf162725 773*4609Szf162725 ring->cur = ring->next = 0; 774*4609Szf162725 ring->cur_decrypt = 0; 775*4609Szf162725 } 776*4609Szf162725 777*4609Szf162725 static void 778*4609Szf162725 rt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) 779*4609Szf162725 { 780*4609Szf162725 int i; 781*4609Szf162725 782*4609Szf162725 ral_dma_region_free(sc, &ring->dr_desc); 783*4609Szf162725 /* rx buf */ 784*4609Szf162725 for (i = 0; i < ring->count; i++) 785*4609Szf162725 ral_dma_region_free(sc, &ring->dr_rxbuf[i]); 786*4609Szf162725 787*4609Szf162725 kmem_free(ring->data, ring->count * (sizeof (struct rt2560_rx_data))); 788*4609Szf162725 kmem_free(ring->dr_rxbuf, ring->count * (sizeof (struct dma_region))); 789*4609Szf162725 } 790*4609Szf162725 791*4609Szf162725 /* ARGSUSED */ 792*4609Szf162725 static struct ieee80211_node * 793*4609Szf162725 rt2560_node_alloc(ieee80211com_t *ic) 794*4609Szf162725 { 795*4609Szf162725 struct rt2560_node *rn; 796*4609Szf162725 797*4609Szf162725 rn = kmem_zalloc(sizeof (struct rt2560_node), KM_SLEEP); 798*4609Szf162725 return ((rn != NULL) ? &rn->ni : NULL); 799*4609Szf162725 } 800*4609Szf162725 801*4609Szf162725 static void 802*4609Szf162725 rt2560_node_free(struct ieee80211_node *in) 803*4609Szf162725 { 804*4609Szf162725 ieee80211com_t *ic = in->in_ic; 805*4609Szf162725 806*4609Szf162725 ic->ic_node_cleanup(in); 807*4609Szf162725 if (in->in_wpa_ie != NULL) 808*4609Szf162725 ieee80211_free(in->in_wpa_ie); 809*4609Szf162725 kmem_free(in, sizeof (struct rt2560_node)); 810*4609Szf162725 } 811*4609Szf162725 812*4609Szf162725 /* 813*4609Szf162725 * This function is called periodically (every 200ms) during scanning to 814*4609Szf162725 * switch from one channel to another. 815*4609Szf162725 */ 816*4609Szf162725 static void 817*4609Szf162725 rt2560_next_scan(void *arg) 818*4609Szf162725 { 819*4609Szf162725 struct rt2560_softc *sc = arg; 820*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 821*4609Szf162725 822*4609Szf162725 if (ic->ic_state == IEEE80211_S_SCAN) 823*4609Szf162725 (void) ieee80211_next_scan(ic); 824*4609Szf162725 } 825*4609Szf162725 826*4609Szf162725 /* 827*4609Szf162725 * This function is called for each node present in the node station table. 828*4609Szf162725 */ 829*4609Szf162725 /* ARGSUSED */ 830*4609Szf162725 static void 831*4609Szf162725 rt2560_iter_func(void *arg, struct ieee80211_node *ni) 832*4609Szf162725 { 833*4609Szf162725 struct rt2560_node *rn = (struct rt2560_node *)ni; 834*4609Szf162725 835*4609Szf162725 ral_rssadapt_updatestats(&rn->rssadapt); 836*4609Szf162725 } 837*4609Szf162725 838*4609Szf162725 /* 839*4609Szf162725 * This function is called periodically (every 100ms) in RUN state to update 840*4609Szf162725 * the rate adaptation statistics. 841*4609Szf162725 */ 842*4609Szf162725 static void 843*4609Szf162725 rt2560_update_rssadapt(void *arg) 844*4609Szf162725 { 845*4609Szf162725 struct rt2560_softc *sc = arg; 846*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 847*4609Szf162725 848*4609Szf162725 ieee80211_iterate_nodes(&ic->ic_sta, rt2560_iter_func, arg); 849*4609Szf162725 sc->sc_rssadapt_id = timeout(rt2560_update_rssadapt, (void *)sc, 850*4609Szf162725 drv_usectohz(100 * 1000)); 851*4609Szf162725 } 852*4609Szf162725 853*4609Szf162725 static void 854*4609Szf162725 rt2560_statedog(void *arg) 855*4609Szf162725 { 856*4609Szf162725 struct rt2560_softc *sc = arg; 857*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 858*4609Szf162725 enum ieee80211_state state; 859*4609Szf162725 860*4609Szf162725 RAL_LOCK(sc); 861*4609Szf162725 862*4609Szf162725 RAL_DEBUG(RAL_DBG_MSG, "rt2560_statedog(...)\n"); 863*4609Szf162725 864*4609Szf162725 sc->sc_state_id = 0; 865*4609Szf162725 state = ic->ic_state; 866*4609Szf162725 ic->ic_state = sc->sc_ostate; 867*4609Szf162725 868*4609Szf162725 RAL_UNLOCK(sc); 869*4609Szf162725 870*4609Szf162725 ieee80211_new_state(ic, state, -1); 871*4609Szf162725 872*4609Szf162725 } 873*4609Szf162725 874*4609Szf162725 static int 875*4609Szf162725 rt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 876*4609Szf162725 { 877*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)ic; 878*4609Szf162725 enum ieee80211_state ostate; 879*4609Szf162725 struct ieee80211_node *ni; 880*4609Szf162725 int err; 881*4609Szf162725 882*4609Szf162725 RAL_LOCK(sc); 883*4609Szf162725 884*4609Szf162725 ostate = ic->ic_state; 885*4609Szf162725 sc->sc_ostate = ostate; 886*4609Szf162725 887*4609Szf162725 if (sc->sc_scan_id != 0) { 888*4609Szf162725 (void) untimeout(sc->sc_scan_id); 889*4609Szf162725 sc->sc_scan_id = 0; 890*4609Szf162725 } 891*4609Szf162725 892*4609Szf162725 if (sc->sc_rssadapt_id != 0) { 893*4609Szf162725 (void) untimeout(sc->sc_rssadapt_id); 894*4609Szf162725 sc->sc_rssadapt_id = 0; 895*4609Szf162725 } 896*4609Szf162725 897*4609Szf162725 if (sc->sc_state_id != 0) { 898*4609Szf162725 (void) untimeout(sc->sc_state_id); 899*4609Szf162725 sc->sc_state_id = 0; 900*4609Szf162725 } 901*4609Szf162725 902*4609Szf162725 switch (nstate) { 903*4609Szf162725 case IEEE80211_S_INIT: 904*4609Szf162725 if (ostate == IEEE80211_S_RUN) { 905*4609Szf162725 /* abort TSF synchronization */ 906*4609Szf162725 RAL_WRITE(sc, RT2560_CSR14, 0); 907*4609Szf162725 /* turn association led off */ 908*4609Szf162725 rt2560_update_led(sc, 0, 0); 909*4609Szf162725 } 910*4609Szf162725 break; 911*4609Szf162725 912*4609Szf162725 case IEEE80211_S_SCAN: 913*4609Szf162725 rt2560_set_chan(sc, ic->ic_curchan); 914*4609Szf162725 sc->sc_scan_id = timeout(rt2560_next_scan, (void *)sc, 915*4609Szf162725 drv_usectohz(sc->dwelltime * 1000)); 916*4609Szf162725 break; 917*4609Szf162725 918*4609Szf162725 case IEEE80211_S_AUTH: 919*4609Szf162725 RAL_DEBUG(RAL_DBG_STATE, "-> IEEE80211_S_AUTH ...\n"); 920*4609Szf162725 rt2560_set_chan(sc, ic->ic_curchan); 921*4609Szf162725 break; 922*4609Szf162725 923*4609Szf162725 case IEEE80211_S_ASSOC: 924*4609Szf162725 RAL_DEBUG(RAL_DBG_STATE, "-> IEEE80211_S_ASSOC ...\n"); 925*4609Szf162725 rt2560_set_chan(sc, ic->ic_curchan); 926*4609Szf162725 927*4609Szf162725 drv_usecwait(10 * 1000); /* dlink */ 928*4609Szf162725 sc->sc_state_id = timeout(rt2560_statedog, (void *)sc, 929*4609Szf162725 drv_usectohz(300 * 1000)); /* ap7-3 */ 930*4609Szf162725 break; 931*4609Szf162725 932*4609Szf162725 case IEEE80211_S_RUN: 933*4609Szf162725 RAL_DEBUG(RAL_DBG_STATE, "-> IEEE80211_S_RUN ...\n"); 934*4609Szf162725 rt2560_set_chan(sc, ic->ic_curchan); 935*4609Szf162725 936*4609Szf162725 ni = ic->ic_bss; 937*4609Szf162725 938*4609Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 939*4609Szf162725 rt2560_update_plcp(sc); 940*4609Szf162725 rt2560_set_basicrates(sc); 941*4609Szf162725 rt2560_set_bssid(sc, ni->in_bssid); 942*4609Szf162725 } 943*4609Szf162725 944*4609Szf162725 /* turn assocation led on */ 945*4609Szf162725 rt2560_update_led(sc, 1, 0); 946*4609Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 947*4609Szf162725 sc->sc_rssadapt_id = timeout(rt2560_update_rssadapt, 948*4609Szf162725 (void *)sc, drv_usectohz(100 * 1000)); 949*4609Szf162725 rt2560_enable_tsf_sync(sc); 950*4609Szf162725 } 951*4609Szf162725 break; 952*4609Szf162725 } 953*4609Szf162725 954*4609Szf162725 RAL_UNLOCK(sc); 955*4609Szf162725 956*4609Szf162725 err = sc->sc_newstate(ic, nstate, arg); 957*4609Szf162725 /* 958*4609Szf162725 * Finally, start any timers. 959*4609Szf162725 */ 960*4609Szf162725 if (nstate == IEEE80211_S_RUN) 961*4609Szf162725 ieee80211_start_watchdog(ic, 1); 962*4609Szf162725 963*4609Szf162725 return (err); 964*4609Szf162725 } 965*4609Szf162725 966*4609Szf162725 /* 967*4609Szf162725 * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or 968*4609Szf162725 * 93C66). 969*4609Szf162725 */ 970*4609Szf162725 static uint16_t 971*4609Szf162725 rt2560_eeprom_read(struct rt2560_softc *sc, uint8_t addr) 972*4609Szf162725 { 973*4609Szf162725 uint32_t tmp; 974*4609Szf162725 uint16_t val; 975*4609Szf162725 int n; 976*4609Szf162725 977*4609Szf162725 /* clock C once before the first command */ 978*4609Szf162725 RT2560_EEPROM_CTL(sc, 0); 979*4609Szf162725 980*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 981*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 982*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 983*4609Szf162725 984*4609Szf162725 /* write start bit (1) */ 985*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D); 986*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C); 987*4609Szf162725 988*4609Szf162725 /* write READ opcode (10) */ 989*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D); 990*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C); 991*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 992*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 993*4609Szf162725 994*4609Szf162725 /* write address (A5-A0 or A7-A0) */ 995*4609Szf162725 n = (RAL_READ(sc, RT2560_CSR21) & RT2560_93C46) ? 5 : 7; 996*4609Szf162725 for (; n >= 0; n--) { 997*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | 998*4609Szf162725 (((addr >> n) & 1) << RT2560_SHIFT_D)); 999*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | 1000*4609Szf162725 (((addr >> n) & 1) << RT2560_SHIFT_D) | RT2560_C); 1001*4609Szf162725 } 1002*4609Szf162725 1003*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 1004*4609Szf162725 1005*4609Szf162725 /* read data Q15-Q0 */ 1006*4609Szf162725 val = 0; 1007*4609Szf162725 for (n = 15; n >= 0; n--) { 1008*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 1009*4609Szf162725 tmp = RAL_READ(sc, RT2560_CSR21); 1010*4609Szf162725 val |= ((tmp & RT2560_Q) >> RT2560_SHIFT_Q) << n; 1011*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 1012*4609Szf162725 } 1013*4609Szf162725 1014*4609Szf162725 RT2560_EEPROM_CTL(sc, 0); 1015*4609Szf162725 1016*4609Szf162725 /* clear Chip Select and clock C */ 1017*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_S); 1018*4609Szf162725 RT2560_EEPROM_CTL(sc, 0); 1019*4609Szf162725 RT2560_EEPROM_CTL(sc, RT2560_C); 1020*4609Szf162725 1021*4609Szf162725 return (val); 1022*4609Szf162725 } 1023*4609Szf162725 1024*4609Szf162725 static void 1025*4609Szf162725 rt2560_tx_intr(struct rt2560_softc *sc) 1026*4609Szf162725 { 1027*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1028*4609Szf162725 struct rt2560_tx_desc *desc; 1029*4609Szf162725 struct rt2560_tx_data *data; 1030*4609Szf162725 struct rt2560_node *rn; 1031*4609Szf162725 1032*4609Szf162725 struct dma_region *dr; 1033*4609Szf162725 int count; 1034*4609Szf162725 1035*4609Szf162725 dr = &sc->txq.dr_desc; 1036*4609Szf162725 count = sc->txq.count; 1037*4609Szf162725 1038*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_TX_DESC_SIZE, 1039*4609Szf162725 DDI_DMA_SYNC_FORKERNEL); 1040*4609Szf162725 1041*4609Szf162725 mutex_enter(&sc->txq.tx_lock); 1042*4609Szf162725 1043*4609Szf162725 for (;;) { 1044*4609Szf162725 desc = &sc->txq.desc[sc->txq.next]; 1045*4609Szf162725 data = &sc->txq.data[sc->txq.next]; 1046*4609Szf162725 1047*4609Szf162725 if ((LE_32(desc->flags) & RT2560_TX_BUSY) || 1048*4609Szf162725 (LE_32(desc->flags) & RT2560_TX_CIPHER_BUSY) || 1049*4609Szf162725 !(LE_32(desc->flags) & RT2560_TX_VALID)) 1050*4609Szf162725 break; 1051*4609Szf162725 1052*4609Szf162725 rn = (struct rt2560_node *)data->ni; 1053*4609Szf162725 1054*4609Szf162725 switch (LE_32(desc->flags) & RT2560_TX_RESULT_MASK) { 1055*4609Szf162725 case RT2560_TX_SUCCESS: 1056*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "data frame sent success\n"); 1057*4609Szf162725 if (data->id.id_node != NULL) { 1058*4609Szf162725 ral_rssadapt_raise_rate(ic, &rn->rssadapt, 1059*4609Szf162725 &data->id); 1060*4609Szf162725 } 1061*4609Szf162725 break; 1062*4609Szf162725 1063*4609Szf162725 case RT2560_TX_SUCCESS_RETRY: 1064*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, 1065*4609Szf162725 "data frame sent after %u retries\n", 1066*4609Szf162725 (LE_32(desc->flags) >> 5) & 0x7); 1067*4609Szf162725 sc->sc_tx_retries++; 1068*4609Szf162725 break; 1069*4609Szf162725 1070*4609Szf162725 case RT2560_TX_FAIL_RETRY: 1071*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, 1072*4609Szf162725 "sending data frame failed (too much retries)\n"); 1073*4609Szf162725 if (data->id.id_node != NULL) { 1074*4609Szf162725 ral_rssadapt_lower_rate(ic, data->ni, 1075*4609Szf162725 &rn->rssadapt, &data->id); 1076*4609Szf162725 } 1077*4609Szf162725 break; 1078*4609Szf162725 1079*4609Szf162725 case RT2560_TX_FAIL_INVALID: 1080*4609Szf162725 case RT2560_TX_FAIL_OTHER: 1081*4609Szf162725 default: 1082*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "sending data frame failed " 1083*4609Szf162725 "0x%08x\n", LE_32(desc->flags)); 1084*4609Szf162725 break; 1085*4609Szf162725 } 1086*4609Szf162725 1087*4609Szf162725 ieee80211_free_node(data->ni); 1088*4609Szf162725 data->ni = NULL; 1089*4609Szf162725 1090*4609Szf162725 /* descriptor is no longer valid */ 1091*4609Szf162725 desc->flags &= ~LE_32(RT2560_TX_VALID); 1092*4609Szf162725 1093*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "tx done idx=%u\n", sc->txq.next); 1094*4609Szf162725 1095*4609Szf162725 sc->txq.queued--; 1096*4609Szf162725 sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT; 1097*4609Szf162725 1098*4609Szf162725 if (sc->sc_need_sched && 1099*4609Szf162725 sc->txq.queued < (RT2560_TX_RING_COUNT - 32)) { 1100*4609Szf162725 sc->sc_need_sched = 0; 1101*4609Szf162725 mac_tx_update(ic->ic_mach); 1102*4609Szf162725 } 1103*4609Szf162725 } 1104*4609Szf162725 1105*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_TX_DESC_SIZE, 1106*4609Szf162725 DDI_DMA_SYNC_FORDEV); 1107*4609Szf162725 1108*4609Szf162725 sc->sc_tx_timer = 0; 1109*4609Szf162725 mutex_exit(&sc->txq.tx_lock); 1110*4609Szf162725 } 1111*4609Szf162725 1112*4609Szf162725 static void 1113*4609Szf162725 rt2560_prio_intr(struct rt2560_softc *sc) 1114*4609Szf162725 { 1115*4609Szf162725 struct rt2560_tx_desc *desc; 1116*4609Szf162725 struct rt2560_tx_data *data; 1117*4609Szf162725 1118*4609Szf162725 struct dma_region *dr; 1119*4609Szf162725 int count; 1120*4609Szf162725 1121*4609Szf162725 dr = &sc->prioq.dr_desc; 1122*4609Szf162725 count = sc->prioq.count; 1123*4609Szf162725 1124*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_TX_DESC_SIZE, 1125*4609Szf162725 DDI_DMA_SYNC_FORKERNEL); 1126*4609Szf162725 1127*4609Szf162725 mutex_enter(&sc->prioq.tx_lock); 1128*4609Szf162725 1129*4609Szf162725 for (;;) { 1130*4609Szf162725 desc = &sc->prioq.desc[sc->prioq.next]; 1131*4609Szf162725 data = &sc->prioq.data[sc->prioq.next]; 1132*4609Szf162725 1133*4609Szf162725 if ((LE_32(desc->flags) & RT2560_TX_BUSY) || 1134*4609Szf162725 !(LE_32(desc->flags) & RT2560_TX_VALID)) 1135*4609Szf162725 break; 1136*4609Szf162725 1137*4609Szf162725 switch (LE_32(desc->flags) & RT2560_TX_RESULT_MASK) { 1138*4609Szf162725 case RT2560_TX_SUCCESS: 1139*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "mgt frame sent success\n"); 1140*4609Szf162725 break; 1141*4609Szf162725 1142*4609Szf162725 case RT2560_TX_SUCCESS_RETRY: 1143*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, 1144*4609Szf162725 "mgt frame sent after %u retries\n", 1145*4609Szf162725 (LE_32(desc->flags) >> 5) & 0x7); 1146*4609Szf162725 break; 1147*4609Szf162725 1148*4609Szf162725 case RT2560_TX_FAIL_RETRY: 1149*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, 1150*4609Szf162725 "sending mgt frame failed (too much " "retries)\n"); 1151*4609Szf162725 break; 1152*4609Szf162725 1153*4609Szf162725 case RT2560_TX_FAIL_INVALID: 1154*4609Szf162725 case RT2560_TX_FAIL_OTHER: 1155*4609Szf162725 default: 1156*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "sending mgt frame failed " 1157*4609Szf162725 "0x%08x\n", LE_32(desc->flags)); 1158*4609Szf162725 } 1159*4609Szf162725 1160*4609Szf162725 ieee80211_free_node(data->ni); 1161*4609Szf162725 data->ni = NULL; 1162*4609Szf162725 1163*4609Szf162725 /* descriptor is no longer valid */ 1164*4609Szf162725 desc->flags &= ~LE_32(RT2560_TX_VALID); 1165*4609Szf162725 1166*4609Szf162725 RAL_DEBUG(RAL_DBG_INTR, "prio done idx=%u\n", sc->prioq.next); 1167*4609Szf162725 1168*4609Szf162725 sc->prioq.queued--; 1169*4609Szf162725 sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT; 1170*4609Szf162725 } 1171*4609Szf162725 1172*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_TX_DESC_SIZE, 1173*4609Szf162725 DDI_DMA_SYNC_FORDEV); 1174*4609Szf162725 1175*4609Szf162725 sc->sc_tx_timer = 0; 1176*4609Szf162725 mutex_exit(&sc->prioq.tx_lock); 1177*4609Szf162725 } 1178*4609Szf162725 1179*4609Szf162725 /* 1180*4609Szf162725 * Some frames were received. Pass them to the hardware cipher engine before 1181*4609Szf162725 * sending them to the 802.11 layer. 1182*4609Szf162725 */ 1183*4609Szf162725 void 1184*4609Szf162725 rt2560_rx_intr(struct rt2560_softc *sc) 1185*4609Szf162725 { 1186*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1187*4609Szf162725 struct rt2560_rx_desc *desc; 1188*4609Szf162725 struct rt2560_rx_data *data; 1189*4609Szf162725 struct ieee80211_frame *wh; 1190*4609Szf162725 struct ieee80211_node *ni; 1191*4609Szf162725 struct rt2560_node *rn; 1192*4609Szf162725 1193*4609Szf162725 mblk_t *m; 1194*4609Szf162725 uint32_t len; 1195*4609Szf162725 char *rxbuf; 1196*4609Szf162725 1197*4609Szf162725 struct dma_region *dr, *dr_bf; 1198*4609Szf162725 int count; 1199*4609Szf162725 1200*4609Szf162725 dr = &sc->rxq.dr_desc; 1201*4609Szf162725 count = sc->rxq.count; 1202*4609Szf162725 1203*4609Szf162725 mutex_enter(&sc->rxq.rx_lock); 1204*4609Szf162725 1205*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_RX_DESC_SIZE, 1206*4609Szf162725 DDI_DMA_SYNC_FORKERNEL); 1207*4609Szf162725 1208*4609Szf162725 for (;;) { 1209*4609Szf162725 desc = &sc->rxq.desc[sc->rxq.cur]; 1210*4609Szf162725 data = &sc->rxq.data[sc->rxq.cur]; 1211*4609Szf162725 1212*4609Szf162725 if ((LE_32(desc->flags) & RT2560_RX_BUSY) || 1213*4609Szf162725 (LE_32(desc->flags) & RT2560_RX_CIPHER_BUSY)) 1214*4609Szf162725 break; 1215*4609Szf162725 1216*4609Szf162725 data->drop = 0; 1217*4609Szf162725 1218*4609Szf162725 if ((LE_32(desc->flags) & RT2560_RX_PHY_ERROR) || 1219*4609Szf162725 (LE_32(desc->flags) & RT2560_RX_CRC_ERROR)) { 1220*4609Szf162725 /* 1221*4609Szf162725 * This should not happen since we did not request 1222*4609Szf162725 * to receive those frames when we filled RXCSR0. 1223*4609Szf162725 */ 1224*4609Szf162725 RAL_DEBUG(RAL_DBG_RX, "PHY or CRC error flags 0x%08x\n", 1225*4609Szf162725 LE_32(desc->flags)); 1226*4609Szf162725 data->drop = 1; 1227*4609Szf162725 } 1228*4609Szf162725 1229*4609Szf162725 if (((LE_32(desc->flags) >> 16) & 0xfff) > RAL_RXBUF_SIZE) { 1230*4609Szf162725 RAL_DEBUG(RAL_DBG_RX, "bad length\n"); 1231*4609Szf162725 data->drop = 1; 1232*4609Szf162725 } 1233*4609Szf162725 1234*4609Szf162725 if (data->drop) { 1235*4609Szf162725 sc->sc_rx_err++; 1236*4609Szf162725 goto skip; 1237*4609Szf162725 } 1238*4609Szf162725 1239*4609Szf162725 rxbuf = data->buf; 1240*4609Szf162725 len = (LE_32(desc->flags) >> 16) & 0xfff; 1241*4609Szf162725 1242*4609Szf162725 if ((len < sizeof (struct ieee80211_frame_min)) || 1243*4609Szf162725 (len > RAL_RXBUF_SIZE)) { 1244*4609Szf162725 RAL_DEBUG(RAL_DBG_RX, "bad frame length=%u\n", len); 1245*4609Szf162725 sc->sc_rx_err++; 1246*4609Szf162725 goto skip; 1247*4609Szf162725 } 1248*4609Szf162725 1249*4609Szf162725 if ((m = allocb(len, BPRI_MED)) == NULL) { 1250*4609Szf162725 RAL_DEBUG(RAL_DBG_RX, "rt2560_rx_intr():" 1251*4609Szf162725 " allocate mblk failed.\n"); 1252*4609Szf162725 sc->sc_rx_nobuf++; 1253*4609Szf162725 goto skip; 1254*4609Szf162725 } 1255*4609Szf162725 1256*4609Szf162725 dr_bf = &sc->rxq.dr_rxbuf[sc->rxq.cur]; 1257*4609Szf162725 (void) ddi_dma_sync(dr_bf->dr_hnd, 0, dr_bf->dr_size, 1258*4609Szf162725 DDI_DMA_SYNC_FORCPU); 1259*4609Szf162725 1260*4609Szf162725 bcopy(rxbuf, m->b_rptr, len); 1261*4609Szf162725 m->b_wptr += len; 1262*4609Szf162725 1263*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1264*4609Szf162725 ni = ieee80211_find_rxnode(ic, wh); 1265*4609Szf162725 1266*4609Szf162725 /* give rssi to the rate adatation algorithm */ 1267*4609Szf162725 rn = (struct rt2560_node *)ni; 1268*4609Szf162725 ral_rssadapt_input(ic, ni, &rn->rssadapt, desc->rssi); 1269*4609Szf162725 1270*4609Szf162725 /* send the frame to the 802.11 layer */ 1271*4609Szf162725 (void) ieee80211_input(ic, m, ni, desc->rssi, 0); 1272*4609Szf162725 1273*4609Szf162725 /* node is no longer needed */ 1274*4609Szf162725 ieee80211_free_node(ni); 1275*4609Szf162725 1276*4609Szf162725 skip: desc->flags = LE_32(RT2560_RX_BUSY); 1277*4609Szf162725 RAL_DEBUG(RAL_DBG_RX, "rx done idx=%u\n", sc->rxq.cur); 1278*4609Szf162725 1279*4609Szf162725 sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT; 1280*4609Szf162725 } 1281*4609Szf162725 mutex_exit(&sc->rxq.rx_lock); 1282*4609Szf162725 1283*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, count * RT2560_TX_DESC_SIZE, 1284*4609Szf162725 DDI_DMA_SYNC_FORDEV); 1285*4609Szf162725 } 1286*4609Szf162725 1287*4609Szf162725 uint_t 1288*4609Szf162725 ral_softint_handler(caddr_t data) 1289*4609Szf162725 { 1290*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)data; 1291*4609Szf162725 1292*4609Szf162725 /* 1293*4609Szf162725 * Check if the soft interrupt is triggered by another 1294*4609Szf162725 * driver at the same level. 1295*4609Szf162725 */ 1296*4609Szf162725 RAL_LOCK(sc); 1297*4609Szf162725 if (sc->sc_rx_pend) { 1298*4609Szf162725 sc->sc_rx_pend = 0; 1299*4609Szf162725 RAL_UNLOCK(sc); 1300*4609Szf162725 rt2560_rx_intr((struct rt2560_softc *)data); 1301*4609Szf162725 return (DDI_INTR_CLAIMED); 1302*4609Szf162725 } 1303*4609Szf162725 RAL_UNLOCK(sc); 1304*4609Szf162725 return (DDI_INTR_UNCLAIMED); 1305*4609Szf162725 } 1306*4609Szf162725 1307*4609Szf162725 /* 1308*4609Szf162725 * Return the expected ack rate for a frame transmitted at rate `rate'. 1309*4609Szf162725 * XXX: this should depend on the destination node basic rate set. 1310*4609Szf162725 */ 1311*4609Szf162725 static int 1312*4609Szf162725 rt2560_ack_rate(struct ieee80211com *ic, int rate) 1313*4609Szf162725 { 1314*4609Szf162725 switch (rate) { 1315*4609Szf162725 /* CCK rates */ 1316*4609Szf162725 case 2: 1317*4609Szf162725 return (2); 1318*4609Szf162725 case 4: 1319*4609Szf162725 case 11: 1320*4609Szf162725 case 22: 1321*4609Szf162725 return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate); 1322*4609Szf162725 1323*4609Szf162725 /* OFDM rates */ 1324*4609Szf162725 case 12: 1325*4609Szf162725 case 18: 1326*4609Szf162725 return (12); 1327*4609Szf162725 case 24: 1328*4609Szf162725 case 36: 1329*4609Szf162725 return (24); 1330*4609Szf162725 case 48: 1331*4609Szf162725 case 72: 1332*4609Szf162725 case 96: 1333*4609Szf162725 case 108: 1334*4609Szf162725 return (48); 1335*4609Szf162725 } 1336*4609Szf162725 1337*4609Szf162725 /* default to 1Mbps */ 1338*4609Szf162725 return (2); 1339*4609Szf162725 } 1340*4609Szf162725 1341*4609Szf162725 /* 1342*4609Szf162725 * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. 1343*4609Szf162725 * The function automatically determines the operating mode depending on the 1344*4609Szf162725 * given rate. `flags' indicates whether short preamble is in use or not. 1345*4609Szf162725 */ 1346*4609Szf162725 static uint16_t 1347*4609Szf162725 rt2560_txtime(int len, int rate, uint32_t flags) 1348*4609Szf162725 { 1349*4609Szf162725 uint16_t txtime; 1350*4609Szf162725 1351*4609Szf162725 if (RAL_RATE_IS_OFDM(rate)) { 1352*4609Szf162725 /* IEEE Std 802.11a-1999, pp. 37 */ 1353*4609Szf162725 txtime = (8 + 4 * len + 3 + rate - 1) / rate; 1354*4609Szf162725 txtime = 16 + 4 + 4 * txtime + 6; 1355*4609Szf162725 } else { 1356*4609Szf162725 /* IEEE Std 802.11b-1999, pp. 28 */ 1357*4609Szf162725 txtime = (16 * len + rate - 1) / rate; 1358*4609Szf162725 if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) 1359*4609Szf162725 txtime += 72 + 24; 1360*4609Szf162725 else 1361*4609Szf162725 txtime += 144 + 48; 1362*4609Szf162725 } 1363*4609Szf162725 1364*4609Szf162725 return (txtime); 1365*4609Szf162725 } 1366*4609Szf162725 1367*4609Szf162725 static uint8_t 1368*4609Szf162725 rt2560_plcp_signal(int rate) 1369*4609Szf162725 { 1370*4609Szf162725 switch (rate) { 1371*4609Szf162725 /* CCK rates (returned values are device-dependent) */ 1372*4609Szf162725 case 2: return (0x0); 1373*4609Szf162725 case 4: return (0x1); 1374*4609Szf162725 case 11: return (0x2); 1375*4609Szf162725 case 22: return (0x3); 1376*4609Szf162725 1377*4609Szf162725 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 1378*4609Szf162725 case 12: return (0xb); 1379*4609Szf162725 case 18: return (0xf); 1380*4609Szf162725 case 24: return (0xa); 1381*4609Szf162725 case 36: return (0xe); 1382*4609Szf162725 case 48: return (0x9); 1383*4609Szf162725 case 72: return (0xd); 1384*4609Szf162725 case 96: return (0x8); 1385*4609Szf162725 case 108: return (0xc); 1386*4609Szf162725 1387*4609Szf162725 /* unsupported rates (should not get there) */ 1388*4609Szf162725 default: return (0xff); 1389*4609Szf162725 } 1390*4609Szf162725 } 1391*4609Szf162725 1392*4609Szf162725 void 1393*4609Szf162725 rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc, 1394*4609Szf162725 uint32_t flags, int len, int rate, int encrypt) 1395*4609Szf162725 { 1396*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1397*4609Szf162725 uint16_t plcp_length; 1398*4609Szf162725 int remainder; 1399*4609Szf162725 1400*4609Szf162725 desc->flags = LE_32(flags); 1401*4609Szf162725 desc->flags |= LE_32(len << 16); 1402*4609Szf162725 desc->flags |= encrypt ? LE_32(RT2560_TX_CIPHER_BUSY) : 1403*4609Szf162725 LE_32(RT2560_TX_BUSY | RT2560_TX_VALID); 1404*4609Szf162725 1405*4609Szf162725 desc->wme = LE_16( 1406*4609Szf162725 RT2560_AIFSN(2) | 1407*4609Szf162725 RT2560_LOGCWMIN(3) | 1408*4609Szf162725 RT2560_LOGCWMAX(8)); 1409*4609Szf162725 1410*4609Szf162725 /* setup PLCP fields */ 1411*4609Szf162725 desc->plcp_signal = rt2560_plcp_signal(rate); 1412*4609Szf162725 desc->plcp_service = 4; 1413*4609Szf162725 1414*4609Szf162725 len += IEEE80211_CRC_LEN; 1415*4609Szf162725 if (RAL_RATE_IS_OFDM(rate)) { 1416*4609Szf162725 desc->flags |= LE_32(RT2560_TX_OFDM); 1417*4609Szf162725 1418*4609Szf162725 plcp_length = len & 0xfff; 1419*4609Szf162725 desc->plcp_length_hi = plcp_length >> 6; 1420*4609Szf162725 desc->plcp_length_lo = plcp_length & 0x3f; 1421*4609Szf162725 } else { 1422*4609Szf162725 plcp_length = (16 * len + rate - 1) / rate; 1423*4609Szf162725 if (rate == 22) { 1424*4609Szf162725 remainder = (16 * len) % 22; 1425*4609Szf162725 if (remainder != 0 && remainder < 7) 1426*4609Szf162725 desc->plcp_service |= RT2560_PLCP_LENGEXT; 1427*4609Szf162725 } 1428*4609Szf162725 desc->plcp_length_hi = plcp_length >> 8; 1429*4609Szf162725 desc->plcp_length_lo = plcp_length & 0xff; 1430*4609Szf162725 1431*4609Szf162725 if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1432*4609Szf162725 desc->plcp_signal |= 0x08; 1433*4609Szf162725 } 1434*4609Szf162725 } 1435*4609Szf162725 1436*4609Szf162725 /* ARGSUSED */ 1437*4609Szf162725 int 1438*4609Szf162725 rt2560_mgmt_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 1439*4609Szf162725 { 1440*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)ic; 1441*4609Szf162725 struct rt2560_tx_desc *desc; 1442*4609Szf162725 struct rt2560_tx_data *data; 1443*4609Szf162725 struct ieee80211_frame *wh; 1444*4609Szf162725 uint16_t dur; 1445*4609Szf162725 uint32_t flags = 0; 1446*4609Szf162725 int rate, err = DDI_SUCCESS; 1447*4609Szf162725 1448*4609Szf162725 int off, pktlen, mblen; 1449*4609Szf162725 caddr_t dest; 1450*4609Szf162725 mblk_t *m, *m0; 1451*4609Szf162725 1452*4609Szf162725 struct dma_region *dr; 1453*4609Szf162725 uint32_t idx; 1454*4609Szf162725 struct ieee80211_node *ni; 1455*4609Szf162725 struct ieee80211_key *k; 1456*4609Szf162725 1457*4609Szf162725 mutex_enter(&sc->prioq.tx_lock); 1458*4609Szf162725 1459*4609Szf162725 if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { 1460*4609Szf162725 err = ENOMEM; 1461*4609Szf162725 sc->sc_tx_nobuf++; 1462*4609Szf162725 goto fail1; 1463*4609Szf162725 } 1464*4609Szf162725 1465*4609Szf162725 m = allocb(msgdsize(mp) + 32, BPRI_MED); 1466*4609Szf162725 if (m == NULL) { 1467*4609Szf162725 RAL_DEBUG(RAL_DBG_TX, "rt2560_mgmt_send: can't alloc mblk.\n"); 1468*4609Szf162725 err = DDI_FAILURE; 1469*4609Szf162725 goto fail1; 1470*4609Szf162725 } 1471*4609Szf162725 1472*4609Szf162725 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 1473*4609Szf162725 mblen = MBLKL(m0); 1474*4609Szf162725 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 1475*4609Szf162725 off += mblen; 1476*4609Szf162725 } 1477*4609Szf162725 m->b_wptr += off; 1478*4609Szf162725 1479*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1480*4609Szf162725 ni = ieee80211_find_txnode(ic, wh->i_addr1); 1481*4609Szf162725 1482*4609Szf162725 if (ni == NULL) { 1483*4609Szf162725 err = DDI_FAILURE; 1484*4609Szf162725 sc->sc_tx_err++; 1485*4609Szf162725 goto fail2; 1486*4609Szf162725 } 1487*4609Szf162725 1488*4609Szf162725 /* to support shared_key auth mode */ 1489*4609Szf162725 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1490*4609Szf162725 k = ieee80211_crypto_encap(ic, m); 1491*4609Szf162725 if (k == NULL) { 1492*4609Szf162725 err = DDI_FAILURE; 1493*4609Szf162725 sc->sc_tx_err++; 1494*4609Szf162725 goto fail3; 1495*4609Szf162725 } 1496*4609Szf162725 /* packet header may have moved, reset our local pointer */ 1497*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1498*4609Szf162725 } 1499*4609Szf162725 1500*4609Szf162725 desc = &sc->prioq.desc[sc->prioq.cur]; 1501*4609Szf162725 data = &sc->prioq.data[sc->prioq.cur]; 1502*4609Szf162725 1503*4609Szf162725 rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 1504*4609Szf162725 data->ni = ieee80211_ref_node(ni); 1505*4609Szf162725 1506*4609Szf162725 pktlen = msgdsize(m); 1507*4609Szf162725 dest = data->buf; 1508*4609Szf162725 bcopy(m->b_rptr, dest, pktlen); 1509*4609Szf162725 1510*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1511*4609Szf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1512*4609Szf162725 flags |= RT2560_TX_ACK; 1513*4609Szf162725 1514*4609Szf162725 dur = rt2560_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) + 1515*4609Szf162725 RAL_SIFS; 1516*4609Szf162725 *(uint16_t *)wh->i_dur = LE_16(dur); 1517*4609Szf162725 1518*4609Szf162725 /* tell hardware to add timestamp for probe responses */ 1519*4609Szf162725 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 1520*4609Szf162725 IEEE80211_FC0_TYPE_MGT && 1521*4609Szf162725 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 1522*4609Szf162725 IEEE80211_FC0_SUBTYPE_PROBE_RESP) 1523*4609Szf162725 flags |= RT2560_TX_TIMESTAMP; 1524*4609Szf162725 } 1525*4609Szf162725 1526*4609Szf162725 rt2560_setup_tx_desc(sc, desc, flags, pktlen, rate, 0); 1527*4609Szf162725 1528*4609Szf162725 idx = sc->prioq.cur; 1529*4609Szf162725 1530*4609Szf162725 dr = &sc->prioq.dr_txbuf[idx]; 1531*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, RAL_TXBUF_SIZE, DDI_DMA_SYNC_FORDEV); 1532*4609Szf162725 1533*4609Szf162725 dr = &sc->prioq.dr_desc; 1534*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, idx * RT2560_TX_DESC_SIZE, 1535*4609Szf162725 RT2560_TX_DESC_SIZE, DDI_DMA_SYNC_FORDEV); 1536*4609Szf162725 1537*4609Szf162725 RAL_DEBUG(RAL_DBG_MGMT, "sending mgt frame len=%u idx=%u rate=%u\n", 1538*4609Szf162725 pktlen, sc->prioq.cur, rate); 1539*4609Szf162725 1540*4609Szf162725 /* kick prio */ 1541*4609Szf162725 sc->prioq.queued++; /* IF > RT2560_PRIO_RING_COUNT? FULL */ 1542*4609Szf162725 sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT; 1543*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO); 1544*4609Szf162725 1545*4609Szf162725 sc->sc_tx_timer = 5; 1546*4609Szf162725 1547*4609Szf162725 fail3: 1548*4609Szf162725 ieee80211_free_node(ni); 1549*4609Szf162725 fail2: 1550*4609Szf162725 freemsg(m); 1551*4609Szf162725 fail1: 1552*4609Szf162725 freemsg(mp); 1553*4609Szf162725 mutex_exit(&sc->prioq.tx_lock); 1554*4609Szf162725 1555*4609Szf162725 return (err); 1556*4609Szf162725 } 1557*4609Szf162725 1558*4609Szf162725 static int 1559*4609Szf162725 rt2560_send(ieee80211com_t *ic, mblk_t *mp) 1560*4609Szf162725 { 1561*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)ic; 1562*4609Szf162725 struct rt2560_tx_desc *desc; 1563*4609Szf162725 struct rt2560_tx_data *data; 1564*4609Szf162725 struct rt2560_node *rn; 1565*4609Szf162725 struct ieee80211_rateset *rs; 1566*4609Szf162725 struct ieee80211_frame *wh; 1567*4609Szf162725 struct ieee80211_key *k; 1568*4609Szf162725 uint16_t dur; 1569*4609Szf162725 uint32_t flags = 0; 1570*4609Szf162725 int rate, err = DDI_SUCCESS; 1571*4609Szf162725 1572*4609Szf162725 struct ieee80211_node *ni; 1573*4609Szf162725 mblk_t *m, *m0; 1574*4609Szf162725 int off, mblen, pktlen; 1575*4609Szf162725 caddr_t dest; 1576*4609Szf162725 1577*4609Szf162725 struct dma_region *dr; 1578*4609Szf162725 uint32_t idx; 1579*4609Szf162725 1580*4609Szf162725 mutex_enter(&sc->txq.tx_lock); 1581*4609Szf162725 1582*4609Szf162725 if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { 1583*4609Szf162725 RAL_DEBUG(RAL_DBG_TX, "ral: rt2560_tx_data(): " 1584*4609Szf162725 "no TX DMA buffer available!\n"); 1585*4609Szf162725 sc->sc_need_sched = 1; 1586*4609Szf162725 sc->sc_tx_nobuf++; 1587*4609Szf162725 err = ENOMEM; 1588*4609Szf162725 goto fail1; 1589*4609Szf162725 } 1590*4609Szf162725 1591*4609Szf162725 m = allocb(msgdsize(mp) + 32, BPRI_MED); 1592*4609Szf162725 if (m == NULL) { 1593*4609Szf162725 RAL_DEBUG(RAL_DBG_TX, "rt2560_xmit(): can't alloc mblk.\n"); 1594*4609Szf162725 err = DDI_FAILURE; 1595*4609Szf162725 goto fail1; 1596*4609Szf162725 } 1597*4609Szf162725 1598*4609Szf162725 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 1599*4609Szf162725 mblen = MBLKL(m0); 1600*4609Szf162725 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 1601*4609Szf162725 off += mblen; 1602*4609Szf162725 } 1603*4609Szf162725 m->b_wptr += off; 1604*4609Szf162725 1605*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1606*4609Szf162725 ni = ieee80211_find_txnode(ic, wh->i_addr1); 1607*4609Szf162725 1608*4609Szf162725 if (ni == NULL) { 1609*4609Szf162725 err = DDI_FAILURE; 1610*4609Szf162725 sc->sc_tx_err++; 1611*4609Szf162725 goto fail2; 1612*4609Szf162725 } 1613*4609Szf162725 1614*4609Szf162725 (void) ieee80211_encap(ic, m, ni); 1615*4609Szf162725 1616*4609Szf162725 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1617*4609Szf162725 k = ieee80211_crypto_encap(ic, m); 1618*4609Szf162725 if (k == NULL) { 1619*4609Szf162725 sc->sc_tx_err++; 1620*4609Szf162725 err = DDI_FAILURE; 1621*4609Szf162725 goto fail3; 1622*4609Szf162725 } 1623*4609Szf162725 /* packet header may have moved, reset our local pointer */ 1624*4609Szf162725 wh = (struct ieee80211_frame *)m->b_rptr; 1625*4609Szf162725 } 1626*4609Szf162725 1627*4609Szf162725 /* 1628*4609Szf162725 * RTS/CTS exchange ignore, since the max packet will less than 1629*4609Szf162725 * the rtsthreshold (2346) 1630*4609Szf162725 * Unnecessary codes deleted. 1631*4609Szf162725 */ 1632*4609Szf162725 1633*4609Szf162725 data = &sc->txq.data[sc->txq.cur]; 1634*4609Szf162725 desc = &sc->txq.desc[sc->txq.cur]; 1635*4609Szf162725 1636*4609Szf162725 data->ni = ieee80211_ref_node(ni); 1637*4609Szf162725 1638*4609Szf162725 pktlen = msgdsize(m); 1639*4609Szf162725 dest = data->buf; 1640*4609Szf162725 bcopy(m->b_rptr, dest, pktlen); 1641*4609Szf162725 1642*4609Szf162725 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 1643*4609Szf162725 rs = &ic->ic_sup_rates[ic->ic_curmode]; 1644*4609Szf162725 rate = rs->ir_rates[ic->ic_fixed_rate]; 1645*4609Szf162725 } else { 1646*4609Szf162725 rs = &ni->in_rates; 1647*4609Szf162725 rn = (struct rt2560_node *)ni; 1648*4609Szf162725 ni->in_txrate = ral_rssadapt_choose(&rn->rssadapt, rs, wh, 1649*4609Szf162725 pktlen, NULL, 0); 1650*4609Szf162725 rate = rs->ir_rates[ni->in_txrate]; 1651*4609Szf162725 } 1652*4609Szf162725 1653*4609Szf162725 rate &= IEEE80211_RATE_VAL; 1654*4609Szf162725 if (rate <= 0) { 1655*4609Szf162725 rate = 2; /* basic rate */ 1656*4609Szf162725 } 1657*4609Szf162725 1658*4609Szf162725 /* remember link conditions for rate adaptation algorithm */ 1659*4609Szf162725 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 1660*4609Szf162725 data->id.id_len = pktlen; 1661*4609Szf162725 data->id.id_rateidx = ni->in_txrate; 1662*4609Szf162725 data->id.id_node = ni; 1663*4609Szf162725 data->id.id_rssi = ni->in_rssi; 1664*4609Szf162725 } else 1665*4609Szf162725 data->id.id_node = NULL; 1666*4609Szf162725 1667*4609Szf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1668*4609Szf162725 flags |= RT2560_TX_ACK; 1669*4609Szf162725 1670*4609Szf162725 dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate), 1671*4609Szf162725 ic->ic_flags) + RAL_SIFS; 1672*4609Szf162725 *(uint16_t *)wh->i_dur = LE_16(dur); 1673*4609Szf162725 } 1674*4609Szf162725 1675*4609Szf162725 /* flags |= RT2560_TX_CIPHER_NONE; */ 1676*4609Szf162725 rt2560_setup_tx_desc(sc, desc, flags, pktlen, rate, 0); 1677*4609Szf162725 1678*4609Szf162725 idx = sc->txq.cur; 1679*4609Szf162725 1680*4609Szf162725 dr = &sc->txq.dr_txbuf[idx]; 1681*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, 0, RAL_TXBUF_SIZE, DDI_DMA_SYNC_FORDEV); 1682*4609Szf162725 1683*4609Szf162725 dr = &sc->txq.dr_desc; 1684*4609Szf162725 (void) ddi_dma_sync(dr->dr_hnd, idx * RT2560_TX_DESC_SIZE, 1685*4609Szf162725 RT2560_TX_DESC_SIZE, DDI_DMA_SYNC_FORDEV); 1686*4609Szf162725 1687*4609Szf162725 RAL_DEBUG(RAL_DBG_TX, "sending data frame len=%u idx=%u rate=%u\n", 1688*4609Szf162725 pktlen, sc->txq.cur, rate); 1689*4609Szf162725 1690*4609Szf162725 /* kick tx */ 1691*4609Szf162725 sc->txq.queued++; 1692*4609Szf162725 sc->txq.cur = (sc->txq.cur + 1) % RT2560_TX_RING_COUNT; 1693*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_TX); 1694*4609Szf162725 1695*4609Szf162725 sc->sc_tx_timer = 5; 1696*4609Szf162725 1697*4609Szf162725 freemsg(mp); 1698*4609Szf162725 fail3: 1699*4609Szf162725 ieee80211_free_node(ni); 1700*4609Szf162725 fail2: 1701*4609Szf162725 freemsg(m); 1702*4609Szf162725 fail1: 1703*4609Szf162725 mutex_exit(&sc->txq.tx_lock); 1704*4609Szf162725 return (err); 1705*4609Szf162725 } 1706*4609Szf162725 1707*4609Szf162725 static mblk_t * 1708*4609Szf162725 rt2560_m_tx(void *arg, mblk_t *mp) 1709*4609Szf162725 { 1710*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 1711*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1712*4609Szf162725 mblk_t *next; 1713*4609Szf162725 1714*4609Szf162725 /* 1715*4609Szf162725 * No data frames go out unless we're associated; this 1716*4609Szf162725 * should not happen as the 802.11 layer does not enable 1717*4609Szf162725 * the xmit queue until we enter the RUN state. 1718*4609Szf162725 */ 1719*4609Szf162725 if (ic->ic_state != IEEE80211_S_RUN) { 1720*4609Szf162725 RAL_DEBUG(RAL_DBG_TX, "ral: rt2560_tx_data(): " 1721*4609Szf162725 "discard, state %u\n", ic->ic_state); 1722*4609Szf162725 freemsgchain(mp); 1723*4609Szf162725 return (NULL); 1724*4609Szf162725 } 1725*4609Szf162725 1726*4609Szf162725 while (mp != NULL) { 1727*4609Szf162725 next = mp->b_next; 1728*4609Szf162725 mp->b_next = NULL; 1729*4609Szf162725 if (rt2560_send(ic, mp) != DDI_SUCCESS) { 1730*4609Szf162725 mp->b_next = next; 1731*4609Szf162725 freemsgchain(mp); 1732*4609Szf162725 return (NULL); 1733*4609Szf162725 } 1734*4609Szf162725 mp = next; 1735*4609Szf162725 } 1736*4609Szf162725 return (mp); 1737*4609Szf162725 } 1738*4609Szf162725 1739*4609Szf162725 static void 1740*4609Szf162725 rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr) 1741*4609Szf162725 { 1742*4609Szf162725 uint32_t tmp; 1743*4609Szf162725 1744*4609Szf162725 tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24; 1745*4609Szf162725 RAL_WRITE(sc, RT2560_CSR3, tmp); 1746*4609Szf162725 1747*4609Szf162725 tmp = addr[4] | addr[5] << 8; 1748*4609Szf162725 RAL_WRITE(sc, RT2560_CSR4, tmp); 1749*4609Szf162725 1750*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, 1751*4609Szf162725 "setting MAC address to " MACSTR "\n", MAC2STR(addr)); 1752*4609Szf162725 } 1753*4609Szf162725 1754*4609Szf162725 static void 1755*4609Szf162725 rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr) 1756*4609Szf162725 { 1757*4609Szf162725 uint32_t tmp; 1758*4609Szf162725 1759*4609Szf162725 tmp = RAL_READ(sc, RT2560_CSR3); 1760*4609Szf162725 addr[0] = tmp & 0xff; 1761*4609Szf162725 addr[1] = (tmp >> 8) & 0xff; 1762*4609Szf162725 addr[2] = (tmp >> 16) & 0xff; 1763*4609Szf162725 addr[3] = (tmp >> 24); 1764*4609Szf162725 1765*4609Szf162725 tmp = RAL_READ(sc, RT2560_CSR4); 1766*4609Szf162725 addr[4] = tmp & 0xff; 1767*4609Szf162725 addr[5] = (tmp >> 8) & 0xff; 1768*4609Szf162725 } 1769*4609Szf162725 1770*4609Szf162725 static void 1771*4609Szf162725 rt2560_update_promisc(struct rt2560_softc *sc) 1772*4609Szf162725 { 1773*4609Szf162725 uint32_t tmp; 1774*4609Szf162725 1775*4609Szf162725 tmp = RAL_READ(sc, RT2560_RXCSR0); 1776*4609Szf162725 tmp &= ~RT2560_DROP_NOT_TO_ME; 1777*4609Szf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC)) 1778*4609Szf162725 tmp |= RT2560_DROP_NOT_TO_ME; 1779*4609Szf162725 1780*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR0, tmp); 1781*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "%s promiscuous mode\n", 1782*4609Szf162725 (sc->sc_rcr & RAL_RCR_PROMISC) ? "entering" : "leaving"); 1783*4609Szf162725 } 1784*4609Szf162725 1785*4609Szf162725 static const char * 1786*4609Szf162725 rt2560_get_rf(int rev) 1787*4609Szf162725 { 1788*4609Szf162725 switch (rev) { 1789*4609Szf162725 case RT2560_RF_2522: return ("RT2522"); 1790*4609Szf162725 case RT2560_RF_2523: return ("RT2523"); 1791*4609Szf162725 case RT2560_RF_2524: return ("RT2524"); 1792*4609Szf162725 case RT2560_RF_2525: return ("RT2525"); 1793*4609Szf162725 case RT2560_RF_2525E: return ("RT2525e"); 1794*4609Szf162725 case RT2560_RF_2526: return ("RT2526"); 1795*4609Szf162725 case RT2560_RF_5222: return ("RT5222"); 1796*4609Szf162725 default: return ("unknown"); 1797*4609Szf162725 } 1798*4609Szf162725 } 1799*4609Szf162725 1800*4609Szf162725 static void 1801*4609Szf162725 rt2560_read_eeprom(struct rt2560_softc *sc) 1802*4609Szf162725 { 1803*4609Szf162725 uint16_t val; 1804*4609Szf162725 int i; 1805*4609Szf162725 1806*4609Szf162725 val = rt2560_eeprom_read(sc, RT2560_EEPROM_CONFIG0); 1807*4609Szf162725 sc->rf_rev = (val >> 11) & 0x7; 1808*4609Szf162725 sc->hw_radio = (val >> 10) & 0x1; 1809*4609Szf162725 sc->led_mode = (val >> 6) & 0x7; 1810*4609Szf162725 sc->rx_ant = (val >> 4) & 0x3; 1811*4609Szf162725 sc->tx_ant = (val >> 2) & 0x3; 1812*4609Szf162725 sc->nb_ant = val & 0x3; 1813*4609Szf162725 1814*4609Szf162725 /* read default values for BBP registers */ 1815*4609Szf162725 for (i = 0; i < 16; i++) { 1816*4609Szf162725 val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i); 1817*4609Szf162725 sc->bbp_prom[i].reg = val >> 8; 1818*4609Szf162725 sc->bbp_prom[i].val = val & 0xff; 1819*4609Szf162725 } 1820*4609Szf162725 1821*4609Szf162725 /* read Tx power for all b/g channels */ 1822*4609Szf162725 for (i = 0; i < 14 / 2; i++) { 1823*4609Szf162725 val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i); 1824*4609Szf162725 sc->txpow[i * 2] = val >> 8; 1825*4609Szf162725 sc->txpow[i * 2 + 1] = val & 0xff; 1826*4609Szf162725 } 1827*4609Szf162725 } 1828*4609Szf162725 1829*4609Szf162725 static int 1830*4609Szf162725 rt2560_bbp_init(struct rt2560_softc *sc) 1831*4609Szf162725 { 1832*4609Szf162725 #define N(a) (sizeof (a) / sizeof ((a)[0])) 1833*4609Szf162725 int i, ntries; 1834*4609Szf162725 1835*4609Szf162725 /* wait for BBP to be ready */ 1836*4609Szf162725 for (ntries = 0; ntries < 100; ntries++) { 1837*4609Szf162725 if (rt2560_bbp_read(sc, RT2560_BBP_VERSION) != 0) 1838*4609Szf162725 break; 1839*4609Szf162725 drv_usecwait(1); 1840*4609Szf162725 } 1841*4609Szf162725 if (ntries == 100) { 1842*4609Szf162725 RAL_DEBUG(RAL_DBG_HW, "timeout waiting for BBP\n"); 1843*4609Szf162725 return (EIO); 1844*4609Szf162725 } 1845*4609Szf162725 /* initialize BBP registers to default values */ 1846*4609Szf162725 for (i = 0; i < N(rt2560_def_bbp); i++) { 1847*4609Szf162725 rt2560_bbp_write(sc, rt2560_def_bbp[i].reg, 1848*4609Szf162725 rt2560_def_bbp[i].val); 1849*4609Szf162725 } 1850*4609Szf162725 1851*4609Szf162725 return (0); 1852*4609Szf162725 #undef N 1853*4609Szf162725 } 1854*4609Szf162725 1855*4609Szf162725 static void 1856*4609Szf162725 rt2560_set_txantenna(struct rt2560_softc *sc, int antenna) 1857*4609Szf162725 { 1858*4609Szf162725 uint32_t tmp; 1859*4609Szf162725 uint8_t tx; 1860*4609Szf162725 1861*4609Szf162725 tx = rt2560_bbp_read(sc, RT2560_BBP_TX) & ~RT2560_BBP_ANTMASK; 1862*4609Szf162725 if (antenna == 1) 1863*4609Szf162725 tx |= RT2560_BBP_ANTA; 1864*4609Szf162725 else if (antenna == 2) 1865*4609Szf162725 tx |= RT2560_BBP_ANTB; 1866*4609Szf162725 else 1867*4609Szf162725 tx |= RT2560_BBP_DIVERSITY; 1868*4609Szf162725 1869*4609Szf162725 /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ 1870*4609Szf162725 if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526 || 1871*4609Szf162725 sc->rf_rev == RT2560_RF_5222) 1872*4609Szf162725 tx |= RT2560_BBP_FLIPIQ; 1873*4609Szf162725 1874*4609Szf162725 rt2560_bbp_write(sc, RT2560_BBP_TX, tx); 1875*4609Szf162725 1876*4609Szf162725 /* update values for CCK and OFDM in BBPCSR1 */ 1877*4609Szf162725 tmp = RAL_READ(sc, RT2560_BBPCSR1) & ~0x00070007; 1878*4609Szf162725 tmp |= (tx & 0x7) << 16 | (tx & 0x7); 1879*4609Szf162725 RAL_WRITE(sc, RT2560_BBPCSR1, tmp); 1880*4609Szf162725 } 1881*4609Szf162725 1882*4609Szf162725 static void 1883*4609Szf162725 rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna) 1884*4609Szf162725 { 1885*4609Szf162725 uint8_t rx; 1886*4609Szf162725 1887*4609Szf162725 rx = rt2560_bbp_read(sc, RT2560_BBP_RX) & ~RT2560_BBP_ANTMASK; 1888*4609Szf162725 if (antenna == 1) 1889*4609Szf162725 rx |= RT2560_BBP_ANTA; 1890*4609Szf162725 else if (antenna == 2) 1891*4609Szf162725 rx |= RT2560_BBP_ANTB; 1892*4609Szf162725 else 1893*4609Szf162725 rx |= RT2560_BBP_DIVERSITY; 1894*4609Szf162725 1895*4609Szf162725 /* need to force no I/Q flip for RF 2525e and 2526 */ 1896*4609Szf162725 if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526) 1897*4609Szf162725 rx &= ~RT2560_BBP_FLIPIQ; 1898*4609Szf162725 1899*4609Szf162725 rt2560_bbp_write(sc, RT2560_BBP_RX, rx); 1900*4609Szf162725 } 1901*4609Szf162725 1902*4609Szf162725 static void 1903*4609Szf162725 rt2560_stop(struct rt2560_softc *sc) 1904*4609Szf162725 { 1905*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1906*4609Szf162725 1907*4609Szf162725 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1908*4609Szf162725 ieee80211_stop_watchdog(ic); /* stop the watchdog */ 1909*4609Szf162725 1910*4609Szf162725 RAL_LOCK(sc); 1911*4609Szf162725 sc->sc_tx_timer = 0; 1912*4609Szf162725 1913*4609Szf162725 /* abort Tx */ 1914*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); 1915*4609Szf162725 1916*4609Szf162725 /* disable Rx */ 1917*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX); 1918*4609Szf162725 1919*4609Szf162725 /* reset ASIC (imply reset BBP) */ 1920*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC); 1921*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, 0); 1922*4609Szf162725 1923*4609Szf162725 /* disable interrupts */ 1924*4609Szf162725 RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); 1925*4609Szf162725 1926*4609Szf162725 /* reset Tx and Rx rings */ 1927*4609Szf162725 rt2560_reset_tx_ring(sc, &sc->txq); 1928*4609Szf162725 rt2560_reset_tx_ring(sc, &sc->prioq); 1929*4609Szf162725 rt2560_reset_rx_ring(sc, &sc->rxq); 1930*4609Szf162725 RAL_UNLOCK(sc); 1931*4609Szf162725 } 1932*4609Szf162725 1933*4609Szf162725 static int 1934*4609Szf162725 rt2560_init(struct rt2560_softc *sc) 1935*4609Szf162725 { 1936*4609Szf162725 #define N(a) (sizeof (a) / sizeof ((a)[0])) 1937*4609Szf162725 /* struct rt2560_softc *sc = priv; */ 1938*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 1939*4609Szf162725 uint32_t tmp; 1940*4609Szf162725 int i; 1941*4609Szf162725 1942*4609Szf162725 rt2560_stop(sc); 1943*4609Szf162725 1944*4609Szf162725 RAL_LOCK(sc); 1945*4609Szf162725 /* setup tx/rx ring */ 1946*4609Szf162725 rt2560_ring_hwsetup(sc); 1947*4609Szf162725 1948*4609Szf162725 /* initialize MAC registers to default values */ 1949*4609Szf162725 for (i = 0; i < N(rt2560_def_mac); i++) 1950*4609Szf162725 RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val); 1951*4609Szf162725 1952*4609Szf162725 rt2560_set_macaddr(sc, ic->ic_macaddr); 1953*4609Szf162725 1954*4609Szf162725 /* set basic rate set (will be updated later) */ 1955*4609Szf162725 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153); 1956*4609Szf162725 1957*4609Szf162725 rt2560_set_txantenna(sc, sc->tx_ant); 1958*4609Szf162725 rt2560_set_rxantenna(sc, sc->rx_ant); 1959*4609Szf162725 rt2560_update_slot(ic, 1); 1960*4609Szf162725 rt2560_update_plcp(sc); 1961*4609Szf162725 rt2560_update_led(sc, 0, 0); 1962*4609Szf162725 1963*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC); 1964*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY); 1965*4609Szf162725 1966*4609Szf162725 if (rt2560_bbp_init(sc) != 0) { 1967*4609Szf162725 RAL_UNLOCK(sc); 1968*4609Szf162725 rt2560_stop(sc); 1969*4609Szf162725 return (DDI_FAILURE); 1970*4609Szf162725 } 1971*4609Szf162725 1972*4609Szf162725 /* set default BSS channel */ 1973*4609Szf162725 rt2560_set_chan(sc, ic->ic_curchan); 1974*4609Szf162725 1975*4609Szf162725 /* kick Rx */ 1976*4609Szf162725 tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR; 1977*4609Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1978*4609Szf162725 tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR; 1979*4609Szf162725 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1980*4609Szf162725 tmp |= RT2560_DROP_TODS; 1981*4609Szf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC)) 1982*4609Szf162725 tmp |= RT2560_DROP_NOT_TO_ME; 1983*4609Szf162725 1984*4609Szf162725 } 1985*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR0, tmp); 1986*4609Szf162725 1987*4609Szf162725 /* clear old FCS and Rx FIFO errors */ 1988*4609Szf162725 (void) RAL_READ(sc, RT2560_CNT0); 1989*4609Szf162725 (void) RAL_READ(sc, RT2560_CNT4); 1990*4609Szf162725 1991*4609Szf162725 /* clear any pending interrupts */ 1992*4609Szf162725 RAL_WRITE(sc, RT2560_CSR7, 0xffffffff); 1993*4609Szf162725 /* enable interrupts */ 1994*4609Szf162725 RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); 1995*4609Szf162725 1996*4609Szf162725 RAL_UNLOCK(sc); 1997*4609Szf162725 #undef N 1998*4609Szf162725 return (DDI_SUCCESS); 1999*4609Szf162725 } 2000*4609Szf162725 2001*4609Szf162725 void 2002*4609Szf162725 rt2560_watchdog(void *arg) 2003*4609Szf162725 { 2004*4609Szf162725 struct rt2560_softc *sc = arg; 2005*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 2006*4609Szf162725 int ntimer = 0; 2007*4609Szf162725 2008*4609Szf162725 RAL_LOCK(sc); 2009*4609Szf162725 ic->ic_watchdog_timer = 0; 2010*4609Szf162725 2011*4609Szf162725 if (!RAL_IS_RUNNING(sc)) { 2012*4609Szf162725 RAL_UNLOCK(sc); 2013*4609Szf162725 return; 2014*4609Szf162725 } 2015*4609Szf162725 2016*4609Szf162725 if (sc->sc_tx_timer > 0) { 2017*4609Szf162725 if (--sc->sc_tx_timer == 0) { 2018*4609Szf162725 RAL_DEBUG(RAL_DBG_MSG, "tx timer timeout\n"); 2019*4609Szf162725 RAL_UNLOCK(sc); 2020*4609Szf162725 (void) rt2560_init(sc); 2021*4609Szf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2022*4609Szf162725 return; 2023*4609Szf162725 } 2024*4609Szf162725 } 2025*4609Szf162725 2026*4609Szf162725 if (ic->ic_state == IEEE80211_S_RUN) 2027*4609Szf162725 ntimer = 1; 2028*4609Szf162725 2029*4609Szf162725 RAL_UNLOCK(sc); 2030*4609Szf162725 2031*4609Szf162725 ieee80211_watchdog(ic); 2032*4609Szf162725 2033*4609Szf162725 if (ntimer) 2034*4609Szf162725 ieee80211_start_watchdog(ic, ntimer); 2035*4609Szf162725 } 2036*4609Szf162725 2037*4609Szf162725 static int 2038*4609Szf162725 rt2560_m_start(void *arg) 2039*4609Szf162725 { 2040*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2041*4609Szf162725 crypto_mech_type_t type; 2042*4609Szf162725 int err; 2043*4609Szf162725 2044*4609Szf162725 2045*4609Szf162725 type = crypto_mech2id(SUN_CKM_RC4); /* load rc4 module into kernel */ 2046*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "enter rt2560_m_start(%d)\n", type); 2047*4609Szf162725 2048*4609Szf162725 /* 2049*4609Szf162725 * initialize rt2560 hardware 2050*4609Szf162725 */ 2051*4609Szf162725 err = rt2560_init(sc); 2052*4609Szf162725 if (err != DDI_SUCCESS) { 2053*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "device configuration failed\n"); 2054*4609Szf162725 goto fail; 2055*4609Szf162725 } 2056*4609Szf162725 sc->sc_flags |= RAL_FLAG_RUNNING; /* RUNNING */ 2057*4609Szf162725 return (err); 2058*4609Szf162725 2059*4609Szf162725 fail: 2060*4609Szf162725 rt2560_stop(sc); 2061*4609Szf162725 return (err); 2062*4609Szf162725 } 2063*4609Szf162725 2064*4609Szf162725 static void 2065*4609Szf162725 rt2560_m_stop(void *arg) 2066*4609Szf162725 { 2067*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2068*4609Szf162725 2069*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "enter rt2560_m_stop()\n"); 2070*4609Szf162725 2071*4609Szf162725 (void) rt2560_stop(sc); 2072*4609Szf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */ 2073*4609Szf162725 } 2074*4609Szf162725 2075*4609Szf162725 static int 2076*4609Szf162725 rt2560_m_unicst(void *arg, const uint8_t *macaddr) 2077*4609Szf162725 { 2078*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2079*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 2080*4609Szf162725 2081*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "rt2560_m_unicst(): " MACSTR "\n", 2082*4609Szf162725 MAC2STR(macaddr)); 2083*4609Szf162725 2084*4609Szf162725 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 2085*4609Szf162725 (void) rt2560_set_macaddr(sc, (uint8_t *)macaddr); 2086*4609Szf162725 (void) rt2560_init(sc); 2087*4609Szf162725 2088*4609Szf162725 return (0); 2089*4609Szf162725 } 2090*4609Szf162725 2091*4609Szf162725 /*ARGSUSED*/ 2092*4609Szf162725 static int 2093*4609Szf162725 rt2560_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 2094*4609Szf162725 { 2095*4609Szf162725 return (0); 2096*4609Szf162725 } 2097*4609Szf162725 2098*4609Szf162725 static int 2099*4609Szf162725 rt2560_m_promisc(void *arg, boolean_t on) 2100*4609Szf162725 { 2101*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2102*4609Szf162725 2103*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "rt2560_m_promisc()\n"); 2104*4609Szf162725 2105*4609Szf162725 if (on) { 2106*4609Szf162725 sc->sc_rcr |= RAL_RCR_PROMISC; 2107*4609Szf162725 sc->sc_rcr |= RAL_RCR_MULTI; 2108*4609Szf162725 } else { 2109*4609Szf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC; 2110*4609Szf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC; 2111*4609Szf162725 } 2112*4609Szf162725 2113*4609Szf162725 rt2560_update_promisc(sc); 2114*4609Szf162725 return (0); 2115*4609Szf162725 } 2116*4609Szf162725 2117*4609Szf162725 static void 2118*4609Szf162725 rt2560_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 2119*4609Szf162725 { 2120*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2121*4609Szf162725 struct ieee80211com *ic = &sc->sc_ic; 2122*4609Szf162725 int err; 2123*4609Szf162725 2124*4609Szf162725 err = ieee80211_ioctl(ic, wq, mp); 2125*4609Szf162725 RAL_LOCK(sc); 2126*4609Szf162725 if (err == ENETRESET) { 2127*4609Szf162725 if (RAL_IS_RUNNING(sc)) { 2128*4609Szf162725 RAL_UNLOCK(sc); 2129*4609Szf162725 (void) rt2560_init(sc); 2130*4609Szf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2131*4609Szf162725 RAL_LOCK(sc); 2132*4609Szf162725 } 2133*4609Szf162725 } 2134*4609Szf162725 RAL_UNLOCK(sc); 2135*4609Szf162725 } 2136*4609Szf162725 2137*4609Szf162725 static int 2138*4609Szf162725 rt2560_m_stat(void *arg, uint_t stat, uint64_t *val) 2139*4609Szf162725 { 2140*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2141*4609Szf162725 ieee80211com_t *ic = &sc->sc_ic; 2142*4609Szf162725 ieee80211_node_t *ni = ic->ic_bss; 2143*4609Szf162725 struct ieee80211_rateset *rs = &ni->in_rates; 2144*4609Szf162725 2145*4609Szf162725 RAL_LOCK(sc); 2146*4609Szf162725 switch (stat) { 2147*4609Szf162725 case MAC_STAT_IFSPEED: 2148*4609Szf162725 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 2149*4609Szf162725 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 2150*4609Szf162725 : ic->ic_fixed_rate) * 5000000ull; 2151*4609Szf162725 break; 2152*4609Szf162725 case MAC_STAT_NOXMTBUF: 2153*4609Szf162725 *val = sc->sc_tx_nobuf; 2154*4609Szf162725 break; 2155*4609Szf162725 case MAC_STAT_NORCVBUF: 2156*4609Szf162725 *val = sc->sc_rx_nobuf; 2157*4609Szf162725 break; 2158*4609Szf162725 case MAC_STAT_IERRORS: 2159*4609Szf162725 *val = sc->sc_rx_err; 2160*4609Szf162725 break; 2161*4609Szf162725 case MAC_STAT_RBYTES: 2162*4609Szf162725 *val = ic->ic_stats.is_rx_bytes; 2163*4609Szf162725 break; 2164*4609Szf162725 case MAC_STAT_IPACKETS: 2165*4609Szf162725 *val = ic->ic_stats.is_rx_frags; 2166*4609Szf162725 break; 2167*4609Szf162725 case MAC_STAT_OBYTES: 2168*4609Szf162725 *val = ic->ic_stats.is_tx_bytes; 2169*4609Szf162725 break; 2170*4609Szf162725 case MAC_STAT_OPACKETS: 2171*4609Szf162725 *val = ic->ic_stats.is_tx_frags; 2172*4609Szf162725 break; 2173*4609Szf162725 case MAC_STAT_OERRORS: 2174*4609Szf162725 case WIFI_STAT_TX_FAILED: 2175*4609Szf162725 *val = sc->sc_tx_err; 2176*4609Szf162725 break; 2177*4609Szf162725 case WIFI_STAT_TX_RETRANS: 2178*4609Szf162725 *val = sc->sc_tx_retries; 2179*4609Szf162725 break; 2180*4609Szf162725 case WIFI_STAT_FCS_ERRORS: 2181*4609Szf162725 case WIFI_STAT_WEP_ERRORS: 2182*4609Szf162725 case WIFI_STAT_TX_FRAGS: 2183*4609Szf162725 case WIFI_STAT_MCAST_TX: 2184*4609Szf162725 case WIFI_STAT_RTS_SUCCESS: 2185*4609Szf162725 case WIFI_STAT_RTS_FAILURE: 2186*4609Szf162725 case WIFI_STAT_ACK_FAILURE: 2187*4609Szf162725 case WIFI_STAT_RX_FRAGS: 2188*4609Szf162725 case WIFI_STAT_MCAST_RX: 2189*4609Szf162725 case WIFI_STAT_RX_DUPS: 2190*4609Szf162725 RAL_UNLOCK(sc); 2191*4609Szf162725 return (ieee80211_stat(ic, stat, val)); 2192*4609Szf162725 default: 2193*4609Szf162725 RAL_UNLOCK(sc); 2194*4609Szf162725 return (ENOTSUP); 2195*4609Szf162725 } 2196*4609Szf162725 RAL_UNLOCK(sc); 2197*4609Szf162725 2198*4609Szf162725 return (0); 2199*4609Szf162725 } 2200*4609Szf162725 2201*4609Szf162725 static uint_t 2202*4609Szf162725 rt2560_intr(caddr_t arg) 2203*4609Szf162725 { 2204*4609Szf162725 struct rt2560_softc *sc = (struct rt2560_softc *)arg; 2205*4609Szf162725 uint32_t r; 2206*4609Szf162725 2207*4609Szf162725 RAL_LOCK(sc); 2208*4609Szf162725 2209*4609Szf162725 r = RAL_READ(sc, RT2560_CSR7); 2210*4609Szf162725 RAL_WRITE(sc, RT2560_CSR7, r); 2211*4609Szf162725 2212*4609Szf162725 if (r == 0xffffffff) { 2213*4609Szf162725 RAL_UNLOCK(sc); 2214*4609Szf162725 return (DDI_INTR_UNCLAIMED); 2215*4609Szf162725 } 2216*4609Szf162725 2217*4609Szf162725 if (!(r & RT2560_INTR_ALL)) { 2218*4609Szf162725 RAL_UNLOCK(sc); 2219*4609Szf162725 return (DDI_INTR_UNCLAIMED); 2220*4609Szf162725 } 2221*4609Szf162725 2222*4609Szf162725 /* disable interrupts */ 2223*4609Szf162725 RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); 2224*4609Szf162725 2225*4609Szf162725 if (r & RT2560_TX_DONE) { 2226*4609Szf162725 RAL_UNLOCK(sc); 2227*4609Szf162725 rt2560_tx_intr(sc); 2228*4609Szf162725 RAL_LOCK(sc); 2229*4609Szf162725 } 2230*4609Szf162725 2231*4609Szf162725 if (r & RT2560_PRIO_DONE) { 2232*4609Szf162725 RAL_UNLOCK(sc); 2233*4609Szf162725 rt2560_prio_intr(sc); 2234*4609Szf162725 RAL_LOCK(sc); 2235*4609Szf162725 } 2236*4609Szf162725 2237*4609Szf162725 if (r & RT2560_RX_DONE) { 2238*4609Szf162725 sc->sc_rx_pend = 1; 2239*4609Szf162725 ddi_trigger_softintr(sc->sc_softint_id); 2240*4609Szf162725 } 2241*4609Szf162725 2242*4609Szf162725 /* re-enable interrupts */ 2243*4609Szf162725 RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); 2244*4609Szf162725 RAL_UNLOCK(sc); 2245*4609Szf162725 2246*4609Szf162725 return (DDI_INTR_CLAIMED); 2247*4609Szf162725 } 2248*4609Szf162725 2249*4609Szf162725 static int 2250*4609Szf162725 rt2560_reset(dev_info_t *devinfo, ddi_reset_cmd_t cmd) 2251*4609Szf162725 { 2252*4609Szf162725 struct rt2560_softc *sc; 2253*4609Szf162725 2254*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "rt2560_reset(0x%p)\n", (void *)devinfo); 2255*4609Szf162725 2256*4609Szf162725 if (cmd != DDI_RESET_FORCE) 2257*4609Szf162725 return (DDI_FAILURE); 2258*4609Szf162725 2259*4609Szf162725 sc = ddi_get_soft_state(ral_soft_state_p, ddi_get_instance(devinfo)); 2260*4609Szf162725 2261*4609Szf162725 /* abort Tx */ 2262*4609Szf162725 RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); 2263*4609Szf162725 2264*4609Szf162725 /* disable Rx */ 2265*4609Szf162725 RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX); 2266*4609Szf162725 2267*4609Szf162725 /* reset ASIC (imply reset BBP) */ 2268*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC); 2269*4609Szf162725 RAL_WRITE(sc, RT2560_CSR1, 0); 2270*4609Szf162725 2271*4609Szf162725 /* disable interrupts */ 2272*4609Szf162725 RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); 2273*4609Szf162725 2274*4609Szf162725 return (DDI_SUCCESS); 2275*4609Szf162725 } 2276*4609Szf162725 2277*4609Szf162725 static int 2278*4609Szf162725 rt2560_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 2279*4609Szf162725 { 2280*4609Szf162725 struct rt2560_softc *sc; 2281*4609Szf162725 struct ieee80211com *ic; 2282*4609Szf162725 int err, i; 2283*4609Szf162725 int instance; 2284*4609Szf162725 2285*4609Szf162725 ddi_acc_handle_t ioh; 2286*4609Szf162725 caddr_t regs; 2287*4609Szf162725 uint16_t vendor_id, device_id, command; 2288*4609Szf162725 uint8_t cachelsz; 2289*4609Szf162725 char strbuf[32]; 2290*4609Szf162725 2291*4609Szf162725 wifi_data_t wd = { 0 }; 2292*4609Szf162725 mac_register_t *macp; 2293*4609Szf162725 2294*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "enter rt2560_attach()\n"); 2295*4609Szf162725 2296*4609Szf162725 if (cmd != DDI_ATTACH) 2297*4609Szf162725 return (DDI_FAILURE); 2298*4609Szf162725 2299*4609Szf162725 instance = ddi_get_instance(devinfo); 2300*4609Szf162725 2301*4609Szf162725 if (ddi_soft_state_zalloc(ral_soft_state_p, instance) != DDI_SUCCESS) { 2302*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2303*4609Szf162725 "unable to alloc soft_state_p\n"); 2304*4609Szf162725 return (DDI_FAILURE); 2305*4609Szf162725 } 2306*4609Szf162725 2307*4609Szf162725 sc = ddi_get_soft_state(ral_soft_state_p, instance); 2308*4609Szf162725 ic = (ieee80211com_t *)&sc->sc_ic; 2309*4609Szf162725 sc->sc_dev = devinfo; 2310*4609Szf162725 2311*4609Szf162725 /* pci configuration */ 2312*4609Szf162725 err = ddi_regs_map_setup(devinfo, 0, ®s, 0, 0, &ral_csr_accattr, 2313*4609Szf162725 &ioh); 2314*4609Szf162725 if (err != DDI_SUCCESS) { 2315*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2316*4609Szf162725 "ddi_regs_map_setup() failed"); 2317*4609Szf162725 goto fail1; 2318*4609Szf162725 } 2319*4609Szf162725 2320*4609Szf162725 cachelsz = ddi_get8(ioh, (uint8_t *)(regs + PCI_CONF_CACHE_LINESZ)); 2321*4609Szf162725 if (cachelsz == 0) 2322*4609Szf162725 cachelsz = 0x10; 2323*4609Szf162725 sc->sc_cachelsz = cachelsz << 2; 2324*4609Szf162725 2325*4609Szf162725 vendor_id = ddi_get16(ioh, (uint16_t *)(regs + PCI_CONF_VENID)); 2326*4609Szf162725 device_id = ddi_get16(ioh, (uint16_t *)(regs + PCI_CONF_DEVID)); 2327*4609Szf162725 2328*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): vendor 0x%x, " 2329*4609Szf162725 "device id 0x%x, cache size %d\n", vendor_id, device_id, cachelsz); 2330*4609Szf162725 2331*4609Szf162725 /* 2332*4609Szf162725 * Enable response to memory space accesses, 2333*4609Szf162725 * and enabe bus master. 2334*4609Szf162725 */ 2335*4609Szf162725 command = PCI_COMM_MAE | PCI_COMM_ME; 2336*4609Szf162725 ddi_put16(ioh, (uint16_t *)(regs + PCI_CONF_COMM), command); 2337*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2338*4609Szf162725 "set command reg to 0x%x \n", command); 2339*4609Szf162725 2340*4609Szf162725 ddi_put8(ioh, (uint8_t *)(regs + PCI_CONF_LATENCY_TIMER), 0xa8); 2341*4609Szf162725 ddi_put8(ioh, (uint8_t *)(regs + PCI_CONF_ILINE), 0x10); 2342*4609Szf162725 ddi_regs_map_free(&ioh); 2343*4609Szf162725 2344*4609Szf162725 /* pci i/o space */ 2345*4609Szf162725 err = ddi_regs_map_setup(devinfo, 1, 2346*4609Szf162725 &sc->sc_rbase, 0, 0, &ral_csr_accattr, &sc->sc_ioh); 2347*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2348*4609Szf162725 "regs map1 = %x err=%d\n", regs, err); 2349*4609Szf162725 if (err != DDI_SUCCESS) { 2350*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2351*4609Szf162725 "ddi_regs_map_setup() failed"); 2352*4609Szf162725 goto fail1; 2353*4609Szf162725 } 2354*4609Szf162725 2355*4609Szf162725 /* initialize the ral rate */ 2356*4609Szf162725 ral_rate_init(); 2357*4609Szf162725 2358*4609Szf162725 /* retrieve RT2560 rev. no */ 2359*4609Szf162725 sc->asic_rev = RAL_READ(sc, RT2560_CSR0); 2360*4609Szf162725 2361*4609Szf162725 /* retrieve MAC address */ 2362*4609Szf162725 rt2560_get_macaddr(sc, ic->ic_macaddr); 2363*4609Szf162725 2364*4609Szf162725 /* retrieve RF rev. no and various other things from EEPROM */ 2365*4609Szf162725 rt2560_read_eeprom(sc); 2366*4609Szf162725 2367*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n", 2368*4609Szf162725 sc->asic_rev, rt2560_get_rf(sc->rf_rev)); 2369*4609Szf162725 2370*4609Szf162725 /* 2371*4609Szf162725 * Allocate Tx and Rx rings. 2372*4609Szf162725 */ 2373*4609Szf162725 err = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT); 2374*4609Szf162725 if (err != DDI_SUCCESS) { 2375*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "could not allocate Tx ring\n"); 2376*4609Szf162725 goto fail2; 2377*4609Szf162725 } 2378*4609Szf162725 err = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT); 2379*4609Szf162725 if (err != DDI_SUCCESS) { 2380*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "could not allocate Prio ring\n"); 2381*4609Szf162725 goto fail3; 2382*4609Szf162725 } 2383*4609Szf162725 err = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT); 2384*4609Szf162725 if (err != DDI_SUCCESS) { 2385*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "could not allocate Rx ring\n"); 2386*4609Szf162725 goto fail4; 2387*4609Szf162725 } 2388*4609Szf162725 2389*4609Szf162725 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 2390*4609Szf162725 mutex_init(&sc->txq.tx_lock, NULL, MUTEX_DRIVER, NULL); 2391*4609Szf162725 mutex_init(&sc->prioq.tx_lock, NULL, MUTEX_DRIVER, NULL); 2392*4609Szf162725 mutex_init(&sc->rxq.rx_lock, NULL, MUTEX_DRIVER, NULL); 2393*4609Szf162725 2394*4609Szf162725 2395*4609Szf162725 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 2396*4609Szf162725 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 2397*4609Szf162725 ic->ic_state = IEEE80211_S_INIT; 2398*4609Szf162725 2399*4609Szf162725 ic->ic_maxrssi = 63; 2400*4609Szf162725 ic->ic_set_shortslot = rt2560_update_slot; 2401*4609Szf162725 ic->ic_xmit = rt2560_mgmt_send; 2402*4609Szf162725 2403*4609Szf162725 /* set device capabilities */ 2404*4609Szf162725 ic->ic_caps = 2405*4609Szf162725 IEEE80211_C_TXPMGT | /* tx power management */ 2406*4609Szf162725 IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 2407*4609Szf162725 IEEE80211_C_SHSLOT; /* short slot time supported */ 2408*4609Szf162725 2409*4609Szf162725 #define IEEE80211_CHAN_A \ 2410*4609Szf162725 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2411*4609Szf162725 2412*4609Szf162725 if (sc->rf_rev == RT2560_RF_5222) { 2413*4609Szf162725 /* set supported .11a rates */ 2414*4609Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11A] = rt2560_rateset_11a; 2415*4609Szf162725 2416*4609Szf162725 /* set supported .11a channels */ 2417*4609Szf162725 for (i = 36; i <= 64; i += 4) { 2418*4609Szf162725 ic->ic_sup_channels[i].ich_freq = 2419*4609Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 2420*4609Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 2421*4609Szf162725 } 2422*4609Szf162725 for (i = 100; i <= 140; i += 4) { 2423*4609Szf162725 ic->ic_sup_channels[i].ich_freq = 2424*4609Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 2425*4609Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 2426*4609Szf162725 } 2427*4609Szf162725 for (i = 149; i <= 161; i += 4) { 2428*4609Szf162725 ic->ic_sup_channels[i].ich_freq = 2429*4609Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 2430*4609Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 2431*4609Szf162725 } 2432*4609Szf162725 } 2433*4609Szf162725 2434*4609Szf162725 /* set supported .11b and .11g rates */ 2435*4609Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2560_rateset_11b; 2436*4609Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2560_rateset_11g; 2437*4609Szf162725 2438*4609Szf162725 /* set supported .11b and .11g channels (1 through 14) */ 2439*4609Szf162725 for (i = 1; i <= 14; i++) { 2440*4609Szf162725 ic->ic_sup_channels[i].ich_freq = 2441*4609Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 2442*4609Szf162725 ic->ic_sup_channels[i].ich_flags = 2443*4609Szf162725 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 2444*4609Szf162725 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 2445*4609Szf162725 } 2446*4609Szf162725 2447*4609Szf162725 ieee80211_attach(ic); 2448*4609Szf162725 2449*4609Szf162725 ic->ic_node_alloc = rt2560_node_alloc; 2450*4609Szf162725 ic->ic_node_free = rt2560_node_free; 2451*4609Szf162725 2452*4609Szf162725 /* override state transition machine */ 2453*4609Szf162725 sc->sc_newstate = ic->ic_newstate; 2454*4609Szf162725 ic->ic_newstate = rt2560_newstate; 2455*4609Szf162725 ic->ic_watchdog = rt2560_watchdog; 2456*4609Szf162725 ieee80211_media_init(ic); 2457*4609Szf162725 ic->ic_def_txkey = 0; 2458*4609Szf162725 2459*4609Szf162725 sc->sc_rcr = 0; 2460*4609Szf162725 sc->sc_rx_pend = 0; 2461*4609Szf162725 sc->dwelltime = 300; 2462*4609Szf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; 2463*4609Szf162725 2464*4609Szf162725 err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, 2465*4609Szf162725 &sc->sc_softint_id, NULL, 0, ral_softint_handler, (caddr_t)sc); 2466*4609Szf162725 if (err != DDI_SUCCESS) { 2467*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2468*4609Szf162725 "ddi_add_softintr() failed"); 2469*4609Szf162725 goto fail5; 2470*4609Szf162725 } 2471*4609Szf162725 2472*4609Szf162725 err = ddi_get_iblock_cookie(devinfo, 0, &sc->sc_iblock); 2473*4609Szf162725 if (err != DDI_SUCCESS) { 2474*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2475*4609Szf162725 "Can not get iblock cookie for INT\n"); 2476*4609Szf162725 goto fail6; 2477*4609Szf162725 } 2478*4609Szf162725 2479*4609Szf162725 err = ddi_add_intr(devinfo, 0, NULL, NULL, rt2560_intr, (caddr_t)sc); 2480*4609Szf162725 if (err != DDI_SUCCESS) { 2481*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, 2482*4609Szf162725 "unable to add device interrupt handler\n"); 2483*4609Szf162725 goto fail6; 2484*4609Szf162725 } 2485*4609Szf162725 2486*4609Szf162725 /* 2487*4609Szf162725 * Provide initial settings for the WiFi plugin; whenever this 2488*4609Szf162725 * information changes, we need to call mac_plugindata_update() 2489*4609Szf162725 */ 2490*4609Szf162725 wd.wd_opmode = ic->ic_opmode; 2491*4609Szf162725 wd.wd_secalloc = WIFI_SEC_NONE; 2492*4609Szf162725 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 2493*4609Szf162725 2494*4609Szf162725 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 2495*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2496*4609Szf162725 "MAC version mismatch\n"); 2497*4609Szf162725 goto fail7; 2498*4609Szf162725 } 2499*4609Szf162725 2500*4609Szf162725 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 2501*4609Szf162725 macp->m_driver = sc; 2502*4609Szf162725 macp->m_dip = devinfo; 2503*4609Szf162725 macp->m_src_addr = ic->ic_macaddr; 2504*4609Szf162725 macp->m_callbacks = &rt2560_m_callbacks; 2505*4609Szf162725 macp->m_min_sdu = 0; 2506*4609Szf162725 macp->m_max_sdu = IEEE80211_MTU; 2507*4609Szf162725 macp->m_pdata = &wd; 2508*4609Szf162725 macp->m_pdata_size = sizeof (wd); 2509*4609Szf162725 2510*4609Szf162725 err = mac_register(macp, &ic->ic_mach); 2511*4609Szf162725 mac_free(macp); 2512*4609Szf162725 if (err != 0) { 2513*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ral: rt2560_attach(): " 2514*4609Szf162725 "mac_register err %x\n", err); 2515*4609Szf162725 goto fail7; 2516*4609Szf162725 } 2517*4609Szf162725 2518*4609Szf162725 /* 2519*4609Szf162725 * Create minor node of type DDI_NT_NET_WIFI 2520*4609Szf162725 */ 2521*4609Szf162725 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 2522*4609Szf162725 "ral", instance); 2523*4609Szf162725 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 2524*4609Szf162725 instance + 1, DDI_NT_NET_WIFI, 0); 2525*4609Szf162725 2526*4609Szf162725 if (err != DDI_SUCCESS) 2527*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "ddi_create_minor_node() failed\n"); 2528*4609Szf162725 2529*4609Szf162725 /* 2530*4609Szf162725 * Notify link is down now 2531*4609Szf162725 */ 2532*4609Szf162725 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 2533*4609Szf162725 2534*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "rt2560_attach() exit successfully.\n"); 2535*4609Szf162725 return (DDI_SUCCESS); 2536*4609Szf162725 fail7: 2537*4609Szf162725 ddi_remove_intr(devinfo, 0, sc->sc_iblock); 2538*4609Szf162725 fail6: 2539*4609Szf162725 ddi_remove_softintr(sc->sc_softint_id); 2540*4609Szf162725 fail5: 2541*4609Szf162725 mutex_destroy(&sc->sc_genlock); 2542*4609Szf162725 mutex_destroy(&sc->txq.tx_lock); 2543*4609Szf162725 mutex_destroy(&sc->prioq.tx_lock); 2544*4609Szf162725 mutex_destroy(&sc->rxq.rx_lock); 2545*4609Szf162725 2546*4609Szf162725 rt2560_free_rx_ring(sc, &sc->rxq); 2547*4609Szf162725 fail4: 2548*4609Szf162725 rt2560_free_tx_ring(sc, &sc->prioq); 2549*4609Szf162725 fail3: 2550*4609Szf162725 rt2560_free_tx_ring(sc, &sc->txq); 2551*4609Szf162725 fail2: 2552*4609Szf162725 ddi_regs_map_free(&sc->sc_ioh); 2553*4609Szf162725 fail1: 2554*4609Szf162725 ddi_soft_state_free(ral_soft_state_p, ddi_get_instance(devinfo)); 2555*4609Szf162725 2556*4609Szf162725 return (DDI_FAILURE); 2557*4609Szf162725 } 2558*4609Szf162725 2559*4609Szf162725 static int 2560*4609Szf162725 rt2560_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 2561*4609Szf162725 { 2562*4609Szf162725 struct rt2560_softc *sc; 2563*4609Szf162725 2564*4609Szf162725 RAL_DEBUG(RAL_DBG_GLD, "enter rt2560_detach()\n"); 2565*4609Szf162725 sc = ddi_get_soft_state(ral_soft_state_p, ddi_get_instance(devinfo)); 2566*4609Szf162725 2567*4609Szf162725 if (cmd != DDI_DETACH) 2568*4609Szf162725 return (DDI_FAILURE); 2569*4609Szf162725 2570*4609Szf162725 rt2560_stop(sc); 2571*4609Szf162725 2572*4609Szf162725 /* 2573*4609Szf162725 * Unregister from the MAC layer subsystem 2574*4609Szf162725 */ 2575*4609Szf162725 if (mac_unregister(sc->sc_ic.ic_mach) != 0) 2576*4609Szf162725 return (DDI_FAILURE); 2577*4609Szf162725 2578*4609Szf162725 ddi_remove_intr(devinfo, 0, sc->sc_iblock); 2579*4609Szf162725 ddi_remove_softintr(sc->sc_softint_id); 2580*4609Szf162725 2581*4609Szf162725 /* 2582*4609Szf162725 * detach ieee80211 layer 2583*4609Szf162725 */ 2584*4609Szf162725 ieee80211_detach(&sc->sc_ic); 2585*4609Szf162725 2586*4609Szf162725 rt2560_free_tx_ring(sc, &sc->txq); 2587*4609Szf162725 rt2560_free_tx_ring(sc, &sc->prioq); 2588*4609Szf162725 rt2560_free_rx_ring(sc, &sc->rxq); 2589*4609Szf162725 2590*4609Szf162725 ddi_regs_map_free(&sc->sc_ioh); 2591*4609Szf162725 2592*4609Szf162725 mutex_destroy(&sc->sc_genlock); 2593*4609Szf162725 mutex_destroy(&sc->txq.tx_lock); 2594*4609Szf162725 mutex_destroy(&sc->prioq.tx_lock); 2595*4609Szf162725 mutex_destroy(&sc->rxq.rx_lock); 2596*4609Szf162725 2597*4609Szf162725 ddi_remove_minor_node(devinfo, NULL); 2598*4609Szf162725 ddi_soft_state_free(ral_soft_state_p, ddi_get_instance(devinfo)); 2599*4609Szf162725 2600*4609Szf162725 return (DDI_SUCCESS); 2601*4609Szf162725 } 2602*4609Szf162725 2603*4609Szf162725 int 2604*4609Szf162725 _info(struct modinfo *modinfop) 2605*4609Szf162725 { 2606*4609Szf162725 return (mod_info(&modlinkage, modinfop)); 2607*4609Szf162725 } 2608*4609Szf162725 2609*4609Szf162725 int 2610*4609Szf162725 _init(void) 2611*4609Szf162725 { 2612*4609Szf162725 int status; 2613*4609Szf162725 2614*4609Szf162725 status = ddi_soft_state_init(&ral_soft_state_p, 2615*4609Szf162725 sizeof (struct rt2560_softc), 1); 2616*4609Szf162725 if (status != 0) 2617*4609Szf162725 return (status); 2618*4609Szf162725 2619*4609Szf162725 mac_init_ops(&ral_dev_ops, "ral"); 2620*4609Szf162725 status = mod_install(&modlinkage); 2621*4609Szf162725 if (status != 0) { 2622*4609Szf162725 mac_fini_ops(&ral_dev_ops); 2623*4609Szf162725 ddi_soft_state_fini(&ral_soft_state_p); 2624*4609Szf162725 } 2625*4609Szf162725 return (status); 2626*4609Szf162725 } 2627*4609Szf162725 2628*4609Szf162725 int 2629*4609Szf162725 _fini(void) 2630*4609Szf162725 { 2631*4609Szf162725 int status; 2632*4609Szf162725 2633*4609Szf162725 status = mod_remove(&modlinkage); 2634*4609Szf162725 if (status == 0) { 2635*4609Szf162725 mac_fini_ops(&ral_dev_ops); 2636*4609Szf162725 ddi_soft_state_fini(&ral_soft_state_p); 2637*4609Szf162725 } 2638*4609Szf162725 return (status); 2639*4609Szf162725 } 2640