1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
2
3 /*-
4 * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
6 * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #ifndef IF_RTWN_RIDX_H
22 #define IF_RTWN_RIDX_H
23
24 /* HW rate indices. */
25
26 /*
27 * Note - these are also used as offsets into the TX power table
28 * array.
29 */
30 #define RTWN_RIDX_CCK1 0
31 #define RTWN_RIDX_CCK2 1
32 #define RTWN_RIDX_CCK55 2
33 #define RTWN_RIDX_CCK11 3
34 #define RTWN_RIDX_OFDM6 4
35 #define RTWN_RIDX_OFDM9 5
36 #define RTWN_RIDX_OFDM12 6
37 #define RTWN_RIDX_OFDM18 7
38 #define RTWN_RIDX_OFDM24 8
39 #define RTWN_RIDX_OFDM36 9
40 #define RTWN_RIDX_OFDM48 10
41 #define RTWN_RIDX_OFDM54 11
42
43 #define RTWN_RIDX_HT_MCS_SHIFT 12
44 #define RTWN_RIDX_HT_MCS(i) (RTWN_RIDX_HT_MCS_SHIFT + (i))
45 #define RTWN_RIDX_TO_MCS(ridx) ((ridx) - RTWN_RIDX_HT_MCS_SHIFT)
46
47 /* HT supports up to MCS31, so goes from 12 -> 43 */
48
49 #define RTWN_RIDX_LEGACY_HT_COUNT 44
50
51 /*
52 * VHT supports MCS0..9 for up to 4 spatial streams, so
53 * goes from 44 -> 83.
54 */
55 #define RTWN_RIDX_VHT_MCS_SHIFT 44
56 #define RTWN_RIDX_VHT_MCS(s, i) (RTWN_RIDX_VHT_MCS_SHIFT + ((10*s) + i))
57
58 /*
59 * The total amount of rate indexes, CCK, OFDM, HT MCS0..31,
60 * VHT MCS0..9 for 1-4 streams.
61 */
62 #define RTWN_RIDX_COUNT 84
63
64 #define RTWN_RIDX_UNKNOWN (uint8_t)-1
65
66 #define RTWN_RATE_IS_CCK(rate) ((rate) <= RTWN_RIDX_CCK11)
67 #define RTWN_RATE_IS_OFDM(rate) \
68 ((rate) >= RTWN_RIDX_OFDM6 && (rate) <= RTWN_RIDX_OFDM54)
69 #define RTWN_RATE_IS_HT(rate) \
70 ((rate) >= RTWN_RIDX_HT_MCS_SHIFT && (rate) < RTWN_RIDX_VHT_MCS_SHIFT)
71 #define RTWN_RATE_IS_VHT(rate) \
72 ((rate) >= RTWN_RIDX_VHT_MCS_SHIFT && (rate) <= RTWN_RIDX_COUNT)
73
74 static const uint8_t ridx2rate[] =
75 { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
76
77 static __inline uint8_t
rate2ridx(uint8_t rate)78 rate2ridx(uint8_t rate)
79 {
80 if (rate & IEEE80211_RATE_MCS) {
81 return ((rate & 0xf) + RTWN_RIDX_HT_MCS_SHIFT);
82 }
83 switch (rate) {
84 /* 11g */
85 case 12: return 4;
86 case 18: return 5;
87 case 24: return 6;
88 case 36: return 7;
89 case 48: return 8;
90 case 72: return 9;
91 case 96: return 10;
92 case 108: return 11;
93 /* 11b */
94 case 2: return 0;
95 case 4: return 1;
96 case 11: return 2;
97 case 22: return 3;
98 default: return RTWN_RIDX_UNKNOWN;
99 }
100 }
101
102 /* XXX move to net80211 */
103 static __inline__ uint8_t
rtwn_ctl_mcsrate(const struct ieee80211_rate_table * rt,uint8_t ridx)104 rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx)
105 {
106 uint8_t cix, rate;
107
108 /* Check if we are using MCS rate. */
109 KASSERT(RTWN_RATE_IS_HT(ridx), ("bad mcs rate index %d", ridx));
110
111 rate = (ridx - RTWN_RIDX_HT_MCS(0)) | IEEE80211_RATE_MCS;
112 cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
113 KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx));
114 return rt->info[cix].dot11Rate;
115 }
116
117 #endif /* IF_RTWN_RIDX_H */
118