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