1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting 8 * Copyright (c) 2007-2008 Marvell Semiconductor, Inc. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 /* 37 * Copyright 2019 Joyent, Inc. 38 */ 39 40 /* 41 * Driver for the Marvell 88W8363 Wireless LAN controller. 42 */ 43 #include <sys/stat.h> 44 #include <sys/dlpi.h> 45 #include <inet/common.h> 46 #include <inet/mi.h> 47 #include <sys/stream.h> 48 #include <sys/errno.h> 49 #include <sys/stropts.h> 50 #include <sys/stat.h> 51 #include <sys/sunddi.h> 52 #include <sys/strsubr.h> 53 #include <sys/strsun.h> 54 #include <sys/pci.h> 55 #include <sys/mac_provider.h> 56 #include <sys/mac_wifi.h> 57 #include <sys/net80211.h> 58 #include <inet/wifi_ioctl.h> 59 60 #include "mwl_var.h" 61 62 static int mwl_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd); 63 static int mwl_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd); 64 static int mwl_quiesce(dev_info_t *devinfo); 65 66 DDI_DEFINE_STREAM_OPS(mwl_dev_ops, nulldev, nulldev, mwl_attach, mwl_detach, 67 nodev, NULL, D_MP, NULL, mwl_quiesce); 68 69 static struct modldrv mwl_modldrv = { 70 &mod_driverops, /* Type of module. This one is a driver */ 71 "Marvell 88W8363 WiFi driver v1.1", /* short description */ 72 &mwl_dev_ops /* driver specific ops */ 73 }; 74 75 static struct modlinkage modlinkage = { 76 MODREV_1, (void *)&mwl_modldrv, NULL 77 }; 78 79 static void *mwl_soft_state_p = NULL; 80 81 static int mwl_m_stat(void *, uint_t, uint64_t *); 82 static int mwl_m_start(void *); 83 static void mwl_m_stop(void *); 84 static int mwl_m_promisc(void *, boolean_t); 85 static int mwl_m_multicst(void *, boolean_t, const uint8_t *); 86 static int mwl_m_unicst(void *, const uint8_t *); 87 static mblk_t *mwl_m_tx(void *, mblk_t *); 88 static void mwl_m_ioctl(void *, queue_t *, mblk_t *); 89 static int mwl_m_setprop(void *arg, const char *pr_name, 90 mac_prop_id_t wldp_pr_num, 91 uint_t wldp_length, const void *wldp_buf); 92 static int mwl_m_getprop(void *arg, const char *pr_name, 93 mac_prop_id_t wldp_pr_num, uint_t wldp_length, 94 void *wldp_buf); 95 static void mwl_m_propinfo(void *, const char *, mac_prop_id_t, 96 mac_prop_info_handle_t); 97 98 static mac_callbacks_t mwl_m_callbacks = { 99 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 100 mwl_m_stat, 101 mwl_m_start, 102 mwl_m_stop, 103 mwl_m_promisc, 104 mwl_m_multicst, 105 mwl_m_unicst, 106 mwl_m_tx, 107 NULL, 108 mwl_m_ioctl, 109 NULL, 110 NULL, 111 NULL, 112 mwl_m_setprop, 113 mwl_m_getprop, 114 mwl_m_propinfo 115 }; 116 117 #define MWL_DBG_ATTACH (1 << 0) 118 #define MWL_DBG_DMA (1 << 1) 119 #define MWL_DBG_FW (1 << 2) 120 #define MWL_DBG_HW (1 << 3) 121 #define MWL_DBG_INTR (1 << 4) 122 #define MWL_DBG_RX (1 << 5) 123 #define MWL_DBG_TX (1 << 6) 124 #define MWL_DBG_CMD (1 << 7) 125 #define MWL_DBG_CRYPTO (1 << 8) 126 #define MWL_DBG_SR (1 << 9) 127 #define MWL_DBG_MSG (1 << 10) 128 129 uint32_t mwl_dbg_flags = 0x0; 130 131 #ifdef DEBUG 132 #define MWL_DBG \ 133 mwl_debug 134 #else 135 #define MWL_DBG(...) (void)(0) 136 #endif 137 138 /* 139 * PIO access attributes for registers 140 */ 141 static ddi_device_acc_attr_t mwl_reg_accattr = { 142 DDI_DEVICE_ATTR_V0, 143 DDI_STRUCTURE_LE_ACC, 144 DDI_STRICTORDER_ACC, 145 DDI_DEFAULT_ACC 146 }; 147 148 static ddi_device_acc_attr_t mwl_cmdbuf_accattr = { 149 DDI_DEVICE_ATTR_V0, 150 DDI_NEVERSWAP_ACC, 151 DDI_STRICTORDER_ACC, 152 DDI_DEFAULT_ACC 153 }; 154 155 /* 156 * DMA access attributes for descriptors and bufs: NOT to be byte swapped. 157 */ 158 static ddi_device_acc_attr_t mwl_desc_accattr = { 159 DDI_DEVICE_ATTR_V0, 160 DDI_NEVERSWAP_ACC, 161 DDI_STRICTORDER_ACC, 162 DDI_DEFAULT_ACC 163 }; 164 165 static ddi_device_acc_attr_t mwl_buf_accattr = { 166 DDI_DEVICE_ATTR_V0, 167 DDI_NEVERSWAP_ACC, 168 DDI_STRICTORDER_ACC, 169 DDI_DEFAULT_ACC 170 }; 171 172 /* 173 * Describes the chip's DMA engine 174 */ 175 static ddi_dma_attr_t mwl_dma_attr = { 176 DMA_ATTR_V0, /* dma_attr version */ 177 0x0000000000000000ull, /* dma_attr_addr_lo */ 178 0xFFFFFFFF, /* dma_attr_addr_hi */ 179 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 180 0x0000000000000001ull, /* dma_attr_align */ 181 0x00000FFF, /* dma_attr_burstsizes */ 182 0x00000001, /* dma_attr_minxfer */ 183 0x000000000000FFFFull, /* dma_attr_maxxfer */ 184 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 185 1, /* dma_attr_sgllen */ 186 0x00000001, /* dma_attr_granular */ 187 0 /* dma_attr_flags */ 188 }; 189 190 /* 191 * Supported rates for 802.11a/b/g modes (in 500Kbps unit). 192 */ 193 static const struct ieee80211_rateset mwl_rateset_11b = 194 { 4, { 2, 4, 11, 22 } }; 195 196 static const struct ieee80211_rateset mwl_rateset_11g = 197 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 198 199 static int mwl_alloc_dma_mem(dev_info_t *, ddi_dma_attr_t *, size_t, 200 ddi_device_acc_attr_t *, uint_t, uint_t, 201 struct dma_area *); 202 static void mwl_free_dma_mem(struct dma_area *); 203 static int mwl_alloc_cmdbuf(struct mwl_softc *); 204 static void mwl_free_cmdbuf(struct mwl_softc *); 205 static int mwl_alloc_rx_ring(struct mwl_softc *, int); 206 static void mwl_free_rx_ring(struct mwl_softc *); 207 static int mwl_alloc_tx_ring(struct mwl_softc *, struct mwl_tx_ring *, 208 int); 209 static void mwl_free_tx_ring(struct mwl_softc *, struct mwl_tx_ring *); 210 static int mwl_setupdma(struct mwl_softc *); 211 static void mwl_txq_init(struct mwl_softc *, struct mwl_tx_ring *, int); 212 static int mwl_tx_setup(struct mwl_softc *, int, int); 213 static int mwl_setup_txq(struct mwl_softc *); 214 static int mwl_fwload(struct mwl_softc *, void *); 215 static int mwl_loadsym(ddi_modhandle_t, char *, char **, size_t *); 216 static void mwlFwReset(struct mwl_softc *); 217 static void mwlPokeSdramController(struct mwl_softc *, int); 218 static void mwlTriggerPciCmd(struct mwl_softc *); 219 static int mwlWaitFor(struct mwl_softc *, uint32_t); 220 static int mwlSendBlock(struct mwl_softc *, int, const void *, size_t); 221 static int mwlSendBlock2(struct mwl_softc *, const void *, size_t); 222 static void mwlSendCmd(struct mwl_softc *); 223 static int mwlExecuteCmd(struct mwl_softc *, unsigned short); 224 static int mwlWaitForCmdComplete(struct mwl_softc *, uint16_t); 225 static void dumpresult(struct mwl_softc *, int); 226 static int mwlResetHalState(struct mwl_softc *); 227 static int mwlGetPwrCalTable(struct mwl_softc *); 228 static int mwlGetCalTable(struct mwl_softc *, uint8_t, uint8_t); 229 static int mwlGetPwrCalTable(struct mwl_softc *); 230 static void dumpcaldata(const char *, const uint8_t *, int); 231 static void get2Ghz(MWL_HAL_CHANNELINFO *, const uint8_t *, int); 232 static void get5Ghz(MWL_HAL_CHANNELINFO *, const uint8_t *, int); 233 static void setmaxtxpow(struct mwl_hal_channel *, int, int); 234 static uint16_t ieee2mhz(int); 235 static const char * 236 mwlcmdname(int); 237 static int mwl_gethwspecs(struct mwl_softc *); 238 static int mwl_getchannels(struct mwl_softc *); 239 static void getchannels(struct mwl_softc *, int, int *, 240 struct mwl_channel *); 241 static void addchannels(struct mwl_channel *, int, int *, 242 const MWL_HAL_CHANNELINFO *, int); 243 static void addht40channels(struct mwl_channel *, int, int *, 244 const MWL_HAL_CHANNELINFO *, int); 245 static const struct mwl_channel * 246 findchannel(const struct mwl_channel *, int, 247 int, int); 248 static void addchan(struct mwl_channel *, int, int, int, int); 249 250 static int mwl_chan_set(struct mwl_softc *, struct mwl_channel *); 251 static void mwl_mapchan(MWL_HAL_CHANNEL *, const struct mwl_channel *); 252 static int mwl_setcurchanrates(struct mwl_softc *); 253 const struct ieee80211_rateset * 254 mwl_get_suprates(struct ieee80211com *, 255 const struct mwl_channel *); 256 static uint32_t cvtChannelFlags(const MWL_HAL_CHANNEL *); 257 static const struct mwl_hal_channel * 258 findhalchannel(const struct mwl_softc *, 259 const MWL_HAL_CHANNEL *); 260 enum ieee80211_phymode 261 mwl_chan2mode(const struct mwl_channel *); 262 static int mwl_map2regioncode(const struct mwl_regdomain *); 263 static int mwl_startrecv(struct mwl_softc *); 264 static int mwl_mode_init(struct mwl_softc *); 265 static void mwl_hal_intrset(struct mwl_softc *, uint32_t); 266 static void mwl_hal_getisr(struct mwl_softc *, uint32_t *); 267 static int mwl_hal_sethwdma(struct mwl_softc *, 268 const struct mwl_hal_txrxdma *); 269 static int mwl_hal_getchannelinfo(struct mwl_softc *, int, int, 270 const MWL_HAL_CHANNELINFO **); 271 static int mwl_hal_setmac_locked(struct mwl_softc *, 272 const uint8_t [IEEE80211_ADDR_LEN]); 273 static int mwl_hal_keyreset(struct mwl_softc *, const MWL_HAL_KEYVAL *, 274 const uint8_t mac[IEEE80211_ADDR_LEN]); 275 static int mwl_hal_keyset(struct mwl_softc *, const MWL_HAL_KEYVAL *, 276 const uint8_t mac[IEEE80211_ADDR_LEN]); 277 static int mwl_hal_newstation(struct mwl_softc *, 278 const uint8_t [IEEE80211_ADDR_LEN], 279 uint16_t, uint16_t, const MWL_HAL_PEERINFO *, int, int); 280 static int mwl_hal_setantenna(struct mwl_softc *, MWL_HAL_ANTENNA, int); 281 static int mwl_hal_setradio(struct mwl_softc *, int, MWL_HAL_PREAMBLE); 282 static int mwl_hal_setwmm(struct mwl_softc *, int); 283 static int mwl_hal_setchannel(struct mwl_softc *, const MWL_HAL_CHANNEL *); 284 static int mwl_hal_settxpower(struct mwl_softc *, const MWL_HAL_CHANNEL *, 285 uint8_t); 286 static int mwl_hal_settxrate(struct mwl_softc *, MWL_HAL_TXRATE_HANDLING, 287 const MWL_HAL_TXRATE *); 288 static int mwl_hal_settxrate_auto(struct mwl_softc *, 289 const MWL_HAL_TXRATE *); 290 static int mwl_hal_setrateadaptmode(struct mwl_softc *, uint16_t); 291 static int mwl_hal_setoptimizationlevel(struct mwl_softc *, int); 292 static int mwl_hal_setregioncode(struct mwl_softc *, int); 293 static int mwl_hal_setassocid(struct mwl_softc *, 294 const uint8_t [IEEE80211_ADDR_LEN], uint16_t); 295 static int mwl_setrates(struct ieee80211com *); 296 static int mwl_hal_setrtsthreshold(struct mwl_softc *, int); 297 static int mwl_hal_setcsmode(struct mwl_softc *, MWL_HAL_CSMODE); 298 static int mwl_hal_setpromisc(struct mwl_softc *, int); 299 static int mwl_hal_start(struct mwl_softc *); 300 static int mwl_hal_setinframode(struct mwl_softc *); 301 static int mwl_hal_stop(struct mwl_softc *); 302 static struct ieee80211_node * 303 mwl_node_alloc(struct ieee80211com *); 304 static void mwl_node_free(struct ieee80211_node *); 305 static int mwl_key_alloc(struct ieee80211com *, 306 const struct ieee80211_key *, 307 ieee80211_keyix *, ieee80211_keyix *); 308 static int mwl_key_delete(struct ieee80211com *, 309 const struct ieee80211_key *); 310 static int mwl_key_set(struct ieee80211com *, const struct ieee80211_key *, 311 const uint8_t mac[IEEE80211_ADDR_LEN]); 312 static void mwl_setanywepkey(struct ieee80211com *, 313 const uint8_t [IEEE80211_ADDR_LEN]); 314 static void mwl_setglobalkeys(struct ieee80211com *c); 315 static int addgroupflags(MWL_HAL_KEYVAL *, const struct ieee80211_key *); 316 static void mwl_hal_txstart(struct mwl_softc *, int); 317 static int mwl_send(ieee80211com_t *, mblk_t *, uint8_t); 318 static void mwl_next_scan(void *); 319 static MWL_HAL_PEERINFO * 320 mkpeerinfo(MWL_HAL_PEERINFO *, const struct ieee80211_node *); 321 static uint32_t get_rate_bitmap(const struct ieee80211_rateset *); 322 static int mwl_newstate(struct ieee80211com *, enum ieee80211_state, int); 323 static int cvtrssi(uint8_t); 324 static uint_t mwl_intr(caddr_t, caddr_t); 325 static uint_t mwl_softintr(caddr_t, caddr_t); 326 static void mwl_tx_intr(struct mwl_softc *); 327 static void mwl_rx_intr(struct mwl_softc *); 328 static int mwl_init(struct mwl_softc *); 329 static void mwl_stop(struct mwl_softc *); 330 static int mwl_resume(struct mwl_softc *); 331 332 333 #ifdef DEBUG 334 static void 335 mwl_debug(uint32_t dbg_flags, const int8_t *fmt, ...) 336 { 337 va_list args; 338 339 if (dbg_flags & mwl_dbg_flags) { 340 va_start(args, fmt); 341 vcmn_err(CE_CONT, fmt, args); 342 va_end(args); 343 } 344 } 345 #endif 346 347 /* 348 * Allocate an DMA memory and a DMA handle for accessing it 349 */ 350 static int 351 mwl_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, 352 size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags, 353 uint_t bind_flags, struct dma_area *dma_p) 354 { 355 int err; 356 357 /* 358 * Allocate handle 359 */ 360 err = ddi_dma_alloc_handle(devinfo, dma_attr, 361 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 362 if (err != DDI_SUCCESS) { 363 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_dma_mem(): " 364 "failed to alloc handle\n"); 365 goto fail1; 366 } 367 368 /* 369 * Allocate memory 370 */ 371 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 372 alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va, 373 &dma_p->alength, &dma_p->acc_hdl); 374 if (err != DDI_SUCCESS) { 375 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_dma_mem(): " 376 "failed to alloc mem\n"); 377 goto fail2; 378 } 379 380 /* 381 * Bind the two together 382 */ 383 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 384 dma_p->mem_va, dma_p->alength, bind_flags, 385 DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies); 386 if (err != DDI_DMA_MAPPED) { 387 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_dma_mem(): " 388 "failed to bind handle\n"); 389 goto fail3; 390 } 391 392 if (dma_p->ncookies != 1) { 393 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_dma_mem(): " 394 "failed to alloc cookies\n"); 395 goto fail4; 396 } 397 398 dma_p->nslots = ~0U; 399 dma_p->size = ~0U; 400 dma_p->token = ~0U; 401 dma_p->offset = 0; 402 403 return (DDI_SUCCESS); 404 405 fail4: 406 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 407 fail3: 408 ddi_dma_mem_free(&dma_p->acc_hdl); 409 fail2: 410 ddi_dma_free_handle(&dma_p->dma_hdl); 411 fail1: 412 return (err); 413 } 414 415 static void 416 mwl_free_dma_mem(struct dma_area *dma_p) 417 { 418 if (dma_p->dma_hdl != NULL) { 419 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 420 if (dma_p->acc_hdl != NULL) { 421 ddi_dma_mem_free(&dma_p->acc_hdl); 422 dma_p->acc_hdl = NULL; 423 } 424 ddi_dma_free_handle(&dma_p->dma_hdl); 425 dma_p->ncookies = 0; 426 dma_p->dma_hdl = NULL; 427 } 428 } 429 430 static int 431 mwl_alloc_cmdbuf(struct mwl_softc *sc) 432 { 433 int err; 434 size_t size; 435 436 size = MWL_CMDBUF_SIZE; 437 438 err = mwl_alloc_dma_mem(sc->sc_dev, &mwl_dma_attr, size, 439 &mwl_cmdbuf_accattr, DDI_DMA_CONSISTENT, 440 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 441 &sc->sc_cmd_dma); 442 if (err != DDI_SUCCESS) { 443 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_cmdbuf(): " 444 "failed to alloc dma mem\n"); 445 return (DDI_FAILURE); 446 } 447 448 sc->sc_cmd_mem = (uint16_t *)sc->sc_cmd_dma.mem_va; 449 sc->sc_cmd_dmaaddr = sc->sc_cmd_dma.cookie.dmac_address; 450 451 return (DDI_SUCCESS); 452 } 453 454 static void 455 mwl_free_cmdbuf(struct mwl_softc *sc) 456 { 457 if (sc->sc_cmd_mem != NULL) 458 mwl_free_dma_mem(&sc->sc_cmd_dma); 459 } 460 461 static int 462 mwl_alloc_rx_ring(struct mwl_softc *sc, int count) 463 { 464 struct mwl_rx_ring *ring; 465 struct mwl_rxdesc *ds; 466 struct mwl_rxbuf *bf; 467 int i, err, datadlen; 468 469 ring = &sc->sc_rxring; 470 ring->count = count; 471 ring->cur = ring->next = 0; 472 err = mwl_alloc_dma_mem(sc->sc_dev, &mwl_dma_attr, 473 count * sizeof (struct mwl_rxdesc), 474 &mwl_desc_accattr, 475 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 476 &ring->rxdesc_dma); 477 if (err) { 478 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_rxring(): " 479 "alloc tx ring failed, size %d\n", 480 (uint32_t)(count * sizeof (struct mwl_rxdesc))); 481 return (DDI_FAILURE); 482 } 483 484 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_rx_ring(): " 485 "dma len = %d\n", (uint32_t)(ring->rxdesc_dma.alength)); 486 ring->desc = (struct mwl_rxdesc *)ring->rxdesc_dma.mem_va; 487 ring->physaddr = ring->rxdesc_dma.cookie.dmac_address; 488 bzero(ring->desc, count * sizeof (struct mwl_rxdesc)); 489 490 datadlen = count * sizeof (struct mwl_rxbuf); 491 ring->buf = (struct mwl_rxbuf *)kmem_zalloc(datadlen, KM_SLEEP); 492 if (ring->buf == NULL) { 493 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_rxring(): " 494 "could not alloc rx ring data buffer\n"); 495 return (DDI_FAILURE); 496 } 497 bzero(ring->buf, count * sizeof (struct mwl_rxbuf)); 498 499 /* 500 * Pre-allocate Rx buffers and populate Rx ring. 501 */ 502 for (i = 0; i < count; i++) { 503 ds = &ring->desc[i]; 504 bf = &ring->buf[i]; 505 /* alloc DMA memory */ 506 (void) mwl_alloc_dma_mem(sc->sc_dev, &mwl_dma_attr, 507 sc->sc_dmabuf_size, 508 &mwl_buf_accattr, 509 DDI_DMA_STREAMING, 510 DDI_DMA_READ | DDI_DMA_STREAMING, 511 &bf->rxbuf_dma); 512 bf->bf_mem = (uint8_t *)(bf->rxbuf_dma.mem_va); 513 bf->bf_baddr = bf->rxbuf_dma.cookie.dmac_address; 514 bf->bf_desc = ds; 515 bf->bf_daddr = ring->physaddr + _PTRDIFF(ds, ring->desc); 516 } 517 518 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 519 0, 520 ring->rxdesc_dma.alength, 521 DDI_DMA_SYNC_FORDEV); 522 523 return (0); 524 } 525 526 static void 527 mwl_free_rx_ring(struct mwl_softc *sc) 528 { 529 struct mwl_rx_ring *ring; 530 struct mwl_rxbuf *bf; 531 int i; 532 533 ring = &sc->sc_rxring; 534 535 if (ring->desc != NULL) { 536 mwl_free_dma_mem(&ring->rxdesc_dma); 537 } 538 539 if (ring->buf != NULL) { 540 for (i = 0; i < ring->count; i++) { 541 bf = &ring->buf[i]; 542 mwl_free_dma_mem(&bf->rxbuf_dma); 543 } 544 kmem_free(ring->buf, 545 (ring->count * sizeof (struct mwl_rxbuf))); 546 } 547 } 548 549 static int 550 mwl_alloc_tx_ring(struct mwl_softc *sc, struct mwl_tx_ring *ring, 551 int count) 552 { 553 struct mwl_txdesc *ds; 554 struct mwl_txbuf *bf; 555 int i, err, datadlen; 556 557 ring->count = count; 558 ring->queued = 0; 559 ring->cur = ring->next = ring->stat = 0; 560 err = mwl_alloc_dma_mem(sc->sc_dev, &mwl_dma_attr, 561 count * sizeof (struct mwl_txdesc), &mwl_desc_accattr, 562 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 563 &ring->txdesc_dma); 564 if (err) { 565 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_tx_ring(): " 566 "alloc tx ring failed, size %d\n", 567 (uint32_t)(count * sizeof (struct mwl_txdesc))); 568 return (DDI_FAILURE); 569 } 570 571 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_tx_ring(): " 572 "dma len = %d\n", (uint32_t)(ring->txdesc_dma.alength)); 573 ring->desc = (struct mwl_txdesc *)ring->txdesc_dma.mem_va; 574 ring->physaddr = ring->txdesc_dma.cookie.dmac_address; 575 bzero(ring->desc, count * sizeof (struct mwl_txdesc)); 576 577 datadlen = count * sizeof (struct mwl_txbuf); 578 ring->buf = kmem_zalloc(datadlen, KM_SLEEP); 579 if (ring->buf == NULL) { 580 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_alloc_tx_ring(): " 581 "could not alloc tx ring data buffer\n"); 582 return (DDI_FAILURE); 583 } 584 bzero(ring->buf, count * sizeof (struct mwl_txbuf)); 585 586 for (i = 0; i < count; i++) { 587 ds = &ring->desc[i]; 588 bf = &ring->buf[i]; 589 /* alloc DMA memory */ 590 (void) mwl_alloc_dma_mem(sc->sc_dev, &mwl_dma_attr, 591 sc->sc_dmabuf_size, 592 &mwl_buf_accattr, 593 DDI_DMA_STREAMING, 594 DDI_DMA_WRITE | DDI_DMA_STREAMING, 595 &bf->txbuf_dma); 596 bf->bf_baddr = bf->txbuf_dma.cookie.dmac_address; 597 bf->bf_mem = (uint8_t *)(bf->txbuf_dma.mem_va); 598 bf->bf_daddr = ring->physaddr + _PTRDIFF(ds, ring->desc); 599 bf->bf_desc = ds; 600 } 601 602 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 603 0, 604 ring->txdesc_dma.alength, 605 DDI_DMA_SYNC_FORDEV); 606 607 return (0); 608 } 609 610 /* ARGSUSED */ 611 static void 612 mwl_free_tx_ring(struct mwl_softc *sc, struct mwl_tx_ring *ring) 613 { 614 struct mwl_txbuf *bf; 615 int i; 616 617 if (ring->desc != NULL) { 618 mwl_free_dma_mem(&ring->txdesc_dma); 619 } 620 621 if (ring->buf != NULL) { 622 for (i = 0; i < ring->count; i++) { 623 bf = &ring->buf[i]; 624 mwl_free_dma_mem(&bf->txbuf_dma); 625 } 626 kmem_free(ring->buf, 627 (ring->count * sizeof (struct mwl_txbuf))); 628 } 629 } 630 631 /* 632 * Inform the f/w about location of the tx/rx dma data structures 633 * and related state. This cmd must be done immediately after a 634 * mwl_hal_gethwspecs call or the f/w will lockup. 635 */ 636 static int 637 mwl_hal_sethwdma(struct mwl_softc *sc, const struct mwl_hal_txrxdma *dma) 638 { 639 HostCmd_DS_SET_HW_SPEC *pCmd; 640 int retval; 641 642 _CMD_SETUP(pCmd, HostCmd_DS_SET_HW_SPEC, HostCmd_CMD_SET_HW_SPEC); 643 pCmd->WcbBase[0] = LE_32(dma->wcbBase[0]); 644 pCmd->WcbBase[1] = LE_32(dma->wcbBase[1]); 645 pCmd->WcbBase[2] = LE_32(dma->wcbBase[2]); 646 pCmd->WcbBase[3] = LE_32(dma->wcbBase[3]); 647 pCmd->TxWcbNumPerQueue = LE_32(dma->maxNumTxWcb); 648 pCmd->NumTxQueues = LE_32(dma->maxNumWCB); 649 pCmd->TotalRxWcb = LE_32(1); /* XXX */ 650 pCmd->RxPdWrPtr = LE_32(dma->rxDescRead); 651 /* 652 * pCmd->Flags = LE_32(SET_HW_SPEC_HOSTFORM_BEACON 653 * #ifdef MWL_HOST_PS_SUPPORT 654 * | SET_HW_SPEC_HOST_POWERSAVE 655 * #endif 656 * | SET_HW_SPEC_HOSTFORM_PROBERESP); 657 */ 658 pCmd->Flags = 0; 659 /* disable multi-bss operation for A1-A4 parts */ 660 if (sc->sc_revs.mh_macRev < 5) 661 pCmd->Flags |= LE_32(SET_HW_SPEC_DISABLEMBSS); 662 663 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_HW_SPEC); 664 if (retval == 0) { 665 if (pCmd->Flags & LE_32(SET_HW_SPEC_DISABLEMBSS)) 666 sc->sc_hw_flags &= ~MHF_MBSS; 667 else 668 sc->sc_hw_flags |= MHF_MBSS; 669 } 670 671 return (retval); 672 } 673 674 /* 675 * Inform firmware of our tx/rx dma setup. The BAR 0 676 * writes below are for compatibility with older firmware. 677 * For current firmware we send this information with a 678 * cmd block via mwl_hal_sethwdma. 679 */ 680 static int 681 mwl_setupdma(struct mwl_softc *sc) 682 { 683 int i, err; 684 685 sc->sc_hwdma.rxDescRead = sc->sc_rxring.physaddr; 686 mwl_mem_write4(sc, sc->sc_hwspecs.rxDescRead, sc->sc_hwdma.rxDescRead); 687 mwl_mem_write4(sc, sc->sc_hwspecs.rxDescWrite, sc->sc_hwdma.rxDescRead); 688 689 for (i = 0; i < MWL_NUM_TX_QUEUES - MWL_NUM_ACK_QUEUES; i++) { 690 struct mwl_tx_ring *txring = &sc->sc_txring[i]; 691 sc->sc_hwdma.wcbBase[i] = txring->physaddr; 692 mwl_mem_write4(sc, sc->sc_hwspecs.wcbBase[i], 693 sc->sc_hwdma.wcbBase[i]); 694 } 695 sc->sc_hwdma.maxNumTxWcb = MWL_TX_RING_COUNT; 696 sc->sc_hwdma.maxNumWCB = MWL_NUM_TX_QUEUES - MWL_NUM_ACK_QUEUES; 697 698 err = mwl_hal_sethwdma(sc, &sc->sc_hwdma); 699 if (err != 0) { 700 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_setupdma(): " 701 "unable to setup tx/rx dma; hal status %u\n", err); 702 /* XXX */ 703 } 704 705 return (err); 706 } 707 708 /* ARGSUSED */ 709 static void 710 mwl_txq_init(struct mwl_softc *sc, struct mwl_tx_ring *txring, int qnum) 711 { 712 struct mwl_txbuf *bf; 713 struct mwl_txdesc *ds; 714 int i; 715 716 txring->qnum = qnum; 717 txring->txpri = 0; /* XXX */ 718 719 bf = txring->buf; 720 ds = txring->desc; 721 for (i = 0; i < MWL_TX_RING_COUNT - 1; i++) { 722 bf++; 723 ds->pPhysNext = bf->bf_daddr; 724 ds++; 725 } 726 bf = txring->buf; 727 ds->pPhysNext = LE_32(bf->bf_daddr); 728 } 729 730 /* 731 * Setup a hardware data transmit queue for the specified 732 * access control. We record the mapping from ac's 733 * to h/w queues for use by mwl_tx_start. 734 */ 735 static int 736 mwl_tx_setup(struct mwl_softc *sc, int ac, int mvtype) 737 { 738 #define N(a) (sizeof (a)/sizeof (a[0])) 739 struct mwl_tx_ring *txring; 740 741 if (ac >= N(sc->sc_ac2q)) { 742 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_tx_setup(): " 743 "AC %u out of range, max %u!\n", 744 ac, (uint_t)N(sc->sc_ac2q)); 745 return (0); 746 } 747 if (mvtype >= MWL_NUM_TX_QUEUES) { 748 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_tx_setup(): " 749 "mvtype %u out of range, max %u!\n", 750 mvtype, MWL_NUM_TX_QUEUES); 751 return (0); 752 } 753 txring = &sc->sc_txring[mvtype]; 754 mwl_txq_init(sc, txring, mvtype); 755 sc->sc_ac2q[ac] = txring; 756 return (1); 757 #undef N 758 } 759 760 static int 761 mwl_setup_txq(struct mwl_softc *sc) 762 { 763 int err = 0; 764 765 /* NB: insure BK queue is the lowest priority h/w queue */ 766 if (!mwl_tx_setup(sc, WME_AC_BK, MWL_WME_AC_BK)) { 767 MWL_DBG(MWL_DBG_DMA, "mwl: mwl_setup_txq(): " 768 "unable to setup xmit queue for %s traffic!\n", 769 mwl_wme_acnames[WME_AC_BK]); 770 err = EIO; 771 return (err); 772 } 773 if (!mwl_tx_setup(sc, WME_AC_BE, MWL_WME_AC_BE) || 774 !mwl_tx_setup(sc, WME_AC_VI, MWL_WME_AC_VI) || 775 !mwl_tx_setup(sc, WME_AC_VO, MWL_WME_AC_VO)) { 776 /* 777 * Not enough hardware tx queues to properly do WME; 778 * just punt and assign them all to the same h/w queue. 779 * We could do a better job of this if, for example, 780 * we allocate queues when we switch from station to 781 * AP mode. 782 */ 783 sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK]; 784 sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK]; 785 sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK]; 786 } 787 788 return (err); 789 } 790 791 /* 792 * find mwl firmware module's "_start" "_end" symbols 793 * and get its size. 794 */ 795 static int 796 mwl_loadsym(ddi_modhandle_t modp, char *sym, char **start, size_t *len) 797 { 798 char start_sym[64]; 799 char end_sym[64]; 800 char *p, *end; 801 int rv; 802 size_t n; 803 804 (void) snprintf(start_sym, sizeof (start_sym), "%s_start", sym); 805 (void) snprintf(end_sym, sizeof (end_sym), "%s_end", sym); 806 807 p = (char *)ddi_modsym(modp, start_sym, &rv); 808 if (p == NULL || rv != 0) { 809 MWL_DBG(MWL_DBG_FW, "mwl: mwl_loadsym(): " 810 "mod %s: symbol %s not found\n", sym, start_sym); 811 return (-1); 812 } 813 814 end = (char *)ddi_modsym(modp, end_sym, &rv); 815 if (end == NULL || rv != 0) { 816 MWL_DBG(MWL_DBG_FW, "mwl: mwl_loadsym(): " 817 "mod %s: symbol %s not found\n", sym, end_sym); 818 return (-1); 819 } 820 821 n = _PTRDIFF(end, p); 822 *start = p; 823 *len = n; 824 825 return (0); 826 } 827 828 static void 829 mwlFwReset(struct mwl_softc *sc) 830 { 831 if (mwl_ctl_read4(sc, MACREG_REG_INT_CODE) == 0xffffffff) { 832 MWL_DBG(MWL_DBG_FW, "mwl: mwlFWReset(): " 833 "device not present!\n"); 834 return; 835 } 836 837 mwl_ctl_write4(sc, MACREG_REG_H2A_INTERRUPT_EVENTS, ISR_RESET); 838 sc->sc_hw_flags &= ~MHF_FWHANG; 839 } 840 841 static void 842 mwlPokeSdramController(struct mwl_softc *sc, int SDRAMSIZE_Addr) 843 { 844 /* Set up sdram controller for superflyv2 */ 845 mwl_ctl_write4(sc, 0x00006014, 0x33); 846 mwl_ctl_write4(sc, 0x00006018, 0xa3a2632); 847 mwl_ctl_write4(sc, 0x00006010, SDRAMSIZE_Addr); 848 } 849 850 static void 851 mwlTriggerPciCmd(struct mwl_softc *sc) 852 { 853 (void) ddi_dma_sync(sc->sc_cmd_dma.dma_hdl, 854 0, 855 sc->sc_cmd_dma.alength, 856 DDI_DMA_SYNC_FORDEV); 857 858 mwl_ctl_write4(sc, MACREG_REG_GEN_PTR, sc->sc_cmd_dmaaddr); 859 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 860 861 mwl_ctl_write4(sc, MACREG_REG_INT_CODE, 0x00); 862 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 863 864 mwl_ctl_write4(sc, MACREG_REG_H2A_INTERRUPT_EVENTS, 865 MACREG_H2ARIC_BIT_DOOR_BELL); 866 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 867 } 868 869 static int 870 mwlWaitFor(struct mwl_softc *sc, uint32_t val) 871 { 872 int i; 873 874 for (i = 0; i < FW_MAX_NUM_CHECKS; i++) { 875 DELAY(FW_CHECK_USECS); 876 if (mwl_ctl_read4(sc, MACREG_REG_INT_CODE) == val) 877 return (1); 878 } 879 return (0); 880 } 881 882 /* 883 * Firmware block xmit when talking to the boot-rom. 884 */ 885 static int 886 mwlSendBlock(struct mwl_softc *sc, int bsize, const void *data, size_t dsize) 887 { 888 sc->sc_cmd_mem[0] = LE_16(HostCmd_CMD_CODE_DNLD); 889 sc->sc_cmd_mem[1] = LE_16(bsize); 890 (void) memcpy(&sc->sc_cmd_mem[4], data, dsize); 891 mwlTriggerPciCmd(sc); 892 /* XXX 2000 vs 200 */ 893 if (mwlWaitFor(sc, MACREG_INT_CODE_CMD_FINISHED)) { 894 mwl_ctl_write4(sc, MACREG_REG_INT_CODE, 0); 895 return (1); 896 } 897 898 MWL_DBG(MWL_DBG_FW, "mwl: mwlSendBlock(): " 899 "timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n", 900 mwl_ctl_read4(sc, MACREG_REG_INT_CODE)); 901 return (0); 902 } 903 904 /* 905 * Firmware block xmit when talking to the 1st-stage loader. 906 */ 907 static int 908 mwlSendBlock2(struct mwl_softc *sc, const void *data, size_t dsize) 909 { 910 (void) memcpy(&sc->sc_cmd_mem[0], data, dsize); 911 mwlTriggerPciCmd(sc); 912 if (mwlWaitFor(sc, MACREG_INT_CODE_CMD_FINISHED)) { 913 mwl_ctl_write4(sc, MACREG_REG_INT_CODE, 0); 914 return (1); 915 } 916 917 MWL_DBG(MWL_DBG_FW, "mwl: mwlSendBlock2(): " 918 "timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n", 919 mwl_ctl_read4(sc, MACREG_REG_INT_CODE)); 920 return (0); 921 } 922 923 /* ARGSUSED */ 924 static int 925 mwl_fwload(struct mwl_softc *sc, void *fwargs) 926 { 927 char *fwname = "mwlfw"; 928 char *fwbootname = "mwlboot"; 929 char *fwbinname = "mw88W8363fw"; 930 char *fwboot_index, *fw_index; 931 uint8_t *fw, *fwboot; 932 ddi_modhandle_t modfw; 933 /* XXX get from firmware header */ 934 uint32_t FwReadySignature = HostCmd_SOFTAP_FWRDY_SIGNATURE; 935 uint32_t OpMode = HostCmd_SOFTAP_MODE; 936 const uint8_t *fp, *ep; 937 size_t fw_size, fwboot_size; 938 uint32_t blocksize, nbytes; 939 int i, rv, err, ntries; 940 941 rv = err = 0; 942 fw = fwboot = NULL; 943 fw_index = fwboot_index = NULL; 944 945 modfw = ddi_modopen(fwname, KRTLD_MODE_FIRST, &rv); 946 if (modfw == NULL) { 947 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 948 "module %s not found\n", fwname); 949 err = -1; 950 goto bad2; 951 } 952 953 err = mwl_loadsym(modfw, fwbootname, &fwboot_index, &fwboot_size); 954 if (err != 0) { 955 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 956 "could not get boot firmware\n"); 957 err = -1; 958 goto bad2; 959 } 960 961 err = mwl_loadsym(modfw, fwbinname, &fw_index, &fw_size); 962 if (err != 0) { 963 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 964 "could not get firmware\n"); 965 err = -1; 966 goto bad2; 967 } 968 969 fwboot = (uint8_t *)kmem_alloc(fwboot_size, KM_SLEEP); 970 if (fwboot == NULL) { 971 MWL_DBG(MWL_DBG_FW, "mwl: mwl_loadfirmware(): " 972 "failed to alloc boot firmware memory\n"); 973 err = -1; 974 goto bad2; 975 } 976 (void) memcpy(fwboot, fwboot_index, fwboot_size); 977 978 fw = (uint8_t *)kmem_alloc(fw_size, KM_SLEEP); 979 if (fw == NULL) { 980 MWL_DBG(MWL_DBG_FW, "mwl: mwl_loadfirmware(): " 981 "failed to alloc firmware memory\n"); 982 err = -1; 983 goto bad2; 984 } 985 (void) memcpy(fw, fw_index, fw_size); 986 987 if (modfw != NULL) 988 (void) ddi_modclose(modfw); 989 990 if (fw_size < 4) { 991 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 992 "could not load firmware image %s\n", 993 fwname); 994 err = ENXIO; 995 goto bad2; 996 } 997 998 if (fw[0] == 0x01 && fw[1] == 0x00 && 999 fw[2] == 0x00 && fw[3] == 0x00) { 1000 /* 1001 * 2-stage load, get the boot firmware. 1002 */ 1003 if (fwboot == NULL) { 1004 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 1005 "could not load firmware image %s\n", 1006 fwbootname); 1007 err = ENXIO; 1008 goto bad2; 1009 } 1010 } else 1011 fwboot = NULL; 1012 1013 mwlFwReset(sc); 1014 1015 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_CLEAR_SEL, 1016 MACREG_A2HRIC_BIT_MASK); 1017 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_CAUSE, 0x00); 1018 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_MASK, 0x00); 1019 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_STATUS_MASK, 1020 MACREG_A2HRIC_BIT_MASK); 1021 if (sc->sc_SDRAMSIZE_Addr != 0) { 1022 /* Set up sdram controller for superflyv2 */ 1023 mwlPokeSdramController(sc, sc->sc_SDRAMSIZE_Addr); 1024 } 1025 1026 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 1027 "load %s firmware image (%u bytes)\n", 1028 fwname, (unsigned int)fw_size); 1029 1030 if (fwboot != NULL) { 1031 /* 1032 * Do 2-stage load. The 1st stage loader is setup 1033 * with the bootrom loader then we load the real 1034 * image using a different handshake. With this 1035 * mechanism the firmware is segmented into chunks 1036 * that have a CRC. If a chunk is incorrect we'll 1037 * be told to retransmit. 1038 */ 1039 /* XXX assumes hlpimage fits in a block */ 1040 /* NB: zero size block indicates download is finished */ 1041 if (!mwlSendBlock(sc, fwboot_size, fwboot, fwboot_size) || 1042 !mwlSendBlock(sc, 0, NULL, 0)) { 1043 err = ETIMEDOUT; 1044 goto bad; 1045 } 1046 DELAY(200 * FW_CHECK_USECS); 1047 if (sc->sc_SDRAMSIZE_Addr != 0) { 1048 /* Set up sdram controller for superflyv2 */ 1049 mwlPokeSdramController(sc, sc->sc_SDRAMSIZE_Addr); 1050 } 1051 nbytes = ntries = 0; /* NB: silence compiler */ 1052 for (fp = fw, ep = fp + fw_size; fp < ep; ) { 1053 mwl_ctl_write4(sc, MACREG_REG_INT_CODE, 0); 1054 blocksize = mwl_ctl_read4(sc, MACREG_REG_SCRATCH); 1055 if (blocksize == 0) /* download complete */ 1056 break; 1057 if (blocksize > 0x00000c00) { 1058 err = EINVAL; 1059 goto bad; 1060 } 1061 if ((blocksize & 0x1) == 0) { 1062 /* block successfully downloaded, advance */ 1063 fp += nbytes; 1064 ntries = 0; 1065 } else { 1066 if (++ntries > 2) { 1067 /* 1068 * Guard against f/w telling us to 1069 * retry infinitely. 1070 */ 1071 err = ELOOP; 1072 goto bad; 1073 } 1074 /* clear NAK bit/flag */ 1075 blocksize &= ~0x1; 1076 } 1077 if (blocksize > _PTRDIFF(ep, fp)) { 1078 /* XXX this should not happen, what to do? */ 1079 blocksize = _PTRDIFF(ep, fp); 1080 } 1081 nbytes = blocksize; 1082 if (!mwlSendBlock2(sc, fp, nbytes)) { 1083 err = ETIMEDOUT; 1084 goto bad; 1085 } 1086 } 1087 } else { 1088 for (fp = fw, ep = fp + fw_size; fp < ep; ) { 1089 nbytes = _PTRDIFF(ep, fp); 1090 if (nbytes > FW_DOWNLOAD_BLOCK_SIZE) 1091 nbytes = FW_DOWNLOAD_BLOCK_SIZE; 1092 if (!mwlSendBlock(sc, FW_DOWNLOAD_BLOCK_SIZE, fp, 1093 nbytes)) { 1094 err = EIO; 1095 goto bad; 1096 } 1097 fp += nbytes; 1098 } 1099 } 1100 1101 /* 1102 * Wait for firmware to startup; we monitor the 1103 * INT_CODE register waiting for a signature to 1104 * written back indicating it's ready to go. 1105 */ 1106 sc->sc_cmd_mem[1] = 0; 1107 /* 1108 * XXX WAR for mfg fw download 1109 */ 1110 if (OpMode != HostCmd_STA_MODE) 1111 mwlTriggerPciCmd(sc); 1112 for (i = 0; i < FW_MAX_NUM_CHECKS; i++) { 1113 mwl_ctl_write4(sc, MACREG_REG_GEN_PTR, OpMode); 1114 DELAY(FW_CHECK_USECS); 1115 if (mwl_ctl_read4(sc, MACREG_REG_INT_CODE) == 1116 FwReadySignature) { 1117 mwl_ctl_write4(sc, MACREG_REG_INT_CODE, 0x00); 1118 return (mwlResetHalState(sc)); 1119 } 1120 } 1121 MWL_DBG(MWL_DBG_FW, "mwl: mwl_fwload(): " 1122 "firmware download timeout\n"); 1123 return (ETIMEDOUT); 1124 bad: 1125 mwlFwReset(sc); 1126 bad2: 1127 if (fw != NULL) 1128 kmem_free(fw, fw_size); 1129 if (fwboot != NULL) 1130 kmem_free(fwboot, fwboot_size); 1131 fwboot = fw = NULL; 1132 fwboot_index = fw_index = NULL; 1133 if (modfw != NULL) 1134 (void) ddi_modclose(modfw); 1135 return (err); 1136 } 1137 1138 /* 1139 * Low level firmware cmd block handshake support. 1140 */ 1141 static void 1142 mwlSendCmd(struct mwl_softc *sc) 1143 { 1144 (void) ddi_dma_sync(sc->sc_cmd_dma.dma_hdl, 1145 0, 1146 sc->sc_cmd_dma.alength, 1147 DDI_DMA_SYNC_FORDEV); 1148 1149 mwl_ctl_write4(sc, MACREG_REG_GEN_PTR, sc->sc_cmd_dmaaddr); 1150 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 1151 1152 mwl_ctl_write4(sc, MACREG_REG_H2A_INTERRUPT_EVENTS, 1153 MACREG_H2ARIC_BIT_DOOR_BELL); 1154 } 1155 1156 static int 1157 mwlExecuteCmd(struct mwl_softc *sc, unsigned short cmd) 1158 { 1159 if (mwl_ctl_read4(sc, MACREG_REG_INT_CODE) == 0xffffffff) { 1160 MWL_DBG(MWL_DBG_CMD, "mwl: mwlExecuteCmd(): " 1161 "device not present!\n"); 1162 return (EIO); 1163 } 1164 mwlSendCmd(sc); 1165 if (!mwlWaitForCmdComplete(sc, 0x8000 | cmd)) { 1166 MWL_DBG(MWL_DBG_CMD, "mwl: mwlExecuteCmd(): " 1167 "timeout waiting for f/w cmd %s\n", mwlcmdname(cmd)); 1168 return (ETIMEDOUT); 1169 } 1170 (void) ddi_dma_sync(sc->sc_cmd_dma.dma_hdl, 1171 0, 1172 sc->sc_cmd_dma.alength, 1173 DDI_DMA_SYNC_FORDEV); 1174 1175 MWL_DBG(MWL_DBG_CMD, "mwl: mwlExecuteCmd(): " 1176 "send cmd %s\n", mwlcmdname(cmd)); 1177 1178 if (mwl_dbg_flags & MWL_DBG_CMD) 1179 dumpresult(sc, 1); 1180 1181 return (0); 1182 } 1183 1184 static int 1185 mwlWaitForCmdComplete(struct mwl_softc *sc, uint16_t cmdCode) 1186 { 1187 #define MAX_WAIT_FW_COMPLETE_ITERATIONS 10000 1188 int i; 1189 1190 for (i = 0; i < MAX_WAIT_FW_COMPLETE_ITERATIONS; i++) { 1191 if (sc->sc_cmd_mem[0] == LE_16(cmdCode)) 1192 return (1); 1193 DELAY(1 * 1000); 1194 } 1195 return (0); 1196 #undef MAX_WAIT_FW_COMPLETE_ITERATIONS 1197 } 1198 1199 static const char * 1200 mwlcmdname(int cmd) 1201 { 1202 static char buf[12]; 1203 #define CMD(x) case HostCmd_CMD_##x: return #x 1204 switch (cmd) { 1205 CMD(CODE_DNLD); 1206 CMD(GET_HW_SPEC); 1207 CMD(SET_HW_SPEC); 1208 CMD(MAC_MULTICAST_ADR); 1209 CMD(802_11_GET_STAT); 1210 CMD(MAC_REG_ACCESS); 1211 CMD(BBP_REG_ACCESS); 1212 CMD(RF_REG_ACCESS); 1213 CMD(802_11_RADIO_CONTROL); 1214 CMD(802_11_RF_TX_POWER); 1215 CMD(802_11_RF_ANTENNA); 1216 CMD(SET_BEACON); 1217 CMD(SET_RF_CHANNEL); 1218 CMD(SET_AID); 1219 CMD(SET_INFRA_MODE); 1220 CMD(SET_G_PROTECT_FLAG); 1221 CMD(802_11_RTS_THSD); 1222 CMD(802_11_SET_SLOT); 1223 CMD(SET_EDCA_PARAMS); 1224 CMD(802_11H_DETECT_RADAR); 1225 CMD(SET_WMM_MODE); 1226 CMD(HT_GUARD_INTERVAL); 1227 CMD(SET_FIXED_RATE); 1228 CMD(SET_LINKADAPT_CS_MODE); 1229 CMD(SET_MAC_ADDR); 1230 CMD(SET_RATE_ADAPT_MODE); 1231 CMD(BSS_START); 1232 CMD(SET_NEW_STN); 1233 CMD(SET_KEEP_ALIVE); 1234 CMD(SET_APMODE); 1235 CMD(SET_SWITCH_CHANNEL); 1236 CMD(UPDATE_ENCRYPTION); 1237 CMD(BASTREAM); 1238 CMD(SET_RIFS); 1239 CMD(SET_N_PROTECT_FLAG); 1240 CMD(SET_N_PROTECT_OPMODE); 1241 CMD(SET_OPTIMIZATION_LEVEL); 1242 CMD(GET_CALTABLE); 1243 CMD(SET_MIMOPSHT); 1244 CMD(GET_BEACON); 1245 CMD(SET_REGION_CODE); 1246 CMD(SET_POWERSAVESTATION); 1247 CMD(SET_TIM); 1248 CMD(GET_TIM); 1249 CMD(GET_SEQNO); 1250 CMD(DWDS_ENABLE); 1251 CMD(AMPDU_RETRY_RATEDROP_MODE); 1252 CMD(CFEND_ENABLE); 1253 } 1254 (void) snprintf(buf, sizeof (buf), "0x%x", cmd); 1255 return (buf); 1256 #undef CMD 1257 } 1258 1259 static void 1260 dumpresult(struct mwl_softc *sc, int showresult) 1261 { 1262 const FWCmdHdr *h = (const FWCmdHdr *)sc->sc_cmd_mem; 1263 int len; 1264 1265 len = LE_16(h->Length); 1266 #ifdef MWL_MBSS_SUPPORT 1267 MWL_DBG(MWL_DBG_CMD, "mwl: mwl_dumpresult(): " 1268 "Cmd %s Length %d SeqNum %d MacId %d", 1269 mwlcmdname(LE_16(h->Cmd) & ~0x8000), len, h->SeqNum, h->MacId); 1270 #else 1271 MWL_DBG(MWL_DBG_CMD, "mwl: mwl_dumpresult(): " 1272 "Cmd %s Length %d SeqNum %d", 1273 mwlcmdname(LE_16(h->Cmd) & ~0x8000), len, LE_16(h->SeqNum)); 1274 #endif 1275 if (showresult) { 1276 const char *results[] = 1277 { "OK", "ERROR", "NOT_SUPPORT", "PENDING", "BUSY", 1278 "PARTIAL_DATA" }; 1279 int result = LE_16(h->Result); 1280 1281 if (result <= HostCmd_RESULT_PARTIAL_DATA) 1282 MWL_DBG(MWL_DBG_CMD, "mwl: dumpresult(): " 1283 "Result %s", results[result]); 1284 else 1285 MWL_DBG(MWL_DBG_CMD, "mwl: dumpresult(): " 1286 "Result %d", result); 1287 } 1288 } 1289 1290 static int 1291 mwlGetCalTable(struct mwl_softc *sc, uint8_t annex, uint8_t index) 1292 { 1293 HostCmd_FW_GET_CALTABLE *pCmd; 1294 int retval; 1295 1296 _CMD_SETUP(pCmd, HostCmd_FW_GET_CALTABLE, HostCmd_CMD_GET_CALTABLE); 1297 pCmd->annex = annex; 1298 pCmd->index = index; 1299 (void) memset(pCmd->calTbl, 0, sizeof (pCmd->calTbl)); 1300 1301 retval = mwlExecuteCmd(sc, HostCmd_CMD_GET_CALTABLE); 1302 if (retval == 0 && 1303 pCmd->calTbl[0] != annex && annex != 0 && annex != 255) 1304 retval = EIO; 1305 return (retval); 1306 } 1307 1308 /* 1309 * Construct channel info for 2.4GHz channels from cal data. 1310 */ 1311 static void 1312 get2Ghz(MWL_HAL_CHANNELINFO *ci, const uint8_t table[], int len) 1313 { 1314 int i, j; 1315 1316 j = 0; 1317 for (i = 0; i < len; i += 4) { 1318 struct mwl_hal_channel *hc = &ci->channels[j]; 1319 hc->ieee = 1+j; 1320 hc->freq = ieee2mhz(1+j); 1321 (void) memcpy(hc->targetPowers, &table[i], 4); 1322 setmaxtxpow(hc, 0, 4); 1323 j++; 1324 } 1325 ci->nchannels = j; 1326 ci->freqLow = ieee2mhz(1); 1327 ci->freqHigh = ieee2mhz(j); 1328 } 1329 1330 /* 1331 * Construct channel info for 5GHz channels from cal data. 1332 */ 1333 static void 1334 get5Ghz(MWL_HAL_CHANNELINFO *ci, const uint8_t table[], int len) 1335 { 1336 int i, j, f, l, h; 1337 1338 l = 32000; 1339 h = 0; 1340 j = 0; 1341 for (i = 0; i < len; i += 4) { 1342 struct mwl_hal_channel *hc; 1343 1344 if (table[i] == 0) 1345 continue; 1346 f = 5000 + 5*table[i]; 1347 if (f < l) 1348 l = f; 1349 if (f > h) 1350 h = f; 1351 hc = &ci->channels[j]; 1352 hc->freq = (uint16_t)f; 1353 hc->ieee = table[i]; 1354 (void) memcpy(hc->targetPowers, &table[i], 4); 1355 setmaxtxpow(hc, 1, 4); /* NB: col 1 is the freq, skip */ 1356 j++; 1357 } 1358 ci->nchannels = j; 1359 ci->freqLow = (uint16_t)((l == 32000) ? 0 : l); 1360 ci->freqHigh = (uint16_t)h; 1361 } 1362 1363 /* 1364 * Calculate the max tx power from the channel's cal data. 1365 */ 1366 static void 1367 setmaxtxpow(struct mwl_hal_channel *hc, int i, int maxix) 1368 { 1369 hc->maxTxPow = hc->targetPowers[i]; 1370 for (i++; i < maxix; i++) 1371 if (hc->targetPowers[i] > hc->maxTxPow) 1372 hc->maxTxPow = hc->targetPowers[i]; 1373 } 1374 1375 static uint16_t 1376 ieee2mhz(int chan) 1377 { 1378 if (chan == 14) 1379 return (2484); 1380 if (chan < 14) 1381 return (2407 + chan * 5); 1382 return (2512 + (chan - 15) * 20); 1383 } 1384 1385 static void 1386 dumpcaldata(const char *name, const uint8_t *table, int n) 1387 { 1388 int i; 1389 MWL_DBG(MWL_DBG_HW, "\n%s:\n", name); 1390 for (i = 0; i < n; i += 4) 1391 MWL_DBG(MWL_DBG_HW, "[%2d] %3d %3d %3d %3d\n", 1392 i/4, table[i+0], table[i+1], table[i+2], table[i+3]); 1393 } 1394 1395 static int 1396 mwlGetPwrCalTable(struct mwl_softc *sc) 1397 { 1398 const uint8_t *data; 1399 MWL_HAL_CHANNELINFO *ci; 1400 int len; 1401 1402 /* NB: we hold the lock so it's ok to use cmdbuf */ 1403 data = ((const HostCmd_FW_GET_CALTABLE *) sc->sc_cmd_mem)->calTbl; 1404 if (mwlGetCalTable(sc, 33, 0) == 0) { 1405 len = (data[2] | (data[3] << 8)) - 12; 1406 if (len > PWTAGETRATETABLE20M) 1407 len = PWTAGETRATETABLE20M; 1408 dumpcaldata("2.4G 20M", &data[12], len); 1409 get2Ghz(&sc->sc_20M, &data[12], len); 1410 } 1411 if (mwlGetCalTable(sc, 34, 0) == 0) { 1412 len = (data[2] | (data[3] << 8)) - 12; 1413 if (len > PWTAGETRATETABLE40M) 1414 len = PWTAGETRATETABLE40M; 1415 dumpcaldata("2.4G 40M", &data[12], len); 1416 ci = &sc->sc_40M; 1417 get2Ghz(ci, &data[12], len); 1418 } 1419 if (mwlGetCalTable(sc, 35, 0) == 0) { 1420 len = (data[2] | (data[3] << 8)) - 20; 1421 if (len > PWTAGETRATETABLE20M_5G) 1422 len = PWTAGETRATETABLE20M_5G; 1423 dumpcaldata("5G 20M", &data[20], len); 1424 get5Ghz(&sc->sc_20M_5G, &data[20], len); 1425 } 1426 if (mwlGetCalTable(sc, 36, 0) == 0) { 1427 len = (data[2] | (data[3] << 8)) - 20; 1428 if (len > PWTAGETRATETABLE40M_5G) 1429 len = PWTAGETRATETABLE40M_5G; 1430 dumpcaldata("5G 40M", &data[20], len); 1431 ci = &sc->sc_40M_5G; 1432 get5Ghz(ci, &data[20], len); 1433 } 1434 sc->sc_hw_flags |= MHF_CALDATA; 1435 return (0); 1436 } 1437 1438 /* 1439 * Reset internal state after a firmware download. 1440 */ 1441 static int 1442 mwlResetHalState(struct mwl_softc *sc) 1443 { 1444 int err = 0; 1445 1446 /* 1447 * Fetch cal data for later use. 1448 * XXX may want to fetch other stuff too. 1449 */ 1450 /* XXX check return */ 1451 if ((sc->sc_hw_flags & MHF_CALDATA) == 0) 1452 err = mwlGetPwrCalTable(sc); 1453 return (err); 1454 } 1455 1456 #define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT|IEEE80211_CHAN_G) 1457 #define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT|IEEE80211_CHAN_A) 1458 1459 static void 1460 addchan(struct mwl_channel *c, int freq, int flags, int ieee, int txpow) 1461 { 1462 c->ic_freq = (uint16_t)freq; 1463 c->ic_flags = flags; 1464 c->ic_ieee = (uint8_t)ieee; 1465 c->ic_minpower = 0; 1466 c->ic_maxpower = 2*txpow; 1467 c->ic_maxregpower = (uint8_t)txpow; 1468 } 1469 1470 static const struct mwl_channel * 1471 findchannel(const struct mwl_channel chans[], int nchans, 1472 int freq, int flags) 1473 { 1474 const struct mwl_channel *c; 1475 int i; 1476 1477 for (i = 0; i < nchans; i++) { 1478 c = &chans[i]; 1479 if (c->ic_freq == freq && c->ic_flags == flags) 1480 return (c); 1481 } 1482 return (NULL); 1483 } 1484 1485 static void 1486 addht40channels(struct mwl_channel chans[], int maxchans, int *nchans, 1487 const MWL_HAL_CHANNELINFO *ci, int flags) 1488 { 1489 struct mwl_channel *c; 1490 const struct mwl_channel *extc; 1491 const struct mwl_hal_channel *hc; 1492 int i; 1493 1494 c = &chans[*nchans]; 1495 1496 flags &= ~IEEE80211_CHAN_HT; 1497 for (i = 0; i < ci->nchannels; i++) { 1498 /* 1499 * Each entry defines an HT40 channel pair; find the 1500 * extension channel above and the insert the pair. 1501 */ 1502 hc = &ci->channels[i]; 1503 extc = findchannel(chans, *nchans, hc->freq+20, 1504 flags | IEEE80211_CHAN_HT20); 1505 if (extc != NULL) { 1506 if (*nchans >= maxchans) 1507 break; 1508 addchan(c, hc->freq, flags | IEEE80211_CHAN_HT40U, 1509 hc->ieee, hc->maxTxPow); 1510 c->ic_extieee = extc->ic_ieee; 1511 c++, (*nchans)++; 1512 if (*nchans >= maxchans) 1513 break; 1514 addchan(c, extc->ic_freq, flags | IEEE80211_CHAN_HT40D, 1515 extc->ic_ieee, hc->maxTxPow); 1516 c->ic_extieee = hc->ieee; 1517 c++, (*nchans)++; 1518 } 1519 } 1520 } 1521 1522 static void 1523 addchannels(struct mwl_channel chans[], int maxchans, int *nchans, 1524 const MWL_HAL_CHANNELINFO *ci, int flags) 1525 { 1526 struct mwl_channel *c; 1527 int i; 1528 1529 c = &chans[*nchans]; 1530 1531 for (i = 0; i < ci->nchannels; i++) { 1532 const struct mwl_hal_channel *hc; 1533 1534 hc = &ci->channels[i]; 1535 if (*nchans >= maxchans) 1536 break; 1537 addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow); 1538 c++, (*nchans)++; 1539 1540 if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) { 1541 /* g channel have a separate b-only entry */ 1542 if (*nchans >= maxchans) 1543 break; 1544 c[0] = c[-1]; 1545 c[-1].ic_flags = IEEE80211_CHAN_B; 1546 c++, (*nchans)++; 1547 } 1548 if (flags == IEEE80211_CHAN_HTG) { 1549 /* HT g channel have a separate g-only entry */ 1550 if (*nchans >= maxchans) 1551 break; 1552 c[-1].ic_flags = IEEE80211_CHAN_G; 1553 c[0] = c[-1]; 1554 c[0].ic_flags &= ~IEEE80211_CHAN_HT; 1555 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ 1556 c++, (*nchans)++; 1557 } 1558 if (flags == IEEE80211_CHAN_HTA) { 1559 /* HT a channel have a separate a-only entry */ 1560 if (*nchans >= maxchans) 1561 break; 1562 c[-1].ic_flags = IEEE80211_CHAN_A; 1563 c[0] = c[-1]; 1564 c[0].ic_flags &= ~IEEE80211_CHAN_HT; 1565 c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ 1566 c++, (*nchans)++; 1567 } 1568 } 1569 } 1570 1571 static int 1572 mwl_hal_getchannelinfo(struct mwl_softc *sc, int band, int chw, 1573 const MWL_HAL_CHANNELINFO **ci) 1574 { 1575 switch (band) { 1576 case MWL_FREQ_BAND_2DOT4GHZ: 1577 *ci = (chw == MWL_CH_20_MHz_WIDTH) ? &sc->sc_20M : &sc->sc_40M; 1578 break; 1579 case MWL_FREQ_BAND_5GHZ: 1580 *ci = (chw == MWL_CH_20_MHz_WIDTH) ? 1581 &sc->sc_20M_5G : &sc->sc_40M_5G; 1582 break; 1583 default: 1584 return (EINVAL); 1585 } 1586 return (((*ci)->freqLow == (*ci)->freqHigh) ? EINVAL : 0); 1587 } 1588 1589 static void 1590 getchannels(struct mwl_softc *sc, int maxchans, int *nchans, 1591 struct mwl_channel chans[]) 1592 { 1593 const MWL_HAL_CHANNELINFO *ci; 1594 1595 /* 1596 * Use the channel info from the hal to craft the 1597 * channel list. Note that we pass back an unsorted 1598 * list; the caller is required to sort it for us 1599 * (if desired). 1600 */ 1601 *nchans = 0; 1602 if (mwl_hal_getchannelinfo(sc, 1603 MWL_FREQ_BAND_2DOT4GHZ, MWL_CH_20_MHz_WIDTH, &ci) == 0) 1604 addchannels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTG); 1605 if (mwl_hal_getchannelinfo(sc, 1606 MWL_FREQ_BAND_5GHZ, MWL_CH_20_MHz_WIDTH, &ci) == 0) 1607 addchannels(chans, maxchans, nchans, ci, IEEE80211_CHAN_HTA); 1608 if (mwl_hal_getchannelinfo(sc, 1609 MWL_FREQ_BAND_2DOT4GHZ, MWL_CH_40_MHz_WIDTH, &ci) == 0) 1610 addht40channels(chans, maxchans, nchans, ci, 1611 IEEE80211_CHAN_HTG); 1612 if (mwl_hal_getchannelinfo(sc, 1613 MWL_FREQ_BAND_5GHZ, MWL_CH_40_MHz_WIDTH, &ci) == 0) 1614 addht40channels(chans, maxchans, nchans, ci, 1615 IEEE80211_CHAN_HTA); 1616 } 1617 1618 static int 1619 mwl_getchannels(struct mwl_softc *sc) 1620 { 1621 /* 1622 * Use the channel info from the hal to craft the 1623 * channel list for net80211. Note that we pass up 1624 * an unsorted list; net80211 will sort it for us. 1625 */ 1626 (void) memset(sc->sc_channels, 0, sizeof (sc->sc_channels)); 1627 sc->sc_nchans = 0; 1628 getchannels(sc, IEEE80211_CHAN_MAX, &sc->sc_nchans, sc->sc_channels); 1629 1630 sc->sc_regdomain.regdomain = SKU_DEBUG; 1631 sc->sc_regdomain.country = CTRY_DEFAULT; 1632 sc->sc_regdomain.location = 'I'; 1633 sc->sc_regdomain.isocc[0] = ' '; /* XXX? */ 1634 sc->sc_regdomain.isocc[1] = ' '; 1635 return (sc->sc_nchans == 0 ? EIO : 0); 1636 } 1637 1638 #undef IEEE80211_CHAN_HTA 1639 #undef IEEE80211_CHAN_HTG 1640 1641 /* 1642 * Return "hw specs". Note this must be the first 1643 * cmd MUST be done after a firmware download or the 1644 * f/w will lockup. 1645 * XXX move into the hal so driver doesn't need to be responsible 1646 */ 1647 static int 1648 mwl_gethwspecs(struct mwl_softc *sc) 1649 { 1650 struct mwl_hal_hwspec *hw; 1651 HostCmd_DS_GET_HW_SPEC *pCmd; 1652 int retval; 1653 1654 hw = &sc->sc_hwspecs; 1655 _CMD_SETUP(pCmd, HostCmd_DS_GET_HW_SPEC, HostCmd_CMD_GET_HW_SPEC); 1656 (void) memset(&pCmd->PermanentAddr[0], 0xff, IEEE80211_ADDR_LEN); 1657 pCmd->ulFwAwakeCookie = LE_32((unsigned int)sc->sc_cmd_dmaaddr + 2048); 1658 1659 retval = mwlExecuteCmd(sc, HostCmd_CMD_GET_HW_SPEC); 1660 if (retval == 0) { 1661 IEEE80211_ADDR_COPY(hw->macAddr, pCmd->PermanentAddr); 1662 hw->wcbBase[0] = LE_32(pCmd->WcbBase0) & 0x0000ffff; 1663 hw->wcbBase[1] = LE_32(pCmd->WcbBase1[0]) & 0x0000ffff; 1664 hw->wcbBase[2] = LE_32(pCmd->WcbBase1[1]) & 0x0000ffff; 1665 hw->wcbBase[3] = LE_32(pCmd->WcbBase1[2]) & 0x0000ffff; 1666 hw->rxDescRead = LE_32(pCmd->RxPdRdPtr)& 0x0000ffff; 1667 hw->rxDescWrite = LE_32(pCmd->RxPdWrPtr)& 0x0000ffff; 1668 hw->regionCode = LE_16(pCmd->RegionCode) & 0x00ff; 1669 hw->fwReleaseNumber = LE_32(pCmd->FWReleaseNumber); 1670 hw->maxNumWCB = LE_16(pCmd->NumOfWCB); 1671 hw->maxNumMCAddr = LE_16(pCmd->NumOfMCastAddr); 1672 hw->numAntennas = LE_16(pCmd->NumberOfAntenna); 1673 hw->hwVersion = pCmd->Version; 1674 hw->hostInterface = pCmd->HostIf; 1675 1676 sc->sc_revs.mh_macRev = hw->hwVersion; /* XXX */ 1677 sc->sc_revs.mh_phyRev = hw->hostInterface; /* XXX */ 1678 } 1679 1680 return (retval); 1681 } 1682 1683 static int 1684 mwl_hal_setmac_locked(struct mwl_softc *sc, 1685 const uint8_t addr[IEEE80211_ADDR_LEN]) 1686 { 1687 HostCmd_DS_SET_MAC *pCmd; 1688 1689 _VCMD_SETUP(pCmd, HostCmd_DS_SET_MAC, HostCmd_CMD_SET_MAC_ADDR); 1690 IEEE80211_ADDR_COPY(&pCmd->MacAddr[0], addr); 1691 #ifdef MWL_MBSS_SUPPORT 1692 /* NB: already byte swapped */ 1693 pCmd->MacType = WL_MAC_TYPE_PRIMARY_CLIENT; 1694 #endif 1695 return (mwlExecuteCmd(sc, HostCmd_CMD_SET_MAC_ADDR)); 1696 } 1697 1698 static void 1699 cvtPeerInfo(PeerInfo_t *to, const MWL_HAL_PEERINFO *from) 1700 { 1701 to->LegacyRateBitMap = LE_32(from->LegacyRateBitMap); 1702 to->HTRateBitMap = LE_32(from->HTRateBitMap); 1703 to->CapInfo = LE_16(from->CapInfo); 1704 to->HTCapabilitiesInfo = LE_16(from->HTCapabilitiesInfo); 1705 to->MacHTParamInfo = from->MacHTParamInfo; 1706 to->AddHtInfo.ControlChan = from->AddHtInfo.ControlChan; 1707 to->AddHtInfo.AddChan = from->AddHtInfo.AddChan; 1708 to->AddHtInfo.OpMode = LE_16(from->AddHtInfo.OpMode); 1709 to->AddHtInfo.stbc = LE_16(from->AddHtInfo.stbc); 1710 } 1711 1712 /* XXX station id must be in [0..63] */ 1713 static int 1714 mwl_hal_newstation(struct mwl_softc *sc, 1715 const uint8_t addr[IEEE80211_ADDR_LEN], uint16_t aid, uint16_t sid, 1716 const MWL_HAL_PEERINFO *peer, int isQosSta, int wmeInfo) 1717 { 1718 HostCmd_FW_SET_NEW_STN *pCmd; 1719 int retval; 1720 1721 _VCMD_SETUP(pCmd, HostCmd_FW_SET_NEW_STN, HostCmd_CMD_SET_NEW_STN); 1722 pCmd->AID = LE_16(aid); 1723 pCmd->StnId = LE_16(sid); 1724 pCmd->Action = LE_16(0); /* SET */ 1725 if (peer != NULL) { 1726 /* NB: must fix up byte order */ 1727 cvtPeerInfo(&pCmd->PeerInfo, peer); 1728 } 1729 IEEE80211_ADDR_COPY(&pCmd->MacAddr[0], addr); 1730 pCmd->Qosinfo = (uint8_t)wmeInfo; 1731 pCmd->isQosSta = (isQosSta != 0); 1732 1733 MWL_DBG(MWL_DBG_HW, "mwl: mwl_hal_newstation(): " 1734 "LegacyRateBitMap %x, CapInfo %x\n", 1735 pCmd->PeerInfo.LegacyRateBitMap, pCmd->PeerInfo.CapInfo); 1736 1737 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_NEW_STN); 1738 return (retval); 1739 } 1740 1741 /* 1742 * Configure antenna use. 1743 * Takes effect immediately. 1744 * XXX tx antenna setting ignored 1745 * XXX rx antenna setting should always be 3 (for now) 1746 */ 1747 static int 1748 mwl_hal_setantenna(struct mwl_softc *sc, MWL_HAL_ANTENNA dirSet, int ant) 1749 { 1750 HostCmd_DS_802_11_RF_ANTENNA *pCmd; 1751 int retval; 1752 1753 if (!(dirSet == WL_ANTENNATYPE_RX || dirSet == WL_ANTENNATYPE_TX)) 1754 return (EINVAL); 1755 1756 _CMD_SETUP(pCmd, HostCmd_DS_802_11_RF_ANTENNA, 1757 HostCmd_CMD_802_11_RF_ANTENNA); 1758 pCmd->Action = LE_16(dirSet); 1759 if (ant == 0) /* default to all/both antennae */ 1760 ant = 3; 1761 pCmd->AntennaMode = LE_16(ant); 1762 1763 retval = mwlExecuteCmd(sc, HostCmd_CMD_802_11_RF_ANTENNA); 1764 return (retval); 1765 } 1766 1767 /* 1768 * Configure radio. 1769 * Takes effect immediately. 1770 * XXX preamble installed after set fixed rate cmd 1771 */ 1772 static int 1773 mwl_hal_setradio(struct mwl_softc *sc, int onoff, MWL_HAL_PREAMBLE preamble) 1774 { 1775 HostCmd_DS_802_11_RADIO_CONTROL *pCmd; 1776 int retval; 1777 1778 _CMD_SETUP(pCmd, HostCmd_DS_802_11_RADIO_CONTROL, 1779 HostCmd_CMD_802_11_RADIO_CONTROL); 1780 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET); 1781 if (onoff == 0) 1782 pCmd->Control = 0; 1783 else 1784 pCmd->Control = LE_16(preamble); 1785 pCmd->RadioOn = LE_16(onoff); 1786 1787 retval = mwlExecuteCmd(sc, HostCmd_CMD_802_11_RADIO_CONTROL); 1788 return (retval); 1789 } 1790 1791 static int 1792 mwl_hal_setwmm(struct mwl_softc *sc, int onoff) 1793 { 1794 HostCmd_FW_SetWMMMode *pCmd; 1795 int retval; 1796 1797 _CMD_SETUP(pCmd, HostCmd_FW_SetWMMMode, 1798 HostCmd_CMD_SET_WMM_MODE); 1799 pCmd->Action = LE_16(onoff); 1800 1801 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_WMM_MODE); 1802 return (retval); 1803 } 1804 1805 /* 1806 * Convert public channel flags definition to a 1807 * value suitable for feeding to the firmware. 1808 * Note this includes byte swapping. 1809 */ 1810 static uint32_t 1811 cvtChannelFlags(const MWL_HAL_CHANNEL *chan) 1812 { 1813 uint32_t w; 1814 1815 /* 1816 * NB: f/w only understands FREQ_BAND_5GHZ, supplying the more 1817 * precise band info causes it to lockup (sometimes). 1818 */ 1819 w = (chan->channelFlags.FreqBand == MWL_FREQ_BAND_2DOT4GHZ) ? 1820 FREQ_BAND_2DOT4GHZ : FREQ_BAND_5GHZ; 1821 switch (chan->channelFlags.ChnlWidth) { 1822 case MWL_CH_10_MHz_WIDTH: 1823 w |= CH_10_MHz_WIDTH; 1824 break; 1825 case MWL_CH_20_MHz_WIDTH: 1826 w |= CH_20_MHz_WIDTH; 1827 break; 1828 case MWL_CH_40_MHz_WIDTH: 1829 default: 1830 w |= CH_40_MHz_WIDTH; 1831 break; 1832 } 1833 switch (chan->channelFlags.ExtChnlOffset) { 1834 case MWL_EXT_CH_NONE: 1835 w |= EXT_CH_NONE; 1836 break; 1837 case MWL_EXT_CH_ABOVE_CTRL_CH: 1838 w |= EXT_CH_ABOVE_CTRL_CH; 1839 break; 1840 case MWL_EXT_CH_BELOW_CTRL_CH: 1841 w |= EXT_CH_BELOW_CTRL_CH; 1842 break; 1843 } 1844 return (LE_32(w)); 1845 } 1846 1847 static int 1848 mwl_hal_setchannel(struct mwl_softc *sc, const MWL_HAL_CHANNEL *chan) 1849 { 1850 HostCmd_FW_SET_RF_CHANNEL *pCmd; 1851 int retval; 1852 1853 _CMD_SETUP(pCmd, HostCmd_FW_SET_RF_CHANNEL, HostCmd_CMD_SET_RF_CHANNEL); 1854 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET); 1855 pCmd->CurrentChannel = chan->channel; 1856 pCmd->ChannelFlags = cvtChannelFlags(chan); /* NB: byte-swapped */ 1857 1858 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_RF_CHANNEL); 1859 return (retval); 1860 } 1861 1862 static int 1863 mwl_hal_settxpower(struct mwl_softc *sc, 1864 const MWL_HAL_CHANNEL *c, uint8_t maxtxpow) 1865 { 1866 HostCmd_DS_802_11_RF_TX_POWER *pCmd; 1867 const struct mwl_hal_channel *hc; 1868 int i = 0, retval; 1869 1870 hc = findhalchannel(sc, c); 1871 if (hc == NULL) { 1872 /* XXX temp while testing */ 1873 MWL_DBG(MWL_DBG_HW, "mwl: mwl_hal_settxpower(): " 1874 "no cal data for channel %u band %u width %u ext %u\n", 1875 c->channel, c->channelFlags.FreqBand, 1876 c->channelFlags.ChnlWidth, c->channelFlags.ExtChnlOffset); 1877 return (EINVAL); 1878 } 1879 1880 _CMD_SETUP(pCmd, HostCmd_DS_802_11_RF_TX_POWER, 1881 HostCmd_CMD_802_11_RF_TX_POWER); 1882 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET_LIST); 1883 /* NB: 5Ghz cal data have the channel # in [0]; don't truncate */ 1884 if (c->channelFlags.FreqBand == MWL_FREQ_BAND_5GHZ) 1885 pCmd->PowerLevelList[i++] = LE_16(hc->targetPowers[0]); 1886 for (; i < 4; i++) { 1887 uint16_t pow = hc->targetPowers[i]; 1888 if (pow > maxtxpow) 1889 pow = maxtxpow; 1890 pCmd->PowerLevelList[i] = LE_16(pow); 1891 } 1892 retval = mwlExecuteCmd(sc, HostCmd_CMD_802_11_RF_TX_POWER); 1893 return (retval); 1894 } 1895 1896 #define RATEVAL(r) ((r) &~ RATE_MCS) 1897 #define RATETYPE(r) (((r) & RATE_MCS) ? HT_RATE_TYPE : LEGACY_RATE_TYPE) 1898 1899 static int 1900 mwl_hal_settxrate(struct mwl_softc *sc, MWL_HAL_TXRATE_HANDLING handling, 1901 const MWL_HAL_TXRATE *rate) 1902 { 1903 HostCmd_FW_USE_FIXED_RATE *pCmd; 1904 FIXED_RATE_ENTRY *fp; 1905 int retval, i, n; 1906 1907 _VCMD_SETUP(pCmd, HostCmd_FW_USE_FIXED_RATE, 1908 HostCmd_CMD_SET_FIXED_RATE); 1909 1910 pCmd->MulticastRate = RATEVAL(rate->McastRate); 1911 pCmd->MultiRateTxType = RATETYPE(rate->McastRate); 1912 /* NB: no rate type field */ 1913 pCmd->ManagementRate = RATEVAL(rate->MgtRate); 1914 (void) memset(pCmd->FixedRateTable, 0, sizeof (pCmd->FixedRateTable)); 1915 if (handling == RATE_FIXED) { 1916 pCmd->Action = LE_32(HostCmd_ACT_GEN_SET); 1917 pCmd->AllowRateDrop = LE_32(FIXED_RATE_WITHOUT_AUTORATE_DROP); 1918 fp = pCmd->FixedRateTable; 1919 fp->FixedRate = 1920 LE_32(RATEVAL(rate->RateSeries[0].Rate)); 1921 fp->FixRateTypeFlags.FixRateType = 1922 LE_32(RATETYPE(rate->RateSeries[0].Rate)); 1923 pCmd->EntryCount = LE_32(1); 1924 } else if (handling == RATE_FIXED_DROP) { 1925 pCmd->Action = LE_32(HostCmd_ACT_GEN_SET); 1926 pCmd->AllowRateDrop = LE_32(FIXED_RATE_WITH_AUTO_RATE_DROP); 1927 n = 0; 1928 fp = pCmd->FixedRateTable; 1929 for (i = 0; i < 4; i++) { 1930 if (rate->RateSeries[0].TryCount == 0) 1931 break; 1932 fp->FixRateTypeFlags.FixRateType = 1933 LE_32(RATETYPE(rate->RateSeries[i].Rate)); 1934 fp->FixedRate = 1935 LE_32(RATEVAL(rate->RateSeries[i].Rate)); 1936 fp->FixRateTypeFlags.RetryCountValid = 1937 LE_32(RETRY_COUNT_VALID); 1938 fp->RetryCount = 1939 LE_32(rate->RateSeries[i].TryCount-1); 1940 n++; 1941 } 1942 pCmd->EntryCount = LE_32(n); 1943 } else 1944 pCmd->Action = LE_32(HostCmd_ACT_NOT_USE_FIXED_RATE); 1945 1946 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_FIXED_RATE); 1947 return (retval); 1948 } 1949 1950 static int 1951 mwl_hal_settxrate_auto(struct mwl_softc *sc, const MWL_HAL_TXRATE *rate) 1952 { 1953 HostCmd_FW_USE_FIXED_RATE *pCmd; 1954 int retval; 1955 1956 _CMD_SETUP(pCmd, HostCmd_FW_USE_FIXED_RATE, 1957 HostCmd_CMD_SET_FIXED_RATE); 1958 1959 pCmd->MulticastRate = RATEVAL(rate->McastRate); 1960 pCmd->MultiRateTxType = RATETYPE(rate->McastRate); 1961 /* NB: no rate type field */ 1962 pCmd->ManagementRate = RATEVAL(rate->MgtRate); 1963 (void) memset(pCmd->FixedRateTable, 0, sizeof (pCmd->FixedRateTable)); 1964 pCmd->Action = LE_32(HostCmd_ACT_NOT_USE_FIXED_RATE); 1965 1966 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_FIXED_RATE); 1967 return (retval); 1968 } 1969 1970 #undef RATEVAL 1971 #undef RATETYPE 1972 1973 /* XXX 0 = indoor, 1 = outdoor */ 1974 static int 1975 mwl_hal_setrateadaptmode(struct mwl_softc *sc, uint16_t mode) 1976 { 1977 HostCmd_DS_SET_RATE_ADAPT_MODE *pCmd; 1978 int retval; 1979 1980 _CMD_SETUP(pCmd, HostCmd_DS_SET_RATE_ADAPT_MODE, 1981 HostCmd_CMD_SET_RATE_ADAPT_MODE); 1982 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET); 1983 pCmd->RateAdaptMode = LE_16(mode); 1984 1985 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_RATE_ADAPT_MODE); 1986 return (retval); 1987 } 1988 1989 static int 1990 mwl_hal_setoptimizationlevel(struct mwl_softc *sc, int level) 1991 { 1992 HostCmd_FW_SET_OPTIMIZATION_LEVEL *pCmd; 1993 int retval; 1994 1995 _CMD_SETUP(pCmd, HostCmd_FW_SET_OPTIMIZATION_LEVEL, 1996 HostCmd_CMD_SET_OPTIMIZATION_LEVEL); 1997 pCmd->OptLevel = (uint8_t)level; 1998 1999 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_OPTIMIZATION_LEVEL); 2000 return (retval); 2001 } 2002 2003 /* 2004 * Set the region code that selects the radar bin'ing agorithm. 2005 */ 2006 static int 2007 mwl_hal_setregioncode(struct mwl_softc *sc, int regionCode) 2008 { 2009 HostCmd_SET_REGIONCODE_INFO *pCmd; 2010 int retval; 2011 2012 _CMD_SETUP(pCmd, HostCmd_SET_REGIONCODE_INFO, 2013 HostCmd_CMD_SET_REGION_CODE); 2014 /* XXX map pseudo-codes to fw codes */ 2015 switch (regionCode) { 2016 case DOMAIN_CODE_ETSI_131: 2017 pCmd->regionCode = LE_16(DOMAIN_CODE_ETSI); 2018 break; 2019 default: 2020 pCmd->regionCode = LE_16(regionCode); 2021 break; 2022 } 2023 2024 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_REGION_CODE); 2025 return (retval); 2026 } 2027 2028 static int 2029 mwl_hal_setassocid(struct mwl_softc *sc, 2030 const uint8_t bssId[IEEE80211_ADDR_LEN], uint16_t assocId) 2031 { 2032 HostCmd_FW_SET_AID *pCmd = (HostCmd_FW_SET_AID *) &sc->sc_cmd_mem[0]; 2033 int retval; 2034 2035 _VCMD_SETUP(pCmd, HostCmd_FW_SET_AID, HostCmd_CMD_SET_AID); 2036 pCmd->AssocID = LE_16(assocId); 2037 IEEE80211_ADDR_COPY(&pCmd->MacAddr[0], bssId); 2038 2039 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_AID); 2040 return (retval); 2041 } 2042 2043 /* 2044 * Inform firmware of tx rate parameters. Called whenever 2045 * user-settable params change and after a channel change. 2046 */ 2047 static int 2048 mwl_setrates(struct ieee80211com *ic) 2049 { 2050 struct mwl_softc *sc = (struct mwl_softc *)ic; 2051 MWL_HAL_TXRATE rates; 2052 2053 const struct ieee80211_rateset *rs; 2054 rs = &ic->ic_bss->in_rates; 2055 2056 /* 2057 * Update the h/w rate map. 2058 * NB: 0x80 for MCS is passed through unchanged 2059 */ 2060 (void) memset(&rates, 0, sizeof (rates)); 2061 /* rate used to send management frames */ 2062 rates.MgtRate = rs->ir_rates[0] & IEEE80211_RATE_VAL; 2063 /* rate used to send multicast frames */ 2064 rates.McastRate = rates.MgtRate; 2065 2066 return (mwl_hal_settxrate(sc, RATE_AUTO, &rates)); 2067 } 2068 2069 /* 2070 * Set packet size threshold for implicit use of RTS. 2071 * Takes effect immediately. 2072 * XXX packet length > threshold =>'s RTS 2073 */ 2074 static int 2075 mwl_hal_setrtsthreshold(struct mwl_softc *sc, int threshold) 2076 { 2077 HostCmd_DS_802_11_RTS_THSD *pCmd; 2078 int retval; 2079 2080 _VCMD_SETUP(pCmd, HostCmd_DS_802_11_RTS_THSD, 2081 HostCmd_CMD_802_11_RTS_THSD); 2082 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET); 2083 pCmd->Threshold = LE_16(threshold); 2084 2085 retval = mwlExecuteCmd(sc, HostCmd_CMD_802_11_RTS_THSD); 2086 return (retval); 2087 } 2088 2089 static int 2090 mwl_hal_setcsmode(struct mwl_softc *sc, MWL_HAL_CSMODE csmode) 2091 { 2092 HostCmd_DS_SET_LINKADAPT_CS_MODE *pCmd; 2093 int retval; 2094 2095 _CMD_SETUP(pCmd, HostCmd_DS_SET_LINKADAPT_CS_MODE, 2096 HostCmd_CMD_SET_LINKADAPT_CS_MODE); 2097 pCmd->Action = LE_16(HostCmd_ACT_GEN_SET); 2098 pCmd->CSMode = LE_16(csmode); 2099 2100 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_LINKADAPT_CS_MODE); 2101 return (retval); 2102 } 2103 2104 static int 2105 mwl_hal_setpromisc(struct mwl_softc *sc, int ena) 2106 { 2107 uint32_t v; 2108 2109 v = mwl_ctl_read4(sc, MACREG_REG_PROMISCUOUS); 2110 mwl_ctl_write4(sc, MACREG_REG_PROMISCUOUS, ena ? v | 1 : v & ~1); 2111 2112 return (0); 2113 } 2114 2115 static int 2116 mwl_hal_start(struct mwl_softc *sc) 2117 { 2118 HostCmd_DS_BSS_START *pCmd; 2119 int retval; 2120 2121 _VCMD_SETUP(pCmd, HostCmd_DS_BSS_START, HostCmd_CMD_BSS_START); 2122 pCmd->Enable = LE_32(HostCmd_ACT_GEN_ON); 2123 2124 retval = mwlExecuteCmd(sc, HostCmd_CMD_BSS_START); 2125 return (retval); 2126 } 2127 2128 /* 2129 * Enable sta-mode operation (disables beacon frame xmit). 2130 */ 2131 static int 2132 mwl_hal_setinframode(struct mwl_softc *sc) 2133 { 2134 HostCmd_FW_SET_INFRA_MODE *pCmd; 2135 int retval; 2136 2137 _VCMD_SETUP(pCmd, HostCmd_FW_SET_INFRA_MODE, 2138 HostCmd_CMD_SET_INFRA_MODE); 2139 2140 retval = mwlExecuteCmd(sc, HostCmd_CMD_SET_INFRA_MODE); 2141 return (retval); 2142 } 2143 2144 static int 2145 mwl_hal_stop(struct mwl_softc *sc) 2146 { 2147 HostCmd_DS_BSS_START *pCmd; 2148 int retval; 2149 2150 _VCMD_SETUP(pCmd, HostCmd_DS_BSS_START, 2151 HostCmd_CMD_BSS_START); 2152 pCmd->Enable = LE_32(HostCmd_ACT_GEN_OFF); 2153 retval = mwlExecuteCmd(sc, HostCmd_CMD_BSS_START); 2154 2155 return (retval); 2156 } 2157 2158 static int 2159 mwl_hal_keyset(struct mwl_softc *sc, const MWL_HAL_KEYVAL *kv, 2160 const uint8_t mac[IEEE80211_ADDR_LEN]) 2161 { 2162 HostCmd_FW_UPDATE_ENCRYPTION_SET_KEY *pCmd; 2163 int retval; 2164 2165 _VCMD_SETUP(pCmd, HostCmd_FW_UPDATE_ENCRYPTION_SET_KEY, 2166 HostCmd_CMD_UPDATE_ENCRYPTION); 2167 if (kv->keyFlags & (KEY_FLAG_TXGROUPKEY|KEY_FLAG_RXGROUPKEY)) 2168 pCmd->ActionType = LE_32(EncrActionTypeSetGroupKey); 2169 else 2170 pCmd->ActionType = LE_32(EncrActionTypeSetKey); 2171 pCmd->KeyParam.Length = LE_16(sizeof (pCmd->KeyParam)); 2172 pCmd->KeyParam.KeyTypeId = LE_16(kv->keyTypeId); 2173 pCmd->KeyParam.KeyInfo = LE_32(kv->keyFlags); 2174 pCmd->KeyParam.KeyIndex = LE_32(kv->keyIndex); 2175 /* NB: includes TKIP MIC keys */ 2176 (void) memcpy(&pCmd->KeyParam.Key, &kv->key, kv->keyLen); 2177 switch (kv->keyTypeId) { 2178 case KEY_TYPE_ID_WEP: 2179 pCmd->KeyParam.KeyLen = LE_16(kv->keyLen); 2180 break; 2181 case KEY_TYPE_ID_TKIP: 2182 pCmd->KeyParam.KeyLen = LE_16(sizeof (TKIP_TYPE_KEY)); 2183 pCmd->KeyParam.Key.TkipKey.TkipRsc.low = 2184 LE_16(kv->key.tkip.rsc.low); 2185 pCmd->KeyParam.Key.TkipKey.TkipRsc.high = 2186 LE_32(kv->key.tkip.rsc.high); 2187 pCmd->KeyParam.Key.TkipKey.TkipTsc.low = 2188 LE_16(kv->key.tkip.tsc.low); 2189 pCmd->KeyParam.Key.TkipKey.TkipTsc.high = 2190 LE_32(kv->key.tkip.tsc.high); 2191 break; 2192 case KEY_TYPE_ID_AES: 2193 pCmd->KeyParam.KeyLen = LE_16(sizeof (AES_TYPE_KEY)); 2194 break; 2195 } 2196 #ifdef MWL_MBSS_SUPPORT 2197 IEEE80211_ADDR_COPY(pCmd->KeyParam.Macaddr, mac); 2198 #else 2199 IEEE80211_ADDR_COPY(pCmd->Macaddr, mac); 2200 #endif 2201 2202 retval = mwlExecuteCmd(sc, HostCmd_CMD_UPDATE_ENCRYPTION); 2203 return (retval); 2204 } 2205 2206 static int 2207 mwl_hal_keyreset(struct mwl_softc *sc, const MWL_HAL_KEYVAL *kv, 2208 const uint8_t mac[IEEE80211_ADDR_LEN]) 2209 { 2210 HostCmd_FW_UPDATE_ENCRYPTION_SET_KEY *pCmd; 2211 int retval; 2212 2213 _VCMD_SETUP(pCmd, HostCmd_FW_UPDATE_ENCRYPTION_SET_KEY, 2214 HostCmd_CMD_UPDATE_ENCRYPTION); 2215 pCmd->ActionType = LE_16(EncrActionTypeRemoveKey); 2216 pCmd->KeyParam.Length = LE_16(sizeof (pCmd->KeyParam)); 2217 pCmd->KeyParam.KeyTypeId = LE_16(kv->keyTypeId); 2218 pCmd->KeyParam.KeyInfo = LE_32(kv->keyFlags); 2219 pCmd->KeyParam.KeyIndex = LE_32(kv->keyIndex); 2220 #ifdef MWL_MBSS_SUPPORT 2221 IEEE80211_ADDR_COPY(pCmd->KeyParam.Macaddr, mac); 2222 #else 2223 IEEE80211_ADDR_COPY(pCmd->Macaddr, mac); 2224 #endif 2225 retval = mwlExecuteCmd(sc, HostCmd_CMD_UPDATE_ENCRYPTION); 2226 return (retval); 2227 } 2228 2229 /* ARGSUSED */ 2230 static struct ieee80211_node * 2231 mwl_node_alloc(struct ieee80211com *ic) 2232 { 2233 struct mwl_node *mn; 2234 2235 mn = kmem_zalloc(sizeof (struct mwl_node), KM_SLEEP); 2236 if (mn == NULL) { 2237 /* XXX stat+msg */ 2238 MWL_DBG(MWL_DBG_MSG, "mwl: mwl_node_alloc(): " 2239 "alloc node failed\n"); 2240 return (NULL); 2241 } 2242 return (&mn->mn_node); 2243 } 2244 2245 static void 2246 mwl_node_free(struct ieee80211_node *ni) 2247 { 2248 struct ieee80211com *ic = ni->in_ic; 2249 struct mwl_node *mn = MWL_NODE(ni); 2250 2251 if (mn->mn_staid != 0) { 2252 // mwl_hal_delstation(mn->mn_hvap, vap->iv_myaddr); 2253 // delstaid(sc, mn->mn_staid); 2254 mn->mn_staid = 0; 2255 } 2256 ic->ic_node_cleanup(ni); 2257 kmem_free(ni, sizeof (struct mwl_node)); 2258 } 2259 2260 /* 2261 * Allocate a key cache slot for a unicast key. The 2262 * firmware handles key allocation and every station is 2263 * guaranteed key space so we are always successful. 2264 */ 2265 static int 2266 mwl_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k, 2267 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 2268 { 2269 if (k->wk_keyix != IEEE80211_KEYIX_NONE || 2270 (k->wk_flags & IEEE80211_KEY_GROUP)) { 2271 if (!(&ic->ic_nw_keys[0] <= k && 2272 k < &ic->ic_nw_keys[IEEE80211_WEP_NKID])) { 2273 /* should not happen */ 2274 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_key_alloc(): " 2275 "bogus group key\n"); 2276 return (0); 2277 } 2278 /* give the caller what they requested */ 2279 *keyix = *rxkeyix = k - ic->ic_nw_keys; 2280 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_key_alloc(): " 2281 "alloc GROUP key keyix %x, rxkeyix %x\n", 2282 *keyix, *rxkeyix); 2283 } else { 2284 /* 2285 * Firmware handles key allocation. 2286 */ 2287 *keyix = *rxkeyix = 0; 2288 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_key_alloc(): " 2289 "reset key index in key allocation\n"); 2290 } 2291 2292 return (1); 2293 } 2294 2295 /* 2296 * Delete a key entry allocated by mwl_key_alloc. 2297 */ 2298 static int 2299 mwl_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k) 2300 { 2301 struct mwl_softc *sc = (struct mwl_softc *)ic; 2302 MWL_HAL_KEYVAL hk; 2303 const uint8_t bcastaddr[IEEE80211_ADDR_LEN] = 2304 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 2305 2306 (void) memset(&hk, 0, sizeof (hk)); 2307 hk.keyIndex = k->wk_keyix; 2308 switch (k->wk_cipher->ic_cipher) { 2309 case IEEE80211_CIPHER_WEP: 2310 hk.keyTypeId = KEY_TYPE_ID_WEP; 2311 break; 2312 case IEEE80211_CIPHER_TKIP: 2313 hk.keyTypeId = KEY_TYPE_ID_TKIP; 2314 break; 2315 case IEEE80211_CIPHER_AES_CCM: 2316 hk.keyTypeId = KEY_TYPE_ID_AES; 2317 break; 2318 default: 2319 /* XXX should not happen */ 2320 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_key_delete(): " 2321 "unknown cipher %d\n", k->wk_cipher->ic_cipher); 2322 return (0); 2323 } 2324 return (mwl_hal_keyreset(sc, &hk, bcastaddr) == 0); 2325 } 2326 2327 /* 2328 * Set the key cache contents for the specified key. Key cache 2329 * slot(s) must already have been allocated by mwl_key_alloc. 2330 */ 2331 /* ARGSUSED */ 2332 static int 2333 mwl_key_set(struct ieee80211com *ic, const struct ieee80211_key *k, 2334 const uint8_t mac[IEEE80211_ADDR_LEN]) 2335 { 2336 #define GRPXMIT (IEEE80211_KEY_XMIT | IEEE80211_KEY_GROUP) 2337 /* NB: static wep keys are marked GROUP+tx/rx; GTK will be tx or rx */ 2338 #define IEEE80211_IS_STATICKEY(k) \ 2339 (((k)->wk_flags & (GRPXMIT|IEEE80211_KEY_RECV)) == \ 2340 (GRPXMIT|IEEE80211_KEY_RECV)) 2341 struct mwl_softc *sc = (struct mwl_softc *)ic; 2342 const struct ieee80211_cipher *cip = k->wk_cipher; 2343 const uint8_t *macaddr; 2344 MWL_HAL_KEYVAL hk; 2345 2346 (void) memset(&hk, 0, sizeof (hk)); 2347 hk.keyIndex = k->wk_keyix; 2348 switch (cip->ic_cipher) { 2349 case IEEE80211_CIPHER_WEP: 2350 hk.keyTypeId = KEY_TYPE_ID_WEP; 2351 hk.keyLen = k->wk_keylen; 2352 if (k->wk_keyix == ic->ic_def_txkey) 2353 hk.keyFlags = KEY_FLAG_WEP_TXKEY; 2354 if (!IEEE80211_IS_STATICKEY(k)) { 2355 /* NB: WEP is never used for the PTK */ 2356 (void) addgroupflags(&hk, k); 2357 } 2358 break; 2359 case IEEE80211_CIPHER_TKIP: 2360 hk.keyTypeId = KEY_TYPE_ID_TKIP; 2361 hk.key.tkip.tsc.high = (uint32_t)(k->wk_keytsc >> 16); 2362 hk.key.tkip.tsc.low = (uint16_t)k->wk_keytsc; 2363 hk.keyFlags = KEY_FLAG_TSC_VALID | KEY_FLAG_MICKEY_VALID; 2364 hk.keyLen = k->wk_keylen + IEEE80211_MICBUF_SIZE; 2365 if (!addgroupflags(&hk, k)) 2366 hk.keyFlags |= KEY_FLAG_PAIRWISE; 2367 break; 2368 case IEEE80211_CIPHER_AES_CCM: 2369 hk.keyTypeId = KEY_TYPE_ID_AES; 2370 hk.keyLen = k->wk_keylen; 2371 if (!addgroupflags(&hk, k)) 2372 hk.keyFlags |= KEY_FLAG_PAIRWISE; 2373 break; 2374 default: 2375 /* XXX should not happen */ 2376 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_key_set(): " 2377 "unknown cipher %d\n", 2378 k->wk_cipher->ic_cipher); 2379 return (0); 2380 } 2381 /* 2382 * NB: tkip mic keys get copied here too; the layout 2383 * just happens to match that in ieee80211_key. 2384 */ 2385 (void) memcpy(hk.key.aes, k->wk_key, hk.keyLen); 2386 2387 /* 2388 * Locate address of sta db entry for writing key; 2389 * the convention unfortunately is somewhat different 2390 * than how net80211, hostapd, and wpa_supplicant think. 2391 */ 2392 2393 /* 2394 * NB: keys plumbed before the sta reaches AUTH state 2395 * will be discarded or written to the wrong sta db 2396 * entry because iv_bss is meaningless. This is ok 2397 * (right now) because we handle deferred plumbing of 2398 * WEP keys when the sta reaches AUTH state. 2399 */ 2400 macaddr = ic->ic_bss->in_bssid; 2401 if (k->wk_flags & IEEE80211_KEY_XMIT) { 2402 /* XXX plumb to local sta db too for static key wep */ 2403 (void) mwl_hal_keyset(sc, &hk, ic->ic_macaddr); 2404 } 2405 return (mwl_hal_keyset(sc, &hk, macaddr) == 0); 2406 #undef IEEE80211_IS_STATICKEY 2407 #undef GRPXMIT 2408 } 2409 2410 /* 2411 * Plumb any static WEP key for the station. This is 2412 * necessary as we must propagate the key from the 2413 * global key table of the vap to each sta db entry. 2414 */ 2415 static void 2416 mwl_setanywepkey(struct ieee80211com *ic, const uint8_t mac[IEEE80211_ADDR_LEN]) 2417 { 2418 if ((ic->ic_flags & (IEEE80211_F_PRIVACY|IEEE80211_F_WPA)) == 2419 IEEE80211_F_PRIVACY && 2420 ic->ic_def_txkey != IEEE80211_KEYIX_NONE && 2421 ic->ic_nw_keys[ic->ic_def_txkey].wk_keyix != IEEE80211_KEYIX_NONE) 2422 (void) mwl_key_set(ic, &ic->ic_nw_keys[ic->ic_def_txkey], mac); 2423 } 2424 2425 static void 2426 mwl_setglobalkeys(struct ieee80211com *ic) 2427 { 2428 struct ieee80211_key *wk; 2429 2430 wk = &ic->ic_nw_keys[0]; 2431 for (; wk < &ic->ic_nw_keys[IEEE80211_WEP_NKID]; wk++) 2432 if (wk->wk_keyix != IEEE80211_KEYIX_NONE) 2433 (void) mwl_key_set(ic, wk, ic->ic_macaddr); 2434 } 2435 2436 static int 2437 addgroupflags(MWL_HAL_KEYVAL *hk, const struct ieee80211_key *k) 2438 { 2439 if (k->wk_flags & IEEE80211_KEY_GROUP) { 2440 if (k->wk_flags & IEEE80211_KEY_XMIT) 2441 hk->keyFlags |= KEY_FLAG_TXGROUPKEY; 2442 if (k->wk_flags & IEEE80211_KEY_RECV) 2443 hk->keyFlags |= KEY_FLAG_RXGROUPKEY; 2444 return (1); 2445 } else 2446 return (0); 2447 } 2448 2449 /* 2450 * Set/change channels. 2451 */ 2452 static int 2453 mwl_chan_set(struct mwl_softc *sc, struct mwl_channel *chan) 2454 { 2455 MWL_HAL_CHANNEL hchan; 2456 int maxtxpow; 2457 2458 MWL_DBG(MWL_DBG_HW, "mwl: mwl_chan_set(): " 2459 "chan %u MHz/flags 0x%x\n", 2460 chan->ic_freq, chan->ic_flags); 2461 2462 /* 2463 * Convert to a HAL channel description with 2464 * the flags constrained to reflect the current 2465 * operating mode. 2466 */ 2467 mwl_mapchan(&hchan, chan); 2468 mwl_hal_intrset(sc, 0); /* disable interrupts */ 2469 2470 (void) mwl_hal_setchannel(sc, &hchan); 2471 /* 2472 * Tx power is cap'd by the regulatory setting and 2473 * possibly a user-set limit. We pass the min of 2474 * these to the hal to apply them to the cal data 2475 * for this channel. 2476 * XXX min bound? 2477 */ 2478 maxtxpow = 2 * chan->ic_maxregpower; 2479 if (maxtxpow > 100) 2480 maxtxpow = 100; 2481 (void) mwl_hal_settxpower(sc, &hchan, maxtxpow / 2); 2482 /* NB: potentially change mcast/mgt rates */ 2483 (void) mwl_setcurchanrates(sc); 2484 2485 sc->sc_curchan = hchan; 2486 mwl_hal_intrset(sc, sc->sc_imask); 2487 2488 return (0); 2489 } 2490 2491 /* 2492 * Convert net80211 channel to a HAL channel. 2493 */ 2494 static void 2495 mwl_mapchan(MWL_HAL_CHANNEL *hc, const struct mwl_channel *chan) 2496 { 2497 hc->channel = chan->ic_ieee; 2498 2499 *(uint32_t *)&hc->channelFlags = 0; 2500 if (((chan)->ic_flags & IEEE80211_CHAN_2GHZ) != 0) 2501 hc->channelFlags.FreqBand = MWL_FREQ_BAND_2DOT4GHZ; 2502 else if (((chan)->ic_flags & IEEE80211_CHAN_5GHZ) != 0) 2503 hc->channelFlags.FreqBand = MWL_FREQ_BAND_5GHZ; 2504 if (((chan)->ic_flags & IEEE80211_CHAN_HT40) != 0) { 2505 hc->channelFlags.ChnlWidth = MWL_CH_40_MHz_WIDTH; 2506 if (((chan)->ic_flags & IEEE80211_CHAN_HT40U) != 0) 2507 hc->channelFlags.ExtChnlOffset = 2508 MWL_EXT_CH_ABOVE_CTRL_CH; 2509 else 2510 hc->channelFlags.ExtChnlOffset = 2511 MWL_EXT_CH_BELOW_CTRL_CH; 2512 } else 2513 hc->channelFlags.ChnlWidth = MWL_CH_20_MHz_WIDTH; 2514 /* XXX 10MHz channels */ 2515 } 2516 2517 /* 2518 * Return the phy mode for with the specified channel. 2519 */ 2520 enum ieee80211_phymode 2521 mwl_chan2mode(const struct mwl_channel *chan) 2522 { 2523 2524 if (IEEE80211_IS_CHAN_HTA(chan)) 2525 return (IEEE80211_MODE_11NA); 2526 else if (IEEE80211_IS_CHAN_HTG(chan)) 2527 return (IEEE80211_MODE_11NG); 2528 else if (IEEE80211_IS_CHAN_108G(chan)) 2529 return (IEEE80211_MODE_TURBO_G); 2530 else if (IEEE80211_IS_CHAN_ST(chan)) 2531 return (IEEE80211_MODE_STURBO_A); 2532 else if (IEEE80211_IS_CHAN_TURBO(chan)) 2533 return (IEEE80211_MODE_TURBO_A); 2534 else if (IEEE80211_IS_CHAN_HALF(chan)) 2535 return (IEEE80211_MODE_HALF); 2536 else if (IEEE80211_IS_CHAN_QUARTER(chan)) 2537 return (IEEE80211_MODE_QUARTER); 2538 else if (IEEE80211_IS_CHAN_A(chan)) 2539 return (IEEE80211_MODE_11A); 2540 else if (IEEE80211_IS_CHAN_ANYG(chan)) 2541 return (IEEE80211_MODE_11G); 2542 else if (IEEE80211_IS_CHAN_B(chan)) 2543 return (IEEE80211_MODE_11B); 2544 else if (IEEE80211_IS_CHAN_FHSS(chan)) 2545 return (IEEE80211_MODE_FH); 2546 2547 /* NB: should not get here */ 2548 MWL_DBG(MWL_DBG_HW, "mwl: mwl_chan2mode(): " 2549 "cannot map channel to mode; freq %u flags 0x%x\n", 2550 chan->ic_freq, chan->ic_flags); 2551 return (IEEE80211_MODE_11B); 2552 } 2553 2554 /* XXX inline or eliminate? */ 2555 const struct ieee80211_rateset * 2556 mwl_get_suprates(struct ieee80211com *ic, const struct mwl_channel *c) 2557 { 2558 /* XXX does this work for 11ng basic rates? */ 2559 return (&ic->ic_sup_rates[mwl_chan2mode(c)]); 2560 } 2561 2562 /* 2563 * Inform firmware of tx rate parameters. 2564 * Called after a channel change. 2565 */ 2566 static int 2567 mwl_setcurchanrates(struct mwl_softc *sc) 2568 { 2569 struct ieee80211com *ic = &sc->sc_ic; 2570 const struct ieee80211_rateset *rs; 2571 MWL_HAL_TXRATE rates; 2572 2573 (void) memset(&rates, 0, sizeof (rates)); 2574 rs = mwl_get_suprates(ic, sc->sc_cur_chan); 2575 /* rate used to send management frames */ 2576 rates.MgtRate = rs->ir_rates[0] & IEEE80211_RATE_VAL; 2577 /* rate used to send multicast frames */ 2578 rates.McastRate = rates.MgtRate; 2579 2580 return (mwl_hal_settxrate_auto(sc, &rates)); 2581 } 2582 2583 static const struct mwl_hal_channel * 2584 findhalchannel(const struct mwl_softc *sc, const MWL_HAL_CHANNEL *c) 2585 { 2586 const struct mwl_hal_channel *hc; 2587 const MWL_HAL_CHANNELINFO *ci; 2588 int chan = c->channel, i; 2589 2590 if (c->channelFlags.FreqBand == MWL_FREQ_BAND_2DOT4GHZ) { 2591 i = chan - 1; 2592 if (c->channelFlags.ChnlWidth == MWL_CH_40_MHz_WIDTH) { 2593 ci = &sc->sc_40M; 2594 if (c->channelFlags.ExtChnlOffset == 2595 MWL_EXT_CH_BELOW_CTRL_CH) 2596 i -= 4; 2597 } else 2598 ci = &sc->sc_20M; 2599 /* 2.4G channel table is directly indexed */ 2600 hc = ((unsigned)i < ci->nchannels) ? &ci->channels[i] : NULL; 2601 } else if (c->channelFlags.FreqBand == MWL_FREQ_BAND_5GHZ) { 2602 if (c->channelFlags.ChnlWidth == MWL_CH_40_MHz_WIDTH) { 2603 ci = &sc->sc_40M_5G; 2604 if (c->channelFlags.ExtChnlOffset == 2605 MWL_EXT_CH_BELOW_CTRL_CH) 2606 chan -= 4; 2607 } else 2608 ci = &sc->sc_20M_5G; 2609 /* 5GHz channel table is sparse and must be searched */ 2610 for (i = 0; i < ci->nchannels; i++) 2611 if (ci->channels[i].ieee == chan) 2612 break; 2613 hc = (i < ci->nchannels) ? &ci->channels[i] : NULL; 2614 } else 2615 hc = NULL; 2616 return (hc); 2617 } 2618 2619 /* 2620 * Map SKU+country code to region code for radar bin'ing. 2621 */ 2622 static int 2623 mwl_map2regioncode(const struct mwl_regdomain *rd) 2624 { 2625 switch (rd->regdomain) { 2626 case SKU_FCC: 2627 case SKU_FCC3: 2628 return (DOMAIN_CODE_FCC); 2629 case SKU_CA: 2630 return (DOMAIN_CODE_IC); 2631 case SKU_ETSI: 2632 case SKU_ETSI2: 2633 case SKU_ETSI3: 2634 if (rd->country == CTRY_SPAIN) 2635 return (DOMAIN_CODE_SPAIN); 2636 if (rd->country == CTRY_FRANCE || rd->country == CTRY_FRANCE2) 2637 return (DOMAIN_CODE_FRANCE); 2638 /* XXX force 1.3.1 radar type */ 2639 return (DOMAIN_CODE_ETSI_131); 2640 case SKU_JAPAN: 2641 return (DOMAIN_CODE_MKK); 2642 case SKU_ROW: 2643 return (DOMAIN_CODE_DGT); /* Taiwan */ 2644 case SKU_APAC: 2645 case SKU_APAC2: 2646 case SKU_APAC3: 2647 return (DOMAIN_CODE_AUS); /* Australia */ 2648 } 2649 /* XXX KOREA? */ 2650 return (DOMAIN_CODE_FCC); /* XXX? */ 2651 } 2652 2653 /* 2654 * Setup the rx data structures. This should only be 2655 * done once or we may get out of sync with the firmware. 2656 */ 2657 static int 2658 mwl_startrecv(struct mwl_softc *sc) 2659 { 2660 struct mwl_rx_ring *ring; 2661 struct mwl_rxdesc *ds; 2662 struct mwl_rxbuf *bf, *prev; 2663 2664 int i; 2665 2666 ring = &sc->sc_rxring; 2667 bf = ring->buf; 2668 2669 prev = NULL; 2670 for (i = 0; i < MWL_RX_RING_COUNT; i++, bf++) { 2671 ds = bf->bf_desc; 2672 /* 2673 * NB: DMA buffer contents is known to be unmodified 2674 * so there's no need to flush the data cache. 2675 */ 2676 2677 /* 2678 * Setup descriptor. 2679 */ 2680 ds->QosCtrl = 0; 2681 ds->RSSI = 0; 2682 ds->Status = EAGLE_RXD_STATUS_IDLE; 2683 ds->Channel = 0; 2684 ds->PktLen = LE_16(MWL_AGGR_SIZE); 2685 ds->SQ2 = 0; 2686 ds->pPhysBuffData = LE_32(bf->bf_baddr); 2687 /* NB: don't touch pPhysNext, set once */ 2688 ds->RxControl = EAGLE_RXD_CTRL_DRIVER_OWN; 2689 2690 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 2691 i * sizeof (struct mwl_rxdesc), 2692 sizeof (struct mwl_rxdesc), 2693 DDI_DMA_SYNC_FORDEV); 2694 2695 if (prev != NULL) { 2696 ds = prev->bf_desc; 2697 ds->pPhysNext = LE_32(bf->bf_daddr); 2698 } 2699 prev = bf; 2700 } 2701 2702 if (prev != NULL) { 2703 ds = prev->bf_desc; 2704 ds->pPhysNext = ring->physaddr; 2705 } 2706 2707 /* set filters, etc. */ 2708 (void) mwl_mode_init(sc); 2709 2710 return (0); 2711 } 2712 2713 static int 2714 mwl_mode_init(struct mwl_softc *sc) 2715 { 2716 /* 2717 * NB: Ignore promisc in hostap mode; it's set by the 2718 * bridge. This is wrong but we have no way to 2719 * identify internal requests (from the bridge) 2720 * versus external requests such as for tcpdump. 2721 */ 2722 /* mwl_setmcastfilter - not support now */ 2723 (void) mwl_hal_setpromisc(sc, 0); 2724 2725 return (0); 2726 } 2727 2728 /* 2729 * Kick the firmware to tell it there are new tx descriptors 2730 * for processing. The driver says what h/w q has work in 2731 * case the f/w ever gets smarter. 2732 */ 2733 /* ARGSUSED */ 2734 static void 2735 mwl_hal_txstart(struct mwl_softc *sc, int qnum) 2736 { 2737 2738 mwl_ctl_write4(sc, MACREG_REG_H2A_INTERRUPT_EVENTS, 2739 MACREG_H2ARIC_BIT_PPA_READY); 2740 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 2741 } 2742 2743 static int 2744 mwl_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2745 { 2746 struct mwl_softc *sc = (struct mwl_softc *)ic; 2747 struct mwl_tx_ring *ring; 2748 struct mwl_txdesc *ds; 2749 struct mwl_txbuf *bf; 2750 struct ieee80211_frame *wh, *wh1; 2751 struct ieee80211_node *ni = NULL; 2752 2753 int err, off; 2754 int mblen, pktlen, hdrlen; 2755 mblk_t *m, *m0; 2756 uint8_t *addr_4, *txbuf; 2757 uint16_t *pfwlen; 2758 2759 MWL_TXLOCK(sc); 2760 2761 err = DDI_SUCCESS; 2762 if (!MWL_IS_RUNNING(sc) || MWL_IS_SUSPEND(sc)) { 2763 err = ENXIO; 2764 goto fail1; 2765 } 2766 2767 ring = &sc->sc_txring[1]; 2768 if (ring->queued > 15) { 2769 MWL_DBG(MWL_DBG_TX, "mwl: mwl_send(): " 2770 "no txbuf, %d\n", ring->queued); 2771 sc->sc_need_sched = 1; 2772 sc->sc_tx_nobuf++; 2773 err = ENOMEM; 2774 goto fail1; 2775 } 2776 2777 m = allocb(msgdsize(mp) + 32, BPRI_MED); 2778 if (m == NULL) { 2779 MWL_DBG(MWL_DBG_TX, "mwl: mwl_send():" 2780 "can't alloc mblk.\n"); 2781 err = DDI_FAILURE; 2782 goto fail1; 2783 } 2784 2785 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2786 mblen = MBLKL(m0); 2787 (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen); 2788 off += mblen; 2789 } 2790 m->b_wptr += off; 2791 2792 wh = (struct ieee80211_frame *)m->b_rptr; 2793 ni = ieee80211_find_txnode(ic, wh->i_addr1); 2794 if (ni == NULL) { 2795 err = DDI_FAILURE; 2796 sc->sc_tx_err++; 2797 goto fail2; 2798 } 2799 2800 hdrlen = sizeof (*wh); 2801 pktlen = msgdsize(m); 2802 2803 (void) ieee80211_encap(ic, m, ni); 2804 2805 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2806 const struct ieee80211_cipher *cip; 2807 struct ieee80211_key *k; 2808 k = ieee80211_crypto_encap(ic, m); 2809 if (k == NULL) { 2810 sc->sc_tx_err++; 2811 err = DDI_FAILURE; 2812 goto fail3; 2813 } 2814 2815 /* 2816 * Adjust the packet length for the crypto additions 2817 * done during encap and any other bits that the f/w 2818 * will add later on. 2819 */ 2820 cip = k->wk_cipher; 2821 pktlen += cip->ic_header + cip->ic_miclen + cip->ic_trailer; 2822 /* packet header may have moved, reset our local pointer */ 2823 wh = (struct ieee80211_frame *)m->b_rptr; 2824 } 2825 2826 ds = &ring->desc[ring->cur]; 2827 bf = &ring->buf[ring->cur]; 2828 2829 bf->bf_node = ieee80211_ref_node(ni); 2830 txbuf = (uint8_t *)bf->bf_mem; 2831 2832 /* 2833 * inject FW specific fields into the 802.11 frame 2834 * 2835 * 2 bytes FW len (inject) 2836 * 24 bytes 802.11 frame header 2837 * 6 bytes addr4 (inject) 2838 * n bytes 802.11 frame body 2839 */ 2840 pfwlen = (uint16_t *)txbuf; 2841 *pfwlen = pktlen - hdrlen; 2842 wh1 = (struct ieee80211_frame *)(txbuf + 2); 2843 bcopy(wh, wh1, sizeof (struct ieee80211_frame)); 2844 addr_4 = txbuf + (sizeof (struct ieee80211_frame) + sizeof (uint16_t)); 2845 (void) memset(addr_4, 0, 6); 2846 bcopy(m->b_rptr + sizeof (struct ieee80211_frame), txbuf + 32, *pfwlen); 2847 pktlen += 8; 2848 2849 (void) ddi_dma_sync(bf->txbuf_dma.dma_hdl, 2850 0, 2851 pktlen, 2852 DDI_DMA_SYNC_FORDEV); 2853 2854 ds->QosCtrl = 0; 2855 ds->PktLen = (uint16_t)pktlen; 2856 ds->PktPtr = bf->bf_baddr; 2857 ds->Status = LE_32(EAGLE_TXD_STATUS_FW_OWNED); 2858 ds->Format = 0; 2859 ds->pad = 0; 2860 ds->ack_wcb_addr = 0; 2861 ds->TxPriority = 1; 2862 2863 MWL_DBG(MWL_DBG_TX, "mwl: mwl_send(): " 2864 "tx desc Status %x, DataRate %x, TxPriority %x, QosCtrl %x, " 2865 "PktLen %x, SapPktInfo %x, Format %x, Pad %x, ack_wcb_addr %x\n", 2866 ds->Status, ds->DataRate, ds->TxPriority, ds->QosCtrl, ds->PktLen, 2867 ds->SapPktInfo, ds->Format, ds->pad, ds->ack_wcb_addr); 2868 2869 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 2870 ring->cur * sizeof (struct mwl_txdesc), 2871 sizeof (struct mwl_txdesc), 2872 DDI_DMA_SYNC_FORDEV); 2873 2874 MWL_DBG(MWL_DBG_TX, "mwl: mwl_send(): " 2875 "pktlen = %u, slot = %u, queued = %x\n", 2876 mblen, ring->cur, ring->queued); 2877 2878 ring->queued++; 2879 ring->cur = (ring->cur + 1) % MWL_TX_RING_COUNT; 2880 2881 /* 2882 * NB: We don't need to lock against tx done because 2883 * this just prods the firmware to check the transmit 2884 * descriptors. The firmware will also start fetching 2885 * descriptors by itself if it notices new ones are 2886 * present when it goes to deliver a tx done interrupt 2887 * to the host. So if we race with tx done processing 2888 * it's ok. Delivering the kick here rather than in 2889 * mwl_tx_start is an optimization to avoid poking the 2890 * firmware for each packet. 2891 * 2892 * NB: the queue id isn't used so 0 is ok. 2893 */ 2894 mwl_hal_txstart(sc, 0); 2895 2896 ic->ic_stats.is_tx_frags++; 2897 ic->ic_stats.is_tx_bytes += pktlen; 2898 2899 fail3: 2900 ieee80211_free_node(ni); 2901 fail2: 2902 freemsg(m); 2903 fail1: 2904 if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 2905 err == DDI_SUCCESS) 2906 freemsg(mp); 2907 MWL_TXUNLOCK(sc); 2908 return (err); 2909 } 2910 2911 /* 2912 * This function is called periodically (every 200ms) during scanning to 2913 * switch from one channel to another. 2914 */ 2915 static void 2916 mwl_next_scan(void *arg) 2917 { 2918 struct mwl_softc *sc = (struct mwl_softc *)arg; 2919 struct ieee80211com *ic = &sc->sc_ic; 2920 2921 if (ic->ic_state == IEEE80211_S_SCAN) 2922 (void) ieee80211_next_scan(ic); 2923 2924 sc->sc_scan_id = 0; 2925 } 2926 2927 /* 2928 * Convert a legacy rate set to a firmware bitmask. 2929 */ 2930 static uint32_t 2931 get_rate_bitmap(const struct ieee80211_rateset *rs) 2932 { 2933 uint32_t rates; 2934 int i; 2935 2936 rates = 0; 2937 for (i = 0; i < rs->ir_nrates; i++) 2938 switch (rs->ir_rates[i] & IEEE80211_RATE_VAL) { 2939 case 2: rates |= 0x001; break; 2940 case 4: rates |= 0x002; break; 2941 case 11: rates |= 0x004; break; 2942 case 22: rates |= 0x008; break; 2943 case 44: rates |= 0x010; break; 2944 case 12: rates |= 0x020; break; 2945 case 18: rates |= 0x040; break; 2946 case 24: rates |= 0x080; break; 2947 case 36: rates |= 0x100; break; 2948 case 48: rates |= 0x200; break; 2949 case 72: rates |= 0x400; break; 2950 case 96: rates |= 0x800; break; 2951 case 108: rates |= 0x1000; break; 2952 } 2953 return (rates); 2954 } 2955 2956 /* 2957 * Craft station database entry for station. 2958 * NB: use host byte order here, the hal handles byte swapping. 2959 */ 2960 static MWL_HAL_PEERINFO * 2961 mkpeerinfo(MWL_HAL_PEERINFO *pi, const struct ieee80211_node *ni) 2962 { 2963 (void) memset(pi, 0, sizeof (*pi)); 2964 pi->LegacyRateBitMap = get_rate_bitmap(&ni->in_rates); 2965 pi->CapInfo = ni->in_capinfo; 2966 return (pi); 2967 } 2968 2969 static int 2970 mwl_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 2971 { 2972 struct mwl_softc *sc = (struct mwl_softc *)ic; 2973 enum ieee80211_state ostate; 2974 struct ieee80211_channel *ic_chan; 2975 struct ieee80211_node *ni = NULL; 2976 MWL_HAL_PEERINFO pi; 2977 uint32_t chan; 2978 2979 if (sc->sc_scan_id != 0) { 2980 (void) untimeout(sc->sc_scan_id); 2981 sc->sc_scan_id = 0; 2982 } 2983 2984 MWL_GLOCK(sc); 2985 2986 ostate = ic->ic_state; 2987 MWL_DBG(MWL_DBG_MSG, "mwl: mwl_newstate(): " 2988 "ostate %x -> nstate %x\n", 2989 ostate, nstate); 2990 2991 switch (nstate) { 2992 case IEEE80211_S_INIT: 2993 break; 2994 case IEEE80211_S_SCAN: 2995 if (ostate != IEEE80211_S_INIT) { 2996 ic_chan = ic->ic_curchan; 2997 chan = ieee80211_chan2ieee(ic, ic_chan); 2998 if (chan != 0 && chan != IEEE80211_CHAN_ANY) { 2999 sc->sc_cur_chan = 3000 &sc->sc_channels[3 * chan - 2]; 3001 MWL_DBG(MWL_DBG_MSG, "mwl: mwl_newstate(): " 3002 "chan num is %u, sc chan is %u\n", 3003 chan, sc->sc_cur_chan->ic_ieee); 3004 (void) mwl_chan_set(sc, sc->sc_cur_chan); 3005 } 3006 } 3007 sc->sc_scan_id = timeout(mwl_next_scan, (void *)sc, 3008 drv_usectohz(250000)); 3009 break; 3010 case IEEE80211_S_AUTH: 3011 ic_chan = ic->ic_curchan; 3012 chan = ieee80211_chan2ieee(ic, ic_chan); 3013 sc->sc_cur_chan = &sc->sc_channels[3 * chan - 2]; 3014 MWL_DBG(MWL_DBG_MSG, "mwl: mwl_newstate(): " 3015 "chan num is %u, sc chan is %u\n", 3016 chan, sc->sc_cur_chan->ic_ieee); 3017 (void) mwl_chan_set(sc, sc->sc_cur_chan); 3018 ni = ic->ic_bss; 3019 (void) mwl_hal_newstation(sc, ic->ic_macaddr, 0, 0, NULL, 0, 0); 3020 mwl_setanywepkey(ic, ni->in_macaddr); 3021 break; 3022 case IEEE80211_S_ASSOC: 3023 break; 3024 case IEEE80211_S_RUN: 3025 ni = ic->ic_bss; 3026 (void) mwl_hal_newstation(sc, 3027 ic->ic_macaddr, 0, 0, mkpeerinfo(&pi, ni), 0, 0); 3028 mwl_setglobalkeys(ic); 3029 (void) mwl_hal_setassocid(sc, 3030 ic->ic_bss->in_bssid, ic->ic_bss->in_associd); 3031 (void) mwl_setrates(ic); 3032 (void) mwl_hal_setrtsthreshold(sc, ic->ic_rtsthreshold); 3033 (void) mwl_hal_setcsmode(sc, CSMODE_AUTO_ENA); 3034 break; 3035 default: 3036 break; 3037 } 3038 3039 MWL_GUNLOCK(sc); 3040 3041 return (sc->sc_newstate(ic, nstate, arg)); 3042 } 3043 3044 /* 3045 * Set the interrupt mask. 3046 */ 3047 static void 3048 mwl_hal_intrset(struct mwl_softc *sc, uint32_t mask) 3049 { 3050 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_MASK, 0); 3051 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 3052 3053 sc->sc_hal_imask = mask; 3054 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_MASK, mask); 3055 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 3056 } 3057 3058 /* 3059 * Return the current ISR setting and clear the cause. 3060 */ 3061 static void 3062 mwl_hal_getisr(struct mwl_softc *sc, uint32_t *status) 3063 { 3064 uint32_t cause; 3065 3066 cause = mwl_ctl_read4(sc, MACREG_REG_A2H_INTERRUPT_CAUSE); 3067 if (cause == 0xffffffff) { /* card removed */ 3068 cause = 0; 3069 } else if (cause != 0) { 3070 /* clear cause bits */ 3071 mwl_ctl_write4(sc, MACREG_REG_A2H_INTERRUPT_CAUSE, 3072 cause & ~sc->sc_hal_imask); 3073 (void) mwl_ctl_read4(sc, MACREG_REG_INT_CODE); 3074 cause &= sc->sc_hal_imask; 3075 } 3076 *status = cause; 3077 } 3078 3079 static void 3080 mwl_tx_intr(struct mwl_softc *sc) 3081 { 3082 struct ieee80211com *ic = &sc->sc_ic; 3083 struct mwl_tx_ring *ring; 3084 struct mwl_txdesc *ds; 3085 3086 uint32_t status; 3087 3088 MWL_TXLOCK(sc); 3089 3090 ring = &sc->sc_txring[1]; 3091 3092 if (!(ring->queued)) { 3093 MWL_TXUNLOCK(sc); 3094 return; 3095 } 3096 3097 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 3098 0, 3099 ring->txdesc_dma.alength, 3100 DDI_DMA_SYNC_FORCPU); 3101 3102 for (;;) { 3103 ds = &ring->desc[ring->next]; 3104 3105 status = LE_32(ds->Status); 3106 3107 if (status & LE_32(EAGLE_TXD_STATUS_FW_OWNED)) { 3108 break; 3109 } 3110 3111 if (status == LE_32(EAGLE_TXD_STATUS_IDLE)) { 3112 break; 3113 } 3114 3115 MWL_DBG(MWL_DBG_TX, "mwl: mwl_tx_intr(): " 3116 "recv tx desc status %x, datarate %x, txpriority %x, " 3117 "QosCtrl %x, pktLen %x, SapPktInfo %x, Format %x, " 3118 "pad %x, ack_wcb_addr %x\n", 3119 ds->Status, ds->DataRate, ds->TxPriority, 3120 ds->QosCtrl, ds->PktLen, ds->SapPktInfo, 3121 ds->Format, ds->pad, ds->ack_wcb_addr); 3122 3123 /* descriptor is no longer valid */ 3124 ds->Status = LE_32(EAGLE_TXD_STATUS_IDLE); 3125 3126 (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 3127 ring->next * sizeof (struct mwl_txdesc), 3128 sizeof (struct mwl_txdesc), 3129 DDI_DMA_SYNC_FORDEV); 3130 3131 ring->queued--; 3132 ring->next = (ring->next + 1) % MWL_TX_RING_COUNT; 3133 MWL_DBG(MWL_DBG_TX, "mwl: mwl_tx_intr(): " 3134 " tx done idx=%u, queued= %d\n", 3135 ring->next, ring->queued); 3136 3137 if (sc->sc_need_sched && 3138 (ring->queued < MWL_TX_RING_COUNT)) { 3139 sc->sc_need_sched = 0; 3140 mac_tx_update(ic->ic_mach); 3141 } 3142 3143 } 3144 3145 MWL_TXUNLOCK(sc); 3146 } 3147 3148 /* 3149 * Convert hardware signal strength to rssi. The value 3150 * provided by the device has the noise floor added in; 3151 * we need to compensate for this but we don't have that 3152 * so we use a fixed value. 3153 * 3154 * The offset of 8 is good for both 2.4 and 5GHz. The LNA 3155 * offset is already set as part of the initial gain. This 3156 * will give at least +/- 3dB for 2.4GHz and +/- 5dB for 5GHz. 3157 */ 3158 static int 3159 cvtrssi(uint8_t ssi) 3160 { 3161 int rssi = (int)ssi + 8; 3162 /* XXX hack guess until we have a real noise floor */ 3163 rssi = 2 * (87 - rssi); /* NB: .5 dBm units */ 3164 return (rssi < 0 ? 0 : rssi > 127 ? 127 : rssi); 3165 } 3166 3167 static void 3168 mwl_rx_intr(struct mwl_softc *sc) 3169 { 3170 struct ieee80211com *ic = &sc->sc_ic; 3171 struct mwl_rx_ring *ring; 3172 struct ieee80211_node *ni; 3173 struct ieee80211_frame *wh; 3174 3175 struct mwl_rxbuf *bf; 3176 struct mwl_rxdesc *ds; 3177 mblk_t *mp0; 3178 3179 int ntodo, len, rssi; 3180 uint8_t *data, status; 3181 3182 MWL_RXLOCK(sc); 3183 3184 ring = &sc->sc_rxring; 3185 for (ntodo = MWL_RX_RING_COUNT; ntodo > 0; ntodo--) { 3186 bf = &ring->buf[ring->cur]; 3187 ds = bf->bf_desc; 3188 data = bf->bf_mem; 3189 3190 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 3191 ring->cur * sizeof (struct mwl_rxdesc), 3192 sizeof (struct mwl_rxdesc), 3193 DDI_DMA_SYNC_FORCPU); 3194 3195 if (ds->RxControl != EAGLE_RXD_CTRL_DMA_OWN) 3196 break; 3197 3198 status = ds->Status; 3199 if (status & EAGLE_RXD_STATUS_DECRYPT_ERR_MASK) { 3200 MWL_DBG(MWL_DBG_CRYPTO, "mwl: mwl_rx_intr(): " 3201 "rx decrypt error\n"); 3202 sc->sc_rx_err++; 3203 } 3204 3205 /* 3206 * Sync the data buffer. 3207 */ 3208 len = LE_16(ds->PktLen); 3209 3210 (void) ddi_dma_sync(bf->rxbuf_dma.dma_hdl, 3211 0, 3212 bf->rxbuf_dma.alength, 3213 DDI_DMA_SYNC_FORCPU); 3214 3215 if (len < 32 || len > sc->sc_dmabuf_size) { 3216 MWL_DBG(MWL_DBG_RX, "mwl: mwl_rx_intr(): " 3217 "packet len error %d\n", len); 3218 sc->sc_rx_err++; 3219 goto rxnext; 3220 } 3221 3222 mp0 = allocb(sc->sc_dmabuf_size, BPRI_MED); 3223 if (mp0 == NULL) { 3224 MWL_DBG(MWL_DBG_RX, "mwl: mwl_rx_intr(): " 3225 "alloc mblk error\n"); 3226 sc->sc_rx_nobuf++; 3227 goto rxnext; 3228 } 3229 bcopy(data+ 2, mp0->b_wptr, 24); 3230 mp0->b_wptr += 24; 3231 bcopy(data + 32, mp0->b_wptr, len - 32); 3232 mp0->b_wptr += (len - 32); 3233 3234 wh = (struct ieee80211_frame *)mp0->b_rptr; 3235 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 3236 IEEE80211_FC0_TYPE_CTL) { 3237 freemsg(mp0); 3238 goto rxnext; 3239 } 3240 3241 /* 3242 * The f/w strips WEP header but doesn't clear 3243 * the WEP bit; mark the packet with M_WEP so 3244 * net80211 will treat the data as decrypted. 3245 * While here also clear the PWR_MGT bit since 3246 * power save is handled by the firmware and 3247 * passing this up will potentially cause the 3248 * upper layer to put a station in power save 3249 * (except when configured with MWL_HOST_PS_SUPPORT). 3250 */ 3251 #ifdef MWL_HOST_PS_SUPPORT 3252 wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 3253 #else 3254 wh->i_fc[1] &= ~(IEEE80211_FC1_WEP | IEEE80211_FC1_PWR_MGT); 3255 #endif 3256 3257 /* calculate rssi early so we can re-use for each aggregate */ 3258 rssi = cvtrssi(ds->RSSI); 3259 3260 ni = ieee80211_find_rxnode(ic, wh); 3261 3262 /* send the frame to the 802.11 layer */ 3263 (void) ieee80211_input(ic, mp0, ni, rssi, 0); 3264 ieee80211_free_node(ni); 3265 rxnext: 3266 /* 3267 * Setup descriptor. 3268 */ 3269 ds->QosCtrl = 0; 3270 ds->RSSI = 0; 3271 ds->Status = EAGLE_RXD_STATUS_IDLE; 3272 ds->Channel = 0; 3273 ds->PktLen = LE_16(MWL_AGGR_SIZE); 3274 ds->SQ2 = 0; 3275 ds->pPhysBuffData = bf->bf_baddr; 3276 /* NB: don't touch pPhysNext, set once */ 3277 ds->RxControl = EAGLE_RXD_CTRL_DRIVER_OWN; 3278 3279 (void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 3280 ring->cur * sizeof (struct mwl_rxdesc), 3281 sizeof (struct mwl_rxdesc), 3282 DDI_DMA_SYNC_FORDEV); 3283 3284 /* NB: ignore ENOMEM so we process more descriptors */ 3285 ring->cur = (ring->cur + 1) % MWL_RX_RING_COUNT; 3286 } 3287 3288 MWL_RXUNLOCK(sc); 3289 } 3290 3291 /*ARGSUSED*/ 3292 static uint_t 3293 mwl_softintr(caddr_t data, caddr_t unused) 3294 { 3295 struct mwl_softc *sc = (struct mwl_softc *)data; 3296 3297 /* 3298 * Check if the soft interrupt is triggered by another 3299 * driver at the same level. 3300 */ 3301 MWL_GLOCK(sc); 3302 if (sc->sc_rx_pend) { 3303 sc->sc_rx_pend = 0; 3304 MWL_GUNLOCK(sc); 3305 mwl_rx_intr(sc); 3306 return (DDI_INTR_CLAIMED); 3307 } 3308 MWL_GUNLOCK(sc); 3309 3310 return (DDI_INTR_UNCLAIMED); 3311 } 3312 3313 /*ARGSUSED*/ 3314 static uint_t 3315 mwl_intr(caddr_t arg, caddr_t unused) 3316 { 3317 struct mwl_softc *sc = (struct mwl_softc *)arg; 3318 uint32_t status; 3319 3320 MWL_GLOCK(sc); 3321 3322 if (!MWL_IS_RUNNING(sc) || MWL_IS_SUSPEND(sc)) { 3323 MWL_GUNLOCK(sc); 3324 return (DDI_INTR_UNCLAIMED); 3325 } 3326 3327 /* 3328 * Figure out the reason(s) for the interrupt. 3329 */ 3330 mwl_hal_getisr(sc, &status); /* NB: clears ISR too */ 3331 if (status == 0) { 3332 MWL_GUNLOCK(sc); 3333 return (DDI_INTR_UNCLAIMED); 3334 } 3335 3336 if (status & MACREG_A2HRIC_BIT_RX_RDY) { 3337 sc->sc_rx_pend = 1; 3338 (void) ddi_intr_trigger_softint(sc->sc_softintr_hdl, NULL); 3339 } 3340 if (status & MACREG_A2HRIC_BIT_TX_DONE) { 3341 mwl_tx_intr(sc); 3342 } 3343 if (status & MACREG_A2HRIC_BIT_BA_WATCHDOG) { 3344 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3345 "ba watchdog\n"); 3346 } 3347 if (status & MACREG_A2HRIC_BIT_OPC_DONE) { 3348 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3349 "opc done\n"); 3350 } 3351 if (status & MACREG_A2HRIC_BIT_MAC_EVENT) { 3352 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3353 "mac event\n"); 3354 } 3355 if (status & MACREG_A2HRIC_BIT_ICV_ERROR) { 3356 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3357 "ICV error\n"); 3358 } 3359 if (status & MACREG_A2HRIC_BIT_QUEUE_EMPTY) { 3360 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3361 "queue empty\n"); 3362 } 3363 if (status & MACREG_A2HRIC_BIT_QUEUE_FULL) { 3364 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3365 "queue full\n"); 3366 } 3367 if (status & MACREG_A2HRIC_BIT_RADAR_DETECT) { 3368 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3369 "radar detect\n"); 3370 } 3371 if (status & MACREG_A2HRIC_BIT_CHAN_SWITCH) { 3372 MWL_DBG(MWL_DBG_INTR, "mwl: mwl_intr(): " 3373 "chan switch\n"); 3374 } 3375 3376 MWL_GUNLOCK(sc); 3377 3378 return (DDI_INTR_CLAIMED); 3379 } 3380 3381 static int 3382 mwl_init(struct mwl_softc *sc) 3383 { 3384 struct ieee80211com *ic = &sc->sc_ic; 3385 int err = 0; 3386 3387 mwl_hal_intrset(sc, 0); 3388 3389 sc->sc_txantenna = 0; /* h/w default */ 3390 sc->sc_rxantenna = 0; /* h/w default */ 3391 3392 err = mwl_hal_setantenna(sc, WL_ANTENNATYPE_RX, sc->sc_rxantenna); 3393 if (err != 0) { 3394 MWL_DBG(MWL_DBG_HW, "mwl: mwl_init(): " 3395 "could not set rx antenna\n"); 3396 goto fail; 3397 } 3398 3399 err = mwl_hal_setantenna(sc, WL_ANTENNATYPE_TX, sc->sc_txantenna); 3400 if (err != 0) { 3401 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3402 "could not set tx antenna\n"); 3403 goto fail; 3404 } 3405 3406 err = mwl_hal_setradio(sc, 1, WL_AUTO_PREAMBLE); 3407 if (err != 0) { 3408 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3409 "could not set radio\n"); 3410 goto fail; 3411 } 3412 3413 err = mwl_hal_setwmm(sc, (ic->ic_flags & IEEE80211_F_WME) != 0); 3414 if (err != 0) { 3415 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3416 "could not set wme\n"); 3417 goto fail; 3418 } 3419 3420 /* select default channel */ 3421 ic->ic_ibss_chan = &ic->ic_sup_channels[0]; 3422 ic->ic_curchan = ic->ic_ibss_chan; 3423 sc->sc_cur_chan = &sc->sc_channels[1]; 3424 3425 err = mwl_chan_set(sc, sc->sc_cur_chan); 3426 if (err != 0) { 3427 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3428 "could not set wme\n"); 3429 goto fail; 3430 } 3431 3432 err = mwl_hal_setrateadaptmode(sc, 0); 3433 if (err != 0) { 3434 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3435 "could not set rate adapt mode\n"); 3436 goto fail; 3437 } 3438 3439 err = mwl_hal_setoptimizationlevel(sc, 3440 (ic->ic_flags & IEEE80211_F_BURST) != 0); 3441 if (err != 0) { 3442 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3443 "could not set optimization level\n"); 3444 goto fail; 3445 } 3446 3447 err = mwl_hal_setregioncode(sc, mwl_map2regioncode(&sc->sc_regdomain)); 3448 if (err != 0) { 3449 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3450 "could not set regioncode\n"); 3451 goto fail; 3452 } 3453 3454 err = mwl_startrecv(sc); 3455 if (err != 0) { 3456 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3457 "could not set start recv logic\n"); 3458 goto fail; 3459 } 3460 3461 /* 3462 * Enable interrupts. 3463 */ 3464 sc->sc_imask = MACREG_A2HRIC_BIT_RX_RDY 3465 | MACREG_A2HRIC_BIT_TX_DONE 3466 | MACREG_A2HRIC_BIT_OPC_DONE 3467 | MACREG_A2HRIC_BIT_ICV_ERROR 3468 | MACREG_A2HRIC_BIT_RADAR_DETECT 3469 | MACREG_A2HRIC_BIT_CHAN_SWITCH 3470 | MACREG_A2HRIC_BIT_BA_WATCHDOG 3471 | MACREQ_A2HRIC_BIT_TX_ACK; 3472 3473 mwl_hal_intrset(sc, sc->sc_imask); 3474 3475 err = mwl_hal_start(sc); 3476 if (err != 0) { 3477 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3478 "could not get hal start\n"); 3479 goto fail; 3480 } 3481 3482 err = mwl_hal_setinframode(sc); 3483 if (err != 0) { 3484 MWL_DBG(MWL_DBG_HW, "mwl: init(): " 3485 "could not set infra mode\n"); 3486 goto fail; 3487 } 3488 3489 fail: 3490 return (err); 3491 } 3492 3493 static int 3494 mwl_resume(struct mwl_softc *sc) 3495 { 3496 int qid, err = 0; 3497 3498 err = mwl_fwload(sc, NULL); 3499 if (err != 0) { 3500 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3501 "failed to load fw\n"); 3502 goto fail; 3503 } 3504 3505 err = mwl_gethwspecs(sc); 3506 if (err != 0) { 3507 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3508 "failed to get hw spec\n"); 3509 goto fail; 3510 } 3511 3512 err = mwl_alloc_rx_ring(sc, MWL_RX_RING_COUNT); 3513 if (err != 0) { 3514 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3515 "could not alloc cmd dma buffer\n"); 3516 goto fail; 3517 } 3518 3519 for (qid = 0; qid < MWL_NUM_TX_QUEUES; qid++) { 3520 err = mwl_alloc_tx_ring(sc, 3521 &sc->sc_txring[qid], MWL_TX_RING_COUNT); 3522 if (err != 0) { 3523 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3524 "could not alloc tx ring %d\n", qid); 3525 goto fail; 3526 } 3527 } 3528 3529 err = mwl_setupdma(sc); 3530 if (err != 0) { 3531 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3532 "could not setup dma\n"); 3533 goto fail; 3534 } 3535 3536 err = mwl_setup_txq(sc); 3537 if (err != 0) { 3538 MWL_DBG(MWL_DBG_SR, "mwl: mwl_resume(): " 3539 "could not setup txq\n"); 3540 goto fail; 3541 } 3542 3543 fail: 3544 return (err); 3545 } 3546 3547 static void 3548 mwl_stop(struct mwl_softc *sc) 3549 { 3550 int err; 3551 3552 /* by pass if it's quiesced */ 3553 if (!MWL_IS_QUIESCE(sc)) 3554 MWL_GLOCK(sc); 3555 3556 err = mwl_hal_stop(sc); 3557 if (err != 0) { 3558 MWL_DBG(MWL_DBG_HW, "mwl: mwl_stop(): " 3559 "could not stop hw\n"); 3560 } 3561 3562 /* by pass if it's quiesced */ 3563 if (!MWL_IS_QUIESCE(sc)) 3564 MWL_GUNLOCK(sc); 3565 } 3566 3567 static int 3568 mwl_m_stat(void *arg, uint_t stat, uint64_t *val) 3569 { 3570 struct mwl_softc *sc = (struct mwl_softc *)arg; 3571 struct ieee80211com *ic = &sc->sc_ic; 3572 struct ieee80211_node *ni = NULL; 3573 struct ieee80211_rateset *rs = NULL; 3574 3575 MWL_GLOCK(sc); 3576 switch (stat) { 3577 case MAC_STAT_IFSPEED: 3578 ni = ic->ic_bss; 3579 rs = &ni->in_rates; 3580 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 3581 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 3582 : ic->ic_fixed_rate) / 2 * 1000000; 3583 break; 3584 case MAC_STAT_NOXMTBUF: 3585 *val = sc->sc_tx_nobuf; 3586 break; 3587 case MAC_STAT_NORCVBUF: 3588 *val = sc->sc_rx_nobuf; 3589 break; 3590 case MAC_STAT_IERRORS: 3591 *val = sc->sc_rx_err; 3592 break; 3593 case MAC_STAT_RBYTES: 3594 *val = ic->ic_stats.is_rx_bytes; 3595 break; 3596 case MAC_STAT_IPACKETS: 3597 *val = ic->ic_stats.is_rx_frags; 3598 break; 3599 case MAC_STAT_OBYTES: 3600 *val = ic->ic_stats.is_tx_bytes; 3601 break; 3602 case MAC_STAT_OPACKETS: 3603 *val = ic->ic_stats.is_tx_frags; 3604 break; 3605 case MAC_STAT_OERRORS: 3606 case WIFI_STAT_TX_FAILED: 3607 *val = sc->sc_tx_err; 3608 break; 3609 case WIFI_STAT_TX_RETRANS: 3610 *val = sc->sc_tx_retries; 3611 break; 3612 case WIFI_STAT_FCS_ERRORS: 3613 case WIFI_STAT_WEP_ERRORS: 3614 case WIFI_STAT_TX_FRAGS: 3615 case WIFI_STAT_MCAST_TX: 3616 case WIFI_STAT_RTS_SUCCESS: 3617 case WIFI_STAT_RTS_FAILURE: 3618 case WIFI_STAT_ACK_FAILURE: 3619 case WIFI_STAT_RX_FRAGS: 3620 case WIFI_STAT_MCAST_RX: 3621 case WIFI_STAT_RX_DUPS: 3622 MWL_GUNLOCK(sc); 3623 return (ieee80211_stat(ic, stat, val)); 3624 default: 3625 MWL_GUNLOCK(sc); 3626 return (ENOTSUP); 3627 } 3628 3629 MWL_GUNLOCK(sc); 3630 return (0); 3631 } 3632 3633 static int 3634 mwl_m_start(void *arg) 3635 { 3636 struct mwl_softc *sc = (struct mwl_softc *)arg; 3637 struct ieee80211com *ic = &sc->sc_ic; 3638 int err; 3639 3640 err = mwl_init(sc); 3641 if (err != DDI_SUCCESS) { 3642 MWL_DBG(MWL_DBG_HW, "mwl: mwl_m_start():" 3643 "Hardware initialization failed\n"); 3644 goto fail1; 3645 } 3646 3647 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3648 3649 MWL_GLOCK(sc); 3650 sc->sc_flags |= MWL_F_RUNNING; 3651 MWL_GUNLOCK(sc); 3652 3653 return (0); 3654 fail1: 3655 mwl_stop(sc); 3656 return (err); 3657 } 3658 3659 static void 3660 mwl_m_stop(void *arg) 3661 { 3662 struct mwl_softc *sc = (struct mwl_softc *)arg; 3663 3664 mwl_stop(sc); 3665 3666 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3667 3668 MWL_GLOCK(sc); 3669 sc->sc_flags &= ~MWL_F_RUNNING; 3670 MWL_GUNLOCK(sc); 3671 } 3672 3673 /*ARGSUSED*/ 3674 static int 3675 mwl_m_promisc(void *arg, boolean_t on) 3676 { 3677 struct mwl_softc *sc = (struct mwl_softc *)arg; 3678 int err; 3679 3680 err = mwl_hal_setpromisc(sc, on); 3681 3682 return (err); 3683 } 3684 3685 /*ARGSUSED*/ 3686 static int 3687 mwl_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 3688 { 3689 return (ENOTSUP); 3690 } 3691 3692 /*ARGSUSED*/ 3693 static int 3694 mwl_m_unicst(void *arg, const uint8_t *macaddr) 3695 { 3696 return (ENOTSUP); 3697 } 3698 3699 static mblk_t * 3700 mwl_m_tx(void *arg, mblk_t *mp) 3701 { 3702 struct mwl_softc *sc = (struct mwl_softc *)arg; 3703 struct ieee80211com *ic = &sc->sc_ic; 3704 mblk_t *next; 3705 3706 if (MWL_IS_SUSPEND(sc)) { 3707 freemsgchain(mp); 3708 return (NULL); 3709 } 3710 3711 /* 3712 * No data frames go out unless we're associated; this 3713 * should not happen as the 802.11 layer does not enable 3714 * the xmit queue until we enter the RUN state. 3715 */ 3716 if (ic->ic_state != IEEE80211_S_RUN) { 3717 MWL_DBG(MWL_DBG_TX, "mwl: mwl_m_tx(): " 3718 "discard, state %u\n", ic->ic_state); 3719 freemsgchain(mp); 3720 return (NULL); 3721 } 3722 3723 while (mp != NULL) { 3724 next = mp->b_next; 3725 mp->b_next = NULL; 3726 if (mwl_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 3727 DDI_SUCCESS) { 3728 mp->b_next = next; 3729 break; 3730 } 3731 mp = next; 3732 } 3733 return (mp); 3734 } 3735 3736 static void 3737 mwl_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 3738 { 3739 struct mwl_softc *sc = (struct mwl_softc *)arg; 3740 struct ieee80211com *ic = &sc->sc_ic; 3741 int err; 3742 3743 err = ieee80211_ioctl(ic, wq, mp); 3744 if (err == ENETRESET) { 3745 if (ic->ic_des_esslen) { 3746 if (MWL_IS_RUNNING(sc)) { 3747 (void) mwl_init(sc); 3748 (void) ieee80211_new_state(ic, 3749 IEEE80211_S_SCAN, -1); 3750 } 3751 } 3752 } 3753 } 3754 3755 /* 3756 * Call back function for get/set proporty 3757 */ 3758 static int 3759 mwl_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3760 uint_t wldp_length, void *wldp_buf) 3761 { 3762 struct mwl_softc *sc = (struct mwl_softc *)arg; 3763 int err = 0; 3764 3765 err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 3766 wldp_length, wldp_buf); 3767 3768 return (err); 3769 } 3770 3771 static void 3772 mwl_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3773 mac_prop_info_handle_t prh) 3774 { 3775 struct mwl_softc *sc = (struct mwl_softc *)arg; 3776 3777 ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, prh); 3778 } 3779 3780 static int 3781 mwl_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3782 uint_t wldp_length, const void *wldp_buf) 3783 { 3784 struct mwl_softc *sc = (struct mwl_softc *)arg; 3785 ieee80211com_t *ic = &sc->sc_ic; 3786 int err; 3787 3788 err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length, 3789 wldp_buf); 3790 if (err == ENETRESET) { 3791 if (ic->ic_des_esslen) { 3792 if (MWL_IS_RUNNING(sc)) { 3793 (void) mwl_init(sc); 3794 (void) ieee80211_new_state(ic, 3795 IEEE80211_S_SCAN, -1); 3796 } 3797 } 3798 err = 0; 3799 } 3800 return (err); 3801 } 3802 3803 static int 3804 mwl_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 3805 { 3806 struct mwl_softc *sc; 3807 struct ieee80211com *ic; 3808 int i, err, qid, instance; 3809 int intr_type, intr_count, intr_actual; 3810 char strbuf[32]; 3811 uint8_t csz; 3812 uint16_t vendor_id, device_id, command; 3813 3814 wifi_data_t wd = { 0 }; 3815 mac_register_t *macp; 3816 3817 switch (cmd) { 3818 case DDI_ATTACH: 3819 break; 3820 case DDI_RESUME: 3821 sc = ddi_get_soft_state(mwl_soft_state_p, 3822 ddi_get_instance(devinfo)); 3823 ASSERT(sc != NULL); 3824 MWL_GLOCK(sc); 3825 sc->sc_flags &= ~MWL_F_SUSPEND; 3826 MWL_GUNLOCK(sc); 3827 if (mwl_resume(sc) != 0) { 3828 MWL_DBG(MWL_DBG_SR, "mwl: mwl_attach(): " 3829 "failed to resume\n"); 3830 return (DDI_FAILURE); 3831 } 3832 if (MWL_IS_RUNNING(sc)) { 3833 (void) mwl_init(sc); 3834 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3835 } 3836 MWL_DBG(MWL_DBG_SR, "mwl: mwl_attach(): " 3837 "resume now\n"); 3838 return (DDI_SUCCESS); 3839 default: 3840 return (DDI_FAILURE); 3841 } 3842 3843 instance = ddi_get_instance(devinfo); 3844 if (ddi_soft_state_zalloc(mwl_soft_state_p, 3845 ddi_get_instance(devinfo)) != DDI_SUCCESS) { 3846 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3847 "Unable to alloc soft state\n"); 3848 return (DDI_FAILURE); 3849 } 3850 3851 sc = ddi_get_soft_state(mwl_soft_state_p, ddi_get_instance(devinfo)); 3852 ic = &sc->sc_ic; 3853 sc->sc_dev = devinfo; 3854 3855 /* PCI configuration space */ 3856 err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&sc->sc_cfg_base, 0, 0, 3857 &mwl_reg_accattr, &sc->sc_cfg_handle); 3858 if (err != DDI_SUCCESS) { 3859 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3860 "ddi_regs_map_setup() failed"); 3861 goto attach_fail0; 3862 } 3863 csz = ddi_get8(sc->sc_cfg_handle, 3864 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 3865 if (!csz) 3866 csz = 16; 3867 sc->sc_cachelsz = csz << 2; 3868 sc->sc_dmabuf_size = roundup(IEEE80211_MAX_LEN, sc->sc_cachelsz); 3869 vendor_id = ddi_get16(sc->sc_cfg_handle, 3870 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_VENID)); 3871 device_id = ddi_get16(sc->sc_cfg_handle, 3872 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_DEVID)); 3873 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3874 "vendor 0x%x, device id 0x%x, cache size %d\n", 3875 vendor_id, device_id, csz); 3876 3877 /* 3878 * Enable response to memory space accesses, 3879 * and enabe bus master. 3880 */ 3881 command = PCI_COMM_MAE | PCI_COMM_ME; 3882 ddi_put16(sc->sc_cfg_handle, 3883 (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_COMM), 3884 command); 3885 ddi_put8(sc->sc_cfg_handle, 3886 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8); 3887 ddi_put8(sc->sc_cfg_handle, 3888 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_ILINE), 0x10); 3889 3890 /* BAR0 */ 3891 err = ddi_regs_map_setup(devinfo, 1, 3892 &sc->sc_mem_base, 0, 0, &mwl_reg_accattr, &sc->sc_mem_handle); 3893 if (err != DDI_SUCCESS) { 3894 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3895 "i/o space failed"); 3896 goto attach_fail1; 3897 } 3898 3899 /* BAR1 */ 3900 err = ddi_regs_map_setup(devinfo, 2, 3901 &sc->sc_io_base, 0, 0, &mwl_reg_accattr, &sc->sc_io_handle); 3902 if (err != DDI_SUCCESS) { 3903 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3904 "memory space failed"); 3905 goto attach_fail2; 3906 } 3907 3908 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3909 "PCI configuration is done successfully\n"); 3910 3911 /* 3912 * Alloc cmd DMA buffer for firmware download 3913 */ 3914 err = mwl_alloc_cmdbuf(sc); 3915 if (err != 0) { 3916 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3917 "could not alloc cmd dma buffer\n"); 3918 goto attach_fail3; 3919 } 3920 3921 sc->sc_imask = 0; 3922 sc->sc_hw_flags = 0; 3923 sc->sc_flags = 0; 3924 3925 /* 3926 * Some cards have SDRAM. When loading firmware we need 3927 * to reset the SDRAM controller prior to doing this. 3928 * When the SDRAMSIZE is non-zero we do that work in 3929 * mwl_hal_fwload. 3930 */ 3931 switch (device_id) { 3932 case 0x2a02: /* CB82 */ 3933 case 0x2a03: /* CB85 */ 3934 case 0x2a08: /* MC85_B1 */ 3935 case 0x2a0b: /* CB85AP */ 3936 case 0x2a24: 3937 sc->sc_SDRAMSIZE_Addr = 0x40fe70b7; /* 8M SDRAM */ 3938 break; 3939 case 0x2a04: /* MC85 */ 3940 sc->sc_SDRAMSIZE_Addr = 0x40fc70b7; /* 16M SDRAM */ 3941 break; 3942 default: 3943 break; 3944 } 3945 3946 err = mwl_fwload(sc, NULL); 3947 if (err != 0) { 3948 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3949 "firmware download failed\n"); 3950 goto attach_fail4; 3951 } 3952 3953 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3954 "firmware download successfully\n"); 3955 3956 err = mwl_gethwspecs(sc); 3957 if (err != 0) { 3958 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3959 "failed to get hw spec\n"); 3960 goto attach_fail4; 3961 } 3962 3963 err = mwl_getchannels(sc); 3964 if (err != 0) { 3965 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3966 "failed to get channels\n"); 3967 goto attach_fail4; 3968 } 3969 3970 /* 3971 * Alloc rx DMA buffer 3972 */ 3973 err = mwl_alloc_rx_ring(sc, MWL_RX_RING_COUNT); 3974 if (err != 0) { 3975 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3976 "could not alloc cmd dma buffer\n"); 3977 goto attach_fail5; 3978 } 3979 3980 /* 3981 * Alloc rx DMA buffer 3982 */ 3983 for (qid = 0; qid < MWL_NUM_TX_QUEUES; qid++) { 3984 err = mwl_alloc_tx_ring(sc, 3985 &sc->sc_txring[qid], MWL_TX_RING_COUNT); 3986 if (err != 0) { 3987 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3988 "could not alloc tx ring %d\n", qid); 3989 goto attach_fail6; 3990 } 3991 } 3992 3993 err = mwl_setupdma(sc); 3994 if (err != 0) { 3995 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 3996 "could not setup dma\n"); 3997 goto attach_fail6; 3998 } 3999 4000 err = mwl_setup_txq(sc); 4001 if (err != 0) { 4002 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4003 "could not setup txq\n"); 4004 goto attach_fail6; 4005 } 4006 4007 IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->sc_hwspecs.macAddr); 4008 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4009 "mwl MAC:%2x:%2x:%2x:%2x:%2x:%2x\n", 4010 ic->ic_macaddr[0], 4011 ic->ic_macaddr[1], 4012 ic->ic_macaddr[2], 4013 ic->ic_macaddr[3], 4014 ic->ic_macaddr[4], 4015 ic->ic_macaddr[5]); 4016 4017 err = mwl_hal_setmac_locked(sc, ic->ic_macaddr); 4018 if (err != 0) { /* NB: mwl_setupdma prints msg */ 4019 MWL_DBG(MWL_DBG_ATTACH, "mwl: attach(): " 4020 "could not set mac\n"); 4021 goto attach_fail6; 4022 } 4023 4024 mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER, NULL); 4025 mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL); 4026 mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL); 4027 4028 4029 /* set supported rates */ 4030 ic->ic_sup_rates[IEEE80211_MODE_11B] = mwl_rateset_11b; 4031 ic->ic_sup_rates[IEEE80211_MODE_11G] = mwl_rateset_11g; 4032 4033 /* set supported .11b and .11g channels (1 through 14) */ 4034 for (i = 1; i <= 14; i++) { 4035 ic->ic_sup_channels[i].ich_freq = 4036 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 4037 ic->ic_sup_channels[i].ich_flags = 4038 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 4039 } 4040 4041 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 4042 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 4043 ic->ic_state = IEEE80211_S_INIT; 4044 4045 /* set device capabilities */ 4046 ic->ic_caps = 4047 IEEE80211_C_TXPMGT | /* tx power management */ 4048 IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 4049 IEEE80211_C_SHSLOT; /* short slot time supported */ 4050 4051 /* WPA/WPA2 support */ 4052 ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */ 4053 4054 /* Enable hardware encryption */ 4055 ic->ic_caps |= IEEE80211_C_WEP | IEEE80211_C_TKIP | IEEE80211_C_AES_CCM; 4056 4057 ic->ic_xmit = mwl_send; 4058 4059 ieee80211_attach(ic); 4060 4061 /* register WPA door */ 4062 ieee80211_register_door(ic, ddi_driver_name(devinfo), 4063 ddi_get_instance(devinfo)); 4064 4065 /* override state transition machine */ 4066 sc->sc_newstate = ic->ic_newstate; 4067 ic->ic_newstate = mwl_newstate; 4068 ic->ic_node_alloc = mwl_node_alloc; 4069 ic->ic_node_free = mwl_node_free; 4070 ic->ic_crypto.cs_max_keyix = 0; 4071 ic->ic_crypto.cs_key_alloc = mwl_key_alloc; 4072 ic->ic_crypto.cs_key_delete = mwl_key_delete; 4073 ic->ic_crypto.cs_key_set = mwl_key_set; 4074 4075 ieee80211_media_init(ic); 4076 4077 ic->ic_def_txkey = 0; 4078 4079 err = mwl_hal_newstation(sc, ic->ic_macaddr, 0, 0, NULL, 0, 0); 4080 if (err != 0) { 4081 MWL_DBG(MWL_DBG_ATTACH, "mwl: attach(): " 4082 "could not create new station\n"); 4083 goto attach_fail7; 4084 } 4085 4086 IEEE80211_ADDR_COPY(ic->ic_bss->in_bssid, ic->ic_macaddr); 4087 // mwl_setglobalkeys(ic); 4088 4089 err = ddi_intr_get_supported_types(devinfo, &intr_type); 4090 if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) { 4091 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4092 "fixed type interrupt is not supported\n"); 4093 goto attach_fail7; 4094 } 4095 4096 err = ddi_intr_get_nintrs(devinfo, DDI_INTR_TYPE_FIXED, &intr_count); 4097 if ((err != DDI_SUCCESS) || (intr_count != 1)) { 4098 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4099 "no fixed interrupts\n"); 4100 goto attach_fail7; 4101 } 4102 4103 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP); 4104 4105 err = ddi_intr_alloc(devinfo, sc->sc_intr_htable, 4106 DDI_INTR_TYPE_FIXED, 0, intr_count, &intr_actual, 0); 4107 if ((err != DDI_SUCCESS) || (intr_actual != 1)) { 4108 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4109 "ddi_intr_alloc() failed 0x%x\n", err); 4110 goto attach_fail8; 4111 } 4112 4113 err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri); 4114 if (err != DDI_SUCCESS) { 4115 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4116 "ddi_intr_get_pri() failed 0x%x\n", err); 4117 goto attach_fail9; 4118 } 4119 4120 err = ddi_intr_add_softint(devinfo, &sc->sc_softintr_hdl, 4121 DDI_INTR_SOFTPRI_MAX, mwl_softintr, (caddr_t)sc); 4122 if (err != DDI_SUCCESS) { 4123 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4124 "ddi_add_softintr() failed"); 4125 goto attach_fail9; 4126 } 4127 4128 err = ddi_intr_add_handler(sc->sc_intr_htable[0], mwl_intr, 4129 (caddr_t)sc, NULL); 4130 if (err != DDI_SUCCESS) { 4131 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4132 "ddi_intr_addr_handle() failed\n"); 4133 goto attach_fail10; 4134 } 4135 4136 err = ddi_intr_enable(sc->sc_intr_htable[0]); 4137 if (err != DDI_SUCCESS) { 4138 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4139 "ddi_intr_enable() failed\n"); 4140 goto attach_fail11; 4141 } 4142 4143 /* 4144 * Provide initial settings for the WiFi plugin; whenever this 4145 * information changes, we need to call mac_plugindata_update() 4146 */ 4147 wd.wd_opmode = ic->ic_opmode; 4148 wd.wd_secalloc = WIFI_SEC_NONE; 4149 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 4150 4151 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 4152 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4153 "MAC version mismatch\n"); 4154 goto attach_fail12; 4155 } 4156 4157 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 4158 macp->m_driver = sc; 4159 macp->m_dip = devinfo; 4160 macp->m_src_addr = ic->ic_macaddr; 4161 macp->m_callbacks = &mwl_m_callbacks; 4162 macp->m_min_sdu = 0; 4163 macp->m_max_sdu = IEEE80211_MTU; 4164 macp->m_pdata = &wd; 4165 macp->m_pdata_size = sizeof (wd); 4166 4167 err = mac_register(macp, &ic->ic_mach); 4168 mac_free(macp); 4169 if (err != 0) { 4170 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4171 "mac_register err %x\n", err); 4172 goto attach_fail12; 4173 } 4174 4175 /* 4176 * Create minor node of type DDI_NT_NET_WIFI 4177 */ 4178 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 4179 "mwl", instance); 4180 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 4181 instance + 1, DDI_NT_NET_WIFI, 0); 4182 if (err != 0) { 4183 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4184 "create minor node error\n"); 4185 goto attach_fail13; 4186 } 4187 4188 /* 4189 * Notify link is down now 4190 */ 4191 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 4192 4193 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_attach(): " 4194 "driver attach successfully\n"); 4195 return (DDI_SUCCESS); 4196 4197 attach_fail13: 4198 (void) mac_disable(ic->ic_mach); 4199 (void) mac_unregister(ic->ic_mach); 4200 attach_fail12: 4201 (void) ddi_intr_disable(sc->sc_intr_htable[0]); 4202 attach_fail11: 4203 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 4204 attach_fail10: 4205 (void) ddi_intr_remove_softint(sc->sc_softintr_hdl); 4206 sc->sc_softintr_hdl = NULL; 4207 attach_fail9: 4208 (void) ddi_intr_free(sc->sc_intr_htable[0]); 4209 attach_fail8: 4210 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 4211 attach_fail7: 4212 mutex_destroy(&sc->sc_txlock); 4213 mutex_destroy(&sc->sc_rxlock); 4214 mutex_destroy(&sc->sc_glock); 4215 attach_fail6: 4216 while (--qid >= 0) 4217 mwl_free_tx_ring(sc, &sc->sc_txring[qid]); 4218 attach_fail5: 4219 mwl_free_rx_ring(sc); 4220 attach_fail4: 4221 mwl_free_cmdbuf(sc); 4222 attach_fail3: 4223 ddi_regs_map_free(&sc->sc_mem_handle); 4224 attach_fail2: 4225 ddi_regs_map_free(&sc->sc_io_handle); 4226 attach_fail1: 4227 ddi_regs_map_free(&sc->sc_cfg_handle); 4228 attach_fail0: 4229 ddi_soft_state_free(mwl_soft_state_p, ddi_get_instance(devinfo)); 4230 return (DDI_FAILURE); 4231 } 4232 4233 static int32_t 4234 mwl_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 4235 { 4236 struct mwl_softc *sc; 4237 int qid; 4238 4239 sc = ddi_get_soft_state(mwl_soft_state_p, ddi_get_instance(devinfo)); 4240 ASSERT(sc != NULL); 4241 4242 switch (cmd) { 4243 case DDI_DETACH: 4244 break; 4245 case DDI_SUSPEND: 4246 if (MWL_IS_RUNNING(sc)) 4247 mwl_stop(sc); 4248 for (qid = 0; qid < MWL_NUM_TX_QUEUES; qid++) 4249 mwl_free_tx_ring(sc, &sc->sc_txring[qid]); 4250 mwl_free_rx_ring(sc); 4251 MWL_GLOCK(sc); 4252 sc->sc_flags |= MWL_F_SUSPEND; 4253 MWL_GUNLOCK(sc); 4254 MWL_DBG(MWL_DBG_SR, "mwl: mwl_detach(): " 4255 "suspend now\n"); 4256 return (DDI_SUCCESS); 4257 default: 4258 return (DDI_FAILURE); 4259 } 4260 4261 if (mac_disable(sc->sc_ic.ic_mach) != 0) 4262 return (DDI_FAILURE); 4263 4264 /* 4265 * Unregister from the MAC layer subsystem 4266 */ 4267 (void) mac_unregister(sc->sc_ic.ic_mach); 4268 4269 (void) ddi_intr_remove_softint(sc->sc_softintr_hdl); 4270 sc->sc_softintr_hdl = NULL; 4271 (void) ddi_intr_disable(sc->sc_intr_htable[0]); 4272 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 4273 (void) ddi_intr_free(sc->sc_intr_htable[0]); 4274 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 4275 4276 /* 4277 * detach ieee80211 layer 4278 */ 4279 ieee80211_detach(&sc->sc_ic); 4280 4281 4282 for (qid = 0; qid < MWL_NUM_TX_QUEUES; qid++) 4283 mwl_free_tx_ring(sc, &sc->sc_txring[qid]); 4284 mwl_free_rx_ring(sc); 4285 mwl_free_cmdbuf(sc); 4286 4287 mutex_destroy(&sc->sc_txlock); 4288 mutex_destroy(&sc->sc_rxlock); 4289 mutex_destroy(&sc->sc_glock); 4290 4291 ddi_regs_map_free(&sc->sc_mem_handle); 4292 ddi_regs_map_free(&sc->sc_io_handle); 4293 ddi_regs_map_free(&sc->sc_cfg_handle); 4294 4295 ddi_remove_minor_node(devinfo, NULL); 4296 ddi_soft_state_free(mwl_soft_state_p, ddi_get_instance(devinfo)); 4297 4298 MWL_DBG(MWL_DBG_ATTACH, "mwl: mwl_detach(): " 4299 "detach successfully\n"); 4300 return (DDI_SUCCESS); 4301 } 4302 4303 /* 4304 * quiesce(9E) entry point. 4305 * 4306 * This function is called when the system is single-threaded at high 4307 * PIL with preemption disabled. Therefore, this function must not be 4308 * blocked. 4309 * 4310 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 4311 * DDI_FAILURE indicates an error condition and should almost never happen. 4312 */ 4313 int 4314 mwl_quiesce(dev_info_t *dip) 4315 { 4316 struct mwl_softc *sc; 4317 4318 sc = ddi_get_soft_state(mwl_soft_state_p, ddi_get_instance(dip)); 4319 if (sc == NULL) 4320 return (DDI_FAILURE); 4321 4322 #ifdef DEBUG 4323 mwl_dbg_flags = 0; 4324 #endif 4325 4326 /* 4327 * No more blocking is allowed while we are in quiesce(9E) entry point 4328 */ 4329 sc->sc_flags |= MWL_F_QUIESCE; 4330 4331 /* 4332 * Disable all interrupts 4333 */ 4334 mwl_stop(sc); 4335 return (DDI_SUCCESS); 4336 } 4337 4338 int 4339 _init(void) 4340 { 4341 int status; 4342 4343 status = ddi_soft_state_init(&mwl_soft_state_p, 4344 sizeof (struct mwl_softc), 1); 4345 if (status != 0) 4346 return (status); 4347 4348 mac_init_ops(&mwl_dev_ops, "mwl"); 4349 status = mod_install(&modlinkage); 4350 if (status != 0) { 4351 mac_fini_ops(&mwl_dev_ops); 4352 ddi_soft_state_fini(&mwl_soft_state_p); 4353 } 4354 return (status); 4355 } 4356 4357 int 4358 _info(struct modinfo *modinfop) 4359 { 4360 return (mod_info(&modlinkage, modinfop)); 4361 } 4362 4363 int 4364 _fini(void) 4365 { 4366 int status; 4367 4368 status = mod_remove(&modlinkage); 4369 if (status == 0) { 4370 mac_fini_ops(&mwl_dev_ops); 4371 ddi_soft_state_fini(&mwl_soft_state_p); 4372 } 4373 return (status); 4374 } 4375