1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2004 David Young. All rights reserved. 8 * 9 * This code was written by David Young. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the author nor the names of any co-contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David 27 * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 34 * OF SUCH DAMAGE. 35 */ 36 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 41 #include <sys/param.h> 42 #include <sys/types.h> 43 #include <sys/signal.h> 44 #include <sys/stream.h> 45 #include <sys/termio.h> 46 #include <sys/errno.h> 47 #include <sys/file.h> 48 #include <sys/cmn_err.h> 49 #include <sys/stropts.h> 50 #include <sys/strtty.h> 51 #include <sys/kbio.h> 52 #include <sys/cred.h> 53 #include <sys/stat.h> 54 #include <sys/consdev.h> 55 #include <sys/kmem.h> 56 #include <sys/modctl.h> 57 #include <sys/ddi.h> 58 #include <sys/sunddi.h> 59 #include <sys/pci.h> 60 #include <sys/errno.h> 61 #include <sys/mac.h> 62 #include <sys/dlpi.h> 63 #include <sys/ethernet.h> 64 #include <sys/list.h> 65 #include <sys/byteorder.h> 66 #include <sys/strsun.h> 67 #include <sys/strsubr.h> 68 #include <sys/policy.h> 69 #include <inet/common.h> 70 #include <inet/nd.h> 71 #include <inet/mi.h> 72 #include <inet/wifi_ioctl.h> 73 #include <sys/mac_wifi.h> 74 #include <sys/crypto/common.h> 75 #include <sys/crypto/api.h> 76 77 #include "rtwreg.h" 78 #include "rtwvar.h" 79 #include "smc93cx6var.h" 80 #include "rtwphy.h" 81 #include "rtwphyio.h" 82 83 /* 84 * PIO access attributes for registers 85 */ 86 static ddi_device_acc_attr_t rtw_reg_accattr = { 87 DDI_DEVICE_ATTR_V0, 88 DDI_STRUCTURE_LE_ACC, 89 DDI_STRICTORDER_ACC, 90 DDI_DEFAULT_ACC 91 }; 92 93 /* 94 * DMA access attributes for descriptors and bufs: NOT to be byte swapped. 95 */ 96 static ddi_device_acc_attr_t rtw_desc_accattr = { 97 DDI_DEVICE_ATTR_V0, 98 DDI_NEVERSWAP_ACC, 99 DDI_STRICTORDER_ACC, 100 DDI_DEFAULT_ACC 101 }; 102 static ddi_device_acc_attr_t rtw_buf_accattr = { 103 DDI_DEVICE_ATTR_V0, 104 DDI_NEVERSWAP_ACC, 105 DDI_STRICTORDER_ACC, 106 DDI_DEFAULT_ACC 107 }; 108 109 /* 110 * Describes the chip's DMA engine 111 */ 112 static ddi_dma_attr_t dma_attr_desc = { 113 DMA_ATTR_V0, /* dma_attr version */ 114 0x0000000000000000ull, /* dma_attr_addr_lo */ 115 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */ 116 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 117 0x100, /* dma_attr_align */ 118 0xFFFFFFFF, /* dma_attr_burstsizes */ 119 0x00000001, /* dma_attr_minxfer */ 120 0x00000000FFFFull, /* dma_attr_maxxfer */ 121 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 122 1, /* dma_attr_sgllen */ 123 1, /* dma_attr_granular */ 124 0 /* dma_attr_flags */ 125 }; 126 127 static ddi_dma_attr_t dma_attr_rxbuf = { 128 DMA_ATTR_V0, /* dma_attr version */ 129 0x0000000000000000ull, /* dma_attr_addr_lo */ 130 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */ 131 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 132 (uint32_t)16, /* dma_attr_align */ 133 0xFFFFFFFF, /* dma_attr_burstsizes */ 134 0x00000001, /* dma_attr_minxfer */ 135 0x00000000FFFFull, /* dma_attr_maxxfer */ 136 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 137 1, /* dma_attr_sgllen */ 138 1, /* dma_attr_granular */ 139 0 /* dma_attr_flags */ 140 }; 141 142 static ddi_dma_attr_t dma_attr_txbuf = { 143 DMA_ATTR_V0, /* dma_attr version */ 144 0x0000000000000000ull, /* dma_attr_addr_lo */ 145 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */ 146 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 147 (uint32_t)16, /* dma_attr_align */ 148 0xFFFFFFFF, /* dma_attr_burstsizes */ 149 0x00000001, /* dma_attr_minxfer */ 150 0x00000000FFFFull, /* dma_attr_maxxfer */ 151 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 152 1, /* dma_attr_sgllen */ 153 1, /* dma_attr_granular */ 154 0 /* dma_attr_flags */ 155 }; 156 157 158 static void *rtw_soft_state_p = NULL; 159 160 static int rtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd); 161 static int rtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd); 162 static int rtw_m_stat(void *, uint_t, uint64_t *); 163 static int rtw_m_start(void *); 164 static void rtw_m_stop(void *); 165 static int rtw_m_promisc(void *, boolean_t); 166 static int rtw_m_multicst(void *, boolean_t, const uint8_t *); 167 static int rtw_m_unicst(void *, const uint8_t *); 168 static mblk_t *rtw_m_tx(void *, mblk_t *); 169 static void rtw_m_ioctl(void *, queue_t *, mblk_t *); 170 static mac_callbacks_t rtw_m_callbacks = { 171 MC_IOCTL, 172 rtw_m_stat, 173 rtw_m_start, 174 rtw_m_stop, 175 rtw_m_promisc, 176 rtw_m_multicst, 177 rtw_m_unicst, 178 rtw_m_tx, 179 NULL, 180 rtw_m_ioctl 181 }; 182 183 DDI_DEFINE_STREAM_OPS(rtw_dev_ops, nulldev, nulldev, rtw_attach, rtw_detach, 184 nodev, NULL, D_MP, NULL); 185 186 static struct modldrv rtw_modldrv = { 187 &mod_driverops, /* Type of module. This one is a driver */ 188 "realtek 802.11b driver", /* short description */ 189 &rtw_dev_ops /* driver specific ops */ 190 }; 191 192 static struct modlinkage modlinkage = { 193 MODREV_1, (void *)&rtw_modldrv, NULL 194 }; 195 196 static uint32_t rtw_qlen[RTW_NTXPRI] = { 197 RTW_TXQLENLO, 198 RTW_TXQLENMD, 199 RTW_TXQLENHI, 200 RTW_TXQLENBCN 201 }; 202 203 static uint32_t rtw_dbg_flags = 0; 204 /* 205 * RTW_DEBUG_ATTACH | RTW_DEBUG_TUNE | 206 * RTW_DEBUG_ACCESS | RTW_DEBUG_INIT | RTW_DEBUG_PKTFILT | 207 * RTW_DEBUG_RECV | RTW_DEBUG_XMIT | RTW_DEBUG_80211 | RTW_DEBUG_INTR | 208 * RTW_DEBUG_PKTDUMP; 209 */ 210 211 int 212 _info(struct modinfo *modinfop) 213 { 214 return (mod_info(&modlinkage, modinfop)); 215 } 216 217 int 218 _init(void) 219 { 220 int status; 221 222 status = ddi_soft_state_init(&rtw_soft_state_p, 223 sizeof (rtw_softc_t), 1); 224 if (status != 0) 225 return (status); 226 227 mac_init_ops(&rtw_dev_ops, "rtw"); 228 status = mod_install(&modlinkage); 229 if (status != 0) { 230 mac_fini_ops(&rtw_dev_ops); 231 ddi_soft_state_fini(&rtw_soft_state_p); 232 } 233 return (status); 234 } 235 236 int 237 _fini(void) 238 { 239 int status; 240 241 status = mod_remove(&modlinkage); 242 if (status == 0) { 243 mac_fini_ops(&rtw_dev_ops); 244 ddi_soft_state_fini(&rtw_soft_state_p); 245 } 246 return (status); 247 } 248 249 void 250 rtw_dbg(uint32_t dbg_flags, const int8_t *fmt, ...) 251 { 252 va_list args; 253 254 if (dbg_flags & rtw_dbg_flags) { 255 va_start(args, fmt); 256 vcmn_err(CE_CONT, fmt, args); 257 va_end(args); 258 } 259 } 260 261 #ifdef DEBUG 262 static void 263 rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where) 264 { 265 #define PRINTREG32(sc, reg) \ 266 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 267 "%s: reg[ " #reg " / %03x ] = %08x\n", \ 268 dvname, reg, RTW_READ(regs, reg)) 269 270 #define PRINTREG16(sc, reg) \ 271 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 272 "%s: reg[ " #reg " / %03x ] = %04x\n", \ 273 dvname, reg, RTW_READ16(regs, reg)) 274 275 #define PRINTREG8(sc, reg) \ 276 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 277 "%s: reg[ " #reg " / %03x ] = %02x\n", \ 278 dvname, reg, RTW_READ8(regs, reg)) 279 280 RTW_DPRINTF(RTW_DEBUG_REGDUMP, "%s: %s\n", dvname, where); 281 282 PRINTREG32(regs, RTW_IDR0); 283 PRINTREG32(regs, RTW_IDR1); 284 PRINTREG32(regs, RTW_MAR0); 285 PRINTREG32(regs, RTW_MAR1); 286 PRINTREG32(regs, RTW_TSFTRL); 287 PRINTREG32(regs, RTW_TSFTRH); 288 PRINTREG32(regs, RTW_TLPDA); 289 PRINTREG32(regs, RTW_TNPDA); 290 PRINTREG32(regs, RTW_THPDA); 291 PRINTREG32(regs, RTW_TCR); 292 PRINTREG32(regs, RTW_RCR); 293 PRINTREG32(regs, RTW_TINT); 294 PRINTREG32(regs, RTW_TBDA); 295 PRINTREG32(regs, RTW_ANAPARM); 296 PRINTREG32(regs, RTW_BB); 297 PRINTREG32(regs, RTW_PHYCFG); 298 PRINTREG32(regs, RTW_WAKEUP0L); 299 PRINTREG32(regs, RTW_WAKEUP0H); 300 PRINTREG32(regs, RTW_WAKEUP1L); 301 PRINTREG32(regs, RTW_WAKEUP1H); 302 PRINTREG32(regs, RTW_WAKEUP2LL); 303 PRINTREG32(regs, RTW_WAKEUP2LH); 304 PRINTREG32(regs, RTW_WAKEUP2HL); 305 PRINTREG32(regs, RTW_WAKEUP2HH); 306 PRINTREG32(regs, RTW_WAKEUP3LL); 307 PRINTREG32(regs, RTW_WAKEUP3LH); 308 PRINTREG32(regs, RTW_WAKEUP3HL); 309 PRINTREG32(regs, RTW_WAKEUP3HH); 310 PRINTREG32(regs, RTW_WAKEUP4LL); 311 PRINTREG32(regs, RTW_WAKEUP4LH); 312 PRINTREG32(regs, RTW_WAKEUP4HL); 313 PRINTREG32(regs, RTW_WAKEUP4HH); 314 PRINTREG32(regs, RTW_DK0); 315 PRINTREG32(regs, RTW_DK1); 316 PRINTREG32(regs, RTW_DK2); 317 PRINTREG32(regs, RTW_DK3); 318 PRINTREG32(regs, RTW_RETRYCTR); 319 PRINTREG32(regs, RTW_RDSAR); 320 PRINTREG32(regs, RTW_FER); 321 PRINTREG32(regs, RTW_FEMR); 322 PRINTREG32(regs, RTW_FPSR); 323 PRINTREG32(regs, RTW_FFER); 324 325 /* 16-bit registers */ 326 PRINTREG16(regs, RTW_BRSR); 327 PRINTREG16(regs, RTW_IMR); 328 PRINTREG16(regs, RTW_ISR); 329 PRINTREG16(regs, RTW_BCNITV); 330 PRINTREG16(regs, RTW_ATIMWND); 331 PRINTREG16(regs, RTW_BINTRITV); 332 PRINTREG16(regs, RTW_ATIMTRITV); 333 PRINTREG16(regs, RTW_CRC16ERR); 334 PRINTREG16(regs, RTW_CRC0); 335 PRINTREG16(regs, RTW_CRC1); 336 PRINTREG16(regs, RTW_CRC2); 337 PRINTREG16(regs, RTW_CRC3); 338 PRINTREG16(regs, RTW_CRC4); 339 PRINTREG16(regs, RTW_CWR); 340 341 /* 8-bit registers */ 342 PRINTREG8(regs, RTW_CR); 343 PRINTREG8(regs, RTW_9346CR); 344 PRINTREG8(regs, RTW_CONFIG0); 345 PRINTREG8(regs, RTW_CONFIG1); 346 PRINTREG8(regs, RTW_CONFIG2); 347 PRINTREG8(regs, RTW_MSR); 348 PRINTREG8(regs, RTW_CONFIG3); 349 PRINTREG8(regs, RTW_CONFIG4); 350 PRINTREG8(regs, RTW_TESTR); 351 PRINTREG8(regs, RTW_PSR); 352 PRINTREG8(regs, RTW_SCR); 353 PRINTREG8(regs, RTW_PHYDELAY); 354 PRINTREG8(regs, RTW_CRCOUNT); 355 PRINTREG8(regs, RTW_PHYADDR); 356 PRINTREG8(regs, RTW_PHYDATAW); 357 PRINTREG8(regs, RTW_PHYDATAR); 358 PRINTREG8(regs, RTW_CONFIG5); 359 PRINTREG8(regs, RTW_TPPOLL); 360 361 PRINTREG16(regs, RTW_BSSID16); 362 PRINTREG32(regs, RTW_BSSID32); 363 #undef PRINTREG32 364 #undef PRINTREG16 365 #undef PRINTREG8 366 } 367 368 #endif /* DEBUG */ 369 static const char * 370 rtw_access_string(enum rtw_access access) 371 { 372 switch (access) { 373 case RTW_ACCESS_NONE: 374 return ("none"); 375 case RTW_ACCESS_CONFIG: 376 return ("config"); 377 case RTW_ACCESS_ANAPARM: 378 return ("anaparm"); 379 default: 380 return ("unknown"); 381 } 382 } 383 384 /* 385 * Enable registers, switch register banks. 386 */ 387 void 388 rtw_config0123_enable(struct rtw_regs *regs, int enable) 389 { 390 uint8_t ecr; 391 ecr = RTW_READ8(regs, RTW_9346CR); 392 ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK); 393 if (enable) 394 ecr |= RTW_9346CR_EEM_CONFIG; 395 else { 396 RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3)); 397 ecr |= RTW_9346CR_EEM_NORMAL; 398 } 399 RTW_WRITE8(regs, RTW_9346CR, ecr); 400 RTW_SYNC(regs, RTW_9346CR, RTW_9346CR); 401 } 402 403 /* 404 * requires rtw_config0123_enable(, 1) 405 */ 406 void 407 rtw_anaparm_enable(struct rtw_regs *regs, int enable) 408 { 409 uint8_t cfg3; 410 411 cfg3 = RTW_READ8(regs, RTW_CONFIG3); 412 cfg3 |= RTW_CONFIG3_CLKRUNEN; 413 if (enable) 414 cfg3 |= RTW_CONFIG3_PARMEN; 415 else 416 cfg3 &= ~RTW_CONFIG3_PARMEN; 417 RTW_WRITE8(regs, RTW_CONFIG3, cfg3); 418 RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3); 419 } 420 421 /* 422 * requires rtw_anaparm_enable(, 1) 423 */ 424 void 425 rtw_txdac_enable(rtw_softc_t *rsc, int enable) 426 { 427 uint32_t anaparm; 428 struct rtw_regs *regs = &rsc->sc_regs; 429 430 anaparm = RTW_READ(regs, RTW_ANAPARM); 431 if (enable) 432 anaparm &= ~RTW_ANAPARM_TXDACOFF; 433 else 434 anaparm |= RTW_ANAPARM_TXDACOFF; 435 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 436 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 437 } 438 439 static void 440 rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess) 441 { 442 ASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM); 443 ASSERT(regs->r_access >= RTW_ACCESS_NONE && 444 regs->r_access <= RTW_ACCESS_ANAPARM); 445 446 if (naccess == regs->r_access) 447 return; 448 449 switch (naccess) { 450 case RTW_ACCESS_NONE: 451 switch (regs->r_access) { 452 case RTW_ACCESS_ANAPARM: 453 rtw_anaparm_enable(regs, 0); 454 /*FALLTHROUGH*/ 455 case RTW_ACCESS_CONFIG: 456 rtw_config0123_enable(regs, 0); 457 /*FALLTHROUGH*/ 458 case RTW_ACCESS_NONE: 459 break; 460 } 461 break; 462 case RTW_ACCESS_CONFIG: 463 switch (regs->r_access) { 464 case RTW_ACCESS_NONE: 465 rtw_config0123_enable(regs, 1); 466 /*FALLTHROUGH*/ 467 case RTW_ACCESS_CONFIG: 468 break; 469 case RTW_ACCESS_ANAPARM: 470 rtw_anaparm_enable(regs, 0); 471 break; 472 } 473 break; 474 case RTW_ACCESS_ANAPARM: 475 switch (regs->r_access) { 476 case RTW_ACCESS_NONE: 477 rtw_config0123_enable(regs, 1); 478 /*FALLTHROUGH*/ 479 case RTW_ACCESS_CONFIG: 480 rtw_anaparm_enable(regs, 1); 481 /*FALLTHROUGH*/ 482 case RTW_ACCESS_ANAPARM: 483 break; 484 } 485 break; 486 } 487 } 488 489 void 490 rtw_set_access(struct rtw_regs *regs, enum rtw_access access) 491 { 492 rtw_set_access1(regs, access); 493 RTW_DPRINTF(RTW_DEBUG_ACCESS, 494 "%s: access %s -> %s\n", __func__, 495 rtw_access_string(regs->r_access), 496 rtw_access_string(access)); 497 regs->r_access = access; 498 } 499 500 501 void 502 rtw_continuous_tx_enable(rtw_softc_t *rsc, int enable) 503 { 504 struct rtw_regs *regs = &rsc->sc_regs; 505 506 uint32_t tcr; 507 tcr = RTW_READ(regs, RTW_TCR); 508 tcr &= ~RTW_TCR_LBK_MASK; 509 if (enable) 510 tcr |= RTW_TCR_LBK_CONT; 511 else 512 tcr |= RTW_TCR_LBK_NORMAL; 513 RTW_WRITE(regs, RTW_TCR, tcr); 514 RTW_SYNC(regs, RTW_TCR, RTW_TCR); 515 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 516 rtw_txdac_enable(rsc, !enable); 517 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 518 rtw_set_access(regs, RTW_ACCESS_NONE); 519 } 520 521 static int 522 rtw_chip_reset1(struct rtw_regs *regs, const char *dvname) 523 { 524 uint8_t cr; 525 int i; 526 527 RTW_WRITE8(regs, RTW_CR, RTW_CR_RST); 528 529 RTW_WBR(regs, RTW_CR, RTW_CR); 530 531 for (i = 0; i < 1000; i++) { 532 cr = RTW_READ8(regs, RTW_CR); 533 if ((cr & RTW_CR_RST) == 0) { 534 RTW_DPRINTF(RTW_DEBUG_RESET, 535 "%s: reset in %dus\n", dvname, i); 536 return (0); 537 } 538 RTW_RBR(regs, RTW_CR, RTW_CR); 539 DELAY(10); /* 10us */ 540 } 541 542 cmn_err(CE_WARN, "%s: reset failed\n", dvname); 543 return (ETIMEDOUT); 544 } 545 546 static int 547 rtw_chip_reset(struct rtw_regs *regs, const char *dvname) 548 { 549 RTW_WBW(regs, RTW_CR, RTW_TCR); 550 return (rtw_chip_reset1(regs, dvname)); 551 } 552 553 static void 554 rtw_disable_interrupts(struct rtw_regs *regs) 555 { 556 RTW_WRITE16(regs, RTW_IMR, 0); 557 RTW_WRITE16(regs, RTW_ISR, 0xffff); 558 (void) RTW_READ16(regs, RTW_IMR); 559 } 560 561 static void 562 rtw_enable_interrupts(rtw_softc_t *rsc) 563 { 564 struct rtw_regs *regs = &rsc->sc_regs; 565 566 rsc->sc_inten = RTW_INTR_RX | RTW_INTR_TX | RTW_INTR_IOERROR; 567 568 RTW_WRITE16(regs, RTW_IMR, rsc->sc_inten); 569 RTW_WRITE16(regs, RTW_ISR, 0xffff); 570 571 /* XXX necessary? */ 572 if (rsc->sc_intr_ack != NULL) 573 (*rsc->sc_intr_ack)(regs); 574 } 575 576 static int 577 rtw_recall_eeprom(struct rtw_regs *regs, const char *dvname) 578 { 579 int i; 580 uint8_t ecr; 581 582 ecr = RTW_READ8(regs, RTW_9346CR); 583 ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD; 584 RTW_WRITE8(regs, RTW_9346CR, ecr); 585 586 RTW_WBR(regs, RTW_9346CR, RTW_9346CR); 587 588 /* wait 25ms for completion */ 589 for (i = 0; i < 250; i++) { 590 ecr = RTW_READ8(regs, RTW_9346CR); 591 if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) { 592 RTW_DPRINTF(RTW_DEBUG_RESET, 593 "%s: recall EEPROM in %dus\n", dvname, i * 100); 594 return (0); 595 } 596 RTW_RBR(regs, RTW_9346CR, RTW_9346CR); 597 DELAY(100); 598 } 599 cmn_err(CE_WARN, "%s: recall EEPROM failed\n", dvname); 600 return (ETIMEDOUT); 601 } 602 603 static int 604 rtw_reset(rtw_softc_t *rsc) 605 { 606 int rc; 607 608 rc = rtw_chip_reset(&rsc->sc_regs, "rtw"); 609 if (rc != 0) 610 return (rc); 611 612 (void) rtw_recall_eeprom(&rsc->sc_regs, "rtw"); 613 return (0); 614 } 615 616 void 617 rtw_set_mode(struct rtw_regs *regs, int mode) 618 { 619 uint8_t command; 620 command = RTW_READ8(regs, RTW_9346CR); 621 command = command &~ RTW_EPROM_CMD_OPERATING_MODE_MASK; 622 command = command | (mode<<RTW_EPROM_CMD_OPERATING_MODE_SHIFT); 623 command = command &~ (1<<RTW_EPROM_CS_SHIFT); 624 command = command &~ (1<<RTW_EPROM_CK_SHIFT); 625 RTW_WRITE8(regs, RTW_9346CR, command); 626 } 627 628 void 629 rtw_dma_start(struct rtw_regs *regs, int priority) 630 { 631 uint8_t check = 0; 632 633 check = RTW_READ8(regs, RTW_TPPOLL); 634 switch (priority) { 635 case (0): 636 RTW_WRITE8(regs, RTW_TPPOLL, 637 (1<< RTW_TX_DMA_POLLING_LOWPRIORITY_SHIFT) | check); 638 break; 639 case (1): 640 RTW_WRITE8(regs, RTW_TPPOLL, 641 (1<< RTW_TX_DMA_POLLING_NORMPRIORITY_SHIFT) | check); 642 break; 643 case (2): 644 RTW_WRITE8(regs, RTW_TPPOLL, 645 (1<< RTW_TX_DMA_POLLING_HIPRIORITY_SHIFT) | check); 646 break; 647 } 648 (void) RTW_READ8(regs, RTW_TPPOLL); 649 } 650 651 void 652 rtw_beacon_tx_disable(struct rtw_regs *regs) 653 { 654 uint8_t mask = 0; 655 mask |= (1 << RTW_TX_DMA_STOP_BEACON_SHIFT); 656 rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG); 657 RTW_WRITE8(regs, RTW_TPPOLL, mask); 658 rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL); 659 } 660 661 static void 662 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable); 663 664 void 665 rtw_rtx_disable(rtw_softc_t *rsc) 666 { 667 struct rtw_regs *regs = &rsc->sc_regs; 668 669 rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 0); 670 (void) RTW_READ8(regs, RTW_CR); 671 } 672 673 static void 674 rtw_srom_free(struct rtw_srom *sr) 675 { 676 if (sr->sr_content == NULL) 677 return; 678 kmem_free(sr->sr_content, sr->sr_size); 679 sr->sr_size = 0; 680 sr->sr_content = NULL; 681 } 682 683 /*ARGSUSED*/ 684 static void 685 rtw_srom_defaults(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold, 686 enum rtw_rfchipid *rfchipid, uint32_t *rcr) 687 { 688 *flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV); 689 *cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT; 690 *rcr |= RTW_RCR_ENCS1; 691 *rfchipid = RTW_RFCHIPID_PHILIPS; 692 } 693 694 static int 695 rtw_srom_parse(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold, 696 enum rtw_rfchipid *rfchipid, uint32_t *rcr, enum rtw_locale *locale, 697 const char *dvname) 698 { 699 int i; 700 const char *rfname, *paname; 701 char scratch[sizeof ("unknown 0xXX")]; 702 uint16_t version; 703 uint8_t mac[IEEE80211_ADDR_LEN]; 704 705 *flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV); 706 *rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2); 707 708 version = RTW_SR_GET16(sr, RTW_SR_VERSION); 709 RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: SROM version %d.%d", dvname, 710 version >> 8, version & 0xff); 711 712 if (version <= 0x0101) { 713 cmn_err(CE_NOTE, " is not understood, limping along " 714 "with defaults\n"); 715 rtw_srom_defaults(sr, flags, cs_threshold, rfchipid, rcr); 716 return (0); 717 } 718 719 for (i = 0; i < IEEE80211_ADDR_LEN; i++) 720 mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i); 721 722 RTW_DPRINTF(RTW_DEBUG_ATTACH, 723 "%s: EEPROM MAC %s\n", dvname, mac); 724 725 *cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR); 726 727 if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0) 728 *flags |= RTW_F_ANTDIV; 729 730 /* 731 * Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems 732 * to be reversed. 733 */ 734 if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0) 735 *flags |= RTW_F_DIGPHY; 736 if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0) 737 *flags |= RTW_F_DFLANTB; 738 739 *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM), 740 RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1); 741 742 *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID); 743 switch (*rfchipid) { 744 case RTW_RFCHIPID_GCT: /* this combo seen in the wild */ 745 rfname = "GCT GRF5101"; 746 paname = "Winspring WS9901"; 747 break; 748 case RTW_RFCHIPID_MAXIM: 749 rfname = "Maxim MAX2820"; /* guess */ 750 paname = "Maxim MAX2422"; /* guess */ 751 break; 752 case RTW_RFCHIPID_INTERSIL: 753 rfname = "Intersil HFA3873"; /* guess */ 754 paname = "Intersil <unknown>"; 755 break; 756 case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */ 757 rfname = "Philips SA2400A"; 758 paname = "Philips SA2411"; 759 break; 760 case RTW_RFCHIPID_RFMD: 761 /* 762 * this is the same front-end as an atw(4)! 763 */ 764 rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */ 765 "LNA: RFMD RF2494, " /* mentioned in Realtek docs */ 766 "SYN: Silicon Labs Si4126"; 767 paname = "RFMD RF2189"; /* mentioned in Realtek docs */ 768 break; 769 case RTW_RFCHIPID_RESERVED: 770 rfname = paname = "reserved"; 771 break; 772 default: 773 (void) snprintf(scratch, sizeof (scratch), 774 "unknown 0x%02x", *rfchipid); 775 rfname = paname = scratch; 776 } 777 RTW_DPRINTF(RTW_DEBUG_PHY, "%s: RF: %s, PA: %s\n", 778 dvname, rfname, paname); 779 780 switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) { 781 case RTW_CONFIG0_GL_USA: 782 *locale = RTW_LOCALE_USA; 783 break; 784 case RTW_CONFIG0_GL_EUROPE: 785 *locale = RTW_LOCALE_EUROPE; 786 break; 787 case RTW_CONFIG0_GL_JAPAN: 788 *locale = RTW_LOCALE_JAPAN; 789 break; 790 default: 791 *locale = RTW_LOCALE_UNKNOWN; 792 break; 793 } 794 return (0); 795 } 796 797 /* 798 * Returns -1 on failure. 799 */ 800 static int 801 rtw_srom_read(struct rtw_regs *regs, uint32_t flags, struct rtw_srom *sr, 802 const char *dvname) 803 { 804 int rc; 805 struct seeprom_descriptor sd; 806 uint8_t ecr; 807 808 (void) memset(&sd, 0, sizeof (sd)); 809 810 ecr = RTW_READ8(regs, RTW_9346CR); 811 812 if ((flags & RTW_F_9356SROM) != 0) { 813 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c56 SROM\n", dvname); 814 sr->sr_size = 256; 815 sd.sd_chip = C56_66; 816 } else { 817 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c46 SROM\n", dvname); 818 sr->sr_size = 128; 819 sd.sd_chip = C46; 820 } 821 822 ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK | 823 RTW_9346CR_EEM_MASK | RTW_9346CR_EECS); 824 ecr |= RTW_9346CR_EEM_PROGRAM; 825 826 RTW_WRITE8(regs, RTW_9346CR, ecr); 827 828 sr->sr_content = kmem_zalloc(sr->sr_size, KM_SLEEP); 829 830 if (sr->sr_content == NULL) { 831 cmn_err(CE_WARN, "%s: unable to allocate SROM buffer\n", 832 dvname); 833 return (ENOMEM); 834 } 835 836 (void) memset(sr->sr_content, 0, sr->sr_size); 837 838 /* 839 * RTL8180 has a single 8-bit register for controlling the 840 * 93cx6 SROM. There is no "ready" bit. The RTL8180 841 * input/output sense is the reverse of read_seeprom's. 842 */ 843 sd.sd_handle = regs->r_handle; 844 sd.sd_base = regs->r_base; 845 sd.sd_regsize = 1; 846 sd.sd_control_offset = RTW_9346CR; 847 sd.sd_status_offset = RTW_9346CR; 848 sd.sd_dataout_offset = RTW_9346CR; 849 sd.sd_CK = RTW_9346CR_EESK; 850 sd.sd_CS = RTW_9346CR_EECS; 851 sd.sd_DI = RTW_9346CR_EEDO; 852 sd.sd_DO = RTW_9346CR_EEDI; 853 /* 854 * make read_seeprom enter EEPROM read/write mode 855 */ 856 sd.sd_MS = ecr; 857 sd.sd_RDY = 0; 858 859 /* 860 * TBD bus barriers 861 */ 862 if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) { 863 cmn_err(CE_WARN, "%s: could not read SROM\n", dvname); 864 kmem_free(sr->sr_content, sr->sr_size); 865 sr->sr_content = NULL; 866 return (-1); /* XXX */ 867 } 868 869 /* 870 * end EEPROM read/write mode 871 */ 872 RTW_WRITE8(regs, RTW_9346CR, 873 (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL); 874 RTW_WBRW(regs, RTW_9346CR, RTW_9346CR); 875 876 if ((rc = rtw_recall_eeprom(regs, dvname)) != 0) 877 return (rc); 878 879 #ifdef SROM_DEBUG 880 { 881 int i; 882 RTW_DPRINTF(RTW_DEBUG_ATTACH, 883 "\n%s: serial ROM:\n\t", dvname); 884 for (i = 0; i < sr->sr_size/2; i++) { 885 RTW_DPRINTF(RTW_DEBUG_ATTACH, 886 "offset-0x%x: %04x", 2*i, sr->sr_content[i]); 887 } 888 } 889 #endif /* DEBUG */ 890 return (0); 891 } 892 893 static void 894 rtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 895 const char *dvname) 896 { 897 uint8_t cfg4; 898 const char *method; 899 900 cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK; 901 902 switch (rfchipid) { 903 default: 904 cfg4 |= LSHIFT(0, RTW_CONFIG4_RFTYPE_MASK); 905 method = "fallback"; 906 break; 907 case RTW_RFCHIPID_INTERSIL: 908 cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL; 909 method = "Intersil"; 910 break; 911 case RTW_RFCHIPID_PHILIPS: 912 cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS; 913 method = "Philips"; 914 break; 915 case RTW_RFCHIPID_GCT: /* XXX a guess */ 916 case RTW_RFCHIPID_RFMD: 917 cfg4 |= RTW_CONFIG4_RFTYPE_RFMD; 918 method = "RFMD"; 919 break; 920 } 921 922 RTW_WRITE8(regs, RTW_CONFIG4, cfg4); 923 924 RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4); 925 926 RTW_DPRINTF(RTW_DEBUG_INIT, 927 "%s: %s RF programming method, %02x\n", dvname, method, 928 RTW_READ8(regs, RTW_CONFIG4)); 929 } 930 931 static void 932 rtw_init_channels(enum rtw_locale locale, 933 struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1], 934 const char *dvname) 935 { 936 int i; 937 const char *name = NULL; 938 #define ADD_CHANNEL(_chans, _chan) { \ 939 (*_chans)[_chan].ich_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;\ 940 (*_chans)[_chan].ich_freq = \ 941 ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ich_flags);\ 942 } 943 944 switch (locale) { 945 case RTW_LOCALE_USA: /* 1-11 */ 946 name = "USA"; 947 for (i = 1; i <= 11; i++) 948 ADD_CHANNEL(chans, i); 949 break; 950 case RTW_LOCALE_JAPAN: /* 1-14 */ 951 name = "Japan"; 952 ADD_CHANNEL(chans, 14); 953 for (i = 1; i <= 14; i++) 954 ADD_CHANNEL(chans, i); 955 break; 956 case RTW_LOCALE_EUROPE: /* 1-13 */ 957 name = "Europe"; 958 for (i = 1; i <= 13; i++) 959 ADD_CHANNEL(chans, i); 960 break; 961 default: /* 10-11 allowed by most countries */ 962 name = "<unknown>"; 963 for (i = 10; i <= 11; i++) 964 ADD_CHANNEL(chans, i); 965 break; 966 } 967 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: Geographic Location %s\n", 968 dvname, name); 969 #undef ADD_CHANNEL 970 } 971 972 static void 973 rtw_set80211props(struct ieee80211com *ic) 974 { 975 uint8_t nrate; 976 977 /* ic->ic_curmode = IEEE80211_MODE_11B; */ 978 ic->ic_phytype = IEEE80211_T_DS; 979 ic->ic_opmode = IEEE80211_M_STA; 980 ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS | 981 IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | 982 IEEE80211_C_SHPREAMBLE; /* | IEEE80211_C_WEP */ 983 984 nrate = 0; 985 ic->ic_sup_rates[IEEE80211_MODE_11B].ir_rates[nrate++] = 986 IEEE80211_RATE_BASIC | 2; 987 ic->ic_sup_rates[IEEE80211_MODE_11B].ir_rates[nrate++] = 988 IEEE80211_RATE_BASIC | 4; 989 ic->ic_sup_rates[IEEE80211_MODE_11B].ir_rates[nrate++] = 11; 990 ic->ic_sup_rates[IEEE80211_MODE_11B].ir_rates[nrate++] = 22; 991 ic->ic_sup_rates[IEEE80211_MODE_11B].ir_nrates = nrate; 992 } 993 994 /*ARGSUSED*/ 995 static void 996 rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale, 997 const char *dvname) 998 { 999 uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0); 1000 1001 switch (cfg0 & RTW_CONFIG0_GL_MASK) { 1002 case RTW_CONFIG0_GL_USA: 1003 *locale = RTW_LOCALE_USA; 1004 break; 1005 case RTW_CONFIG0_GL_JAPAN: 1006 *locale = RTW_LOCALE_JAPAN; 1007 break; 1008 case RTW_CONFIG0_GL_EUROPE: 1009 *locale = RTW_LOCALE_EUROPE; 1010 break; 1011 default: 1012 *locale = RTW_LOCALE_UNKNOWN; 1013 break; 1014 } 1015 } 1016 1017 static int 1018 rtw_identify_sta(struct rtw_regs *regs, uint8_t *addr, 1019 const char *dvname) 1020 { 1021 uint32_t idr0 = RTW_READ(regs, RTW_IDR0), 1022 idr1 = RTW_READ(regs, RTW_IDR1); 1023 1024 *addr = MASK_AND_RSHIFT(idr0, BITS(0, 7)); 1025 *(addr + 1) = MASK_AND_RSHIFT(idr0, BITS(8, 15)); 1026 *(addr + 2) = MASK_AND_RSHIFT(idr0, BITS(16, 23)); 1027 *(addr + 3) = MASK_AND_RSHIFT(idr0, BITS(24, 31)); 1028 1029 *(addr + 4) = MASK_AND_RSHIFT(idr1, BITS(0, 7)); 1030 *(addr + 5) = MASK_AND_RSHIFT(idr1, BITS(8, 15)); 1031 1032 RTW_DPRINTF(RTW_DEBUG_ATTACH, 1033 "%s: 802.11mac address %x:%x:%x:%x:%x:%x\n", dvname, 1034 *addr, *(addr+1), *(addr+2), *(addr+3), *(addr+4), *(addr+5)); 1035 1036 return (0); 1037 } 1038 1039 static uint8_t 1040 rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic, 1041 struct ieee80211_channel *chan) 1042 { 1043 uint32_t idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1; 1044 return (RTW_SR_GET(sr, idx)); 1045 } 1046 1047 static void 1048 rtw_rxdesc_init(rtw_softc_t *rsc, struct rtw_rxbuf *rbf, int idx, int is_last) 1049 { 1050 uint32_t ctl = 0; 1051 uint8_t *buf = (uint8_t *)rbf->bf_dma.mem_va; 1052 1053 ASSERT(rbf != NULL); 1054 rbf->rxdesc->rd_buf = (rbf->bf_dma.cookie.dmac_address); 1055 bzero(buf, rbf->bf_dma.alength); 1056 RTW_DMA_SYNC(rbf->bf_dma, DDI_DMA_SYNC_FORDEV); 1057 1058 ctl = (rbf->bf_dma.alength & 0xfff) | RTW_RXCTL_OWN; 1059 1060 if (is_last) 1061 ctl |= RTW_RXCTL_EOR; 1062 1063 rbf->rxdesc->rd_ctl = (ctl); 1064 /* sync the mbuf */ 1065 1066 /* sync the descriptor */ 1067 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 1068 RTW_DESC_OFFSET(hd_rx, idx), 1069 sizeof (struct rtw_rxdesc), 1070 DDI_DMA_SYNC_FORDEV); 1071 } 1072 1073 /* Check all queues' activity. */ 1074 #define RTW_TPPOLL_ACTIVE RTW_TPPOLL_ALL 1075 1076 static void 1077 rtw_idle(struct rtw_regs *regs) 1078 { 1079 int active; 1080 1081 /* request stop DMA; wait for packets to stop transmitting. */ 1082 1083 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 1084 1085 for (active = 0; active < 300 && 1086 (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ACTIVE) != 0; active++) 1087 drv_usecwait(10); 1088 } 1089 1090 static void 1091 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable) 1092 { 1093 uint8_t cr; 1094 struct rtw_regs *regs = &rsc->sc_regs; 1095 1096 RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: %s 0x%02x\n", __func__, 1097 enable ? "enable" : "disable", flags); 1098 1099 cr = RTW_READ8(regs, RTW_CR); 1100 #if 1 1101 /* The receive engine will always start at RDSAR. */ 1102 if (enable && (flags & ~cr & RTW_CR_RE)) { 1103 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 1104 RTW_DESC_OFFSET(hd_rx, 0), 1105 sizeof (struct rtw_rxdesc), 1106 DDI_DMA_SYNC_FORCPU); 1107 rsc->rx_next = 0; 1108 rtw_rxdesc_init(rsc, rsc->rxbuf_h, 0, 0); 1109 } 1110 #endif 1111 if (enable) 1112 cr |= flags; 1113 else 1114 cr &= ~flags; 1115 RTW_WRITE8(regs, RTW_CR, cr); 1116 (void) RTW_READ8(regs, RTW_CR); 1117 } 1118 1119 /* 1120 * Allocate an area of memory and a DMA handle for accessing it 1121 */ 1122 static int 1123 rtw_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, 1124 size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags, 1125 uint_t bind_flags, dma_area_t *dma_p) 1126 { 1127 int err; 1128 1129 /* 1130 * Allocate handle 1131 */ 1132 err = ddi_dma_alloc_handle(devinfo, dma_attr, 1133 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 1134 if (err != DDI_SUCCESS) 1135 return (DDI_FAILURE); 1136 1137 /* 1138 * Allocate memory 1139 */ 1140 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 1141 alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va, 1142 &dma_p->alength, &dma_p->acc_hdl); 1143 if (err != DDI_SUCCESS) 1144 return (DDI_FAILURE); 1145 1146 /* 1147 * Bind the two together 1148 */ 1149 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 1150 dma_p->mem_va, dma_p->alength, bind_flags, 1151 DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies); 1152 if ((dma_p->ncookies != 1) || (err != DDI_DMA_MAPPED)) 1153 return (DDI_FAILURE); 1154 1155 dma_p->nslots = ~0U; 1156 dma_p->size = ~0U; 1157 dma_p->token = ~0U; 1158 dma_p->offset = 0; 1159 return (DDI_SUCCESS); 1160 } 1161 1162 /* 1163 * Free one allocated area of DMAable memory 1164 */ 1165 static void 1166 rtw_free_dma_mem(dma_area_t *dma_p) 1167 { 1168 if (dma_p->dma_hdl != NULL) { 1169 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 1170 if (dma_p->acc_hdl != NULL) { 1171 ddi_dma_mem_free(&dma_p->acc_hdl); 1172 dma_p->acc_hdl = NULL; 1173 } 1174 ddi_dma_free_handle(&dma_p->dma_hdl); 1175 dma_p->ncookies = 0; 1176 dma_p->dma_hdl = NULL; 1177 } 1178 } 1179 1180 static void 1181 rtw_dma_free(rtw_softc_t *rsc) 1182 { 1183 struct rtw_txbuf *txbf; 1184 struct rtw_rxbuf *rxbf; 1185 int i, j; 1186 1187 /* Free TX DMA buffer */ 1188 for (i = 0; i < RTW_NTXPRI; i++) { 1189 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1190 while (txbf != NULL) { 1191 rtw_free_dma_mem(&txbf->bf_dma); 1192 list_remove(&rsc->sc_txq[i].tx_free_list, txbf); 1193 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1194 } 1195 list_destroy(&rsc->sc_txq[i].tx_free_list); 1196 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1197 while (txbf != NULL) { 1198 rtw_free_dma_mem(&txbf->bf_dma); 1199 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf); 1200 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1201 } 1202 list_destroy(&rsc->sc_txq[i].tx_dirty_list); 1203 1204 if (rsc->sc_txq[i].txbuf_h != NULL) { 1205 kmem_free(rsc->sc_txq[i].txbuf_h, 1206 sizeof (struct rtw_txbuf) * rtw_qlen[i]); 1207 rsc->sc_txq[i].txbuf_h = NULL; 1208 } 1209 } 1210 1211 /* Free RX DMA buffer */ 1212 rxbf = rsc->rxbuf_h; 1213 for (j = 0; j < RTW_RXQLEN; j++) { 1214 rtw_free_dma_mem(&rxbf->bf_dma); 1215 rxbf++; 1216 } 1217 1218 if (rsc->rxbuf_h != NULL) { 1219 kmem_free(rsc->rxbuf_h, sizeof (struct rtw_rxbuf) * RTW_RXQLEN); 1220 rsc->rxbuf_h = NULL; 1221 } 1222 1223 rtw_free_dma_mem(&rsc->sc_desc_dma); 1224 } 1225 1226 static int 1227 rtw_dma_init(dev_info_t *devinfo, rtw_softc_t *rsc) 1228 { 1229 int i, j, err; 1230 size_t size; 1231 uint32_t buflen; 1232 struct rtw_txdesc *txds; 1233 struct rtw_rxdesc *rxds; 1234 struct rtw_txbuf *txbf; 1235 struct rtw_rxbuf *rxbf; 1236 uint32_t phybaseaddr, ptx[RTW_NTXPRI], prx; 1237 caddr_t virbaseaddr, vtx[RTW_NTXPRI], vrx; 1238 1239 /* DMA buffer size for each TX/RX packet */ 1240 rsc->sc_dmabuf_size = roundup(sizeof (struct ieee80211_frame) + 0x100 + 1241 IEEE80211_MTU + IEEE80211_CRC_LEN + sizeof (struct ieee80211_llc) + 1242 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 1243 IEEE80211_WEP_CRCLEN), rsc->sc_cachelsz); 1244 size = sizeof (struct rtw_descs); 1245 err = rtw_alloc_dma_mem(devinfo, &dma_attr_desc, size, 1246 &rtw_desc_accattr, 1247 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1248 &rsc->sc_desc_dma); 1249 if (err != DDI_SUCCESS) 1250 goto error; 1251 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1252 virbaseaddr = rsc->sc_desc_dma.mem_va; 1253 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo); 1254 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd); 1255 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi); 1256 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn); 1257 vtx[0] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txlo)); 1258 vtx[1] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txmd)); 1259 vtx[2] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txhi)); 1260 vtx[3] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_bcn)); 1261 for (i = 0; i < RTW_NTXPRI; i++) { 1262 RTW_DPRINTF(RTW_DEBUG_DMA, "p[%d]=%x, v[%d]=%x", i, ptx[i], 1263 i, vtx[i]); 1264 RTW_DPRINTF(RTW_DEBUG_DMA, "ring%d:", i); 1265 list_create(&rsc->sc_txq[i].tx_free_list, 1266 sizeof (struct rtw_txbuf), 1267 offsetof(struct rtw_txbuf, bf_node)); 1268 list_create(&rsc->sc_txq[i].tx_dirty_list, 1269 sizeof (struct rtw_txbuf), 1270 offsetof(struct rtw_txbuf, bf_node)); 1271 /* virtual address of the first descriptor */ 1272 rsc->sc_txq[i].txdesc_h = (struct rtw_txdesc *)vtx[i]; 1273 1274 txds = rsc->sc_txq[i].txdesc_h; 1275 /* allocate data structures to describe TX DMA buffers */ 1276 buflen = sizeof (struct rtw_txbuf) * rtw_qlen[i]; 1277 txbf = (struct rtw_txbuf *)kmem_zalloc(buflen, KM_SLEEP); 1278 rsc->sc_txq[i].txbuf_h = txbf; 1279 for (j = 0; j < rtw_qlen[i]; j++, txbf++, txds++) { 1280 txbf->txdesc = txds; 1281 txbf->bf_daddr = ptx[i] + ((caddr_t)txds - 1282 (caddr_t)rsc->sc_txq[i].txdesc_h); 1283 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf); 1284 1285 /* alloc DMA memory */ 1286 err = rtw_alloc_dma_mem(devinfo, &dma_attr_txbuf, 1287 rsc->sc_dmabuf_size, 1288 &rtw_buf_accattr, 1289 DDI_DMA_STREAMING, 1290 DDI_DMA_WRITE | DDI_DMA_STREAMING, 1291 &txbf->bf_dma); 1292 if (err != DDI_SUCCESS) 1293 goto error; 1294 RTW_DPRINTF(RTW_DEBUG_DMA, "pbufaddr[%d]=%x", 1295 j, txbf->bf_dma.cookie.dmac_address); 1296 } 1297 } 1298 prx = RTW_RING_BASE(phybaseaddr, hd_rx); 1299 vrx = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_rx)); 1300 /* virtual address of the first descriptor */ 1301 rsc->rxdesc_h = (struct rtw_rxdesc *)vrx; 1302 rxds = rsc->rxdesc_h; 1303 1304 /* allocate data structures to describe RX DMA buffers */ 1305 buflen = sizeof (struct rtw_rxbuf) * RTW_RXQLEN; 1306 rxbf = (struct rtw_rxbuf *)kmem_zalloc(buflen, KM_SLEEP); 1307 rsc->rxbuf_h = rxbf; 1308 1309 for (j = 0; j < RTW_RXQLEN; j++, rxbf++, rxds++) { 1310 rxbf->rxdesc = rxds; 1311 rxbf->bf_daddr = prx + ((caddr_t)rxds - (caddr_t)rsc->rxdesc_h); 1312 1313 /* alloc DMA memory */ 1314 err = rtw_alloc_dma_mem(devinfo, &dma_attr_rxbuf, 1315 rsc->sc_dmabuf_size, 1316 &rtw_buf_accattr, 1317 DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING, 1318 &rxbf->bf_dma); 1319 if (err != DDI_SUCCESS) 1320 goto error; 1321 } 1322 1323 return (DDI_SUCCESS); 1324 error: 1325 return (DDI_FAILURE); 1326 } 1327 1328 static void 1329 rtw_hwring_setup(rtw_softc_t *rsc) 1330 { 1331 struct rtw_regs *regs = &rsc->sc_regs; 1332 uint32_t phybaseaddr; 1333 1334 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1335 1336 RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(phybaseaddr, hd_rx)); 1337 RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(phybaseaddr, hd_txlo)); 1338 RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(phybaseaddr, hd_txmd)); 1339 RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(phybaseaddr, hd_txhi)); 1340 RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(phybaseaddr, hd_bcn)); 1341 rsc->hw_start = RTW_READ(regs, RTW_TNPDA); 1342 rsc->hw_go = RTW_READ(regs, RTW_TNPDA); 1343 } 1344 1345 static void 1346 rtw_swring_setup(rtw_softc_t *rsc, int flag) 1347 { 1348 int i, j; 1349 int is_last; 1350 struct rtw_txbuf *txbf; 1351 struct rtw_rxbuf *rxbf; 1352 uint32_t phybaseaddr, ptx[RTW_NTXPRI], baddr_desc, taddr_desc; 1353 1354 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1355 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo); 1356 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd); 1357 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi); 1358 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn); 1359 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORDEV); 1360 /* sync tx desc and tx buf */ 1361 for (i = 0; i < RTW_NTXPRI; i++) { 1362 rsc->sc_txq[i].tx_prod = rsc->sc_txq[i].tx_cons = 0; 1363 rsc->sc_txq[i].tx_nfree = rtw_qlen[i]; 1364 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1365 while (txbf != NULL) { 1366 list_remove(&rsc->sc_txq[i].tx_free_list, txbf); 1367 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1368 } 1369 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1370 while (txbf != NULL) { 1371 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf); 1372 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1373 } 1374 txbf = rsc->sc_txq[i].txbuf_h; 1375 baddr_desc = ptx[i]; 1376 taddr_desc = baddr_desc + sizeof (struct rtw_txdesc); 1377 for (j = 0; j < rtw_qlen[i]; j++) { 1378 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf); 1379 if (j == (rtw_qlen[i] - 1)) { 1380 is_last = 1; 1381 } else { 1382 is_last = 0; 1383 } 1384 1385 if (is_last) { 1386 txbf->txdesc->td_next = baddr_desc; 1387 } else { 1388 txbf->txdesc->td_next = taddr_desc; 1389 } 1390 txbf->next_bf_daddr = txbf->txdesc->td_next; 1391 RTW_DMA_SYNC(txbf->bf_dma, DDI_DMA_SYNC_FORDEV); 1392 txbf->order = j; 1393 txbf++; 1394 taddr_desc += sizeof (struct rtw_txdesc); 1395 } 1396 } 1397 if (!flag) 1398 return; 1399 1400 /* sync rx desc and rx buf */ 1401 rsc->rx_next = 0; 1402 rxbf = rsc->rxbuf_h; 1403 for (j = 0; j < RTW_RXQLEN; j++) { 1404 RTW_DMA_SYNC(rxbf->bf_dma, DDI_DMA_SYNC_FORCPU); 1405 if (j == (RTW_RXQLEN - 1)) 1406 is_last = 1; 1407 else 1408 is_last = 0; 1409 rtw_rxdesc_init(rsc, rxbf, j, is_last); 1410 rxbf++; 1411 } 1412 } 1413 1414 static void 1415 rtw_resume_ticks(rtw_softc_t *rsc) 1416 { 1417 RTW_WRITE(&rsc->sc_regs, RTW_TINT, 0xffffffff); 1418 } 1419 1420 const char * 1421 rtw_pwrstate_string(enum rtw_pwrstate power) 1422 { 1423 switch (power) { 1424 case RTW_ON: 1425 return ("on"); 1426 case RTW_SLEEP: 1427 return ("sleep"); 1428 case RTW_OFF: 1429 return ("off"); 1430 default: 1431 return ("unknown"); 1432 } 1433 } 1434 1435 /* 1436 * XXX For Maxim, I am using the RFMD settings gleaned from the 1437 * reference driver, plus a magic Maxim "ON" value that comes from 1438 * the Realtek document "Windows PG for Rtl8180." 1439 */ 1440 /*ARGSUSED*/ 1441 static void 1442 rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1443 int before_rf, int digphy) 1444 { 1445 uint32_t anaparm; 1446 1447 anaparm = RTW_READ(regs, RTW_ANAPARM); 1448 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1449 1450 switch (power) { 1451 case RTW_OFF: 1452 if (before_rf) 1453 return; 1454 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF; 1455 anaparm |= RTW_ANAPARM_TXDACOFF; 1456 break; 1457 case RTW_SLEEP: 1458 if (!before_rf) 1459 return; 1460 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP; 1461 anaparm |= RTW_ANAPARM_TXDACOFF; 1462 break; 1463 case RTW_ON: 1464 if (!before_rf) 1465 return; 1466 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON; 1467 break; 1468 } 1469 RTW_DPRINTF(RTW_DEBUG_PWR, 1470 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1471 __func__, rtw_pwrstate_string(power), 1472 (before_rf) ? "before" : "after", anaparm); 1473 1474 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1475 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1476 } 1477 1478 /* 1479 * XXX I am using the RFMD settings gleaned from the reference 1480 * driver. They agree 1481 */ 1482 /*ARGSUSED*/ 1483 static void 1484 rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1485 int before_rf, int digphy) 1486 { 1487 uint32_t anaparm; 1488 1489 anaparm = RTW_READ(regs, RTW_ANAPARM); 1490 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1491 1492 switch (power) { 1493 case RTW_OFF: 1494 if (before_rf) 1495 return; 1496 anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF; 1497 anaparm |= RTW_ANAPARM_TXDACOFF; 1498 break; 1499 case RTW_SLEEP: 1500 if (!before_rf) 1501 return; 1502 anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP; 1503 anaparm |= RTW_ANAPARM_TXDACOFF; 1504 break; 1505 case RTW_ON: 1506 if (!before_rf) 1507 return; 1508 anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON; 1509 break; 1510 } 1511 RTW_DPRINTF(RTW_DEBUG_PWR, 1512 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1513 __func__, rtw_pwrstate_string(power), 1514 (before_rf) ? "before" : "after", anaparm); 1515 1516 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1517 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1518 } 1519 1520 static void 1521 rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1522 int before_rf, int digphy) 1523 { 1524 uint32_t anaparm; 1525 1526 anaparm = RTW_READ(regs, RTW_ANAPARM); 1527 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1528 1529 switch (power) { 1530 case RTW_OFF: 1531 if (before_rf) 1532 return; 1533 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF; 1534 anaparm |= RTW_ANAPARM_TXDACOFF; 1535 break; 1536 case RTW_SLEEP: 1537 if (!before_rf) 1538 return; 1539 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP; 1540 anaparm |= RTW_ANAPARM_TXDACOFF; 1541 break; 1542 case RTW_ON: 1543 if (!before_rf) 1544 return; 1545 if (digphy) { 1546 anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON; 1547 /* XXX guess */ 1548 anaparm |= RTW_ANAPARM_TXDACOFF; 1549 } else 1550 anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON; 1551 break; 1552 } 1553 RTW_DPRINTF(RTW_DEBUG_PWR, 1554 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1555 __func__, rtw_pwrstate_string(power), 1556 (before_rf) ? "before" : "after", anaparm); 1557 1558 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1559 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1560 } 1561 1562 static void 1563 rtw_pwrstate0(rtw_softc_t *rsc, enum rtw_pwrstate power, int before_rf, 1564 int digphy) 1565 { 1566 struct rtw_regs *regs = &rsc->sc_regs; 1567 1568 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 1569 1570 (*rsc->sc_pwrstate_cb)(regs, power, before_rf, digphy); 1571 1572 rtw_set_access(regs, RTW_ACCESS_NONE); 1573 } 1574 1575 static void 1576 rtw_rf_destroy(struct rtw_rf *rf) 1577 { 1578 (*rf->rf_destroy)(rf); 1579 } 1580 1581 static int 1582 rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) 1583 { 1584 return (*rf->rf_pwrstate)(rf, power); 1585 } 1586 1587 static int 1588 rtw_pwrstate(rtw_softc_t *rsc, enum rtw_pwrstate power) 1589 { 1590 int rc; 1591 1592 RTW_DPRINTF(RTW_DEBUG_PWR, 1593 "%s: %s->%s\n", __func__, 1594 rtw_pwrstate_string(rsc->sc_pwrstate), rtw_pwrstate_string(power)); 1595 1596 if (rsc->sc_pwrstate == power) 1597 return (0); 1598 1599 rtw_pwrstate0(rsc, power, 1, rsc->sc_flags & RTW_F_DIGPHY); 1600 rc = rtw_rf_pwrstate(rsc->sc_rf, power); 1601 rtw_pwrstate0(rsc, power, 0, rsc->sc_flags & RTW_F_DIGPHY); 1602 1603 switch (power) { 1604 case RTW_ON: 1605 /* TBD set LEDs */ 1606 break; 1607 case RTW_SLEEP: 1608 /* TBD */ 1609 break; 1610 case RTW_OFF: 1611 /* TBD */ 1612 break; 1613 } 1614 if (rc == 0) 1615 rsc->sc_pwrstate = power; 1616 else 1617 rsc->sc_pwrstate = RTW_OFF; 1618 return (rc); 1619 } 1620 1621 void 1622 rtw_disable(rtw_softc_t *rsc) 1623 { 1624 int rc; 1625 1626 if ((rsc->sc_flags & RTW_F_ENABLED) == 0) 1627 return; 1628 1629 /* turn off PHY */ 1630 if ((rsc->sc_flags & RTW_F_INVALID) == 0 && 1631 (rc = rtw_pwrstate(rsc, RTW_OFF)) != 0) { 1632 cmn_err(CE_WARN, "failed to turn off PHY (%d)\n", rc); 1633 } 1634 1635 if (rsc->sc_disable != NULL) 1636 (*rsc->sc_disable)(rsc); 1637 1638 rsc->sc_flags &= ~RTW_F_ENABLED; 1639 } 1640 1641 int 1642 rtw_enable(rtw_softc_t *rsc) 1643 { 1644 if ((rsc->sc_flags & RTW_F_ENABLED) == 0) { 1645 if (rsc->sc_enable != NULL && (*rsc->sc_enable)(rsc) != 0) { 1646 cmn_err(CE_WARN, "device enable failed\n"); 1647 return (EIO); 1648 } 1649 rsc->sc_flags |= RTW_F_ENABLED; 1650 if (rtw_pwrstate(rsc, RTW_ON) != 0) 1651 cmn_err(CE_WARN, "PHY turn on failed\n"); 1652 } 1653 return (0); 1654 } 1655 1656 static void 1657 rtw_set_nettype(rtw_softc_t *rsc, enum ieee80211_opmode opmode) 1658 { 1659 uint8_t msr; 1660 1661 /* I'm guessing that MSR is protected as CONFIG[0123] are. */ 1662 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_CONFIG); 1663 1664 msr = RTW_READ8(&rsc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK; 1665 1666 switch (opmode) { 1667 case IEEE80211_M_AHDEMO: 1668 case IEEE80211_M_IBSS: 1669 msr |= RTW_MSR_NETYPE_ADHOC_OK; 1670 break; 1671 case IEEE80211_M_HOSTAP: 1672 msr |= RTW_MSR_NETYPE_AP_OK; 1673 break; 1674 case IEEE80211_M_STA: 1675 msr |= RTW_MSR_NETYPE_INFRA_OK; 1676 break; 1677 } 1678 RTW_WRITE8(&rsc->sc_regs, RTW_MSR, msr); 1679 1680 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_NONE); 1681 } 1682 1683 static void 1684 rtw_pktfilt_load(rtw_softc_t *rsc) 1685 { 1686 struct rtw_regs *regs = &rsc->sc_regs; 1687 struct ieee80211com *ic = &rsc->sc_ic; 1688 1689 /* XXX might be necessary to stop Rx/Tx engines while setting filters */ 1690 rsc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK; 1691 rsc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK); 1692 1693 rsc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT; 1694 /* MAC auto-reset PHY (huh?) */ 1695 rsc->sc_rcr |= RTW_RCR_ENMARP; 1696 /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */ 1697 rsc->sc_rcr |= RTW_RCR_RXFTH_WHOLE |RTW_RCR_MXDMA_1024; 1698 1699 switch (ic->ic_opmode) { 1700 case IEEE80211_M_AHDEMO: 1701 case IEEE80211_M_IBSS: 1702 /* receive broadcasts in our BSS */ 1703 rsc->sc_rcr |= RTW_RCR_ADD3; 1704 break; 1705 default: 1706 break; 1707 } 1708 #if 0 1709 /* XXX accept all broadcast if scanning */ 1710 rsc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */ 1711 #endif 1712 RTW_WRITE(regs, RTW_MAR0, 0xffffffff); 1713 RTW_WRITE(regs, RTW_MAR1, 0xffffffff); 1714 rsc->sc_rcr |= RTW_RCR_AM; 1715 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 1716 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */ 1717 1718 RTW_DPRINTF(RTW_DEBUG_PKTFILT, 1719 "RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n", 1720 RTW_READ(regs, RTW_MAR0), 1721 RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR)); 1722 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 1723 } 1724 1725 static void 1726 rtw_transmit_config(struct rtw_regs *regs) 1727 { 1728 uint32_t tcr; 1729 1730 tcr = RTW_READ(regs, RTW_TCR); 1731 1732 tcr |= RTW_TCR_CWMIN; 1733 tcr &= ~RTW_TCR_MXDMA_MASK; 1734 tcr |= RTW_TCR_MXDMA_1024; 1735 tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */ 1736 tcr &= ~RTW_TCR_LBK_MASK; 1737 tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */ 1738 1739 /* set short/long retry limits */ 1740 tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK); 1741 tcr |= LSHIFT(0x4, RTW_TCR_SRL_MASK) | LSHIFT(0x4, RTW_TCR_LRL_MASK); 1742 1743 tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */ 1744 RTW_WRITE(regs, RTW_TCR, tcr); 1745 RTW_SYNC(regs, RTW_TCR, RTW_TCR); 1746 } 1747 1748 int 1749 rtw_refine_setting(rtw_softc_t *rsc) 1750 { 1751 struct rtw_regs *regs; 1752 int rc = 0; 1753 1754 regs = &rsc->sc_regs; 1755 rc = rtw_reset(rsc); 1756 if (rc != 0) 1757 return (-1); 1758 1759 rtw_beacon_tx_disable(regs); 1760 rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 1); 1761 rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG); 1762 1763 rtw_transmit_config(regs); 1764 rtw_pktfilt_load(rsc); 1765 rtw_set_access(regs, RTW_ACCESS_CONFIG); 1766 RTW_WRITE(regs, RTW_TINT, 0xffffffff); 1767 RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */ 1768 RTW_WRITE16(regs, RTW_BRSR, 0); 1769 1770 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 1771 rtw_set_access(regs, RTW_ACCESS_NONE); 1772 RTW_WRITE(regs, RTW_FEMR, 0xffff); 1773 RTW_SYNC(regs, RTW_FEMR, RTW_FEMR); 1774 rtw_set_rfprog(regs, rsc->sc_rfchipid, "rtw"); 1775 1776 RTW_WRITE8(regs, RTW_PHYDELAY, rsc->sc_phydelay); 1777 RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC); 1778 rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL); 1779 return (0); 1780 } 1781 1782 static int 1783 rtw_tune(rtw_softc_t *rsc) 1784 { 1785 struct ieee80211com *ic = &rsc->sc_ic; 1786 uint32_t chan; 1787 int rc; 1788 int antdiv = rsc->sc_flags & RTW_F_ANTDIV, 1789 dflantb = rsc->sc_flags & RTW_F_DFLANTB; 1790 1791 ASSERT(ic->ic_curchan != NULL); 1792 1793 chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 1794 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw: chan no = %x", chan); 1795 1796 if (chan == IEEE80211_CHAN_ANY) { 1797 cmn_err(CE_WARN, "%s: chan == IEEE80211_CHAN_ANY\n", __func__); 1798 return (-1); 1799 } 1800 1801 if (chan == rsc->sc_cur_chan) { 1802 RTW_DPRINTF(RTW_DEBUG_TUNE, 1803 "%s: already tuned chan %d\n", __func__, chan); 1804 return (0); 1805 } 1806 rtw_idle(&rsc->sc_regs); 1807 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 1808 ASSERT((rsc->sc_flags & RTW_F_ENABLED) != 0); 1809 1810 if ((rc = rtw_phy_init(&rsc->sc_regs, rsc->sc_rf, 1811 rtw_chan2txpower(&rsc->sc_srom, ic, ic->ic_curchan), 1812 rsc->sc_csthr, ic->ic_curchan->ich_freq, antdiv, 1813 dflantb, RTW_ON)) != 0) { 1814 /* XXX condition on powersaving */ 1815 cmn_err(CE_NOTE, "phy init failed\n"); 1816 } 1817 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1); 1818 rtw_resume_ticks(rsc); 1819 rsc->sc_cur_chan = chan; 1820 return (rc); 1821 } 1822 1823 static int 1824 rtw_init(rtw_softc_t *rsc) 1825 { 1826 struct ieee80211com *ic = &rsc->sc_ic; 1827 int rc = 0; 1828 1829 if ((rc = rtw_enable(rsc)) != 0) 1830 goto out; 1831 rc = rtw_refine_setting(rsc); 1832 if (rc != 0) 1833 return (rc); 1834 1835 rtw_swring_setup(rsc, 1); 1836 rtw_hwring_setup(rsc); 1837 RTW_WRITE16(&rsc->sc_regs, RTW_BSSID16, 0x0); 1838 RTW_WRITE(&rsc->sc_regs, RTW_BSSID32, 0x0); 1839 rtw_enable_interrupts(rsc); 1840 1841 ic->ic_ibss_chan = &ic->ic_sup_channels[1]; 1842 ic->ic_curchan = ic->ic_ibss_chan; 1843 RTW_DPRINTF(RTW_DEBUG_TUNE, "%s: channel %d freq %d flags 0x%04x\n", 1844 __func__, ieee80211_chan2ieee(ic, ic->ic_curchan), 1845 ic->ic_curchan->ich_freq, ic->ic_curchan->ich_flags); 1846 out: 1847 return (rc); 1848 } 1849 1850 static struct rtw_rf * 1851 rtw_rf_attach(rtw_softc_t *rsc, enum rtw_rfchipid rfchipid, int digphy) 1852 { 1853 rtw_rf_write_t rf_write; 1854 struct rtw_rf *rf; 1855 int rtw_host_rfio; 1856 1857 switch (rfchipid) { 1858 default: 1859 rf_write = rtw_rf_hostwrite; 1860 break; 1861 case RTW_RFCHIPID_INTERSIL: 1862 case RTW_RFCHIPID_PHILIPS: 1863 case RTW_RFCHIPID_GCT: /* XXX a guess */ 1864 case RTW_RFCHIPID_RFMD: 1865 rtw_host_rfio = 1; 1866 rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite; 1867 break; 1868 } 1869 1870 switch (rfchipid) { 1871 case RTW_RFCHIPID_MAXIM: 1872 rf = rtw_max2820_create(&rsc->sc_regs, rf_write, 0); 1873 rsc->sc_pwrstate_cb = rtw_maxim_pwrstate; 1874 break; 1875 case RTW_RFCHIPID_PHILIPS: 1876 rf = rtw_sa2400_create(&rsc->sc_regs, rf_write, digphy); 1877 rsc->sc_pwrstate_cb = rtw_philips_pwrstate; 1878 break; 1879 case RTW_RFCHIPID_RFMD: 1880 /* XXX RFMD has no RF constructor */ 1881 rsc->sc_pwrstate_cb = rtw_rfmd_pwrstate; 1882 /*FALLTHROUGH*/ 1883 default: 1884 return (NULL); 1885 } 1886 if (rf != NULL) { 1887 rf->rf_continuous_tx_cb = 1888 (rtw_continuous_tx_cb_t)rtw_continuous_tx_enable; 1889 rf->rf_continuous_tx_arg = (void *)rsc; 1890 } 1891 return (rf); 1892 } 1893 1894 /* 1895 * Revision C and later use a different PHY delay setting than 1896 * revisions A and B. 1897 */ 1898 static uint8_t 1899 rtw_check_phydelay(struct rtw_regs *regs, uint32_t rcr0) 1900 { 1901 #define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV) 1902 #define REVC (REVAB | RTW_RCR_RXFTH_WHOLE) 1903 1904 uint8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY); 1905 1906 RTW_WRITE(regs, RTW_RCR, REVAB); 1907 RTW_WBW(regs, RTW_RCR, RTW_RCR); 1908 RTW_WRITE(regs, RTW_RCR, REVC); 1909 1910 RTW_WBR(regs, RTW_RCR, RTW_RCR); 1911 if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC) 1912 phydelay |= RTW_PHYDELAY_REVC_MAGIC; 1913 1914 RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */ 1915 RTW_SYNC(regs, RTW_RCR, RTW_RCR); 1916 1917 return (phydelay); 1918 #undef REVC 1919 } 1920 1921 static void rtw_intr_rx(rtw_softc_t *rsc); 1922 static void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri); 1923 1924 static int 1925 rtw_get_rate(struct ieee80211com *ic) 1926 { 1927 uint8_t (*rates)[IEEE80211_RATE_MAXSIZE]; 1928 int rate; 1929 1930 rates = &ic->ic_bss->in_rates.ir_rates; 1931 1932 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 1933 rate = ic->ic_fixed_rate; 1934 else if (ic->ic_state == IEEE80211_S_RUN) 1935 rate = (*rates)[ic->ic_bss->in_txrate]; 1936 else 1937 rate = 0; 1938 return (rate & IEEE80211_RATE_VAL); 1939 } 1940 1941 /* 1942 * Arguments in: 1943 * 1944 * paylen: payload length (no FCS, no WEP header) 1945 * 1946 * hdrlen: header length 1947 * 1948 * rate: MSDU speed, units 500kb/s 1949 * 1950 * flags: IEEE80211_F_SHPREAMBLE (use short preamble), 1951 * IEEE80211_F_SHSLOT (use short slot length) 1952 * 1953 * Arguments out: 1954 * 1955 * d: 802.11 Duration field for RTS, 1956 * 802.11 Duration field for data frame, 1957 * PLCP Length for data frame, 1958 * residual octets at end of data slot 1959 */ 1960 static int 1961 rtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate, 1962 struct rtw_ieee80211_duration *d) 1963 { 1964 int pre, ctsrate; 1965 uint16_t ack, bitlen, data_dur, remainder; 1966 1967 /* 1968 * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK 1969 * DATA reserves medium for SIFS | ACK 1970 * 1971 * XXXMYC: no ACK on multicast/broadcast or control packets 1972 */ 1973 1974 bitlen = len * 8; 1975 1976 pre = IEEE80211_DUR_DS_SIFS; 1977 if ((flags & IEEE80211_F_SHPREAMBLE) != 0) 1978 pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + 1979 IEEE80211_DUR_DS_FAST_PLCPHDR; 1980 else 1981 pre += IEEE80211_DUR_DS_LONG_PREAMBLE + 1982 IEEE80211_DUR_DS_SLOW_PLCPHDR; 1983 1984 d->d_residue = 0; 1985 data_dur = (bitlen * 2) / rate; 1986 remainder = (bitlen * 2) % rate; 1987 if (remainder != 0) { 1988 if (rate == 22) 1989 d->d_residue = (rate - remainder) / 16; 1990 data_dur++; 1991 } 1992 1993 switch (rate) { 1994 case 2: /* 1 Mb/s */ 1995 case 4: /* 2 Mb/s */ 1996 /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */ 1997 ctsrate = 2; 1998 break; 1999 case 11: /* 5.5 Mb/s */ 2000 case 22: /* 11 Mb/s */ 2001 case 44: /* 22 Mb/s */ 2002 /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */ 2003 ctsrate = 4; 2004 break; 2005 default: 2006 /* TBD */ 2007 return (-1); 2008 } 2009 2010 d->d_plcp_len = data_dur; 2011 2012 ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0; 2013 2014 d->d_rts_dur = 2015 pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate + 2016 pre + data_dur + 2017 ack; 2018 2019 d->d_data_dur = ack; 2020 2021 return (0); 2022 } 2023 2024 /* 2025 * Arguments in: 2026 * 2027 * wh: 802.11 header 2028 * 2029 * paylen: payload length (no FCS, no WEP header) 2030 * 2031 * rate: MSDU speed, units 500kb/s 2032 * 2033 * fraglen: fragment length, set to maximum (or higher) for no 2034 * fragmentation 2035 * 2036 * flags: IEEE80211_F_PRIVACY (hardware adds WEP), 2037 * IEEE80211_F_SHPREAMBLE (use short preamble), 2038 * IEEE80211_F_SHSLOT (use short slot length) 2039 * 2040 * Arguments out: 2041 * 2042 * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 2043 * of first/only fragment 2044 * 2045 * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 2046 * of first/only fragment 2047 */ 2048 static int 2049 rtw_compute_duration(struct ieee80211_frame *wh, int len, 2050 uint32_t flags, int fraglen, int rate, struct rtw_ieee80211_duration *d0, 2051 struct rtw_ieee80211_duration *dn, int *npktp) 2052 { 2053 int ack, rc; 2054 int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen; 2055 2056 /* don't think about addr4 here */ 2057 hdrlen = sizeof (struct ieee80211_frame); 2058 2059 paylen = len - hdrlen; 2060 2061 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) { 2062 overlen = 8 + IEEE80211_CRC_LEN; 2063 paylen -= 8; 2064 } else 2065 overlen = IEEE80211_CRC_LEN; 2066 2067 npkt = paylen / fraglen; 2068 lastlen0 = paylen % fraglen; 2069 2070 if (npkt == 0) /* no fragments */ 2071 lastlen = paylen + overlen; 2072 else if (lastlen0 != 0) { /* a short "tail" fragment */ 2073 lastlen = lastlen0 + overlen; 2074 npkt++; 2075 } else /* full-length "tail" fragment */ 2076 lastlen = fraglen + overlen; 2077 2078 if (npktp != NULL) 2079 *npktp = npkt; 2080 2081 if (npkt > 1) 2082 firstlen = fraglen + overlen; 2083 else 2084 firstlen = paylen + overlen; 2085 2086 ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) && 2087 (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != 2088 IEEE80211_FC0_TYPE_CTL; 2089 2090 rc = rtw_compute_duration1(firstlen + hdrlen, 2091 ack, flags, rate, d0); 2092 if (rc == -1) 2093 return (rc); 2094 2095 if (npkt <= 1) { 2096 *dn = *d0; 2097 return (0); 2098 } 2099 return (rtw_compute_duration1(lastlen + hdrlen, ack, flags, 2100 rate, dn)); 2101 } 2102 2103 static int 2104 rtw_assembly_80211(rtw_softc_t *rsc, struct rtw_txbuf *bf, 2105 mblk_t *mp) 2106 { 2107 ieee80211com_t *ic; 2108 struct rtw_txdesc *ds; 2109 struct ieee80211_frame *wh; 2110 uint8_t *buf; 2111 uint32_t ctl0 = 0, ctl1 = 0; 2112 int npkt, rate; 2113 struct rtw_ieee80211_duration d0, dn; 2114 int32_t iswep, pktlen, mblen; 2115 mblk_t *mp0; 2116 2117 ic = &rsc->sc_ic; 2118 ds = bf->txdesc; 2119 buf = (uint8_t *)bf->bf_dma.mem_va; 2120 bzero(buf, bf->bf_dma.alength); 2121 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc)); 2122 wh = (struct ieee80211_frame *)mp->b_rptr; 2123 iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; 2124 2125 /* ieee80211_crypto_encap() needs a single mblk */ 2126 mp0 = allocb(bf->bf_dma.alength, BPRI_MED); 2127 if (mp0 == NULL) { 2128 cmn_err(CE_WARN, "%s: allocb(mp) error", __func__); 2129 return (-1); 2130 } 2131 for (; mp != NULL; mp = mp->b_cont) { 2132 mblen = MBLKL(mp); 2133 bcopy(mp->b_rptr, mp0->b_wptr, mblen); 2134 mp0->b_wptr += mblen; 2135 } 2136 2137 if (iswep) { 2138 struct ieee80211_key *k; 2139 2140 k = ieee80211_crypto_encap(ic, mp0); 2141 if (k == NULL) { 2142 cmn_err(CE_WARN, "%s: ieee80211_crypto_encap() error", 2143 __func__); 2144 freemsg(mp0); 2145 return (-1); 2146 } 2147 } 2148 pktlen = msgdsize(mp0); 2149 2150 #if 0 2151 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------begin--------"); 2152 ieee80211_dump_pkt((uint8_t *)(mp0->b_rptr), pktlen, 0, 0); 2153 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------end--------"); 2154 #endif 2155 /* RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); */ 2156 if (pktlen > bf->bf_dma.alength) { 2157 cmn_err(CE_WARN, "%s: overlength packet pktlen = %d\n", 2158 __func__, pktlen); 2159 freemsg(mp0); 2160 return (-1); 2161 } 2162 bcopy(mp0->b_rptr, buf, pktlen); 2163 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); 2164 2165 /* setup descriptor */ 2166 ctl0 = RTW_TXCTL0_RTSRATE_1MBPS; 2167 2168 if (((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0) && 2169 (ic->ic_bss->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { 2170 ctl0 |= RTW_TXCTL0_SPLCP; 2171 } 2172 /* XXX do real rate control */ 2173 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2174 IEEE80211_FC0_TYPE_MGT) 2175 rate = 2; 2176 else { 2177 rate = MAX(2, rtw_get_rate(ic)); 2178 } 2179 ctl0 = ctl0 | 2180 LSHIFT(pktlen, RTW_TXCTL0_TPKTSIZE_MASK); 2181 2182 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: rate = %d", __func__, rate); 2183 2184 switch (rate) { 2185 default: 2186 case 2: 2187 ctl0 |= RTW_TXCTL0_RATE_1MBPS; 2188 break; 2189 case 4: 2190 ctl0 |= RTW_TXCTL0_RATE_2MBPS; 2191 break; 2192 case 11: 2193 ctl0 |= RTW_TXCTL0_RATE_5MBPS; 2194 break; 2195 case 22: 2196 ctl0 |= RTW_TXCTL0_RATE_11MBPS; 2197 break; 2198 } 2199 2200 /* XXX >= ? Compare after fragmentation? */ 2201 if (pktlen > ic->ic_rtsthreshold) { 2202 ctl0 |= RTW_TXCTL0_RTSEN; 2203 cmn_err(CE_NOTE, "%s: fragmentation: pktlen = %d", 2204 __func__, pktlen); 2205 } 2206 2207 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2208 IEEE80211_FC0_TYPE_MGT) { 2209 ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN); 2210 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 2211 IEEE80211_FC0_SUBTYPE_BEACON) 2212 ctl0 |= RTW_TXCTL0_BEACON; 2213 } 2214 2215 if (rtw_compute_duration(wh, pktlen, 2216 ic->ic_flags, ic->ic_fragthreshold, 2217 rate, &d0, &dn, &npkt) == -1) { 2218 RTW_DPRINTF(RTW_DEBUG_XMIT, 2219 "%s: fail compute duration\n", __func__); 2220 freemsg(mp0); 2221 return (-1); 2222 } 2223 *(uint16_t *)wh->i_dur = (d0.d_data_dur); 2224 2225 ctl1 = LSHIFT(d0.d_plcp_len, RTW_TXCTL1_LENGTH_MASK) | 2226 LSHIFT(d0.d_rts_dur, RTW_TXCTL1_RTSDUR_MASK); 2227 2228 if (d0.d_residue) 2229 ctl1 |= RTW_TXCTL1_LENGEXT; 2230 2231 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: duration=%x, ctl1=%x", __func__, 2232 *(uint16_t *)wh->i_dur, ctl1); 2233 2234 if (bf->bf_dma.alength > RTW_TXLEN_LENGTH_MASK) { 2235 RTW_DPRINTF(RTW_DEBUG_XMIT, 2236 "%s: seg too long\n", __func__); 2237 freemsg(mp0); 2238 return (-1); 2239 } 2240 ds->td_ctl0 = ctl0; 2241 ds->td_ctl0 |= RTW_TXCTL0_OWN | RTW_TXCTL0_LS | RTW_TXCTL0_FS; 2242 ds->td_ctl1 = ctl1; 2243 ds->td_buf = bf->bf_dma.cookie.dmac_address; 2244 ds->td_len = pktlen & 0xfff; 2245 ds->td_next = bf->next_bf_daddr; 2246 2247 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2248 RTW_DESC_OFFSET(hd_txmd, bf->order), 2249 sizeof (struct rtw_txdesc), 2250 DDI_DMA_SYNC_FORDEV); 2251 2252 RTW_DPRINTF(RTW_DEBUG_XMIT, 2253 "descriptor: order = %d, phy_addr=%x, ctl0=%x," 2254 " ctl1=%x, buf=%x, len=%x, next=%x", bf->order, 2255 bf->bf_daddr, ds->td_ctl0, ds->td_ctl1, 2256 ds->td_buf, ds->td_len, ds->td_next); 2257 rsc->sc_pktxmt64++; 2258 rsc->sc_bytexmt64 += pktlen; 2259 2260 freemsg(mp0); 2261 return (0); 2262 } 2263 2264 static int 2265 rtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2266 { 2267 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2268 struct ieee80211_node *in = ic->ic_bss; 2269 struct rtw_txbuf *bf = NULL; 2270 int ret, i = RTW_TXPRIMD; 2271 2272 mutex_enter(&rsc->sc_txlock); 2273 mutex_enter(&rsc->sc_txq[i].txbuf_lock); 2274 bf = list_head(&rsc->sc_txq[i].tx_free_list); 2275 2276 if ((bf == NULL) || (rsc->sc_txq[i].tx_nfree <= 4)) { 2277 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: no tx buf\n", __func__); 2278 rsc->sc_noxmtbuf++; 2279 if ((type & IEEE80211_FC0_TYPE_MASK) == 2280 IEEE80211_FC0_TYPE_DATA) { 2281 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: need reschedule\n", 2282 __func__); 2283 rsc->sc_need_reschedule = 1; 2284 } else { 2285 freemsg(mp); 2286 } 2287 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2288 mutex_exit(&rsc->sc_txlock); 2289 return (1); 2290 } 2291 list_remove(&rsc->sc_txq[i].tx_free_list, bf); 2292 rsc->sc_txq[i].tx_nfree--; 2293 2294 /* assemble 802.11 frame here */ 2295 ret = rtw_assembly_80211(rsc, bf, mp); 2296 if (ret != 0) { 2297 cmn_err(CE_WARN, "%s assembly frame error\n", __func__); 2298 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2299 mutex_exit(&rsc->sc_txlock); 2300 if ((type & IEEE80211_FC0_TYPE_MASK) != 2301 IEEE80211_FC0_TYPE_DATA) { 2302 freemsg(mp); 2303 } 2304 return (1); 2305 } 2306 list_insert_tail(&rsc->sc_txq[i].tx_dirty_list, bf); 2307 bf->bf_in = in; 2308 rtw_dma_start(&rsc->sc_regs, i); 2309 2310 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2311 mutex_exit(&rsc->sc_txlock); 2312 2313 freemsg(mp); 2314 return (0); 2315 } 2316 2317 static mblk_t * 2318 rtw_m_tx(void *arg, mblk_t *mp) 2319 { 2320 rtw_softc_t *rsc = arg; 2321 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2322 mblk_t *next; 2323 2324 if (ic->ic_state != IEEE80211_S_RUN) { 2325 freemsgchain(mp); 2326 return (NULL); 2327 } 2328 2329 while (mp != NULL) { 2330 next = mp->b_next; 2331 mp->b_next = NULL; 2332 2333 if (rtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA)) { 2334 mp->b_next = next; 2335 break; 2336 } 2337 mp = next; 2338 } 2339 2340 return (mp); 2341 2342 } 2343 2344 static void 2345 rtw_next_scan(void *arg) 2346 { 2347 ieee80211com_t *ic = arg; 2348 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2349 2350 rsc->sc_scan_id = 0; 2351 if (ic->ic_state == IEEE80211_S_SCAN) { 2352 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw_next_scan\n"); 2353 (void) ieee80211_next_scan(ic); 2354 } 2355 2356 } 2357 2358 static void 2359 rtw_join_bss(rtw_softc_t *rsc, uint8_t *bssid, uint16_t intval0) 2360 { 2361 uint16_t bcnitv, intval; 2362 int i; 2363 struct rtw_regs *regs = &rsc->sc_regs; 2364 2365 for (i = 0; i < IEEE80211_ADDR_LEN; i++) 2366 RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]); 2367 2368 RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32); 2369 rtw_set_access(regs, RTW_ACCESS_CONFIG); 2370 2371 RTW_WRITE8(regs, RTW_MSR, 0x8); /* sta mode link ok */ 2372 intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK)); 2373 2374 bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK; 2375 bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK); 2376 RTW_WRITE16(regs, RTW_BCNITV, bcnitv); 2377 RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND)); 2378 RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV)); 2379 2380 rtw_set_access(regs, RTW_ACCESS_NONE); 2381 2382 /* TBD WEP */ 2383 /* RTW_WRITE8(regs, RTW_SCR, 0); */ 2384 2385 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1); 2386 } 2387 2388 /* 2389 * Set the starting transmit rate for a node. 2390 */ 2391 static void 2392 rtw_rate_ctl_start(rtw_softc_t *rsc, struct ieee80211_node *in) 2393 { 2394 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2395 int32_t srate; 2396 2397 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 2398 /* 2399 * No fixed rate is requested. For 11b start with 2400 * the highest negotiated rate; otherwise, for 11g 2401 * and 11a, we start "in the middle" at 24Mb or 36Mb. 2402 */ 2403 srate = in->in_rates.ir_nrates - 1; 2404 if (ic->ic_curmode != IEEE80211_MODE_11B) { 2405 /* 2406 * Scan the negotiated rate set to find the 2407 * closest rate. 2408 */ 2409 /* NB: the rate set is assumed sorted */ 2410 for (; srate >= 0 && IEEE80211_RATE(srate) > 72; 2411 srate--) 2412 ; 2413 } 2414 } else { 2415 /* 2416 * A fixed rate is to be used; We know the rate is 2417 * there because the rate set is checked when the 2418 * station associates. 2419 */ 2420 /* NB: the rate set is assumed sorted */ 2421 srate = in->in_rates.ir_nrates - 1; 2422 for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate; 2423 srate--) 2424 ; 2425 } 2426 in->in_txrate = srate; 2427 } 2428 2429 2430 /* 2431 * Reset the rate control state for each 802.11 state transition. 2432 */ 2433 static void 2434 rtw_rate_ctl_reset(rtw_softc_t *rsc, enum ieee80211_state state) 2435 { 2436 ieee80211com_t *ic = &rsc->sc_ic; 2437 ieee80211_node_t *in; 2438 2439 if (ic->ic_opmode == IEEE80211_M_STA) { 2440 /* 2441 * Reset local xmit state; this is really only 2442 * meaningful when operating in station mode. 2443 */ 2444 in = (struct ieee80211_node *)ic->ic_bss; 2445 2446 if (state == IEEE80211_S_RUN) { 2447 rtw_rate_ctl_start(rsc, in); 2448 } else { 2449 in->in_txrate = 0; 2450 } 2451 } 2452 #if 0 2453 else { 2454 /* 2455 * When operating as a station the node table holds 2456 * the AP's that were discovered during scanning. 2457 * For any other operating mode we want to reset the 2458 * tx rate state of each node. 2459 */ 2460 in = list_head(&ic->ic_in_list); 2461 while (in != NULL) { 2462 in->in_txrate = 0; 2463 in = list_next(&ic->ic_in_list, in); 2464 } 2465 in->in_txrate = 0; 2466 } 2467 #endif 2468 } 2469 2470 static int startctl = 0; 2471 2472 /* 2473 * Examine and potentially adjust the transmit rate. 2474 */ 2475 static void 2476 rtw_rate_ctl(void *arg) 2477 { 2478 ieee80211com_t *ic = (ieee80211com_t *)arg; 2479 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2480 struct ieee80211_node *in = ic->ic_bss; 2481 struct ieee80211_rateset *rs = &in->in_rates; 2482 int32_t mod = 0, nrate, enough; 2483 2484 mutex_enter(&rsc->sc_genlock); 2485 2486 enough = (rsc->sc_tx_ok + rsc->sc_tx_err >= 10); 2487 2488 /* no packet reached -> down */ 2489 if (rsc->sc_tx_err > 0 && rsc->sc_tx_ok == 0) 2490 mod = -1; 2491 2492 /* all packets needs retry in average -> down */ 2493 if (enough && rsc->sc_tx_ok < rsc->sc_tx_err) 2494 mod = -1; 2495 2496 /* no error and less than 10% of packets needs retry -> up */ 2497 if (enough && 2498 rsc->sc_tx_ok > rsc->sc_tx_err * 5) 2499 mod = 1; 2500 2501 nrate = in->in_txrate; 2502 switch (mod) { 2503 case 0: 2504 if (enough && rsc->sc_tx_upper > 0) 2505 rsc->sc_tx_upper--; 2506 break; 2507 case -1: 2508 if (nrate > 0) { 2509 nrate--; 2510 } 2511 rsc->sc_tx_upper = 0; 2512 break; 2513 case 1: 2514 if (++rsc->sc_tx_upper < 10) 2515 break; 2516 rsc->sc_tx_upper = 0; 2517 if (nrate + 1 < rs->ir_nrates) { 2518 nrate++; 2519 } 2520 break; 2521 } 2522 2523 if (nrate != in->in_txrate) { 2524 in->in_txrate = nrate; 2525 } else if (enough) 2526 rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0; 2527 if (!startctl) { 2528 rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0; 2529 startctl = 1; 2530 } 2531 2532 mutex_exit(&rsc->sc_genlock); 2533 if (ic->ic_state == IEEE80211_S_RUN) 2534 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic, 2535 drv_usectohz(1000000)); 2536 } 2537 2538 static int32_t 2539 rtw_new_state(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 2540 { 2541 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2542 int error; 2543 enum ieee80211_state ostate; 2544 2545 ostate = ic->ic_state; 2546 2547 RTW_DPRINTF(RTW_DEBUG_ATTACH, 2548 "rtw_new_state: ostate:0x%x, nstate:0x%x, opmode:0x%x\n", 2549 ostate, nstate, ic->ic_opmode); 2550 2551 2552 mutex_enter(&rsc->sc_genlock); 2553 if (rsc->sc_scan_id != 0) { 2554 (void) untimeout(rsc->sc_scan_id); 2555 rsc->sc_scan_id = 0; 2556 } 2557 if (rsc->sc_ratectl_id != 0) { 2558 (void) untimeout(rsc->sc_ratectl_id); 2559 rsc->sc_ratectl_id = 0; 2560 } 2561 rtw_rate_ctl_reset(rsc, nstate); 2562 if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT) 2563 (void) rtw_pwrstate(rsc, RTW_ON); 2564 if ((error = rtw_tune(rsc)) != 0) { 2565 mutex_exit(&rsc->sc_genlock); 2566 return (error); 2567 } 2568 switch (nstate) { 2569 case IEEE80211_S_INIT: 2570 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_INIT\n"); 2571 startctl = 0; 2572 break; 2573 case IEEE80211_S_SCAN: 2574 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_SCAN\n"); 2575 rsc->sc_scan_id = timeout(rtw_next_scan, ic, 2576 drv_usectohz(200000)); 2577 rtw_set_nettype(rsc, IEEE80211_M_MONITOR); 2578 break; 2579 case IEEE80211_S_RUN: 2580 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_RUN\n"); 2581 switch (ic->ic_opmode) { 2582 case IEEE80211_M_HOSTAP: 2583 case IEEE80211_M_IBSS: 2584 rtw_set_nettype(rsc, IEEE80211_M_MONITOR); 2585 /* TBD */ 2586 /*FALLTHROUGH*/ 2587 case IEEE80211_M_AHDEMO: 2588 case IEEE80211_M_STA: 2589 RTW_DPRINTF(RTW_DEBUG_ATTACH, 2590 "rtw_new_state: sta\n"); 2591 rtw_join_bss(rsc, ic->ic_bss->in_bssid, 0); 2592 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic, 2593 drv_usectohz(1000000)); 2594 break; 2595 case IEEE80211_M_MONITOR: 2596 break; 2597 } 2598 rtw_set_nettype(rsc, ic->ic_opmode); 2599 break; 2600 case IEEE80211_S_ASSOC: 2601 case IEEE80211_S_AUTH: 2602 break; 2603 } 2604 2605 mutex_exit(&rsc->sc_genlock); 2606 /* 2607 * Invoke the parent method to complete the work. 2608 */ 2609 error = rsc->sc_newstate(ic, nstate, arg); 2610 2611 return (error); 2612 } 2613 2614 static void 2615 rtw_intr_rx(rtw_softc_t *rsc) 2616 { 2617 #define IS_BEACON(__fc0) \ 2618 ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\ 2619 (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON)) 2620 /* 2621 * ratetbl[4] = {2, 4, 11, 22}; 2622 */ 2623 struct rtw_rxbuf *bf; 2624 struct rtw_rxdesc *ds; 2625 int hwrate, len, rssi; 2626 uint32_t hstat, hrssi, htsftl; 2627 int is_last, next, n = 0, i; 2628 struct ieee80211_frame *wh; 2629 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2630 mblk_t *mp; 2631 2632 RTW_DPRINTF(RTW_DEBUG_RECV, "%s rtw_intr_rx: enter ic_state=%x\n", 2633 __func__, rsc->sc_ic.ic_state); 2634 mutex_enter(&rsc->rxbuf_lock); 2635 next = rsc->rx_next; 2636 mutex_exit(&rsc->rxbuf_lock); 2637 for (i = 0; i < RTW_RXQLEN; i++) { 2638 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2639 RTW_DESC_OFFSET(hd_rx, next), 2640 sizeof (struct rtw_rxdesc), 2641 DDI_DMA_SYNC_FORKERNEL); 2642 n++; 2643 bf = rsc->rxbuf_h + next; 2644 ds = bf->rxdesc; 2645 hstat = (ds->rd_stat); 2646 hrssi = ds->rd_rssi; 2647 htsftl = ds->rd_tsftl; 2648 /* htsfth = ds->rd_tsfth; */ 2649 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: stat=%x\n", __func__, hstat); 2650 /* still belongs to NIC */ 2651 if ((hstat & RTW_RXSTAT_OWN) != 0) { 2652 if (n > 1) { 2653 RTW_DPRINTF(RTW_DEBUG_RECV, 2654 "%s: n > 1\n", __func__); 2655 break; 2656 } 2657 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2658 RTW_DESC_OFFSET(hd_rx, 0), 2659 sizeof (struct rtw_rxdesc), 2660 DDI_DMA_SYNC_FORCPU); 2661 bf = rsc->rxbuf_h; 2662 ds = bf->rxdesc; 2663 hstat = (ds->rd_stat); 2664 if ((hstat & RTW_RXSTAT_OWN) != 0) 2665 break; 2666 next = 0 /* RTW_RXQLEN - 1 */; 2667 continue; 2668 } 2669 2670 rsc->sc_pktrcv64++; 2671 if ((hstat & RTW_RXSTAT_IOERROR) != 0) { 2672 RTW_DPRINTF(RTW_DEBUG_RECV, 2673 "rtw: DMA error/FIFO overflow %08x, " 2674 "rx descriptor %d\n", 2675 hstat & RTW_RXSTAT_IOERROR, next); 2676 goto next; 2677 } 2678 2679 len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK); 2680 rsc->sc_bytercv64 += len; 2681 2682 /* CRC is included with the packet; trim it off. */ 2683 /* len -= IEEE80211_CRC_LEN; */ 2684 2685 hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK); 2686 if (hwrate >= 4) { 2687 goto next; 2688 } 2689 2690 if ((hstat & RTW_RXSTAT_RES) != 0 && 2691 rsc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) { 2692 goto next; 2693 } 2694 2695 /* if bad flags, skip descriptor */ 2696 if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) { 2697 RTW_DPRINTF(RTW_DEBUG_RECV, 2698 "rtw too many rx segments\n"); 2699 goto next; 2700 } 2701 2702 if (rsc->sc_rfchipid == RTW_RFCHIPID_PHILIPS) 2703 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI); 2704 else { 2705 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI); 2706 /* 2707 * TBD find out each front-end's LNA gain in the 2708 * front-end's units 2709 */ 2710 if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0) 2711 rssi |= 0x80; 2712 } 2713 /* sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ); */ 2714 2715 2716 /* deal with the frame itself here */ 2717 mp = allocb(rsc->sc_dmabuf_size, BPRI_MED); 2718 if (mp == NULL) { 2719 cmn_err(CE_WARN, "rtw: alloc mblk error"); 2720 rsc->sc_norcvbuf++; 2721 return; 2722 } 2723 len -= IEEE80211_CRC_LEN; 2724 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORKERNEL); 2725 bcopy(bf->bf_dma.mem_va, mp->b_rptr, len); 2726 mp->b_wptr += len; 2727 wh = (struct ieee80211_frame *)mp->b_rptr; 2728 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2729 IEEE80211_FC0_TYPE_CTL) { 2730 cmn_err(CE_WARN, "TYPE CTL !!\n"); 2731 freemsg(mp); 2732 goto next; 2733 } 2734 (void) ieee80211_input(ic, mp, ic->ic_bss, rssi, htsftl); 2735 next: 2736 if (next == 63) 2737 is_last = 1; 2738 else 2739 is_last = 0; 2740 rtw_rxdesc_init(rsc, bf, next, is_last); 2741 2742 next = (next + 1)%RTW_RXQLEN; 2743 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: next = %d\n", __func__, next); 2744 } 2745 mutex_enter(&rsc->rxbuf_lock); 2746 rsc->rx_next = next; 2747 mutex_exit(&rsc->rxbuf_lock); 2748 } 2749 2750 static void 2751 rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri) 2752 { 2753 struct rtw_txbuf *bf; 2754 struct rtw_txdesc *ds; 2755 uint32_t hstat; 2756 uint32_t head = 0; 2757 uint32_t cnt = 0, idx = 0; 2758 2759 mutex_enter(&rsc->sc_txq[pri].txbuf_lock); 2760 head = RTW_READ(&rsc->sc_regs, RTW_TNPDA); 2761 if (head == rsc->hw_go) { 2762 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2763 return; 2764 } 2765 RTW_DPRINTF(RTW_DEBUG_XMIT, "rtw_ring_recycling: enter ic_state=%x\n", 2766 rsc->sc_ic.ic_state); 2767 2768 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list); 2769 if (bf == NULL) { 2770 RTW_DPRINTF(RTW_DEBUG_XMIT, 2771 "rtw_ring_recycling: dirty bf[%d] NULL\n", pri); 2772 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2773 return; 2774 } 2775 2776 while ((bf != NULL) && (rsc->hw_go != head)) { 2777 cnt++; 2778 idx = (rsc->hw_go - rsc->hw_start) / sizeof (struct rtw_txdesc); 2779 if (idx == 63) 2780 rsc->hw_go = rsc->hw_start; 2781 else 2782 rsc->hw_go += sizeof (struct rtw_txdesc); 2783 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2784 RTW_DESC_OFFSET(hd_txmd, idx), 2785 sizeof (struct rtw_txdesc), 2786 DDI_DMA_SYNC_FORCPU); 2787 2788 RTW_DPRINTF(RTW_DEBUG_XMIT, "Head = 0x%x\n", head); 2789 ds = bf->txdesc; 2790 hstat = (ds->td_stat); 2791 ds->td_len = ds->td_len & 0xfff; 2792 RTW_DPRINTF(RTW_DEBUG_XMIT, 2793 "%s rtw_ring_recycling: stat=%x, pri=%x\n", 2794 __func__, hstat, pri); 2795 if (hstat & RTW_TXSTAT_TOK) 2796 rsc->sc_tx_ok++; 2797 else { 2798 RTW_DPRINTF(RTW_DEBUG_XMIT, 2799 "TX err @%d, o %d, retry[%d], isr[0x%x], cnt %d\n", 2800 idx, (hstat & RTW_TXSTAT_OWN)?1:0, 2801 (hstat & RTW_TXSTAT_DRC_MASK), isr, cnt); 2802 if ((hstat & RTW_TXSTAT_DRC_MASK) <= 4) { 2803 rsc->sc_tx_ok++; 2804 } else { 2805 rsc->sc_tx_err++; 2806 } 2807 } 2808 rsc->sc_tx_retr += 2809 (hstat & RTW_TXSTAT_DRC_MASK); 2810 rsc->sc_xmtretry += 2811 (hstat & RTW_TXSTAT_DRC_MASK); 2812 list_remove(&rsc->sc_txq[pri].tx_dirty_list, bf); 2813 list_insert_tail(&rsc->sc_txq[pri].tx_free_list, 2814 bf); 2815 (rsc->sc_txq[pri].tx_nfree)++; 2816 if (rsc->sc_need_reschedule == 1) { 2817 mac_tx_update(rsc->sc_ic.ic_mach); 2818 rsc->sc_need_reschedule = 0; 2819 } 2820 RTW_DPRINTF(RTW_DEBUG_XMIT, 2821 "rtw_ring_recycling: nfree[%d]=%d\n", 2822 pri, rsc->sc_txq[pri].tx_nfree); 2823 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc)); 2824 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2825 RTW_DESC_OFFSET(hd_txmd, idx), 2826 sizeof (struct rtw_txdesc), 2827 DDI_DMA_SYNC_FORDEV); 2828 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list); 2829 } 2830 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2831 } 2832 2833 static void 2834 rtw_intr_timeout(rtw_softc_t *rsc) 2835 { 2836 rtw_resume_ticks(rsc); 2837 } 2838 2839 static uint_t 2840 rtw_intr(caddr_t arg) 2841 { 2842 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2843 struct rtw_regs *regs = &rsc->sc_regs; 2844 uint16_t isr = 0; 2845 2846 mutex_enter(&rsc->sc_genlock); 2847 isr = RTW_READ16(regs, RTW_ISR); 2848 RTW_WRITE16(regs, RTW_ISR, isr); 2849 2850 if (isr == 0) { 2851 mutex_exit(&rsc->sc_genlock); 2852 return (DDI_INTR_UNCLAIMED); 2853 } 2854 2855 #ifdef DEBUG 2856 #define PRINTINTR(flag) { \ 2857 if ((isr & flag) != 0) { \ 2858 RTW_DPRINTF(RTW_DEBUG_INTR, "|" #flag); \ 2859 } \ 2860 } 2861 2862 if ((rtw_dbg_flags & RTW_DEBUG_INTR) != 0 && isr != 0) { 2863 2864 RTW_DPRINTF(RTW_DEBUG_INTR, "rtw: reg[ISR] = %x", isr); 2865 2866 PRINTINTR(RTW_INTR_TXFOVW); 2867 PRINTINTR(RTW_INTR_TIMEOUT); 2868 PRINTINTR(RTW_INTR_BCNINT); 2869 PRINTINTR(RTW_INTR_ATIMINT); 2870 PRINTINTR(RTW_INTR_TBDER); 2871 PRINTINTR(RTW_INTR_TBDOK); 2872 PRINTINTR(RTW_INTR_THPDER); 2873 PRINTINTR(RTW_INTR_THPDOK); 2874 PRINTINTR(RTW_INTR_TNPDER); 2875 PRINTINTR(RTW_INTR_TNPDOK); 2876 PRINTINTR(RTW_INTR_RXFOVW); 2877 PRINTINTR(RTW_INTR_RDU); 2878 PRINTINTR(RTW_INTR_TLPDER); 2879 PRINTINTR(RTW_INTR_TLPDOK); 2880 PRINTINTR(RTW_INTR_RER); 2881 PRINTINTR(RTW_INTR_ROK); 2882 } 2883 #undef PRINTINTR 2884 #endif /* DEBUG */ 2885 2886 rsc->sc_intr++; 2887 2888 if ((isr & RTW_INTR_RX) != 0) { 2889 mutex_exit(&rsc->sc_genlock); 2890 rtw_intr_rx(rsc); 2891 mutex_enter(&rsc->sc_genlock); 2892 } 2893 if ((isr & RTW_INTR_TIMEOUT) != 0) 2894 rtw_intr_timeout(rsc); 2895 2896 if ((isr & RTW_INTR_TX) != 0) 2897 rtw_ring_recycling(rsc, isr, 1); 2898 mutex_exit(&rsc->sc_genlock); 2899 return (DDI_INTR_CLAIMED); 2900 } 2901 2902 #ifdef DMA_DEBUG 2903 static int 2904 is_dma_over(rtw_softc_t *rsc) 2905 { 2906 int i, j; 2907 uint32_t hstat; 2908 struct rtw_rxbuf *bf; 2909 struct rtw_rxdesc *ds; 2910 #define DMA_WAIT 5 2911 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORCPU); 2912 for (i = 0; i < RTW_NTXPRI; i++) { 2913 j = 0; 2914 while (rsc->sc_txq[i].tx_nfree != rtw_qlen[i]) { 2915 drv_usecwait(100000); 2916 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORCPU); 2917 j++; 2918 if (j >= DMA_WAIT) 2919 break; 2920 } 2921 if (j == DMA_WAIT) 2922 return (1); 2923 } 2924 j = 0; 2925 for (i = 0; i < RTW_RXQLEN; i++) { 2926 bf = rsc->rxbuf_h + i; 2927 ds = bf->rxdesc; 2928 hstat = (ds->rd_stat); 2929 while (((hstat & RTW_RXSTAT_OWN) == 0) && (j < DMA_WAIT)) { 2930 drv_usecwait(100000); 2931 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORCPU); 2932 j++; 2933 } 2934 if (j == DMA_WAIT) 2935 return (1); 2936 } 2937 return (0); 2938 } 2939 #endif 2940 2941 static void 2942 rtw_m_stop(void *arg) 2943 { 2944 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2945 struct rtw_regs *regs = &rsc->sc_regs; 2946 2947 (void) ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1); 2948 /* 2949 * Stop the transmit and receive processes. First stop DMA, 2950 * then disable receiver and transmitter. 2951 */ 2952 mutex_enter(&rsc->sc_genlock); 2953 rtw_disable_interrupts(regs); 2954 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 2955 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 2956 mutex_exit(&rsc->sc_genlock); 2957 delay(1); 2958 2959 rsc->sc_invalid = 1; 2960 } 2961 2962 2963 static int 2964 rtw_m_start(void *arg) 2965 { 2966 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2967 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2968 int ret; 2969 #ifdef DEBUG 2970 rtw_print_regs(&rsc->sc_regs, "rtw", "rtw_start"); 2971 #endif 2972 mutex_enter(&rsc->sc_genlock); 2973 ret = rtw_init(rsc); 2974 if (ret) { 2975 cmn_err(CE_WARN, "rtw: failed to do rtw_init\n"); 2976 mutex_exit(&rsc->sc_genlock); 2977 return (-1); 2978 } 2979 ic->ic_state = IEEE80211_S_INIT; 2980 mutex_exit(&rsc->sc_genlock); 2981 2982 /* 2983 * fix KCF bug. - workaround, need to fix it in net80211 2984 */ 2985 (void) crypto_mech2id(SUN_CKM_RC4); 2986 2987 (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2988 rsc->sc_invalid = 0; 2989 return (0); 2990 } 2991 2992 2993 static int 2994 rtw_m_unicst(void *arg, const uint8_t *macaddr) 2995 { 2996 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2997 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2998 struct rtw_regs *regs = &rsc->sc_regs; 2999 uint32_t t; 3000 3001 mutex_enter(&rsc->sc_genlock); 3002 bcopy(macaddr, ic->ic_macaddr, 6); 3003 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) | 3004 ((*(macaddr + 2))<<8) | (*(macaddr + 3)); 3005 RTW_WRITE(regs, RTW_IDR0, ntohl(t)); 3006 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16); 3007 RTW_WRITE(regs, RTW_IDR1, ntohl(t)); 3008 mutex_exit(&rsc->sc_genlock); 3009 return (0); 3010 } 3011 3012 static int 3013 rtw_m_promisc(void *arg, boolean_t on) 3014 { 3015 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3016 struct rtw_regs *regs = &rsc->sc_regs; 3017 3018 mutex_enter(&rsc->sc_genlock); 3019 3020 if (on) 3021 rsc->sc_rcr |= RTW_RCR_PROMIC; 3022 else 3023 rsc->sc_rcr &= ~RTW_RCR_PROMIC; 3024 3025 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3026 3027 mutex_exit(&rsc->sc_genlock); 3028 return (0); 3029 } 3030 3031 static int 3032 rtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 3033 { 3034 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3035 struct rtw_regs *regs = &rsc->sc_regs; 3036 uint32_t t; 3037 3038 mutex_enter(&rsc->sc_genlock); 3039 if (add) { 3040 rsc->sc_rcr |= RTW_RCR_AM; 3041 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) | 3042 ((*(macaddr + 2))<<8) | (*(macaddr + 3)); 3043 RTW_WRITE(regs, RTW_MAR0, ntohl(t)); 3044 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16); 3045 RTW_WRITE(regs, RTW_MAR1, ntohl(t)); 3046 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3047 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); 3048 } else { 3049 rsc->sc_rcr &= ~RTW_RCR_AM; 3050 RTW_WRITE(regs, RTW_MAR0, 0); 3051 RTW_WRITE(regs, RTW_MAR1, 0); 3052 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3053 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); 3054 } 3055 mutex_exit(&rsc->sc_genlock); 3056 return (0); 3057 } 3058 3059 static void 3060 rtw_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 3061 { 3062 rtw_softc_t *rsc = arg; 3063 int32_t err; 3064 3065 err = ieee80211_ioctl(&rsc->sc_ic, wq, mp); 3066 if (err == ENETRESET) { 3067 if (rsc->sc_invalid == 0) { 3068 (void) ieee80211_new_state(&rsc->sc_ic, 3069 IEEE80211_S_INIT, -1); 3070 (void) ieee80211_new_state(&rsc->sc_ic, 3071 IEEE80211_S_SCAN, -1); 3072 } 3073 } 3074 } 3075 3076 static int 3077 rtw_m_stat(void *arg, uint_t stat, uint64_t *val) 3078 { 3079 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3080 ieee80211com_t *ic = (ieee80211com_t *)rsc; 3081 struct ieee80211_node *in = ic->ic_bss; 3082 struct ieee80211_rateset *rs = &in->in_rates; 3083 3084 mutex_enter(&rsc->sc_genlock); 3085 switch (stat) { 3086 case MAC_STAT_IFSPEED: 3087 *val = ((rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL)) 3088 * 500000; 3089 break; 3090 case MAC_STAT_NOXMTBUF: 3091 *val = rsc->sc_noxmtbuf; 3092 break; 3093 case MAC_STAT_NORCVBUF: 3094 *val = rsc->sc_norcvbuf; 3095 break; 3096 case MAC_STAT_RBYTES: 3097 *val = rsc->sc_bytercv64; 3098 break; 3099 case MAC_STAT_IPACKETS: 3100 *val = rsc->sc_pktrcv64; 3101 break; 3102 case MAC_STAT_OBYTES: 3103 *val = rsc->sc_bytexmt64; 3104 break; 3105 case MAC_STAT_OPACKETS: 3106 *val = rsc->sc_pktxmt64; 3107 break; 3108 case WIFI_STAT_TX_RETRANS: 3109 *val = rsc->sc_xmtretry; 3110 break; 3111 case WIFI_STAT_TX_FRAGS: 3112 case WIFI_STAT_MCAST_TX: 3113 case WIFI_STAT_RTS_SUCCESS: 3114 case WIFI_STAT_RTS_FAILURE: 3115 case WIFI_STAT_ACK_FAILURE: 3116 case WIFI_STAT_RX_FRAGS: 3117 case WIFI_STAT_MCAST_RX: 3118 case WIFI_STAT_RX_DUPS: 3119 mutex_exit(&rsc->sc_genlock); 3120 return (ieee80211_stat(ic, stat, val)); 3121 default: 3122 *val = 0; 3123 break; 3124 } 3125 mutex_exit(&rsc->sc_genlock); 3126 3127 return (0); 3128 } 3129 3130 3131 static void 3132 rtw_mutex_destroy(rtw_softc_t *rsc) 3133 { 3134 int i; 3135 3136 mutex_destroy(&rsc->rxbuf_lock); 3137 mutex_destroy(&rsc->sc_txlock); 3138 for (i = 0; i < RTW_NTXPRI; i++) { 3139 mutex_destroy(&rsc->sc_txq[RTW_NTXPRI - 1 - i].txbuf_lock); 3140 } 3141 mutex_destroy(&rsc->sc_genlock); 3142 } 3143 3144 static int 3145 rtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 3146 { 3147 rtw_softc_t *rsc; 3148 ieee80211com_t *ic; 3149 uint8_t csz; 3150 uint32_t i; 3151 uint16_t vendor_id, device_id, command; 3152 int32_t err; 3153 char strbuf[32]; 3154 wifi_data_t wd = { 0 }; 3155 mac_register_t *macp; 3156 int instance = ddi_get_instance(devinfo); 3157 3158 switch (cmd) { 3159 case DDI_ATTACH: 3160 break; 3161 default: 3162 return (DDI_FAILURE); 3163 } 3164 3165 if (ddi_soft_state_zalloc(rtw_soft_state_p, 3166 ddi_get_instance(devinfo)) != DDI_SUCCESS) { 3167 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3168 "Unable to alloc softstate\n"); 3169 return (DDI_FAILURE); 3170 } 3171 3172 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo)); 3173 ic = &rsc->sc_ic; 3174 rsc->sc_dev = devinfo; 3175 3176 err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&rsc->sc_cfg_base, 0, 0, 3177 &rtw_reg_accattr, &rsc->sc_cfg_handle); 3178 if (err != DDI_SUCCESS) { 3179 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3180 "ddi_regs_map_setup() failed"); 3181 goto attach_fail0; 3182 } 3183 csz = ddi_get8(rsc->sc_cfg_handle, 3184 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 3185 if (!csz) 3186 csz = 16; 3187 rsc->sc_cachelsz = csz << 2; 3188 vendor_id = ddi_get16(rsc->sc_cfg_handle, 3189 (uint16_t *)(rsc->sc_cfg_base + PCI_CONF_VENID)); 3190 device_id = ddi_get16(rsc->sc_cfg_handle, 3191 (uint16_t *)(rsc->sc_cfg_base + PCI_CONF_DEVID)); 3192 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): vendor 0x%x, " 3193 "device id 0x%x, cache size %d\n", vendor_id, device_id, csz); 3194 3195 /* 3196 * Enable response to memory space accesses, 3197 * and enabe bus master. 3198 */ 3199 command = PCI_COMM_MAE | PCI_COMM_ME; 3200 ddi_put16(rsc->sc_cfg_handle, 3201 (uint16_t *)(rsc->sc_cfg_base + PCI_CONF_COMM), command); 3202 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3203 "set command reg to 0x%x \n", command); 3204 3205 ddi_put8(rsc->sc_cfg_handle, 3206 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8); 3207 3208 ddi_regs_map_free(&rsc->sc_cfg_handle); 3209 3210 err = ddi_regs_map_setup(devinfo, 2, (caddr_t *)&rsc->sc_regs.r_base, 3211 0, 0, &rtw_reg_accattr, &rsc->sc_regs.r_handle); 3212 if (err != DDI_SUCCESS) { 3213 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3214 "ddi_regs_map_setup() failed"); 3215 goto attach_fail0; 3216 } 3217 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: r_base=%x, r_handle=%x\n", 3218 rsc->sc_regs.r_base, rsc->sc_regs.r_handle); 3219 3220 err = rtw_dma_init(devinfo, rsc); 3221 if (err != DDI_SUCCESS) { 3222 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3223 "failed to init dma: %d\n", err); 3224 goto attach_fail1; 3225 } 3226 3227 /* 3228 * Stop the transmit and receive processes. First stop DMA, 3229 * then disable receiver and transmitter. 3230 */ 3231 RTW_WRITE8(&rsc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 3232 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 3233 3234 /* Reset the chip to a known state. */ 3235 if (rtw_reset(rsc) != 0) { 3236 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3237 "failed to reset\n"); 3238 goto attach_fail2; 3239 } 3240 rsc->sc_rcr = RTW_READ(&rsc->sc_regs, RTW_RCR); 3241 3242 if ((rsc->sc_rcr & RTW_RCR_9356SEL) != 0) 3243 rsc->sc_flags |= RTW_F_9356SROM; 3244 3245 if (rtw_srom_read(&rsc->sc_regs, rsc->sc_flags, &rsc->sc_srom, 3246 "rtw") != 0) { 3247 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3248 "failed to read srom\n"); 3249 goto attach_fail2; 3250 } 3251 3252 if (rtw_srom_parse(&rsc->sc_srom, &rsc->sc_flags, &rsc->sc_csthr, 3253 &rsc->sc_rfchipid, &rsc->sc_rcr, &rsc->sc_locale, 3254 "rtw") != 0) { 3255 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_attach():" 3256 " malformed serial ROM\n"); 3257 goto attach_fail3; 3258 } 3259 3260 RTW_DPRINTF(RTW_DEBUG_PHY, "rtw: %s PHY\n", 3261 ((rsc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog"); 3262 3263 3264 rsc->sc_rf = rtw_rf_attach(rsc, rsc->sc_rfchipid, 3265 rsc->sc_flags & RTW_F_DIGPHY); 3266 3267 if (rsc->sc_rf == NULL) { 3268 cmn_err(CE_WARN, "rtw: rtw_attach(): could not attach RF\n"); 3269 goto attach_fail3; 3270 } 3271 rsc->sc_phydelay = rtw_check_phydelay(&rsc->sc_regs, rsc->sc_rcr); 3272 3273 RTW_DPRINTF(RTW_DEBUG_ATTACH, 3274 "rtw: PHY delay %d\n", rsc->sc_phydelay); 3275 3276 if (rsc->sc_locale == RTW_LOCALE_UNKNOWN) 3277 rtw_identify_country(&rsc->sc_regs, &rsc->sc_locale, 3278 "rtw"); 3279 3280 rtw_init_channels(rsc->sc_locale, &rsc->sc_ic.ic_sup_channels, 3281 "rtw"); 3282 3283 rtw_set80211props(ic); 3284 3285 if (rtw_identify_sta(&rsc->sc_regs, ic->ic_macaddr, 3286 "rtw") != 0) 3287 goto attach_fail4; 3288 3289 ic->ic_xmit = rtw_send; 3290 ieee80211_attach(ic); 3291 3292 rsc->sc_newstate = ic->ic_newstate; 3293 ic->ic_newstate = rtw_new_state; 3294 ieee80211_media_init(ic); 3295 ic->ic_def_txkey = 0; 3296 3297 if (ddi_get_iblock_cookie(devinfo, 0, &(rsc->sc_iblock)) 3298 != DDI_SUCCESS) { 3299 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3300 "Can not get iblock cookie for INT\n"); 3301 goto attach_fail5; 3302 } 3303 3304 mutex_init(&rsc->sc_genlock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3305 for (i = 0; i < RTW_NTXPRI; i++) { 3306 mutex_init(&rsc->sc_txq[i].txbuf_lock, NULL, MUTEX_DRIVER, 3307 rsc->sc_iblock); 3308 } 3309 mutex_init(&rsc->rxbuf_lock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3310 mutex_init(&rsc->sc_txlock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3311 3312 if (ddi_add_intr(devinfo, 0, &rsc->sc_iblock, NULL, rtw_intr, 3313 (caddr_t)(rsc)) != DDI_SUCCESS) { 3314 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3315 "Can not add intr for rtw driver\n"); 3316 goto attach_fail7; 3317 } 3318 3319 /* 3320 * Provide initial settings for the WiFi plugin; whenever this 3321 * information changes, we need to call mac_plugindata_update() 3322 */ 3323 wd.wd_opmode = ic->ic_opmode; 3324 wd.wd_secalloc = WIFI_SEC_NONE; 3325 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 3326 3327 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 3328 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3329 "MAC version mismatch\n"); 3330 goto attach_fail8; 3331 } 3332 3333 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 3334 macp->m_driver = rsc; 3335 macp->m_dip = devinfo; 3336 macp->m_src_addr = ic->ic_macaddr; 3337 macp->m_callbacks = &rtw_m_callbacks; 3338 macp->m_min_sdu = 0; 3339 macp->m_max_sdu = IEEE80211_MTU; 3340 macp->m_pdata = &wd; 3341 macp->m_pdata_size = sizeof (wd); 3342 3343 err = mac_register(macp, &ic->ic_mach); 3344 mac_free(macp); 3345 if (err != 0) { 3346 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3347 "mac_register err %x\n", err); 3348 goto attach_fail8; 3349 } 3350 3351 /* Create minor node of type DDI_NT_NET_WIFI */ 3352 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 3353 "rtw", instance); 3354 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 3355 instance + 1, DDI_NT_NET_WIFI, 0); 3356 if (err != DDI_SUCCESS) { 3357 RTW_DPRINTF(RTW_DEBUG_ATTACH, "WARN: rtw: rtw_attach(): " 3358 "Create minor node failed - %d\n", err); 3359 goto attach_fail9; 3360 } 3361 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 3362 rsc->sc_flags |= RTW_F_ATTACHED; 3363 rsc->sc_need_reschedule = 0; 3364 rsc->sc_invalid = 1; 3365 return (DDI_SUCCESS); 3366 attach_fail9: 3367 (void) mac_unregister(ic->ic_mach); 3368 attach_fail8: 3369 ddi_remove_intr(devinfo, 0, rsc->sc_iblock); 3370 attach_fail7: 3371 attach_fail6: 3372 rtw_mutex_destroy(rsc); 3373 attach_fail5: 3374 ieee80211_detach(ic); 3375 attach_fail4: 3376 rtw_rf_destroy(rsc->sc_rf); 3377 attach_fail3: 3378 rtw_srom_free(&rsc->sc_srom); 3379 attach_fail2: 3380 rtw_dma_free(rsc); 3381 attach_fail1: 3382 ddi_regs_map_free(&rsc->sc_regs.r_handle); 3383 attach_fail0: 3384 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo)); 3385 return (DDI_FAILURE); 3386 } 3387 3388 static int32_t 3389 rtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 3390 { 3391 rtw_softc_t *rsc; 3392 3393 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo)); 3394 ASSERT(rsc != NULL); 3395 3396 switch (cmd) { 3397 case DDI_DETACH: 3398 break; 3399 default: 3400 return (DDI_FAILURE); 3401 } 3402 if (!(rsc->sc_flags & RTW_F_ATTACHED)) 3403 return (DDI_FAILURE); 3404 3405 /* free intterrupt resources */ 3406 ddi_remove_intr(devinfo, 0, rsc->sc_iblock); 3407 3408 rtw_mutex_destroy(rsc); 3409 ieee80211_detach((ieee80211com_t *)rsc); 3410 /* 3411 * Unregister from the MAC layer subsystem 3412 */ 3413 (void) mac_unregister(rsc->sc_ic.ic_mach); 3414 3415 rtw_rf_destroy(rsc->sc_rf); 3416 rtw_srom_free(&rsc->sc_srom); 3417 rtw_dma_free(rsc); 3418 ddi_remove_minor_node(devinfo, NULL); 3419 ddi_regs_map_free(&rsc->sc_regs.r_handle); 3420 3421 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo)); 3422 3423 return (DDI_SUCCESS); 3424 } 3425