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