#ifndef _NET80211_IEEE80211_PHY_H_
#define _NET80211_IEEE80211_PHY_H_
#ifdef _KERNEL
#define IEEE80211_CW_MAX 1023
#define IEEE80211_CW_MIN_0 31
#define IEEE80211_CW_MIN_1 15
#define IEEE80211_DUR_SIFS 10
#define IEEE80211_DUR_OFDM_SIFS 16
#define IEEE80211_DUR_SLOT 20
#define IEEE80211_DUR_SHSLOT 9
#define IEEE80211_DUR_OFDM_SLOT 9
#define IEEE80211_GET_SLOTTIME(ic) \
((ic->ic_flags & IEEE80211_F_SHSLOT) ? \
IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
#define IEEE80211_VAP_GET_SLOTTIME(vap) \
((vap->iv_flags & IEEE80211_F_SHSLOT) ? \
IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
#define IEEE80211_DUR_DIFS(sifs, slot) ((sifs) + 2 * (slot))
struct ieee80211_channel;
#define IEEE80211_RATE_TABLE_SIZE 128
struct ieee80211_rate_table {
int rateCount;
uint8_t rateCodeToIndex[256];
struct {
uint8_t phy;
uint32_t rateKbps;
uint8_t shortPreamble;
uint8_t dot11Rate;
uint8_t ctlRateIndex;
uint16_t lpAckDuration;
uint16_t spAckDuration;
} info[IEEE80211_RATE_TABLE_SIZE];
};
const struct ieee80211_rate_table *ieee80211_get_ratetable(
struct ieee80211_channel *);
static __inline__ uint8_t
ieee80211_ack_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
{
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
return rt->info[cix].dot11Rate;
}
static __inline__ uint8_t
ieee80211_ctl_rate(const struct ieee80211_rate_table *rt, uint8_t rate)
{
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex;
KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate));
return rt->info[cix].dot11Rate;
}
static __inline__ enum ieee80211_phytype
ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate)
{
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
uint8_t rix = rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL];
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
return rt->info[rix].phy;
}
static __inline__ int
ieee80211_isratevalid(const struct ieee80211_rate_table *rt, uint8_t rate)
{
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate));
return rt->rateCodeToIndex[rate] != (uint8_t)-1;
}
static __inline__ uint16_t
ieee80211_ack_duration(const struct ieee80211_rate_table *rt,
uint8_t rate, int isShortPreamble)
{
uint8_t rix = rt->rateCodeToIndex[rate];
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
if (isShortPreamble) {
KASSERT(rt->info[rix].spAckDuration != 0,
("shpreamble ack dur is not computed!\n"));
return rt->info[rix].spAckDuration;
} else {
KASSERT(rt->info[rix].lpAckDuration != 0,
("lgpreamble ack dur is not computed!\n"));
return rt->info[rix].lpAckDuration;
}
}
static __inline__ uint8_t
ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table *rt,
uint8_t rate)
{
return (rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]);
}
uint16_t ieee80211_compute_duration(const struct ieee80211_rate_table *,
uint32_t frameLen, uint16_t rate, int isShortPreamble);
uint8_t ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype);
uint8_t ieee80211_rate2plcp(int, enum ieee80211_phytype);
#define IEEE80211_HT_RC_2_MCS(_rc) ((_rc) & 0x1f)
#define IEEE80211_HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
#define IEEE80211_IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
uint32_t ieee80211_compute_duration_ht(uint32_t frameLen,
uint16_t rate, int streams, int isht40,
int isShortGI);
enum net80211_sta_rx_bw;
uint16_t ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw,
uint8_t);
bool ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw,
uint8_t, uint8_t);
uint32_t ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw,
uint8_t, uint8_t, bool);
#endif
#endif