1 | /* $NetBSD: rt2860.c,v 1.24 2016/10/08 15:57:11 christos Exp $ */ |
2 | /* $OpenBSD: rt2860.c,v 1.90 2016/04/13 10:49:26 mpi Exp $ */ |
3 | /* $FreeBSD: head/sys/dev/ral/rt2860.c 306591 2016-10-02 20:35:55Z avos $ */ |
4 | |
5 | /*- |
6 | * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> |
7 | * Copyright (c) 2012 Bernhard Schmidt <bschmidt@FreeBSD.org> |
8 | * |
9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above |
11 | * copyright notice and this permission notice appear in all copies. |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | */ |
21 | |
22 | /*- |
23 | * Ralink Technology RT2860/RT3090/RT3390/RT3562/RT5390/RT5392 chipset driver |
24 | * http://www.ralinktech.com/ |
25 | */ |
26 | |
27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.24 2016/10/08 15:57:11 christos Exp $" ); |
29 | |
30 | #include <sys/param.h> |
31 | #include <sys/sockio.h> |
32 | #include <sys/sysctl.h> |
33 | #include <sys/mbuf.h> |
34 | #include <sys/kernel.h> |
35 | #include <sys/socket.h> |
36 | #include <sys/systm.h> |
37 | #include <sys/malloc.h> |
38 | #include <sys/queue.h> |
39 | #include <sys/callout.h> |
40 | #include <sys/module.h> |
41 | #include <sys/conf.h> |
42 | #include <sys/device.h> |
43 | #include <sys/endian.h> |
44 | #include <sys/cprng.h> |
45 | |
46 | #include <sys/bus.h> |
47 | #include <sys/intr.h> |
48 | |
49 | #include <net/bpf.h> |
50 | #include <net/if.h> |
51 | #include <net/if_dl.h> |
52 | #include <net/if_ether.h> |
53 | #include <net/if_media.h> |
54 | |
55 | #include <net80211/ieee80211_var.h> |
56 | #include <net80211/ieee80211_amrr.h> |
57 | #include <net80211/ieee80211_radiotap.h> |
58 | |
59 | #include <dev/firmload.h> |
60 | |
61 | #include <dev/ic/rt2860var.h> |
62 | #include <dev/ic/rt2860reg.h> |
63 | |
64 | #include <dev/pci/pcidevs.h> |
65 | |
66 | #ifdef RAL_DEBUG |
67 | #define DPRINTF(x) do { if (rt2860_debug > 0) printf x; } while (0) |
68 | #define DPRINTFN(n, x) do { if (rt2860_debug >= (n)) printf x; } while (0) |
69 | int rt2860_debug = 0; |
70 | #else |
71 | #define DPRINTF(x) |
72 | #define DPRINTFN(n, x) |
73 | #endif |
74 | #define MAXQS 6 /* Tx (4 EDCAs + HCCA + Mgt) and Rx rings */ |
75 | |
76 | static void rt2860_attachhook(device_t); |
77 | static int rt2860_alloc_tx_ring(struct rt2860_softc *, |
78 | struct rt2860_tx_ring *); |
79 | static void rt2860_reset_tx_ring(struct rt2860_softc *, |
80 | struct rt2860_tx_ring *); |
81 | static void rt2860_free_tx_ring(struct rt2860_softc *, |
82 | struct rt2860_tx_ring *); |
83 | static int rt2860_alloc_tx_pool(struct rt2860_softc *); |
84 | static void rt2860_free_tx_pool(struct rt2860_softc *); |
85 | static int rt2860_alloc_rx_ring(struct rt2860_softc *, |
86 | struct rt2860_rx_ring *); |
87 | static void rt2860_reset_rx_ring(struct rt2860_softc *, |
88 | struct rt2860_rx_ring *); |
89 | static void rt2860_free_rx_ring(struct rt2860_softc *, |
90 | struct rt2860_rx_ring *); |
91 | static struct ieee80211_node *rt2860_node_alloc(struct ieee80211_node_table *); |
92 | static int rt2860_media_change(struct ifnet *); |
93 | static void rt2860_iter_func(void *, struct ieee80211_node *); |
94 | static void rt2860_updatestats(struct rt2860_softc *); |
95 | static void rt2860_update_promisc(struct ifnet *); |
96 | static void rt2860_newassoc(struct ieee80211_node *, |
97 | int); |
98 | #ifdef notyet |
99 | static int rt2860_ampdu_rx_start(struct ieee80211com *, |
100 | struct ieee80211_node *, uint8_t); |
101 | static void rt2860_ampdu_rx_stop(struct ieee80211com *, |
102 | struct ieee80211_node *, uint8_t); |
103 | #endif |
104 | static int rt2860_newstate(struct ieee80211com *, enum ieee80211_state, |
105 | int); |
106 | static uint16_t rt3090_efuse_read_2(struct rt2860_softc *, uint16_t); |
107 | static uint16_t rt2860_eeprom_read_2(struct rt2860_softc *, uint16_t); |
108 | static void rt2860_intr_coherent(struct rt2860_softc *); |
109 | static void rt2860_drain_stats_fifo(struct rt2860_softc *); |
110 | static void rt2860_tx_intr(struct rt2860_softc *, int); |
111 | static void rt2860_rx_intr(struct rt2860_softc *); |
112 | static void rt2860_tbtt_intr(struct rt2860_softc *); |
113 | static void rt2860_gp_intr(struct rt2860_softc *); |
114 | static int rt2860_tx(struct rt2860_softc *, struct mbuf *, |
115 | struct ieee80211_node *); |
116 | static void rt2860_start(struct ifnet *); |
117 | static void rt2860_watchdog(struct ifnet *); |
118 | static int rt2860_ioctl(struct ifnet *, u_long, void *); |
119 | static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); |
120 | static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); |
121 | static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); |
122 | static uint8_t rt3090_rf_read(struct rt2860_softc *, uint8_t); |
123 | static void rt3090_rf_write(struct rt2860_softc *, uint8_t, uint8_t); |
124 | static int rt2860_mcu_cmd(struct rt2860_softc *, uint8_t, uint16_t, int); |
125 | static void rt2860_enable_mrr(struct rt2860_softc *); |
126 | static void rt2860_set_txpreamble(struct rt2860_softc *); |
127 | static void rt2860_set_basicrates(struct rt2860_softc *); |
128 | static void rt2860_select_chan_group(struct rt2860_softc *, int); |
129 | static void rt2860_set_chan(struct rt2860_softc *, u_int); |
130 | static void rt3090_set_chan(struct rt2860_softc *, u_int); |
131 | static void rt5390_set_chan(struct rt2860_softc *, u_int); |
132 | static void rt3090_rf_init(struct rt2860_softc *); |
133 | static void rt5390_rf_init(struct rt2860_softc *); |
134 | static void rt3090_rf_wakeup(struct rt2860_softc *); |
135 | static void rt5390_rf_wakeup(struct rt2860_softc *); |
136 | static int rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t, |
137 | uint8_t *); |
138 | static void rt3090_rf_setup(struct rt2860_softc *); |
139 | static void rt2860_set_leds(struct rt2860_softc *, uint16_t); |
140 | static void rt2860_set_gp_timer(struct rt2860_softc *, int); |
141 | static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); |
142 | static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); |
143 | static void rt2860_updateslot(struct ifnet *); |
144 | static void rt2860_updateprot(struct ieee80211com *); |
145 | static int rt2860_updateedca(struct ieee80211com *); |
146 | |
147 | #ifdef HW_CRYPTO |
148 | static int rt2860_set_key(struct ieee80211com *, |
149 | const struct ieee80211_key *, const uint8_t *); |
150 | static int rt2860_delete_key(struct ieee80211com *, |
151 | const struct ieee80211_key *); |
152 | #endif |
153 | static int8_t rt2860_rssi2dbm(struct rt2860_softc *, uint8_t, uint8_t); |
154 | static const char * rt2860_get_rf(uint32_t); |
155 | static int rt2860_read_eeprom(struct rt2860_softc *); |
156 | static int rt2860_bbp_init(struct rt2860_softc *); |
157 | static int rt5390_bbp_init(struct rt2860_softc *); |
158 | static int rt2860_txrx_enable(struct rt2860_softc *); |
159 | static int rt2860_init(struct ifnet *); |
160 | static void rt2860_stop(struct ifnet *, int); |
161 | static int rt2860_load_microcode(struct rt2860_softc *); |
162 | #if 0 |
163 | static void rt2860_calib(struct rt2860_softc *); |
164 | #endif |
165 | static void rt3090_set_rx_antenna(struct rt2860_softc *, int); |
166 | static void rt2860_switch_chan(struct rt2860_softc *, |
167 | struct ieee80211_channel *); |
168 | #ifndef IEEE80211_STA_ONLY |
169 | static int rt2860_setup_beacon(struct rt2860_softc *); |
170 | #endif |
171 | static void rt2860_enable_tsf_sync(struct rt2860_softc *); |
172 | |
173 | static const struct { |
174 | uint32_t reg; |
175 | uint32_t val; |
176 | } rt2860_def_mac[] = { |
177 | RT2860_DEF_MAC |
178 | }; |
179 | |
180 | static const struct { |
181 | uint8_t reg; |
182 | uint8_t val; |
183 | } rt2860_def_bbp[] = { |
184 | RT2860_DEF_BBP |
185 | }, rt5390_def_bbp[] = { |
186 | RT5390_DEF_BBP |
187 | }; |
188 | |
189 | static const struct rfprog { |
190 | uint8_t chan; |
191 | uint32_t r1, r2, r3, r4; |
192 | } rt2860_rf2850[] = { |
193 | RT2860_RF2850 |
194 | }; |
195 | |
196 | struct { |
197 | uint8_t n, r, k; |
198 | } rt3090_freqs[] = { |
199 | RT3070_RF3052 |
200 | }; |
201 | |
202 | static const struct { |
203 | uint8_t reg; |
204 | uint8_t val; |
205 | } rt3090_def_rf[] = { |
206 | RT3070_DEF_RF |
207 | }, rt3572_def_rf[] = { |
208 | RT3572_DEF_RF |
209 | }, rt5390_def_rf[] = { |
210 | RT5390_DEF_RF |
211 | }, rt5392_def_rf[] = { |
212 | RT5392_DEF_RF |
213 | }; |
214 | |
215 | int |
216 | rt2860_attach(void *xsc, int id) |
217 | { |
218 | struct rt2860_softc *sc = xsc; |
219 | struct ieee80211com *ic = &sc->sc_ic; |
220 | int qid, ntries, error; |
221 | uint32_t tmp; |
222 | |
223 | sc->amrr.amrr_min_success_threshold = 1; |
224 | sc->amrr.amrr_max_success_threshold = 15; |
225 | |
226 | /* wait for NIC to initialize */ |
227 | for (ntries = 0; ntries < 100; ntries++) { |
228 | tmp = RAL_READ(sc, RT2860_ASIC_VER_ID); |
229 | if (tmp != 0 && tmp != 0xffffffff) |
230 | break; |
231 | DELAY(10); |
232 | } |
233 | if (ntries == 100) { |
234 | aprint_error_dev(sc->sc_dev, |
235 | "timeout waiting for NIC to initialize\n" ); |
236 | return ETIMEDOUT; |
237 | } |
238 | sc->mac_ver = tmp >> 16; |
239 | sc->mac_rev = tmp & 0xffff; |
240 | |
241 | if (sc->mac_ver != 0x2860 && |
242 | (id == PCI_PRODUCT_RALINK_RT2890 || |
243 | id == PCI_PRODUCT_RALINK_RT2790 || |
244 | id == PCI_PRODUCT_AWT_RT2890)) |
245 | sc->sc_flags |= RT2860_ADVANCED_PS; |
246 | |
247 | /* retrieve RF rev. no and various other things from EEPROM */ |
248 | rt2860_read_eeprom(sc); |
249 | aprint_normal_dev(sc->sc_dev, "802.11 address %s\n" , |
250 | ether_sprintf(ic->ic_myaddr)); |
251 | aprint_normal_dev(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " |
252 | "RF %s (MIMO %dT%dR)\n" , |
253 | sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), |
254 | sc->ntxchains, sc->nrxchains); |
255 | |
256 | /* |
257 | * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. |
258 | */ |
259 | for (qid = 0; qid < MAXQS; qid++) { |
260 | if ((error = rt2860_alloc_tx_ring(sc, &sc->txq[qid])) != 0) { |
261 | aprint_error_dev(sc->sc_dev, |
262 | "could not allocate Tx ring %d\n" , qid); |
263 | goto fail1; |
264 | } |
265 | } |
266 | |
267 | if ((error = rt2860_alloc_rx_ring(sc, &sc->rxq)) != 0) { |
268 | aprint_error_dev(sc->sc_dev, "could not allocate Rx ring\n" ); |
269 | goto fail1; |
270 | } |
271 | |
272 | if ((error = rt2860_alloc_tx_pool(sc)) != 0) { |
273 | aprint_error_dev(sc->sc_dev, "could not allocate Tx pool\n" ); |
274 | goto fail2; |
275 | } |
276 | |
277 | /* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */ |
278 | sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? |
279 | WME_AC_VO : 5; |
280 | |
281 | config_mountroot(sc->sc_dev, rt2860_attachhook); |
282 | |
283 | return 0; |
284 | |
285 | fail2: rt2860_free_rx_ring(sc, &sc->rxq); |
286 | fail1: while (--qid >= 0) |
287 | rt2860_free_tx_ring(sc, &sc->txq[qid]); |
288 | return error; |
289 | } |
290 | |
291 | static int |
292 | firmware_load(const char *dname, const char *iname, uint8_t **ucodep, |
293 | size_t *sizep) |
294 | { |
295 | firmware_handle_t fh; |
296 | int error; |
297 | |
298 | if ((error = firmware_open(dname, iname, &fh)) != 0) |
299 | return (error); |
300 | *sizep = firmware_get_size(fh); |
301 | if ((*ucodep = firmware_malloc(*sizep)) == NULL) { |
302 | firmware_close(fh); |
303 | return (ENOMEM); |
304 | } |
305 | if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0) |
306 | firmware_free(*ucodep, *sizep); |
307 | firmware_close(fh); |
308 | |
309 | return (error); |
310 | } |
311 | |
312 | static void |
313 | rt2860_attachhook(device_t self) |
314 | { |
315 | struct rt2860_softc *sc = device_private(self); |
316 | struct ieee80211com *ic = &sc->sc_ic; |
317 | struct ifnet *ifp = &sc->sc_if; |
318 | int i, error; |
319 | |
320 | error = firmware_load("ral" , "ral-rt2860" , &sc->ucode, &sc->ucsize); |
321 | if (error != 0) { |
322 | aprint_error_dev(sc->sc_dev, |
323 | "error %d, could not read firmware file %s\n" , |
324 | error, "ral-rt2860" ); |
325 | return; |
326 | } |
327 | |
328 | ic->ic_ifp = ifp; |
329 | ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ |
330 | ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ |
331 | ic->ic_state = IEEE80211_S_INIT; |
332 | |
333 | /* set device capabilities */ |
334 | ic->ic_caps = |
335 | IEEE80211_C_MONITOR | /* monitor mode supported */ |
336 | #ifndef IEEE80211_STA_ONLY |
337 | IEEE80211_C_IBSS | /* IBSS mode supported */ |
338 | IEEE80211_C_HOSTAP | /* HostAP mode supported */ |
339 | #ifdef IEEE80211_C_APPMGT |
340 | IEEE80211_C_APPMGT | /* HostAP power management */ |
341 | #endif |
342 | #endif |
343 | IEEE80211_C_WDS | /* 4-address traffic works */ |
344 | IEEE80211_C_WME | /* 802.11e */ |
345 | IEEE80211_C_SHPREAMBLE | /* short preamble supported */ |
346 | IEEE80211_C_SHSLOT | /* short slot time supported */ |
347 | #ifdef HW_CRYPTO |
348 | IEEE80211_C_WEP | /* WEP */ |
349 | #endif |
350 | IEEE80211_C_WPA; /* 802.11i */ |
351 | |
352 | if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850) { |
353 | /* set supported .11a rates */ |
354 | ic->ic_sup_rates[IEEE80211_MODE_11A] = |
355 | ieee80211_std_rateset_11a; |
356 | |
357 | /* set supported .11a channels */ |
358 | for (i = 14; i < (int)__arraycount(rt2860_rf2850); i++) { |
359 | uint8_t chan = rt2860_rf2850[i].chan; |
360 | ic->ic_channels[chan].ic_freq = |
361 | ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ); |
362 | ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A; |
363 | } |
364 | } |
365 | |
366 | /* set supported .11b and .11g rates */ |
367 | ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; |
368 | ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; |
369 | |
370 | /* set supported .11b and .11g channels (1 through 14) */ |
371 | for (i = 1; i <= 14; i++) { |
372 | ic->ic_channels[i].ic_freq = |
373 | ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); |
374 | ic->ic_channels[i].ic_flags = |
375 | IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | |
376 | IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; |
377 | } |
378 | |
379 | /* HW supports up to 255 STAs (0-254) in HostAP and IBSS modes */ |
380 | ic->ic_max_aid = min(IEEE80211_AID_MAX, RT2860_WCID_MAX); |
381 | |
382 | ifp->if_softc = sc; |
383 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; |
384 | ifp->if_init = rt2860_init; |
385 | ifp->if_ioctl = rt2860_ioctl; |
386 | ifp->if_start = rt2860_start; |
387 | ifp->if_watchdog = rt2860_watchdog; |
388 | IFQ_SET_READY(&ifp->if_snd); |
389 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
390 | |
391 | if_attach(ifp); |
392 | ieee80211_ifattach(ic); |
393 | ic->ic_node_alloc = rt2860_node_alloc; |
394 | ic->ic_newassoc = rt2860_newassoc; |
395 | #ifdef notyet |
396 | ic->ic_ampdu_rx_start = rt2860_ampdu_rx_start; |
397 | ic->ic_ampdu_rx_stop = rt2860_ampdu_rx_stop; |
398 | #endif |
399 | ic->ic_updateslot = rt2860_updateslot; |
400 | ic->ic_wme.wme_update = rt2860_updateedca; |
401 | #ifdef HW_CRYPTO |
402 | ic->ic_crypto.cs_key_set = rt2860_set_key; |
403 | ic->ic_crypto.cs_key_delete = rt2860_delete_key; |
404 | #endif |
405 | /* override state transition machine */ |
406 | sc->sc_newstate = ic->ic_newstate; |
407 | ic->ic_newstate = rt2860_newstate; |
408 | ieee80211_media_init(ic, rt2860_media_change, ieee80211_media_status); |
409 | |
410 | bpf_attach2(ifp, DLT_IEEE802_11_RADIO, |
411 | sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf); |
412 | |
413 | sc->sc_rxtap_len = roundup(sizeof(sc->sc_rxtap), sizeof(u_int32_t)); |
414 | sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); |
415 | sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2860_RX_RADIOTAP_PRESENT); |
416 | |
417 | sc->sc_txtap_len = roundup(sizeof(sc->sc_txtap), sizeof(u_int32_t)); |
418 | sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); |
419 | sc->sc_txtap.wt_ihdr.it_present = htole32(RT2860_TX_RADIOTAP_PRESENT); |
420 | |
421 | ieee80211_announce(ic); |
422 | |
423 | if (pmf_device_register(sc->sc_dev, NULL, NULL)) |
424 | pmf_class_network_register(sc->sc_dev, ifp); |
425 | else |
426 | aprint_error_dev(sc->sc_dev, |
427 | "couldn't establish power handler\n" ); |
428 | } |
429 | |
430 | int |
431 | rt2860_detach(void *xsc) |
432 | { |
433 | struct rt2860_softc *sc = xsc; |
434 | struct ifnet *ifp = &sc->sc_if; |
435 | int qid; |
436 | |
437 | pmf_device_deregister(sc->sc_dev); |
438 | |
439 | rt2860_stop(ifp, 1); |
440 | |
441 | ieee80211_ifdetach(&sc->sc_ic); /* free all nodes */ |
442 | if_detach(ifp); |
443 | |
444 | for (qid = 0; qid < MAXQS; qid++) |
445 | rt2860_free_tx_ring(sc, &sc->txq[qid]); |
446 | rt2860_free_rx_ring(sc, &sc->rxq); |
447 | rt2860_free_tx_pool(sc); |
448 | |
449 | if (sc->ucode != NULL) |
450 | free(sc->ucode, M_DEVBUF); |
451 | |
452 | return 0; |
453 | } |
454 | |
455 | void |
456 | rt2860_suspend(void *xsc) |
457 | { |
458 | struct rt2860_softc *sc = xsc; |
459 | struct ifnet *ifp = &sc->sc_if; |
460 | |
461 | if (ifp->if_flags & IFF_RUNNING) |
462 | rt2860_stop(ifp, 1); |
463 | } |
464 | |
465 | void |
466 | rt2860_wakeup(void *xsc) |
467 | { |
468 | struct rt2860_softc *sc = xsc; |
469 | struct ifnet *ifp = &sc->sc_if; |
470 | |
471 | if (ifp->if_flags & IFF_UP) |
472 | rt2860_init(ifp); |
473 | } |
474 | |
475 | static int |
476 | rt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) |
477 | { |
478 | int nsegs, size, error; |
479 | |
480 | size = RT2860_TX_RING_COUNT * sizeof (struct rt2860_txd); |
481 | |
482 | error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, |
483 | BUS_DMA_NOWAIT, &ring->map); |
484 | if (error != 0) { |
485 | aprint_error_dev(sc->sc_dev, "could not create DMA map\n" ); |
486 | goto fail; |
487 | } |
488 | |
489 | /* Tx rings must be 4-DWORD aligned */ |
490 | error = bus_dmamem_alloc(sc->sc_dmat, size, 16, 0, &ring->seg, 1, |
491 | &nsegs, BUS_DMA_NOWAIT); |
492 | if (error != 0) { |
493 | aprint_error_dev(sc->sc_dev, |
494 | "could not allocate DMA memory\n" ); |
495 | goto fail; |
496 | } |
497 | |
498 | error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs, size, |
499 | (void **)&ring->txd, BUS_DMA_NOWAIT); |
500 | if (error != 0) { |
501 | aprint_error_dev(sc->sc_dev, "can't map DMA memory\n" ); |
502 | goto fail; |
503 | } |
504 | |
505 | error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->txd, size, NULL, |
506 | BUS_DMA_NOWAIT); |
507 | if (error != 0) { |
508 | aprint_error_dev(sc->sc_dev, "could not load DMA map\n" ); |
509 | goto fail; |
510 | } |
511 | |
512 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, size, BUS_DMASYNC_PREWRITE); |
513 | |
514 | ring->paddr = ring->map->dm_segs[0].ds_addr; |
515 | |
516 | return 0; |
517 | |
518 | fail: rt2860_free_tx_ring(sc, ring); |
519 | return error; |
520 | } |
521 | |
522 | static void |
523 | rt2860_reset_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) |
524 | { |
525 | struct rt2860_tx_data *data; |
526 | int i; |
527 | |
528 | for (i = 0; i < RT2860_TX_RING_COUNT; i++) { |
529 | if ((data = ring->data[i]) == NULL) |
530 | continue; /* nothing mapped in this slot */ |
531 | |
532 | if (data->ni != NULL) { |
533 | ieee80211_free_node(data->ni); |
534 | data->ni = NULL; |
535 | } |
536 | |
537 | if (data->m != NULL) { |
538 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
539 | data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
540 | bus_dmamap_unload(sc->sc_dmat, data->map); |
541 | m_freem(data->m); |
542 | data->m = NULL; |
543 | } |
544 | |
545 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); |
546 | ring->data[i] = NULL; |
547 | } |
548 | |
549 | ring->queued = 0; |
550 | ring->cur = ring->next = 0; |
551 | } |
552 | |
553 | static void |
554 | rt2860_free_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) |
555 | { |
556 | struct rt2860_tx_data *data; |
557 | int i; |
558 | |
559 | if (ring->txd != NULL) { |
560 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, |
561 | ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
562 | bus_dmamap_unload(sc->sc_dmat, ring->map); |
563 | bus_dmamem_unmap(sc->sc_dmat, (void *)ring->txd, |
564 | RT2860_TX_RING_COUNT * sizeof (struct rt2860_txd)); |
565 | bus_dmamem_free(sc->sc_dmat, &ring->seg, 1); |
566 | } |
567 | if (ring->map != NULL) |
568 | bus_dmamap_destroy(sc->sc_dmat, ring->map); |
569 | |
570 | for (i = 0; i < RT2860_TX_RING_COUNT; i++) { |
571 | if ((data = ring->data[i]) == NULL) |
572 | continue; /* nothing mapped in this slot */ |
573 | |
574 | if (data->ni != NULL) { |
575 | ieee80211_free_node(data->ni); |
576 | data->ni = NULL; |
577 | } |
578 | if (data->m != NULL) { |
579 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
580 | data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
581 | bus_dmamap_unload(sc->sc_dmat, data->map); |
582 | m_freem(data->m); |
583 | data->m = NULL; |
584 | } |
585 | |
586 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); |
587 | ring->data[i] = NULL; |
588 | } |
589 | ring->queued = 0; |
590 | ring->cur = ring->next = 0; |
591 | } |
592 | |
593 | /* |
594 | * Allocate a pool of TX Wireless Information blocks. |
595 | */ |
596 | static int |
597 | rt2860_alloc_tx_pool(struct rt2860_softc *sc) |
598 | { |
599 | char *vaddr; |
600 | bus_addr_t paddr; |
601 | int i, nsegs, size, error; |
602 | |
603 | size = RT2860_TX_POOL_COUNT * RT2860_TXWI_DMASZ; |
604 | |
605 | /* init data_pool early in case of failure.. */ |
606 | SLIST_INIT(&sc->data_pool); |
607 | |
608 | error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, |
609 | BUS_DMA_NOWAIT, &sc->txwi_map); |
610 | if (error != 0) { |
611 | aprint_error_dev(sc->sc_dev, "could not create DMA map\n" ); |
612 | goto fail; |
613 | } |
614 | |
615 | error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, |
616 | &sc->txwi_seg, 1, &nsegs, BUS_DMA_NOWAIT); |
617 | if (error != 0) { |
618 | aprint_error_dev(sc->sc_dev, |
619 | "could not allocate DMA memory\n" ); |
620 | goto fail; |
621 | } |
622 | |
623 | error = bus_dmamem_map(sc->sc_dmat, &sc->txwi_seg, nsegs, size, |
624 | &sc->txwi_vaddr, BUS_DMA_NOWAIT); |
625 | if (error != 0) { |
626 | aprint_error_dev(sc->sc_dev, "can't map DMA memory\n" ); |
627 | goto fail; |
628 | } |
629 | |
630 | error = bus_dmamap_load(sc->sc_dmat, sc->txwi_map, sc->txwi_vaddr, |
631 | size, NULL, BUS_DMA_NOWAIT); |
632 | if (error != 0) { |
633 | aprint_error_dev(sc->sc_dev, "could not load DMA map\n" ); |
634 | goto fail; |
635 | } |
636 | |
637 | bus_dmamap_sync(sc->sc_dmat, sc->txwi_map, 0, size, |
638 | BUS_DMASYNC_PREWRITE); |
639 | |
640 | vaddr = sc->txwi_vaddr; |
641 | paddr = sc->txwi_map->dm_segs[0].ds_addr; |
642 | for (i = 0; i < RT2860_TX_POOL_COUNT; i++) { |
643 | struct rt2860_tx_data *data = &sc->data[i]; |
644 | |
645 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, |
646 | RT2860_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT, |
647 | &data->map); /* <0> */ |
648 | if (error != 0) { |
649 | aprint_error_dev(sc->sc_dev, |
650 | "could not create DMA map\n" ); |
651 | goto fail; |
652 | } |
653 | data->txwi = (struct rt2860_txwi *)vaddr; |
654 | data->paddr = paddr; |
655 | vaddr += RT2860_TXWI_DMASZ; |
656 | paddr += RT2860_TXWI_DMASZ; |
657 | |
658 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); |
659 | } |
660 | |
661 | return 0; |
662 | |
663 | fail: rt2860_free_tx_pool(sc); |
664 | return error; |
665 | } |
666 | |
667 | static void |
668 | rt2860_free_tx_pool(struct rt2860_softc *sc) |
669 | { |
670 | if (sc->txwi_vaddr != NULL) { |
671 | bus_dmamap_sync(sc->sc_dmat, sc->txwi_map, 0, |
672 | sc->txwi_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
673 | bus_dmamap_unload(sc->sc_dmat, sc->txwi_map); |
674 | bus_dmamem_unmap(sc->sc_dmat, sc->txwi_vaddr, |
675 | RT2860_TX_POOL_COUNT * RT2860_TXWI_DMASZ); |
676 | bus_dmamem_free(sc->sc_dmat, &sc->txwi_seg, 1); |
677 | } |
678 | if (sc->txwi_map != NULL) |
679 | bus_dmamap_destroy(sc->sc_dmat, sc->txwi_map); |
680 | |
681 | while (!SLIST_EMPTY(&sc->data_pool)) { |
682 | struct rt2860_tx_data *data; |
683 | data = SLIST_FIRST(&sc->data_pool); |
684 | bus_dmamap_destroy(sc->sc_dmat, data->map); |
685 | SLIST_REMOVE_HEAD(&sc->data_pool, next); |
686 | } |
687 | } |
688 | |
689 | static int |
690 | rt2860_alloc_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) |
691 | { |
692 | int i, nsegs, size, error; |
693 | |
694 | size = RT2860_RX_RING_COUNT * sizeof (struct rt2860_rxd); |
695 | |
696 | error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, |
697 | BUS_DMA_NOWAIT, &ring->map); |
698 | if (error != 0) { |
699 | aprint_error_dev(sc->sc_dev, "could not create DMA map\n" ); |
700 | goto fail; |
701 | } |
702 | |
703 | /* Rx ring must be 4-DWORD aligned */ |
704 | error = bus_dmamem_alloc(sc->sc_dmat, size, 16, 0, &ring->seg, 1, |
705 | &nsegs, BUS_DMA_NOWAIT); |
706 | if (error != 0) { |
707 | aprint_error_dev(sc->sc_dev, |
708 | "could not allocate DMA memory\n" ); |
709 | goto fail; |
710 | } |
711 | |
712 | error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs, size, |
713 | (void **)&ring->rxd, BUS_DMA_NOWAIT); |
714 | if (error != 0) { |
715 | aprint_error_dev(sc->sc_dev, "can't map DMA memory\n" ); |
716 | goto fail; |
717 | } |
718 | |
719 | error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->rxd, size, NULL, |
720 | BUS_DMA_NOWAIT); |
721 | if (error != 0) { |
722 | aprint_error_dev(sc->sc_dev, "could not load DMA map\n" ); |
723 | goto fail; |
724 | } |
725 | |
726 | ring->paddr = ring->map->dm_segs[0].ds_addr; |
727 | |
728 | for (i = 0; i < RT2860_RX_RING_COUNT; i++) { |
729 | struct rt2860_rx_data *data = &ring->data[i]; |
730 | struct rt2860_rxd *rxd = &ring->rxd[i]; |
731 | const char *msg; |
732 | |
733 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, |
734 | 0, BUS_DMA_NOWAIT, &data->map); |
735 | if (error != 0) { |
736 | aprint_error_dev(sc->sc_dev, |
737 | "could not create DMA map\n" ); |
738 | goto fail; |
739 | } |
740 | |
741 | MGETHDR(data->m, M_DONTWAIT, MT_DATA); |
742 | if (data->m == NULL) { |
743 | msg = "allocate Rx mbuf" ; |
744 | goto fail1; |
745 | } |
746 | MCLGET(data->m, M_DONTWAIT); |
747 | if ((data->m->m_flags & M_EXT) == 0) { |
748 | msg = "allocate Rx mbuf cluster" ; |
749 | goto fail1; |
750 | } |
751 | |
752 | |
753 | error = bus_dmamap_load(sc->sc_dmat, data->map, |
754 | mtod(data->m, void *), MCLBYTES, NULL, |
755 | BUS_DMA_READ | BUS_DMA_NOWAIT); |
756 | if (error != 0) { |
757 | msg = "load DMA map" ; |
758 | fail1: |
759 | aprint_error_dev(sc->sc_dev, "could not %s\n" , msg); |
760 | m_freem(data->m); |
761 | data->m = NULL; |
762 | error = ENOBUFS; |
763 | goto fail; |
764 | } |
765 | |
766 | rxd->sdp0 = htole32(data->map->dm_segs[0].ds_addr); |
767 | rxd->sdl0 = htole16(MCLBYTES); |
768 | } |
769 | |
770 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, size, BUS_DMASYNC_PREWRITE); |
771 | |
772 | return 0; |
773 | fail: rt2860_free_rx_ring(sc, ring); |
774 | return error; |
775 | } |
776 | |
777 | static void |
778 | rt2860_reset_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) |
779 | { |
780 | int i; |
781 | |
782 | for (i = 0; i < RT2860_RX_RING_COUNT; i++) |
783 | ring->rxd[i].sdl0 &= ~htole16(RT2860_RX_DDONE); |
784 | |
785 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, |
786 | BUS_DMASYNC_PREWRITE); |
787 | |
788 | ring->cur = 0; |
789 | } |
790 | |
791 | static void |
792 | rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) |
793 | { |
794 | int i; |
795 | |
796 | if (ring->rxd != NULL) { |
797 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, |
798 | ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
799 | bus_dmamap_unload(sc->sc_dmat, ring->map); |
800 | bus_dmamem_unmap(sc->sc_dmat, (void *)ring->rxd, |
801 | RT2860_RX_RING_COUNT * sizeof (struct rt2860_rxd)); |
802 | bus_dmamem_free(sc->sc_dmat, &ring->seg, 1); |
803 | ring->rxd = NULL; |
804 | } |
805 | if (ring->map != NULL) { |
806 | bus_dmamap_destroy(sc->sc_dmat, ring->map); |
807 | ring->map = NULL; |
808 | } |
809 | |
810 | for (i = 0; i < RT2860_RX_RING_COUNT; i++) { |
811 | struct rt2860_rx_data *data = &ring->data[i]; |
812 | |
813 | if (data->m != NULL) { |
814 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
815 | data->map->dm_mapsize, BUS_DMASYNC_POSTREAD); |
816 | bus_dmamap_unload(sc->sc_dmat, data->map); |
817 | m_freem(data->m); |
818 | data->m = NULL; |
819 | } |
820 | if (data->map != NULL) { |
821 | bus_dmamap_destroy(sc->sc_dmat, data->map); |
822 | data->map = NULL; |
823 | } |
824 | } |
825 | } |
826 | |
827 | static struct ieee80211_node * |
828 | rt2860_node_alloc(struct ieee80211_node_table *nt) |
829 | { |
830 | struct rt2860_node *rn = malloc(sizeof(*rn), M_80211_NODE, |
831 | M_NOWAIT | M_ZERO); |
832 | return rn ? &rn->ni : NULL; |
833 | } |
834 | |
835 | static int |
836 | rt2860_media_change(struct ifnet *ifp) |
837 | { |
838 | struct rt2860_softc *sc = ifp->if_softc; |
839 | struct ieee80211com *ic = &sc->sc_ic; |
840 | uint8_t rate, ridx; |
841 | int error; |
842 | |
843 | error = ieee80211_media_change(ifp); |
844 | if (error != ENETRESET) |
845 | return error; |
846 | |
847 | if (ic->ic_fixed_rate != -1) { |
848 | rate = ic->ic_sup_rates[ic->ic_curmode]. |
849 | rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; |
850 | for (ridx = 0; ridx <= RT2860_RIDX_MAX; ridx++) |
851 | if (rt2860_rates[ridx].rate == rate) |
852 | break; |
853 | sc->fixed_ridx = ridx; |
854 | } |
855 | |
856 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == |
857 | (IFF_UP | IFF_RUNNING)) { |
858 | rt2860_stop(ifp, 0); |
859 | rt2860_init(ifp); |
860 | } |
861 | return 0; |
862 | } |
863 | |
864 | static void |
865 | rt2860_iter_func(void *arg, struct ieee80211_node *ni) |
866 | { |
867 | struct rt2860_softc *sc = arg; |
868 | uint8_t wcid = ((struct rt2860_node *)ni)->wcid; |
869 | |
870 | ieee80211_amrr_choose(&sc->amrr, ni, &sc->amn[wcid]); |
871 | } |
872 | |
873 | static void |
874 | rt2860_updatestats(struct rt2860_softc *sc) |
875 | { |
876 | struct ieee80211com *ic = &sc->sc_ic; |
877 | |
878 | #ifndef IEEE80211_STA_ONLY |
879 | /* |
880 | * In IBSS or HostAP modes (when the hardware sends beacons), the |
881 | * MAC can run into a livelock and start sending CTS-to-self frames |
882 | * like crazy if protection is enabled. Fortunately, we can detect |
883 | * when such a situation occurs and reset the MAC. |
884 | */ |
885 | if (ic->ic_curmode != IEEE80211_M_STA) { |
886 | /* check if we're in a livelock situation.. */ |
887 | uint32_t tmp = RAL_READ(sc, RT2860_DEBUG); |
888 | if ((tmp & (1 << 29)) && (tmp & (1 << 7 | 1 << 5))) { |
889 | /* ..and reset MAC/BBP for a while.. */ |
890 | DPRINTF(("CTS-to-self livelock detected\n" )); |
891 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_SRST); |
892 | RAL_BARRIER_WRITE(sc); |
893 | DELAY(1); |
894 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, |
895 | RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); |
896 | } |
897 | } |
898 | #endif |
899 | if (ic->ic_opmode == IEEE80211_M_STA) |
900 | rt2860_iter_func(sc, ic->ic_bss); |
901 | #ifndef IEEE80211_STA_ONLY |
902 | else |
903 | ieee80211_iterate_nodes(&ic->ic_sta, rt2860_iter_func, sc); |
904 | #endif |
905 | } |
906 | |
907 | static void |
908 | rt2860_newassoc(struct ieee80211_node *ni, int isnew) |
909 | { |
910 | struct rt2860_softc *sc = ni->ni_ic->ic_ifp->if_softc; |
911 | struct rt2860_node *rn = (void *)ni; |
912 | struct ieee80211_rateset *rs = &ni->ni_rates; |
913 | uint8_t rate, wcid = 0; |
914 | int ridx, i, j; |
915 | |
916 | if (isnew && ni->ni_associd != 0) { |
917 | /* only interested in true associations */ |
918 | wcid = rn->wcid = IEEE80211_AID(ni->ni_associd); |
919 | |
920 | /* init WCID table entry */ |
921 | RAL_WRITE_REGION_1(sc, RT2860_WCID_ENTRY(wcid), |
922 | ni->ni_macaddr, IEEE80211_ADDR_LEN); |
923 | } |
924 | DPRINTF(("new assoc isnew=%d addr=%s WCID=%d\n" , |
925 | isnew, ether_sprintf(ni->ni_macaddr), wcid)); |
926 | |
927 | ieee80211_amrr_node_init(&sc->amrr, &sc->amn[wcid]); |
928 | /* start at lowest available bit-rate, AMRR will raise */ |
929 | ni->ni_txrate = 0; |
930 | |
931 | for (i = 0; i < rs->rs_nrates; i++) { |
932 | rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; |
933 | /* convert 802.11 rate to hardware rate index */ |
934 | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) |
935 | if (rt2860_rates[ridx].rate == rate) |
936 | break; |
937 | rn->ridx[i] = ridx; |
938 | /* determine rate of control response frames */ |
939 | for (j = i; j >= 0; j--) { |
940 | if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && |
941 | rt2860_rates[rn->ridx[i]].phy == |
942 | rt2860_rates[rn->ridx[j]].phy) |
943 | break; |
944 | } |
945 | if (j >= 0) { |
946 | rn->ctl_ridx[i] = rn->ridx[j]; |
947 | } else { |
948 | /* no basic rate found, use mandatory one */ |
949 | rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; |
950 | } |
951 | DPRINTF(("rate=0x%02x ridx=%d ctl_ridx=%d\n" , |
952 | rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i])); |
953 | } |
954 | } |
955 | |
956 | #ifdef notyet |
957 | static int |
958 | rt2860_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, |
959 | uint8_t tid) |
960 | { |
961 | struct rt2860_softc *sc = ic->ic_softc; |
962 | uint8_t wcid = ((struct rt2860_node *)ni)->wcid; |
963 | uint32_t tmp; |
964 | |
965 | /* update BA session mask */ |
966 | tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); |
967 | tmp |= (1 << tid) << 16; |
968 | RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); |
969 | return 0; |
970 | } |
971 | |
972 | static void |
973 | rt2860_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, |
974 | uint8_t tid) |
975 | { |
976 | struct rt2860_softc *sc = ic->ic_softc; |
977 | uint8_t wcid = ((struct rt2860_node *)ni)->wcid; |
978 | uint32_t tmp; |
979 | |
980 | /* update BA session mask */ |
981 | tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); |
982 | tmp &= ~((1 << tid) << 16); |
983 | RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); |
984 | } |
985 | #endif |
986 | |
987 | static int |
988 | rt2860_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) |
989 | { |
990 | struct rt2860_softc *sc = ic->ic_ifp->if_softc; |
991 | enum ieee80211_state ostate; |
992 | uint32_t tmp; |
993 | |
994 | ostate = ic->ic_state; |
995 | |
996 | DPRINTF(("ostate = %d nstate = %d\n" , ostate, nstate)); |
997 | if (ostate == IEEE80211_S_RUN) { |
998 | /* turn link LED off */ |
999 | rt2860_set_leds(sc, RT2860_LED_RADIO); |
1000 | } |
1001 | |
1002 | switch (nstate) { |
1003 | case IEEE80211_S_INIT: |
1004 | if (ostate == IEEE80211_S_RUN) { |
1005 | /* abort TSF synchronization */ |
1006 | tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); |
1007 | RAL_WRITE(sc, RT2860_BCN_TIME_CFG, |
1008 | tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | |
1009 | RT2860_TBTT_TIMER_EN)); |
1010 | } |
1011 | rt2860_set_gp_timer(sc, 0); |
1012 | break; |
1013 | |
1014 | case IEEE80211_S_SCAN: |
1015 | rt2860_switch_chan(sc, ic->ic_curchan); |
1016 | if (ostate != IEEE80211_S_SCAN) |
1017 | rt2860_set_gp_timer(sc, 150); |
1018 | break; |
1019 | |
1020 | case IEEE80211_S_AUTH: |
1021 | case IEEE80211_S_ASSOC: |
1022 | rt2860_set_gp_timer(sc, 0); |
1023 | rt2860_switch_chan(sc, ic->ic_curchan); |
1024 | break; |
1025 | |
1026 | case IEEE80211_S_RUN: |
1027 | rt2860_set_gp_timer(sc, 0); |
1028 | rt2860_switch_chan(sc, ic->ic_curchan); |
1029 | |
1030 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
1031 | rt2860_updateslot(ic->ic_ifp); |
1032 | rt2860_enable_mrr(sc); |
1033 | rt2860_set_txpreamble(sc); |
1034 | rt2860_set_basicrates(sc); |
1035 | rt2860_set_bssid(sc, ic->ic_bss->ni_bssid); |
1036 | } |
1037 | |
1038 | #ifndef IEEE80211_STA_ONLY |
1039 | if (ic->ic_opmode == IEEE80211_M_HOSTAP || |
1040 | ic->ic_opmode == IEEE80211_M_IBSS) |
1041 | (void)rt2860_setup_beacon(sc); |
1042 | #endif |
1043 | |
1044 | if (ic->ic_opmode == IEEE80211_M_STA) { |
1045 | /* fake a join to init the tx rate */ |
1046 | rt2860_newassoc(ic->ic_bss, 1); |
1047 | } |
1048 | |
1049 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
1050 | rt2860_enable_tsf_sync(sc); |
1051 | rt2860_set_gp_timer(sc, 500); |
1052 | } |
1053 | |
1054 | /* turn link LED on */ |
1055 | rt2860_set_leds(sc, RT2860_LED_RADIO | |
1056 | (IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? |
1057 | RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); |
1058 | break; |
1059 | } |
1060 | |
1061 | return sc->sc_newstate(ic, nstate, arg); |
1062 | } |
1063 | |
1064 | /* Read 16-bit from eFUSE ROM (>=RT3071 only.) */ |
1065 | static uint16_t |
1066 | rt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) |
1067 | { |
1068 | uint32_t tmp; |
1069 | uint16_t reg; |
1070 | int ntries; |
1071 | |
1072 | addr *= 2; |
1073 | /*- |
1074 | * Read one 16-byte block into registers EFUSE_DATA[0-3]: |
1075 | * DATA0: F E D C |
1076 | * DATA1: B A 9 8 |
1077 | * DATA2: 7 6 5 4 |
1078 | * DATA3: 3 2 1 0 |
1079 | */ |
1080 | tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); |
1081 | tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); |
1082 | tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; |
1083 | RAL_WRITE(sc, RT3070_EFUSE_CTRL, tmp); |
1084 | for (ntries = 0; ntries < 500; ntries++) { |
1085 | tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); |
1086 | if (!(tmp & RT3070_EFSROM_KICK)) |
1087 | break; |
1088 | DELAY(2); |
1089 | } |
1090 | if (ntries == 500) |
1091 | return 0xffff; |
1092 | |
1093 | if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) |
1094 | return 0xffff; /* address not found */ |
1095 | |
1096 | /* determine to which 32-bit register our 16-bit word belongs */ |
1097 | reg = RT3070_EFUSE_DATA3 - (addr & 0xc); |
1098 | tmp = RAL_READ(sc, reg); |
1099 | |
1100 | return (addr & 2) ? tmp >> 16 : tmp & 0xffff; |
1101 | } |
1102 | |
1103 | /* |
1104 | * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, |
1105 | * 93C66 or 93C86). |
1106 | */ |
1107 | static uint16_t |
1108 | rt2860_eeprom_read_2(struct rt2860_softc *sc, uint16_t addr) |
1109 | { |
1110 | uint32_t tmp; |
1111 | uint16_t val; |
1112 | int n; |
1113 | |
1114 | /* clock C once before the first command */ |
1115 | RT2860_EEPROM_CTL(sc, 0); |
1116 | |
1117 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1118 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); |
1119 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1120 | |
1121 | /* write start bit (1) */ |
1122 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); |
1123 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); |
1124 | |
1125 | /* write READ opcode (10) */ |
1126 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); |
1127 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); |
1128 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1129 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); |
1130 | |
1131 | /* write address (A5-A0 or A7-A0) */ |
1132 | n = ((RAL_READ(sc, RT2860_PCI_EECTRL) & 0x30) == 0) ? 5 : 7; |
1133 | for (; n >= 0; n--) { |
1134 | RT2860_EEPROM_CTL(sc, RT2860_S | |
1135 | (((addr >> n) & 1) << RT2860_SHIFT_D)); |
1136 | RT2860_EEPROM_CTL(sc, RT2860_S | |
1137 | (((addr >> n) & 1) << RT2860_SHIFT_D) | RT2860_C); |
1138 | } |
1139 | |
1140 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1141 | |
1142 | /* read data Q15-Q0 */ |
1143 | val = 0; |
1144 | for (n = 15; n >= 0; n--) { |
1145 | RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); |
1146 | tmp = RAL_READ(sc, RT2860_PCI_EECTRL); |
1147 | val |= ((tmp & RT2860_Q) >> RT2860_SHIFT_Q) << n; |
1148 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1149 | } |
1150 | |
1151 | RT2860_EEPROM_CTL(sc, 0); |
1152 | |
1153 | /* clear Chip Select and clock C */ |
1154 | RT2860_EEPROM_CTL(sc, RT2860_S); |
1155 | RT2860_EEPROM_CTL(sc, 0); |
1156 | RT2860_EEPROM_CTL(sc, RT2860_C); |
1157 | |
1158 | return val; |
1159 | } |
1160 | |
1161 | static __inline uint16_t |
1162 | rt2860_srom_read(struct rt2860_softc *sc, uint8_t addr) |
1163 | { |
1164 | /* either eFUSE ROM or EEPROM */ |
1165 | return sc->sc_srom_read(sc, addr); |
1166 | } |
1167 | |
1168 | static void |
1169 | rt2860_intr_coherent(struct rt2860_softc *sc) |
1170 | { |
1171 | uint32_t tmp; |
1172 | |
1173 | /* DMA finds data coherent event when checking the DDONE bit */ |
1174 | |
1175 | DPRINTF(("Tx/Rx Coherent interrupt\n" )); |
1176 | |
1177 | /* restart DMA engine */ |
1178 | tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); |
1179 | tmp &= ~(RT2860_TX_WB_DDONE | RT2860_RX_DMA_EN | RT2860_TX_DMA_EN); |
1180 | RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); |
1181 | |
1182 | (void)rt2860_txrx_enable(sc); |
1183 | } |
1184 | |
1185 | static void |
1186 | rt2860_drain_stats_fifo(struct rt2860_softc *sc) |
1187 | { |
1188 | struct ifnet *ifp = &sc->sc_if; |
1189 | struct ieee80211_amrr_node *amn; |
1190 | uint32_t stat; |
1191 | uint8_t wcid, mcs, pid; |
1192 | |
1193 | /* drain Tx status FIFO (maxsize = 16) */ |
1194 | while ((stat = RAL_READ(sc, RT2860_TX_STAT_FIFO)) & RT2860_TXQ_VLD) { |
1195 | DPRINTFN(4, ("tx stat 0x%08x\n" , stat)); |
1196 | |
1197 | wcid = (stat >> RT2860_TXQ_WCID_SHIFT) & 0xff; |
1198 | |
1199 | /* if no ACK was requested, no feedback is available */ |
1200 | if (!(stat & RT2860_TXQ_ACKREQ) || wcid == 0xff) |
1201 | continue; |
1202 | |
1203 | /* update per-STA AMRR stats */ |
1204 | amn = &sc->amn[wcid]; |
1205 | amn->amn_txcnt++; |
1206 | if (stat & RT2860_TXQ_OK) { |
1207 | /* |
1208 | * Check if there were retries, ie if the Tx success |
1209 | * rate is different from the requested rate. Note |
1210 | * that it works only because we do not allow rate |
1211 | * fallback from OFDM to CCK. |
1212 | */ |
1213 | mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; |
1214 | pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; |
1215 | if (mcs + 1 != pid) |
1216 | amn->amn_retrycnt++; |
1217 | } else { |
1218 | amn->amn_retrycnt++; |
1219 | ifp->if_oerrors++; |
1220 | } |
1221 | } |
1222 | } |
1223 | |
1224 | static void |
1225 | rt2860_tx_intr(struct rt2860_softc *sc, int qid) |
1226 | { |
1227 | struct ifnet *ifp = &sc->sc_if; |
1228 | struct rt2860_tx_ring *ring = &sc->txq[qid]; |
1229 | uint32_t hw; |
1230 | |
1231 | rt2860_drain_stats_fifo(sc); |
1232 | |
1233 | hw = RAL_READ(sc, RT2860_TX_DTX_IDX(qid)); |
1234 | DPRINTF(("%s: tx mbuf %#x\n" , __func__, hw)); |
1235 | while (ring->next != hw) { |
1236 | struct rt2860_tx_data *data = ring->data[ring->next]; |
1237 | |
1238 | if (data != NULL) { |
1239 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
1240 | data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
1241 | bus_dmamap_unload(sc->sc_dmat, data->map); |
1242 | m_freem(data->m); |
1243 | data->m = NULL; |
1244 | ieee80211_free_node(data->ni); |
1245 | data->ni = NULL; |
1246 | |
1247 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); |
1248 | ring->data[ring->next] = NULL; |
1249 | |
1250 | ifp->if_opackets++; |
1251 | } |
1252 | ring->queued--; |
1253 | ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; |
1254 | } |
1255 | |
1256 | sc->sc_tx_timer = 0; |
1257 | if (ring->queued <= RT2860_TX_RING_ONEMORE) |
1258 | sc->qfullmsk &= ~(1 << qid); |
1259 | ifp->if_flags &= ~IFF_OACTIVE; |
1260 | rt2860_start(ifp); |
1261 | } |
1262 | |
1263 | /* |
1264 | * Return the Rx chain with the highest RSSI for a given frame. |
1265 | */ |
1266 | static __inline uint8_t |
1267 | (struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) |
1268 | { |
1269 | uint8_t rxchain = 0; |
1270 | |
1271 | if (sc->nrxchains > 1) { |
1272 | if (rxwi->rssi[1] > rxwi->rssi[rxchain]) |
1273 | rxchain = 1; |
1274 | if (sc->nrxchains > 2) |
1275 | if (rxwi->rssi[2] > rxwi->rssi[rxchain]) |
1276 | rxchain = 2; |
1277 | } |
1278 | return rxchain; |
1279 | } |
1280 | |
1281 | static void |
1282 | rt2860_rx_intr(struct rt2860_softc *sc) |
1283 | { |
1284 | struct ieee80211com *ic = &sc->sc_ic; |
1285 | struct ifnet *ifp = &sc->sc_if; |
1286 | struct ieee80211_frame *wh; |
1287 | struct ieee80211_node *ni; |
1288 | struct mbuf *m, *m1; |
1289 | uint32_t hw; |
1290 | uint8_t ant, ; |
1291 | int error; |
1292 | struct rt2860_rx_radiotap_header *tap; |
1293 | uint16_t phy; |
1294 | |
1295 | hw = RAL_READ(sc, RT2860_FS_DRX_IDX) & 0xfff; |
1296 | DPRINTF(("%s: rx mbuf %#x\n" , __func__, hw)); |
1297 | while (sc->rxq.cur != hw) { |
1298 | struct rt2860_rx_data *data = &sc->rxq.data[sc->rxq.cur]; |
1299 | struct rt2860_rxd *rxd = &sc->rxq.rxd[sc->rxq.cur]; |
1300 | struct rt2860_rxwi *rxwi; |
1301 | |
1302 | bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, |
1303 | sc->rxq.cur * sizeof (struct rt2860_rxd), |
1304 | sizeof (struct rt2860_rxd), BUS_DMASYNC_POSTREAD); |
1305 | |
1306 | if (__predict_false(!(rxd->sdl0 & htole16(RT2860_RX_DDONE)))) { |
1307 | DPRINTF(("RXD DDONE bit not set!\n" )); |
1308 | break; /* should not happen */ |
1309 | } |
1310 | |
1311 | if (__predict_false(rxd->flags & |
1312 | htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { |
1313 | DPRINTF(("error %#x\n" , rxd->flags)); |
1314 | ifp->if_ierrors++; |
1315 | goto skip; |
1316 | } |
1317 | |
1318 | |
1319 | MGETHDR(m1, M_DONTWAIT, MT_DATA); |
1320 | if (__predict_false(m1 == NULL)) { |
1321 | DPRINTF(("error2 %#x\n" , rxd->flags)); |
1322 | ifp->if_ierrors++; |
1323 | goto skip; |
1324 | } |
1325 | MCLGET(m1, M_DONTWAIT); |
1326 | if (__predict_false((m1->m_flags & M_EXT) == 0)) { |
1327 | DPRINTF(("no mbuf\n" )); |
1328 | m_freem(m1); |
1329 | ifp->if_ierrors++; |
1330 | goto skip; |
1331 | } |
1332 | |
1333 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
1334 | data->map->dm_mapsize, BUS_DMASYNC_POSTREAD); |
1335 | bus_dmamap_unload(sc->sc_dmat, data->map); |
1336 | |
1337 | error = bus_dmamap_load(sc->sc_dmat, data->map, |
1338 | mtod(m1, void *), MCLBYTES, NULL, |
1339 | BUS_DMA_READ | BUS_DMA_NOWAIT); |
1340 | if (__predict_false(error != 0)) { |
1341 | DPRINTF(("dma error %d\n" , error)); |
1342 | m_freem(m1); |
1343 | |
1344 | /* try to reload the old mbuf */ |
1345 | error = bus_dmamap_load(sc->sc_dmat, data->map, |
1346 | mtod(data->m, void *), MCLBYTES, NULL, |
1347 | BUS_DMA_READ | BUS_DMA_NOWAIT); |
1348 | if (__predict_false(error != 0)) { |
1349 | panic("%s: could not load old rx mbuf" , |
1350 | device_xname(sc->sc_dev)); |
1351 | } |
1352 | /* physical address may have changed */ |
1353 | rxd->sdp0 = htole32(data->map->dm_segs[0].ds_addr); |
1354 | ifp->if_ierrors++; |
1355 | goto skip; |
1356 | } |
1357 | |
1358 | /* |
1359 | * New mbuf successfully loaded, update Rx ring and continue |
1360 | * processing. |
1361 | */ |
1362 | m = data->m; |
1363 | data->m = m1; |
1364 | rxd->sdp0 = htole32(data->map->dm_segs[0].ds_addr); |
1365 | |
1366 | rxwi = mtod(m, struct rt2860_rxwi *); |
1367 | |
1368 | /* finalize mbuf */ |
1369 | m->m_data = (void *)(rxwi + 1); |
1370 | m_set_rcvif(m, ifp); |
1371 | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; |
1372 | |
1373 | wh = mtod(m, struct ieee80211_frame *); |
1374 | #ifdef HW_CRYPTO |
1375 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { |
1376 | /* frame is decrypted by hardware */ |
1377 | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; |
1378 | } |
1379 | #endif |
1380 | |
1381 | /* HW may insert 2 padding bytes after 802.11 header */ |
1382 | if (rxd->flags & htole32(RT2860_RX_L2PAD)) { |
1383 | u_int hdrlen = ieee80211_hdrsize(wh); |
1384 | memmove((char *)wh + 2, wh, hdrlen); |
1385 | m->m_data += 2; |
1386 | wh = mtod(m, struct ieee80211_frame *); |
1387 | } |
1388 | |
1389 | #ifdef HW_CRYPTO |
1390 | if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { |
1391 | /* report MIC failures to net80211 for TKIP */ |
1392 | ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); |
1393 | DPRINTF(("error2 %#x\n" , rxd->flags)); |
1394 | ifp->if_ierrors++; |
1395 | goto skip; |
1396 | } |
1397 | #endif |
1398 | ant = rt2860_maxrssi_chain(sc, rxwi); |
1399 | rssi = rxwi->rssi[ant]; |
1400 | |
1401 | if (__predict_true(sc->sc_drvbpf == NULL)) |
1402 | goto skipbpf; |
1403 | |
1404 | tap = &sc->sc_rxtap; |
1405 | tap->wr_flags = 0; |
1406 | tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); |
1407 | tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); |
1408 | tap->wr_antsignal = rssi; |
1409 | tap->wr_antenna = ant; |
1410 | tap->wr_dbm_antsignal = rt2860_rssi2dbm(sc, rssi, ant); |
1411 | tap->wr_rate = 2; /* in case it can't be found below */ |
1412 | phy = le16toh(rxwi->phy); |
1413 | switch (phy & RT2860_PHY_MODE) { |
1414 | case RT2860_PHY_CCK: |
1415 | switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) { |
1416 | case 0: tap->wr_rate = 2; break; |
1417 | case 1: tap->wr_rate = 4; break; |
1418 | case 2: tap->wr_rate = 11; break; |
1419 | case 3: tap->wr_rate = 22; break; |
1420 | } |
1421 | if (phy & RT2860_PHY_SHPRE) |
1422 | tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; |
1423 | break; |
1424 | case RT2860_PHY_OFDM: |
1425 | switch (phy & RT2860_PHY_MCS) { |
1426 | case 0: tap->wr_rate = 12; break; |
1427 | case 1: tap->wr_rate = 18; break; |
1428 | case 2: tap->wr_rate = 24; break; |
1429 | case 3: tap->wr_rate = 36; break; |
1430 | case 4: tap->wr_rate = 48; break; |
1431 | case 5: tap->wr_rate = 72; break; |
1432 | case 6: tap->wr_rate = 96; break; |
1433 | case 7: tap->wr_rate = 108; break; |
1434 | } |
1435 | break; |
1436 | } |
1437 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); |
1438 | skipbpf: |
1439 | /* grab a reference to the source node */ |
1440 | ni = ieee80211_find_rxnode(ic, |
1441 | (struct ieee80211_frame_min *)wh); |
1442 | |
1443 | /* send the frame to the 802.11 layer */ |
1444 | ieee80211_input(ic, m, ni, rssi, 0); |
1445 | |
1446 | /* node is no longer needed */ |
1447 | ieee80211_free_node(ni); |
1448 | |
1449 | skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); |
1450 | |
1451 | bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, |
1452 | sc->rxq.cur * sizeof (struct rt2860_rxd), |
1453 | sizeof (struct rt2860_rxd), BUS_DMASYNC_PREWRITE); |
1454 | |
1455 | sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT; |
1456 | } |
1457 | |
1458 | /* tell HW what we have processed */ |
1459 | RAL_WRITE(sc, RT2860_RX_CALC_IDX, |
1460 | (sc->rxq.cur - 1) % RT2860_RX_RING_COUNT); |
1461 | } |
1462 | |
1463 | static void |
1464 | rt2860_tbtt_intr(struct rt2860_softc *sc) |
1465 | { |
1466 | struct ieee80211com *ic = &sc->sc_ic; |
1467 | |
1468 | #ifndef IEEE80211_STA_ONLY |
1469 | if (ic->ic_opmode == IEEE80211_M_HOSTAP) { |
1470 | /* one less beacon until next DTIM */ |
1471 | if (ic->ic_dtim_count == 0) |
1472 | ic->ic_dtim_count = ic->ic_dtim_period - 1; |
1473 | else |
1474 | ic->ic_dtim_count--; |
1475 | |
1476 | /* update dynamic parts of beacon */ |
1477 | rt2860_setup_beacon(sc); |
1478 | |
1479 | #if 0 |
1480 | /* flush buffered multicast frames */ |
1481 | if (ic->ic_dtim_count == 0) |
1482 | ieee80211_notify_dtim(ic); |
1483 | #endif |
1484 | } |
1485 | #endif |
1486 | /* check if protection mode has changed */ |
1487 | if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { |
1488 | rt2860_updateprot(ic); |
1489 | sc->sc_ic_flags = ic->ic_flags; |
1490 | } |
1491 | } |
1492 | |
1493 | static void |
1494 | rt2860_gp_intr(struct rt2860_softc *sc) |
1495 | { |
1496 | struct ieee80211com *ic = &sc->sc_ic; |
1497 | |
1498 | DPRINTFN(2, ("GP timeout state=%d\n" , ic->ic_state)); |
1499 | |
1500 | if (ic->ic_state == IEEE80211_S_SCAN) |
1501 | ieee80211_next_scan(ic); |
1502 | else if (ic->ic_state == IEEE80211_S_RUN) |
1503 | rt2860_updatestats(sc); |
1504 | } |
1505 | |
1506 | int |
1507 | rt2860_intr(void *arg) |
1508 | { |
1509 | struct rt2860_softc *sc = arg; |
1510 | uint32_t r; |
1511 | |
1512 | r = RAL_READ(sc, RT2860_INT_STATUS); |
1513 | if (__predict_false(r == 0xffffffff)) |
1514 | return 0; /* device likely went away */ |
1515 | if (r == 0) |
1516 | return 0; /* not for us */ |
1517 | |
1518 | /* acknowledge interrupts */ |
1519 | RAL_WRITE(sc, RT2860_INT_STATUS, r); |
1520 | |
1521 | if (r & RT2860_TX_RX_COHERENT) |
1522 | rt2860_intr_coherent(sc); |
1523 | |
1524 | if (r & RT2860_MAC_INT_2) /* TX status */ |
1525 | rt2860_drain_stats_fifo(sc); |
1526 | |
1527 | if (r & RT2860_TX_DONE_INT5) |
1528 | rt2860_tx_intr(sc, 5); |
1529 | |
1530 | if (r & RT2860_RX_DONE_INT) |
1531 | rt2860_rx_intr(sc); |
1532 | |
1533 | if (r & RT2860_TX_DONE_INT4) |
1534 | rt2860_tx_intr(sc, 4); |
1535 | |
1536 | if (r & RT2860_TX_DONE_INT3) |
1537 | rt2860_tx_intr(sc, 3); |
1538 | |
1539 | if (r & RT2860_TX_DONE_INT2) |
1540 | rt2860_tx_intr(sc, 2); |
1541 | |
1542 | if (r & RT2860_TX_DONE_INT1) |
1543 | rt2860_tx_intr(sc, 1); |
1544 | |
1545 | if (r & RT2860_TX_DONE_INT0) |
1546 | rt2860_tx_intr(sc, 0); |
1547 | |
1548 | if (r & RT2860_MAC_INT_0) /* TBTT */ |
1549 | rt2860_tbtt_intr(sc); |
1550 | |
1551 | if (r & RT2860_MAC_INT_3) { /* Auto wakeup */ |
1552 | /* TBD wakeup */ |
1553 | } |
1554 | |
1555 | if (r & RT2860_MAC_INT_4) /* GP timer */ |
1556 | rt2860_gp_intr(sc); |
1557 | |
1558 | return 1; |
1559 | } |
1560 | |
1561 | static int |
1562 | rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) |
1563 | { |
1564 | struct ieee80211com *ic = &sc->sc_ic; |
1565 | struct rt2860_node *rn = (void *)ni; |
1566 | struct rt2860_tx_ring *ring; |
1567 | struct rt2860_tx_data *data; |
1568 | struct rt2860_txd *txd; |
1569 | struct rt2860_txwi *txwi; |
1570 | struct ieee80211_frame *wh; |
1571 | bus_dma_segment_t *seg; |
1572 | u_int hdrlen; |
1573 | uint16_t qos, dur; |
1574 | uint8_t type, qsel, mcs, pid, tid, qid; |
1575 | int nsegs, hasqos, ridx, ctl_ridx; |
1576 | |
1577 | /* the data pool contains at least one element, pick the first */ |
1578 | data = SLIST_FIRST(&sc->data_pool); |
1579 | |
1580 | wh = mtod(m, struct ieee80211_frame *); |
1581 | #ifndef HW_CRYPTO |
1582 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { |
1583 | struct ieee80211_key *k = ieee80211_crypto_encap(ic, ni, m); |
1584 | if (k == NULL) { |
1585 | m_freem(m); |
1586 | return ENOBUFS; |
1587 | } |
1588 | |
1589 | /* packet header may have moved, reset our local pointer */ |
1590 | wh = mtod(m, struct ieee80211_frame *); |
1591 | } |
1592 | #endif |
1593 | |
1594 | hdrlen = ieee80211_anyhdrsize(wh); |
1595 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; |
1596 | |
1597 | if ((hasqos = ieee80211_has_qos(wh))) { |
1598 | qos = ieee80211_get_qos(wh); |
1599 | tid = qos & IEEE80211_QOS_TID; |
1600 | qid = TID_TO_WME_AC(tid); |
1601 | } else { |
1602 | qos = 0; |
1603 | tid = 0; |
1604 | qid = (type == IEEE80211_FC0_TYPE_MGT) ? |
1605 | sc->mgtqid : WME_AC_BE; |
1606 | } |
1607 | KASSERT(qid < MAXQS); |
1608 | ring = &sc->txq[qid]; |
1609 | |
1610 | /* pickup a rate index */ |
1611 | if (IEEE80211_IS_MULTICAST(wh->i_addr1) || |
1612 | type != IEEE80211_FC0_TYPE_DATA) { |
1613 | ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? |
1614 | RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; |
1615 | ctl_ridx = rt2860_rates[ridx].ctl_ridx; |
1616 | } else if (ic->ic_fixed_rate != -1) { |
1617 | ridx = sc->fixed_ridx; |
1618 | ctl_ridx = rt2860_rates[ridx].ctl_ridx; |
1619 | } else { |
1620 | ridx = rn->ridx[ni->ni_txrate]; |
1621 | ctl_ridx = rn->ctl_ridx[ni->ni_txrate]; |
1622 | } |
1623 | |
1624 | /* get MCS code from rate index */ |
1625 | mcs = rt2860_rates[ridx].mcs; |
1626 | |
1627 | /* setup TX Wireless Information */ |
1628 | txwi = data->txwi; |
1629 | txwi->flags = 0; |
1630 | /* let HW generate seq numbers for non-QoS frames */ |
1631 | txwi->xflags = hasqos ? 0 : RT2860_TX_NSEQ; |
1632 | txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ? rn->wcid : 0xff; |
1633 | txwi->len = htole16(m->m_pkthdr.len); |
1634 | if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { |
1635 | txwi->phy = htole16(RT2860_PHY_CCK); |
1636 | if (ridx != RT2860_RIDX_CCK1 && |
1637 | (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) |
1638 | mcs |= RT2860_PHY_SHPRE; |
1639 | } else |
1640 | txwi->phy = htole16(RT2860_PHY_OFDM); |
1641 | txwi->phy |= htole16(mcs); |
1642 | |
1643 | /* |
1644 | * We store the MCS code into the driver-private PacketID field. |
1645 | * The PacketID is latched into TX_STAT_FIFO when Tx completes so |
1646 | * that we know at which initial rate the frame was transmitted. |
1647 | * We add 1 to the MCS code because setting the PacketID field to |
1648 | * 0 means that we don't want feedback in TX_STAT_FIFO. |
1649 | */ |
1650 | pid = (mcs + 1) & 0xf; |
1651 | txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); |
1652 | |
1653 | /* check if RTS/CTS or CTS-to-self protection is required */ |
1654 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && |
1655 | (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold || |
1656 | ((ic->ic_flags & IEEE80211_F_USEPROT) && |
1657 | rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) |
1658 | txwi->txop = RT2860_TX_TXOP_HT; |
1659 | else |
1660 | txwi->txop = RT2860_TX_TXOP_BACKOFF; |
1661 | |
1662 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && |
1663 | (!hasqos || (qos & IEEE80211_QOS_ACKPOLICY) != |
1664 | IEEE80211_QOS_ACKPOLICY_NOACK)) { |
1665 | txwi->xflags |= RT2860_TX_ACK; |
1666 | |
1667 | if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) |
1668 | dur = rt2860_rates[ctl_ridx].sp_ack_dur; |
1669 | else |
1670 | dur = rt2860_rates[ctl_ridx].lp_ack_dur; |
1671 | *(uint16_t *)wh->i_dur = htole16(dur); |
1672 | } |
1673 | #ifndef IEEE80211_STA_ONLY |
1674 | /* ask MAC to insert timestamp into probe responses */ |
1675 | if ((wh->i_fc[0] & |
1676 | (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == |
1677 | (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) |
1678 | /* NOTE: beacons do not pass through tx_data() */ |
1679 | txwi->flags |= RT2860_TX_TS; |
1680 | #endif |
1681 | |
1682 | if (__predict_false(sc->sc_drvbpf != NULL)) { |
1683 | struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; |
1684 | |
1685 | tap->wt_flags = 0; |
1686 | tap->wt_rate = rt2860_rates[ridx].rate; |
1687 | tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); |
1688 | tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); |
1689 | tap->wt_hwqueue = qid; |
1690 | if (mcs & RT2860_PHY_SHPRE) |
1691 | tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; |
1692 | |
1693 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m); |
1694 | } |
1695 | |
1696 | /* copy and trim 802.11 header */ |
1697 | memcpy(txwi + 1, wh, hdrlen); |
1698 | m_adj(m, hdrlen); |
1699 | |
1700 | KASSERT (ring->queued <= RT2860_TX_RING_ONEMORE); /* <1> */ |
1701 | if (bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, BUS_DMA_NOWAIT)) { |
1702 | if (m_defrag(m, M_DONTWAIT)) |
1703 | return (ENOBUFS); |
1704 | if (bus_dmamap_load_mbuf(sc->sc_dmat, |
1705 | data->map, m, BUS_DMA_NOWAIT)) |
1706 | return (EFBIG); |
1707 | } |
1708 | |
1709 | /* The map will fit into the tx ring: (a "full" ring may have a few |
1710 | * unused descriptors, at most (txds(MAX_SCATTER) - 1)) |
1711 | * |
1712 | * ring->queued + txds(data->map->nsegs) |
1713 | * <= { <0> data->map->nsegs <= MAX_SCATTER } |
1714 | * ring->queued + txds(MAX_SCATTER) |
1715 | * <= { <1> ring->queued <= TX_RING_MAX - txds(MAX_SCATTER) } |
1716 | * TX_RING_MAX - txds(MAX_SCATTER) + txds(MAX_SCATTER) |
1717 | * <= { arithmetic } |
1718 | * TX_RING_MAX |
1719 | */ |
1720 | |
1721 | qsel = (qid < WME_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; |
1722 | |
1723 | /* first segment is TXWI + 802.11 header */ |
1724 | txd = &ring->txd[ring->cur]; |
1725 | txd->sdp0 = htole32(data->paddr); |
1726 | txd->sdl0 = htole16(sizeof (struct rt2860_txwi) + hdrlen); |
1727 | txd->flags = qsel; |
1728 | |
1729 | /* setup payload segments */ |
1730 | seg = data->map->dm_segs; |
1731 | for (nsegs = data->map->dm_nsegs; nsegs >= 2; nsegs -= 2) { |
1732 | txd->sdp1 = htole32(seg->ds_addr); |
1733 | txd->sdl1 = htole16(seg->ds_len); |
1734 | seg++; |
1735 | ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; |
1736 | /* grab a new Tx descriptor */ |
1737 | txd = &ring->txd[ring->cur]; |
1738 | txd->sdp0 = htole32(seg->ds_addr); |
1739 | txd->sdl0 = htole16(seg->ds_len); |
1740 | txd->flags = qsel; |
1741 | seg++; |
1742 | } |
1743 | /* finalize last segment */ |
1744 | if (nsegs > 0) { |
1745 | txd->sdp1 = htole32(seg->ds_addr); |
1746 | txd->sdl1 = htole16(seg->ds_len | RT2860_TX_LS1); |
1747 | } else { |
1748 | txd->sdl0 |= htole16(RT2860_TX_LS0); |
1749 | txd->sdl1 = 0; |
1750 | } |
1751 | |
1752 | /* remove from the free pool and link it into the SW Tx slot */ |
1753 | SLIST_REMOVE_HEAD(&sc->data_pool, next); |
1754 | data->m = m; |
1755 | data->ni = ni; |
1756 | ring->data[ring->cur] = data; |
1757 | |
1758 | bus_dmamap_sync(sc->sc_dmat, sc->txwi_map, |
1759 | (uintptr_t)txwi - (uintptr_t)sc->txwi_vaddr, RT2860_TXWI_DMASZ, |
1760 | BUS_DMASYNC_PREWRITE); |
1761 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize, |
1762 | BUS_DMASYNC_PREWRITE); |
1763 | bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, |
1764 | BUS_DMASYNC_PREWRITE); |
1765 | |
1766 | DPRINTFN(4, ("sending frame qid=%d wcid=%d nsegs=%d ridx=%d\n" , |
1767 | qid, txwi->wcid, data->map->dm_nsegs, ridx)); |
1768 | |
1769 | ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; |
1770 | ring->queued += 1 + (data->map->dm_nsegs / 2); |
1771 | if (ring->queued > RT2860_TX_RING_ONEMORE) |
1772 | sc->qfullmsk |= 1 << qid; |
1773 | |
1774 | /* kick Tx */ |
1775 | RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); |
1776 | |
1777 | return 0; |
1778 | } |
1779 | |
1780 | static void |
1781 | rt2860_start(struct ifnet *ifp) |
1782 | { |
1783 | struct rt2860_softc *sc = ifp->if_softc; |
1784 | struct ieee80211com *ic = &sc->sc_ic; |
1785 | struct ether_header *eh; |
1786 | struct ieee80211_node *ni; |
1787 | struct mbuf *m; |
1788 | |
1789 | if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) |
1790 | return; |
1791 | |
1792 | for (;;) { |
1793 | if (SLIST_EMPTY(&sc->data_pool) || sc->qfullmsk != 0) { |
1794 | DPRINTF(("%s: stuffup\n" , __func__)); |
1795 | ifp->if_flags |= IFF_OACTIVE; |
1796 | break; |
1797 | } |
1798 | /* send pending management frames first */ |
1799 | IF_DEQUEUE(&ic->ic_mgtq, m); |
1800 | if (m != NULL) { |
1801 | ni = M_GETCTX(m, struct ieee80211_node *); |
1802 | M_CLEARCTX(m); |
1803 | DPRINTF(("%s: send management\n" , __func__)); |
1804 | goto sendit; |
1805 | } |
1806 | if (ic->ic_state != IEEE80211_S_RUN) { |
1807 | DPRINTF(("%s: not running %d\n" , __func__, |
1808 | ic->ic_state)); |
1809 | break; |
1810 | } |
1811 | |
1812 | /* encapsulate and send data frames */ |
1813 | IFQ_DEQUEUE(&ifp->if_snd, m); |
1814 | if (m == NULL) { |
1815 | DPRINTF(("%s: nothing to send\n" , __func__)); |
1816 | break; |
1817 | } |
1818 | if (m->m_len < (int)sizeof(*eh) && |
1819 | (m = m_pullup(m, sizeof(*eh))) == NULL) { |
1820 | DPRINTF(("%s: nothing to send\n" , __func__)); |
1821 | ifp->if_oerrors++; |
1822 | continue; |
1823 | } |
1824 | |
1825 | eh = mtod(m, struct ether_header *); |
1826 | |
1827 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); |
1828 | if (ni == NULL) { |
1829 | DPRINTF(("%s: can't find tx node\n" , __func__)); |
1830 | m_freem(m); |
1831 | ifp->if_oerrors++; |
1832 | continue; |
1833 | } |
1834 | |
1835 | bpf_mtap(ifp, m); |
1836 | |
1837 | if ((m = ieee80211_encap(ic, m, ni)) == NULL) { |
1838 | DPRINTF(("%s: can't encap\n" , __func__)); |
1839 | ieee80211_free_node(ni); |
1840 | ifp->if_oerrors++; |
1841 | continue; |
1842 | } |
1843 | sendit: |
1844 | bpf_mtap3(ic->ic_rawbpf, m); |
1845 | |
1846 | if (rt2860_tx(sc, m, ni) != 0) { |
1847 | DPRINTF(("%s: can't tx\n" , __func__)); |
1848 | m_freem(m); |
1849 | ieee80211_free_node(ni); |
1850 | ifp->if_oerrors++; |
1851 | continue; |
1852 | } |
1853 | |
1854 | sc->sc_tx_timer = 5; |
1855 | ifp->if_timer = 1; |
1856 | } |
1857 | } |
1858 | |
1859 | static void |
1860 | rt2860_watchdog(struct ifnet *ifp) |
1861 | { |
1862 | struct rt2860_softc *sc = ifp->if_softc; |
1863 | struct ieee80211com *ic = &sc->sc_ic; |
1864 | |
1865 | ifp->if_timer = 0; |
1866 | |
1867 | if (sc->sc_tx_timer > 0) { |
1868 | if (--sc->sc_tx_timer == 0) { |
1869 | aprint_error_dev(sc->sc_dev, "device timeout\n" ); |
1870 | rt2860_stop(ifp, 0); |
1871 | rt2860_init(ifp); |
1872 | ifp->if_oerrors++; |
1873 | return; |
1874 | } |
1875 | ifp->if_timer = 1; |
1876 | } |
1877 | |
1878 | ieee80211_watchdog(ic); |
1879 | } |
1880 | |
1881 | static int |
1882 | rt2860_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1883 | { |
1884 | struct rt2860_softc *sc = ifp->if_softc; |
1885 | struct ieee80211com *ic = &sc->sc_ic; |
1886 | int s, error = 0; |
1887 | |
1888 | s = splnet(); |
1889 | |
1890 | switch (cmd) { |
1891 | case SIOCSIFFLAGS: |
1892 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) |
1893 | break; |
1894 | switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { |
1895 | case IFF_UP|IFF_RUNNING: |
1896 | rt2860_update_promisc(ifp); |
1897 | break; |
1898 | case IFF_UP: |
1899 | rt2860_init(ifp); |
1900 | break; |
1901 | case IFF_RUNNING: |
1902 | rt2860_stop(ifp, 1); |
1903 | break; |
1904 | case 0: |
1905 | break; |
1906 | } |
1907 | break; |
1908 | |
1909 | case SIOCADDMULTI: |
1910 | case SIOCDELMULTI: |
1911 | if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { |
1912 | /* setup multicast filter, etc */ |
1913 | error = 0; |
1914 | } |
1915 | break; |
1916 | |
1917 | case SIOCS80211CHANNEL: |
1918 | /* |
1919 | * This allows for fast channel switching in monitor mode |
1920 | * (used by kismet). In IBSS mode, we must explicitly reset |
1921 | * the interface to generate a new beacon frame. |
1922 | */ |
1923 | error = ieee80211_ioctl(ic, cmd, data); |
1924 | if (error == ENETRESET && |
1925 | ic->ic_opmode == IEEE80211_M_MONITOR) { |
1926 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == |
1927 | (IFF_UP | IFF_RUNNING)) |
1928 | rt2860_switch_chan(sc, ic->ic_ibss_chan); |
1929 | error = 0; |
1930 | } |
1931 | break; |
1932 | |
1933 | default: |
1934 | error = ieee80211_ioctl(ic, cmd, data); |
1935 | } |
1936 | |
1937 | if (error == ENETRESET) { |
1938 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == |
1939 | (IFF_UP | IFF_RUNNING)) { |
1940 | rt2860_stop(ifp, 0); |
1941 | rt2860_init(ifp); |
1942 | } |
1943 | error = 0; |
1944 | } |
1945 | |
1946 | splx(s); |
1947 | |
1948 | return error; |
1949 | } |
1950 | |
1951 | /* |
1952 | * Reading and writing from/to the BBP is different from RT2560 and RT2661. |
1953 | * We access the BBP through the 8051 microcontroller unit which means that |
1954 | * the microcode must be loaded first. |
1955 | */ |
1956 | static void |
1957 | rt2860_mcu_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) |
1958 | { |
1959 | int ntries; |
1960 | |
1961 | for (ntries = 0; ntries < 100; ntries++) { |
1962 | if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) |
1963 | break; |
1964 | DELAY(1); |
1965 | } |
1966 | if (ntries == 100) { |
1967 | aprint_error_dev(sc->sc_dev, |
1968 | "could not write to BBP through MCU\n" ); |
1969 | return; |
1970 | } |
1971 | |
1972 | RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | |
1973 | RT2860_BBP_CSR_KICK | reg << 8 | val); |
1974 | RAL_BARRIER_WRITE(sc); |
1975 | |
1976 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); |
1977 | DELAY(1000); |
1978 | } |
1979 | |
1980 | static uint8_t |
1981 | rt2860_mcu_bbp_read(struct rt2860_softc *sc, uint8_t reg) |
1982 | { |
1983 | uint32_t val; |
1984 | int ntries; |
1985 | |
1986 | for (ntries = 0; ntries < 100; ntries++) { |
1987 | if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) |
1988 | break; |
1989 | DELAY(1); |
1990 | } |
1991 | if (ntries == 100) { |
1992 | aprint_error_dev(sc->sc_dev, |
1993 | "could not read from BBP through MCU\n" ); |
1994 | return 0; |
1995 | } |
1996 | |
1997 | RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | |
1998 | RT2860_BBP_CSR_KICK | RT2860_BBP_CSR_READ | reg << 8); |
1999 | RAL_BARRIER_WRITE(sc); |
2000 | |
2001 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); |
2002 | DELAY(1000); |
2003 | |
2004 | for (ntries = 0; ntries < 100; ntries++) { |
2005 | val = RAL_READ(sc, RT2860_H2M_BBPAGENT); |
2006 | if (!(val & RT2860_BBP_CSR_KICK)) |
2007 | return val & 0xff; |
2008 | DELAY(1); |
2009 | } |
2010 | aprint_error_dev(sc->sc_dev, "could not read from BBP through MCU\n" ); |
2011 | |
2012 | return 0; |
2013 | } |
2014 | |
2015 | /* |
2016 | * Write to one of the 4 programmable 24-bit RF registers. |
2017 | */ |
2018 | static void |
2019 | rt2860_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val) |
2020 | { |
2021 | uint32_t tmp; |
2022 | int ntries; |
2023 | |
2024 | for (ntries = 0; ntries < 100; ntries++) { |
2025 | if (!(RAL_READ(sc, RT2860_RF_CSR_CFG0) & RT2860_RF_REG_CTRL)) |
2026 | break; |
2027 | DELAY(1); |
2028 | } |
2029 | if (ntries == 100) { |
2030 | aprint_error_dev(sc->sc_dev, "could not write to RF\n" ); |
2031 | return; |
2032 | } |
2033 | |
2034 | /* RF registers are 24-bit on the RT2860 */ |
2035 | tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT | |
2036 | (val & 0x3fffff) << 2 | (reg & 3); |
2037 | RAL_WRITE(sc, RT2860_RF_CSR_CFG0, tmp); |
2038 | } |
2039 | |
2040 | static uint8_t |
2041 | rt3090_rf_read(struct rt2860_softc *sc, uint8_t reg) |
2042 | { |
2043 | uint32_t tmp; |
2044 | int ntries; |
2045 | |
2046 | for (ntries = 0; ntries < 100; ntries++) { |
2047 | if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) |
2048 | break; |
2049 | DELAY(1); |
2050 | } |
2051 | if (ntries == 100) { |
2052 | aprint_error_dev(sc->sc_dev, "could not read RF register\n" ); |
2053 | return 0xff; |
2054 | } |
2055 | tmp = RT3070_RF_KICK | reg << 8; |
2056 | RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); |
2057 | |
2058 | for (ntries = 0; ntries < 100; ntries++) { |
2059 | tmp = RAL_READ(sc, RT3070_RF_CSR_CFG); |
2060 | if (!(tmp & RT3070_RF_KICK)) |
2061 | break; |
2062 | DELAY(1); |
2063 | } |
2064 | if (ntries == 100) { |
2065 | aprint_error_dev(sc->sc_dev, "could not read RF register\n" ); |
2066 | return 0xff; |
2067 | } |
2068 | return tmp & 0xff; |
2069 | } |
2070 | |
2071 | static void |
2072 | rt3090_rf_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) |
2073 | { |
2074 | uint32_t tmp; |
2075 | int ntries; |
2076 | |
2077 | for (ntries = 0; ntries < 10; ntries++) { |
2078 | if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) |
2079 | break; |
2080 | DELAY(10); |
2081 | } |
2082 | if (ntries == 10) { |
2083 | aprint_error_dev(sc->sc_dev, "could not write to RF\n" ); |
2084 | return; |
2085 | } |
2086 | |
2087 | tmp = RT3070_RF_WRITE | RT3070_RF_KICK | reg << 8 | val; |
2088 | RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); |
2089 | } |
2090 | |
2091 | /* |
2092 | * Send a command to the 8051 microcontroller unit. |
2093 | */ |
2094 | static int |
2095 | rt2860_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd, uint16_t arg, int wait) |
2096 | { |
2097 | int slot, ntries; |
2098 | uint32_t tmp; |
2099 | uint8_t cid; |
2100 | |
2101 | for (ntries = 0; ntries < 100; ntries++) { |
2102 | if (!(RAL_READ(sc, RT2860_H2M_MAILBOX) & RT2860_H2M_BUSY)) |
2103 | break; |
2104 | DELAY(2); |
2105 | } |
2106 | if (ntries == 100) |
2107 | return EIO; |
2108 | |
2109 | cid = wait ? cmd : RT2860_TOKEN_NO_INTR; |
2110 | RAL_WRITE(sc, RT2860_H2M_MAILBOX, RT2860_H2M_BUSY | cid << 16 | arg); |
2111 | RAL_BARRIER_WRITE(sc); |
2112 | RAL_WRITE(sc, RT2860_HOST_CMD, cmd); |
2113 | |
2114 | if (!wait) |
2115 | return 0; |
2116 | /* wait for the command to complete */ |
2117 | for (ntries = 0; ntries < 200; ntries++) { |
2118 | tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_CID); |
2119 | /* find the command slot */ |
2120 | for (slot = 0; slot < 4; slot++, tmp >>= 8) |
2121 | if ((tmp & 0xff) == cid) |
2122 | break; |
2123 | if (slot < 4) |
2124 | break; |
2125 | DELAY(100); |
2126 | } |
2127 | if (ntries == 200) { |
2128 | /* clear command and status */ |
2129 | RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); |
2130 | RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); |
2131 | return ETIMEDOUT; |
2132 | } |
2133 | /* get command status (1 means success) */ |
2134 | tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_STATUS); |
2135 | tmp = (tmp >> (slot * 8)) & 0xff; |
2136 | DPRINTF(("MCU command=0x%02x slot=%d status=0x%02x\n" , |
2137 | cmd, slot, tmp)); |
2138 | /* clear command and status */ |
2139 | RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); |
2140 | RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); |
2141 | return (tmp == 1) ? 0 : EIO; |
2142 | } |
2143 | |
2144 | static void |
2145 | rt2860_enable_mrr(struct rt2860_softc *sc) |
2146 | { |
2147 | #define CCK(mcs) (mcs) |
2148 | #define OFDM(mcs) (1 << 3 | (mcs)) |
2149 | RAL_WRITE(sc, RT2860_LG_FBK_CFG0, |
2150 | OFDM(6) << 28 | /* 54->48 */ |
2151 | OFDM(5) << 24 | /* 48->36 */ |
2152 | OFDM(4) << 20 | /* 36->24 */ |
2153 | OFDM(3) << 16 | /* 24->18 */ |
2154 | OFDM(2) << 12 | /* 18->12 */ |
2155 | OFDM(1) << 8 | /* 12-> 9 */ |
2156 | OFDM(0) << 4 | /* 9-> 6 */ |
2157 | OFDM(0)); /* 6-> 6 */ |
2158 | |
2159 | RAL_WRITE(sc, RT2860_LG_FBK_CFG1, |
2160 | CCK(2) << 12 | /* 11->5.5 */ |
2161 | CCK(1) << 8 | /* 5.5-> 2 */ |
2162 | CCK(0) << 4 | /* 2-> 1 */ |
2163 | CCK(0)); /* 1-> 1 */ |
2164 | #undef OFDM |
2165 | #undef CCK |
2166 | } |
2167 | |
2168 | static void |
2169 | rt2860_set_txpreamble(struct rt2860_softc *sc) |
2170 | { |
2171 | uint32_t tmp; |
2172 | |
2173 | tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); |
2174 | tmp &= ~RT2860_CCK_SHORT_EN; |
2175 | if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE) |
2176 | tmp |= RT2860_CCK_SHORT_EN; |
2177 | RAL_WRITE(sc, RT2860_AUTO_RSP_CFG, tmp); |
2178 | } |
2179 | |
2180 | static void |
2181 | rt2860_set_basicrates(struct rt2860_softc *sc) |
2182 | { |
2183 | struct ieee80211com *ic = &sc->sc_ic; |
2184 | |
2185 | /* set basic rates mask */ |
2186 | if (ic->ic_curmode == IEEE80211_MODE_11B) |
2187 | RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x003); |
2188 | else if (ic->ic_curmode == IEEE80211_MODE_11A) |
2189 | RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x150); |
2190 | else /* 11g */ |
2191 | RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x15f); |
2192 | } |
2193 | |
2194 | static void |
2195 | rt2860_select_chan_group(struct rt2860_softc *sc, int group) |
2196 | { |
2197 | uint32_t tmp; |
2198 | uint8_t agc; |
2199 | |
2200 | /* Wait for BBP to settle */ |
2201 | DELAY(1000); |
2202 | |
2203 | rt2860_mcu_bbp_write(sc, 62, 0x37 - sc->lna[group]); |
2204 | rt2860_mcu_bbp_write(sc, 63, 0x37 - sc->lna[group]); |
2205 | rt2860_mcu_bbp_write(sc, 64, 0x37 - sc->lna[group]); |
2206 | rt2860_mcu_bbp_write(sc, 86, 0x00); |
2207 | |
2208 | if (group == 0) { |
2209 | if (sc->ext_2ghz_lna) { |
2210 | rt2860_mcu_bbp_write(sc, 82, 0x62); |
2211 | rt2860_mcu_bbp_write(sc, 75, 0x46); |
2212 | } else { |
2213 | rt2860_mcu_bbp_write(sc, 82, 0x84); |
2214 | rt2860_mcu_bbp_write(sc, 75, 0x50); |
2215 | } |
2216 | } else { |
2217 | if (sc->mac_ver == 0x3572) |
2218 | rt2860_mcu_bbp_write(sc, 82, 0x94); |
2219 | else |
2220 | rt2860_mcu_bbp_write(sc, 82, 0xf2); |
2221 | |
2222 | if (sc->ext_5ghz_lna) |
2223 | rt2860_mcu_bbp_write(sc, 75, 0x46); |
2224 | else |
2225 | rt2860_mcu_bbp_write(sc, 75, 0x50); |
2226 | } |
2227 | |
2228 | tmp = RAL_READ(sc, RT2860_TX_BAND_CFG); |
2229 | tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P); |
2230 | tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P; |
2231 | RAL_WRITE(sc, RT2860_TX_BAND_CFG, tmp); |
2232 | |
2233 | /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ |
2234 | tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN; |
2235 | if (sc->nrxchains > 1) |
2236 | tmp |= RT2860_LNA_PE1_EN; |
2237 | if (sc->mac_ver == 0x3593 && sc->nrxchains > 2) |
2238 | tmp |= RT3593_LNA_PE2_EN; |
2239 | if (group == 0) { /* 2GHz */ |
2240 | tmp |= RT2860_PA_PE_G0_EN; |
2241 | if (sc->ntxchains > 1) |
2242 | tmp |= RT2860_PA_PE_G1_EN; |
2243 | if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) |
2244 | tmp |= RT3593_PA_PE_G2_EN; |
2245 | } else { /* 5GHz */ |
2246 | tmp |= RT2860_PA_PE_A0_EN; |
2247 | if (sc->ntxchains > 1) |
2248 | tmp |= RT2860_PA_PE_A1_EN; |
2249 | if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) |
2250 | tmp |= RT3593_PA_PE_A2_EN; |
2251 | } |
2252 | if (sc->mac_ver == 0x3572) { |
2253 | rt3090_rf_write(sc, 8, 0x00); |
2254 | RAL_WRITE(sc, RT2860_TX_PIN_CFG, tmp); |
2255 | rt3090_rf_write(sc, 8, 0x80); |
2256 | } else |
2257 | RAL_WRITE(sc, RT2860_TX_PIN_CFG, tmp); |
2258 | |
2259 | if (sc->mac_ver == 0x3593) { |
2260 | tmp = RAL_READ(sc, RT2860_GPIO_CTRL); |
2261 | if (sc->sc_flags & RT2860_PCIE) { |
2262 | tmp &= ~0x01010000; |
2263 | if (group == 0) |
2264 | tmp |= 0x00010000; |
2265 | } else { |
2266 | tmp &= ~0x00008080; |
2267 | if (group == 0) |
2268 | tmp |= 0x00000080; |
2269 | } |
2270 | tmp = (tmp & ~0x00001000) | 0x00000010; |
2271 | RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp); |
2272 | } |
2273 | |
2274 | /* set initial AGC value */ |
2275 | if (group == 0) { /* 2GHz band */ |
2276 | if (sc->mac_ver >= 0x3071) |
2277 | agc = 0x1c + sc->lna[0] * 2; |
2278 | else |
2279 | agc = 0x2e + sc->lna[0]; |
2280 | } else { /* 5GHz band */ |
2281 | if (sc->mac_ver == 0x3572) |
2282 | agc = 0x22 + (sc->lna[group] * 5) / 3; |
2283 | else |
2284 | agc = 0x32 + (sc->lna[group] * 5) / 3; |
2285 | } |
2286 | rt2860_mcu_bbp_write(sc, 66, agc); |
2287 | |
2288 | DELAY(1000); |
2289 | } |
2290 | |
2291 | static void |
2292 | rt2860_set_chan(struct rt2860_softc *sc, u_int chan) |
2293 | { |
2294 | const struct rfprog *rfprog = rt2860_rf2850; |
2295 | uint32_t r2, r3, r4; |
2296 | int8_t txpow1, txpow2; |
2297 | u_int i; |
2298 | |
2299 | /* find the settings for this channel (we know it exists) */ |
2300 | for (i = 0; rfprog[i].chan != chan; i++); |
2301 | |
2302 | r2 = rfprog[i].r2; |
2303 | if (sc->ntxchains == 1) |
2304 | r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ |
2305 | if (sc->nrxchains == 1) |
2306 | r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ |
2307 | else if (sc->nrxchains == 2) |
2308 | r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ |
2309 | |
2310 | /* use Tx power values from EEPROM */ |
2311 | txpow1 = sc->txpow1[i]; |
2312 | txpow2 = sc->txpow2[i]; |
2313 | if (chan > 14) { |
2314 | if (txpow1 >= 0) |
2315 | txpow1 = txpow1 << 1 | 1; |
2316 | else |
2317 | txpow1 = (7 + txpow1) << 1; |
2318 | if (txpow2 >= 0) |
2319 | txpow2 = txpow2 << 1 | 1; |
2320 | else |
2321 | txpow2 = (7 + txpow2) << 1; |
2322 | } |
2323 | r3 = rfprog[i].r3 | txpow1 << 7; |
2324 | r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4; |
2325 | |
2326 | rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); |
2327 | rt2860_rf_write(sc, RT2860_RF2, r2); |
2328 | rt2860_rf_write(sc, RT2860_RF3, r3); |
2329 | rt2860_rf_write(sc, RT2860_RF4, r4); |
2330 | |
2331 | DELAY(200); |
2332 | |
2333 | rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); |
2334 | rt2860_rf_write(sc, RT2860_RF2, r2); |
2335 | rt2860_rf_write(sc, RT2860_RF3, r3 | 1); |
2336 | rt2860_rf_write(sc, RT2860_RF4, r4); |
2337 | |
2338 | DELAY(200); |
2339 | |
2340 | rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); |
2341 | rt2860_rf_write(sc, RT2860_RF2, r2); |
2342 | rt2860_rf_write(sc, RT2860_RF3, r3); |
2343 | rt2860_rf_write(sc, RT2860_RF4, r4); |
2344 | } |
2345 | |
2346 | static void |
2347 | rt3090_set_chan(struct rt2860_softc *sc, u_int chan) |
2348 | { |
2349 | int8_t txpow1, txpow2; |
2350 | uint8_t rf; |
2351 | int i; |
2352 | |
2353 | KASSERT(chan >= 1 && chan <= 14); /* RT3090 is 2GHz only */ |
2354 | |
2355 | /* find the settings for this channel (we know it exists) */ |
2356 | for (i = 0; rt2860_rf2850[i].chan != chan; i++); |
2357 | |
2358 | /* use Tx power values from EEPROM */ |
2359 | txpow1 = sc->txpow1[i]; |
2360 | txpow2 = sc->txpow2[i]; |
2361 | |
2362 | rt3090_rf_write(sc, 2, rt3090_freqs[i].n); |
2363 | rf = rt3090_rf_read(sc, 3); |
2364 | rf = (rf & ~0x0f) | rt3090_freqs[i].k; |
2365 | rt3090_rf_write(sc, 3, rf); |
2366 | rf = rt3090_rf_read(sc, 6); |
2367 | rf = (rf & ~0x03) | rt3090_freqs[i].r; |
2368 | rt3090_rf_write(sc, 6, rf); |
2369 | |
2370 | /* set Tx0 power */ |
2371 | rf = rt3090_rf_read(sc, 12); |
2372 | rf = (rf & ~0x1f) | txpow1; |
2373 | rt3090_rf_write(sc, 12, rf); |
2374 | |
2375 | /* set Tx1 power */ |
2376 | rf = rt3090_rf_read(sc, 13); |
2377 | rf = (rf & ~0x1f) | txpow2; |
2378 | rt3090_rf_write(sc, 13, rf); |
2379 | |
2380 | rf = rt3090_rf_read(sc, 1); |
2381 | rf &= ~0xfc; |
2382 | if (sc->ntxchains == 1) |
2383 | rf |= RT3070_TX1_PD | RT3070_TX2_PD; |
2384 | else if (sc->ntxchains == 2) |
2385 | rf |= RT3070_TX2_PD; |
2386 | if (sc->nrxchains == 1) |
2387 | rf |= RT3070_RX1_PD | RT3070_RX2_PD; |
2388 | else if (sc->nrxchains == 2) |
2389 | rf |= RT3070_RX2_PD; |
2390 | rt3090_rf_write(sc, 1, rf); |
2391 | |
2392 | /* set RF offset */ |
2393 | rf = rt3090_rf_read(sc, 23); |
2394 | rf = (rf & ~0x7f) | sc->freq; |
2395 | rt3090_rf_write(sc, 23, rf); |
2396 | |
2397 | /* program RF filter */ |
2398 | rf = rt3090_rf_read(sc, 24); /* Tx */ |
2399 | rf = (rf & ~0x3f) | sc->rf24_20mhz; |
2400 | rt3090_rf_write(sc, 24, rf); |
2401 | rf = rt3090_rf_read(sc, 31); /* Rx */ |
2402 | rf = (rf & ~0x3f) | sc->rf24_20mhz; |
2403 | rt3090_rf_write(sc, 31, rf); |
2404 | |
2405 | /* enable RF tuning */ |
2406 | rf = rt3090_rf_read(sc, 7); |
2407 | rt3090_rf_write(sc, 7, rf | RT3070_TUNE); |
2408 | } |
2409 | |
2410 | static void |
2411 | rt5390_set_chan(struct rt2860_softc *sc, u_int chan) |
2412 | { |
2413 | uint8_t h20mhz, rf, tmp; |
2414 | int8_t txpow1, txpow2; |
2415 | int i; |
2416 | |
2417 | /* RT5390 is 2GHz only */ |
2418 | KASSERT(chan >= 1 && chan <= 14); |
2419 | |
2420 | /* find the settings for this channel (we know it exists) */ |
2421 | for (i = 0; rt2860_rf2850[i].chan != chan; i++); |
2422 | |
2423 | /* use Tx power values from EEPROM */ |
2424 | txpow1 = sc->txpow1[i]; |
2425 | txpow2 = sc->txpow2[i]; |
2426 | |
2427 | rt3090_rf_write(sc, 8, rt3090_freqs[i].n); |
2428 | rt3090_rf_write(sc, 9, rt3090_freqs[i].k & 0x0f); |
2429 | rf = rt3090_rf_read(sc, 11); |
2430 | rf = (rf & ~0x03) | (rt3090_freqs[i].r & 0x03); |
2431 | rt3090_rf_write(sc, 11, rf); |
2432 | |
2433 | rf = rt3090_rf_read(sc, 49); |
2434 | rf = (rf & ~0x3f) | (txpow1 & 0x3f); |
2435 | /* the valid range of the RF R49 is 0x00~0x27 */ |
2436 | if ((rf & 0x3f) > 0x27) |
2437 | rf = (rf & ~0x3f) | 0x27; |
2438 | rt3090_rf_write(sc, 49, rf); |
2439 | if (sc->mac_ver == 0x5392) { |
2440 | rf = rt3090_rf_read(sc, 50); |
2441 | rf = (rf & ~0x3f) | (txpow2 & 0x3f); |
2442 | /* the valid range of the RF R50 is 0x00~0x27 */ |
2443 | if ((rf & 0x3f) > 0x27) |
2444 | rf = (rf & ~0x3f) | 0x27; |
2445 | rt3090_rf_write(sc, 50, rf); |
2446 | } |
2447 | |
2448 | rf = rt3090_rf_read(sc, 1); |
2449 | rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD; |
2450 | if (sc->mac_ver == 0x5392) |
2451 | rf |= RT3070_RX1_PD | RT3070_TX1_PD; |
2452 | rt3090_rf_write(sc, 1, rf); |
2453 | |
2454 | rf = rt3090_rf_read(sc, 2); |
2455 | rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); |
2456 | DELAY(1000); |
2457 | rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); |
2458 | |
2459 | rf = rt3090_rf_read(sc, 17); |
2460 | tmp = rf; |
2461 | rf = (rf & ~0x7f) | (sc->freq & 0x7f); |
2462 | rf = MIN(rf, 0x5f); |
2463 | if (tmp != rf) |
2464 | rt2860_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf, 0); |
2465 | |
2466 | if (sc->mac_ver == 0x5390) { |
2467 | if (chan <= 4) |
2468 | rf = 0x73; |
2469 | else if (chan >= 5 && chan <= 6) |
2470 | rf = 0x63; |
2471 | else if (chan >= 7 && chan <= 10) |
2472 | rf = 0x53; |
2473 | else |
2474 | rf = 43; |
2475 | rt3090_rf_write(sc, 55, rf); |
2476 | |
2477 | if (chan == 1) |
2478 | rf = 0x0c; |
2479 | else if (chan == 2) |
2480 | rf = 0x0b; |
2481 | else if (chan == 3) |
2482 | rf = 0x0a; |
2483 | else if (chan >= 4 && chan <= 6) |
2484 | rf = 0x09; |
2485 | else if (chan >= 7 && chan <= 12) |
2486 | rf = 0x08; |
2487 | else if (chan == 13) |
2488 | rf = 0x07; |
2489 | else |
2490 | rf = 0x06; |
2491 | rt3090_rf_write(sc, 59, rf); |
2492 | } |
2493 | |
2494 | /* Tx/Rx h20M */ |
2495 | h20mhz = (sc->rf24_20mhz & 0x20) >> 5; |
2496 | rf = rt3090_rf_read(sc, 30); |
2497 | rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2); |
2498 | rt3090_rf_write(sc, 30, rf); |
2499 | |
2500 | /* Rx BB filter VCM */ |
2501 | rf = rt3090_rf_read(sc, 30); |
2502 | rf = (rf & ~0x18) | 0x10; |
2503 | rt3090_rf_write(sc, 30, rf); |
2504 | |
2505 | /* Initiate VCO calibration. */ |
2506 | rf = rt3090_rf_read(sc, 3); |
2507 | rf |= RT3593_VCOCAL; |
2508 | rt3090_rf_write(sc, 3, rf); |
2509 | } |
2510 | |
2511 | static void |
2512 | rt3090_rf_init(struct rt2860_softc *sc) |
2513 | { |
2514 | uint32_t tmp; |
2515 | uint8_t rf, bbp; |
2516 | int i; |
2517 | |
2518 | rf = rt3090_rf_read(sc, 30); |
2519 | /* toggle RF R30 bit 7 */ |
2520 | rt3090_rf_write(sc, 30, rf | 0x80); |
2521 | DELAY(1000); |
2522 | rt3090_rf_write(sc, 30, rf & ~0x80); |
2523 | |
2524 | tmp = RAL_READ(sc, RT3070_LDO_CFG0); |
2525 | tmp &= ~0x1f000000; |
2526 | if (sc->patch_dac && sc->mac_rev < 0x0211) |
2527 | tmp |= 0x0d000000; /* 1.35V */ |
2528 | else |
2529 | tmp |= 0x01000000; /* 1.2V */ |
2530 | RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); |
2531 | |
2532 | /* patch LNA_PE_G1 */ |
2533 | tmp = RAL_READ(sc, RT3070_GPIO_SWITCH); |
2534 | RAL_WRITE(sc, RT3070_GPIO_SWITCH, tmp & ~0x20); |
2535 | |
2536 | /* initialize RF registers to default value */ |
2537 | if (sc->mac_ver == 0x3572) { |
2538 | for (i = 0; i < (int)__arraycount(rt3572_def_rf); i++) { |
2539 | rt3090_rf_write(sc, rt3572_def_rf[i].reg, |
2540 | rt3572_def_rf[i].val); |
2541 | } |
2542 | } else { |
2543 | for (i = 0; i < (int)__arraycount(rt3090_def_rf); i++) { |
2544 | rt3090_rf_write(sc, rt3090_def_rf[i].reg, |
2545 | rt3090_def_rf[i].val); |
2546 | } |
2547 | } |
2548 | |
2549 | /* select 20MHz bandwidth */ |
2550 | rt3090_rf_write(sc, 31, 0x14); |
2551 | |
2552 | rf = rt3090_rf_read(sc, 6); |
2553 | rt3090_rf_write(sc, 6, rf | 0x40); |
2554 | |
2555 | if (sc->mac_ver != 0x3593) { |
2556 | /* calibrate filter for 20MHz bandwidth */ |
2557 | sc->rf24_20mhz = 0x1f; /* default value */ |
2558 | rt3090_filter_calib(sc, 0x07, 0x16, &sc->rf24_20mhz); |
2559 | |
2560 | /* select 40MHz bandwidth */ |
2561 | bbp = rt2860_mcu_bbp_read(sc, 4); |
2562 | rt2860_mcu_bbp_write(sc, 4, (bbp & ~0x08) | 0x10); |
2563 | rf = rt3090_rf_read(sc, 31); |
2564 | rt3090_rf_write(sc, 31, rf | 0x20); |
2565 | |
2566 | /* calibrate filter for 40MHz bandwidth */ |
2567 | sc->rf24_40mhz = 0x2f; /* default value */ |
2568 | rt3090_filter_calib(sc, 0x27, 0x19, &sc->rf24_40mhz); |
2569 | |
2570 | /* go back to 20MHz bandwidth */ |
2571 | bbp = rt2860_mcu_bbp_read(sc, 4); |
2572 | rt2860_mcu_bbp_write(sc, 4, bbp & ~0x18); |
2573 | } |
2574 | if (sc->mac_rev < 0x0211) |
2575 | rt3090_rf_write(sc, 27, 0x03); |
2576 | |
2577 | tmp = RAL_READ(sc, RT3070_OPT_14); |
2578 | RAL_WRITE(sc, RT3070_OPT_14, tmp | 1); |
2579 | |
2580 | if (sc->rf_rev == RT3070_RF_3020) |
2581 | rt3090_set_rx_antenna(sc, 0); |
2582 | |
2583 | bbp = rt2860_mcu_bbp_read(sc, 138); |
2584 | if (sc->mac_ver == 0x3593) { |
2585 | if (sc->ntxchains == 1) |
2586 | bbp |= 0x60; /* turn off DAC1 and DAC2 */ |
2587 | else if (sc->ntxchains == 2) |
2588 | bbp |= 0x40; /* turn off DAC2 */ |
2589 | if (sc->nrxchains == 1) |
2590 | bbp &= ~0x06; /* turn off ADC1 and ADC2 */ |
2591 | else if (sc->nrxchains == 2) |
2592 | bbp &= ~0x04; /* turn off ADC2 */ |
2593 | } else { |
2594 | if (sc->ntxchains == 1) |
2595 | bbp |= 0x20; /* turn off DAC1 */ |
2596 | if (sc->nrxchains == 1) |
2597 | bbp &= ~0x02; /* turn off ADC1 */ |
2598 | } |
2599 | rt2860_mcu_bbp_write(sc, 138, bbp); |
2600 | |
2601 | rf = rt3090_rf_read(sc, 1); |
2602 | rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD); |
2603 | rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD; |
2604 | rt3090_rf_write(sc, 1, rf); |
2605 | |
2606 | rf = rt3090_rf_read(sc, 15); |
2607 | rt3090_rf_write(sc, 15, rf & ~RT3070_TX_LO2); |
2608 | |
2609 | rf = rt3090_rf_read(sc, 17); |
2610 | rf &= ~RT3070_TX_LO1; |
2611 | if (sc->mac_rev >= 0x0211 && !sc->ext_2ghz_lna) |
2612 | rf |= 0x20; /* fix for long range Rx issue */ |
2613 | if (sc->txmixgain_2ghz >= 2) |
2614 | rf = (rf & ~0x7) | sc->txmixgain_2ghz; |
2615 | rt3090_rf_write(sc, 17, rf); |
2616 | |
2617 | rf = rt3090_rf_read(sc, 20); |
2618 | rt3090_rf_write(sc, 20, rf & ~RT3070_RX_LO1); |
2619 | |
2620 | rf = rt3090_rf_read(sc, 21); |
2621 | rt3090_rf_write(sc, 21, rf & ~RT3070_RX_LO2); |
2622 | } |
2623 | |
2624 | static void |
2625 | rt5390_rf_init(struct rt2860_softc *sc) |
2626 | { |
2627 | uint8_t rf, bbp; |
2628 | int i; |
2629 | |
2630 | rf = rt3090_rf_read(sc, 2); |
2631 | /* Toggle RF R2 bit 7. */ |
2632 | rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); |
2633 | DELAY(1000); |
2634 | rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); |
2635 | |
2636 | /* Initialize RF registers to default value. */ |
2637 | if (sc->mac_ver == 0x5392) { |
2638 | for (i = 0; i < __arraycount(rt5392_def_rf); i++) { |
2639 | rt3090_rf_write(sc, rt5392_def_rf[i].reg, |
2640 | rt5392_def_rf[i].val); |
2641 | } |
2642 | } else { |
2643 | for (i = 0; i < __arraycount(rt5390_def_rf); i++) { |
2644 | rt3090_rf_write(sc, rt5390_def_rf[i].reg, |
2645 | rt5390_def_rf[i].val); |
2646 | } |
2647 | } |
2648 | |
2649 | sc->rf24_20mhz = 0x1f; |
2650 | sc->rf24_40mhz = 0x2f; |
2651 | |
2652 | if (sc->mac_rev < 0x0211) |
2653 | rt3090_rf_write(sc, 27, 0x03); |
2654 | |
2655 | /* Set led open drain enable. */ |
2656 | RAL_WRITE(sc, RT3070_OPT_14, RAL_READ(sc, RT3070_OPT_14) | 1); |
2657 | |
2658 | RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); |
2659 | RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); |
2660 | |
2661 | if (sc->mac_ver == 0x5390) |
2662 | rt3090_set_rx_antenna(sc, 0); |
2663 | |
2664 | /* Patch RSSI inaccurate issue. */ |
2665 | rt2860_mcu_bbp_write(sc, 79, 0x13); |
2666 | rt2860_mcu_bbp_write(sc, 80, 0x05); |
2667 | rt2860_mcu_bbp_write(sc, 81, 0x33); |
2668 | |
2669 | /* Enable DC filter. */ |
2670 | if (sc->mac_rev >= 0x0211) |
2671 | rt2860_mcu_bbp_write(sc, 103, 0xc0); |
2672 | |
2673 | bbp = rt2860_mcu_bbp_read(sc, 138); |
2674 | if (sc->ntxchains == 1) |
2675 | bbp |= 0x20; /* Turn off DAC1. */ |
2676 | if (sc->nrxchains == 1) |
2677 | bbp &= ~0x02; /* Turn off ADC1. */ |
2678 | rt2860_mcu_bbp_write(sc, 138, bbp); |
2679 | |
2680 | /* Enable RX LO1 and LO2. */ |
2681 | rt3090_rf_write(sc, 38, rt3090_rf_read(sc, 38) & ~RT5390_RX_LO1); |
2682 | rt3090_rf_write(sc, 39, rt3090_rf_read(sc, 39) & ~RT5390_RX_LO2); |
2683 | |
2684 | /* Avoid data lost and CRC error. */ |
2685 | rt2860_mcu_bbp_write(sc, 4, |
2686 | rt2860_mcu_bbp_read(sc, 4) | RT5390_MAC_IF_CTRL); |
2687 | |
2688 | rf = rt3090_rf_read(sc, 30); |
2689 | rf = (rf & ~0x18) | 0x10; |
2690 | rt3090_rf_write(sc, 30, rf); |
2691 | } |
2692 | |
2693 | static void |
2694 | rt3090_rf_wakeup(struct rt2860_softc *sc) |
2695 | { |
2696 | uint32_t tmp; |
2697 | uint8_t rf; |
2698 | |
2699 | if (sc->mac_ver == 0x3593) { |
2700 | /* enable VCO */ |
2701 | rf = rt3090_rf_read(sc, 1); |
2702 | rt3090_rf_write(sc, 1, rf | RT3593_VCO); |
2703 | |
2704 | /* initiate VCO calibration */ |
2705 | rf = rt3090_rf_read(sc, 3); |
2706 | rt3090_rf_write(sc, 3, rf | RT3593_VCOCAL); |
2707 | |
2708 | /* enable VCO bias current control */ |
2709 | rf = rt3090_rf_read(sc, 6); |
2710 | rt3090_rf_write(sc, 6, rf | RT3593_VCO_IC); |
2711 | |
2712 | /* initiate res calibration */ |
2713 | rf = rt3090_rf_read(sc, 2); |
2714 | rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); |
2715 | |
2716 | /* set reference current control to 0.33 mA */ |
2717 | rf = rt3090_rf_read(sc, 22); |
2718 | rf &= ~RT3593_CP_IC_MASK; |
2719 | rf |= 1 << RT3593_CP_IC_SHIFT; |
2720 | rt3090_rf_write(sc, 22, rf); |
2721 | |
2722 | /* enable RX CTB */ |
2723 | rf = rt3090_rf_read(sc, 46); |
2724 | rt3090_rf_write(sc, 46, rf | RT3593_RX_CTB); |
2725 | |
2726 | rf = rt3090_rf_read(sc, 20); |
2727 | rf &= ~(RT3593_LDO_RF_VC_MASK | RT3593_LDO_PLL_VC_MASK); |
2728 | rt3090_rf_write(sc, 20, rf); |
2729 | } else { |
2730 | /* enable RF block */ |
2731 | rf = rt3090_rf_read(sc, 1); |
2732 | rt3090_rf_write(sc, 1, rf | RT3070_RF_BLOCK); |
2733 | |
2734 | /* enable VCO bias current control */ |
2735 | rf = rt3090_rf_read(sc, 7); |
2736 | rt3090_rf_write(sc, 7, rf | 0x30); |
2737 | |
2738 | rf = rt3090_rf_read(sc, 9); |
2739 | rt3090_rf_write(sc, 9, rf | 0x0e); |
2740 | |
2741 | /* enable RX CTB */ |
2742 | rf = rt3090_rf_read(sc, 21); |
2743 | rt3090_rf_write(sc, 21, rf | RT3070_RX_CTB); |
2744 | |
2745 | /* fix Tx to Rx IQ glitch by raising RF voltage */ |
2746 | rf = rt3090_rf_read(sc, 27); |
2747 | rf &= ~0x77; |
2748 | if (sc->mac_rev < 0x0211) |
2749 | rf |= 0x03; |
2750 | rt3090_rf_write(sc, 27, rf); |
2751 | } |
2752 | if (sc->patch_dac && sc->mac_rev < 0x0211) { |
2753 | tmp = RAL_READ(sc, RT3070_LDO_CFG0); |
2754 | tmp = (tmp & ~0x1f000000) | 0x0d000000; |
2755 | RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); |
2756 | } |
2757 | } |
2758 | |
2759 | static void |
2760 | rt5390_rf_wakeup(struct rt2860_softc *sc) |
2761 | { |
2762 | uint32_t tmp; |
2763 | uint8_t rf; |
2764 | |
2765 | rf = rt3090_rf_read(sc, 1); |
2766 | rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | |
2767 | RT3070_TX0_PD; |
2768 | if (sc->mac_ver == 0x5392) |
2769 | rf |= RT3070_RX1_PD | RT3070_TX1_PD; |
2770 | rt3090_rf_write(sc, 1, rf); |
2771 | |
2772 | rf = rt3090_rf_read(sc, 6); |
2773 | rf |= RT3593_VCO_IC | RT3593_VCOCAL; |
2774 | if (sc->mac_ver == 0x5390) |
2775 | rf &= ~RT3593_VCO_IC; |
2776 | rt3090_rf_write(sc, 6, rf); |
2777 | |
2778 | rt3090_rf_write(sc, 2, rt3090_rf_read(sc, 2) | RT3593_RESCAL); |
2779 | |
2780 | rf = rt3090_rf_read(sc, 22); |
2781 | rf = (rf & ~0xe0) | 0x20; |
2782 | rt3090_rf_write(sc, 22, rf); |
2783 | |
2784 | rt3090_rf_write(sc, 42, rt3090_rf_read(sc, 42) | RT5390_RX_CTB); |
2785 | rt3090_rf_write(sc, 20, rt3090_rf_read(sc, 20) & ~0x77); |
2786 | rt3090_rf_write(sc, 3, rt3090_rf_read(sc, 3) | RT3593_VCOCAL); |
2787 | |
2788 | if (sc->patch_dac && sc->mac_rev < 0x0211) { |
2789 | tmp = RAL_READ(sc, RT3070_LDO_CFG0); |
2790 | tmp = (tmp & ~0x1f000000) | 0x0d000000; |
2791 | RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); |
2792 | } |
2793 | } |
2794 | |
2795 | static int |
2796 | rt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target, |
2797 | uint8_t *val) |
2798 | { |
2799 | uint8_t rf22, rf24; |
2800 | uint8_t bbp55_pb, bbp55_sb, delta; |
2801 | int ntries; |
2802 | |
2803 | /* program filter */ |
2804 | rf24 = rt3090_rf_read(sc, 24); |
2805 | rf24 = (rf24 & 0xc0) | init; /* initial filter value */ |
2806 | rt3090_rf_write(sc, 24, rf24); |
2807 | |
2808 | /* enable baseband loopback mode */ |
2809 | rf22 = rt3090_rf_read(sc, 22); |
2810 | rt3090_rf_write(sc, 22, rf22 | RT3070_BB_LOOPBACK); |
2811 | |
2812 | /* set power and frequency of passband test tone */ |
2813 | rt2860_mcu_bbp_write(sc, 24, 0x00); |
2814 | for (ntries = 0; ntries < 100; ntries++) { |
2815 | /* transmit test tone */ |
2816 | rt2860_mcu_bbp_write(sc, 25, 0x90); |
2817 | DELAY(1000); |
2818 | /* read received power */ |
2819 | bbp55_pb = rt2860_mcu_bbp_read(sc, 55); |
2820 | if (bbp55_pb != 0) |
2821 | break; |
2822 | } |
2823 | if (ntries == 100) |
2824 | return ETIMEDOUT; |
2825 | |
2826 | /* set power and frequency of stopband test tone */ |
2827 | rt2860_mcu_bbp_write(sc, 24, 0x06); |
2828 | for (ntries = 0; ntries < 100; ntries++) { |
2829 | /* transmit test tone */ |
2830 | rt2860_mcu_bbp_write(sc, 25, 0x90); |
2831 | DELAY(1000); |
2832 | /* read received power */ |
2833 | bbp55_sb = rt2860_mcu_bbp_read(sc, 55); |
2834 | |
2835 | delta = bbp55_pb - bbp55_sb; |
2836 | if (delta > target) |
2837 | break; |
2838 | |
2839 | /* reprogram filter */ |
2840 | rf24++; |
2841 | rt3090_rf_write(sc, 24, rf24); |
2842 | } |
2843 | if (ntries < 100) { |
2844 | if (rf24 != init) |
2845 | rf24--; /* backtrack */ |
2846 | *val = rf24; |
2847 | rt3090_rf_write(sc, 24, rf24); |
2848 | } |
2849 | |
2850 | /* restore initial state */ |
2851 | rt2860_mcu_bbp_write(sc, 24, 0x00); |
2852 | |
2853 | /* disable baseband loopback mode */ |
2854 | rf22 = rt3090_rf_read(sc, 22); |
2855 | rt3090_rf_write(sc, 22, rf22 & ~RT3070_BB_LOOPBACK); |
2856 | |
2857 | return 0; |
2858 | } |
2859 | |
2860 | static void |
2861 | rt3090_rf_setup(struct rt2860_softc *sc) |
2862 | { |
2863 | uint8_t bbp; |
2864 | int i; |
2865 | |
2866 | if (sc->mac_rev >= 0x0211) { |
2867 | /* enable DC filter */ |
2868 | rt2860_mcu_bbp_write(sc, 103, 0xc0); |
2869 | |
2870 | /* improve power consumption */ |
2871 | bbp = rt2860_mcu_bbp_read(sc, 31); |
2872 | rt2860_mcu_bbp_write(sc, 31, bbp & ~0x03); |
2873 | } |
2874 | |
2875 | RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); |
2876 | if (sc->mac_rev < 0x0211) { |
2877 | RAL_WRITE(sc, RT2860_TX_SW_CFG2, |
2878 | sc->patch_dac ? 0x2c : 0x0f); |
2879 | } else |
2880 | RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); |
2881 | |
2882 | /* initialize RF registers from ROM */ |
2883 | if (sc->mac_ver < 0x5390) { |
2884 | for (i = 0; i < 10; i++) { |
2885 | if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff) |
2886 | continue; |
2887 | rt3090_rf_write(sc, sc->rf[i].reg, sc->rf[i].val); |
2888 | } |
2889 | } |
2890 | } |
2891 | |
2892 | static void |
2893 | rt2860_set_leds(struct rt2860_softc *sc, uint16_t which) |
2894 | { |
2895 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LEDS, |
2896 | which | (sc->leds & 0x7f), 0); |
2897 | } |
2898 | |
2899 | /* |
2900 | * Hardware has a general-purpose programmable timer interrupt that can |
2901 | * periodically raise MAC_INT_4. |
2902 | */ |
2903 | static void |
2904 | rt2860_set_gp_timer(struct rt2860_softc *sc, int ms) |
2905 | { |
2906 | uint32_t tmp; |
2907 | |
2908 | /* disable GP timer before reprogramming it */ |
2909 | tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); |
2910 | RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp & ~RT2860_GP_TIMER_EN); |
2911 | |
2912 | if (ms == 0) |
2913 | return; |
2914 | |
2915 | tmp = RAL_READ(sc, RT2860_INT_TIMER_CFG); |
2916 | ms *= 16; /* Unit: 64us */ |
2917 | tmp = (tmp & 0xffff) | ms << RT2860_GP_TIMER_SHIFT; |
2918 | RAL_WRITE(sc, RT2860_INT_TIMER_CFG, tmp); |
2919 | |
2920 | /* enable GP timer */ |
2921 | tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); |
2922 | RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp | RT2860_GP_TIMER_EN); |
2923 | } |
2924 | |
2925 | static void |
2926 | rt2860_set_bssid(struct rt2860_softc *sc, const uint8_t *bssid) |
2927 | { |
2928 | RAL_WRITE(sc, RT2860_MAC_BSSID_DW0, |
2929 | bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24); |
2930 | RAL_WRITE(sc, RT2860_MAC_BSSID_DW1, |
2931 | bssid[4] | bssid[5] << 8); |
2932 | } |
2933 | |
2934 | static void |
2935 | rt2860_set_macaddr(struct rt2860_softc *sc, const uint8_t *addr) |
2936 | { |
2937 | RAL_WRITE(sc, RT2860_MAC_ADDR_DW0, |
2938 | addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); |
2939 | RAL_WRITE(sc, RT2860_MAC_ADDR_DW1, |
2940 | addr[4] | addr[5] << 8 | 0xff << 16); |
2941 | } |
2942 | |
2943 | static void |
2944 | rt2860_updateslot(struct ifnet *ifp) |
2945 | { |
2946 | struct rt2860_softc *sc = ifp->if_softc; |
2947 | struct ieee80211com *ic = &sc->sc_ic; |
2948 | uint32_t tmp; |
2949 | |
2950 | tmp = RAL_READ(sc, RT2860_BKOFF_SLOT_CFG); |
2951 | tmp &= ~0xff; |
2952 | tmp |= (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; |
2953 | RAL_WRITE(sc, RT2860_BKOFF_SLOT_CFG, tmp); |
2954 | } |
2955 | |
2956 | static void |
2957 | rt2860_updateprot(struct ieee80211com *ic) |
2958 | { |
2959 | struct rt2860_softc *sc = ic->ic_ifp->if_softc; |
2960 | uint32_t tmp; |
2961 | |
2962 | tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; |
2963 | /* setup protection frame rate (MCS code) */ |
2964 | tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ? |
2965 | rt2860_rates[RT2860_RIDX_OFDM6].mcs : |
2966 | rt2860_rates[RT2860_RIDX_CCK11].mcs; |
2967 | |
2968 | /* CCK frames don't require protection */ |
2969 | RAL_WRITE(sc, RT2860_CCK_PROT_CFG, tmp); |
2970 | |
2971 | if (ic->ic_flags & IEEE80211_F_USEPROT) { |
2972 | if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) |
2973 | tmp |= RT2860_PROT_CTRL_RTS_CTS; |
2974 | else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) |
2975 | tmp |= RT2860_PROT_CTRL_CTS; |
2976 | } |
2977 | RAL_WRITE(sc, RT2860_OFDM_PROT_CFG, tmp); |
2978 | } |
2979 | |
2980 | static void |
2981 | rt2860_update_promisc(struct ifnet *ifp) |
2982 | { |
2983 | struct rt2860_softc *sc = ifp->if_softc; |
2984 | uint32_t tmp; |
2985 | |
2986 | tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); |
2987 | tmp &= ~RT2860_DROP_NOT_MYBSS; |
2988 | if (!(ifp->if_flags & IFF_PROMISC)) |
2989 | tmp |= RT2860_DROP_NOT_MYBSS; |
2990 | RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); |
2991 | } |
2992 | |
2993 | static int |
2994 | rt2860_updateedca(struct ieee80211com *ic) |
2995 | { |
2996 | struct rt2860_softc *sc = ic->ic_ifp->if_softc; |
2997 | int aci; |
2998 | |
2999 | /* update MAC TX configuration registers */ |
3000 | for (aci = 0; aci < WME_NUM_AC; aci++) { |
3001 | RAL_WRITE(sc, RT2860_EDCA_AC_CFG(aci), |
3002 | ic->ic_wme.wme_params[aci].wmep_logcwmax << 16 | |
3003 | ic->ic_wme.wme_params[aci].wmep_logcwmin << 12 | |
3004 | ic->ic_wme.wme_params[aci].wmep_aifsn << 8 | |
3005 | ic->ic_wme.wme_params[aci].wmep_txopLimit); |
3006 | } |
3007 | |
3008 | /* update SCH/DMA registers too */ |
3009 | RAL_WRITE(sc, RT2860_WMM_AIFSN_CFG, |
3010 | ic->ic_wme.wme_params[WME_AC_VO].wmep_aifsn << 12 | |
3011 | ic->ic_wme.wme_params[WME_AC_VI].wmep_aifsn << 8 | |
3012 | ic->ic_wme.wme_params[WME_AC_BK].wmep_aifsn << 4 | |
3013 | ic->ic_wme.wme_params[WME_AC_BE].wmep_aifsn); |
3014 | RAL_WRITE(sc, RT2860_WMM_CWMIN_CFG, |
3015 | ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmin << 12 | |
3016 | ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmin << 8 | |
3017 | ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmin << 4 | |
3018 | ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmin); |
3019 | RAL_WRITE(sc, RT2860_WMM_CWMAX_CFG, |
3020 | ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmax << 12 | |
3021 | ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmax << 8 | |
3022 | ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmax << 4 | |
3023 | ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmax); |
3024 | RAL_WRITE(sc, RT2860_WMM_TXOP0_CFG, |
3025 | ic->ic_wme.wme_params[WME_AC_BK].wmep_txopLimit << 16 | |
3026 | ic->ic_wme.wme_params[WME_AC_BE].wmep_txopLimit); |
3027 | RAL_WRITE(sc, RT2860_WMM_TXOP1_CFG, |
3028 | ic->ic_wme.wme_params[WME_AC_VO].wmep_txopLimit << 16 | |
3029 | ic->ic_wme.wme_params[WME_AC_VI].wmep_txopLimit); |
3030 | return 0; |
3031 | } |
3032 | |
3033 | #ifdef HW_CRYPTO |
3034 | static int |
3035 | rt2860_set_key(struct ieee80211com *ic, const struct ieee80211_key *ck, |
3036 | const uint8_t *mac) |
3037 | { |
3038 | struct rt2860_softc *sc = ic->ic_ifp->if_softc; |
3039 | struct ieee80211_node *ni = ic->ic_bss; |
3040 | bus_size_t base; |
3041 | uint32_t attr; |
3042 | uint8_t mode, wcid, iv[8]; |
3043 | struct ieee80211_key *k = __UNCONST(ck); /* XXX */ |
3044 | |
3045 | DPRINTF(("%s: cipher %d\n" , __func__, k->wk_cipher->ic_cipher)); |
3046 | /* defer setting of WEP keys until interface is brought up */ |
3047 | if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) != |
3048 | (IFF_UP | IFF_RUNNING)) { |
3049 | DPRINTF(("%s: not running %d\n" , __func__, |
3050 | k->wk_cipher->ic_cipher)); |
3051 | return 1; |
3052 | } |
3053 | /* map net80211 cipher to RT2860 security mode */ |
3054 | switch (k->wk_cipher->ic_cipher) { |
3055 | case IEEE80211_CIPHER_WEP: |
3056 | k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */ |
3057 | if (k->wk_keylen == 5) |
3058 | mode = RT2860_MODE_WEP40; |
3059 | else |
3060 | mode = RT2860_MODE_WEP104; |
3061 | break; |
3062 | case IEEE80211_CIPHER_TKIP: |
3063 | mode = RT2860_MODE_TKIP; |
3064 | break; |
3065 | case IEEE80211_CIPHER_AES_CCM: |
3066 | mode = RT2860_MODE_AES_CCMP; |
3067 | break; |
3068 | default: |
3069 | DPRINTF(("%s: bad\n" , __func__)); |
3070 | return 0; |
3071 | } |
3072 | |
3073 | if (k->wk_flags & IEEE80211_KEY_GROUP) { |
3074 | wcid = 0; /* NB: update WCID0 for group keys */ |
3075 | base = RT2860_SKEY(0, k->wk_keyix); |
3076 | } else { |
3077 | wcid = ((struct rt2860_node *)ni)->wcid; |
3078 | base = RT2860_PKEY(wcid); |
3079 | } |
3080 | |
3081 | if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { |
3082 | RAL_WRITE_REGION_1(sc, base, k->wk_key, 16); |
3083 | #ifndef IEEE80211_STA_ONLY |
3084 | if (ic->ic_opmode == IEEE80211_M_HOSTAP) { |
3085 | RAL_WRITE_REGION_1(sc, base + 16, &k->wk_key[16], 8); |
3086 | RAL_WRITE_REGION_1(sc, base + 24, &k->wk_key[24], 8); |
3087 | } else |
3088 | #endif |
3089 | { |
3090 | RAL_WRITE_REGION_1(sc, base + 16, &k->wk_key[24], 8); |
3091 | RAL_WRITE_REGION_1(sc, base + 24, &k->wk_key[16], 8); |
3092 | } |
3093 | } else |
3094 | RAL_WRITE_REGION_1(sc, base, k->wk_key, k->wk_keylen); |
3095 | |
3096 | if (!(k->wk_flags & IEEE80211_KEY_GROUP) || |
3097 | (k->wk_flags & IEEE80211_KEY_XMIT)) { |
3098 | /* set initial packet number in IV+EIV */ |
3099 | if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) { |
3100 | uint32_t val = cprng_fast32(); |
3101 | /* skip weak IVs from Fluhrer/Mantin/Shamir */ |
3102 | if (val >= 0x03ff00 && (val & 0xf8ff00) == 0x00ff00) |
3103 | val += 0x000100; |
3104 | iv[0] = val; |
3105 | iv[1] = val >> 8; |
3106 | iv[2] = val >> 16; |
3107 | iv[3] = k->wk_keyix << 6; |
3108 | iv[4] = iv[5] = iv[6] = iv[7] = 0; |
3109 | } else { |
3110 | if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { |
3111 | iv[0] = k->wk_keytsc >> 8; |
3112 | iv[1] = (iv[0] | 0x20) & 0x7f; |
3113 | iv[2] = k->wk_keytsc; |
3114 | } else /* CCMP */ { |
3115 | iv[0] = k->wk_keytsc; |
3116 | iv[1] = k->wk_keytsc >> 8; |
3117 | iv[2] = 0; |
3118 | } |
3119 | iv[3] = k->wk_keyix << 6 | IEEE80211_WEP_EXTIV; |
3120 | iv[4] = k->wk_keytsc >> 16; |
3121 | iv[5] = k->wk_keytsc >> 24; |
3122 | iv[6] = k->wk_keytsc >> 32; |
3123 | iv[7] = k->wk_keytsc >> 40; |
3124 | } |
3125 | RAL_WRITE_REGION_1(sc, RT2860_IVEIV(wcid), iv, 8); |
3126 | } |
3127 | |
3128 | if (k->wk_flags & IEEE80211_KEY_GROUP) { |
3129 | /* install group key */ |
3130 | attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); |
3131 | attr &= ~(0xf << (k->wk_keyix * 4)); |
3132 | attr |= mode << (k->wk_keyix * 4); |
3133 | RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); |
3134 | } else { |
3135 | /* install pairwise key */ |
3136 | attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); |
3137 | attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN; |
3138 | RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); |
3139 | } |
3140 | DPRINTF(("%s: ok\n" , __func__)); |
3141 | return 1; |
3142 | } |
3143 | |
3144 | static int |
3145 | rt2860_delete_key(struct ieee80211com *ic, const struct ieee80211_key *k) |
3146 | { |
3147 | struct rt2860_softc *sc = ic->ic_ifp->if_softc; |
3148 | struct ieee80211_node *ni = ic->ic_bss; |
3149 | uint32_t attr; |
3150 | uint8_t wcid; |
3151 | |
3152 | if (k->wk_flags & IEEE80211_KEY_GROUP) { |
3153 | /* remove group key */ |
3154 | attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); |
3155 | attr &= ~(0xf << (k->wk_keyix * 4)); |
3156 | RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); |
3157 | |
3158 | } else { |
3159 | /* remove pairwise key */ |
3160 | wcid = ((struct rt2860_node *)ni)->wcid; |
3161 | attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); |
3162 | attr &= ~0xf; |
3163 | RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); |
3164 | } |
3165 | return 1; |
3166 | } |
3167 | #endif |
3168 | |
3169 | static int8_t |
3170 | (struct rt2860_softc *sc, uint8_t , uint8_t rxchain) |
3171 | { |
3172 | struct ieee80211com *ic = &sc->sc_ic; |
3173 | struct ieee80211_channel *c = ic->ic_curchan; |
3174 | int delta; |
3175 | |
3176 | if (IEEE80211_IS_CHAN_5GHZ(c)) { |
3177 | u_int chan = ieee80211_chan2ieee(ic, c); |
3178 | delta = sc->rssi_5ghz[rxchain]; |
3179 | |
3180 | /* determine channel group */ |
3181 | if (chan <= 64) |
3182 | delta -= sc->lna[1]; |
3183 | else if (chan <= 128) |
3184 | delta -= sc->lna[2]; |
3185 | else |
3186 | delta -= sc->lna[3]; |
3187 | } else |
3188 | delta = sc->rssi_2ghz[rxchain] - sc->lna[0]; |
3189 | |
3190 | return -12 - delta - rssi; |
3191 | } |
3192 | |
3193 | /* |
3194 | * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. |
3195 | * Used to adjust per-rate Tx power registers. |
3196 | */ |
3197 | static __inline uint32_t |
3198 | b4inc(uint32_t b32, int8_t delta) |
3199 | { |
3200 | int8_t i, b4; |
3201 | |
3202 | for (i = 0; i < 8; i++) { |
3203 | b4 = b32 & 0xf; |
3204 | b4 += delta; |
3205 | if (b4 < 0) |
3206 | b4 = 0; |
3207 | else if (b4 > 0xf) |
3208 | b4 = 0xf; |
3209 | b32 = b32 >> 4 | b4 << 28; |
3210 | } |
3211 | return b32; |
3212 | } |
3213 | |
3214 | static const char * |
3215 | rt2860_get_rf(uint32_t rev) |
3216 | { |
3217 | switch (rev) { |
3218 | case RT2860_RF_2820: return "RT2820" ; |
3219 | case RT2860_RF_2850: return "RT2850" ; |
3220 | case RT2860_RF_2720: return "RT2720" ; |
3221 | case RT2860_RF_2750: return "RT2750" ; |
3222 | case RT3070_RF_3020: return "RT3020" ; |
3223 | case RT3070_RF_2020: return "RT2020" ; |
3224 | case RT3070_RF_3021: return "RT3021" ; |
3225 | case RT3070_RF_3022: return "RT3022" ; |
3226 | case RT3070_RF_3052: return "RT3052" ; |
3227 | case RT3070_RF_3320: return "RT3320" ; |
3228 | case RT3070_RF_3053: return "RT3053" ; |
3229 | case RT5390_RF_5360: return "RT5360" ; |
3230 | case RT5390_RF_5390: return "RT5390" ; |
3231 | case RT5390_RF_5392: return "RT5392" ; |
3232 | default: return "unknown" ; |
3233 | } |
3234 | } |
3235 | |
3236 | static int |
3237 | rt2860_read_eeprom(struct rt2860_softc *sc) |
3238 | { |
3239 | struct ieee80211com *ic = &sc->sc_ic; |
3240 | int8_t delta_2ghz, delta_5ghz; |
3241 | uint32_t tmp; |
3242 | uint16_t val; |
3243 | int ridx, ant, i; |
3244 | |
3245 | /* check whether the ROM is eFUSE ROM or EEPROM */ |
3246 | sc->sc_srom_read = rt2860_eeprom_read_2; |
3247 | if (sc->mac_ver >= 0x3071) { |
3248 | tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); |
3249 | DPRINTF(("EFUSE_CTRL=0x%08x\n" , tmp)); |
3250 | if (tmp & RT3070_SEL_EFUSE) |
3251 | sc->sc_srom_read = rt3090_efuse_read_2; |
3252 | } |
3253 | |
3254 | #ifdef RAL_DEBUG |
3255 | /* read EEPROM version */ |
3256 | val = rt2860_srom_read(sc, RT2860_EEPROM_VERSION); |
3257 | DPRINTF(("EEPROM rev=%d, FAE=%d\n" , val & 0xff, val >> 8)); |
3258 | #endif |
3259 | |
3260 | /* read MAC address */ |
3261 | val = rt2860_srom_read(sc, RT2860_EEPROM_MAC01); |
3262 | ic->ic_myaddr[0] = val & 0xff; |
3263 | ic->ic_myaddr[1] = val >> 8; |
3264 | val = rt2860_srom_read(sc, RT2860_EEPROM_MAC23); |
3265 | ic->ic_myaddr[2] = val & 0xff; |
3266 | ic->ic_myaddr[3] = val >> 8; |
3267 | val = rt2860_srom_read(sc, RT2860_EEPROM_MAC45); |
3268 | ic->ic_myaddr[4] = val & 0xff; |
3269 | ic->ic_myaddr[5] = val >> 8; |
3270 | |
3271 | #ifdef RAL_DEBUG |
3272 | /* read country code */ |
3273 | val = rt2860_srom_read(sc, RT2860_EEPROM_COUNTRY); |
3274 | DPRINTF(("EEPROM region code=0x%04x\n" , val)); |
3275 | #endif |
3276 | |
3277 | /* read vendor BBP settings */ |
3278 | for (i = 0; i < 8; i++) { |
3279 | val = rt2860_srom_read(sc, RT2860_EEPROM_BBP_BASE + i); |
3280 | sc->bbp[i].val = val & 0xff; |
3281 | sc->bbp[i].reg = val >> 8; |
3282 | DPRINTF(("BBP%d=0x%02x\n" , sc->bbp[i].reg, sc->bbp[i].val)); |
3283 | } |
3284 | if (sc->mac_ver >= 0x3071) { |
3285 | /* read vendor RF settings */ |
3286 | for (i = 0; i < 10; i++) { |
3287 | val = rt2860_srom_read(sc, RT3071_EEPROM_RF_BASE + i); |
3288 | sc->rf[i].val = val & 0xff; |
3289 | sc->rf[i].reg = val >> 8; |
3290 | DPRINTF(("RF%d=0x%02x\n" , sc->rf[i].reg, |
3291 | sc->rf[i].val)); |
3292 | } |
3293 | } |
3294 | |
3295 | /* read RF frequency offset from EEPROM */ |
3296 | val = rt2860_srom_read(sc, RT2860_EEPROM_FREQ_LEDS); |
3297 | sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; |
3298 | DPRINTF(("EEPROM freq offset %d\n" , sc->freq & 0xff)); |
3299 | if ((val >> 8) != 0xff) { |
3300 | /* read LEDs operating mode */ |
3301 | sc->leds = val >> 8; |
3302 | sc->led[0] = rt2860_srom_read(sc, RT2860_EEPROM_LED1); |
3303 | sc->led[1] = rt2860_srom_read(sc, RT2860_EEPROM_LED2); |
3304 | sc->led[2] = rt2860_srom_read(sc, RT2860_EEPROM_LED3); |
3305 | } else { |
3306 | /* broken EEPROM, use default settings */ |
3307 | sc->leds = 0x01; |
3308 | sc->led[0] = 0x5555; |
3309 | sc->led[1] = 0x2221; |
3310 | sc->led[2] = 0xa9f8; |
3311 | } |
3312 | DPRINTF(("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n" , |
3313 | sc->leds, sc->led[0], sc->led[1], sc->led[2])); |
3314 | |
3315 | /* read RF information */ |
3316 | val = rt2860_srom_read(sc, RT2860_EEPROM_ANTENNA); |
3317 | if (sc->mac_ver >= 0x5390) |
3318 | sc->rf_rev = rt2860_srom_read(sc, RT2860_EEPROM_CHIPID); |
3319 | else |
3320 | sc->rf_rev = (val >> 8) & 0xf; |
3321 | sc->ntxchains = (val >> 4) & 0xf; |
3322 | sc->nrxchains = val & 0xf; |
3323 | DPRINTF(("EEPROM RF rev=0x%02x chains=%dT%dR\n" , |
3324 | sc->rf_rev, sc->ntxchains, sc->nrxchains)); |
3325 | |
3326 | /* check if RF supports automatic Tx access gain control */ |
3327 | val = rt2860_srom_read(sc, RT2860_EEPROM_CONFIG); |
3328 | DPRINTF(("EEPROM CFG 0x%04x\n" , val)); |
3329 | /* check if driver should patch the DAC issue */ |
3330 | if ((val >> 8) != 0xff) |
3331 | sc->patch_dac = (val >> 15) & 1; |
3332 | if ((val & 0xff) != 0xff) { |
3333 | sc->ext_5ghz_lna = (val >> 3) & 1; |
3334 | sc->ext_2ghz_lna = (val >> 2) & 1; |
3335 | /* check if RF supports automatic Tx access gain control */ |
3336 | sc->calib_2ghz = sc->calib_5ghz = 0; /* XXX (val >> 1) & 1 */ |
3337 | /* check if we have a hardware radio switch */ |
3338 | sc->rfswitch = val & 1; |
3339 | } |
3340 | if (sc->sc_flags & RT2860_ADVANCED_PS) { |
3341 | /* read PCIe power save level */ |
3342 | val = rt2860_srom_read(sc, RT2860_EEPROM_PCIE_PSLEVEL); |
3343 | if ((val & 0xff) != 0xff) { |
3344 | sc->pslevel = val & 0x3; |
3345 | val = rt2860_srom_read(sc, RT2860_EEPROM_REV); |
3346 | if ((val & 0xff80) != 0x9280) |
3347 | sc->pslevel = MIN(sc->pslevel, 1); |
3348 | DPRINTF(("EEPROM PCIe PS Level=%d\n" , sc->pslevel)); |
3349 | } |
3350 | } |
3351 | |
3352 | /* read power settings for 2GHz channels */ |
3353 | for (i = 0; i < 14; i += 2) { |
3354 | val = rt2860_srom_read(sc, |
3355 | RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2); |
3356 | sc->txpow1[i + 0] = (int8_t)(val & 0xff); |
3357 | sc->txpow1[i + 1] = (int8_t)(val >> 8); |
3358 | |
3359 | if (sc->mac_ver != 0x5390) { |
3360 | val = rt2860_srom_read(sc, |
3361 | RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2); |
3362 | sc->txpow2[i + 0] = (int8_t)(val & 0xff); |
3363 | sc->txpow2[i + 1] = (int8_t)(val >> 8); |
3364 | } |
3365 | } |
3366 | /* fix broken Tx power entries */ |
3367 | for (i = 0; i < 14; i++) { |
3368 | if (sc->txpow1[i] < 0 || |
3369 | sc->txpow1[i] > ((sc->mac_ver >= 0x5390) ? 39 : 31)) |
3370 | sc->txpow1[i] = 5; |
3371 | if (sc->mac_ver != 0x5390) { |
3372 | if (sc->txpow2[i] < 0 || |
3373 | sc->txpow2[i] > ((sc->mac_ver >= 0x5392) ? 39 : 31)) |
3374 | sc->txpow2[i] = 5; |
3375 | } |
3376 | DPRINTF(("chan %d: power1=%d, power2=%d\n" , |
3377 | rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i])); |
3378 | } |
3379 | /* read power settings for 5GHz channels */ |
3380 | for (i = 0; i < 40; i += 2) { |
3381 | val = rt2860_srom_read(sc, |
3382 | RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2); |
3383 | sc->txpow1[i + 14] = (int8_t)(val & 0xff); |
3384 | sc->txpow1[i + 15] = (int8_t)(val >> 8); |
3385 | |
3386 | val = rt2860_srom_read(sc, |
3387 | RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2); |
3388 | sc->txpow2[i + 14] = (int8_t)(val & 0xff); |
3389 | sc->txpow2[i + 15] = (int8_t)(val >> 8); |
3390 | } |
3391 | /* fix broken Tx power entries */ |
3392 | for (i = 0; i < 40; i++) { |
3393 | if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) |
3394 | sc->txpow1[14 + i] = 5; |
3395 | if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) |
3396 | sc->txpow2[14 + i] = 5; |
3397 | DPRINTF(("chan %d: power1=%d, power2=%d\n" , |
3398 | rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], |
3399 | sc->txpow2[14 + i])); |
3400 | } |
3401 | |
3402 | /* read Tx power compensation for each Tx rate */ |
3403 | val = rt2860_srom_read(sc, RT2860_EEPROM_DELTAPWR); |
3404 | delta_2ghz = delta_5ghz = 0; |
3405 | if ((val & 0xff) != 0xff && (val & 0x80)) { |
3406 | delta_2ghz = val & 0xf; |
3407 | if (!(val & 0x40)) /* negative number */ |
3408 | delta_2ghz = -delta_2ghz; |
3409 | } |
3410 | val >>= 8; |
3411 | if ((val & 0xff) != 0xff && (val & 0x80)) { |
3412 | delta_5ghz = val & 0xf; |
3413 | if (!(val & 0x40)) /* negative number */ |
3414 | delta_5ghz = -delta_5ghz; |
3415 | } |
3416 | DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n" , |
3417 | delta_2ghz, delta_5ghz)); |
3418 | |
3419 | for (ridx = 0; ridx < 5; ridx++) { |
3420 | uint32_t reg; |
3421 | |
3422 | val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2); |
3423 | reg = val; |
3424 | val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1); |
3425 | reg |= (uint32_t)val << 16; |
3426 | |
3427 | sc->txpow20mhz[ridx] = reg; |
3428 | sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); |
3429 | sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); |
3430 | |
3431 | DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " |
3432 | "40MHz/5GHz=0x%08x\n" , ridx, sc->txpow20mhz[ridx], |
3433 | sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx])); |
3434 | } |
3435 | |
3436 | /* read factory-calibrated samples for temperature compensation */ |
3437 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_2GHZ); |
3438 | sc->tssi_2ghz[0] = val & 0xff; /* [-4] */ |
3439 | sc->tssi_2ghz[1] = val >> 8; /* [-3] */ |
3440 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_2GHZ); |
3441 | sc->tssi_2ghz[2] = val & 0xff; /* [-2] */ |
3442 | sc->tssi_2ghz[3] = val >> 8; /* [-1] */ |
3443 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_2GHZ); |
3444 | sc->tssi_2ghz[4] = val & 0xff; /* [+0] */ |
3445 | sc->tssi_2ghz[5] = val >> 8; /* [+1] */ |
3446 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_2GHZ); |
3447 | sc->tssi_2ghz[6] = val & 0xff; /* [+2] */ |
3448 | sc->tssi_2ghz[7] = val >> 8; /* [+3] */ |
3449 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_2GHZ); |
3450 | sc->tssi_2ghz[8] = val & 0xff; /* [+4] */ |
3451 | sc->step_2ghz = val >> 8; |
3452 | DPRINTF(("TSSI 2GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " |
3453 | "0x%02x 0x%02x step=%d\n" , sc->tssi_2ghz[0], sc->tssi_2ghz[1], |
3454 | sc->tssi_2ghz[2], sc->tssi_2ghz[3], sc->tssi_2ghz[4], |
3455 | sc->tssi_2ghz[5], sc->tssi_2ghz[6], sc->tssi_2ghz[7], |
3456 | sc->tssi_2ghz[8], sc->step_2ghz)); |
3457 | /* check that ref value is correct, otherwise disable calibration */ |
3458 | if (sc->tssi_2ghz[4] == 0xff) |
3459 | sc->calib_2ghz = 0; |
3460 | |
3461 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_5GHZ); |
3462 | sc->tssi_5ghz[0] = val & 0xff; /* [-4] */ |
3463 | sc->tssi_5ghz[1] = val >> 8; /* [-3] */ |
3464 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_5GHZ); |
3465 | sc->tssi_5ghz[2] = val & 0xff; /* [-2] */ |
3466 | sc->tssi_5ghz[3] = val >> 8; /* [-1] */ |
3467 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_5GHZ); |
3468 | sc->tssi_5ghz[4] = val & 0xff; /* [+0] */ |
3469 | sc->tssi_5ghz[5] = val >> 8; /* [+1] */ |
3470 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_5GHZ); |
3471 | sc->tssi_5ghz[6] = val & 0xff; /* [+2] */ |
3472 | sc->tssi_5ghz[7] = val >> 8; /* [+3] */ |
3473 | val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_5GHZ); |
3474 | sc->tssi_5ghz[8] = val & 0xff; /* [+4] */ |
3475 | sc->step_5ghz = val >> 8; |
3476 | DPRINTF(("TSSI 5GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " |
3477 | "0x%02x 0x%02x step=%d\n" , sc->tssi_5ghz[0], sc->tssi_5ghz[1], |
3478 | sc->tssi_5ghz[2], sc->tssi_5ghz[3], sc->tssi_5ghz[4], |
3479 | sc->tssi_5ghz[5], sc->tssi_5ghz[6], sc->tssi_5ghz[7], |
3480 | sc->tssi_5ghz[8], sc->step_5ghz)); |
3481 | /* check that ref value is correct, otherwise disable calibration */ |
3482 | if (sc->tssi_5ghz[4] == 0xff) |
3483 | sc->calib_5ghz = 0; |
3484 | |
3485 | /* read RSSI offsets and LNA gains from EEPROM */ |
3486 | val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ); |
3487 | sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ |
3488 | sc->rssi_2ghz[1] = val >> 8; /* Ant B */ |
3489 | val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ); |
3490 | if (sc->mac_ver >= 0x3071) { |
3491 | /* |
3492 | * On RT3090 chips (limited to 2 Rx chains), this ROM |
3493 | * field contains the Tx mixer gain for the 2GHz band. |
3494 | */ |
3495 | if ((val & 0xff) != 0xff) |
3496 | sc->txmixgain_2ghz = val & 0x7; |
3497 | DPRINTF(("tx mixer gain=%u (2GHz)\n" , sc->txmixgain_2ghz)); |
3498 | } else |
3499 | sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ |
3500 | sc->lna[2] = val >> 8; /* channel group 2 */ |
3501 | |
3502 | val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ); |
3503 | sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ |
3504 | sc->rssi_5ghz[1] = val >> 8; /* Ant B */ |
3505 | val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ); |
3506 | sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ |
3507 | sc->lna[3] = val >> 8; /* channel group 3 */ |
3508 | |
3509 | val = rt2860_srom_read(sc, RT2860_EEPROM_LNA); |
3510 | if (sc->mac_ver >= 0x3071) |
3511 | sc->lna[0] = RT3090_DEF_LNA; |
3512 | else /* channel group 0 */ |
3513 | sc->lna[0] = val & 0xff; |
3514 | sc->lna[1] = val >> 8; /* channel group 1 */ |
3515 | |
3516 | /* fix broken 5GHz LNA entries */ |
3517 | if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { |
3518 | DPRINTF(("invalid LNA for channel group %d\n" , 2)); |
3519 | sc->lna[2] = sc->lna[1]; |
3520 | } |
3521 | if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { |
3522 | DPRINTF(("invalid LNA for channel group %d\n" , 3)); |
3523 | sc->lna[3] = sc->lna[1]; |
3524 | } |
3525 | |
3526 | /* fix broken RSSI offset entries */ |
3527 | for (ant = 0; ant < 3; ant++) { |
3528 | if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { |
3529 | DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n" , |
3530 | ant + 1, sc->rssi_2ghz[ant])); |
3531 | sc->rssi_2ghz[ant] = 0; |
3532 | } |
3533 | if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { |
3534 | DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n" , |
3535 | ant + 1, sc->rssi_5ghz[ant])); |
3536 | sc->rssi_5ghz[ant] = 0; |
3537 | } |
3538 | } |
3539 | |
3540 | return 0; |
3541 | } |
3542 | |
3543 | static int |
3544 | rt2860_bbp_init(struct rt2860_softc *sc) |
3545 | { |
3546 | int i, ntries; |
3547 | |
3548 | /* wait for BBP to wake up */ |
3549 | for (ntries = 0; ntries < 20; ntries++) { |
3550 | uint8_t bbp0 = rt2860_mcu_bbp_read(sc, 0); |
3551 | if (bbp0 != 0 && bbp0 != 0xff) |
3552 | break; |
3553 | } |
3554 | if (ntries == 20) { |
3555 | aprint_error_dev(sc->sc_dev, |
3556 | "timeout waiting for BBP to wake up\n" ); |
3557 | return ETIMEDOUT; |
3558 | } |
3559 | |
3560 | /* initialize BBP registers to default values */ |
3561 | if (sc->mac_ver >= 0x5390) |
3562 | rt5390_bbp_init(sc); |
3563 | else { |
3564 | for (i = 0; i < (int)__arraycount(rt2860_def_bbp); i++) { |
3565 | rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg, |
3566 | rt2860_def_bbp[i].val); |
3567 | } |
3568 | } |
3569 | |
3570 | /* fix BBP84 for RT2860E */ |
3571 | if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101) |
3572 | rt2860_mcu_bbp_write(sc, 84, 0x19); |
3573 | |
3574 | if (sc->mac_ver >= 0x3071) { |
3575 | rt2860_mcu_bbp_write(sc, 79, 0x13); |
3576 | rt2860_mcu_bbp_write(sc, 80, 0x05); |
3577 | rt2860_mcu_bbp_write(sc, 81, 0x33); |
3578 | } else if (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) { |
3579 | rt2860_mcu_bbp_write(sc, 69, 0x16); |
3580 | rt2860_mcu_bbp_write(sc, 73, 0x12); |
3581 | } |
3582 | |
3583 | return 0; |
3584 | } |
3585 | |
3586 | static int |
3587 | rt5390_bbp_init(struct rt2860_softc *sc) |
3588 | { |
3589 | uint8_t bbp; |
3590 | int i; |
3591 | |
3592 | /* Apply maximum likelihood detection for 2 stream case. */ |
3593 | if (sc->nrxchains > 1) { |
3594 | bbp = rt2860_mcu_bbp_read(sc, 105); |
3595 | rt2860_mcu_bbp_write(sc, 105, bbp | RT5390_MLD); |
3596 | } |
3597 | |
3598 | /* Avoid data lost and CRC error. */ |
3599 | bbp = rt2860_mcu_bbp_read(sc, 4); |
3600 | rt2860_mcu_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); |
3601 | |
3602 | for (i = 0; i < __arraycount(rt5390_def_bbp); i++) { |
3603 | rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg, |
3604 | rt5390_def_bbp[i].val); |
3605 | } |
3606 | |
3607 | if (sc->mac_ver == 0x5392) { |
3608 | rt2860_mcu_bbp_write(sc, 84, 0x9a); |
3609 | rt2860_mcu_bbp_write(sc, 95, 0x9a); |
3610 | rt2860_mcu_bbp_write(sc, 98, 0x12); |
3611 | rt2860_mcu_bbp_write(sc, 106, 0x05); |
3612 | rt2860_mcu_bbp_write(sc, 134, 0xd0); |
3613 | rt2860_mcu_bbp_write(sc, 135, 0xf6); |
3614 | } |
3615 | |
3616 | bbp = rt2860_mcu_bbp_read(sc, 152); |
3617 | rt2860_mcu_bbp_write(sc, 152, bbp | 0x80); |
3618 | |
3619 | /* Disable hardware antenna diversity. */ |
3620 | if (sc->mac_ver == 0x5390) |
3621 | rt2860_mcu_bbp_write(sc, 154, 0); |
3622 | |
3623 | return 0; |
3624 | } |
3625 | |
3626 | static int |
3627 | rt2860_txrx_enable(struct rt2860_softc *sc) |
3628 | { |
3629 | uint32_t tmp; |
3630 | int ntries; |
3631 | |
3632 | /* enable Tx/Rx DMA engine */ |
3633 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); |
3634 | RAL_BARRIER_READ_WRITE(sc); |
3635 | for (ntries = 0; ntries < 200; ntries++) { |
3636 | tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); |
3637 | if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) |
3638 | break; |
3639 | DELAY(1000); |
3640 | } |
3641 | if (ntries == 200) { |
3642 | aprint_error_dev(sc->sc_dev, |
3643 | "timeout waiting for DMA engine\n" ); |
3644 | return ETIMEDOUT; |
3645 | } |
3646 | |
3647 | DELAY(50); |
3648 | |
3649 | tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | |
3650 | RT2860_WPDMA_BT_SIZE64 << RT2860_WPDMA_BT_SIZE_SHIFT; |
3651 | RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); |
3652 | |
3653 | /* set Rx filter */ |
3654 | tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; |
3655 | if (sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) { |
3656 | tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | |
3657 | RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | |
3658 | RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | |
3659 | RT2860_DROP_CFACK | RT2860_DROP_CFEND; |
3660 | if (sc->sc_ic.ic_opmode == IEEE80211_M_STA) |
3661 | tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; |
3662 | } |
3663 | RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); |
3664 | |
3665 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, |
3666 | RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); |
3667 | |
3668 | return 0; |
3669 | } |
3670 | |
3671 | static int |
3672 | rt2860_init(struct ifnet *ifp) |
3673 | { |
3674 | struct rt2860_softc *sc = ifp->if_softc; |
3675 | struct ieee80211com *ic = &sc->sc_ic; |
3676 | uint32_t tmp; |
3677 | uint8_t bbp1, bbp3; |
3678 | int i, qid, ridx, ntries, error; |
3679 | |
3680 | /* for CardBus, power on the socket */ |
3681 | if (!(sc->sc_flags & RT2860_ENABLED)) { |
3682 | if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) { |
3683 | aprint_error_dev(sc->sc_dev, |
3684 | "could not enable device\n" ); |
3685 | return EIO; |
3686 | } |
3687 | sc->sc_flags |= RT2860_ENABLED; |
3688 | } |
3689 | |
3690 | if (sc->rfswitch) { |
3691 | /* hardware has a radio switch on GPIO pin 2 */ |
3692 | if (!(RAL_READ(sc, RT2860_GPIO_CTRL) & (1 << 2))) { |
3693 | aprint_normal_dev(sc->sc_dev, |
3694 | "radio is disabled by hardware switch\n" ); |
3695 | #ifdef notyet |
3696 | rt2860_stop(ifp, 1); |
3697 | return EPERM; |
3698 | #endif |
3699 | } |
3700 | } |
3701 | RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE); |
3702 | |
3703 | /* disable DMA */ |
3704 | tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); |
3705 | tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | |
3706 | RT2860_TX_DMA_EN); |
3707 | tmp |= RT2860_TX_WB_DDONE; |
3708 | RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); |
3709 | |
3710 | /* reset DMA indexes */ |
3711 | RAL_WRITE(sc, RT2860_WPDMA_RST_IDX, RT2860_RST_DRX_IDX0 | |
3712 | RT2860_RST_DTX_IDX5 | RT2860_RST_DTX_IDX4 | RT2860_RST_DTX_IDX3 | |
3713 | RT2860_RST_DTX_IDX2 | RT2860_RST_DTX_IDX1 | RT2860_RST_DTX_IDX0); |
3714 | |
3715 | /* PBF hardware reset */ |
3716 | RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); |
3717 | RAL_BARRIER_WRITE(sc); |
3718 | RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); |
3719 | |
3720 | if ((error = rt2860_load_microcode(sc)) != 0) { |
3721 | aprint_error_dev(sc->sc_dev, |
3722 | "could not load 8051 microcode\n" ); |
3723 | rt2860_stop(ifp, 1); |
3724 | return error; |
3725 | } |
3726 | |
3727 | IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); |
3728 | rt2860_set_macaddr(sc, ic->ic_myaddr); |
3729 | |
3730 | /* init Tx power for all Tx rates (from EEPROM) */ |
3731 | for (ridx = 0; ridx < 5; ridx++) { |
3732 | if (sc->txpow20mhz[ridx] == 0xffffffff) |
3733 | continue; |
3734 | RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); |
3735 | } |
3736 | |
3737 | for (ntries = 0; ntries < 100; ntries++) { |
3738 | tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); |
3739 | if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) |
3740 | break; |
3741 | DELAY(1000); |
3742 | } |
3743 | if (ntries == 100) { |
3744 | aprint_error_dev(sc->sc_dev, |
3745 | "timeout waiting for DMA engine\n" ); |
3746 | rt2860_stop(ifp, 1); |
3747 | return ETIMEDOUT; |
3748 | } |
3749 | tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | |
3750 | RT2860_TX_DMA_EN); |
3751 | tmp |= RT2860_TX_WB_DDONE; |
3752 | RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); |
3753 | |
3754 | /* reset Rx ring and all 6 Tx rings */ |
3755 | RAL_WRITE(sc, RT2860_WPDMA_RST_IDX, 0x1003f); |
3756 | |
3757 | /* PBF hardware reset */ |
3758 | RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); |
3759 | RAL_BARRIER_WRITE(sc); |
3760 | RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); |
3761 | |
3762 | RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE | RT2860_IO_RF_PE); |
3763 | |
3764 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); |
3765 | RAL_BARRIER_WRITE(sc); |
3766 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); |
3767 | |
3768 | for (i = 0; i < (int)__arraycount(rt2860_def_mac); i++) |
3769 | RAL_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); |
3770 | if (sc->mac_ver >= 0x5390) |
3771 | RAL_WRITE(sc, RT2860_TX_SW_CFG0, 0x00000404); |
3772 | else if (sc->mac_ver >= 0x3071) { |
3773 | /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ |
3774 | RAL_WRITE(sc, RT2860_TX_SW_CFG0, |
3775 | 4 << RT2860_DLY_PAPE_EN_SHIFT); |
3776 | } |
3777 | |
3778 | if (!(RAL_READ(sc, RT2860_PCI_CFG) & RT2860_PCI_CFG_PCI)) { |
3779 | sc->sc_flags |= RT2860_PCIE; |
3780 | /* PCIe has different clock cycle count than PCI */ |
3781 | tmp = RAL_READ(sc, RT2860_US_CYC_CNT); |
3782 | tmp = (tmp & ~0xff) | 0x7d; |
3783 | RAL_WRITE(sc, RT2860_US_CYC_CNT, tmp); |
3784 | } |
3785 | |
3786 | /* wait while MAC is busy */ |
3787 | for (ntries = 0; ntries < 100; ntries++) { |
3788 | if (!(RAL_READ(sc, RT2860_MAC_STATUS_REG) & |
3789 | (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY))) |
3790 | break; |
3791 | DELAY(1000); |
3792 | } |
3793 | if (ntries == 100) { |
3794 | aprint_error_dev(sc->sc_dev, "timeout waiting for MAC\n" ); |
3795 | rt2860_stop(ifp, 1); |
3796 | return ETIMEDOUT; |
3797 | } |
3798 | |
3799 | /* clear Host to MCU mailbox */ |
3800 | RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); |
3801 | RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); |
3802 | |
3803 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); |
3804 | DELAY(1000); |
3805 | |
3806 | if ((error = rt2860_bbp_init(sc)) != 0) { |
3807 | rt2860_stop(ifp, 1); |
3808 | return error; |
3809 | } |
3810 | |
3811 | /* clear RX WCID search table */ |
3812 | RAL_SET_REGION_4(sc, RT2860_WCID_ENTRY(0), 0, 512); |
3813 | /* clear pairwise key table */ |
3814 | RAL_SET_REGION_4(sc, RT2860_PKEY(0), 0, 2048); |
3815 | /* clear IV/EIV table */ |
3816 | RAL_SET_REGION_4(sc, RT2860_IVEIV(0), 0, 512); |
3817 | /* clear WCID attribute table */ |
3818 | RAL_SET_REGION_4(sc, RT2860_WCID_ATTR(0), 0, 256); |
3819 | /* clear shared key table */ |
3820 | RAL_SET_REGION_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); |
3821 | /* clear shared key mode */ |
3822 | RAL_SET_REGION_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); |
3823 | |
3824 | /* init Tx rings (4 EDCAs + HCCA + Mgt) */ |
3825 | for (qid = 0; qid < MAXQS; qid++) { |
3826 | RAL_WRITE(sc, RT2860_TX_BASE_PTR(qid), sc->txq[qid].paddr); |
3827 | RAL_WRITE(sc, RT2860_TX_MAX_CNT(qid), RT2860_TX_RING_COUNT); |
3828 | RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), 0); |
3829 | } |
3830 | |
3831 | /* init Rx ring */ |
3832 | RAL_WRITE(sc, RT2860_RX_BASE_PTR, sc->rxq.paddr); |
3833 | RAL_WRITE(sc, RT2860_RX_MAX_CNT, RT2860_RX_RING_COUNT); |
3834 | RAL_WRITE(sc, RT2860_RX_CALC_IDX, RT2860_RX_RING_COUNT - 1); |
3835 | |
3836 | /* setup maximum buffer sizes */ |
3837 | RAL_WRITE(sc, RT2860_MAX_LEN_CFG, 1 << 12 | |
3838 | (MCLBYTES - sizeof (struct rt2860_rxwi) - 2)); |
3839 | |
3840 | for (ntries = 0; ntries < 100; ntries++) { |
3841 | tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); |
3842 | if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) |
3843 | break; |
3844 | DELAY(1000); |
3845 | } |
3846 | if (ntries == 100) { |
3847 | aprint_error_dev(sc->sc_dev, |
3848 | "timeout waiting for DMA engine\n" ); |
3849 | rt2860_stop(ifp, 1); |
3850 | return ETIMEDOUT; |
3851 | } |
3852 | tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | |
3853 | RT2860_TX_DMA_EN); |
3854 | tmp |= RT2860_TX_WB_DDONE; |
3855 | RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); |
3856 | |
3857 | /* disable interrupts mitigation */ |
3858 | RAL_WRITE(sc, RT2860_DELAY_INT_CFG, 0); |
3859 | |
3860 | /* write vendor-specific BBP values (from EEPROM) */ |
3861 | for (i = 0; i < 8; i++) { |
3862 | if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff) |
3863 | continue; |
3864 | rt2860_mcu_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val); |
3865 | } |
3866 | |
3867 | /* select Main antenna for 1T1R devices */ |
3868 | if (sc->rf_rev == RT3070_RF_2020 || |
3869 | sc->rf_rev == RT3070_RF_3020 || |
3870 | sc->rf_rev == RT3070_RF_3320 || |
3871 | sc->rf_rev == RT5390_RF_5390) |
3872 | rt3090_set_rx_antenna(sc, 0); |
3873 | |
3874 | /* send LEDs operating mode to microcontroller */ |
3875 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0], 0); |
3876 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1], 0); |
3877 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2], 0); |
3878 | |
3879 | if (sc->mac_ver >= 0x5390) |
3880 | rt5390_rf_init(sc); |
3881 | else if (sc->mac_ver >= 0x3071) |
3882 | rt3090_rf_init(sc); |
3883 | |
3884 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_SLEEP, 0x02ff, 1); |
3885 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_WAKEUP, 0, 1); |
3886 | |
3887 | if (sc->mac_ver >= 0x5390) |
3888 | rt5390_rf_wakeup(sc); |
3889 | else if (sc->mac_ver >= 0x3071) |
3890 | rt3090_rf_wakeup(sc); |
3891 | |
3892 | /* disable non-existing Rx chains */ |
3893 | bbp3 = rt2860_mcu_bbp_read(sc, 3); |
3894 | bbp3 &= ~(1 << 3 | 1 << 4); |
3895 | if (sc->nrxchains == 2) |
3896 | bbp3 |= 1 << 3; |
3897 | else if (sc->nrxchains == 3) |
3898 | bbp3 |= 1 << 4; |
3899 | rt2860_mcu_bbp_write(sc, 3, bbp3); |
3900 | |
3901 | /* disable non-existing Tx chains */ |
3902 | bbp1 = rt2860_mcu_bbp_read(sc, 1); |
3903 | if (sc->ntxchains == 1) |
3904 | bbp1 = (bbp1 & ~(1 << 3 | 1 << 4)); |
3905 | else if (sc->mac_ver == 0x3593 && sc->ntxchains == 2) |
3906 | bbp1 = (bbp1 & ~(1 << 4)) | 1 << 3; |
3907 | else if (sc->mac_ver == 0x3593 && sc->ntxchains == 3) |
3908 | bbp1 = (bbp1 & ~(1 << 3)) | 1 << 4; |
3909 | rt2860_mcu_bbp_write(sc, 1, bbp1); |
3910 | |
3911 | if (sc->mac_ver >= 0x3071) |
3912 | rt3090_rf_setup(sc); |
3913 | |
3914 | /* select default channel */ |
3915 | ic->ic_bss->ni_chan = ic->ic_ibss_chan; |
3916 | rt2860_switch_chan(sc, ic->ic_ibss_chan); |
3917 | |
3918 | /* reset RF from MCU */ |
3919 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); |
3920 | |
3921 | /* set RTS threshold */ |
3922 | tmp = RAL_READ(sc, RT2860_TX_RTS_CFG); |
3923 | tmp &= ~0xffff00; |
3924 | tmp |= ic->ic_rtsthreshold << 8; |
3925 | RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); |
3926 | |
3927 | /* setup initial protection mode */ |
3928 | sc->sc_ic_flags = ic->ic_flags; |
3929 | rt2860_updateprot(ic); |
3930 | |
3931 | /* turn radio LED on */ |
3932 | rt2860_set_leds(sc, RT2860_LED_RADIO); |
3933 | |
3934 | /* enable Tx/Rx DMA engine */ |
3935 | if ((error = rt2860_txrx_enable(sc)) != 0) { |
3936 | rt2860_stop(ifp, 1); |
3937 | return error; |
3938 | } |
3939 | |
3940 | /* clear pending interrupts */ |
3941 | RAL_WRITE(sc, RT2860_INT_STATUS, 0xffffffff); |
3942 | /* enable interrupts */ |
3943 | RAL_WRITE(sc, RT2860_INT_MASK, 0x3fffc); |
3944 | |
3945 | if (sc->sc_flags & RT2860_ADVANCED_PS) |
3946 | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); |
3947 | |
3948 | ifp->if_flags |= IFF_RUNNING; |
3949 | ifp->if_flags &= ~IFF_OACTIVE; |
3950 | |
3951 | if (ic->ic_opmode != IEEE80211_M_MONITOR) |
3952 | ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); |
3953 | else |
3954 | ieee80211_new_state(ic, IEEE80211_S_RUN, -1); |
3955 | |
3956 | return 0; |
3957 | } |
3958 | |
3959 | static void |
3960 | rt2860_stop(struct ifnet *ifp, int disable) |
3961 | { |
3962 | struct rt2860_softc *sc = ifp->if_softc; |
3963 | struct ieee80211com *ic = &sc->sc_ic; |
3964 | uint32_t tmp; |
3965 | int qid; |
3966 | |
3967 | if (ifp->if_flags & IFF_RUNNING) |
3968 | rt2860_set_leds(sc, 0); /* turn all LEDs off */ |
3969 | |
3970 | sc->sc_tx_timer = 0; |
3971 | ifp->if_timer = 0; |
3972 | ifp->if_flags &= ~IFF_RUNNING; |
3973 | ifp->if_flags &= ~IFF_OACTIVE; |
3974 | |
3975 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */ |
3976 | |
3977 | /* disable interrupts */ |
3978 | RAL_WRITE(sc, RT2860_INT_MASK, 0); |
3979 | |
3980 | /* disable GP timer */ |
3981 | rt2860_set_gp_timer(sc, 0); |
3982 | |
3983 | /* disable Rx */ |
3984 | tmp = RAL_READ(sc, RT2860_MAC_SYS_CTRL); |
3985 | tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); |
3986 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, tmp); |
3987 | |
3988 | /* reset adapter */ |
3989 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); |
3990 | RAL_BARRIER_WRITE(sc); |
3991 | RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); |
3992 | |
3993 | /* reset Tx and Rx rings (and reclaim TXWIs) */ |
3994 | sc->qfullmsk = 0; |
3995 | for (qid = 0; qid < MAXQS; qid++) |
3996 | rt2860_reset_tx_ring(sc, &sc->txq[qid]); |
3997 | rt2860_reset_rx_ring(sc, &sc->rxq); |
3998 | |
3999 | /* for CardBus, power down the socket */ |
4000 | if (disable && sc->sc_disable != NULL) { |
4001 | if (sc->sc_flags & RT2860_ENABLED) { |
4002 | (*sc->sc_disable)(sc); |
4003 | sc->sc_flags &= ~RT2860_ENABLED; |
4004 | } |
4005 | } |
4006 | } |
4007 | |
4008 | static int |
4009 | rt2860_load_microcode(struct rt2860_softc *sc) |
4010 | { |
4011 | int ntries; |
4012 | |
4013 | /* set "host program ram write selection" bit */ |
4014 | RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); |
4015 | /* write microcode image */ |
4016 | RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, sc->ucode, sc->ucsize); |
4017 | /* kick microcontroller unit */ |
4018 | RAL_WRITE(sc, RT2860_SYS_CTRL, 0); |
4019 | RAL_BARRIER_WRITE(sc); |
4020 | RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_MCU_RESET); |
4021 | |
4022 | RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); |
4023 | RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); |
4024 | |
4025 | /* wait until microcontroller is ready */ |
4026 | RAL_BARRIER_READ_WRITE(sc); |
4027 | for (ntries = 0; ntries < 1000; ntries++) { |
4028 | if (RAL_READ(sc, RT2860_SYS_CTRL) & RT2860_MCU_READY) |
4029 | break; |
4030 | DELAY(1000); |
4031 | } |
4032 | if (ntries == 1000) { |
4033 | aprint_error_dev(sc->sc_dev, |
4034 | "timeout waiting for MCU to initialize\n" ); |
4035 | return ETIMEDOUT; |
4036 | } |
4037 | return 0; |
4038 | } |
4039 | |
4040 | #if 0 |
4041 | /* |
4042 | * This function is called periodically to adjust Tx power based on |
4043 | * temperature variation. |
4044 | */ |
4045 | static void |
4046 | rt2860_calib(struct rt2860_softc *sc) |
4047 | { |
4048 | struct ieee80211com *ic = &sc->sc_ic; |
4049 | const uint8_t *tssi; |
4050 | uint8_t step, bbp49; |
4051 | int8_t ridx, d; |
4052 | |
4053 | /* read current temperature */ |
4054 | bbp49 = rt2860_mcu_bbp_read(sc, 49); |
4055 | |
4056 | if (IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)) { |
4057 | tssi = &sc->tssi_2ghz[4]; |
4058 | step = sc->step_2ghz; |
4059 | } else { |
4060 | tssi = &sc->tssi_5ghz[4]; |
4061 | step = sc->step_5ghz; |
4062 | } |
4063 | |
4064 | if (bbp49 < tssi[0]) { /* lower than reference */ |
4065 | /* use higher Tx power than default */ |
4066 | for (d = 0; d > -4 && bbp49 <= tssi[d - 1]; d--); |
4067 | } else if (bbp49 > tssi[0]) { /* greater than reference */ |
4068 | /* use lower Tx power than default */ |
4069 | for (d = 0; d < +4 && bbp49 >= tssi[d + 1]; d++); |
4070 | } else { |
4071 | /* use default Tx power */ |
4072 | d = 0; |
4073 | } |
4074 | d *= step; |
4075 | |
4076 | DPRINTF(("BBP49=0x%02x, adjusting Tx power by %d\n" , bbp49, d)); |
4077 | |
4078 | /* write adjusted Tx power values for each Tx rate */ |
4079 | for (ridx = 0; ridx < 5; ridx++) { |
4080 | if (sc->txpow20mhz[ridx] == 0xffffffff) |
4081 | continue; |
4082 | RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), |
4083 | b4inc(sc->txpow20mhz[ridx], d)); |
4084 | } |
4085 | } |
4086 | #endif /* 0 */ |
4087 | |
4088 | static void |
4089 | rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux) |
4090 | { |
4091 | uint32_t tmp; |
4092 | |
4093 | if (aux) { |
4094 | if (sc->mac_ver == 0x5390) { |
4095 | rt2860_mcu_bbp_write(sc, 152, |
4096 | rt2860_mcu_bbp_read(sc, 152) & ~0x80); |
4097 | } else { |
4098 | tmp = RAL_READ(sc, RT2860_PCI_EECTRL); |
4099 | RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp & ~RT2860_C); |
4100 | tmp = RAL_READ(sc, RT2860_GPIO_CTRL); |
4101 | RAL_WRITE(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08); |
4102 | } |
4103 | } else { |
4104 | if (sc->mac_ver == 0x5390) { |
4105 | rt2860_mcu_bbp_write(sc, 152, |
4106 | rt2860_mcu_bbp_read(sc, 152) | 0x80); |
4107 | } else { |
4108 | tmp = RAL_READ(sc, RT2860_PCI_EECTRL); |
4109 | RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp | RT2860_C); |
4110 | tmp = RAL_READ(sc, RT2860_GPIO_CTRL); |
4111 | RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp & ~0x0808); |
4112 | } |
4113 | } |
4114 | } |
4115 | |
4116 | static void |
4117 | rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) |
4118 | { |
4119 | struct ieee80211com *ic = &sc->sc_ic; |
4120 | u_int chan, group; |
4121 | |
4122 | chan = ieee80211_chan2ieee(ic, c); |
4123 | DPRINTF(("switch channel %u\n" , chan)); |
4124 | if (chan == 0 || chan == IEEE80211_CHAN_ANY) |
4125 | return; |
4126 | |
4127 | if (sc->mac_ver >= 0x5390) |
4128 | rt5390_set_chan(sc, chan); |
4129 | else if (sc->mac_ver >= 0x3071) |
4130 | rt3090_set_chan(sc, chan); |
4131 | else |
4132 | rt2860_set_chan(sc, chan); |
4133 | |
4134 | /* determine channel group */ |
4135 | if (chan <= 14) |
4136 | group = 0; |
4137 | else if (chan <= 64) |
4138 | group = 1; |
4139 | else if (chan <= 128) |
4140 | group = 2; |
4141 | else |
4142 | group = 3; |
4143 | |
4144 | /* XXX necessary only when group has changed! */ |
4145 | if (sc->mac_ver < 0x5390) |
4146 | rt2860_select_chan_group(sc, group); |
4147 | |
4148 | DELAY(1000); |
4149 | } |
4150 | |
4151 | #ifndef IEEE80211_STA_ONLY |
4152 | static int |
4153 | rt2860_setup_beacon(struct rt2860_softc *sc) |
4154 | { |
4155 | struct ieee80211com *ic = &sc->sc_ic; |
4156 | struct rt2860_txwi txwi; |
4157 | struct mbuf *m; |
4158 | int ridx; |
4159 | |
4160 | if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo)) == NULL) |
4161 | return ENOBUFS; |
4162 | |
4163 | memset(&txwi, 0, sizeof txwi); |
4164 | txwi.wcid = 0xff; |
4165 | txwi.len = htole16(m->m_pkthdr.len); |
4166 | /* send beacons at the lowest available rate */ |
4167 | ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? |
4168 | RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; |
4169 | txwi.phy = htole16(rt2860_rates[ridx].mcs); |
4170 | if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) |
4171 | txwi.phy |= htole16(RT2860_PHY_OFDM); |
4172 | txwi.txop = RT2860_TX_TXOP_HT; |
4173 | txwi.flags = RT2860_TX_TS; |
4174 | txwi.xflags = RT2860_TX_NSEQ; |
4175 | |
4176 | RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0), |
4177 | (uint8_t *)&txwi, sizeof txwi); |
4178 | RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0) + sizeof txwi, |
4179 | mtod(m, uint8_t *), m->m_pkthdr.len); |
4180 | |
4181 | m_freem(m); |
4182 | |
4183 | return 0; |
4184 | } |
4185 | #endif |
4186 | |
4187 | static void |
4188 | rt2860_enable_tsf_sync(struct rt2860_softc *sc) |
4189 | { |
4190 | struct ieee80211com *ic = &sc->sc_ic; |
4191 | uint32_t tmp; |
4192 | |
4193 | tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); |
4194 | |
4195 | tmp &= ~0x1fffff; |
4196 | tmp |= ic->ic_bss->ni_intval * 16; |
4197 | tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; |
4198 | if (ic->ic_opmode == IEEE80211_M_STA) { |
4199 | /* |
4200 | * Local TSF is always updated with remote TSF on beacon |
4201 | * reception. |
4202 | */ |
4203 | tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; |
4204 | } |
4205 | #ifndef IEEE80211_STA_ONLY |
4206 | else if (ic->ic_opmode == IEEE80211_M_IBSS) { |
4207 | tmp |= RT2860_BCN_TX_EN; |
4208 | /* |
4209 | * Local TSF is updated with remote TSF on beacon reception |
4210 | * only if the remote TSF is greater than local TSF. |
4211 | */ |
4212 | tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; |
4213 | } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) { |
4214 | tmp |= RT2860_BCN_TX_EN; |
4215 | /* SYNC with nobody */ |
4216 | tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; |
4217 | } |
4218 | #endif |
4219 | |
4220 | RAL_WRITE(sc, RT2860_BCN_TIME_CFG, tmp); |
4221 | } |
4222 | |