Line data Source code
1 : /* $OpenBSD: rtwn.c,v 1.37 2018/09/13 09:28:07 kevlo Exp $ */
2 :
3 : /*-
4 : * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
5 : * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
6 : *
7 : * Permission to use, copy, modify, and distribute this software for any
8 : * purpose with or without fee is hereby granted, provided that the above
9 : * copyright notice and this permission notice appear in all copies.
10 : *
11 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 : */
19 :
20 : /*
21 : * Driver for Realtek 802.11b/g/n chipsets.
22 : */
23 :
24 : #include "bpfilter.h"
25 :
26 : #include <sys/param.h>
27 : #include <sys/sockio.h>
28 : #include <sys/mbuf.h>
29 : #include <sys/kernel.h>
30 : #include <sys/socket.h>
31 : #include <sys/systm.h>
32 : #include <sys/task.h>
33 : #include <sys/timeout.h>
34 : #include <sys/conf.h>
35 : #include <sys/device.h>
36 : #include <sys/endian.h>
37 :
38 : #include <machine/bus.h>
39 : #include <machine/intr.h>
40 :
41 : #if NBPFILTER > 0
42 : #include <net/bpf.h>
43 : #endif
44 : #include <net/if.h>
45 : #include <net/if_dl.h>
46 : #include <net/if_media.h>
47 :
48 : #include <netinet/in.h>
49 : #include <netinet/if_ether.h>
50 :
51 : #include <net80211/ieee80211_var.h>
52 : #include <net80211/ieee80211_radiotap.h>
53 :
54 : #include <dev/ic/r92creg.h>
55 : #include <dev/ic/rtwnvar.h>
56 :
57 : #define RTWN_RIDX_CCK1 0
58 : #define RTWN_RIDX_CCK2 1
59 : #define RTWN_RIDX_CCK11 3
60 : #define RTWN_RIDX_OFDM6 4
61 : #define RTWN_RIDX_OFDM54 11
62 : #define RTWN_RIDX_MCS0 12
63 : #define RTWN_RIDX_MCS8 (RTWN_RIDX_MCS0 + 8)
64 : #define RTWN_RIDX_MCS15 27
65 : #define RTWN_RIDX_MAX 27
66 :
67 : #define RTWN_POWER_CCK1 0
68 : #define RTWN_POWER_CCK2 1
69 : #define RTWN_POWER_CCK55 2
70 : #define RTWN_POWER_CCK11 3
71 : #define RTWN_POWER_OFDM6 4
72 : #define RTWN_POWER_OFDM9 5
73 : #define RTWN_POWER_OFDM12 6
74 : #define RTWN_POWER_OFDM18 7
75 : #define RTWN_POWER_OFDM24 8
76 : #define RTWN_POWER_OFDM36 9
77 : #define RTWN_POWER_OFDM48 10
78 : #define RTWN_POWER_OFDM54 11
79 : #define RTWN_POWER_MCS(mcs) (12 + (mcs))
80 : #define RTWN_POWER_COUNT 28
81 :
82 :
83 : #ifdef RTWN_DEBUG
84 : #define DPRINTF(x) do { if (rtwn_debug) printf x; } while (0)
85 : #define DPRINTFN(n, x) do { if (rtwn_debug >= (n)) printf x; } while (0)
86 : int rtwn_debug = 0;
87 : #else
88 : #define DPRINTF(x)
89 : #define DPRINTFN(n, x)
90 : #endif
91 :
92 : /* Registers to save and restore during IQ calibration. */
93 : struct rtwn_iq_cal_regs {
94 : uint32_t adda[16];
95 : uint8_t txpause;
96 : uint8_t bcn_ctrl;
97 : uint8_t bcn_ctrl1;
98 : uint32_t gpio_muxcfg;
99 : uint32_t ofdm0_trxpathena;
100 : uint32_t ofdm0_trmuxpar;
101 : uint32_t fpga0_rfifacesw1;
102 : };
103 :
104 : void rtwn_write_1(struct rtwn_softc *, uint16_t, uint8_t);
105 : void rtwn_write_2(struct rtwn_softc *, uint16_t, uint16_t);
106 : void rtwn_write_4(struct rtwn_softc *, uint16_t, uint32_t);
107 : uint8_t rtwn_read_1(struct rtwn_softc *, uint16_t);
108 : uint16_t rtwn_read_2(struct rtwn_softc *, uint16_t);
109 : uint32_t rtwn_read_4(struct rtwn_softc *, uint16_t);
110 : int rtwn_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int);
111 : void rtwn_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
112 : uint32_t rtwn_rf_read(struct rtwn_softc *, int, uint8_t);
113 : void rtwn_cam_write(struct rtwn_softc *, uint32_t, uint32_t);
114 : uint8_t rtwn_efuse_read_1(struct rtwn_softc *, uint16_t);
115 : void rtwn_efuse_read(struct rtwn_softc *, uint8_t *, size_t);
116 : void rtwn_efuse_switch_power(struct rtwn_softc *);
117 : int rtwn_read_chipid(struct rtwn_softc *);
118 : void rtwn_read_rom(struct rtwn_softc *);
119 : void rtwn_r92c_read_rom(struct rtwn_softc *);
120 : void rtwn_r88e_read_rom(struct rtwn_softc *);
121 : int rtwn_media_change(struct ifnet *);
122 : int rtwn_ra_init(struct rtwn_softc *);
123 : int rtwn_r92c_ra_init(struct rtwn_softc *, u_int8_t, u_int32_t,
124 : int, uint32_t, int);
125 : int rtwn_r88e_ra_init(struct rtwn_softc *, u_int8_t, u_int32_t,
126 : int, uint32_t, int);
127 : void rtwn_tsf_sync_enable(struct rtwn_softc *);
128 : void rtwn_set_led(struct rtwn_softc *, int, int);
129 : void rtwn_set_nettype(struct rtwn_softc *, enum ieee80211_opmode);
130 : void rtwn_update_short_preamble(struct ieee80211com *);
131 : void rtwn_r92c_update_short_preamble(struct rtwn_softc *);
132 : void rtwn_r88e_update_short_preamble(struct rtwn_softc *);
133 : int8_t rtwn_r88e_get_rssi(struct rtwn_softc *, int, void *);
134 : void rtwn_watchdog(struct ifnet *);
135 : void rtwn_fw_reset(struct rtwn_softc *);
136 : void rtwn_r92c_fw_reset(struct rtwn_softc *);
137 : void rtwn_r88e_fw_reset(struct rtwn_softc *);
138 : int rtwn_load_firmware(struct rtwn_softc *);
139 : void rtwn_rf_init(struct rtwn_softc *);
140 : void rtwn_cam_init(struct rtwn_softc *);
141 : void rtwn_pa_bias_init(struct rtwn_softc *);
142 : void rtwn_rxfilter_init(struct rtwn_softc *);
143 : void rtwn_edca_init(struct rtwn_softc *);
144 : void rtwn_rate_fallback_init(struct rtwn_softc *);
145 : void rtwn_usb_aggr_init(struct rtwn_softc *);
146 : void rtwn_write_txpower(struct rtwn_softc *, int, uint16_t[]);
147 : void rtwn_get_txpower(struct rtwn_softc *sc, int,
148 : struct ieee80211_channel *, struct ieee80211_channel *,
149 : uint16_t[]);
150 : void rtwn_r92c_get_txpower(struct rtwn_softc *, int,
151 : struct ieee80211_channel *, struct ieee80211_channel *,
152 : uint16_t[]);
153 : void rtwn_r88e_get_txpower(struct rtwn_softc *, int,
154 : struct ieee80211_channel *,
155 : struct ieee80211_channel *, uint16_t[]);
156 : void rtwn_set_txpower(struct rtwn_softc *,
157 : struct ieee80211_channel *, struct ieee80211_channel *);
158 : void rtwn_set_chan(struct rtwn_softc *,
159 : struct ieee80211_channel *, struct ieee80211_channel *);
160 : int rtwn_iq_calib_chain(struct rtwn_softc *, int, uint16_t[2],
161 : uint16_t[2]);
162 : void rtwn_iq_calib_run(struct rtwn_softc *, int, uint16_t[2][2],
163 : uint16_t rx[2][2], struct rtwn_iq_cal_regs *);
164 : int rtwn_iq_calib_compare_results(uint16_t[2][2], uint16_t[2][2],
165 : uint16_t[2][2], uint16_t[2][2], int);
166 : void rtwn_iq_calib_write_results(struct rtwn_softc *, uint16_t[2],
167 : uint16_t[2], int);
168 : void rtwn_iq_calib(struct rtwn_softc *);
169 : void rtwn_lc_calib(struct rtwn_softc *);
170 : void rtwn_temp_calib(struct rtwn_softc *);
171 : void rtwn_enable_intr(struct rtwn_softc *);
172 : void rtwn_disable_intr(struct rtwn_softc *);
173 : int rtwn_init(struct ifnet *);
174 : void rtwn_init_task(void *);
175 : void rtwn_stop(struct ifnet *);
176 :
177 : /* Aliases. */
178 : #define rtwn_bb_write rtwn_write_4
179 : #define rtwn_bb_read rtwn_read_4
180 :
181 : /*
182 : * Macro to convert 4-bit signed integer to 8-bit signed integer.
183 : */
184 : #define RTWN_SIGN4TO8(val) (((val) & 0x08) ? (val) | 0xf0 : (val))
185 :
186 : int
187 0 : rtwn_attach(struct device *pdev, struct rtwn_softc *sc)
188 : {
189 0 : struct ieee80211com *ic = &sc->sc_ic;
190 0 : struct ifnet *ifp = &ic->ic_if;
191 : int i, error;
192 :
193 0 : sc->sc_pdev = pdev;
194 :
195 0 : task_set(&sc->init_task, rtwn_init_task, sc);
196 :
197 0 : error = rtwn_read_chipid(sc);
198 0 : if (error != 0) {
199 0 : printf("%s: unsupported chip\n", sc->sc_pdev->dv_xname);
200 0 : return (ENXIO);
201 : }
202 :
203 : /* Determine number of Tx/Rx chains. */
204 0 : if (sc->chip & RTWN_CHIP_92C) {
205 0 : sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2;
206 0 : sc->nrxchains = 2;
207 0 : } else {
208 0 : sc->ntxchains = 1;
209 0 : sc->nrxchains = 1;
210 : }
211 :
212 0 : rtwn_read_rom(sc);
213 :
214 0 : if (sc->chip & RTWN_CHIP_PCI) {
215 0 : printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
216 0 : sc->sc_pdev->dv_xname,
217 0 : (sc->chip & RTWN_CHIP_92C) ? "8192CE" :
218 0 : (sc->chip & RTWN_CHIP_88E) ? "8188EE" : "8188CE",
219 0 : sc->ntxchains, sc->nrxchains,
220 0 : ether_sprintf(ic->ic_myaddr));
221 0 : } else if (sc->chip & RTWN_CHIP_USB) {
222 0 : printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
223 : sc->sc_pdev->dv_xname,
224 0 : (sc->chip & RTWN_CHIP_92C) ? "8192CU" :
225 0 : (sc->chip & RTWN_CHIP_88E) ? "8188EU" :
226 0 : (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" :
227 0 : (sc->board_type == R92C_BOARD_TYPE_MINICARD) ?
228 : "8188CE-VAU" : "8188CUS",
229 0 : sc->ntxchains, sc->nrxchains,
230 0 : ether_sprintf(ic->ic_myaddr));
231 : } else {
232 0 : printf("%s: unsupported chip\n", sc->sc_pdev->dv_xname);
233 0 : return (ENXIO);
234 : }
235 :
236 0 : ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
237 0 : ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
238 0 : ic->ic_state = IEEE80211_S_INIT;
239 :
240 : /* Set device capabilities. */
241 0 : ic->ic_caps =
242 : IEEE80211_C_MONITOR | /* Monitor mode supported. */
243 : IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */
244 : IEEE80211_C_SHSLOT | /* Short slot time supported. */
245 : IEEE80211_C_WEP | /* WEP. */
246 : IEEE80211_C_RSN; /* WPA/RSN. */
247 :
248 : /* Set HT capabilities. */
249 0 : ic->ic_htcaps =
250 : IEEE80211_HTCAP_CBW20_40 |
251 : IEEE80211_HTCAP_DSSSCCK40;
252 : /* Set supported HT rates. */
253 0 : for (i = 0; i < sc->nrxchains; i++)
254 0 : ic->ic_sup_mcs[i] = 0xff;
255 :
256 : /* Set supported .11b and .11g rates. */
257 0 : ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
258 0 : ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
259 :
260 : /* Set supported .11b and .11g channels (1 through 14). */
261 0 : for (i = 1; i <= 14; i++) {
262 0 : ic->ic_channels[i].ic_freq =
263 0 : ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
264 0 : ic->ic_channels[i].ic_flags =
265 : IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
266 : IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
267 : }
268 :
269 : #ifdef notyet
270 : /*
271 : * The number of STAs that we can support is limited by the number
272 : * of CAM entries used for hardware crypto.
273 : */
274 : ic->ic_max_nnodes = R92C_CAM_ENTRY_COUNT - 4;
275 : if (ic->ic_max_nnodes > IEEE80211_CACHE_SIZE)
276 : ic->ic_max_nnodes = IEEE80211_CACHE_SIZE;
277 : #endif
278 :
279 0 : ifp->if_softc = sc;
280 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
281 0 : ifp->if_ioctl = rtwn_ioctl;
282 0 : ifp->if_start = rtwn_start;
283 0 : ifp->if_watchdog = rtwn_watchdog;
284 0 : memcpy(ifp->if_xname, sc->sc_pdev->dv_xname, IFNAMSIZ);
285 :
286 0 : if_attach(ifp);
287 0 : ieee80211_ifattach(ifp);
288 0 : ic->ic_updateslot = rtwn_updateslot;
289 0 : ic->ic_updateedca = rtwn_updateedca;
290 : #ifdef notyet
291 : ic->ic_set_key = rtwn_set_key;
292 : ic->ic_delete_key = rtwn_delete_key;
293 : #endif
294 : /* Override state transition machine. */
295 0 : sc->sc_newstate = ic->ic_newstate;
296 0 : ic->ic_newstate = rtwn_newstate;
297 0 : ieee80211_media_init(ifp, rtwn_media_change, ieee80211_media_status);
298 :
299 0 : return (0);
300 0 : }
301 :
302 : int
303 0 : rtwn_detach(struct rtwn_softc *sc, int flags)
304 : {
305 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
306 : int s;
307 :
308 0 : s = splnet();
309 :
310 0 : task_del(systq, &sc->init_task);
311 :
312 0 : if (ifp->if_softc != NULL) {
313 0 : ieee80211_ifdetach(ifp);
314 0 : if_detach(ifp);
315 0 : }
316 :
317 0 : splx(s);
318 :
319 0 : return (0);
320 : }
321 :
322 : int
323 0 : rtwn_activate(struct rtwn_softc *sc, int act)
324 : {
325 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
326 :
327 0 : switch (act) {
328 : case DVACT_QUIESCE: /* rtwn_stop() may sleep */
329 0 : if (ifp->if_flags & IFF_RUNNING)
330 0 : rtwn_stop(ifp);
331 : break;
332 : case DVACT_WAKEUP:
333 0 : rtwn_init_task(sc);
334 0 : break;
335 : }
336 0 : return (0);
337 : }
338 :
339 : void
340 0 : rtwn_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val)
341 : {
342 0 : sc->sc_ops.write_1(sc->sc_ops.cookie, addr, val);
343 0 : }
344 :
345 : void
346 0 : rtwn_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val)
347 : {
348 0 : sc->sc_ops.write_2(sc->sc_ops.cookie, addr, val);
349 0 : }
350 :
351 : void
352 0 : rtwn_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val)
353 : {
354 0 : sc->sc_ops.write_4(sc->sc_ops.cookie, addr, val);
355 0 : }
356 :
357 : uint8_t
358 0 : rtwn_read_1(struct rtwn_softc *sc, uint16_t addr)
359 : {
360 0 : return sc->sc_ops.read_1(sc->sc_ops.cookie, addr);
361 : }
362 :
363 : uint16_t
364 0 : rtwn_read_2(struct rtwn_softc *sc, uint16_t addr)
365 : {
366 0 : return sc->sc_ops.read_2(sc->sc_ops.cookie, addr);
367 : }
368 :
369 : uint32_t
370 0 : rtwn_read_4(struct rtwn_softc *sc, uint16_t addr)
371 : {
372 0 : return sc->sc_ops.read_4(sc->sc_ops.cookie, addr);
373 : }
374 :
375 : int
376 0 : rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
377 : {
378 0 : struct r92c_fw_cmd cmd;
379 : int ntries;
380 :
381 : /* Wait for current FW box to be empty. */
382 0 : for (ntries = 0; ntries < 100; ntries++) {
383 0 : if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
384 : break;
385 0 : DELAY(1);
386 : }
387 0 : if (ntries == 100) {
388 0 : printf("%s: could not send firmware command %d\n",
389 0 : sc->sc_pdev->dv_xname, id);
390 0 : return (ETIMEDOUT);
391 : }
392 0 : memset(&cmd, 0, sizeof(cmd));
393 : cmd.id = id;
394 0 : if (len > 3)
395 0 : cmd.id |= R92C_CMD_FLAG_EXT;
396 0 : KASSERT(len <= sizeof(cmd.msg));
397 0 : memcpy(cmd.msg, buf, len);
398 :
399 : /* Write the first word last since that will trigger the FW. */
400 0 : rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *((uint8_t *)&cmd + 4));
401 0 : rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *((uint8_t *)&cmd + 0));
402 :
403 0 : sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
404 :
405 0 : if (sc->chip & RTWN_CHIP_PCI) {
406 : /* Give firmware some time for processing. */
407 0 : DELAY(2000);
408 0 : }
409 :
410 0 : return (0);
411 0 : }
412 :
413 : void
414 0 : rtwn_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
415 : {
416 : uint32_t param_addr;
417 :
418 0 : if (sc->chip & RTWN_CHIP_88E)
419 0 : param_addr = SM(R88E_LSSI_PARAM_ADDR, addr);
420 : else
421 0 : param_addr = SM(R92C_LSSI_PARAM_ADDR, addr);
422 :
423 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
424 0 : param_addr | SM(R92C_LSSI_PARAM_DATA, val));
425 0 : }
426 :
427 : uint32_t
428 0 : rtwn_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr)
429 : {
430 0 : uint32_t reg[R92C_MAX_CHAINS], val;
431 :
432 0 : reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0));
433 0 : if (chain != 0)
434 0 : reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain));
435 :
436 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
437 0 : reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE);
438 0 : DELAY(1000);
439 :
440 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
441 0 : RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) |
442 : R92C_HSSI_PARAM2_READ_EDGE);
443 0 : DELAY(1000);
444 :
445 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
446 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
447 0 : reg[0] | R92C_HSSI_PARAM2_READ_EDGE);
448 0 : DELAY(1000);
449 0 : }
450 :
451 0 : if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI)
452 0 : val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain));
453 : else
454 0 : val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain));
455 0 : return (MS(val, R92C_LSSI_READBACK_DATA));
456 0 : }
457 :
458 : void
459 0 : rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
460 : {
461 0 : rtwn_write_4(sc, R92C_CAMWRITE, data);
462 0 : rtwn_write_4(sc, R92C_CAMCMD,
463 0 : R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
464 0 : SM(R92C_CAMCMD_ADDR, addr));
465 0 : }
466 :
467 : uint8_t
468 0 : rtwn_efuse_read_1(struct rtwn_softc *sc, uint16_t addr)
469 : {
470 : uint32_t reg;
471 : int ntries;
472 :
473 0 : reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
474 0 : reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
475 0 : reg &= ~R92C_EFUSE_CTRL_VALID;
476 0 : rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
477 : /* Wait for read operation to complete. */
478 0 : for (ntries = 0; ntries < 100; ntries++) {
479 0 : reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
480 0 : if (reg & R92C_EFUSE_CTRL_VALID)
481 0 : return (MS(reg, R92C_EFUSE_CTRL_DATA));
482 0 : DELAY(5);
483 : }
484 0 : printf("%s: could not read efuse byte at address 0x%x\n",
485 0 : sc->sc_pdev->dv_xname, addr);
486 0 : return (0xff);
487 0 : }
488 :
489 : void
490 0 : rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, size_t size)
491 : {
492 : uint8_t off, msk, tmp;
493 : uint16_t addr = 0;
494 : uint32_t reg;
495 : int i, len;
496 :
497 0 : rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
498 0 : rtwn_efuse_switch_power(sc);
499 :
500 0 : memset(rom, 0xff, size);
501 0 : len = (sc->chip & RTWN_CHIP_88E) ? 256 : 512;
502 0 : while (addr < len) {
503 0 : reg = rtwn_efuse_read_1(sc, addr);
504 0 : if (reg == 0xff)
505 : break;
506 0 : addr++;
507 :
508 : /* Check for extended header. */
509 0 : if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
510 0 : (reg & 0x1f) == 0x0f) {
511 0 : tmp = (reg & 0xe0) >> 5;
512 0 : reg = rtwn_efuse_read_1(sc, addr);
513 0 : addr++;
514 0 : if ((reg & 0x0f) != 0x0f)
515 0 : off = ((reg & 0xf0) >> 1) | tmp;
516 : else
517 0 : continue;
518 0 : } else
519 0 : off = reg >> 4;
520 0 : msk = reg & 0xf;
521 0 : for (i = 0; i < 4; i++) {
522 0 : if (msk & (1 << i))
523 : continue;
524 0 : rom[off * 8 + i * 2 + 0] = rtwn_efuse_read_1(sc, addr);
525 0 : addr++;
526 0 : rom[off * 8 + i * 2 + 1] = rtwn_efuse_read_1(sc, addr);
527 0 : addr++;
528 0 : }
529 : }
530 : #ifdef RTWN_DEBUG
531 : if (rtwn_debug >= 2) {
532 : /* Dump ROM content. */
533 : printf("\n");
534 : for (i = 0; i < size; i++)
535 : printf("%02x:", rom[i]);
536 : printf("\n");
537 : }
538 : #endif
539 0 : rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
540 0 : }
541 :
542 : void
543 0 : rtwn_efuse_switch_power(struct rtwn_softc *sc)
544 : {
545 : uint16_t reg;
546 :
547 0 : reg = rtwn_read_2(sc, R92C_SYS_ISO_CTRL);
548 0 : if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) {
549 0 : rtwn_write_2(sc, R92C_SYS_ISO_CTRL,
550 0 : reg | R92C_SYS_ISO_CTRL_PWC_EV12V);
551 0 : }
552 0 : reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
553 0 : if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
554 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN,
555 0 : reg | R92C_SYS_FUNC_EN_ELDR);
556 0 : }
557 0 : reg = rtwn_read_2(sc, R92C_SYS_CLKR);
558 0 : if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
559 : (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
560 0 : rtwn_write_2(sc, R92C_SYS_CLKR,
561 0 : reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
562 0 : }
563 0 : }
564 :
565 : int
566 0 : rtwn_read_chipid(struct rtwn_softc *sc)
567 : {
568 : uint32_t reg;
569 :
570 0 : if (sc->chip & RTWN_CHIP_88E) {
571 0 : sc->sc_flags |= RTWN_FLAG_EXT_HDR;
572 0 : return (0);
573 : }
574 :
575 0 : reg = rtwn_read_4(sc, R92C_SYS_CFG);
576 0 : if (reg & R92C_SYS_CFG_TRP_VAUX_EN)
577 : /* Unsupported test chip. */
578 0 : return (EIO);
579 :
580 0 : if ((sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) != 0) {
581 0 : if (reg & R92C_SYS_CFG_TYPE_92C) {
582 0 : sc->chip &= ~RTWN_CHIP_88C;
583 : /* Check if it is a castrated 8192C. */
584 0 : if (MS(rtwn_read_4(sc, R92C_HPON_FSM),
585 0 : R92C_HPON_FSM_CHIP_BONDING_ID) ==
586 : R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R)
587 0 : sc->chip |= RTWN_CHIP_92C_1T2R;
588 : } else
589 0 : sc->chip &= ~RTWN_CHIP_92C;
590 :
591 0 : if (reg & R92C_SYS_CFG_VENDOR_UMC) {
592 0 : sc->chip |= RTWN_CHIP_UMC;
593 0 : if (MS(reg, R92C_SYS_CFG_CHIP_VER_RTL) == 0)
594 0 : sc->chip |= RTWN_CHIP_UMC_A_CUT;
595 : }
596 :
597 0 : return (0);
598 : }
599 :
600 0 : return (ENXIO); /* unsupported chip */
601 0 : }
602 :
603 : void
604 0 : rtwn_read_rom(struct rtwn_softc *sc)
605 : {
606 0 : if (sc->chip & RTWN_CHIP_88E)
607 0 : rtwn_r88e_read_rom(sc);
608 : else
609 0 : rtwn_r92c_read_rom(sc);
610 0 : }
611 :
612 : void
613 0 : rtwn_r92c_read_rom(struct rtwn_softc *sc)
614 : {
615 0 : struct ieee80211com *ic = &sc->sc_ic;
616 0 : struct r92c_rom *rom = &sc->sc_r92c_rom;
617 :
618 : /* Read full ROM image. */
619 0 : rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r92c_rom,
620 : sizeof(sc->sc_r92c_rom));
621 :
622 : /* XXX Weird but this is what the vendor driver does. */
623 0 : sc->pa_setting = rtwn_efuse_read_1(sc, 0x1fa);
624 : DPRINTF(("PA setting=0x%x\n", sc->pa_setting));
625 :
626 0 : sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
627 : DPRINTF(("board type=%d\n", sc->board_type));
628 :
629 0 : sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
630 : DPRINTF(("regulatory type=%d\n", sc->regulatory));
631 :
632 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
633 0 : }
634 :
635 : void
636 0 : rtwn_r88e_read_rom(struct rtwn_softc *sc)
637 : {
638 0 : struct ieee80211com *ic = &sc->sc_ic;
639 0 : struct r88e_rom *rom = &sc->sc_r88e_rom;
640 :
641 : /* Read full ROM image. */
642 0 : rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r88e_rom,
643 : sizeof(sc->sc_r88e_rom));
644 :
645 0 : sc->crystal_cap = rom->xtal;
646 : DPRINTF(("Crystal cap=0x%x\n", sc->crystal_cap));
647 :
648 0 : sc->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
649 : DPRINTF(("regulatory type=%d\n", sc->regulatory));
650 :
651 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
652 0 : }
653 :
654 : int
655 0 : rtwn_media_change(struct ifnet *ifp)
656 : {
657 : int error;
658 :
659 0 : error = ieee80211_media_change(ifp);
660 0 : if (error != ENETRESET)
661 0 : return (error);
662 :
663 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
664 : (IFF_UP | IFF_RUNNING)) {
665 0 : rtwn_stop(ifp);
666 0 : rtwn_init(ifp);
667 0 : }
668 0 : return (0);
669 0 : }
670 :
671 : /*
672 : * Initialize rate adaptation.
673 : */
674 : int
675 0 : rtwn_ra_init(struct rtwn_softc *sc)
676 : {
677 : static const uint8_t map[] =
678 : { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
679 0 : struct ieee80211com *ic = &sc->sc_ic;
680 0 : struct ieee80211_node *ni = ic->ic_bss;
681 0 : struct ieee80211_rateset *rs = &ni->ni_rates;
682 : uint32_t rates, basicrates;
683 : uint8_t mode;
684 : int maxrate, maxbasicrate, i, j;
685 : int error = 0;
686 :
687 : /* Get normal and basic rates mask. */
688 : rates = basicrates = 0;
689 : maxrate = maxbasicrate = 0;
690 0 : for (i = 0; i < rs->rs_nrates; i++) {
691 : /* Convert 802.11 rate to HW rate index. */
692 0 : for (j = 0; j < nitems(map); j++)
693 0 : if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j])
694 : break;
695 0 : if (j == nitems(map)) /* Unknown rate, skip. */
696 : continue;
697 0 : rates |= 1 << j;
698 0 : if (j > maxrate)
699 0 : maxrate = j;
700 0 : if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) {
701 0 : basicrates |= 1 << j;
702 0 : if (j > maxbasicrate)
703 0 : maxbasicrate = j;
704 : }
705 : }
706 0 : if (ic->ic_curmode == IEEE80211_MODE_11B)
707 0 : mode = R92C_RAID_11B;
708 : else
709 : mode = R92C_RAID_11BG;
710 : DPRINTF(("mode=0x%x rates=0x%08x, basicrates=0x%08x\n",
711 : mode, rates, basicrates));
712 :
713 0 : if (sc->chip & RTWN_CHIP_PCI) {
714 : /* Configure Automatic Rate Fallback Register. */
715 0 : if (ic->ic_curmode == IEEE80211_MODE_11B) {
716 0 : if (rates & 0x0c)
717 0 : rtwn_write_4(sc, R92C_ARFR(0), rates & 0x05);
718 : else
719 0 : rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07);
720 : } else
721 0 : rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07f5);
722 : }
723 :
724 0 : if (sc->chip & RTWN_CHIP_88E) {
725 0 : error = rtwn_r88e_ra_init(sc, mode, rates, maxrate,
726 : basicrates, maxbasicrate);
727 : /* We use AMRR with this chip. Start with the lowest rate. */
728 0 : ni->ni_txrate = 0;
729 0 : } else {
730 0 : if (sc->chip & RTWN_CHIP_PCI) {
731 0 : ni->ni_txrate = 0; /* AMRR will raise. */
732 : /* Set initial MRR rates. */
733 0 : rtwn_write_1(sc,
734 0 : R92C_INIDATA_RATE_SEL(R92C_MACID_BC), maxbasicrate);
735 0 : rtwn_write_1(sc,
736 : R92C_INIDATA_RATE_SEL(R92C_MACID_BSS), 0);
737 0 : } else {
738 0 : error = rtwn_r92c_ra_init(sc, mode, rates, maxrate,
739 : basicrates, maxbasicrate);
740 : /* No AMRR support. Indicate highest supported rate. */
741 0 : ni->ni_txrate = rs->rs_nrates - 1;
742 : }
743 : }
744 0 : return (error);
745 : }
746 :
747 : /*
748 : * Initialize rate adaptation in firmware.
749 : */
750 0 : int rtwn_r92c_ra_init(struct rtwn_softc *sc, u_int8_t mode, u_int32_t rates,
751 : int maxrate, uint32_t basicrates, int maxbasicrate)
752 : {
753 0 : struct r92c_fw_cmd_macid_cfg cmd;
754 : int error;
755 :
756 : /* Set rates mask for group addressed frames. */
757 0 : cmd.macid = R92C_MACID_BC | R92C_MACID_VALID;
758 0 : cmd.mask = htole32(mode << 28 | basicrates);
759 0 : error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
760 0 : if (error != 0) {
761 0 : printf("%s: could not add broadcast station\n",
762 0 : sc->sc_pdev->dv_xname);
763 0 : return (error);
764 : }
765 : /* Set initial MRR rate. */
766 : DPRINTF(("maxbasicrate=%d\n", maxbasicrate));
767 0 : rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BC),
768 0 : maxbasicrate);
769 :
770 : /* Set rates mask for unicast frames. */
771 0 : cmd.macid = R92C_MACID_BSS | R92C_MACID_VALID;
772 0 : cmd.mask = htole32(mode << 28 | rates);
773 0 : error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
774 0 : if (error != 0) {
775 0 : printf("%s: could not add BSS station\n",
776 0 : sc->sc_pdev->dv_xname);
777 0 : return (error);
778 : }
779 : /* Set initial MRR rate. */
780 : DPRINTF(("maxrate=%d\n", maxrate));
781 0 : rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BSS),
782 0 : maxrate);
783 :
784 0 : return (0);
785 0 : }
786 :
787 : int
788 0 : rtwn_r88e_ra_init(struct rtwn_softc *sc, u_int8_t mode, u_int32_t rates,
789 : int maxrate, uint32_t basicrates, int maxbasicrate)
790 : {
791 : u_int32_t reg;
792 :
793 0 : rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, maxbasicrate);
794 :
795 0 : reg = rtwn_read_4(sc, R92C_RRSR);
796 0 : reg = RW(reg, R92C_RRSR_RATE_BITMAP, rates);
797 0 : rtwn_write_4(sc, R92C_RRSR, reg);
798 :
799 : /*
800 : * Workaround for performance problems with firmware rate adaptation:
801 : * If the AP only supports 11b rates, disable mixed B/G mode.
802 : */
803 0 : if (mode != R92C_RAID_11B && maxrate <= 3 /* 11M */)
804 0 : sc->sc_flags |= RTWN_FLAG_FORCE_RAID_11B;
805 :
806 0 : return (0);
807 : }
808 :
809 : void
810 0 : rtwn_tsf_sync_enable(struct rtwn_softc *sc)
811 : {
812 0 : struct ieee80211_node *ni = sc->sc_ic.ic_bss;
813 : uint64_t tsf;
814 :
815 : /* Enable TSF synchronization. */
816 0 : rtwn_write_1(sc, R92C_BCN_CTRL,
817 0 : rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0);
818 :
819 0 : rtwn_write_1(sc, R92C_BCN_CTRL,
820 0 : rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_EN_BCN);
821 :
822 : /* Set initial TSF. */
823 0 : memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));
824 : tsf = letoh64(tsf);
825 0 : tsf = tsf - (tsf % (ni->ni_intval * IEEE80211_DUR_TU));
826 0 : tsf -= IEEE80211_DUR_TU;
827 0 : rtwn_write_4(sc, R92C_TSFTR + 0, tsf);
828 0 : rtwn_write_4(sc, R92C_TSFTR + 4, tsf >> 32);
829 :
830 0 : rtwn_write_1(sc, R92C_BCN_CTRL,
831 0 : rtwn_read_1(sc, R92C_BCN_CTRL) | R92C_BCN_CTRL_EN_BCN);
832 0 : }
833 :
834 : void
835 0 : rtwn_set_led(struct rtwn_softc *sc, int led, int on)
836 : {
837 : uint8_t reg;
838 :
839 0 : if (led != RTWN_LED_LINK)
840 0 : return; /* not supported */
841 :
842 0 : if (sc->chip & RTWN_CHIP_PCI) {
843 0 : reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
844 0 : if (!on)
845 0 : reg |= R92C_LEDCFG2_DIS;
846 : else
847 0 : reg |= R92C_LEDCFG2_EN;
848 0 : rtwn_write_1(sc, R92C_LEDCFG2, reg);
849 0 : } else if (sc->chip & RTWN_CHIP_USB) {
850 0 : if (sc->chip & RTWN_CHIP_88E) {
851 0 : reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
852 0 : rtwn_write_1(sc, R92C_LEDCFG2, reg | R92C_LEDCFG2_EN);
853 0 : if (!on) {
854 0 : reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0x90;
855 0 : rtwn_write_1(sc, R92C_LEDCFG2,
856 0 : reg | R92C_LEDCFG0_DIS);
857 0 : rtwn_write_1(sc, R92C_MAC_PINMUX_CFG,
858 0 : rtwn_read_1(sc, R92C_MAC_PINMUX_CFG) &
859 : 0xfe);
860 0 : }
861 : } else {
862 0 : reg = rtwn_read_1(sc, R92C_LEDCFG0) & 0x70;
863 0 : if (!on)
864 0 : reg |= R92C_LEDCFG0_DIS;
865 0 : rtwn_write_1(sc, R92C_LEDCFG0, reg);
866 : }
867 : }
868 0 : sc->ledlink = on; /* Save LED state. */
869 0 : }
870 :
871 : void
872 0 : rtwn_set_nettype(struct rtwn_softc *sc, enum ieee80211_opmode opmode)
873 : {
874 : uint8_t msr;
875 :
876 0 : msr = rtwn_read_1(sc, R92C_MSR) & ~R92C_MSR_NETTYPE_MASK;
877 :
878 0 : switch (opmode) {
879 : case IEEE80211_M_MONITOR:
880 0 : msr |= R92C_MSR_NETTYPE_NOLINK;
881 0 : break;
882 : case IEEE80211_M_STA:
883 0 : msr |= R92C_MSR_NETTYPE_INFRA;
884 0 : break;
885 : default:
886 : break;
887 : }
888 :
889 0 : rtwn_write_1(sc, R92C_MSR, msr);
890 0 : }
891 :
892 : void
893 0 : rtwn_calib(struct rtwn_softc *sc)
894 : {
895 0 : struct r92c_fw_cmd_rssi cmd;
896 :
897 0 : if (sc->avg_pwdb != -1) {
898 : /* Indicate Rx signal strength to FW for rate adaptation. */
899 0 : memset(&cmd, 0, sizeof(cmd));
900 0 : cmd.macid = 0; /* BSS. */
901 0 : cmd.pwdb = sc->avg_pwdb;
902 : DPRINTFN(3, ("sending RSSI command avg=%d\n", sc->avg_pwdb));
903 0 : rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
904 0 : }
905 :
906 : /* Do temperature compensation. */
907 0 : rtwn_temp_calib(sc);
908 :
909 0 : sc->sc_ops.next_calib(sc->sc_ops.cookie);
910 0 : }
911 :
912 : void
913 0 : rtwn_next_scan(struct rtwn_softc *sc)
914 : {
915 0 : struct ieee80211com *ic = &sc->sc_ic;
916 : int s;
917 :
918 0 : s = splnet();
919 0 : if (ic->ic_state == IEEE80211_S_SCAN)
920 0 : ieee80211_next_scan(&ic->ic_if);
921 0 : splx(s);
922 0 : }
923 :
924 : int
925 0 : rtwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
926 : {
927 0 : struct rtwn_softc *sc = ic->ic_softc;
928 : struct ieee80211_node *ni;
929 : enum ieee80211_state ostate;
930 : uint32_t reg;
931 : int s, error;
932 :
933 0 : s = splnet();
934 0 : ostate = ic->ic_state;
935 :
936 : if (nstate != ostate)
937 : DPRINTF(("newstate %s -> %s\n",
938 : ieee80211_state_name[ostate],
939 : ieee80211_state_name[nstate]));
940 :
941 0 : if (ostate == IEEE80211_S_RUN) {
942 : /* Stop calibration. */
943 0 : sc->sc_ops.cancel_calib(sc->sc_ops.cookie);
944 :
945 : /* Turn link LED off. */
946 0 : rtwn_set_led(sc, RTWN_LED_LINK, 0);
947 :
948 : /* Set media status to 'No Link'. */
949 0 : rtwn_set_nettype(sc, IEEE80211_M_MONITOR);
950 :
951 : /* Stop Rx of data frames. */
952 0 : rtwn_write_2(sc, R92C_RXFLTMAP2, 0);
953 :
954 : /* Rest TSF. */
955 0 : rtwn_write_1(sc, R92C_DUAL_TSF_RST, 0x03);
956 :
957 : /* Disable TSF synchronization. */
958 0 : rtwn_write_1(sc, R92C_BCN_CTRL,
959 0 : rtwn_read_1(sc, R92C_BCN_CTRL) |
960 : R92C_BCN_CTRL_DIS_TSF_UDT0);
961 :
962 : /* Reset EDCA parameters. */
963 0 : rtwn_edca_init(sc);
964 :
965 0 : rtwn_updateslot(ic);
966 0 : rtwn_update_short_preamble(ic);
967 :
968 : /* Disable 11b-only AP workaround (see rtwn_r88e_ra_init). */
969 0 : sc->sc_flags &= ~RTWN_FLAG_FORCE_RAID_11B;
970 0 : }
971 0 : switch (nstate) {
972 : case IEEE80211_S_INIT:
973 : /* Turn link LED off. */
974 0 : rtwn_set_led(sc, RTWN_LED_LINK, 0);
975 0 : break;
976 : case IEEE80211_S_SCAN:
977 0 : if (ostate != IEEE80211_S_SCAN) {
978 : /* Allow Rx from any BSSID. */
979 0 : rtwn_write_4(sc, R92C_RCR,
980 0 : rtwn_read_4(sc, R92C_RCR) &
981 : ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
982 :
983 : /* Set gain for scanning. */
984 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
985 0 : reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
986 0 : rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
987 :
988 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
989 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
990 0 : reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
991 0 : rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
992 0 : }
993 : }
994 :
995 : /* Make link LED blink during scan. */
996 0 : rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink);
997 :
998 : /* Pause AC Tx queues. */
999 0 : rtwn_write_1(sc, R92C_TXPAUSE,
1000 0 : rtwn_read_1(sc, R92C_TXPAUSE) | R92C_TXPAUSE_AC_VO |
1001 0 : R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE |
1002 : R92C_TXPAUSE_AC_BK);
1003 :
1004 0 : rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL);
1005 0 : sc->sc_ops.next_scan(sc->sc_ops.cookie);
1006 0 : break;
1007 :
1008 : case IEEE80211_S_AUTH:
1009 : /* Set initial gain under link. */
1010 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
1011 0 : reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
1012 0 : rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
1013 :
1014 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
1015 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
1016 0 : reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
1017 0 : rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
1018 0 : }
1019 :
1020 0 : rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL);
1021 0 : break;
1022 : case IEEE80211_S_ASSOC:
1023 : break;
1024 : case IEEE80211_S_RUN:
1025 0 : if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1026 0 : rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
1027 :
1028 : /* Enable Rx of data frames. */
1029 0 : rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
1030 :
1031 : /* Turn link LED on. */
1032 0 : rtwn_set_led(sc, RTWN_LED_LINK, 1);
1033 0 : break;
1034 : }
1035 0 : ni = ic->ic_bss;
1036 :
1037 : /* Set media status to 'Associated'. */
1038 0 : rtwn_set_nettype(sc, IEEE80211_M_STA);
1039 :
1040 : /* Set BSSID. */
1041 0 : rtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0]));
1042 0 : rtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4]));
1043 :
1044 0 : if (ic->ic_curmode == IEEE80211_MODE_11B)
1045 0 : rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
1046 : else /* 802.11b/g */
1047 0 : rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
1048 :
1049 0 : rtwn_updateslot(ic);
1050 0 : rtwn_update_short_preamble(ic);
1051 :
1052 : /* Enable Rx of data frames. */
1053 0 : rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
1054 :
1055 : /* Flush all AC queues. */
1056 0 : rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
1057 :
1058 : /* Set beacon interval. */
1059 0 : rtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
1060 :
1061 : /* Allow Rx from our BSSID only. */
1062 0 : rtwn_write_4(sc, R92C_RCR,
1063 0 : rtwn_read_4(sc, R92C_RCR) |
1064 0 : R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
1065 :
1066 : /* Enable TSF synchronization. */
1067 0 : rtwn_tsf_sync_enable(sc);
1068 :
1069 : /* Intialize rate adaptation. */
1070 0 : rtwn_ra_init(sc);
1071 :
1072 : /* Turn link LED on. */
1073 0 : rtwn_set_led(sc, RTWN_LED_LINK, 1);
1074 :
1075 0 : sc->avg_pwdb = -1; /* Reset average RSSI. */
1076 : /* Reset temperature calibration state machine. */
1077 0 : sc->thcal_state = 0;
1078 0 : sc->thcal_lctemp = 0;
1079 : /* Start periodic calibration. */
1080 0 : sc->sc_ops.next_calib(sc->sc_ops.cookie);
1081 0 : break;
1082 : }
1083 :
1084 0 : error = sc->sc_newstate(ic, nstate, arg);
1085 0 : splx(s);
1086 :
1087 0 : return (error);
1088 : }
1089 :
1090 : void
1091 0 : rtwn_update_short_preamble(struct ieee80211com *ic)
1092 : {
1093 0 : struct rtwn_softc *sc = ic->ic_softc;
1094 :
1095 0 : if (sc->chip & RTWN_CHIP_88E)
1096 0 : rtwn_r88e_update_short_preamble(sc);
1097 : else
1098 0 : rtwn_r92c_update_short_preamble(sc);
1099 0 : }
1100 :
1101 : void
1102 0 : rtwn_r92c_update_short_preamble(struct rtwn_softc *sc)
1103 : {
1104 : uint32_t reg;
1105 :
1106 0 : reg = rtwn_read_4(sc, R92C_RRSR);
1107 0 : if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
1108 0 : reg |= R92C_RRSR_SHORT;
1109 : else
1110 0 : reg &= ~R92C_RRSR_SHORT;
1111 0 : rtwn_write_4(sc, R92C_RRSR, reg);
1112 0 : }
1113 :
1114 : void
1115 0 : rtwn_r88e_update_short_preamble(struct rtwn_softc *sc)
1116 : {
1117 : uint32_t reg;
1118 :
1119 0 : reg = rtwn_read_4(sc, R92C_WMAC_TRXPTCL_CTL);
1120 0 : if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
1121 0 : reg |= R92C_WMAC_TRXPTCL_CTL_SHORT;
1122 : else
1123 0 : reg &= ~R92C_WMAC_TRXPTCL_CTL_SHORT;
1124 0 : rtwn_write_4(sc, R92C_WMAC_TRXPTCL_CTL, reg);
1125 0 : }
1126 :
1127 : void
1128 0 : rtwn_updateslot(struct ieee80211com *ic)
1129 : {
1130 0 : struct rtwn_softc *sc = ic->ic_softc;
1131 : int s;
1132 :
1133 0 : s = splnet();
1134 0 : if (ic->ic_flags & IEEE80211_F_SHSLOT)
1135 0 : rtwn_write_1(sc, R92C_SLOT, IEEE80211_DUR_DS_SHSLOT);
1136 : else
1137 0 : rtwn_write_1(sc, R92C_SLOT, IEEE80211_DUR_DS_SLOT);
1138 0 : splx(s);
1139 0 : }
1140 :
1141 : void
1142 0 : rtwn_updateedca(struct ieee80211com *ic)
1143 : {
1144 0 : struct rtwn_softc *sc = ic->ic_softc;
1145 : const uint16_t aci2reg[EDCA_NUM_AC] = {
1146 : R92C_EDCA_BE_PARAM,
1147 : R92C_EDCA_BK_PARAM,
1148 : R92C_EDCA_VI_PARAM,
1149 : R92C_EDCA_VO_PARAM
1150 : };
1151 : struct ieee80211_edca_ac_params *ac;
1152 : int s, aci, aifs, slottime;
1153 : uint8_t acm = 0;
1154 :
1155 0 : if (ic->ic_flags & IEEE80211_F_SHSLOT)
1156 0 : slottime = IEEE80211_DUR_DS_SHSLOT;
1157 : else
1158 : slottime = IEEE80211_DUR_DS_SLOT;
1159 0 : s = splnet();
1160 0 : for (aci = 0; aci < EDCA_NUM_AC; aci++) {
1161 0 : ac = &ic->ic_edca_ac[aci];
1162 : /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */
1163 0 : aifs = ac->ac_aifsn * slottime + IEEE80211_DUR_DS_SIFS;
1164 0 : rtwn_write_4(sc, aci2reg[aci],
1165 0 : SM(R92C_EDCA_PARAM_TXOP, ac->ac_txoplimit) |
1166 0 : SM(R92C_EDCA_PARAM_ECWMIN, ac->ac_ecwmin) |
1167 0 : SM(R92C_EDCA_PARAM_ECWMAX, ac->ac_ecwmax) |
1168 0 : SM(R92C_EDCA_PARAM_AIFS, aifs));
1169 :
1170 : /* Is admission control mandatory for this queue? */
1171 0 : if (ac->ac_acm) {
1172 0 : switch (aci) {
1173 : case EDCA_AC_BE:
1174 0 : acm |= R92C_ACMHW_BEQEN;
1175 0 : break;
1176 : case EDCA_AC_VI:
1177 0 : acm |= R92C_ACMHW_VIQEN;
1178 0 : break;
1179 : case EDCA_AC_VO:
1180 0 : acm |= R92C_ACMHW_VOQEN;
1181 0 : break;
1182 : default:
1183 : break;
1184 : }
1185 : }
1186 : }
1187 0 : splx(s);
1188 :
1189 : /* Enable hardware admission control. */
1190 0 : rtwn_write_1(sc, R92C_ACMHWCTRL, R92C_ACMHW_HWEN | acm);
1191 0 : }
1192 :
1193 : int
1194 0 : rtwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1195 : struct ieee80211_key *k)
1196 : {
1197 0 : struct rtwn_softc *sc = ic->ic_softc;
1198 : static const uint8_t etherzeroaddr[6] = { 0 };
1199 : const uint8_t *macaddr;
1200 0 : uint8_t keybuf[16], algo;
1201 : int i, entry;
1202 :
1203 : /* Defer setting of WEP keys until interface is brought up. */
1204 0 : if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
1205 : (IFF_UP | IFF_RUNNING))
1206 0 : return (0);
1207 :
1208 : /* Map net80211 cipher to HW crypto algorithm. */
1209 0 : switch (k->k_cipher) {
1210 : case IEEE80211_CIPHER_WEP40:
1211 : algo = R92C_CAM_ALGO_WEP40;
1212 0 : break;
1213 : case IEEE80211_CIPHER_WEP104:
1214 : algo = R92C_CAM_ALGO_WEP104;
1215 0 : break;
1216 : case IEEE80211_CIPHER_TKIP:
1217 : algo = R92C_CAM_ALGO_TKIP;
1218 0 : break;
1219 : case IEEE80211_CIPHER_CCMP:
1220 : algo = R92C_CAM_ALGO_AES;
1221 0 : break;
1222 : default:
1223 : /* Fallback to software crypto for other ciphers. */
1224 0 : return (ieee80211_set_key(ic, ni, k));
1225 : }
1226 0 : if (k->k_flags & IEEE80211_KEY_GROUP) {
1227 : macaddr = etherzeroaddr;
1228 0 : entry = k->k_id;
1229 0 : } else {
1230 0 : macaddr = ic->ic_bss->ni_macaddr;
1231 : entry = 4;
1232 : }
1233 : /* Write key. */
1234 0 : memset(keybuf, 0, sizeof(keybuf));
1235 0 : memcpy(keybuf, k->k_key, MIN(k->k_len, sizeof(keybuf)));
1236 0 : for (i = 0; i < 4; i++) {
1237 0 : rtwn_cam_write(sc, R92C_CAM_KEY(entry, i),
1238 0 : LE_READ_4(&keybuf[i * 4]));
1239 : }
1240 : /* Write CTL0 last since that will validate the CAM entry. */
1241 0 : rtwn_cam_write(sc, R92C_CAM_CTL1(entry),
1242 0 : LE_READ_4(&macaddr[2]));
1243 0 : rtwn_cam_write(sc, R92C_CAM_CTL0(entry),
1244 0 : SM(R92C_CAM_ALGO, algo) |
1245 0 : SM(R92C_CAM_KEYID, k->k_id) |
1246 0 : SM(R92C_CAM_MACLO, LE_READ_2(&macaddr[0])) |
1247 : R92C_CAM_VALID);
1248 :
1249 0 : return (0);
1250 0 : }
1251 :
1252 : void
1253 0 : rtwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1254 : struct ieee80211_key *k)
1255 : {
1256 0 : struct rtwn_softc *sc = ic->ic_softc;
1257 : int i, entry;
1258 :
1259 0 : if (!(ic->ic_if.if_flags & IFF_RUNNING) ||
1260 0 : ic->ic_state != IEEE80211_S_RUN)
1261 0 : return; /* Nothing to do. */
1262 :
1263 0 : if (k->k_flags & IEEE80211_KEY_GROUP)
1264 0 : entry = k->k_id;
1265 : else
1266 : entry = 4;
1267 0 : rtwn_cam_write(sc, R92C_CAM_CTL0(entry), 0);
1268 0 : rtwn_cam_write(sc, R92C_CAM_CTL1(entry), 0);
1269 : /* Clear key. */
1270 0 : for (i = 0; i < 4; i++)
1271 0 : rtwn_cam_write(sc, R92C_CAM_KEY(entry, i), 0);
1272 0 : }
1273 :
1274 : void
1275 0 : rtwn_update_avgrssi(struct rtwn_softc *sc, int rate, int8_t rssi)
1276 : {
1277 : int pwdb;
1278 :
1279 : /* Convert antenna signal to percentage. */
1280 0 : if (rssi <= -100 || rssi >= 20)
1281 0 : pwdb = 0;
1282 0 : else if (rssi >= 0)
1283 0 : pwdb = 100;
1284 : else
1285 0 : pwdb = 100 + rssi;
1286 0 : if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) {
1287 0 : if (rate <= 3) {
1288 : /* CCK gain is smaller than OFDM/MCS gain. */
1289 0 : pwdb += 6;
1290 0 : if (pwdb > 100)
1291 : pwdb = 100;
1292 0 : if (pwdb <= 14)
1293 0 : pwdb -= 4;
1294 0 : else if (pwdb <= 26)
1295 0 : pwdb -= 8;
1296 0 : else if (pwdb <= 34)
1297 0 : pwdb -= 6;
1298 0 : else if (pwdb <= 42)
1299 0 : pwdb -= 2;
1300 : }
1301 : }
1302 0 : if (sc->avg_pwdb == -1) /* Init. */
1303 0 : sc->avg_pwdb = pwdb;
1304 0 : else if (sc->avg_pwdb < pwdb)
1305 0 : sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1;
1306 : else
1307 0 : sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20);
1308 : DPRINTFN(4, ("PWDB=%d EMA=%d\n", pwdb, sc->avg_pwdb));
1309 0 : }
1310 :
1311 : int8_t
1312 0 : rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
1313 : {
1314 : static const int8_t cckoff[] = { 16, -12, -26, -46 };
1315 : struct r92c_rx_phystat *phy;
1316 : struct r92c_rx_cck *cck;
1317 : uint8_t rpt;
1318 : int8_t rssi;
1319 :
1320 0 : if (sc->chip & RTWN_CHIP_88E)
1321 0 : return rtwn_r88e_get_rssi(sc, rate, physt);
1322 :
1323 0 : if (rate <= 3) {
1324 0 : cck = (struct r92c_rx_cck *)physt;
1325 0 : if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) {
1326 0 : rpt = (cck->agc_rpt >> 5) & 0x3;
1327 0 : rssi = (cck->agc_rpt & 0x1f) << 1;
1328 0 : } else {
1329 0 : rpt = (cck->agc_rpt >> 6) & 0x3;
1330 0 : rssi = cck->agc_rpt & 0x3e;
1331 : }
1332 0 : rssi = cckoff[rpt] - rssi;
1333 0 : } else { /* OFDM/HT. */
1334 0 : phy = (struct r92c_rx_phystat *)physt;
1335 0 : rssi = ((letoh32(phy->phydw1) >> 1) & 0x7f) - 110;
1336 : }
1337 0 : return (rssi);
1338 0 : }
1339 :
1340 : int8_t
1341 0 : rtwn_r88e_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
1342 : {
1343 : static const int8_t cckoff[] = { 20, 14, 10, -4, -16, -22, -38, -40 };
1344 : struct r88e_rx_phystat *phy;
1345 : uint8_t rpt;
1346 : int8_t rssi;
1347 :
1348 0 : phy = (struct r88e_rx_phystat *)physt;
1349 :
1350 0 : if (rate <= 3) {
1351 0 : rpt = (phy->agc_rpt >> 5) & 0x7;
1352 0 : rssi = (phy->agc_rpt & 0x1f) << 1;
1353 0 : if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) {
1354 0 : if (rpt == 2)
1355 0 : rssi -= 6;
1356 : }
1357 0 : rssi = (phy->agc_rpt & 0x1f) > 27 ? -94 : cckoff[rpt] - rssi;
1358 0 : } else { /* OFDM/HT. */
1359 0 : rssi = ((le32toh(phy->sq_rpt) >> 1) & 0x7f) - 110;
1360 : }
1361 0 : return (rssi);
1362 : }
1363 :
1364 : void
1365 0 : rtwn_start(struct ifnet *ifp)
1366 : {
1367 0 : struct rtwn_softc *sc = ifp->if_softc;
1368 0 : struct ieee80211com *ic = &sc->sc_ic;
1369 0 : struct ieee80211_node *ni;
1370 : struct mbuf *m;
1371 :
1372 0 : if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
1373 0 : return;
1374 :
1375 0 : for (;;) {
1376 0 : if (sc->sc_ops.is_oactive(sc->sc_ops.cookie)) {
1377 0 : ifq_set_oactive(&ifp->if_snd);
1378 0 : break;
1379 : }
1380 : /* Send pending management frames first. */
1381 0 : m = mq_dequeue(&ic->ic_mgtq);
1382 0 : if (m != NULL) {
1383 0 : ni = m->m_pkthdr.ph_cookie;
1384 0 : goto sendit;
1385 : }
1386 0 : if (ic->ic_state != IEEE80211_S_RUN)
1387 : break;
1388 :
1389 : /* Encapsulate and send data frames. */
1390 0 : IFQ_DEQUEUE(&ifp->if_snd, m);
1391 0 : if (m == NULL)
1392 : break;
1393 : #if NBPFILTER > 0
1394 0 : if (ifp->if_bpf != NULL)
1395 0 : bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1396 : #endif
1397 0 : if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
1398 0 : continue;
1399 : sendit:
1400 : #if NBPFILTER > 0
1401 0 : if (ic->ic_rawbpf != NULL)
1402 0 : bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
1403 : #endif
1404 0 : if (sc->sc_ops.tx(sc->sc_ops.cookie, m, ni) != 0) {
1405 0 : ieee80211_release_node(ic, ni);
1406 0 : ifp->if_oerrors++;
1407 0 : continue;
1408 : }
1409 :
1410 0 : sc->sc_tx_timer = 5;
1411 0 : ifp->if_timer = 1;
1412 : }
1413 0 : }
1414 :
1415 : void
1416 0 : rtwn_watchdog(struct ifnet *ifp)
1417 : {
1418 0 : struct rtwn_softc *sc = ifp->if_softc;
1419 :
1420 0 : ifp->if_timer = 0;
1421 :
1422 0 : if (sc->sc_tx_timer > 0) {
1423 0 : if (--sc->sc_tx_timer == 0) {
1424 0 : printf("%s: device timeout\n", sc->sc_pdev->dv_xname);
1425 0 : task_add(systq, &sc->init_task);
1426 0 : ifp->if_oerrors++;
1427 0 : return;
1428 : }
1429 0 : ifp->if_timer = 1;
1430 0 : }
1431 0 : ieee80211_watchdog(ifp);
1432 0 : }
1433 :
1434 : int
1435 0 : rtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1436 : {
1437 0 : struct rtwn_softc *sc = ifp->if_softc;
1438 0 : struct ieee80211com *ic = &sc->sc_ic;
1439 : int s, error = 0;
1440 :
1441 0 : s = splnet();
1442 : /*
1443 : * Prevent processes from entering this function while another
1444 : * process is tsleep'ing in it.
1445 : */
1446 0 : while ((sc->sc_flags & RTWN_FLAG_BUSY) && error == 0)
1447 0 : error = tsleep(&sc->sc_flags, PCATCH, "rtwnioc", 0);
1448 0 : if (error != 0) {
1449 0 : splx(s);
1450 0 : return error;
1451 : }
1452 0 : sc->sc_flags |= RTWN_FLAG_BUSY;
1453 :
1454 0 : switch (cmd) {
1455 : case SIOCSIFADDR:
1456 0 : ifp->if_flags |= IFF_UP;
1457 : /* FALLTHROUGH */
1458 : case SIOCSIFFLAGS:
1459 0 : if (ifp->if_flags & IFF_UP) {
1460 0 : if (!(ifp->if_flags & IFF_RUNNING))
1461 0 : rtwn_init(ifp);
1462 : } else {
1463 0 : if (ifp->if_flags & IFF_RUNNING)
1464 0 : rtwn_stop(ifp);
1465 : }
1466 : break;
1467 : case SIOCS80211CHANNEL:
1468 0 : error = ieee80211_ioctl(ifp, cmd, data);
1469 0 : if (error == ENETRESET &&
1470 0 : ic->ic_opmode == IEEE80211_M_MONITOR) {
1471 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1472 : (IFF_UP | IFF_RUNNING))
1473 0 : rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
1474 : error = 0;
1475 0 : }
1476 : break;
1477 : default:
1478 0 : error = ieee80211_ioctl(ifp, cmd, data);
1479 0 : }
1480 :
1481 0 : if (error == ENETRESET) {
1482 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1483 : (IFF_UP | IFF_RUNNING)) {
1484 0 : rtwn_stop(ifp);
1485 0 : rtwn_init(ifp);
1486 0 : }
1487 : error = 0;
1488 0 : }
1489 0 : sc->sc_flags &= ~RTWN_FLAG_BUSY;
1490 0 : wakeup(&sc->sc_flags);
1491 0 : splx(s);
1492 :
1493 0 : return (error);
1494 0 : }
1495 :
1496 : void
1497 0 : rtwn_fw_reset(struct rtwn_softc *sc)
1498 : {
1499 0 : if (sc->chip & RTWN_CHIP_88E)
1500 0 : rtwn_r88e_fw_reset(sc);
1501 : else
1502 0 : rtwn_r92c_fw_reset(sc);
1503 0 : }
1504 :
1505 : void
1506 0 : rtwn_r92c_fw_reset(struct rtwn_softc *sc)
1507 : {
1508 0 : uint16_t reg;
1509 : int ntries;
1510 :
1511 : /* Tell 8051 to reset itself. */
1512 0 : rtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
1513 :
1514 : /* Wait until 8051 resets by itself. */
1515 0 : for (ntries = 0; ntries < 100; ntries++) {
1516 0 : reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
1517 0 : if (!(reg & R92C_SYS_FUNC_EN_CPUEN))
1518 : goto sleep;
1519 0 : DELAY(50);
1520 : }
1521 : /* Force 8051 reset. */
1522 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
1523 : sleep:
1524 0 : if (sc->chip & RTWN_CHIP_PCI) {
1525 : /*
1526 : * We must sleep for one second to let the firmware settle.
1527 : * Accessing registers too early will hang the whole system.
1528 : */
1529 0 : tsleep(®, 0, "rtwnrst", hz);
1530 0 : }
1531 0 : }
1532 :
1533 : void
1534 0 : rtwn_r88e_fw_reset(struct rtwn_softc *sc)
1535 : {
1536 : uint16_t reg;
1537 :
1538 : /* Reset MCU IO wrapper. */
1539 0 : rtwn_write_1(sc, R92C_RSV_CTRL + 1,
1540 0 : rtwn_read_1(sc, R92C_RSV_CTRL + 1) & ~R92C_RSV_CTRL_WLOCK_08);
1541 0 : reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
1542 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
1543 : /* Enable MCU IO wrapper. */
1544 0 : rtwn_write_1(sc, R92C_RSV_CTRL + 1,
1545 0 : rtwn_read_1(sc, R92C_RSV_CTRL) | R92C_RSV_CTRL_WLOCK_08);
1546 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
1547 0 : }
1548 :
1549 : int
1550 0 : rtwn_load_firmware(struct rtwn_softc *sc)
1551 : {
1552 : const struct r92c_fw_hdr *hdr;
1553 0 : u_char *fw, *ptr;
1554 0 : size_t len0, len;
1555 : uint32_t reg;
1556 : int mlen, ntries, page, error;
1557 :
1558 : /* Read firmware image from the filesystem. */
1559 0 : error = sc->sc_ops.load_firmware(sc->sc_ops.cookie, &fw, &len0);
1560 0 : if (error)
1561 0 : return (error);
1562 0 : len = len0;
1563 0 : if (len < sizeof(*hdr)) {
1564 0 : printf("%s: firmware too short\n", sc->sc_pdev->dv_xname);
1565 : error = EINVAL;
1566 0 : goto fail;
1567 : }
1568 0 : ptr = fw;
1569 0 : hdr = (const struct r92c_fw_hdr *)ptr;
1570 : /* Check if there is a valid FW header and skip it. */
1571 0 : if ((letoh16(hdr->signature) >> 4) == 0x88c ||
1572 0 : (letoh16(hdr->signature) >> 4) == 0x88e ||
1573 0 : (letoh16(hdr->signature) >> 4) == 0x92c) {
1574 : DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n",
1575 : letoh16(hdr->version), letoh16(hdr->subversion),
1576 : hdr->month, hdr->date, hdr->hour, hdr->minute));
1577 0 : ptr += sizeof(*hdr);
1578 0 : len -= sizeof(*hdr);
1579 0 : }
1580 :
1581 0 : if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) {
1582 0 : rtwn_write_1(sc, R92C_MCUFWDL, 0);
1583 0 : rtwn_fw_reset(sc);
1584 0 : }
1585 :
1586 0 : if (sc->chip & RTWN_CHIP_PCI) {
1587 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN,
1588 0 : rtwn_read_2(sc, R92C_SYS_FUNC_EN) | R92C_SYS_FUNC_EN_CPUEN);
1589 0 : }
1590 :
1591 : /* Enable FW download. */
1592 0 : rtwn_write_1(sc, R92C_MCUFWDL,
1593 0 : rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN);
1594 0 : rtwn_write_4(sc, R92C_MCUFWDL,
1595 0 : rtwn_read_4(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_ROM_DLEN);
1596 :
1597 : /* Reset the FWDL checksum. */
1598 0 : rtwn_write_1(sc, R92C_MCUFWDL,
1599 0 : rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT);
1600 :
1601 0 : for (page = 0; len > 0; page++) {
1602 0 : mlen = MIN(len, R92C_FW_PAGE_SIZE);
1603 0 : error = sc->sc_ops.fw_loadpage(sc->sc_ops.cookie, page, ptr,
1604 : mlen);
1605 0 : if (error != 0) {
1606 0 : printf("%s: could not load firmware page %d\n",
1607 0 : sc->sc_pdev->dv_xname, page);
1608 0 : goto fail;
1609 : }
1610 0 : ptr += mlen;
1611 0 : len -= mlen;
1612 : }
1613 :
1614 : /* Wait for checksum report. */
1615 0 : for (ntries = 0; ntries < 1000; ntries++) {
1616 0 : if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT)
1617 : break;
1618 0 : DELAY(5);
1619 : }
1620 0 : if (ntries == 1000) {
1621 0 : printf("%s: timeout waiting for checksum report\n",
1622 0 : sc->sc_pdev->dv_xname);
1623 : error = ETIMEDOUT;
1624 0 : goto fail;
1625 : }
1626 :
1627 : /* Disable FW download. */
1628 0 : rtwn_write_1(sc, R92C_MCUFWDL,
1629 0 : rtwn_read_1(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_EN);
1630 0 : rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
1631 :
1632 0 : reg = rtwn_read_4(sc, R92C_MCUFWDL);
1633 0 : reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY;
1634 0 : rtwn_write_4(sc, R92C_MCUFWDL, reg);
1635 0 : if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) {
1636 0 : reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
1637 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN,
1638 0 : reg & ~R92C_SYS_FUNC_EN_CPUEN);
1639 0 : rtwn_write_2(sc, R92C_SYS_FUNC_EN,
1640 0 : reg | R92C_SYS_FUNC_EN_CPUEN);
1641 0 : } else
1642 0 : rtwn_fw_reset(sc);
1643 : /* Wait for firmware readiness. */
1644 0 : for (ntries = 0; ntries < 1000; ntries++) {
1645 0 : if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
1646 : break;
1647 0 : DELAY(10);
1648 : }
1649 0 : if (ntries == 1000) {
1650 0 : printf("%s: timeout waiting for firmware readiness\n",
1651 0 : sc->sc_pdev->dv_xname);
1652 : error = ETIMEDOUT;
1653 0 : goto fail;
1654 : }
1655 : fail:
1656 0 : free(fw, M_DEVBUF, len0);
1657 0 : return (error);
1658 0 : }
1659 :
1660 : void
1661 0 : rtwn_rf_init(struct rtwn_softc *sc)
1662 : {
1663 : const struct r92c_rf_prog *prog;
1664 : uint32_t reg, type;
1665 : int i, j, idx, off;
1666 :
1667 : /* Select RF programming based on board type. */
1668 0 : if (sc->chip & RTWN_CHIP_88E)
1669 0 : prog = rtl8188eu_rf_prog;
1670 0 : else if (!(sc->chip & RTWN_CHIP_92C)) {
1671 0 : if (sc->board_type == R92C_BOARD_TYPE_MINICARD)
1672 0 : prog = rtl8188ce_rf_prog;
1673 0 : else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA)
1674 0 : prog = rtl8188ru_rf_prog;
1675 : else
1676 : prog = rtl8188cu_rf_prog;
1677 : } else
1678 : prog = rtl8192ce_rf_prog;
1679 :
1680 0 : for (i = 0; i < sc->nrxchains; i++) {
1681 : /* Save RF_ENV control type. */
1682 0 : idx = i / 2;
1683 0 : off = (i % 2) * 16;
1684 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
1685 0 : type = (reg >> off) & 0x10;
1686 :
1687 : /* Set RF_ENV enable. */
1688 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
1689 0 : reg |= 0x100000;
1690 0 : rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
1691 0 : DELAY(1);
1692 : /* Set RF_ENV output high. */
1693 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
1694 0 : reg |= 0x10;
1695 0 : rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
1696 0 : DELAY(1);
1697 : /* Set address and data lengths of RF registers. */
1698 0 : reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
1699 0 : reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH;
1700 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
1701 0 : DELAY(1);
1702 0 : reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
1703 0 : reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH;
1704 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
1705 0 : DELAY(1);
1706 :
1707 : /* Write RF initialization values for this chain. */
1708 0 : for (j = 0; j < prog[i].count; j++) {
1709 0 : if (prog[i].regs[j] >= 0xf9 &&
1710 0 : prog[i].regs[j] <= 0xfe) {
1711 : /*
1712 : * These are fake RF registers offsets that
1713 : * indicate a delay is required.
1714 : */
1715 0 : DELAY(50);
1716 0 : continue;
1717 : }
1718 0 : rtwn_rf_write(sc, i, prog[i].regs[j],
1719 0 : prog[i].vals[j]);
1720 0 : DELAY(1);
1721 0 : }
1722 :
1723 : /* Restore RF_ENV control type. */
1724 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
1725 0 : reg &= ~(0x10 << off) | (type << off);
1726 0 : rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg);
1727 :
1728 : /* Cache RF register CHNLBW. */
1729 0 : sc->rf_chnlbw[i] = rtwn_rf_read(sc, i, R92C_RF_CHNLBW);
1730 : }
1731 :
1732 0 : if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) ==
1733 : RTWN_CHIP_UMC_A_CUT) {
1734 0 : rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
1735 0 : rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
1736 0 : }
1737 0 : }
1738 :
1739 : void
1740 0 : rtwn_cam_init(struct rtwn_softc *sc)
1741 : {
1742 : /* Invalidate all CAM entries. */
1743 0 : rtwn_write_4(sc, R92C_CAMCMD,
1744 : R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
1745 0 : }
1746 :
1747 : void
1748 0 : rtwn_pa_bias_init(struct rtwn_softc *sc)
1749 : {
1750 : uint8_t reg;
1751 : int i;
1752 :
1753 0 : for (i = 0; i < sc->nrxchains; i++) {
1754 0 : if (sc->pa_setting & (1 << i))
1755 : continue;
1756 0 : rtwn_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
1757 0 : rtwn_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
1758 0 : rtwn_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
1759 0 : rtwn_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
1760 0 : }
1761 0 : if (!(sc->pa_setting & 0x10)) {
1762 0 : reg = rtwn_read_1(sc, 0x16);
1763 0 : reg = (reg & ~0xf0) | 0x90;
1764 0 : rtwn_write_1(sc, 0x16, reg);
1765 0 : }
1766 0 : }
1767 :
1768 : void
1769 0 : rtwn_rxfilter_init(struct rtwn_softc *sc)
1770 : {
1771 : /* Initialize Rx filter. */
1772 : /* TODO: use better filter for monitor mode. */
1773 0 : rtwn_write_4(sc, R92C_RCR,
1774 : R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB |
1775 : R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL |
1776 : R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS);
1777 : /* Accept all multicast frames. */
1778 0 : rtwn_write_4(sc, R92C_MAR + 0, 0xffffffff);
1779 0 : rtwn_write_4(sc, R92C_MAR + 4, 0xffffffff);
1780 : /* Accept all management frames. */
1781 0 : rtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff);
1782 : /* Reject all control frames. */
1783 0 : rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
1784 : /* Accept all data frames. */
1785 0 : rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
1786 0 : }
1787 :
1788 : void
1789 0 : rtwn_edca_init(struct rtwn_softc *sc)
1790 : {
1791 0 : struct ieee80211com *ic = &sc->sc_ic;
1792 : int mode, aci;
1793 :
1794 : /* Set SIFS; 0x10 = 16 usec (SIFS 11g), 0x0a = 10 usec (SIFS 11b) */
1795 0 : rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
1796 0 : rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
1797 0 : rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
1798 0 : rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
1799 0 : rtwn_write_2(sc, R92C_RESP_SIFS_CCK, 0x100a);
1800 0 : rtwn_write_2(sc, R92C_RESP_SIFS_OFDM, 0x100a);
1801 :
1802 0 : if (ic->ic_curmode == IEEE80211_MODE_AUTO)
1803 0 : mode = IEEE80211_MODE_11G; /* XXX */
1804 : else
1805 : mode = ic->ic_curmode;
1806 0 : for (aci = 0; aci < EDCA_NUM_AC; aci++)
1807 0 : memcpy(&ic->ic_edca_ac[aci], &ieee80211_edca_table[mode][aci],
1808 : sizeof(struct ieee80211_edca_ac_params));
1809 0 : rtwn_updateedca(ic);
1810 :
1811 0 : if (sc->chip & RTWN_CHIP_PCI) {
1812 : /* linux magic */
1813 0 : rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x086666);
1814 0 : }
1815 :
1816 0 : rtwn_write_4(sc, R92C_EDCA_RANDOM_GEN, arc4random());
1817 0 : }
1818 :
1819 : void
1820 0 : rtwn_rate_fallback_init(struct rtwn_softc *sc)
1821 : {
1822 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
1823 0 : if (sc->chip & RTWN_CHIP_PCI) {
1824 0 : rtwn_write_4(sc, R92C_DARFRC + 0, 0x01000000);
1825 0 : rtwn_write_4(sc, R92C_DARFRC + 4, 0x07060504);
1826 0 : rtwn_write_4(sc, R92C_RARFRC + 0, 0x01000000);
1827 0 : rtwn_write_4(sc, R92C_RARFRC + 4, 0x07060504);
1828 0 : } else if (sc->chip & RTWN_CHIP_USB) {
1829 0 : rtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000);
1830 0 : rtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404);
1831 0 : rtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201);
1832 0 : rtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605);
1833 0 : }
1834 : }
1835 0 : }
1836 :
1837 : void
1838 0 : rtwn_usb_aggr_init(struct rtwn_softc *sc)
1839 : {
1840 : uint32_t reg;
1841 : int dmasize, dmatiming, ndesc;
1842 :
1843 : dmasize = 48;
1844 : dmatiming = 4;
1845 0 : ndesc = (sc->chip & RTWN_CHIP_88E) ? 1 : 6;
1846 :
1847 : /* Tx aggregation setting. */
1848 0 : reg = rtwn_read_4(sc, R92C_TDECTRL);
1849 0 : reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, ndesc);
1850 0 : rtwn_write_4(sc, R92C_TDECTRL, reg);
1851 :
1852 : /* Rx aggregation setting. */
1853 0 : rtwn_write_1(sc, R92C_TRXDMA_CTRL,
1854 0 : rtwn_read_1(sc, R92C_TRXDMA_CTRL) |
1855 : R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
1856 0 : rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, dmasize);
1857 0 : if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C))
1858 0 : rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, dmatiming);
1859 : else
1860 0 : rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, dmatiming);
1861 0 : }
1862 :
1863 : void
1864 0 : rtwn_write_txpower(struct rtwn_softc *sc, int chain,
1865 : uint16_t power[RTWN_POWER_COUNT])
1866 : {
1867 : uint32_t reg;
1868 :
1869 : /* Write per-CCK rate Tx power. */
1870 0 : if (chain == 0) {
1871 0 : reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
1872 0 : reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_POWER_CCK1]);
1873 0 : rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
1874 0 : reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
1875 0 : reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_POWER_CCK2]);
1876 0 : reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_POWER_CCK55]);
1877 0 : reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_POWER_CCK11]);
1878 0 : rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
1879 0 : } else {
1880 0 : reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
1881 0 : reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_POWER_CCK1]);
1882 0 : reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_POWER_CCK2]);
1883 0 : reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_POWER_CCK55]);
1884 0 : rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
1885 0 : reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
1886 0 : reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_POWER_CCK11]);
1887 0 : rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
1888 : }
1889 : /* Write per-OFDM rate Tx power. */
1890 0 : rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
1891 0 : SM(R92C_TXAGC_RATE06, power[RTWN_POWER_OFDM6]) |
1892 0 : SM(R92C_TXAGC_RATE09, power[RTWN_POWER_OFDM9]) |
1893 0 : SM(R92C_TXAGC_RATE12, power[RTWN_POWER_OFDM12]) |
1894 0 : SM(R92C_TXAGC_RATE18, power[RTWN_POWER_OFDM18]));
1895 0 : rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
1896 0 : SM(R92C_TXAGC_RATE24, power[RTWN_POWER_OFDM24]) |
1897 0 : SM(R92C_TXAGC_RATE36, power[RTWN_POWER_OFDM36]) |
1898 0 : SM(R92C_TXAGC_RATE48, power[RTWN_POWER_OFDM48]) |
1899 0 : SM(R92C_TXAGC_RATE54, power[RTWN_POWER_OFDM54]));
1900 : /* Write per-MCS Tx power. */
1901 0 : rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
1902 0 : SM(R92C_TXAGC_MCS00, power[RTWN_POWER_MCS( 0)]) |
1903 0 : SM(R92C_TXAGC_MCS01, power[RTWN_POWER_MCS( 1)]) |
1904 0 : SM(R92C_TXAGC_MCS02, power[RTWN_POWER_MCS( 2)]) |
1905 0 : SM(R92C_TXAGC_MCS03, power[RTWN_POWER_MCS( 3)]));
1906 0 : rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
1907 0 : SM(R92C_TXAGC_MCS04, power[RTWN_POWER_MCS( 4)]) |
1908 0 : SM(R92C_TXAGC_MCS05, power[RTWN_POWER_MCS( 5)]) |
1909 0 : SM(R92C_TXAGC_MCS06, power[RTWN_POWER_MCS( 6)]) |
1910 0 : SM(R92C_TXAGC_MCS07, power[RTWN_POWER_MCS( 7)]));
1911 0 : if (sc->ntxchains > 1) {
1912 0 : rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
1913 0 : SM(R92C_TXAGC_MCS08, power[RTWN_POWER_MCS( 8)]) |
1914 0 : SM(R92C_TXAGC_MCS09, power[RTWN_POWER_MCS( 9)]) |
1915 0 : SM(R92C_TXAGC_MCS10, power[RTWN_POWER_MCS(10)]) |
1916 0 : SM(R92C_TXAGC_MCS11, power[RTWN_POWER_MCS(11)]));
1917 0 : rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
1918 0 : SM(R92C_TXAGC_MCS12, power[RTWN_POWER_MCS(12)]) |
1919 0 : SM(R92C_TXAGC_MCS13, power[RTWN_POWER_MCS(13)]) |
1920 0 : SM(R92C_TXAGC_MCS14, power[RTWN_POWER_MCS(14)]) |
1921 0 : SM(R92C_TXAGC_MCS15, power[RTWN_POWER_MCS(15)]));
1922 0 : }
1923 0 : }
1924 :
1925 : void
1926 0 : rtwn_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
1927 : struct ieee80211_channel *extc, uint16_t power[RTWN_POWER_COUNT])
1928 : {
1929 0 : if (sc->chip & RTWN_CHIP_88E)
1930 0 : rtwn_r88e_get_txpower(sc, chain, c, extc, power);
1931 : else
1932 0 : rtwn_r92c_get_txpower(sc, chain, c, extc, power);
1933 0 : }
1934 :
1935 : void
1936 0 : rtwn_r92c_get_txpower(struct rtwn_softc *sc, int chain,
1937 : struct ieee80211_channel *c, struct ieee80211_channel *extc,
1938 : uint16_t power[RTWN_POWER_COUNT])
1939 : {
1940 0 : struct ieee80211com *ic = &sc->sc_ic;
1941 0 : struct r92c_rom *rom = &sc->sc_r92c_rom;
1942 : uint16_t cckpow, ofdmpow, htpow, diff, max;
1943 : const struct r92c_txpwr *base;
1944 : int ridx, chan, group;
1945 :
1946 : /* Determine channel group. */
1947 0 : chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
1948 0 : if (chan <= 3)
1949 0 : group = 0;
1950 0 : else if (chan <= 9)
1951 0 : group = 1;
1952 : else
1953 : group = 2;
1954 :
1955 : /* Get original Tx power based on board type and RF chain. */
1956 0 : if (!(sc->chip & RTWN_CHIP_92C)) {
1957 0 : if (sc->board_type == R92C_BOARD_TYPE_HIGHPA)
1958 0 : base = &rtl8188ru_txagc[chain];
1959 : else
1960 0 : base = &rtl8192cu_txagc[chain];
1961 : } else
1962 0 : base = &rtl8192cu_txagc[chain];
1963 :
1964 0 : memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
1965 0 : if (sc->regulatory == 0) {
1966 0 : for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
1967 0 : power[ridx] = base->pwr[0][ridx];
1968 : }
1969 0 : for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_MAX; ridx++) {
1970 0 : if (sc->regulatory == 3) {
1971 0 : power[ridx] = base->pwr[0][ridx];
1972 : /* Apply vendor limits. */
1973 0 : if (extc != NULL)
1974 0 : max = rom->ht40_max_pwr[group];
1975 : else
1976 0 : max = rom->ht20_max_pwr[group];
1977 0 : max = (max >> (chain * 4)) & 0xf;
1978 0 : if (power[ridx] > max)
1979 0 : power[ridx] = max;
1980 0 : } else if (sc->regulatory == 1) {
1981 0 : if (extc == NULL)
1982 0 : power[ridx] = base->pwr[group][ridx];
1983 0 : } else if (sc->regulatory != 2)
1984 0 : power[ridx] = base->pwr[0][ridx];
1985 : }
1986 :
1987 : /* Compute per-CCK rate Tx power. */
1988 0 : cckpow = rom->cck_tx_pwr[chain][group];
1989 0 : for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
1990 0 : power[ridx] += cckpow;
1991 0 : if (power[ridx] > R92C_MAX_TX_PWR)
1992 0 : power[ridx] = R92C_MAX_TX_PWR;
1993 : }
1994 :
1995 0 : htpow = rom->ht40_1s_tx_pwr[chain][group];
1996 0 : if (sc->ntxchains > 1) {
1997 : /* Apply reduction for 2 spatial streams. */
1998 0 : diff = rom->ht40_2s_tx_pwr_diff[group];
1999 0 : diff = (diff >> (chain * 4)) & 0xf;
2000 0 : htpow = (htpow > diff) ? htpow - diff : 0;
2001 0 : }
2002 :
2003 : /* Compute per-OFDM rate Tx power. */
2004 0 : diff = rom->ofdm_tx_pwr_diff[group];
2005 0 : diff = (diff >> (chain * 4)) & 0xf;
2006 0 : ofdmpow = htpow + diff; /* HT->OFDM correction. */
2007 0 : for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
2008 0 : power[ridx] += ofdmpow;
2009 0 : if (power[ridx] > R92C_MAX_TX_PWR)
2010 0 : power[ridx] = R92C_MAX_TX_PWR;
2011 : }
2012 :
2013 : /* Compute per-MCS Tx power. */
2014 0 : if (extc == NULL) {
2015 0 : diff = rom->ht20_tx_pwr_diff[group];
2016 0 : diff = (diff >> (chain * 4)) & 0xf;
2017 0 : htpow += diff; /* HT40->HT20 correction. */
2018 0 : }
2019 0 : for (ridx = RTWN_RIDX_MCS0; ridx <= RTWN_RIDX_MCS15; ridx++) {
2020 0 : power[ridx] += htpow;
2021 0 : if (power[ridx] > R92C_MAX_TX_PWR)
2022 0 : power[ridx] = R92C_MAX_TX_PWR;
2023 : }
2024 : #ifdef RTWN_DEBUG
2025 : if (rtwn_debug >= 4) {
2026 : /* Dump per-rate Tx power values. */
2027 : printf("Tx power for chain %d:\n", chain);
2028 : for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_MAX; ridx++)
2029 : printf("Rate %d = %u\n", ridx, power[ridx]);
2030 : }
2031 : #endif
2032 0 : }
2033 :
2034 : void
2035 0 : rtwn_r88e_get_txpower(struct rtwn_softc *sc, int chain,
2036 : struct ieee80211_channel *c, struct ieee80211_channel *extc,
2037 : uint16_t power[RTWN_POWER_COUNT])
2038 : {
2039 0 : struct ieee80211com *ic = &sc->sc_ic;
2040 0 : struct r88e_rom *rom = &sc->sc_r88e_rom;
2041 : uint8_t cckpow, htpow, ofdmpow;
2042 : int8_t diff;
2043 : int ridx, chan, group;
2044 :
2045 : /* Determine channel group. */
2046 0 : chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
2047 0 : if (chan <= 2)
2048 0 : group = 0;
2049 0 : else if (chan <= 5)
2050 0 : group = 1;
2051 0 : else if (chan <= 8)
2052 0 : group = 2;
2053 0 : else if (chan <= 11)
2054 0 : group = 3;
2055 0 : else if (chan <= 13)
2056 0 : group = 4;
2057 : else
2058 : group = 5;
2059 :
2060 0 : memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
2061 :
2062 : /* Compute per-CCK rate Tx power. */
2063 0 : cckpow = rom->txpwr.cck_tx_pwr[group];
2064 0 : for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
2065 0 : power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow;
2066 0 : if (power[ridx] > R92C_MAX_TX_PWR)
2067 0 : power[ridx] = R92C_MAX_TX_PWR;
2068 : }
2069 :
2070 0 : htpow = (group == 5) ? rom->txpwr.ht40_tx_pwr[group - 1] :
2071 0 : rom->txpwr.ht40_tx_pwr[group];
2072 :
2073 : /* Compute per-OFDM rate Tx power. */
2074 0 : diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
2075 : R88E_ROM_TXPWR_OFDM_DIFF));
2076 0 : ofdmpow = htpow + diff;
2077 0 : for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
2078 0 : power[ridx] = ofdmpow;
2079 0 : if (power[ridx] > R92C_MAX_TX_PWR)
2080 0 : power[ridx] = R92C_MAX_TX_PWR;
2081 : }
2082 :
2083 : /* Compute per-MCS Tx power. */
2084 0 : if (extc == NULL) {
2085 0 : diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
2086 : R88E_ROM_TXPWR_HT20_DIFF));
2087 0 : htpow += diff;
2088 0 : }
2089 0 : for (ridx = RTWN_RIDX_MCS0; ridx < RTWN_RIDX_MCS8; ridx++) {
2090 0 : power[ridx] = htpow;
2091 0 : if (power[ridx] > R92C_MAX_TX_PWR)
2092 0 : power[ridx] = R92C_MAX_TX_PWR;
2093 : }
2094 0 : }
2095 :
2096 : void
2097 0 : rtwn_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c,
2098 : struct ieee80211_channel *extc)
2099 : {
2100 0 : uint16_t power[RTWN_POWER_COUNT];
2101 : int i;
2102 :
2103 0 : for (i = 0; i < sc->ntxchains; i++) {
2104 : /* Compute per-rate Tx power values. */
2105 0 : rtwn_get_txpower(sc, i, c, extc, power);
2106 : /* Write per-rate Tx power values to hardware. */
2107 0 : rtwn_write_txpower(sc, i, power);
2108 : }
2109 0 : }
2110 :
2111 : void
2112 0 : rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
2113 : struct ieee80211_channel *extc)
2114 : {
2115 0 : struct ieee80211com *ic = &sc->sc_ic;
2116 : u_int chan;
2117 : int i;
2118 :
2119 0 : chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
2120 :
2121 : /* Set Tx power for this new channel. */
2122 0 : rtwn_set_txpower(sc, c, extc);
2123 :
2124 0 : for (i = 0; i < sc->nrxchains; i++) {
2125 0 : rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
2126 0 : RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
2127 : }
2128 0 : if (extc != NULL) {
2129 : uint32_t reg;
2130 :
2131 : /* Is secondary channel below or above primary? */
2132 0 : int prichlo = c->ic_freq < extc->ic_freq;
2133 :
2134 0 : rtwn_write_1(sc, R92C_BWOPMODE,
2135 0 : rtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ);
2136 :
2137 0 : reg = rtwn_read_1(sc, R92C_RRSR + 2);
2138 0 : reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5;
2139 0 : rtwn_write_1(sc, R92C_RRSR + 2, reg);
2140 :
2141 0 : rtwn_bb_write(sc, R92C_FPGA0_RFMOD,
2142 0 : rtwn_bb_read(sc, R92C_FPGA0_RFMOD) | R92C_RFMOD_40MHZ);
2143 0 : rtwn_bb_write(sc, R92C_FPGA1_RFMOD,
2144 0 : rtwn_bb_read(sc, R92C_FPGA1_RFMOD) | R92C_RFMOD_40MHZ);
2145 :
2146 : /* Set CCK side band. */
2147 0 : reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM);
2148 0 : reg = (reg & ~0x00000010) | (prichlo ? 0 : 1) << 4;
2149 0 : rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg);
2150 :
2151 0 : reg = rtwn_bb_read(sc, R92C_OFDM1_LSTF);
2152 0 : reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10;
2153 0 : rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
2154 :
2155 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
2156 0 : rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
2157 0 : rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) &
2158 : ~R92C_FPGA0_ANAPARAM2_CBW20);
2159 0 : }
2160 :
2161 0 : reg = rtwn_bb_read(sc, 0x818);
2162 0 : reg = (reg & ~0x0c000000) | (prichlo ? 2 : 1) << 26;
2163 0 : rtwn_bb_write(sc, 0x818, reg);
2164 :
2165 : /* Select 40MHz bandwidth. */
2166 0 : rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
2167 0 : (sc->rf_chnlbw[0] & ~0xfff) | chan);
2168 0 : } else {
2169 0 : rtwn_write_1(sc, R92C_BWOPMODE,
2170 0 : rtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ);
2171 :
2172 0 : rtwn_bb_write(sc, R92C_FPGA0_RFMOD,
2173 0 : rtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ);
2174 0 : rtwn_bb_write(sc, R92C_FPGA1_RFMOD,
2175 0 : rtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ);
2176 :
2177 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
2178 0 : rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
2179 0 : rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) |
2180 : R92C_FPGA0_ANAPARAM2_CBW20);
2181 0 : }
2182 :
2183 : /* Select 20MHz bandwidth. */
2184 0 : rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
2185 0 : (sc->rf_chnlbw[0] & ~0xfff) | chan |
2186 0 : ((sc->chip & RTWN_CHIP_88E) ? R88E_RF_CHNLBW_BW20 :
2187 : R92C_RF_CHNLBW_BW20));
2188 : }
2189 0 : }
2190 :
2191 : int
2192 0 : rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
2193 : uint16_t rx[2])
2194 : {
2195 : uint32_t status;
2196 0 : int offset = chain * 0x20;
2197 :
2198 0 : if (chain == 0) { /* IQ calibration for chain 0. */
2199 : /* IQ calibration settings for chain 0. */
2200 0 : rtwn_bb_write(sc, 0xe30, 0x10008c1f);
2201 0 : rtwn_bb_write(sc, 0xe34, 0x10008c1f);
2202 0 : rtwn_bb_write(sc, 0xe38, 0x82140102);
2203 :
2204 0 : if (sc->ntxchains > 1) {
2205 0 : rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */
2206 : /* IQ calibration settings for chain 1. */
2207 0 : rtwn_bb_write(sc, 0xe50, 0x10008c22);
2208 0 : rtwn_bb_write(sc, 0xe54, 0x10008c22);
2209 0 : rtwn_bb_write(sc, 0xe58, 0x82140102);
2210 0 : rtwn_bb_write(sc, 0xe5c, 0x28160202);
2211 0 : } else
2212 0 : rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */
2213 :
2214 : /* LO calibration settings. */
2215 0 : rtwn_bb_write(sc, 0xe4c, 0x001028d1);
2216 : /* We're doing LO and IQ calibration in one shot. */
2217 0 : rtwn_bb_write(sc, 0xe48, 0xf9000000);
2218 0 : rtwn_bb_write(sc, 0xe48, 0xf8000000);
2219 :
2220 0 : } else { /* IQ calibration for chain 1. */
2221 : /* We're doing LO and IQ calibration in one shot. */
2222 0 : rtwn_bb_write(sc, 0xe60, 0x00000002);
2223 0 : rtwn_bb_write(sc, 0xe60, 0x00000000);
2224 : }
2225 :
2226 : /* Give LO and IQ calibrations the time to complete. */
2227 0 : DELAY(1000);
2228 :
2229 : /* Read IQ calibration status. */
2230 0 : status = rtwn_bb_read(sc, 0xeac);
2231 :
2232 0 : if (status & (1 << (28 + chain * 3)))
2233 0 : return (0); /* Tx failed. */
2234 : /* Read Tx IQ calibration results. */
2235 0 : tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
2236 0 : tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
2237 0 : if (tx[0] == 0x142 || tx[1] == 0x042)
2238 0 : return (0); /* Tx failed. */
2239 :
2240 0 : if (status & (1 << (27 + chain * 3)))
2241 0 : return (1); /* Rx failed. */
2242 : /* Read Rx IQ calibration results. */
2243 0 : rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
2244 0 : rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
2245 0 : if (rx[0] == 0x132 || rx[1] == 0x036)
2246 0 : return (1); /* Rx failed. */
2247 :
2248 0 : return (3); /* Both Tx and Rx succeeded. */
2249 0 : }
2250 :
2251 : void
2252 0 : rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
2253 : uint16_t rx[2][2], struct rtwn_iq_cal_regs *iq_cal_regs)
2254 : {
2255 : static const uint16_t reg_adda[16] = {
2256 : 0x85c, 0xe6c, 0xe70, 0xe74,
2257 : 0xe78, 0xe7c, 0xe80, 0xe84,
2258 : 0xe88, 0xe8c, 0xed0, 0xed4,
2259 : 0xed8, 0xedc, 0xee0, 0xeec
2260 : };
2261 : int i, chain;
2262 : uint32_t hssi_param1;
2263 :
2264 0 : if (n == 0) {
2265 0 : for (i = 0; i < nitems(reg_adda); i++)
2266 0 : iq_cal_regs->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
2267 :
2268 0 : iq_cal_regs->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
2269 0 : iq_cal_regs->bcn_ctrl = rtwn_read_1(sc, R92C_BCN_CTRL);
2270 0 : iq_cal_regs->bcn_ctrl1 = rtwn_read_1(sc, R92C_BCN_CTRL1);
2271 0 : iq_cal_regs->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
2272 0 : }
2273 :
2274 0 : if (sc->ntxchains == 1) {
2275 0 : rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
2276 0 : for (i = 1; i < nitems(reg_adda); i++)
2277 0 : rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
2278 : } else {
2279 0 : for (i = 0; i < nitems(reg_adda); i++)
2280 0 : rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
2281 : }
2282 :
2283 0 : hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
2284 0 : if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
2285 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
2286 0 : hssi_param1 | R92C_HSSI_PARAM1_PI);
2287 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
2288 : hssi_param1 | R92C_HSSI_PARAM1_PI);
2289 0 : }
2290 :
2291 0 : if (n == 0) {
2292 0 : iq_cal_regs->ofdm0_trxpathena =
2293 0 : rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
2294 0 : iq_cal_regs->ofdm0_trmuxpar =
2295 0 : rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
2296 0 : iq_cal_regs->fpga0_rfifacesw1 =
2297 0 : rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
2298 0 : }
2299 :
2300 0 : rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
2301 0 : rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
2302 0 : rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
2303 0 : if (sc->ntxchains > 1) {
2304 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
2305 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
2306 0 : }
2307 :
2308 0 : rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_AC_VO |
2309 : R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE | R92C_TXPAUSE_AC_BK |
2310 : R92C_TXPAUSE_MGNT | R92C_TXPAUSE_HIGH);
2311 0 : rtwn_write_1(sc, R92C_BCN_CTRL,
2312 0 : iq_cal_regs->bcn_ctrl & ~(R92C_BCN_CTRL_EN_BCN));
2313 0 : rtwn_write_1(sc, R92C_BCN_CTRL1,
2314 0 : iq_cal_regs->bcn_ctrl1 & ~(R92C_BCN_CTRL_EN_BCN));
2315 0 : rtwn_write_1(sc, R92C_GPIO_MUXCFG,
2316 0 : iq_cal_regs->gpio_muxcfg & ~(R92C_GPIO_MUXCFG_ENBT));
2317 :
2318 0 : rtwn_bb_write(sc, 0x0b68, 0x00080000);
2319 0 : if (sc->ntxchains > 1)
2320 0 : rtwn_bb_write(sc, 0x0b6c, 0x00080000);
2321 :
2322 0 : rtwn_bb_write(sc, 0x0e28, 0x80800000);
2323 0 : rtwn_bb_write(sc, 0x0e40, 0x01007c00);
2324 0 : rtwn_bb_write(sc, 0x0e44, 0x01004800);
2325 :
2326 0 : rtwn_bb_write(sc, 0x0b68, 0x00080000);
2327 :
2328 0 : for (chain = 0; chain < sc->ntxchains; chain++) {
2329 0 : if (chain > 0) {
2330 : /* Put chain 0 on standby. */
2331 0 : rtwn_bb_write(sc, 0x0e28, 0x00);
2332 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
2333 0 : rtwn_bb_write(sc, 0x0e28, 0x80800000);
2334 :
2335 : /* Enable chain 1. */
2336 0 : for (i = 0; i < nitems(reg_adda); i++)
2337 0 : rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
2338 : }
2339 :
2340 : /* Run IQ calibration twice. */
2341 0 : for (i = 0; i < 2; i++) {
2342 : int ret;
2343 :
2344 0 : ret = rtwn_iq_calib_chain(sc, chain,
2345 0 : tx[chain], rx[chain]);
2346 0 : if (ret == 0) {
2347 : DPRINTF(("%s: chain %d: Tx failed.\n",
2348 : __func__, chain));
2349 0 : tx[chain][0] = 0xff;
2350 0 : tx[chain][1] = 0xff;
2351 0 : rx[chain][0] = 0xff;
2352 0 : rx[chain][1] = 0xff;
2353 0 : } else if (ret == 1) {
2354 : DPRINTF(("%s: chain %d: Rx failed.\n",
2355 : __func__, chain));
2356 0 : rx[chain][0] = 0xff;
2357 0 : rx[chain][1] = 0xff;
2358 0 : } else if (ret == 3) {
2359 : DPRINTF(("%s: chain %d: Both Tx and Rx "
2360 : "succeeded.\n", __func__, chain));
2361 : }
2362 : }
2363 :
2364 : DPRINTF(("%s: results for run %d chain %d: tx[0]=0x%x, "
2365 : "tx[1]=0x%x rx[0]=0x%x rx[1]=0x%x\n", __func__, n, chain,
2366 : tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]));
2367 : }
2368 :
2369 0 : rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
2370 0 : iq_cal_regs->ofdm0_trxpathena);
2371 0 : rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
2372 0 : iq_cal_regs->fpga0_rfifacesw1);
2373 0 : rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, iq_cal_regs->ofdm0_trmuxpar);
2374 :
2375 0 : rtwn_bb_write(sc, 0x0e28, 0x00);
2376 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
2377 0 : if (sc->ntxchains > 1)
2378 0 : rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
2379 :
2380 0 : if (n != 0) {
2381 0 : if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
2382 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
2383 0 : rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
2384 0 : }
2385 :
2386 0 : for (i = 0; i < nitems(reg_adda); i++)
2387 0 : rtwn_bb_write(sc, reg_adda[i], iq_cal_regs->adda[i]);
2388 :
2389 0 : rtwn_write_1(sc, R92C_TXPAUSE, iq_cal_regs->txpause);
2390 0 : rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs->bcn_ctrl);
2391 0 : rtwn_write_1(sc, R92C_BCN_CTRL1, iq_cal_regs->bcn_ctrl1);
2392 0 : rtwn_write_4(sc, R92C_GPIO_MUXCFG, iq_cal_regs->gpio_muxcfg);
2393 0 : }
2394 0 : }
2395 :
2396 : #define RTWN_IQ_CAL_MAX_TOLERANCE 5
2397 : int
2398 0 : rtwn_iq_calib_compare_results(uint16_t tx1[2][2], uint16_t rx1[2][2],
2399 : uint16_t tx2[2][2], uint16_t rx2[2][2], int ntxchains)
2400 : {
2401 0 : int chain, i, tx_ok[2], rx_ok[2];
2402 :
2403 0 : tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
2404 0 : for (chain = 0; chain < ntxchains; chain++) {
2405 0 : for (i = 0; i < 2; i++) {
2406 0 : if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
2407 0 : rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
2408 : continue;
2409 :
2410 0 : tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
2411 : RTWN_IQ_CAL_MAX_TOLERANCE);
2412 :
2413 0 : rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
2414 : RTWN_IQ_CAL_MAX_TOLERANCE);
2415 0 : }
2416 : }
2417 :
2418 0 : if (ntxchains > 1)
2419 0 : return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
2420 : else
2421 0 : return (tx_ok[0] && rx_ok[0]);
2422 0 : }
2423 : #undef RTWN_IQ_CAL_MAX_TOLERANCE
2424 :
2425 : void
2426 0 : rtwn_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
2427 : uint16_t rx[2], int chain)
2428 : {
2429 : uint32_t reg, val, x;
2430 : long y, tx_c;
2431 :
2432 0 : if (tx[0] == 0xff || tx[1] == 0xff)
2433 0 : return;
2434 :
2435 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
2436 0 : val = ((reg >> 22) & 0x3ff);
2437 0 : x = tx[0];
2438 0 : if (x & 0x00000200)
2439 0 : x |= 0xfffffc00;
2440 0 : reg &= ~0x3ff;
2441 0 : reg |= (((x * val) >> 8) & 0x3ff);
2442 0 : rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg);
2443 :
2444 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
2445 0 : if (((x * val) >> 7) & 0x01)
2446 0 : reg |= 0x80000000;
2447 : else
2448 0 : reg &= ~0x80000000;
2449 0 : rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
2450 :
2451 0 : y = tx[1];
2452 0 : if (y & 0x00000200)
2453 0 : y |= 0xfffffc00;
2454 0 : tx_c = (y * val) >> 8;
2455 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_TXAFE(chain));
2456 0 : reg &= ~0xf0000000;
2457 0 : reg |= ((tx_c & 0x3c0) << 22);
2458 0 : rtwn_bb_write(sc, R92C_OFDM0_TXAFE(chain), reg);
2459 :
2460 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
2461 0 : reg &= ~0x003f0000;
2462 0 : reg |= ((tx_c & 0x3f) << 16);
2463 0 : rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg);
2464 :
2465 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
2466 0 : if (((y * val) >> 7) & 0x01)
2467 0 : reg |= 0x20000000;
2468 : else
2469 0 : reg &= ~0x20000000;
2470 0 : rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
2471 :
2472 0 : if (rx[0] == 0xff || rx[1] == 0xff)
2473 0 : return;
2474 :
2475 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQIMBALANCE(chain));
2476 0 : reg &= ~0x3ff;
2477 0 : reg |= (rx[0] & 0x3ff);
2478 0 : rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg);
2479 :
2480 0 : reg &= ~0xfc00;
2481 0 : reg |= ((rx[1] & 0x03f) << 10);
2482 0 : rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg);
2483 :
2484 0 : if (chain == 0) {
2485 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQEXTANTA);
2486 0 : reg &= ~0xf0000000;
2487 0 : reg |= ((rx[1] & 0x3c0) << 22);
2488 0 : rtwn_bb_write(sc, R92C_OFDM0_RXIQEXTANTA, reg);
2489 0 : } else {
2490 0 : reg = rtwn_bb_read(sc, R92C_OFDM0_AGCRSSITABLE);
2491 0 : reg &= ~0xf000;
2492 0 : reg |= ((rx[1] & 0x3c0) << 6);
2493 0 : rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, reg);
2494 : }
2495 0 : }
2496 :
2497 : #define RTWN_IQ_CAL_NRUN 3
2498 : void
2499 0 : rtwn_iq_calib(struct rtwn_softc *sc)
2500 : {
2501 0 : uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
2502 : int n, valid;
2503 0 : struct rtwn_iq_cal_regs regs;
2504 :
2505 : valid = 0;
2506 0 : memset(®s, 0, sizeof(regs));
2507 0 : for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
2508 0 : rtwn_iq_calib_run(sc, n, tx[n], rx[n], ®s);
2509 :
2510 0 : if (n == 0)
2511 : continue;
2512 :
2513 : /* Valid results remain stable after consecutive runs. */
2514 0 : valid = rtwn_iq_calib_compare_results(tx[n - 1], rx[n - 1],
2515 0 : tx[n], rx[n], sc->ntxchains);
2516 0 : if (valid)
2517 : break;
2518 : }
2519 :
2520 0 : if (valid) {
2521 0 : rtwn_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
2522 0 : if (sc->ntxchains > 1)
2523 0 : rtwn_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
2524 : }
2525 0 : }
2526 : #undef RTWN_IQ_CAL_NRUN
2527 :
2528 : void
2529 0 : rtwn_lc_calib(struct rtwn_softc *sc)
2530 : {
2531 0 : uint32_t rf_ac[2];
2532 : uint8_t txmode;
2533 : int i;
2534 :
2535 0 : txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
2536 0 : if ((txmode & 0x70) != 0) {
2537 : /* Disable all continuous Tx. */
2538 0 : rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
2539 :
2540 : /* Set RF mode to standby mode. */
2541 0 : for (i = 0; i < sc->nrxchains; i++) {
2542 0 : rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
2543 0 : rtwn_rf_write(sc, i, R92C_RF_AC,
2544 0 : RW(rf_ac[i], R92C_RF_AC_MODE,
2545 : R92C_RF_AC_MODE_STANDBY));
2546 : }
2547 : } else {
2548 : /* Block all Tx queues. */
2549 0 : rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_ALL);
2550 : }
2551 : /* Start calibration. */
2552 0 : rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
2553 0 : rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART);
2554 :
2555 : /* Give calibration the time to complete. */
2556 0 : DELAY(100);
2557 :
2558 : /* Restore configuration. */
2559 0 : if ((txmode & 0x70) != 0) {
2560 : /* Restore Tx mode. */
2561 0 : rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
2562 : /* Restore RF mode. */
2563 0 : for (i = 0; i < sc->nrxchains; i++)
2564 0 : rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
2565 : } else {
2566 : /* Unblock all Tx queues. */
2567 0 : rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
2568 : }
2569 0 : }
2570 :
2571 : void
2572 0 : rtwn_temp_calib(struct rtwn_softc *sc)
2573 : {
2574 : int temp;
2575 :
2576 0 : if (sc->thcal_state == 0) {
2577 : /* Start measuring temperature. */
2578 0 : rtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60);
2579 0 : sc->thcal_state = 1;
2580 0 : return;
2581 : }
2582 0 : sc->thcal_state = 0;
2583 :
2584 : /* Read measured temperature. */
2585 0 : temp = rtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f;
2586 0 : if (temp == 0) /* Read failed, skip. */
2587 0 : return;
2588 : DPRINTFN(2, ("temperature=%d\n", temp));
2589 :
2590 : /*
2591 : * Redo IQ and LC calibration if temperature changed significantly
2592 : * since last calibration.
2593 : */
2594 0 : if (sc->thcal_lctemp == 0) {
2595 : /* First calibration is performed in rtwn_init(). */
2596 0 : sc->thcal_lctemp = temp;
2597 0 : } else if (abs(temp - sc->thcal_lctemp) > 1) {
2598 : DPRINTF(("IQ/LC calib triggered by temp: %d -> %d\n",
2599 : sc->thcal_lctemp, temp));
2600 0 : rtwn_iq_calib(sc);
2601 0 : rtwn_lc_calib(sc);
2602 : /* Record temperature of last calibration. */
2603 0 : sc->thcal_lctemp = temp;
2604 0 : }
2605 0 : }
2606 :
2607 : void
2608 0 : rtwn_enable_intr(struct rtwn_softc *sc)
2609 : {
2610 0 : if (sc->chip & RTWN_CHIP_88E) {
2611 0 : rtwn_write_4(sc, R88E_HISR, 0xffffffff);
2612 0 : rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM |
2613 : R88E_HIMR_CPWM2 | R88E_HIMR_TBDER |
2614 : R88E_HIMR_PSTIMEOUT);
2615 0 : rtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW |
2616 : R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR |
2617 : R88E_HIMRE_TXERR);
2618 0 : if (sc->chip & RTWN_CHIP_USB) {
2619 0 : rtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
2620 0 : rtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) |
2621 : R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
2622 0 : }
2623 : } else {
2624 : uint32_t imask = 0;
2625 :
2626 0 : if (sc->chip & RTWN_CHIP_USB)
2627 0 : imask = 0xffffffff;
2628 0 : else if (sc->chip & RTWN_CHIP_PCI)
2629 : imask = RTWN_INT_ENABLE;
2630 : else
2631 0 : panic("unknown chip type 0x%x", sc->chip);
2632 :
2633 : /* CLear pending interrupts. */
2634 0 : rtwn_write_4(sc, R92C_HISR, 0xffffffff);
2635 :
2636 : /* Enable interrupts. */
2637 0 : rtwn_write_4(sc, R92C_HIMR, imask);
2638 : }
2639 0 : }
2640 :
2641 : void
2642 0 : rtwn_disable_intr(struct rtwn_softc *sc)
2643 : {
2644 0 : if (sc->chip & RTWN_CHIP_88E) {
2645 0 : rtwn_write_4(sc, R88E_HISR, 0x00000000);
2646 0 : rtwn_write_4(sc, R88E_HIMR, 0x00000000);
2647 0 : rtwn_write_4(sc, R88E_HIMRE, 0x00000000);
2648 0 : if (sc->chip & RTWN_CHIP_USB) {
2649 0 : rtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
2650 0 : rtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) &
2651 : ~R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
2652 0 : }
2653 : } else {
2654 0 : rtwn_write_4(sc, R92C_HISR, 0x00000000);
2655 0 : rtwn_write_4(sc, R92C_HIMR, 0x00000000);
2656 : }
2657 0 : }
2658 :
2659 : int
2660 0 : rtwn_init(struct ifnet *ifp)
2661 : {
2662 0 : struct rtwn_softc *sc = ifp->if_softc;
2663 0 : struct ieee80211com *ic = &sc->sc_ic;
2664 : uint32_t reg;
2665 : int i, error;
2666 :
2667 : /* Init firmware commands ring. */
2668 0 : sc->fwcur = 0;
2669 :
2670 0 : error = sc->sc_ops.alloc_buffers(sc->sc_ops.cookie);
2671 0 : if (error)
2672 : goto fail;
2673 :
2674 : /* Power on adapter. */
2675 0 : error = sc->sc_ops.power_on(sc->sc_ops.cookie);
2676 0 : if (error != 0) {
2677 0 : printf("%s: could not power on adapter\n",
2678 0 : sc->sc_pdev->dv_xname);
2679 0 : goto fail;
2680 : }
2681 :
2682 : /* Initialize DMA. */
2683 0 : error = sc->sc_ops.dma_init(sc->sc_ops.cookie);
2684 0 : if (error != 0) {
2685 0 : printf("%s: could not initialize DMA\n",
2686 0 : sc->sc_pdev->dv_xname);
2687 0 : goto fail;
2688 : }
2689 :
2690 : /* Set info size in Rx descriptors (in 64-bit words). */
2691 0 : rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4);
2692 :
2693 0 : if (sc->chip & RTWN_CHIP_USB) {
2694 : /* Init interrupts. */
2695 0 : rtwn_enable_intr(sc);
2696 0 : } else if (sc->chip & RTWN_CHIP_PCI) {
2697 0 : rtwn_disable_intr(sc);
2698 0 : }
2699 :
2700 : /* Set MAC address. */
2701 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
2702 0 : for (i = 0; i < IEEE80211_ADDR_LEN; i++)
2703 0 : rtwn_write_1(sc, R92C_MACID + i, ic->ic_myaddr[i]);
2704 :
2705 : /* Set initial network type. */
2706 0 : rtwn_set_nettype(sc, IEEE80211_M_MONITOR);
2707 :
2708 0 : rtwn_rxfilter_init(sc);
2709 :
2710 0 : reg = rtwn_read_4(sc, R92C_RRSR);
2711 0 : if (sc->chip & RTWN_CHIP_USB) {
2712 0 : reg = RW(reg, R92C_RRSR_RATE_BITMAP,
2713 : R92C_RRSR_RATE_CCK_ONLY_1M);
2714 0 : } else {
2715 0 : reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_ALL);
2716 : }
2717 0 : rtwn_write_4(sc, R92C_RRSR, reg);
2718 :
2719 : /* Set short/long retry limits. */
2720 0 : if (sc->chip & RTWN_CHIP_USB) {
2721 0 : rtwn_write_2(sc, R92C_RL,
2722 : SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30));
2723 0 : } else {
2724 0 : rtwn_write_2(sc, R92C_RL,
2725 : SM(R92C_RL_SRL, 0x07) | SM(R92C_RL_LRL, 0x07));
2726 : }
2727 :
2728 : /* Initialize EDCA parameters. */
2729 0 : rtwn_edca_init(sc);
2730 :
2731 : /* Set data and response automatic rate fallback retry counts. */
2732 0 : rtwn_rate_fallback_init(sc);
2733 :
2734 0 : if (sc->chip & RTWN_CHIP_USB) {
2735 0 : rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
2736 0 : rtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) |
2737 : R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
2738 0 : } else {
2739 0 : rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, 0x1f80);
2740 : }
2741 :
2742 : /* Set ACK timeout. */
2743 0 : rtwn_write_1(sc, R92C_ACKTO, 0x40);
2744 :
2745 0 : if (sc->chip & RTWN_CHIP_USB) {
2746 : /* Setup USB aggregation. */
2747 0 : rtwn_usb_aggr_init(sc);
2748 0 : }
2749 :
2750 : /* Initialize beacon parameters. */
2751 0 : rtwn_write_2(sc, R92C_BCN_CTRL,
2752 : (R92C_BCN_CTRL_DIS_TSF_UDT0 << 8) | R92C_BCN_CTRL_DIS_TSF_UDT0);
2753 0 : rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404);
2754 0 : rtwn_write_1(sc, R92C_DRVERLYINT, R92C_DRVERLYINT_INIT_TIME);
2755 0 : rtwn_write_1(sc, R92C_BCNDMATIM, R92C_BCNDMATIM_INIT_TIME);
2756 0 : rtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
2757 :
2758 0 : if (!(sc->chip & RTWN_CHIP_88E)) {
2759 : /* Setup AMPDU aggregation. */
2760 0 : rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
2761 0 : rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
2762 0 : rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708);
2763 :
2764 0 : rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff);
2765 0 : }
2766 :
2767 0 : if (sc->chip & RTWN_CHIP_PCI) {
2768 : /* Reset H2C protection register. */
2769 0 : rtwn_write_4(sc, R92C_MCUTST_1, 0x0);
2770 0 : }
2771 :
2772 : /* Load 8051 microcode. */
2773 0 : error = rtwn_load_firmware(sc);
2774 0 : if (error != 0)
2775 : goto fail;
2776 :
2777 : /* Initialize MAC/BB/RF blocks. */
2778 0 : sc->sc_ops.mac_init(sc->sc_ops.cookie);
2779 0 : sc->sc_ops.bb_init(sc->sc_ops.cookie);
2780 0 : rtwn_rf_init(sc);
2781 :
2782 0 : if (sc->chip & RTWN_CHIP_88E) {
2783 0 : rtwn_write_2(sc, R92C_CR,
2784 0 : rtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN |
2785 : R92C_CR_MACRXEN);
2786 0 : }
2787 :
2788 : /* Turn CCK and OFDM blocks on. */
2789 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD);
2790 0 : reg |= R92C_RFMOD_CCK_EN;
2791 0 : rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
2792 0 : reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD);
2793 0 : reg |= R92C_RFMOD_OFDM_EN;
2794 0 : rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
2795 :
2796 : /* Clear per-station keys table. */
2797 0 : rtwn_cam_init(sc);
2798 :
2799 : /* Enable hardware sequence numbering. */
2800 0 : rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
2801 :
2802 : /* Perform LO and IQ calibrations. */
2803 0 : rtwn_iq_calib(sc);
2804 : /* Perform LC calibration. */
2805 0 : rtwn_lc_calib(sc);
2806 :
2807 : /* Fix USB interference issue. */
2808 0 : if ((sc->chip & RTWN_CHIP_USB) && !(sc->chip & RTWN_CHIP_88E)) {
2809 0 : rtwn_write_1(sc, 0xfe40, 0xe0);
2810 0 : rtwn_write_1(sc, 0xfe41, 0x8d);
2811 0 : rtwn_write_1(sc, 0xfe42, 0x80);
2812 :
2813 0 : rtwn_pa_bias_init(sc);
2814 0 : }
2815 :
2816 : /* Initialize GPIO setting. */
2817 0 : rtwn_write_1(sc, R92C_GPIO_MUXCFG,
2818 0 : rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT);
2819 :
2820 : /* Fix for lower temperature. */
2821 0 : if (!(sc->chip & RTWN_CHIP_88E))
2822 0 : rtwn_write_1(sc, 0x15, 0xe9);
2823 :
2824 : /* Set default channel. */
2825 0 : ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2826 0 : rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
2827 :
2828 0 : if (sc->chip & RTWN_CHIP_PCI)
2829 0 : rtwn_enable_intr(sc);
2830 :
2831 0 : error = sc->sc_ops.init(sc->sc_ops.cookie);
2832 0 : if (error)
2833 : goto fail;
2834 :
2835 : /* We're ready to go. */
2836 0 : ifq_clr_oactive(&ifp->if_snd);
2837 0 : ifp->if_flags |= IFF_RUNNING;
2838 :
2839 : #ifdef notyet
2840 : if (ic->ic_flags & IEEE80211_F_WEPON) {
2841 : /* Install WEP keys. */
2842 : for (i = 0; i < IEEE80211_WEP_NKID; i++)
2843 : ic->ic_set_key(ic, NULL, &ic->ic_nw_keys[i]);
2844 : sc->sc_ops.wait_async(sc->sc_ops.cookie);
2845 : }
2846 : #endif
2847 0 : if (ic->ic_opmode == IEEE80211_M_MONITOR)
2848 0 : ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2849 : else
2850 0 : ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2851 0 : return (0);
2852 : fail:
2853 0 : rtwn_stop(ifp);
2854 0 : return (error);
2855 0 : }
2856 :
2857 : void
2858 0 : rtwn_init_task(void *arg1)
2859 : {
2860 0 : struct rtwn_softc *sc = arg1;
2861 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
2862 : int s;
2863 :
2864 0 : s = splnet();
2865 0 : while (sc->sc_flags & RTWN_FLAG_BUSY)
2866 0 : tsleep(&sc->sc_flags, 0, "rtwnpwr", 0);
2867 0 : sc->sc_flags |= RTWN_FLAG_BUSY;
2868 :
2869 0 : rtwn_stop(ifp);
2870 :
2871 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
2872 0 : rtwn_init(ifp);
2873 :
2874 0 : sc->sc_flags &= ~RTWN_FLAG_BUSY;
2875 0 : wakeup(&sc->sc_flags);
2876 0 : splx(s);
2877 0 : }
2878 :
2879 : void
2880 0 : rtwn_stop(struct ifnet *ifp)
2881 : {
2882 0 : struct rtwn_softc *sc = ifp->if_softc;
2883 0 : struct ieee80211com *ic = &sc->sc_ic;
2884 : int s;
2885 :
2886 0 : sc->sc_tx_timer = 0;
2887 0 : ifp->if_timer = 0;
2888 0 : ifp->if_flags &= ~IFF_RUNNING;
2889 0 : ifq_clr_oactive(&ifp->if_snd);
2890 :
2891 0 : s = splnet();
2892 0 : ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2893 0 : splx(s);
2894 :
2895 0 : sc->sc_ops.wait_async(sc->sc_ops.cookie);
2896 :
2897 0 : s = splnet();
2898 :
2899 0 : sc->sc_ops.cancel_scan(sc->sc_ops.cookie);
2900 0 : sc->sc_ops.cancel_calib(sc->sc_ops.cookie);
2901 :
2902 0 : task_del(systq, &sc->init_task);
2903 :
2904 0 : splx(s);
2905 :
2906 0 : sc->sc_ops.stop(sc->sc_ops.cookie);
2907 0 : }
|