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