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