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