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