1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2009-2010 Weongyo Jeong <[email protected]>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15 * redistribution must be conditioned upon including a substantially
16 * similar Disclaimer requirement for further binary redistribution.
17 *
18 * NO WARRANTY
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 * THE POSSIBILITY OF SUCH DAMAGES.
30 *
31 * $FreeBSD$
32 */
33
34 #ifndef _IF_BWNVAR_H
35 #define _IF_BWNVAR_H
36
37 #include <dev/bhnd/bhnd.h>
38
39 struct bwn_softc;
40 struct bwn_mac;
41
42 #define N(a) (sizeof(a) / sizeof(a[0]))
43 #define BWN_ALIGN 0x1000
44 #define BWN_RETRY_SHORT 7
45 #define BWN_RETRY_LONG 4
46 #define BWN_STAID_MAX 64
47 #define BWN_TXPWR_IGNORE_TIME (1 << 0)
48 #define BWN_TXPWR_IGNORE_TSSI (1 << 1)
49 #define BWN_HAS_TXMAG(phy) \
50 (((phy)->rev >= 2) && ((phy)->rf_ver == 0x2050) && \
51 ((phy)->rf_rev == 8))
52 #define BWN_HAS_LOOPBACK(phy) \
53 (((phy)->rev > 1) || ((phy)->gmode))
54 #define BWN_TXERROR_MAX 1000
55 #define BWN_GETTIME(v) do { \
56 struct timespec ts; \
57 nanouptime(&ts); \
58 (v) = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; \
59 } while (0)
60 #define BWN_ISOLDFMT(mac) ((mac)->mac_fw.rev <= 351)
61 #define BWN_TSSI2DBM(num, den) \
62 ((int32_t)((num < 0) ? num / den : (num + den / 2) / den))
63 #define BWN_HDRSIZE(mac) bwn_tx_hdrsize(mac)
64 #define BWN_MAXTXHDRSIZE (112 + (sizeof(struct bwn_plcp6)))
65
66 #define BWN_PIO_COOKIE(tq, tp) \
67 ((uint16_t)((((uint16_t)tq->tq_index + 1) << 12) | tp->tp_index))
68 #define BWN_DMA_COOKIE(dr, slot) \
69 ((uint16_t)(((uint16_t)dr->dr_index + 1) << 12) | (uint16_t)slot)
70 #define BWN_READ_2(mac, o) \
71 (bus_read_2((mac)->mac_sc->sc_mem_res, (o)))
72 #define BWN_READ_4(mac, o) \
73 (bus_read_4((mac)->mac_sc->sc_mem_res, (o)))
74 #define BWN_WRITE_2(mac, o, v) \
75 (bus_write_2((mac)->mac_sc->sc_mem_res, (o), (v)))
76 #define BWN_WRITE_2_F(mac, o, v) do { \
77 (BWN_WRITE_2(mac, o, v)); \
78 BWN_READ_2(mac, o); \
79 } while(0)
80 #define BWN_WRITE_SETMASK2(mac, offset, mask, set) \
81 BWN_WRITE_2(mac, offset, (BWN_READ_2(mac, offset) & mask) | set)
82 #define BWN_WRITE_4(mac, o, v) \
83 (bus_write_4((mac)->mac_sc->sc_mem_res, (o), (v)))
84 #define BWN_WRITE_SETMASK4(mac, offset, mask, set) \
85 BWN_WRITE_4(mac, offset, (BWN_READ_4(mac, offset) & mask) | set)
86 #define BWN_PIO_TXQOFFSET(mac) \
87 ((bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 11) ? 0x18 : 0)
88 #define BWN_PIO_RXQOFFSET(mac) \
89 ((bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 11) ? 0x38 : 8)
90 #define BWN_SEC_NEWAPI(mac) (mac->mac_fw.rev >= 351)
91 #define BWN_SEC_KEY2FW(mac, idx) \
92 (BWN_SEC_NEWAPI(mac) ? idx : ((idx >= 4) ? idx - 4 : idx))
93 #define BWN_RF_READ(mac, r) (mac->mac_phy.rf_read(mac, r))
94 #define BWN_RF_WRITE(mac, r, v) (mac->mac_phy.rf_write(mac, r, v))
95 #define BWN_RF_MASK(mac, o, m) \
96 BWN_RF_WRITE(mac, o, BWN_RF_READ(mac, o) & m)
97 #define BWN_RF_SETMASK(mac, offset, mask, set) \
98 BWN_RF_WRITE(mac, offset, (BWN_RF_READ(mac, offset) & mask) | set)
99 #define BWN_RF_SET(mac, offset, set) \
100 BWN_RF_WRITE(mac, offset, BWN_RF_READ(mac, offset) | set)
101 #define BWN_PHY_READ(mac, r) (mac->mac_phy.phy_read(mac, r))
102 #define BWN_PHY_WRITE(mac, r, v) \
103 (mac->mac_phy.phy_write(mac, r, v))
104 #define BWN_PHY_SET(mac, offset, set) do { \
105 if (mac->mac_phy.phy_maskset != NULL) { \
106 KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED || \
107 mac->mac_suspended > 0, \
108 ("dont access PHY or RF registers after turning on MAC")); \
109 mac->mac_phy.phy_maskset(mac, offset, 0xffff, set); \
110 } else \
111 BWN_PHY_WRITE(mac, offset, \
112 BWN_PHY_READ(mac, offset) | (set)); \
113 } while (0)
114 #define BWN_PHY_SETMASK(mac, offset, mask, set) do { \
115 if (mac->mac_phy.phy_maskset != NULL) { \
116 KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED || \
117 mac->mac_suspended > 0, \
118 ("dont access PHY or RF registers after turning on MAC")); \
119 mac->mac_phy.phy_maskset(mac, offset, mask, set); \
120 } else \
121 BWN_PHY_WRITE(mac, offset, \
122 (BWN_PHY_READ(mac, offset) & (mask)) | (set)); \
123 } while (0)
124 #define BWN_PHY_MASK(mac, offset, mask) do { \
125 if (mac->mac_phy.phy_maskset != NULL) { \
126 KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED || \
127 mac->mac_suspended > 0, \
128 ("dont access PHY or RF registers after turning on MAC")); \
129 mac->mac_phy.phy_maskset(mac, offset, mask, 0); \
130 } else \
131 BWN_PHY_WRITE(mac, offset, \
132 BWN_PHY_READ(mac, offset) & mask); \
133 } while (0)
134 #define BWN_PHY_COPY(mac, dst, src) do { \
135 KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED || \
136 mac->mac_suspended > 0, \
137 ("dont access PHY or RF registers after turning on MAC")); \
138 BWN_PHY_WRITE(mac, dst, BWN_PHY_READ(mac, src)); \
139 } while (0)
140 #define BWN_LO_CALIB_EXPIRE (1000 * (30 - 2))
141 #define BWN_LO_PWRVEC_EXPIRE (1000 * (30 - 2))
142 #define BWN_LO_TXCTL_EXPIRE (1000 * (180 - 4))
143 #define BWN_LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
144 #define BWN_BITREV4(tmp) (BWN_BITREV8(tmp) >> 4)
145 #define BWN_BITREV8(byte) (bwn_bitrev_table[byte])
146 #define BWN_BBATTCMP(a, b) ((a)->att == (b)->att)
147 #define BWN_RFATTCMP(a, b) \
148 (((a)->att == (b)->att) && ((a)->padmix == (b)->padmix))
149 #define BWN_PIO_WRITE_2(mac, tq, offset, value) \
150 BWN_WRITE_2(mac, (tq)->tq_base + offset, value)
151 #define BWN_PIO_READ_4(mac, tq, offset) \
152 BWN_READ_4(mac, tq->tq_base + offset)
153 #define BWN_ISCCKRATE(rate) \
154 (rate == BWN_CCK_RATE_1MB || rate == BWN_CCK_RATE_2MB || \
155 rate == BWN_CCK_RATE_5MB || rate == BWN_CCK_RATE_11MB)
156 #define BWN_ISOFDMRATE(rate) (!BWN_ISCCKRATE(rate))
157 #define BWN_BARRIER(mac, offset, length, flags) \
158 bus_barrier((mac)->mac_sc->sc_mem_res, (offset), (length), (flags))
159 #define BWN_DMA_READ(dr, offset) \
160 (BWN_READ_4(dr->dr_mac, dr->dr_base + offset))
161 #define BWN_DMA_WRITE(dr, offset, value) \
162 (BWN_WRITE_4(dr->dr_mac, dr->dr_base + offset, value))
163
164
165 typedef enum {
166 BWN_PHY_BAND_2G = 0,
167 BWN_PHY_BAND_5G_LO = 1,
168 BWN_PHY_BAND_5G_MI = 2,
169 BWN_PHY_BAND_5G_HI = 3
170 } bwn_phy_band_t;
171
172 typedef enum {
173 BWN_BAND_2G,
174 BWN_BAND_5G,
175 } bwn_band_t;
176
177 typedef enum {
178 BWN_CHAN_TYPE_20,
179 BWN_CHAN_TYPE_20_HT,
180 BWN_CHAN_TYPE_40_HT_U,
181 BWN_CHAN_TYPE_40_HT_D,
182 } bwn_chan_type_t;
183
184 struct bwn_rate {
185 uint16_t rateid;
186 uint32_t flags;
187 };
188
189 #define BWN_ANT0 0
190 #define BWN_ANT1 1
191 #define BWN_ANTAUTO0 2
192 #define BWN_ANTAUTO1 3
193 #define BWN_ANT2 4
194 #define BWN_ANT3 8
195 #define BWN_ANTAUTO BWN_ANTAUTO0
196 #define BWN_ANT_DEFAULT BWN_ANTAUTO
197 #define BWN_TX_SLOTS_PER_FRAME 2
198
199 struct bwn_channel {
200 unsigned freq;
201 unsigned ieee;
202 unsigned maxTxPow;
203 };
204
205 struct bwn_channelinfo {
206 struct bwn_channel channels[IEEE80211_CHAN_MAX];
207 unsigned nchannels;
208 };
209
210 struct bwn_bbatt {
211 uint8_t att;
212 };
213
214 struct bwn_bbatt_list {
215 const struct bwn_bbatt *array;
216 uint8_t len;
217 uint8_t min;
218 uint8_t max;
219 };
220
221 struct bwn_rfatt {
222 uint8_t att;
223 int padmix;
224 };
225
226 struct bwn_rfatt_list {
227 const struct bwn_rfatt *array;
228 uint8_t len;
229 uint8_t min;
230 uint8_t max;
231 };
232
233 #define BWN_DC_LT_SIZE 32
234
235 struct bwn_loctl {
236 int8_t i;
237 int8_t q;
238 };
239
240 typedef enum {
241 BWN_TXPWR_RES_NEED_ADJUST,
242 BWN_TXPWR_RES_DONE,
243 } bwn_txpwr_result_t;
244
245 struct bwn_lo_calib {
246 struct bwn_bbatt bbatt;
247 struct bwn_rfatt rfatt;
248 struct bwn_loctl ctl;
249 unsigned long calib_time;
250 TAILQ_ENTRY(bwn_lo_calib) list;
251 };
252
253 struct bwn_rxhdr4 {
254 uint16_t frame_len;
255 uint8_t pad1[2];
256 uint16_t phy_status0;
257 union {
258 struct {
259 uint8_t rssi;
260 uint8_t sig_qual;
261 } __packed abg;
262 struct {
263 int8_t power0;
264 int8_t power1;
265 } __packed n;
266 } __packed phy;
267 union {
268 struct {
269 int8_t power2;
270 uint8_t pad;
271 } __packed n;
272 struct {
273 uint8_t pad;
274 int8_t ht_power0;
275 } __packed ht;
276 uint16_t phy_status2;
277 } __packed ps2;
278 union {
279 struct {
280 uint16_t phy_status3;
281 } __packed lp;
282 struct {
283 int8_t phy_ht_power1;
284 int8_t phy_ht_power2;
285 } __packed ht;
286 } __packed ps3;
287 union {
288 struct {
289 uint32_t mac_status;
290 uint16_t mac_time;
291 uint16_t channel;
292 } __packed r351;
293 struct {
294 uint16_t phy_status4;
295 uint16_t phy_status5;
296 uint32_t mac_status;
297 uint16_t mac_time;
298 uint16_t channel;
299 } __packed r598;
300 } __packed ps4;
301 } __packed;
302
303 struct bwn_txstatus {
304 uint16_t cookie;
305 uint16_t seq;
306 uint8_t phy_stat;
307 uint8_t framecnt;
308 uint8_t rtscnt;
309 uint8_t sreason;
310 uint8_t pm;
311 uint8_t im;
312 uint8_t ampdu;
313 uint8_t ack;
314 };
315
316 #define BWN_TXCTL_PA3DB 0x40
317 #define BWN_TXCTL_PA2DB 0x20
318 #define BWN_TXCTL_TXMIX 0x10
319
320 struct bwn_txpwr_loctl {
321 struct bwn_rfatt_list rfatt;
322 struct bwn_bbatt_list bbatt;
323 uint16_t dc_lt[BWN_DC_LT_SIZE];
324 TAILQ_HEAD(, bwn_lo_calib) calib_list;
325 unsigned long pwr_vec_read_time;
326 unsigned long txctl_measured_time;
327 uint8_t tx_bias;
328 uint8_t tx_magn;
329 uint64_t power_vector;
330 };
331
332 #define BWN_OFDMTAB_DIR_UNKNOWN 0
333 #define BWN_OFDMTAB_DIR_READ 1
334 #define BWN_OFDMTAB_DIR_WRITE 2
335
336 struct bwn_phy_g {
337 unsigned pg_flags;
338 #define BWN_PHY_G_FLAG_TSSITABLE_ALLOC (1 << 0)
339 #define BWN_PHY_G_FLAG_RADIOCTX_VALID (1 << 1)
340 int pg_aci_enable;
341 int pg_aci_wlan_automatic;
342 int pg_aci_hw_rssi;
343 int pg_rf_on;
344 uint16_t pg_radioctx_over;
345 uint16_t pg_radioctx_overval;
346 uint16_t pg_minlowsig[2];
347 uint16_t pg_minlowsigpos[2];
348 uint16_t pg_pa0maxpwr;
349 int8_t *pg_tssi2dbm;
350 int pg_idletssi;
351 int pg_curtssi;
352 uint8_t pg_avgtssi;
353 struct bwn_bbatt pg_bbatt;
354 struct bwn_rfatt pg_rfatt;
355 uint8_t pg_txctl;
356 int pg_bbatt_delta;
357 int pg_rfatt_delta;
358
359 struct bwn_txpwr_loctl pg_loctl;
360 int16_t pg_max_lb_gain;
361 int16_t pg_trsw_rx_gain;
362 int16_t pg_lna_lod_gain;
363 int16_t pg_lna_gain;
364 int16_t pg_pga_gain;
365 int pg_immode;
366 #define BWN_INTERFSTACK_SIZE 26
367 uint32_t pg_interfstack[BWN_INTERFSTACK_SIZE];
368
369 int16_t pg_nrssi[2];
370 int32_t pg_nrssi_slope;
371 int8_t pg_nrssi_lt[64];
372
373 uint16_t pg_lofcal;
374
375 uint16_t pg_initval;
376 uint16_t pg_ofdmtab_addr;
377 unsigned pg_ofdmtab_dir;
378 };
379
380 #define BWN_IMMODE_NONE 0
381 #define BWN_IMMODE_NONWLAN 1
382 #define BWN_IMMODE_MANUAL 2
383 #define BWN_IMMODE_AUTO 3
384
385 #define BWN_PHYLP_TXPCTL_UNKNOWN 0
386 #define BWN_PHYLP_TXPCTL_OFF 1
387 #define BWN_PHYLP_TXPCTL_ON_SW 2
388 #define BWN_PHYLP_TXPCTL_ON_HW 3
389
390 struct bwn_phy_lp {
391 uint8_t plp_chan;
392 uint8_t plp_chanfullcal;
393 int32_t plp_antenna;
394 uint8_t plp_txpctlmode;
395 uint8_t plp_txisoband_h;
396 uint8_t plp_txisoband_m;
397 uint8_t plp_txisoband_l;
398 uint8_t plp_rxpwroffset;
399 int8_t plp_txpwridx;
400 uint16_t plp_tssiidx;
401 uint16_t plp_tssinpt;
402 uint8_t plp_rssivf;
403 uint8_t plp_rssivc;
404 uint8_t plp_rssigs;
405 uint8_t plp_rccap;
406 uint8_t plp_bxarch;
407 uint8_t plp_crsusr_off;
408 uint8_t plp_crssys_off;
409 uint32_t plp_div;
410 int32_t plp_tonefreq;
411 uint16_t plp_digfilt[9];
412 };
413
414 /* for LP */
415 struct bwn_txgain {
416 uint16_t tg_gm;
417 uint16_t tg_pga;
418 uint16_t tg_pad;
419 uint16_t tg_dac;
420 };
421
422 struct bwn_rxcompco {
423 uint8_t rc_chan;
424 int8_t rc_c1;
425 int8_t rc_c0;
426 };
427
428 struct bwn_phy_lp_iq_est {
429 uint32_t ie_iqprod;
430 uint32_t ie_ipwr;
431 uint32_t ie_qpwr;
432 };
433
434 struct bwn_txgain_entry {
435 uint8_t te_gm;
436 uint8_t te_pga;
437 uint8_t te_pad;
438 uint8_t te_dac;
439 uint8_t te_bbmult;
440 };
441
442 /* only for LP PHY */
443 struct bwn_stxtable {
444 uint16_t st_phyoffset;
445 uint16_t st_physhift;
446 uint16_t st_rfaddr;
447 uint16_t st_rfshift;
448 uint16_t st_mask;
449 };
450
451 struct bwn_b206x_chan {
452 uint8_t bc_chan;
453 uint16_t bc_freq;
454 const uint8_t *bc_data;
455 };
456
457 struct bwn_b206x_rfinit_entry {
458 uint16_t br_offset;
459 uint16_t br_valuea;
460 uint16_t br_valueg;
461 uint8_t br_flags;
462 };
463
464 struct bwn_phy_n;
465
466 struct bwn_phy {
467 uint8_t type;
468 uint8_t rev;
469 uint8_t analog;
470
471 int supports_2ghz;
472 int supports_5ghz;
473
474 int gmode;
475 struct bwn_phy_g phy_g;
476 struct bwn_phy_lp phy_lp;
477
478 /*
479 * I'd like the newer PHY code to not hide in the top-level
480 * structs..
481 */
482 struct bwn_phy_n *phy_n;
483
484 uint16_t rf_manuf;
485 uint16_t rf_ver;
486 uint8_t rf_rev;
487 int rf_on;
488 int phy_do_full_init;
489
490 int txpower;
491 int hwpctl;
492 unsigned long nexttime;
493 unsigned int chan;
494 int txerrors;
495
496 int (*attach)(struct bwn_mac *);
497 void (*detach)(struct bwn_mac *);
498 int (*prepare_hw)(struct bwn_mac *);
499 void (*init_pre)(struct bwn_mac *);
500 int (*init)(struct bwn_mac *);
501 void (*exit)(struct bwn_mac *);
502 uint16_t (*phy_read)(struct bwn_mac *, uint16_t);
503 void (*phy_write)(struct bwn_mac *, uint16_t,
504 uint16_t);
505 void (*phy_maskset)(struct bwn_mac *,
506 uint16_t, uint16_t, uint16_t);
507 uint16_t (*rf_read)(struct bwn_mac *, uint16_t);
508 void (*rf_write)(struct bwn_mac *, uint16_t,
509 uint16_t);
510 int (*use_hwpctl)(struct bwn_mac *);
511 void (*rf_onoff)(struct bwn_mac *, int);
512 void (*switch_analog)(struct bwn_mac *, int);
513 int (*switch_channel)(struct bwn_mac *,
514 unsigned int);
515 uint32_t (*get_default_chan)(struct bwn_mac *);
516 void (*set_antenna)(struct bwn_mac *, int);
517 int (*set_im)(struct bwn_mac *, int);
518 bwn_txpwr_result_t (*recalc_txpwr)(struct bwn_mac *, int);
519 void (*set_txpwr)(struct bwn_mac *);
520 void (*task_15s)(struct bwn_mac *);
521 void (*task_60s)(struct bwn_mac *);
522 };
523
524 struct bwn_chan_band {
525 uint32_t flags;
526 uint8_t nchan;
527 #define BWN_MAX_CHAN_PER_BAND 14
528 uint8_t chan[BWN_MAX_CHAN_PER_BAND];
529 };
530
531 #define BWN_NR_WMEPARAMS 16
532 enum {
533 BWN_WMEPARAM_TXOP = 0,
534 BWN_WMEPARAM_CWMIN,
535 BWN_WMEPARAM_CWMAX,
536 BWN_WMEPARAM_CWCUR,
537 BWN_WMEPARAM_AIFS,
538 BWN_WMEPARAM_BSLOTS,
539 BWN_WMEPARAM_REGGAP,
540 BWN_WMEPARAM_STATUS,
541 };
542
543 #define BWN_WME_PARAMS(queue) \
544 (BWN_SHARED_EDCFQ + (BWN_NR_WMEPARAMS * sizeof(uint16_t) * (queue)))
545 #define BWN_WME_BACKGROUND BWN_WME_PARAMS(0)
546 #define BWN_WME_BESTEFFORT BWN_WME_PARAMS(1)
547 #define BWN_WME_VIDEO BWN_WME_PARAMS(2)
548 #define BWN_WME_VOICE BWN_WME_PARAMS(3)
549
550 /*
551 * Radio capture format.
552 */
553 #define BWN_RX_RADIOTAP_PRESENT ( \
554 (1 << IEEE80211_RADIOTAP_TSFT) | \
555 (1 << IEEE80211_RADIOTAP_FLAGS) | \
556 (1 << IEEE80211_RADIOTAP_RATE) | \
557 (1 << IEEE80211_RADIOTAP_CHANNEL) | \
558 (1 << IEEE80211_RADIOTAP_ANTENNA) | \
559 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
560 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
561 0)
562
563 struct bwn_rx_radiotap_header {
564 struct ieee80211_radiotap_header wr_ihdr;
565 uint64_t wr_tsf;
566 u_int8_t wr_flags;
567 u_int8_t wr_rate;
568 u_int16_t wr_chan_freq;
569 u_int16_t wr_chan_flags;
570 int8_t wr_antsignal;
571 int8_t wr_antnoise;
572 u_int8_t wr_antenna;
573 } __packed __aligned(8);
574
575 #define BWN_TX_RADIOTAP_PRESENT ( \
576 (1 << IEEE80211_RADIOTAP_FLAGS) | \
577 (1 << IEEE80211_RADIOTAP_RATE) | \
578 (1 << IEEE80211_RADIOTAP_CHANNEL) | \
579 (1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
580 (1 << IEEE80211_RADIOTAP_ANTENNA) | \
581 0)
582
583 struct bwn_tx_radiotap_header {
584 struct ieee80211_radiotap_header wt_ihdr;
585 u_int8_t wt_flags;
586 u_int8_t wt_rate;
587 u_int16_t wt_chan_freq;
588 u_int16_t wt_chan_flags;
589 u_int8_t wt_txpower;
590 u_int8_t wt_antenna;
591 } __packed;
592
593 struct bwn_stats {
594 int32_t rtsfail;
595 int32_t rts;
596 int32_t link_noise;
597 };
598
599 /* Noise Calculation (Link Quality) */
600 struct bwn_noise {
601 uint8_t noi_running;
602 uint8_t noi_nsamples;
603 int8_t noi_samples[8][4];
604 };
605
606 struct bwn_dmadesc_meta {
607 bus_dmamap_t mt_dmap;
608 bus_addr_t mt_paddr;
609 struct mbuf *mt_m;
610 struct ieee80211_node *mt_ni;
611 uint8_t mt_txtype;
612 #define BWN_DMADESC_METATYPE_HEADER 0
613 #define BWN_DMADESC_METATYPE_BODY 1
614 uint8_t mt_islast;
615 };
616
617 #define BWN_DMAINTR_FATALMASK \
618 ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 14) | (1 << 15))
619 #define BWN_DMAINTR_NONFATALMASK (1 << 13)
620 #define BWN_DMAINTR_RX_DONE (1 << 16)
621
622 #define BWN_DMA32_DCTL_BYTECNT 0x00001fff
623 #define BWN_DMA32_DCTL_ADDREXT_MASK 0x00030000
624 #define BWN_DMA32_DCTL_ADDREXT_SHIFT 16
625 #define BWN_DMA32_DCTL_DTABLEEND 0x10000000
626 #define BWN_DMA32_DCTL_IRQ 0x20000000
627 #define BWN_DMA32_DCTL_FRAMEEND 0x40000000
628 #define BWN_DMA32_DCTL_FRAMESTART 0x80000000
629 struct bwn_dmadesc32 {
630 uint32_t control;
631 uint32_t address;
632 } __packed;
633
634 #define BWN_DMA64_DCTL0_DTABLEEND 0x10000000
635 #define BWN_DMA64_DCTL0_IRQ 0x20000000
636 #define BWN_DMA64_DCTL0_FRAMEEND 0x40000000
637 #define BWN_DMA64_DCTL0_FRAMESTART 0x80000000
638 #define BWN_DMA64_DCTL1_BYTECNT 0x00001fff
639 #define BWN_DMA64_DCTL1_ADDREXT_MASK 0x00030000
640 #define BWN_DMA64_DCTL1_ADDREXT_SHIFT 16
641 struct bwn_dmadesc64 {
642 uint32_t control0;
643 uint32_t control1;
644 uint32_t address_low;
645 uint32_t address_high;
646 } __packed;
647
648 struct bwn_dmadesc_generic {
649 union {
650 struct bwn_dmadesc32 dma32;
651 struct bwn_dmadesc64 dma64;
652 } __packed dma;
653 } __packed;
654
655 struct bwn_dma_ring;
656
657 struct bwn_dma_ring {
658 struct bwn_mac *dr_mac;
659 const struct bwn_dma_ops *dr_ops;
660 struct bwn_dmadesc_meta *dr_meta;
661 void *dr_txhdr_cache;
662 bus_dma_tag_t dr_ring_dtag;
663 bus_dma_tag_t dr_txring_dtag;
664 bus_dmamap_t dr_spare_dmap; /* only for RX */
665 bus_dmamap_t dr_ring_dmap;
666 bus_addr_t dr_txring_paddr;
667 void *dr_ring_descbase;
668 bus_addr_t dr_ring_dmabase;
669 int dr_numslots;
670 int dr_usedslot;
671 int dr_curslot;
672 uint32_t dr_frameoffset;
673 uint16_t dr_rx_bufsize;
674 uint16_t dr_base;
675 int dr_index;
676 uint8_t dr_tx;
677 uint8_t dr_stop;
678 int dr_type;
679
680 void (*getdesc)(struct bwn_dma_ring *,
681 int, struct bwn_dmadesc_generic **,
682 struct bwn_dmadesc_meta **);
683 void (*setdesc)(struct bwn_dma_ring *,
684 struct bwn_dmadesc_generic *,
685 bus_addr_t, uint16_t, int, int,
686 int);
687 void (*start_transfer)(struct bwn_dma_ring *,
688 int);
689 void (*suspend)(struct bwn_dma_ring *);
690 void (*resume)(struct bwn_dma_ring *);
691 int (*get_curslot)(struct bwn_dma_ring *);
692 void (*set_curslot)(struct bwn_dma_ring *,
693 int);
694 };
695
696 struct bwn_dma {
697 bus_dma_tag_t parent_dtag;
698 bus_dma_tag_t rxbuf_dtag;
699 bus_dma_tag_t txbuf_dtag;
700 struct bhnd_dma_translation translation;
701 u_int addrext_shift;
702
703 struct bwn_dma_ring *wme[5];
704 struct bwn_dma_ring *mcast;
705 struct bwn_dma_ring *rx;
706 uint64_t lastseq; /* XXX FIXME */
707 };
708
709 struct bwn_pio_rxqueue {
710 struct bwn_mac *prq_mac;
711 uint16_t prq_base;
712 uint8_t prq_rev;
713 };
714
715 struct bwn_pio_txqueue;
716 struct bwn_pio_txpkt {
717 struct bwn_pio_txqueue *tp_queue;
718 struct ieee80211_node *tp_ni;
719 struct mbuf *tp_m;
720 uint8_t tp_index;
721 TAILQ_ENTRY(bwn_pio_txpkt) tp_list;
722 };
723
724 #define BWN_PIO_MAX_TXPACKETS 32
725 struct bwn_pio_txqueue {
726 uint16_t tq_base;
727 uint16_t tq_size;
728 uint16_t tq_used;
729 uint16_t tq_free;
730 uint8_t tq_index;
731 struct bwn_pio_txpkt tq_pkts[BWN_PIO_MAX_TXPACKETS];
732 TAILQ_HEAD(, bwn_pio_txpkt) tq_pktlist;
733 };
734
735 struct bwn_pio {
736 struct bwn_pio_txqueue wme[5];
737 struct bwn_pio_txqueue mcast;
738 struct bwn_pio_rxqueue rx;
739 };
740
741 struct bwn_plcp4 {
742 union {
743 uint32_t data;
744 uint8_t raw[4];
745 } __packed o;
746 } __packed;
747
748 struct bwn_plcp6 {
749 union {
750 uint32_t data;
751 uint8_t raw[6];
752 } __packed o;
753 } __packed;
754
755 struct bwn_txhdr {
756 uint32_t macctl;
757 uint8_t macfc[2];
758 uint16_t tx_festime;
759 uint16_t phyctl;
760 uint16_t phyctl_1;
761 uint16_t phyctl_1fb;
762 uint16_t phyctl_1rts;
763 uint16_t phyctl_1rtsfb;
764 uint8_t phyrate;
765 uint8_t phyrate_rts;
766 uint8_t eftypes; /* extra frame types */
767 uint8_t chan;
768 uint8_t iv[16];
769 uint8_t addr1[IEEE80211_ADDR_LEN];
770 uint16_t tx_festime_fb;
771 struct bwn_plcp6 rts_plcp_fb;
772 uint16_t rts_dur_fb;
773 struct bwn_plcp6 plcp_fb;
774 uint16_t dur_fb;
775 uint16_t mimo_modelen;
776 uint16_t mimo_ratelen_fb;
777 uint32_t timeout;
778
779 union {
780 /* format <= r351 */
781 struct {
782 uint8_t pad0[2];
783 uint16_t cookie;
784 uint16_t tx_status;
785 struct bwn_plcp6 rts_plcp;
786 uint8_t rts_frame[16];
787 uint8_t pad1[2];
788 struct bwn_plcp6 plcp;
789 } __packed r351;
790 /* format > r410 < r598 */
791 struct {
792 uint16_t mimo_antenna;
793 uint16_t preload_size;
794 uint8_t pad0[2];
795 uint16_t cookie;
796 uint16_t tx_status;
797 struct bwn_plcp6 rts_plcp;
798 uint8_t rts_frame[16];
799 uint8_t pad1[2];
800 struct bwn_plcp6 plcp;
801 } __packed r410;
802 struct {
803 uint16_t mimo_antenna;
804 uint16_t preload_size;
805 uint8_t pad0[2];
806 uint16_t cookie;
807 uint16_t tx_status;
808 uint16_t max_n_mpdus;
809 uint16_t max_a_bytes_mrt;
810 uint16_t max_a_bytes_fbr;
811 uint16_t min_m_bytes;
812 struct bwn_plcp6 rts_plcp;
813 uint8_t rts_frame[16];
814 uint8_t pad1[2];
815 struct bwn_plcp6 plcp;
816 } __packed r598;
817 } __packed body;
818 } __packed;
819
820 #define BWN_FWTYPE_UCODE 'u'
821 #define BWN_FWTYPE_PCM 'p'
822 #define BWN_FWTYPE_IV 'i'
823 struct bwn_fwhdr {
824 uint8_t type;
825 uint8_t ver;
826 uint8_t pad[2];
827 uint32_t size;
828 } __packed;
829
830 #define BWN_FWINITVALS_OFFSET_MASK 0x7fff
831 #define BWN_FWINITVALS_32BIT 0x8000
832 struct bwn_fwinitvals {
833 uint16_t offset_size;
834 union {
835 uint16_t d16;
836 uint32_t d32;
837 } __packed data;
838 } __packed;
839
840 enum bwn_fw_hdr_format {
841 BWN_FW_HDR_598,
842 BWN_FW_HDR_410,
843 BWN_FW_HDR_351,
844 };
845
846 enum bwn_fwtype {
847 BWN_FWTYPE_DEFAULT,
848 BWN_FWTYPE_OPENSOURCE,
849 BWN_NR_FWTYPES,
850 };
851
852 struct bwn_fwfile {
853 const char *filename;
854 const struct firmware *fw;
855 enum bwn_fwtype type;
856 };
857
858 struct bwn_key {
859 void *keyconf;
860 uint8_t algorithm;
861 };
862
863 struct bwn_fw {
864 struct bwn_fwfile ucode;
865 struct bwn_fwfile pcm;
866 struct bwn_fwfile initvals;
867 struct bwn_fwfile initvals_band;
868 enum bwn_fw_hdr_format fw_hdr_format;
869
870 uint16_t rev;
871 uint16_t patch;
872 uint8_t opensource;
873 uint8_t no_pcmfile;
874 };
875
876 struct bwn_lo_g_sm {
877 int curstate;
878 int nmeasure;
879 int multipler;
880 uint16_t feedth;
881 struct bwn_loctl loctl;
882 };
883
884 struct bwn_lo_g_value {
885 uint8_t old_channel;
886 uint16_t phy_lomask;
887 uint16_t phy_extg;
888 uint16_t phy_dacctl_hwpctl;
889 uint16_t phy_dacctl;
890 uint16_t phy_hpwr_tssictl;
891 uint16_t phy_analogover;
892 uint16_t phy_analogoverval;
893 uint16_t phy_rfover;
894 uint16_t phy_rfoverval;
895 uint16_t phy_classctl;
896 uint16_t phy_crs0;
897 uint16_t phy_pgactl;
898 uint16_t phy_syncctl;
899 uint16_t phy_cck0;
900 uint16_t phy_cck1;
901 uint16_t phy_cck2;
902 uint16_t phy_cck3;
903 uint16_t phy_cck4;
904 uint16_t reg0;
905 uint16_t reg1;
906 uint16_t rf0;
907 uint16_t rf1;
908 uint16_t rf2;
909 };
910
911 #define BWN_LED_MAX 4
912
913 #define BWN_LED_EVENT_NONE -1
914 #define BWN_LED_EVENT_POLL 0
915 #define BWN_LED_EVENT_TX 1
916 #define BWN_LED_EVENT_RX 2
917 #define BWN_LED_SLOWDOWN(dur) (dur) = (((dur) * 3) / 2)
918
919 struct bwn_led {
920 uint8_t led_flags; /* BWN_LED_F_ */
921 uint8_t led_act; /* BWN_LED_ACT_ */
922 uint8_t led_mask;
923 };
924
925 #define BWN_LED_F_ACTLOW 0x1
926 #define BWN_LED_F_BLINK 0x2
927 #define BWN_LED_F_POLLABLE 0x4
928 #define BWN_LED_F_SLOW 0x8
929
930 struct bwn_mac {
931 struct bwn_softc *mac_sc;
932 unsigned mac_status;
933 #define BWN_MAC_STATUS_UNINIT 0
934 #define BWN_MAC_STATUS_INITED 1
935 #define BWN_MAC_STATUS_STARTED 2
936 unsigned mac_flags;
937 /* use "Bad Frames Preemption" */
938 #define BWN_MAC_FLAG_BADFRAME_PREEMP (1 << 0)
939 #define BWN_MAC_FLAG_DFQVALID (1 << 1)
940 #define BWN_MAC_FLAG_RADIO_ON (1 << 2)
941 #define BWN_MAC_FLAG_DMA (1 << 3)
942 #define BWN_MAC_FLAG_WME (1 << 4)
943 #define BWN_MAC_FLAG_HWCRYPTO (1 << 5)
944
945 struct resource *mac_res_irq;
946 int mac_rid_irq;
947 void *mac_intrhand;
948
949 struct bwn_noise mac_noise;
950 struct bwn_phy mac_phy;
951 struct bwn_stats mac_stats;
952 uint32_t mac_reason_intr;
953 uint32_t mac_reason[6];
954 uint32_t mac_intr_mask;
955 int mac_suspended;
956
957 struct bwn_fw mac_fw;
958
959 int mac_dmatype;
960 union {
961 struct bwn_dma dma;
962 struct bwn_pio pio;
963 } mac_method;
964
965 uint16_t mac_ktp; /* Key table pointer */
966 uint8_t mac_max_nr_keys;
967 struct bwn_key mac_key[58];
968
969 unsigned int mac_task_state;
970 struct task mac_intrtask;
971 struct task mac_hwreset;
972 struct task mac_txpower;
973
974 TAILQ_ENTRY(bwn_mac) mac_list;
975 };
976
977 static inline int
bwn_tx_hdrsize(struct bwn_mac * mac)978 bwn_tx_hdrsize(struct bwn_mac *mac)
979 {
980 switch (mac->mac_fw.fw_hdr_format) {
981 case BWN_FW_HDR_598:
982 return (112 + (sizeof(struct bwn_plcp6)));
983 case BWN_FW_HDR_410:
984 return (104 + (sizeof(struct bwn_plcp6)));
985 case BWN_FW_HDR_351:
986 return (100 + (sizeof(struct bwn_plcp6)));
987 default:
988 printf("%s: unknown header format (%d)\n", __func__,
989 mac->mac_fw.fw_hdr_format);
990 return (112 + (sizeof(struct bwn_plcp6)));
991 }
992 }
993
994 /*
995 * Driver-specific vap state.
996 */
997 struct bwn_vap {
998 struct ieee80211vap bv_vap; /* base class */
999 int (*bv_newstate)(struct ieee80211vap *,
1000 enum ieee80211_state, int);
1001 };
1002 #define BWN_VAP(vap) ((struct bwn_vap *)(vap))
1003 #define BWN_VAP_CONST(vap) ((const struct mwl_vap *)(vap))
1004
1005 enum bwn_quirk {
1006 /**
1007 * The ucode PCI slowclock workaround is required on this device.
1008 * @see BWN_HF_PCI_SLOWCLOCK_WORKAROUND.
1009 */
1010 BWN_QUIRK_UCODE_SLOWCLOCK_WAR = (1<<0),
1011
1012 /**
1013 * DMA is unsupported on this device; PIO should be used instead.
1014 */
1015 BWN_QUIRK_NODMA = (1<<1),
1016 };
1017
1018 struct bwn_softc {
1019 device_t sc_dev;
1020 struct bhnd_board_info sc_board_info;
1021 struct bhnd_chipid sc_cid;
1022 uint32_t sc_quirks; /**< @see bwn_quirk */
1023 struct resource *sc_mem_res;
1024 int sc_mem_rid;
1025
1026 device_t sc_chipc; /**< ChipCommon device */
1027 device_t sc_gpio; /**< GPIO device */
1028 device_t sc_pmu; /**< PMU device, or NULL if unsupported */
1029
1030 struct mtx sc_mtx;
1031 struct ieee80211com sc_ic;
1032 struct mbufq sc_snd;
1033 unsigned sc_flags;
1034 #define BWN_FLAG_ATTACHED (1 << 0)
1035 #define BWN_FLAG_INVALID (1 << 1)
1036 #define BWN_FLAG_NEED_BEACON_TP (1 << 2)
1037 #define BWN_FLAG_RUNNING (1 << 3)
1038 unsigned sc_debug;
1039
1040 struct bwn_mac *sc_curmac;
1041 TAILQ_HEAD(, bwn_mac) sc_maclist;
1042
1043 uint8_t sc_bssid[IEEE80211_ADDR_LEN];
1044 unsigned int sc_filters;
1045 uint8_t sc_beacons[2];
1046 uint8_t sc_rf_enabled;
1047
1048 struct wmeParams sc_wmeParams[4];
1049
1050 struct callout sc_rfswitch_ch; /* for laptop */
1051 struct callout sc_task_ch;
1052 struct callout sc_watchdog_ch;
1053 int sc_watchdog_timer;
1054 struct taskqueue *sc_tq; /* private task queue */
1055 int (*sc_newstate)(struct ieee80211com *,
1056 enum ieee80211_state, int);
1057 void (*sc_node_cleanup)(
1058 struct ieee80211_node *);
1059
1060 int sc_rx_rate;
1061 int sc_tx_rate;
1062
1063 int sc_led_blinking;
1064 int sc_led_ticks;
1065 struct bwn_led *sc_blink_led;
1066 struct callout sc_led_blink_ch;
1067 int sc_led_blink_offdur;
1068 struct bwn_led sc_leds[BWN_LED_MAX];
1069 int sc_led_idle;
1070 int sc_led_blink;
1071
1072 uint8_t sc_ant2g; /**< available 2GHz antennas */
1073 uint8_t sc_ant5g; /**< available 5GHz antennas */
1074
1075 struct bwn_tx_radiotap_header sc_tx_th;
1076 struct bwn_rx_radiotap_header sc_rx_th;
1077 };
1078
1079 #define BWN_LOCK_INIT(sc) \
1080 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
1081 MTX_NETWORK_LOCK, MTX_DEF)
1082 #define BWN_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
1083 #define BWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
1084 #define BWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
1085 #define BWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
1086
1087 static inline bwn_band_t
bwn_channel_band(struct bwn_mac * mac,struct ieee80211_channel * c)1088 bwn_channel_band(struct bwn_mac *mac, struct ieee80211_channel *c)
1089 {
1090 if (IEEE80211_IS_CHAN_5GHZ(c))
1091 return BWN_BAND_5G;
1092 /* XXX check 2g, log error if not 2g or 5g? */
1093 return BWN_BAND_2G;
1094 }
1095
1096 static inline bwn_band_t
bwn_current_band(struct bwn_mac * mac)1097 bwn_current_band(struct bwn_mac *mac)
1098 {
1099 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1100 if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
1101 return BWN_BAND_5G;
1102 /* XXX check 2g, log error if not 2g or 5g? */
1103 return BWN_BAND_2G;
1104 }
1105
1106 static inline bool
bwn_is_40mhz(struct bwn_mac * mac)1107 bwn_is_40mhz(struct bwn_mac *mac)
1108 {
1109 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1110
1111 return !! (IEEE80211_IS_CHAN_HT40(ic->ic_curchan));
1112 }
1113
1114 static inline int
bwn_get_centre_freq(struct bwn_mac * mac)1115 bwn_get_centre_freq(struct bwn_mac *mac)
1116 {
1117
1118 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1119 /* XXX TODO: calculate correctly for HT40 mode */
1120 return ic->ic_curchan->ic_freq;
1121 }
1122
1123 static inline int
bwn_get_chan_centre_freq(struct bwn_mac * mac,struct ieee80211_channel * chan)1124 bwn_get_chan_centre_freq(struct bwn_mac *mac, struct ieee80211_channel *chan)
1125 {
1126
1127 /* XXX TODO: calculate correctly for HT40 mode */
1128 return chan->ic_freq;
1129 }
1130
1131 static inline int
bwn_get_chan(struct bwn_mac * mac)1132 bwn_get_chan(struct bwn_mac *mac)
1133 {
1134
1135 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1136 /* XXX TODO: calculate correctly for HT40 mode */
1137 return ic->ic_curchan->ic_ieee;
1138 }
1139
1140 static inline struct ieee80211_channel *
bwn_get_channel(struct bwn_mac * mac)1141 bwn_get_channel(struct bwn_mac *mac)
1142 {
1143
1144 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1145 return ic->ic_curchan;
1146 }
1147
1148 static inline bool
bwn_is_chan_passive(struct bwn_mac * mac)1149 bwn_is_chan_passive(struct bwn_mac *mac)
1150 {
1151
1152 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1153 return !! IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan);
1154 }
1155
1156 static inline bwn_chan_type_t
bwn_get_chan_type(struct bwn_mac * mac,struct ieee80211_channel * c)1157 bwn_get_chan_type(struct bwn_mac *mac, struct ieee80211_channel *c)
1158 {
1159 struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1160 if (c == NULL)
1161 c = ic->ic_curchan;
1162 if (IEEE80211_IS_CHAN_HT40U(c))
1163 return BWN_CHAN_TYPE_40_HT_U;
1164 else if (IEEE80211_IS_CHAN_HT40D(c))
1165 return BWN_CHAN_TYPE_40_HT_D;
1166 else if (IEEE80211_IS_CHAN_HT20(c))
1167 return BWN_CHAN_TYPE_20_HT;
1168 else
1169 return BWN_CHAN_TYPE_20;
1170 }
1171
1172 static inline int
bwn_get_chan_power(struct bwn_mac * mac,struct ieee80211_channel * c)1173 bwn_get_chan_power(struct bwn_mac *mac, struct ieee80211_channel *c)
1174 {
1175
1176 /* return in dbm */
1177 return c->ic_maxpower / 2;
1178 }
1179
1180 #endif /* !_IF_BWNVAR_H */
1181