Line data Source code
1 : /* $OpenBSD: ar5008.c,v 1.46 2017/11/28 04:35:39 stsp Exp $ */
2 :
3 : /*-
4 : * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
5 : * Copyright (c) 2008-2009 Atheros Communications Inc.
6 : *
7 : * Permission to use, copy, modify, and/or 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 Atheros 802.11a/g/n chipsets.
22 : * Routines common to AR5008, AR9001 and AR9002 families.
23 : */
24 :
25 : #include "bpfilter.h"
26 :
27 : #include <sys/param.h>
28 : #include <sys/sockio.h>
29 : #include <sys/mbuf.h>
30 : #include <sys/kernel.h>
31 : #include <sys/socket.h>
32 : #include <sys/systm.h>
33 : #include <sys/malloc.h>
34 : #include <sys/queue.h>
35 : #include <sys/timeout.h>
36 : #include <sys/conf.h>
37 : #include <sys/device.h>
38 : #include <sys/stdint.h> /* uintptr_t */
39 : #include <sys/endian.h>
40 :
41 : #include <machine/bus.h>
42 :
43 : #if NBPFILTER > 0
44 : #include <net/bpf.h>
45 : #endif
46 : #include <net/if.h>
47 : #include <net/if_media.h>
48 :
49 : #include <netinet/in.h>
50 : #include <netinet/if_ether.h>
51 :
52 : #include <net80211/ieee80211_var.h>
53 : #include <net80211/ieee80211_amrr.h>
54 : #include <net80211/ieee80211_mira.h>
55 : #include <net80211/ieee80211_radiotap.h>
56 :
57 : #include <dev/ic/athnreg.h>
58 : #include <dev/ic/athnvar.h>
59 :
60 : #include <dev/ic/ar5008reg.h>
61 :
62 : int ar5008_attach(struct athn_softc *);
63 : int ar5008_read_eep_word(struct athn_softc *, uint32_t, uint16_t *);
64 : int ar5008_read_rom(struct athn_softc *);
65 : void ar5008_swap_rom(struct athn_softc *);
66 : int ar5008_gpio_read(struct athn_softc *, int);
67 : void ar5008_gpio_write(struct athn_softc *, int, int);
68 : void ar5008_gpio_config_input(struct athn_softc *, int);
69 : void ar5008_gpio_config_output(struct athn_softc *, int, int);
70 : void ar5008_rfsilent_init(struct athn_softc *);
71 : int ar5008_dma_alloc(struct athn_softc *);
72 : void ar5008_dma_free(struct athn_softc *);
73 : int ar5008_tx_alloc(struct athn_softc *);
74 : void ar5008_tx_free(struct athn_softc *);
75 : int ar5008_rx_alloc(struct athn_softc *);
76 : void ar5008_rx_free(struct athn_softc *);
77 : void ar5008_rx_enable(struct athn_softc *);
78 : void ar5008_rx_radiotap(struct athn_softc *, struct mbuf *,
79 : struct ar_rx_desc *);
80 : void ar5008_rx_intr(struct athn_softc *);
81 : int ar5008_tx_process(struct athn_softc *, int);
82 : void ar5008_tx_intr(struct athn_softc *);
83 : int ar5008_swba_intr(struct athn_softc *);
84 : int ar5008_intr(struct athn_softc *);
85 : int ar5008_tx(struct athn_softc *, struct mbuf *, struct ieee80211_node *,
86 : int);
87 : void ar5008_set_rf_mode(struct athn_softc *, struct ieee80211_channel *);
88 : int ar5008_rf_bus_request(struct athn_softc *);
89 : void ar5008_rf_bus_release(struct athn_softc *);
90 : void ar5008_set_phy(struct athn_softc *, struct ieee80211_channel *,
91 : struct ieee80211_channel *);
92 : void ar5008_set_delta_slope(struct athn_softc *, struct ieee80211_channel *,
93 : struct ieee80211_channel *);
94 : void ar5008_enable_antenna_diversity(struct athn_softc *);
95 : void ar5008_init_baseband(struct athn_softc *);
96 : void ar5008_disable_phy(struct athn_softc *);
97 : void ar5008_init_chains(struct athn_softc *);
98 : void ar5008_set_rxchains(struct athn_softc *);
99 : void ar5008_read_noisefloor(struct athn_softc *, int16_t *, int16_t *);
100 : void ar5008_write_noisefloor(struct athn_softc *, int16_t *, int16_t *);
101 : void ar5008_get_noisefloor(struct athn_softc *, struct ieee80211_channel *);
102 : void ar5008_bb_load_noisefloor(struct athn_softc *);
103 : void ar5008_noisefloor_calib(struct athn_softc *);
104 : void ar5008_do_noisefloor_calib(struct athn_softc *);
105 : void ar5008_do_calib(struct athn_softc *);
106 : void ar5008_next_calib(struct athn_softc *);
107 : void ar5008_calib_iq(struct athn_softc *);
108 : void ar5008_calib_adc_gain(struct athn_softc *);
109 : void ar5008_calib_adc_dc_off(struct athn_softc *);
110 : void ar5008_write_txpower(struct athn_softc *, int16_t power[]);
111 : void ar5008_set_viterbi_mask(struct athn_softc *, int);
112 : void ar5008_hw_init(struct athn_softc *, struct ieee80211_channel *,
113 : struct ieee80211_channel *);
114 : uint8_t ar5008_get_vpd(uint8_t, const uint8_t *, const uint8_t *, int);
115 : void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
116 : struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
117 : void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
118 : uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
119 : void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
120 : uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
121 : void ar5008_set_noise_immunity_level(struct athn_softc *, int);
122 : void ar5008_enable_ofdm_weak_signal(struct athn_softc *);
123 : void ar5008_disable_ofdm_weak_signal(struct athn_softc *);
124 : void ar5008_set_cck_weak_signal(struct athn_softc *, int);
125 : void ar5008_set_firstep_level(struct athn_softc *, int);
126 : void ar5008_set_spur_immunity_level(struct athn_softc *, int);
127 :
128 : /* Extern functions. */
129 : void athn_stop(struct ifnet *, int);
130 : int athn_interpolate(int, int, int, int, int);
131 : int athn_txtime(struct athn_softc *, int, int, u_int);
132 : void athn_inc_tx_trigger_level(struct athn_softc *);
133 : int athn_tx_pending(struct athn_softc *, int);
134 : void athn_stop_tx_dma(struct athn_softc *, int);
135 : void athn_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
136 : void athn_config_pcie(struct athn_softc *);
137 : void athn_config_nonpcie(struct athn_softc *);
138 : uint8_t athn_chan2fbin(struct ieee80211_channel *);
139 : uint8_t ar5416_get_rf_rev(struct athn_softc *);
140 : void ar5416_reset_addac(struct athn_softc *, struct ieee80211_channel *);
141 : void ar5416_rf_reset(struct athn_softc *, struct ieee80211_channel *);
142 : void ar5416_reset_bb_gain(struct athn_softc *, struct ieee80211_channel *);
143 : void ar9280_reset_rx_gain(struct athn_softc *, struct ieee80211_channel *);
144 : void ar9280_reset_tx_gain(struct athn_softc *, struct ieee80211_channel *);
145 :
146 :
147 : int
148 0 : ar5008_attach(struct athn_softc *sc)
149 : {
150 0 : struct athn_ops *ops = &sc->ops;
151 0 : struct ieee80211com *ic = &sc->sc_ic;
152 : struct ar_base_eep_header *base;
153 : uint8_t eep_ver, kc_entries_log;
154 : int error;
155 :
156 : /* Set callbacks for AR5008, AR9001 and AR9002 families. */
157 0 : ops->gpio_read = ar5008_gpio_read;
158 0 : ops->gpio_write = ar5008_gpio_write;
159 0 : ops->gpio_config_input = ar5008_gpio_config_input;
160 0 : ops->gpio_config_output = ar5008_gpio_config_output;
161 0 : ops->rfsilent_init = ar5008_rfsilent_init;
162 :
163 0 : ops->dma_alloc = ar5008_dma_alloc;
164 0 : ops->dma_free = ar5008_dma_free;
165 0 : ops->rx_enable = ar5008_rx_enable;
166 0 : ops->intr = ar5008_intr;
167 0 : ops->tx = ar5008_tx;
168 :
169 0 : ops->set_rf_mode = ar5008_set_rf_mode;
170 0 : ops->rf_bus_request = ar5008_rf_bus_request;
171 0 : ops->rf_bus_release = ar5008_rf_bus_release;
172 0 : ops->set_phy = ar5008_set_phy;
173 0 : ops->set_delta_slope = ar5008_set_delta_slope;
174 0 : ops->enable_antenna_diversity = ar5008_enable_antenna_diversity;
175 0 : ops->init_baseband = ar5008_init_baseband;
176 0 : ops->disable_phy = ar5008_disable_phy;
177 0 : ops->set_rxchains = ar5008_set_rxchains;
178 0 : ops->noisefloor_calib = ar5008_do_noisefloor_calib;
179 0 : ops->do_calib = ar5008_do_calib;
180 0 : ops->next_calib = ar5008_next_calib;
181 0 : ops->hw_init = ar5008_hw_init;
182 :
183 0 : ops->set_noise_immunity_level = ar5008_set_noise_immunity_level;
184 0 : ops->enable_ofdm_weak_signal = ar5008_enable_ofdm_weak_signal;
185 0 : ops->disable_ofdm_weak_signal = ar5008_disable_ofdm_weak_signal;
186 0 : ops->set_cck_weak_signal = ar5008_set_cck_weak_signal;
187 0 : ops->set_firstep_level = ar5008_set_firstep_level;
188 0 : ops->set_spur_immunity_level = ar5008_set_spur_immunity_level;
189 :
190 : /* Set MAC registers offsets. */
191 0 : sc->obs_off = AR_OBS;
192 0 : sc->gpio_input_en_off = AR_GPIO_INPUT_EN_VAL;
193 :
194 0 : if (!(sc->flags & ATHN_FLAG_PCIE))
195 0 : athn_config_nonpcie(sc);
196 : else
197 0 : athn_config_pcie(sc);
198 :
199 : /* Read entire ROM content in memory. */
200 0 : if ((error = ar5008_read_rom(sc)) != 0) {
201 0 : printf("%s: could not read ROM\n", sc->sc_dev.dv_xname);
202 0 : return (error);
203 : }
204 :
205 : /* Get RF revision. */
206 0 : sc->rf_rev = ar5416_get_rf_rev(sc);
207 :
208 0 : base = sc->eep;
209 0 : eep_ver = (base->version >> 12) & 0xf;
210 0 : sc->eep_rev = (base->version & 0xfff);
211 0 : if (eep_ver != AR_EEP_VER || sc->eep_rev == 0) {
212 0 : printf("%s: unsupported ROM version %d.%d\n",
213 0 : sc->sc_dev.dv_xname, eep_ver, sc->eep_rev);
214 0 : return (EINVAL);
215 : }
216 :
217 0 : if (base->opCapFlags & AR_OPFLAGS_11A) {
218 0 : sc->flags |= ATHN_FLAG_11A;
219 0 : if ((base->opCapFlags & AR_OPFLAGS_11N_5G20) == 0)
220 0 : sc->flags |= ATHN_FLAG_11N;
221 : #ifdef notyet
222 : if ((base->opCapFlags & AR_OPFLAGS_11N_5G40) == 0)
223 : sc->flags |= ATHN_FLAG_11N;
224 : #endif
225 : }
226 0 : if (base->opCapFlags & AR_OPFLAGS_11G) {
227 0 : sc->flags |= ATHN_FLAG_11G;
228 0 : if ((base->opCapFlags & AR_OPFLAGS_11N_2G20) == 0)
229 0 : sc->flags |= ATHN_FLAG_11N;
230 : #ifdef notyet
231 : if ((base->opCapFlags & AR_OPFLAGS_11N_2G40) == 0)
232 : sc->flags |= ATHN_FLAG_11N;
233 : #endif
234 : }
235 :
236 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, base->macAddr);
237 :
238 : /* Check if we have a hardware radio switch. */
239 0 : if (base->rfSilent & AR_EEP_RFSILENT_ENABLED) {
240 0 : sc->flags |= ATHN_FLAG_RFSILENT;
241 : /* Get GPIO pin used by hardware radio switch. */
242 0 : sc->rfsilent_pin = MS(base->rfSilent,
243 : AR_EEP_RFSILENT_GPIO_SEL);
244 : /* Get polarity of hardware radio switch. */
245 0 : if (base->rfSilent & AR_EEP_RFSILENT_POLARITY)
246 0 : sc->flags |= ATHN_FLAG_RFSILENT_REVERSED;
247 : }
248 :
249 : /* Get the number of HW key cache entries. */
250 0 : kc_entries_log = MS(base->deviceCap, AR_EEP_DEVCAP_KC_ENTRIES);
251 0 : sc->kc_entries = (kc_entries_log != 0) ?
252 0 : 1 << kc_entries_log : AR_KEYTABLE_SIZE;
253 :
254 0 : sc->txchainmask = base->txMask;
255 0 : if (sc->mac_ver == AR_SREV_VERSION_5416_PCI &&
256 0 : !(base->opCapFlags & AR_OPFLAGS_11A)) {
257 : /* For single-band AR5416 PCI, use GPIO pin 0. */
258 0 : sc->rxchainmask = ar5008_gpio_read(sc, 0) ? 0x5 : 0x7;
259 0 : } else
260 0 : sc->rxchainmask = base->rxMask;
261 :
262 0 : ops->setup(sc);
263 0 : return (0);
264 0 : }
265 :
266 : /*
267 : * Read 16-bit word from ROM.
268 : */
269 : int
270 0 : ar5008_read_eep_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
271 : {
272 : uint32_t reg;
273 : int ntries;
274 :
275 0 : reg = AR_READ(sc, AR_EEPROM_OFFSET(addr));
276 0 : for (ntries = 0; ntries < 1000; ntries++) {
277 0 : reg = AR_READ(sc, AR_EEPROM_STATUS_DATA);
278 0 : if (!(reg & (AR_EEPROM_STATUS_DATA_BUSY |
279 : AR_EEPROM_STATUS_DATA_PROT_ACCESS))) {
280 0 : *val = MS(reg, AR_EEPROM_STATUS_DATA_VAL);
281 0 : return (0);
282 : }
283 0 : DELAY(10);
284 : }
285 0 : *val = 0xffff;
286 0 : return (ETIMEDOUT);
287 0 : }
288 :
289 : int
290 0 : ar5008_read_rom(struct athn_softc *sc)
291 : {
292 : uint32_t addr, end;
293 0 : uint16_t magic, sum, *eep;
294 : int need_swap = 0;
295 : int error;
296 :
297 : /* Determine ROM endianness. */
298 0 : error = ar5008_read_eep_word(sc, AR_EEPROM_MAGIC_OFFSET, &magic);
299 0 : if (error != 0)
300 0 : return (error);
301 0 : if (magic != AR_EEPROM_MAGIC) {
302 0 : if (magic != swap16(AR_EEPROM_MAGIC)) {
303 : DPRINTF(("invalid ROM magic 0x%x != 0x%x\n",
304 : magic, AR_EEPROM_MAGIC));
305 0 : return (EIO);
306 : }
307 : DPRINTF(("non-native ROM endianness\n"));
308 : need_swap = 1;
309 0 : }
310 :
311 : /* Allocate space to store ROM in host memory. */
312 0 : sc->eep = malloc(sc->eep_size, M_DEVBUF, M_NOWAIT);
313 0 : if (sc->eep == NULL)
314 0 : return (ENOMEM);
315 :
316 : /* Read entire ROM and compute checksum. */
317 : sum = 0;
318 0 : eep = sc->eep;
319 0 : end = sc->eep_base + sc->eep_size / sizeof(uint16_t);
320 0 : for (addr = sc->eep_base; addr < end; addr++, eep++) {
321 0 : if ((error = ar5008_read_eep_word(sc, addr, eep)) != 0) {
322 : DPRINTF(("could not read ROM at 0x%x\n", addr));
323 0 : return (error);
324 : }
325 0 : if (need_swap)
326 0 : *eep = swap16(*eep);
327 0 : sum ^= *eep;
328 : }
329 0 : if (sum != 0xffff) {
330 0 : printf("%s: bad ROM checksum 0x%04x\n",
331 0 : sc->sc_dev.dv_xname, sum);
332 0 : return (EIO);
333 : }
334 0 : if (need_swap)
335 0 : ar5008_swap_rom(sc);
336 :
337 0 : return (0);
338 0 : }
339 :
340 : void
341 0 : ar5008_swap_rom(struct athn_softc *sc)
342 : {
343 0 : struct ar_base_eep_header *base = sc->eep;
344 :
345 : /* Swap common fields first. */
346 0 : base->length = swap16(base->length);
347 0 : base->version = swap16(base->version);
348 0 : base->regDmn[0] = swap16(base->regDmn[0]);
349 0 : base->regDmn[1] = swap16(base->regDmn[1]);
350 0 : base->rfSilent = swap16(base->rfSilent);
351 0 : base->blueToothOptions = swap16(base->blueToothOptions);
352 0 : base->deviceCap = swap16(base->deviceCap);
353 :
354 : /* Swap device-dependent fields. */
355 0 : sc->ops.swap_rom(sc);
356 0 : }
357 :
358 : /*
359 : * Access to General Purpose Input/Output ports.
360 : */
361 : int
362 0 : ar5008_gpio_read(struct athn_softc *sc, int pin)
363 : {
364 0 : KASSERT(pin < sc->ngpiopins);
365 0 : if ((sc->flags & ATHN_FLAG_USB) && !AR_SREV_9271(sc))
366 0 : return (!((AR_READ(sc, AR7010_GPIO_IN) >> pin) & 1));
367 0 : return ((AR_READ(sc, AR_GPIO_IN_OUT) >> (sc->ngpiopins + pin)) & 1);
368 0 : }
369 :
370 : void
371 0 : ar5008_gpio_write(struct athn_softc *sc, int pin, int set)
372 : {
373 : uint32_t reg;
374 :
375 0 : KASSERT(pin < sc->ngpiopins);
376 :
377 0 : if (sc->flags & ATHN_FLAG_USB)
378 0 : set = !set; /* AR9271/AR7010 is reversed. */
379 :
380 0 : if ((sc->flags & ATHN_FLAG_USB) && !AR_SREV_9271(sc)) {
381 : /* Special case for AR7010. */
382 0 : reg = AR_READ(sc, AR7010_GPIO_OUT);
383 0 : if (set)
384 0 : reg |= 1 << pin;
385 : else
386 0 : reg &= ~(1 << pin);
387 0 : AR_WRITE(sc, AR7010_GPIO_OUT, reg);
388 0 : } else {
389 0 : reg = AR_READ(sc, AR_GPIO_IN_OUT);
390 0 : if (set)
391 0 : reg |= 1 << pin;
392 : else
393 0 : reg &= ~(1 << pin);
394 0 : AR_WRITE(sc, AR_GPIO_IN_OUT, reg);
395 : }
396 0 : AR_WRITE_BARRIER(sc);
397 0 : }
398 :
399 : void
400 0 : ar5008_gpio_config_input(struct athn_softc *sc, int pin)
401 : {
402 : uint32_t reg;
403 :
404 0 : if ((sc->flags & ATHN_FLAG_USB) && !AR_SREV_9271(sc)) {
405 : /* Special case for AR7010. */
406 0 : AR_SETBITS(sc, AR7010_GPIO_OE, 1 << pin);
407 0 : } else {
408 0 : reg = AR_READ(sc, AR_GPIO_OE_OUT);
409 0 : reg &= ~(AR_GPIO_OE_OUT_DRV_M << (pin * 2));
410 : reg |= AR_GPIO_OE_OUT_DRV_NO << (pin * 2);
411 0 : AR_WRITE(sc, AR_GPIO_OE_OUT, reg);
412 : }
413 0 : AR_WRITE_BARRIER(sc);
414 0 : }
415 :
416 : void
417 0 : ar5008_gpio_config_output(struct athn_softc *sc, int pin, int type)
418 : {
419 : uint32_t reg;
420 : int mux, off;
421 :
422 0 : if ((sc->flags & ATHN_FLAG_USB) && !AR_SREV_9271(sc)) {
423 : /* Special case for AR7010. */
424 0 : AR_CLRBITS(sc, AR7010_GPIO_OE, 1 << pin);
425 0 : AR_WRITE_BARRIER(sc);
426 0 : return;
427 : }
428 0 : mux = pin / 6;
429 0 : off = pin % 6;
430 :
431 0 : reg = AR_READ(sc, AR_GPIO_OUTPUT_MUX(mux));
432 0 : if (!AR_SREV_9280_20_OR_LATER(sc) && mux == 0)
433 0 : reg = (reg & ~0x1f0) | (reg & 0x1f0) << 1;
434 0 : reg &= ~(0x1f << (off * 5));
435 0 : reg |= (type & 0x1f) << (off * 5);
436 0 : AR_WRITE(sc, AR_GPIO_OUTPUT_MUX(mux), reg);
437 :
438 0 : reg = AR_READ(sc, AR_GPIO_OE_OUT);
439 0 : reg &= ~(AR_GPIO_OE_OUT_DRV_M << (pin * 2));
440 0 : reg |= AR_GPIO_OE_OUT_DRV_ALL << (pin * 2);
441 0 : AR_WRITE(sc, AR_GPIO_OE_OUT, reg);
442 0 : AR_WRITE_BARRIER(sc);
443 0 : }
444 :
445 : void
446 0 : ar5008_rfsilent_init(struct athn_softc *sc)
447 : {
448 : uint32_t reg;
449 :
450 : /* Configure hardware radio switch. */
451 0 : AR_SETBITS(sc, AR_GPIO_INPUT_EN_VAL, AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
452 0 : reg = AR_READ(sc, AR_GPIO_INPUT_MUX2);
453 0 : reg = RW(reg, AR_GPIO_INPUT_MUX2_RFSILENT, 0);
454 0 : AR_WRITE(sc, AR_GPIO_INPUT_MUX2, reg);
455 0 : ar5008_gpio_config_input(sc, sc->rfsilent_pin);
456 0 : AR_SETBITS(sc, AR_PHY_TEST, AR_PHY_TEST_RFSILENT_BB);
457 0 : if (!(sc->flags & ATHN_FLAG_RFSILENT_REVERSED)) {
458 0 : AR_SETBITS(sc, AR_GPIO_INTR_POL,
459 : AR_GPIO_INTR_POL_PIN(sc->rfsilent_pin));
460 0 : }
461 0 : AR_WRITE_BARRIER(sc);
462 0 : }
463 :
464 : int
465 0 : ar5008_dma_alloc(struct athn_softc *sc)
466 : {
467 : int error;
468 :
469 0 : error = ar5008_tx_alloc(sc);
470 0 : if (error != 0)
471 0 : return (error);
472 :
473 0 : error = ar5008_rx_alloc(sc);
474 0 : if (error != 0)
475 0 : return (error);
476 :
477 0 : return (0);
478 0 : }
479 :
480 : void
481 0 : ar5008_dma_free(struct athn_softc *sc)
482 : {
483 0 : ar5008_tx_free(sc);
484 0 : ar5008_rx_free(sc);
485 0 : }
486 :
487 : int
488 0 : ar5008_tx_alloc(struct athn_softc *sc)
489 : {
490 : struct athn_tx_buf *bf;
491 : bus_size_t size;
492 0 : int error, nsegs, i;
493 :
494 : /*
495 : * Allocate a pool of Tx descriptors shared between all Tx queues.
496 : */
497 : size = ATHN_NTXBUFS * AR5008_MAX_SCATTER * sizeof(struct ar_tx_desc);
498 :
499 0 : error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
500 : BUS_DMA_NOWAIT, &sc->map);
501 0 : if (error != 0)
502 : goto fail;
503 :
504 0 : error = bus_dmamem_alloc(sc->sc_dmat, size, 4, 0, &sc->seg, 1,
505 : &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
506 0 : if (error != 0)
507 : goto fail;
508 :
509 0 : error = bus_dmamem_map(sc->sc_dmat, &sc->seg, 1, size,
510 : (caddr_t *)&sc->descs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
511 0 : if (error != 0)
512 : goto fail;
513 :
514 0 : error = bus_dmamap_load_raw(sc->sc_dmat, sc->map, &sc->seg, 1, size,
515 : BUS_DMA_NOWAIT);
516 0 : if (error != 0)
517 : goto fail;
518 :
519 0 : SIMPLEQ_INIT(&sc->txbufs);
520 0 : for (i = 0; i < ATHN_NTXBUFS; i++) {
521 0 : bf = &sc->txpool[i];
522 :
523 0 : error = bus_dmamap_create(sc->sc_dmat, ATHN_TXBUFSZ,
524 : AR5008_MAX_SCATTER, ATHN_TXBUFSZ, 0, BUS_DMA_NOWAIT,
525 : &bf->bf_map);
526 0 : if (error != 0) {
527 0 : printf("%s: could not create Tx buf DMA map\n",
528 0 : sc->sc_dev.dv_xname);
529 0 : goto fail;
530 : }
531 :
532 0 : bf->bf_descs =
533 0 : &((struct ar_tx_desc *)sc->descs)[i * AR5008_MAX_SCATTER];
534 0 : bf->bf_daddr = sc->map->dm_segs[0].ds_addr +
535 0 : i * AR5008_MAX_SCATTER * sizeof(struct ar_tx_desc);
536 :
537 0 : SIMPLEQ_INSERT_TAIL(&sc->txbufs, bf, bf_list);
538 : }
539 0 : return (0);
540 : fail:
541 0 : ar5008_tx_free(sc);
542 0 : return (error);
543 0 : }
544 :
545 : void
546 0 : ar5008_tx_free(struct athn_softc *sc)
547 : {
548 : struct athn_tx_buf *bf;
549 : int i;
550 :
551 0 : for (i = 0; i < ATHN_NTXBUFS; i++) {
552 0 : bf = &sc->txpool[i];
553 :
554 0 : if (bf->bf_map != NULL)
555 0 : bus_dmamap_destroy(sc->sc_dmat, bf->bf_map);
556 : }
557 : /* Free Tx descriptors. */
558 0 : if (sc->map != NULL) {
559 0 : if (sc->descs != NULL) {
560 0 : bus_dmamap_unload(sc->sc_dmat, sc->map);
561 0 : bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->descs,
562 : ATHN_NTXBUFS * AR5008_MAX_SCATTER *
563 : sizeof(struct ar_tx_desc));
564 0 : bus_dmamem_free(sc->sc_dmat, &sc->seg, 1);
565 0 : }
566 0 : bus_dmamap_destroy(sc->sc_dmat, sc->map);
567 0 : }
568 0 : }
569 :
570 : int
571 0 : ar5008_rx_alloc(struct athn_softc *sc)
572 : {
573 0 : struct athn_rxq *rxq = &sc->rxq[0];
574 : struct athn_rx_buf *bf;
575 : struct ar_rx_desc *ds;
576 : bus_size_t size;
577 0 : int error, nsegs, i;
578 :
579 0 : rxq->bf = mallocarray(ATHN_NRXBUFS, sizeof(*bf), M_DEVBUF,
580 : M_NOWAIT | M_ZERO);
581 0 : if (rxq->bf == NULL)
582 0 : return (ENOMEM);
583 :
584 : size = ATHN_NRXBUFS * sizeof(struct ar_rx_desc);
585 :
586 0 : error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
587 : BUS_DMA_NOWAIT, &rxq->map);
588 0 : if (error != 0)
589 : goto fail;
590 :
591 0 : error = bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &rxq->seg, 1,
592 : &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
593 0 : if (error != 0)
594 : goto fail;
595 :
596 0 : error = bus_dmamem_map(sc->sc_dmat, &rxq->seg, 1, size,
597 : (caddr_t *)&rxq->descs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
598 0 : if (error != 0)
599 : goto fail;
600 :
601 0 : error = bus_dmamap_load_raw(sc->sc_dmat, rxq->map, &rxq->seg, 1,
602 : size, BUS_DMA_NOWAIT);
603 0 : if (error != 0)
604 : goto fail;
605 :
606 0 : for (i = 0; i < ATHN_NRXBUFS; i++) {
607 0 : bf = &rxq->bf[i];
608 0 : ds = &((struct ar_rx_desc *)rxq->descs)[i];
609 :
610 0 : error = bus_dmamap_create(sc->sc_dmat, ATHN_RXBUFSZ, 1,
611 : ATHN_RXBUFSZ, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
612 : &bf->bf_map);
613 0 : if (error != 0) {
614 0 : printf("%s: could not create Rx buf DMA map\n",
615 0 : sc->sc_dev.dv_xname);
616 0 : goto fail;
617 : }
618 : /*
619 : * Assumes MCLGETI returns cache-line-size aligned buffers.
620 : */
621 0 : bf->bf_m = MCLGETI(NULL, M_DONTWAIT, NULL, ATHN_RXBUFSZ);
622 0 : if (bf->bf_m == NULL) {
623 0 : printf("%s: could not allocate Rx mbuf\n",
624 0 : sc->sc_dev.dv_xname);
625 : error = ENOBUFS;
626 0 : goto fail;
627 : }
628 :
629 0 : error = bus_dmamap_load(sc->sc_dmat, bf->bf_map,
630 : mtod(bf->bf_m, void *), ATHN_RXBUFSZ, NULL,
631 : BUS_DMA_NOWAIT | BUS_DMA_READ);
632 0 : if (error != 0) {
633 0 : printf("%s: could not DMA map Rx buffer\n",
634 0 : sc->sc_dev.dv_xname);
635 0 : goto fail;
636 : }
637 :
638 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, ATHN_RXBUFSZ,
639 : BUS_DMASYNC_PREREAD);
640 :
641 0 : bf->bf_desc = ds;
642 0 : bf->bf_daddr = rxq->map->dm_segs[0].ds_addr +
643 0 : i * sizeof(struct ar_rx_desc);
644 : }
645 0 : return (0);
646 : fail:
647 0 : ar5008_rx_free(sc);
648 0 : return (error);
649 0 : }
650 :
651 : void
652 0 : ar5008_rx_free(struct athn_softc *sc)
653 : {
654 0 : struct athn_rxq *rxq = &sc->rxq[0];
655 : struct athn_rx_buf *bf;
656 : int i;
657 :
658 0 : if (rxq->bf == NULL)
659 0 : return;
660 0 : for (i = 0; i < ATHN_NRXBUFS; i++) {
661 0 : bf = &rxq->bf[i];
662 :
663 0 : if (bf->bf_map != NULL)
664 0 : bus_dmamap_destroy(sc->sc_dmat, bf->bf_map);
665 0 : m_freem(bf->bf_m);
666 : }
667 0 : free(rxq->bf, M_DEVBUF, 0);
668 :
669 : /* Free Rx descriptors. */
670 0 : if (rxq->map != NULL) {
671 0 : if (rxq->descs != NULL) {
672 0 : bus_dmamap_unload(sc->sc_dmat, rxq->map);
673 0 : bus_dmamem_unmap(sc->sc_dmat, (caddr_t)rxq->descs,
674 : ATHN_NRXBUFS * sizeof(struct ar_rx_desc));
675 0 : bus_dmamem_free(sc->sc_dmat, &rxq->seg, 1);
676 0 : }
677 0 : bus_dmamap_destroy(sc->sc_dmat, rxq->map);
678 0 : }
679 0 : }
680 :
681 : void
682 0 : ar5008_rx_enable(struct athn_softc *sc)
683 : {
684 0 : struct athn_rxq *rxq = &sc->rxq[0];
685 : struct athn_rx_buf *bf;
686 : struct ar_rx_desc *ds;
687 : int i;
688 :
689 : /* Setup and link Rx descriptors. */
690 0 : SIMPLEQ_INIT(&rxq->head);
691 0 : rxq->lastds = NULL;
692 0 : for (i = 0; i < ATHN_NRXBUFS; i++) {
693 0 : bf = &rxq->bf[i];
694 0 : ds = bf->bf_desc;
695 :
696 0 : memset(ds, 0, sizeof(*ds));
697 0 : ds->ds_data = bf->bf_map->dm_segs[0].ds_addr;
698 0 : ds->ds_ctl1 = SM(AR_RXC1_BUF_LEN, ATHN_RXBUFSZ);
699 :
700 0 : if (rxq->lastds != NULL) {
701 0 : ((struct ar_rx_desc *)rxq->lastds)->ds_link =
702 0 : bf->bf_daddr;
703 0 : }
704 0 : SIMPLEQ_INSERT_TAIL(&rxq->head, bf, bf_list);
705 0 : rxq->lastds = ds;
706 : }
707 0 : bus_dmamap_sync(sc->sc_dmat, rxq->map, 0, rxq->map->dm_mapsize,
708 : BUS_DMASYNC_PREREAD);
709 :
710 : /* Enable Rx. */
711 0 : AR_WRITE(sc, AR_RXDP, SIMPLEQ_FIRST(&rxq->head)->bf_daddr);
712 0 : AR_WRITE(sc, AR_CR, AR_CR_RXE);
713 0 : AR_WRITE_BARRIER(sc);
714 0 : }
715 :
716 : #if NBPFILTER > 0
717 : void
718 0 : ar5008_rx_radiotap(struct athn_softc *sc, struct mbuf *m,
719 : struct ar_rx_desc *ds)
720 : {
721 : #define IEEE80211_RADIOTAP_F_SHORTGI 0x80 /* XXX from FBSD */
722 :
723 0 : struct athn_rx_radiotap_header *tap = &sc->sc_rxtap;
724 0 : struct ieee80211com *ic = &sc->sc_ic;
725 0 : struct mbuf mb;
726 : uint64_t tsf;
727 : uint32_t tstamp;
728 : uint8_t rate;
729 :
730 : /* Extend the 15-bit timestamp from Rx descriptor to 64-bit TSF. */
731 0 : tstamp = ds->ds_status2;
732 0 : tsf = AR_READ(sc, AR_TSF_U32);
733 0 : tsf = tsf << 32 | AR_READ(sc, AR_TSF_L32);
734 0 : if ((tsf & 0x7fff) < tstamp)
735 0 : tsf -= 0x8000;
736 0 : tsf = (tsf & ~0x7fff) | tstamp;
737 :
738 0 : tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
739 0 : tap->wr_tsft = htole64(tsf);
740 0 : tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
741 0 : tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
742 0 : tap->wr_dbm_antsignal = MS(ds->ds_status4, AR_RXS4_RSSI_COMBINED);
743 : /* XXX noise. */
744 0 : tap->wr_antenna = MS(ds->ds_status3, AR_RXS3_ANTENNA);
745 0 : tap->wr_rate = 0; /* In case it can't be found below. */
746 0 : if (AR_SREV_5416_20_OR_LATER(sc))
747 0 : rate = MS(ds->ds_status0, AR_RXS0_RATE);
748 : else
749 0 : rate = MS(ds->ds_status3, AR_RXS3_RATE);
750 0 : if (rate & 0x80) { /* HT. */
751 : /* Bit 7 set means HT MCS instead of rate. */
752 0 : tap->wr_rate = rate;
753 0 : if (!(ds->ds_status3 & AR_RXS3_GI))
754 0 : tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
755 :
756 0 : } else if (rate & 0x10) { /* CCK. */
757 0 : if (rate & 0x04)
758 0 : tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
759 0 : switch (rate & ~0x14) {
760 0 : case 0xb: tap->wr_rate = 2; break;
761 0 : case 0xa: tap->wr_rate = 4; break;
762 0 : case 0x9: tap->wr_rate = 11; break;
763 0 : case 0x8: tap->wr_rate = 22; break;
764 : }
765 : } else { /* OFDM. */
766 0 : switch (rate) {
767 0 : case 0xb: tap->wr_rate = 12; break;
768 0 : case 0xf: tap->wr_rate = 18; break;
769 0 : case 0xa: tap->wr_rate = 24; break;
770 0 : case 0xe: tap->wr_rate = 36; break;
771 0 : case 0x9: tap->wr_rate = 48; break;
772 0 : case 0xd: tap->wr_rate = 72; break;
773 0 : case 0x8: tap->wr_rate = 96; break;
774 0 : case 0xc: tap->wr_rate = 108; break;
775 : }
776 : }
777 0 : mb.m_data = (caddr_t)tap;
778 0 : mb.m_len = sc->sc_rxtap_len;
779 0 : mb.m_next = m;
780 0 : mb.m_nextpkt = NULL;
781 0 : mb.m_type = 0;
782 0 : mb.m_flags = 0;
783 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
784 0 : }
785 : #endif
786 :
787 : static __inline int
788 0 : ar5008_rx_process(struct athn_softc *sc)
789 : {
790 0 : struct ieee80211com *ic = &sc->sc_ic;
791 0 : struct ifnet *ifp = &ic->ic_if;
792 0 : struct athn_rxq *rxq = &sc->rxq[0];
793 : struct athn_rx_buf *bf, *nbf;
794 : struct ar_rx_desc *ds;
795 : struct ieee80211_frame *wh;
796 0 : struct ieee80211_rxinfo rxi;
797 : struct ieee80211_node *ni;
798 : struct mbuf *m, *m1;
799 : int error, len;
800 :
801 0 : bf = SIMPLEQ_FIRST(&rxq->head);
802 0 : if (__predict_false(bf == NULL)) { /* Should not happen. */
803 0 : printf("%s: Rx queue is empty!\n", sc->sc_dev.dv_xname);
804 0 : return (ENOENT);
805 : }
806 0 : ds = bf->bf_desc;
807 :
808 0 : if (!(ds->ds_status8 & AR_RXS8_DONE)) {
809 : /*
810 : * On some parts, the status words can get corrupted
811 : * (including the "done" bit), so we check the next
812 : * descriptor "done" bit. If it is set, it is a good
813 : * indication that the status words are corrupted, so
814 : * we skip this descriptor and drop the frame.
815 : */
816 0 : nbf = SIMPLEQ_NEXT(bf, bf_list);
817 0 : if (nbf != NULL &&
818 0 : (((struct ar_rx_desc *)nbf->bf_desc)->ds_status8 &
819 : AR_RXS8_DONE)) {
820 : DPRINTF(("corrupted descriptor status=0x%x\n",
821 : ds->ds_status8));
822 : /* HW will not "move" RXDP in this case, so do it. */
823 0 : AR_WRITE(sc, AR_RXDP, nbf->bf_daddr);
824 0 : AR_WRITE_BARRIER(sc);
825 0 : ifp->if_ierrors++;
826 0 : goto skip;
827 : }
828 0 : return (EBUSY);
829 : }
830 :
831 0 : if (__predict_false(ds->ds_status1 & AR_RXS1_MORE)) {
832 : /* Drop frames that span multiple Rx descriptors. */
833 : DPRINTF(("dropping split frame\n"));
834 0 : ifp->if_ierrors++;
835 0 : goto skip;
836 : }
837 0 : if (!(ds->ds_status8 & AR_RXS8_FRAME_OK)) {
838 0 : if (ds->ds_status8 & AR_RXS8_CRC_ERR)
839 : DPRINTFN(6, ("CRC error\n"));
840 0 : else if (ds->ds_status8 & AR_RXS8_PHY_ERR)
841 : DPRINTFN(6, ("PHY error=0x%x\n",
842 : MS(ds->ds_status8, AR_RXS8_PHY_ERR_CODE)));
843 0 : else if (ds->ds_status8 & AR_RXS8_DECRYPT_CRC_ERR)
844 : DPRINTFN(6, ("Decryption CRC error\n"));
845 0 : else if (ds->ds_status8 & AR_RXS8_MICHAEL_ERR) {
846 : DPRINTFN(2, ("Michael MIC failure\n"));
847 : /* Report Michael MIC failures to net80211. */
848 0 : ic->ic_stats.is_rx_locmicfail++;
849 0 : ieee80211_michael_mic_failure(ic, 0);
850 : /*
851 : * XXX Check that it is not a control frame
852 : * (invalid MIC failures on valid ctl frames).
853 : */
854 0 : }
855 0 : ifp->if_ierrors++;
856 0 : goto skip;
857 : }
858 :
859 0 : len = MS(ds->ds_status1, AR_RXS1_DATA_LEN);
860 0 : if (__predict_false(len < IEEE80211_MIN_LEN || len > ATHN_RXBUFSZ)) {
861 : DPRINTF(("corrupted descriptor length=%d\n", len));
862 0 : ifp->if_ierrors++;
863 0 : goto skip;
864 : }
865 :
866 : /* Allocate a new Rx buffer. */
867 0 : m1 = MCLGETI(NULL, M_DONTWAIT, NULL, ATHN_RXBUFSZ);
868 0 : if (__predict_false(m1 == NULL)) {
869 0 : ic->ic_stats.is_rx_nombuf++;
870 0 : ifp->if_ierrors++;
871 0 : goto skip;
872 : }
873 :
874 : /* Sync and unmap the old Rx buffer. */
875 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, ATHN_RXBUFSZ,
876 : BUS_DMASYNC_POSTREAD);
877 0 : bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
878 :
879 : /* Map the new Rx buffer. */
880 0 : error = bus_dmamap_load(sc->sc_dmat, bf->bf_map, mtod(m1, void *),
881 : ATHN_RXBUFSZ, NULL, BUS_DMA_NOWAIT | BUS_DMA_READ);
882 0 : if (__predict_false(error != 0)) {
883 0 : m_freem(m1);
884 :
885 : /* Remap the old Rx buffer or panic. */
886 0 : error = bus_dmamap_load(sc->sc_dmat, bf->bf_map,
887 : mtod(bf->bf_m, void *), ATHN_RXBUFSZ, NULL,
888 : BUS_DMA_NOWAIT | BUS_DMA_READ);
889 0 : KASSERT(error != 0);
890 0 : ifp->if_ierrors++;
891 0 : goto skip;
892 : }
893 :
894 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, ATHN_RXBUFSZ,
895 : BUS_DMASYNC_PREREAD);
896 :
897 : /* Write physical address of new Rx buffer. */
898 0 : ds->ds_data = bf->bf_map->dm_segs[0].ds_addr;
899 :
900 0 : m = bf->bf_m;
901 0 : bf->bf_m = m1;
902 :
903 : /* Finalize mbuf. */
904 0 : m->m_pkthdr.len = m->m_len = len;
905 :
906 : /* Grab a reference to the source node. */
907 0 : wh = mtod(m, struct ieee80211_frame *);
908 0 : ni = ieee80211_find_rxnode(ic, wh);
909 :
910 : /* Remove any HW padding after the 802.11 header. */
911 0 : if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) {
912 0 : u_int hdrlen = ieee80211_get_hdrlen(wh);
913 0 : if (hdrlen & 3) {
914 0 : memmove((caddr_t)wh + 2, wh, hdrlen);
915 0 : m_adj(m, 2);
916 0 : }
917 0 : }
918 : #if NBPFILTER > 0
919 0 : if (__predict_false(sc->sc_drvbpf != NULL))
920 0 : ar5008_rx_radiotap(sc, m, ds);
921 : #endif
922 : /* Trim 802.11 FCS after radiotap. */
923 0 : m_adj(m, -IEEE80211_CRC_LEN);
924 :
925 : /* Send the frame to the 802.11 layer. */
926 0 : rxi.rxi_flags = 0; /* XXX */
927 0 : rxi.rxi_rssi = MS(ds->ds_status4, AR_RXS4_RSSI_COMBINED);
928 0 : rxi.rxi_rssi += AR_DEFAULT_NOISE_FLOOR;
929 0 : rxi.rxi_tstamp = ds->ds_status2;
930 0 : ieee80211_input(ifp, m, ni, &rxi);
931 :
932 : /* Node is no longer needed. */
933 0 : ieee80211_release_node(ic, ni);
934 :
935 : skip:
936 : /* Unlink this descriptor from head. */
937 0 : SIMPLEQ_REMOVE_HEAD(&rxq->head, bf_list);
938 0 : memset(&ds->ds_status0, 0, 36); /* XXX Really needed? */
939 0 : ds->ds_status8 &= ~AR_RXS8_DONE;
940 0 : ds->ds_link = 0;
941 :
942 : /* Re-use this descriptor and link it to tail. */
943 0 : if (__predict_true(!SIMPLEQ_EMPTY(&rxq->head)))
944 0 : ((struct ar_rx_desc *)rxq->lastds)->ds_link = bf->bf_daddr;
945 : else
946 0 : AR_WRITE(sc, AR_RXDP, bf->bf_daddr);
947 0 : SIMPLEQ_INSERT_TAIL(&rxq->head, bf, bf_list);
948 0 : rxq->lastds = ds;
949 :
950 : /* Re-enable Rx. */
951 0 : AR_WRITE(sc, AR_CR, AR_CR_RXE);
952 0 : AR_WRITE_BARRIER(sc);
953 0 : return (0);
954 0 : }
955 :
956 : void
957 0 : ar5008_rx_intr(struct athn_softc *sc)
958 : {
959 0 : while (ar5008_rx_process(sc) == 0);
960 0 : }
961 :
962 : int
963 0 : ar5008_tx_process(struct athn_softc *sc, int qid)
964 : {
965 0 : struct ieee80211com *ic = &sc->sc_ic;
966 0 : struct ifnet *ifp = &ic->ic_if;
967 0 : struct athn_txq *txq = &sc->txq[qid];
968 : struct athn_node *an;
969 : struct ieee80211_node *ni;
970 : struct athn_tx_buf *bf;
971 : struct ar_tx_desc *ds;
972 : uint8_t failcnt;
973 : int txfail;
974 :
975 0 : bf = SIMPLEQ_FIRST(&txq->head);
976 0 : if (bf == NULL)
977 0 : return (ENOENT);
978 : /* Get descriptor of last DMA segment. */
979 0 : ds = &((struct ar_tx_desc *)bf->bf_descs)[bf->bf_map->dm_nsegs - 1];
980 :
981 0 : if (!(ds->ds_status9 & AR_TXS9_DONE))
982 0 : return (EBUSY);
983 :
984 0 : SIMPLEQ_REMOVE_HEAD(&txq->head, bf_list);
985 :
986 0 : sc->sc_tx_timer = 0;
987 :
988 0 : txfail = (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES);
989 0 : if (txfail)
990 0 : ifp->if_oerrors++;
991 :
992 0 : if (ds->ds_status1 & AR_TXS1_UNDERRUN)
993 0 : athn_inc_tx_trigger_level(sc);
994 :
995 0 : an = (struct athn_node *)bf->bf_ni;
996 : ni = (struct ieee80211_node *)bf->bf_ni;
997 :
998 : /*
999 : * NB: the data fail count contains the number of un-acked tries
1000 : * for the final series used. We must add the number of tries for
1001 : * each series that was fully processed to punish transmit rates in
1002 : * the earlier series which did not perform well.
1003 : * If RTS/CTS was used, each series used the same transmit rate.
1004 : * Ignore the series count in this case, since each series had
1005 : * the same chance of success.
1006 : */
1007 0 : failcnt = MS(ds->ds_status1, AR_TXS1_DATA_FAIL_CNT);
1008 0 : if (!(ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE))) {
1009 : /* NB: Assume two tries per series. */
1010 0 : failcnt += MS(ds->ds_status9, AR_TXS9_FINAL_IDX) * 2;
1011 0 : }
1012 :
1013 : /* Update rate control statistics. */
1014 0 : if (ni->ni_flags & IEEE80211_NODE_HT) {
1015 0 : an->mn.frames++;
1016 0 : an->mn.ampdu_size = bf->bf_m->m_pkthdr.len + IEEE80211_CRC_LEN;
1017 0 : an->mn.agglen = 1; /* XXX We do not yet support Tx agg. */
1018 0 : if (failcnt > 0)
1019 0 : an->mn.retries += failcnt;
1020 0 : if (txfail)
1021 0 : an->mn.txfail++;
1022 0 : if (ic->ic_state == IEEE80211_S_RUN) {
1023 : #ifndef IEEE80211_STA_ONLY
1024 0 : if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
1025 0 : ni->ni_state == IEEE80211_STA_ASSOC)
1026 : #endif
1027 0 : ieee80211_mira_choose(&an->mn, ic, ni);
1028 : }
1029 : } else {
1030 0 : an->amn.amn_txcnt++;
1031 0 : if (failcnt > 0)
1032 0 : an->amn.amn_retrycnt++;
1033 : }
1034 : DPRINTFN(5, ("Tx done qid=%d status1=%d fail count=%d\n",
1035 : qid, ds->ds_status1, failcnt));
1036 :
1037 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
1038 : BUS_DMASYNC_POSTWRITE);
1039 0 : bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
1040 :
1041 0 : m_freem(bf->bf_m);
1042 0 : bf->bf_m = NULL;
1043 0 : ieee80211_release_node(ic, bf->bf_ni);
1044 0 : bf->bf_ni = NULL;
1045 :
1046 : /* Link Tx buffer back to global free list. */
1047 0 : SIMPLEQ_INSERT_TAIL(&sc->txbufs, bf, bf_list);
1048 0 : return (0);
1049 0 : }
1050 :
1051 : void
1052 0 : ar5008_tx_intr(struct athn_softc *sc)
1053 : {
1054 0 : struct ieee80211com *ic = &sc->sc_ic;
1055 0 : struct ifnet *ifp = &ic->ic_if;
1056 : uint16_t mask = 0;
1057 : uint32_t reg;
1058 : int qid;
1059 :
1060 0 : reg = AR_READ(sc, AR_ISR_S0_S);
1061 0 : mask |= MS(reg, AR_ISR_S0_QCU_TXOK);
1062 0 : mask |= MS(reg, AR_ISR_S0_QCU_TXDESC);
1063 :
1064 0 : reg = AR_READ(sc, AR_ISR_S1_S);
1065 0 : mask |= MS(reg, AR_ISR_S1_QCU_TXERR);
1066 0 : mask |= MS(reg, AR_ISR_S1_QCU_TXEOL);
1067 :
1068 : DPRINTFN(4, ("Tx interrupt mask=0x%x\n", mask));
1069 0 : for (qid = 0; mask != 0; mask >>= 1, qid++) {
1070 0 : if (mask & 1)
1071 0 : while (ar5008_tx_process(sc, qid) == 0);
1072 : }
1073 0 : if (!SIMPLEQ_EMPTY(&sc->txbufs)) {
1074 0 : ifq_clr_oactive(&ifp->if_snd);
1075 0 : ifp->if_start(ifp);
1076 0 : }
1077 0 : }
1078 :
1079 : #ifndef IEEE80211_STA_ONLY
1080 : /*
1081 : * Process Software Beacon Alert interrupts.
1082 : */
1083 : int
1084 0 : ar5008_swba_intr(struct athn_softc *sc)
1085 : {
1086 0 : struct ieee80211com *ic = &sc->sc_ic;
1087 0 : struct ifnet *ifp = &ic->ic_if;
1088 0 : struct ieee80211_node *ni = ic->ic_bss;
1089 0 : struct athn_tx_buf *bf = sc->bcnbuf;
1090 : struct ieee80211_frame *wh;
1091 : struct ar_tx_desc *ds;
1092 : struct mbuf *m;
1093 : uint8_t ridx, hwrate;
1094 : int error, totlen;
1095 :
1096 0 : if (ic->ic_tim_mcast_pending &&
1097 0 : mq_empty(&ni->ni_savedq) &&
1098 0 : SIMPLEQ_EMPTY(&sc->txq[ATHN_QID_CAB].head))
1099 0 : ic->ic_tim_mcast_pending = 0;
1100 :
1101 0 : if (ic->ic_dtim_count == 0)
1102 0 : ic->ic_dtim_count = ic->ic_dtim_period - 1;
1103 : else
1104 0 : ic->ic_dtim_count--;
1105 :
1106 : /* Make sure previous beacon has been sent. */
1107 0 : if (athn_tx_pending(sc, ATHN_QID_BEACON)) {
1108 : DPRINTF(("beacon stuck\n"));
1109 0 : return (EBUSY);
1110 : }
1111 : /* Get new beacon. */
1112 0 : m = ieee80211_beacon_alloc(ic, ic->ic_bss);
1113 0 : if (__predict_false(m == NULL))
1114 0 : return (ENOBUFS);
1115 : /* Assign sequence number. */
1116 0 : wh = mtod(m, struct ieee80211_frame *);
1117 0 : *(uint16_t *)&wh->i_seq[0] =
1118 0 : htole16(ic->ic_bss->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
1119 0 : ic->ic_bss->ni_txseq++;
1120 :
1121 : /* Unmap and free old beacon if any. */
1122 0 : if (__predict_true(bf->bf_m != NULL)) {
1123 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0,
1124 : bf->bf_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1125 0 : bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
1126 0 : m_freem(bf->bf_m);
1127 0 : bf->bf_m = NULL;
1128 0 : }
1129 : /* DMA map new beacon. */
1130 0 : error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_map, m,
1131 : BUS_DMA_NOWAIT | BUS_DMA_WRITE);
1132 0 : if (__predict_false(error != 0)) {
1133 0 : m_freem(m);
1134 0 : return (error);
1135 : }
1136 0 : bf->bf_m = m;
1137 :
1138 : /* Setup Tx descriptor (simplified ar5008_tx()). */
1139 0 : ds = bf->bf_descs;
1140 0 : memset(ds, 0, sizeof(*ds));
1141 :
1142 0 : totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
1143 0 : ds->ds_ctl0 = SM(AR_TXC0_FRAME_LEN, totlen);
1144 0 : ds->ds_ctl0 |= SM(AR_TXC0_XMIT_POWER, AR_MAX_RATE_POWER);
1145 0 : ds->ds_ctl1 = SM(AR_TXC1_FRAME_TYPE, AR_FRAME_TYPE_BEACON);
1146 0 : ds->ds_ctl1 |= AR_TXC1_NO_ACK;
1147 0 : ds->ds_ctl6 = SM(AR_TXC6_ENCR_TYPE, AR_ENCR_TYPE_CLEAR);
1148 :
1149 : /* Write number of tries. */
1150 0 : ds->ds_ctl2 = SM(AR_TXC2_XMIT_DATA_TRIES0, 1);
1151 :
1152 : /* Write Tx rate. */
1153 0 : ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
1154 : ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1;
1155 0 : hwrate = athn_rates[ridx].hwrate;
1156 0 : ds->ds_ctl3 = SM(AR_TXC3_XMIT_RATE0, hwrate);
1157 :
1158 : /* Write Tx chains. */
1159 0 : ds->ds_ctl7 = SM(AR_TXC7_CHAIN_SEL0, sc->txchainmask);
1160 :
1161 0 : ds->ds_data = bf->bf_map->dm_segs[0].ds_addr;
1162 : /* Segment length must be a multiple of 4. */
1163 0 : ds->ds_ctl1 |= SM(AR_TXC1_BUF_LEN,
1164 : (bf->bf_map->dm_segs[0].ds_len + 3) & ~3);
1165 :
1166 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
1167 : BUS_DMASYNC_PREWRITE);
1168 :
1169 : /* Stop Tx DMA before putting the new beacon on the queue. */
1170 0 : athn_stop_tx_dma(sc, ATHN_QID_BEACON);
1171 :
1172 0 : AR_WRITE(sc, AR_QTXDP(ATHN_QID_BEACON), bf->bf_daddr);
1173 :
1174 0 : for(;;) {
1175 0 : if (SIMPLEQ_EMPTY(&sc->txbufs))
1176 : break;
1177 :
1178 0 : m = mq_dequeue(&ni->ni_savedq);
1179 0 : if (m == NULL)
1180 : break;
1181 0 : if (!mq_empty(&ni->ni_savedq)) {
1182 : /* more queued frames, set the more data bit */
1183 0 : wh = mtod(m, struct ieee80211_frame *);
1184 0 : wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
1185 0 : }
1186 :
1187 0 : if (sc->ops.tx(sc, m, ni, ATHN_TXFLAG_CAB) != 0) {
1188 0 : ieee80211_release_node(ic, ni);
1189 0 : ifp->if_oerrors++;
1190 0 : break;
1191 : }
1192 : }
1193 :
1194 : /* Kick Tx. */
1195 0 : AR_WRITE(sc, AR_Q_TXE, 1 << ATHN_QID_BEACON);
1196 0 : AR_WRITE_BARRIER(sc);
1197 0 : return (0);
1198 0 : }
1199 : #endif
1200 :
1201 : int
1202 0 : ar5008_intr(struct athn_softc *sc)
1203 : {
1204 : uint32_t intr, intr2, intr5, sync;
1205 :
1206 : /* Get pending interrupts. */
1207 0 : intr = AR_READ(sc, AR_INTR_ASYNC_CAUSE);
1208 0 : if (!(intr & AR_INTR_MAC_IRQ) || intr == AR_INTR_SPURIOUS) {
1209 0 : intr = AR_READ(sc, AR_INTR_SYNC_CAUSE);
1210 0 : if (intr == AR_INTR_SPURIOUS || (intr & sc->isync) == 0)
1211 0 : return (0); /* Not for us. */
1212 : }
1213 :
1214 0 : if ((AR_READ(sc, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) &&
1215 0 : (AR_READ(sc, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
1216 0 : intr = AR_READ(sc, AR_ISR);
1217 : else
1218 : intr = 0;
1219 0 : sync = AR_READ(sc, AR_INTR_SYNC_CAUSE) & sc->isync;
1220 0 : if (intr == 0 && sync == 0)
1221 0 : return (0); /* Not for us. */
1222 :
1223 0 : if (intr != 0) {
1224 0 : if (intr & AR_ISR_BCNMISC) {
1225 0 : intr2 = AR_READ(sc, AR_ISR_S2);
1226 0 : if (intr2 & AR_ISR_S2_TIM)
1227 : /* TBD */;
1228 0 : if (intr2 & AR_ISR_S2_TSFOOR)
1229 : /* TBD */;
1230 0 : }
1231 0 : intr = AR_READ(sc, AR_ISR_RAC);
1232 0 : if (intr == AR_INTR_SPURIOUS)
1233 0 : return (1);
1234 :
1235 : #ifndef IEEE80211_STA_ONLY
1236 0 : if (intr & AR_ISR_SWBA)
1237 0 : ar5008_swba_intr(sc);
1238 : #endif
1239 0 : if (intr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
1240 0 : ar5008_rx_intr(sc);
1241 0 : if (intr & (AR_ISR_RXOK | AR_ISR_RXERR | AR_ISR_RXORN))
1242 0 : ar5008_rx_intr(sc);
1243 :
1244 0 : if (intr & (AR_ISR_TXOK | AR_ISR_TXDESC |
1245 : AR_ISR_TXERR | AR_ISR_TXEOL))
1246 0 : ar5008_tx_intr(sc);
1247 :
1248 0 : intr5 = AR_READ(sc, AR_ISR_S5_S);
1249 0 : if (intr & AR_ISR_GENTMR) {
1250 0 : if (intr5 & AR_ISR_GENTMR) {
1251 : DPRINTF(("GENTMR trigger=%d thresh=%d\n",
1252 : MS(intr5, AR_ISR_S5_GENTIMER_TRIG),
1253 : MS(intr5, AR_ISR_S5_GENTIMER_THRESH)));
1254 : }
1255 0 : }
1256 :
1257 0 : if (intr5 & AR_ISR_S5_TIM_TIMER)
1258 : /* TBD */;
1259 0 : }
1260 0 : if (sync != 0) {
1261 0 : if (sync & (AR_INTR_SYNC_HOST1_FATAL |
1262 : AR_INTR_SYNC_HOST1_PERR))
1263 : /* TBD */;
1264 :
1265 0 : if (sync & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
1266 0 : AR_WRITE(sc, AR_RC, AR_RC_HOSTIF);
1267 0 : AR_WRITE(sc, AR_RC, 0);
1268 0 : }
1269 :
1270 0 : if ((sc->flags & ATHN_FLAG_RFSILENT) &&
1271 0 : (sync & AR_INTR_SYNC_GPIO_PIN(sc->rfsilent_pin))) {
1272 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
1273 :
1274 0 : printf("%s: radio switch turned off\n",
1275 0 : sc->sc_dev.dv_xname);
1276 : /* Turn the interface down. */
1277 0 : athn_stop(ifp, 1);
1278 : return (1);
1279 : }
1280 :
1281 0 : AR_WRITE(sc, AR_INTR_SYNC_CAUSE, sync);
1282 0 : (void)AR_READ(sc, AR_INTR_SYNC_CAUSE);
1283 0 : }
1284 0 : return (1);
1285 0 : }
1286 :
1287 : int
1288 0 : ar5008_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
1289 : int txflags)
1290 : {
1291 0 : struct ieee80211com *ic = &sc->sc_ic;
1292 : struct ieee80211_key *k = NULL;
1293 : struct ieee80211_frame *wh;
1294 0 : struct athn_series series[4];
1295 : struct ar_tx_desc *ds, *lastds;
1296 : struct athn_txq *txq;
1297 : struct athn_tx_buf *bf;
1298 0 : struct athn_node *an = (void *)ni;
1299 : struct mbuf *m1;
1300 : uintptr_t entry;
1301 : uint16_t qos;
1302 0 : uint8_t txpower, type, encrtype, tid, ridx[4];
1303 : int i, error, totlen, hasqos, qid;
1304 :
1305 : /* Grab a Tx buffer from our global free list. */
1306 0 : bf = SIMPLEQ_FIRST(&sc->txbufs);
1307 0 : KASSERT(bf != NULL);
1308 :
1309 : /* Map 802.11 frame type to hardware frame type. */
1310 0 : wh = mtod(m, struct ieee80211_frame *);
1311 0 : if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
1312 : IEEE80211_FC0_TYPE_MGT) {
1313 : /* NB: Beacons do not use ar5008_tx(). */
1314 0 : if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
1315 : IEEE80211_FC0_SUBTYPE_PROBE_RESP)
1316 0 : type = AR_FRAME_TYPE_PROBE_RESP;
1317 0 : else if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
1318 : IEEE80211_FC0_SUBTYPE_ATIM)
1319 0 : type = AR_FRAME_TYPE_ATIM;
1320 : else
1321 : type = AR_FRAME_TYPE_NORMAL;
1322 0 : } else if ((wh->i_fc[0] &
1323 0 : (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
1324 : (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) {
1325 : type = AR_FRAME_TYPE_PSPOLL;
1326 0 : } else
1327 : type = AR_FRAME_TYPE_NORMAL;
1328 :
1329 0 : if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1330 0 : k = ieee80211_get_txkey(ic, wh, ni);
1331 0 : if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
1332 0 : return (ENOBUFS);
1333 0 : wh = mtod(m, struct ieee80211_frame *);
1334 0 : }
1335 :
1336 : /* XXX 2-byte padding for QoS and 4-addr headers. */
1337 :
1338 : /* Select the HW Tx queue to use for this frame. */
1339 0 : if ((hasqos = ieee80211_has_qos(wh))) {
1340 0 : qos = ieee80211_get_qos(wh);
1341 0 : tid = qos & IEEE80211_QOS_TID;
1342 0 : qid = athn_ac2qid[ieee80211_up_to_ac(ic, tid)];
1343 0 : } else if (type == AR_FRAME_TYPE_PSPOLL) {
1344 : qid = ATHN_QID_PSPOLL;
1345 0 : } else if (txflags & ATHN_TXFLAG_CAB) {
1346 : qid = ATHN_QID_CAB;
1347 0 : } else
1348 : qid = ATHN_QID_AC_BE;
1349 0 : txq = &sc->txq[qid];
1350 :
1351 : /* Select the transmit rates to use for this frame. */
1352 0 : if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1353 0 : (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
1354 : IEEE80211_FC0_TYPE_DATA) {
1355 : /* Use lowest rate for all tries. */
1356 0 : ridx[0] = ridx[1] = ridx[2] = ridx[3] =
1357 0 : (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
1358 : ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1);
1359 0 : } else if ((ni->ni_flags & IEEE80211_NODE_HT) &&
1360 0 : ic->ic_fixed_mcs != -1) {
1361 : /* Use same fixed rate for all tries. */
1362 0 : ridx[0] = ridx[1] = ridx[2] = ridx[3] =
1363 0 : ATHN_RIDX_MCS0 + ic->ic_fixed_mcs;
1364 0 : } else if (ic->ic_fixed_rate != -1) {
1365 : /* Use same fixed rate for all tries. */
1366 0 : ridx[0] = ridx[1] = ridx[2] = ridx[3] =
1367 0 : sc->fixed_ridx;
1368 0 : } else {
1369 : /* Use fallback table of the node. */
1370 : int txrate;
1371 :
1372 0 : if (ni->ni_flags & IEEE80211_NODE_HT)
1373 0 : txrate = ATHN_NUM_LEGACY_RATES + ni->ni_txmcs;
1374 : else
1375 0 : txrate = ni->ni_txrate;
1376 0 : for (i = 0; i < 4; i++) {
1377 0 : ridx[i] = an->ridx[txrate];
1378 0 : txrate = an->fallback[txrate];
1379 : }
1380 : }
1381 :
1382 : #if NBPFILTER > 0
1383 0 : if (__predict_false(sc->sc_drvbpf != NULL)) {
1384 0 : struct athn_tx_radiotap_header *tap = &sc->sc_txtap;
1385 0 : struct mbuf mb;
1386 :
1387 0 : tap->wt_flags = 0;
1388 : /* Use initial transmit rate. */
1389 0 : if (athn_rates[ridx[0]].hwrate & 0x80) /* MCS */
1390 0 : tap->wt_rate = athn_rates[ridx[0]].hwrate;
1391 : else
1392 0 : tap->wt_rate = athn_rates[ridx[0]].rate;
1393 0 : tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
1394 0 : tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
1395 0 : tap->wt_hwqueue = qid;
1396 0 : if (ridx[0] != ATHN_RIDX_CCK1 &&
1397 0 : (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
1398 0 : tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
1399 0 : mb.m_data = (caddr_t)tap;
1400 0 : mb.m_len = sc->sc_txtap_len;
1401 0 : mb.m_next = m;
1402 0 : mb.m_nextpkt = NULL;
1403 0 : mb.m_type = 0;
1404 0 : mb.m_flags = 0;
1405 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
1406 0 : }
1407 : #endif
1408 :
1409 : /* DMA map mbuf. */
1410 0 : error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_map, m,
1411 : BUS_DMA_NOWAIT | BUS_DMA_WRITE);
1412 0 : if (__predict_false(error != 0)) {
1413 0 : if (error != EFBIG) {
1414 0 : printf("%s: can't map mbuf (error %d)\n",
1415 0 : sc->sc_dev.dv_xname, error);
1416 0 : m_freem(m);
1417 0 : return (error);
1418 : }
1419 : /*
1420 : * DMA mapping requires too many DMA segments; linearize
1421 : * mbuf in kernel virtual address space and retry.
1422 : */
1423 0 : MGETHDR(m1, M_DONTWAIT, MT_DATA);
1424 0 : if (m1 == NULL) {
1425 0 : m_freem(m);
1426 0 : return (ENOBUFS);
1427 : }
1428 0 : if (m->m_pkthdr.len > MHLEN) {
1429 0 : MCLGET(m1, M_DONTWAIT);
1430 0 : if (!(m1->m_flags & M_EXT)) {
1431 0 : m_freem(m);
1432 0 : m_freem(m1);
1433 0 : return (ENOBUFS);
1434 : }
1435 : }
1436 0 : m_copydata(m, 0, m->m_pkthdr.len, mtod(m1, caddr_t));
1437 0 : m1->m_pkthdr.len = m1->m_len = m->m_pkthdr.len;
1438 0 : m_freem(m);
1439 : m = m1;
1440 :
1441 0 : error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_map, m,
1442 : BUS_DMA_NOWAIT | BUS_DMA_WRITE);
1443 0 : if (error != 0) {
1444 0 : printf("%s: can't map mbuf (error %d)\n",
1445 0 : sc->sc_dev.dv_xname, error);
1446 0 : m_freem(m);
1447 0 : return (error);
1448 : }
1449 : }
1450 0 : bf->bf_m = m;
1451 0 : bf->bf_ni = ni;
1452 0 : bf->bf_txflags = txflags;
1453 :
1454 0 : wh = mtod(m, struct ieee80211_frame *);
1455 :
1456 0 : totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
1457 :
1458 : /* Clear all Tx descriptors that we will use. */
1459 0 : memset(bf->bf_descs, 0, bf->bf_map->dm_nsegs * sizeof(*ds));
1460 :
1461 : /* Setup first Tx descriptor. */
1462 0 : ds = bf->bf_descs;
1463 :
1464 0 : ds->ds_ctl0 = AR_TXC0_INTR_REQ | AR_TXC0_CLR_DEST_MASK;
1465 : txpower = AR_MAX_RATE_POWER; /* Get from per-rate registers. */
1466 0 : ds->ds_ctl0 |= SM(AR_TXC0_XMIT_POWER, txpower);
1467 :
1468 0 : ds->ds_ctl1 = SM(AR_TXC1_FRAME_TYPE, type);
1469 :
1470 0 : if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1471 0 : (hasqos && (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==
1472 : IEEE80211_QOS_ACK_POLICY_NOACK))
1473 0 : ds->ds_ctl1 |= AR_TXC1_NO_ACK;
1474 :
1475 : if (0 && k != NULL) {
1476 : /*
1477 : * Map 802.11 cipher to hardware encryption type and
1478 : * compute MIC+ICV overhead.
1479 : */
1480 : switch (k->k_cipher) {
1481 : case IEEE80211_CIPHER_WEP40:
1482 : case IEEE80211_CIPHER_WEP104:
1483 : encrtype = AR_ENCR_TYPE_WEP;
1484 : totlen += 4;
1485 : break;
1486 : case IEEE80211_CIPHER_TKIP:
1487 : encrtype = AR_ENCR_TYPE_TKIP;
1488 : totlen += 12;
1489 : break;
1490 : case IEEE80211_CIPHER_CCMP:
1491 : encrtype = AR_ENCR_TYPE_AES;
1492 : totlen += 8;
1493 : break;
1494 : default:
1495 : panic("unsupported cipher");
1496 : }
1497 : /*
1498 : * NB: The key cache entry index is stored in the key
1499 : * private field when the key is installed.
1500 : */
1501 : entry = (uintptr_t)k->k_priv;
1502 : ds->ds_ctl1 |= SM(AR_TXC1_DEST_IDX, entry);
1503 : ds->ds_ctl0 |= AR_TXC0_DEST_IDX_VALID;
1504 : } else
1505 : encrtype = AR_ENCR_TYPE_CLEAR;
1506 0 : ds->ds_ctl6 = SM(AR_TXC6_ENCR_TYPE, encrtype);
1507 :
1508 : /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
1509 0 : if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
1510 0 : (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
1511 : IEEE80211_FC0_TYPE_DATA) {
1512 : enum ieee80211_htprot htprot;
1513 :
1514 0 : htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);
1515 : /* NB: Group frames are sent using CCK in 802.11b/g. */
1516 0 : if (totlen > ic->ic_rtsthreshold) {
1517 0 : ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
1518 0 : } else if (((ic->ic_flags & IEEE80211_F_USEPROT) &&
1519 0 : athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) ||
1520 0 : ((ni->ni_flags & IEEE80211_NODE_HT) &&
1521 0 : htprot != IEEE80211_HTPROT_NONE)) {
1522 0 : if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
1523 0 : ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
1524 0 : else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
1525 0 : ds->ds_ctl0 |= AR_TXC0_CTS_ENABLE;
1526 : }
1527 0 : }
1528 : /*
1529 : * Disable multi-rate retries when protection is used.
1530 : * The RTS/CTS frame's duration field is fixed and won't be
1531 : * updated by hardware when the data rate changes.
1532 : */
1533 0 : if (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)) {
1534 0 : ridx[1] = ridx[2] = ridx[3] = ridx[0];
1535 0 : }
1536 : /* Setup multi-rate retries. */
1537 0 : for (i = 0; i < 4; i++) {
1538 0 : series[i].hwrate = athn_rates[ridx[i]].hwrate;
1539 0 : if (athn_rates[ridx[i]].phy == IEEE80211_T_DS &&
1540 0 : ridx[i] != ATHN_RIDX_CCK1 &&
1541 0 : (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
1542 0 : series[i].hwrate |= 0x04;
1543 0 : series[i].dur = 0;
1544 : }
1545 0 : if (!(ds->ds_ctl1 & AR_TXC1_NO_ACK)) {
1546 : /* Compute duration for each series. */
1547 0 : for (i = 0; i < 4; i++) {
1548 0 : series[i].dur = athn_txtime(sc, IEEE80211_ACK_LEN,
1549 0 : athn_rates[ridx[i]].rspridx, ic->ic_flags);
1550 : }
1551 : }
1552 :
1553 : /* Write number of tries for each series. */
1554 0 : ds->ds_ctl2 =
1555 : SM(AR_TXC2_XMIT_DATA_TRIES0, 2) |
1556 : SM(AR_TXC2_XMIT_DATA_TRIES1, 2) |
1557 : SM(AR_TXC2_XMIT_DATA_TRIES2, 2) |
1558 : SM(AR_TXC2_XMIT_DATA_TRIES3, 4);
1559 :
1560 : /* Tell HW to update duration field in 802.11 header. */
1561 0 : if (type != AR_FRAME_TYPE_PSPOLL)
1562 0 : ds->ds_ctl2 |= AR_TXC2_DUR_UPDATE_ENA;
1563 :
1564 : /* Write Tx rate for each series. */
1565 0 : ds->ds_ctl3 =
1566 0 : SM(AR_TXC3_XMIT_RATE0, series[0].hwrate) |
1567 0 : SM(AR_TXC3_XMIT_RATE1, series[1].hwrate) |
1568 0 : SM(AR_TXC3_XMIT_RATE2, series[2].hwrate) |
1569 0 : SM(AR_TXC3_XMIT_RATE3, series[3].hwrate);
1570 :
1571 : /* Write duration for each series. */
1572 0 : ds->ds_ctl4 =
1573 0 : SM(AR_TXC4_PACKET_DUR0, series[0].dur) |
1574 0 : SM(AR_TXC4_PACKET_DUR1, series[1].dur);
1575 0 : ds->ds_ctl5 =
1576 0 : SM(AR_TXC5_PACKET_DUR2, series[2].dur) |
1577 0 : SM(AR_TXC5_PACKET_DUR3, series[3].dur);
1578 :
1579 : /* Use the same Tx chains for all tries. */
1580 0 : ds->ds_ctl7 =
1581 0 : SM(AR_TXC7_CHAIN_SEL0, sc->txchainmask) |
1582 0 : SM(AR_TXC7_CHAIN_SEL1, sc->txchainmask) |
1583 0 : SM(AR_TXC7_CHAIN_SEL2, sc->txchainmask) |
1584 0 : SM(AR_TXC7_CHAIN_SEL3, sc->txchainmask);
1585 : #ifdef notyet
1586 : /* Use the same short GI setting for all tries. */
1587 : if (ni->ni_htcaps & IEEE80211_HTCAP_SGI20)
1588 : ds->ds_ctl7 |= AR_TXC7_GI0123;
1589 : /* Use the same channel width for all tries. */
1590 : if (ic->ic_flags & IEEE80211_F_CBW40)
1591 : ds->ds_ctl7 |= AR_TXC7_2040_0123;
1592 : #endif
1593 :
1594 0 : if (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)) {
1595 : uint8_t protridx, hwrate;
1596 : uint16_t dur = 0;
1597 :
1598 : /* Use the same protection mode for all tries. */
1599 0 : if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) {
1600 0 : ds->ds_ctl4 |= AR_TXC4_RTSCTS_QUAL01;
1601 0 : ds->ds_ctl5 |= AR_TXC5_RTSCTS_QUAL23;
1602 0 : }
1603 : /* Select protection rate (suboptimal but ok). */
1604 0 : protridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
1605 : ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK2;
1606 0 : if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) {
1607 : /* Account for CTS duration. */
1608 0 : dur += athn_txtime(sc, IEEE80211_ACK_LEN,
1609 0 : athn_rates[protridx].rspridx, ic->ic_flags);
1610 0 : }
1611 0 : dur += athn_txtime(sc, totlen, ridx[0], ic->ic_flags);
1612 0 : if (!(ds->ds_ctl1 & AR_TXC1_NO_ACK)) {
1613 : /* Account for ACK duration. */
1614 0 : dur += athn_txtime(sc, IEEE80211_ACK_LEN,
1615 0 : athn_rates[ridx[0]].rspridx, ic->ic_flags);
1616 0 : }
1617 : /* Write protection frame duration and rate. */
1618 0 : ds->ds_ctl2 |= SM(AR_TXC2_BURST_DUR, dur);
1619 0 : hwrate = athn_rates[protridx].hwrate;
1620 0 : if (protridx == ATHN_RIDX_CCK2 &&
1621 0 : (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
1622 0 : hwrate |= 0x04;
1623 0 : ds->ds_ctl7 |= SM(AR_TXC7_RTSCTS_RATE, hwrate);
1624 0 : }
1625 :
1626 : /* Finalize first Tx descriptor and fill others (if any). */
1627 0 : ds->ds_ctl0 |= SM(AR_TXC0_FRAME_LEN, totlen);
1628 :
1629 0 : for (i = 0; i < bf->bf_map->dm_nsegs; i++, ds++) {
1630 0 : ds->ds_data = bf->bf_map->dm_segs[i].ds_addr;
1631 0 : ds->ds_ctl1 |= SM(AR_TXC1_BUF_LEN,
1632 : bf->bf_map->dm_segs[i].ds_len);
1633 :
1634 0 : if (i != bf->bf_map->dm_nsegs - 1)
1635 0 : ds->ds_ctl1 |= AR_TXC1_MORE;
1636 0 : ds->ds_link = 0;
1637 :
1638 : /* Chain Tx descriptor. */
1639 0 : if (i != 0)
1640 0 : lastds->ds_link = bf->bf_daddr + i * sizeof(*ds);
1641 : lastds = ds;
1642 : }
1643 0 : bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
1644 : BUS_DMASYNC_PREWRITE);
1645 :
1646 0 : if (!SIMPLEQ_EMPTY(&txq->head))
1647 0 : ((struct ar_tx_desc *)txq->lastds)->ds_link = bf->bf_daddr;
1648 : else
1649 0 : AR_WRITE(sc, AR_QTXDP(qid), bf->bf_daddr);
1650 0 : txq->lastds = lastds;
1651 0 : SIMPLEQ_REMOVE_HEAD(&sc->txbufs, bf_list);
1652 0 : SIMPLEQ_INSERT_TAIL(&txq->head, bf, bf_list);
1653 :
1654 0 : ds = bf->bf_descs;
1655 : DPRINTFN(6, ("Tx qid=%d nsegs=%d ctl0=0x%x ctl1=0x%x ctl3=0x%x\n",
1656 : qid, bf->bf_map->dm_nsegs, ds->ds_ctl0, ds->ds_ctl1, ds->ds_ctl3));
1657 :
1658 : /* Kick Tx. */
1659 0 : AR_WRITE(sc, AR_Q_TXE, 1 << qid);
1660 0 : AR_WRITE_BARRIER(sc);
1661 0 : return (0);
1662 0 : }
1663 :
1664 : void
1665 0 : ar5008_set_rf_mode(struct athn_softc *sc, struct ieee80211_channel *c)
1666 : {
1667 : uint32_t reg;
1668 :
1669 0 : reg = IEEE80211_IS_CHAN_2GHZ(c) ?
1670 : AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
1671 0 : if (!AR_SREV_9280_10_OR_LATER(sc)) {
1672 0 : reg |= IEEE80211_IS_CHAN_2GHZ(c) ?
1673 : AR_PHY_MODE_RF2GHZ : AR_PHY_MODE_RF5GHZ;
1674 0 : } else if (IEEE80211_IS_CHAN_5GHZ(c) &&
1675 0 : (sc->flags & ATHN_FLAG_FAST_PLL_CLOCK)) {
1676 : reg |= AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE;
1677 0 : }
1678 0 : AR_WRITE(sc, AR_PHY_MODE, reg);
1679 0 : AR_WRITE_BARRIER(sc);
1680 0 : }
1681 :
1682 : static __inline uint32_t
1683 0 : ar5008_synth_delay(struct athn_softc *sc)
1684 : {
1685 : uint32_t delay;
1686 :
1687 0 : delay = MS(AR_READ(sc, AR_PHY_RX_DELAY), AR_PHY_RX_DELAY_DELAY);
1688 0 : if (sc->sc_ic.ic_curmode == IEEE80211_MODE_11B)
1689 0 : delay = (delay * 4) / 22;
1690 : else
1691 0 : delay = delay / 10; /* in 100ns steps */
1692 0 : return (delay);
1693 : }
1694 :
1695 : int
1696 0 : ar5008_rf_bus_request(struct athn_softc *sc)
1697 : {
1698 : int ntries;
1699 :
1700 : /* Request RF Bus grant. */
1701 0 : AR_WRITE(sc, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
1702 0 : for (ntries = 0; ntries < 10000; ntries++) {
1703 0 : if (AR_READ(sc, AR_PHY_RFBUS_GRANT) & AR_PHY_RFBUS_GRANT_EN)
1704 0 : return (0);
1705 0 : DELAY(10);
1706 : }
1707 : DPRINTF(("could not kill baseband Rx"));
1708 0 : return (ETIMEDOUT);
1709 0 : }
1710 :
1711 : void
1712 0 : ar5008_rf_bus_release(struct athn_softc *sc)
1713 : {
1714 : /* Wait for the synthesizer to settle. */
1715 0 : DELAY(AR_BASE_PHY_ACTIVE_DELAY + ar5008_synth_delay(sc));
1716 :
1717 : /* Release the RF Bus grant. */
1718 0 : AR_WRITE(sc, AR_PHY_RFBUS_REQ, 0);
1719 0 : AR_WRITE_BARRIER(sc);
1720 0 : }
1721 :
1722 : void
1723 0 : ar5008_set_phy(struct athn_softc *sc, struct ieee80211_channel *c,
1724 : struct ieee80211_channel *extc)
1725 : {
1726 : uint32_t phy;
1727 :
1728 0 : if (AR_SREV_9285_10_OR_LATER(sc))
1729 0 : phy = AR_READ(sc, AR_PHY_TURBO) & AR_PHY_FC_ENABLE_DAC_FIFO;
1730 : else
1731 : phy = 0;
1732 0 : phy |= AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 |
1733 : AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
1734 0 : if (extc != NULL) {
1735 0 : phy |= AR_PHY_FC_DYN2040_EN;
1736 0 : if (extc > c) /* XXX */
1737 0 : phy |= AR_PHY_FC_DYN2040_PRI_CH;
1738 : }
1739 0 : AR_WRITE(sc, AR_PHY_TURBO, phy);
1740 :
1741 0 : AR_WRITE(sc, AR_2040_MODE,
1742 : (extc != NULL) ? AR_2040_JOINED_RX_CLEAR : 0);
1743 :
1744 : /* Set global transmit timeout. */
1745 0 : AR_WRITE(sc, AR_GTXTO, SM(AR_GTXTO_TIMEOUT_LIMIT, 25));
1746 : /* Set carrier sense timeout. */
1747 0 : AR_WRITE(sc, AR_CST, SM(AR_CST_TIMEOUT_LIMIT, 15));
1748 0 : AR_WRITE_BARRIER(sc);
1749 0 : }
1750 :
1751 : void
1752 0 : ar5008_set_delta_slope(struct athn_softc *sc, struct ieee80211_channel *c,
1753 : struct ieee80211_channel *extc)
1754 : {
1755 0 : uint32_t coeff, exp, man, reg;
1756 :
1757 : /* Set Delta Slope (exponent and mantissa). */
1758 0 : coeff = (100 << 24) / c->ic_freq;
1759 0 : athn_get_delta_slope(coeff, &exp, &man);
1760 : DPRINTFN(5, ("delta slope coeff exp=%u man=%u\n", exp, man));
1761 :
1762 0 : reg = AR_READ(sc, AR_PHY_TIMING3);
1763 0 : reg = RW(reg, AR_PHY_TIMING3_DSC_EXP, exp);
1764 0 : reg = RW(reg, AR_PHY_TIMING3_DSC_MAN, man);
1765 0 : AR_WRITE(sc, AR_PHY_TIMING3, reg);
1766 :
1767 : /* For Short GI, coeff is 9/10 that of normal coeff. */
1768 0 : coeff = (9 * coeff) / 10;
1769 0 : athn_get_delta_slope(coeff, &exp, &man);
1770 : DPRINTFN(5, ("delta slope coeff exp=%u man=%u\n", exp, man));
1771 :
1772 0 : reg = AR_READ(sc, AR_PHY_HALFGI);
1773 0 : reg = RW(reg, AR_PHY_HALFGI_DSC_EXP, exp);
1774 0 : reg = RW(reg, AR_PHY_HALFGI_DSC_MAN, man);
1775 0 : AR_WRITE(sc, AR_PHY_HALFGI, reg);
1776 0 : AR_WRITE_BARRIER(sc);
1777 0 : }
1778 :
1779 : void
1780 0 : ar5008_enable_antenna_diversity(struct athn_softc *sc)
1781 : {
1782 0 : AR_SETBITS(sc, AR_PHY_CCK_DETECT,
1783 : AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
1784 0 : AR_WRITE_BARRIER(sc);
1785 0 : }
1786 :
1787 : void
1788 0 : ar5008_init_baseband(struct athn_softc *sc)
1789 : {
1790 : uint32_t synth_delay;
1791 :
1792 0 : synth_delay = ar5008_synth_delay(sc);
1793 : /* Activate the PHY (includes baseband activate and synthesizer on). */
1794 0 : AR_WRITE(sc, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
1795 0 : AR_WRITE_BARRIER(sc);
1796 0 : DELAY(AR_BASE_PHY_ACTIVE_DELAY + synth_delay);
1797 0 : }
1798 :
1799 : void
1800 0 : ar5008_disable_phy(struct athn_softc *sc)
1801 : {
1802 0 : AR_WRITE(sc, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1803 0 : AR_WRITE_BARRIER(sc);
1804 0 : }
1805 :
1806 : void
1807 0 : ar5008_init_chains(struct athn_softc *sc)
1808 : {
1809 0 : if (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5)
1810 0 : AR_SETBITS(sc, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
1811 :
1812 : /* Setup chain masks. */
1813 0 : if (sc->mac_ver <= AR_SREV_VERSION_9160 &&
1814 0 : (sc->rxchainmask == 0x3 || sc->rxchainmask == 0x5)) {
1815 0 : AR_WRITE(sc, AR_PHY_RX_CHAINMASK, 0x7);
1816 0 : AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, 0x7);
1817 0 : } else {
1818 0 : AR_WRITE(sc, AR_PHY_RX_CHAINMASK, sc->rxchainmask);
1819 0 : AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, sc->rxchainmask);
1820 : }
1821 0 : AR_WRITE(sc, AR_SELFGEN_MASK, sc->txchainmask);
1822 0 : AR_WRITE_BARRIER(sc);
1823 0 : }
1824 :
1825 : void
1826 0 : ar5008_set_rxchains(struct athn_softc *sc)
1827 : {
1828 0 : if (sc->rxchainmask == 0x3 || sc->rxchainmask == 0x5) {
1829 0 : AR_WRITE(sc, AR_PHY_RX_CHAINMASK, sc->rxchainmask);
1830 0 : AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, sc->rxchainmask);
1831 0 : AR_WRITE_BARRIER(sc);
1832 0 : }
1833 0 : }
1834 :
1835 : void
1836 0 : ar5008_read_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
1837 : {
1838 : /* Sign-extends 9-bit value (assumes upper bits are zeroes). */
1839 : #define SIGN_EXT(v) (((v) ^ 0x100) - 0x100)
1840 : uint32_t reg;
1841 : int i;
1842 :
1843 0 : for (i = 0; i < sc->nrxchains; i++) {
1844 0 : reg = AR_READ(sc, AR_PHY_CCA(i));
1845 0 : if (AR_SREV_9280_10_OR_LATER(sc))
1846 0 : nf[i] = MS(reg, AR9280_PHY_MINCCA_PWR);
1847 : else
1848 0 : nf[i] = MS(reg, AR_PHY_MINCCA_PWR);
1849 0 : nf[i] = SIGN_EXT(nf[i]);
1850 :
1851 0 : reg = AR_READ(sc, AR_PHY_EXT_CCA(i));
1852 0 : if (AR_SREV_9280_10_OR_LATER(sc))
1853 0 : nf_ext[i] = MS(reg, AR9280_PHY_EXT_MINCCA_PWR);
1854 : else
1855 0 : nf_ext[i] = MS(reg, AR_PHY_EXT_MINCCA_PWR);
1856 0 : nf_ext[i] = SIGN_EXT(nf_ext[i]);
1857 : }
1858 : #undef SIGN_EXT
1859 0 : }
1860 :
1861 : void
1862 0 : ar5008_write_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
1863 : {
1864 : uint32_t reg;
1865 : int i;
1866 :
1867 0 : for (i = 0; i < sc->nrxchains; i++) {
1868 0 : reg = AR_READ(sc, AR_PHY_CCA(i));
1869 0 : reg = RW(reg, AR_PHY_MAXCCA_PWR, nf[i]);
1870 0 : AR_WRITE(sc, AR_PHY_CCA(i), reg);
1871 :
1872 0 : reg = AR_READ(sc, AR_PHY_EXT_CCA(i));
1873 0 : reg = RW(reg, AR_PHY_EXT_MAXCCA_PWR, nf_ext[i]);
1874 0 : AR_WRITE(sc, AR_PHY_EXT_CCA(i), reg);
1875 : }
1876 0 : AR_WRITE_BARRIER(sc);
1877 0 : }
1878 :
1879 : void
1880 0 : ar5008_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c)
1881 : {
1882 0 : int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS];
1883 : int i;
1884 :
1885 0 : if (AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
1886 : /* Noisefloor calibration not finished. */
1887 0 : return;
1888 : }
1889 : /* Noisefloor calibration is finished. */
1890 0 : ar5008_read_noisefloor(sc, nf, nf_ext);
1891 :
1892 : /* Update noisefloor history. */
1893 0 : for (i = 0; i < sc->nrxchains; i++) {
1894 0 : sc->nf_hist[sc->nf_hist_cur].nf[i] = nf[i];
1895 0 : sc->nf_hist[sc->nf_hist_cur].nf_ext[i] = nf_ext[i];
1896 : }
1897 0 : if (++sc->nf_hist_cur >= ATHN_NF_CAL_HIST_MAX)
1898 0 : sc->nf_hist_cur = 0;
1899 0 : }
1900 :
1901 : void
1902 0 : ar5008_bb_load_noisefloor(struct athn_softc *sc)
1903 : {
1904 0 : int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS];
1905 : int i, ntries;
1906 :
1907 : /* Write filtered noisefloor values. */
1908 0 : for (i = 0; i < sc->nrxchains; i++) {
1909 0 : nf[i] = sc->nf_priv[i] * 2;
1910 0 : nf_ext[i] = sc->nf_ext_priv[i] * 2;
1911 : }
1912 0 : ar5008_write_noisefloor(sc, nf, nf_ext);
1913 :
1914 : /* Load filtered noisefloor values into baseband. */
1915 0 : AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
1916 0 : AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1917 0 : AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1918 : /* Wait for load to complete. */
1919 0 : for (ntries = 0; ntries < 1000; ntries++) {
1920 0 : if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
1921 : break;
1922 0 : DELAY(50);
1923 : }
1924 0 : if (ntries == 1000) {
1925 : DPRINTF(("failed to load noisefloor values\n"));
1926 0 : return;
1927 : }
1928 :
1929 : /* Restore noisefloor values to initial (max) values. */
1930 0 : for (i = 0; i < AR_MAX_CHAINS; i++)
1931 0 : nf[i] = nf_ext[i] = AR_DEFAULT_NOISE_FLOOR;
1932 0 : ar5008_write_noisefloor(sc, nf, nf_ext);
1933 0 : }
1934 :
1935 : void
1936 0 : ar5008_noisefloor_calib(struct athn_softc *sc)
1937 : {
1938 0 : AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
1939 0 : AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1940 0 : AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1941 0 : AR_WRITE_BARRIER(sc);
1942 0 : }
1943 :
1944 : void
1945 0 : ar5008_do_noisefloor_calib(struct athn_softc *sc)
1946 : {
1947 0 : AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1948 0 : AR_WRITE_BARRIER(sc);
1949 0 : }
1950 :
1951 : void
1952 0 : ar5008_do_calib(struct athn_softc *sc)
1953 : {
1954 : uint32_t mode, reg;
1955 : int log;
1956 :
1957 0 : reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
1958 0 : log = AR_SREV_9280_10_OR_LATER(sc) ? 10 : 2;
1959 0 : reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, log);
1960 0 : AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg);
1961 :
1962 0 : if (sc->cur_calib_mask & ATHN_CAL_ADC_GAIN)
1963 0 : mode = AR_PHY_CALMODE_ADC_GAIN;
1964 0 : else if (sc->cur_calib_mask & ATHN_CAL_ADC_DC)
1965 0 : mode = AR_PHY_CALMODE_ADC_DC_PER;
1966 : else /* ATHN_CAL_IQ */
1967 : mode = AR_PHY_CALMODE_IQ;
1968 0 : AR_WRITE(sc, AR_PHY_CALMODE, mode);
1969 :
1970 : DPRINTF(("starting calibration mode=0x%x\n", mode));
1971 0 : AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0, AR_PHY_TIMING_CTRL4_DO_CAL);
1972 0 : AR_WRITE_BARRIER(sc);
1973 0 : }
1974 :
1975 : void
1976 0 : ar5008_next_calib(struct athn_softc *sc)
1977 : {
1978 : /* Check if we have any calibration in progress. */
1979 0 : if (sc->cur_calib_mask != 0) {
1980 0 : if (!(AR_READ(sc, AR_PHY_TIMING_CTRL4_0) &
1981 : AR_PHY_TIMING_CTRL4_DO_CAL)) {
1982 : /* Calibration completed for current sample. */
1983 0 : if (sc->cur_calib_mask & ATHN_CAL_ADC_GAIN)
1984 0 : ar5008_calib_adc_gain(sc);
1985 0 : else if (sc->cur_calib_mask & ATHN_CAL_ADC_DC)
1986 0 : ar5008_calib_adc_dc_off(sc);
1987 : else /* ATHN_CAL_IQ */
1988 0 : ar5008_calib_iq(sc);
1989 : }
1990 : }
1991 0 : }
1992 :
1993 : void
1994 0 : ar5008_calib_iq(struct athn_softc *sc)
1995 : {
1996 : struct athn_iq_cal *cal;
1997 : uint32_t reg, i_coff_denom, q_coff_denom;
1998 : int32_t i_coff, q_coff;
1999 : int i, iq_corr_neg;
2000 :
2001 0 : for (i = 0; i < AR_MAX_CHAINS; i++) {
2002 0 : cal = &sc->calib.iq[i];
2003 :
2004 : /* Accumulate IQ calibration measures (clear on read). */
2005 0 : cal->pwr_meas_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
2006 0 : cal->pwr_meas_q += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
2007 0 : cal->iq_corr_meas +=
2008 0 : (int32_t)AR_READ(sc, AR_PHY_CAL_MEAS_2(i));
2009 : }
2010 0 : if (!AR_SREV_9280_10_OR_LATER(sc) &&
2011 0 : ++sc->calib.nsamples < AR_CAL_SAMPLES) {
2012 : /* Not enough samples accumulated, continue. */
2013 0 : ar5008_do_calib(sc);
2014 0 : return;
2015 : }
2016 :
2017 0 : for (i = 0; i < sc->nrxchains; i++) {
2018 0 : cal = &sc->calib.iq[i];
2019 :
2020 0 : if (cal->pwr_meas_q == 0)
2021 : continue;
2022 :
2023 0 : if ((iq_corr_neg = cal->iq_corr_meas < 0))
2024 0 : cal->iq_corr_meas = -cal->iq_corr_meas;
2025 :
2026 : i_coff_denom =
2027 0 : (cal->pwr_meas_i / 2 + cal->pwr_meas_q / 2) / 128;
2028 0 : q_coff_denom = cal->pwr_meas_q / 64;
2029 :
2030 0 : if (i_coff_denom == 0 || q_coff_denom == 0)
2031 : continue; /* Prevents division by zero. */
2032 :
2033 0 : i_coff = cal->iq_corr_meas / i_coff_denom;
2034 0 : q_coff = (cal->pwr_meas_i / q_coff_denom) - 64;
2035 :
2036 : /* Negate i_coff if iq_corr_meas is positive. */
2037 0 : if (!iq_corr_neg)
2038 0 : i_coff = 0x40 - (i_coff & 0x3f);
2039 0 : if (q_coff > 15)
2040 0 : q_coff = 15;
2041 0 : else if (q_coff <= -16)
2042 0 : q_coff = -16; /* XXX Linux has a bug here? */
2043 :
2044 : DPRINTFN(2, ("IQ calibration for chain %d\n", i));
2045 0 : reg = AR_READ(sc, AR_PHY_TIMING_CTRL4(i));
2046 0 : reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, i_coff);
2047 0 : reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, q_coff);
2048 0 : AR_WRITE(sc, AR_PHY_TIMING_CTRL4(i), reg);
2049 0 : }
2050 :
2051 : /* Apply new settings. */
2052 0 : AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
2053 : AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
2054 0 : AR_WRITE_BARRIER(sc);
2055 :
2056 : /* IQ calibration done. */
2057 0 : sc->cur_calib_mask &= ~ATHN_CAL_IQ;
2058 0 : memset(&sc->calib, 0, sizeof(sc->calib));
2059 0 : }
2060 :
2061 : void
2062 0 : ar5008_calib_adc_gain(struct athn_softc *sc)
2063 : {
2064 : struct athn_adc_cal *cal;
2065 : uint32_t reg, gain_mismatch_i, gain_mismatch_q;
2066 : int i;
2067 :
2068 0 : for (i = 0; i < AR_MAX_CHAINS; i++) {
2069 0 : cal = &sc->calib.adc_gain[i];
2070 :
2071 : /* Accumulate ADC gain measures (clear on read). */
2072 0 : cal->pwr_meas_odd_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
2073 0 : cal->pwr_meas_even_i += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
2074 0 : cal->pwr_meas_odd_q += AR_READ(sc, AR_PHY_CAL_MEAS_2(i));
2075 0 : cal->pwr_meas_even_q += AR_READ(sc, AR_PHY_CAL_MEAS_3(i));
2076 : }
2077 0 : if (!AR_SREV_9280_10_OR_LATER(sc) &&
2078 0 : ++sc->calib.nsamples < AR_CAL_SAMPLES) {
2079 : /* Not enough samples accumulated, continue. */
2080 0 : ar5008_do_calib(sc);
2081 0 : return;
2082 : }
2083 :
2084 0 : for (i = 0; i < sc->nrxchains; i++) {
2085 0 : cal = &sc->calib.adc_gain[i];
2086 :
2087 0 : if (cal->pwr_meas_odd_i == 0 || cal->pwr_meas_even_q == 0)
2088 : continue; /* Prevents division by zero. */
2089 :
2090 : gain_mismatch_i =
2091 0 : (cal->pwr_meas_even_i * 32) / cal->pwr_meas_odd_i;
2092 : gain_mismatch_q =
2093 0 : (cal->pwr_meas_odd_q * 32) / cal->pwr_meas_even_q;
2094 :
2095 : DPRINTFN(2, ("ADC gain calibration for chain %d\n", i));
2096 0 : reg = AR_READ(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
2097 0 : reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_IGAIN, gain_mismatch_i);
2098 0 : reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_QGAIN, gain_mismatch_q);
2099 0 : AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg);
2100 0 : }
2101 :
2102 : /* Apply new settings. */
2103 0 : AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
2104 : AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
2105 0 : AR_WRITE_BARRIER(sc);
2106 :
2107 : /* ADC gain calibration done. */
2108 0 : sc->cur_calib_mask &= ~ATHN_CAL_ADC_GAIN;
2109 0 : memset(&sc->calib, 0, sizeof(sc->calib));
2110 0 : }
2111 :
2112 : void
2113 0 : ar5008_calib_adc_dc_off(struct athn_softc *sc)
2114 : {
2115 : struct athn_adc_cal *cal;
2116 : int32_t dc_offset_mismatch_i, dc_offset_mismatch_q;
2117 : uint32_t reg;
2118 : int count, i;
2119 :
2120 0 : for (i = 0; i < AR_MAX_CHAINS; i++) {
2121 0 : cal = &sc->calib.adc_dc_offset[i];
2122 :
2123 : /* Accumulate ADC DC offset measures (clear on read). */
2124 0 : cal->pwr_meas_odd_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
2125 0 : cal->pwr_meas_even_i += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
2126 0 : cal->pwr_meas_odd_q += AR_READ(sc, AR_PHY_CAL_MEAS_2(i));
2127 0 : cal->pwr_meas_even_q += AR_READ(sc, AR_PHY_CAL_MEAS_3(i));
2128 : }
2129 0 : if (!AR_SREV_9280_10_OR_LATER(sc) &&
2130 0 : ++sc->calib.nsamples < AR_CAL_SAMPLES) {
2131 : /* Not enough samples accumulated, continue. */
2132 0 : ar5008_do_calib(sc);
2133 0 : return;
2134 : }
2135 :
2136 0 : if (AR_SREV_9280_10_OR_LATER(sc))
2137 0 : count = (1 << (10 + 5));
2138 : else
2139 : count = (1 << ( 2 + 5)) * AR_CAL_SAMPLES;
2140 0 : for (i = 0; i < sc->nrxchains; i++) {
2141 0 : cal = &sc->calib.adc_dc_offset[i];
2142 :
2143 : dc_offset_mismatch_i =
2144 0 : (cal->pwr_meas_even_i - cal->pwr_meas_odd_i * 2) / count;
2145 : dc_offset_mismatch_q =
2146 0 : (cal->pwr_meas_odd_q - cal->pwr_meas_even_q * 2) / count;
2147 :
2148 : DPRINTFN(2, ("ADC DC offset calibration for chain %d\n", i));
2149 0 : reg = AR_READ(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
2150 0 : reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_QDC,
2151 : dc_offset_mismatch_q);
2152 0 : reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_IDC,
2153 : dc_offset_mismatch_i);
2154 0 : AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg);
2155 : }
2156 :
2157 : /* Apply new settings. */
2158 0 : AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
2159 : AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
2160 0 : AR_WRITE_BARRIER(sc);
2161 :
2162 : /* ADC DC offset calibration done. */
2163 0 : sc->cur_calib_mask &= ~ATHN_CAL_ADC_DC;
2164 0 : memset(&sc->calib, 0, sizeof(sc->calib));
2165 0 : }
2166 :
2167 : void
2168 0 : ar5008_write_txpower(struct athn_softc *sc, int16_t power[ATHN_POWER_COUNT])
2169 : {
2170 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE1,
2171 : (power[ATHN_POWER_OFDM18 ] & 0x3f) << 24 |
2172 : (power[ATHN_POWER_OFDM12 ] & 0x3f) << 16 |
2173 : (power[ATHN_POWER_OFDM9 ] & 0x3f) << 8 |
2174 : (power[ATHN_POWER_OFDM6 ] & 0x3f));
2175 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE2,
2176 : (power[ATHN_POWER_OFDM54 ] & 0x3f) << 24 |
2177 : (power[ATHN_POWER_OFDM48 ] & 0x3f) << 16 |
2178 : (power[ATHN_POWER_OFDM36 ] & 0x3f) << 8 |
2179 : (power[ATHN_POWER_OFDM24 ] & 0x3f));
2180 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE3,
2181 : (power[ATHN_POWER_CCK2_SP ] & 0x3f) << 24 |
2182 : (power[ATHN_POWER_CCK2_LP ] & 0x3f) << 16 |
2183 : (power[ATHN_POWER_XR ] & 0x3f) << 8 |
2184 : (power[ATHN_POWER_CCK1_LP ] & 0x3f));
2185 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE4,
2186 : (power[ATHN_POWER_CCK11_SP] & 0x3f) << 24 |
2187 : (power[ATHN_POWER_CCK11_LP] & 0x3f) << 16 |
2188 : (power[ATHN_POWER_CCK55_SP] & 0x3f) << 8 |
2189 : (power[ATHN_POWER_CCK55_LP] & 0x3f));
2190 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE5,
2191 : (power[ATHN_POWER_HT20(3) ] & 0x3f) << 24 |
2192 : (power[ATHN_POWER_HT20(2) ] & 0x3f) << 16 |
2193 : (power[ATHN_POWER_HT20(1) ] & 0x3f) << 8 |
2194 : (power[ATHN_POWER_HT20(0) ] & 0x3f));
2195 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE6,
2196 : (power[ATHN_POWER_HT20(7) ] & 0x3f) << 24 |
2197 : (power[ATHN_POWER_HT20(6) ] & 0x3f) << 16 |
2198 : (power[ATHN_POWER_HT20(5) ] & 0x3f) << 8 |
2199 : (power[ATHN_POWER_HT20(4) ] & 0x3f));
2200 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE7,
2201 : (power[ATHN_POWER_HT40(3) ] & 0x3f) << 24 |
2202 : (power[ATHN_POWER_HT40(2) ] & 0x3f) << 16 |
2203 : (power[ATHN_POWER_HT40(1) ] & 0x3f) << 8 |
2204 : (power[ATHN_POWER_HT40(0) ] & 0x3f));
2205 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE8,
2206 : (power[ATHN_POWER_HT40(7) ] & 0x3f) << 24 |
2207 : (power[ATHN_POWER_HT40(6) ] & 0x3f) << 16 |
2208 : (power[ATHN_POWER_HT40(5) ] & 0x3f) << 8 |
2209 : (power[ATHN_POWER_HT40(4) ] & 0x3f));
2210 0 : AR_WRITE(sc, AR_PHY_POWER_TX_RATE9,
2211 : (power[ATHN_POWER_OFDM_EXT] & 0x3f) << 24 |
2212 : (power[ATHN_POWER_CCK_EXT ] & 0x3f) << 16 |
2213 : (power[ATHN_POWER_OFDM_DUP] & 0x3f) << 8 |
2214 : (power[ATHN_POWER_CCK_DUP ] & 0x3f));
2215 0 : AR_WRITE_BARRIER(sc);
2216 0 : }
2217 :
2218 : void
2219 0 : ar5008_set_viterbi_mask(struct athn_softc *sc, int bin)
2220 : {
2221 0 : uint32_t mask[4], reg;
2222 0 : uint8_t m[62], p[62]; /* XXX use bit arrays? */
2223 : int i, bit, cur;
2224 :
2225 : /* Compute pilot mask. */
2226 : cur = -6000;
2227 0 : for (i = 0; i < 4; i++) {
2228 0 : mask[i] = 0;
2229 0 : for (bit = 0; bit < 30; bit++) {
2230 0 : if (abs(cur - bin) < 100)
2231 0 : mask[i] |= 1 << bit;
2232 0 : cur += 100;
2233 : }
2234 0 : if (cur == 0) /* Skip entry "0". */
2235 0 : cur = 100;
2236 : }
2237 : /* Write entries from -6000 to -3100. */
2238 0 : AR_WRITE(sc, AR_PHY_TIMING7, mask[0]);
2239 0 : AR_WRITE(sc, AR_PHY_TIMING9, mask[0]);
2240 : /* Write entries from -3000 to -100. */
2241 0 : AR_WRITE(sc, AR_PHY_TIMING8, mask[1]);
2242 0 : AR_WRITE(sc, AR_PHY_TIMING10, mask[1]);
2243 : /* Write entries from 100 to 3000. */
2244 0 : AR_WRITE(sc, AR_PHY_PILOT_MASK_01_30, mask[2]);
2245 0 : AR_WRITE(sc, AR_PHY_CHANNEL_MASK_01_30, mask[2]);
2246 : /* Write entries from 3100 to 6000. */
2247 0 : AR_WRITE(sc, AR_PHY_PILOT_MASK_31_60, mask[3]);
2248 0 : AR_WRITE(sc, AR_PHY_CHANNEL_MASK_31_60, mask[3]);
2249 :
2250 : /* Compute viterbi mask. */
2251 0 : for (cur = 6100; cur >= 0; cur -= 100)
2252 0 : p[+cur / 100] = abs(cur - bin) < 75;
2253 0 : for (cur = -100; cur >= -6100; cur -= 100)
2254 0 : m[-cur / 100] = abs(cur - bin) < 75;
2255 :
2256 : /* Write viterbi mask (XXX needs to be reworked). */
2257 : reg =
2258 0 : m[46] << 30 | m[47] << 28 | m[48] << 26 | m[49] << 24 |
2259 0 : m[50] << 22 | m[51] << 20 | m[52] << 18 | m[53] << 16 |
2260 0 : m[54] << 14 | m[55] << 12 | m[56] << 10 | m[57] << 8 |
2261 0 : m[58] << 6 | m[59] << 4 | m[60] << 2 | m[61] << 0;
2262 0 : AR_WRITE(sc, AR_PHY_BIN_MASK_1, reg);
2263 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_M_46_61, reg);
2264 :
2265 : /* XXX m[48] should be m[38] ? */
2266 0 : reg = m[31] << 28 | m[32] << 26 | m[33] << 24 |
2267 0 : m[34] << 22 | m[35] << 20 | m[36] << 18 | m[37] << 16 |
2268 0 : m[48] << 14 | m[39] << 12 | m[40] << 10 | m[41] << 8 |
2269 0 : m[42] << 6 | m[43] << 4 | m[44] << 2 | m[45] << 0;
2270 0 : AR_WRITE(sc, AR_PHY_BIN_MASK_2, reg);
2271 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_M_31_45, reg);
2272 :
2273 : /* XXX This one is weird too. */
2274 : reg =
2275 0 : m[16] << 30 | m[16] << 28 | m[18] << 26 | m[18] << 24 |
2276 0 : m[20] << 22 | m[20] << 20 | m[22] << 18 | m[22] << 16 |
2277 0 : m[24] << 14 | m[24] << 12 | m[25] << 10 | m[26] << 8 |
2278 0 : m[27] << 6 | m[28] << 4 | m[29] << 2 | m[30] << 0;
2279 0 : AR_WRITE(sc, AR_PHY_BIN_MASK_3, reg);
2280 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_M_16_30, reg);
2281 :
2282 : reg =
2283 0 : m[ 0] << 30 | m[ 1] << 28 | m[ 2] << 26 | m[ 3] << 24 |
2284 0 : m[ 4] << 22 | m[ 5] << 20 | m[ 6] << 18 | m[ 7] << 16 |
2285 0 : m[ 8] << 14 | m[ 9] << 12 | m[10] << 10 | m[11] << 8 |
2286 0 : m[12] << 6 | m[13] << 4 | m[14] << 2 | m[15] << 0;
2287 0 : AR_WRITE(sc, AR_PHY_MASK_CTL, reg);
2288 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_M_00_15, reg);
2289 :
2290 0 : reg = p[15] << 28 | p[14] << 26 | p[13] << 24 |
2291 0 : p[12] << 22 | p[11] << 20 | p[10] << 18 | p[ 9] << 16 |
2292 0 : p[ 8] << 14 | p[ 7] << 12 | p[ 6] << 10 | p[ 5] << 8 |
2293 0 : p[ 4] << 6 | p[ 3] << 4 | p[ 2] << 2 | p[ 1] << 0;
2294 0 : AR_WRITE(sc, AR_PHY_BIN_MASK2_1, reg);
2295 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_P_15_01, reg);
2296 :
2297 0 : reg = p[30] << 28 | p[29] << 26 | p[28] << 24 |
2298 0 : p[27] << 22 | p[26] << 20 | p[25] << 18 | p[24] << 16 |
2299 0 : p[23] << 14 | p[22] << 12 | p[21] << 10 | p[20] << 8 |
2300 0 : p[19] << 6 | p[18] << 4 | p[17] << 2 | p[16] << 0;
2301 0 : AR_WRITE(sc, AR_PHY_BIN_MASK2_2, reg);
2302 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_P_30_16, reg);
2303 :
2304 0 : reg = p[45] << 28 | p[44] << 26 | p[43] << 24 |
2305 0 : p[42] << 22 | p[41] << 20 | p[40] << 18 | p[39] << 16 |
2306 0 : p[38] << 14 | p[37] << 12 | p[36] << 10 | p[35] << 8 |
2307 0 : p[34] << 6 | p[33] << 4 | p[32] << 2 | p[31] << 0;
2308 0 : AR_WRITE(sc, AR_PHY_BIN_MASK2_3, reg);
2309 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_P_45_31, reg);
2310 :
2311 : reg =
2312 0 : p[61] << 30 | p[60] << 28 | p[59] << 26 | p[58] << 24 |
2313 0 : p[57] << 22 | p[56] << 20 | p[55] << 18 | p[54] << 16 |
2314 0 : p[53] << 14 | p[52] << 12 | p[51] << 10 | p[50] << 8 |
2315 0 : p[49] << 6 | p[48] << 4 | p[47] << 2 | p[46] << 0;
2316 0 : AR_WRITE(sc, AR_PHY_BIN_MASK2_4, reg);
2317 0 : AR_WRITE(sc, AR_PHY_VIT_MASK2_P_61_46, reg);
2318 0 : AR_WRITE_BARRIER(sc);
2319 0 : }
2320 :
2321 : void
2322 0 : ar5008_hw_init(struct athn_softc *sc, struct ieee80211_channel *c,
2323 : struct ieee80211_channel *extc)
2324 : {
2325 0 : struct athn_ops *ops = &sc->ops;
2326 0 : const struct athn_ini *ini = sc->ini;
2327 : const uint32_t *pvals;
2328 : uint32_t reg;
2329 : int i;
2330 :
2331 0 : AR_WRITE(sc, AR_PHY(0), 0x00000007);
2332 0 : AR_WRITE(sc, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
2333 :
2334 0 : if (!AR_SINGLE_CHIP(sc))
2335 0 : ar5416_reset_addac(sc, c);
2336 :
2337 0 : AR_WRITE(sc, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
2338 :
2339 : /* First initialization step (depends on channel band/bandwidth). */
2340 0 : if (extc != NULL) {
2341 0 : if (IEEE80211_IS_CHAN_2GHZ(c))
2342 0 : pvals = ini->vals_2g40;
2343 : else
2344 0 : pvals = ini->vals_5g40;
2345 : } else {
2346 0 : if (IEEE80211_IS_CHAN_2GHZ(c))
2347 0 : pvals = ini->vals_2g20;
2348 : else
2349 0 : pvals = ini->vals_5g20;
2350 : }
2351 : DPRINTFN(4, ("writing modal init vals\n"));
2352 0 : for (i = 0; i < ini->nregs; i++) {
2353 0 : uint32_t val = pvals[i];
2354 :
2355 : /* Fix AR_AN_TOP2 initialization value if required. */
2356 0 : if (ini->regs[i] == AR_AN_TOP2 &&
2357 0 : (sc->flags & ATHN_FLAG_AN_TOP2_FIXUP))
2358 0 : val &= ~AR_AN_TOP2_PWDCLKIND;
2359 0 : AR_WRITE(sc, ini->regs[i], val);
2360 0 : if (AR_IS_ANALOG_REG(ini->regs[i])) {
2361 0 : AR_WRITE_BARRIER(sc);
2362 0 : DELAY(100);
2363 0 : }
2364 0 : if ((i & 0x1f) == 0)
2365 0 : DELAY(1);
2366 : }
2367 0 : AR_WRITE_BARRIER(sc);
2368 :
2369 0 : if (sc->rx_gain != NULL)
2370 0 : ar9280_reset_rx_gain(sc, c);
2371 0 : if (sc->tx_gain != NULL)
2372 0 : ar9280_reset_tx_gain(sc, c);
2373 :
2374 0 : if (AR_SREV_9271_10(sc)) {
2375 0 : AR_WRITE(sc, AR_PHY(68), 0x30002311);
2376 0 : AR_WRITE(sc, AR_PHY_RF_CTL3, 0x0a020001);
2377 0 : }
2378 0 : AR_WRITE_BARRIER(sc);
2379 :
2380 : /* Second initialization step (common to all channels). */
2381 : DPRINTFN(4, ("writing common init vals\n"));
2382 0 : for (i = 0; i < ini->ncmregs; i++) {
2383 0 : AR_WRITE(sc, ini->cmregs[i], ini->cmvals[i]);
2384 0 : if (AR_IS_ANALOG_REG(ini->cmregs[i])) {
2385 0 : AR_WRITE_BARRIER(sc);
2386 0 : DELAY(100);
2387 0 : }
2388 0 : if ((i & 0x1f) == 0)
2389 0 : DELAY(1);
2390 : }
2391 0 : AR_WRITE_BARRIER(sc);
2392 :
2393 0 : if (!AR_SINGLE_CHIP(sc))
2394 0 : ar5416_reset_bb_gain(sc, c);
2395 :
2396 0 : if (IEEE80211_IS_CHAN_5GHZ(c) &&
2397 0 : (sc->flags & ATHN_FLAG_FAST_PLL_CLOCK)) {
2398 : /* Update modal values for fast PLL clock. */
2399 0 : if (extc != NULL)
2400 0 : pvals = ini->fastvals_5g40;
2401 : else
2402 0 : pvals = ini->fastvals_5g20;
2403 : DPRINTFN(4, ("writing fast pll clock init vals\n"));
2404 0 : for (i = 0; i < ini->nfastregs; i++) {
2405 0 : AR_WRITE(sc, ini->fastregs[i], pvals[i]);
2406 0 : if (AR_IS_ANALOG_REG(ini->fastregs[i])) {
2407 0 : AR_WRITE_BARRIER(sc);
2408 0 : DELAY(100);
2409 0 : }
2410 0 : if ((i & 0x1f) == 0)
2411 0 : DELAY(1);
2412 : }
2413 : }
2414 :
2415 : /*
2416 : * Set the RX_ABORT and RX_DIS bits to prevent frames with corrupted
2417 : * descriptor status.
2418 : */
2419 0 : AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
2420 :
2421 : /* Hardware workarounds for occasional Rx data corruption. */
2422 0 : if (AR_SREV_9280_10_OR_LATER(sc)) {
2423 0 : reg = AR_READ(sc, AR_PCU_MISC_MODE2);
2424 0 : if (!AR_SREV_9271(sc))
2425 0 : reg &= ~AR_PCU_MISC_MODE2_HWWAR1;
2426 0 : if (AR_SREV_9287_10_OR_LATER(sc))
2427 0 : reg &= ~AR_PCU_MISC_MODE2_HWWAR2;
2428 0 : AR_WRITE(sc, AR_PCU_MISC_MODE2, reg);
2429 :
2430 0 : } else if (AR_SREV_5416_20_OR_LATER(sc)) {
2431 : /* Disable baseband clock gating. */
2432 0 : AR_WRITE(sc, AR_PHY(651), 0x11);
2433 :
2434 0 : if (AR_SREV_9160(sc)) {
2435 : /* Disable RIFS search to fix baseband hang. */
2436 0 : AR_CLRBITS(sc, AR_PHY_HEAVY_CLIP_FACTOR_RIFS,
2437 : AR_PHY_RIFS_INIT_DELAY_M);
2438 0 : }
2439 : }
2440 0 : AR_WRITE_BARRIER(sc);
2441 :
2442 0 : ar5008_set_phy(sc, c, extc);
2443 0 : ar5008_init_chains(sc);
2444 :
2445 0 : if (sc->flags & ATHN_FLAG_OLPC) {
2446 : extern int ticks;
2447 0 : sc->olpc_ticks = ticks;
2448 0 : ops->olpc_init(sc);
2449 0 : }
2450 :
2451 0 : ops->set_txpower(sc, c, extc);
2452 :
2453 0 : if (!AR_SINGLE_CHIP(sc))
2454 0 : ar5416_rf_reset(sc, c);
2455 0 : }
2456 :
2457 : uint8_t
2458 0 : ar5008_get_vpd(uint8_t pwr, const uint8_t *pwrPdg, const uint8_t *vpdPdg,
2459 : int nicepts)
2460 : {
2461 : uint8_t vpd;
2462 : int i, lo, hi;
2463 :
2464 0 : for (i = 0; i < nicepts; i++)
2465 0 : if (pwrPdg[i] > pwr)
2466 : break;
2467 : hi = i;
2468 0 : lo = hi - 1;
2469 0 : if (lo == -1)
2470 0 : lo = hi;
2471 0 : else if (hi == nicepts)
2472 0 : hi = lo;
2473 :
2474 0 : vpd = athn_interpolate(pwr, pwrPdg[lo], vpdPdg[lo],
2475 0 : pwrPdg[hi], vpdPdg[hi]);
2476 0 : return (vpd);
2477 : }
2478 :
2479 : void
2480 0 : ar5008_get_pdadcs(struct athn_softc *sc, uint8_t fbin,
2481 : struct athn_pier *lopier, struct athn_pier *hipier, int nxpdgains,
2482 : int nicepts, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs)
2483 : {
2484 : #define DB(x) ((x) / 2) /* Convert half dB to dB. */
2485 0 : uint8_t minpwr[AR_PD_GAINS_IN_MASK], maxpwr[AR_PD_GAINS_IN_MASK];
2486 0 : uint8_t vpd[AR_MAX_PWR_RANGE_IN_HALF_DB], pwr;
2487 : uint8_t lovpd, hivpd, boundary;
2488 : int16_t ss, delta, vpdstep, val;
2489 : int i, j, npdadcs, nvpds, maxidx, tgtidx;
2490 :
2491 : /* Compute min and max power in half dB for each pdGain. */
2492 0 : for (i = 0; i < nxpdgains; i++) {
2493 0 : minpwr[i] = MAX(lopier->pwr[i][0], hipier->pwr[i][0]);
2494 0 : maxpwr[i] = MIN(lopier->pwr[i][nicepts - 1],
2495 : hipier->pwr[i][nicepts - 1]);
2496 : }
2497 :
2498 : /* Fill phase domain analog-to-digital converter (PDADC) table. */
2499 : npdadcs = 0;
2500 0 : for (i = 0; i < nxpdgains; i++) {
2501 0 : if (i != nxpdgains - 1)
2502 0 : boundaries[i] = DB(maxpwr[i] + minpwr[i + 1]) / 2;
2503 : else
2504 0 : boundaries[i] = DB(maxpwr[i]);
2505 0 : if (boundaries[i] > AR_MAX_RATE_POWER)
2506 0 : boundaries[i] = AR_MAX_RATE_POWER;
2507 :
2508 0 : if (i == 0 && !AR_SREV_5416_20_OR_LATER(sc)) {
2509 : /* Fix the gain delta (AR5416 1.0 only). */
2510 0 : delta = boundaries[0] - 23;
2511 0 : boundaries[0] = 23;
2512 0 : } else
2513 : delta = 0;
2514 :
2515 : /* Find starting index for this pdGain. */
2516 0 : if (i != 0) {
2517 0 : ss = boundaries[i - 1] - DB(minpwr[i]) -
2518 0 : overlap + 1 + delta;
2519 0 : } else if (AR_SREV_9280_10_OR_LATER(sc)) {
2520 0 : ss = -DB(minpwr[i]);
2521 0 : } else
2522 : ss = 0;
2523 :
2524 : /* Compute Vpd table for this pdGain. */
2525 0 : nvpds = DB(maxpwr[i] - minpwr[i]) + 1;
2526 0 : memset(vpd, 0, sizeof(vpd));
2527 0 : pwr = minpwr[i];
2528 0 : for (j = 0; j < nvpds; j++) {
2529 : /* Get lower and higher Vpd. */
2530 0 : lovpd = ar5008_get_vpd(pwr, lopier->pwr[i],
2531 0 : lopier->vpd[i], nicepts);
2532 0 : hivpd = ar5008_get_vpd(pwr, hipier->pwr[i],
2533 0 : hipier->vpd[i], nicepts);
2534 :
2535 : /* Interpolate the final Vpd. */
2536 0 : vpd[j] = athn_interpolate(fbin,
2537 0 : lopier->fbin, lovpd, hipier->fbin, hivpd);
2538 :
2539 0 : pwr += 2; /* In half dB. */
2540 : }
2541 :
2542 : /* Extrapolate data for ss < 0. */
2543 0 : if (vpd[1] > vpd[0])
2544 0 : vpdstep = vpd[1] - vpd[0];
2545 : else
2546 : vpdstep = 1;
2547 0 : while (ss < 0 && npdadcs < AR_NUM_PDADC_VALUES - 1) {
2548 0 : val = vpd[0] + ss * vpdstep;
2549 0 : pdadcs[npdadcs++] = MAX(val, 0);
2550 0 : ss++;
2551 : }
2552 :
2553 0 : tgtidx = boundaries[i] + overlap - DB(minpwr[i]);
2554 0 : maxidx = MIN(tgtidx, nvpds);
2555 0 : while (ss < maxidx && npdadcs < AR_NUM_PDADC_VALUES - 1)
2556 0 : pdadcs[npdadcs++] = vpd[ss++];
2557 :
2558 0 : if (tgtidx < maxidx)
2559 : continue;
2560 :
2561 : /* Extrapolate data for maxidx <= ss <= tgtidx. */
2562 0 : if (vpd[nvpds - 1] > vpd[nvpds - 2])
2563 0 : vpdstep = vpd[nvpds - 1] - vpd[nvpds - 2];
2564 : else
2565 : vpdstep = 1;
2566 0 : while (ss <= tgtidx && npdadcs < AR_NUM_PDADC_VALUES - 1) {
2567 0 : val = vpd[nvpds - 1] + (ss - maxidx + 1) * vpdstep;
2568 0 : pdadcs[npdadcs++] = MIN(val, 255);
2569 0 : ss++;
2570 : }
2571 : }
2572 :
2573 : /* Fill remaining PDADC and boundaries entries. */
2574 0 : if (AR_SREV_9285(sc))
2575 0 : boundary = AR9285_PD_GAIN_BOUNDARY_DEFAULT;
2576 : else /* Fill with latest. */
2577 0 : boundary = boundaries[nxpdgains - 1];
2578 :
2579 0 : for (; nxpdgains < AR_PD_GAINS_IN_MASK; nxpdgains++)
2580 0 : boundaries[nxpdgains] = boundary;
2581 :
2582 0 : for (; npdadcs < AR_NUM_PDADC_VALUES; npdadcs++)
2583 0 : pdadcs[npdadcs] = pdadcs[npdadcs - 1];
2584 : #undef DB
2585 0 : }
2586 :
2587 : void
2588 0 : ar5008_get_lg_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
2589 : uint8_t ctl, const struct ar_cal_target_power_leg *tgt, int nchans,
2590 : uint8_t tpow[4])
2591 : {
2592 : uint8_t fbin;
2593 : int i, lo, hi;
2594 :
2595 : /* Find interval (lower and upper indices). */
2596 0 : fbin = athn_chan2fbin(c);
2597 0 : for (i = 0; i < nchans; i++) {
2598 0 : if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
2599 0 : tgt[i].bChannel > fbin)
2600 : break;
2601 : }
2602 : hi = i;
2603 0 : lo = hi - 1;
2604 0 : if (lo == -1)
2605 0 : lo = hi;
2606 0 : else if (hi == nchans || tgt[hi].bChannel == AR_BCHAN_UNUSED)
2607 0 : hi = lo;
2608 :
2609 : /* Interpolate values. */
2610 0 : for (i = 0; i < 4; i++) {
2611 0 : tpow[i] = athn_interpolate(fbin,
2612 0 : tgt[lo].bChannel, tgt[lo].tPow2x[i],
2613 0 : tgt[hi].bChannel, tgt[hi].tPow2x[i]);
2614 : }
2615 : /* XXX Apply conformance testing limit. */
2616 0 : }
2617 :
2618 : void
2619 0 : ar5008_get_ht_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
2620 : uint8_t ctl, const struct ar_cal_target_power_ht *tgt, int nchans,
2621 : uint8_t tpow[8])
2622 : {
2623 : uint8_t fbin;
2624 : int i, lo, hi;
2625 :
2626 : /* Find interval (lower and upper indices). */
2627 0 : fbin = athn_chan2fbin(c);
2628 0 : for (i = 0; i < nchans; i++) {
2629 0 : if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
2630 0 : tgt[i].bChannel > fbin)
2631 : break;
2632 : }
2633 : hi = i;
2634 0 : lo = hi - 1;
2635 0 : if (lo == -1)
2636 0 : lo = hi;
2637 0 : else if (hi == nchans || tgt[hi].bChannel == AR_BCHAN_UNUSED)
2638 0 : hi = lo;
2639 :
2640 : /* Interpolate values. */
2641 0 : for (i = 0; i < 8; i++) {
2642 0 : tpow[i] = athn_interpolate(fbin,
2643 0 : tgt[lo].bChannel, tgt[lo].tPow2x[i],
2644 0 : tgt[hi].bChannel, tgt[hi].tPow2x[i]);
2645 : }
2646 : /* XXX Apply conformance testing limit. */
2647 0 : }
2648 :
2649 : /*
2650 : * Adaptive noise immunity.
2651 : */
2652 : void
2653 0 : ar5008_set_noise_immunity_level(struct athn_softc *sc, int level)
2654 : {
2655 0 : int high = level == 4;
2656 : uint32_t reg;
2657 :
2658 0 : reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
2659 0 : reg = RW(reg, AR_PHY_DESIRED_SZ_TOT_DES, high ? -62 : -55);
2660 0 : AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
2661 :
2662 0 : reg = AR_READ(sc, AR_PHY_AGC_CTL1);
2663 0 : reg = RW(reg, AR_PHY_AGC_CTL1_COARSE_LOW, high ? -70 : -64);
2664 0 : reg = RW(reg, AR_PHY_AGC_CTL1_COARSE_HIGH, high ? -12 : -14);
2665 0 : AR_WRITE(sc, AR_PHY_AGC_CTL1, reg);
2666 :
2667 0 : reg = AR_READ(sc, AR_PHY_FIND_SIG);
2668 0 : reg = RW(reg, AR_PHY_FIND_SIG_FIRPWR, high ? -80 : -78);
2669 0 : AR_WRITE(sc, AR_PHY_FIND_SIG, reg);
2670 :
2671 0 : AR_WRITE_BARRIER(sc);
2672 0 : }
2673 :
2674 : void
2675 0 : ar5008_enable_ofdm_weak_signal(struct athn_softc *sc)
2676 : {
2677 : uint32_t reg;
2678 :
2679 0 : reg = AR_READ(sc, AR_PHY_SFCORR_LOW);
2680 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, 50);
2681 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, 40);
2682 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, 48);
2683 0 : AR_WRITE(sc, AR_PHY_SFCORR_LOW, reg);
2684 :
2685 0 : reg = AR_READ(sc, AR_PHY_SFCORR);
2686 0 : reg = RW(reg, AR_PHY_SFCORR_M1_THRESH, 77);
2687 0 : reg = RW(reg, AR_PHY_SFCORR_M2_THRESH, 64);
2688 0 : reg = RW(reg, AR_PHY_SFCORR_M2COUNT_THR, 16);
2689 0 : AR_WRITE(sc, AR_PHY_SFCORR, reg);
2690 :
2691 0 : reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
2692 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, 50);
2693 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, 40);
2694 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH, 77);
2695 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH, 64);
2696 0 : AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
2697 :
2698 0 : AR_SETBITS(sc, AR_PHY_SFCORR_LOW,
2699 : AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
2700 0 : AR_WRITE_BARRIER(sc);
2701 0 : }
2702 :
2703 : void
2704 0 : ar5008_disable_ofdm_weak_signal(struct athn_softc *sc)
2705 : {
2706 : uint32_t reg;
2707 :
2708 0 : reg = AR_READ(sc, AR_PHY_SFCORR_LOW);
2709 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, 127);
2710 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, 127);
2711 0 : reg = RW(reg, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, 63);
2712 0 : AR_WRITE(sc, AR_PHY_SFCORR_LOW, reg);
2713 :
2714 0 : reg = AR_READ(sc, AR_PHY_SFCORR);
2715 0 : reg = RW(reg, AR_PHY_SFCORR_M1_THRESH, 127);
2716 0 : reg = RW(reg, AR_PHY_SFCORR_M2_THRESH, 127);
2717 0 : reg = RW(reg, AR_PHY_SFCORR_M2COUNT_THR, 31);
2718 0 : AR_WRITE(sc, AR_PHY_SFCORR, reg);
2719 :
2720 0 : reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
2721 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, 127);
2722 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, 127);
2723 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH, 127);
2724 0 : reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH, 127);
2725 0 : AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
2726 :
2727 0 : AR_CLRBITS(sc, AR_PHY_SFCORR_LOW,
2728 : AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
2729 0 : AR_WRITE_BARRIER(sc);
2730 0 : }
2731 :
2732 : void
2733 0 : ar5008_set_cck_weak_signal(struct athn_softc *sc, int high)
2734 : {
2735 : uint32_t reg;
2736 :
2737 0 : reg = AR_READ(sc, AR_PHY_CCK_DETECT);
2738 0 : reg = RW(reg, AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, high ? 6 : 8);
2739 0 : AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
2740 0 : AR_WRITE_BARRIER(sc);
2741 0 : }
2742 :
2743 : void
2744 0 : ar5008_set_firstep_level(struct athn_softc *sc, int level)
2745 : {
2746 : uint32_t reg;
2747 :
2748 0 : reg = AR_READ(sc, AR_PHY_FIND_SIG);
2749 0 : reg = RW(reg, AR_PHY_FIND_SIG_FIRSTEP, level * 4);
2750 0 : AR_WRITE(sc, AR_PHY_FIND_SIG, reg);
2751 0 : AR_WRITE_BARRIER(sc);
2752 0 : }
2753 :
2754 : void
2755 0 : ar5008_set_spur_immunity_level(struct athn_softc *sc, int level)
2756 : {
2757 : uint32_t reg;
2758 :
2759 0 : reg = AR_READ(sc, AR_PHY_TIMING5);
2760 0 : reg = RW(reg, AR_PHY_TIMING5_CYCPWR_THR1, (level + 1) * 2);
2761 0 : AR_WRITE(sc, AR_PHY_TIMING5, reg);
2762 0 : AR_WRITE_BARRIER(sc);
2763 0 : }
|