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