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