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