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