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