From cc11086634aba5c816a85dfad6f8659173a6021c Mon Sep 17 00:00:00 2001 From: adrian Date: Sat, 14 May 2016 23:38:21 +0000 Subject: [PATCH] [bwn] add new types, prepare for PHY-N; prepare for rev 5xx firmware. This is a big commit with a whole lot of little changes, all in preparation for PHY-N and rev 5xx firmware. * add in a write method that does an explicit flush * change the txpwr recalc type to return an enum, versus just an int. * add in PHY-N RX frame format bits, for decoding RX RSSI and such * add in the header space calculation for rev 5xx firmware. * add in a whole bunch of new types that the newer and 5g phy code needs. Notably, broadcom has a split 5GHz band concept - 5G-Low, 5G(-Mid) and 5G-High. I kept encountering this at my day job and wondered whether it was just some marketing thing. Nope, turns out it isn't; it's an actual PHY thing. * Add a "am I a siba bus device" method, that returns true. The aim is to convert all the siba/bhnd specific bits in if_bwn over to be wrapped in this check, so when landon does a BHND drive through he knows which bits need updating. Now, this the /complete/ set of changes for rev 5xx firmware. Notably, the TX descriptor handling isn't at all done yet and the format has changed. So don' try blindly flipping this on just yet! --- sys/dev/bwn/if_bwn_phy_g.h | 2 +- sys/dev/bwn/if_bwnvar.h | 183 +++++++++++++++++++++++++++++++++++-- 2 files changed, 177 insertions(+), 8 deletions(-) diff --git a/sys/dev/bwn/if_bwn_phy_g.h b/sys/dev/bwn/if_bwn_phy_g.h index 2de14e898d13..77c6fbba5d86 100644 --- a/sys/dev/bwn/if_bwn_phy_g.h +++ b/sys/dev/bwn/if_bwn_phy_g.h @@ -49,7 +49,7 @@ extern int bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan); extern uint32_t bwn_phy_g_get_default_chan(struct bwn_mac *mac); extern void bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna); extern int bwn_phy_g_im(struct bwn_mac *mac, int mode); -extern int bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi); +extern bwn_txpwr_result_t bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi); extern void bwn_phy_g_set_txpwr(struct bwn_mac *mac); extern void bwn_phy_g_task_15s(struct bwn_mac *mac); extern void bwn_phy_g_task_60s(struct bwn_mac *mac); diff --git a/sys/dev/bwn/if_bwnvar.h b/sys/dev/bwn/if_bwnvar.h index e3e58158f5df..6743af1f8175 100644 --- a/sys/dev/bwn/if_bwnvar.h +++ b/sys/dev/bwn/if_bwnvar.h @@ -58,9 +58,8 @@ struct bwn_mac; #define BWN_ISOLDFMT(mac) ((mac)->mac_fw.rev <= 351) #define BWN_TSSI2DBM(num, den) \ ((int32_t)((num < 0) ? num / den : (num + den / 2) / den)) -#define BWN_HDRSIZE(mac) \ - ((BWN_ISOLDFMT(mac)) ? (100 + sizeof(struct bwn_plcp6)) : \ - (104 + sizeof(struct bwn_plcp6))) +#define BWN_HDRSIZE(mac) bwn_tx_hdrsize(mac) + #define BWN_PIO_COOKIE(tq, tp) \ ((uint16_t)((((uint16_t)tq->tq_index + 1) << 12) | tp->tp_index)) #define BWN_DMA_COOKIE(dr, slot) \ @@ -69,8 +68,16 @@ struct bwn_mac; #define BWN_READ_4(mac, o) (siba_read_4(mac->mac_sc->sc_dev, o)) #define BWN_WRITE_2(mac, o, v) \ (siba_write_2(mac->mac_sc->sc_dev, o, v)) +#define BWN_WRITE_2_F(mac, o, v) do { \ + (BWN_WRITE_2(mac, o, v)); \ + BWN_READ_2(mac, o); \ +} while(0) +#define BWN_WRITE_SETMASK2(mac, offset, mask, set) \ + BWN_WRITE_2(mac, offset, (BWN_READ_2(mac, offset) & mask) | set) #define BWN_WRITE_4(mac, o, v) \ (siba_write_4(mac->mac_sc->sc_dev, o, v)) +#define BWN_WRITE_SETMASK4(mac, offset, mask, set) \ + BWN_WRITE_4(mac, offset, (BWN_READ_4(mac, offset) & mask) | set) #define BWN_PIO_TXQOFFSET(mac) \ ((siba_get_revid(mac->mac_sc->sc_dev) >= 11) ? 0x18 : 0) #define BWN_PIO_RXQOFFSET(mac) \ @@ -149,6 +156,26 @@ struct bwn_mac; #define BWN_DMA_WRITE(dr, offset, value) \ (BWN_WRITE_4(dr->dr_mac, dr->dr_base + offset, value)) + +typedef enum { + BWN_PHY_BAND_2G = 0, + BWN_PHY_BAND_5G_LO = 1, + BWN_PHY_BAND_5G_MI = 2, + BWN_PHY_BAND_5G_HI = 3 +} bwn_phy_band_t; + +typedef enum { + BWN_BAND_2G, + BWN_BAND_5G, +} bwn_band_t; + +typedef enum { + BWN_CHAN_TYPE_20, + BWN_CHAN_TYPE_20_HT, + BWN_CHAN_TYPE_40_HT_U, + BWN_CHAN_TYPE_40_HT_D, +} bwn_chan_type_t; + struct bwn_rate { uint16_t rateid; uint32_t flags; @@ -205,6 +232,11 @@ struct bwn_loctl { int8_t q; }; +typedef enum { + BWN_TXPWR_RES_NEED_ADJUST, + BWN_TXPWR_RES_DONE, +} bwn_txpwr_result_t; + struct bwn_lo_calib { struct bwn_bbatt bbatt; struct bwn_rfatt rfatt; @@ -227,7 +259,17 @@ struct bwn_rxhdr4 { int8_t power1; } __packed n; } __packed phy; - uint16_t phy_status2; + union { + struct { + int8_t power2; + uint8_t pad; + } __packed n; + struct { + uint8_t pad; + int8_t ht_power0; + } __packed ht; + uint16_t phy_status2; + } __packed ps2; uint16_t phy_status3; uint32_t mac_status; uint16_t mac_time; @@ -314,8 +356,6 @@ struct bwn_phy_g { #define BWN_IMMODE_NONWLAN 1 #define BWN_IMMODE_MANUAL 2 #define BWN_IMMODE_AUTO 3 -#define BWN_TXPWR_RES_NEED_ADJUST 0 -#define BWN_TXPWR_RES_DONE 1 #define BWN_PHYLP_TXPCTL_UNKNOWN 0 #define BWN_PHYLP_TXPCTL_OFF 1 @@ -396,6 +436,8 @@ struct bwn_b206x_rfinit_entry { uint8_t br_flags; }; +struct bwn_phy_n; + struct bwn_phy { uint8_t type; uint8_t rev; @@ -408,10 +450,17 @@ struct bwn_phy { struct bwn_phy_g phy_g; struct bwn_phy_lp phy_lp; + /* + * I'd like the newer PHY code to not hide in the top-level + * structs.. + */ + struct bwn_phy_n *phy_n; + uint16_t rf_manuf; uint16_t rf_ver; uint8_t rf_rev; int rf_on; + int phy_do_full_init; int txpower; int hwpctl; @@ -441,7 +490,7 @@ struct bwn_phy { uint32_t (*get_default_chan)(struct bwn_mac *); void (*set_antenna)(struct bwn_mac *, int); int (*set_im)(struct bwn_mac *, int); - int (*recalc_txpwr)(struct bwn_mac *, int); + bwn_txpwr_result_t (*recalc_txpwr)(struct bwn_mac *, int); void (*set_txpwr)(struct bwn_mac *); void (*task_15s)(struct bwn_mac *); void (*task_60s)(struct bwn_mac *); @@ -889,6 +938,23 @@ struct bwn_mac { TAILQ_ENTRY(bwn_mac) mac_list; }; +static inline int +bwn_tx_hdrsize(struct bwn_mac *mac) +{ + switch (mac->mac_fw.fw_hdr_format) { + case BWN_FW_HDR_598: + return (112 + (sizeof(struct bwn_plcp6))); + case BWN_FW_HDR_410: + return (104 + (sizeof(struct bwn_plcp6))); + case BWN_FW_HDR_351: + return (100 + (sizeof(struct bwn_plcp6))); + default: + printf("%s: unknown header format (%d)\n", __func__, + mac->mac_fw.fw_hdr_format); + return (112 + (sizeof(struct bwn_plcp6))); + } +} + /* * Driver-specific vap state. */ @@ -956,4 +1022,107 @@ struct bwn_softc { #define BWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) #define BWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) +static inline bwn_band_t +bwn_channel_band(struct bwn_mac *mac, struct ieee80211_channel *c) +{ + if (IEEE80211_IS_CHAN_5GHZ(c)) + return BWN_BAND_5G; + /* XXX check 2g, log error if not 2g or 5g? */ + return BWN_BAND_2G; +} + +static inline bwn_band_t +bwn_current_band(struct bwn_mac *mac) +{ + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) + return BWN_BAND_5G; + /* XXX check 2g, log error if not 2g or 5g? */ + return BWN_BAND_2G; +} + +static inline bool +bwn_is_40mhz(struct bwn_mac *mac) +{ + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + + return !! (IEEE80211_IS_CHAN_HT40(ic->ic_curchan)); +} + +static inline int +bwn_get_centre_freq(struct bwn_mac *mac) +{ + + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + /* XXX TODO: calculate correctly for HT40 mode */ + return ic->ic_curchan->ic_freq; +} + +static inline int +bwn_get_chan_centre_freq(struct bwn_mac *mac, struct ieee80211_channel *chan) +{ + + /* XXX TODO: calculate correctly for HT40 mode */ + return chan->ic_freq; +} + +static inline int +bwn_get_chan(struct bwn_mac *mac) +{ + + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + /* XXX TODO: calculate correctly for HT40 mode */ + return ic->ic_curchan->ic_ieee; +} + +static inline struct ieee80211_channel * +bwn_get_channel(struct bwn_mac *mac) +{ + + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + return ic->ic_curchan; +} + +static inline bool +bwn_is_chan_passive(struct bwn_mac *mac) +{ + + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + return !! IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan); +} + +static inline bwn_chan_type_t +bwn_get_chan_type(struct bwn_mac *mac, struct ieee80211_channel *c) +{ + struct ieee80211com *ic = &mac->mac_sc->sc_ic; + if (c == NULL) + c = ic->ic_curchan; + if (IEEE80211_IS_CHAN_HT40U(c)) + return BWN_CHAN_TYPE_40_HT_U; + else if (IEEE80211_IS_CHAN_HT40D(c)) + return BWN_CHAN_TYPE_40_HT_D; + else if (IEEE80211_IS_CHAN_HT20(c)) + return BWN_CHAN_TYPE_20_HT; + else + return BWN_CHAN_TYPE_20; +} + +static inline int +bwn_get_chan_power(struct bwn_mac *mac, struct ieee80211_channel *c) +{ + + /* return in dbm */ + return c->ic_maxpower / 2; +} + +/* + * For now there's no bhnd bus support. Places where it matters + * should call this routine so we can start logging things. + */ +static inline int +bwn_is_bus_siba(struct bwn_mac *mac) +{ + + return 1; +} #endif /* !_IF_BWNVAR_H */