Annotation of sys/dev/ic/rtw.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rtw.c,v 1.61 2007/06/07 20:20:15 damien Exp $ */
2: /* $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */
3:
4: /*-
5: * Copyright (c) 2004, 2005 David Young. All rights reserved.
6: *
7: * Programmed for NetBSD by David Young.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of David Young may not be used to endorse or promote
18: * products derived from this software without specific prior
19: * written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
22: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
25: * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32: * OF SUCH DAMAGE.
33: */
34: /*
35: * Device driver for the Realtek RTL8180 802.11 MAC/BBP.
36: */
37:
38: #include <sys/cdefs.h>
39: #include "bpfilter.h"
40:
41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/mbuf.h>
44: #include <sys/malloc.h>
45: #include <sys/kernel.h>
46: #include <sys/ioctl.h>
47: #include <sys/socket.h>
48: #include <sys/time.h>
49: #include <sys/types.h>
50:
51: #include <machine/endian.h>
52: #include <machine/bus.h>
53: #include <machine/intr.h> /* splnet */
54:
55: #include <uvm/uvm_extern.h>
56:
57: #include <net/if.h>
58: #include <net/if_media.h>
59:
60: #if NBPFILTER > 0
61: #include <net/bpf.h>
62: #endif
63:
64: #ifdef INET
65: #include <netinet/in.h>
66: #include <netinet/if_ether.h>
67: #endif
68:
69: #include <net80211/ieee80211_var.h>
70: #include <net80211/ieee80211_radiotap.h>
71:
72: #include <dev/ic/rtwreg.h>
73: #include <dev/ic/rtwvar.h>
74: #include <dev/ic/max2820reg.h>
75: #include <dev/ic/sa2400reg.h>
76: #include <dev/ic/si4136reg.h>
77: #include <dev/ic/rtl8225reg.h>
78: #include <dev/ic/smc93cx6var.h>
79:
80: int rtw_rfprog_fallback = 0;
81: int rtw_do_chip_reset = 0;
82: int rtw_dwelltime = 200; /* milliseconds per channel */
83: int rtw_macbangbits_timeout = 100;
84:
85: #ifdef RTW_DEBUG
86: int rtw_debug = 0;
87: int rtw_rxbufs_limit = RTW_RXQLEN;
88: #endif /* RTW_DEBUG */
89:
90: void rtw_start(struct ifnet *);
91: void rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *);
92: void rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *);
93: void rtw_txdesc_blk_init(struct rtw_txdesc_blk *);
94: void rtw_txdescs_sync(struct rtw_txdesc_blk *, u_int, u_int, int);
95: u_int rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *);
96: void rtw_txring_fixup(struct rtw_softc *);
97: void rtw_rxbufs_release(bus_dma_tag_t, struct rtw_rxsoft *);
98: void rtw_rxdesc_init(struct rtw_rxdesc_blk *, struct rtw_rxsoft *, int, int);
99: void rtw_rxring_fixup(struct rtw_softc *);
100: void rtw_io_enable(struct rtw_regs *, u_int8_t, int);
101: void rtw_intr_rx(struct rtw_softc *, u_int16_t);
102: void rtw_intr_beacon(struct rtw_softc *, u_int16_t);
103: void rtw_intr_atim(struct rtw_softc *);
104: void rtw_transmit_config(struct rtw_softc *);
105: void rtw_pktfilt_load(struct rtw_softc *);
106: void rtw_start(struct ifnet *);
107: void rtw_watchdog(struct ifnet *);
108: void rtw_next_scan(void *);
109: void rtw_recv_mgmt(struct ieee80211com *, struct mbuf *,
110: struct ieee80211_node *, int, int, u_int32_t);
111: struct ieee80211_node *rtw_node_alloc(struct ieee80211com *);
112: void rtw_node_free(struct ieee80211com *, struct ieee80211_node *);
113: void rtw_media_status(struct ifnet *, struct ifmediareq *);
114: void rtw_txsoft_blk_cleanup_all(struct rtw_softc *);
115: void rtw_txdesc_blk_setup(struct rtw_txdesc_blk *, struct rtw_txdesc *,
116: u_int, bus_addr_t, bus_addr_t);
117: void rtw_txdesc_blk_setup_all(struct rtw_softc *);
118: void rtw_intr_tx(struct rtw_softc *, u_int16_t);
119: void rtw_intr_ioerror(struct rtw_softc *, u_int16_t);
120: void rtw_intr_timeout(struct rtw_softc *);
121: void rtw_stop(struct ifnet *, int);
122: void rtw_maxim_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
123: void rtw_philips_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
124: void rtw_rtl_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
125: void rtw_pwrstate0(struct rtw_softc *, enum rtw_pwrstate, int, int);
126: void rtw_join_bss(struct rtw_softc *, u_int8_t *, u_int16_t);
127: void rtw_set_access1(struct rtw_regs *, enum rtw_access);
128: int rtw_srom_parse(struct rtw_softc *);
129: int rtw_srom_read(struct rtw_regs *, u_int32_t, struct rtw_srom *,
130: const char *);
131: void rtw_set_rfprog(struct rtw_regs *, int, const char *);
132: u_int8_t rtw_chan2txpower(struct rtw_srom *, struct ieee80211com *,
133: struct ieee80211_channel *);
134: int rtw_txsoft_blk_init(struct rtw_txsoft_blk *);
135: int rtw_rxsoft_init_all(bus_dma_tag_t, struct rtw_rxsoft *,
136: int *, const char *);
137: void rtw_txsoft_release(bus_dma_tag_t, struct ieee80211com *,
138: struct rtw_txsoft *);
139: void rtw_txsofts_release(bus_dma_tag_t, struct ieee80211com *,
140: struct rtw_txsoft_blk *);
141: void rtw_hwring_setup(struct rtw_softc *);
142: int rtw_swring_setup(struct rtw_softc *);
143: void rtw_txdescs_reset(struct rtw_softc *);
144: void rtw_rfmd_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
145: int rtw_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
146: int rtw_tune(struct rtw_softc *);
147: void rtw_set_nettype(struct rtw_softc *, enum ieee80211_opmode);
148: int rtw_compute_duration1(int, int, uint32_t, int, struct rtw_duration *);
149: int rtw_compute_duration(struct ieee80211_frame *, int, uint32_t, int,
150: int, struct rtw_duration *, struct rtw_duration *, int *, int);
151: int rtw_init(struct ifnet *);
152: int rtw_ioctl(struct ifnet *, u_long, caddr_t);
153: int rtw_seg_too_short(bus_dmamap_t);
154: struct mbuf *rtw_dmamap_load_txbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
155: u_int, short *, const char *);
156: int rtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
157: int rtw_media_change(struct ifnet *);
158: int rtw_txsoft_blk_setup_all(struct rtw_softc *);
159: int rtw_rf_attach(struct rtw_softc *, int);
160: u_int8_t rtw_check_phydelay(struct rtw_regs *, u_int32_t);
161: int rtw_chip_reset1(struct rtw_regs *, const char *);
162: int rtw_chip_reset(struct rtw_regs *, const char *);
163: int rtw_recall_eeprom(struct rtw_regs *, const char *);
164: int rtw_reset(struct rtw_softc *);
165: void rtw_reset_oactive(struct rtw_softc *);
166: int rtw_txdesc_dmamaps_create(bus_dma_tag_t, struct rtw_txsoft *, u_int);
167: int rtw_rxdesc_dmamaps_create(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
168: void rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
169: void rtw_txdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_txsoft *, u_int);
170: void rtw_init_channels(enum rtw_locale, struct ieee80211_channel (*)[],
171: const char*);
172: void rtw_identify_country(struct rtw_regs *, enum rtw_locale *);
173: int rtw_identify_sta(struct rtw_regs *, u_int8_t (*)[], const char *);
174: void rtw_rxdescs_sync(struct rtw_rxdesc_blk *, int, int, int);
175: int rtw_rxsoft_alloc(bus_dma_tag_t, struct rtw_rxsoft *);
176: void rtw_collect_txpkt(struct rtw_softc *, struct rtw_txdesc_blk *,
177: struct rtw_txsoft *, int);
178: void rtw_collect_txring(struct rtw_softc *, struct rtw_txsoft_blk *,
179: struct rtw_txdesc_blk *, int);
180: void rtw_suspend_ticks(struct rtw_softc *);
181: void rtw_resume_ticks(struct rtw_softc *);
182: void rtw_enable_interrupts(struct rtw_softc *);
183: int rtw_dequeue(struct ifnet *, struct rtw_txsoft_blk **,
184: struct rtw_txdesc_blk **, struct mbuf **,
185: struct ieee80211_node **);
186: void rtw_establish_hooks(struct rtw_hooks *, const char *, void *);
187: void rtw_disestablish_hooks(struct rtw_hooks *, const char *, void *);
188: int rtw_txsoft_blk_setup(struct rtw_txsoft_blk *, u_int);
189: void rtw_rxdesc_init_all(struct rtw_rxdesc_blk *, struct rtw_rxsoft *,
190: int);
191: int rtw_txring_choose(struct rtw_softc *, struct rtw_txsoft_blk **,
192: struct rtw_txdesc_blk **, int);
193: u_int rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *);
194: struct mbuf *rtw_80211_dequeue(struct rtw_softc *, struct ifqueue *, int,
195: struct rtw_txsoft_blk **, struct rtw_txdesc_blk **,
196: struct ieee80211_node **, short *);
197: uint64_t rtw_tsf_extend(struct rtw_regs *, u_int32_t);
198: void rtw_ibss_merge(struct rtw_softc *, struct ieee80211_node *,
199: u_int32_t);
200: void rtw_idle(struct rtw_regs *);
201: void rtw_led_attach(struct rtw_led_state *, void *);
202: void rtw_led_init(struct rtw_regs *);
203: void rtw_led_slowblink(void *);
204: void rtw_led_fastblink(void *);
205: void rtw_led_set(struct rtw_led_state *, struct rtw_regs *, u_int);
206: void rtw_led_newstate(struct rtw_softc *, enum ieee80211_state);
207:
208: int rtw_phy_init(struct rtw_softc *);
209: int rtw_bbp_preinit(struct rtw_regs *, u_int, int, u_int);
210: int rtw_bbp_init(struct rtw_regs *, struct rtw_bbpset *, int,
211: int, u_int8_t, u_int);
212: void rtw_verify_syna(u_int, u_int32_t);
213: int rtw_sa2400_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
214: int rtw_sa2400_txpower(struct rtw_softc *, u_int8_t);
215: int rtw_sa2400_tune(struct rtw_softc *, u_int);
216: int rtw_sa2400_vcocal_start(struct rtw_softc *, int);
217: int rtw_sa2400_vco_calibration(struct rtw_softc *);
218: int rtw_sa2400_filter_calibration(struct rtw_softc *);
219: int rtw_sa2400_dc_calibration(struct rtw_softc *);
220: int rtw_sa2400_calibrate(struct rtw_softc *, u_int);
221: int rtw_sa2400_init(struct rtw_softc *, u_int, u_int8_t,
222: enum rtw_pwrstate);
223: int rtw_max2820_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
224: int rtw_max2820_init(struct rtw_softc *, u_int, u_int8_t,
225: enum rtw_pwrstate);
226: int rtw_max2820_txpower(struct rtw_softc *, u_int8_t);
227: int rtw_max2820_tune(struct rtw_softc *, u_int);
228: int rtw_rtl8225_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
229: int rtw_rtl8225_init(struct rtw_softc *, u_int, u_int8_t,
230: enum rtw_pwrstate);
231: int rtw_rtl8225_txpower(struct rtw_softc *, u_int8_t);
232: int rtw_rtl8225_tune(struct rtw_softc *, u_int);
233: int rtw_rtl8255_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
234: int rtw_rtl8255_init(struct rtw_softc *, u_int, u_int8_t,
235: enum rtw_pwrstate);
236: int rtw_rtl8255_txpower(struct rtw_softc *, u_int8_t);
237: int rtw_rtl8255_tune(struct rtw_softc *, u_int);
238: int rtw_grf5101_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
239: int rtw_grf5101_init(struct rtw_softc *, u_int, u_int8_t,
240: enum rtw_pwrstate);
241: int rtw_grf5101_txpower(struct rtw_softc *, u_int8_t);
242: int rtw_grf5101_tune(struct rtw_softc *, u_int);
243: int rtw_rf_hostwrite(struct rtw_softc *, u_int, u_int32_t);
244: int rtw_rf_macwrite(struct rtw_softc *, u_int, u_int32_t);
245: int rtw_bbp_write(struct rtw_regs *, u_int, u_int);
246: u_int32_t rtw_grf5101_host_crypt(u_int, u_int32_t);
247: u_int32_t rtw_maxim_swizzle(u_int, uint32_t);
248: u_int32_t rtw_grf5101_mac_crypt(u_int, u_int32_t);
249: void rtw_rf_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
250: void rtw_rf_rtl8225_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
251: int rtw_rf_macbangbits(struct rtw_regs *, u_int32_t);
252:
253: u_int8_t rtw_read8(void *, u_int32_t);
254: u_int16_t rtw_read16(void *, u_int32_t);
255: u_int32_t rtw_read32(void *, u_int32_t);
256: void rtw_write8(void *, u_int32_t, u_int8_t);
257: void rtw_write16(void *, u_int32_t, u_int16_t);
258: void rtw_write32(void *, u_int32_t, u_int32_t);
259: void rtw_barrier(void *, u_int32_t, u_int32_t, int);
260:
261: #ifdef RTW_DEBUG
262: void rtw_print_txdesc(struct rtw_softc *, const char *,
263: struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
264: const char *rtw_access_string(enum rtw_access);
265: void rtw_dump_rings(struct rtw_softc *);
266: void rtw_print_txdesc(struct rtw_softc *, const char *,
267: struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
268: #endif
269:
270: struct cfdriver rtw_cd = {
271: NULL, "rtw", DV_IFNET
272: };
273:
274: void
275: rtw_continuous_tx_enable(struct rtw_softc *sc, int enable)
276: {
277: struct rtw_regs *regs = &sc->sc_regs;
278:
279: u_int32_t tcr;
280: tcr = RTW_READ(regs, RTW_TCR);
281: tcr &= ~RTW_TCR_LBK_MASK;
282: if (enable)
283: tcr |= RTW_TCR_LBK_CONT;
284: else
285: tcr |= RTW_TCR_LBK_NORMAL;
286: RTW_WRITE(regs, RTW_TCR, tcr);
287: RTW_SYNC(regs, RTW_TCR, RTW_TCR);
288: rtw_set_access(regs, RTW_ACCESS_ANAPARM);
289: rtw_txdac_enable(sc, !enable);
290: rtw_set_access(regs, RTW_ACCESS_ANAPARM);/* XXX Voodoo from Linux. */
291: rtw_set_access(regs, RTW_ACCESS_NONE);
292: }
293:
294: #ifdef RTW_DEBUG
295: const char *
296: rtw_access_string(enum rtw_access access)
297: {
298: switch (access) {
299: case RTW_ACCESS_NONE:
300: return "none";
301: case RTW_ACCESS_CONFIG:
302: return "config";
303: case RTW_ACCESS_ANAPARM:
304: return "anaparm";
305: default:
306: return "unknown";
307: }
308: }
309: #endif
310:
311: void
312: rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess)
313: {
314: KASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
315: KASSERT(regs->r_access >= RTW_ACCESS_NONE &&
316: regs->r_access <= RTW_ACCESS_ANAPARM);
317:
318: if (naccess == regs->r_access)
319: return;
320:
321: switch (naccess) {
322: case RTW_ACCESS_NONE:
323: switch (regs->r_access) {
324: case RTW_ACCESS_ANAPARM:
325: rtw_anaparm_enable(regs, 0);
326: /*FALLTHROUGH*/
327: case RTW_ACCESS_CONFIG:
328: rtw_config0123_enable(regs, 0);
329: /*FALLTHROUGH*/
330: case RTW_ACCESS_NONE:
331: break;
332: }
333: break;
334: case RTW_ACCESS_CONFIG:
335: switch (regs->r_access) {
336: case RTW_ACCESS_NONE:
337: rtw_config0123_enable(regs, 1);
338: /*FALLTHROUGH*/
339: case RTW_ACCESS_CONFIG:
340: break;
341: case RTW_ACCESS_ANAPARM:
342: rtw_anaparm_enable(regs, 0);
343: break;
344: }
345: break;
346: case RTW_ACCESS_ANAPARM:
347: switch (regs->r_access) {
348: case RTW_ACCESS_NONE:
349: rtw_config0123_enable(regs, 1);
350: /*FALLTHROUGH*/
351: case RTW_ACCESS_CONFIG:
352: rtw_anaparm_enable(regs, 1);
353: /*FALLTHROUGH*/
354: case RTW_ACCESS_ANAPARM:
355: break;
356: }
357: break;
358: }
359: }
360:
361: void
362: rtw_set_access(struct rtw_regs *regs, enum rtw_access access)
363: {
364: rtw_set_access1(regs, access);
365: RTW_DPRINTF(RTW_DEBUG_ACCESS,
366: ("%s: access %s -> %s\n",__func__,
367: rtw_access_string(regs->r_access),
368: rtw_access_string(access)));
369: regs->r_access = access;
370: }
371:
372: /*
373: * Enable registers, switch register banks.
374: */
375: void
376: rtw_config0123_enable(struct rtw_regs *regs, int enable)
377: {
378: u_int8_t ecr;
379: ecr = RTW_READ8(regs, RTW_9346CR);
380: ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK);
381: if (enable)
382: ecr |= RTW_9346CR_EEM_CONFIG;
383: else {
384: RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3));
385: ecr |= RTW_9346CR_EEM_NORMAL;
386: }
387: RTW_WRITE8(regs, RTW_9346CR, ecr);
388: RTW_SYNC(regs, RTW_9346CR, RTW_9346CR);
389: }
390:
391: /* requires rtw_config0123_enable(, 1) */
392: void
393: rtw_anaparm_enable(struct rtw_regs *regs, int enable)
394: {
395: u_int8_t cfg3;
396:
397: cfg3 = RTW_READ8(regs, RTW_CONFIG3);
398: cfg3 |= RTW_CONFIG3_CLKRUNEN;
399: if (enable)
400: cfg3 |= RTW_CONFIG3_PARMEN;
401: else
402: cfg3 &= ~RTW_CONFIG3_PARMEN;
403: RTW_WRITE8(regs, RTW_CONFIG3, cfg3);
404: RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3);
405: }
406:
407: /* requires rtw_anaparm_enable(, 1) */
408: void
409: rtw_txdac_enable(struct rtw_softc *sc, int enable)
410: {
411: u_int32_t anaparm;
412: struct rtw_regs *regs = &sc->sc_regs;
413:
414: anaparm = RTW_READ(regs, RTW_ANAPARM_0);
415: if (enable)
416: anaparm &= ~RTW_ANAPARM_TXDACOFF;
417: else
418: anaparm |= RTW_ANAPARM_TXDACOFF;
419: RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
420: RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
421: }
422:
423: int
424: rtw_chip_reset1(struct rtw_regs *regs, const char *dvname)
425: {
426: u_int8_t cr;
427: int i;
428:
429: RTW_WRITE8(regs, RTW_CR, RTW_CR_RST);
430:
431: RTW_WBR(regs, RTW_CR, RTW_CR);
432:
433: for (i = 0; i < 1000; i++) {
434: if ((cr = RTW_READ8(regs, RTW_CR) & RTW_CR_RST) == 0) {
435: RTW_DPRINTF(RTW_DEBUG_RESET,
436: ("%s: reset in %dus\n", dvname, i));
437: return 0;
438: }
439: RTW_RBR(regs, RTW_CR, RTW_CR);
440: DELAY(10); /* 10us */
441: }
442:
443: printf("\n%s: reset failed\n", dvname);
444: return ETIMEDOUT;
445: }
446:
447: int
448: rtw_chip_reset(struct rtw_regs *regs, const char *dvname)
449: {
450: uint32_t tcr;
451:
452: /* from Linux driver */
453: tcr = RTW_TCR_CWMIN | RTW_TCR_MXDMA_2048 |
454: LSHIFT(7, RTW_TCR_SRL_MASK) | LSHIFT(7, RTW_TCR_LRL_MASK);
455:
456: RTW_WRITE(regs, RTW_TCR, tcr);
457:
458: RTW_WBW(regs, RTW_CR, RTW_TCR);
459:
460: return rtw_chip_reset1(regs, dvname);
461: }
462:
463: int
464: rtw_recall_eeprom(struct rtw_regs *regs, const char *dvname)
465: {
466: int i;
467: u_int8_t ecr;
468:
469: ecr = RTW_READ8(regs, RTW_9346CR);
470: ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD;
471: RTW_WRITE8(regs, RTW_9346CR, ecr);
472:
473: RTW_WBR(regs, RTW_9346CR, RTW_9346CR);
474:
475: /* wait 10ms for completion */
476: for (i = 0; i < 50; i++) {
477: ecr = RTW_READ8(regs, RTW_9346CR);
478: if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) {
479: RTW_DPRINTF(RTW_DEBUG_RESET,
480: ("%s: recall EEPROM in %dus\n", dvname, i * 200));
481: return (0);
482: }
483: RTW_RBR(regs, RTW_9346CR, RTW_9346CR);
484: DELAY(200);
485: }
486:
487: printf("\n%s: could not recall EEPROM in %dus\n", dvname, i * 200);
488:
489: return (ETIMEDOUT);
490: }
491:
492: int
493: rtw_reset(struct rtw_softc *sc)
494: {
495: int rc;
496: uint8_t config1;
497:
498: if ((rc = rtw_chip_reset(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
499: return rc;
500:
501: if ((rc = rtw_recall_eeprom(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
502: ;
503:
504: config1 = RTW_READ8(&sc->sc_regs, RTW_CONFIG1);
505: RTW_WRITE8(&sc->sc_regs, RTW_CONFIG1, config1 & ~RTW_CONFIG1_PMEN);
506: /* TBD turn off maximum power saving? */
507:
508: return 0;
509: }
510:
511: int
512: rtw_txdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
513: u_int ndescs)
514: {
515: int i, rc = 0;
516: for (i = 0; i < ndescs; i++) {
517: rc = bus_dmamap_create(dmat, MCLBYTES, RTW_MAXPKTSEGS, MCLBYTES,
518: 0, 0, &descs[i].ts_dmamap);
519: if (rc != 0)
520: break;
521: }
522: return rc;
523: }
524:
525: int
526: rtw_rxdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
527: u_int ndescs)
528: {
529: int i, rc = 0;
530: for (i = 0; i < ndescs; i++) {
531: rc = bus_dmamap_create(dmat, MCLBYTES, 1, MCLBYTES, 0, 0,
532: &descs[i].rs_dmamap);
533: if (rc != 0)
534: break;
535: }
536: return rc;
537: }
538:
539: void
540: rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
541: u_int ndescs)
542: {
543: int i;
544: for (i = 0; i < ndescs; i++) {
545: if (descs[i].rs_dmamap != NULL)
546: bus_dmamap_destroy(dmat, descs[i].rs_dmamap);
547: }
548: }
549:
550: void
551: rtw_txdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
552: u_int ndescs)
553: {
554: int i;
555: for (i = 0; i < ndescs; i++) {
556: if (descs[i].ts_dmamap != NULL)
557: bus_dmamap_destroy(dmat, descs[i].ts_dmamap);
558: }
559: }
560:
561: int
562: rtw_srom_parse(struct rtw_softc *sc)
563: {
564: int i;
565: struct rtw_srom *sr = &sc->sc_srom;
566: u_int32_t *flags = &sc->sc_flags;
567: u_int8_t *cs_threshold = &sc->sc_csthr;
568: int *rfchipid = &sc->sc_rfchipid;
569: u_int32_t *rcr = &sc->sc_rcr;
570: enum rtw_locale *locale = &sc->sc_locale;
571: u_int16_t version;
572: u_int8_t mac[IEEE80211_ADDR_LEN];
573:
574: *flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV);
575: *rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2);
576:
577: version = RTW_SR_GET16(sr, RTW_SR_VERSION);
578: RTW_DPRINTF(RTW_DEBUG_ATTACH,
579: ("%s: SROM %d.%d\n", sc->sc_dev.dv_xname, version >> 8,
580: version & 0xff));
581:
582: if (version <= 0x0101) {
583: printf(" is not understood, limping along with defaults ");
584: *flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV);
585: *cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT;
586: *rcr |= RTW_RCR_ENCS1;
587: *rfchipid = RTW_RFCHIPID_PHILIPS;
588: return 0;
589: }
590:
591: for (i = 0; i < IEEE80211_ADDR_LEN; i++)
592: mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i);
593:
594: RTW_DPRINTF(RTW_DEBUG_ATTACH,
595: ("%s: EEPROM MAC %s\n", sc->sc_dev.dv_xname, ether_sprintf(mac)));
596:
597: *cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR);
598:
599: if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW8180_CONFIG2_ANT) != 0)
600: *flags |= RTW_F_ANTDIV;
601:
602: /* Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
603: * to be reversed.
604: */
605: if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0)
606: *flags |= RTW_F_DIGPHY;
607: if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0)
608: *flags |= RTW_F_DFLANTB;
609:
610: *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM),
611: RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1);
612:
613: *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID);
614:
615: if (sc->sc_flags & RTW_F_RTL8185) {
616: *locale = RTW_LOCALE_UNKNOWN;
617: return (0);
618: }
619:
620: switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW8180_CONFIG0_GL_MASK) {
621: case RTW8180_CONFIG0_GL_USA:
622: *locale = RTW_LOCALE_USA;
623: break;
624: case RTW8180_CONFIG0_GL_EUROPE:
625: *locale = RTW_LOCALE_EUROPE;
626: break;
627: case RTW8180_CONFIG0_GL_JAPAN:
628: case RTW8180_CONFIG0_GL_JAPAN2:
629: *locale = RTW_LOCALE_JAPAN;
630: break;
631: default:
632: *locale = RTW_LOCALE_UNKNOWN;
633: break;
634: }
635: return 0;
636: }
637:
638: /* Returns -1 on failure. */
639: int
640: rtw_srom_read(struct rtw_regs *regs, u_int32_t flags, struct rtw_srom *sr,
641: const char *dvname)
642: {
643: int rc;
644: struct seeprom_descriptor sd;
645: u_int8_t ecr;
646:
647: bzero(&sd, sizeof(sd));
648:
649: ecr = RTW_READ8(regs, RTW_9346CR);
650:
651: if ((flags & RTW_F_9356SROM) != 0) {
652: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c56 SROM\n", dvname));
653: sr->sr_size = 256;
654: sd.sd_chip = C56_66;
655: } else {
656: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c46 SROM\n", dvname));
657: sr->sr_size = 128;
658: sd.sd_chip = C46;
659: }
660:
661: ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK |
662: RTW_9346CR_EEM_MASK | RTW_9346CR_EECS);
663: ecr |= RTW_9346CR_EEM_PROGRAM;
664:
665: RTW_WRITE8(regs, RTW_9346CR, ecr);
666:
667: sr->sr_content = malloc(sr->sr_size, M_DEVBUF, M_NOWAIT);
668:
669: if (sr->sr_content == NULL) {
670: printf("%s: unable to allocate SROM buffer\n", dvname);
671: return ENOMEM;
672: }
673:
674: bzero(sr->sr_content, sr->sr_size);
675:
676: /* RTL8180 has a single 8-bit register for controlling the
677: * 93cx6 SROM. There is no "ready" bit. The RTL8180
678: * input/output sense is the reverse of read_seeprom's.
679: */
680: sd.sd_tag = regs->r_bt;
681: sd.sd_bsh = regs->r_bh;
682: sd.sd_regsize = 1;
683: sd.sd_control_offset = RTW_9346CR;
684: sd.sd_status_offset = RTW_9346CR;
685: sd.sd_dataout_offset = RTW_9346CR;
686: sd.sd_CK = RTW_9346CR_EESK;
687: sd.sd_CS = RTW_9346CR_EECS;
688: sd.sd_DI = RTW_9346CR_EEDO;
689: sd.sd_DO = RTW_9346CR_EEDI;
690: /* make read_seeprom enter EEPROM read/write mode */
691: sd.sd_MS = ecr;
692: sd.sd_RDY = 0;
693:
694: /* TBD bus barriers */
695: if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
696: printf("\n%s: could not read SROM\n", dvname);
697: free(sr->sr_content, M_DEVBUF);
698: sr->sr_content = NULL;
699: return -1; /* XXX */
700: }
701:
702: /* end EEPROM read/write mode */
703: RTW_WRITE8(regs, RTW_9346CR,
704: (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL);
705: RTW_WBRW(regs, RTW_9346CR, RTW_9346CR);
706:
707: if ((rc = rtw_recall_eeprom(regs, dvname)) != 0)
708: return rc;
709:
710: #ifdef RTW_DEBUG
711: {
712: int i;
713: RTW_DPRINTF(RTW_DEBUG_ATTACH,
714: ("\n%s: serial ROM:\n\t", dvname));
715: for (i = 0; i < sr->sr_size/2; i++) {
716: if (((i % 8) == 0) && (i != 0))
717: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n\t"));
718: RTW_DPRINTF(RTW_DEBUG_ATTACH,
719: (" %04x", sr->sr_content[i]));
720: }
721: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n"));
722: }
723: #endif /* RTW_DEBUG */
724: return 0;
725: }
726:
727: void
728: rtw_set_rfprog(struct rtw_regs *regs, int rfchipid,
729: const char *dvname)
730: {
731: u_int8_t cfg4;
732: const char *method;
733:
734: cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
735:
736: switch (rfchipid) {
737: default:
738: cfg4 |= LSHIFT(rtw_rfprog_fallback, RTW_CONFIG4_RFTYPE_MASK);
739: method = "fallback";
740: break;
741: case RTW_RFCHIPID_INTERSIL:
742: cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL;
743: method = "Intersil";
744: break;
745: case RTW_RFCHIPID_PHILIPS:
746: cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
747: method = "Philips";
748: break;
749: case RTW_RFCHIPID_RFMD2948:
750: cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
751: method = "RFMD";
752: break;
753: }
754:
755: RTW_WRITE8(regs, RTW_CONFIG4, cfg4);
756:
757: RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4);
758:
759: RTW_DPRINTF(RTW_DEBUG_INIT,
760: ("%s: %s RF programming method, %#02x\n", dvname, method,
761: RTW_READ8(regs, RTW_CONFIG4)));
762: }
763:
764: void
765: rtw_init_channels(enum rtw_locale locale,
766: struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1],
767: const char *dvname)
768: {
769: int i;
770: const char *name = NULL;
771: #define ADD_CHANNEL(_chans, _chan) do { \
772: (*_chans)[_chan].ic_flags = IEEE80211_CHAN_B; \
773: (*_chans)[_chan].ic_freq = \
774: ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ic_flags);\
775: } while (0)
776:
777: switch (locale) {
778: case RTW_LOCALE_USA: /* 1-11 */
779: name = "USA";
780: for (i = 1; i <= 11; i++)
781: ADD_CHANNEL(chans, i);
782: break;
783: case RTW_LOCALE_JAPAN: /* 1-14 */
784: name = "Japan";
785: ADD_CHANNEL(chans, 14);
786: for (i = 1; i <= 14; i++)
787: ADD_CHANNEL(chans, i);
788: break;
789: case RTW_LOCALE_EUROPE: /* 1-13 */
790: name = "Europe";
791: for (i = 1; i <= 13; i++)
792: ADD_CHANNEL(chans, i);
793: break;
794: default: /* 10-11 allowed by most countries */
795: name = "<unknown>";
796: for (i = 10; i <= 11; i++)
797: ADD_CHANNEL(chans, i);
798: break;
799: }
800: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: Geographic Location %s\n",
801: dvname, name));
802: #undef ADD_CHANNEL
803: }
804:
805: void
806: rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale)
807: {
808: u_int8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
809:
810: switch (cfg0 & RTW8180_CONFIG0_GL_MASK) {
811: case RTW8180_CONFIG0_GL_USA:
812: *locale = RTW_LOCALE_USA;
813: break;
814: case RTW8180_CONFIG0_GL_JAPAN:
815: case RTW8180_CONFIG0_GL_JAPAN2:
816: *locale = RTW_LOCALE_JAPAN;
817: break;
818: case RTW8180_CONFIG0_GL_EUROPE:
819: *locale = RTW_LOCALE_EUROPE;
820: break;
821: default:
822: *locale = RTW_LOCALE_UNKNOWN;
823: break;
824: }
825: }
826:
827: int
828: rtw_identify_sta(struct rtw_regs *regs, u_int8_t (*addr)[IEEE80211_ADDR_LEN],
829: const char *dvname)
830: {
831: static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
832: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
833: };
834: u_int32_t idr0 = RTW_READ(regs, RTW_IDR0),
835: idr1 = RTW_READ(regs, RTW_IDR1);
836:
837: (*addr)[0] = MASK_AND_RSHIFT(idr0, BITS(0, 7));
838: (*addr)[1] = MASK_AND_RSHIFT(idr0, BITS(8, 15));
839: (*addr)[2] = MASK_AND_RSHIFT(idr0, BITS(16, 23));
840: (*addr)[3] = MASK_AND_RSHIFT(idr0, BITS(24 ,31));
841:
842: (*addr)[4] = MASK_AND_RSHIFT(idr1, BITS(0, 7));
843: (*addr)[5] = MASK_AND_RSHIFT(idr1, BITS(8, 15));
844:
845: if (IEEE80211_ADDR_EQ(addr, empty_macaddr)) {
846: printf("\n%s: could not get mac address, attach failed\n",
847: dvname);
848: return ENXIO;
849: }
850:
851: printf("address %s\n", ether_sprintf(*addr));
852:
853: return 0;
854: }
855:
856: u_int8_t
857: rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
858: struct ieee80211_channel *chan)
859: {
860: u_int idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
861: KASSERT2(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14,
862: ("%s: channel %d out of range", __func__,
863: idx - RTW_SR_TXPOWER1 + 1));
864: return RTW_SR_GET(sr, idx);
865: }
866:
867: void
868: rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *tdb)
869: {
870: int pri;
871: /* nfree: the number of free descriptors in each ring.
872: * The beacon ring is a special case: I do not let the
873: * driver use all of the descriptors on the beacon ring.
874: * The reasons are two-fold:
875: *
876: * (1) A BEACON descriptor's OWN bit is (apparently) not
877: * updated, so the driver cannot easily know if the descriptor
878: * belongs to it, or if it is racing the NIC. If the NIC
879: * does not OWN every descriptor, then the driver can safely
880: * update the descriptors when RTW_TBDA points at tdb_next.
881: *
882: * (2) I hope that the NIC will process more than one BEACON
883: * descriptor in a single beacon interval, since that will
884: * enable multiple-BSS support. Since the NIC does not
885: * clear the OWN bit, there is no natural place for it to
886: * stop processing BEACON desciptors. Maybe it will *not*
887: * stop processing them! I do not want to chance the NIC
888: * looping around and around a saturated beacon ring, so
889: * I will leave one descriptor unOWNed at all times.
890: */
891: u_int nfree[RTW_NTXPRI] =
892: {RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI,
893: RTW_NTXDESCBCN - 1};
894:
895: for (pri = 0; pri < RTW_NTXPRI; pri++) {
896: tdb[pri].tdb_nfree = nfree[pri];
897: tdb[pri].tdb_next = 0;
898: }
899: }
900:
901: int
902: rtw_txsoft_blk_init(struct rtw_txsoft_blk *tsb)
903: {
904: int i;
905: struct rtw_txsoft *ts;
906:
907: SIMPLEQ_INIT(&tsb->tsb_dirtyq);
908: SIMPLEQ_INIT(&tsb->tsb_freeq);
909: for (i = 0; i < tsb->tsb_ndesc; i++) {
910: ts = &tsb->tsb_desc[i];
911: ts->ts_mbuf = NULL;
912: SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
913: }
914: tsb->tsb_tx_timer = 0;
915: return 0;
916: }
917:
918: void
919: rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *tsb)
920: {
921: int pri;
922: for (pri = 0; pri < RTW_NTXPRI; pri++)
923: rtw_txsoft_blk_init(&tsb[pri]);
924: }
925:
926: void
927: rtw_rxdescs_sync(struct rtw_rxdesc_blk *rdb, int desc0, int nsync, int ops)
928: {
929: KASSERT(nsync <= rdb->rdb_ndesc);
930: /* sync to end of ring */
931: if (desc0 + nsync > rdb->rdb_ndesc) {
932: bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
933: offsetof(struct rtw_descs, hd_rx[desc0]),
934: sizeof(struct rtw_rxdesc) * (rdb->rdb_ndesc - desc0), ops);
935: nsync -= (rdb->rdb_ndesc - desc0);
936: desc0 = 0;
937: }
938:
939: KASSERT(desc0 < rdb->rdb_ndesc);
940: KASSERT(nsync <= rdb->rdb_ndesc);
941: KASSERT(desc0 + nsync <= rdb->rdb_ndesc);
942:
943: /* sync what remains */
944: bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
945: offsetof(struct rtw_descs, hd_rx[desc0]),
946: sizeof(struct rtw_rxdesc) * nsync, ops);
947: }
948:
949: void
950: rtw_txdescs_sync(struct rtw_txdesc_blk *tdb, u_int desc0, u_int nsync, int ops)
951: {
952: /* sync to end of ring */
953: if (desc0 + nsync > tdb->tdb_ndesc) {
954: bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
955: tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
956: sizeof(struct rtw_txdesc) * (tdb->tdb_ndesc - desc0),
957: ops);
958: nsync -= (tdb->tdb_ndesc - desc0);
959: desc0 = 0;
960: }
961:
962: /* sync what remains */
963: bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
964: tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
965: sizeof(struct rtw_txdesc) * nsync, ops);
966: }
967:
968: void
969: rtw_rxbufs_release(bus_dma_tag_t dmat, struct rtw_rxsoft *desc)
970: {
971: int i;
972: struct rtw_rxsoft *rs;
973:
974: for (i = 0; i < RTW_RXQLEN; i++) {
975: rs = &desc[i];
976: if (rs->rs_mbuf == NULL)
977: continue;
978: bus_dmamap_sync(dmat, rs->rs_dmamap, 0,
979: rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
980: bus_dmamap_unload(dmat, rs->rs_dmamap);
981: m_freem(rs->rs_mbuf);
982: rs->rs_mbuf = NULL;
983: }
984: }
985:
986: int
987: rtw_rxsoft_alloc(bus_dma_tag_t dmat, struct rtw_rxsoft *rs)
988: {
989: int rc;
990: struct mbuf *m;
991:
992: MGETHDR(m, M_DONTWAIT, MT_DATA);
993: if (m == NULL)
994: return ENOBUFS;
995:
996: MCLGET(m, M_DONTWAIT);
997: if ((m->m_flags & M_EXT) == 0) {
998: m_freem(m);
999: return ENOBUFS;
1000: }
1001:
1002: m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
1003:
1004: if (rs->rs_mbuf != NULL)
1005: bus_dmamap_unload(dmat, rs->rs_dmamap);
1006:
1007: rs->rs_mbuf = NULL;
1008:
1009: rc = bus_dmamap_load_mbuf(dmat, rs->rs_dmamap, m, BUS_DMA_NOWAIT);
1010: if (rc != 0) {
1011: m_freem(m);
1012: return -1;
1013: }
1014:
1015: rs->rs_mbuf = m;
1016:
1017: return 0;
1018: }
1019:
1020: int
1021: rtw_rxsoft_init_all(bus_dma_tag_t dmat, struct rtw_rxsoft *desc,
1022: int *ndesc, const char *dvname)
1023: {
1024: int i, rc = 0;
1025: struct rtw_rxsoft *rs;
1026:
1027: for (i = 0; i < RTW_RXQLEN; i++) {
1028: rs = &desc[i];
1029: /* we're in rtw_init, so there should be no mbufs allocated */
1030: KASSERT(rs->rs_mbuf == NULL);
1031: #ifdef RTW_DEBUG
1032: if (i == rtw_rxbufs_limit) {
1033: printf("%s: TEST hit %d-buffer limit\n", dvname, i);
1034: rc = ENOBUFS;
1035: break;
1036: }
1037: #endif /* RTW_DEBUG */
1038: if ((rc = rtw_rxsoft_alloc(dmat, rs)) != 0) {
1039: printf("%s: rtw_rxsoft_alloc failed, %d buffers, "
1040: "rc %d\n", dvname, i, rc);
1041: break;
1042: }
1043: }
1044: *ndesc = i;
1045: return rc;
1046: }
1047:
1048: void
1049: rtw_rxdesc_init(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *rs,
1050: int idx, int kick)
1051: {
1052: int is_last = (idx == rdb->rdb_ndesc - 1);
1053: uint32_t ctl, octl, obuf;
1054: struct rtw_rxdesc *rd = &rdb->rdb_desc[idx];
1055:
1056: obuf = rd->rd_buf;
1057: rd->rd_buf = htole32(rs->rs_dmamap->dm_segs[0].ds_addr);
1058:
1059: ctl = LSHIFT(rs->rs_mbuf->m_len, RTW_RXCTL_LENGTH_MASK) |
1060: RTW_RXCTL_OWN | RTW_RXCTL_FS | RTW_RXCTL_LS;
1061:
1062: if (is_last)
1063: ctl |= RTW_RXCTL_EOR;
1064:
1065: octl = rd->rd_ctl;
1066: rd->rd_ctl = htole32(ctl);
1067:
1068: RTW_DPRINTF(kick ? (RTW_DEBUG_RECV_DESC | RTW_DEBUG_IO_KICK)
1069: : RTW_DEBUG_RECV_DESC,
1070: ("%s: rd %p buf %08x -> %08x ctl %08x -> %08x\n", __func__, rd,
1071: letoh32(obuf), letoh32(rd->rd_buf), letoh32(octl),
1072: letoh32(rd->rd_ctl)));
1073:
1074: /* sync the mbuf */
1075: bus_dmamap_sync(rdb->rdb_dmat, rs->rs_dmamap, 0,
1076: rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1077:
1078: /* sync the descriptor */
1079: bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
1080: RTW_DESC_OFFSET(hd_rx, idx), sizeof(struct rtw_rxdesc),
1081: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1082: }
1083:
1084: void
1085: rtw_rxdesc_init_all(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *ctl,
1086: int kick)
1087: {
1088: int i;
1089: struct rtw_rxdesc *rd;
1090: struct rtw_rxsoft *rs;
1091:
1092: for (i = 0; i < rdb->rdb_ndesc; i++) {
1093: rd = &rdb->rdb_desc[i];
1094: rs = &ctl[i];
1095: rtw_rxdesc_init(rdb, rs, i, kick);
1096: }
1097: }
1098:
1099: void
1100: rtw_io_enable(struct rtw_regs *regs, u_int8_t flags, int enable)
1101: {
1102: u_int8_t cr;
1103:
1104: RTW_DPRINTF(RTW_DEBUG_IOSTATE, ("%s: %s 0x%02x\n", __func__,
1105: enable ? "enable" : "disable", flags));
1106:
1107: cr = RTW_READ8(regs, RTW_CR);
1108:
1109: /* XXX reference source does not enable MULRW */
1110: #if 0
1111: /* enable PCI Read/Write Multiple */
1112: cr |= RTW_CR_MULRW;
1113: #endif
1114:
1115: RTW_RBW(regs, RTW_CR, RTW_CR); /* XXX paranoia? */
1116: if (enable)
1117: cr |= flags;
1118: else
1119: cr &= ~flags;
1120: RTW_WRITE8(regs, RTW_CR, cr);
1121: RTW_SYNC(regs, RTW_CR, RTW_CR);
1122: }
1123:
1124: void
1125: rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
1126: {
1127: #define IS_BEACON(__fc0) \
1128: ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
1129: (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
1130:
1131: static const int ratetbl[4] = {2, 4, 11, 22}; /* convert rates:
1132: * hardware -> net80211
1133: */
1134: u_int next, nproc = 0;
1135: int hwrate, len, rate, rssi, sq;
1136: u_int32_t hrssi, hstat, htsfth, htsftl;
1137: struct rtw_rxdesc *rd;
1138: struct rtw_rxsoft *rs;
1139: struct rtw_rxdesc_blk *rdb;
1140: struct mbuf *m;
1141:
1142: struct ieee80211_node *ni;
1143: struct ieee80211_frame *wh;
1144:
1145: rdb = &sc->sc_rxdesc_blk;
1146:
1147: KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
1148:
1149: for (next = rdb->rdb_next; ; next = (next + 1) % rdb->rdb_ndesc) {
1150: rtw_rxdescs_sync(rdb, next, 1,
1151: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1152: rd = &rdb->rdb_desc[next];
1153: rs = &sc->sc_rxsoft[next];
1154:
1155: hstat = letoh32(rd->rd_stat);
1156: hrssi = letoh32(rd->rd_rssi);
1157: htsfth = letoh32(rd->rd_tsfth);
1158: htsftl = letoh32(rd->rd_tsftl);
1159:
1160: RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
1161: ("%s: rxdesc[%d] hstat %08x hrssi %08x htsft %08x%08x\n",
1162: __func__, next, hstat, hrssi, htsfth, htsftl));
1163:
1164: ++nproc;
1165:
1166: /* still belongs to NIC */
1167: if ((hstat & RTW_RXSTAT_OWN) != 0) {
1168: if (nproc > 1)
1169: break;
1170:
1171: /* sometimes the NIC skips to the 0th descriptor */
1172: rtw_rxdescs_sync(rdb, 0, 1,
1173: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1174: rd = &rdb->rdb_desc[0];
1175: if ((rd->rd_stat & htole32(RTW_RXSTAT_OWN)) != 0)
1176: break;
1177: RTW_DPRINTF(RTW_DEBUG_BUGS,
1178: ("%s: NIC skipped from rxdesc[%u] to rxdesc[0]\n",
1179: sc->sc_dev.dv_xname, next));
1180: next = rdb->rdb_ndesc - 1;
1181: continue;
1182: }
1183:
1184: #ifdef RTW_DEBUG
1185: #define PRINTSTAT(flag) do { \
1186: if ((hstat & flag) != 0) { \
1187: printf("%s" #flag, delim); \
1188: delim = ","; \
1189: } \
1190: } while (0)
1191: if ((rtw_debug & RTW_DEBUG_RECV_DESC) != 0) {
1192: const char *delim = "<";
1193: printf("%s: ", sc->sc_dev.dv_xname);
1194: if ((hstat & RTW_RXSTAT_DEBUG) != 0) {
1195: printf("status %08x", hstat);
1196: PRINTSTAT(RTW_RXSTAT_SPLCP);
1197: PRINTSTAT(RTW_RXSTAT_MAR);
1198: PRINTSTAT(RTW_RXSTAT_PAR);
1199: PRINTSTAT(RTW_RXSTAT_BAR);
1200: PRINTSTAT(RTW_RXSTAT_PWRMGT);
1201: PRINTSTAT(RTW_RXSTAT_CRC32);
1202: PRINTSTAT(RTW_RXSTAT_ICV);
1203: printf(">, ");
1204: }
1205: }
1206: #undef PRINTSTAT
1207: #endif /* RTW_DEBUG */
1208:
1209: if ((hstat & RTW_RXSTAT_IOERROR) != 0) {
1210: printf("%s: DMA error/FIFO overflow %08x, "
1211: "rx descriptor %d\n", sc->sc_dev.dv_xname,
1212: hstat & RTW_RXSTAT_IOERROR, next);
1213: sc->sc_if.if_ierrors++;
1214: goto next;
1215: }
1216:
1217: len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
1218: if (len < IEEE80211_MIN_LEN) {
1219: sc->sc_ic.ic_stats.is_rx_tooshort++;
1220: goto next;
1221: }
1222:
1223: /* CRC is included with the packet; trim it off. */
1224: len -= IEEE80211_CRC_LEN;
1225:
1226: hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);
1227: if (hwrate >= sizeof(ratetbl) / sizeof(ratetbl[0])) {
1228: printf("%s: unknown rate #%d\n", sc->sc_dev.dv_xname,
1229: MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK));
1230: sc->sc_if.if_ierrors++;
1231: goto next;
1232: }
1233: rate = ratetbl[hwrate];
1234:
1235: #ifdef RTW_DEBUG
1236: RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
1237: ("rate %d.%d Mb/s, time %08x%08x\n", (rate * 5) / 10,
1238: (rate * 5) % 10, htsfth, htsftl));
1239: #endif /* RTW_DEBUG */
1240:
1241: if ((hstat & RTW_RXSTAT_RES) != 0 &&
1242: sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
1243: goto next;
1244:
1245: /* if bad flags, skip descriptor */
1246: if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
1247: printf("%s: too many rx segments\n",
1248: sc->sc_dev.dv_xname);
1249: goto next;
1250: }
1251:
1252: bus_dmamap_sync(sc->sc_dmat, rs->rs_dmamap, 0,
1253: rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1254:
1255: m = rs->rs_mbuf;
1256:
1257: /* if temporarily out of memory, re-use mbuf */
1258: switch (rtw_rxsoft_alloc(sc->sc_dmat, rs)) {
1259: case 0:
1260: break;
1261: case ENOBUFS:
1262: printf("%s: rtw_rxsoft_alloc(, %d) failed, "
1263: "dropping this packet\n", sc->sc_dev.dv_xname,
1264: next);
1265: goto next;
1266: default:
1267: /* XXX shorten rx ring, instead? */
1268: panic("%s: could not load DMA map",
1269: sc->sc_dev.dv_xname);
1270: }
1271:
1272: if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
1273: rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);
1274: else {
1275: rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);
1276: /* TBD find out each front-end's LNA gain in the
1277: * front-end's units
1278: */
1279: if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
1280: rssi |= 0x80;
1281: }
1282:
1283: sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ);
1284:
1285: /*
1286: * Note well: now we cannot recycle the rs_mbuf unless
1287: * we restore its original length.
1288: */
1289: m->m_pkthdr.rcvif = &sc->sc_if;
1290: m->m_pkthdr.len = m->m_len = len;
1291:
1292: wh = mtod(m, struct ieee80211_frame *);
1293:
1294: if (!IS_BEACON(wh->i_fc[0]))
1295: sc->sc_led_state.ls_event |= RTW_LED_S_RX;
1296: /* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
1297: ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
1298:
1299: sc->sc_tsfth = htsfth;
1300:
1301: #ifdef RTW_DEBUG
1302: if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
1303: (IFF_DEBUG|IFF_LINK2)) {
1304: ieee80211_dump_pkt(mtod(m, uint8_t *), m->m_pkthdr.len,
1305: rate, rssi);
1306: }
1307: #endif /* RTW_DEBUG */
1308:
1309: #if NBPFILTER > 0
1310: if (sc->sc_radiobpf != NULL) {
1311: struct mbuf mb;
1312: struct ieee80211com *ic = &sc->sc_ic;
1313: struct rtw_rx_radiotap_header *rr = &sc->sc_rxtap;
1314:
1315: rr->rr_tsft =
1316: htole64(((uint64_t)htsfth << 32) | htsftl);
1317:
1318: if ((hstat & RTW_RXSTAT_SPLCP) != 0)
1319: rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE;
1320:
1321: rr->rr_flags = 0;
1322: rr->rr_rate = rate;
1323: rr->rr_chan_freq =
1324: htole16(ic->ic_bss->ni_chan->ic_freq);
1325: rr->rr_chan_flags =
1326: htole16(ic->ic_bss->ni_chan->ic_flags);
1327: rr->rr_antsignal = rssi;
1328: rr->rr_barker_lock = htole16(sq);
1329:
1330: mb.m_data = (caddr_t)rr;
1331: mb.m_len = sizeof(sc->sc_rxtapu);
1332: mb.m_next = m;
1333: mb.m_nextpkt = NULL;
1334: mb.m_type = 0;
1335: mb.m_flags = 0;
1336: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
1337: }
1338: #endif /* NPBFILTER > 0 */
1339:
1340: ieee80211_input(&sc->sc_if, m, ni, rssi, htsftl);
1341: ieee80211_release_node(&sc->sc_ic, ni);
1342: next:
1343: rtw_rxdesc_init(rdb, rs, next, 0);
1344: }
1345: rdb->rdb_next = next;
1346:
1347: KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
1348:
1349: /*
1350: * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
1351: * without calling if_start().
1352: */
1353: if (!IFQ_IS_EMPTY(&sc->sc_if.if_snd) &&
1354: !(sc->sc_if.if_flags & IFF_OACTIVE))
1355: (*sc->sc_if.if_start)(&sc->sc_if);
1356:
1357: return;
1358: #undef IS_BEACON
1359: }
1360:
1361: void
1362: rtw_txsoft_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
1363: struct rtw_txsoft *ts)
1364: {
1365: struct mbuf *m;
1366: struct ieee80211_node *ni;
1367:
1368: m = ts->ts_mbuf;
1369: ni = ts->ts_ni;
1370: KASSERT(m != NULL);
1371: KASSERT(ni != NULL);
1372: ts->ts_mbuf = NULL;
1373: ts->ts_ni = NULL;
1374:
1375: bus_dmamap_sync(dmat, ts->ts_dmamap, 0, ts->ts_dmamap->dm_mapsize,
1376: BUS_DMASYNC_POSTWRITE);
1377: bus_dmamap_unload(dmat, ts->ts_dmamap);
1378: m_freem(m);
1379: ieee80211_release_node(ic, ni);
1380: }
1381:
1382: void
1383: rtw_txsofts_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
1384: struct rtw_txsoft_blk *tsb)
1385: {
1386: struct rtw_txsoft *ts;
1387:
1388: while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
1389: rtw_txsoft_release(dmat, ic, ts);
1390: SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
1391: SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
1392: }
1393: tsb->tsb_tx_timer = 0;
1394: }
1395:
1396: void
1397: rtw_collect_txpkt(struct rtw_softc *sc, struct rtw_txdesc_blk *tdb,
1398: struct rtw_txsoft *ts, int ndesc)
1399: {
1400: uint32_t hstat;
1401: int data_retry, rts_retry;
1402: struct rtw_txdesc *tdn;
1403: const char *condstring;
1404:
1405: rtw_txsoft_release(sc->sc_dmat, &sc->sc_ic, ts);
1406:
1407: tdb->tdb_nfree += ndesc;
1408:
1409: tdn = &tdb->tdb_desc[ts->ts_last];
1410:
1411: hstat = letoh32(tdn->td_stat);
1412: rts_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_RTSRETRY_MASK);
1413: data_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_DRC_MASK);
1414:
1415: sc->sc_if.if_collisions += rts_retry + data_retry;
1416:
1417: if ((hstat & RTW_TXSTAT_TOK) != 0)
1418: condstring = "ok";
1419: else {
1420: sc->sc_if.if_oerrors++;
1421: condstring = "error";
1422: }
1423:
1424: DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
1425: ("%s: ts %p txdesc[%d, %d] %s tries rts %u data %u\n",
1426: sc->sc_dev.dv_xname, ts, ts->ts_first, ts->ts_last,
1427: condstring, rts_retry, data_retry));
1428: }
1429:
1430: void
1431: rtw_reset_oactive(struct rtw_softc *sc)
1432: {
1433: short oflags;
1434: int pri;
1435: struct rtw_txsoft_blk *tsb;
1436: struct rtw_txdesc_blk *tdb;
1437: oflags = sc->sc_if.if_flags;
1438: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1439: tsb = &sc->sc_txsoft_blk[pri];
1440: tdb = &sc->sc_txdesc_blk[pri];
1441: if (!SIMPLEQ_EMPTY(&tsb->tsb_freeq) && tdb->tdb_nfree > 0)
1442: sc->sc_if.if_flags &= ~IFF_OACTIVE;
1443: }
1444: if (oflags != sc->sc_if.if_flags) {
1445: DPRINTF(sc, RTW_DEBUG_OACTIVE,
1446: ("%s: reset OACTIVE\n", __func__));
1447: }
1448: }
1449:
1450: /* Collect transmitted packets. */
1451: void
1452: rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb,
1453: struct rtw_txdesc_blk *tdb, int force)
1454: {
1455: int ndesc;
1456: struct rtw_txsoft *ts;
1457:
1458: while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
1459: ndesc = 1 + ts->ts_last - ts->ts_first;
1460: if (ts->ts_last < ts->ts_first)
1461: ndesc += tdb->tdb_ndesc;
1462:
1463: KASSERT(ndesc > 0);
1464:
1465: rtw_txdescs_sync(tdb, ts->ts_first, ndesc,
1466: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1467:
1468: if (force) {
1469: int i;
1470: for (i = ts->ts_first; ; i = RTW_NEXT_IDX(tdb, i)) {
1471: tdb->tdb_desc[i].td_stat &=
1472: ~htole32(RTW_TXSTAT_OWN);
1473: if (i == ts->ts_last)
1474: break;
1475: }
1476: rtw_txdescs_sync(tdb, ts->ts_first, ndesc,
1477: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1478: } else if ((tdb->tdb_desc[ts->ts_last].td_stat &
1479: htole32(RTW_TXSTAT_OWN)) != 0)
1480: break;
1481:
1482: rtw_collect_txpkt(sc, tdb, ts, ndesc);
1483: SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
1484: SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
1485: }
1486: /* no more pending transmissions, cancel watchdog */
1487: if (ts == NULL)
1488: tsb->tsb_tx_timer = 0;
1489: rtw_reset_oactive(sc);
1490: }
1491:
1492: void
1493: rtw_intr_tx(struct rtw_softc *sc, u_int16_t isr)
1494: {
1495: int pri;
1496: struct rtw_txsoft_blk *tsb;
1497: struct rtw_txdesc_blk *tdb;
1498:
1499: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1500: tsb = &sc->sc_txsoft_blk[pri];
1501: tdb = &sc->sc_txdesc_blk[pri];
1502:
1503: rtw_collect_txring(sc, tsb, tdb, 0);
1504:
1505: }
1506:
1507: if ((isr & RTW_INTR_TX) != 0)
1508: rtw_start(&sc->sc_if);
1509: }
1510:
1511: void
1512: rtw_intr_beacon(struct rtw_softc *sc, u_int16_t isr)
1513: {
1514: u_int next;
1515: uint32_t tsfth, tsftl;
1516: struct ieee80211com *ic;
1517: struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[RTW_TXPRIBCN];
1518: struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[RTW_TXPRIBCN];
1519: struct mbuf *m;
1520:
1521: tsfth = RTW_READ(&sc->sc_regs, RTW_TSFTRH);
1522: tsftl = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
1523:
1524: if ((isr & (RTW_INTR_TBDOK|RTW_INTR_TBDER)) != 0) {
1525: next = rtw_txring_next(&sc->sc_regs, tdb);
1526: RTW_DPRINTF(RTW_DEBUG_BEACON,
1527: ("%s: beacon ring %sprocessed, isr = %#04hx"
1528: ", next %u expected %u, %llu\n", __func__,
1529: (next == tdb->tdb_next) ? "" : "un", isr, next,
1530: tdb->tdb_next, (uint64_t)tsfth << 32 | tsftl));
1531: if ((RTW_READ8(&sc->sc_regs, RTW_TPPOLL) & RTW_TPPOLL_BQ) == 0){
1532: rtw_collect_txring(sc, tsb, tdb, 1);
1533: tdb->tdb_next = 0;
1534: }
1535: }
1536: /* Start beacon transmission. */
1537:
1538: if ((isr & RTW_INTR_BCNINT) != 0 &&
1539: sc->sc_ic.ic_state == IEEE80211_S_RUN &&
1540: SIMPLEQ_EMPTY(&tsb->tsb_dirtyq)) {
1541: RTW_DPRINTF(RTW_DEBUG_BEACON,
1542: ("%s: beacon prep. time, isr = %#04hx"
1543: ", %16llu\n", __func__, isr,
1544: (uint64_t)tsfth << 32 | tsftl));
1545: ic = &sc->sc_ic;
1546: if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss)) != NULL) {
1547: RTW_DPRINTF(RTW_DEBUG_BEACON,
1548: ("%s: m %p len %u\n", __func__, m, m->m_len));
1549: }
1550:
1551: if (m == NULL) {
1552: printf("%s: could not allocate beacon\n",
1553: sc->sc_dev.dv_xname);
1554: return;
1555: }
1556: m->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ic->ic_bss);
1557: IF_ENQUEUE(&sc->sc_beaconq, m);
1558: rtw_start(&sc->sc_if);
1559: }
1560: }
1561:
1562: void
1563: rtw_intr_atim(struct rtw_softc *sc)
1564: {
1565: /* TBD */
1566: return;
1567: }
1568:
1569: #ifdef RTW_DEBUG
1570: void
1571: rtw_dump_rings(struct rtw_softc *sc)
1572: {
1573: struct rtw_txdesc_blk *tdb;
1574: struct rtw_rxdesc *rd;
1575: struct rtw_rxdesc_blk *rdb;
1576: int desc, pri;
1577:
1578: if ((rtw_debug & RTW_DEBUG_IO_KICK) == 0)
1579: return;
1580:
1581: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1582: tdb = &sc->sc_txdesc_blk[pri];
1583: printf("%s: txpri %d ndesc %d nfree %d\n", __func__, pri,
1584: tdb->tdb_ndesc, tdb->tdb_nfree);
1585: for (desc = 0; desc < tdb->tdb_ndesc; desc++)
1586: rtw_print_txdesc(sc, ".", NULL, tdb, desc);
1587: }
1588:
1589: rdb = &sc->sc_rxdesc_blk;
1590:
1591: for (desc = 0; desc < RTW_RXQLEN; desc++) {
1592: rd = &rdb->rdb_desc[desc];
1593: printf("%s: %sctl %08x rsvd0/rssi %08x buf/tsftl %08x "
1594: "rsvd1/tsfth %08x\n", __func__,
1595: (desc >= rdb->rdb_ndesc) ? "UNUSED " : "",
1596: letoh32(rd->rd_ctl), letoh32(rd->rd_rssi),
1597: letoh32(rd->rd_buf), letoh32(rd->rd_tsfth));
1598: }
1599: }
1600: #endif /* RTW_DEBUG */
1601:
1602: void
1603: rtw_hwring_setup(struct rtw_softc *sc)
1604: {
1605: int pri;
1606: struct rtw_regs *regs = &sc->sc_regs;
1607: struct rtw_txdesc_blk *tdb;
1608:
1609: sc->sc_txdesc_blk[RTW_TXPRILO].tdb_basereg = RTW_TLPDA;
1610: sc->sc_txdesc_blk[RTW_TXPRILO].tdb_base = RTW_RING_BASE(sc, hd_txlo);
1611: sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_basereg = RTW_TNPDA;
1612: sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_base = RTW_RING_BASE(sc, hd_txmd);
1613: sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_basereg = RTW_THPDA;
1614: sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_base = RTW_RING_BASE(sc, hd_txhi);
1615: sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_basereg = RTW_TBDA;
1616: sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_base = RTW_RING_BASE(sc, hd_bcn);
1617:
1618: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1619: tdb = &sc->sc_txdesc_blk[pri];
1620: RTW_WRITE(regs, tdb->tdb_basereg, tdb->tdb_base);
1621: RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
1622: ("%s: reg[tdb->tdb_basereg] <- %lx\n", __func__,
1623: (u_int *)tdb->tdb_base));
1624: }
1625:
1626: RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(sc, hd_rx));
1627:
1628: RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
1629: ("%s: reg[RDSAR] <- %lx\n", __func__,
1630: (u_int *)RTW_RING_BASE(sc, hd_rx)));
1631:
1632: RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR);
1633: }
1634:
1635: int
1636: rtw_swring_setup(struct rtw_softc *sc)
1637: {
1638: int rc, pri;
1639: struct rtw_rxdesc_blk *rdb;
1640: struct rtw_txdesc_blk *tdb;
1641:
1642: rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk[0]);
1643:
1644: rtw_txsoft_blk_init_all(&sc->sc_txsoft_blk[0]);
1645:
1646: rdb = &sc->sc_rxdesc_blk;
1647: if ((rc = rtw_rxsoft_init_all(sc->sc_dmat, sc->sc_rxsoft,
1648: &rdb->rdb_ndesc, sc->sc_dev.dv_xname)) != 0 &&
1649: rdb->rdb_ndesc == 0) {
1650: printf("%s: could not allocate rx buffers\n",
1651: sc->sc_dev.dv_xname);
1652: return rc;
1653: }
1654:
1655: rdb = &sc->sc_rxdesc_blk;
1656: rtw_rxdescs_sync(rdb, 0, rdb->rdb_ndesc,
1657: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1658: rtw_rxdesc_init_all(rdb, sc->sc_rxsoft, 1);
1659: rdb->rdb_next = 0;
1660:
1661: tdb = &sc->sc_txdesc_blk[0];
1662: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1663: rtw_txdescs_sync(&tdb[pri], 0, tdb[pri].tdb_ndesc,
1664: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1665: }
1666: return 0;
1667: }
1668:
1669: void
1670: rtw_txdesc_blk_init(struct rtw_txdesc_blk *tdb)
1671: {
1672: int i;
1673:
1674: bzero(tdb->tdb_desc, sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
1675: for (i = 0; i < tdb->tdb_ndesc; i++)
1676: tdb->tdb_desc[i].td_next = htole32(RTW_NEXT_DESC(tdb, i));
1677: }
1678:
1679: u_int
1680: rtw_txring_next(struct rtw_regs *regs, struct rtw_txdesc_blk *tdb)
1681: {
1682: return (letoh32(RTW_READ(regs, tdb->tdb_basereg)) - tdb->tdb_base) /
1683: sizeof(struct rtw_txdesc);
1684: }
1685:
1686: void
1687: rtw_txring_fixup(struct rtw_softc *sc)
1688: {
1689: int pri;
1690: u_int next;
1691: struct rtw_txdesc_blk *tdb;
1692: struct rtw_regs *regs = &sc->sc_regs;
1693:
1694: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1695: tdb = &sc->sc_txdesc_blk[pri];
1696: next = rtw_txring_next(regs, tdb);
1697: if (tdb->tdb_next == next)
1698: continue;
1699: RTW_DPRINTF(RTW_DEBUG_BUGS,
1700: ("%s: tx-ring %d expected next %u, read %u\n", __func__,
1701: pri, tdb->tdb_next, next));
1702: tdb->tdb_next = MIN(next, tdb->tdb_ndesc - 1);
1703: }
1704: }
1705:
1706: void
1707: rtw_rxring_fixup(struct rtw_softc *sc)
1708: {
1709: u_int next;
1710: uint32_t rdsar;
1711: struct rtw_rxdesc_blk *rdb;
1712:
1713: rdsar = letoh32(RTW_READ(&sc->sc_regs, RTW_RDSAR));
1714: next = (rdsar - RTW_RING_BASE(sc, hd_rx)) / sizeof(struct rtw_rxdesc);
1715:
1716: rdb = &sc->sc_rxdesc_blk;
1717: if (rdb->rdb_next != next) {
1718: RTW_DPRINTF(RTW_DEBUG_BUGS,
1719: ("%s: rx-ring expected next %u, read %u\n", __func__,
1720: rdb->rdb_next, next));
1721: rdb->rdb_next = MIN(next, rdb->rdb_ndesc - 1);
1722: }
1723: }
1724:
1725: void
1726: rtw_txdescs_reset(struct rtw_softc *sc)
1727: {
1728: int pri;
1729:
1730: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1731: rtw_collect_txring(sc, &sc->sc_txsoft_blk[pri],
1732: &sc->sc_txdesc_blk[pri], 1);
1733: }
1734: }
1735:
1736: void
1737: rtw_intr_ioerror(struct rtw_softc *sc, u_int16_t isr)
1738: {
1739: uint8_t cr = 0;
1740: int xmtr = 0, rcvr = 0;
1741: struct rtw_regs *regs = &sc->sc_regs;
1742:
1743: if ((isr & RTW_INTR_TXFOVW) != 0) {
1744: RTW_DPRINTF(RTW_DEBUG_BUGS,
1745: ("%s: tx fifo underflow\n", sc->sc_dev.dv_xname));
1746: rcvr = xmtr = 1;
1747: cr |= RTW_CR_TE | RTW_CR_RE;
1748: }
1749:
1750: if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) != 0) {
1751: cr |= RTW_CR_RE;
1752: rcvr = 1;
1753: }
1754:
1755: RTW_DPRINTF(RTW_DEBUG_BUGS, ("%s: restarting xmit/recv, isr %hx"
1756: "\n", sc->sc_dev.dv_xname, isr));
1757:
1758: #ifdef RTW_DEBUG
1759: rtw_dump_rings(sc);
1760: #endif /* RTW_DEBUG */
1761:
1762: rtw_io_enable(regs, cr, 0);
1763:
1764: /* Collect rx'd packets. Refresh rx buffers. */
1765: if (rcvr)
1766: rtw_intr_rx(sc, 0);
1767: /* Collect tx'd packets. XXX let's hope this stops the transmit
1768: * timeouts.
1769: */
1770: if (xmtr)
1771: rtw_txdescs_reset(sc);
1772:
1773: RTW_WRITE16(regs, RTW_IMR, 0);
1774: RTW_SYNC(regs, RTW_IMR, RTW_IMR);
1775:
1776: if (rtw_do_chip_reset) {
1777: rtw_chip_reset1(regs, sc->sc_dev.dv_xname);
1778: }
1779:
1780: rtw_rxdesc_init_all(&sc->sc_rxdesc_blk, &sc->sc_rxsoft[0], 1);
1781:
1782: #ifdef RTW_DEBUG
1783: rtw_dump_rings(sc);
1784: #endif /* RTW_DEBUG */
1785:
1786: RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
1787: RTW_SYNC(regs, RTW_IMR, RTW_IMR);
1788: if (rcvr)
1789: rtw_rxring_fixup(sc);
1790: rtw_io_enable(regs, cr, 1);
1791: if (xmtr)
1792: rtw_txring_fixup(sc);
1793: }
1794:
1795: void
1796: rtw_suspend_ticks(struct rtw_softc *sc)
1797: {
1798: RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
1799: ("%s: suspending ticks\n", sc->sc_dev.dv_xname));
1800: sc->sc_do_tick = 0;
1801: }
1802:
1803: void
1804: rtw_resume_ticks(struct rtw_softc *sc)
1805: {
1806: u_int32_t tsftrl0, tsftrl1, next_tick;
1807:
1808: tsftrl0 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
1809:
1810: tsftrl1 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
1811: next_tick = tsftrl1 + 1000000;
1812: RTW_WRITE(&sc->sc_regs, RTW_TINT, next_tick);
1813:
1814: sc->sc_do_tick = 1;
1815:
1816: RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
1817: ("%s: resume ticks delta %#08x now %#08x next %#08x\n",
1818: sc->sc_dev.dv_xname, tsftrl1 - tsftrl0, tsftrl1, next_tick));
1819: }
1820:
1821: void
1822: rtw_intr_timeout(struct rtw_softc *sc)
1823: {
1824: RTW_DPRINTF(RTW_DEBUG_TIMEOUT, ("%s: timeout\n", sc->sc_dev.dv_xname));
1825: if (sc->sc_do_tick)
1826: rtw_resume_ticks(sc);
1827: return;
1828: }
1829:
1830: int
1831: rtw_intr(void *arg)
1832: {
1833: int i;
1834: struct rtw_softc *sc = arg;
1835: struct rtw_regs *regs = &sc->sc_regs;
1836: u_int16_t isr;
1837:
1838: /*
1839: * If the interface isn't running, the interrupt couldn't
1840: * possibly have come from us.
1841: */
1842: if ((sc->sc_flags & RTW_F_ENABLED) == 0 ||
1843: (sc->sc_if.if_flags & IFF_RUNNING) == 0 ||
1844: (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
1845: RTW_DPRINTF(RTW_DEBUG_INTR, ("%s: stray interrupt\n",
1846: sc->sc_dev.dv_xname));
1847: return (0);
1848: }
1849:
1850: for (i = 0; i < 10; i++) {
1851: isr = RTW_READ16(regs, RTW_ISR);
1852:
1853: RTW_WRITE16(regs, RTW_ISR, isr);
1854: RTW_WBR(regs, RTW_ISR, RTW_ISR);
1855:
1856: if (sc->sc_intr_ack != NULL)
1857: (*sc->sc_intr_ack)(regs);
1858:
1859: if (isr == 0)
1860: break;
1861:
1862: #ifdef RTW_DEBUG
1863: #define PRINTINTR(flag) do { \
1864: if ((isr & flag) != 0) { \
1865: printf("%s" #flag, delim); \
1866: delim = ","; \
1867: } \
1868: } while (0)
1869:
1870: if ((rtw_debug & RTW_DEBUG_INTR) != 0 && isr != 0) {
1871: const char *delim = "<";
1872:
1873: printf("%s: reg[ISR] = %x", sc->sc_dev.dv_xname, isr);
1874:
1875: PRINTINTR(RTW_INTR_TXFOVW);
1876: PRINTINTR(RTW_INTR_TIMEOUT);
1877: PRINTINTR(RTW_INTR_BCNINT);
1878: PRINTINTR(RTW_INTR_ATIMINT);
1879: PRINTINTR(RTW_INTR_TBDER);
1880: PRINTINTR(RTW_INTR_TBDOK);
1881: PRINTINTR(RTW_INTR_THPDER);
1882: PRINTINTR(RTW_INTR_THPDOK);
1883: PRINTINTR(RTW_INTR_TNPDER);
1884: PRINTINTR(RTW_INTR_TNPDOK);
1885: PRINTINTR(RTW_INTR_RXFOVW);
1886: PRINTINTR(RTW_INTR_RDU);
1887: PRINTINTR(RTW_INTR_TLPDER);
1888: PRINTINTR(RTW_INTR_TLPDOK);
1889: PRINTINTR(RTW_INTR_RER);
1890: PRINTINTR(RTW_INTR_ROK);
1891:
1892: printf(">\n");
1893: }
1894: #undef PRINTINTR
1895: #endif /* RTW_DEBUG */
1896:
1897: if ((isr & RTW_INTR_RX) != 0)
1898: rtw_intr_rx(sc, isr & RTW_INTR_RX);
1899: if ((isr & RTW_INTR_TX) != 0)
1900: rtw_intr_tx(sc, isr & RTW_INTR_TX);
1901: if ((isr & RTW_INTR_BEACON) != 0)
1902: rtw_intr_beacon(sc, isr & RTW_INTR_BEACON);
1903: if ((isr & RTW_INTR_ATIMINT) != 0)
1904: rtw_intr_atim(sc);
1905: if ((isr & RTW_INTR_IOERROR) != 0)
1906: rtw_intr_ioerror(sc, isr & RTW_INTR_IOERROR);
1907: if ((isr & RTW_INTR_TIMEOUT) != 0)
1908: rtw_intr_timeout(sc);
1909: }
1910:
1911: return 1;
1912: }
1913:
1914: /* Must be called at splnet. */
1915: void
1916: rtw_stop(struct ifnet *ifp, int disable)
1917: {
1918: int pri;
1919: struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
1920: struct ieee80211com *ic = &sc->sc_ic;
1921: struct rtw_regs *regs = &sc->sc_regs;
1922:
1923: if ((sc->sc_flags & RTW_F_ENABLED) == 0)
1924: return;
1925:
1926: rtw_suspend_ticks(sc);
1927:
1928: ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1929:
1930: if ((sc->sc_flags & RTW_F_INVALID) == 0) {
1931: /* Disable interrupts. */
1932: RTW_WRITE16(regs, RTW_IMR, 0);
1933:
1934: RTW_WBW(regs, RTW_TPPOLL, RTW_IMR);
1935:
1936: /* Stop the transmit and receive processes. First stop DMA,
1937: * then disable receiver and transmitter.
1938: */
1939: RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
1940:
1941: RTW_SYNC(regs, RTW_TPPOLL, RTW_IMR);
1942:
1943: rtw_io_enable(&sc->sc_regs, RTW_CR_RE|RTW_CR_TE, 0);
1944: }
1945:
1946: for (pri = 0; pri < RTW_NTXPRI; pri++) {
1947: rtw_txsofts_release(sc->sc_dmat, &sc->sc_ic,
1948: &sc->sc_txsoft_blk[pri]);
1949: }
1950:
1951: rtw_rxbufs_release(sc->sc_dmat, &sc->sc_rxsoft[0]);
1952:
1953: if (disable)
1954: rtw_disable(sc);
1955:
1956: /* Mark the interface as not running. Cancel the watchdog timer. */
1957: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1958: ifp->if_timer = 0;
1959:
1960: return;
1961: }
1962:
1963: #ifdef RTW_DEBUG
1964: const char *
1965: rtw_pwrstate_string(enum rtw_pwrstate power)
1966: {
1967: switch (power) {
1968: case RTW_ON:
1969: return "on";
1970: case RTW_SLEEP:
1971: return "sleep";
1972: case RTW_OFF:
1973: return "off";
1974: default:
1975: return "unknown";
1976: }
1977: }
1978: #endif
1979:
1980: /* XXX For Maxim, I am using the RFMD settings gleaned from the
1981: * reference driver, plus a magic Maxim "ON" value that comes from
1982: * the Realtek document "Windows PG for Rtl8180."
1983: */
1984: void
1985: rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
1986: int before_rf, int digphy)
1987: {
1988: u_int32_t anaparm;
1989:
1990: anaparm = RTW_READ(regs, RTW_ANAPARM_0);
1991: anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
1992:
1993: switch (power) {
1994: case RTW_OFF:
1995: if (before_rf)
1996: return;
1997: anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF;
1998: anaparm |= RTW_ANAPARM_TXDACOFF;
1999: break;
2000: case RTW_SLEEP:
2001: if (!before_rf)
2002: return;
2003: anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP;
2004: anaparm |= RTW_ANAPARM_TXDACOFF;
2005: break;
2006: case RTW_ON:
2007: if (!before_rf)
2008: return;
2009: anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON;
2010: break;
2011: }
2012: RTW_DPRINTF(RTW_DEBUG_PWR,
2013: ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
2014: __func__, rtw_pwrstate_string(power),
2015: (before_rf) ? "before" : "after", anaparm));
2016:
2017: RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
2018: RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
2019: }
2020:
2021: /* XXX I am using the RFMD settings gleaned from the reference
2022: * driver. They agree
2023: */
2024: void
2025: rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
2026: int before_rf, int digphy)
2027: {
2028: u_int32_t anaparm;
2029:
2030: anaparm = RTW_READ(regs, RTW_ANAPARM_0);
2031: anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
2032:
2033: switch (power) {
2034: case RTW_OFF:
2035: if (before_rf)
2036: return;
2037: anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF;
2038: anaparm |= RTW_ANAPARM_TXDACOFF;
2039: break;
2040: case RTW_SLEEP:
2041: if (!before_rf)
2042: return;
2043: anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP;
2044: anaparm |= RTW_ANAPARM_TXDACOFF;
2045: break;
2046: case RTW_ON:
2047: if (!before_rf)
2048: return;
2049: anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON;
2050: break;
2051: }
2052: RTW_DPRINTF(RTW_DEBUG_PWR,
2053: ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
2054: __func__, rtw_pwrstate_string(power),
2055: (before_rf) ? "before" : "after", anaparm));
2056:
2057: RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
2058: RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
2059: }
2060:
2061: void
2062: rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
2063: int before_rf, int digphy)
2064: {
2065: u_int32_t anaparm;
2066:
2067: anaparm = RTW_READ(regs, RTW_ANAPARM_0);
2068: anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
2069:
2070: switch (power) {
2071: case RTW_OFF:
2072: if (before_rf)
2073: return;
2074: anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF;
2075: anaparm |= RTW_ANAPARM_TXDACOFF;
2076: break;
2077: case RTW_SLEEP:
2078: if (!before_rf)
2079: return;
2080: anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP;
2081: anaparm |= RTW_ANAPARM_TXDACOFF;
2082: break;
2083: case RTW_ON:
2084: if (!before_rf)
2085: return;
2086: if (digphy) {
2087: anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON;
2088: /* XXX guess */
2089: anaparm |= RTW_ANAPARM_TXDACOFF;
2090: } else
2091: anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON;
2092: break;
2093: }
2094: RTW_DPRINTF(RTW_DEBUG_PWR,
2095: ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
2096: __func__, rtw_pwrstate_string(power),
2097: (before_rf) ? "before" : "after", anaparm));
2098:
2099: RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
2100: RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
2101: }
2102:
2103: void
2104: rtw_rtl_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
2105: int before_rf, int digphy)
2106: {
2107: /* empty */
2108: }
2109:
2110: void
2111: rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf,
2112: int digphy)
2113: {
2114: struct rtw_regs *regs = &sc->sc_regs;
2115:
2116: rtw_set_access(regs, RTW_ACCESS_ANAPARM);
2117:
2118: (*sc->sc_pwrstate_cb)(regs, power, before_rf, digphy);
2119:
2120: rtw_set_access(regs, RTW_ACCESS_NONE);
2121:
2122: return;
2123: }
2124:
2125: int
2126: rtw_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
2127: {
2128: int rc;
2129:
2130: RTW_DPRINTF(RTW_DEBUG_PWR,
2131: ("%s: %s->%s\n", __func__,
2132: rtw_pwrstate_string(sc->sc_pwrstate), rtw_pwrstate_string(power)));
2133:
2134: if (sc->sc_pwrstate == power)
2135: return 0;
2136:
2137: rtw_pwrstate0(sc, power, 1, sc->sc_flags & RTW_F_DIGPHY);
2138: rc = (*sc->sc_rf_pwrstate)(sc, power);
2139: rtw_pwrstate0(sc, power, 0, sc->sc_flags & RTW_F_DIGPHY);
2140:
2141: switch (power) {
2142: case RTW_ON:
2143: /* TBD set LEDs */
2144: break;
2145: case RTW_SLEEP:
2146: /* TBD */
2147: break;
2148: case RTW_OFF:
2149: /* TBD */
2150: break;
2151: }
2152: if (rc == 0)
2153: sc->sc_pwrstate = power;
2154: else
2155: sc->sc_pwrstate = RTW_OFF;
2156: return rc;
2157: }
2158:
2159: int
2160: rtw_tune(struct rtw_softc *sc)
2161: {
2162: struct ieee80211com *ic = &sc->sc_ic;
2163: u_int chan, idx;
2164: u_int8_t txpower;
2165: int rc;
2166:
2167: KASSERT(ic->ic_bss->ni_chan != NULL);
2168:
2169: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
2170: if (chan == 0 || chan == IEEE80211_CHAN_ANY)
2171: return 0;
2172:
2173: if (chan == sc->sc_cur_chan) {
2174: RTW_DPRINTF(RTW_DEBUG_TUNE,
2175: ("%s: already tuned chan #%d\n", __func__, chan));
2176: return 0;
2177: }
2178:
2179: rtw_suspend_ticks(sc);
2180:
2181: rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 0);
2182:
2183: /* TBD wait for Tx to complete */
2184:
2185: KASSERT((sc->sc_flags & RTW_F_ENABLED) != 0);
2186:
2187: idx = RTW_SR_TXPOWER1 +
2188: ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan) - 1;
2189: KASSERT2(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14,
2190: ("%s: channel %d out of range", __func__,
2191: idx - RTW_SR_TXPOWER1 + 1));
2192: txpower = RTW_SR_GET(&sc->sc_srom, idx);
2193:
2194: if ((rc = rtw_phy_init(sc)) != 0) {
2195: /* XXX condition on powersaving */
2196: printf("%s: phy init failed\n", sc->sc_dev.dv_xname);
2197: }
2198:
2199: sc->sc_cur_chan = chan;
2200:
2201: rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 1);
2202:
2203: rtw_resume_ticks(sc);
2204:
2205: return rc;
2206: }
2207:
2208: void
2209: rtw_disable(struct rtw_softc *sc)
2210: {
2211: int rc;
2212:
2213: if ((sc->sc_flags & RTW_F_ENABLED) == 0)
2214: return;
2215:
2216: /* turn off PHY */
2217: if ((sc->sc_flags & RTW_F_INVALID) == 0 &&
2218: (rc = rtw_pwrstate(sc, RTW_OFF)) != 0) {
2219: printf("%s: failed to turn off PHY (%d)\n",
2220: sc->sc_dev.dv_xname, rc);
2221: }
2222:
2223: if (sc->sc_disable != NULL)
2224: (*sc->sc_disable)(sc);
2225:
2226: sc->sc_flags &= ~RTW_F_ENABLED;
2227: }
2228:
2229: int
2230: rtw_enable(struct rtw_softc *sc)
2231: {
2232: if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
2233: if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
2234: printf("%s: device enable failed\n",
2235: sc->sc_dev.dv_xname);
2236: return (EIO);
2237: }
2238: sc->sc_flags |= RTW_F_ENABLED;
2239: }
2240: return (0);
2241: }
2242:
2243: void
2244: rtw_transmit_config(struct rtw_softc *sc)
2245: {
2246: struct rtw_regs *regs = &sc->sc_regs;
2247: u_int32_t tcr;
2248:
2249: tcr = RTW_READ(regs, RTW_TCR);
2250:
2251: tcr |= RTW_TCR_CWMIN;
2252: tcr &= ~RTW_TCR_MXDMA_MASK;
2253: tcr |= RTW_TCR_MXDMA_256;
2254: if ((sc->sc_flags & RTW_F_RTL8185) == 0)
2255: tcr |= RTW8180_TCR_SAT; /* send ACK as fast as possible */
2256: tcr &= ~RTW_TCR_LBK_MASK;
2257: tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */
2258:
2259: /* set short/long retry limits */
2260: tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK);
2261: tcr |= LSHIFT(4, RTW_TCR_SRL_MASK) | LSHIFT(4, RTW_TCR_LRL_MASK);
2262:
2263: tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */
2264:
2265: RTW_WRITE(regs, RTW_TCR, tcr);
2266: RTW_SYNC(regs, RTW_TCR, RTW_TCR);
2267: }
2268:
2269: void
2270: rtw_enable_interrupts(struct rtw_softc *sc)
2271: {
2272: struct rtw_regs *regs = &sc->sc_regs;
2273:
2274: sc->sc_inten = RTW_INTR_RX|RTW_INTR_TX|RTW_INTR_BEACON|RTW_INTR_ATIMINT;
2275: sc->sc_inten |= RTW_INTR_IOERROR|RTW_INTR_TIMEOUT;
2276:
2277: RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
2278: RTW_WBW(regs, RTW_IMR, RTW_ISR);
2279: RTW_WRITE16(regs, RTW_ISR, 0xffff);
2280: RTW_SYNC(regs, RTW_IMR, RTW_ISR);
2281:
2282: /* XXX necessary? */
2283: if (sc->sc_intr_ack != NULL)
2284: (*sc->sc_intr_ack)(regs);
2285: }
2286:
2287: void
2288: rtw_set_nettype(struct rtw_softc *sc, enum ieee80211_opmode opmode)
2289: {
2290: uint8_t msr;
2291:
2292: /* I'm guessing that MSR is protected as CONFIG[0123] are. */
2293: rtw_set_access(&sc->sc_regs, RTW_ACCESS_CONFIG);
2294:
2295: msr = RTW_READ8(&sc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
2296:
2297: switch (opmode) {
2298: case IEEE80211_M_AHDEMO:
2299: case IEEE80211_M_IBSS:
2300: msr |= RTW_MSR_NETYPE_ADHOC_OK;
2301: break;
2302: case IEEE80211_M_HOSTAP:
2303: msr |= RTW_MSR_NETYPE_AP_OK;
2304: break;
2305: case IEEE80211_M_MONITOR:
2306: /* XXX */
2307: msr |= RTW_MSR_NETYPE_NOLINK;
2308: break;
2309: case IEEE80211_M_STA:
2310: msr |= RTW_MSR_NETYPE_INFRA_OK;
2311: break;
2312: }
2313: RTW_WRITE8(&sc->sc_regs, RTW_MSR, msr);
2314:
2315: rtw_set_access(&sc->sc_regs, RTW_ACCESS_NONE);
2316: }
2317:
2318: void
2319: rtw_pktfilt_load(struct rtw_softc *sc)
2320: {
2321: struct rtw_regs *regs = &sc->sc_regs;
2322: struct ieee80211com *ic = &sc->sc_ic;
2323: struct arpcom *ec = &ic->ic_ac;
2324: struct ifnet *ifp = &sc->sc_ic.ic_if;
2325: int hash;
2326: u_int32_t hashes[2] = { 0, 0 };
2327: struct ether_multi *enm;
2328: struct ether_multistep step;
2329:
2330: /* XXX might be necessary to stop Rx/Tx engines while setting filters */
2331:
2332: sc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
2333: sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW8180_RCR_RXFTH_MASK);
2334:
2335: sc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
2336: /* MAC auto-reset PHY (huh?) */
2337: sc->sc_rcr |= RTW_RCR_ENMARP;
2338: /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
2339: sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW8180_RCR_RXFTH_WHOLE;
2340:
2341: switch (ic->ic_opmode) {
2342: case IEEE80211_M_MONITOR:
2343: sc->sc_rcr |= RTW_RCR_MONITOR;
2344: break;
2345: case IEEE80211_M_AHDEMO:
2346: case IEEE80211_M_IBSS:
2347: /* receive broadcasts in our BSS */
2348: sc->sc_rcr |= RTW_RCR_ADD3;
2349: break;
2350: default:
2351: break;
2352: }
2353:
2354: ifp->if_flags &= ~IFF_ALLMULTI;
2355:
2356: /* XXX accept all broadcast if scanning */
2357: if ((ifp->if_flags & IFF_BROADCAST) != 0)
2358: sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
2359:
2360: if (ifp->if_flags & IFF_PROMISC) {
2361: sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
2362: allmulti:
2363: ifp->if_flags |= IFF_ALLMULTI;
2364: goto setit;
2365: }
2366:
2367: /*
2368: * Program the 64-bit multicast hash filter.
2369: */
2370: ETHER_FIRST_MULTI(step, ec, enm);
2371: while (enm != NULL) {
2372: /* XXX */
2373: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
2374: ETHER_ADDR_LEN) != 0)
2375: goto allmulti;
2376:
2377: hash = ether_crc32_be((enm->enm_addrlo),
2378: IEEE80211_ADDR_LEN) >> 26;
2379: hashes[hash >> 5] |= (1 << (hash & 0x1f));
2380: sc->sc_rcr |= RTW_RCR_AM;
2381: ETHER_NEXT_MULTI(step, enm);
2382: }
2383:
2384: /* all bits set => hash is useless */
2385: if (~(hashes[0] & hashes[1]) == 0)
2386: goto allmulti;
2387:
2388: setit:
2389: if (ifp->if_flags & IFF_ALLMULTI) {
2390: sc->sc_rcr |= RTW_RCR_AM; /* accept all multicast */
2391: hashes[0] = hashes[1] = 0xffffffff;
2392: }
2393:
2394: RTW_WRITE(regs, RTW_MAR0, hashes[0]);
2395: RTW_WRITE(regs, RTW_MAR1, hashes[1]);
2396: RTW_WRITE(regs, RTW_RCR, sc->sc_rcr);
2397: RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
2398:
2399: DPRINTF(sc, RTW_DEBUG_PKTFILT,
2400: ("%s: RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
2401: sc->sc_dev.dv_xname, RTW_READ(regs, RTW_MAR0),
2402: RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR)));
2403:
2404: return;
2405: }
2406:
2407: /* Must be called at splnet. */
2408: int
2409: rtw_init(struct ifnet *ifp)
2410: {
2411: struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
2412: struct ieee80211com *ic = &sc->sc_ic;
2413: struct rtw_regs *regs = &sc->sc_regs;
2414: int rc = 0;
2415:
2416: if ((rc = rtw_enable(sc)) != 0)
2417: goto out;
2418:
2419: /* Cancel pending I/O and reset. */
2420: rtw_stop(ifp, 0);
2421:
2422: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2423: DPRINTF(sc, RTW_DEBUG_TUNE, ("%s: channel %d freq %d flags 0x%04x\n",
2424: __func__, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
2425: ic->ic_bss->ni_chan->ic_freq, ic->ic_bss->ni_chan->ic_flags));
2426:
2427: if ((rc = rtw_pwrstate(sc, RTW_OFF)) != 0)
2428: goto out;
2429:
2430: if ((rc = rtw_swring_setup(sc)) != 0)
2431: goto out;
2432:
2433: rtw_transmit_config(sc);
2434:
2435: rtw_set_access(regs, RTW_ACCESS_CONFIG);
2436:
2437: RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */
2438: RTW_WBW(regs, RTW_MSR, RTW_BRSR);
2439:
2440: /* long PLCP header, 1Mb/2Mb basic rate */
2441: if (sc->sc_flags & RTW_F_RTL8185)
2442: RTW_WRITE16(regs, RTW_BRSR, RTW8185_BRSR_MBR_2MBPS);
2443: else
2444: RTW_WRITE16(regs, RTW_BRSR, RTW8180_BRSR_MBR_2MBPS);
2445: RTW_SYNC(regs, RTW_BRSR, RTW_BRSR);
2446:
2447: rtw_set_access(regs, RTW_ACCESS_ANAPARM);
2448: rtw_set_access(regs, RTW_ACCESS_NONE);
2449:
2450: /* XXX from reference sources */
2451: RTW_WRITE(regs, RTW_FEMR, 0xffff);
2452: RTW_SYNC(regs, RTW_FEMR, RTW_FEMR);
2453:
2454: rtw_set_rfprog(regs, sc->sc_rfchipid, sc->sc_dev.dv_xname);
2455:
2456: RTW_WRITE8(regs, RTW_PHYDELAY, sc->sc_phydelay);
2457: /* from Linux driver */
2458: RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC);
2459:
2460: RTW_SYNC(regs, RTW_PHYDELAY, RTW_CRCOUNT);
2461:
2462: rtw_enable_interrupts(sc);
2463:
2464: rtw_pktfilt_load(sc);
2465:
2466: rtw_hwring_setup(sc);
2467:
2468: rtw_io_enable(regs, RTW_CR_RE|RTW_CR_TE, 1);
2469:
2470: ifp->if_flags |= IFF_RUNNING;
2471: ic->ic_state = IEEE80211_S_INIT;
2472:
2473: RTW_WRITE16(regs, RTW_BSSID16, 0x0);
2474: RTW_WRITE(regs, RTW_BSSID32, 0x0);
2475:
2476: rtw_resume_ticks(sc);
2477:
2478: rtw_set_nettype(sc, IEEE80211_M_MONITOR);
2479:
2480: if (ic->ic_opmode == IEEE80211_M_MONITOR)
2481: return ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2482: else
2483: return ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2484:
2485: out:
2486: printf("%s: interface not running\n", sc->sc_dev.dv_xname);
2487: return rc;
2488: }
2489:
2490: void
2491: rtw_led_init(struct rtw_regs *regs)
2492: {
2493: u_int8_t cfg0, cfg1;
2494:
2495: rtw_set_access(regs, RTW_ACCESS_CONFIG);
2496:
2497: cfg0 = RTW_READ8(regs, RTW_CONFIG0);
2498: cfg0 |= RTW8180_CONFIG0_LEDGPOEN;
2499: RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
2500:
2501: cfg1 = RTW_READ8(regs, RTW_CONFIG1);
2502: RTW_DPRINTF(RTW_DEBUG_LED,
2503: ("%s: read % from reg[CONFIG1]\n", __func__, cfg1));
2504:
2505: cfg1 &= ~RTW_CONFIG1_LEDS_MASK;
2506: cfg1 |= RTW_CONFIG1_LEDS_TX_RX;
2507: RTW_WRITE8(regs, RTW_CONFIG1, cfg1);
2508:
2509: rtw_set_access(regs, RTW_ACCESS_NONE);
2510: }
2511:
2512: /*
2513: * IEEE80211_S_INIT: LED1 off
2514: *
2515: * IEEE80211_S_AUTH,
2516: * IEEE80211_S_ASSOC,
2517: * IEEE80211_S_SCAN: LED1 blinks @ 1 Hz, blinks at 5Hz for tx/rx
2518: *
2519: * IEEE80211_S_RUN: LED1 on, blinks @ 5Hz for tx/rx
2520: */
2521: void
2522: rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
2523: {
2524: struct rtw_led_state *ls;
2525:
2526: ls = &sc->sc_led_state;
2527:
2528: switch (nstate) {
2529: case IEEE80211_S_INIT:
2530: rtw_led_init(&sc->sc_regs);
2531: timeout_del(&ls->ls_slow_ch);
2532: timeout_del(&ls->ls_fast_ch);
2533: ls->ls_slowblink = 0;
2534: ls->ls_actblink = 0;
2535: ls->ls_default = 0;
2536: break;
2537: case IEEE80211_S_SCAN:
2538: timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
2539: timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
2540: /*FALLTHROUGH*/
2541: case IEEE80211_S_AUTH:
2542: case IEEE80211_S_ASSOC:
2543: ls->ls_default = RTW_LED1;
2544: ls->ls_actblink = RTW_LED1;
2545: ls->ls_slowblink = RTW_LED1;
2546: break;
2547: case IEEE80211_S_RUN:
2548: ls->ls_slowblink = 0;
2549: break;
2550: }
2551: rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
2552: }
2553:
2554: void
2555: rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, u_int hwverid)
2556: {
2557: u_int8_t led_condition;
2558: bus_size_t ofs;
2559: u_int8_t mask, newval, val;
2560:
2561: led_condition = ls->ls_default;
2562:
2563: if (ls->ls_state & RTW_LED_S_SLOW)
2564: led_condition ^= ls->ls_slowblink;
2565: if (ls->ls_state & (RTW_LED_S_RX|RTW_LED_S_TX))
2566: led_condition ^= ls->ls_actblink;
2567:
2568: RTW_DPRINTF(RTW_DEBUG_LED,
2569: ("%s: LED condition %\n", __func__, led_condition));
2570:
2571: switch (hwverid) {
2572: default:
2573: case RTW_TCR_HWVERID_RTL8180F:
2574: ofs = RTW_PSR;
2575: newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1;
2576: if (led_condition & RTW_LED0)
2577: newval &= ~RTW_PSR_LEDGPO0;
2578: if (led_condition & RTW_LED1)
2579: newval &= ~RTW_PSR_LEDGPO1;
2580: break;
2581: case RTW_TCR_HWVERID_RTL8180D:
2582: ofs = RTW_9346CR;
2583: mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS;
2584: newval = RTW_9346CR_EEM_PROGRAM;
2585: if (led_condition & RTW_LED0)
2586: newval |= RTW_9346CR_EEDI;
2587: if (led_condition & RTW_LED1)
2588: newval |= RTW_9346CR_EECS;
2589: break;
2590: }
2591: val = RTW_READ8(regs, ofs);
2592: RTW_DPRINTF(RTW_DEBUG_LED,
2593: ("%s: read % from reg[%#02]\n", __func__, val,
2594: (u_int *)ofs));
2595: val &= ~mask;
2596: val |= newval;
2597: RTW_WRITE8(regs, ofs, val);
2598: RTW_DPRINTF(RTW_DEBUG_LED,
2599: ("%s: wrote % to reg[%#02]\n", __func__, val,
2600: (u_int *)ofs));
2601: RTW_SYNC(regs, ofs, ofs);
2602: }
2603:
2604: void
2605: rtw_led_fastblink(void *arg)
2606: {
2607: int ostate, s;
2608: struct rtw_softc *sc = (struct rtw_softc *)arg;
2609: struct rtw_led_state *ls = &sc->sc_led_state;
2610:
2611: s = splnet();
2612: ostate = ls->ls_state;
2613: ls->ls_state ^= ls->ls_event;
2614:
2615: if ((ls->ls_event & RTW_LED_S_TX) == 0)
2616: ls->ls_state &= ~RTW_LED_S_TX;
2617:
2618: if ((ls->ls_event & RTW_LED_S_RX) == 0)
2619: ls->ls_state &= ~RTW_LED_S_RX;
2620:
2621: ls->ls_event = 0;
2622:
2623: if (ostate != ls->ls_state)
2624: rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
2625: splx(s);
2626:
2627: timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
2628: }
2629:
2630: void
2631: rtw_led_slowblink(void *arg)
2632: {
2633: int s;
2634: struct rtw_softc *sc = (struct rtw_softc *)arg;
2635: struct rtw_led_state *ls = &sc->sc_led_state;
2636:
2637: s = splnet();
2638: ls->ls_state ^= RTW_LED_S_SLOW;
2639: rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
2640: splx(s);
2641: timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
2642: }
2643:
2644: void
2645: rtw_led_attach(struct rtw_led_state *ls, void *arg)
2646: {
2647: timeout_set(&ls->ls_fast_ch, rtw_led_fastblink, arg);
2648: timeout_set(&ls->ls_slow_ch, rtw_led_slowblink, arg);
2649: }
2650:
2651: int
2652: rtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2653: {
2654: int rc = 0, s;
2655: struct rtw_softc *sc = ifp->if_softc;
2656: struct ieee80211com *ic = &sc->sc_ic;
2657: struct ifreq *ifr = (struct ifreq *)data;
2658: struct ifaddr *ifa = (struct ifaddr *)data;
2659:
2660: s = splnet();
2661: switch (cmd) {
2662: case SIOCSIFMTU:
2663: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
2664: rc = EINVAL;
2665: } else if (ifp->if_mtu != ifr->ifr_mtu) {
2666: ifp->if_mtu = ifr->ifr_mtu;
2667: }
2668: break;
2669: case SIOCSIFADDR:
2670: ifp->if_flags |= IFF_UP;
2671: #ifdef INET
2672: if (ifa->ifa_addr->sa_family == AF_INET) {
2673: arp_ifinit(&ic->ic_ac, ifa);
2674: }
2675: #endif /* INET */
2676: /* FALLTHROUGH */
2677:
2678: case SIOCSIFFLAGS:
2679: if ((ifp->if_flags & IFF_UP) != 0) {
2680: if ((sc->sc_flags & RTW_F_ENABLED) != 0) {
2681: rtw_pktfilt_load(sc);
2682: } else
2683: rc = rtw_init(ifp);
2684: } else if ((sc->sc_flags & RTW_F_ENABLED) != 0)
2685: rtw_stop(ifp, 1);
2686: break;
2687: case SIOCADDMULTI:
2688: case SIOCDELMULTI:
2689: if (cmd == SIOCADDMULTI)
2690: rc = ether_addmulti(ifr, &sc->sc_ic.ic_ac);
2691: else
2692: rc = ether_delmulti(ifr, &sc->sc_ic.ic_ac);
2693: if (rc != ENETRESET)
2694: break;
2695: if (ifp->if_flags & IFF_RUNNING)
2696: rtw_pktfilt_load(sc);
2697: rc = 0;
2698: break;
2699: default:
2700: if ((rc = ieee80211_ioctl(ifp, cmd, data)) == ENETRESET) {
2701: if ((sc->sc_flags & RTW_F_ENABLED) != 0)
2702: rc = rtw_init(ifp);
2703: else
2704: rc = 0;
2705: }
2706: break;
2707: }
2708: splx(s);
2709: return rc;
2710: }
2711:
2712: /* Select a transmit ring with at least one h/w and s/w descriptor free.
2713: * Return 0 on success, -1 on failure.
2714: */
2715: int
2716: rtw_txring_choose(struct rtw_softc *sc, struct rtw_txsoft_blk **tsbp,
2717: struct rtw_txdesc_blk **tdbp, int pri)
2718: {
2719: struct rtw_txsoft_blk *tsb;
2720: struct rtw_txdesc_blk *tdb;
2721:
2722: KASSERT(pri >= 0 && pri < RTW_NTXPRI);
2723:
2724: tsb = &sc->sc_txsoft_blk[pri];
2725: tdb = &sc->sc_txdesc_blk[pri];
2726:
2727: if (SIMPLEQ_EMPTY(&tsb->tsb_freeq) || tdb->tdb_nfree == 0) {
2728: if (tsb->tsb_tx_timer == 0)
2729: tsb->tsb_tx_timer = 5;
2730: *tsbp = NULL;
2731: *tdbp = NULL;
2732: return -1;
2733: }
2734: *tsbp = tsb;
2735: *tdbp = tdb;
2736: return 0;
2737: }
2738:
2739: struct mbuf *
2740: rtw_80211_dequeue(struct rtw_softc *sc, struct ifqueue *ifq, int pri,
2741: struct rtw_txsoft_blk **tsbp, struct rtw_txdesc_blk **tdbp,
2742: struct ieee80211_node **nip, short *if_flagsp)
2743: {
2744: struct mbuf *m;
2745:
2746: if (IF_IS_EMPTY(ifq))
2747: return NULL;
2748: if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) {
2749: DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, ("%s: no ring %d descriptor\n",
2750: __func__, pri));
2751: *if_flagsp |= IFF_OACTIVE;
2752: sc->sc_if.if_timer = 1;
2753: return NULL;
2754: }
2755: IF_DEQUEUE(ifq, m);
2756: *nip = (struct ieee80211_node *)m->m_pkthdr.rcvif;
2757: m->m_pkthdr.rcvif = NULL;
2758: return m;
2759: }
2760:
2761: /* Point *mp at the next 802.11 frame to transmit. Point *tsbp
2762: * at the driver's selection of transmit control block for the packet.
2763: */
2764: int
2765: rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp,
2766: struct rtw_txdesc_blk **tdbp, struct mbuf **mp,
2767: struct ieee80211_node **nip)
2768: {
2769: struct mbuf *m0;
2770: struct rtw_softc *sc;
2771: short *if_flagsp;
2772:
2773: sc = (struct rtw_softc *)ifp->if_softc;
2774:
2775: DPRINTF(sc, RTW_DEBUG_XMIT,
2776: ("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
2777:
2778: if_flagsp = &ifp->if_flags;
2779:
2780: if (sc->sc_ic.ic_state == IEEE80211_S_RUN &&
2781: (*mp = rtw_80211_dequeue(sc, &sc->sc_beaconq, RTW_TXPRIBCN, tsbp,
2782: tdbp, nip, if_flagsp)) != NULL) {
2783: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue beacon frame\n",
2784: __func__));
2785: return 0;
2786: }
2787:
2788: if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_mgtq, RTW_TXPRIMD, tsbp,
2789: tdbp, nip, if_flagsp)) != NULL) {
2790: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue mgt frame\n",
2791: __func__));
2792: return 0;
2793: }
2794:
2795: if (sc->sc_ic.ic_state != IEEE80211_S_RUN) {
2796: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: not running\n", __func__));
2797: return 0;
2798: }
2799:
2800: if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_pwrsaveq, RTW_TXPRIHI,
2801: tsbp, tdbp, nip, if_flagsp)) != NULL) {
2802: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue pwrsave frame\n",
2803: __func__));
2804: return 0;
2805: }
2806:
2807: if (sc->sc_ic.ic_state != IEEE80211_S_RUN) {
2808: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: not running\n", __func__));
2809: return 0;
2810: }
2811:
2812: *mp = NULL;
2813:
2814: IFQ_POLL(&ifp->if_snd, m0);
2815: if (m0 == NULL) {
2816: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame ready\n",
2817: __func__));
2818: return 0;
2819: }
2820:
2821: if (rtw_txring_choose(sc, tsbp, tdbp, RTW_TXPRIMD) == -1) {
2822: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no descriptor\n", __func__));
2823: *if_flagsp |= IFF_OACTIVE;
2824: sc->sc_if.if_timer = 1;
2825: return 0;
2826: }
2827:
2828: IFQ_DEQUEUE(&ifp->if_snd, m0);
2829: if (m0 == NULL) {
2830: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame/ring ready\n",
2831: __func__));
2832: return 0;
2833: }
2834: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue data frame\n", __func__));
2835: ifp->if_opackets++;
2836: #if NBPFILTER > 0
2837: if (ifp->if_bpf)
2838: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
2839: #endif
2840: if ((m0 = ieee80211_encap(ifp, m0, nip)) == NULL) {
2841: DPRINTF(sc, RTW_DEBUG_XMIT,
2842: ("%s: encap error\n", __func__));
2843: ifp->if_oerrors++;
2844: return -1;
2845: }
2846:
2847: /* XXX should do WEP in hardware */
2848: if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
2849: if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL)
2850: return -1;
2851: }
2852:
2853: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
2854: *mp = m0;
2855: return 0;
2856: }
2857:
2858: int
2859: rtw_seg_too_short(bus_dmamap_t dmamap)
2860: {
2861: int i;
2862: for (i = 0; i < dmamap->dm_nsegs; i++) {
2863: if (dmamap->dm_segs[i].ds_len < 4) {
2864: printf("%s: segment too short\n", __func__);
2865: return 1;
2866: }
2867: }
2868: return 0;
2869: }
2870:
2871: /* TBD factor with atw_start */
2872: struct mbuf *
2873: rtw_dmamap_load_txbuf(bus_dma_tag_t dmat, bus_dmamap_t dmam, struct mbuf *chain,
2874: u_int ndescfree, short *ifflagsp, const char *dvname)
2875: {
2876: int first, rc;
2877: struct mbuf *m, *m0;
2878:
2879: m0 = chain;
2880:
2881: /*
2882: * Load the DMA map. Copy and try (once) again if the packet
2883: * didn't fit in the alloted number of segments.
2884: */
2885: for (first = 1;
2886: ((rc = bus_dmamap_load_mbuf(dmat, dmam, m0,
2887: BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 ||
2888: dmam->dm_nsegs > ndescfree || rtw_seg_too_short(dmam)) && first;
2889: first = 0) {
2890: if (rc == 0)
2891: bus_dmamap_unload(dmat, dmam);
2892: MGETHDR(m, M_DONTWAIT, MT_DATA);
2893: if (m == NULL) {
2894: printf("%s: unable to allocate Tx mbuf\n",
2895: dvname);
2896: break;
2897: }
2898: if (m0->m_pkthdr.len > MHLEN) {
2899: MCLGET(m, M_DONTWAIT);
2900: if ((m->m_flags & M_EXT) == 0) {
2901: printf("%s: cannot allocate Tx cluster\n",
2902: dvname);
2903: m_freem(m);
2904: break;
2905: }
2906: }
2907: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
2908: m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
2909: m_freem(m0);
2910: m0 = m;
2911: m = NULL;
2912: }
2913: if (rc != 0) {
2914: printf("%s: cannot load Tx buffer, rc = %d\n", dvname, rc);
2915: m_freem(m0);
2916: return NULL;
2917: } else if (rtw_seg_too_short(dmam)) {
2918: printf("%s: cannot load Tx buffer, segment too short\n",
2919: dvname);
2920: bus_dmamap_unload(dmat, dmam);
2921: m_freem(m0);
2922: return NULL;
2923: } else if (dmam->dm_nsegs > ndescfree) {
2924: printf("%s: too many tx segments\n", dvname);
2925: bus_dmamap_unload(dmat, dmam);
2926: m_freem(m0);
2927: return NULL;
2928: }
2929: return m0;
2930: }
2931:
2932:
2933: /*
2934: * Arguments in:
2935: *
2936: * paylen: payload length (no FCS, no WEP header)
2937: *
2938: * hdrlen: header length
2939: *
2940: * rate: MSDU speed, units 500kb/s
2941: *
2942: * flags: IEEE80211_F_SHPREAMBLE (use short preamble),
2943: * IEEE80211_F_SHSLOT (use short slot length)
2944: *
2945: * Arguments out:
2946: *
2947: * d: 802.11 Duration field for RTS,
2948: * 802.11 Duration field for data frame,
2949: * PLCP Length for data frame,
2950: * residual octets at end of data slot
2951: */
2952: int
2953: rtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
2954: struct rtw_duration *d)
2955: {
2956: int pre, ctsrate;
2957: int ack, bitlen, data_dur, remainder;
2958:
2959: /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
2960: * DATA reserves medium for SIFS | ACK
2961: *
2962: * XXXMYC: no ACK on multicast/broadcast or control packets
2963: */
2964:
2965: bitlen = len * 8;
2966:
2967: pre = IEEE80211_DUR_DS_SIFS;
2968: if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
2969: pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
2970: IEEE80211_DUR_DS_FAST_PLCPHDR;
2971: else
2972: pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
2973: IEEE80211_DUR_DS_SLOW_PLCPHDR;
2974:
2975: d->d_residue = 0;
2976: data_dur = (bitlen * 2) / rate;
2977: remainder = (bitlen * 2) % rate;
2978: if (remainder != 0) {
2979: d->d_residue = (rate - remainder) / 16;
2980: data_dur++;
2981: }
2982:
2983: switch (rate) {
2984: case 2: /* 1 Mb/s */
2985: case 4: /* 2 Mb/s */
2986: /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
2987: ctsrate = 2;
2988: break;
2989: case 11: /* 5.5 Mb/s */
2990: case 22: /* 11 Mb/s */
2991: case 44: /* 22 Mb/s */
2992: /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
2993: ctsrate = 4;
2994: break;
2995: default:
2996: /* TBD */
2997: return -1;
2998: }
2999:
3000: d->d_plcp_len = data_dur;
3001:
3002: ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
3003:
3004: d->d_rts_dur =
3005: pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
3006: pre + data_dur +
3007: ack;
3008:
3009: d->d_data_dur = ack;
3010:
3011: return 0;
3012: }
3013:
3014: /*
3015: * Arguments in:
3016: *
3017: * wh: 802.11 header
3018: *
3019: * len: packet length
3020: *
3021: * rate: MSDU speed, units 500kb/s
3022: *
3023: * fraglen: fragment length, set to maximum (or higher) for no
3024: * fragmentation
3025: *
3026: * flags: IEEE80211_F_WEPON (hardware adds WEP),
3027: * IEEE80211_F_SHPREAMBLE (use short preamble),
3028: * IEEE80211_F_SHSLOT (use short slot length)
3029: *
3030: * Arguments out:
3031: *
3032: * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
3033: * of first/only fragment
3034: *
3035: * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
3036: * of first/only fragment
3037: */
3038: int
3039: rtw_compute_duration(struct ieee80211_frame *wh, int len, uint32_t flags,
3040: int fraglen, int rate, struct rtw_duration *d0, struct rtw_duration *dn,
3041: int *npktp, int debug)
3042: {
3043: int ack, rc;
3044: int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
3045:
3046: if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
3047: hdrlen = sizeof(struct ieee80211_frame_addr4);
3048: else
3049: hdrlen = sizeof(struct ieee80211_frame);
3050:
3051: paylen = len - hdrlen;
3052:
3053: if ((flags & IEEE80211_F_WEPON) != 0)
3054: overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN;
3055: else
3056: overlen = IEEE80211_CRC_LEN;
3057:
3058: npkt = paylen / fraglen;
3059: lastlen0 = paylen % fraglen;
3060:
3061: if (npkt == 0) /* no fragments */
3062: lastlen = paylen + overlen;
3063: else if (lastlen0 != 0) { /* a short "tail" fragment */
3064: lastlen = lastlen0 + overlen;
3065: npkt++;
3066: } else /* full-length "tail" fragment */
3067: lastlen = fraglen + overlen;
3068:
3069: if (npktp != NULL)
3070: *npktp = npkt;
3071:
3072: if (npkt > 1)
3073: firstlen = fraglen + overlen;
3074: else
3075: firstlen = paylen + overlen;
3076:
3077: if (debug) {
3078: printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d "
3079: "fraglen %d overlen %d len %d rate %d flags %08x\n",
3080: __func__, npkt, firstlen, lastlen0, lastlen, fraglen,
3081: overlen, len, rate, flags);
3082: }
3083:
3084: ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
3085: (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL;
3086:
3087: rc = rtw_compute_duration1(firstlen + hdrlen, ack, flags, rate, d0);
3088: if (rc == -1)
3089: return rc;
3090:
3091: if (npkt <= 1) {
3092: *dn = *d0;
3093: return 0;
3094: }
3095: return rtw_compute_duration1(lastlen + hdrlen, ack, flags, rate, dn);
3096: }
3097:
3098: #ifdef RTW_DEBUG
3099: void
3100: rtw_print_txdesc(struct rtw_softc *sc, const char *action,
3101: struct rtw_txsoft *ts, struct rtw_txdesc_blk *tdb, int desc)
3102: {
3103: struct rtw_txdesc *td = &tdb->tdb_desc[desc];
3104: DPRINTF(sc, RTW_DEBUG_XMIT_DESC, ("%s: %p %s txdesc[%d] next %#08x "
3105: "buf %#08x ctl0 %#08x ctl1 %#08x len %#08x\n",
3106: sc->sc_dev.dv_xname, ts, action, desc,
3107: letoh32(td->td_buf), letoh32(td->td_next),
3108: letoh32(td->td_ctl0), letoh32(td->td_ctl1),
3109: letoh32(td->td_len)));
3110: }
3111: #endif /* RTW_DEBUG */
3112:
3113: void
3114: rtw_start(struct ifnet *ifp)
3115: {
3116: uint8_t tppoll;
3117: int desc, i, lastdesc, npkt, rate;
3118: uint32_t proto_ctl0, ctl0, ctl1;
3119: bus_dmamap_t dmamap;
3120: struct ieee80211com *ic;
3121: struct ieee80211_frame *wh;
3122: struct ieee80211_node *ni;
3123: struct mbuf *m0;
3124: struct rtw_softc *sc;
3125: struct rtw_duration *d0;
3126: struct rtw_txsoft_blk *tsb;
3127: struct rtw_txdesc_blk *tdb;
3128: struct rtw_txsoft *ts;
3129: struct rtw_txdesc *td;
3130:
3131: sc = (struct rtw_softc *)ifp->if_softc;
3132: ic = &sc->sc_ic;
3133:
3134: DPRINTF(sc, RTW_DEBUG_XMIT,
3135: ("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
3136:
3137: if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
3138: goto out;
3139:
3140: /* XXX do real rate control */
3141: proto_ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;
3142:
3143: if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0)
3144: proto_ctl0 |= RTW_TXCTL0_SPLCP;
3145:
3146: for (;;) {
3147: if (rtw_dequeue(ifp, &tsb, &tdb, &m0, &ni) == -1)
3148: continue;
3149: if (m0 == NULL)
3150: break;
3151: ts = SIMPLEQ_FIRST(&tsb->tsb_freeq);
3152:
3153: dmamap = ts->ts_dmamap;
3154:
3155: m0 = rtw_dmamap_load_txbuf(sc->sc_dmat, dmamap, m0,
3156: tdb->tdb_nfree, &ifp->if_flags, sc->sc_dev.dv_xname);
3157:
3158: if (m0 == NULL || dmamap->dm_nsegs == 0) {
3159: DPRINTF(sc, RTW_DEBUG_XMIT,
3160: ("%s: fail dmamap load\n", __func__));
3161: goto post_dequeue_err;
3162: }
3163:
3164: wh = mtod(m0, struct ieee80211_frame *);
3165:
3166: /* XXX do real rate control */
3167: if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
3168: IEEE80211_FC0_TYPE_MGT)
3169: rate = 2;
3170: else
3171: rate = MAX(2, ieee80211_get_rate(ic));
3172:
3173: #ifdef RTW_DEBUG
3174: if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
3175: (IFF_DEBUG|IFF_LINK2)) {
3176: ieee80211_dump_pkt(mtod(m0, uint8_t *),
3177: (dmamap->dm_nsegs == 1) ? m0->m_pkthdr.len
3178: : sizeof(wh), rate, 0);
3179: }
3180: #endif /* RTW_DEBUG */
3181: ctl0 = proto_ctl0 |
3182: LSHIFT(m0->m_pkthdr.len, RTW_TXCTL0_TPKTSIZE_MASK);
3183:
3184: switch (rate) {
3185: default:
3186: case 2:
3187: ctl0 |= RTW_TXCTL0_RATE_1MBPS;
3188: break;
3189: case 4:
3190: ctl0 |= RTW_TXCTL0_RATE_2MBPS;
3191: break;
3192: case 11:
3193: ctl0 |= RTW_TXCTL0_RATE_5MBPS;
3194: break;
3195: case 22:
3196: ctl0 |= RTW_TXCTL0_RATE_11MBPS;
3197: break;
3198: }
3199:
3200: /* XXX >= ? Compare after fragmentation? */
3201: if (m0->m_pkthdr.len > ic->ic_rtsthreshold)
3202: ctl0 |= RTW_TXCTL0_RTSEN;
3203:
3204: if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
3205: IEEE80211_FC0_TYPE_MGT) {
3206: ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN);
3207: if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3208: IEEE80211_FC0_SUBTYPE_BEACON)
3209: ctl0 |= RTW_TXCTL0_BEACON;
3210: }
3211:
3212: if (rtw_compute_duration(wh, m0->m_pkthdr.len,
3213: ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold,
3214: rate, &ts->ts_d0, &ts->ts_dn, &npkt,
3215: (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
3216: (IFF_DEBUG|IFF_LINK2)) == -1) {
3217: DPRINTF(sc, RTW_DEBUG_XMIT,
3218: ("%s: fail compute duration\n", __func__));
3219: goto post_load_err;
3220: }
3221:
3222: d0 = &ts->ts_d0;
3223:
3224: *(uint16_t*)wh->i_dur = htole16(d0->d_data_dur);
3225:
3226: ctl1 = LSHIFT(d0->d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |
3227: LSHIFT(d0->d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);
3228:
3229: if (d0->d_residue)
3230: ctl1 |= RTW_TXCTL1_LENGEXT;
3231:
3232: /* TBD fragmentation */
3233:
3234: ts->ts_first = tdb->tdb_next;
3235:
3236: rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
3237: BUS_DMASYNC_PREWRITE);
3238:
3239: KASSERT(ts->ts_first < tdb->tdb_ndesc);
3240:
3241: #if NBPFILTER > 0
3242: if (ic->ic_rawbpf != NULL)
3243: bpf_mtap((caddr_t)ic->ic_rawbpf, m0,
3244: BPF_DIRECTION_OUT);
3245:
3246: if (sc->sc_radiobpf != NULL) {
3247: struct mbuf mb;
3248: struct rtw_tx_radiotap_header *rt = &sc->sc_txtap;
3249:
3250: rt->rt_flags = 0;
3251: rt->rt_rate = rate;
3252: rt->rt_chan_freq =
3253: htole16(ic->ic_bss->ni_chan->ic_freq);
3254: rt->rt_chan_flags =
3255: htole16(ic->ic_bss->ni_chan->ic_flags);
3256:
3257: mb.m_data = (caddr_t)rt;
3258: mb.m_len = sizeof(sc->sc_txtapu);
3259: mb.m_next = m0;
3260: mb.m_nextpkt = NULL;
3261: mb.m_type = 0;
3262: mb.m_flags = 0;
3263: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
3264:
3265: }
3266: #endif /* NPBFILTER > 0 */
3267:
3268: for (i = 0, lastdesc = desc = ts->ts_first;
3269: i < dmamap->dm_nsegs;
3270: i++, desc = RTW_NEXT_IDX(tdb, desc)) {
3271: if (dmamap->dm_segs[i].ds_len > RTW_TXLEN_LENGTH_MASK) {
3272: DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
3273: ("%s: seg too long\n", __func__));
3274: goto post_load_err;
3275: }
3276: td = &tdb->tdb_desc[desc];
3277: td->td_ctl0 = htole32(ctl0);
3278: if (i != 0)
3279: td->td_ctl0 |= htole32(RTW_TXCTL0_OWN);
3280: td->td_ctl1 = htole32(ctl1);
3281: td->td_buf = htole32(dmamap->dm_segs[i].ds_addr);
3282: td->td_len = htole32(dmamap->dm_segs[i].ds_len);
3283: lastdesc = desc;
3284: #ifdef RTW_DEBUG
3285: rtw_print_txdesc(sc, "load", ts, tdb, desc);
3286: #endif /* RTW_DEBUG */
3287: }
3288:
3289: KASSERT(desc < tdb->tdb_ndesc);
3290:
3291: ts->ts_ni = ni;
3292: ts->ts_mbuf = m0;
3293: ts->ts_last = lastdesc;
3294: tdb->tdb_desc[ts->ts_last].td_ctl0 |= htole32(RTW_TXCTL0_LS);
3295: tdb->tdb_desc[ts->ts_first].td_ctl0 |=
3296: htole32(RTW_TXCTL0_FS);
3297:
3298: #ifdef RTW_DEBUG
3299: rtw_print_txdesc(sc, "FS on", ts, tdb, ts->ts_first);
3300: rtw_print_txdesc(sc, "LS on", ts, tdb, ts->ts_last);
3301: #endif /* RTW_DEBUG */
3302:
3303: tdb->tdb_nfree -= dmamap->dm_nsegs;
3304: tdb->tdb_next = desc;
3305:
3306: rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
3307: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3308:
3309: tdb->tdb_desc[ts->ts_first].td_ctl0 |=
3310: htole32(RTW_TXCTL0_OWN);
3311:
3312: #ifdef RTW_DEBUG
3313: rtw_print_txdesc(sc, "OWN on", ts, tdb, ts->ts_first);
3314: #endif /* RTW_DEBUG */
3315:
3316: rtw_txdescs_sync(tdb, ts->ts_first, 1,
3317: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3318:
3319: SIMPLEQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q);
3320: SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q);
3321:
3322: if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN])
3323: sc->sc_led_state.ls_event |= RTW_LED_S_TX;
3324: tsb->tsb_tx_timer = 5;
3325: ifp->if_timer = 1;
3326: tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
3327: tppoll &= ~RTW_TPPOLL_SALL;
3328: tppoll |= tsb->tsb_poll & RTW_TPPOLL_ALL;
3329: RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
3330: RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL);
3331: }
3332: out:
3333: DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
3334: return;
3335: post_load_err:
3336: bus_dmamap_unload(sc->sc_dmat, dmamap);
3337: m_freem(m0);
3338: post_dequeue_err:
3339: ieee80211_release_node(&sc->sc_ic, ni);
3340: return;
3341: }
3342:
3343: void
3344: rtw_idle(struct rtw_regs *regs)
3345: {
3346: int active;
3347:
3348: /* request stop DMA; wait for packets to stop transmitting. */
3349:
3350: RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
3351: RTW_WBR(regs, RTW_TPPOLL, RTW_TPPOLL);
3352:
3353: for (active = 0; active < 300 &&
3354: (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ACTIVE) != 0; active++)
3355: DELAY(10);
3356: RTW_DPRINTF(RTW_DEBUG_BUGS,
3357: ("%s: transmit DMA idle in %dus\n", __func__, active * 10));
3358: }
3359:
3360: void
3361: rtw_watchdog(struct ifnet *ifp)
3362: {
3363: int pri, tx_timeouts = 0;
3364: struct rtw_softc *sc;
3365: struct rtw_txsoft_blk *tsb;
3366:
3367: sc = ifp->if_softc;
3368:
3369: ifp->if_timer = 0;
3370:
3371: if ((sc->sc_flags & RTW_F_ENABLED) == 0)
3372: return;
3373:
3374: for (pri = 0; pri < RTW_NTXPRI; pri++) {
3375: tsb = &sc->sc_txsoft_blk[pri];
3376:
3377: if (tsb->tsb_tx_timer == 0)
3378: continue;
3379: else if (--tsb->tsb_tx_timer == 0) {
3380: if (SIMPLEQ_EMPTY(&tsb->tsb_dirtyq))
3381: continue;
3382: RTW_DPRINTF(RTW_DEBUG_BUGS,
3383: ("%s: transmit timeout, priority %d\n",
3384: ifp->if_xname, pri));
3385: ifp->if_oerrors++;
3386: tx_timeouts++;
3387: } else
3388: ifp->if_timer = 1;
3389: }
3390:
3391: if (tx_timeouts > 0) {
3392: /* Stop Tx DMA, disable xmtr, flush Tx rings, enable xmtr,
3393: * reset s/w tx-ring pointers, and start transmission.
3394: *
3395: * TBD Stop/restart just the broken rings?
3396: */
3397: rtw_idle(&sc->sc_regs);
3398: rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 0);
3399: rtw_txdescs_reset(sc);
3400: rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 1);
3401: rtw_txring_fixup(sc);
3402: rtw_start(ifp);
3403: }
3404: ieee80211_watchdog(ifp);
3405: }
3406:
3407: void
3408: rtw_next_scan(void *arg)
3409: {
3410: struct rtw_softc *sc = arg;
3411: struct ieee80211com *ic = &sc->sc_ic;
3412: struct ifnet *ifp = &ic->ic_if;
3413: int s;
3414:
3415: /* don't call rtw_start w/o network interrupts blocked */
3416: s = splnet();
3417: if (ic->ic_state == IEEE80211_S_SCAN)
3418: ieee80211_next_scan(ifp);
3419: splx(s);
3420: }
3421:
3422: void
3423: rtw_join_bss(struct rtw_softc *sc, u_int8_t *bssid, u_int16_t intval0)
3424: {
3425: uint16_t bcnitv, bintritv, intval;
3426: int i;
3427: struct rtw_regs *regs = &sc->sc_regs;
3428:
3429: for (i = 0; i < IEEE80211_ADDR_LEN; i++)
3430: RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]);
3431:
3432: RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32);
3433:
3434: rtw_set_access(regs, RTW_ACCESS_CONFIG);
3435:
3436: intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK));
3437:
3438: bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
3439: bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK);
3440: RTW_WRITE16(regs, RTW_BCNITV, bcnitv);
3441: /* interrupt host 1ms before the TBTT */
3442: bintritv = RTW_READ16(regs, RTW_BINTRITV) & ~RTW_BINTRITV_BINTRITV;
3443: bintritv |= LSHIFT(1000, RTW_BINTRITV_BINTRITV);
3444: RTW_WRITE16(regs, RTW_BINTRITV, bintritv);
3445: /* magic from Linux */
3446: RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
3447: RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
3448: rtw_set_access(regs, RTW_ACCESS_NONE);
3449:
3450: /* TBD WEP */
3451: RTW_WRITE8(regs, RTW8180_SCR, 0);
3452:
3453: rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
3454: }
3455:
3456: /* Synchronize the hardware state with the software state. */
3457: int
3458: rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
3459: {
3460: struct ifnet *ifp = &ic->ic_if;
3461: struct rtw_softc *sc = ifp->if_softc;
3462: enum ieee80211_state ostate;
3463: int error;
3464:
3465: ostate = ic->ic_state;
3466:
3467: rtw_led_newstate(sc, nstate);
3468:
3469: if (nstate == IEEE80211_S_INIT) {
3470: timeout_del(&sc->sc_scan_to);
3471: sc->sc_cur_chan = IEEE80211_CHAN_ANY;
3472: return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
3473: }
3474:
3475: if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
3476: rtw_pwrstate(sc, RTW_ON);
3477:
3478: if ((error = rtw_tune(sc)) != 0)
3479: return error;
3480:
3481: switch (nstate) {
3482: case IEEE80211_S_INIT:
3483: panic("%s: unexpected state IEEE80211_S_INIT", __func__);
3484: break;
3485: case IEEE80211_S_SCAN:
3486: if (ostate != IEEE80211_S_SCAN) {
3487: bzero(ic->ic_bss->ni_bssid, IEEE80211_ADDR_LEN);
3488: rtw_set_nettype(sc, IEEE80211_M_MONITOR);
3489: }
3490:
3491: timeout_add(&sc->sc_scan_to, rtw_dwelltime * hz / 1000);
3492:
3493: break;
3494: case IEEE80211_S_RUN:
3495: switch (ic->ic_opmode) {
3496: case IEEE80211_M_HOSTAP:
3497: case IEEE80211_M_IBSS:
3498: rtw_set_nettype(sc, IEEE80211_M_MONITOR);
3499: /*FALLTHROUGH*/
3500: case IEEE80211_M_AHDEMO:
3501: case IEEE80211_M_STA:
3502: rtw_join_bss(sc, ic->ic_bss->ni_bssid,
3503: ic->ic_bss->ni_intval);
3504: break;
3505: case IEEE80211_M_MONITOR:
3506: break;
3507: }
3508: rtw_set_nettype(sc, ic->ic_opmode);
3509: break;
3510: case IEEE80211_S_ASSOC:
3511: case IEEE80211_S_AUTH:
3512: break;
3513: }
3514:
3515: if (nstate != IEEE80211_S_SCAN)
3516: timeout_del(&sc->sc_scan_to);
3517:
3518: return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
3519: }
3520:
3521: /* Extend a 32-bit TSF timestamp to a 64-bit timestamp. */
3522: uint64_t
3523: rtw_tsf_extend(struct rtw_regs *regs, u_int32_t rstamp)
3524: {
3525: u_int32_t tsftl, tsfth;
3526:
3527: tsfth = RTW_READ(regs, RTW_TSFTRH);
3528: tsftl = RTW_READ(regs, RTW_TSFTRL);
3529: if (tsftl < rstamp) /* Compensate for rollover. */
3530: tsfth--;
3531: return ((u_int64_t)tsfth << 32) | rstamp;
3532: }
3533:
3534: void
3535: rtw_ibss_merge(struct rtw_softc *sc, struct ieee80211_node *ni,
3536: u_int32_t rstamp)
3537: {
3538: u_int8_t tppoll;
3539: struct ieee80211com *ic = &sc->sc_ic;
3540:
3541: if (ieee80211_ibss_merge(ic, ni,
3542: rtw_tsf_extend(&sc->sc_regs, rstamp)) == ENETRESET) {
3543: /* Stop beacon queue. Kick state machine to synchronize
3544: * with the new IBSS.
3545: */
3546: tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
3547: tppoll |= RTW_TPPOLL_SBQ;
3548: RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
3549: (void)ieee80211_new_state(&sc->sc_ic, IEEE80211_S_RUN, -1);
3550: }
3551: return;
3552: }
3553:
3554: void
3555: rtw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
3556: struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
3557: {
3558: struct rtw_softc *sc = (struct rtw_softc*)ic->ic_softc;
3559:
3560: (*sc->sc_mtbl.mt_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
3561:
3562: switch (subtype) {
3563: case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
3564: case IEEE80211_FC0_SUBTYPE_BEACON:
3565: if (ic->ic_opmode != IEEE80211_M_IBSS ||
3566: ic->ic_state != IEEE80211_S_RUN)
3567: return;
3568: rtw_ibss_merge(sc, ni, rstamp);
3569: break;
3570: default:
3571: break;
3572: }
3573: return;
3574: }
3575:
3576: struct ieee80211_node *
3577: rtw_node_alloc(struct ieee80211com *ic)
3578: {
3579: struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
3580: struct ieee80211_node *ni = (*sc->sc_mtbl.mt_node_alloc)(ic);
3581:
3582: DPRINTF(sc, RTW_DEBUG_NODE,
3583: ("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni));
3584: return ni;
3585: }
3586:
3587: void
3588: rtw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
3589: {
3590: struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
3591:
3592: DPRINTF(sc, RTW_DEBUG_NODE,
3593: ("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni,
3594: ether_sprintf(ni->ni_bssid)));
3595: (*sc->sc_mtbl.mt_node_free)(ic, ni);
3596: }
3597:
3598: int
3599: rtw_media_change(struct ifnet *ifp)
3600: {
3601: int error;
3602:
3603: error = ieee80211_media_change(ifp);
3604: if (error == ENETRESET) {
3605: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
3606: (IFF_RUNNING|IFF_UP))
3607: rtw_init(ifp); /* XXX lose error */
3608: error = 0;
3609: }
3610: return error;
3611: }
3612:
3613: void
3614: rtw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
3615: {
3616: struct rtw_softc *sc = ifp->if_softc;
3617:
3618: if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
3619: imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
3620: imr->ifm_status = 0;
3621: return;
3622: }
3623: ieee80211_media_status(ifp, imr);
3624: }
3625:
3626: void
3627: rtw_power(int why, void *arg)
3628: {
3629: struct rtw_softc *sc = arg;
3630: struct ifnet *ifp = &sc->sc_ic.ic_if;
3631: int s;
3632:
3633: DPRINTF(sc, RTW_DEBUG_PWR,
3634: ("%s: rtw_power(%d,)\n", sc->sc_dev.dv_xname, why));
3635:
3636: s = splnet();
3637: switch (why) {
3638: case PWR_STANDBY:
3639: /* XXX do nothing. */
3640: break;
3641: case PWR_SUSPEND:
3642: rtw_stop(ifp, 1);
3643: if (sc->sc_power != NULL)
3644: (*sc->sc_power)(sc, why);
3645: break;
3646: case PWR_RESUME:
3647: if (ifp->if_flags & IFF_UP) {
3648: if (sc->sc_power != NULL)
3649: (*sc->sc_power)(sc, why);
3650: rtw_init(ifp);
3651: }
3652: break;
3653: }
3654: splx(s);
3655: }
3656:
3657: /* rtw_shutdown: make sure the interface is stopped at reboot time. */
3658: void
3659: rtw_shutdown(void *arg)
3660: {
3661: struct rtw_softc *sc = arg;
3662:
3663: rtw_stop(&sc->sc_ic.ic_if, 1);
3664: }
3665:
3666: void
3667: rtw_establish_hooks(struct rtw_hooks *hooks, const char *dvname,
3668: void *arg)
3669: {
3670: /*
3671: * Make sure the interface is shutdown during reboot.
3672: */
3673: hooks->rh_shutdown = shutdownhook_establish(rtw_shutdown, arg);
3674: if (hooks->rh_shutdown == NULL)
3675: printf("%s: WARNING: unable to establish shutdown hook\n",
3676: dvname);
3677:
3678: /*
3679: * Add a suspend hook to make sure we come back up after a
3680: * resume.
3681: */
3682: hooks->rh_power = powerhook_establish(rtw_power, arg);
3683: if (hooks->rh_power == NULL)
3684: printf("%s: WARNING: unable to establish power hook\n",
3685: dvname);
3686: }
3687:
3688: void
3689: rtw_disestablish_hooks(struct rtw_hooks *hooks, const char *dvname,
3690: void *arg)
3691: {
3692: if (hooks->rh_shutdown != NULL)
3693: shutdownhook_disestablish(hooks->rh_shutdown);
3694:
3695: if (hooks->rh_power != NULL)
3696: powerhook_disestablish(hooks->rh_power);
3697: }
3698:
3699: int
3700: rtw_txsoft_blk_setup(struct rtw_txsoft_blk *tsb, u_int qlen)
3701: {
3702: SIMPLEQ_INIT(&tsb->tsb_dirtyq);
3703: SIMPLEQ_INIT(&tsb->tsb_freeq);
3704: tsb->tsb_ndesc = qlen;
3705: tsb->tsb_desc = malloc(qlen * sizeof(*tsb->tsb_desc), M_DEVBUF,
3706: M_NOWAIT);
3707: if (tsb->tsb_desc == NULL)
3708: return ENOMEM;
3709: return 0;
3710: }
3711:
3712: void
3713: rtw_txsoft_blk_cleanup_all(struct rtw_softc *sc)
3714: {
3715: int pri;
3716: struct rtw_txsoft_blk *tsb;
3717:
3718: for (pri = 0; pri < RTW_NTXPRI; pri++) {
3719: tsb = &sc->sc_txsoft_blk[pri];
3720: free(tsb->tsb_desc, M_DEVBUF);
3721: tsb->tsb_desc = NULL;
3722: }
3723: }
3724:
3725: int
3726: rtw_txsoft_blk_setup_all(struct rtw_softc *sc)
3727: {
3728: int pri, rc = 0;
3729: int qlen[RTW_NTXPRI] =
3730: {RTW_TXQLENLO, RTW_TXQLENMD, RTW_TXQLENHI, RTW_TXQLENBCN};
3731: struct rtw_txsoft_blk *tsbs;
3732:
3733: tsbs = sc->sc_txsoft_blk;
3734:
3735: for (pri = 0; pri < RTW_NTXPRI; pri++) {
3736: rc = rtw_txsoft_blk_setup(&tsbs[pri], qlen[pri]);
3737: if (rc != 0)
3738: break;
3739: }
3740: tsbs[RTW_TXPRILO].tsb_poll = RTW_TPPOLL_LPQ | RTW_TPPOLL_SLPQ;
3741: tsbs[RTW_TXPRIMD].tsb_poll = RTW_TPPOLL_NPQ | RTW_TPPOLL_SNPQ;
3742: tsbs[RTW_TXPRIHI].tsb_poll = RTW_TPPOLL_HPQ | RTW_TPPOLL_SHPQ;
3743: tsbs[RTW_TXPRIBCN].tsb_poll = RTW_TPPOLL_BQ | RTW_TPPOLL_SBQ;
3744: return rc;
3745: }
3746:
3747: void
3748: rtw_txdesc_blk_setup(struct rtw_txdesc_blk *tdb, struct rtw_txdesc *desc,
3749: u_int ndesc, bus_addr_t ofs, bus_addr_t physbase)
3750: {
3751: tdb->tdb_ndesc = ndesc;
3752: tdb->tdb_desc = desc;
3753: tdb->tdb_physbase = physbase;
3754: tdb->tdb_ofs = ofs;
3755:
3756: bzero(tdb->tdb_desc, sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
3757:
3758: rtw_txdesc_blk_init(tdb);
3759: tdb->tdb_next = 0;
3760: }
3761:
3762: void
3763: rtw_txdesc_blk_setup_all(struct rtw_softc *sc)
3764: {
3765: rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRILO],
3766: &sc->sc_descs->hd_txlo[0], RTW_NTXDESCLO,
3767: RTW_RING_OFFSET(hd_txlo), RTW_RING_BASE(sc, hd_txlo));
3768:
3769: rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIMD],
3770: &sc->sc_descs->hd_txmd[0], RTW_NTXDESCMD,
3771: RTW_RING_OFFSET(hd_txmd), RTW_RING_BASE(sc, hd_txmd));
3772:
3773: rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIHI],
3774: &sc->sc_descs->hd_txhi[0], RTW_NTXDESCHI,
3775: RTW_RING_OFFSET(hd_txhi), RTW_RING_BASE(sc, hd_txhi));
3776:
3777: rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIBCN],
3778: &sc->sc_descs->hd_bcn[0], RTW_NTXDESCBCN,
3779: RTW_RING_OFFSET(hd_bcn), RTW_RING_BASE(sc, hd_bcn));
3780: }
3781:
3782: int
3783: rtw_rf_attach(struct rtw_softc *sc, int rfchipid)
3784: {
3785: struct rtw_bbpset *bb = &sc->sc_bbpset;
3786: int notsup = 0;
3787: const char *rfname, *paname = NULL;
3788: char scratch[sizeof("unknown 0xXX")];
3789:
3790: switch (rfchipid) {
3791: case RTW_RFCHIPID_RTL8225:
3792: rfname = "RTL8225";
3793: sc->sc_pwrstate_cb = rtw_rtl_pwrstate;
3794: sc->sc_rf_init = rtw_rtl8255_init;
3795: sc->sc_rf_pwrstate = rtw_rtl8225_pwrstate;
3796: sc->sc_rf_tune = rtw_rtl8225_tune;
3797: sc->sc_rf_txpower = rtw_rtl8225_txpower;
3798: break;
3799: case RTW_RFCHIPID_RTL8255:
3800: rfname = "RTL8255";
3801: sc->sc_pwrstate_cb = rtw_rtl_pwrstate;
3802: sc->sc_rf_init = rtw_rtl8255_init;
3803: sc->sc_rf_pwrstate = rtw_rtl8255_pwrstate;
3804: sc->sc_rf_tune = rtw_rtl8255_tune;
3805: sc->sc_rf_txpower = rtw_rtl8255_txpower;
3806: break;
3807: case RTW_RFCHIPID_MAXIM2820:
3808: rfname = "MAX2820"; /* guess */
3809: paname = "MAX2422"; /* guess */
3810: /* XXX magic */
3811: bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC;
3812: bb->bb_chestlim = 0x00;
3813: bb->bb_chsqlim = 0x9f;
3814: bb->bb_ifagcdet = 0x64;
3815: bb->bb_ifagcini = 0x90;
3816: bb->bb_ifagclimit = 0x1a;
3817: bb->bb_lnadet = 0xf8;
3818: bb->bb_sys1 = 0x88;
3819: bb->bb_sys2 = 0x47;
3820: bb->bb_sys3 = 0x9b;
3821: bb->bb_trl = 0x88;
3822: bb->bb_txagc = 0x08;
3823: sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
3824: sc->sc_rf_init = rtw_max2820_init;
3825: sc->sc_rf_pwrstate = rtw_max2820_pwrstate;
3826: sc->sc_rf_tune = rtw_max2820_tune;
3827: sc->sc_rf_txpower = rtw_max2820_txpower;
3828: break;
3829: case RTW_RFCHIPID_PHILIPS:
3830: rfname = "SA2400A";
3831: paname = "SA2411";
3832: /* XXX magic */
3833: bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC;
3834: bb->bb_chestlim = 0x00;
3835: bb->bb_chsqlim = 0xa0;
3836: bb->bb_ifagcdet = 0x64;
3837: bb->bb_ifagcini = 0x90;
3838: bb->bb_ifagclimit = 0x1a;
3839: bb->bb_lnadet = 0xe0;
3840: bb->bb_sys1 = 0x98;
3841: bb->bb_sys2 = 0x47;
3842: bb->bb_sys3 = 0x90;
3843: bb->bb_trl = 0x88;
3844: bb->bb_txagc = 0x38;
3845: sc->sc_pwrstate_cb = rtw_philips_pwrstate;
3846: sc->sc_rf_init = rtw_sa2400_init;
3847: sc->sc_rf_pwrstate = rtw_sa2400_pwrstate;
3848: sc->sc_rf_tune = rtw_sa2400_tune;
3849: sc->sc_rf_txpower = rtw_sa2400_txpower;
3850: break;
3851: case RTW_RFCHIPID_RFMD2948:
3852: /* this is the same front-end as an atw(4)! */
3853: rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */
3854: "LNA: RFMD RF2494, " /* mentioned in Realtek docs */
3855: "SYN: Silicon Labs Si4126"; /* inferred from
3856: * reference driver
3857: */
3858: paname = "RF2189"; /* mentioned in Realtek docs */
3859: /* XXX RFMD has no RF constructor */
3860: sc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
3861: notsup = 1;
3862: break;
3863: case RTW_RFCHIPID_GCT: /* this combo seen in the wild */
3864: rfname = "GRF5101";
3865: paname = "WS9901";
3866: /* XXX magic */
3867: bb->bb_antatten = RTW_BBP_ANTATTEN_GCT_MAGIC;
3868: bb->bb_chestlim = 0x00;
3869: bb->bb_chsqlim = 0xa0;
3870: bb->bb_ifagcdet = 0x64;
3871: bb->bb_ifagcini = 0x90;
3872: bb->bb_ifagclimit = 0x1e;
3873: bb->bb_lnadet = 0xc0;
3874: bb->bb_sys1 = 0xa8;
3875: bb->bb_sys2 = 0x47;
3876: bb->bb_sys3 = 0x9b;
3877: bb->bb_trl = 0x88;
3878: bb->bb_txagc = 0x08;
3879: sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
3880: sc->sc_rf_init = rtw_grf5101_init;
3881: sc->sc_rf_pwrstate = rtw_grf5101_pwrstate;
3882: sc->sc_rf_tune = rtw_grf5101_tune;
3883: sc->sc_rf_txpower = rtw_grf5101_txpower;
3884: break;
3885: case RTW_RFCHIPID_INTERSIL:
3886: rfname = "HFA3873"; /* guess */
3887: paname = "Intersil <unknown>";
3888: notsup = 1;
3889: break;
3890: default:
3891: snprintf(scratch, sizeof(scratch), "unknown 0x%02x", rfchipid);
3892: rfname = scratch;
3893: notsup = 1;
3894: }
3895:
3896: printf("radio %s, ", rfname);
3897: if (paname != NULL)
3898: printf("amp %s, ", paname);
3899:
3900: return (notsup);
3901: }
3902:
3903: /* Revision C and later use a different PHY delay setting than
3904: * revisions A and B.
3905: */
3906: u_int8_t
3907: rtw_check_phydelay(struct rtw_regs *regs, u_int32_t rcr0)
3908: {
3909: #define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
3910: #define REVC (REVAB | RTW8180_RCR_RXFTH_WHOLE)
3911:
3912: u_int8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
3913:
3914: RTW_WRITE(regs, RTW_RCR, REVAB);
3915: RTW_WBW(regs, RTW_RCR, RTW_RCR);
3916: RTW_WRITE(regs, RTW_RCR, REVC);
3917:
3918: RTW_WBR(regs, RTW_RCR, RTW_RCR);
3919: if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC)
3920: phydelay |= RTW_PHYDELAY_REVC_MAGIC;
3921:
3922: RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */
3923: RTW_SYNC(regs, RTW_RCR, RTW_RCR);
3924:
3925: return phydelay;
3926: #undef REVC
3927: }
3928:
3929: void
3930: rtw_attach(struct rtw_softc *sc)
3931: {
3932: struct ieee80211com *ic = &sc->sc_ic;
3933: struct rtw_txsoft_blk *tsb;
3934: struct rtw_mtbl *mtbl;
3935: struct rtw_srom *sr;
3936: const char *vername;
3937: struct ifnet *ifp;
3938: char scratch[sizeof("unknown 0xXXXXXXXX")];
3939: int pri, rc;
3940:
3941:
3942: /* Use default DMA memory access */
3943: if (sc->sc_regs.r_read8 == NULL) {
3944: sc->sc_regs.r_read8 = rtw_read8;
3945: sc->sc_regs.r_read16 = rtw_read16;
3946: sc->sc_regs.r_read32 = rtw_read32;
3947: sc->sc_regs.r_write8 = rtw_write8;
3948: sc->sc_regs.r_write16 = rtw_write16;
3949: sc->sc_regs.r_write32 = rtw_write32;
3950: sc->sc_regs.r_barrier = rtw_barrier;
3951: }
3952:
3953: sc->sc_hwverid = RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK;
3954: switch (sc->sc_hwverid) {
3955: case RTW_TCR_HWVERID_RTL8185:
3956: vername = "RTL8185";
3957: sc->sc_flags |= RTW_F_RTL8185;
3958: break;
3959: case RTW_TCR_HWVERID_RTL8180F:
3960: vername = "RTL8180F";
3961: break;
3962: case RTW_TCR_HWVERID_RTL8180D:
3963: vername = "RTL8180D";
3964: break;
3965: default:
3966: snprintf(scratch, sizeof(scratch), "unknown 0x%08x",
3967: sc->sc_hwverid);
3968: vername = scratch;
3969: break;
3970: }
3971:
3972: printf("%s: ver %s, ", sc->sc_dev.dv_xname, vername);
3973:
3974: rc = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct rtw_descs),
3975: RTW_DESC_ALIGNMENT, 0, &sc->sc_desc_segs, 1, &sc->sc_desc_nsegs,
3976: 0);
3977:
3978: if (rc != 0) {
3979: printf("\n%s: could not allocate hw descriptors, error %d\n",
3980: sc->sc_dev.dv_xname, rc);
3981: goto fail0;
3982: }
3983:
3984: rc = bus_dmamem_map(sc->sc_dmat, &sc->sc_desc_segs,
3985: sc->sc_desc_nsegs, sizeof(struct rtw_descs),
3986: (caddr_t*)&sc->sc_descs, BUS_DMA_COHERENT);
3987:
3988: if (rc != 0) {
3989: printf("\n%s: could not map hw descriptors, error %d\n",
3990: sc->sc_dev.dv_xname, rc);
3991: goto fail1;
3992: }
3993:
3994: rc = bus_dmamap_create(sc->sc_dmat, sizeof(struct rtw_descs), 1,
3995: sizeof(struct rtw_descs), 0, 0, &sc->sc_desc_dmamap);
3996:
3997: if (rc != 0) {
3998: printf("\n%s: could not create DMA map for hw descriptors, "
3999: "error %d\n", sc->sc_dev.dv_xname, rc);
4000: goto fail2;
4001: }
4002:
4003: sc->sc_rxdesc_blk.rdb_dmat = sc->sc_dmat;
4004: sc->sc_rxdesc_blk.rdb_dmamap = sc->sc_desc_dmamap;
4005:
4006: for (pri = 0; pri < RTW_NTXPRI; pri++) {
4007: sc->sc_txdesc_blk[pri].tdb_dmat = sc->sc_dmat;
4008: sc->sc_txdesc_blk[pri].tdb_dmamap = sc->sc_desc_dmamap;
4009: }
4010:
4011: rc = bus_dmamap_load(sc->sc_dmat, sc->sc_desc_dmamap, sc->sc_descs,
4012: sizeof(struct rtw_descs), NULL, 0);
4013:
4014: if (rc != 0) {
4015: printf("\n%s: could not load DMA map for hw descriptors, "
4016: "error %d\n", sc->sc_dev.dv_xname, rc);
4017: goto fail3;
4018: }
4019:
4020: if (rtw_txsoft_blk_setup_all(sc) != 0)
4021: goto fail4;
4022:
4023: rtw_txdesc_blk_setup_all(sc);
4024:
4025: sc->sc_rxdesc_blk.rdb_desc = &sc->sc_descs->hd_rx[0];
4026:
4027: for (pri = 0; pri < RTW_NTXPRI; pri++) {
4028: tsb = &sc->sc_txsoft_blk[pri];
4029:
4030: if ((rc = rtw_txdesc_dmamaps_create(sc->sc_dmat,
4031: &tsb->tsb_desc[0], tsb->tsb_ndesc)) != 0) {
4032: printf("\n%s: could not load DMA map for "
4033: "hw tx descriptors, error %d\n",
4034: sc->sc_dev.dv_xname, rc);
4035: goto fail5;
4036: }
4037: }
4038:
4039: if ((rc = rtw_rxdesc_dmamaps_create(sc->sc_dmat, &sc->sc_rxsoft[0],
4040: RTW_RXQLEN)) != 0) {
4041: printf("\n%s: could not load DMA map for hw rx descriptors, "
4042: "error %d\n", sc->sc_dev.dv_xname, rc);
4043: goto fail6;
4044: }
4045:
4046: /* Reset the chip to a known state. */
4047: if (rtw_reset(sc) != 0)
4048: goto fail7;
4049:
4050: sc->sc_rcr = RTW_READ(&sc->sc_regs, RTW_RCR);
4051:
4052: if ((sc->sc_rcr & RTW_RCR_9356SEL) != 0)
4053: sc->sc_flags |= RTW_F_9356SROM;
4054:
4055: if (rtw_srom_read(&sc->sc_regs, sc->sc_flags, &sc->sc_srom,
4056: sc->sc_dev.dv_xname) != 0)
4057: goto fail7;
4058:
4059: if (rtw_srom_parse(sc) != 0) {
4060: printf("\n%s: attach failed, malformed serial ROM\n",
4061: sc->sc_dev.dv_xname);
4062: goto fail8;
4063: }
4064:
4065: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: %s PHY\n", sc->sc_dev.dv_xname,
4066: ((sc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog"));
4067:
4068: RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: CS threshold %u\n",
4069: sc->sc_dev.dv_xname, sc->sc_csthr));
4070:
4071: if ((rtw_rf_attach(sc, sc->sc_rfchipid)) != 0) {
4072: printf("\n%s: attach failed, could not attach RF\n",
4073: sc->sc_dev.dv_xname);
4074: goto fail8;
4075: }
4076:
4077: sc->sc_phydelay = rtw_check_phydelay(&sc->sc_regs, sc->sc_rcr);
4078:
4079: RTW_DPRINTF(RTW_DEBUG_ATTACH,
4080: ("%s: PHY delay %d\n", sc->sc_dev.dv_xname, sc->sc_phydelay));
4081:
4082: if (sc->sc_locale == RTW_LOCALE_UNKNOWN)
4083: rtw_identify_country(&sc->sc_regs, &sc->sc_locale);
4084:
4085: rtw_init_channels(sc->sc_locale, &sc->sc_ic.ic_channels,
4086: sc->sc_dev.dv_xname);
4087:
4088: if (rtw_identify_sta(&sc->sc_regs, &sc->sc_ic.ic_myaddr,
4089: sc->sc_dev.dv_xname) != 0)
4090: goto fail8;
4091:
4092: ifp = &sc->sc_if;
4093: (void)memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
4094: ifp->if_softc = sc;
4095: ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
4096: IFF_NOTRAILERS;
4097: ifp->if_ioctl = rtw_ioctl;
4098: ifp->if_start = rtw_start;
4099: ifp->if_watchdog = rtw_watchdog;
4100:
4101: IFQ_SET_READY(&sc->sc_if.if_snd);
4102:
4103: ic->ic_phytype = IEEE80211_T_DS;
4104: ic->ic_opmode = IEEE80211_M_STA;
4105: ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
4106: IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP;
4107:
4108: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
4109:
4110: rtw_led_attach(&sc->sc_led_state, (void *)sc);
4111:
4112: /*
4113: * Call MI attach routines.
4114: */
4115: if_attach(&sc->sc_if);
4116: ieee80211_ifattach(&sc->sc_if);
4117:
4118: mtbl = &sc->sc_mtbl;
4119: mtbl->mt_newstate = ic->ic_newstate;
4120: ic->ic_newstate = rtw_newstate;
4121:
4122: mtbl->mt_recv_mgmt = ic->ic_recv_mgmt;
4123: ic->ic_recv_mgmt = rtw_recv_mgmt;
4124:
4125: mtbl->mt_node_free = ic->ic_node_free;
4126: ic->ic_node_free = rtw_node_free;
4127:
4128: mtbl->mt_node_alloc = ic->ic_node_alloc;
4129: ic->ic_node_alloc = rtw_node_alloc;
4130:
4131: /* possibly we should fill in our own sc_send_prresp, since
4132: * the RTL8180 is probably sending probe responses in ad hoc
4133: * mode.
4134: */
4135:
4136: /* complete initialization */
4137: ieee80211_media_init(&sc->sc_if, rtw_media_change, rtw_media_status);
4138: timeout_set(&sc->sc_scan_to, rtw_next_scan, sc);
4139:
4140: #if NBPFILTER > 0
4141: bzero(&sc->sc_rxtapu, sizeof(sc->sc_rxtapu));
4142: sc->sc_rxtap.rr_ihdr.it_len = sizeof(sc->sc_rxtapu);
4143: sc->sc_rxtap.rr_ihdr.it_present = RTW_RX_RADIOTAP_PRESENT;
4144:
4145: bzero(&sc->sc_txtapu, sizeof(sc->sc_txtapu));
4146: sc->sc_txtap.rt_ihdr.it_len = sizeof(sc->sc_txtapu);
4147: sc->sc_txtap.rt_ihdr.it_present = RTW_TX_RADIOTAP_PRESENT;
4148:
4149: bpfattach(&sc->sc_radiobpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
4150: sizeof(struct ieee80211_frame) + 64);
4151: #endif
4152:
4153: rtw_establish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname, (void*)sc);
4154:
4155: return;
4156:
4157: fail8:
4158: sr = &sc->sc_srom;
4159: sr->sr_size = 0;
4160: if (sr->sr_content != NULL) {
4161: free(sr->sr_content, M_DEVBUF);
4162: sr->sr_content = NULL;
4163: }
4164:
4165: fail7:
4166: rtw_rxdesc_dmamaps_destroy(sc->sc_dmat, &sc->sc_rxsoft[0],
4167: RTW_RXQLEN);
4168:
4169: fail6:
4170: for (pri = 0; pri < RTW_NTXPRI; pri++) {
4171: rtw_txdesc_dmamaps_destroy(sc->sc_dmat,
4172: sc->sc_txsoft_blk[pri].tsb_desc,
4173: sc->sc_txsoft_blk[pri].tsb_ndesc);
4174: }
4175:
4176: fail5:
4177: rtw_txsoft_blk_cleanup_all(sc);
4178:
4179: fail4:
4180: bus_dmamap_unload(sc->sc_dmat, sc->sc_desc_dmamap);
4181: fail3:
4182: bus_dmamap_destroy(sc->sc_dmat, sc->sc_desc_dmamap);
4183: fail2:
4184: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_descs,
4185: sizeof(struct rtw_descs));
4186: fail1:
4187: bus_dmamem_free(sc->sc_dmat, &sc->sc_desc_segs,
4188: sc->sc_desc_nsegs);
4189: fail0:
4190: return;
4191: }
4192:
4193: int
4194: rtw_detach(struct rtw_softc *sc)
4195: {
4196: sc->sc_flags |= RTW_F_INVALID;
4197:
4198: rtw_stop(&sc->sc_if, 1);
4199:
4200: rtw_disestablish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname,
4201: (void*)sc);
4202: timeout_del(&sc->sc_scan_to);
4203: ieee80211_ifdetach(&sc->sc_if);
4204: if_detach(&sc->sc_if);
4205:
4206: return 0;
4207: }
4208:
4209: /*
4210: * PHY specific functions
4211: */
4212:
4213: int
4214: rtw_bbp_preinit(struct rtw_regs *regs, u_int antatten0, int dflantb,
4215: u_int freq)
4216: {
4217: u_int antatten = antatten0;
4218: if (dflantb)
4219: antatten |= RTW_BBP_ANTATTEN_DFLANTB;
4220: if (freq == 2484) /* channel 14 */
4221: antatten |= RTW_BBP_ANTATTEN_CHAN14;
4222: return rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten);
4223: }
4224:
4225: int
4226: rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv,
4227: int dflantb, u_int8_t cs_threshold, u_int freq)
4228: {
4229: int rc;
4230: u_int32_t sys2, sys3;
4231:
4232: sys2 = bb->bb_sys2;
4233: if (antdiv)
4234: sys2 |= RTW_BBP_SYS2_ANTDIV;
4235: sys3 = bb->bb_sys3 |
4236: LSHIFT(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK);
4237:
4238: #define RTW_BBP_WRITE_OR_RETURN(reg, val) \
4239: if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \
4240: return rc;
4241:
4242: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1, bb->bb_sys1);
4243: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC, bb->bb_txagc);
4244: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET, bb->bb_lnadet);
4245: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI, bb->bb_ifagcini);
4246: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT, bb->bb_ifagclimit);
4247: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET, bb->bb_ifagcdet);
4248:
4249: if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0)
4250: return rc;
4251:
4252: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL, bb->bb_trl);
4253: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2, sys2);
4254: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3, sys3);
4255: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM, bb->bb_chestlim);
4256: RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM, bb->bb_chsqlim);
4257: return 0;
4258: }
4259:
4260: int
4261: rtw_sa2400_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
4262: {
4263: return rtw_rf_macwrite(sc, SA2400_TX, opaque_txpower);
4264: }
4265:
4266: /* make sure we're using the same settings as the reference driver */
4267: void
4268: rtw_verify_syna(u_int freq, u_int32_t val)
4269: {
4270: u_int32_t expected_val = ~val;
4271:
4272: switch (freq) {
4273: case 2412:
4274: expected_val = 0x0000096c; /* ch 1 */
4275: break;
4276: case 2417:
4277: expected_val = 0x00080970; /* ch 2 */
4278: break;
4279: case 2422:
4280: expected_val = 0x00100974; /* ch 3 */
4281: break;
4282: case 2427:
4283: expected_val = 0x00180978; /* ch 4 */
4284: break;
4285: case 2432:
4286: expected_val = 0x00000980; /* ch 5 */
4287: break;
4288: case 2437:
4289: expected_val = 0x00080984; /* ch 6 */
4290: break;
4291: case 2442:
4292: expected_val = 0x00100988; /* ch 7 */
4293: break;
4294: case 2447:
4295: expected_val = 0x0018098c; /* ch 8 */
4296: break;
4297: case 2452:
4298: expected_val = 0x00000994; /* ch 9 */
4299: break;
4300: case 2457:
4301: expected_val = 0x00080998; /* ch 10 */
4302: break;
4303: case 2462:
4304: expected_val = 0x0010099c; /* ch 11 */
4305: break;
4306: case 2467:
4307: expected_val = 0x001809a0; /* ch 12 */
4308: break;
4309: case 2472:
4310: expected_val = 0x000009a8; /* ch 13 */
4311: break;
4312: case 2484:
4313: expected_val = 0x000009b4; /* ch 14 */
4314: break;
4315: }
4316: KASSERT(val == expected_val);
4317: }
4318:
4319: /* freq is in MHz */
4320: int
4321: rtw_sa2400_tune(struct rtw_softc *sc, u_int freq)
4322: {
4323: int rc;
4324: u_int32_t syna, synb, sync;
4325:
4326: /* XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz.
4327: *
4328: * The channel spacing (5MHz) is not divisible by 4MHz, so
4329: * we set the fractional part of N to compensate.
4330: */
4331: int n = freq / 4, nf = (freq % 4) * 2;
4332:
4333: syna = LSHIFT(nf, SA2400_SYNA_NF_MASK) | LSHIFT(n, SA2400_SYNA_N_MASK);
4334: rtw_verify_syna(freq, syna);
4335:
4336: /* Divide the 44MHz crystal down to 4MHz. Set the fractional
4337: * compensation charge pump value to agree with the fractional
4338: * modulus.
4339: */
4340: synb = LSHIFT(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL |
4341: SA2400_SYNB_ON | SA2400_SYNB_ONE |
4342: LSHIFT(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */
4343:
4344: sync = SA2400_SYNC_CP_NORMAL;
4345:
4346: if ((rc = rtw_rf_macwrite(sc, SA2400_SYNA, syna)) != 0)
4347: return rc;
4348: if ((rc = rtw_rf_macwrite(sc, SA2400_SYNB, synb)) != 0)
4349: return rc;
4350: if ((rc = rtw_rf_macwrite(sc, SA2400_SYNC, sync)) != 0)
4351: return rc;
4352: return rtw_rf_macwrite(sc, SA2400_SYND, 0x0);
4353: }
4354:
4355: int
4356: rtw_sa2400_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
4357: {
4358: u_int32_t opmode;
4359: opmode = SA2400_OPMODE_DEFAULTS;
4360: switch (power) {
4361: case RTW_ON:
4362: opmode |= SA2400_OPMODE_MODE_TXRX;
4363: break;
4364: case RTW_SLEEP:
4365: opmode |= SA2400_OPMODE_MODE_WAIT;
4366: break;
4367: case RTW_OFF:
4368: opmode |= SA2400_OPMODE_MODE_SLEEP;
4369: break;
4370: }
4371:
4372: if (sc->sc_flags & RTW_F_DIGPHY)
4373: opmode |= SA2400_OPMODE_DIGIN;
4374:
4375: return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
4376: }
4377:
4378: int
4379: rtw_sa2400_vcocal_start(struct rtw_softc *sc, int start)
4380: {
4381: u_int32_t opmode;
4382:
4383: opmode = SA2400_OPMODE_DEFAULTS;
4384: if (start)
4385: opmode |= SA2400_OPMODE_MODE_VCOCALIB;
4386: else
4387: opmode |= SA2400_OPMODE_MODE_SLEEP;
4388:
4389: if (sc->sc_flags & RTW_F_DIGPHY)
4390: opmode |= SA2400_OPMODE_DIGIN;
4391:
4392: return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
4393: }
4394:
4395: int
4396: rtw_sa2400_vco_calibration(struct rtw_softc *sc)
4397: {
4398: int rc;
4399: /* calibrate VCO */
4400: if ((rc = rtw_sa2400_vcocal_start(sc, 1)) != 0)
4401: return rc;
4402: DELAY(2200); /* 2.2 milliseconds */
4403: /* XXX superfluous: SA2400 automatically entered SLEEP mode. */
4404: return rtw_sa2400_vcocal_start(sc, 0);
4405: }
4406:
4407: int
4408: rtw_sa2400_filter_calibration(struct rtw_softc *sc)
4409: {
4410: u_int32_t opmode;
4411:
4412: opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB;
4413: if (sc->sc_flags & RTW_F_DIGPHY)
4414: opmode |= SA2400_OPMODE_DIGIN;
4415:
4416: return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
4417: }
4418:
4419: int
4420: rtw_sa2400_dc_calibration(struct rtw_softc *sc)
4421: {
4422: int rc;
4423: u_int32_t dccal;
4424:
4425: rtw_continuous_tx_enable(sc, 1);
4426:
4427: dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX;
4428:
4429: rc = rtw_rf_macwrite(sc, SA2400_OPMODE, dccal);
4430:
4431: if (rc != 0)
4432: return rc;
4433:
4434: DELAY(5); /* DCALIB after being in Tx mode for 5
4435: * microseconds
4436: */
4437:
4438: dccal &= ~SA2400_OPMODE_MODE_MASK;
4439: dccal |= SA2400_OPMODE_MODE_DCALIB;
4440:
4441: rc = rtw_rf_macwrite(sc, SA2400_OPMODE, dccal);
4442: if (rc != 0)
4443: return rc;
4444:
4445: DELAY(20); /* calibration takes at most 20 microseconds */
4446:
4447: rtw_continuous_tx_enable(sc, 0);
4448:
4449: return 0;
4450: }
4451:
4452: int
4453: rtw_sa2400_calibrate(struct rtw_softc *sc, u_int freq)
4454: {
4455: int i, rc;
4456:
4457: /* XXX reference driver calibrates VCO twice. Is it a bug? */
4458: for (i = 0; i < 2; i++) {
4459: if ((rc = rtw_sa2400_vco_calibration(sc)) != 0)
4460: return rc;
4461: }
4462: /* VCO calibration erases synthesizer registers, so re-tune */
4463: if ((rc = rtw_sa2400_tune(sc, freq)) != 0)
4464: return rc;
4465: if ((rc = rtw_sa2400_filter_calibration(sc)) != 0)
4466: return rc;
4467: /* analog PHY needs DC calibration */
4468: if (!(sc->sc_flags & RTW_F_DIGPHY))
4469: return rtw_sa2400_dc_calibration(sc);
4470: return 0;
4471: }
4472:
4473: int
4474: rtw_sa2400_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
4475: enum rtw_pwrstate power)
4476: {
4477: int rc;
4478: u_int32_t agc, manrx;
4479:
4480: if ((rc = rtw_sa2400_txpower(sc, opaque_txpower)) != 0)
4481: return rc;
4482:
4483: /* skip configuration if it's time to sleep or to power-down. */
4484: if (power == RTW_SLEEP || power == RTW_OFF)
4485: return rtw_sa2400_pwrstate(sc, power);
4486:
4487: /* go to sleep for configuration */
4488: if ((rc = rtw_sa2400_pwrstate(sc, RTW_SLEEP)) != 0)
4489: return rc;
4490:
4491: if ((rc = rtw_sa2400_tune(sc, freq)) != 0)
4492: return rc;
4493:
4494: agc = LSHIFT(25, SA2400_AGC_MAXGAIN_MASK);
4495: agc |= LSHIFT(7, SA2400_AGC_BBPDELAY_MASK);
4496: agc |= LSHIFT(15, SA2400_AGC_LNADELAY_MASK);
4497: agc |= LSHIFT(27, SA2400_AGC_RXONDELAY_MASK);
4498:
4499: if ((rc = rtw_rf_macwrite(sc, SA2400_AGC, agc)) != 0)
4500: return rc;
4501:
4502: /* XXX we are not supposed to be in RXMGC mode when we do this? */
4503: manrx = SA2400_MANRX_AHSN;
4504: manrx |= SA2400_MANRX_TEN;
4505: manrx |= LSHIFT(1023, SA2400_MANRX_RXGAIN_MASK);
4506:
4507: if ((rc = rtw_rf_macwrite(sc, SA2400_MANRX, manrx)) != 0)
4508: return rc;
4509:
4510: if ((rc = rtw_sa2400_calibrate(sc, freq)) != 0)
4511: return rc;
4512:
4513: /* enter Tx/Rx mode */
4514: return rtw_sa2400_pwrstate(sc, power);
4515: }
4516:
4517: /* freq is in MHz */
4518: int
4519: rtw_max2820_tune(struct rtw_softc *sc, u_int freq)
4520: {
4521: if (freq < 2400 || freq > 2499)
4522: return -1;
4523:
4524: return rtw_rf_hostwrite(sc, MAX2820_CHANNEL,
4525: LSHIFT(freq - 2400, MAX2820_CHANNEL_CF_MASK));
4526: }
4527:
4528: int
4529: rtw_max2820_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
4530: enum rtw_pwrstate power)
4531: {
4532: int rc;
4533:
4534: if ((rc = rtw_rf_hostwrite(sc, MAX2820_TEST,
4535: MAX2820_TEST_DEFAULT)) != 0)
4536: return rc;
4537:
4538: if ((rc = rtw_rf_hostwrite(sc, MAX2820_ENABLE,
4539: MAX2820_ENABLE_DEFAULT)) != 0)
4540: return rc;
4541:
4542: /* skip configuration if it's time to sleep or to power-down. */
4543: if ((rc = rtw_max2820_pwrstate(sc, power)) != 0)
4544: return rc;
4545: else if (power == RTW_OFF || power == RTW_SLEEP)
4546: return 0;
4547:
4548: if ((rc = rtw_rf_hostwrite(sc, MAX2820_SYNTH,
4549: MAX2820_SYNTH_R_44MHZ)) != 0)
4550: return rc;
4551:
4552: if ((rc = rtw_max2820_tune(sc, freq)) != 0)
4553: return rc;
4554:
4555: /* XXX The MAX2820 datasheet indicates that 1C and 2C should not
4556: * be changed from 7, however, the reference driver sets them
4557: * to 4 and 1, respectively.
4558: */
4559: if ((rc = rtw_rf_hostwrite(sc, MAX2820_RECEIVE,
4560: MAX2820_RECEIVE_DL_DEFAULT |
4561: LSHIFT(4, MAX2820A_RECEIVE_1C_MASK) |
4562: LSHIFT(1, MAX2820A_RECEIVE_2C_MASK))) != 0)
4563: return rc;
4564:
4565: return rtw_rf_hostwrite(sc, MAX2820_TRANSMIT,
4566: MAX2820_TRANSMIT_PA_DEFAULT);
4567: }
4568:
4569: int
4570: rtw_max2820_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
4571: {
4572: /* TBD */
4573: return 0;
4574: }
4575:
4576: int
4577: rtw_max2820_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
4578: {
4579: uint32_t enable;
4580:
4581: switch (power) {
4582: case RTW_OFF:
4583: case RTW_SLEEP:
4584: default:
4585: enable = 0x0;
4586: break;
4587: case RTW_ON:
4588: enable = MAX2820_ENABLE_DEFAULT;
4589: break;
4590: }
4591: return rtw_rf_hostwrite(sc, MAX2820_ENABLE, enable);
4592: }
4593:
4594: int
4595: rtw_grf5101_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
4596: enum rtw_pwrstate power)
4597: {
4598: int rc;
4599:
4600: /*
4601: * These values have been derived from the rtl8180-sa2400 Linux driver.
4602: * It is unknown what they all do, GCT refuse to release any documentation
4603: * so these are more than likely sub optimal settings
4604: */
4605:
4606: rtw_rf_macwrite(sc, 0x01, 0x1a23);
4607: rtw_rf_macwrite(sc, 0x02, 0x4971);
4608: rtw_rf_macwrite(sc, 0x03, 0x41de);
4609: rtw_rf_macwrite(sc, 0x04, 0x2d80);
4610:
4611: rtw_rf_macwrite(sc, 0x05, 0x61ff);
4612:
4613: rtw_rf_macwrite(sc, 0x06, 0x0);
4614:
4615: rtw_rf_macwrite(sc, 0x08, 0x7533);
4616: rtw_rf_macwrite(sc, 0x09, 0xc401);
4617: rtw_rf_macwrite(sc, 0x0a, 0x0);
4618: rtw_rf_macwrite(sc, 0x0c, 0x1c7);
4619: rtw_rf_macwrite(sc, 0x0d, 0x29d3);
4620: rtw_rf_macwrite(sc, 0x0e, 0x2e8);
4621: rtw_rf_macwrite(sc, 0x10, 0x192);
4622: rtw_rf_macwrite(sc, 0x11, 0x248);
4623: rtw_rf_macwrite(sc, 0x12, 0x0);
4624: rtw_rf_macwrite(sc, 0x13, 0x20c4);
4625: rtw_rf_macwrite(sc, 0x14, 0xf4fc);
4626: rtw_rf_macwrite(sc, 0x15, 0x0);
4627: rtw_rf_macwrite(sc, 0x16, 0x1500);
4628:
4629: if ((rc = rtw_grf5101_txpower(sc, opaque_txpower)) != 0)
4630: return rc;
4631:
4632: if ((rc = rtw_grf5101_tune(sc, freq)) != 0)
4633: return rc;
4634:
4635: return (0);
4636: }
4637:
4638: int
4639: rtw_grf5101_tune(struct rtw_softc *sc, u_int freq)
4640: {
4641: struct ieee80211com *ic = &sc->sc_ic;
4642: u_int channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
4643:
4644: /* set channel */
4645: rtw_rf_macwrite(sc, 0x07, 0);
4646: rtw_rf_macwrite(sc, 0x0b, channel - 1);
4647: rtw_rf_macwrite(sc, 0x07, 0x1000);
4648:
4649: return (0);
4650: }
4651:
4652: int
4653: rtw_grf5101_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
4654: {
4655: rtw_rf_macwrite(sc, 0x15, 0);
4656: rtw_rf_macwrite(sc, 0x06, opaque_txpower);
4657: rtw_rf_macwrite(sc, 0x15, 0x10);
4658: rtw_rf_macwrite(sc, 0x15, 0x00);
4659:
4660: return (0);
4661: }
4662:
4663: int
4664: rtw_grf5101_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
4665: {
4666: switch (power) {
4667: case RTW_OFF:
4668: case RTW_SLEEP:
4669: rtw_rf_macwrite(sc, 0x07, 0x0000);
4670: rtw_rf_macwrite(sc, 0x1f, 0x0045);
4671: rtw_rf_macwrite(sc, 0x1f, 0x0005);
4672: rtw_rf_macwrite(sc, 0x00, 0x08e4);
4673: default:
4674: break;
4675: case RTW_ON:
4676: rtw_rf_macwrite(sc, 0x1f, 0x0001);
4677: DELAY(10);
4678: rtw_rf_macwrite(sc, 0x1f, 0x0001);
4679: DELAY(10);
4680: rtw_rf_macwrite(sc, 0x1f, 0x0041);
4681: DELAY(10);
4682: rtw_rf_macwrite(sc, 0x1f, 0x0061);
4683: DELAY(10);
4684: rtw_rf_macwrite(sc, 0x00, 0x0ae4);
4685: DELAY(10);
4686: rtw_rf_macwrite(sc, 0x07, 0x1000);
4687: DELAY(100);
4688: break;
4689: }
4690:
4691: return 0;
4692: }
4693:
4694: int
4695: rtw_rtl8225_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
4696: {
4697: return (0);
4698: }
4699:
4700: int
4701: rtw_rtl8225_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
4702: enum rtw_pwrstate power)
4703: {
4704: return (0);
4705: }
4706:
4707: int
4708: rtw_rtl8225_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
4709: {
4710: return (0);
4711: }
4712:
4713: int
4714: rtw_rtl8225_tune(struct rtw_softc *sc, u_int freq)
4715: {
4716: return (0);
4717: }
4718:
4719: int
4720: rtw_rtl8255_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
4721: {
4722: return (0);
4723: }
4724:
4725: int
4726: rtw_rtl8255_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
4727: enum rtw_pwrstate power)
4728: {
4729: return (0);
4730: }
4731:
4732: int
4733: rtw_rtl8255_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
4734: {
4735: return (0);
4736: }
4737:
4738: int
4739: rtw_rtl8255_tune(struct rtw_softc *sc, u_int freq)
4740: {
4741: return (0);
4742: }
4743:
4744: int
4745: rtw_phy_init(struct rtw_softc *sc)
4746: {
4747: int rc;
4748: struct ieee80211com *ic = &sc->sc_ic;
4749: struct rtw_regs *regs = &sc->sc_regs;
4750: int antdiv = sc->sc_flags & RTW_F_ANTDIV;
4751: int dflantb = sc->sc_flags & RTW_F_DFLANTB;
4752: u_int freq = ic->ic_bss->ni_chan->ic_freq; /* freq is in MHz */
4753: u_int8_t opaque_txpower = rtw_chan2txpower(&sc->sc_srom, ic,
4754: ic->ic_bss->ni_chan);
4755: u_int8_t cs_threshold = sc->sc_csthr;
4756: enum rtw_pwrstate power = RTW_ON;
4757:
4758: RTW_DPRINTF(RTW_DEBUG_PHY,
4759: ("%s: txpower %u csthresh %u freq %u antdiv %u dflantb %u "
4760: "pwrstate %s\n", __func__, opaque_txpower, cs_threshold, freq,
4761: antdiv, dflantb, rtw_pwrstate_string(power)));
4762:
4763: /* XXX is this really necessary? */
4764: if ((rc = (*sc->sc_rf_txpower)(sc, opaque_txpower)) != 0)
4765: return rc;
4766: if ((rc = rtw_bbp_preinit(regs, sc->sc_bbpset.bb_antatten, dflantb,
4767: freq)) != 0)
4768: return rc;
4769: if ((rc = (*sc->sc_rf_tune)(sc, freq)) != 0)
4770: return rc;
4771: /* initialize RF */
4772: if ((rc = (*sc->sc_rf_init)(sc, freq, opaque_txpower, power)) != 0)
4773: return rc;
4774: #if 0 /* what is this redundant tx power setting here for? */
4775: if ((rc = (*sc->sc_rf_txpower)(sc, opaque_txpower)) != 0)
4776: return rc;
4777: #endif
4778: return rtw_bbp_init(regs, &sc->sc_bbpset, antdiv, dflantb,
4779: cs_threshold, freq);
4780: }
4781:
4782: /*
4783: * Generic PHY I/O functions
4784: */
4785:
4786: int
4787: rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val)
4788: {
4789: #define BBP_WRITE_ITERS 50
4790: #define BBP_WRITE_DELAY 1
4791: int i;
4792: u_int32_t wrbbp, rdbbp;
4793:
4794: RTW_DPRINTF(RTW_DEBUG_PHYIO,
4795: ("%s: bbp[%u] <- %u\n", __func__, addr, val));
4796:
4797: KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
4798: KASSERT((val & ~PRESHIFT(RTW_BB_WR_MASK)) == 0);
4799:
4800: wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN |
4801: LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK,
4802:
4803: rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) |
4804: RTW_BB_WR_MASK | RTW_BB_RD_MASK;
4805:
4806: RTW_DPRINTF(RTW_DEBUG_PHYIO,
4807: ("%s: rdbbp = %#08x, wrbbp = %#08x\n", __func__, rdbbp, wrbbp));
4808:
4809: for (i = BBP_WRITE_ITERS; --i >= 0; ) {
4810: RTW_RBW(regs, RTW_BB, RTW_BB);
4811: RTW_WRITE(regs, RTW_BB, wrbbp);
4812: RTW_SYNC(regs, RTW_BB, RTW_BB);
4813: RTW_WRITE(regs, RTW_BB, rdbbp);
4814: RTW_SYNC(regs, RTW_BB, RTW_BB);
4815: delay(BBP_WRITE_DELAY); /* 1 microsecond */
4816: if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB),
4817: RTW_BB_RD_MASK) == val) {
4818: RTW_DPRINTF(RTW_DEBUG_PHYIO,
4819: ("%s: finished in %dus\n", __func__,
4820: BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i)));
4821: return 0;
4822: }
4823: delay(BBP_WRITE_DELAY); /* again */
4824: }
4825: printf("%s: timeout\n", __func__);
4826: return -1;
4827: }
4828:
4829: /* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */
4830: void
4831: rtw_rf_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
4832: u_int nbits)
4833: {
4834: int i;
4835: u_int32_t mask, reg;
4836:
4837: KASSERT(nbits <= 32);
4838:
4839: RTW_DPRINTF(RTW_DEBUG_PHYIO,
4840: ("%s: %u bits, %#08x, %s\n", __func__, nbits, bits,
4841: (lo_to_hi) ? "lo to hi" : "hi to lo"));
4842:
4843: reg = RTW8180_PHYCFG_HST;
4844: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4845: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4846:
4847: if (lo_to_hi)
4848: mask = 0x1;
4849: else
4850: mask = 1 << (nbits - 1);
4851:
4852: for (i = 0; i < nbits; i++) {
4853: RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
4854: ("%s: bits %#08x mask %#08x -> bit %#08x\n",
4855: __func__, bits, mask, bits & mask));
4856:
4857: if ((bits & mask) != 0)
4858: reg |= RTW8180_PHYCFG_HST_DATA;
4859: else
4860: reg &= ~RTW8180_PHYCFG_HST_DATA;
4861:
4862: reg |= RTW8180_PHYCFG_HST_CLK;
4863: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4864: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4865:
4866: DELAY(2); /* arbitrary delay */
4867:
4868: reg &= ~RTW8180_PHYCFG_HST_CLK;
4869: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4870: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4871:
4872: if (lo_to_hi)
4873: mask <<= 1;
4874: else
4875: mask >>= 1;
4876: }
4877:
4878: reg |= RTW8180_PHYCFG_HST_EN;
4879: KASSERT((reg & RTW8180_PHYCFG_HST_CLK) == 0);
4880: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4881: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4882: }
4883:
4884: #if 0
4885: void
4886: rtw_rf_rtl8225_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
4887: u_int nbits)
4888: {
4889: int i;
4890: u_int8_t page;
4891: u_int16_t reg0, reg1, reg2;
4892: u_int32_t mask;
4893:
4894: /* enable page 0 */
4895: page = RTW_READ8(regs, RTW_PSR);
4896: RTW_WRITE8(regs, RTW_PSR, page & ~RTW_PSR_PSEN);
4897:
4898: /* enable RF access */
4899: reg0 = RTW_READ16(regs, RTW8185_RFPINSOUTPUT) &
4900: RTW8185_RFPINSOUTPUT_MASK;
4901: reg1 = RTW_READ16(regs, RTW8185_RFPINSENABLE);
4902: RTW_WRITE16(regs, RTW8185_RFPINSENABLE,
4903: RTW8185_RFPINSENABLE_ENABLE | reg0);
4904: reg2 = RTW_READ16(regs, RTW8185_RFPINSSELECT);
4905: RTW_WRITE16(regs, RTW8185_RFPINSSELECT,
4906: RTW8185_RFPINSSELECT_ENABLE | reg1 /* XXX | SW_GPIO_CTL */);
4907: DELAY(10);
4908:
4909: RTW_WRITE16(regs, RTW8185_RFPINSOUTPUT, reg0);
4910: DELAY(10);
4911:
4912: if (lo_to_hi)
4913: mask = 0x1;
4914: else
4915: mask = 1 << (nbits - 1);
4916:
4917: for (i = 0; i < nbits; i++) {
4918: RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
4919: ("%s: bits %#08x mask %#08x -> bit %#08x\n",
4920: __func__, bits, mask, bits & mask));
4921:
4922: if ((bits & mask) != 0)
4923: reg |= RTW8180_PHYCFG_HST_DATA;
4924: else
4925: reg &= ~RTW8180_PHYCFG_HST_DATA;
4926:
4927: reg |= RTW8180_PHYCFG_HST_CLK;
4928: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4929: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4930:
4931: DELAY(2); /* arbitrary delay */
4932:
4933: reg &= ~RTW8180_PHYCFG_HST_CLK;
4934: RTW_WRITE(regs, RTW8180_PHYCFG, reg);
4935: RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4936:
4937: if (lo_to_hi)
4938: mask <<= 1;
4939: else
4940: mask >>= 1;
4941: }
4942:
4943: /* reset the page */
4944: RTW_WRITE8(regs, RTW_PSR, page);
4945: }
4946: #endif
4947:
4948: /* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire
4949: * interface.
4950: */
4951: int
4952: rtw_rf_macbangbits(struct rtw_regs *regs, u_int32_t reg)
4953: {
4954: int i;
4955:
4956: RTW_DPRINTF(RTW_DEBUG_PHY, ("%s: %#08x\n", __func__, reg));
4957:
4958: RTW_WRITE(regs, RTW8180_PHYCFG, RTW8180_PHYCFG_MAC_POLL | reg);
4959:
4960: RTW_WBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4961:
4962: for (i = rtw_macbangbits_timeout; --i >= 0; delay(1)) {
4963: if ((RTW_READ(regs, RTW8180_PHYCFG) &
4964: RTW8180_PHYCFG_MAC_POLL) == 0) {
4965: RTW_DPRINTF(RTW_DEBUG_PHY,
4966: ("%s: finished in %dus\n", __func__,
4967: rtw_macbangbits_timeout - i));
4968: return 0;
4969: }
4970: RTW_RBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
4971: }
4972:
4973: printf("%s: RTW8180_PHYCFG_MAC_POLL still set.\n", __func__);
4974: return -1;
4975: }
4976:
4977: u_int32_t
4978: rtw_grf5101_host_crypt(u_int addr, u_int32_t val)
4979: {
4980: /* TBD */
4981: return 0;
4982: }
4983:
4984: u_int32_t
4985: rtw_grf5101_mac_crypt(u_int addr, u_int32_t val)
4986: {
4987: u_int32_t data_and_addr;
4988: #define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf)
4989: static u_int8_t caesar[16] = {
4990: 0x0, 0x8, 0x4, 0xc,
4991: 0x2, 0xa, 0x6, 0xe,
4992: 0x1, 0x9, 0x5, 0xd,
4993: 0x3, 0xb, 0x7, 0xf
4994: };
4995: data_and_addr =
4996: caesar[EXTRACT_NIBBLE(val, 2)] |
4997: (caesar[EXTRACT_NIBBLE(val, 1)] << 4) |
4998: (caesar[EXTRACT_NIBBLE(val, 0)] << 8) |
4999: (caesar[(addr >> 1) & 0xf] << 12) |
5000: ((addr & 0x1) << 16) |
5001: (caesar[EXTRACT_NIBBLE(val, 3)] << 24);
5002: return LSHIFT(data_and_addr, RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK |
5003: RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
5004: #undef EXTRACT_NIBBLE
5005: }
5006:
5007: /* Bang bits over the 3-wire interface. */
5008: int
5009: rtw_rf_hostwrite(struct rtw_softc *sc, u_int addr, u_int32_t val)
5010: {
5011: u_int nbits;
5012: int lo_to_hi;
5013: u_int32_t bits;
5014: void(*rf_bangbits)(struct rtw_regs *, u_int32_t, int, u_int) =
5015: rtw_rf_hostbangbits;
5016:
5017: RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: [%u] <- %#08x\n", __func__,
5018: addr, val));
5019:
5020: switch (sc->sc_rfchipid) {
5021: case RTW_RFCHIPID_MAXIM2820:
5022: nbits = 16;
5023: lo_to_hi = 0;
5024: bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) |
5025: LSHIFT(addr, MAX2820_TWI_ADDR_MASK);
5026: break;
5027: case RTW_RFCHIPID_PHILIPS:
5028: KASSERT((addr & ~PRESHIFT(SA2400_TWI_ADDR_MASK)) == 0);
5029: KASSERT((val & ~PRESHIFT(SA2400_TWI_DATA_MASK)) == 0);
5030: bits = LSHIFT(val, SA2400_TWI_DATA_MASK) |
5031: LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN;
5032: nbits = 32;
5033: lo_to_hi = 1;
5034: break;
5035: case RTW_RFCHIPID_GCT:
5036: KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
5037: KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
5038: bits = rtw_grf5101_host_crypt(addr, val);
5039: nbits = 21;
5040: lo_to_hi = 1;
5041: break;
5042: case RTW_RFCHIPID_RFMD2948:
5043: KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
5044: KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
5045: bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
5046: LSHIFT(addr, SI4126_TWI_ADDR_MASK);
5047: nbits = 22;
5048: lo_to_hi = 0;
5049: break;
5050: case RTW_RFCHIPID_RTL8225:
5051: case RTW_RFCHIPID_RTL8255:
5052: nbits = 16;
5053: lo_to_hi = 0;
5054: bits = LSHIFT(val, RTL8225_TWI_DATA_MASK) |
5055: LSHIFT(addr, RTL8225_TWI_ADDR_MASK);
5056:
5057: /* the RTL8225 uses a slightly modified RF interface */
5058: rf_bangbits = rtw_rf_hostbangbits;
5059: break;
5060: case RTW_RFCHIPID_INTERSIL:
5061: default:
5062: printf("%s: unknown rfchipid %d\n", __func__, sc->sc_rfchipid);
5063: return -1;
5064: }
5065:
5066: (*rf_bangbits)(&sc->sc_regs, bits, lo_to_hi, nbits);
5067:
5068: return 0;
5069: }
5070:
5071: u_int32_t
5072: rtw_maxim_swizzle(u_int addr, u_int32_t val)
5073: {
5074: u_int32_t hidata, lodata;
5075:
5076: KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0);
5077: lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK);
5078: hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK);
5079: return LSHIFT(lodata, RTW8180_PHYCFG_MAC_MAXIM_LODATA_MASK) |
5080: LSHIFT(hidata, RTW8180_PHYCFG_MAC_MAXIM_HIDATA_MASK) |
5081: LSHIFT(addr, RTW8180_PHYCFG_MAC_MAXIM_ADDR_MASK);
5082: }
5083:
5084: /* Tell the MAC what to bang over the 3-wire interface. */
5085: int
5086: rtw_rf_macwrite(struct rtw_softc *sc, u_int addr, u_int32_t val)
5087: {
5088: u_int32_t reg;
5089:
5090: RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__,
5091: addr, val));
5092:
5093: switch (sc->sc_rfchipid) {
5094: case RTW_RFCHIPID_GCT:
5095: reg = rtw_grf5101_mac_crypt(addr, val);
5096: break;
5097: case RTW_RFCHIPID_MAXIM2820:
5098: reg = rtw_maxim_swizzle(addr, val);
5099: break;
5100: default: /* XXX */
5101: case RTW_RFCHIPID_PHILIPS:
5102: KASSERT((addr &
5103: ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0);
5104: KASSERT((val &
5105: ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0);
5106:
5107: reg = LSHIFT(addr, RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK) |
5108: LSHIFT(val, RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
5109: }
5110:
5111: switch (sc->sc_rfchipid) {
5112: case RTW_RFCHIPID_GCT:
5113: case RTW_RFCHIPID_MAXIM2820:
5114: case RTW_RFCHIPID_RFMD2948:
5115: reg |= RTW8180_PHYCFG_MAC_RFTYPE_RFMD;
5116: break;
5117: case RTW_RFCHIPID_INTERSIL:
5118: reg |= RTW8180_PHYCFG_MAC_RFTYPE_INTERSIL;
5119: break;
5120: case RTW_RFCHIPID_PHILIPS:
5121: reg |= RTW8180_PHYCFG_MAC_RFTYPE_PHILIPS;
5122: break;
5123: default:
5124: printf("%s: unknown rfchipid %d\n", __func__, sc->sc_rfchipid);
5125: return -1;
5126: }
5127:
5128: return rtw_rf_macbangbits(&sc->sc_regs, reg);
5129: }
5130:
5131:
5132: u_int8_t
5133: rtw_read8(void *arg, u_int32_t off)
5134: {
5135: struct rtw_regs *regs = (struct rtw_regs *)arg;
5136: return (bus_space_read_1(regs->r_bt, regs->r_bh, off));
5137: }
5138:
5139: u_int16_t
5140: rtw_read16(void *arg, u_int32_t off)
5141: {
5142: struct rtw_regs *regs = (struct rtw_regs *)arg;
5143: return (bus_space_read_2(regs->r_bt, regs->r_bh, off));
5144: }
5145:
5146: u_int32_t
5147: rtw_read32(void *arg, u_int32_t off)
5148: {
5149: struct rtw_regs *regs = (struct rtw_regs *)arg;
5150: return (bus_space_read_4(regs->r_bt, regs->r_bh, off));
5151: }
5152:
5153: void
5154: rtw_write8(void *arg, u_int32_t off, u_int8_t val)
5155: {
5156: struct rtw_regs *regs = (struct rtw_regs *)arg;
5157: bus_space_write_1(regs->r_bt, regs->r_bh, off, val);
5158: }
5159:
5160: void
5161: rtw_write16(void *arg, u_int32_t off, u_int16_t val)
5162: {
5163: struct rtw_regs *regs = (struct rtw_regs *)arg;
5164: bus_space_write_2(regs->r_bt, regs->r_bh, off, val);
5165: }
5166:
5167: void
5168: rtw_write32(void *arg, u_int32_t off, u_int32_t val)
5169: {
5170: struct rtw_regs *regs = (struct rtw_regs *)arg;
5171: bus_space_write_4(regs->r_bt, regs->r_bh, off, val);
5172: }
5173:
5174: void
5175: rtw_barrier(void *arg, u_int32_t reg0, u_int32_t reg1, int flags)
5176: {
5177: struct rtw_regs *regs = (struct rtw_regs *)arg;
5178: bus_space_barrier(regs->r_bt, regs->r_bh, MIN(reg0, reg1),
5179: MAX(reg0, reg1) - MIN(reg0, reg1) + 4, flags);
5180: }
CVSweb