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