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