xref: /dflybsd-src/sys/netproto/802_11/ieee80211_phy.h (revision 4f655ef568316df0b575f05cebf37546415c0d24)
132176cfdSRui Paulo /*-
232176cfdSRui Paulo  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
332176cfdSRui Paulo  * All rights reserved.
432176cfdSRui Paulo  *
532176cfdSRui Paulo  * Redistribution and use in source and binary forms, with or without
632176cfdSRui Paulo  * modification, are permitted provided that the following conditions
732176cfdSRui Paulo  * are met:
832176cfdSRui Paulo  * 1. Redistributions of source code must retain the above copyright
932176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer.
1032176cfdSRui Paulo  * 2. Redistributions in binary form must reproduce the above copyright
1132176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer in the
1232176cfdSRui Paulo  *    documentation and/or other materials provided with the distribution.
1332176cfdSRui Paulo  *
1432176cfdSRui Paulo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1532176cfdSRui Paulo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1632176cfdSRui Paulo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1732176cfdSRui Paulo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1832176cfdSRui Paulo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1932176cfdSRui Paulo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2032176cfdSRui Paulo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2132176cfdSRui Paulo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2232176cfdSRui Paulo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2332176cfdSRui Paulo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2432176cfdSRui Paulo  *
25085ff963SMatthew Dillon  * $FreeBSD$
2632176cfdSRui Paulo  */
2732176cfdSRui Paulo 
2832176cfdSRui Paulo #ifndef _NET80211_IEEE80211_PHY_H_
2932176cfdSRui Paulo #define _NET80211_IEEE80211_PHY_H_
3032176cfdSRui Paulo 
3132176cfdSRui Paulo #ifdef _KERNEL
3232176cfdSRui Paulo /*
3332176cfdSRui Paulo  * IEEE 802.11 PHY-related definitions.
3432176cfdSRui Paulo  */
3532176cfdSRui Paulo 
3632176cfdSRui Paulo /*
3732176cfdSRui Paulo  * Contention window (slots).
3832176cfdSRui Paulo  */
3932176cfdSRui Paulo #define IEEE80211_CW_MAX	1023	/* aCWmax */
4032176cfdSRui Paulo #define IEEE80211_CW_MIN_0	31	/* DS/CCK aCWmin, ERP aCWmin(0) */
4132176cfdSRui Paulo #define IEEE80211_CW_MIN_1	15	/* OFDM aCWmin, ERP aCWmin(1) */
4232176cfdSRui Paulo 
4332176cfdSRui Paulo /*
4432176cfdSRui Paulo  * SIFS (microseconds).
4532176cfdSRui Paulo  */
4632176cfdSRui Paulo #define IEEE80211_DUR_SIFS	10	/* DS/CCK/ERP SIFS */
4732176cfdSRui Paulo #define IEEE80211_DUR_OFDM_SIFS	16	/* OFDM SIFS */
4832176cfdSRui Paulo 
4932176cfdSRui Paulo /*
5032176cfdSRui Paulo  * Slot time (microseconds).
5132176cfdSRui Paulo  */
5232176cfdSRui Paulo #define IEEE80211_DUR_SLOT	20	/* DS/CCK slottime, ERP long slottime */
5332176cfdSRui Paulo #define IEEE80211_DUR_SHSLOT	9	/* ERP short slottime */
5432176cfdSRui Paulo #define IEEE80211_DUR_OFDM_SLOT	9	/* OFDM slottime */
5532176cfdSRui Paulo 
56*4f655ef5SMatthew Dillon #define IEEE80211_GET_SLOTTIME(ic) \
57*4f655ef5SMatthew Dillon 	((ic->ic_flags & IEEE80211_F_SHSLOT) ? \
58*4f655ef5SMatthew Dillon 	    IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
59*4f655ef5SMatthew Dillon 
6032176cfdSRui Paulo /*
6132176cfdSRui Paulo  * DIFS (microseconds).
6232176cfdSRui Paulo  */
6332176cfdSRui Paulo #define IEEE80211_DUR_DIFS(sifs, slot)	((sifs) + 2 * (slot))
6432176cfdSRui Paulo 
6532176cfdSRui Paulo struct ieee80211_channel;
6632176cfdSRui Paulo 
67085ff963SMatthew Dillon #define	IEEE80211_RATE_TABLE_SIZE	128
68085ff963SMatthew Dillon 
6932176cfdSRui Paulo struct ieee80211_rate_table {
7032176cfdSRui Paulo 	int		rateCount;		/* NB: for proper padding */
7132176cfdSRui Paulo 	uint8_t		rateCodeToIndex[256];	/* back mapping */
7232176cfdSRui Paulo 	struct {
7332176cfdSRui Paulo 		uint8_t		phy;		/* CCK/OFDM/TURBO */
7432176cfdSRui Paulo 		uint32_t	rateKbps;	/* transfer rate in kbs */
7532176cfdSRui Paulo 		uint8_t		shortPreamble;	/* mask for enabling short
7632176cfdSRui Paulo 						 * preamble in CCK rate code */
7732176cfdSRui Paulo 		uint8_t		dot11Rate;	/* value for supported rates
7832176cfdSRui Paulo 						 * info element of MLME */
7932176cfdSRui Paulo 		uint8_t		ctlRateIndex;	/* index of next lower basic
8032176cfdSRui Paulo 						 * rate; used for dur. calcs */
8132176cfdSRui Paulo 		uint16_t	lpAckDuration;	/* long preamble ACK dur. */
8232176cfdSRui Paulo 		uint16_t	spAckDuration;	/* short preamble ACK dur. */
83085ff963SMatthew Dillon 	} info[IEEE80211_RATE_TABLE_SIZE];
8432176cfdSRui Paulo };
8532176cfdSRui Paulo 
8632176cfdSRui Paulo const struct ieee80211_rate_table *ieee80211_get_ratetable(
8732176cfdSRui Paulo 			struct ieee80211_channel *);
8832176cfdSRui Paulo 
8932176cfdSRui Paulo static __inline__ uint8_t
ieee80211_ack_rate(const struct ieee80211_rate_table * rt,uint8_t rate)9032176cfdSRui Paulo ieee80211_ack_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
9132176cfdSRui Paulo {
92085ff963SMatthew Dillon 	/*
93085ff963SMatthew Dillon 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
94085ff963SMatthew Dillon 	 * If the caller wishes to use it for a basic rate, they should
95085ff963SMatthew Dillon 	 * clear the high bit first.
96085ff963SMatthew Dillon 	 */
97085ff963SMatthew Dillon 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
98085ff963SMatthew Dillon 
99085ff963SMatthew Dillon 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
10032176cfdSRui Paulo 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
10132176cfdSRui Paulo 	return rt->info[cix].dot11Rate;
10232176cfdSRui Paulo }
10332176cfdSRui Paulo 
10432176cfdSRui Paulo static __inline__ uint8_t
ieee80211_ctl_rate(const struct ieee80211_rate_table * rt,uint8_t rate)10532176cfdSRui Paulo ieee80211_ctl_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
10632176cfdSRui Paulo {
107085ff963SMatthew Dillon 	/*
108085ff963SMatthew Dillon 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
109085ff963SMatthew Dillon 	 * If the caller wishes to use it for a basic rate, they should
110085ff963SMatthew Dillon 	 * clear the high bit first.
111085ff963SMatthew Dillon 	 */
112085ff963SMatthew Dillon 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
113085ff963SMatthew Dillon 
114085ff963SMatthew Dillon 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
11532176cfdSRui Paulo 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
11632176cfdSRui Paulo 	return rt->info[cix].dot11Rate;
11732176cfdSRui Paulo }
11832176cfdSRui Paulo 
11932176cfdSRui Paulo static __inline__ enum ieee80211_phytype
ieee80211_rate2phytype(const struct ieee80211_rate_table * rt,uint8_t rate)12032176cfdSRui Paulo ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate)
12132176cfdSRui Paulo {
122085ff963SMatthew Dillon 	/*
123085ff963SMatthew Dillon 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
124085ff963SMatthew Dillon 	 * If the caller wishes to use it for a basic rate, they should
125085ff963SMatthew Dillon 	 * clear the high bit first.
126085ff963SMatthew Dillon 	 */
127085ff963SMatthew Dillon 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
128085ff963SMatthew Dillon 
129085ff963SMatthew Dillon 	uint8_t rix = rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL];
13032176cfdSRui Paulo 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
13132176cfdSRui Paulo 	return rt->info[rix].phy;
13232176cfdSRui Paulo }
13332176cfdSRui Paulo 
13432176cfdSRui Paulo static __inline__ int
ieee80211_isratevalid(const struct ieee80211_rate_table * rt,uint8_t rate)13532176cfdSRui Paulo ieee80211_isratevalid(const struct ieee80211_rate_table *rt, uint8_t rate)
13632176cfdSRui Paulo {
137085ff963SMatthew Dillon 	/*
138085ff963SMatthew Dillon 	 * XXX Assert this is for a legacy rate; not for an MCS rate.
139085ff963SMatthew Dillon 	 * If the caller wishes to use it for a basic rate, they should
140085ff963SMatthew Dillon 	 * clear the high bit first.
141085ff963SMatthew Dillon 	 */
142085ff963SMatthew Dillon 	KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
143085ff963SMatthew Dillon 
14432176cfdSRui Paulo 	return rt->rateCodeToIndex[rate] != (uint8_t)-1;
14532176cfdSRui Paulo }
14632176cfdSRui Paulo 
14732176cfdSRui Paulo /*
14832176cfdSRui Paulo  * Calculate ACK field for
14932176cfdSRui Paulo  * o  non-fragment data frames
15032176cfdSRui Paulo  * o  management frames
15132176cfdSRui Paulo  * sent using rate, phy and short preamble setting.
15232176cfdSRui Paulo  */
15332176cfdSRui Paulo static __inline__ uint16_t
ieee80211_ack_duration(const struct ieee80211_rate_table * rt,uint8_t rate,int isShortPreamble)15432176cfdSRui Paulo ieee80211_ack_duration(const struct ieee80211_rate_table *rt,
15532176cfdSRui Paulo     uint8_t rate, int isShortPreamble)
15632176cfdSRui Paulo {
15732176cfdSRui Paulo 	uint8_t rix = rt->rateCodeToIndex[rate];
15832176cfdSRui Paulo 
15932176cfdSRui Paulo 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
16032176cfdSRui Paulo 	if (isShortPreamble) {
16132176cfdSRui Paulo 		KASSERT(rt->info[rix].spAckDuration != 0,
162085ff963SMatthew Dillon 			("shpreamble ack dur is not computed!\n"));
16332176cfdSRui Paulo 		return rt->info[rix].spAckDuration;
16432176cfdSRui Paulo 	} else {
16532176cfdSRui Paulo 		KASSERT(rt->info[rix].lpAckDuration != 0,
166085ff963SMatthew Dillon 			("lgpreamble ack dur is not computed!\n"));
16732176cfdSRui Paulo 		return rt->info[rix].lpAckDuration;
16832176cfdSRui Paulo 	}
16932176cfdSRui Paulo }
17032176cfdSRui Paulo 
1717115973eSMatthew Dillon static __inline__ uint8_t
ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table * rt,uint8_t rate)1727115973eSMatthew Dillon ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table *rt,
1737115973eSMatthew Dillon     uint8_t rate)
1747115973eSMatthew Dillon {
175085ff963SMatthew Dillon 
1767115973eSMatthew Dillon 	return (rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]);
1777115973eSMatthew Dillon }
1787115973eSMatthew Dillon 
17932176cfdSRui Paulo /*
18032176cfdSRui Paulo  * Compute the time to transmit a frame of length frameLen bytes
18132176cfdSRui Paulo  * using the specified 802.11 rate code, phy, and short preamble
18232176cfdSRui Paulo  * setting.
18332176cfdSRui Paulo  *
18432176cfdSRui Paulo  * NB: SIFS is included.
18532176cfdSRui Paulo  */
18632176cfdSRui Paulo uint16_t	ieee80211_compute_duration(const struct ieee80211_rate_table *,
18732176cfdSRui Paulo 			uint32_t frameLen, uint16_t rate, int isShortPreamble);
18832176cfdSRui Paulo /*
18932176cfdSRui Paulo  * Convert PLCP signal/rate field to 802.11 rate code (.5Mbits/s)
19032176cfdSRui Paulo  */
19132176cfdSRui Paulo uint8_t		ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype);
19232176cfdSRui Paulo /*
19332176cfdSRui Paulo  * Convert 802.11 rate code to PLCP signal.
19432176cfdSRui Paulo  */
19532176cfdSRui Paulo uint8_t		ieee80211_rate2plcp(int, enum ieee80211_phytype);
196085ff963SMatthew Dillon 
197*4f655ef5SMatthew Dillon /*
198*4f655ef5SMatthew Dillon  * 802.11n rate manipulation.
199*4f655ef5SMatthew Dillon  */
200*4f655ef5SMatthew Dillon 
201*4f655ef5SMatthew Dillon #define	IEEE80211_HT_RC_2_MCS(_rc)	((_rc) & 0x1f)
202*4f655ef5SMatthew Dillon #define	IEEE80211_HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
203*4f655ef5SMatthew Dillon #define	IEEE80211_IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
204*4f655ef5SMatthew Dillon 
205085ff963SMatthew Dillon uint32_t	ieee80211_compute_duration_ht(uint32_t frameLen,
206085ff963SMatthew Dillon 			uint16_t rate, int streams, int isht40,
207085ff963SMatthew Dillon 			int isShortGI);
208085ff963SMatthew Dillon 
20932176cfdSRui Paulo #endif	/* _KERNEL */
21032176cfdSRui Paulo #endif	/* !_NET80211_IEEE80211_PHY_H_ */
211