1 /*-
2  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD: head/sys/net80211/ieee80211_phy.h 193072 2009-05-29 23:39:16Z sam $
26  * $DragonFly$
27  */
28 
29 #ifndef _NET80211_IEEE80211_PHY_H_
30 #define _NET80211_IEEE80211_PHY_H_
31 
32 #ifdef _KERNEL
33 /*
34  * IEEE 802.11 PHY-related definitions.
35  */
36 
37 /*
38  * Contention window (slots).
39  */
40 #define IEEE80211_CW_MAX	1023	/* aCWmax */
41 #define IEEE80211_CW_MIN_0	31	/* DS/CCK aCWmin, ERP aCWmin(0) */
42 #define IEEE80211_CW_MIN_1	15	/* OFDM aCWmin, ERP aCWmin(1) */
43 
44 /*
45  * SIFS (microseconds).
46  */
47 #define IEEE80211_DUR_SIFS	10	/* DS/CCK/ERP SIFS */
48 #define IEEE80211_DUR_OFDM_SIFS	16	/* OFDM SIFS */
49 
50 /*
51  * Slot time (microseconds).
52  */
53 #define IEEE80211_DUR_SLOT	20	/* DS/CCK slottime, ERP long slottime */
54 #define IEEE80211_DUR_SHSLOT	9	/* ERP short slottime */
55 #define IEEE80211_DUR_OFDM_SLOT	9	/* OFDM slottime */
56 
57 /*
58  * DIFS (microseconds).
59  */
60 #define IEEE80211_DUR_DIFS(sifs, slot)	((sifs) + 2 * (slot))
61 
62 struct ieee80211_channel;
63 
64 struct ieee80211_rate_table {
65 	int		rateCount;		/* NB: for proper padding */
66 	uint8_t		rateCodeToIndex[256];	/* back mapping */
67 	struct {
68 		uint8_t		phy;		/* CCK/OFDM/TURBO */
69 		uint32_t	rateKbps;	/* transfer rate in kbs */
70 		uint8_t		shortPreamble;	/* mask for enabling short
71 						 * preamble in CCK rate code */
72 		uint8_t		dot11Rate;	/* value for supported rates
73 						 * info element of MLME */
74 		uint8_t		ctlRateIndex;	/* index of next lower basic
75 						 * rate; used for dur. calcs */
76 		uint16_t	lpAckDuration;	/* long preamble ACK dur. */
77 		uint16_t	spAckDuration;	/* short preamble ACK dur. */
78 	} info[32];
79 };
80 
81 const struct ieee80211_rate_table *ieee80211_get_ratetable(
82 			struct ieee80211_channel *);
83 
84 static __inline__ uint8_t
85 ieee80211_ack_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
86 {
87 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
88 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
89 	return rt->info[cix].dot11Rate;
90 }
91 
92 static __inline__ uint8_t
93 ieee80211_ctl_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
94 {
95 	uint8_t cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
96 	KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
97 	return rt->info[cix].dot11Rate;
98 }
99 
100 static __inline__ enum ieee80211_phytype
101 ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate)
102 {
103 	uint8_t rix = rt->rateCodeToIndex[rate];
104 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
105 	return rt->info[rix].phy;
106 }
107 
108 static __inline__ int
109 ieee80211_isratevalid(const struct ieee80211_rate_table *rt, uint8_t rate)
110 {
111 	return rt->rateCodeToIndex[rate] != (uint8_t)-1;
112 }
113 
114 /*
115  * Calculate ACK field for
116  * o  non-fragment data frames
117  * o  management frames
118  * sent using rate, phy and short preamble setting.
119  */
120 static __inline__ uint16_t
121 ieee80211_ack_duration(const struct ieee80211_rate_table *rt,
122     uint8_t rate, int isShortPreamble)
123 {
124 	uint8_t rix = rt->rateCodeToIndex[rate];
125 
126 	KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
127 	if (isShortPreamble) {
128 		KASSERT(rt->info[rix].spAckDuration != 0,
129 			("shpreamble ack dur is not computed!\n"));
130 		return rt->info[rix].spAckDuration;
131 	} else {
132 		KASSERT(rt->info[rix].lpAckDuration != 0,
133 			("lgpreamble ack dur is not computed!\n"));
134 		return rt->info[rix].lpAckDuration;
135 	}
136 }
137 
138 /*
139  * Compute the time to transmit a frame of length frameLen bytes
140  * using the specified 802.11 rate code, phy, and short preamble
141  * setting.
142  *
143  * NB: SIFS is included.
144  */
145 uint16_t	ieee80211_compute_duration(const struct ieee80211_rate_table *,
146 			uint32_t frameLen, uint16_t rate, int isShortPreamble);
147 /*
148  * Convert PLCP signal/rate field to 802.11 rate code (.5Mbits/s)
149  */
150 uint8_t		ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype);
151 /*
152  * Convert 802.11 rate code to PLCP signal.
153  */
154 uint8_t		ieee80211_rate2plcp(int, enum ieee80211_phytype);
155 #endif	/* _KERNEL */
156 #endif	/* !_NET80211_IEEE80211_PHY_H_ */
157