xref: /illumos-gate/usr/src/uts/common/io/rtw/rtw.c (revision 0dc2366f)
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  */
54 static 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  */
64 static 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 };
70 static 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  */
80 static 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 
95 static 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 
110 static 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 
126 static void *rtw_soft_state_p = NULL;
127 
128 static void	rtw_stop(void *);
129 static int	rtw_attach(dev_info_t *, ddi_attach_cmd_t);
130 static int	rtw_detach(dev_info_t *, ddi_detach_cmd_t);
131 static int	rtw_quiesce(dev_info_t *);
132 static int	rtw_m_stat(void *,  uint_t, uint64_t *);
133 static int	rtw_m_start(void *);
134 static void	rtw_m_stop(void *);
135 static int	rtw_m_promisc(void *, boolean_t);
136 static int	rtw_m_multicst(void *, boolean_t, const uint8_t *);
137 static int	rtw_m_unicst(void *, const uint8_t *);
138 static mblk_t	*rtw_m_tx(void *, mblk_t *);
139 static void	rtw_m_ioctl(void *, queue_t *, mblk_t *);
140 static int	rtw_m_setprop(void *, const char *, mac_prop_id_t,
141     uint_t, const void *);
142 static int	rtw_m_getprop(void *, const char *, mac_prop_id_t,
143     uint_t, void *);
144 static void	rtw_m_propinfo(void *, const char *, mac_prop_id_t,
145     mac_prop_info_handle_t);
146 
147 static 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 
166 DDI_DEFINE_STREAM_OPS(rtw_dev_ops, nulldev, nulldev, rtw_attach, rtw_detach,
167     nodev, NULL, D_MP, NULL, rtw_quiesce);
168 
169 static 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 
175 static struct modlinkage modlinkage = {
176 	MODREV_1, (void *)&rtw_modldrv, NULL
177 };
178 
179 static uint32_t rtw_qlen[RTW_NTXPRI] = {
180 	RTW_TXQLENLO,
181 	RTW_TXQLENMD,
182 	RTW_TXQLENHI,
183 	RTW_TXQLENBCN
184 };
185 
186 uint32_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  */
197 static const struct ieee80211_rateset rtw_rateset_11b =
198 	{ 4, { 2, 4, 11, 22 } };
199 
200 int
_info(struct modinfo * modinfop)201 _info(struct modinfo *modinfop)
202 {
203 	return (mod_info(&modlinkage, modinfop));
204 }
205 
206 int
_init(void)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 
225 int
_fini(void)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 
238 void
rtw_dbg(uint32_t dbg_flags,const int8_t * fmt,...)239 rtw_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
251 static void
rtw_print_regs(struct rtw_regs * regs,const char * dvname,const char * where)252 rtw_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 */
358 static const char *
rtw_access_string(enum rtw_access access)359 rtw_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  */
376 void
rtw_config0123_enable(struct rtw_regs * regs,int enable)377 rtw_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  */
395 void
rtw_anaparm_enable(struct rtw_regs * regs,int enable)396 rtw_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  */
413 void
rtw_txdac_enable(rtw_softc_t * rsc,int enable)414 rtw_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 
428 static void
rtw_set_access1(struct rtw_regs * regs,enum rtw_access naccess)429 rtw_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 
478 void
rtw_set_access(struct rtw_regs * regs,enum rtw_access access)479 rtw_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 
490 void
rtw_continuous_tx_enable(rtw_softc_t * rsc,int enable)491 rtw_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 
510 static int
rtw_chip_reset1(struct rtw_regs * regs,const char * dvname)511 rtw_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 
535 static int
rtw_chip_reset(struct rtw_regs * regs,const char * dvname)536 rtw_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 
542 static void
rtw_disable_interrupts(struct rtw_regs * regs)543 rtw_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 
550 static void
rtw_enable_interrupts(rtw_softc_t * rsc)551 rtw_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 
565 static int
rtw_recall_eeprom(struct rtw_regs * regs,const char * dvname)566 rtw_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 
592 static int
rtw_reset(rtw_softc_t * rsc)593 rtw_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 
605 void
rtw_set_mode(struct rtw_regs * regs,int mode)606 rtw_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 
617 void
rtw_dma_start(struct rtw_regs * regs,int priority)618 rtw_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 
640 void
rtw_beacon_tx_disable(struct rtw_regs * regs)641 rtw_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 
650 static void
651 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable);
652 
653 void
rtw_rtx_disable(rtw_softc_t * rsc)654 rtw_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 
662 static void
rtw_srom_free(struct rtw_srom * sr)663 rtw_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*/
673 static void
rtw_srom_defaults(struct rtw_srom * sr,uint32_t * flags,uint8_t * cs_threshold,enum rtw_rfchipid * rfchipid,uint32_t * rcr)674 rtw_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 
683 static int
rtw_srom_parse(struct rtw_srom * sr,uint32_t * flags,uint8_t * cs_threshold,enum rtw_rfchipid * rfchipid,uint32_t * rcr,enum rtw_locale * locale,const char * dvname)684 rtw_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  */
789 static int
rtw_srom_read(struct rtw_regs * regs,uint32_t flags,struct rtw_srom * sr,const char * dvname)790 rtw_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 
882 static void
rtw_set_rfprog(struct rtw_regs * regs,enum rtw_rfchipid rfchipid,const char * dvname)883 rtw_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 
920 static void
rtw_init_channels(enum rtw_locale locale,struct ieee80211_channel (* chans)[IEEE80211_CHAN_MAX+1],const char * dvname)921 rtw_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 
961 static void
rtw_set80211props(struct ieee80211com * ic)962 rtw_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*/
974 static void
rtw_identify_country(struct rtw_regs * regs,enum rtw_locale * locale,const char * dvname)975 rtw_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 
996 static int
rtw_identify_sta(struct rtw_regs * regs,uint8_t * addr,const char * dvname)997 rtw_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 
1018 static uint8_t
rtw_chan2txpower(struct rtw_srom * sr,struct ieee80211com * ic,struct ieee80211_channel * chan)1019 rtw_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 
1026 static void
rtw_rxdesc_init(rtw_softc_t * rsc,struct rtw_rxbuf * rbf,int idx,int is_last)1027 rtw_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 
1052 static void
rtw_idle(struct rtw_regs * regs)1053 rtw_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 
1066 static void
rtw_io_enable(rtw_softc_t * rsc,uint8_t flags,int enable)1067 rtw_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  */
1098 static int
rtw_alloc_dma_mem(dev_info_t * devinfo,ddi_dma_attr_t * dma_attr,size_t memsize,ddi_device_acc_attr_t * attr_p,uint_t alloc_flags,uint_t bind_flags,dma_area_t * dma_p)1099 rtw_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  */
1141 static void
rtw_free_dma_mem(dma_area_t * dma_p)1142 rtw_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 
1156 static void
rtw_dma_free(rtw_softc_t * rsc)1157 rtw_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 
1203 static int
rtw_dma_init(dev_info_t * devinfo,rtw_softc_t * rsc)1204 rtw_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);
1303 error:
1304 	return (DDI_FAILURE);
1305 }
1306 
1307 static void
rtw_hwring_setup(rtw_softc_t * rsc)1308 rtw_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 
1324 static void
rtw_swring_setup(rtw_softc_t * rsc,int flag)1325 rtw_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 
1393 static void
rtw_resume_ticks(rtw_softc_t * rsc)1394 rtw_resume_ticks(rtw_softc_t *rsc)
1395 {
1396 	RTW_WRITE(&rsc->sc_regs, RTW_TINT, 0xffffffff);
1397 }
1398 
1399 const char *
rtw_pwrstate_string(enum rtw_pwrstate power)1400 rtw_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*/
1420 static void
rtw_maxim_pwrstate(struct rtw_regs * regs,enum rtw_pwrstate power,int before_rf,int digphy)1421 rtw_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*/
1462 static void
rtw_rfmd_pwrstate(struct rtw_regs * regs,enum rtw_pwrstate power,int before_rf,int digphy)1463 rtw_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 
1499 static void
rtw_philips_pwrstate(struct rtw_regs * regs,enum rtw_pwrstate power,int before_rf,int digphy)1500 rtw_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 
1541 static void
rtw_pwrstate0(rtw_softc_t * rsc,enum rtw_pwrstate power,int before_rf,int digphy)1542 rtw_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 
1554 static void
rtw_rf_destroy(struct rtw_rf * rf)1555 rtw_rf_destroy(struct rtw_rf *rf)
1556 {
1557 	(*rf->rf_destroy)(rf);
1558 }
1559 
1560 static int
rtw_rf_pwrstate(struct rtw_rf * rf,enum rtw_pwrstate power)1561 rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
1562 {
1563 	return (*rf->rf_pwrstate)(rf, power);
1564 }
1565 
1566 static int
rtw_pwrstate(rtw_softc_t * rsc,enum rtw_pwrstate power)1567 rtw_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 
1600 void
rtw_disable(rtw_softc_t * rsc)1601 rtw_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 
1620 int
rtw_enable(rtw_softc_t * rsc)1621 rtw_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 
1635 static void
rtw_set_nettype(rtw_softc_t * rsc,enum ieee80211_opmode opmode)1636 rtw_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 
1662 static void
rtw_pktfilt_load(rtw_softc_t * rsc)1663 rtw_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 
1704 static void
rtw_transmit_config(struct rtw_regs * regs)1705 rtw_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 
1727 int
rtw_refine_setting(rtw_softc_t * rsc)1728 rtw_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 
1761 static int
rtw_tune(rtw_softc_t * rsc)1762 rtw_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 
1802 static int
rtw_init(rtw_softc_t * rsc)1803 rtw_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;
1829 out:
1830 	mutex_exit(&rsc->sc_genlock);
1831 	return (rc);
1832 }
1833 
1834 static struct rtw_rf *
rtw_rf_attach(rtw_softc_t * rsc,enum rtw_rfchipid rfchipid,int digphy)1835 rtw_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  */
1882 static uint8_t
rtw_check_phydelay(struct rtw_regs * regs,uint32_t rcr0)1883 rtw_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 
1905 static void rtw_intr_rx(rtw_softc_t *rsc);
1906 static void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri);
1907 
1908 static int
rtw_get_rate(struct ieee80211com * ic)1909 rtw_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  */
1944 static int
rtw_compute_duration1(int len,int use_ack,uint32_t flags,int rate,struct rtw_ieee80211_duration * d)1945 rtw_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  */
2032 static int
rtw_compute_duration(struct ieee80211_frame * wh,int len,uint32_t flags,int fraglen,int rate,struct rtw_ieee80211_duration * d0,struct rtw_ieee80211_duration * dn,int * npktp)2033 rtw_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 
2087 static int
rtw_assembly_80211(rtw_softc_t * rsc,struct rtw_txbuf * bf,mblk_t * mp)2088 rtw_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 
2248 static int
rtw_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)2249 rtw_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 
2301 static mblk_t *
rtw_m_tx(void * arg,mblk_t * mp)2302 rtw_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 
2328 static void
rtw_next_scan(void * arg)2329 rtw_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 
2342 static void
rtw_join_bss(rtw_softc_t * rsc,uint8_t * bssid,uint16_t intval0)2343 rtw_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  */
2375 static void
rtw_rate_ctl_start(rtw_softc_t * rsc,struct ieee80211_node * in)2376 rtw_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  */
2417 static void
rtw_rate_ctl_reset(rtw_softc_t * rsc,enum ieee80211_state state)2418 rtw_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  */
2441 static void
rtw_rate_ctl(void * arg)2442 rtw_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 
2480 static int32_t
rtw_new_state(ieee80211com_t * ic,enum ieee80211_state nstate,int arg)2481 rtw_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 
2557 static void
rtw_intr_rx(rtw_softc_t * rsc)2558 rtw_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);
2678 next:
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 
2693 static void
rtw_ring_recycling(rtw_softc_t * rsc,uint16_t isr,uint32_t pri)2694 rtw_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 
2776 static void
rtw_intr_timeout(rtw_softc_t * rsc)2777 rtw_intr_timeout(rtw_softc_t *rsc)
2778 {
2779 	rtw_resume_ticks(rsc);
2780 }
2781 
2782 static uint_t
rtw_intr(caddr_t arg)2783 rtw_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 
2846 static void
rtw_stop(void * arg)2847 rtw_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 
2860 static void
rtw_m_stop(void * arg)2861 rtw_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  */
2879 int
rtw_quiesce(dev_info_t * dip)2880 rtw_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  */
2900 static int
rtw_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)2901 rtw_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 
2920 static int
rtw_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)2921 rtw_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 
2933 static void
rtw_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t prh)2934 rtw_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 
2942 static int
rtw_m_start(void * arg)2943 rtw_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 
2962 static int
rtw_m_unicst(void * arg,const uint8_t * macaddr)2963 rtw_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 
2981 static int
rtw_m_promisc(void * arg,boolean_t on)2982 rtw_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 
3000 static int
rtw_m_multicst(void * arg,boolean_t add,const uint8_t * macaddr)3001 rtw_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 
3028 static void
rtw_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)3029 rtw_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 
3045 static int
rtw_m_stat(void * arg,uint_t stat,uint64_t * val)3046 rtw_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 
3103 static void
rtw_mutex_destroy(rtw_softc_t * rsc)3104 rtw_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 
3116 static int
rtw_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)3117 rtw_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);
3354 attach_fail9:
3355 	(void) mac_disable(ic->ic_mach);
3356 	(void) mac_unregister(ic->ic_mach);
3357 attach_fail8:
3358 	ddi_remove_intr(devinfo, 0, rsc->sc_iblock);
3359 attach_fail7:
3360 attach_fail6:
3361 	rtw_mutex_destroy(rsc);
3362 attach_fail5:
3363 	ieee80211_detach(ic);
3364 attach_fail4:
3365 	rtw_rf_destroy(rsc->sc_rf);
3366 attach_fail3:
3367 	rtw_srom_free(&rsc->sc_srom);
3368 attach_fail2:
3369 	rtw_dma_free(rsc);
3370 attach_fail1:
3371 	ddi_regs_map_free(&rsc->sc_regs.r_handle);
3372 attach_fail0:
3373 	ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
3374 	return (DDI_FAILURE);
3375 }
3376 
3377 static int32_t
rtw_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)3378 rtw_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