1/* 2 3 Broadcom B43 wireless driver 4 IEEE 802.11n PHY data tables 5 6 Copyright (c) 2008 Michael Buesch <m@bues.ch> 7 Copyright (c) 2010 Rafa�� Mi��ecki <zajec5@gmail.com> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; see the file COPYING. If not, write to 21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 22 Boston, MA 02110-1301, USA. 23 24*/ 25 26#include <sys/cdefs.h>
| 1/* 2 3 Broadcom B43 wireless driver 4 IEEE 802.11n PHY data tables 5 6 Copyright (c) 2008 Michael Buesch <m@bues.ch> 7 Copyright (c) 2010 Rafa�� Mi��ecki <zajec5@gmail.com> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; see the file COPYING. If not, write to 21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 22 Boston, MA 02110-1301, USA. 23 24*/ 25 26#include <sys/cdefs.h>
|
32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/module.h> 38#include <sys/endian.h> 39#include <sys/errno.h> 40#include <sys/firmware.h> 41#include <sys/lock.h> 42#include <sys/mutex.h> 43#include <machine/bus.h> 44#include <machine/resource.h> 45#include <sys/bus.h> 46#include <sys/rman.h> 47#include <sys/socket.h> 48#include <sys/sockio.h> 49 50#include <net/ethernet.h> 51#include <net/if.h> 52#include <net/if_var.h> 53#include <net/if_arp.h> 54#include <net/if_dl.h> 55#include <net/if_llc.h> 56#include <net/if_media.h> 57#include <net/if_types.h> 58 59#include <dev/pci/pcivar.h> 60#include <dev/pci/pcireg.h> 61#include <dev/siba/siba_ids.h> 62#include <dev/siba/sibareg.h> 63#include <dev/siba/sibavar.h> 64 65#include <net80211/ieee80211_var.h> 66#include <net80211/ieee80211_radiotap.h> 67#include <net80211/ieee80211_regdomain.h> 68#include <net80211/ieee80211_phy.h> 69#include <net80211/ieee80211_ratectl.h> 70 71#include <dev/bwn/if_bwnreg.h> 72#include <dev/bwn/if_bwnvar.h> 73#include <dev/bwn/if_bwn_debug.h> 74#include <dev/bwn/if_bwn_util.h> 75#include <dev/bwn/if_bwn_phy_common.h> 76 77#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h> 78#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h> 79 80#define ppr_for_each_entry(ppr, i, entry) \ 81 for (i = 0, entry = &(ppr)->__all_rates[i]; \ 82 i < BWN_PPR_RATES_NUM; \ 83 i++, entry++) 84 85void bwn_ppr_clear(struct bwn_mac *mac, struct bwn_ppr *ppr) 86{ 87 memset(ppr, 0, sizeof(*ppr)); 88 89 /* Compile-time PPR check */ 90 CTASSERT(sizeof(struct bwn_ppr) == BWN_PPR_RATES_NUM * sizeof(uint8_t)); 91} 92 93void bwn_ppr_add(struct bwn_mac *mac, struct bwn_ppr *ppr, int diff) 94{ 95 int i; 96 uint8_t *rate; 97 98 ppr_for_each_entry(ppr, i, rate) { 99 *rate = bwn_clamp_val(*rate + diff, 0, 127); 100 } 101} 102 103void bwn_ppr_apply_max(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t max) 104{ 105 int i; 106 uint8_t *rate; 107 108 ppr_for_each_entry(ppr, i, rate) { 109 *rate = min(*rate, max); 110 } 111} 112 113void bwn_ppr_apply_min(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t min) 114{ 115 int i; 116 uint8_t *rate; 117 118 ppr_for_each_entry(ppr, i, rate) { 119 *rate = max(*rate, min); 120 } 121} 122 123uint8_t bwn_ppr_get_max(struct bwn_mac *mac, struct bwn_ppr *ppr) 124{ 125 uint8_t res = 0; 126 int i; 127 uint8_t *rate; 128 129 ppr_for_each_entry(ppr, i, rate) { 130 res = max(*rate, res); 131 } 132 133 return res; 134} 135 136bool bwn_ppr_load_max_from_sprom(struct bwn_mac *mac, struct bwn_ppr *ppr, 137 bwn_phy_band_t band) 138{ 139 struct bwn_softc *sc = mac->mac_sc; 140 struct siba_sprom_core_pwr_info core_pwr_info[4]; 141 struct bwn_ppr_rates *rates = &ppr->rates; 142 struct bwn_phy *phy = &mac->mac_phy; 143 uint8_t maxpwr, off; 144 uint32_t sprom_ofdm_po; 145 uint16_t sprom_mcs_po[8]; 146 uint8_t extra_cdd_po, extra_stbc_po; 147 int i; 148 149 for (i = 0; i < 4; i++) { 150 bzero(&core_pwr_info[i], sizeof(core_pwr_info[i])); 151 if (siba_sprom_get_core_power_info(sc->sc_dev, i, 152 &core_pwr_info[i]) != 0) { 153 BWN_ERRPRINTF(mac->mac_sc, 154 "%s: failed to get core_pwr_info for core %d\n", 155 __func__, 156 i); 157 } 158 } 159 160 switch (band) { 161 case BWN_PHY_BAND_2G: 162 maxpwr = min(core_pwr_info[0].maxpwr_2g, 163 core_pwr_info[1].maxpwr_2g); 164 sprom_ofdm_po = siba_sprom_get_ofdm2gpo(sc->sc_dev); 165 siba_sprom_get_mcs2gpo(sc->sc_dev, sprom_mcs_po); 166 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 0) & 0xf; 167 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 0) & 0xf; 168 break; 169 case BWN_PHY_BAND_5G_LO: 170 maxpwr = min(core_pwr_info[0].maxpwr_5gl, 171 core_pwr_info[1].maxpwr_5gl); 172 sprom_ofdm_po = siba_sprom_get_ofdm5glpo(sc->sc_dev); 173 siba_sprom_get_mcs5glpo(sc->sc_dev, sprom_mcs_po); 174 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 8) & 0xf; 175 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 8) & 0xf; 176 break; 177 case BWN_PHY_BAND_5G_MI: 178 maxpwr = min(core_pwr_info[0].maxpwr_5g, 179 core_pwr_info[1].maxpwr_5g); 180 sprom_ofdm_po = siba_sprom_get_ofdm5gpo(sc->sc_dev); 181 siba_sprom_get_mcs5gpo(sc->sc_dev, sprom_mcs_po); 182 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 4) & 0xf; 183 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 4) & 0xf; 184 break; 185 case BWN_PHY_BAND_5G_HI: 186 maxpwr = min(core_pwr_info[0].maxpwr_5gh, 187 core_pwr_info[1].maxpwr_5gh); 188 sprom_ofdm_po = siba_sprom_get_ofdm5ghpo(sc->sc_dev); 189 siba_sprom_get_mcs5ghpo(sc->sc_dev, sprom_mcs_po); 190 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 12) & 0xf; 191 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 12) & 0xf; 192 break; 193 default: 194 device_printf(mac->mac_sc->sc_dev, "%s: invalid band (%d)\n", 195 __func__, 196 band); 197 return false; 198 } 199 200 if (band == BWN_BAND_2G) { 201 for (i = 0; i < 4; i++) { 202 off = ((siba_sprom_get_cck2gpo(sc->sc_dev) >> (i * 4)) & 0xf) * 2; 203 rates->cck[i] = maxpwr - off; 204 } 205 } 206 207 /* OFDM */ 208 for (i = 0; i < 8; i++) { 209 off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2; 210 rates->ofdm[i] = maxpwr - off; 211 } 212 213 /* MCS 20 SISO */ 214 rates->mcs_20[0] = rates->ofdm[0]; 215 rates->mcs_20[1] = rates->ofdm[2]; 216 rates->mcs_20[2] = rates->ofdm[3]; 217 rates->mcs_20[3] = rates->ofdm[4]; 218 rates->mcs_20[4] = rates->ofdm[5]; 219 rates->mcs_20[5] = rates->ofdm[6]; 220 rates->mcs_20[6] = rates->ofdm[7]; 221 rates->mcs_20[7] = rates->ofdm[7]; 222 223 /* MCS 20 CDD */ 224 for (i = 0; i < 4; i++) { 225 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2; 226 rates->mcs_20_cdd[i] = maxpwr - off; 227 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 228 rates->mcs_20_cdd[i] -= extra_cdd_po; 229 } 230 for (i = 0; i < 4; i++) { 231 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2; 232 rates->mcs_20_cdd[4 + i] = maxpwr - off; 233 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 234 rates->mcs_20_cdd[4 + i] -= extra_cdd_po; 235 } 236 237 /* OFDM 20 CDD */ 238 rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0]; 239 rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0]; 240 rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1]; 241 rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2]; 242 rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3]; 243 rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4]; 244 rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5]; 245 rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6]; 246 247 /* MCS 20 STBC */ 248 for (i = 0; i < 4; i++) { 249 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2; 250 rates->mcs_20_stbc[i] = maxpwr - off; 251 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 252 rates->mcs_20_stbc[i] -= extra_stbc_po; 253 } 254 for (i = 0; i < 4; i++) { 255 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2; 256 rates->mcs_20_stbc[4 + i] = maxpwr - off; 257 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 258 rates->mcs_20_stbc[4 + i] -= extra_stbc_po; 259 } 260 261 /* MCS 20 SDM */ 262 for (i = 0; i < 4; i++) { 263 off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2; 264 rates->mcs_20_sdm[i] = maxpwr - off; 265 } 266 for (i = 0; i < 4; i++) { 267 off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2; 268 rates->mcs_20_sdm[4 + i] = maxpwr - off; 269 } 270 271 return true; 272}
| 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/module.h> 40#include <sys/endian.h> 41#include <sys/errno.h> 42#include <sys/firmware.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <machine/bus.h> 46#include <machine/resource.h> 47#include <sys/bus.h> 48#include <sys/rman.h> 49#include <sys/socket.h> 50#include <sys/sockio.h> 51 52#include <net/ethernet.h> 53#include <net/if.h> 54#include <net/if_var.h> 55#include <net/if_arp.h> 56#include <net/if_dl.h> 57#include <net/if_llc.h> 58#include <net/if_media.h> 59#include <net/if_types.h> 60 61#include <dev/pci/pcivar.h> 62#include <dev/pci/pcireg.h> 63#include <dev/siba/siba_ids.h> 64#include <dev/siba/sibareg.h> 65#include <dev/siba/sibavar.h> 66 67#include <net80211/ieee80211_var.h> 68#include <net80211/ieee80211_radiotap.h> 69#include <net80211/ieee80211_regdomain.h> 70#include <net80211/ieee80211_phy.h> 71#include <net80211/ieee80211_ratectl.h> 72 73#include <dev/bwn/if_bwnreg.h> 74#include <dev/bwn/if_bwnvar.h> 75#include <dev/bwn/if_bwn_debug.h> 76#include <dev/bwn/if_bwn_util.h> 77#include <dev/bwn/if_bwn_phy_common.h> 78 79#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h> 80#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h> 81 82#define ppr_for_each_entry(ppr, i, entry) \ 83 for (i = 0, entry = &(ppr)->__all_rates[i]; \ 84 i < BWN_PPR_RATES_NUM; \ 85 i++, entry++) 86 87void bwn_ppr_clear(struct bwn_mac *mac, struct bwn_ppr *ppr) 88{ 89 memset(ppr, 0, sizeof(*ppr)); 90 91 /* Compile-time PPR check */ 92 CTASSERT(sizeof(struct bwn_ppr) == BWN_PPR_RATES_NUM * sizeof(uint8_t)); 93} 94 95void bwn_ppr_add(struct bwn_mac *mac, struct bwn_ppr *ppr, int diff) 96{ 97 int i; 98 uint8_t *rate; 99 100 ppr_for_each_entry(ppr, i, rate) { 101 *rate = bwn_clamp_val(*rate + diff, 0, 127); 102 } 103} 104 105void bwn_ppr_apply_max(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t max) 106{ 107 int i; 108 uint8_t *rate; 109 110 ppr_for_each_entry(ppr, i, rate) { 111 *rate = min(*rate, max); 112 } 113} 114 115void bwn_ppr_apply_min(struct bwn_mac *mac, struct bwn_ppr *ppr, uint8_t min) 116{ 117 int i; 118 uint8_t *rate; 119 120 ppr_for_each_entry(ppr, i, rate) { 121 *rate = max(*rate, min); 122 } 123} 124 125uint8_t bwn_ppr_get_max(struct bwn_mac *mac, struct bwn_ppr *ppr) 126{ 127 uint8_t res = 0; 128 int i; 129 uint8_t *rate; 130 131 ppr_for_each_entry(ppr, i, rate) { 132 res = max(*rate, res); 133 } 134 135 return res; 136} 137 138bool bwn_ppr_load_max_from_sprom(struct bwn_mac *mac, struct bwn_ppr *ppr, 139 bwn_phy_band_t band) 140{ 141 struct bwn_softc *sc = mac->mac_sc; 142 struct siba_sprom_core_pwr_info core_pwr_info[4]; 143 struct bwn_ppr_rates *rates = &ppr->rates; 144 struct bwn_phy *phy = &mac->mac_phy; 145 uint8_t maxpwr, off; 146 uint32_t sprom_ofdm_po; 147 uint16_t sprom_mcs_po[8]; 148 uint8_t extra_cdd_po, extra_stbc_po; 149 int i; 150 151 for (i = 0; i < 4; i++) { 152 bzero(&core_pwr_info[i], sizeof(core_pwr_info[i])); 153 if (siba_sprom_get_core_power_info(sc->sc_dev, i, 154 &core_pwr_info[i]) != 0) { 155 BWN_ERRPRINTF(mac->mac_sc, 156 "%s: failed to get core_pwr_info for core %d\n", 157 __func__, 158 i); 159 } 160 } 161 162 switch (band) { 163 case BWN_PHY_BAND_2G: 164 maxpwr = min(core_pwr_info[0].maxpwr_2g, 165 core_pwr_info[1].maxpwr_2g); 166 sprom_ofdm_po = siba_sprom_get_ofdm2gpo(sc->sc_dev); 167 siba_sprom_get_mcs2gpo(sc->sc_dev, sprom_mcs_po); 168 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 0) & 0xf; 169 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 0) & 0xf; 170 break; 171 case BWN_PHY_BAND_5G_LO: 172 maxpwr = min(core_pwr_info[0].maxpwr_5gl, 173 core_pwr_info[1].maxpwr_5gl); 174 sprom_ofdm_po = siba_sprom_get_ofdm5glpo(sc->sc_dev); 175 siba_sprom_get_mcs5glpo(sc->sc_dev, sprom_mcs_po); 176 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 8) & 0xf; 177 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 8) & 0xf; 178 break; 179 case BWN_PHY_BAND_5G_MI: 180 maxpwr = min(core_pwr_info[0].maxpwr_5g, 181 core_pwr_info[1].maxpwr_5g); 182 sprom_ofdm_po = siba_sprom_get_ofdm5gpo(sc->sc_dev); 183 siba_sprom_get_mcs5gpo(sc->sc_dev, sprom_mcs_po); 184 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 4) & 0xf; 185 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 4) & 0xf; 186 break; 187 case BWN_PHY_BAND_5G_HI: 188 maxpwr = min(core_pwr_info[0].maxpwr_5gh, 189 core_pwr_info[1].maxpwr_5gh); 190 sprom_ofdm_po = siba_sprom_get_ofdm5ghpo(sc->sc_dev); 191 siba_sprom_get_mcs5ghpo(sc->sc_dev, sprom_mcs_po); 192 extra_cdd_po = (siba_sprom_get_cddpo(sc->sc_dev) >> 12) & 0xf; 193 extra_stbc_po = (siba_sprom_get_stbcpo(sc->sc_dev) >> 12) & 0xf; 194 break; 195 default: 196 device_printf(mac->mac_sc->sc_dev, "%s: invalid band (%d)\n", 197 __func__, 198 band); 199 return false; 200 } 201 202 if (band == BWN_BAND_2G) { 203 for (i = 0; i < 4; i++) { 204 off = ((siba_sprom_get_cck2gpo(sc->sc_dev) >> (i * 4)) & 0xf) * 2; 205 rates->cck[i] = maxpwr - off; 206 } 207 } 208 209 /* OFDM */ 210 for (i = 0; i < 8; i++) { 211 off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2; 212 rates->ofdm[i] = maxpwr - off; 213 } 214 215 /* MCS 20 SISO */ 216 rates->mcs_20[0] = rates->ofdm[0]; 217 rates->mcs_20[1] = rates->ofdm[2]; 218 rates->mcs_20[2] = rates->ofdm[3]; 219 rates->mcs_20[3] = rates->ofdm[4]; 220 rates->mcs_20[4] = rates->ofdm[5]; 221 rates->mcs_20[5] = rates->ofdm[6]; 222 rates->mcs_20[6] = rates->ofdm[7]; 223 rates->mcs_20[7] = rates->ofdm[7]; 224 225 /* MCS 20 CDD */ 226 for (i = 0; i < 4; i++) { 227 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2; 228 rates->mcs_20_cdd[i] = maxpwr - off; 229 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 230 rates->mcs_20_cdd[i] -= extra_cdd_po; 231 } 232 for (i = 0; i < 4; i++) { 233 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2; 234 rates->mcs_20_cdd[4 + i] = maxpwr - off; 235 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 236 rates->mcs_20_cdd[4 + i] -= extra_cdd_po; 237 } 238 239 /* OFDM 20 CDD */ 240 rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0]; 241 rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0]; 242 rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1]; 243 rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2]; 244 rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3]; 245 rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4]; 246 rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5]; 247 rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6]; 248 249 /* MCS 20 STBC */ 250 for (i = 0; i < 4; i++) { 251 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2; 252 rates->mcs_20_stbc[i] = maxpwr - off; 253 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 254 rates->mcs_20_stbc[i] -= extra_stbc_po; 255 } 256 for (i = 0; i < 4; i++) { 257 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2; 258 rates->mcs_20_stbc[4 + i] = maxpwr - off; 259 if (phy->type == BWN_PHYTYPE_N && phy->rev >= 3) 260 rates->mcs_20_stbc[4 + i] -= extra_stbc_po; 261 } 262 263 /* MCS 20 SDM */ 264 for (i = 0; i < 4; i++) { 265 off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2; 266 rates->mcs_20_sdm[i] = maxpwr - off; 267 } 268 for (i = 0; i < 4; i++) { 269 off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2; 270 rates->mcs_20_sdm[4 + i] = maxpwr - off; 271 } 272 273 return true; 274}
|