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 (void) memset(sr->sr_content, 0, sr->sr_size);
820
821 /*
822 * RTL8180 has a single 8-bit register for controlling the
823 * 93cx6 SROM. There is no "ready" bit. The RTL8180
824 * input/output sense is the reverse of read_seeprom's.
825 */
826 sd.sd_handle = regs->r_handle;
827 sd.sd_base = regs->r_base;
828 sd.sd_regsize = 1;
829 sd.sd_control_offset = RTW_9346CR;
830 sd.sd_status_offset = RTW_9346CR;
831 sd.sd_dataout_offset = RTW_9346CR;
832 sd.sd_CK = RTW_9346CR_EESK;
833 sd.sd_CS = RTW_9346CR_EECS;
834 sd.sd_DI = RTW_9346CR_EEDO;
835 sd.sd_DO = RTW_9346CR_EEDI;
836 /*
837 * make read_seeprom enter EEPROM read/write mode
838 */
839 sd.sd_MS = ecr;
840 sd.sd_RDY = 0;
841
842 /*
843 * TBD bus barriers
844 */
845 if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
846 cmn_err(CE_WARN, "%s: could not read SROM\n", dvname);
847 kmem_free(sr->sr_content, sr->sr_size);
848 sr->sr_content = NULL;
849 return (-1); /* XXX */
850 }
851
852 /*
853 * end EEPROM read/write mode
854 */
855 RTW_WRITE8(regs, RTW_9346CR,
856 (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL);
857 RTW_WBRW(regs, RTW_9346CR, RTW_9346CR);
858
859 if ((rc = rtw_recall_eeprom(regs, dvname)) != 0)
860 return (rc);
861
862 #ifdef SROM_DEBUG
863 {
864 int i;
865 RTW_DPRINTF(RTW_DEBUG_ATTACH,
866 "\n%s: serial ROM:\n\t", dvname);
867 for (i = 0; i < sr->sr_size/2; i++) {
868 RTW_DPRINTF(RTW_DEBUG_ATTACH,
869 "offset-0x%x: %04x", 2*i, sr->sr_content[i]);
870 }
871 }
872 #endif /* DEBUG */
873 return (0);
874 }
875
876 static void
877 rtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
878 const char *dvname)
879 {
880 uint8_t cfg4;
881 const char *method;
882
883 cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
884
885 switch (rfchipid) {
886 default:
887 cfg4 |= LSHIFT(0, RTW_CONFIG4_RFTYPE_MASK);
888 method = "fallback";
889 break;
890 case RTW_RFCHIPID_INTERSIL:
891 cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL;
892 method = "Intersil";
893 break;
894 case RTW_RFCHIPID_PHILIPS:
895 cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
896 method = "Philips";
897 break;
898 case RTW_RFCHIPID_GCT: /* XXX a guess */
899 case RTW_RFCHIPID_RFMD:
900 cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
901 method = "RFMD";
902 break;
903 }
904
905 RTW_WRITE8(regs, RTW_CONFIG4, cfg4);
906
907 RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4);
908
909 RTW_DPRINTF(RTW_DEBUG_INIT,
910 "%s: %s RF programming method, %02x\n", dvname, method,
911 RTW_READ8(regs, RTW_CONFIG4));
912 }
913
914 static void
915 rtw_init_channels(enum rtw_locale locale,
916 struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1],
917 const char *dvname)
918 {
919 int i;
920 const char *name = NULL;
921 #define ADD_CHANNEL(_chans, _chan) { \
922 (*_chans)[_chan].ich_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;\
923 (*_chans)[_chan].ich_freq = \
924 ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ich_flags);\
925 }
926
927 switch (locale) {
928 case RTW_LOCALE_USA: /* 1-11 */
929 name = "USA";
930 for (i = 1; i <= 11; i++)
931 ADD_CHANNEL(chans, i);
932 break;
933 case RTW_LOCALE_JAPAN: /* 1-14 */
934 name = "Japan";
935 ADD_CHANNEL(chans, 14);
936 for (i = 1; i <= 14; i++)
937 ADD_CHANNEL(chans, i);
938 break;
939 case RTW_LOCALE_EUROPE: /* 1-13 */
940 name = "Europe";
941 for (i = 1; i <= 13; i++)
942 ADD_CHANNEL(chans, i);
943 break;
944 default: /* 10-11 allowed by most countries */
945 name = "<unknown>";
946 for (i = 10; i <= 11; i++)
947 ADD_CHANNEL(chans, i);
948 break;
949 }
950 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: Geographic Location %s\n",
951 dvname, name);
952 #undef ADD_CHANNEL
953 }
954
955 static void
956 rtw_set80211props(struct ieee80211com *ic)
957 {
958 ic->ic_phytype = IEEE80211_T_DS;
959 ic->ic_opmode = IEEE80211_M_STA;
960 ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
961 IEEE80211_C_SHPREAMBLE;
962 /* IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP */
963
964 ic->ic_sup_rates[IEEE80211_MODE_11B] = rtw_rateset_11b;
965 }
966
967 /*ARGSUSED*/
968 static void
969 rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale,
970 const char *dvname)
971 {
972 uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
973
974 switch (cfg0 & RTW_CONFIG0_GL_MASK) {
975 case RTW_CONFIG0_GL_USA:
976 *locale = RTW_LOCALE_USA;
977 break;
978 case RTW_CONFIG0_GL_JAPAN:
979 *locale = RTW_LOCALE_JAPAN;
980 break;
981 case RTW_CONFIG0_GL_EUROPE:
982 *locale = RTW_LOCALE_EUROPE;
983 break;
984 default:
985 *locale = RTW_LOCALE_UNKNOWN;
986 break;
987 }
988 }
989
990 static int
991 rtw_identify_sta(struct rtw_regs *regs, uint8_t *addr,
992 const char *dvname)
993 {
994 uint32_t idr0 = RTW_READ(regs, RTW_IDR0),
995 idr1 = RTW_READ(regs, RTW_IDR1);
996
997 *addr = MASK_AND_RSHIFT(idr0, BITS(0, 7));
998 *(addr + 1) = MASK_AND_RSHIFT(idr0, BITS(8, 15));
999 *(addr + 2) = MASK_AND_RSHIFT(idr0, BITS(16, 23));
1000 *(addr + 3) = MASK_AND_RSHIFT(idr0, BITS(24, 31));
1001
1002 *(addr + 4) = MASK_AND_RSHIFT(idr1, BITS(0, 7));
1003 *(addr + 5) = MASK_AND_RSHIFT(idr1, BITS(8, 15));
1004
1005 RTW_DPRINTF(RTW_DEBUG_ATTACH,
1006 "%s: 802.11mac address %x:%x:%x:%x:%x:%x\n", dvname,
1007 *addr, *(addr+1), *(addr+2), *(addr+3), *(addr+4), *(addr+5));
1008
1009 return (0);
1010 }
1011
1012 static uint8_t
1013 rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
1014 struct ieee80211_channel *chan)
1015 {
1016 uint32_t idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
1017 return (RTW_SR_GET(sr, idx));
1018 }
1019
1020 static void
1021 rtw_rxdesc_init(rtw_softc_t *rsc, struct rtw_rxbuf *rbf, int idx, int is_last)
1022 {
1023 uint32_t ctl = 0;
1024 uint8_t *buf = (uint8_t *)rbf->bf_dma.mem_va;
1025
1026 ASSERT(rbf != NULL);
1027 rbf->rxdesc->rd_buf = (rbf->bf_dma.cookie.dmac_address);
1028 bzero(buf, rbf->bf_dma.alength);
1029 RTW_DMA_SYNC(rbf->bf_dma, DDI_DMA_SYNC_FORDEV);
1030
1031 ctl = (rbf->bf_dma.alength & 0xfff) | RTW_RXCTL_OWN;
1032
1033 if (is_last)
1034 ctl |= RTW_RXCTL_EOR;
1035
1036 rbf->rxdesc->rd_ctl = (ctl);
1037 /* sync the mbuf */
1038
1039 /* sync the descriptor */
1040 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
1041 RTW_DESC_OFFSET(hd_rx, idx),
1042 sizeof (struct rtw_rxdesc),
1043 DDI_DMA_SYNC_FORDEV);
1044 }
1045
1046 static void
1047 rtw_idle(struct rtw_regs *regs)
1048 {
1049 int active;
1050
1051 /* request stop DMA; wait for packets to stop transmitting. */
1052
1053 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
1054
1055 for (active = 0; active < 300 &&
1056 (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ALL) != 0; active++)
1057 drv_usecwait(10);
1058 }
1059
1060 static void
1061 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable)
1062 {
1063 uint8_t cr;
1064 struct rtw_regs *regs = &rsc->sc_regs;
1065
1066 RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: %s 0x%02x\n", __func__,
1067 enable ? "enable" : "disable", flags);
1068
1069 cr = RTW_READ8(regs, RTW_CR);
1070
1071 /* The receive engine will always start at RDSAR. */
1072 if (enable && (flags & ~cr & RTW_CR_RE)) {
1073 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
1074 RTW_DESC_OFFSET(hd_rx, 0),
1075 sizeof (struct rtw_rxdesc),
1076 DDI_DMA_SYNC_FORCPU);
1077 rsc->rx_next = 0;
1078 rtw_rxdesc_init(rsc, rsc->rxbuf_h, 0, 0);
1079 }
1080
1081 if (enable)
1082 cr |= flags;
1083 else
1084 cr &= ~flags;
1085 RTW_WRITE8(regs, RTW_CR, cr);
1086 (void) RTW_READ8(regs, RTW_CR);
1087 }
1088
1089 /*
1090 * Allocate an area of memory and a DMA handle for accessing it
1091 */
1092 static int
1093 rtw_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr,
1094 size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
1095 uint_t bind_flags, dma_area_t *dma_p)
1096 {
1097 int err;
1098
1099 /*
1100 * Allocate handle
1101 */
1102 err = ddi_dma_alloc_handle(devinfo, dma_attr,
1103 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
1104 if (err != DDI_SUCCESS)
1105 return (DDI_FAILURE);
1106
1107 /*
1108 * Allocate memory
1109 */
1110 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
1111 alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
1112 &dma_p->alength, &dma_p->acc_hdl);
1113 if (err != DDI_SUCCESS)
1114 return (DDI_FAILURE);
1115
1116 /*
1117 * Bind the two together
1118 */
1119 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1120 dma_p->mem_va, dma_p->alength, bind_flags,
1121 DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
1122 if ((dma_p->ncookies != 1) || (err != DDI_DMA_MAPPED))
1123 return (DDI_FAILURE);
1124
1125 dma_p->nslots = ~0U;
1126 dma_p->size = ~0U;
1127 dma_p->token = ~0U;
1128 dma_p->offset = 0;
1129 return (DDI_SUCCESS);
1130 }
1131
1132 /*
1133 * Free one allocated area of DMAable memory
1134 */
1135 static void
1136 rtw_free_dma_mem(dma_area_t *dma_p)
1137 {
1138 if (dma_p->dma_hdl != NULL) {
1139 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
1140 if (dma_p->acc_hdl != NULL) {
1141 ddi_dma_mem_free(&dma_p->acc_hdl);
1142 dma_p->acc_hdl = NULL;
1143 }
1144 ddi_dma_free_handle(&dma_p->dma_hdl);
1145 dma_p->ncookies = 0;
1146 dma_p->dma_hdl = NULL;
1147 }
1148 }
1149
1150 static void
1151 rtw_dma_free(rtw_softc_t *rsc)
1152 {
1153 struct rtw_txbuf *txbf;
1154 struct rtw_rxbuf *rxbf;
1155 int i, j;
1156
1157 /* Free TX DMA buffer */
1158 for (i = 0; i < RTW_NTXPRI; i++) {
1159 txbf = list_head(&rsc->sc_txq[i].tx_free_list);
1160 while (txbf != NULL) {
1161 rtw_free_dma_mem(&txbf->bf_dma);
1162 list_remove(&rsc->sc_txq[i].tx_free_list, txbf);
1163 txbf = list_head(&rsc->sc_txq[i].tx_free_list);
1164 }
1165 list_destroy(&rsc->sc_txq[i].tx_free_list);
1166 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
1167 while (txbf != NULL) {
1168 rtw_free_dma_mem(&txbf->bf_dma);
1169 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf);
1170 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
1171 }
1172 list_destroy(&rsc->sc_txq[i].tx_dirty_list);
1173
1174 if (rsc->sc_txq[i].txbuf_h != NULL) {
1175 kmem_free(rsc->sc_txq[i].txbuf_h,
1176 sizeof (struct rtw_txbuf) * rtw_qlen[i]);
1177 rsc->sc_txq[i].txbuf_h = NULL;
1178 }
1179 }
1180
1181 /* Free RX DMA buffer */
1182 rxbf = rsc->rxbuf_h;
1183 for (j = 0; j < RTW_RXQLEN; j++) {
1184 rtw_free_dma_mem(&rxbf->bf_dma);
1185 rxbf++;
1186 }
1187
1188 if (rsc->rxbuf_h != NULL) {
1189 kmem_free(rsc->rxbuf_h,
1190 sizeof (struct rtw_rxbuf) * RTW_RXQLEN);
1191 rsc->rxbuf_h = NULL;
1192 }
1193
1194 rtw_free_dma_mem(&rsc->sc_desc_dma);
1195 }
1196
1197 static int
1198 rtw_dma_init(dev_info_t *devinfo, rtw_softc_t *rsc)
1199 {
1200 int i, j, err;
1201 size_t size;
1202 uint32_t buflen;
1203 struct rtw_txdesc *txds;
1204 struct rtw_rxdesc *rxds;
1205 struct rtw_txbuf *txbf;
1206 struct rtw_rxbuf *rxbf;
1207 uint32_t phybaseaddr, ptx[RTW_NTXPRI], prx;
1208 caddr_t virbaseaddr, vtx[RTW_NTXPRI], vrx;
1209
1210 /* DMA buffer size for each TX/RX packet */
1211 rsc->sc_dmabuf_size = roundup(sizeof (struct ieee80211_frame) + 0x100 +
1212 IEEE80211_MTU + IEEE80211_CRC_LEN + sizeof (struct ieee80211_llc) +
1213 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
1214 IEEE80211_WEP_CRCLEN), rsc->sc_cachelsz);
1215 size = sizeof (struct rtw_descs);
1216 err = rtw_alloc_dma_mem(devinfo, &dma_attr_desc, size,
1217 &rtw_desc_accattr,
1218 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1219 &rsc->sc_desc_dma);
1220 if (err != DDI_SUCCESS)
1221 goto error;
1222 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
1223 virbaseaddr = rsc->sc_desc_dma.mem_va;
1224 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo);
1225 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd);
1226 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi);
1227 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn);
1228 vtx[0] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txlo));
1229 vtx[1] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txmd));
1230 vtx[2] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txhi));
1231 vtx[3] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_bcn));
1232 for (i = 0; i < RTW_NTXPRI; i++) {
1233 RTW_DPRINTF(RTW_DEBUG_DMA, "p[%d]=%x, v[%d]=%x", i, ptx[i],
1234 i, vtx[i]);
1235 RTW_DPRINTF(RTW_DEBUG_DMA, "ring%d:", i);
1236 list_create(&rsc->sc_txq[i].tx_free_list,
1237 sizeof (struct rtw_txbuf),
1238 offsetof(struct rtw_txbuf, bf_node));
1239 list_create(&rsc->sc_txq[i].tx_dirty_list,
1240 sizeof (struct rtw_txbuf),
1241 offsetof(struct rtw_txbuf, bf_node));
1242 /* virtual address of the first descriptor */
1243 rsc->sc_txq[i].txdesc_h =
1244 (struct rtw_txdesc *)(uintptr_t)vtx[i];
1245
1246 txds = rsc->sc_txq[i].txdesc_h;
1247 /* allocate data structures to describe TX DMA buffers */
1248 buflen = sizeof (struct rtw_txbuf) * rtw_qlen[i];
1249 txbf = (struct rtw_txbuf *)kmem_zalloc(buflen, KM_SLEEP);
1250 rsc->sc_txq[i].txbuf_h = txbf;
1251 for (j = 0; j < rtw_qlen[i]; j++, txbf++, txds++) {
1252 txbf->txdesc = txds;
1253 txbf->bf_daddr = ptx[i] + ((uintptr_t)txds -
1254 (uintptr_t)rsc->sc_txq[i].txdesc_h);
1255 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf);
1256
1257 /* alloc DMA memory */
1258 err = rtw_alloc_dma_mem(devinfo, &dma_attr_txbuf,
1259 rsc->sc_dmabuf_size,
1260 &rtw_buf_accattr,
1261 DDI_DMA_STREAMING,
1262 DDI_DMA_WRITE | DDI_DMA_STREAMING,
1263 &txbf->bf_dma);
1264 if (err != DDI_SUCCESS)
1265 goto error;
1266 RTW_DPRINTF(RTW_DEBUG_DMA, "pbufaddr[%d]=%x",
1267 j, txbf->bf_dma.cookie.dmac_address);
1268 }
1269 }
1270 prx = RTW_RING_BASE(phybaseaddr, hd_rx);
1271 vrx = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_rx));
1272 /* virtual address of the first descriptor */
1273 rsc->rxdesc_h = (struct rtw_rxdesc *)(uintptr_t)vrx;
1274 rxds = rsc->rxdesc_h;
1275
1276 /* allocate data structures to describe RX DMA buffers */
1277 buflen = sizeof (struct rtw_rxbuf) * RTW_RXQLEN;
1278 rxbf = (struct rtw_rxbuf *)kmem_zalloc(buflen, KM_SLEEP);
1279 rsc->rxbuf_h = rxbf;
1280
1281 for (j = 0; j < RTW_RXQLEN; j++, rxbf++, rxds++) {
1282 rxbf->rxdesc = rxds;
1283 rxbf->bf_daddr =
1284 prx + ((uintptr_t)rxds - (uintptr_t)rsc->rxdesc_h);
1285
1286 /* alloc DMA memory */
1287 err = rtw_alloc_dma_mem(devinfo, &dma_attr_rxbuf,
1288 rsc->sc_dmabuf_size,
1289 &rtw_buf_accattr,
1290 DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING,
1291 &rxbf->bf_dma);
1292 if (err != DDI_SUCCESS)
1293 goto error;
1294 }
1295
1296 return (DDI_SUCCESS);
1297 error:
1298 return (DDI_FAILURE);
1299 }
1300
1301 static void
1302 rtw_hwring_setup(rtw_softc_t *rsc)
1303 {
1304 struct rtw_regs *regs = &rsc->sc_regs;
1305 uint32_t phybaseaddr;
1306
1307 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
1308
1309 RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(phybaseaddr, hd_rx));
1310 RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(phybaseaddr, hd_txlo));
1311 RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(phybaseaddr, hd_txmd));
1312 RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(phybaseaddr, hd_txhi));
1313 RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(phybaseaddr, hd_bcn));
1314 rsc->hw_start = RTW_READ(regs, RTW_TNPDA);
1315 rsc->hw_go = RTW_READ(regs, RTW_TNPDA);
1316 }
1317
1318 static void
1319 rtw_swring_setup(rtw_softc_t *rsc, int flag)
1320 {
1321 int i, j;
1322 int is_last;
1323 struct rtw_txbuf *txbf;
1324 struct rtw_rxbuf *rxbf;
1325 uint32_t phybaseaddr, ptx[RTW_NTXPRI], baddr_desc, taddr_desc;
1326
1327 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
1328 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo);
1329 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd);
1330 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi);
1331 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn);
1332 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORDEV);
1333 /* sync tx desc and tx buf */
1334 for (i = 0; i < RTW_NTXPRI; i++) {
1335 rsc->sc_txq[i].tx_prod = rsc->sc_txq[i].tx_cons = 0;
1336 rsc->sc_txq[i].tx_nfree = rtw_qlen[i];
1337 txbf = list_head(&rsc->sc_txq[i].tx_free_list);
1338 while (txbf != NULL) {
1339 list_remove(&rsc->sc_txq[i].tx_free_list, txbf);
1340 txbf = list_head(&rsc->sc_txq[i].tx_free_list);
1341 }
1342 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
1343 while (txbf != NULL) {
1344 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf);
1345 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
1346 }
1347 txbf = rsc->sc_txq[i].txbuf_h;
1348 baddr_desc = ptx[i];
1349 taddr_desc = baddr_desc + sizeof (struct rtw_txdesc);
1350 for (j = 0; j < rtw_qlen[i]; j++) {
1351 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf);
1352 if (j == (rtw_qlen[i] - 1)) {
1353 is_last = 1;
1354 } else {
1355 is_last = 0;
1356 }
1357
1358 if (is_last) {
1359 txbf->txdesc->td_next = baddr_desc;
1360 } else {
1361 txbf->txdesc->td_next = taddr_desc;
1362 }
1363 txbf->next_bf_daddr = txbf->txdesc->td_next;
1364 RTW_DMA_SYNC(txbf->bf_dma, DDI_DMA_SYNC_FORDEV);
1365 txbf->order = j;
1366 txbf++;
1367 taddr_desc += sizeof (struct rtw_txdesc);
1368 }
1369 }
1370 if (!flag)
1371 return;
1372
1373 /* sync rx desc and rx buf */
1374 rsc->rx_next = 0;
1375 rxbf = rsc->rxbuf_h;
1376 for (j = 0; j < RTW_RXQLEN; j++) {
1377 RTW_DMA_SYNC(rxbf->bf_dma, DDI_DMA_SYNC_FORCPU);
1378 if (j == (RTW_RXQLEN - 1))
1379 is_last = 1;
1380 else
1381 is_last = 0;
1382 rtw_rxdesc_init(rsc, rxbf, j, is_last);
1383 rxbf++;
1384 }
1385 }
1386
1387 static void
1388 rtw_resume_ticks(rtw_softc_t *rsc)
1389 {
1390 RTW_WRITE(&rsc->sc_regs, RTW_TINT, 0xffffffff);
1391 }
1392
1393 const char *
1394 rtw_pwrstate_string(enum rtw_pwrstate power)
1395 {
1396 switch (power) {
1397 case RTW_ON:
1398 return ("on");
1399 case RTW_SLEEP:
1400 return ("sleep");
1401 case RTW_OFF:
1402 return ("off");
1403 default:
1404 return ("unknown");
1405 }
1406 }
1407
1408 /*
1409 * XXX For Maxim, I am using the RFMD settings gleaned from the
1410 * reference driver, plus a magic Maxim "ON" value that comes from
1411 * the Realtek document "Windows PG for Rtl8180."
1412 */
1413 /*ARGSUSED*/
1414 static void
1415 rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
1416 int before_rf, int digphy)
1417 {
1418 uint32_t anaparm;
1419
1420 anaparm = RTW_READ(regs, RTW_ANAPARM);
1421 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
1422
1423 switch (power) {
1424 case RTW_OFF:
1425 if (before_rf)
1426 return;
1427 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF;
1428 anaparm |= RTW_ANAPARM_TXDACOFF;
1429 break;
1430 case RTW_SLEEP:
1431 if (!before_rf)
1432 return;
1433 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP;
1434 anaparm |= RTW_ANAPARM_TXDACOFF;
1435 break;
1436 case RTW_ON:
1437 if (!before_rf)
1438 return;
1439 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON;
1440 break;
1441 }
1442 RTW_DPRINTF(RTW_DEBUG_PWR,
1443 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
1444 __func__, rtw_pwrstate_string(power),
1445 (before_rf) ? "before" : "after", anaparm);
1446
1447 RTW_WRITE(regs, RTW_ANAPARM, anaparm);
1448 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
1449 }
1450
1451 /*
1452 * XXX I am using the RFMD settings gleaned from the reference
1453 * driver. They agree
1454 */
1455 /*ARGSUSED*/
1456 static void
1457 rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
1458 int before_rf, int digphy)
1459 {
1460 uint32_t anaparm;
1461
1462 anaparm = RTW_READ(regs, RTW_ANAPARM);
1463 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
1464
1465 switch (power) {
1466 case RTW_OFF:
1467 if (before_rf)
1468 return;
1469 anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF;
1470 anaparm |= RTW_ANAPARM_TXDACOFF;
1471 break;
1472 case RTW_SLEEP:
1473 if (!before_rf)
1474 return;
1475 anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP;
1476 anaparm |= RTW_ANAPARM_TXDACOFF;
1477 break;
1478 case RTW_ON:
1479 if (!before_rf)
1480 return;
1481 anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON;
1482 break;
1483 }
1484 RTW_DPRINTF(RTW_DEBUG_PWR,
1485 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
1486 __func__, rtw_pwrstate_string(power),
1487 (before_rf) ? "before" : "after", anaparm);
1488
1489 RTW_WRITE(regs, RTW_ANAPARM, anaparm);
1490 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
1491 }
1492
1493 static void
1494 rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
1495 int before_rf, int digphy)
1496 {
1497 uint32_t anaparm;
1498
1499 anaparm = RTW_READ(regs, RTW_ANAPARM);
1500 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
1501
1502 switch (power) {
1503 case RTW_OFF:
1504 if (before_rf)
1505 return;
1506 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF;
1507 anaparm |= RTW_ANAPARM_TXDACOFF;
1508 break;
1509 case RTW_SLEEP:
1510 if (!before_rf)
1511 return;
1512 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP;
1513 anaparm |= RTW_ANAPARM_TXDACOFF;
1514 break;
1515 case RTW_ON:
1516 if (!before_rf)
1517 return;
1518 if (digphy) {
1519 anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON;
1520 /* XXX guess */
1521 anaparm |= RTW_ANAPARM_TXDACOFF;
1522 } else
1523 anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON;
1524 break;
1525 }
1526 RTW_DPRINTF(RTW_DEBUG_PWR,
1527 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
1528 __func__, rtw_pwrstate_string(power),
1529 (before_rf) ? "before" : "after", anaparm);
1530
1531 RTW_WRITE(regs, RTW_ANAPARM, anaparm);
1532 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
1533 }
1534
1535 static void
1536 rtw_pwrstate0(rtw_softc_t *rsc, enum rtw_pwrstate power, int before_rf,
1537 int digphy)
1538 {
1539 struct rtw_regs *regs = &rsc->sc_regs;
1540
1541 rtw_set_access(regs, RTW_ACCESS_ANAPARM);
1542
1543 (*rsc->sc_pwrstate_cb)(regs, power, before_rf, digphy);
1544
1545 rtw_set_access(regs, RTW_ACCESS_NONE);
1546 }
1547
1548 static void
1549 rtw_rf_destroy(struct rtw_rf *rf)
1550 {
1551 (*rf->rf_destroy)(rf);
1552 }
1553
1554 static int
1555 rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
1556 {
1557 return (*rf->rf_pwrstate)(rf, power);
1558 }
1559
1560 static int
1561 rtw_pwrstate(rtw_softc_t *rsc, enum rtw_pwrstate power)
1562 {
1563 int rc;
1564
1565 RTW_DPRINTF(RTW_DEBUG_PWR,
1566 "%s: %s->%s\n", __func__,
1567 rtw_pwrstate_string(rsc->sc_pwrstate), rtw_pwrstate_string(power));
1568
1569 if (rsc->sc_pwrstate == power)
1570 return (0);
1571
1572 rtw_pwrstate0(rsc, power, 1, rsc->sc_flags & RTW_F_DIGPHY);
1573 rc = rtw_rf_pwrstate(rsc->sc_rf, power);
1574 rtw_pwrstate0(rsc, power, 0, rsc->sc_flags & RTW_F_DIGPHY);
1575
1576 switch (power) {
1577 case RTW_ON:
1578 /* TBD set LEDs */
1579 break;
1580 case RTW_SLEEP:
1581 /* TBD */
1582 break;
1583 case RTW_OFF:
1584 /* TBD */
1585 break;
1586 }
1587 if (rc == 0)
1588 rsc->sc_pwrstate = power;
1589 else
1590 rsc->sc_pwrstate = RTW_OFF;
1591 return (rc);
1592 }
1593
1594 void
1595 rtw_disable(rtw_softc_t *rsc)
1596 {
1597 int rc;
1598
1599 if ((rsc->sc_flags & RTW_F_ENABLED) == 0)
1600 return;
1601
1602 /* turn off PHY */
1603 if ((rsc->sc_flags & RTW_F_INVALID) == 0 &&
1604 (rc = rtw_pwrstate(rsc, RTW_OFF)) != 0) {
1605 cmn_err(CE_WARN, "failed to turn off PHY (%d)\n", rc);
1606 }
1607
1608 if (rsc->sc_disable != NULL)
1609 (*rsc->sc_disable)(rsc);
1610
1611 rsc->sc_flags &= ~RTW_F_ENABLED;
1612 }
1613
1614 int
1615 rtw_enable(rtw_softc_t *rsc)
1616 {
1617 if ((rsc->sc_flags & RTW_F_ENABLED) == 0) {
1618 if (rsc->sc_enable != NULL && (*rsc->sc_enable)(rsc) != 0) {
1619 cmn_err(CE_WARN, "device enable failed\n");
1620 return (EIO);
1621 }
1622 rsc->sc_flags |= RTW_F_ENABLED;
1623 if (rtw_pwrstate(rsc, RTW_ON) != 0)
1624 cmn_err(CE_WARN, "PHY turn on failed\n");
1625 }
1626 return (0);
1627 }
1628
1629 static void
1630 rtw_set_nettype(rtw_softc_t *rsc, enum ieee80211_opmode opmode)
1631 {
1632 uint8_t msr;
1633
1634 /* I'm guessing that MSR is protected as CONFIG[0123] are. */
1635 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_CONFIG);
1636
1637 msr = RTW_READ8(&rsc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
1638
1639 switch (opmode) {
1640 case IEEE80211_M_AHDEMO:
1641 case IEEE80211_M_IBSS:
1642 msr |= RTW_MSR_NETYPE_ADHOC_OK;
1643 break;
1644 case IEEE80211_M_HOSTAP:
1645 msr |= RTW_MSR_NETYPE_AP_OK;
1646 break;
1647 case IEEE80211_M_STA:
1648 msr |= RTW_MSR_NETYPE_INFRA_OK;
1649 break;
1650 }
1651 RTW_WRITE8(&rsc->sc_regs, RTW_MSR, msr);
1652
1653 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_NONE);
1654 }
1655
1656 static void
1657 rtw_pktfilt_load(rtw_softc_t *rsc)
1658 {
1659 struct rtw_regs *regs = &rsc->sc_regs;
1660 struct ieee80211com *ic = &rsc->sc_ic;
1661
1662 /* XXX might be necessary to stop Rx/Tx engines while setting filters */
1663 rsc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
1664 rsc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK);
1665
1666 rsc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
1667 /* MAC auto-reset PHY (huh?) */
1668 rsc->sc_rcr |= RTW_RCR_ENMARP;
1669 /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
1670 rsc->sc_rcr |= RTW_RCR_RXFTH_WHOLE |RTW_RCR_MXDMA_1024;
1671
1672 switch (ic->ic_opmode) {
1673 case IEEE80211_M_AHDEMO:
1674 case IEEE80211_M_IBSS:
1675 /* receive broadcasts in our BSS */
1676 rsc->sc_rcr |= RTW_RCR_ADD3;
1677 break;
1678 default:
1679 break;
1680 }
1681 #if 0
1682 /* XXX accept all broadcast if scanning */
1683 rsc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
1684 #endif
1685 RTW_WRITE(regs, RTW_MAR0, 0xffffffff);
1686 RTW_WRITE(regs, RTW_MAR1, 0xffffffff);
1687 rsc->sc_rcr |= RTW_RCR_AM;
1688 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
1689 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
1690
1691 RTW_DPRINTF(RTW_DEBUG_PKTFILT,
1692 "RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
1693 RTW_READ(regs, RTW_MAR0),
1694 RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR));
1695 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
1696 }
1697
1698 static void
1699 rtw_transmit_config(struct rtw_regs *regs)
1700 {
1701 uint32_t tcr;
1702
1703 tcr = RTW_READ(regs, RTW_TCR);
1704
1705 tcr |= RTW_TCR_CWMIN;
1706 tcr &= ~RTW_TCR_MXDMA_MASK;
1707 tcr |= RTW_TCR_MXDMA_1024;
1708 tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */
1709 tcr &= ~RTW_TCR_LBK_MASK;
1710 tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */
1711
1712 /* set short/long retry limits */
1713 tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK);
1714 tcr |= LSHIFT(0x4, RTW_TCR_SRL_MASK) | LSHIFT(0x4, RTW_TCR_LRL_MASK);
1715
1716 tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */
1717 RTW_WRITE(regs, RTW_TCR, tcr);
1718 RTW_SYNC(regs, RTW_TCR, RTW_TCR);
1719 }
1720
1721 int
1722 rtw_refine_setting(rtw_softc_t *rsc)
1723 {
1724 struct rtw_regs *regs;
1725 int rc = 0;
1726
1727 regs = &rsc->sc_regs;
1728 rc = rtw_reset(rsc);
1729 if (rc != 0)
1730 return (-1);
1731
1732 rtw_beacon_tx_disable(regs);
1733 rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 1);
1734 rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG);
1735
1736 rtw_transmit_config(regs);
1737 rtw_pktfilt_load(rsc);
1738 rtw_set_access(regs, RTW_ACCESS_CONFIG);
1739 RTW_WRITE(regs, RTW_TINT, 0xffffffff);
1740 RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */
1741 RTW_WRITE16(regs, RTW_BRSR, 0);
1742
1743 rtw_set_access(regs, RTW_ACCESS_ANAPARM);
1744 rtw_set_access(regs, RTW_ACCESS_NONE);
1745 RTW_WRITE(regs, RTW_FEMR, 0xffff);
1746 RTW_SYNC(regs, RTW_FEMR, RTW_FEMR);
1747 rtw_set_rfprog(regs, rsc->sc_rfchipid, "rtw");
1748
1749 RTW_WRITE8(regs, RTW_PHYDELAY, rsc->sc_phydelay);
1750 RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC);
1751 rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL);
1752 return (0);
1753 }
1754
1755 static int
1756 rtw_tune(rtw_softc_t *rsc)
1757 {
1758 struct ieee80211com *ic = &rsc->sc_ic;
1759 uint32_t chan;
1760 int rc;
1761 int antdiv = rsc->sc_flags & RTW_F_ANTDIV,
1762 dflantb = rsc->sc_flags & RTW_F_DFLANTB;
1763
1764 ASSERT(ic->ic_curchan != NULL);
1765
1766 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
1767 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw: chan no = %x", chan);
1768
1769 if (chan == IEEE80211_CHAN_ANY) {
1770 cmn_err(CE_WARN, "%s: chan == IEEE80211_CHAN_ANY\n", __func__);
1771 return (-1);
1772 }
1773
1774 if (chan == rsc->sc_cur_chan) {
1775 RTW_DPRINTF(RTW_DEBUG_TUNE,
1776 "%s: already tuned chan %d\n", __func__, chan);
1777 return (0);
1778 }
1779 rtw_idle(&rsc->sc_regs);
1780 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
1781 ASSERT((rsc->sc_flags & RTW_F_ENABLED) != 0);
1782
1783 if ((rc = rtw_phy_init(&rsc->sc_regs, rsc->sc_rf,
1784 rtw_chan2txpower(&rsc->sc_srom, ic, ic->ic_curchan),
1785 rsc->sc_csthr, ic->ic_curchan->ich_freq, antdiv,
1786 dflantb, RTW_ON)) != 0) {
1787 /* XXX condition on powersaving */
1788 cmn_err(CE_NOTE, "phy init failed\n");
1789 }
1790 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1);
1791 rtw_resume_ticks(rsc);
1792 rsc->sc_cur_chan = chan;
1793 return (rc);
1794 }
1795
1796 static int
1797 rtw_init(rtw_softc_t *rsc)
1798 {
1799 struct ieee80211com *ic = &rsc->sc_ic;
1800 int rc = 0;
1801
1802 rtw_stop(rsc);
1803 mutex_enter(&rsc->sc_genlock);
1804 if ((rc = rtw_enable(rsc)) != 0)
1805 goto out;
1806 rc = rtw_refine_setting(rsc);
1807 if (rc != 0) {
1808 mutex_exit(&rsc->sc_genlock);
1809 return (rc);
1810 }
1811 rtw_swring_setup(rsc, 1);
1812 rtw_hwring_setup(rsc);
1813 RTW_WRITE16(&rsc->sc_regs, RTW_BSSID16, 0x0);
1814 RTW_WRITE(&rsc->sc_regs, RTW_BSSID32, 0x0);
1815 rtw_enable_interrupts(rsc);
1816
1817 ic->ic_ibss_chan = &ic->ic_sup_channels[1];
1818 ic->ic_curchan = ic->ic_ibss_chan;
1819 RTW_DPRINTF(RTW_DEBUG_TUNE, "%s: channel %d freq %d flags 0x%04x\n",
1820 __func__, ieee80211_chan2ieee(ic, ic->ic_curchan),
1821 ic->ic_curchan->ich_freq, ic->ic_curchan->ich_flags);
1822 rsc->sc_invalid = 0;
1823 out:
1824 mutex_exit(&rsc->sc_genlock);
1825 return (rc);
1826 }
1827
1828 static struct rtw_rf *
1829 rtw_rf_attach(rtw_softc_t *rsc, enum rtw_rfchipid rfchipid, int digphy)
1830 {
1831 rtw_rf_write_t rf_write;
1832 struct rtw_rf *rf;
1833 int rtw_host_rfio;
1834
1835 switch (rfchipid) {
1836 default:
1837 rf_write = rtw_rf_hostwrite;
1838 break;
1839 case RTW_RFCHIPID_INTERSIL:
1840 case RTW_RFCHIPID_PHILIPS:
1841 case RTW_RFCHIPID_GCT: /* XXX a guess */
1842 case RTW_RFCHIPID_RFMD:
1843 rtw_host_rfio = 1;
1844 rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite;
1845 break;
1846 }
1847
1848 switch (rfchipid) {
1849 case RTW_RFCHIPID_MAXIM:
1850 rf = rtw_max2820_create(&rsc->sc_regs, rf_write, 0);
1851 rsc->sc_pwrstate_cb = rtw_maxim_pwrstate;
1852 break;
1853 case RTW_RFCHIPID_PHILIPS:
1854 rf = rtw_sa2400_create(&rsc->sc_regs, rf_write, digphy);
1855 rsc->sc_pwrstate_cb = rtw_philips_pwrstate;
1856 break;
1857 case RTW_RFCHIPID_RFMD:
1858 /* XXX RFMD has no RF constructor */
1859 rsc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
1860 /*FALLTHROUGH*/
1861 default:
1862 return (NULL);
1863 }
1864 if (rf != NULL) {
1865 rf->rf_continuous_tx_cb =
1866 (rtw_continuous_tx_cb_t)rtw_continuous_tx_enable;
1867 rf->rf_continuous_tx_arg = (void *)rsc;
1868 }
1869 return (rf);
1870 }
1871
1872 /*
1873 * Revision C and later use a different PHY delay setting than
1874 * revisions A and B.
1875 */
1876 static uint8_t
1877 rtw_check_phydelay(struct rtw_regs *regs, uint32_t rcr0)
1878 {
1879 #define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
1880 #define REVC (REVAB | RTW_RCR_RXFTH_WHOLE)
1881
1882 uint8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
1883
1884 RTW_WRITE(regs, RTW_RCR, REVAB);
1885 RTW_WBW(regs, RTW_RCR, RTW_RCR);
1886 RTW_WRITE(regs, RTW_RCR, REVC);
1887
1888 RTW_WBR(regs, RTW_RCR, RTW_RCR);
1889 if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC)
1890 phydelay |= RTW_PHYDELAY_REVC_MAGIC;
1891
1892 RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */
1893 RTW_SYNC(regs, RTW_RCR, RTW_RCR);
1894
1895 return (phydelay);
1896 #undef REVC
1897 }
1898
1899 static void rtw_intr_rx(rtw_softc_t *rsc);
1900 static void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri);
1901
1902 static int
1903 rtw_get_rate(struct ieee80211com *ic)
1904 {
1905 uint8_t (*rates)[IEEE80211_RATE_MAXSIZE];
1906 int rate;
1907
1908 rates = &ic->ic_bss->in_rates.ir_rates;
1909
1910 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
1911 rate = ic->ic_fixed_rate;
1912 else if (ic->ic_state == IEEE80211_S_RUN)
1913 rate = (*rates)[ic->ic_bss->in_txrate];
1914 else
1915 rate = 0;
1916 return (rate & IEEE80211_RATE_VAL);
1917 }
1918
1919 /*
1920 * Arguments in:
1921 *
1922 * paylen: payload length (no FCS, no WEP header)
1923 *
1924 * hdrlen: header length
1925 *
1926 * rate: MSDU speed, units 500kb/s
1927 *
1928 * flags: IEEE80211_F_SHPREAMBLE (use short preamble),
1929 * IEEE80211_F_SHSLOT (use short slot length)
1930 *
1931 * Arguments out:
1932 *
1933 * d: 802.11 Duration field for RTS,
1934 * 802.11 Duration field for data frame,
1935 * PLCP Length for data frame,
1936 * residual octets at end of data slot
1937 */
1938 static int
1939 rtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
1940 struct rtw_ieee80211_duration *d)
1941 {
1942 int pre, ctsrate;
1943 uint16_t ack, bitlen, data_dur, remainder;
1944
1945 /*
1946 * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
1947 * DATA reserves medium for SIFS | ACK
1948 *
1949 * XXXMYC: no ACK on multicast/broadcast or control packets
1950 */
1951
1952 bitlen = len * 8;
1953
1954 pre = IEEE80211_DUR_DS_SIFS;
1955 if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
1956 pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
1957 IEEE80211_DUR_DS_FAST_PLCPHDR;
1958 else
1959 pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
1960 IEEE80211_DUR_DS_SLOW_PLCPHDR;
1961
1962 d->d_residue = 0;
1963 data_dur = (bitlen * 2) / rate;
1964 remainder = (bitlen * 2) % rate;
1965 if (remainder != 0) {
1966 if (rate == 22)
1967 d->d_residue = (rate - remainder) / 16;
1968 data_dur++;
1969 }
1970
1971 switch (rate) {
1972 case 2: /* 1 Mb/s */
1973 case 4: /* 2 Mb/s */
1974 /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
1975 ctsrate = 2;
1976 break;
1977 case 11: /* 5.5 Mb/s */
1978 case 22: /* 11 Mb/s */
1979 case 44: /* 22 Mb/s */
1980 /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
1981 ctsrate = 4;
1982 break;
1983 default:
1984 /* TBD */
1985 return (-1);
1986 }
1987
1988 d->d_plcp_len = data_dur;
1989
1990 ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
1991
1992 d->d_rts_dur =
1993 pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
1994 pre + data_dur +
1995 ack;
1996
1997 d->d_data_dur = ack;
1998
1999 return (0);
2000 }
2001
2002 /*
2003 * Arguments in:
2004 *
2005 * wh: 802.11 header
2006 *
2007 * paylen: payload length (no FCS, no WEP header)
2008 *
2009 * rate: MSDU speed, units 500kb/s
2010 *
2011 * fraglen: fragment length, set to maximum (or higher) for no
2012 * fragmentation
2013 *
2014 * flags: IEEE80211_F_PRIVACY (hardware adds WEP),
2015 * IEEE80211_F_SHPREAMBLE (use short preamble),
2016 * IEEE80211_F_SHSLOT (use short slot length)
2017 *
2018 * Arguments out:
2019 *
2020 * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
2021 * of first/only fragment
2022 *
2023 * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
2024 * of first/only fragment
2025 */
2026 static int
2027 rtw_compute_duration(struct ieee80211_frame *wh, int len,
2028 uint32_t flags, int fraglen, int rate, struct rtw_ieee80211_duration *d0,
2029 struct rtw_ieee80211_duration *dn, int *npktp)
2030 {
2031 int ack, rc;
2032 int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
2033
2034 /* don't think about addr4 here */
2035 hdrlen = sizeof (struct ieee80211_frame);
2036
2037 paylen = len - hdrlen;
2038
2039 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) {
2040 overlen = 8 + IEEE80211_CRC_LEN;
2041 paylen -= 8;
2042 } else
2043 overlen = IEEE80211_CRC_LEN;
2044
2045 npkt = paylen / fraglen;
2046 lastlen0 = paylen % fraglen;
2047
2048 if (npkt == 0) /* no fragments */
2049 lastlen = paylen + overlen;
2050 else if (lastlen0 != 0) { /* a short "tail" fragment */
2051 lastlen = lastlen0 + overlen;
2052 npkt++;
2053 } else /* full-length "tail" fragment */
2054 lastlen = fraglen + overlen;
2055
2056 if (npktp != NULL)
2057 *npktp = npkt;
2058
2059 if (npkt > 1)
2060 firstlen = fraglen + overlen;
2061 else
2062 firstlen = paylen + overlen;
2063
2064 ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
2065 (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) !=
2066 IEEE80211_FC0_TYPE_CTL;
2067
2068 rc = rtw_compute_duration1(firstlen + hdrlen,
2069 ack, flags, rate, d0);
2070 if (rc == -1)
2071 return (rc);
2072
2073 if (npkt <= 1) {
2074 *dn = *d0;
2075 return (0);
2076 }
2077 return (rtw_compute_duration1(lastlen + hdrlen, ack, flags,
2078 rate, dn));
2079 }
2080
2081 static int
2082 rtw_assembly_80211(rtw_softc_t *rsc, struct rtw_txbuf *bf,
2083 mblk_t *mp)
2084 {
2085 ieee80211com_t *ic;
2086 struct rtw_txdesc *ds;
2087 struct ieee80211_frame *wh;
2088 uint8_t *buf;
2089 uint32_t ctl0 = 0, ctl1 = 0;
2090 int npkt, rate;
2091 struct rtw_ieee80211_duration d0, dn;
2092 int32_t iswep, pktlen, mblen;
2093 mblk_t *mp0;
2094
2095 ic = &rsc->sc_ic;
2096 ds = bf->txdesc;
2097 buf = (uint8_t *)bf->bf_dma.mem_va;
2098 bzero(buf, bf->bf_dma.alength);
2099 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc));
2100 wh = (struct ieee80211_frame *)mp->b_rptr;
2101 iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
2102
2103 /* ieee80211_crypto_encap() needs a single mblk */
2104 mp0 = allocb(bf->bf_dma.alength, BPRI_MED);
2105 if (mp0 == NULL) {
2106 cmn_err(CE_WARN, "%s: allocb(mp) error", __func__);
2107 return (-1);
2108 }
2109 for (; mp != NULL; mp = mp->b_cont) {
2110 mblen = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
2111 bcopy(mp->b_rptr, mp0->b_wptr, mblen);
2112 mp0->b_wptr += mblen;
2113 }
2114
2115 if (iswep) {
2116 struct ieee80211_key *k;
2117
2118 k = ieee80211_crypto_encap(ic, mp0);
2119 if (k == NULL) {
2120 cmn_err(CE_WARN, "%s: ieee80211_crypto_encap() error",
2121 __func__);
2122 freemsg(mp0);
2123 return (-1);
2124 }
2125 }
2126 pktlen = msgdsize(mp0);
2127
2128 #if 0
2129 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------begin--------");
2130 ieee80211_dump_pkt((uint8_t *)(mp0->b_rptr), pktlen, 0, 0);
2131 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------end--------");
2132 #endif
2133 /* RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); */
2134 if (pktlen > bf->bf_dma.alength) {
2135 cmn_err(CE_WARN, "%s: overlength packet pktlen = %d\n",
2136 __func__, pktlen);
2137 freemsg(mp0);
2138 return (-1);
2139 }
2140 bcopy(mp0->b_rptr, buf, pktlen);
2141 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
2142
2143 /* setup descriptor */
2144 ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;
2145
2146 if (((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0) &&
2147 (ic->ic_bss->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
2148 ctl0 |= RTW_TXCTL0_SPLCP;
2149 }
2150 /* XXX do real rate control */
2151 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2152 IEEE80211_FC0_TYPE_MGT)
2153 rate = 2;
2154 else {
2155 rate = MAX(2, rtw_get_rate(ic));
2156 }
2157 ctl0 = ctl0 |
2158 LSHIFT(pktlen, RTW_TXCTL0_TPKTSIZE_MASK);
2159
2160 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: rate = %d", __func__, rate);
2161
2162 switch (rate) {
2163 default:
2164 case 2:
2165 ctl0 |= RTW_TXCTL0_RATE_1MBPS;
2166 break;
2167 case 4:
2168 ctl0 |= RTW_TXCTL0_RATE_2MBPS;
2169 break;
2170 case 11:
2171 ctl0 |= RTW_TXCTL0_RATE_5MBPS;
2172 break;
2173 case 22:
2174 ctl0 |= RTW_TXCTL0_RATE_11MBPS;
2175 break;
2176 }
2177
2178 /* XXX >= ? Compare after fragmentation? */
2179 if (pktlen > ic->ic_rtsthreshold) {
2180 ctl0 |= RTW_TXCTL0_RTSEN;
2181 cmn_err(CE_NOTE, "%s: fragmentation: pktlen = %d",
2182 __func__, pktlen);
2183 }
2184
2185 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2186 IEEE80211_FC0_TYPE_MGT) {
2187 ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN);
2188 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2189 IEEE80211_FC0_SUBTYPE_BEACON)
2190 ctl0 |= RTW_TXCTL0_BEACON;
2191 }
2192
2193 if (rtw_compute_duration(wh, pktlen,
2194 ic->ic_flags, ic->ic_fragthreshold,
2195 rate, &d0, &dn, &npkt) == -1) {
2196 RTW_DPRINTF(RTW_DEBUG_XMIT,
2197 "%s: fail compute duration\n", __func__);
2198 freemsg(mp0);
2199 return (-1);
2200 }
2201 *(uint16_t *)(uintptr_t)wh->i_dur = (d0.d_data_dur);
2202
2203 ctl1 = LSHIFT(d0.d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |
2204 LSHIFT(d0.d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);
2205
2206 if (d0.d_residue)
2207 ctl1 |= RTW_TXCTL1_LENGEXT;
2208
2209 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: duration=%x, ctl1=%x", __func__,
2210 *(uint16_t *)(uintptr_t)wh->i_dur, ctl1);
2211
2212 if (bf->bf_dma.alength > RTW_TXLEN_LENGTH_MASK) {
2213 RTW_DPRINTF(RTW_DEBUG_XMIT,
2214 "%s: seg too long\n", __func__);
2215 freemsg(mp0);
2216 return (-1);
2217 }
2218 ds->td_ctl0 = ctl0;
2219 ds->td_ctl0 |= RTW_TXCTL0_OWN | RTW_TXCTL0_LS | RTW_TXCTL0_FS;
2220 ds->td_ctl1 = ctl1;
2221 ds->td_buf = bf->bf_dma.cookie.dmac_address;
2222 ds->td_len = pktlen & 0xfff;
2223 ds->td_next = bf->next_bf_daddr;
2224
2225 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
2226 RTW_DESC_OFFSET(hd_txmd, bf->order),
2227 sizeof (struct rtw_txdesc),
2228 DDI_DMA_SYNC_FORDEV);
2229
2230 RTW_DPRINTF(RTW_DEBUG_XMIT,
2231 "descriptor: order = %d, phy_addr=%x, ctl0=%x,"
2232 " ctl1=%x, buf=%x, len=%x, next=%x", bf->order,
2233 bf->bf_daddr, ds->td_ctl0, ds->td_ctl1,
2234 ds->td_buf, ds->td_len, ds->td_next);
2235 rsc->sc_pktxmt64++;
2236 rsc->sc_bytexmt64 += pktlen;
2237
2238 freemsg(mp0);
2239 return (0);
2240 }
2241
2242 static int
2243 rtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
2244 {
2245 rtw_softc_t *rsc = (rtw_softc_t *)ic;
2246 struct ieee80211_node *in = ic->ic_bss;
2247 struct rtw_txbuf *bf = NULL;
2248 int ret, i = RTW_TXPRIMD;
2249
2250 mutex_enter(&rsc->sc_txlock);
2251 mutex_enter(&rsc->sc_txq[i].txbuf_lock);
2252 bf = list_head(&rsc->sc_txq[i].tx_free_list);
2253
2254 if ((bf == NULL) || (rsc->sc_txq[i].tx_nfree <= 4)) {
2255 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: no tx buf\n", __func__);
2256 rsc->sc_noxmtbuf++;
2257 if ((type & IEEE80211_FC0_TYPE_MASK) ==
2258 IEEE80211_FC0_TYPE_DATA) {
2259 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: need reschedule\n",
2260 __func__);
2261 rsc->sc_need_reschedule = 1;
2262 } else {
2263 freemsg(mp);
2264 }
2265 mutex_exit(&rsc->sc_txq[i].txbuf_lock);
2266 mutex_exit(&rsc->sc_txlock);
2267 return (1);
2268 }
2269 list_remove(&rsc->sc_txq[i].tx_free_list, bf);
2270 rsc->sc_txq[i].tx_nfree--;
2271
2272 /* assemble 802.11 frame here */
2273 ret = rtw_assembly_80211(rsc, bf, mp);
2274 if (ret != 0) {
2275 cmn_err(CE_WARN, "%s assembly frame error\n", __func__);
2276 mutex_exit(&rsc->sc_txq[i].txbuf_lock);
2277 mutex_exit(&rsc->sc_txlock);
2278 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2279 IEEE80211_FC0_TYPE_DATA) {
2280 freemsg(mp);
2281 }
2282 return (1);
2283 }
2284 list_insert_tail(&rsc->sc_txq[i].tx_dirty_list, bf);
2285 bf->bf_in = in;
2286 rtw_dma_start(&rsc->sc_regs, i);
2287
2288 mutex_exit(&rsc->sc_txq[i].txbuf_lock);
2289 mutex_exit(&rsc->sc_txlock);
2290
2291 freemsg(mp);
2292 return (0);
2293 }
2294
2295 static mblk_t *
2296 rtw_m_tx(void *arg, mblk_t *mp)
2297 {
2298 rtw_softc_t *rsc = arg;
2299 ieee80211com_t *ic = (ieee80211com_t *)rsc;
2300 mblk_t *next;
2301
2302 if (ic->ic_state != IEEE80211_S_RUN) {
2303 freemsgchain(mp);
2304 return (NULL);
2305 }
2306
2307 while (mp != NULL) {
2308 next = mp->b_next;
2309 mp->b_next = NULL;
2310
2311 if (rtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA)) {
2312 mp->b_next = next;
2313 break;
2314 }
2315 mp = next;
2316 }
2317
2318 return (mp);
2319
2320 }
2321
2322 static void
2323 rtw_next_scan(void *arg)
2324 {
2325 ieee80211com_t *ic = arg;
2326 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2327
2328 rsc->sc_scan_id = 0;
2329 if (ic->ic_state == IEEE80211_S_SCAN) {
2330 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw_next_scan\n");
2331 (void) ieee80211_next_scan(ic);
2332 }
2333
2334 }
2335
2336 static void
2337 rtw_join_bss(rtw_softc_t *rsc, uint8_t *bssid, uint16_t intval0)
2338 {
2339 uint16_t bcnitv, intval;
2340 int i;
2341 struct rtw_regs *regs = &rsc->sc_regs;
2342
2343 for (i = 0; i < IEEE80211_ADDR_LEN; i++)
2344 RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]);
2345
2346 RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32);
2347 rtw_set_access(regs, RTW_ACCESS_CONFIG);
2348
2349 RTW_WRITE8(regs, RTW_MSR, 0x8); /* sta mode link ok */
2350 intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK));
2351
2352 bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
2353 bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK);
2354 RTW_WRITE16(regs, RTW_BCNITV, bcnitv);
2355 RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
2356 RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
2357
2358 rtw_set_access(regs, RTW_ACCESS_NONE);
2359
2360 /* TBD WEP */
2361 /* RTW_WRITE8(regs, RTW_SCR, 0); */
2362
2363 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1);
2364 }
2365
2366 /*
2367 * Set the starting transmit rate for a node.
2368 */
2369 static void
2370 rtw_rate_ctl_start(rtw_softc_t *rsc, struct ieee80211_node *in)
2371 {
2372 ieee80211com_t *ic = (ieee80211com_t *)rsc;
2373 int32_t srate;
2374
2375 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
2376 /*
2377 * No fixed rate is requested. For 11b start with
2378 * the highest negotiated rate; otherwise, for 11g
2379 * and 11a, we start "in the middle" at 24Mb or 36Mb.
2380 */
2381 srate = in->in_rates.ir_nrates - 1;
2382 if (ic->ic_curmode != IEEE80211_MODE_11B) {
2383 /*
2384 * Scan the negotiated rate set to find the
2385 * closest rate.
2386 */
2387 /* NB: the rate set is assumed sorted */
2388 for (; srate >= 0 && IEEE80211_RATE(srate) > 72;
2389 srate--)
2390 ;
2391 }
2392 } else {
2393 /*
2394 * A fixed rate is to be used; We know the rate is
2395 * there because the rate set is checked when the
2396 * station associates.
2397 */
2398 /* NB: the rate set is assumed sorted */
2399 srate = in->in_rates.ir_nrates - 1;
2400 for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
2401 srate--)
2402 ;
2403 }
2404 in->in_txrate = srate;
2405 }
2406
2407
2408 /*
2409 * Reset the rate control state for each 802.11 state transition.
2410 */
2411 static void
2412 rtw_rate_ctl_reset(rtw_softc_t *rsc, enum ieee80211_state state)
2413 {
2414 ieee80211com_t *ic = &rsc->sc_ic;
2415 ieee80211_node_t *in;
2416
2417 if (ic->ic_opmode == IEEE80211_M_STA) {
2418 /*
2419 * Reset local xmit state; this is really only
2420 * meaningful when operating in station mode.
2421 */
2422 in = (struct ieee80211_node *)ic->ic_bss;
2423
2424 if (state == IEEE80211_S_RUN) {
2425 rtw_rate_ctl_start(rsc, in);
2426 } else {
2427 in->in_txrate = 0;
2428 }
2429 }
2430 }
2431
2432 /*
2433 * Examine and potentially adjust the transmit rate.
2434 */
2435 static void
2436 rtw_rate_ctl(void *arg)
2437 {
2438 ieee80211com_t *ic = (ieee80211com_t *)arg;
2439 rtw_softc_t *rsc = (rtw_softc_t *)ic;
2440 struct ieee80211_node *in = ic->ic_bss;
2441 struct ieee80211_rateset *rs = &in->in_rates;
2442 int32_t mod = 1, nrate, enough;
2443
2444 mutex_enter(&rsc->sc_genlock);
2445 enough = (rsc->sc_tx_ok + rsc->sc_tx_err) >= 600? 1 : 0;
2446
2447 /* err ratio is high -> down */
2448 if (enough && rsc->sc_tx_ok < rsc->sc_tx_err)
2449 mod = -1;
2450
2451 nrate = in->in_txrate;
2452 switch (mod) {
2453 case -1:
2454 if (nrate > 0) {
2455 nrate--;
2456 }
2457 break;
2458 case 1:
2459 if (nrate + 1 < rs->ir_nrates) {
2460 nrate++;
2461 }
2462 break;
2463 }
2464
2465 if (nrate != in->in_txrate)
2466 in->in_txrate = nrate;
2467 rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0;
2468 mutex_exit(&rsc->sc_genlock);
2469 if (ic->ic_state == IEEE80211_S_RUN)
2470 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic,
2471 drv_usectohz(1000000));
2472 }
2473
2474 static int32_t
2475 rtw_new_state(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
2476 {
2477 rtw_softc_t *rsc = (rtw_softc_t *)ic;
2478 int error;
2479 enum ieee80211_state ostate;
2480
2481 ostate = ic->ic_state;
2482
2483 RTW_DPRINTF(RTW_DEBUG_ATTACH,
2484 "rtw_new_state: ostate:0x%x, nstate:0x%x, opmode:0x%x\n",
2485 ostate, nstate, ic->ic_opmode);
2486
2487
2488 mutex_enter(&rsc->sc_genlock);
2489 if (rsc->sc_scan_id != 0) {
2490 (void) untimeout(rsc->sc_scan_id);
2491 rsc->sc_scan_id = 0;
2492 }
2493 if (rsc->sc_ratectl_id != 0) {
2494 (void) untimeout(rsc->sc_ratectl_id);
2495 rsc->sc_ratectl_id = 0;
2496 }
2497 rtw_rate_ctl_reset(rsc, nstate);
2498 if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
2499 (void) rtw_pwrstate(rsc, RTW_ON);
2500 if (nstate != IEEE80211_S_INIT) {
2501 if ((error = rtw_tune(rsc)) != 0) {
2502 mutex_exit(&rsc->sc_genlock);
2503 return (error);
2504 }
2505 }
2506 switch (nstate) {
2507 case IEEE80211_S_INIT:
2508 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_INIT\n");
2509 break;
2510 case IEEE80211_S_SCAN:
2511 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_SCAN\n");
2512 rsc->sc_scan_id = timeout(rtw_next_scan, ic,
2513 drv_usectohz(200000));
2514 rtw_set_nettype(rsc, IEEE80211_M_MONITOR);
2515 break;
2516 case IEEE80211_S_RUN:
2517 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_RUN\n");
2518 switch (ic->ic_opmode) {
2519 case IEEE80211_M_HOSTAP:
2520 case IEEE80211_M_IBSS:
2521 rtw_set_nettype(rsc, IEEE80211_M_MONITOR);
2522 /* TBD */
2523 /*FALLTHROUGH*/
2524 case IEEE80211_M_AHDEMO:
2525 case IEEE80211_M_STA:
2526 RTW_DPRINTF(RTW_DEBUG_ATTACH,
2527 "rtw_new_state: sta\n");
2528 rtw_join_bss(rsc, ic->ic_bss->in_bssid, 0);
2529 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic,
2530 drv_usectohz(1000000));
2531 break;
2532 case IEEE80211_M_MONITOR:
2533 break;
2534 }
2535 rtw_set_nettype(rsc, ic->ic_opmode);
2536 break;
2537 case IEEE80211_S_ASSOC:
2538 case IEEE80211_S_AUTH:
2539 break;
2540 }
2541
2542 mutex_exit(&rsc->sc_genlock);
2543 /*
2544 * Invoke the parent method to complete the work.
2545 */
2546 error = rsc->sc_newstate(ic, nstate, arg);
2547
2548 return (error);
2549 }
2550
2551 static void
2552 rtw_intr_rx(rtw_softc_t *rsc)
2553 {
2554 #define IS_BEACON(__fc0) \
2555 ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
2556 (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
2557 /*
2558 * ratetbl[4] = {2, 4, 11, 22};
2559 */
2560 struct rtw_rxbuf *bf;
2561 struct rtw_rxdesc *ds;
2562 int hwrate, len, rssi;
2563 uint32_t hstat, hrssi, htsftl;
2564 int is_last, next, n = 0, i;
2565 struct ieee80211_frame *wh;
2566 ieee80211com_t *ic = (ieee80211com_t *)rsc;
2567 mblk_t *mp;
2568
2569 RTW_DPRINTF(RTW_DEBUG_RECV, "%s rtw_intr_rx: enter ic_state=%x\n",
2570 __func__, rsc->sc_ic.ic_state);
2571 mutex_enter(&rsc->rxbuf_lock);
2572 next = rsc->rx_next;
2573 mutex_exit(&rsc->rxbuf_lock);
2574 for (i = 0; i < RTW_RXQLEN; i++) {
2575 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
2576 RTW_DESC_OFFSET(hd_rx, next),
2577 sizeof (struct rtw_rxdesc),
2578 DDI_DMA_SYNC_FORKERNEL);
2579 n++;
2580 bf = rsc->rxbuf_h + next;
2581 ds = bf->rxdesc;
2582 hstat = (ds->rd_stat);
2583 hrssi = ds->rd_rssi;
2584 htsftl = ds->rd_tsftl;
2585 /* htsfth = ds->rd_tsfth; */
2586 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: stat=%x\n", __func__, hstat);
2587 /* still belongs to NIC */
2588 if ((hstat & RTW_RXSTAT_OWN) != 0) {
2589 if (n > 1) {
2590 RTW_DPRINTF(RTW_DEBUG_RECV,
2591 "%s: n > 1\n", __func__);
2592 break;
2593 }
2594 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
2595 RTW_DESC_OFFSET(hd_rx, 0),
2596 sizeof (struct rtw_rxdesc),
2597 DDI_DMA_SYNC_FORCPU);
2598 bf = rsc->rxbuf_h;
2599 ds = bf->rxdesc;
2600 hstat = (ds->rd_stat);
2601 if ((hstat & RTW_RXSTAT_OWN) != 0)
2602 break;
2603 next = 0 /* RTW_RXQLEN - 1 */;
2604 continue;
2605 }
2606
2607 rsc->sc_pktrcv64++;
2608 if ((hstat & RTW_RXSTAT_IOERROR) != 0) {
2609 RTW_DPRINTF(RTW_DEBUG_RECV,
2610 "rtw: DMA error/FIFO overflow %08x, "
2611 "rx descriptor %d\n",
2612 hstat & RTW_RXSTAT_IOERROR, next);
2613 goto next;
2614 }
2615
2616 len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
2617 rsc->sc_bytercv64 += len;
2618
2619 /* CRC is included with the packet; trim it off. */
2620 /* len -= IEEE80211_CRC_LEN; */
2621
2622 hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);
2623 if (hwrate >= 4) {
2624 goto next;
2625 }
2626
2627 if ((hstat & RTW_RXSTAT_RES) != 0 &&
2628 rsc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) {
2629 goto next;
2630 }
2631
2632 /* if bad flags, skip descriptor */
2633 if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
2634 RTW_DPRINTF(RTW_DEBUG_RECV,
2635 "rtw too many rx segments\n");
2636 goto next;
2637 }
2638
2639 if (rsc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
2640 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);
2641 else {
2642 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);
2643 /*
2644 * TBD find out each front-end's LNA gain in the
2645 * front-end's units
2646 */
2647 if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
2648 rssi |= 0x80;
2649 }
2650 /* sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ); */
2651
2652
2653 /* deal with the frame itself here */
2654 mp = allocb(rsc->sc_dmabuf_size, BPRI_MED);
2655 if (mp == NULL) {
2656 cmn_err(CE_WARN, "rtw: alloc mblk error");
2657 rsc->sc_norcvbuf++;
2658 return;
2659 }
2660 len -= IEEE80211_CRC_LEN;
2661 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORKERNEL);
2662 bcopy(bf->bf_dma.mem_va, mp->b_rptr, len);
2663 mp->b_wptr += len;
2664 wh = (struct ieee80211_frame *)mp->b_rptr;
2665 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2666 IEEE80211_FC0_TYPE_CTL) {
2667 cmn_err(CE_WARN, "TYPE CTL !!\n");
2668 freemsg(mp);
2669 goto next;
2670 }
2671 (void) ieee80211_input(ic, mp, ic->ic_bss, rssi, htsftl);
2672 next:
2673 if (next == 63)
2674 is_last = 1;
2675 else
2676 is_last = 0;
2677 rtw_rxdesc_init(rsc, bf, next, is_last);
2678
2679 next = (next + 1)%RTW_RXQLEN;
2680 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: next = %d\n", __func__, next);
2681 }
2682 mutex_enter(&rsc->rxbuf_lock);
2683 rsc->rx_next = next;
2684 mutex_exit(&rsc->rxbuf_lock);
2685 }
2686
2687 static void
2688 rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri)
2689 {
2690 struct rtw_txbuf *bf;
2691 struct rtw_txdesc *ds;
2692 uint32_t hstat;
2693 uint32_t head = 0;
2694 uint32_t cnt = 0, idx = 0;
2695
2696 mutex_enter(&rsc->sc_txq[pri].txbuf_lock);
2697 head = RTW_READ(&rsc->sc_regs, RTW_TNPDA);
2698 if (head == rsc->hw_go) {
2699 mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
2700 return;
2701 }
2702 RTW_DPRINTF(RTW_DEBUG_XMIT, "rtw_ring_recycling: enter ic_state=%x\n",
2703 rsc->sc_ic.ic_state);
2704
2705 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list);
2706 if (bf == NULL) {
2707 RTW_DPRINTF(RTW_DEBUG_XMIT,
2708 "rtw_ring_recycling: dirty bf[%d] NULL\n", pri);
2709 mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
2710 return;
2711 }
2712
2713 while ((bf != NULL) && (rsc->hw_go != head)) {
2714 cnt++;
2715 idx = (rsc->hw_go - rsc->hw_start) / sizeof (struct rtw_txdesc);
2716 if (idx == 63)
2717 rsc->hw_go = rsc->hw_start;
2718 else
2719 rsc->hw_go += sizeof (struct rtw_txdesc);
2720 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
2721 RTW_DESC_OFFSET(hd_txmd, idx),
2722 sizeof (struct rtw_txdesc),
2723 DDI_DMA_SYNC_FORCPU);
2724
2725 RTW_DPRINTF(RTW_DEBUG_XMIT, "Head = 0x%x\n", head);
2726 ds = bf->txdesc;
2727 hstat = (ds->td_stat);
2728 ds->td_len = ds->td_len & 0xfff;
2729 RTW_DPRINTF(RTW_DEBUG_XMIT,
2730 "%s rtw_ring_recycling: stat=%x, pri=%x\n",
2731 __func__, hstat, pri);
2732 if (hstat & RTW_TXSTAT_TOK)
2733 rsc->sc_tx_ok++;
2734 else {
2735 RTW_DPRINTF(RTW_DEBUG_XMIT,
2736 "TX err @%d, o %d, retry[%d], isr[0x%x], cnt %d\n",
2737 idx, (hstat & RTW_TXSTAT_OWN)?1:0,
2738 (hstat & RTW_TXSTAT_DRC_MASK), isr, cnt);
2739 if ((hstat & RTW_TXSTAT_DRC_MASK) <= 4) {
2740 rsc->sc_tx_ok++;
2741 } else {
2742 rsc->sc_tx_err++;
2743 }
2744 }
2745 rsc->sc_tx_retr +=
2746 (hstat & RTW_TXSTAT_DRC_MASK);
2747 rsc->sc_xmtretry +=
2748 (hstat & RTW_TXSTAT_DRC_MASK);
2749 list_remove(&rsc->sc_txq[pri].tx_dirty_list, bf);
2750 list_insert_tail(&rsc->sc_txq[pri].tx_free_list,
2751 bf);
2752 (rsc->sc_txq[pri].tx_nfree)++;
2753 if (rsc->sc_need_reschedule == 1) {
2754 mac_tx_update(rsc->sc_ic.ic_mach);
2755 rsc->sc_need_reschedule = 0;
2756 }
2757 RTW_DPRINTF(RTW_DEBUG_XMIT,
2758 "rtw_ring_recycling: nfree[%d]=%d\n",
2759 pri, rsc->sc_txq[pri].tx_nfree);
2760 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc));
2761 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
2762 RTW_DESC_OFFSET(hd_txmd, idx),
2763 sizeof (struct rtw_txdesc),
2764 DDI_DMA_SYNC_FORDEV);
2765 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list);
2766 }
2767 mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
2768 }
2769
2770 static void
2771 rtw_intr_timeout(rtw_softc_t *rsc)
2772 {
2773 rtw_resume_ticks(rsc);
2774 }
2775
2776 static uint_t
2777 rtw_intr(caddr_t arg)
2778 {
2779 /* LINTED E_BAD_PTR_CAST_ALIGN */
2780 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2781 struct rtw_regs *regs = &rsc->sc_regs;
2782 uint16_t isr = 0;
2783
2784 mutex_enter(&rsc->sc_genlock);
2785 isr = RTW_READ16(regs, RTW_ISR);
2786 RTW_WRITE16(regs, RTW_ISR, isr);
2787
2788 if (isr == 0) {
2789 mutex_exit(&rsc->sc_genlock);
2790 return (DDI_INTR_UNCLAIMED);
2791 }
2792
2793 #ifdef DEBUG
2794 #define PRINTINTR(flag) { \
2795 if ((isr & flag) != 0) { \
2796 RTW_DPRINTF(RTW_DEBUG_INTR, "|" #flag); \
2797 } \
2798 }
2799
2800 if ((rtw_dbg_flags & RTW_DEBUG_INTR) != 0 && isr != 0) {
2801
2802 RTW_DPRINTF(RTW_DEBUG_INTR, "rtw: reg[ISR] = %x", isr);
2803
2804 PRINTINTR(RTW_INTR_TXFOVW);
2805 PRINTINTR(RTW_INTR_TIMEOUT);
2806 PRINTINTR(RTW_INTR_BCNINT);
2807 PRINTINTR(RTW_INTR_ATIMINT);
2808 PRINTINTR(RTW_INTR_TBDER);
2809 PRINTINTR(RTW_INTR_TBDOK);
2810 PRINTINTR(RTW_INTR_THPDER);
2811 PRINTINTR(RTW_INTR_THPDOK);
2812 PRINTINTR(RTW_INTR_TNPDER);
2813 PRINTINTR(RTW_INTR_TNPDOK);
2814 PRINTINTR(RTW_INTR_RXFOVW);
2815 PRINTINTR(RTW_INTR_RDU);
2816 PRINTINTR(RTW_INTR_TLPDER);
2817 PRINTINTR(RTW_INTR_TLPDOK);
2818 PRINTINTR(RTW_INTR_RER);
2819 PRINTINTR(RTW_INTR_ROK);
2820 }
2821 #undef PRINTINTR
2822 #endif /* DEBUG */
2823
2824 rsc->sc_intr++;
2825
2826 if ((isr & RTW_INTR_RX) != 0) {
2827 mutex_exit(&rsc->sc_genlock);
2828 rtw_intr_rx(rsc);
2829 mutex_enter(&rsc->sc_genlock);
2830 }
2831 if ((isr & RTW_INTR_TIMEOUT) != 0)
2832 rtw_intr_timeout(rsc);
2833
2834 if ((isr & RTW_INTR_TX) != 0)
2835 rtw_ring_recycling(rsc, isr, 1);
2836 mutex_exit(&rsc->sc_genlock);
2837 return (DDI_INTR_CLAIMED);
2838 }
2839
2840 static void
2841 rtw_stop(void *arg)
2842 {
2843 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2844 struct rtw_regs *regs = &rsc->sc_regs;
2845
2846 mutex_enter(&rsc->sc_genlock);
2847 rtw_disable_interrupts(regs);
2848 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
2849 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
2850 rsc->sc_invalid = 1;
2851 mutex_exit(&rsc->sc_genlock);
2852 }
2853
2854 static void
2855 rtw_m_stop(void *arg)
2856 {
2857 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2858
2859 (void) ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
2860 rtw_stop(rsc);
2861 }
2862
2863 /*
2864 * quiesce(9E) entry point.
2865 *
2866 * This function is called when the system is single-threaded at high
2867 * PIL with preemption disabled. Therefore, this function must not be
2868 * blocked.
2869 *
2870 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
2871 * DDI_FAILURE indicates an error condition and should almost never happen.
2872 */
2873 int
2874 rtw_quiesce(dev_info_t *dip)
2875 {
2876 rtw_softc_t *rsc = NULL;
2877 struct rtw_regs *regs;
2878
2879 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(dip));
2880 ASSERT(rsc != NULL);
2881 regs = &rsc->sc_regs;
2882
2883 rtw_dbg_flags = 0;
2884 rtw_disable_interrupts(regs);
2885 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
2886 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
2887
2888 return (DDI_SUCCESS);
2889 }
2890
2891 /*
2892 * callback functions for /get/set properties
2893 */
2894 static int
2895 rtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2896 uint_t wldp_length, const void *wldp_buf)
2897 {
2898 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2899 struct ieee80211com *ic = &rsc->sc_ic;
2900 int err;
2901
2902 err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
2903 wldp_length, wldp_buf);
2904 if (err == ENETRESET) {
2905 if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
2906 (void) rtw_init(rsc);
2907 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2908 }
2909 err = 0;
2910 }
2911 return (err);
2912 }
2913
2914 static int
2915 rtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2916 uint_t wldp_length, void *wldp_buf)
2917 {
2918 rtw_softc_t *rsc = arg;
2919 int err;
2920
2921 err = ieee80211_getprop(&rsc->sc_ic, pr_name, wldp_pr_num,
2922 wldp_length, wldp_buf);
2923
2924 return (err);
2925 }
2926
2927 static void
2928 rtw_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2929 mac_prop_info_handle_t prh)
2930 {
2931 rtw_softc_t *rsc = arg;
2932
2933 ieee80211_propinfo(&rsc->sc_ic, pr_name, wldp_pr_num, prh);
2934 }
2935
2936 static int
2937 rtw_m_start(void *arg)
2938 {
2939 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2940 ieee80211com_t *ic = (ieee80211com_t *)rsc;
2941 int ret;
2942 #ifdef DEBUG
2943 rtw_print_regs(&rsc->sc_regs, "rtw", "rtw_start");
2944 #endif
2945
2946 ret = rtw_init(rsc);
2947 if (ret) {
2948 cmn_err(CE_WARN, "rtw: failed to do rtw_init\n");
2949 return (EIO);
2950 }
2951 (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2952 return (0);
2953 }
2954
2955
2956 static int
2957 rtw_m_unicst(void *arg, const uint8_t *macaddr)
2958 {
2959 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2960 ieee80211com_t *ic = (ieee80211com_t *)rsc;
2961 struct rtw_regs *regs = &rsc->sc_regs;
2962 uint32_t t;
2963
2964 mutex_enter(&rsc->sc_genlock);
2965 bcopy(macaddr, ic->ic_macaddr, 6);
2966 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) |
2967 ((*(macaddr + 2))<<8) | (*(macaddr + 3));
2968 RTW_WRITE(regs, RTW_IDR0, ntohl(t));
2969 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16);
2970 RTW_WRITE(regs, RTW_IDR1, ntohl(t));
2971 mutex_exit(&rsc->sc_genlock);
2972 return (0);
2973 }
2974
2975 static int
2976 rtw_m_promisc(void *arg, boolean_t on)
2977 {
2978 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2979 struct rtw_regs *regs = &rsc->sc_regs;
2980
2981 mutex_enter(&rsc->sc_genlock);
2982
2983 if (on)
2984 rsc->sc_rcr |= RTW_RCR_PROMIC;
2985 else
2986 rsc->sc_rcr &= ~RTW_RCR_PROMIC;
2987
2988 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
2989
2990 mutex_exit(&rsc->sc_genlock);
2991 return (0);
2992 }
2993
2994 static int
2995 rtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
2996 {
2997 rtw_softc_t *rsc = (rtw_softc_t *)arg;
2998 struct rtw_regs *regs = &rsc->sc_regs;
2999 uint32_t t;
3000
3001 mutex_enter(&rsc->sc_genlock);
3002 if (add) {
3003 rsc->sc_rcr |= RTW_RCR_AM;
3004 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) |
3005 ((*(macaddr + 2))<<8) | (*(macaddr + 3));
3006 RTW_WRITE(regs, RTW_MAR0, ntohl(t));
3007 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16);
3008 RTW_WRITE(regs, RTW_MAR1, ntohl(t));
3009 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
3010 RTW_SYNC(regs, RTW_MAR0, RTW_RCR);
3011 } else {
3012 rsc->sc_rcr &= ~RTW_RCR_AM;
3013 RTW_WRITE(regs, RTW_MAR0, 0);
3014 RTW_WRITE(regs, RTW_MAR1, 0);
3015 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
3016 RTW_SYNC(regs, RTW_MAR0, RTW_RCR);
3017 }
3018 mutex_exit(&rsc->sc_genlock);
3019 return (0);
3020 }
3021
3022 static void
3023 rtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
3024 {
3025 rtw_softc_t *rsc = arg;
3026 struct ieee80211com *ic = &rsc->sc_ic;
3027 int err;
3028
3029 err = ieee80211_ioctl(ic, wq, mp);
3030 if (err == ENETRESET) {
3031 if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
3032 (void) rtw_init(rsc);
3033 (void) ieee80211_new_state(ic,
3034 IEEE80211_S_SCAN, -1);
3035 }
3036 }
3037 }
3038
3039 static int
3040 rtw_m_stat(void *arg, uint_t stat, uint64_t *val)
3041 {
3042 rtw_softc_t *rsc = (rtw_softc_t *)arg;
3043 ieee80211com_t *ic = &rsc->sc_ic;
3044 struct ieee80211_node *in = 0;
3045 struct ieee80211_rateset *rs = 0;
3046
3047 mutex_enter(&rsc->sc_genlock);
3048 switch (stat) {
3049 case MAC_STAT_IFSPEED:
3050 in = ic->ic_bss;
3051 rs = &in->in_rates;
3052 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
3053 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL)
3054 : ic->ic_fixed_rate) / 2 * 1000000;
3055 break;
3056 case MAC_STAT_NOXMTBUF:
3057 *val = rsc->sc_noxmtbuf;
3058 break;
3059 case MAC_STAT_NORCVBUF:
3060 *val = rsc->sc_norcvbuf;
3061 break;
3062 case MAC_STAT_RBYTES:
3063 *val = rsc->sc_bytercv64;
3064 break;
3065 case MAC_STAT_IPACKETS:
3066 *val = rsc->sc_pktrcv64;
3067 break;
3068 case MAC_STAT_OBYTES:
3069 *val = rsc->sc_bytexmt64;
3070 break;
3071 case MAC_STAT_OPACKETS:
3072 *val = rsc->sc_pktxmt64;
3073 break;
3074 case WIFI_STAT_TX_RETRANS:
3075 *val = rsc->sc_xmtretry;
3076 break;
3077 case WIFI_STAT_TX_FRAGS:
3078 case WIFI_STAT_MCAST_TX:
3079 case WIFI_STAT_RTS_SUCCESS:
3080 case WIFI_STAT_RTS_FAILURE:
3081 case WIFI_STAT_ACK_FAILURE:
3082 case WIFI_STAT_RX_FRAGS:
3083 case WIFI_STAT_MCAST_RX:
3084 case WIFI_STAT_RX_DUPS:
3085 mutex_exit(&rsc->sc_genlock);
3086 return (ieee80211_stat(ic, stat, val));
3087 default:
3088 *val = 0;
3089 break;
3090 }
3091 mutex_exit(&rsc->sc_genlock);
3092
3093 return (0);
3094 }
3095
3096
3097 static void
3098 rtw_mutex_destroy(rtw_softc_t *rsc)
3099 {
3100 int i;
3101
3102 mutex_destroy(&rsc->rxbuf_lock);
3103 mutex_destroy(&rsc->sc_txlock);
3104 for (i = 0; i < RTW_NTXPRI; i++) {
3105 mutex_destroy(&rsc->sc_txq[RTW_NTXPRI - 1 - i].txbuf_lock);
3106 }
3107 mutex_destroy(&rsc->sc_genlock);
3108 }
3109
3110 static int
3111 rtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
3112 {
3113 rtw_softc_t *rsc;
3114 ieee80211com_t *ic;
3115 uint8_t csz;
3116 uint32_t i;
3117 uint16_t vendor_id, device_id, command;
3118 int32_t err;
3119 char strbuf[32];
3120 wifi_data_t wd = { 0 };
3121 mac_register_t *macp;
3122 int instance = ddi_get_instance(devinfo);
3123
3124 switch (cmd) {
3125 case DDI_ATTACH:
3126 break;
3127 case DDI_RESUME:
3128 rsc = ddi_get_soft_state(rtw_soft_state_p,
3129 ddi_get_instance(devinfo));
3130 ASSERT(rsc != NULL);
3131 mutex_enter(&rsc->sc_genlock);
3132 rsc->sc_flags &= ~RTW_F_SUSPEND;
3133 mutex_exit(&rsc->sc_genlock);
3134 if ((rsc->sc_flags & RTW_F_PLUMBED)) {
3135 err = rtw_init(rsc);
3136 if (err == 0) {
3137 mutex_enter(&rsc->sc_genlock);
3138 rsc->sc_flags &= ~RTW_F_PLUMBED;
3139 mutex_exit(&rsc->sc_genlock);
3140 }
3141 }
3142 return (DDI_SUCCESS);
3143 default:
3144 return (DDI_FAILURE);
3145 }
3146
3147 if (ddi_soft_state_zalloc(rtw_soft_state_p,
3148 ddi_get_instance(devinfo)) != DDI_SUCCESS) {
3149 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3150 "Unable to alloc softstate\n");
3151 return (DDI_FAILURE);
3152 }
3153
3154 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
3155 ic = &rsc->sc_ic;
3156 rsc->sc_dev = devinfo;
3157
3158 err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&rsc->sc_cfg_base, 0, 0,
3159 &rtw_reg_accattr, &rsc->sc_cfg_handle);
3160 if (err != DDI_SUCCESS) {
3161 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3162 "ddi_regs_map_setup() failed");
3163 goto attach_fail0;
3164 }
3165 csz = ddi_get8(rsc->sc_cfg_handle,
3166 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
3167 if (!csz)
3168 csz = 16;
3169 rsc->sc_cachelsz = csz << 2;
3170 vendor_id = ddi_get16(rsc->sc_cfg_handle,
3171 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_VENID));
3172 device_id = ddi_get16(rsc->sc_cfg_handle,
3173 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_DEVID));
3174 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): vendor 0x%x, "
3175 "device id 0x%x, cache size %d\n", vendor_id, device_id, csz);
3176
3177 /*
3178 * Enable response to memory space accesses,
3179 * and enabe bus master.
3180 */
3181 command = PCI_COMM_MAE | PCI_COMM_ME;
3182 ddi_put16(rsc->sc_cfg_handle,
3183 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_COMM), command);
3184 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3185 "set command reg to 0x%x \n", command);
3186
3187 ddi_put8(rsc->sc_cfg_handle,
3188 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8);
3189
3190 ddi_regs_map_free(&rsc->sc_cfg_handle);
3191
3192 err = ddi_regs_map_setup(devinfo, 2, (caddr_t *)&rsc->sc_regs.r_base,
3193 0, 0, &rtw_reg_accattr, &rsc->sc_regs.r_handle);
3194 if (err != DDI_SUCCESS) {
3195 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3196 "ddi_regs_map_setup() failed");
3197 goto attach_fail0;
3198 }
3199 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: r_base=%x, r_handle=%x\n",
3200 rsc->sc_regs.r_base, rsc->sc_regs.r_handle);
3201
3202 err = rtw_dma_init(devinfo, rsc);
3203 if (err != DDI_SUCCESS) {
3204 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3205 "failed to init dma: %d\n", err);
3206 goto attach_fail1;
3207 }
3208
3209 /*
3210 * Stop the transmit and receive processes. First stop DMA,
3211 * then disable receiver and transmitter.
3212 */
3213 RTW_WRITE8(&rsc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
3214 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
3215
3216 /* Reset the chip to a known state. */
3217 if (rtw_reset(rsc) != 0) {
3218 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3219 "failed to reset\n");
3220 goto attach_fail2;
3221 }
3222 rsc->sc_rcr = RTW_READ(&rsc->sc_regs, RTW_RCR);
3223
3224 if ((rsc->sc_rcr & RTW_RCR_9356SEL) != 0)
3225 rsc->sc_flags |= RTW_F_9356SROM;
3226
3227 if (rtw_srom_read(&rsc->sc_regs, rsc->sc_flags, &rsc->sc_srom,
3228 "rtw") != 0) {
3229 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3230 "failed to read srom\n");
3231 goto attach_fail2;
3232 }
3233
3234 if (rtw_srom_parse(&rsc->sc_srom, &rsc->sc_flags, &rsc->sc_csthr,
3235 &rsc->sc_rfchipid, &rsc->sc_rcr, &rsc->sc_locale,
3236 "rtw") != 0) {
3237 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_attach():"
3238 " malformed serial ROM\n");
3239 goto attach_fail3;
3240 }
3241
3242 RTW_DPRINTF(RTW_DEBUG_PHY, "rtw: %s PHY\n",
3243 ((rsc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog");
3244
3245
3246 rsc->sc_rf = rtw_rf_attach(rsc, rsc->sc_rfchipid,
3247 rsc->sc_flags & RTW_F_DIGPHY);
3248
3249 if (rsc->sc_rf == NULL) {
3250 cmn_err(CE_WARN, "rtw: rtw_attach(): could not attach RF\n");
3251 goto attach_fail3;
3252 }
3253 rsc->sc_phydelay = rtw_check_phydelay(&rsc->sc_regs, rsc->sc_rcr);
3254
3255 RTW_DPRINTF(RTW_DEBUG_ATTACH,
3256 "rtw: PHY delay %d\n", rsc->sc_phydelay);
3257
3258 if (rsc->sc_locale == RTW_LOCALE_UNKNOWN)
3259 rtw_identify_country(&rsc->sc_regs, &rsc->sc_locale,
3260 "rtw");
3261
3262 rtw_init_channels(rsc->sc_locale, &rsc->sc_ic.ic_sup_channels,
3263 "rtw");
3264
3265 rtw_set80211props(ic);
3266
3267 if (rtw_identify_sta(&rsc->sc_regs, ic->ic_macaddr,
3268 "rtw") != 0)
3269 goto attach_fail4;
3270
3271 ic->ic_xmit = rtw_send;
3272 ieee80211_attach(ic);
3273
3274 rsc->sc_newstate = ic->ic_newstate;
3275 ic->ic_newstate = rtw_new_state;
3276 ieee80211_media_init(ic);
3277 ic->ic_def_txkey = 0;
3278
3279 if (ddi_get_iblock_cookie(devinfo, 0, &(rsc->sc_iblock))
3280 != DDI_SUCCESS) {
3281 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3282 "Can not get iblock cookie for INT\n");
3283 goto attach_fail5;
3284 }
3285
3286 mutex_init(&rsc->sc_genlock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
3287 for (i = 0; i < RTW_NTXPRI; i++) {
3288 mutex_init(&rsc->sc_txq[i].txbuf_lock, NULL, MUTEX_DRIVER,
3289 rsc->sc_iblock);
3290 }
3291 mutex_init(&rsc->rxbuf_lock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
3292 mutex_init(&rsc->sc_txlock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
3293
3294 if (ddi_add_intr(devinfo, 0, &rsc->sc_iblock, NULL, rtw_intr,
3295 (caddr_t)(rsc)) != DDI_SUCCESS) {
3296 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3297 "Can not add intr for rtw driver\n");
3298 goto attach_fail7;
3299 }
3300
3301 /*
3302 * Provide initial settings for the WiFi plugin; whenever this
3303 * information changes, we need to call mac_plugindata_update()
3304 */
3305 wd.wd_opmode = ic->ic_opmode;
3306 wd.wd_secalloc = WIFI_SEC_NONE;
3307 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
3308
3309 if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
3310 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3311 "MAC version mismatch\n");
3312 goto attach_fail8;
3313 }
3314
3315 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
3316 macp->m_driver = rsc;
3317 macp->m_dip = devinfo;
3318 macp->m_src_addr = ic->ic_macaddr;
3319 macp->m_callbacks = &rtw_m_callbacks;
3320 macp->m_min_sdu = 0;
3321 macp->m_max_sdu = IEEE80211_MTU;
3322 macp->m_pdata = &wd;
3323 macp->m_pdata_size = sizeof (wd);
3324
3325 err = mac_register(macp, &ic->ic_mach);
3326 mac_free(macp);
3327 if (err != 0) {
3328 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
3329 "mac_register err %x\n", err);
3330 goto attach_fail8;
3331 }
3332
3333 /* Create minor node of type DDI_NT_NET_WIFI */
3334 (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
3335 "rtw", instance);
3336 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
3337 instance + 1, DDI_NT_NET_WIFI, 0);
3338 if (err != DDI_SUCCESS) {
3339 RTW_DPRINTF(RTW_DEBUG_ATTACH, "WARN: rtw: rtw_attach(): "
3340 "Create minor node failed - %d\n", err);
3341 goto attach_fail9;
3342 }
3343 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
3344 rsc->sc_flags |= RTW_F_ATTACHED;
3345 rsc->sc_need_reschedule = 0;
3346 rsc->sc_invalid = 1;
3347 return (DDI_SUCCESS);
3348 attach_fail9:
3349 (void) mac_disable(ic->ic_mach);
3350 (void) mac_unregister(ic->ic_mach);
3351 attach_fail8:
3352 ddi_remove_intr(devinfo, 0, rsc->sc_iblock);
3353 attach_fail7:
3354 attach_fail6:
3355 rtw_mutex_destroy(rsc);
3356 attach_fail5:
3357 ieee80211_detach(ic);
3358 attach_fail4:
3359 rtw_rf_destroy(rsc->sc_rf);
3360 attach_fail3:
3361 rtw_srom_free(&rsc->sc_srom);
3362 attach_fail2:
3363 rtw_dma_free(rsc);
3364 attach_fail1:
3365 ddi_regs_map_free(&rsc->sc_regs.r_handle);
3366 attach_fail0:
3367 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
3368 return (DDI_FAILURE);
3369 }
3370
3371 static int32_t
3372 rtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
3373 {
3374 rtw_softc_t *rsc;
3375
3376 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
3377 ASSERT(rsc != NULL);
3378
3379 switch (cmd) {
3380 case DDI_DETACH:
3381 break;
3382 case DDI_SUSPEND:
3383 ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
3384 mutex_enter(&rsc->sc_genlock);
3385 rsc->sc_flags |= RTW_F_SUSPEND;
3386 mutex_exit(&rsc->sc_genlock);
3387 if (rsc->sc_invalid == 0) {
3388 rtw_stop(rsc);
3389 mutex_enter(&rsc->sc_genlock);
3390 rsc->sc_flags |= RTW_F_PLUMBED;
3391 mutex_exit(&rsc->sc_genlock);
3392 }
3393 return (DDI_SUCCESS);
3394 default:
3395 return (DDI_FAILURE);
3396 }
3397 if (!(rsc->sc_flags & RTW_F_ATTACHED))
3398 return (DDI_FAILURE);
3399
3400 if (mac_disable(rsc->sc_ic.ic_mach) != 0)
3401 return (DDI_FAILURE);
3402
3403 /* free intterrupt resources */
3404 ddi_remove_intr(devinfo, 0, rsc->sc_iblock);
3405
3406 rtw_mutex_destroy(rsc);
3407 ieee80211_detach((ieee80211com_t *)rsc);
3408 /*
3409 * Unregister from the MAC layer subsystem
3410 */
3411 (void) mac_unregister(rsc->sc_ic.ic_mach);
3412
3413 rtw_rf_destroy(rsc->sc_rf);
3414 rtw_srom_free(&rsc->sc_srom);
3415 rtw_dma_free(rsc);
3416 ddi_remove_minor_node(devinfo, NULL);
3417 ddi_regs_map_free(&rsc->sc_regs.r_handle);
3418
3419 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
3420
3421 return (DDI_SUCCESS);
3422 }