1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2008, Intel Corporation 8 * All rights reserved. 9 */ 10 11 /* 12 * Copyright (c) 2006 13 * Copyright (c) 2007 14 * Damien Bergamini <damien.bergamini@free.fr> 15 * 16 * Permission to use, copy, modify, and distribute this software for any 17 * purpose with or without fee is hereby granted, provided that the above 18 * copyright notice and this permission notice appear in all copies. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 21 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 23 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 24 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 25 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 26 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 */ 28 29 /* 30 * Intel(R) WiFi Link 5100/5300 Driver 31 */ 32 33 #include <sys/types.h> 34 #include <sys/byteorder.h> 35 #include <sys/conf.h> 36 #include <sys/cmn_err.h> 37 #include <sys/stat.h> 38 #include <sys/ddi.h> 39 #include <sys/sunddi.h> 40 #include <sys/strsubr.h> 41 #include <sys/ethernet.h> 42 #include <inet/common.h> 43 #include <inet/nd.h> 44 #include <inet/mi.h> 45 #include <sys/note.h> 46 #include <sys/stream.h> 47 #include <sys/strsun.h> 48 #include <sys/modctl.h> 49 #include <sys/devops.h> 50 #include <sys/dlpi.h> 51 #include <sys/mac.h> 52 #include <sys/mac_wifi.h> 53 #include <sys/net80211.h> 54 #include <sys/net80211_proto.h> 55 #include <sys/varargs.h> 56 #include <sys/policy.h> 57 #include <sys/pci.h> 58 59 #include "iwh_calibration.h" 60 #include "iwh_hw.h" 61 #include "iwh_eeprom.h" 62 #include "iwh_var.h" 63 #include <inet/wifi_ioctl.h> 64 65 #ifdef DEBUG 66 #define IWH_DEBUG_80211 (1 << 0) 67 #define IWH_DEBUG_CMD (1 << 1) 68 #define IWH_DEBUG_DMA (1 << 2) 69 #define IWH_DEBUG_EEPROM (1 << 3) 70 #define IWH_DEBUG_FW (1 << 4) 71 #define IWH_DEBUG_HW (1 << 5) 72 #define IWH_DEBUG_INTR (1 << 6) 73 #define IWH_DEBUG_MRR (1 << 7) 74 #define IWH_DEBUG_PIO (1 << 8) 75 #define IWH_DEBUG_RX (1 << 9) 76 #define IWH_DEBUG_SCAN (1 << 10) 77 #define IWH_DEBUG_TX (1 << 11) 78 #define IWH_DEBUG_RATECTL (1 << 12) 79 #define IWH_DEBUG_RADIO (1 << 13) 80 #define IWH_DEBUG_RESUME (1 << 14) 81 #define IWH_DEBUG_CALIBRATION (1 << 15) 82 /* 83 * if want to see debug message of a given section, 84 * please set this flag to one of above values 85 */ 86 uint32_t iwh_dbg_flags = 0; 87 #define IWH_DBG(x) \ 88 iwh_dbg x 89 #else 90 #define IWH_DBG(x) 91 #endif 92 93 static void *iwh_soft_state_p = NULL; 94 95 /* 96 * ucode will be compiled into driver image 97 */ 98 static uint8_t iwh_fw_bin [] = { 99 #include "fw-iw/iwh.ucode" 100 }; 101 102 /* 103 * DMA attributes for a shared page 104 */ 105 static ddi_dma_attr_t sh_dma_attr = { 106 DMA_ATTR_V0, /* version of this structure */ 107 0, /* lowest usable address */ 108 0xffffffffU, /* highest usable address */ 109 0xffffffffU, /* maximum DMAable byte count */ 110 0x1000, /* alignment in bytes */ 111 0x1000, /* burst sizes (any?) */ 112 1, /* minimum transfer */ 113 0xffffffffU, /* maximum transfer */ 114 0xffffffffU, /* maximum segment length */ 115 1, /* maximum number of segments */ 116 1, /* granularity */ 117 0, /* flags (reserved) */ 118 }; 119 120 /* 121 * DMA attributes for a keep warm DRAM descriptor 122 */ 123 static ddi_dma_attr_t kw_dma_attr = { 124 DMA_ATTR_V0, /* version of this structure */ 125 0, /* lowest usable address */ 126 0xffffffffU, /* highest usable address */ 127 0xffffffffU, /* maximum DMAable byte count */ 128 0x1000, /* alignment in bytes */ 129 0x1000, /* burst sizes (any?) */ 130 1, /* minimum transfer */ 131 0xffffffffU, /* maximum transfer */ 132 0xffffffffU, /* maximum segment length */ 133 1, /* maximum number of segments */ 134 1, /* granularity */ 135 0, /* flags (reserved) */ 136 }; 137 138 /* 139 * DMA attributes for a ring descriptor 140 */ 141 static ddi_dma_attr_t ring_desc_dma_attr = { 142 DMA_ATTR_V0, /* version of this structure */ 143 0, /* lowest usable address */ 144 0xffffffffU, /* highest usable address */ 145 0xffffffffU, /* maximum DMAable byte count */ 146 0x100, /* alignment in bytes */ 147 0x100, /* burst sizes (any?) */ 148 1, /* minimum transfer */ 149 0xffffffffU, /* maximum transfer */ 150 0xffffffffU, /* maximum segment length */ 151 1, /* maximum number of segments */ 152 1, /* granularity */ 153 0, /* flags (reserved) */ 154 }; 155 156 /* 157 * DMA attributes for a cmd 158 */ 159 static ddi_dma_attr_t cmd_dma_attr = { 160 DMA_ATTR_V0, /* version of this structure */ 161 0, /* lowest usable address */ 162 0xffffffffU, /* highest usable address */ 163 0xffffffffU, /* maximum DMAable byte count */ 164 4, /* alignment in bytes */ 165 0x100, /* burst sizes (any?) */ 166 1, /* minimum transfer */ 167 0xffffffffU, /* maximum transfer */ 168 0xffffffffU, /* maximum segment length */ 169 1, /* maximum number of segments */ 170 1, /* granularity */ 171 0, /* flags (reserved) */ 172 }; 173 174 /* 175 * DMA attributes for a rx buffer 176 */ 177 static ddi_dma_attr_t rx_buffer_dma_attr = { 178 DMA_ATTR_V0, /* version of this structure */ 179 0, /* lowest usable address */ 180 0xffffffffU, /* highest usable address */ 181 0xffffffffU, /* maximum DMAable byte count */ 182 0x100, /* alignment in bytes */ 183 0x100, /* burst sizes (any?) */ 184 1, /* minimum transfer */ 185 0xffffffffU, /* maximum transfer */ 186 0xffffffffU, /* maximum segment length */ 187 1, /* maximum number of segments */ 188 1, /* granularity */ 189 0, /* flags (reserved) */ 190 }; 191 192 /* 193 * DMA attributes for a tx buffer. 194 * the maximum number of segments is 4 for the hardware. 195 * now all the wifi drivers put the whole frame in a single 196 * descriptor, so we define the maximum number of segments 1, 197 * just the same as the rx_buffer. we consider leverage the HW 198 * ability in the future, that is why we don't define rx and tx 199 * buffer_dma_attr as the same. 200 */ 201 static ddi_dma_attr_t tx_buffer_dma_attr = { 202 DMA_ATTR_V0, /* version of this structure */ 203 0, /* lowest usable address */ 204 0xffffffffU, /* highest usable address */ 205 0xffffffffU, /* maximum DMAable byte count */ 206 4, /* alignment in bytes */ 207 0x100, /* burst sizes (any?) */ 208 1, /* minimum transfer */ 209 0xffffffffU, /* maximum transfer */ 210 0xffffffffU, /* maximum segment length */ 211 1, /* maximum number of segments */ 212 1, /* granularity */ 213 0, /* flags (reserved) */ 214 }; 215 216 /* 217 * DMA attributes for text and data part in the firmware 218 */ 219 static ddi_dma_attr_t fw_dma_attr = { 220 DMA_ATTR_V0, /* version of this structure */ 221 0, /* lowest usable address */ 222 0xffffffffU, /* highest usable address */ 223 0x7fffffff, /* maximum DMAable byte count */ 224 0x10, /* alignment in bytes */ 225 0x100, /* burst sizes (any?) */ 226 1, /* minimum transfer */ 227 0xffffffffU, /* maximum transfer */ 228 0xffffffffU, /* maximum segment length */ 229 1, /* maximum number of segments */ 230 1, /* granularity */ 231 0, /* flags (reserved) */ 232 }; 233 234 235 /* 236 * regs access attributes 237 */ 238 static ddi_device_acc_attr_t iwh_reg_accattr = { 239 DDI_DEVICE_ATTR_V0, 240 DDI_STRUCTURE_LE_ACC, 241 DDI_STRICTORDER_ACC, 242 DDI_DEFAULT_ACC 243 }; 244 245 /* 246 * DMA access attributes 247 */ 248 static ddi_device_acc_attr_t iwh_dma_accattr = { 249 DDI_DEVICE_ATTR_V0, 250 DDI_NEVERSWAP_ACC, 251 DDI_STRICTORDER_ACC, 252 DDI_DEFAULT_ACC 253 }; 254 255 static int iwh_ring_init(iwh_sc_t *); 256 static void iwh_ring_free(iwh_sc_t *); 257 static int iwh_alloc_shared(iwh_sc_t *); 258 static void iwh_free_shared(iwh_sc_t *); 259 static int iwh_alloc_kw(iwh_sc_t *); 260 static void iwh_free_kw(iwh_sc_t *); 261 static int iwh_alloc_fw_dma(iwh_sc_t *); 262 static void iwh_free_fw_dma(iwh_sc_t *); 263 static int iwh_alloc_rx_ring(iwh_sc_t *); 264 static void iwh_reset_rx_ring(iwh_sc_t *); 265 static void iwh_free_rx_ring(iwh_sc_t *); 266 static int iwh_alloc_tx_ring(iwh_sc_t *, iwh_tx_ring_t *, 267 int, int); 268 static void iwh_reset_tx_ring(iwh_sc_t *, iwh_tx_ring_t *); 269 static void iwh_free_tx_ring(iwh_tx_ring_t *); 270 static ieee80211_node_t *iwh_node_alloc(ieee80211com_t *); 271 static void iwh_node_free(ieee80211_node_t *); 272 static int iwh_newstate(ieee80211com_t *, enum ieee80211_state, int); 273 static int iwh_key_set(ieee80211com_t *, const struct ieee80211_key *, 274 const uint8_t mac[IEEE80211_ADDR_LEN]); 275 static void iwh_mac_access_enter(iwh_sc_t *); 276 static void iwh_mac_access_exit(iwh_sc_t *); 277 static uint32_t iwh_reg_read(iwh_sc_t *, uint32_t); 278 static void iwh_reg_write(iwh_sc_t *, uint32_t, uint32_t); 279 static int iwh_load_init_firmware(iwh_sc_t *); 280 static int iwh_load_run_firmware(iwh_sc_t *); 281 static void iwh_tx_intr(iwh_sc_t *, iwh_rx_desc_t *); 282 static void iwh_cmd_intr(iwh_sc_t *, iwh_rx_desc_t *); 283 static uint_t iwh_intr(caddr_t, caddr_t); 284 static int iwh_eep_load(iwh_sc_t *); 285 static void iwh_get_mac_from_eep(iwh_sc_t *); 286 static int iwh_eep_sem_down(iwh_sc_t *); 287 static void iwh_eep_sem_up(iwh_sc_t *); 288 static uint_t iwh_rx_softintr(caddr_t, caddr_t); 289 static uint8_t iwh_rate_to_plcp(int); 290 static int iwh_cmd(iwh_sc_t *, int, const void *, int, int); 291 static void iwh_set_led(iwh_sc_t *, uint8_t, uint8_t, uint8_t); 292 static int iwh_hw_set_before_auth(iwh_sc_t *); 293 static int iwh_scan(iwh_sc_t *); 294 static int iwh_config(iwh_sc_t *); 295 static void iwh_stop_master(iwh_sc_t *); 296 static int iwh_power_up(iwh_sc_t *); 297 static int iwh_preinit(iwh_sc_t *); 298 static int iwh_init(iwh_sc_t *); 299 static void iwh_stop(iwh_sc_t *); 300 static void iwh_amrr_init(iwh_amrr_t *); 301 static void iwh_amrr_timeout(iwh_sc_t *); 302 static void iwh_amrr_ratectl(void *, ieee80211_node_t *); 303 static void iwh_ucode_alive(iwh_sc_t *, iwh_rx_desc_t *); 304 static void iwh_rx_phy_intr(iwh_sc_t *, iwh_rx_desc_t *); 305 static void iwh_rx_mpdu_intr(iwh_sc_t *, iwh_rx_desc_t *); 306 static void iwh_release_calib_buffer(iwh_sc_t *); 307 static int iwh_init_common(iwh_sc_t *); 308 static uint8_t *iwh_eep_addr_trans(iwh_sc_t *, uint32_t); 309 static int iwh_put_seg_fw(iwh_sc_t *, uint32_t, uint32_t, uint32_t); 310 static int iwh_alive_common(iwh_sc_t *); 311 static void iwh_save_calib_result(iwh_sc_t *, iwh_rx_desc_t *); 312 static int iwh_tx_power_table(iwh_sc_t *, int); 313 static int iwh_attach(dev_info_t *, ddi_attach_cmd_t); 314 static int iwh_detach(dev_info_t *, ddi_detach_cmd_t); 315 static void iwh_destroy_locks(iwh_sc_t *); 316 static int iwh_send(ieee80211com_t *, mblk_t *, uint8_t); 317 static void iwh_thread(iwh_sc_t *); 318 /* 319 * GLD specific operations 320 */ 321 static int iwh_m_stat(void *, uint_t, uint64_t *); 322 static int iwh_m_start(void *); 323 static void iwh_m_stop(void *); 324 static int iwh_m_unicst(void *, const uint8_t *); 325 static int iwh_m_multicst(void *, boolean_t, const uint8_t *); 326 static int iwh_m_promisc(void *, boolean_t); 327 static mblk_t *iwh_m_tx(void *, mblk_t *); 328 static void iwh_m_ioctl(void *, queue_t *, mblk_t *); 329 330 /* 331 * Supported rates for 802.11b/g modes (in 500Kbps unit). 332 * 11n support will be added later. 333 */ 334 static const struct ieee80211_rateset iwh_rateset_11b = 335 { 4, { 2, 4, 11, 22 } }; 336 337 static const struct ieee80211_rateset iwh_rateset_11g = 338 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 339 340 /* 341 * For mfthread only 342 */ 343 extern pri_t minclsyspri; 344 345 #define DRV_NAME_SP "iwh" 346 347 /* 348 * Module Loading Data & Entry Points 349 */ 350 DDI_DEFINE_STREAM_OPS(iwh_devops, nulldev, nulldev, iwh_attach, 351 iwh_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_supported); 352 353 static struct modldrv iwh_modldrv = { 354 &mod_driverops, 355 "Intel(R) ShirleyPeak driver(N)", 356 &iwh_devops 357 }; 358 359 static struct modlinkage iwh_modlinkage = { 360 MODREV_1, 361 &iwh_modldrv, 362 NULL 363 }; 364 365 int 366 _init(void) 367 { 368 int status; 369 370 status = ddi_soft_state_init(&iwh_soft_state_p, 371 sizeof (iwh_sc_t), 1); 372 if (status != DDI_SUCCESS) { 373 return (status); 374 } 375 376 mac_init_ops(&iwh_devops, DRV_NAME_SP); 377 status = mod_install(&iwh_modlinkage); 378 if (status != DDI_SUCCESS) { 379 mac_fini_ops(&iwh_devops); 380 ddi_soft_state_fini(&iwh_soft_state_p); 381 } 382 383 return (status); 384 } 385 386 int 387 _fini(void) 388 { 389 int status; 390 391 status = mod_remove(&iwh_modlinkage); 392 if (DDI_SUCCESS == status) { 393 mac_fini_ops(&iwh_devops); 394 ddi_soft_state_fini(&iwh_soft_state_p); 395 } 396 397 return (status); 398 } 399 400 int 401 _info(struct modinfo *mip) 402 { 403 return (mod_info(&iwh_modlinkage, mip)); 404 } 405 406 /* 407 * Mac Call Back entries 408 */ 409 mac_callbacks_t iwh_m_callbacks = { 410 MC_IOCTL, 411 iwh_m_stat, 412 iwh_m_start, 413 iwh_m_stop, 414 iwh_m_promisc, 415 iwh_m_multicst, 416 iwh_m_unicst, 417 iwh_m_tx, 418 NULL, 419 iwh_m_ioctl 420 }; 421 422 #ifdef DEBUG 423 void 424 iwh_dbg(uint32_t flags, const char *fmt, ...) 425 { 426 va_list ap; 427 428 if (flags & iwh_dbg_flags) { 429 va_start(ap, fmt); 430 vcmn_err(CE_WARN, fmt, ap); 431 va_end(ap); 432 } 433 } 434 #endif 435 436 /* 437 * device operations 438 */ 439 int 440 iwh_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 441 { 442 iwh_sc_t *sc; 443 ieee80211com_t *ic; 444 int instance, err, i; 445 char strbuf[32]; 446 wifi_data_t wd = { 0 }; 447 mac_register_t *macp; 448 int intr_type; 449 int intr_count; 450 int intr_actual; 451 452 switch (cmd) { 453 case DDI_ATTACH: 454 break; 455 case DDI_RESUME: 456 sc = ddi_get_soft_state(iwh_soft_state_p, 457 ddi_get_instance(dip)); 458 ASSERT(sc != NULL); 459 mutex_enter(&sc->sc_glock); 460 sc->sc_flags &= ~IWH_F_SUSPEND; 461 mutex_exit(&sc->sc_glock); 462 if (sc->sc_flags & IWH_F_RUNNING) { 463 (void) iwh_init(sc); 464 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 465 } 466 IWH_DBG((IWH_DEBUG_RESUME, "iwh: resume\n")); 467 return (DDI_SUCCESS); 468 default: 469 err = DDI_FAILURE; 470 goto attach_fail1; 471 } 472 473 474 instance = ddi_get_instance(dip); 475 err = ddi_soft_state_zalloc(iwh_soft_state_p, instance); 476 if (err != DDI_SUCCESS) { 477 cmn_err(CE_WARN, "iwh_attach(): " 478 "failed to allocate soft state\n"); 479 goto attach_fail1; 480 } 481 sc = ddi_get_soft_state(iwh_soft_state_p, instance); 482 sc->sc_dip = dip; 483 484 /* 485 * map configure space 486 */ 487 err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0, 488 &iwh_reg_accattr, &sc->sc_cfg_handle); 489 if (err != DDI_SUCCESS) { 490 cmn_err(CE_WARN, "iwh_attach(): " 491 "failed to map config spaces regs\n"); 492 goto attach_fail2; 493 } 494 495 496 sc->sc_rev = ddi_get8(sc->sc_cfg_handle, 497 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID)); 498 499 /* 500 * keep from disturbing C3 state of CPU 501 */ 502 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0x41), 0); 503 sc->sc_clsz = ddi_get16(sc->sc_cfg_handle, 504 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 505 if (!sc->sc_clsz) { 506 sc->sc_clsz = 16; 507 } 508 509 /* 510 * determine the size of buffer for frame and command to ucode 511 */ 512 sc->sc_clsz = (sc->sc_clsz << 2); 513 sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) + 514 IEEE80211_MTU + IEEE80211_CRC_LEN + 515 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 516 IEEE80211_WEP_CRCLEN), sc->sc_clsz); 517 518 /* 519 * Map operating registers 520 */ 521 err = ddi_regs_map_setup(dip, 1, &sc->sc_base, 522 0, 0, &iwh_reg_accattr, &sc->sc_handle); 523 if (err != DDI_SUCCESS) { 524 cmn_err(CE_WARN, "iwh_attach(): " 525 "failed to map device regs\n"); 526 goto attach_fail3; 527 } 528 529 /* 530 * this is used to differentiate type of hardware 531 */ 532 sc->sc_hw_rev = IWH_READ(sc, CSR_HW_REV); 533 534 err = ddi_intr_get_supported_types(dip, &intr_type); 535 if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) { 536 cmn_err(CE_WARN, "iwh_attach(): " 537 "fixed type interrupt is not supported\n"); 538 goto attach_fail4; 539 } 540 541 err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count); 542 if ((err != DDI_SUCCESS) || (intr_count != 1)) { 543 cmn_err(CE_WARN, "iwh_attach(): " 544 "no fixed interrupts\n"); 545 goto attach_fail4; 546 } 547 548 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP); 549 550 err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0, 551 intr_count, &intr_actual, 0); 552 if ((err != DDI_SUCCESS) || (intr_actual != 1)) { 553 cmn_err(CE_WARN, "iwh_attach(): " 554 "ddi_intr_alloc() failed 0x%x\n", err); 555 goto attach_fail5; 556 } 557 558 err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri); 559 if (err != DDI_SUCCESS) { 560 cmn_err(CE_WARN, "iwh_attach(): " 561 "ddi_intr_get_pri() failed 0x%x\n", err); 562 goto attach_fail6; 563 } 564 565 mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER, 566 DDI_INTR_PRI(sc->sc_intr_pri)); 567 mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER, 568 DDI_INTR_PRI(sc->sc_intr_pri)); 569 mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER, 570 DDI_INTR_PRI(sc->sc_intr_pri)); 571 mutex_init(&sc->sc_ucode_lock, NULL, MUTEX_DRIVER, 572 DDI_INTR_PRI(sc->sc_intr_pri)); 573 574 575 cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL); 576 cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL); 577 cv_init(&sc->sc_tx_cv, "tx-ring", CV_DRIVER, NULL); 578 cv_init(&sc->sc_put_seg_cv, NULL, CV_DRIVER, NULL); 579 cv_init(&sc->sc_ucode_cv, NULL, CV_DRIVER, NULL); 580 581 /* 582 * initialize the mfthread 583 */ 584 cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL); 585 sc->sc_mf_thread = NULL; 586 sc->sc_mf_thread_switch = 0; 587 588 /* 589 * Allocate shared buffer for communication between driver and ucode. 590 */ 591 err = iwh_alloc_shared(sc); 592 if (err != DDI_SUCCESS) { 593 cmn_err(CE_WARN, "iwh_attach(): " 594 "failed to allocate shared page\n"); 595 goto attach_fail7; 596 } 597 598 (void) memset(sc->sc_shared, 0, sizeof (iwh_shared_t)); 599 600 /* 601 * Allocate keep warm page. 602 */ 603 err = iwh_alloc_kw(sc); 604 if (err != DDI_SUCCESS) { 605 cmn_err(CE_WARN, "iwh_attach(): " 606 "failed to allocate keep warm page\n"); 607 goto attach_fail8; 608 } 609 610 /* 611 * Do some necessary hardware initializations. 612 */ 613 err = iwh_preinit(sc); 614 if (err != IWH_SUCCESS) { 615 cmn_err(CE_WARN, "iwh_attach(): " 616 "failed to initialize hardware\n"); 617 goto attach_fail9; 618 } 619 620 /* 621 * get hardware configurations from eeprom 622 */ 623 err = iwh_eep_load(sc); 624 if (err != 0) { 625 cmn_err(CE_WARN, "iwh_attach(): " 626 "failed to load eeprom\n"); 627 goto attach_fail9; 628 } 629 630 if (IWH_READ_EEP_SHORT(sc, EEP_VERSION) < 0x011a) { 631 IWH_DBG((IWH_DEBUG_EEPROM, "unsupported eeprom detected")); 632 goto attach_fail9; 633 } 634 635 /* 636 * get MAC address of this chipset 637 */ 638 iwh_get_mac_from_eep(sc); 639 640 /* 641 * calibration information from EEPROM 642 */ 643 sc->sc_eep_calib = (struct iwh_eep_calibration *) 644 iwh_eep_addr_trans(sc, EEP_CALIBRATION); 645 646 /* 647 * initialize TX and RX ring buffers 648 */ 649 err = iwh_ring_init(sc); 650 if (err != DDI_SUCCESS) { 651 cmn_err(CE_WARN, "iwh_attach(): " 652 "failed to allocate and initialize ring\n"); 653 goto attach_fail9; 654 } 655 656 sc->sc_hdr = (iwh_firmware_hdr_t *)iwh_fw_bin; 657 658 /* 659 * copy ucode to dma buffer 660 */ 661 err = iwh_alloc_fw_dma(sc); 662 if (err != DDI_SUCCESS) { 663 cmn_err(CE_WARN, "iwh_attach(): " 664 "failed to allocate firmware dma\n"); 665 goto attach_fail10; 666 } 667 668 /* 669 * Initialize the wifi part, which will be used by 670 * 802.11 module 671 */ 672 ic = &sc->sc_ic; 673 ic->ic_phytype = IEEE80211_T_OFDM; 674 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 675 ic->ic_state = IEEE80211_S_INIT; 676 ic->ic_maxrssi = 100; /* experimental number */ 677 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT | 678 IEEE80211_C_PMGT | IEEE80211_C_SHSLOT; 679 680 /* 681 * use software WEP and TKIP, hardware CCMP; 682 */ 683 ic->ic_caps |= IEEE80211_C_AES_CCM; 684 685 /* 686 * Support WPA/WPA2 687 */ 688 ic->ic_caps |= IEEE80211_C_WPA; 689 690 /* 691 * set supported .11b and .11g rates 692 */ 693 ic->ic_sup_rates[IEEE80211_MODE_11B] = iwh_rateset_11b; 694 ic->ic_sup_rates[IEEE80211_MODE_11G] = iwh_rateset_11g; 695 696 /* 697 * set supported .11b and .11g channels (1 through 14) 698 */ 699 for (i = 1; i <= 14; i++) { 700 ic->ic_sup_channels[i].ich_freq = 701 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 702 ic->ic_sup_channels[i].ich_flags = 703 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 704 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 705 } 706 707 ic->ic_ibss_chan = &ic->ic_sup_channels[0]; 708 ic->ic_xmit = iwh_send; 709 710 /* 711 * attach to 802.11 module 712 */ 713 ieee80211_attach(ic); 714 715 /* 716 * different instance has different WPA door 717 */ 718 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR, 719 ddi_driver_name(dip), 720 ddi_get_instance(dip)); 721 722 /* 723 * Override 80211 default routines 724 */ 725 sc->sc_newstate = ic->ic_newstate; 726 ic->ic_newstate = iwh_newstate; 727 ic->ic_node_alloc = iwh_node_alloc; 728 ic->ic_node_free = iwh_node_free; 729 ic->ic_crypto.cs_key_set = iwh_key_set; 730 731 /* 732 * initialize 802.11 module 733 */ 734 ieee80211_media_init(ic); 735 736 /* 737 * initialize default tx key 738 */ 739 ic->ic_def_txkey = 0; 740 741 err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX, 742 iwh_rx_softintr, (caddr_t)sc); 743 if (err != DDI_SUCCESS) { 744 cmn_err(CE_WARN, "iwh_attach(): " 745 "add soft interrupt failed\n"); 746 goto attach_fail12; 747 } 748 749 err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwh_intr, 750 (caddr_t)sc, NULL); 751 if (err != DDI_SUCCESS) { 752 cmn_err(CE_WARN, "iwh_attach(): " 753 "ddi_intr_add_handle() failed\n"); 754 goto attach_fail13; 755 } 756 757 err = ddi_intr_enable(sc->sc_intr_htable[0]); 758 if (err != DDI_SUCCESS) { 759 cmn_err(CE_WARN, "iwh_attach(): " 760 "ddi_intr_enable() failed\n"); 761 goto attach_fail14; 762 } 763 764 /* 765 * Initialize pointer to device specific functions 766 */ 767 wd.wd_secalloc = WIFI_SEC_NONE; 768 wd.wd_opmode = ic->ic_opmode; 769 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr); 770 771 /* 772 * create relation to GLD 773 */ 774 macp = mac_alloc(MAC_VERSION); 775 if (err != DDI_SUCCESS) { 776 cmn_err(CE_WARN, "iwh_attach(): " 777 "failed to do mac_alloc()\n"); 778 goto attach_fail15; 779 } 780 781 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 782 macp->m_driver = sc; 783 macp->m_dip = dip; 784 macp->m_src_addr = ic->ic_macaddr; 785 macp->m_callbacks = &iwh_m_callbacks; 786 macp->m_min_sdu = 0; 787 macp->m_max_sdu = IEEE80211_MTU; 788 macp->m_pdata = &wd; 789 macp->m_pdata_size = sizeof (wd); 790 791 /* 792 * Register the macp to mac 793 */ 794 err = mac_register(macp, &ic->ic_mach); 795 mac_free(macp); 796 if (err != DDI_SUCCESS) { 797 cmn_err(CE_WARN, "iwh_attach(): " 798 "failed to do mac_register()\n"); 799 goto attach_fail15; 800 } 801 802 /* 803 * Create minor node of type DDI_NT_NET_WIFI 804 */ 805 (void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_SP"%d", instance); 806 err = ddi_create_minor_node(dip, strbuf, S_IFCHR, 807 instance + 1, DDI_NT_NET_WIFI, 0); 808 if (err != DDI_SUCCESS) 809 cmn_err(CE_WARN, "iwh_attach(): " 810 "failed to do ddi_create_minor_node()\n"); 811 812 /* 813 * Notify link is down now 814 */ 815 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 816 817 /* 818 * create the mf thread to handle the link status, 819 * recovery fatal error, etc. 820 */ 821 sc->sc_mf_thread_switch = 1; 822 if (NULL == sc->sc_mf_thread) { 823 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0, 824 iwh_thread, sc, 0, &p0, TS_RUN, minclsyspri); 825 } 826 827 sc->sc_flags |= IWH_F_ATTACHED; 828 829 return (DDI_SUCCESS); 830 831 attach_fail15: 832 (void) ddi_intr_disable(sc->sc_intr_htable[0]); 833 834 attach_fail14: 835 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 836 837 attach_fail13: 838 (void) ddi_intr_remove_softint(sc->sc_soft_hdl); 839 sc->sc_soft_hdl = NULL; 840 841 attach_fail12: 842 ieee80211_detach(ic); 843 844 attach_fail11: 845 iwh_free_fw_dma(sc); 846 847 attach_fail10: 848 iwh_ring_free(sc); 849 850 attach_fail9: 851 iwh_free_kw(sc); 852 853 attach_fail8: 854 iwh_free_shared(sc); 855 856 attach_fail7: 857 iwh_destroy_locks(sc); 858 859 attach_fail6: 860 (void) ddi_intr_free(sc->sc_intr_htable[0]); 861 862 attach_fail5: 863 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 864 865 attach_fail4: 866 ddi_regs_map_free(&sc->sc_handle); 867 868 attach_fail3: 869 ddi_regs_map_free(&sc->sc_cfg_handle); 870 871 attach_fail2: 872 ddi_soft_state_free(iwh_soft_state_p, instance); 873 874 attach_fail1: 875 return (err); 876 } 877 878 int 879 iwh_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 880 { 881 iwh_sc_t *sc; 882 int err; 883 884 sc = ddi_get_soft_state(iwh_soft_state_p, ddi_get_instance(dip)); 885 ASSERT(sc != NULL); 886 887 switch (cmd) { 888 case DDI_DETACH: 889 break; 890 case DDI_SUSPEND: 891 if (sc->sc_flags & IWH_F_RUNNING) { 892 iwh_stop(sc); 893 } 894 mutex_enter(&sc->sc_glock); 895 sc->sc_flags |= IWH_F_SUSPEND; 896 mutex_exit(&sc->sc_glock); 897 IWH_DBG((IWH_DEBUG_RESUME, "iwh: suspend\n")); 898 return (DDI_SUCCESS); 899 default: 900 return (DDI_FAILURE); 901 } 902 903 if (!(sc->sc_flags & IWH_F_ATTACHED)) { 904 return (DDI_FAILURE); 905 } 906 err = mac_disable(sc->sc_ic.ic_mach); 907 if (err != DDI_SUCCESS) 908 return (err); 909 910 /* 911 * Destroy the mf_thread 912 */ 913 mutex_enter(&sc->sc_mt_lock); 914 sc->sc_mf_thread_switch = 0; 915 while (sc->sc_mf_thread != NULL) { 916 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0) { 917 break; 918 } 919 } 920 921 mutex_exit(&sc->sc_mt_lock); 922 923 /* 924 * stop chipset 925 */ 926 iwh_stop(sc); 927 928 DELAY(500000); 929 930 /* 931 * release buffer for calibration 932 */ 933 iwh_release_calib_buffer(sc); 934 935 /* 936 * Unregiste from GLD 937 */ 938 (void) mac_unregister(sc->sc_ic.ic_mach); 939 940 mutex_enter(&sc->sc_glock); 941 iwh_free_fw_dma(sc); 942 iwh_ring_free(sc); 943 iwh_free_kw(sc); 944 iwh_free_shared(sc); 945 mutex_exit(&sc->sc_glock); 946 947 948 (void) ddi_intr_disable(sc->sc_intr_htable[0]); 949 (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 950 (void) ddi_intr_free(sc->sc_intr_htable[0]); 951 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 952 953 (void) ddi_intr_remove_softint(sc->sc_soft_hdl); 954 sc->sc_soft_hdl = NULL; 955 956 957 /* 958 * detach from 80211 module 959 */ 960 ieee80211_detach(&sc->sc_ic); 961 962 iwh_destroy_locks(sc); 963 964 ddi_regs_map_free(&sc->sc_handle); 965 ddi_regs_map_free(&sc->sc_cfg_handle); 966 ddi_remove_minor_node(dip, NULL); 967 ddi_soft_state_free(iwh_soft_state_p, ddi_get_instance(dip)); 968 969 return (DDI_SUCCESS); 970 } 971 972 /* 973 * destroy all locks 974 */ 975 static void 976 iwh_destroy_locks(iwh_sc_t *sc) 977 { 978 cv_destroy(&sc->sc_mt_cv); 979 cv_destroy(&sc->sc_tx_cv); 980 cv_destroy(&sc->sc_cmd_cv); 981 cv_destroy(&sc->sc_fw_cv); 982 cv_destroy(&sc->sc_put_seg_cv); 983 cv_destroy(&sc->sc_ucode_cv); 984 mutex_destroy(&sc->sc_mt_lock); 985 mutex_destroy(&sc->sc_tx_lock); 986 mutex_destroy(&sc->sc_glock); 987 mutex_destroy(&sc->sc_ucode_lock); 988 } 989 990 /* 991 * Allocate an area of memory and a DMA handle for accessing it 992 */ 993 static int 994 iwh_alloc_dma_mem(iwh_sc_t *sc, size_t memsize, 995 ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p, 996 uint_t dma_flags, iwh_dma_t *dma_p) 997 { 998 caddr_t vaddr; 999 int err; 1000 1001 /* 1002 * Allocate handle 1003 */ 1004 err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p, 1005 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 1006 if (err != DDI_SUCCESS) { 1007 dma_p->dma_hdl = NULL; 1008 return (DDI_FAILURE); 1009 } 1010 1011 /* 1012 * Allocate memory 1013 */ 1014 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p, 1015 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 1016 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl); 1017 if (err != DDI_SUCCESS) { 1018 ddi_dma_free_handle(&dma_p->dma_hdl); 1019 dma_p->dma_hdl = NULL; 1020 dma_p->acc_hdl = NULL; 1021 return (DDI_FAILURE); 1022 } 1023 1024 /* 1025 * Bind the two together 1026 */ 1027 dma_p->mem_va = vaddr; 1028 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 1029 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL, 1030 &dma_p->cookie, &dma_p->ncookies); 1031 if (err != DDI_DMA_MAPPED) { 1032 ddi_dma_mem_free(&dma_p->acc_hdl); 1033 ddi_dma_free_handle(&dma_p->dma_hdl); 1034 dma_p->acc_hdl = NULL; 1035 dma_p->dma_hdl = NULL; 1036 return (DDI_FAILURE); 1037 } 1038 1039 dma_p->nslots = ~0U; 1040 dma_p->size = ~0U; 1041 dma_p->token = ~0U; 1042 dma_p->offset = 0; 1043 return (DDI_SUCCESS); 1044 } 1045 1046 /* 1047 * Free one allocated area of DMAable memory 1048 */ 1049 static void 1050 iwh_free_dma_mem(iwh_dma_t *dma_p) 1051 { 1052 if (dma_p->dma_hdl != NULL) { 1053 if (dma_p->ncookies) { 1054 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 1055 dma_p->ncookies = 0; 1056 } 1057 ddi_dma_free_handle(&dma_p->dma_hdl); 1058 dma_p->dma_hdl = NULL; 1059 } 1060 1061 if (dma_p->acc_hdl != NULL) { 1062 ddi_dma_mem_free(&dma_p->acc_hdl); 1063 dma_p->acc_hdl = NULL; 1064 } 1065 } 1066 1067 /* 1068 * copy ucode into dma buffers 1069 */ 1070 static int 1071 iwh_alloc_fw_dma(iwh_sc_t *sc) 1072 { 1073 int err = DDI_SUCCESS; 1074 iwh_dma_t *dma_p; 1075 char *t; 1076 1077 /* 1078 * firmware image layout: 1079 * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->| 1080 */ 1081 1082 /* 1083 * copy text of runtime ucode 1084 */ 1085 t = (char *)(sc->sc_hdr + 1); 1086 err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz), 1087 &fw_dma_attr, &iwh_dma_accattr, 1088 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1089 &sc->sc_dma_fw_text); 1090 1091 dma_p = &sc->sc_dma_fw_text; 1092 1093 IWH_DBG((IWH_DEBUG_DMA, "text[ncookies:%d addr:%lx size:%lx]\n", 1094 dma_p->ncookies, dma_p->cookie.dmac_address, 1095 dma_p->cookie.dmac_size)); 1096 1097 if (err != DDI_SUCCESS) { 1098 cmn_err(CE_WARN, "iwh_alloc_fw_dma(): " 1099 "failed to allocate text dma memory.\n"); 1100 goto fail; 1101 } 1102 1103 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->textsz)); 1104 1105 /* 1106 * copy data and bak-data of runtime ucode 1107 */ 1108 t += LE_32(sc->sc_hdr->textsz); 1109 err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz), 1110 &fw_dma_attr, &iwh_dma_accattr, 1111 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1112 &sc->sc_dma_fw_data); 1113 1114 dma_p = &sc->sc_dma_fw_data; 1115 1116 IWH_DBG((IWH_DEBUG_DMA, "data[ncookies:%d addr:%lx size:%lx]\n", 1117 dma_p->ncookies, dma_p->cookie.dmac_address, 1118 dma_p->cookie.dmac_size)); 1119 1120 if (err != DDI_SUCCESS) { 1121 cmn_err(CE_WARN, "iwh_alloc_fw_dma(): " 1122 "failed to allocate data dma memory\n"); 1123 goto fail; 1124 } 1125 1126 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz)); 1127 1128 err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz), 1129 &fw_dma_attr, &iwh_dma_accattr, 1130 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1131 &sc->sc_dma_fw_data_bak); 1132 1133 dma_p = &sc->sc_dma_fw_data_bak; 1134 1135 IWH_DBG((IWH_DEBUG_DMA, "data_bak[ncookies:%d addr:%lx " 1136 "size:%lx]\n", 1137 dma_p->ncookies, dma_p->cookie.dmac_address, 1138 dma_p->cookie.dmac_size)); 1139 1140 if (err != DDI_SUCCESS) { 1141 cmn_err(CE_WARN, "iwh_alloc_fw_dma(): " 1142 "failed to allocate data bakup dma memory\n"); 1143 goto fail; 1144 } 1145 1146 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz)); 1147 1148 /* 1149 * copy text of init ucode 1150 */ 1151 t += LE_32(sc->sc_hdr->datasz); 1152 err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz), 1153 &fw_dma_attr, &iwh_dma_accattr, 1154 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1155 &sc->sc_dma_fw_init_text); 1156 1157 dma_p = &sc->sc_dma_fw_init_text; 1158 1159 IWH_DBG((IWH_DEBUG_DMA, "init_text[ncookies:%d addr:%lx " 1160 "size:%lx]\n", 1161 dma_p->ncookies, dma_p->cookie.dmac_address, 1162 dma_p->cookie.dmac_size)); 1163 1164 if (err != DDI_SUCCESS) { 1165 cmn_err(CE_WARN, "iwh_alloc_fw_dma(): " 1166 "failed to allocate init text dma memory\n"); 1167 goto fail; 1168 } 1169 1170 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_textsz)); 1171 1172 /* 1173 * copy data of init ucode 1174 */ 1175 t += LE_32(sc->sc_hdr->init_textsz); 1176 err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz), 1177 &fw_dma_attr, &iwh_dma_accattr, 1178 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1179 &sc->sc_dma_fw_init_data); 1180 1181 dma_p = &sc->sc_dma_fw_init_data; 1182 1183 IWH_DBG((IWH_DEBUG_DMA, "init_data[ncookies:%d addr:%lx " 1184 "size:%lx]\n", 1185 dma_p->ncookies, dma_p->cookie.dmac_address, 1186 dma_p->cookie.dmac_size)); 1187 1188 if (err != DDI_SUCCESS) { 1189 cmn_err(CE_WARN, "iwh_alloc_fw_dma(): " 1190 "failed to allocate init data dma memory\n"); 1191 goto fail; 1192 } 1193 1194 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_datasz)); 1195 1196 sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz); 1197 fail: 1198 return (err); 1199 } 1200 1201 static void 1202 iwh_free_fw_dma(iwh_sc_t *sc) 1203 { 1204 iwh_free_dma_mem(&sc->sc_dma_fw_text); 1205 iwh_free_dma_mem(&sc->sc_dma_fw_data); 1206 iwh_free_dma_mem(&sc->sc_dma_fw_data_bak); 1207 iwh_free_dma_mem(&sc->sc_dma_fw_init_text); 1208 iwh_free_dma_mem(&sc->sc_dma_fw_init_data); 1209 } 1210 1211 /* 1212 * Allocate a shared buffer between host and NIC. 1213 */ 1214 static int 1215 iwh_alloc_shared(iwh_sc_t *sc) 1216 { 1217 #ifdef DEBUG 1218 iwh_dma_t *dma_p; 1219 #endif 1220 int err = DDI_SUCCESS; 1221 1222 /* 1223 * must be aligned on a 4K-page boundary 1224 */ 1225 err = iwh_alloc_dma_mem(sc, sizeof (iwh_shared_t), 1226 &sh_dma_attr, &iwh_dma_accattr, 1227 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1228 &sc->sc_dma_sh); 1229 if (err != DDI_SUCCESS) { 1230 goto fail; 1231 } 1232 1233 sc->sc_shared = (iwh_shared_t *)sc->sc_dma_sh.mem_va; 1234 1235 #ifdef DEBUG 1236 dma_p = &sc->sc_dma_sh; 1237 #endif 1238 IWH_DBG((IWH_DEBUG_DMA, "sh[ncookies:%d addr:%lx size:%lx]\n", 1239 dma_p->ncookies, dma_p->cookie.dmac_address, 1240 dma_p->cookie.dmac_size)); 1241 1242 return (err); 1243 fail: 1244 iwh_free_shared(sc); 1245 return (err); 1246 } 1247 1248 static void 1249 iwh_free_shared(iwh_sc_t *sc) 1250 { 1251 iwh_free_dma_mem(&sc->sc_dma_sh); 1252 } 1253 1254 /* 1255 * Allocate a keep warm page. 1256 */ 1257 static int 1258 iwh_alloc_kw(iwh_sc_t *sc) 1259 { 1260 #ifdef DEBUG 1261 iwh_dma_t *dma_p; 1262 #endif 1263 int err = DDI_SUCCESS; 1264 1265 /* 1266 * must be aligned on a 4K-page boundary 1267 */ 1268 err = iwh_alloc_dma_mem(sc, IWH_KW_SIZE, 1269 &kw_dma_attr, &iwh_dma_accattr, 1270 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1271 &sc->sc_dma_kw); 1272 if (err != DDI_SUCCESS) { 1273 goto fail; 1274 } 1275 1276 #ifdef DEBUG 1277 dma_p = &sc->sc_dma_kw; 1278 #endif 1279 IWH_DBG((IWH_DEBUG_DMA, "kw[ncookies:%d addr:%lx size:%lx]\n", 1280 dma_p->ncookies, dma_p->cookie.dmac_address, 1281 dma_p->cookie.dmac_size)); 1282 1283 return (err); 1284 fail: 1285 iwh_free_kw(sc); 1286 return (err); 1287 } 1288 1289 static void 1290 iwh_free_kw(iwh_sc_t *sc) 1291 { 1292 iwh_free_dma_mem(&sc->sc_dma_kw); 1293 } 1294 1295 /* 1296 * initialize RX ring buffers 1297 */ 1298 static int 1299 iwh_alloc_rx_ring(iwh_sc_t *sc) 1300 { 1301 iwh_rx_ring_t *ring; 1302 iwh_rx_data_t *data; 1303 #ifdef DEBUG 1304 iwh_dma_t *dma_p; 1305 #endif 1306 int i, err = DDI_SUCCESS; 1307 1308 ring = &sc->sc_rxq; 1309 ring->cur = 0; 1310 1311 /* 1312 * allocate RX description ring buffer 1313 */ 1314 err = iwh_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t), 1315 &ring_desc_dma_attr, &iwh_dma_accattr, 1316 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1317 &ring->dma_desc); 1318 if (err != DDI_SUCCESS) { 1319 IWH_DBG((IWH_DEBUG_DMA, "dma alloc rx ring desc " 1320 "failed\n")); 1321 goto fail; 1322 } 1323 1324 ring->desc = (uint32_t *)ring->dma_desc.mem_va; 1325 #ifdef DEBUG 1326 dma_p = &ring->dma_desc; 1327 #endif 1328 IWH_DBG((IWH_DEBUG_DMA, "rx bd[ncookies:%d addr:%lx size:%lx]\n", 1329 dma_p->ncookies, dma_p->cookie.dmac_address, 1330 dma_p->cookie.dmac_size)); 1331 1332 /* 1333 * Allocate Rx frame buffers. 1334 */ 1335 for (i = 0; i < RX_QUEUE_SIZE; i++) { 1336 data = &ring->data[i]; 1337 err = iwh_alloc_dma_mem(sc, sc->sc_dmabuf_sz, 1338 &rx_buffer_dma_attr, &iwh_dma_accattr, 1339 DDI_DMA_READ | DDI_DMA_STREAMING, 1340 &data->dma_data); 1341 if (err != DDI_SUCCESS) { 1342 IWH_DBG((IWH_DEBUG_DMA, "dma alloc rx ring " 1343 "buf[%d] failed\n", i)); 1344 goto fail; 1345 } 1346 /* 1347 * the physical address bit [8-36] are used, 1348 * instead of bit [0-31] in 3945. 1349 */ 1350 ring->desc[i] = LE_32((uint32_t) 1351 (data->dma_data.cookie.dmac_address >> 8)); 1352 } 1353 1354 #ifdef DEBUG 1355 dma_p = &ring->data[0].dma_data; 1356 #endif 1357 IWH_DBG((IWH_DEBUG_DMA, "rx buffer[0][ncookies:%d addr:%lx " 1358 "size:%lx]\n", 1359 dma_p->ncookies, dma_p->cookie.dmac_address, 1360 dma_p->cookie.dmac_size)); 1361 1362 IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 1363 1364 return (err); 1365 1366 fail: 1367 iwh_free_rx_ring(sc); 1368 return (err); 1369 } 1370 1371 /* 1372 * disable RX ring 1373 */ 1374 static void 1375 iwh_reset_rx_ring(iwh_sc_t *sc) 1376 { 1377 int n; 1378 1379 iwh_mac_access_enter(sc); 1380 IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 1381 for (n = 0; n < 2000; n++) { 1382 if (IWH_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24)) { 1383 break; 1384 } 1385 DELAY(1000); 1386 } 1387 #ifdef DEBUG 1388 if (2000 == n) { 1389 IWH_DBG((IWH_DEBUG_DMA, "timeout resetting Rx ring\n")); 1390 } 1391 #endif 1392 iwh_mac_access_exit(sc); 1393 1394 sc->sc_rxq.cur = 0; 1395 } 1396 1397 static void 1398 iwh_free_rx_ring(iwh_sc_t *sc) 1399 { 1400 int i; 1401 1402 for (i = 0; i < RX_QUEUE_SIZE; i++) { 1403 if (sc->sc_rxq.data[i].dma_data.dma_hdl) { 1404 IWH_DMA_SYNC(sc->sc_rxq.data[i].dma_data, 1405 DDI_DMA_SYNC_FORCPU); 1406 } 1407 1408 iwh_free_dma_mem(&sc->sc_rxq.data[i].dma_data); 1409 } 1410 1411 if (sc->sc_rxq.dma_desc.dma_hdl) { 1412 IWH_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV); 1413 } 1414 1415 iwh_free_dma_mem(&sc->sc_rxq.dma_desc); 1416 } 1417 1418 /* 1419 * initialize TX ring buffers 1420 */ 1421 static int 1422 iwh_alloc_tx_ring(iwh_sc_t *sc, iwh_tx_ring_t *ring, 1423 int slots, int qid) 1424 { 1425 iwh_tx_data_t *data; 1426 iwh_tx_desc_t *desc_h; 1427 uint32_t paddr_desc_h; 1428 iwh_cmd_t *cmd_h; 1429 uint32_t paddr_cmd_h; 1430 #ifdef DEBUG 1431 iwh_dma_t *dma_p; 1432 #endif 1433 int i, err = DDI_SUCCESS; 1434 1435 ring->qid = qid; 1436 ring->count = TFD_QUEUE_SIZE_MAX; 1437 ring->window = slots; 1438 ring->queued = 0; 1439 ring->cur = 0; 1440 1441 /* 1442 * allocate buffer for TX descriptor ring 1443 */ 1444 err = iwh_alloc_dma_mem(sc, 1445 TFD_QUEUE_SIZE_MAX * sizeof (iwh_tx_desc_t), 1446 &ring_desc_dma_attr, &iwh_dma_accattr, 1447 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1448 &ring->dma_desc); 1449 if (err != DDI_SUCCESS) { 1450 IWH_DBG((IWH_DEBUG_DMA, "dma alloc tx ring desc[%d]" 1451 " failed\n", qid)); 1452 goto fail; 1453 } 1454 1455 #ifdef DEBUG 1456 dma_p = &ring->dma_desc; 1457 #endif 1458 IWH_DBG((IWH_DEBUG_DMA, "tx bd[ncookies:%d addr:%lx size:%lx]\n", 1459 dma_p->ncookies, dma_p->cookie.dmac_address, 1460 dma_p->cookie.dmac_size)); 1461 1462 desc_h = (iwh_tx_desc_t *)ring->dma_desc.mem_va; 1463 paddr_desc_h = ring->dma_desc.cookie.dmac_address; 1464 1465 /* 1466 * allocate buffer for ucode command 1467 */ 1468 err = iwh_alloc_dma_mem(sc, 1469 TFD_QUEUE_SIZE_MAX * sizeof (iwh_cmd_t), 1470 &cmd_dma_attr, &iwh_dma_accattr, 1471 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1472 &ring->dma_cmd); 1473 if (err != DDI_SUCCESS) { 1474 IWH_DBG((IWH_DEBUG_DMA, "dma alloc tx ring cmd[%d]" 1475 " failed\n", qid)); 1476 goto fail; 1477 } 1478 1479 #ifdef DEBUG 1480 dma_p = &ring->dma_cmd; 1481 #endif 1482 IWH_DBG((IWH_DEBUG_DMA, "tx cmd[ncookies:%d addr:%lx size:%lx]\n", 1483 dma_p->ncookies, dma_p->cookie.dmac_address, 1484 dma_p->cookie.dmac_size)); 1485 1486 cmd_h = (iwh_cmd_t *)ring->dma_cmd.mem_va; 1487 paddr_cmd_h = ring->dma_cmd.cookie.dmac_address; 1488 1489 /* 1490 * Allocate Tx frame buffers. 1491 */ 1492 ring->data = kmem_zalloc(sizeof (iwh_tx_data_t) * TFD_QUEUE_SIZE_MAX, 1493 KM_NOSLEEP); 1494 if (NULL == ring->data) { 1495 IWH_DBG((IWH_DEBUG_DMA, "could not allocate " 1496 "tx data slots\n")); 1497 goto fail; 1498 } 1499 1500 for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) { 1501 data = &ring->data[i]; 1502 err = iwh_alloc_dma_mem(sc, sc->sc_dmabuf_sz, 1503 &tx_buffer_dma_attr, &iwh_dma_accattr, 1504 DDI_DMA_WRITE | DDI_DMA_STREAMING, 1505 &data->dma_data); 1506 if (err != DDI_SUCCESS) { 1507 IWH_DBG((IWH_DEBUG_DMA, "dma alloc tx " 1508 "ring buf[%d] failed\n", i)); 1509 goto fail; 1510 } 1511 1512 data->desc = desc_h + i; 1513 data->paddr_desc = paddr_desc_h + 1514 _PTRDIFF(data->desc, desc_h); 1515 data->cmd = cmd_h + i; /* (i % slots); */ 1516 data->paddr_cmd = paddr_cmd_h + 1517 _PTRDIFF(data->cmd, cmd_h); 1518 /* ((i % slots) * sizeof (iwh_cmd_t)); */ 1519 } 1520 #ifdef DEBUG 1521 dma_p = &ring->data[0].dma_data; 1522 #endif 1523 IWH_DBG((IWH_DEBUG_DMA, "tx buffer[0][ncookies:%d addr:%lx " 1524 "size:%lx]\n", 1525 dma_p->ncookies, dma_p->cookie.dmac_address, 1526 dma_p->cookie.dmac_size)); 1527 1528 return (err); 1529 1530 fail: 1531 if (ring->data) { 1532 kmem_free(ring->data, 1533 sizeof (iwh_tx_data_t) * TFD_QUEUE_SIZE_MAX); 1534 } 1535 1536 iwh_free_tx_ring(ring); 1537 1538 return (err); 1539 } 1540 1541 /* 1542 * disable TX ring 1543 */ 1544 static void 1545 iwh_reset_tx_ring(iwh_sc_t *sc, iwh_tx_ring_t *ring) 1546 { 1547 iwh_tx_data_t *data; 1548 int i, n; 1549 1550 iwh_mac_access_enter(sc); 1551 1552 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0); 1553 for (n = 0; n < 200; n++) { 1554 if (IWH_READ(sc, IWH_FH_TSSR_TX_STATUS_REG) & 1555 IWH_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid)) { 1556 break; 1557 } 1558 DELAY(10); 1559 } 1560 #ifdef DEBUG 1561 if (200 == n && iwh_dbg_flags > 0) { 1562 IWH_DBG((IWH_DEBUG_DMA, "timeout reset tx ring %d\n", 1563 ring->qid)); 1564 } 1565 #endif 1566 iwh_mac_access_exit(sc); 1567 1568 for (i = 0; i < ring->count; i++) { 1569 data = &ring->data[i]; 1570 IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 1571 } 1572 1573 ring->queued = 0; 1574 ring->cur = 0; 1575 } 1576 1577 static void 1578 iwh_free_tx_ring(iwh_tx_ring_t *ring) 1579 { 1580 int i; 1581 1582 if (ring->dma_desc.dma_hdl != NULL) { 1583 IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 1584 } 1585 iwh_free_dma_mem(&ring->dma_desc); 1586 1587 if (ring->dma_cmd.dma_hdl != NULL) { 1588 IWH_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV); 1589 } 1590 iwh_free_dma_mem(&ring->dma_cmd); 1591 1592 if (ring->data != NULL) { 1593 for (i = 0; i < ring->count; i++) { 1594 if (ring->data[i].dma_data.dma_hdl) { 1595 IWH_DMA_SYNC(ring->data[i].dma_data, 1596 DDI_DMA_SYNC_FORDEV); 1597 } 1598 iwh_free_dma_mem(&ring->data[i].dma_data); 1599 } 1600 kmem_free(ring->data, ring->count * sizeof (iwh_tx_data_t)); 1601 } 1602 } 1603 1604 /* 1605 * initialize TX and RX ring 1606 */ 1607 static int 1608 iwh_ring_init(iwh_sc_t *sc) 1609 { 1610 int i, err = DDI_SUCCESS; 1611 1612 for (i = 0; i < IWH_NUM_QUEUES; i++) { 1613 if (IWH_CMD_QUEUE_NUM == i) { 1614 continue; 1615 } 1616 1617 err = iwh_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS, 1618 i); 1619 if (err != DDI_SUCCESS) { 1620 goto fail; 1621 } 1622 } 1623 1624 /* 1625 * initialize command queue 1626 */ 1627 err = iwh_alloc_tx_ring(sc, &sc->sc_txq[IWH_CMD_QUEUE_NUM], 1628 TFD_CMD_SLOTS, IWH_CMD_QUEUE_NUM); 1629 if (err != DDI_SUCCESS) { 1630 goto fail; 1631 } 1632 1633 err = iwh_alloc_rx_ring(sc); 1634 if (err != DDI_SUCCESS) { 1635 goto fail; 1636 } 1637 1638 return (err); 1639 1640 fail: 1641 return (err); 1642 } 1643 1644 static void 1645 iwh_ring_free(iwh_sc_t *sc) 1646 { 1647 int i = IWH_NUM_QUEUES; 1648 1649 iwh_free_rx_ring(sc); 1650 while (--i >= 0) { 1651 iwh_free_tx_ring(&sc->sc_txq[i]); 1652 } 1653 } 1654 1655 /* 1656 * allocate buffer for a node 1657 */ 1658 /*ARGSUSED*/ 1659 static ieee80211_node_t * 1660 iwh_node_alloc(ieee80211com_t *ic) 1661 { 1662 iwh_amrr_t *amrr; 1663 1664 amrr = kmem_zalloc(sizeof (iwh_amrr_t), KM_SLEEP); 1665 if (amrr != NULL) { 1666 iwh_amrr_init(amrr); 1667 } 1668 1669 return (&amrr->in); 1670 } 1671 1672 static void 1673 iwh_node_free(ieee80211_node_t *in) 1674 { 1675 ieee80211com_t *ic = in->in_ic; 1676 1677 ic->ic_node_cleanup(in); 1678 if (in->in_wpa_ie != NULL) { 1679 ieee80211_free(in->in_wpa_ie); 1680 } 1681 1682 kmem_free(in, sizeof (iwh_amrr_t)); 1683 } 1684 1685 /* 1686 * change station's state. this function will be invoked by 80211 module 1687 * when need to change staton's state. 1688 */ 1689 static int 1690 iwh_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 1691 { 1692 iwh_sc_t *sc = (iwh_sc_t *)ic; 1693 ieee80211_node_t *in = ic->ic_bss; 1694 enum ieee80211_state ostate = ic->ic_state; 1695 int i, err = IWH_SUCCESS; 1696 1697 mutex_enter(&sc->sc_glock); 1698 1699 switch (nstate) { 1700 case IEEE80211_S_SCAN: 1701 ic->ic_state = nstate; 1702 if (IEEE80211_S_INIT == ostate) { 1703 ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN; 1704 /* let LED blink when scanning */ 1705 iwh_set_led(sc, 2, 10, 2); 1706 1707 if ((err = iwh_scan(sc)) != 0) { 1708 IWH_DBG((IWH_DEBUG_80211, 1709 "could not initiate scan\n")); 1710 ic->ic_flags &= ~(IEEE80211_F_SCAN | 1711 IEEE80211_F_ASCAN); 1712 ic->ic_state = ostate; 1713 mutex_exit(&sc->sc_glock); 1714 return (err); 1715 } 1716 } 1717 sc->sc_clk = 0; 1718 mutex_exit(&sc->sc_glock); 1719 return (IWH_SUCCESS); 1720 1721 case IEEE80211_S_AUTH: 1722 /* 1723 * reset state to handle reassociations correctly 1724 */ 1725 sc->sc_config.assoc_id = 0; 1726 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK); 1727 1728 /* 1729 * before sending authentication and association request frame, 1730 * we need do something in the hardware, such as setting the 1731 * channel same to the target AP... 1732 */ 1733 if ((err = iwh_hw_set_before_auth(sc)) != 0) { 1734 IWH_DBG((IWH_DEBUG_80211, 1735 "could not send authentication request\n")); 1736 mutex_exit(&sc->sc_glock); 1737 return (err); 1738 } 1739 break; 1740 1741 case IEEE80211_S_RUN: 1742 if (IEEE80211_M_MONITOR == ic->ic_opmode) { 1743 /* let LED blink when monitoring */ 1744 iwh_set_led(sc, 2, 10, 10); 1745 break; 1746 } 1747 1748 IWH_DBG((IWH_DEBUG_80211, "iwh: associated.")); 1749 1750 1751 /* 1752 * update adapter's configuration 1753 */ 1754 sc->sc_config.assoc_id = sc->sc_assoc_id & 0x3fff; 1755 1756 /* 1757 * short preamble/slot time are 1758 * negotiated when associating 1759 */ 1760 sc->sc_config.flags &= 1761 ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 1762 RXON_FLG_SHORT_SLOT_MSK); 1763 1764 if (ic->ic_flags & IEEE80211_F_SHSLOT) { 1765 sc->sc_config.flags |= 1766 LE_32(RXON_FLG_SHORT_SLOT_MSK); 1767 } 1768 1769 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { 1770 sc->sc_config.flags |= 1771 LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 1772 } 1773 1774 sc->sc_config.filter_flags |= 1775 LE_32(RXON_FILTER_ASSOC_MSK); 1776 1777 if (ic->ic_opmode != IEEE80211_M_STA) { 1778 sc->sc_config.filter_flags |= 1779 LE_32(RXON_FILTER_BCON_AWARE_MSK); 1780 } 1781 1782 IWH_DBG((IWH_DEBUG_80211, "config chan %d flags %x" 1783 " filter_flags %x\n", 1784 sc->sc_config.chan, sc->sc_config.flags, 1785 sc->sc_config.filter_flags)); 1786 1787 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 1788 sizeof (iwh_rxon_cmd_t), 1); 1789 if (err != IWH_SUCCESS) { 1790 IWH_DBG((IWH_DEBUG_80211, 1791 "could not update configuration\n")); 1792 mutex_exit(&sc->sc_glock); 1793 return (err); 1794 } 1795 1796 /* 1797 * send tx power talbe command 1798 */ 1799 err = iwh_tx_power_table(sc, 1); 1800 if (err != IWH_SUCCESS) { 1801 cmn_err(CE_WARN, "iwh_config(): " 1802 "failed to set tx power table.\n"); 1803 return (err); 1804 } 1805 1806 /* 1807 * start automatic rate control 1808 */ 1809 mutex_enter(&sc->sc_mt_lock); 1810 if (IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) { 1811 sc->sc_flags |= IWH_F_RATE_AUTO_CTL; 1812 /* 1813 * set rate to some reasonable initial value 1814 */ 1815 i = in->in_rates.ir_nrates - 1; 1816 while (i > 0 && IEEE80211_RATE(i) > 72) { 1817 i--; 1818 } 1819 in->in_txrate = i; 1820 } else { 1821 sc->sc_flags &= ~IWH_F_RATE_AUTO_CTL; 1822 } 1823 1824 mutex_exit(&sc->sc_mt_lock); 1825 1826 /* 1827 * set LED on after associated 1828 */ 1829 iwh_set_led(sc, 2, 0, 1); 1830 break; 1831 1832 case IEEE80211_S_INIT: 1833 /* 1834 * set LED off after init 1835 */ 1836 iwh_set_led(sc, 2, 1, 0); 1837 break; 1838 1839 case IEEE80211_S_ASSOC: 1840 break; 1841 } 1842 1843 mutex_exit(&sc->sc_glock); 1844 1845 return (sc->sc_newstate(ic, nstate, arg)); 1846 } 1847 1848 /* 1849 * set key for a given node 1850 */ 1851 static int 1852 iwh_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 1853 const uint8_t mac[IEEE80211_ADDR_LEN]) 1854 { 1855 iwh_sc_t *sc = (iwh_sc_t *)ic; 1856 iwh_add_sta_t node; 1857 int err; 1858 1859 switch (k->wk_cipher->ic_cipher) { 1860 case IEEE80211_CIPHER_WEP: 1861 case IEEE80211_CIPHER_TKIP: 1862 return (1); /* sofeware do it. */ 1863 1864 case IEEE80211_CIPHER_AES_CCM: 1865 break; 1866 1867 default: 1868 return (0); 1869 } 1870 1871 sc->sc_config.filter_flags &= ~(RXON_FILTER_DIS_DECRYPT_MSK | 1872 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 1873 1874 mutex_enter(&sc->sc_glock); 1875 1876 /* 1877 * update ap/multicast node 1878 */ 1879 (void) memset(&node, 0, sizeof (node)); 1880 if (IEEE80211_IS_MULTICAST(mac)) { 1881 (void) memset(node.sta.addr, 0xFF, 6); 1882 node.sta.sta_id = IWH_BROADCAST_ID; 1883 1884 } else { 1885 IEEE80211_ADDR_COPY(node.sta.addr, ic->ic_bss->in_bssid); 1886 node.sta.sta_id = IWH_AP_ID; 1887 } 1888 1889 if (k->wk_flags & IEEE80211_KEY_XMIT) { 1890 node.key.key_flags = 0; 1891 node.key.key_offset = k->wk_keyix; 1892 } else { 1893 node.key.key_flags = (1 << 14); 1894 node.key.key_offset = k->wk_keyix + 4; 1895 } 1896 1897 (void) memcpy(node.key.key, k->wk_key, k->wk_keylen); 1898 node.key.key_flags |= (STA_KEY_FLG_CCMP | 1899 (1 << 3) | (k->wk_keyix << 8)); 1900 node.sta.modify_mask = STA_MODIFY_KEY_MASK; 1901 node.mode = 1; 1902 node.station_flags = 0; 1903 1904 err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 1905 if (err != IWH_SUCCESS) { 1906 cmn_err(CE_WARN, "iwh_key_set(): " 1907 "failed to update ap node\n"); 1908 mutex_exit(&sc->sc_glock); 1909 return (0); 1910 } 1911 1912 mutex_exit(&sc->sc_glock); 1913 1914 return (1); 1915 } 1916 1917 /* 1918 * exclusive access to mac begin. 1919 */ 1920 static void 1921 iwh_mac_access_enter(iwh_sc_t *sc) 1922 { 1923 uint32_t tmp; 1924 int n; 1925 1926 tmp = IWH_READ(sc, CSR_GP_CNTRL); 1927 IWH_WRITE(sc, CSR_GP_CNTRL, 1928 tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1929 1930 /* wait until we succeed */ 1931 for (n = 0; n < 1000; n++) { 1932 if ((IWH_READ(sc, CSR_GP_CNTRL) & 1933 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | 1934 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) == 1935 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN) { 1936 break; 1937 } 1938 DELAY(10); 1939 } 1940 1941 #ifdef DEBUG 1942 if (1000 == n) { 1943 IWH_DBG((IWH_DEBUG_PIO, "could not lock memory\n")); 1944 } 1945 #endif 1946 } 1947 1948 /* 1949 * exclusive access to mac end. 1950 */ 1951 static void 1952 iwh_mac_access_exit(iwh_sc_t *sc) 1953 { 1954 uint32_t tmp = IWH_READ(sc, CSR_GP_CNTRL); 1955 IWH_WRITE(sc, CSR_GP_CNTRL, 1956 tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1957 } 1958 1959 /* 1960 * this function defined here for future use. 1961 * static uint32_t 1962 * iwh_mem_read(iwh_sc_t *sc, uint32_t addr) 1963 * { 1964 * IWH_WRITE(sc, HBUS_TARG_MEM_RADDR, addr); 1965 * return (IWH_READ(sc, HBUS_TARG_MEM_RDAT)); 1966 * } 1967 */ 1968 1969 /* 1970 * write mac memory 1971 */ 1972 static void 1973 iwh_mem_write(iwh_sc_t *sc, uint32_t addr, uint32_t data) 1974 { 1975 IWH_WRITE(sc, HBUS_TARG_MEM_WADDR, addr); 1976 IWH_WRITE(sc, HBUS_TARG_MEM_WDAT, data); 1977 } 1978 1979 /* 1980 * read mac register 1981 */ 1982 static uint32_t 1983 iwh_reg_read(iwh_sc_t *sc, uint32_t addr) 1984 { 1985 IWH_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24)); 1986 return (IWH_READ(sc, HBUS_TARG_PRPH_RDAT)); 1987 } 1988 1989 /* 1990 * write mac register 1991 */ 1992 static void 1993 iwh_reg_write(iwh_sc_t *sc, uint32_t addr, uint32_t data) 1994 { 1995 IWH_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24)); 1996 IWH_WRITE(sc, HBUS_TARG_PRPH_WDAT, data); 1997 } 1998 1999 2000 /* 2001 * steps of loading ucode: 2002 * load init ucode=>init alive=>calibrate=> 2003 * receive calibration result=>reinitialize NIC=> 2004 * load runtime ucode=>runtime alive=> 2005 * send calibration result=>running. 2006 */ 2007 static int 2008 iwh_load_init_firmware(iwh_sc_t *sc) 2009 { 2010 int err; 2011 clock_t clk; 2012 2013 sc->sc_flags &= ~IWH_F_PUT_SEG; 2014 2015 /* 2016 * load init_text section of uCode to hardware 2017 */ 2018 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_text.cookie.dmac_address, 2019 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_init_text.cookie.dmac_size); 2020 if (err != IWH_SUCCESS) { 2021 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2022 "failed to write init uCode.\n"); 2023 return (err); 2024 } 2025 2026 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2027 2028 /* wait loading init_text until completed or timeout */ 2029 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2030 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2031 break; 2032 } 2033 } 2034 2035 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2036 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2037 "timeout waiting for init uCode load.\n"); 2038 return (IWH_FAIL); 2039 } 2040 2041 sc->sc_flags &= ~IWH_F_PUT_SEG; 2042 2043 /* 2044 * load init_data section of uCode to hardware 2045 */ 2046 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_data.cookie.dmac_address, 2047 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_init_data.cookie.dmac_size); 2048 if (err != IWH_SUCCESS) { 2049 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2050 "failed to write init_data uCode.\n"); 2051 return (err); 2052 } 2053 2054 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2055 2056 /* 2057 * wait loading init_data until completed or timeout 2058 */ 2059 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2060 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2061 break; 2062 } 2063 } 2064 2065 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2066 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2067 "timeout waiting for init_data uCode load.\n"); 2068 return (IWH_FAIL); 2069 } 2070 2071 sc->sc_flags &= ~IWH_F_PUT_SEG; 2072 2073 return (err); 2074 } 2075 2076 static int 2077 iwh_load_run_firmware(iwh_sc_t *sc) 2078 { 2079 int err; 2080 clock_t clk; 2081 2082 sc->sc_flags &= ~IWH_F_PUT_SEG; 2083 2084 /* 2085 * load init_text section of uCode to hardware 2086 */ 2087 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_text.cookie.dmac_address, 2088 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_text.cookie.dmac_size); 2089 if (err != IWH_SUCCESS) { 2090 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2091 "failed to write run uCode.\n"); 2092 return (err); 2093 } 2094 2095 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2096 2097 /* wait loading run_text until completed or timeout */ 2098 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2099 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2100 break; 2101 } 2102 } 2103 2104 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2105 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2106 "timeout waiting for run uCode load.\n"); 2107 return (IWH_FAIL); 2108 } 2109 2110 sc->sc_flags &= ~IWH_F_PUT_SEG; 2111 2112 /* 2113 * load run_data section of uCode to hardware 2114 */ 2115 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_data_bak.cookie.dmac_address, 2116 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_data.cookie.dmac_size); 2117 if (err != IWH_SUCCESS) { 2118 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2119 "failed to write run_data uCode.\n"); 2120 return (err); 2121 } 2122 2123 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2124 2125 /* 2126 * wait loading run_data until completed or timeout 2127 */ 2128 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2129 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2130 break; 2131 } 2132 } 2133 2134 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2135 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2136 "timeout waiting for run_data uCode load.\n"); 2137 return (IWH_FAIL); 2138 } 2139 2140 sc->sc_flags &= ~IWH_F_PUT_SEG; 2141 2142 return (err); 2143 } 2144 2145 /* 2146 * this function will be invoked to receive phy information 2147 * when a frame is received. 2148 */ 2149 static void 2150 iwh_rx_phy_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2151 { 2152 2153 sc->sc_rx_phy_res.flag = 1; 2154 2155 (void) memcpy(sc->sc_rx_phy_res.buf, (uint8_t *)(desc + 1), 2156 sizeof (iwh_rx_phy_res_t)); 2157 } 2158 2159 /* 2160 * this function will be invoked to receive body of frame when 2161 * a frame is received. 2162 */ 2163 static void 2164 iwh_rx_mpdu_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2165 { 2166 ieee80211com_t *ic = &sc->sc_ic; 2167 #ifdef DEBUG 2168 iwh_rx_ring_t *ring = &sc->sc_rxq; 2169 #endif 2170 iwh_rx_phy_res_t *stat; 2171 ieee80211_node_t *in; 2172 uint32_t *tail; 2173 struct ieee80211_frame *wh; 2174 mblk_t *mp; 2175 uint16_t len, rssi, agc; 2176 int16_t t; 2177 struct iwh_rx_non_cfg_phy *phyinfo; 2178 uint32_t temp; 2179 uint32_t arssi, brssi, crssi, mrssi; 2180 struct iwh_rx_mpdu_body_size *mpdu_size; 2181 2182 /* 2183 * assuming not 11n here. cope with 11n in phase-II 2184 */ 2185 mpdu_size = (struct iwh_rx_mpdu_body_size *)(desc + 1); 2186 stat = (iwh_rx_phy_res_t *)sc->sc_rx_phy_res.buf; 2187 if (stat->cfg_phy_cnt > 20) { 2188 return; 2189 } 2190 2191 phyinfo = (struct iwh_rx_non_cfg_phy *)stat->non_cfg_phy; 2192 temp = phyinfo->non_cfg_phy[IWH_RX_RES_AGC_IDX]; 2193 agc = (temp & IWH_OFDM_AGC_MSK) >> IWH_OFDM_AGC_BIT_POS; 2194 2195 temp = phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_AB_IDX]; 2196 arssi = (temp & IWH_OFDM_RSSI_A_MSK) >> IWH_OFDM_RSSI_A_BIT_POS; 2197 brssi = (temp & IWH_OFDM_RSSI_B_MSK) >> IWH_OFDM_RSSI_B_BIT_POS; 2198 2199 temp = phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_C_IDX]; 2200 crssi = (temp & IWH_OFDM_RSSI_C_MSK) >> IWH_OFDM_RSSI_C_BIT_POS; 2201 2202 mrssi = MAX(arssi, brssi); 2203 mrssi = MAX(mrssi, crssi); 2204 2205 t = mrssi - agc - IWH_RSSI_OFFSET; 2206 /* 2207 * convert dBm to percentage 2208 */ 2209 rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t))) 2210 / (75 * 75); 2211 if (rssi > 100) { 2212 rssi = 100; 2213 } 2214 if (rssi < 1) { 2215 rssi = 1; 2216 } 2217 2218 /* 2219 * size of frame, not include FCS 2220 */ 2221 len = mpdu_size->byte_count; 2222 tail = (uint32_t *)((uint8_t *)(desc + 1) + 2223 sizeof (struct iwh_rx_mpdu_body_size) + len); 2224 2225 2226 IWH_DBG((IWH_DEBUG_RX, "rx intr: idx=%d phy_len=%x len=%d " 2227 "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x " 2228 "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat), 2229 len, stat->rate.r.s.rate, stat->channel, 2230 LE_32(stat->timestampl), stat->non_cfg_phy_cnt, 2231 stat->cfg_phy_cnt, LE_32(*tail))); 2232 2233 if ((len < 16) || (len > sc->sc_dmabuf_sz)) { 2234 IWH_DBG((IWH_DEBUG_RX, "rx frame oversize\n")); 2235 return; 2236 } 2237 2238 /* 2239 * discard Rx frames with bad CRC 2240 */ 2241 if ((LE_32(*tail) & 2242 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) != 2243 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) { 2244 IWH_DBG((IWH_DEBUG_RX, "rx crc error tail: %x\n", 2245 LE_32(*tail))); 2246 sc->sc_rx_err++; 2247 return; 2248 } 2249 2250 wh = (struct ieee80211_frame *) 2251 ((uint8_t *)(desc + 1)+ sizeof (struct iwh_rx_mpdu_body_size)); 2252 2253 if (IEEE80211_FC0_SUBTYPE_ASSOC_RESP == *(uint8_t *)wh) { 2254 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2); 2255 IWH_DBG((IWH_DEBUG_RX, "rx : association id = %x\n", 2256 sc->sc_assoc_id)); 2257 } 2258 2259 #ifdef DEBUG 2260 if (iwh_dbg_flags & IWH_DEBUG_RX) { 2261 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0); 2262 } 2263 #endif 2264 2265 in = ieee80211_find_rxnode(ic, wh); 2266 mp = allocb(len, BPRI_MED); 2267 if (mp) { 2268 (void) memcpy(mp->b_wptr, wh, len); 2269 mp->b_wptr += len; 2270 2271 /* 2272 * send the frame to the 802.11 layer 2273 */ 2274 (void) ieee80211_input(ic, mp, in, rssi, 0); 2275 } else { 2276 sc->sc_rx_nobuf++; 2277 IWH_DBG((IWH_DEBUG_RX, 2278 "iwh_rx_mpdu_intr(): alloc rx buf failed\n")); 2279 } 2280 2281 /* 2282 * release node reference 2283 */ 2284 ieee80211_free_node(in); 2285 } 2286 2287 /* 2288 * process correlative affairs after a frame is sent. 2289 */ 2290 static void 2291 iwh_tx_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2292 { 2293 ieee80211com_t *ic = &sc->sc_ic; 2294 iwh_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3]; 2295 iwh_tx_stat_t *stat = (iwh_tx_stat_t *)(desc + 1); 2296 iwh_amrr_t *amrr = (iwh_amrr_t *)ic->ic_bss; 2297 2298 amrr->txcnt++; 2299 IWH_DBG((IWH_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt)); 2300 2301 if (stat->ntries > 0) { 2302 amrr->retrycnt++; 2303 sc->sc_tx_retries++; 2304 IWH_DBG((IWH_DEBUG_TX, "tx: %d retries\n", 2305 sc->sc_tx_retries)); 2306 } 2307 2308 sc->sc_tx_timer = 0; 2309 2310 mutex_enter(&sc->sc_tx_lock); 2311 2312 ring->queued--; 2313 if (ring->queued < 0) { 2314 ring->queued = 0; 2315 } 2316 2317 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) { 2318 sc->sc_need_reschedule = 0; 2319 mutex_exit(&sc->sc_tx_lock); 2320 mac_tx_update(ic->ic_mach); 2321 mutex_enter(&sc->sc_tx_lock); 2322 } 2323 2324 mutex_exit(&sc->sc_tx_lock); 2325 } 2326 2327 /* 2328 * inform a given command has been executed 2329 */ 2330 static void 2331 iwh_cmd_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2332 { 2333 if ((desc->hdr.qid & 7) != 4) { 2334 return; 2335 } 2336 2337 mutex_enter(&sc->sc_glock); 2338 2339 sc->sc_flags |= IWH_F_CMD_DONE; 2340 cv_signal(&sc->sc_cmd_cv); 2341 2342 mutex_exit(&sc->sc_glock); 2343 2344 IWH_DBG((IWH_DEBUG_CMD, "rx cmd: " 2345 "qid=%x idx=%d flags=%x type=0x%x\n", 2346 desc->hdr.qid, desc->hdr.idx, desc->hdr.flags, 2347 desc->hdr.type)); 2348 } 2349 2350 /* 2351 * this function will be invoked when alive notification occur. 2352 */ 2353 static void 2354 iwh_ucode_alive(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2355 { 2356 uint32_t rv; 2357 struct iwh_calib_cfg_cmd cmd; 2358 struct iwh_alive_resp *ar = 2359 (struct iwh_alive_resp *)(desc + 1); 2360 struct iwh_calib_results *res_p = &sc->sc_calib_results; 2361 2362 /* 2363 * the microcontroller is ready 2364 */ 2365 IWH_DBG((IWH_DEBUG_FW, 2366 "microcode alive notification minor: %x major: %x type:" 2367 " %x subtype: %x\n", 2368 ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype)); 2369 2370 #ifdef DEBUG 2371 if (LE_32(ar->is_valid) != UCODE_VALID_OK) { 2372 IWH_DBG((IWH_DEBUG_FW, 2373 "microcontroller initialization failed\n")); 2374 } 2375 #endif 2376 2377 /* 2378 * determine if init alive or runtime alive. 2379 */ 2380 if (INITIALIZE_SUBTYPE == ar->ver_subtype) { 2381 IWH_DBG((IWH_DEBUG_FW, 2382 "initialization alive received.\n")); 2383 2384 (void) memcpy(&sc->sc_card_alive_init, ar, 2385 sizeof (struct iwh_init_alive_resp)); 2386 2387 /* 2388 * necessary configuration to NIC 2389 */ 2390 mutex_enter(&sc->sc_glock); 2391 2392 rv = iwh_alive_common(sc); 2393 if (rv != IWH_SUCCESS) { 2394 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2395 "common alive process failed in init alive.\n"); 2396 mutex_exit(&sc->sc_glock); 2397 return; 2398 } 2399 2400 (void) memset(&cmd, 0, sizeof (cmd)); 2401 2402 cmd.ucd_calib_cfg.once.is_enable = IWH_CALIB_INIT_CFG_ALL; 2403 cmd.ucd_calib_cfg.once.start = IWH_CALIB_INIT_CFG_ALL; 2404 cmd.ucd_calib_cfg.once.send_res = IWH_CALIB_INIT_CFG_ALL; 2405 cmd.ucd_calib_cfg.flags = IWH_CALIB_INIT_CFG_ALL; 2406 2407 /* 2408 * require ucode execute calibration 2409 */ 2410 rv = iwh_cmd(sc, CALIBRATION_CFG_CMD, &cmd, sizeof (cmd), 1); 2411 if (rv != IWH_SUCCESS) { 2412 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2413 "failed to send calibration configure command.\n"); 2414 mutex_exit(&sc->sc_glock); 2415 return; 2416 } 2417 2418 mutex_exit(&sc->sc_glock); 2419 2420 } else { /* runtime alive */ 2421 2422 IWH_DBG((IWH_DEBUG_FW, "runtime alive received.\n")); 2423 2424 (void) memcpy(&sc->sc_card_alive_run, ar, 2425 sizeof (struct iwh_alive_resp)); 2426 2427 mutex_enter(&sc->sc_glock); 2428 2429 /* 2430 * necessary configuration to NIC 2431 */ 2432 rv = iwh_alive_common(sc); 2433 if (rv != IWH_SUCCESS) { 2434 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2435 "common alive process failed in run alive.\n"); 2436 mutex_exit(&sc->sc_glock); 2437 return; 2438 } 2439 2440 /* 2441 * send the result of local oscilator calibration to uCode. 2442 */ 2443 if (res_p->lo_res != NULL) { 2444 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2445 res_p->lo_res, res_p->lo_res_len, 1); 2446 if (rv != IWH_SUCCESS) { 2447 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2448 "failed to send local" 2449 "oscilator calibration command.\n"); 2450 mutex_exit(&sc->sc_glock); 2451 return; 2452 } 2453 2454 DELAY(1000); 2455 } 2456 2457 /* 2458 * send the result of TX IQ calibration to uCode. 2459 */ 2460 if (res_p->tx_iq_res != NULL) { 2461 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2462 res_p->tx_iq_res, res_p->tx_iq_res_len, 1); 2463 if (rv != IWH_SUCCESS) { 2464 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2465 "failed to send TX IQ" 2466 "calibration command.\n"); 2467 mutex_exit(&sc->sc_glock); 2468 return; 2469 } 2470 2471 DELAY(1000); 2472 } 2473 2474 /* 2475 * sned the result of TX IQ perd calibration to uCode. 2476 */ 2477 if (res_p->tx_iq_perd_res != NULL) { 2478 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2479 res_p->tx_iq_perd_res, 2480 res_p->tx_iq_perd_res_len, 1); 2481 if (rv != IWH_SUCCESS) { 2482 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2483 "failed to send TX IQ perd" 2484 "calibration command.\n"); 2485 mutex_exit(&sc->sc_glock); 2486 return; 2487 } 2488 2489 DELAY(1000); 2490 } 2491 2492 mutex_exit(&sc->sc_glock); 2493 2494 sc->sc_flags |= IWH_F_FW_INIT; 2495 cv_signal(&sc->sc_ucode_cv); 2496 } 2497 2498 } 2499 2500 /* 2501 * deal with receiving frames, command response 2502 * and all notifications from ucode. 2503 */ 2504 static uint_t 2505 /* LINTED: argument unused in function: unused */ 2506 iwh_rx_softintr(caddr_t arg, caddr_t unused) 2507 { 2508 iwh_sc_t *sc = (iwh_sc_t *)arg; 2509 ieee80211com_t *ic = &sc->sc_ic; 2510 iwh_rx_desc_t *desc; 2511 iwh_rx_data_t *data; 2512 uint32_t index; 2513 2514 mutex_enter(&sc->sc_glock); 2515 2516 if (sc->sc_rx_softint_pending != 1) { 2517 mutex_exit(&sc->sc_glock); 2518 return (DDI_INTR_UNCLAIMED); 2519 } 2520 2521 /* 2522 * disable interrupts 2523 */ 2524 IWH_WRITE(sc, CSR_INT_MASK, 0); 2525 2526 mutex_exit(&sc->sc_glock); 2527 2528 /* 2529 * firmware has moved the index of the rx queue, driver get it, 2530 * and deal with it. 2531 */ 2532 index = LE_32(sc->sc_shared->val0) & 0xfff; 2533 2534 while (sc->sc_rxq.cur != index) { 2535 data = &sc->sc_rxq.data[sc->sc_rxq.cur]; 2536 desc = (iwh_rx_desc_t *)data->dma_data.mem_va; 2537 2538 IWH_DBG((IWH_DEBUG_INTR, "rx notification index = %d" 2539 " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n", 2540 index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx, 2541 desc->hdr.flags, desc->hdr.type, LE_32(desc->len))); 2542 2543 /* 2544 * a command other than a tx need to be replied 2545 */ 2546 if (!(desc->hdr.qid & 0x80) && 2547 (desc->hdr.type != REPLY_RX_PHY_CMD) && 2548 (desc->hdr.type != REPLY_RX_MPDU_CMD) && 2549 (desc->hdr.type != REPLY_TX) && 2550 (desc->hdr.type != REPLY_PHY_CALIBRATION_CMD)) { 2551 iwh_cmd_intr(sc, desc); 2552 } 2553 2554 switch (desc->hdr.type) { 2555 case REPLY_RX_PHY_CMD: 2556 iwh_rx_phy_intr(sc, desc); 2557 break; 2558 2559 case REPLY_RX_MPDU_CMD: 2560 iwh_rx_mpdu_intr(sc, desc); 2561 break; 2562 2563 case REPLY_TX: 2564 iwh_tx_intr(sc, desc); 2565 break; 2566 2567 case REPLY_ALIVE: 2568 iwh_ucode_alive(sc, desc); 2569 break; 2570 2571 case CARD_STATE_NOTIFICATION: 2572 { 2573 uint32_t *status = (uint32_t *)(desc + 1); 2574 2575 IWH_DBG((IWH_DEBUG_RADIO, "state changed to %x\n", 2576 LE_32(*status))); 2577 2578 if (LE_32(*status) & 1) { 2579 /* 2580 * the radio button has to be pushed(OFF). It 2581 * is considered as a hw error, the 2582 * iwh_thread() tries to recover it after the 2583 * button is pushed again(ON) 2584 */ 2585 cmn_err(CE_WARN, "iwh_rx_softintr(): " 2586 "radio transmitter is off\n"); 2587 sc->sc_ostate = sc->sc_ic.ic_state; 2588 ieee80211_new_state(&sc->sc_ic, 2589 IEEE80211_S_INIT, -1); 2590 sc->sc_flags |= 2591 (IWH_F_HW_ERR_RECOVER | IWH_F_RADIO_OFF); 2592 } 2593 break; 2594 } 2595 2596 case SCAN_START_NOTIFICATION: 2597 { 2598 iwh_start_scan_t *scan = 2599 (iwh_start_scan_t *)(desc + 1); 2600 2601 IWH_DBG((IWH_DEBUG_SCAN, 2602 "scanning channel %d status %x\n", 2603 scan->chan, LE_32(scan->status))); 2604 2605 ic->ic_curchan = &ic->ic_sup_channels[scan->chan]; 2606 break; 2607 } 2608 2609 case SCAN_COMPLETE_NOTIFICATION: 2610 IWH_DBG((IWH_DEBUG_SCAN, "scan finished\n")); 2611 sc->sc_flags &= ~IWH_F_SCANNING; 2612 ieee80211_end_scan(ic); 2613 break; 2614 2615 case STATISTICS_NOTIFICATION: 2616 { 2617 /* 2618 * handle statistics notification 2619 */ 2620 break; 2621 } 2622 2623 case CALIBRATION_RES_NOTIFICATION: 2624 iwh_save_calib_result(sc, desc); 2625 break; 2626 2627 case CALIBRATION_COMPLETE_NOTIFICATION: 2628 sc->sc_flags |= IWH_F_FW_INIT; 2629 cv_signal(&sc->sc_ucode_cv); 2630 break; 2631 } 2632 2633 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE; 2634 } 2635 2636 /* 2637 * driver dealt with what received in rx queue and tell the information 2638 * to the firmware. 2639 */ 2640 index = (0 == index) ? RX_QUEUE_SIZE - 1 : index - 1; 2641 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7)); 2642 2643 mutex_enter(&sc->sc_glock); 2644 2645 /* 2646 * re-enable interrupts 2647 */ 2648 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2649 sc->sc_rx_softint_pending = 0; 2650 2651 mutex_exit(&sc->sc_glock); 2652 2653 return (DDI_INTR_CLAIMED); 2654 } 2655 2656 /* 2657 * the handle of interrupt 2658 */ 2659 static uint_t 2660 /* LINTED: argument unused in function: unused */ 2661 iwh_intr(caddr_t arg, caddr_t unused) 2662 { 2663 iwh_sc_t *sc = (iwh_sc_t *)arg; 2664 uint32_t r, rfh; 2665 2666 mutex_enter(&sc->sc_glock); 2667 2668 if (sc->sc_flags & IWH_F_SUSPEND) { 2669 mutex_exit(&sc->sc_glock); 2670 return (DDI_INTR_UNCLAIMED); 2671 } 2672 r = IWH_READ(sc, CSR_INT); 2673 if (0 == r || 0xffffffff == r) { 2674 mutex_exit(&sc->sc_glock); 2675 return (DDI_INTR_UNCLAIMED); 2676 } 2677 2678 IWH_DBG((IWH_DEBUG_INTR, "interrupt reg %x\n", r)); 2679 2680 rfh = IWH_READ(sc, CSR_FH_INT_STATUS); 2681 2682 IWH_DBG((IWH_DEBUG_INTR, "FH interrupt reg %x\n", rfh)); 2683 2684 /* 2685 * disable interrupts 2686 */ 2687 IWH_WRITE(sc, CSR_INT_MASK, 0); 2688 2689 /* 2690 * ack interrupts 2691 */ 2692 IWH_WRITE(sc, CSR_INT, r); 2693 IWH_WRITE(sc, CSR_FH_INT_STATUS, rfh); 2694 2695 if (NULL == sc->sc_soft_hdl) { 2696 mutex_exit(&sc->sc_glock); 2697 return (DDI_INTR_CLAIMED); 2698 } 2699 2700 if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) { 2701 IWH_DBG((IWH_DEBUG_FW, "fatal firmware error\n")); 2702 mutex_exit(&sc->sc_glock); 2703 iwh_stop(sc); 2704 sc->sc_ostate = sc->sc_ic.ic_state; 2705 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 2706 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 2707 return (DDI_INTR_CLAIMED); 2708 } 2709 2710 #ifdef DEBUG 2711 if (r & BIT_INT_RF_KILL) { 2712 IWH_DBG((IWH_DEBUG_RADIO, "RF kill\n")); 2713 } 2714 #endif 2715 2716 if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) || 2717 (rfh & FH_INT_RX_MASK)) { 2718 sc->sc_rx_softint_pending = 1; 2719 (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL); 2720 } 2721 2722 if (r & BIT_INT_FH_TX) { 2723 sc->sc_flags |= IWH_F_PUT_SEG; 2724 cv_signal(&sc->sc_put_seg_cv); 2725 } 2726 2727 #ifdef DEBUG 2728 if (r & BIT_INT_ALIVE) { 2729 IWH_DBG((IWH_DEBUG_FW, "firmware initialized.\n")); 2730 } 2731 #endif 2732 2733 /* 2734 * re-enable interrupts 2735 */ 2736 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2737 2738 mutex_exit(&sc->sc_glock); 2739 2740 return (DDI_INTR_CLAIMED); 2741 } 2742 2743 static uint8_t 2744 iwh_rate_to_plcp(int rate) 2745 { 2746 uint8_t ret; 2747 2748 switch (rate) { 2749 /* 2750 * CCK rates 2751 */ 2752 case 2: 2753 ret = 0xa; 2754 break; 2755 2756 case 4: 2757 ret = 0x14; 2758 break; 2759 2760 case 11: 2761 ret = 0x37; 2762 break; 2763 2764 case 22: 2765 ret = 0x6e; 2766 break; 2767 2768 /* 2769 * OFDM rates 2770 */ 2771 case 12: 2772 ret = 0xd; 2773 break; 2774 2775 case 18: 2776 ret = 0xf; 2777 break; 2778 2779 case 24: 2780 ret = 0x5; 2781 break; 2782 2783 case 36: 2784 ret = 0x7; 2785 break; 2786 2787 case 48: 2788 ret = 0x9; 2789 break; 2790 2791 case 72: 2792 ret = 0xb; 2793 break; 2794 2795 case 96: 2796 ret = 0x1; 2797 break; 2798 2799 case 108: 2800 ret = 0x3; 2801 break; 2802 2803 default: 2804 ret = 0; 2805 break; 2806 } 2807 2808 return (ret); 2809 } 2810 2811 /* 2812 * invoked by GLD send frames 2813 */ 2814 static mblk_t * 2815 iwh_m_tx(void *arg, mblk_t *mp) 2816 { 2817 iwh_sc_t *sc = (iwh_sc_t *)arg; 2818 ieee80211com_t *ic = &sc->sc_ic; 2819 mblk_t *next; 2820 2821 if (sc->sc_flags & IWH_F_SUSPEND) { 2822 freemsgchain(mp); 2823 return (NULL); 2824 } 2825 2826 if (ic->ic_state != IEEE80211_S_RUN) { 2827 freemsgchain(mp); 2828 return (NULL); 2829 } 2830 2831 while (mp != NULL) { 2832 next = mp->b_next; 2833 mp->b_next = NULL; 2834 if (iwh_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) { 2835 mp->b_next = next; 2836 break; 2837 } 2838 mp = next; 2839 } 2840 2841 return (mp); 2842 } 2843 2844 /* 2845 * send frames 2846 */ 2847 static int 2848 iwh_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2849 { 2850 iwh_sc_t *sc = (iwh_sc_t *)ic; 2851 iwh_tx_ring_t *ring; 2852 iwh_tx_desc_t *desc; 2853 iwh_tx_data_t *data; 2854 iwh_cmd_t *cmd; 2855 iwh_tx_cmd_t *tx; 2856 ieee80211_node_t *in; 2857 struct ieee80211_frame *wh; 2858 struct ieee80211_key *k = NULL; 2859 mblk_t *m, *m0; 2860 int rate, hdrlen, len, len0, mblen, off, err = IWH_SUCCESS; 2861 uint16_t masks = 0; 2862 uint32_t s_id = 0; 2863 uint8_t s_ctl = 0; 2864 2865 ring = &sc->sc_txq[0]; 2866 data = &ring->data[ring->cur]; 2867 desc = data->desc; 2868 cmd = data->cmd; 2869 bzero(desc, sizeof (*desc)); 2870 bzero(cmd, sizeof (*cmd)); 2871 2872 mutex_enter(&sc->sc_tx_lock); 2873 if (sc->sc_flags & IWH_F_SUSPEND) { 2874 mutex_exit(&sc->sc_tx_lock); 2875 if ((type & IEEE80211_FC0_TYPE_MASK) != 2876 IEEE80211_FC0_TYPE_DATA) { 2877 freemsg(mp); 2878 } 2879 err = IWH_FAIL; 2880 goto exit; 2881 } 2882 if (ring->queued > ring->count - 64) { 2883 IWH_DBG((IWH_DEBUG_TX, "iwh_send(): no txbuf\n")); 2884 2885 sc->sc_need_reschedule = 1; 2886 mutex_exit(&sc->sc_tx_lock); 2887 if ((type & IEEE80211_FC0_TYPE_MASK) != 2888 IEEE80211_FC0_TYPE_DATA) { 2889 freemsg(mp); 2890 } 2891 sc->sc_tx_nobuf++; 2892 err = IWH_FAIL; 2893 goto exit; 2894 } 2895 2896 mutex_exit(&sc->sc_tx_lock); 2897 2898 hdrlen = sizeof (struct ieee80211_frame); 2899 2900 m = allocb(msgdsize(mp) + 32, BPRI_MED); 2901 if (NULL == m) { /* can not alloc buf, drop this package */ 2902 cmn_err(CE_WARN, "iwh_send(): " 2903 "failed to allocate msgbuf\n"); 2904 freemsg(mp); 2905 err = IWH_SUCCESS; 2906 goto exit; 2907 } 2908 2909 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2910 mblen = MBLKL(m0); 2911 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 2912 off += mblen; 2913 } 2914 2915 m->b_wptr += off; 2916 2917 freemsg(mp); 2918 2919 wh = (struct ieee80211_frame *)m->b_rptr; 2920 2921 /* 2922 * determine send which AP or station in IBSS 2923 */ 2924 in = ieee80211_find_txnode(ic, wh->i_addr1); 2925 if (NULL == in) { 2926 cmn_err(CE_WARN, "iwh_send(): " 2927 "failed to find tx node\n"); 2928 freemsg(m); 2929 sc->sc_tx_err++; 2930 err = IWH_SUCCESS; 2931 goto exit; 2932 } 2933 2934 (void) ieee80211_encap(ic, m, in); 2935 2936 cmd->hdr.type = REPLY_TX; 2937 cmd->hdr.flags = 0; 2938 cmd->hdr.qid = ring->qid; 2939 cmd->hdr.idx = ring->cur; 2940 2941 tx = (iwh_tx_cmd_t *)cmd->data; 2942 tx->tx_flags = 0; 2943 2944 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2945 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK)); 2946 } else { 2947 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK); 2948 } 2949 2950 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2951 k = ieee80211_crypto_encap(ic, m); 2952 if (NULL == k) { 2953 freemsg(m); 2954 sc->sc_tx_err++; 2955 err = IWH_SUCCESS; 2956 goto exit; 2957 } 2958 2959 if (IEEE80211_CIPHER_AES_CCM == k->wk_cipher->ic_cipher) { 2960 tx->sec_ctl = 2; /* for CCMP */ 2961 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK); 2962 (void) memcpy(&tx->key, k->wk_key, k->wk_keylen); 2963 } 2964 2965 /* packet header may have moved, reset our local pointer */ 2966 wh = (struct ieee80211_frame *)m->b_rptr; 2967 } 2968 2969 len = msgdsize(m); 2970 2971 #ifdef DEBUG 2972 if (iwh_dbg_flags & IWH_DEBUG_TX) { 2973 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0); 2974 } 2975 #endif 2976 2977 /* 2978 * pickup a rate 2979 */ 2980 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2981 IEEE80211_FC0_TYPE_MGT) { 2982 /* 2983 * mgmt frames are sent at 1M 2984 */ 2985 rate = in->in_rates.ir_rates[0]; 2986 } else { 2987 /* 2988 * do it here for the software way rate control. 2989 * later for rate scaling in hardware. 2990 * maybe like the following, for management frame: 2991 * tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1; 2992 * for data frame: 2993 * tx->tx_flags |= (LE_32(TX_CMD_FLG_STA_RATE_MSK)); 2994 * rate = in->in_rates.ir_rates[in->in_txrate]; 2995 * tx->initial_rate_index = 1; 2996 * 2997 * now the txrate is determined in tx cmd flags, set to the 2998 * max value 54M for 11g and 11M for 11b. 2999 */ 3000 3001 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 3002 rate = ic->ic_fixed_rate; 3003 } else { 3004 rate = in->in_rates.ir_rates[in->in_txrate]; 3005 } 3006 } 3007 3008 rate &= IEEE80211_RATE_VAL; 3009 3010 IWH_DBG((IWH_DEBUG_TX, "tx rate[%d of %d] = %x", 3011 in->in_txrate, in->in_rates.ir_nrates, rate)); 3012 3013 tx->tx_flags |= (LE_32(TX_CMD_FLG_SEQ_CTL_MSK)); 3014 3015 len0 = roundup(4 + sizeof (iwh_tx_cmd_t) + hdrlen, 4); 3016 if (len0 != (4 + sizeof (iwh_tx_cmd_t) + hdrlen)) { 3017 tx->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; 3018 } 3019 3020 /* 3021 * retrieve destination node's id 3022 */ 3023 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3024 tx->sta_id = IWH_BROADCAST_ID; 3025 } else { 3026 tx->sta_id = IWH_AP_ID; 3027 } 3028 3029 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 3030 IEEE80211_FC0_TYPE_MGT) { 3031 /* tell h/w to set timestamp in probe responses */ 3032 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3033 IEEE80211_FC0_SUBTYPE_PROBE_RESP) { 3034 tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK); 3035 } 3036 3037 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3038 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) || 3039 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3040 IEEE80211_FC0_SUBTYPE_REASSOC_REQ)) { 3041 tx->timeout.pm_frame_timeout = 3; 3042 } else { 3043 tx->timeout.pm_frame_timeout = 2; 3044 } 3045 } else { 3046 tx->timeout.pm_frame_timeout = 0; 3047 } 3048 3049 if (2 == rate || 4 == rate || 11 == rate || 22 == rate) { 3050 masks |= RATE_MCS_CCK_MSK; 3051 } 3052 3053 masks |= RATE_MCS_ANT_B_MSK; 3054 tx->rate.r.rate_n_flags = (iwh_rate_to_plcp(rate) | masks); 3055 3056 IWH_DBG((IWH_DEBUG_TX, "tx flag = %x", 3057 tx->tx_flags)); 3058 3059 tx->rts_retry_limit = 60; 3060 tx->data_retry_limit = 15; 3061 3062 tx->stop_time.life_time = LE_32(0xffffffff); 3063 3064 tx->len = LE_16(len); 3065 3066 tx->dram_lsb_ptr = 3067 data->paddr_cmd + 4 + offsetof(iwh_tx_cmd_t, scratch); 3068 tx->dram_msb_ptr = 0; 3069 tx->driver_txop = 0; 3070 tx->next_frame_len = 0; 3071 3072 (void) memcpy(tx + 1, m->b_rptr, hdrlen); 3073 m->b_rptr += hdrlen; 3074 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen); 3075 3076 IWH_DBG((IWH_DEBUG_TX, "sending data: qid=%d idx=%d len=%d", 3077 ring->qid, ring->cur, len)); 3078 3079 /* 3080 * first segment includes the tx cmd plus the 802.11 header, 3081 * the second includes the remaining of the 802.11 frame. 3082 */ 3083 desc->val0 = LE_32(2 << 24); 3084 desc->pa[0].tb1_addr = LE_32(data->paddr_cmd); 3085 desc->pa[0].val1 = ((len0 << 4) & 0xfff0) | 3086 ((data->dma_data.cookie.dmac_address & 0xffff) << 16); 3087 desc->pa[0].val2 = 3088 ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) | 3089 ((len - hdrlen) << 20); 3090 IWH_DBG((IWH_DEBUG_TX, "phy addr1 = 0x%x phy addr2 = 0x%x " 3091 "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x", 3092 data->paddr_cmd, data->dma_data.cookie.dmac_address, 3093 len0, len - hdrlen, desc->pa[0].val1, desc->pa[0].val2)); 3094 3095 mutex_enter(&sc->sc_tx_lock); 3096 ring->queued++; 3097 mutex_exit(&sc->sc_tx_lock); 3098 3099 /* 3100 * kick ring 3101 */ 3102 s_id = tx->sta_id; 3103 s_ctl = tx->sec_ctl; 3104 3105 if (TX_CMD_SEC_CCM == (s_ctl & TX_CMD_SEC_MSK)) { 3106 len += CCMP_MIC_LEN; 3107 } 3108 3109 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3110 tfd_offset[ring->cur].val = 3111 (8 + len) | (s_id << 12); 3112 if (ring->cur < IWH_MAX_WIN_SIZE) { 3113 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3114 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 3115 (8 + len) | (s_id << 12); 3116 } 3117 3118 IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 3119 IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 3120 3121 ring->cur = (ring->cur + 1) % ring->count; 3122 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3123 freemsg(m); 3124 3125 /* 3126 * release node reference 3127 */ 3128 ieee80211_free_node(in); 3129 3130 ic->ic_stats.is_tx_bytes += len; 3131 ic->ic_stats.is_tx_frags++; 3132 3133 if (0 == sc->sc_tx_timer) { 3134 sc->sc_tx_timer = 10; 3135 } 3136 3137 exit: 3138 return (err); 3139 } 3140 3141 /* 3142 * invoked by GLD to deal with IOCTL affaires 3143 */ 3144 static void 3145 iwh_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 3146 { 3147 iwh_sc_t *sc = (iwh_sc_t *)arg; 3148 ieee80211com_t *ic = &sc->sc_ic; 3149 int err; 3150 3151 3152 err = ieee80211_ioctl(ic, wq, mp); 3153 if (ENETRESET == err) { 3154 /* 3155 * This is special for the hidden AP connection. 3156 * In any case, we should make sure only one 'scan' 3157 * in the driver for a 'connect' CLI command. So 3158 * when connecting to a hidden AP, the scan is just 3159 * sent out to the air when we know the desired 3160 * essid of the AP we want to connect. 3161 */ 3162 if (ic->ic_des_esslen) { 3163 (void) ieee80211_new_state(ic, 3164 IEEE80211_S_SCAN, -1); 3165 } 3166 } 3167 } 3168 3169 /* 3170 * invoked by GLD supply statistics NIC and driver 3171 */ 3172 static int 3173 iwh_m_stat(void *arg, uint_t stat, uint64_t *val) 3174 { 3175 iwh_sc_t *sc = (iwh_sc_t *)arg; 3176 ieee80211com_t *ic = &sc->sc_ic; 3177 ieee80211_node_t *in = ic->ic_bss; 3178 struct ieee80211_rateset *rs = &in->in_rates; 3179 3180 mutex_enter(&sc->sc_glock); 3181 3182 switch (stat) { 3183 case MAC_STAT_IFSPEED: 3184 *val = ((IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) ? 3185 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) : 3186 ic->ic_fixed_rate) /2 * 1000000; 3187 break; 3188 3189 case MAC_STAT_NOXMTBUF: 3190 *val = sc->sc_tx_nobuf; 3191 break; 3192 3193 case MAC_STAT_NORCVBUF: 3194 *val = sc->sc_rx_nobuf; 3195 break; 3196 3197 case MAC_STAT_IERRORS: 3198 *val = sc->sc_rx_err; 3199 break; 3200 3201 case MAC_STAT_RBYTES: 3202 *val = ic->ic_stats.is_rx_bytes; 3203 break; 3204 3205 case MAC_STAT_IPACKETS: 3206 *val = ic->ic_stats.is_rx_frags; 3207 break; 3208 3209 case MAC_STAT_OBYTES: 3210 *val = ic->ic_stats.is_tx_bytes; 3211 break; 3212 3213 case MAC_STAT_OPACKETS: 3214 *val = ic->ic_stats.is_tx_frags; 3215 break; 3216 3217 case MAC_STAT_OERRORS: 3218 case WIFI_STAT_TX_FAILED: 3219 *val = sc->sc_tx_err; 3220 break; 3221 3222 case WIFI_STAT_TX_RETRANS: 3223 *val = sc->sc_tx_retries; 3224 break; 3225 3226 case WIFI_STAT_FCS_ERRORS: 3227 case WIFI_STAT_WEP_ERRORS: 3228 case WIFI_STAT_TX_FRAGS: 3229 case WIFI_STAT_MCAST_TX: 3230 case WIFI_STAT_RTS_SUCCESS: 3231 case WIFI_STAT_RTS_FAILURE: 3232 case WIFI_STAT_ACK_FAILURE: 3233 case WIFI_STAT_RX_FRAGS: 3234 case WIFI_STAT_MCAST_RX: 3235 case WIFI_STAT_RX_DUPS: 3236 mutex_exit(&sc->sc_glock); 3237 return (ieee80211_stat(ic, stat, val)); 3238 3239 default: 3240 mutex_exit(&sc->sc_glock); 3241 return (ENOTSUP); 3242 } 3243 3244 mutex_exit(&sc->sc_glock); 3245 3246 return (IWH_SUCCESS); 3247 3248 } 3249 3250 /* 3251 * invoked by GLD to start or open NIC 3252 */ 3253 static int 3254 iwh_m_start(void *arg) 3255 { 3256 iwh_sc_t *sc = (iwh_sc_t *)arg; 3257 ieee80211com_t *ic = &sc->sc_ic; 3258 int err; 3259 3260 err = iwh_init(sc); 3261 3262 if (err != IWH_SUCCESS) { 3263 /* 3264 * The hw init err(eg. RF is OFF). Return Success to make 3265 * the 'plumb' succeed. The iwh_thread() tries to re-init 3266 * background. 3267 */ 3268 mutex_enter(&sc->sc_glock); 3269 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 3270 mutex_exit(&sc->sc_glock); 3271 return (IWH_SUCCESS); 3272 } 3273 3274 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3275 3276 mutex_enter(&sc->sc_glock); 3277 sc->sc_flags |= IWH_F_RUNNING; 3278 mutex_exit(&sc->sc_glock); 3279 3280 return (IWH_SUCCESS); 3281 } 3282 3283 /* 3284 * invoked by GLD to stop or down NIC 3285 */ 3286 static void 3287 iwh_m_stop(void *arg) 3288 { 3289 iwh_sc_t *sc = (iwh_sc_t *)arg; 3290 ieee80211com_t *ic = &sc->sc_ic; 3291 3292 iwh_stop(sc); 3293 3294 /* 3295 * release buffer for calibration 3296 */ 3297 iwh_release_calib_buffer(sc); 3298 3299 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3300 3301 mutex_enter(&sc->sc_mt_lock); 3302 3303 sc->sc_flags &= ~IWH_F_HW_ERR_RECOVER; 3304 sc->sc_flags &= ~IWH_F_RATE_AUTO_CTL; 3305 mutex_exit(&sc->sc_mt_lock); 3306 mutex_enter(&sc->sc_glock); 3307 sc->sc_flags &= ~IWH_F_RUNNING; 3308 3309 mutex_exit(&sc->sc_glock); 3310 } 3311 3312 /* 3313 * invoked by GLD to configure NIC 3314 */ 3315 static int 3316 iwh_m_unicst(void *arg, const uint8_t *macaddr) 3317 { 3318 iwh_sc_t *sc = (iwh_sc_t *)arg; 3319 ieee80211com_t *ic = &sc->sc_ic; 3320 int err; 3321 3322 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) { 3323 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 3324 mutex_enter(&sc->sc_glock); 3325 err = iwh_config(sc); 3326 mutex_exit(&sc->sc_glock); 3327 if (err != IWH_SUCCESS) { 3328 cmn_err(CE_WARN, "iwh_m_unicst(): " 3329 "failed to configure device\n"); 3330 goto fail; 3331 } 3332 } 3333 3334 return (IWH_SUCCESS); 3335 3336 fail: 3337 return (err); 3338 } 3339 3340 static int 3341 /* LINTED: argument unused in function: arg add m */ 3342 iwh_m_multicst(void *arg, boolean_t add, const uint8_t *m) 3343 { 3344 return (IWH_SUCCESS); 3345 } 3346 3347 static int 3348 /* LINTED: argument unused in function: arg on */ 3349 iwh_m_promisc(void *arg, boolean_t on) 3350 { 3351 return (IWH_SUCCESS); 3352 } 3353 3354 /* 3355 * kernel thread to deal with exceptional situation 3356 */ 3357 static void 3358 iwh_thread(iwh_sc_t *sc) 3359 { 3360 ieee80211com_t *ic = &sc->sc_ic; 3361 clock_t clk; 3362 int err, n = 0, timeout = 0; 3363 uint32_t tmp; 3364 #ifdef DEBUG 3365 int times = 0; 3366 #endif 3367 3368 mutex_enter(&sc->sc_mt_lock); 3369 3370 while (sc->sc_mf_thread_switch) { 3371 tmp = IWH_READ(sc, CSR_GP_CNTRL); 3372 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) { 3373 sc->sc_flags &= ~IWH_F_RADIO_OFF; 3374 } else { 3375 sc->sc_flags |= IWH_F_RADIO_OFF; 3376 } 3377 3378 /* 3379 * If in SUSPEND or the RF is OFF, do nothing. 3380 */ 3381 if ((sc->sc_flags & IWH_F_SUSPEND) || 3382 (sc->sc_flags & IWH_F_RADIO_OFF)) { 3383 mutex_exit(&sc->sc_mt_lock); 3384 delay(drv_usectohz(100000)); 3385 mutex_enter(&sc->sc_mt_lock); 3386 continue; 3387 } 3388 3389 /* 3390 * recovery fatal error 3391 */ 3392 if (ic->ic_mach && 3393 (sc->sc_flags & IWH_F_HW_ERR_RECOVER)) { 3394 3395 IWH_DBG((IWH_DEBUG_FW, 3396 "iwh_thread(): " 3397 "try to recover fatal hw error: %d\n", times++)); 3398 3399 iwh_stop(sc); 3400 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3401 3402 mutex_exit(&sc->sc_mt_lock); 3403 3404 delay(drv_usectohz(2000000 + n*500000)); 3405 3406 mutex_enter(&sc->sc_mt_lock); 3407 3408 err = iwh_init(sc); 3409 if (err != IWH_SUCCESS) { 3410 n++; 3411 if (n < 20) { 3412 continue; 3413 } 3414 } 3415 3416 n = 0; 3417 if (!err) { 3418 sc->sc_flags |= IWH_F_RUNNING; 3419 } 3420 3421 sc->sc_flags &= ~IWH_F_HW_ERR_RECOVER; 3422 3423 mutex_exit(&sc->sc_mt_lock); 3424 3425 delay(drv_usectohz(2000000)); 3426 3427 if (sc->sc_ostate != IEEE80211_S_INIT) { 3428 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 3429 } 3430 3431 mutex_enter(&sc->sc_mt_lock); 3432 } 3433 3434 /* 3435 * rate ctl 3436 */ 3437 if (ic->ic_mach && 3438 (sc->sc_flags & IWH_F_RATE_AUTO_CTL)) { 3439 clk = ddi_get_lbolt(); 3440 if (clk > sc->sc_clk + drv_usectohz(500000)) { 3441 iwh_amrr_timeout(sc); 3442 } 3443 } 3444 3445 mutex_exit(&sc->sc_mt_lock); 3446 delay(drv_usectohz(100000)); 3447 mutex_enter(&sc->sc_mt_lock); 3448 3449 if (sc->sc_tx_timer) { 3450 timeout++; 3451 if (10 == timeout) { 3452 sc->sc_tx_timer--; 3453 if (0 == sc->sc_tx_timer) { 3454 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 3455 sc->sc_ostate = IEEE80211_S_RUN; 3456 IWH_DBG((IWH_DEBUG_FW, 3457 "iwh_thread(): try to recover from" 3458 " 'send fail\n")); 3459 } 3460 timeout = 0; 3461 } 3462 } 3463 3464 } 3465 3466 sc->sc_mf_thread = NULL; 3467 cv_signal(&sc->sc_mt_cv); 3468 mutex_exit(&sc->sc_mt_lock); 3469 } 3470 3471 3472 /* 3473 * Send a command to the ucode. 3474 */ 3475 static int 3476 iwh_cmd(iwh_sc_t *sc, int code, const void *buf, int size, int async) 3477 { 3478 iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM]; 3479 iwh_tx_desc_t *desc; 3480 iwh_cmd_t *cmd; 3481 3482 ASSERT(size <= sizeof (cmd->data)); 3483 ASSERT(mutex_owned(&sc->sc_glock)); 3484 3485 IWH_DBG((IWH_DEBUG_CMD, "iwh_cmd() code[%d]", code)); 3486 desc = ring->data[ring->cur].desc; 3487 cmd = ring->data[ring->cur].cmd; 3488 3489 cmd->hdr.type = (uint8_t)code; 3490 cmd->hdr.flags = 0; 3491 cmd->hdr.qid = ring->qid; 3492 cmd->hdr.idx = ring->cur; 3493 (void) memcpy(cmd->data, buf, size); 3494 (void) memset(desc, 0, sizeof (*desc)); 3495 3496 desc->val0 = LE_32(1 << 24); 3497 desc->pa[0].tb1_addr = 3498 (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff); 3499 desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0; 3500 3501 /* 3502 * kick cmd ring XXX 3503 */ 3504 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3505 tfd_offset[ring->cur].val = 8; 3506 if (ring->cur < IWH_MAX_WIN_SIZE) { 3507 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3508 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8; 3509 } 3510 ring->cur = (ring->cur + 1) % ring->count; 3511 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3512 3513 if (async) { 3514 return (IWH_SUCCESS); 3515 } else { 3516 clock_t clk; 3517 sc->sc_flags &= ~IWH_F_CMD_DONE; 3518 clk = ddi_get_lbolt() + drv_usectohz(2000000); 3519 while (!(sc->sc_flags & IWH_F_CMD_DONE)) { 3520 if (cv_timedwait(&sc->sc_cmd_cv, 3521 &sc->sc_glock, clk) < 0) { 3522 break; 3523 } 3524 } 3525 3526 if (sc->sc_flags & IWH_F_CMD_DONE) { 3527 return (IWH_SUCCESS); 3528 } else { 3529 return (IWH_FAIL); 3530 } 3531 } 3532 } 3533 3534 /* 3535 * require ucode seting led of NIC 3536 */ 3537 static void 3538 iwh_set_led(iwh_sc_t *sc, uint8_t id, uint8_t off, uint8_t on) 3539 { 3540 iwh_led_cmd_t led; 3541 3542 led.interval = LE_32(100000); /* unit: 100ms */ 3543 led.id = id; 3544 led.off = off; 3545 led.on = on; 3546 3547 (void) iwh_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1); 3548 } 3549 3550 /* 3551 * necessary setting to NIC before authentication 3552 */ 3553 static int 3554 iwh_hw_set_before_auth(iwh_sc_t *sc) 3555 { 3556 ieee80211com_t *ic = &sc->sc_ic; 3557 ieee80211_node_t *in = ic->ic_bss; 3558 iwh_add_sta_t node; 3559 iwh_link_quality_cmd_t link_quality; 3560 struct ieee80211_rateset rs; 3561 uint16_t masks = 0, rate; 3562 int i, err; 3563 3564 /* 3565 * update adapter's configuration according 3566 * the info of target AP 3567 */ 3568 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid); 3569 sc->sc_config.chan = ieee80211_chan2ieee(ic, in->in_chan); 3570 if (IEEE80211_MODE_11B == ic->ic_curmode) { 3571 sc->sc_config.cck_basic_rates = 0x03; 3572 sc->sc_config.ofdm_basic_rates = 0; 3573 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) && 3574 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) { 3575 sc->sc_config.cck_basic_rates = 0; 3576 sc->sc_config.ofdm_basic_rates = 0x15; 3577 } else { /* assume 802.11b/g */ 3578 sc->sc_config.cck_basic_rates = 0x0f; 3579 sc->sc_config.ofdm_basic_rates = 0xff; 3580 } 3581 3582 sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 3583 RXON_FLG_SHORT_SLOT_MSK); 3584 3585 if (ic->ic_flags & IEEE80211_F_SHSLOT) { 3586 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK); 3587 } else { 3588 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK); 3589 } 3590 3591 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { 3592 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 3593 } else { 3594 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK); 3595 } 3596 3597 IWH_DBG((IWH_DEBUG_80211, "config chan %d flags %x " 3598 "filter_flags %x cck %x ofdm %x" 3599 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n", 3600 sc->sc_config.chan, sc->sc_config.flags, 3601 sc->sc_config.filter_flags, 3602 sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates, 3603 sc->sc_config.bssid[0], sc->sc_config.bssid[1], 3604 sc->sc_config.bssid[2], sc->sc_config.bssid[3], 3605 sc->sc_config.bssid[4], sc->sc_config.bssid[5])); 3606 3607 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 3608 sizeof (iwh_rxon_cmd_t), 1); 3609 if (err != IWH_SUCCESS) { 3610 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3611 "failed to config chan%d\n", sc->sc_config.chan); 3612 return (err); 3613 } 3614 3615 err = iwh_tx_power_table(sc, 1); 3616 if (err != IWH_SUCCESS) { 3617 cmn_err(CE_WARN, "iwh_config(): " 3618 "failed to set tx power table.\n"); 3619 return (err); 3620 } 3621 3622 /* 3623 * add default AP node 3624 */ 3625 (void) memset(&node, 0, sizeof (node)); 3626 IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid); 3627 node.mode = 0; 3628 node.sta.sta_id = IWH_AP_ID; 3629 node.station_flags = 0; 3630 err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 3631 if (err != IWH_SUCCESS) { 3632 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3633 "failed to add BSS node\n"); 3634 return (err); 3635 } 3636 3637 /* 3638 * TX_LINK_QUALITY cmd 3639 */ 3640 (void) memset(&link_quality, 0, sizeof (link_quality)); 3641 rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)]; 3642 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 3643 if (i < rs.ir_nrates) { 3644 rate = rs.ir_rates[rs.ir_nrates - i]; 3645 } else { 3646 rate = 2; 3647 } 3648 3649 if (2 == rate || 4 == rate || 11 == rate || 22 == rate) { 3650 masks |= RATE_MCS_CCK_MSK; 3651 } 3652 masks |= RATE_MCS_ANT_B_MSK; 3653 masks &= ~RATE_MCS_ANT_A_MSK; 3654 link_quality.rate_n_flags[i] = 3655 iwh_rate_to_plcp(rate) | masks; 3656 } 3657 3658 link_quality.general_params.single_stream_ant_msk = 2; 3659 link_quality.general_params.dual_stream_ant_msk = 3; 3660 link_quality.agg_params.agg_dis_start_th = 3; 3661 link_quality.agg_params.agg_time_limit = LE_16(4000); 3662 link_quality.sta_id = IWH_AP_ID; 3663 err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 3664 sizeof (link_quality), 1); 3665 if (err != IWH_SUCCESS) { 3666 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3667 "failed to config link quality table\n"); 3668 return (err); 3669 } 3670 3671 return (IWH_SUCCESS); 3672 } 3673 3674 /* 3675 * Send a scan request(assembly scan cmd) to the firmware. 3676 */ 3677 static int 3678 iwh_scan(iwh_sc_t *sc) 3679 { 3680 ieee80211com_t *ic = &sc->sc_ic; 3681 iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM]; 3682 iwh_tx_desc_t *desc; 3683 iwh_tx_data_t *data; 3684 iwh_cmd_t *cmd; 3685 iwh_scan_hdr_t *hdr; 3686 iwh_scan_chan_t *chan; 3687 struct ieee80211_frame *wh; 3688 ieee80211_node_t *in = ic->ic_bss; 3689 struct ieee80211_rateset *rs; 3690 enum ieee80211_phymode mode; 3691 uint8_t *frm; 3692 int i, pktlen, nrates; 3693 3694 sc->sc_flags |= IWH_F_SCANNING; 3695 3696 data = &ring->data[ring->cur]; 3697 desc = data->desc; 3698 cmd = (iwh_cmd_t *)data->dma_data.mem_va; 3699 3700 cmd->hdr.type = REPLY_SCAN_CMD; 3701 cmd->hdr.flags = 0; 3702 cmd->hdr.qid = ring->qid; 3703 cmd->hdr.idx = ring->cur | 0x40; 3704 3705 hdr = (iwh_scan_hdr_t *)cmd->data; 3706 (void) memset(hdr, 0, sizeof (iwh_scan_hdr_t)); 3707 hdr->nchan = 11; 3708 hdr->quiet_time = LE_16(5); 3709 hdr->quiet_plcp_th = LE_16(1); 3710 3711 hdr->flags = RXON_FLG_BAND_24G_MSK; 3712 hdr->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3713 LE_16((0x7 << RXON_RX_CHAIN_VALID_POS) | 3714 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3715 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3716 3717 hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK); 3718 hdr->tx_cmd.sta_id = IWH_BROADCAST_ID; 3719 hdr->tx_cmd.stop_time.life_time = 0xffffffff; 3720 hdr->tx_cmd.rate.r.rate_n_flags = iwh_rate_to_plcp(2); 3721 hdr->tx_cmd.rate.r.rate_n_flags |= 3722 (RATE_MCS_ANT_B_MSK |RATE_MCS_CCK_MSK); 3723 hdr->direct_scan[0].len = ic->ic_des_esslen; 3724 hdr->direct_scan[0].id = IEEE80211_ELEMID_SSID; 3725 3726 hdr->filter_flags = RXON_FILTER_ACCEPT_GRP_MSK | 3727 RXON_FILTER_BCON_AWARE_MSK; 3728 3729 if (ic->ic_des_esslen) { 3730 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid, 3731 ic->ic_des_esslen); 3732 } else { 3733 bzero(hdr->direct_scan[0].ssid, 3734 sizeof (hdr->direct_scan[0].ssid)); 3735 } 3736 3737 /* 3738 * a probe request frame is required after the REPLY_SCAN_CMD 3739 */ 3740 wh = (struct ieee80211_frame *)(hdr + 1); 3741 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 3742 IEEE80211_FC0_SUBTYPE_PROBE_REQ; 3743 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 3744 (void) memset(wh->i_addr1, 0xff, 6); 3745 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr); 3746 (void) memset(wh->i_addr3, 0xff, 6); 3747 *(uint16_t *)&wh->i_dur[0] = 0; 3748 *(uint16_t *)&wh->i_seq[0] = 0; 3749 3750 frm = (uint8_t *)(wh + 1); 3751 3752 /* 3753 * essid IE 3754 */ 3755 *frm++ = IEEE80211_ELEMID_SSID; 3756 *frm++ = in->in_esslen; 3757 (void) memcpy(frm, in->in_essid, in->in_esslen); 3758 frm += in->in_esslen; 3759 3760 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 3761 rs = &ic->ic_sup_rates[mode]; 3762 3763 /* 3764 * supported rates IE 3765 */ 3766 *frm++ = IEEE80211_ELEMID_RATES; 3767 nrates = rs->ir_nrates; 3768 if (nrates > IEEE80211_RATE_SIZE) { 3769 nrates = IEEE80211_RATE_SIZE; 3770 } 3771 3772 *frm++ = (uint8_t)nrates; 3773 (void) memcpy(frm, rs->ir_rates, nrates); 3774 frm += nrates; 3775 3776 /* 3777 * supported xrates IE 3778 */ 3779 if (rs->ir_nrates > IEEE80211_RATE_SIZE) { 3780 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE; 3781 *frm++ = IEEE80211_ELEMID_XRATES; 3782 *frm++ = (uint8_t)nrates; 3783 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates); 3784 frm += nrates; 3785 } 3786 3787 /* 3788 * optionnal IE (usually for wpa) 3789 */ 3790 if (ic->ic_opt_ie != NULL) { 3791 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len); 3792 frm += ic->ic_opt_ie_len; 3793 } 3794 3795 /* setup length of probe request */ 3796 hdr->tx_cmd.len = _PTRDIFF(frm, wh); 3797 hdr->len = hdr->nchan * sizeof (iwh_scan_chan_t) + 3798 hdr->tx_cmd.len + sizeof (iwh_scan_hdr_t); 3799 3800 /* 3801 * the attribute of the scan channels are required after the probe 3802 * request frame. 3803 */ 3804 chan = (iwh_scan_chan_t *)frm; 3805 for (i = 1; i <= hdr->nchan; i++, chan++) { 3806 chan->type = 3; 3807 chan->chan = (uint8_t)i; 3808 chan->tpc.tx_gain = 0x28; 3809 chan->tpc.dsp_atten = 110; 3810 chan->active_dwell = 20; 3811 chan->passive_dwell = 120; 3812 3813 frm += sizeof (iwh_scan_chan_t); 3814 } 3815 3816 pktlen = _PTRDIFF(frm, cmd); 3817 3818 (void) memset(desc, 0, sizeof (*desc)); 3819 desc->val0 = LE_32(1 << 24); 3820 desc->pa[0].tb1_addr = 3821 (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff); 3822 desc->pa[0].val1 = (pktlen << 4) & 0xfff0; 3823 3824 /* 3825 * maybe for cmd, filling the byte cnt table is not necessary. 3826 * anyway, we fill it here. 3827 */ 3828 sc->sc_shared->queues_byte_cnt_tbls[ring->qid] 3829 .tfd_offset[ring->cur].val = 8; 3830 if (ring->cur < IWH_MAX_WIN_SIZE) { 3831 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3832 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8; 3833 } 3834 3835 /* 3836 * kick cmd ring 3837 */ 3838 ring->cur = (ring->cur + 1) % ring->count; 3839 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3840 3841 return (IWH_SUCCESS); 3842 } 3843 3844 /* 3845 * configure NIC by using ucode commands after loading ucode. 3846 */ 3847 static int 3848 iwh_config(iwh_sc_t *sc) 3849 { 3850 ieee80211com_t *ic = &sc->sc_ic; 3851 iwh_powertable_cmd_t powertable; 3852 iwh_bt_cmd_t bt; 3853 iwh_add_sta_t node; 3854 iwh_rem_sta_t rm_sta; 3855 const uint8_t bcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 3856 iwh_link_quality_cmd_t link_quality; 3857 int i, err; 3858 uint16_t masks = 0; 3859 3860 /* 3861 * set power mode. Disable power management at present, do it later 3862 */ 3863 (void) memset(&powertable, 0, sizeof (powertable)); 3864 powertable.flags = LE_16(0x8); 3865 err = iwh_cmd(sc, POWER_TABLE_CMD, &powertable, 3866 sizeof (powertable), 0); 3867 if (err != IWH_SUCCESS) { 3868 cmn_err(CE_WARN, "iwh_config(): " 3869 "failed to set power mode\n"); 3870 return (err); 3871 } 3872 3873 /* 3874 * configure bt coexistence 3875 */ 3876 (void) memset(&bt, 0, sizeof (bt)); 3877 bt.flags = 3; 3878 bt.lead_time = 0xaa; 3879 bt.max_kill = 1; 3880 err = iwh_cmd(sc, REPLY_BT_CONFIG, &bt, 3881 sizeof (bt), 0); 3882 if (err != IWH_SUCCESS) { 3883 cmn_err(CE_WARN, "iwh_config(): " 3884 "failed to configurate bt coexistence\n"); 3885 return (err); 3886 } 3887 3888 /* 3889 * configure rxon 3890 */ 3891 (void) memset(&sc->sc_config, 0, sizeof (iwh_rxon_cmd_t)); 3892 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr); 3893 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr); 3894 sc->sc_config.chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 3895 sc->sc_config.flags = RXON_FLG_BAND_24G_MSK; 3896 3897 switch (ic->ic_opmode) { 3898 case IEEE80211_M_STA: 3899 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS; 3900 sc->sc_config.filter_flags |= 3901 LE_32(RXON_FILTER_DIS_DECRYPT_MSK | 3902 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3903 break; 3904 3905 case IEEE80211_M_IBSS: 3906 case IEEE80211_M_AHDEMO: 3907 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS; 3908 3909 sc->sc_config.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; 3910 sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3911 RXON_FILTER_DIS_DECRYPT_MSK | 3912 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3913 break; 3914 3915 case IEEE80211_M_HOSTAP: 3916 sc->sc_config.dev_type = RXON_DEV_TYPE_AP; 3917 break; 3918 3919 case IEEE80211_M_MONITOR: 3920 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER; 3921 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3922 RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); 3923 break; 3924 } 3925 3926 sc->sc_config.cck_basic_rates = 0x0f; 3927 sc->sc_config.ofdm_basic_rates = 0xff; 3928 3929 /* 3930 * set antenna 3931 */ 3932 sc->sc_config.rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3933 LE_16((0x7 << RXON_RX_CHAIN_VALID_POS) | 3934 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3935 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3936 3937 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 3938 sizeof (iwh_rxon_cmd_t), 0); 3939 if (err != IWH_SUCCESS) { 3940 cmn_err(CE_WARN, "iwh_config(): " 3941 "failed to set configure command\n"); 3942 return (err); 3943 } 3944 3945 /* 3946 * remove all nodes in NIC 3947 */ 3948 (void) memset(&rm_sta, 0, sizeof (rm_sta)); 3949 rm_sta.num_sta = 1; 3950 (void) memcpy(rm_sta.addr, bcast, 6); 3951 3952 err = iwh_cmd(sc, REPLY_REMOVE_STA, &rm_sta, sizeof (iwh_rem_sta_t), 0); 3953 if (err != IWH_SUCCESS) { 3954 cmn_err(CE_WARN, "iwh_config(): " 3955 "failed to remove broadcast node in hardware.\n"); 3956 return (err); 3957 } 3958 3959 /* 3960 * configure TX pwoer table 3961 */ 3962 err = iwh_tx_power_table(sc, 0); 3963 if (err != IWH_SUCCESS) { 3964 cmn_err(CE_WARN, "iwh_config(): " 3965 "failed to set tx power table.\n"); 3966 return (err); 3967 } 3968 3969 /* 3970 * add broadcast node so that we can send broadcast frame 3971 */ 3972 (void) memset(&node, 0, sizeof (node)); 3973 (void) memset(node.sta.addr, 0xff, 6); 3974 node.mode = 0; 3975 node.sta.sta_id = IWH_BROADCAST_ID; 3976 node.station_flags = 0; 3977 3978 err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0); 3979 if (err != IWH_SUCCESS) { 3980 cmn_err(CE_WARN, "iwh_config(): " 3981 "failed to add broadcast node\n"); 3982 return (err); 3983 } 3984 3985 /* 3986 * TX_LINK_QUALITY cmd 3987 */ 3988 (void) memset(&link_quality, 0, sizeof (link_quality)); 3989 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 3990 masks |= RATE_MCS_CCK_MSK; 3991 masks |= RATE_MCS_ANT_B_MSK; 3992 masks &= ~RATE_MCS_ANT_A_MSK; 3993 link_quality.rate_n_flags[i] = iwh_rate_to_plcp(2) | masks; 3994 } 3995 3996 link_quality.general_params.single_stream_ant_msk = 2; 3997 link_quality.general_params.dual_stream_ant_msk = 3; 3998 link_quality.agg_params.agg_dis_start_th = 3; 3999 link_quality.agg_params.agg_time_limit = LE_16(4000); 4000 link_quality.sta_id = IWH_BROADCAST_ID; 4001 err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 4002 sizeof (link_quality), 0); 4003 if (err != IWH_SUCCESS) { 4004 cmn_err(CE_WARN, "iwh_config(): " 4005 "failed to config link quality table\n"); 4006 return (err); 4007 } 4008 4009 return (IWH_SUCCESS); 4010 } 4011 4012 static void 4013 iwh_stop_master(iwh_sc_t *sc) 4014 { 4015 uint32_t tmp; 4016 int n; 4017 4018 tmp = IWH_READ(sc, CSR_RESET); 4019 IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER); 4020 4021 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4022 if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) == 4023 CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE) { 4024 return; 4025 } 4026 4027 for (n = 0; n < 2000; n++) { 4028 if (IWH_READ(sc, CSR_RESET) & 4029 CSR_RESET_REG_FLAG_MASTER_DISABLED) { 4030 break; 4031 } 4032 DELAY(1000); 4033 } 4034 4035 #ifdef DEBUG 4036 if (2000 == n) { 4037 IWH_DBG((IWH_DEBUG_HW, 4038 "timeout waiting for master stop\n")); 4039 } 4040 #endif 4041 } 4042 4043 static int 4044 iwh_power_up(iwh_sc_t *sc) 4045 { 4046 uint32_t tmp; 4047 4048 iwh_mac_access_enter(sc); 4049 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4050 tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC; 4051 tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN; 4052 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4053 iwh_mac_access_exit(sc); 4054 4055 DELAY(5000); 4056 return (IWH_SUCCESS); 4057 } 4058 4059 /* 4060 * hardware initialization 4061 */ 4062 static int 4063 iwh_preinit(iwh_sc_t *sc) 4064 { 4065 uint32_t tmp; 4066 int n; 4067 uint8_t vlink; 4068 uint16_t radio_cfg; 4069 4070 /* 4071 * clear any pending interrupts 4072 */ 4073 IWH_WRITE(sc, CSR_INT, 0xffffffff); 4074 4075 tmp = IWH_READ(sc, CSR_GIO_CHICKEN_BITS); 4076 IWH_WRITE(sc, CSR_GIO_CHICKEN_BITS, 4077 tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); 4078 4079 tmp = IWH_READ(sc, CSR_ANA_PLL_CFG); 4080 IWH_WRITE(sc, CSR_ANA_PLL_CFG, tmp | IWH_CSR_ANA_PLL_CFG); 4081 4082 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4083 IWH_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 4084 4085 /* 4086 * wait for clock ready 4087 */ 4088 for (n = 0; n < 1000; n++) { 4089 if (IWH_READ(sc, CSR_GP_CNTRL) & 4090 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { 4091 break; 4092 } 4093 DELAY(10); 4094 } 4095 4096 if (1000 == n) { 4097 return (ETIMEDOUT); 4098 } 4099 4100 iwh_mac_access_enter(sc); 4101 4102 iwh_reg_write(sc, ALM_APMG_CLK_EN, APMG_CLK_REG_VAL_DMA_CLK_RQT); 4103 4104 DELAY(20); 4105 tmp = iwh_reg_read(sc, ALM_APMG_PCIDEV_STT); 4106 iwh_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp | 4107 APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE); 4108 iwh_mac_access_exit(sc); 4109 4110 radio_cfg = IWH_READ_EEP_SHORT(sc, EEP_SP_RADIO_CONFIGURATION); 4111 if (SP_RADIO_TYPE_MSK(radio_cfg) < SP_RADIO_TYPE_MAX) { 4112 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4113 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4114 tmp | SP_RADIO_TYPE_MSK(radio_cfg) | 4115 SP_RADIO_STEP_MSK(radio_cfg) | 4116 SP_RADIO_DASH_MSK(radio_cfg)); 4117 } else { 4118 cmn_err(CE_WARN, "iwh_preinit(): " 4119 "radio configuration information in eeprom is wrong\n"); 4120 return (IWH_FAIL); 4121 } 4122 4123 4124 IWH_WRITE(sc, CSR_INT_COALESCING, 512 / 32); 4125 4126 (void) iwh_power_up(sc); 4127 4128 if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) { 4129 tmp = ddi_get32(sc->sc_cfg_handle, 4130 (uint32_t *)(sc->sc_cfg_base + 0xe8)); 4131 ddi_put32(sc->sc_cfg_handle, 4132 (uint32_t *)(sc->sc_cfg_base + 0xe8), 4133 tmp & ~(1 << 11)); 4134 } 4135 4136 vlink = ddi_get8(sc->sc_cfg_handle, 4137 (uint8_t *)(sc->sc_cfg_base + 0xf0)); 4138 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0), 4139 vlink & ~2); 4140 4141 tmp = IWH_READ(sc, CSR_SW_VER); 4142 tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | 4143 CSR_HW_IF_CONFIG_REG_BIT_MAC_SI; 4144 IWH_WRITE(sc, CSR_SW_VER, tmp); 4145 4146 /* 4147 * make sure power supply on each part of the hardware 4148 */ 4149 iwh_mac_access_enter(sc); 4150 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4151 tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4152 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4153 DELAY(5); 4154 4155 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4156 tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4157 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4158 iwh_mac_access_exit(sc); 4159 4160 return (IWH_SUCCESS); 4161 } 4162 4163 /* 4164 * set up semphore flag to own EEPROM 4165 */ 4166 static int 4167 iwh_eep_sem_down(iwh_sc_t *sc) 4168 { 4169 int count1, count2; 4170 uint32_t tmp; 4171 4172 for (count1 = 0; count1 < 1000; count1++) { 4173 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4174 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4175 tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM); 4176 4177 for (count2 = 0; count2 < 2; count2++) { 4178 if (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) & 4179 CSR_HW_IF_CONFIG_REG_EEP_SEM) { 4180 return (IWH_SUCCESS); 4181 } 4182 DELAY(10000); 4183 } 4184 } 4185 return (IWH_FAIL); 4186 } 4187 4188 /* 4189 * reset semphore flag to release EEPROM 4190 */ 4191 static void 4192 iwh_eep_sem_up(iwh_sc_t *sc) 4193 { 4194 uint32_t tmp; 4195 4196 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4197 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4198 tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM)); 4199 } 4200 4201 /* 4202 * This function read all infomation from eeprom 4203 */ 4204 static int 4205 iwh_eep_load(iwh_sc_t *sc) 4206 { 4207 int i, rr; 4208 uint32_t rv, tmp, eep_gp; 4209 uint16_t addr, eep_sz = sizeof (sc->sc_eep_map); 4210 uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map; 4211 4212 /* 4213 * read eeprom gp register in CSR 4214 */ 4215 eep_gp = IWH_READ(sc, CSR_EEPROM_GP); 4216 if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) == 4217 CSR_EEPROM_GP_BAD_SIGNATURE) { 4218 IWH_DBG((IWH_DEBUG_EEPROM, "not find eeprom\n")); 4219 return (IWH_FAIL); 4220 } 4221 4222 rr = iwh_eep_sem_down(sc); 4223 if (rr != 0) { 4224 IWH_DBG((IWH_DEBUG_EEPROM, "driver failed to own EEPROM\n")); 4225 return (IWH_FAIL); 4226 } 4227 4228 for (addr = 0; addr < eep_sz; addr += 2) { 4229 IWH_WRITE(sc, CSR_EEPROM_REG, addr<<1); 4230 tmp = IWH_READ(sc, CSR_EEPROM_REG); 4231 IWH_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2)); 4232 4233 for (i = 0; i < 10; i++) { 4234 rv = IWH_READ(sc, CSR_EEPROM_REG); 4235 if (rv & 1) { 4236 break; 4237 } 4238 DELAY(10); 4239 } 4240 4241 if (!(rv & 1)) { 4242 IWH_DBG((IWH_DEBUG_EEPROM, 4243 "time out when read eeprome\n")); 4244 iwh_eep_sem_up(sc); 4245 return (IWH_FAIL); 4246 } 4247 4248 eep_p[addr/2] = rv >> 16; 4249 } 4250 4251 iwh_eep_sem_up(sc); 4252 return (IWH_SUCCESS); 4253 } 4254 4255 /* 4256 * initialize mac address in ieee80211com_t struct 4257 */ 4258 static void 4259 iwh_get_mac_from_eep(iwh_sc_t *sc) 4260 { 4261 ieee80211com_t *ic = &sc->sc_ic; 4262 4263 IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->sc_eep_map[EEP_MAC_ADDRESS]); 4264 4265 IWH_DBG((IWH_DEBUG_EEPROM, "mac:%2x:%2x:%2x:%2x:%2x:%2x\n", 4266 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2], 4267 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5])); 4268 } 4269 4270 /* 4271 * main initialization function 4272 */ 4273 static int 4274 iwh_init(iwh_sc_t *sc) 4275 { 4276 int n, err; 4277 clock_t clk; 4278 4279 /* 4280 * release buffer for calibration 4281 */ 4282 iwh_release_calib_buffer(sc); 4283 4284 mutex_enter(&sc->sc_glock); 4285 sc->sc_flags &= ~IWH_F_FW_INIT; 4286 4287 err = iwh_init_common(sc); 4288 if (err != IWH_SUCCESS) { 4289 cmn_err(CE_WARN, "iwh_init(): " 4290 "failed to initialize chipset\n"); 4291 mutex_exit(&sc->sc_glock); 4292 return (IWH_FAIL); 4293 } 4294 4295 /* 4296 * backup ucode data part for future use. 4297 */ 4298 (void) memcpy(sc->sc_dma_fw_data_bak.mem_va, 4299 sc->sc_dma_fw_data.mem_va, 4300 sc->sc_dma_fw_data.alength); 4301 4302 for (n = 0; n < 2; n++) { 4303 /* load firmware init segment into NIC */ 4304 err = iwh_load_init_firmware(sc); 4305 if (err != IWH_SUCCESS) { 4306 cmn_err(CE_WARN, "iwh_init(): " 4307 "failed to setup init firmware\n"); 4308 continue; 4309 } 4310 4311 /* 4312 * now press "execute" start running 4313 */ 4314 IWH_WRITE(sc, CSR_RESET, 0); 4315 break; 4316 } 4317 4318 mutex_exit(&sc->sc_glock); 4319 4320 if (2 == n) { 4321 cmn_err(CE_WARN, "iwh_init(): " 4322 "failed to load init firmware\n"); 4323 return (IWH_FAIL); 4324 } 4325 4326 mutex_enter(&sc->sc_ucode_lock); 4327 4328 clk = ddi_get_lbolt() + drv_usectohz(1000000); 4329 while (!(sc->sc_flags & IWH_F_FW_INIT)) { 4330 if (cv_timedwait(&sc->sc_ucode_cv, 4331 &sc->sc_ucode_lock, clk) < 0) { 4332 break; 4333 } 4334 } 4335 4336 if (!(sc->sc_flags & IWH_F_FW_INIT)) { 4337 cmn_err(CE_WARN, "iwh_init(): " 4338 "failed to process init alive.\n"); 4339 mutex_exit(&sc->sc_ucode_lock); 4340 return (IWH_FAIL); 4341 } 4342 4343 mutex_exit(&sc->sc_ucode_lock); 4344 4345 /* 4346 * stop chipset for initializing chipset again 4347 */ 4348 iwh_stop(sc); 4349 4350 mutex_enter(&sc->sc_glock); 4351 sc->sc_flags &= ~IWH_F_FW_INIT; 4352 4353 err = iwh_init_common(sc); 4354 if (err != IWH_SUCCESS) { 4355 cmn_err(CE_WARN, "iwh_init(): " 4356 "failed to initialize chipset\n"); 4357 mutex_exit(&sc->sc_glock); 4358 return (IWH_FAIL); 4359 } 4360 4361 for (n = 0; n < 2; n++) { 4362 /* 4363 * load firmware run segment into NIC 4364 */ 4365 err = iwh_load_run_firmware(sc); 4366 if (err != IWH_SUCCESS) { 4367 cmn_err(CE_WARN, "iwh_init(): " 4368 "failed to setup run firmware\n"); 4369 continue; 4370 } 4371 4372 /* 4373 * now press "execute" start running 4374 */ 4375 IWH_WRITE(sc, CSR_RESET, 0); 4376 break; 4377 } 4378 4379 mutex_exit(&sc->sc_glock); 4380 4381 if (2 == n) { 4382 cmn_err(CE_WARN, "iwh_init(): " 4383 "failed to load run firmware\n"); 4384 return (IWH_FAIL); 4385 } 4386 4387 mutex_enter(&sc->sc_ucode_lock); 4388 4389 clk = ddi_get_lbolt() + drv_usectohz(1000000); 4390 while (!(sc->sc_flags & IWH_F_FW_INIT)) { 4391 if (cv_timedwait(&sc->sc_ucode_cv, 4392 &sc->sc_ucode_lock, clk) < 0) { 4393 break; 4394 } 4395 } 4396 4397 if (!(sc->sc_flags & IWH_F_FW_INIT)) { 4398 cmn_err(CE_WARN, "iwh_init(): " 4399 "failed to process runtime alive.\n"); 4400 mutex_exit(&sc->sc_ucode_lock); 4401 return (IWH_FAIL); 4402 } 4403 4404 mutex_exit(&sc->sc_ucode_lock); 4405 4406 mutex_enter(&sc->sc_glock); 4407 sc->sc_flags &= ~IWH_F_FW_INIT; 4408 4409 /* 4410 * at this point, the firmware is loaded OK, then config the hardware 4411 * with the ucode API, including rxon, txpower, etc. 4412 */ 4413 err = iwh_config(sc); 4414 if (err) { 4415 cmn_err(CE_WARN, "iwh_init(): " 4416 "failed to configure device\n"); 4417 mutex_exit(&sc->sc_glock); 4418 return (IWH_FAIL); 4419 } 4420 4421 /* 4422 * at this point, hardware may receive beacons :) 4423 */ 4424 mutex_exit(&sc->sc_glock); 4425 return (IWH_SUCCESS); 4426 } 4427 4428 /* 4429 * stop or disable NIC 4430 */ 4431 static void 4432 iwh_stop(iwh_sc_t *sc) 4433 { 4434 uint32_t tmp; 4435 int i; 4436 4437 mutex_enter(&sc->sc_glock); 4438 4439 IWH_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); 4440 /* 4441 * disable interrupts 4442 */ 4443 IWH_WRITE(sc, CSR_INT_MASK, 0); 4444 IWH_WRITE(sc, CSR_INT, CSR_INI_SET_MASK); 4445 IWH_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff); 4446 4447 /* 4448 * reset all Tx rings 4449 */ 4450 for (i = 0; i < IWH_NUM_QUEUES; i++) { 4451 iwh_reset_tx_ring(sc, &sc->sc_txq[i]); 4452 } 4453 4454 /* 4455 * reset Rx ring 4456 */ 4457 iwh_reset_rx_ring(sc); 4458 4459 iwh_mac_access_enter(sc); 4460 iwh_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT); 4461 iwh_mac_access_exit(sc); 4462 4463 DELAY(5); 4464 4465 iwh_stop_master(sc); 4466 4467 sc->sc_tx_timer = 0; 4468 tmp = IWH_READ(sc, CSR_RESET); 4469 IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET); 4470 4471 mutex_exit(&sc->sc_glock); 4472 } 4473 4474 /* 4475 * Naive implementation of the Adaptive Multi Rate Retry algorithm: 4476 * "IEEE 802.11 Rate Adaptation: A Practical Approach" 4477 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti 4478 * INRIA Sophia - Projet Planete 4479 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html 4480 */ 4481 #define is_success(amrr) \ 4482 ((amrr)->retrycnt < (amrr)->txcnt / 10) 4483 #define is_failure(amrr) \ 4484 ((amrr)->retrycnt > (amrr)->txcnt / 3) 4485 #define is_enough(amrr) \ 4486 ((amrr)->txcnt > 100) 4487 #define is_min_rate(in) \ 4488 (0 == (in)->in_txrate) 4489 #define is_max_rate(in) \ 4490 ((in)->in_rates.ir_nrates - 1 == (in)->in_txrate) 4491 #define increase_rate(in) \ 4492 ((in)->in_txrate++) 4493 #define decrease_rate(in) \ 4494 ((in)->in_txrate--) 4495 #define reset_cnt(amrr) \ 4496 { (amrr)->txcnt = (amrr)->retrycnt = 0; } 4497 4498 #define IWH_AMRR_MIN_SUCCESS_THRESHOLD 1 4499 #define IWH_AMRR_MAX_SUCCESS_THRESHOLD 15 4500 4501 static void 4502 iwh_amrr_init(iwh_amrr_t *amrr) 4503 { 4504 amrr->success = 0; 4505 amrr->recovery = 0; 4506 amrr->txcnt = amrr->retrycnt = 0; 4507 amrr->success_threshold = IWH_AMRR_MIN_SUCCESS_THRESHOLD; 4508 } 4509 4510 static void 4511 iwh_amrr_timeout(iwh_sc_t *sc) 4512 { 4513 ieee80211com_t *ic = &sc->sc_ic; 4514 4515 IWH_DBG((IWH_DEBUG_RATECTL, "iwh_amrr_timeout() enter\n")); 4516 4517 if (IEEE80211_M_STA == ic->ic_opmode) { 4518 iwh_amrr_ratectl(NULL, ic->ic_bss); 4519 } else { 4520 ieee80211_iterate_nodes(&ic->ic_sta, iwh_amrr_ratectl, NULL); 4521 } 4522 4523 sc->sc_clk = ddi_get_lbolt(); 4524 } 4525 4526 static void 4527 /* LINTED: argument unused in function: arg */ 4528 iwh_amrr_ratectl(void *arg, ieee80211_node_t *in) 4529 { 4530 iwh_amrr_t *amrr = (iwh_amrr_t *)in; 4531 int need_change = 0; 4532 4533 if (is_success(amrr) && is_enough(amrr)) { 4534 amrr->success++; 4535 if (amrr->success >= amrr->success_threshold && 4536 !is_max_rate(in)) { 4537 amrr->recovery = 1; 4538 amrr->success = 0; 4539 increase_rate(in); 4540 IWH_DBG((IWH_DEBUG_RATECTL, 4541 "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n", 4542 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 4543 need_change = 1; 4544 } else { 4545 amrr->recovery = 0; 4546 } 4547 } else if (is_failure(amrr)) { 4548 amrr->success = 0; 4549 if (!is_min_rate(in)) { 4550 if (amrr->recovery) { 4551 amrr->success_threshold++; 4552 if (amrr->success_threshold > 4553 IWH_AMRR_MAX_SUCCESS_THRESHOLD) { 4554 amrr->success_threshold = 4555 IWH_AMRR_MAX_SUCCESS_THRESHOLD; 4556 } 4557 } else { 4558 amrr->success_threshold = 4559 IWH_AMRR_MIN_SUCCESS_THRESHOLD; 4560 } 4561 decrease_rate(in); 4562 IWH_DBG((IWH_DEBUG_RATECTL, 4563 "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n", 4564 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 4565 need_change = 1; 4566 } 4567 amrr->recovery = 0; /* paper is incorrect */ 4568 } 4569 4570 if (is_enough(amrr) || need_change) { 4571 reset_cnt(amrr); 4572 } 4573 } 4574 4575 /* 4576 * translate indirect address in eeprom to direct address 4577 * in eeprom and return address of entry whos indirect address 4578 * is indi_addr 4579 */ 4580 static uint8_t * 4581 iwh_eep_addr_trans(iwh_sc_t *sc, uint32_t indi_addr) 4582 { 4583 uint32_t di_addr; 4584 uint16_t temp; 4585 4586 if (!(indi_addr & INDIRECT_ADDRESS)) { 4587 di_addr = indi_addr; 4588 return (&sc->sc_eep_map[di_addr]); 4589 } 4590 4591 switch (indi_addr & INDIRECT_TYPE_MSK) { 4592 case INDIRECT_GENERAL: 4593 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_GENERAL); 4594 break; 4595 4596 case INDIRECT_HOST: 4597 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_HOST); 4598 break; 4599 4600 case INDIRECT_REGULATORY: 4601 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_REGULATORY); 4602 break; 4603 4604 case INDIRECT_CALIBRATION: 4605 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_CALIBRATION); 4606 break; 4607 4608 case INDIRECT_PROCESS_ADJST: 4609 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_PROCESS_ADJST); 4610 break; 4611 4612 case INDIRECT_OTHERS: 4613 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_OTHERS); 4614 break; 4615 4616 default: 4617 temp = 0; 4618 cmn_err(CE_WARN, "iwh_eep_addr_trans(): " 4619 "incorrect indirect eeprom address.\n"); 4620 break; 4621 } 4622 4623 di_addr = (indi_addr & ADDRESS_MSK) + (temp << 1); 4624 4625 return (&sc->sc_eep_map[di_addr]); 4626 } 4627 4628 /* 4629 * loade a section of ucode into NIC 4630 */ 4631 static int 4632 iwh_put_seg_fw(iwh_sc_t *sc, uint32_t addr_s, uint32_t addr_d, uint32_t len) 4633 { 4634 4635 iwh_mac_access_enter(sc); 4636 4637 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL), 4638 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); 4639 4640 IWH_WRITE(sc, IWH_FH_SRVC_CHNL_SRAM_ADDR_REG(IWH_FH_SRVC_CHNL), addr_d); 4641 4642 IWH_WRITE(sc, IWH_FH_TFDIB_CTRL0_REG(IWH_FH_SRVC_CHNL), 4643 (addr_s & FH_MEM_TFDIB_DRAM_ADDR_LSB_MASK)); 4644 4645 IWH_WRITE(sc, IWH_FH_TFDIB_CTRL1_REG(IWH_FH_SRVC_CHNL), len); 4646 4647 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_BUF_STS_REG(IWH_FH_SRVC_CHNL), 4648 (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) | 4649 (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) | 4650 IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); 4651 4652 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL), 4653 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 4654 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL | 4655 IWH_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 4656 4657 iwh_mac_access_exit(sc); 4658 4659 return (IWH_SUCCESS); 4660 } 4661 4662 /* 4663 * necessary setting during alive notification 4664 */ 4665 static int 4666 iwh_alive_common(iwh_sc_t *sc) 4667 { 4668 uint32_t base; 4669 uint32_t i; 4670 iwh_wimax_coex_cmd_t w_cmd; 4671 iwh_calibration_crystal_cmd_t c_cmd; 4672 uint32_t rv; 4673 4674 /* 4675 * initialize SCD related registers to make TX work. 4676 */ 4677 iwh_mac_access_enter(sc); 4678 4679 /* 4680 * read sram address of data base. 4681 */ 4682 sc->sc_scd_base = iwh_reg_read(sc, IWH_SCD_SRAM_BASE_ADDR); 4683 4684 for (base = sc->sc_scd_base + IWH_SCD_CONTEXT_DATA_OFFSET; 4685 base < sc->sc_scd_base + IWH_SCD_TX_STTS_BITMAP_OFFSET; 4686 base += 4) { 4687 iwh_mem_write(sc, base, 0); 4688 } 4689 4690 for (; base < sc->sc_scd_base + IWH_SCD_TRANSLATE_TBL_OFFSET; 4691 base += 4) { 4692 iwh_mem_write(sc, base, 0); 4693 } 4694 4695 for (i = 0; i < sizeof (uint16_t) * IWH_NUM_QUEUES; i += 4) { 4696 iwh_mem_write(sc, base + i, 0); 4697 } 4698 4699 iwh_reg_write(sc, IWH_SCD_DRAM_BASE_ADDR, 4700 sc->sc_dma_sh.cookie.dmac_address >> 10); 4701 4702 iwh_reg_write(sc, IWH_SCD_QUEUECHAIN_SEL, 4703 IWH_SCD_QUEUECHAIN_SEL_ALL(IWH_NUM_QUEUES)); 4704 4705 iwh_reg_write(sc, IWH_SCD_AGGR_SEL, 0); 4706 4707 for (i = 0; i < IWH_NUM_QUEUES; i++) { 4708 iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(i), 0); 4709 IWH_WRITE(sc, HBUS_TARG_WRPTR, 0 | (i << 8)); 4710 iwh_mem_write(sc, sc->sc_scd_base + 4711 IWH_SCD_CONTEXT_QUEUE_OFFSET(i), 0); 4712 iwh_mem_write(sc, sc->sc_scd_base + 4713 IWH_SCD_CONTEXT_QUEUE_OFFSET(i) + 4714 sizeof (uint32_t), 4715 ((SCD_WIN_SIZE << IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & 4716 IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | 4717 ((SCD_FRAME_LIMIT << 4718 IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & 4719 IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); 4720 } 4721 4722 iwh_reg_write(sc, IWH_SCD_INTERRUPT_MASK, (1 << IWH_NUM_QUEUES) - 1); 4723 4724 iwh_reg_write(sc, (IWH_SCD_BASE + 0x10), 4725 SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); 4726 4727 IWH_WRITE(sc, HBUS_TARG_WRPTR, (IWH_CMD_QUEUE_NUM << 8)); 4728 iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(IWH_CMD_QUEUE_NUM), 0); 4729 4730 /* 4731 * queue 0-7 map to FIFO 0-7 and 4732 * all queues work under FIFO mode(none-scheduler_ack) 4733 */ 4734 for (i = 0; i < 4; i++) { 4735 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i), 4736 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4737 ((3-i) << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4738 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4739 IWH_SCD_QUEUE_STTS_REG_MSK); 4740 } 4741 4742 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(IWH_CMD_QUEUE_NUM), 4743 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4744 (IWH_CMD_FIFO_NUM << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4745 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4746 IWH_SCD_QUEUE_STTS_REG_MSK); 4747 4748 for (i = 5; i < 7; i++) { 4749 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i), 4750 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4751 (i << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4752 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4753 IWH_SCD_QUEUE_STTS_REG_MSK); 4754 } 4755 4756 iwh_mac_access_exit(sc); 4757 4758 (void) memset(&w_cmd, 0, sizeof (w_cmd)); 4759 4760 rv = iwh_cmd(sc, COEX_PRIORITY_TABLE_CMD, &w_cmd, sizeof (w_cmd), 1); 4761 if (rv != IWH_SUCCESS) { 4762 cmn_err(CE_WARN, "iwh_alive_common(): " 4763 "failed to send wimax coexist command.\n"); 4764 return (rv); 4765 } 4766 4767 (void) memset(&c_cmd, 0, sizeof (c_cmd)); 4768 4769 c_cmd.opCode = PHY_CALIBRATE_CRYSTAL_FRQ_CMD; 4770 c_cmd.data.cap_pin1 = sc->sc_eep_calib->xtal_calib[0]; 4771 c_cmd.data.cap_pin2 = sc->sc_eep_calib->xtal_calib[1]; 4772 4773 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &c_cmd, sizeof (c_cmd), 1); 4774 if (rv != IWH_SUCCESS) { 4775 cmn_err(CE_WARN, "iwh_alive_common(): " 4776 "failed to send crystal frq calibration command.\n"); 4777 return (rv); 4778 } 4779 4780 /* 4781 * make sure crystal frequency calibration ready 4782 * before next operations. 4783 */ 4784 DELAY(1000); 4785 4786 return (IWH_SUCCESS); 4787 } 4788 4789 /* 4790 * save results of calibration from ucode 4791 */ 4792 static void 4793 iwh_save_calib_result(iwh_sc_t *sc, iwh_rx_desc_t *desc) 4794 { 4795 struct iwh_calib_results *res_p = &sc->sc_calib_results; 4796 struct iwh_calib_hdr *calib_hdr = (struct iwh_calib_hdr *)(desc + 1); 4797 int len = desc->len; 4798 4799 /* 4800 * ensure the size of buffer is not too big 4801 */ 4802 len = (len & FH_RSCSR_FRAME_SIZE_MASK) - 4; 4803 4804 switch (calib_hdr->op_code) { 4805 case PHY_CALIBRATE_LO_CMD: 4806 if (NULL == res_p->lo_res) { 4807 res_p->lo_res = kmem_alloc(len, KM_NOSLEEP); 4808 } 4809 4810 if (NULL == res_p->lo_res) { 4811 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4812 "failed to allocate memory.\n"); 4813 return; 4814 } 4815 4816 res_p->lo_res_len = len; 4817 (void) memcpy(res_p->lo_res, calib_hdr, len); 4818 break; 4819 4820 case PHY_CALIBRATE_TX_IQ_CMD: 4821 if (NULL == res_p->tx_iq_res) { 4822 res_p->tx_iq_res = kmem_alloc(len, KM_NOSLEEP); 4823 } 4824 4825 if (NULL == res_p->tx_iq_res) { 4826 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4827 "failed to allocate memory.\n"); 4828 return; 4829 } 4830 4831 res_p->tx_iq_res_len = len; 4832 (void) memcpy(res_p->tx_iq_res, calib_hdr, len); 4833 break; 4834 4835 case PHY_CALIBRATE_TX_IQ_PERD_CMD: 4836 if (NULL == res_p->tx_iq_perd_res) { 4837 res_p->tx_iq_perd_res = kmem_alloc(len, KM_NOSLEEP); 4838 } 4839 4840 if (NULL == res_p->tx_iq_perd_res) { 4841 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4842 "failed to allocate memory.\n"); 4843 } 4844 4845 res_p->tx_iq_perd_res_len = len; 4846 (void) memcpy(res_p->tx_iq_perd_res, calib_hdr, len); 4847 break; 4848 4849 default: 4850 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4851 "incorrect calibration type.\n"); 4852 break; 4853 } 4854 4855 } 4856 4857 /* 4858 * configure TX pwoer table 4859 */ 4860 static int 4861 iwh_tx_power_table(iwh_sc_t *sc, int async) 4862 { 4863 iwh_tx_power_table_cmd_t txpower; 4864 int i, err; 4865 4866 (void) memset(&txpower, 0, sizeof (txpower)); 4867 4868 txpower.band = 1; /* for 2.4G */ 4869 txpower.channel = sc->sc_config.chan; 4870 txpower.pa_measurements = 1; 4871 txpower.max_mcs = 23; 4872 4873 for (i = 0; i < 24; i++) { 4874 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[0] = 0x16; 4875 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[1] = 0x16; 4876 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[2] = 0x16; 4877 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[0] = 0x6E; 4878 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[1] = 0x6E; 4879 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[2] = 0x6E; 4880 } 4881 4882 for (i = 0; i < 2; i++) { 4883 txpower.db.cck_power[i].s.radio_tx_gain[0] = 0x16; 4884 txpower.db.cck_power[i].s.radio_tx_gain[1] = 0x16; 4885 txpower.db.cck_power[i].s.radio_tx_gain[2] = 0x16; 4886 txpower.db.cck_power[i].s.dsp_predis_atten[0] = 0x6E; 4887 txpower.db.cck_power[i].s.dsp_predis_atten[1] = 0x6E; 4888 txpower.db.cck_power[i].s.dsp_predis_atten[2] = 0x6E; 4889 } 4890 4891 err = iwh_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower, 4892 sizeof (txpower), async); 4893 if (err != IWH_SUCCESS) { 4894 cmn_err(CE_WARN, "iwh_tx_power_table(): " 4895 "failed to set tx power table.\n"); 4896 return (err); 4897 } 4898 4899 return (IWH_SUCCESS); 4900 } 4901 4902 static void 4903 iwh_release_calib_buffer(iwh_sc_t *sc) 4904 { 4905 if (sc->sc_calib_results.lo_res != NULL) { 4906 kmem_free(sc->sc_calib_results.lo_res, 4907 sc->sc_calib_results.lo_res_len); 4908 sc->sc_calib_results.lo_res = NULL; 4909 } 4910 4911 if (sc->sc_calib_results.tx_iq_res != NULL) { 4912 kmem_free(sc->sc_calib_results.tx_iq_res, 4913 sc->sc_calib_results.tx_iq_res_len); 4914 sc->sc_calib_results.tx_iq_res = NULL; 4915 } 4916 4917 if (sc->sc_calib_results.tx_iq_perd_res != NULL) { 4918 kmem_free(sc->sc_calib_results.tx_iq_perd_res, 4919 sc->sc_calib_results.tx_iq_perd_res_len); 4920 sc->sc_calib_results.tx_iq_perd_res = NULL; 4921 } 4922 4923 } 4924 4925 /* 4926 * a section of intialization 4927 */ 4928 static int 4929 iwh_init_common(iwh_sc_t *sc) 4930 { 4931 int32_t qid; 4932 uint32_t tmp; 4933 4934 (void) iwh_preinit(sc); 4935 4936 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4937 if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) { 4938 cmn_err(CE_WARN, "iwh_init_common(): " 4939 "radio transmitter is off\n"); 4940 return (IWH_FAIL); 4941 } 4942 4943 /* 4944 * init Rx ring 4945 */ 4946 iwh_mac_access_enter(sc); 4947 IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 4948 4949 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); 4950 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG, 4951 sc->sc_rxq.dma_desc.cookie.dmac_address >> 8); 4952 4953 IWH_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG, 4954 ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address + 4955 offsetof(struct iwh_shared, val0)) >> 4)); 4956 4957 IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 4958 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | 4959 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | 4960 IWH_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K | 4961 (RX_QUEUE_SIZE_LOG << 4962 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); 4963 iwh_mac_access_exit(sc); 4964 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 4965 (RX_QUEUE_SIZE - 1) & ~0x7); 4966 4967 /* 4968 * init Tx rings 4969 */ 4970 iwh_mac_access_enter(sc); 4971 iwh_reg_write(sc, IWH_SCD_TXFACT, 0); 4972 4973 /* 4974 * keep warm page 4975 */ 4976 IWH_WRITE(sc, IWH_FH_KW_MEM_ADDR_REG, 4977 sc->sc_dma_kw.cookie.dmac_address >> 4); 4978 4979 for (qid = 0; qid < IWH_NUM_QUEUES; qid++) { 4980 IWH_WRITE(sc, FH_MEM_CBBC_QUEUE(qid), 4981 sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8); 4982 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(qid), 4983 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 4984 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); 4985 } 4986 4987 iwh_mac_access_exit(sc); 4988 4989 /* 4990 * clear "radio off" and "disable command" bits 4991 */ 4992 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 4993 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, 4994 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 4995 4996 /* 4997 * clear any pending interrupts 4998 */ 4999 IWH_WRITE(sc, CSR_INT, 0xffffffff); 5000 5001 /* 5002 * enable interrupts 5003 */ 5004 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 5005 5006 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 5007 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 5008 5009 return (IWH_SUCCESS); 5010 } 5011