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