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