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