xref: /freebsd-src/sys/net80211/ieee80211_phy.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1b032f27cSSam Leffler /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro F. Giffuni  *
4b032f27cSSam Leffler  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
5b032f27cSSam Leffler  * All rights reserved.
6b032f27cSSam Leffler  *
7b032f27cSSam Leffler  * Redistribution and use in source and binary forms, with or without
8b032f27cSSam Leffler  * modification, are permitted provided that the following conditions
9b032f27cSSam Leffler  * are met:
10b032f27cSSam Leffler  * 1. Redistributions of source code must retain the above copyright
11b032f27cSSam Leffler  *    notice, this list of conditions and the following disclaimer.
12b032f27cSSam Leffler  * 2. Redistributions in binary form must reproduce the above copyright
13b032f27cSSam Leffler  *    notice, this list of conditions and the following disclaimer in the
14b032f27cSSam Leffler  *    documentation and/or other materials provided with the distribution.
15b032f27cSSam Leffler  *
16b032f27cSSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b032f27cSSam Leffler  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18b032f27cSSam Leffler  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19b032f27cSSam Leffler  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20b032f27cSSam Leffler  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21b032f27cSSam Leffler  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22b032f27cSSam Leffler  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23b032f27cSSam Leffler  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24b032f27cSSam Leffler  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25b032f27cSSam Leffler  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b032f27cSSam Leffler  */
27b032f27cSSam Leffler 
28b032f27cSSam Leffler #ifndef _NET80211_IEEE80211_PHY_H_
29b032f27cSSam Leffler #define _NET80211_IEEE80211_PHY_H_
30b032f27cSSam Leffler 
31b032f27cSSam Leffler #ifdef _KERNEL
32b032f27cSSam Leffler /*
33b032f27cSSam Leffler  * IEEE 802.11 PHY-related definitions.
34b032f27cSSam Leffler  */
35b032f27cSSam Leffler 
36b032f27cSSam Leffler /*
37b032f27cSSam Leffler  * Contention window (slots).
38b032f27cSSam Leffler  */
39b032f27cSSam Leffler #define IEEE80211_CW_MAX	1023	/* aCWmax */
40b032f27cSSam Leffler #define IEEE80211_CW_MIN_0	31	/* DS/CCK aCWmin, ERP aCWmin(0) */
41b032f27cSSam Leffler #define IEEE80211_CW_MIN_1	15	/* OFDM aCWmin, ERP aCWmin(1) */
42b032f27cSSam Leffler 
43b032f27cSSam Leffler /*
44b032f27cSSam Leffler  * SIFS (microseconds).
45b032f27cSSam Leffler  */
46b032f27cSSam Leffler #define IEEE80211_DUR_SIFS	10	/* DS/CCK/ERP SIFS */
47b032f27cSSam Leffler #define IEEE80211_DUR_OFDM_SIFS	16	/* OFDM SIFS */
48b032f27cSSam Leffler 
49b032f27cSSam Leffler /*
50b032f27cSSam Leffler  * Slot time (microseconds).
51b032f27cSSam Leffler  */
52b032f27cSSam Leffler #define IEEE80211_DUR_SLOT	20	/* DS/CCK slottime, ERP long slottime */
53b032f27cSSam Leffler #define IEEE80211_DUR_SHSLOT	9	/* ERP short slottime */
54b032f27cSSam Leffler #define IEEE80211_DUR_OFDM_SLOT	9	/* OFDM slottime */
55b032f27cSSam Leffler 
56d20ff6e6SAdrian Chadd /*
57d20ff6e6SAdrian Chadd  * For drivers that don't implement per-VAP slot time
58d20ff6e6SAdrian Chadd  * (ie, they rely on net80211 figuring out the union
59d20ff6e6SAdrian Chadd  * between VAPs to program a single radio) - return
60d20ff6e6SAdrian Chadd  * the current radio configured slot time.
61d20ff6e6SAdrian Chadd  */
62bdfff33fSAndriy Voskoboinyk #define IEEE80211_GET_SLOTTIME(ic) \
63bdfff33fSAndriy Voskoboinyk 	((ic->ic_flags & IEEE80211_F_SHSLOT) ? \
64bdfff33fSAndriy Voskoboinyk 	    IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
65bdfff33fSAndriy Voskoboinyk 
66b032f27cSSam Leffler /*
67d20ff6e6SAdrian Chadd  * For drivers that implement per-VAP slot time; look
68d20ff6e6SAdrian Chadd  * at the per-VAP flags to determine whether this VAP
69d20ff6e6SAdrian Chadd  * is in short or long slot time.
70d20ff6e6SAdrian Chadd  */
71d20ff6e6SAdrian Chadd #define IEEE80211_VAP_GET_SLOTTIME(vap) \
72d20ff6e6SAdrian Chadd 	((vap->iv_flags & IEEE80211_F_SHSLOT) ? \
73d20ff6e6SAdrian Chadd 	    IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
74d20ff6e6SAdrian Chadd 
75d20ff6e6SAdrian Chadd /*
76b032f27cSSam Leffler  * DIFS (microseconds).
77b032f27cSSam Leffler  */
78b032f27cSSam Leffler #define IEEE80211_DUR_DIFS(sifs, slot)	((sifs) + 2 * (slot))
79b032f27cSSam Leffler 
80b032f27cSSam Leffler struct ieee80211_channel;
81b032f27cSSam Leffler 
82f8bf74f2SAdrian Chadd #define	IEEE80211_RATE_TABLE_SIZE	128
83f8bf74f2SAdrian Chadd 
84b032f27cSSam Leffler struct ieee80211_rate_table {
85b032f27cSSam Leffler 	int		rateCount;		/* NB: for proper padding */
86b032f27cSSam Leffler 	uint8_t		rateCodeToIndex[256];	/* back mapping */
87b032f27cSSam Leffler 	struct {
88b032f27cSSam Leffler 		uint8_t		phy;		/* CCK/OFDM/TURBO */
89b032f27cSSam Leffler 		uint32_t	rateKbps;	/* transfer rate in kbs */
90b032f27cSSam Leffler 		uint8_t		shortPreamble;	/* mask for enabling short
91b032f27cSSam Leffler 						 * preamble in CCK rate code */
92b032f27cSSam Leffler 		uint8_t		dot11Rate;	/* value for supported rates
93b032f27cSSam Leffler 						 * info element of MLME */
94b032f27cSSam Leffler 		uint8_t		ctlRateIndex;	/* index of next lower basic
95b032f27cSSam Leffler 						 * rate; used for dur. calcs */
96b032f27cSSam Leffler 		uint16_t	lpAckDuration;	/* long preamble ACK dur. */
97b032f27cSSam Leffler 		uint16_t	spAckDuration;	/* short preamble ACK dur. */
98f8bf74f2SAdrian Chadd 	} info[IEEE80211_RATE_TABLE_SIZE];
99b032f27cSSam Leffler };
100b032f27cSSam Leffler 
101b032f27cSSam Leffler const struct ieee80211_rate_table *ieee80211_get_ratetable(
102b032f27cSSam Leffler 			struct ieee80211_channel *);
103b032f27cSSam Leffler 
104b032f27cSSam Leffler static __inline__ uint8_t
ieee80211_ack_rate(const struct ieee80211_rate_table * rt,uint8_t rate)105b032f27cSSam Leffler ieee80211_ack_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
106b032f27cSSam Leffler {
107f8bf74f2SAdrian Chadd 	/*
108f8bf74f2SAdrian Chadd 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
109f8bf74f2SAdrian Chadd 	 * If the caller wishes to use it for a basic rate, they should
110f8bf74f2SAdrian Chadd 	 * clear the high bit first.
111f8bf74f2SAdrian Chadd 	 */
112f8bf74f2SAdrian Chadd 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
113f8bf74f2SAdrian Chadd 
114f8bf74f2SAdrian Chadd 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
115b032f27cSSam Leffler 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
116b032f27cSSam Leffler 	return rt->info[cix].dot11Rate;
117b032f27cSSam Leffler }
118b032f27cSSam Leffler 
119b032f27cSSam Leffler static __inline__ uint8_t
ieee80211_ctl_rate(const struct ieee80211_rate_table * rt,uint8_t rate)120b032f27cSSam Leffler ieee80211_ctl_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
121b032f27cSSam Leffler {
122f8bf74f2SAdrian Chadd 	/*
123f8bf74f2SAdrian Chadd 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
124f8bf74f2SAdrian Chadd 	 * If the caller wishes to use it for a basic rate, they should
125f8bf74f2SAdrian Chadd 	 * clear the high bit first.
126f8bf74f2SAdrian Chadd 	 */
127f8bf74f2SAdrian Chadd 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
128f8bf74f2SAdrian Chadd 
129f8bf74f2SAdrian Chadd 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
130b032f27cSSam Leffler 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
131b032f27cSSam Leffler 	return rt->info[cix].dot11Rate;
132b032f27cSSam Leffler }
133b032f27cSSam Leffler 
134b032f27cSSam Leffler static __inline__ enum ieee80211_phytype
ieee80211_rate2phytype(const struct ieee80211_rate_table * rt,uint8_t rate)135b032f27cSSam Leffler ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate)
136b032f27cSSam Leffler {
137f8bf74f2SAdrian Chadd 	/*
138f8bf74f2SAdrian Chadd 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
139f8bf74f2SAdrian Chadd 	 * If the caller wishes to use it for a basic rate, they should
140f8bf74f2SAdrian Chadd 	 * clear the high bit first.
141f8bf74f2SAdrian Chadd 	 */
142f8bf74f2SAdrian Chadd 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
143f8bf74f2SAdrian Chadd 
144f8bf74f2SAdrian Chadd 	uint8_t rix = rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL];
145b032f27cSSam Leffler 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
146b032f27cSSam Leffler 	return rt->info[rix].phy;
147b032f27cSSam Leffler }
148b032f27cSSam Leffler 
149d0c57eceSSam Leffler static __inline__ int
ieee80211_isratevalid(const struct ieee80211_rate_table * rt,uint8_t rate)150d0c57eceSSam Leffler ieee80211_isratevalid(const struct ieee80211_rate_table *rt, uint8_t rate)
151d0c57eceSSam Leffler {
152f8bf74f2SAdrian Chadd 	/*
153f8bf74f2SAdrian Chadd 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
154f8bf74f2SAdrian Chadd 	 * If the caller wishes to use it for a basic rate, they should
155f8bf74f2SAdrian Chadd 	 * clear the high bit first.
156f8bf74f2SAdrian Chadd 	 */
157f8bf74f2SAdrian Chadd 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
158f8bf74f2SAdrian Chadd 
159d0c57eceSSam Leffler 	return rt->rateCodeToIndex[rate] != (uint8_t)-1;
160d0c57eceSSam Leffler }
161d0c57eceSSam Leffler 
162b032f27cSSam Leffler /*
163b032f27cSSam Leffler  * Calculate ACK field for
164b032f27cSSam Leffler  * o  non-fragment data frames
165b032f27cSSam Leffler  * o  management frames
166b032f27cSSam Leffler  * sent using rate, phy and short preamble setting.
167b032f27cSSam Leffler  */
168b032f27cSSam Leffler static __inline__ uint16_t
ieee80211_ack_duration(const struct ieee80211_rate_table * rt,uint8_t rate,int isShortPreamble)169b032f27cSSam Leffler ieee80211_ack_duration(const struct ieee80211_rate_table *rt,
170b032f27cSSam Leffler     uint8_t rate, int isShortPreamble)
171b032f27cSSam Leffler {
172b032f27cSSam Leffler 	uint8_t rix = rt->rateCodeToIndex[rate];
173b032f27cSSam Leffler 
174b032f27cSSam Leffler 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
175b032f27cSSam Leffler 	if (isShortPreamble) {
176b032f27cSSam Leffler 		KASSERT(rt->info[rix].spAckDuration != 0,
177b032f27cSSam Leffler 			("shpreamble ack dur is not computed!\n"));
178b032f27cSSam Leffler 		return rt->info[rix].spAckDuration;
179b032f27cSSam Leffler 	} else {
180b032f27cSSam Leffler 		KASSERT(rt->info[rix].lpAckDuration != 0,
181b032f27cSSam Leffler 			("lgpreamble ack dur is not computed!\n"));
182b032f27cSSam Leffler 		return rt->info[rix].lpAckDuration;
183b032f27cSSam Leffler 	}
184b032f27cSSam Leffler }
185b032f27cSSam Leffler 
186f8bf74f2SAdrian Chadd static __inline__ uint8_t
ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table * rt,uint8_t rate)187f8bf74f2SAdrian Chadd ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table *rt,
188f8bf74f2SAdrian Chadd     uint8_t rate)
189f8bf74f2SAdrian Chadd {
190f8bf74f2SAdrian Chadd 
191f8bf74f2SAdrian Chadd 	return (rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]);
192f8bf74f2SAdrian Chadd }
193f8bf74f2SAdrian Chadd 
194b032f27cSSam Leffler /*
195b032f27cSSam Leffler  * Compute the time to transmit a frame of length frameLen bytes
196b032f27cSSam Leffler  * using the specified 802.11 rate code, phy, and short preamble
197b032f27cSSam Leffler  * setting.
198b032f27cSSam Leffler  *
199b032f27cSSam Leffler  * NB: SIFS is included.
200b032f27cSSam Leffler  */
201b032f27cSSam Leffler uint16_t	ieee80211_compute_duration(const struct ieee80211_rate_table *,
202b032f27cSSam Leffler 			uint32_t frameLen, uint16_t rate, int isShortPreamble);
203b032f27cSSam Leffler /*
204b032f27cSSam Leffler  * Convert PLCP signal/rate field to 802.11 rate code (.5Mbits/s)
205b032f27cSSam Leffler  */
2068215d906SSam Leffler uint8_t		ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype);
207b032f27cSSam Leffler /*
208b032f27cSSam Leffler  * Convert 802.11 rate code to PLCP signal.
209b032f27cSSam Leffler  */
2108215d906SSam Leffler uint8_t		ieee80211_rate2plcp(int, enum ieee80211_phytype);
211f8bf74f2SAdrian Chadd 
21257f78a35SAdrian Chadd /*
21357f78a35SAdrian Chadd  * 802.11n rate manipulation.
21457f78a35SAdrian Chadd  */
21557f78a35SAdrian Chadd 
21657f78a35SAdrian Chadd #define	IEEE80211_HT_RC_2_MCS(_rc)	((_rc) & 0x1f)
21757f78a35SAdrian Chadd #define	IEEE80211_HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
21857f78a35SAdrian Chadd #define	IEEE80211_IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
21957f78a35SAdrian Chadd 
220f8bf74f2SAdrian Chadd uint32_t	ieee80211_compute_duration_ht(uint32_t frameLen,
221f8bf74f2SAdrian Chadd 			uint16_t rate, int streams, int isht40,
222f8bf74f2SAdrian Chadd 			int isShortGI);
223f8bf74f2SAdrian Chadd 
224b032f27cSSam Leffler #endif	/* _KERNEL */
225b032f27cSSam Leffler #endif	/* !_NET80211_IEEE80211_PHY_H_ */
226