1 /*- 2 * Copyright (c) 2002-2009 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 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: src/tools/tools/ath/athrd/athrd.c,v 1.2 2009/01/29 23:24:21 sam Exp $ 30 */ 31 #include "opt_ah.h" 32 33 #include "ah.h" 34 35 #include <netproto/802_11/_ieee80211.h> 36 #include <netproto/802_11/ieee80211_regdomain.h> 37 38 #include "ah_internal.h" 39 #include "ah_eeprom_v3.h" /* XXX */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <stdarg.h> 44 #include <string.h> 45 #include <unistd.h> 46 47 int ath_hal_debug = 0; 48 HAL_CTRY_CODE cc = CTRY_DEFAULT; 49 HAL_REG_DOMAIN rd = 169; /* FCC */ 50 HAL_BOOL Amode = 1; 51 HAL_BOOL Bmode = 1; 52 HAL_BOOL Gmode = 1; 53 HAL_BOOL HT20mode = 1; 54 HAL_BOOL HT40mode = 1; 55 HAL_BOOL turbo5Disable = AH_FALSE; 56 HAL_BOOL turbo2Disable = AH_FALSE; 57 58 u_int16_t _numCtls = 8; 59 u_int16_t _ctl[32] = 60 { 0x10, 0x13, 0x40, 0x30, 0x11, 0x31, 0x12, 0x32 }; 61 RD_EDGES_POWER _rdEdgesPower[NUM_EDGES*NUM_CTLS] = { 62 { 5180, 28, 0 }, /* 0x10 */ 63 { 5240, 60, 0 }, 64 { 5260, 36, 0 }, 65 { 5320, 27, 0 }, 66 { 5745, 36, 0 }, 67 { 5765, 36, 0 }, 68 { 5805, 36, 0 }, 69 { 5825, 36, 0 }, 70 71 { 5210, 28, 0 }, /* 0x13 */ 72 { 5250, 28, 0 }, 73 { 5290, 30, 0 }, 74 { 5760, 36, 0 }, 75 { 5800, 36, 0 }, 76 { 0, 0, 0 }, 77 { 0, 0, 0 }, 78 { 0, 0, 0 }, 79 80 { 5170, 60, 0 }, /* 0x40 */ 81 { 5230, 60, 0 }, 82 { 0, 0, 0 }, 83 { 0, 0, 0 }, 84 { 0, 0, 0 }, 85 { 0, 0, 0 }, 86 { 0, 0, 0 }, 87 { 0, 0, 0 }, 88 89 { 5180, 33, 0 }, /* 0x30 */ 90 { 5320, 33, 0 }, 91 { 5500, 34, 0 }, 92 { 5700, 34, 0 }, 93 { 5745, 35, 0 }, 94 { 5765, 35, 0 }, 95 { 5785, 35, 0 }, 96 { 5825, 35, 0 }, 97 98 { 2412, 36, 0 }, /* 0x11 */ 99 { 2417, 36, 0 }, 100 { 2422, 36, 0 }, 101 { 2432, 36, 0 }, 102 { 2442, 36, 0 }, 103 { 2457, 36, 0 }, 104 { 2467, 36, 0 }, 105 { 2472, 36, 0 }, 106 107 { 2412, 36, 0 }, /* 0x31 */ 108 { 2417, 36, 0 }, 109 { 2422, 36, 0 }, 110 { 2432, 36, 0 }, 111 { 2442, 36, 0 }, 112 { 2457, 36, 0 }, 113 { 2467, 36, 0 }, 114 { 2472, 36, 0 }, 115 116 { 2412, 36, 0 }, /* 0x12 */ 117 { 2417, 36, 0 }, 118 { 2422, 36, 0 }, 119 { 2432, 36, 0 }, 120 { 2442, 36, 0 }, 121 { 2457, 36, 0 }, 122 { 2467, 36, 0 }, 123 { 2472, 36, 0 }, 124 125 { 2412, 28, 0 }, /* 0x32 */ 126 { 2417, 28, 0 }, 127 { 2422, 28, 0 }, 128 { 2432, 28, 0 }, 129 { 2442, 28, 0 }, 130 { 2457, 28, 0 }, 131 { 2467, 28, 0 }, 132 { 2472, 28, 0 }, 133 }; 134 135 u_int16_t turbo2WMaxPower5 = 32; 136 u_int16_t turbo2WMaxPower2; 137 int8_t antennaGainMax[2] = { 0, 0 }; /* XXX */ 138 int eeversion = AR_EEPROM_VER3_1; 139 TRGT_POWER_ALL_MODES tpow = { 140 8, { 141 { 22, 24, 28, 32, 5180 }, 142 { 22, 24, 28, 32, 5200 }, 143 { 22, 24, 28, 32, 5320 }, 144 { 26, 30, 34, 34, 5500 }, 145 { 26, 30, 34, 34, 5700 }, 146 { 20, 30, 34, 36, 5745 }, 147 { 20, 30, 34, 36, 5825 }, 148 { 20, 30, 34, 36, 5850 }, 149 }, 150 2, { 151 { 23, 27, 31, 34, 2412 }, 152 { 23, 27, 31, 34, 2447 }, 153 }, 154 2, { 155 { 36, 36, 36, 36, 2412 }, 156 { 36, 36, 36, 36, 2484 }, 157 } 158 }; 159 #define numTargetPwr_11a tpow.numTargetPwr_11a 160 #define trgtPwr_11a tpow.trgtPwr_11a 161 #define numTargetPwr_11g tpow.numTargetPwr_11g 162 #define trgtPwr_11g tpow.trgtPwr_11g 163 #define numTargetPwr_11b tpow.numTargetPwr_11b 164 #define trgtPwr_11b tpow.trgtPwr_11b 165 166 static HAL_BOOL 167 getChannelEdges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high) 168 { 169 struct ath_hal_private *ahp = AH_PRIVATE(ah); 170 HAL_CAPABILITIES *pCap = &ahp->ah_caps; 171 172 if (flags & IEEE80211_CHAN_5GHZ) { 173 *low = pCap->halLow5GhzChan; 174 *high = pCap->halHigh5GhzChan; 175 return AH_TRUE; 176 } 177 if (flags & IEEE80211_CHAN_2GHZ) { 178 *low = pCap->halLow2GhzChan; 179 *high = pCap->halHigh2GhzChan; 180 return AH_TRUE; 181 } 182 return AH_FALSE; 183 } 184 185 static u_int 186 getWirelessModes(struct ath_hal *ah) 187 { 188 u_int mode = 0; 189 190 if (Amode) { 191 mode = HAL_MODE_11A; 192 if (!turbo5Disable) 193 mode |= HAL_MODE_TURBO; 194 } 195 if (Bmode) 196 mode |= HAL_MODE_11B; 197 if (Gmode) { 198 mode |= HAL_MODE_11G; 199 if (!turbo2Disable) 200 mode |= HAL_MODE_108G; 201 } 202 if (HT20mode) 203 mode |= HAL_MODE_11NG_HT20|HAL_MODE_11NA_HT20; 204 if (HT40mode) 205 mode |= HAL_MODE_11NG_HT40PLUS|HAL_MODE_11NA_HT40PLUS 206 | HAL_MODE_11NG_HT40MINUS|HAL_MODE_11NA_HT40MINUS 207 ; 208 return mode; 209 } 210 211 /* Enumerated Regulatory Domain Information 8 bit values indicate that 212 * the regdomain is really a pair of unitary regdomains. 12 bit values 213 * are the real unitary regdomains and are the only ones which have the 214 * frequency bitmasks and flags set. 215 */ 216 217 enum EnumRd { 218 /* 219 * The following regulatory domain definitions are 220 * found in the EEPROM. Each regulatory domain 221 * can operate in either a 5GHz or 2.4GHz wireless mode or 222 * both 5GHz and 2.4GHz wireless modes. 223 * In general, the value holds no special 224 * meaning and is used to decode into either specific 225 * 2.4GHz or 5GHz wireless mode for that particular 226 * regulatory domain. 227 */ 228 NO_ENUMRD = 0x00, 229 NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ 230 NULL1_ETSIB = 0x07, /* Israel */ 231 NULL1_ETSIC = 0x08, 232 FCC1_FCCA = 0x10, /* USA */ 233 FCC1_WORLD = 0x11, /* Hong Kong */ 234 FCC4_FCCA = 0x12, /* USA - Public Safety */ 235 236 FCC2_FCCA = 0x20, /* Canada */ 237 FCC2_WORLD = 0x21, /* Australia & HK */ 238 FCC2_ETSIC = 0x22, 239 FRANCE_RES = 0x31, /* Legacy France for OEM */ 240 FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ 241 FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ 242 243 ETSI1_WORLD = 0x37, 244 ETSI3_ETSIA = 0x32, /* France (optional) */ 245 ETSI2_WORLD = 0x35, /* Hungary & others */ 246 ETSI3_WORLD = 0x36, /* France & others */ 247 ETSI4_WORLD = 0x30, 248 ETSI4_ETSIC = 0x38, 249 ETSI5_WORLD = 0x39, 250 ETSI6_WORLD = 0x34, /* Bulgaria */ 251 ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ 252 253 MKK1_MKKA = 0x40, /* Japan (JP1) */ 254 MKK1_MKKB = 0x41, /* Japan (JP0) */ 255 APL4_WORLD = 0x42, /* Singapore */ 256 MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ 257 APL_RESERVED = 0x44, /* Reserved (Do not used) */ 258 APL2_WORLD = 0x45, /* Korea */ 259 APL2_APLC = 0x46, 260 APL3_WORLD = 0x47, 261 MKK1_FCCA = 0x48, /* Japan (JP1-1) */ 262 APL2_APLD = 0x49, /* Korea with 2.3G channels */ 263 MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ 264 MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ 265 MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ 266 267 APL3_FCCA = 0x50, 268 APL1_WORLD = 0x52, /* Latin America */ 269 APL1_FCCA = 0x53, 270 APL1_APLA = 0x54, 271 APL1_ETSIC = 0x55, 272 APL2_ETSIC = 0x56, /* Venezuela */ 273 APL5_WORLD = 0x58, /* Chile */ 274 APL6_WORLD = 0x5B, /* Singapore */ 275 APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ 276 APL8_WORLD = 0x5D, /* Malaysia 5GHz */ 277 APL9_WORLD = 0x5E, /* Korea 5GHz */ 278 279 /* 280 * World mode SKUs 281 */ 282 WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ 283 WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ 284 WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ 285 WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ 286 WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ 287 WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ 288 289 WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ 290 WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ 291 EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ 292 293 WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ 294 WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ 295 296 MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ 297 MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ 298 MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ 299 300 MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ 301 MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ 302 MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ 303 304 MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ 305 MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ 306 MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ 307 308 MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ 309 MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ 310 MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ 311 312 MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ 313 MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ 314 MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ 315 316 MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ 317 MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ 318 MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ 319 320 /* Following definitions are used only by s/w to map old 321 * Japan SKUs. 322 */ 323 MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ 324 MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ 325 MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ 326 MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ 327 MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ 328 MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ 329 MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ 330 MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ 331 332 /* 333 * Regulator domains ending in a number (e.g. APL1, 334 * MK1, ETSI4, etc) apply to 5GHz channel and power 335 * information. Regulator domains ending in a letter 336 * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and 337 * power information. 338 */ 339 APL1 = 0x0150, /* LAT & Asia */ 340 APL2 = 0x0250, /* LAT & Asia */ 341 APL3 = 0x0350, /* Taiwan */ 342 APL4 = 0x0450, /* Jordan */ 343 APL5 = 0x0550, /* Chile */ 344 APL6 = 0x0650, /* Singapore */ 345 APL8 = 0x0850, /* Malaysia */ 346 APL9 = 0x0950, /* Korea (South) ROC 3 */ 347 348 ETSI1 = 0x0130, /* Europe & others */ 349 ETSI2 = 0x0230, /* Europe & others */ 350 ETSI3 = 0x0330, /* Europe & others */ 351 ETSI4 = 0x0430, /* Europe & others */ 352 ETSI5 = 0x0530, /* Europe & others */ 353 ETSI6 = 0x0630, /* Europe & others */ 354 ETSIA = 0x0A30, /* France */ 355 ETSIB = 0x0B30, /* Israel */ 356 ETSIC = 0x0C30, /* Latin America */ 357 358 FCC1 = 0x0110, /* US & others */ 359 FCC2 = 0x0120, /* Canada, Australia & New Zealand */ 360 FCC3 = 0x0160, /* US w/new middle band & DFS */ 361 FCC4 = 0x0165, /* US Public Safety */ 362 FCCA = 0x0A10, 363 364 APLD = 0x0D50, /* South Korea */ 365 366 MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ 367 MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ 368 MKK3 = 0x0340, /* Japan (UNI-1 even) */ 369 MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ 370 MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ 371 MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ 372 MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ 373 MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ 374 MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ 375 MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ 376 MKKA = 0x0A40, /* Japan */ 377 MKKC = 0x0A50, 378 379 NULL1 = 0x0198, 380 WORLD = 0x0199, 381 DEBUG_REG_DMN = 0x01ff, 382 }; 383 #define DEF_REGDMN FCC1_FCCA 384 385 static struct { 386 const char *name; 387 HAL_REG_DOMAIN rd; 388 } domains[] = { 389 #define D(_x) { #_x, _x } 390 D(NO_ENUMRD), 391 D(NULL1_WORLD), /* For 11b-only countries (no 11a allowed) */ 392 D(NULL1_ETSIB), /* Israel */ 393 D(NULL1_ETSIC), 394 D(FCC1_FCCA), /* USA */ 395 D(FCC1_WORLD), /* Hong Kong */ 396 D(FCC4_FCCA), /* USA - Public Safety */ 397 398 D(FCC2_FCCA), /* Canada */ 399 D(FCC2_WORLD), /* Australia & HK */ 400 D(FCC2_ETSIC), 401 D(FRANCE_RES), /* Legacy France for OEM */ 402 D(FCC3_FCCA), 403 D(FCC3_WORLD), 404 405 D(ETSI1_WORLD), 406 D(ETSI3_ETSIA), /* France (optional) */ 407 D(ETSI2_WORLD), /* Hungary & others */ 408 D(ETSI3_WORLD), /* France & others */ 409 D(ETSI4_WORLD), 410 D(ETSI4_ETSIC), 411 D(ETSI5_WORLD), 412 D(ETSI6_WORLD), /* Bulgaria */ 413 D(ETSI_RESERVED), /* Reserved (Do not used) */ 414 415 D(MKK1_MKKA), /* Japan (JP1) */ 416 D(MKK1_MKKB), /* Japan (JP0) */ 417 D(APL4_WORLD), /* Singapore */ 418 D(MKK2_MKKA), /* Japan with 4.9G channels */ 419 D(APL_RESERVED), /* Reserved (Do not used) */ 420 D(APL2_WORLD), /* Korea */ 421 D(APL2_APLC), 422 D(APL3_WORLD), 423 D(MKK1_FCCA), /* Japan (JP1-1) */ 424 D(APL2_APLD), /* Korea with 2.3G channels */ 425 D(MKK1_MKKA1), /* Japan (JE1) */ 426 D(MKK1_MKKA2), /* Japan (JE2) */ 427 D(MKK1_MKKC), 428 429 D(APL3_FCCA), 430 D(APL1_WORLD), /* Latin America */ 431 D(APL1_FCCA), 432 D(APL1_APLA), 433 D(APL1_ETSIC), 434 D(APL2_ETSIC), /* Venezuela */ 435 D(APL5_WORLD), /* Chile */ 436 D(APL6_WORLD), /* Singapore */ 437 D(APL7_FCCA), /* Taiwan 5.47 Band */ 438 D(APL8_WORLD), /* Malaysia 5GHz */ 439 D(APL9_WORLD), /* Korea 5GHz */ 440 441 D(WOR0_WORLD), /* World0 (WO0 SKU) */ 442 D(WOR1_WORLD), /* World1 (WO1 SKU) */ 443 D(WOR2_WORLD), /* World2 (WO2 SKU) */ 444 D(WOR3_WORLD), /* World3 (WO3 SKU) */ 445 D(WOR4_WORLD), /* World4 (WO4 SKU) */ 446 D(WOR5_ETSIC), /* World5 (WO5 SKU) */ 447 448 D(WOR01_WORLD), /* World0-1 (WW0-1 SKU) */ 449 D(WOR02_WORLD), /* World0-2 (WW0-2 SKU) */ 450 D(EU1_WORLD), 451 452 D(WOR9_WORLD), /* World9 (WO9 SKU) */ 453 D(WORA_WORLD), /* WorldA (WOA SKU) */ 454 455 D(MKK3_MKKB), /* Japan UNI-1 even + MKKB */ 456 D(MKK3_MKKA2), /* Japan UNI-1 even + MKKA2 */ 457 D(MKK3_MKKC), /* Japan UNI-1 even + MKKC */ 458 459 D(MKK4_MKKB), /* Japan UNI-1 even + UNI-2 + MKKB */ 460 D(MKK4_MKKA2), /* Japan UNI-1 even + UNI-2 + MKKA2 */ 461 D(MKK4_MKKC), /* Japan UNI-1 even + UNI-2 + MKKC */ 462 463 D(MKK5_MKKB), /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ 464 D(MKK5_MKKA2), /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ 465 D(MKK5_MKKC), /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ 466 467 D(MKK6_MKKB), /* Japan UNI-1 even + UNI-1 odd MKKB */ 468 D(MKK6_MKKA2), /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ 469 D(MKK6_MKKC), /* Japan UNI-1 even + UNI-1 odd + MKKC */ 470 471 D(MKK7_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ 472 D(MKK7_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ 473 D(MKK7_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ 474 475 D(MKK8_MKKB), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ 476 D(MKK8_MKKA2), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ 477 D(MKK8_MKKC), /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ 478 479 D(MKK3_MKKA), /* Japan UNI-1 even + MKKA */ 480 D(MKK3_MKKA1), /* Japan UNI-1 even + MKKA1 */ 481 D(MKK3_FCCA), /* Japan UNI-1 even + FCCA */ 482 D(MKK4_MKKA), /* Japan UNI-1 even + UNI-2 + MKKA */ 483 D(MKK4_MKKA1), /* Japan UNI-1 even + UNI-2 + MKKA1 */ 484 D(MKK4_FCCA), /* Japan UNI-1 even + UNI-2 + FCCA */ 485 D(MKK9_MKKA), /* Japan UNI-1 even + 4.9GHz */ 486 D(MKK10_MKKA), /* Japan UNI-1 even + UNI-2 + 4.9GHz */ 487 488 D(APL1), /* LAT & Asia */ 489 D(APL2), /* LAT & Asia */ 490 D(APL3), /* Taiwan */ 491 D(APL4), /* Jordan */ 492 D(APL5), /* Chile */ 493 D(APL6), /* Singapore */ 494 D(APL8), /* Malaysia */ 495 D(APL9), /* Korea (South) ROC 3 */ 496 497 D(ETSI1), /* Europe & others */ 498 D(ETSI2), /* Europe & others */ 499 D(ETSI3), /* Europe & others */ 500 D(ETSI4), /* Europe & others */ 501 D(ETSI5), /* Europe & others */ 502 D(ETSI6), /* Europe & others */ 503 D(ETSIA), /* France */ 504 D(ETSIB), /* Israel */ 505 D(ETSIC), /* Latin America */ 506 507 D(FCC1), /* US & others */ 508 D(FCC2), 509 D(FCC3), /* US w/new middle band & DFS */ 510 D(FCC4), /* US Public Safety */ 511 D(FCCA), 512 513 D(APLD), /* South Korea */ 514 515 D(MKK1), /* Japan (UNI-1 odd)*/ 516 D(MKK2), /* Japan (4.9 GHz + UNI-1 odd) */ 517 D(MKK3), /* Japan (UNI-1 even) */ 518 D(MKK4), /* Japan (UNI-1 even + UNI-2) */ 519 D(MKK5), /* Japan (UNI-1 even + UNI-2 + mid-band) */ 520 D(MKK6), /* Japan (UNI-1 odd + UNI-1 even) */ 521 D(MKK7), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ 522 D(MKK8), /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ 523 D(MKK9), /* Japan (UNI-1 even + 4.9 GHZ) */ 524 D(MKK10), /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ 525 D(MKKA), /* Japan */ 526 D(MKKC), 527 528 D(NULL1), 529 D(WORLD), 530 D(DEBUG_REG_DMN), 531 #undef D 532 }; 533 534 static HAL_BOOL 535 rdlookup(const char *name, HAL_REG_DOMAIN *rd) 536 { 537 #define N(a) (sizeof(a)/sizeof(a[0])) 538 int i; 539 540 for (i = 0; i < N(domains); i++) 541 if (strcasecmp(domains[i].name, name) == 0) { 542 *rd = domains[i].rd; 543 return AH_TRUE; 544 } 545 return AH_FALSE; 546 #undef N 547 } 548 549 static const char * 550 getrdname(HAL_REG_DOMAIN rd) 551 { 552 #define N(a) (sizeof(a)/sizeof(a[0])) 553 int i; 554 555 for (i = 0; i < N(domains); i++) 556 if (domains[i].rd == rd) 557 return domains[i].name; 558 return NULL; 559 #undef N 560 } 561 562 static void 563 rdlist() 564 { 565 #define N(a) (sizeof(a)/sizeof(a[0])) 566 int i; 567 568 printf("\nRegulatory domains:\n\n"); 569 for (i = 0; i < N(domains); i++) 570 printf("%-15s%s", domains[i].name, 571 ((i+1)%5) == 0 ? "\n" : ""); 572 printf("\n"); 573 #undef N 574 } 575 576 typedef struct { 577 HAL_CTRY_CODE countryCode; 578 HAL_REG_DOMAIN regDmnEnum; 579 const char* isoName; 580 const char* name; 581 } COUNTRY_CODE_TO_ENUM_RD; 582 583 /* 584 * Country Code Table to Enumerated RD 585 */ 586 static COUNTRY_CODE_TO_ENUM_RD allCountries[] = { 587 {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG" }, 588 {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET" }, 589 {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA" }, 590 {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA" }, 591 {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA" }, 592 {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA" }, 593 {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA" }, 594 {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA" }, 595 {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN" }, 596 {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN" }, 597 {CTRY_BELARUS, NULL1_WORLD, "BY", "BELARUS" }, 598 {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM" }, 599 {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE" }, 600 {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA" }, 601 {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL" }, 602 {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD,"BN", "BRUNEI DARUSSALAM" }, 603 {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA" }, 604 {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA" }, 605 {CTRY_CHILE, APL6_WORLD, "CL", "CHILE" }, 606 {CTRY_CHINA, APL1_WORLD, "CN", "CHINA" }, 607 {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA" }, 608 {CTRY_COSTA_RICA, NULL1_WORLD, "CR", "COSTA RICA" }, 609 {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA" }, 610 {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS" }, 611 {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC" }, 612 {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK" }, 613 {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,"DO", "DOMINICAN REPUBLIC" }, 614 {CTRY_ECUADOR, NULL1_WORLD, "EC", "ECUADOR" }, 615 {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT" }, 616 {CTRY_EL_SALVADOR, NULL1_WORLD, "SV", "EL SALVADOR" }, 617 {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA" }, 618 {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND" }, 619 {CTRY_FRANCE, ETSI3_WORLD, "FR", "FRANCE" }, 620 {CTRY_FRANCE2, ETSI3_WORLD, "F2", "FRANCE_RES" }, 621 {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA" }, 622 {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY" }, 623 {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE" }, 624 {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA" }, 625 {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS" }, 626 {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG" }, 627 {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY" }, 628 {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND" }, 629 {CTRY_INDIA, APL6_WORLD, "IN", "INDIA" }, 630 {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA" }, 631 {CTRY_IRAN, APL1_WORLD, "IR", "IRAN" }, 632 {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND" }, 633 {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL" }, 634 {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY" }, 635 {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN" }, 636 {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1" }, 637 {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2" }, 638 {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3" }, 639 {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4" }, 640 {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5" }, 641 {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6" }, 642 643 {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7" }, 644 {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8" }, 645 {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9" }, 646 647 {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10" }, 648 {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11" }, 649 {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12" }, 650 651 {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13" }, 652 {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14" }, 653 {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15" }, 654 655 {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16" }, 656 {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17" }, 657 {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18" }, 658 659 {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19" }, 660 {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20" }, 661 {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21" }, 662 663 {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22" }, 664 {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23" }, 665 {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24" }, 666 667 {CTRY_JORDAN, APL4_WORLD, "JO", "JORDAN" }, 668 {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN" }, 669 {CTRY_KOREA_NORTH, APL2_WORLD, "KP", "NORTH KOREA" }, 670 {CTRY_KOREA_ROC, APL2_WORLD, "KR", "KOREA REPUBLIC" }, 671 {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2" }, 672 {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3" }, 673 {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT" }, 674 {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA" }, 675 {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON" }, 676 {CTRY_LIECHTENSTEIN,ETSI1_WORLD, "LI", "LIECHTENSTEIN" }, 677 {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA" }, 678 {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG" }, 679 {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU" }, 680 {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA" }, 681 {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA" }, 682 {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA" }, 683 {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO" }, 684 {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO" }, 685 {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO" }, 686 {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS" }, 687 {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND" }, 688 {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY" }, 689 {CTRY_OMAN, APL6_WORLD, "OM", "OMAN" }, 690 {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN" }, 691 {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA" }, 692 {CTRY_PERU, APL1_WORLD, "PE", "PERU" }, 693 {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES" }, 694 {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND" }, 695 {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL" }, 696 {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO" }, 697 {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR" }, 698 {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA" }, 699 {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA" }, 700 {CTRY_SAUDI_ARABIA,NULL1_WORLD, "SA", "SAUDI ARABIA" }, 701 {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE" }, 702 {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC" }, 703 {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA" }, 704 {CTRY_SOUTH_AFRICA,FCC3_WORLD, "ZA", "SOUTH AFRICA" }, 705 {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN" }, 706 {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN" }, 707 {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND" }, 708 {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA" }, 709 {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN" }, 710 {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND" }, 711 {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,"TT", "TRINIDAD & TOBAGO" }, 712 {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA" }, 713 {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY" }, 714 {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE" }, 715 {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES" }, 716 {CTRY_UNITED_KINGDOM, ETSI1_WORLD,"GB", "UNITED KINGDOM" }, 717 {CTRY_UNITED_STATES, FCC1_FCCA, "US", "UNITED STATES" }, 718 {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", "UNITED STATES (PUBLIC SAFETY)" }, 719 {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY" }, 720 {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN" }, 721 {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA" }, 722 {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM" }, 723 {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN" }, 724 {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE" } 725 }; 726 727 static HAL_BOOL 728 cclookup(const char *name, HAL_REG_DOMAIN *rd, HAL_CTRY_CODE *cc) 729 { 730 #define N(a) (sizeof(a)/sizeof(a[0])) 731 int i; 732 733 for (i = 0; i < N(allCountries); i++) 734 if (strcasecmp(allCountries[i].isoName, name) == 0 || 735 strcasecmp(allCountries[i].name, name) == 0) { 736 *rd = allCountries[i].regDmnEnum; 737 *cc = allCountries[i].countryCode; 738 return AH_TRUE; 739 } 740 return AH_FALSE; 741 #undef N 742 } 743 744 static const char * 745 getccname(HAL_CTRY_CODE cc) 746 { 747 #define N(a) (sizeof(a)/sizeof(a[0])) 748 int i; 749 750 for (i = 0; i < N(allCountries); i++) 751 if (allCountries[i].countryCode == cc) 752 return allCountries[i].name; 753 return NULL; 754 #undef N 755 } 756 757 static const char * 758 getccisoname(HAL_CTRY_CODE cc) 759 { 760 #define N(a) (sizeof(a)/sizeof(a[0])) 761 int i; 762 763 for (i = 0; i < N(allCountries); i++) 764 if (allCountries[i].countryCode == cc) 765 return allCountries[i].isoName; 766 return NULL; 767 #undef N 768 } 769 770 static void 771 cclist() 772 { 773 #define N(a) (sizeof(a)/sizeof(a[0])) 774 int i; 775 776 printf("\nCountry codes:\n"); 777 for (i = 0; i < N(allCountries); i++) 778 printf("%2s %-15.15s%s", 779 allCountries[i].isoName, 780 allCountries[i].name, 781 ((i+1)%4) == 0 ? "\n" : " "); 782 printf("\n"); 783 #undef N 784 } 785 786 static HAL_BOOL 787 setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, 788 int16_t tpcScaleReduction, int16_t powerLimit, 789 int16_t *pMinPower, int16_t *pMaxPower); 790 791 static void 792 calctxpower(struct ath_hal *ah, 793 int nchan, const struct ieee80211_channel *chans, 794 int16_t tpcScaleReduction, int16_t powerLimit, int16_t *txpow) 795 { 796 int16_t minpow; 797 int i; 798 799 for (i = 0; i < nchan; i++) 800 if (!setRateTable(ah, &chans[i], 801 tpcScaleReduction, powerLimit, &minpow, &txpow[i])) { 802 printf("unable to set rate table\n"); 803 exit(-1); 804 } 805 } 806 807 int n = 1; 808 const char *sep = ""; 809 int dopassive = 0; 810 int showchannels = 0; 811 int isdfs = 0; 812 int is4ms = 0; 813 814 static int 815 anychan(const struct ieee80211_channel *chans, int nc, int flag) 816 { 817 int i; 818 819 for (i = 0; i < nc; i++) 820 if ((chans[i].ic_flags & flag) != 0) 821 return 1; 822 return 0; 823 } 824 825 static __inline int 826 mapgsm(u_int freq, u_int flags) 827 { 828 freq *= 10; 829 if (flags & IEEE80211_CHAN_QUARTER) 830 freq += 5; 831 else if (flags & IEEE80211_CHAN_HALF) 832 freq += 10; 833 else 834 freq += 20; 835 return (freq - 24220) / 5; 836 } 837 838 static __inline int 839 mappsb(u_int freq, u_int flags) 840 { 841 return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; 842 } 843 844 /* 845 * Convert GHz frequency to IEEE channel number. 846 */ 847 int 848 ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) 849 { 850 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ 851 if (freq == 2484) 852 return 14; 853 if (freq < 2484) 854 return ((int)freq - 2407) / 5; 855 else 856 return 15 + ((freq - 2512) / 20); 857 } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */ 858 if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) 859 return mappsb(freq, flags); 860 else if ((flags & IEEE80211_CHAN_A) && (freq <= 5000)) 861 return (freq - 4000) / 5; 862 else 863 return (freq - 5000) / 5; 864 } else { /* either, guess */ 865 if (freq == 2484) 866 return 14; 867 if (freq < 2484) 868 return ((int)freq - 2407) / 5; 869 if (freq < 5000) { 870 if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) 871 return mappsb(freq, flags); 872 else if (freq > 4900) 873 return (freq - 4000) / 5; 874 else 875 return 15 + ((freq - 2512) / 20); 876 } 877 return (freq - 5000) / 5; 878 } 879 } 880 881 #define IEEE80211_IS_CHAN_4MS(_c) \ 882 (((_c)->ic_flags & IEEE80211_CHAN_4MSXMIT) != 0) 883 884 static void 885 dumpchannels(struct ath_hal *ah, int nc, 886 const struct ieee80211_channel *chans, int16_t *txpow) 887 { 888 int i; 889 890 for (i = 0; i < nc; i++) { 891 const struct ieee80211_channel *c = &chans[i]; 892 int type; 893 894 if (showchannels) 895 printf("%s%3d", sep, 896 ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags)); 897 else 898 printf("%s%u", sep, c->ic_freq); 899 if (IEEE80211_IS_CHAN_HALF(c)) 900 type = 'H'; 901 else if (IEEE80211_IS_CHAN_QUARTER(c)) 902 type = 'Q'; 903 else if (IEEE80211_IS_CHAN_TURBO(c)) 904 type = 'T'; 905 else if (IEEE80211_IS_CHAN_HT(c)) 906 type = 'N'; 907 else if (IEEE80211_IS_CHAN_A(c)) 908 type = 'A'; 909 else if (IEEE80211_IS_CHAN_108G(c)) 910 type = 'T'; 911 else if (IEEE80211_IS_CHAN_G(c)) 912 type = 'G'; 913 else 914 type = 'B'; 915 if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c)) 916 type = tolower(type); 917 if (isdfs && is4ms) 918 printf("%c%c%c %d.%d", type, 919 IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', 920 IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', 921 txpow[i]/2, (txpow[i]%2)*5); 922 else if (isdfs) 923 printf("%c%c %d.%d", type, 924 IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', 925 txpow[i]/2, (txpow[i]%2)*5); 926 else if (is4ms) 927 printf("%c%c %d.%d", type, 928 IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', 929 txpow[i]/2, (txpow[i]%2)*5); 930 else 931 printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5); 932 if ((n++ % (showchannels ? 7 : 6)) == 0) 933 sep = "\n"; 934 else 935 sep = " "; 936 } 937 } 938 939 static void 940 intersect(struct ieee80211_channel *dst, int16_t *dtxpow, int *nd, 941 const struct ieee80211_channel *src, int16_t *stxpow, int ns) 942 { 943 int i = 0, j, k, l; 944 while (i < *nd) { 945 for (j = 0; j < ns && dst[i].ic_freq != src[j].ic_freq; j++) 946 ; 947 if (j < ns && dtxpow[i] == stxpow[j]) { 948 for (k = i+1, l = i; k < *nd; k++, l++) 949 dst[l] = dst[k]; 950 (*nd)--; 951 } else 952 i++; 953 } 954 } 955 956 static void 957 usage(const char *progname) 958 { 959 printf("usage: %s [-acdefoilpr4ABGT] [-m opmode] [cc | rd]\n", progname); 960 exit(-1); 961 } 962 963 static HAL_BOOL 964 getChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) 965 { 966 } 967 968 static HAL_BOOL 969 eepromRead(struct ath_hal *ah, u_int off, u_int16_t *data) 970 { 971 /* emulate enough stuff to handle japan channel shift */ 972 switch (off) { 973 case AR_EEPROM_VERSION: 974 *data = eeversion; 975 return AH_TRUE; 976 case AR_EEPROM_REG_CAPABILITIES_OFFSET: 977 *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A; 978 return AH_TRUE; 979 case AR_EEPROM_REG_CAPABILITIES_OFFSET_PRE4_0: 980 *data = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0; 981 return AH_TRUE; 982 } 983 return AH_FALSE; 984 } 985 986 HAL_STATUS 987 getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 988 uint32_t capability, uint32_t *result) 989 { 990 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 991 992 switch (type) { 993 case HAL_CAP_REG_DMN: /* regulatory domain */ 994 *result = AH_PRIVATE(ah)->ah_currentRD; 995 return HAL_OK; 996 default: 997 return HAL_EINVAL; 998 } 999 } 1000 1001 #define HAL_MODE_HT20 \ 1002 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) 1003 #define HAL_MODE_HT40 \ 1004 (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ 1005 HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS) 1006 #define HAL_MODE_HT (HAL_MODE_HT20 | HAL_MODE_HT40) 1007 1008 int 1009 main(int argc, char *argv[]) 1010 { 1011 static const u_int16_t tpcScaleReductionTable[5] = 1012 { 0, 3, 6, 9, MAX_RATE_POWER }; 1013 struct ath_hal_private ahp; 1014 struct ieee80211_channel achans[IEEE80211_CHAN_MAX]; 1015 int16_t atxpow[IEEE80211_CHAN_MAX]; 1016 struct ieee80211_channel bchans[IEEE80211_CHAN_MAX]; 1017 int16_t btxpow[IEEE80211_CHAN_MAX]; 1018 struct ieee80211_channel gchans[IEEE80211_CHAN_MAX]; 1019 int16_t gtxpow[IEEE80211_CHAN_MAX]; 1020 struct ieee80211_channel tchans[IEEE80211_CHAN_MAX]; 1021 int16_t ttxpow[IEEE80211_CHAN_MAX]; 1022 struct ieee80211_channel tgchans[IEEE80211_CHAN_MAX]; 1023 int16_t tgtxpow[IEEE80211_CHAN_MAX]; 1024 struct ieee80211_channel nchans[IEEE80211_CHAN_MAX]; 1025 int16_t ntxpow[IEEE80211_CHAN_MAX]; 1026 int i, na, nb, ng, nt, ntg, nn; 1027 HAL_BOOL showall = AH_FALSE; 1028 HAL_BOOL extendedChanMode = AH_TRUE; 1029 int modes = 0; 1030 int16_t tpcReduction, powerLimit; 1031 int showdfs = 0; 1032 int show4ms = 0; 1033 1034 memset(&ahp, 0, sizeof(ahp)); 1035 ahp.ah_getChannelEdges = getChannelEdges; 1036 ahp.ah_getWirelessModes = getWirelessModes; 1037 ahp.ah_eepromRead = eepromRead; 1038 ahp.ah_getChipPowerLimits = getChipPowerLimits; 1039 ahp.ah_caps.halWirelessModes = HAL_MODE_ALL; 1040 ahp.ah_caps.halLow5GhzChan = 4920; 1041 ahp.ah_caps.halHigh5GhzChan = 6100; 1042 ahp.ah_caps.halLow2GhzChan = 2312; 1043 ahp.ah_caps.halHigh2GhzChan = 2732; 1044 ahp.ah_caps.halChanHalfRate = AH_TRUE; 1045 ahp.ah_caps.halChanQuarterRate = AH_TRUE; 1046 ahp.h.ah_getCapability = getCapability; 1047 ahp.ah_opmode = HAL_M_STA; 1048 1049 tpcReduction = tpcScaleReductionTable[0]; 1050 powerLimit = MAX_RATE_POWER; 1051 1052 while ((i = getopt(argc, argv, "acdeflm:pr4ABGhHNT")) != -1) 1053 switch (i) { 1054 case 'a': 1055 showall = AH_TRUE; 1056 break; 1057 case 'c': 1058 showchannels = AH_TRUE; 1059 break; 1060 case 'd': 1061 ath_hal_debug = HAL_DEBUG_ANY; 1062 break; 1063 case 'e': 1064 extendedChanMode = AH_FALSE; 1065 break; 1066 case 'f': 1067 showchannels = AH_FALSE; 1068 break; 1069 case 'l': 1070 cclist(); 1071 rdlist(); 1072 exit(0); 1073 case 'm': 1074 if (strncasecmp(optarg, "sta", 2) == 0) 1075 ahp.ah_opmode = HAL_M_STA; 1076 else if (strncasecmp(optarg, "ibss", 2) == 0) 1077 ahp.ah_opmode = HAL_M_IBSS; 1078 else if (strncasecmp(optarg, "adhoc", 2) == 0) 1079 ahp.ah_opmode = HAL_M_IBSS; 1080 else if (strncasecmp(optarg, "ap", 2) == 0) 1081 ahp.ah_opmode = HAL_M_HOSTAP; 1082 else if (strncasecmp(optarg, "hostap", 2) == 0) 1083 ahp.ah_opmode = HAL_M_HOSTAP; 1084 else if (strncasecmp(optarg, "monitor", 2) == 0) 1085 ahp.ah_opmode = HAL_M_MONITOR; 1086 else 1087 usage(argv[0]); 1088 break; 1089 case 'p': 1090 dopassive = 1; 1091 break; 1092 case 'A': 1093 modes |= HAL_MODE_11A; 1094 break; 1095 case 'B': 1096 modes |= HAL_MODE_11B; 1097 break; 1098 case 'G': 1099 modes |= HAL_MODE_11G; 1100 break; 1101 case 'h': 1102 modes |= HAL_MODE_HT20; 1103 break; 1104 case 'H': 1105 modes |= HAL_MODE_HT40; 1106 break; 1107 case 'N': 1108 modes |= HAL_MODE_HT; 1109 break; 1110 case 'T': 1111 modes |= HAL_MODE_TURBO | HAL_MODE_108G; 1112 break; 1113 case 'r': 1114 showdfs = 1; 1115 break; 1116 case '4': 1117 show4ms = 1; 1118 break; 1119 default: 1120 usage(argv[0]); 1121 } 1122 switch (argc - optind) { 1123 case 0: 1124 if (!cclookup("US", &rd, &cc)) { 1125 printf("%s: unknown country code\n", "US"); 1126 exit(-1); 1127 } 1128 break; 1129 case 1: /* cc/regdomain */ 1130 if (!cclookup(argv[optind], &rd, &cc)) { 1131 if (!rdlookup(argv[optind], &rd)) { 1132 const char* rdname; 1133 1134 rd = strtoul(argv[optind], NULL, 0); 1135 rdname = getrdname(rd); 1136 if (rdname == NULL) { 1137 printf("%s: unknown country/regulatory " 1138 "domain code\n", argv[optind]); 1139 exit(-1); 1140 } 1141 } 1142 cc = CTRY_DEFAULT; 1143 } 1144 break; 1145 default: /* regdomain cc */ 1146 if (!rdlookup(argv[optind], &rd)) { 1147 const char* rdname; 1148 1149 rd = strtoul(argv[optind], NULL, 0); 1150 rdname = getrdname(rd); 1151 if (rdname == NULL) { 1152 printf("%s: unknown country/regulatory " 1153 "domain code\n", argv[optind]); 1154 exit(-1); 1155 } 1156 } 1157 if (!cclookup(argv[optind+1], &rd, &cc)) 1158 cc = strtoul(argv[optind+1], NULL, 0); 1159 break; 1160 } 1161 if (cc != CTRY_DEFAULT) 1162 printf("\n%s (%s, 0x%x, %u) %s (0x%x, %u)\n", 1163 getccname(cc), getccisoname(cc), cc, cc, 1164 getrdname(rd), rd, rd); 1165 else 1166 printf("\n%s (0x%x, %u)\n", 1167 getrdname(rd), rd, rd); 1168 1169 if (modes == 0) { 1170 /* NB: no HAL_MODE_HT */ 1171 modes = HAL_MODE_11A | HAL_MODE_11B | 1172 HAL_MODE_11G | HAL_MODE_TURBO | HAL_MODE_108G; 1173 } 1174 na = nb = ng = nt = ntg = nn = 0; 1175 if (modes & HAL_MODE_11G) { 1176 ahp.ah_currentRD = rd; 1177 if (ath_hal_getchannels(&ahp.h, gchans, IEEE80211_CHAN_MAX, &ng, 1178 HAL_MODE_11G, cc, rd, extendedChanMode) == HAL_OK) { 1179 calctxpower(&ahp.h, ng, gchans, tpcReduction, powerLimit, gtxpow); 1180 if (showdfs) 1181 isdfs |= anychan(gchans, ng, IEEE80211_CHAN_DFS); 1182 if (show4ms) 1183 is4ms |= anychan(gchans, ng, IEEE80211_CHAN_4MSXMIT); 1184 } 1185 } 1186 if (modes & HAL_MODE_11B) { 1187 ahp.ah_currentRD = rd; 1188 if (ath_hal_getchannels(&ahp.h, bchans, IEEE80211_CHAN_MAX, &nb, 1189 HAL_MODE_11B, cc, rd, extendedChanMode) == HAL_OK) { 1190 calctxpower(&ahp.h, nb, bchans, tpcReduction, powerLimit, btxpow); 1191 if (showdfs) 1192 isdfs |= anychan(bchans, nb, IEEE80211_CHAN_DFS); 1193 if (show4ms) 1194 is4ms |= anychan(bchans, nb, IEEE80211_CHAN_4MSXMIT); 1195 } 1196 } 1197 if (modes & HAL_MODE_11A) { 1198 ahp.ah_currentRD = rd; 1199 if (ath_hal_getchannels(&ahp.h, achans, IEEE80211_CHAN_MAX, &na, 1200 HAL_MODE_11A, cc, rd, extendedChanMode) == HAL_OK) { 1201 calctxpower(&ahp.h, na, achans, tpcReduction, powerLimit, atxpow); 1202 if (showdfs) 1203 isdfs |= anychan(achans, na, IEEE80211_CHAN_DFS); 1204 if (show4ms) 1205 is4ms |= anychan(achans, na, IEEE80211_CHAN_4MSXMIT); 1206 } 1207 } 1208 if (modes & HAL_MODE_TURBO) { 1209 ahp.ah_currentRD = rd; 1210 if (ath_hal_getchannels(&ahp.h, tchans, IEEE80211_CHAN_MAX, &nt, 1211 HAL_MODE_TURBO, cc, rd, extendedChanMode) == HAL_OK) { 1212 calctxpower(&ahp.h, nt, tchans, tpcReduction, powerLimit, ttxpow); 1213 if (showdfs) 1214 isdfs |= anychan(tchans, nt, IEEE80211_CHAN_DFS); 1215 if (show4ms) 1216 is4ms |= anychan(tchans, nt, IEEE80211_CHAN_4MSXMIT); 1217 } 1218 } 1219 if (modes & HAL_MODE_108G) { 1220 ahp.ah_currentRD = rd; 1221 if (ath_hal_getchannels(&ahp.h, tgchans, IEEE80211_CHAN_MAX, &ntg, 1222 HAL_MODE_108G, cc, rd, extendedChanMode) == HAL_OK) { 1223 calctxpower(&ahp.h, ntg, tgchans, tpcReduction, powerLimit, tgtxpow); 1224 if (showdfs) 1225 isdfs |= anychan(tgchans, ntg, IEEE80211_CHAN_DFS); 1226 if (show4ms) 1227 is4ms |= anychan(tgchans, ntg, IEEE80211_CHAN_4MSXMIT); 1228 } 1229 } 1230 if (modes & HAL_MODE_HT) { 1231 ahp.ah_currentRD = rd; 1232 if (ath_hal_getchannels(&ahp.h, nchans, IEEE80211_CHAN_MAX, &nn, 1233 modes & HAL_MODE_HT, cc, rd, extendedChanMode) == HAL_OK) { 1234 calctxpower(&ahp.h, nn, nchans, tpcReduction, powerLimit, ntxpow); 1235 if (showdfs) 1236 isdfs |= anychan(nchans, nn, IEEE80211_CHAN_DFS); 1237 if (show4ms) 1238 is4ms |= anychan(nchans, nn, IEEE80211_CHAN_4MSXMIT); 1239 } 1240 } 1241 1242 if (!showall) { 1243 #define CHECKMODES(_modes, _m) ((_modes & (_m)) == (_m)) 1244 if (CHECKMODES(modes, HAL_MODE_11B|HAL_MODE_11G)) { 1245 /* b ^= g */ 1246 intersect(bchans, btxpow, &nb, gchans, gtxpow, ng); 1247 } 1248 if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_TURBO)) { 1249 /* t ^= a */ 1250 intersect(tchans, ttxpow, &nt, achans, atxpow, na); 1251 } 1252 if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_108G)) { 1253 /* tg ^= g */ 1254 intersect(tgchans, tgtxpow, &ntg, gchans, gtxpow, ng); 1255 } 1256 if (CHECKMODES(modes, HAL_MODE_11G|HAL_MODE_HT)) { 1257 /* g ^= n */ 1258 intersect(gchans, gtxpow, &ng, nchans, ntxpow, nn); 1259 } 1260 if (CHECKMODES(modes, HAL_MODE_11A|HAL_MODE_HT)) { 1261 /* a ^= n */ 1262 intersect(achans, atxpow, &na, nchans, ntxpow, nn); 1263 } 1264 #undef CHECKMODES 1265 } 1266 1267 if (modes & HAL_MODE_11G) 1268 dumpchannels(&ahp.h, ng, gchans, gtxpow); 1269 if (modes & HAL_MODE_11B) 1270 dumpchannels(&ahp.h, nb, bchans, btxpow); 1271 if (modes & HAL_MODE_11A) 1272 dumpchannels(&ahp.h, na, achans, atxpow); 1273 if (modes & HAL_MODE_108G) 1274 dumpchannels(&ahp.h, ntg, tgchans, tgtxpow); 1275 if (modes & HAL_MODE_TURBO) 1276 dumpchannels(&ahp.h, nt, tchans, ttxpow); 1277 if (modes & HAL_MODE_HT) 1278 dumpchannels(&ahp.h, nn, nchans, ntxpow); 1279 printf("\n"); 1280 return (0); 1281 } 1282 1283 /* 1284 * Search a list for a specified value v that is within 1285 * EEP_DELTA of the search values. Return the closest 1286 * values in the list above and below the desired value. 1287 * EEP_DELTA is a factional value; everything is scaled 1288 * so only integer arithmetic is used. 1289 * 1290 * NB: the input list is assumed to be sorted in ascending order 1291 */ 1292 static void 1293 ar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize, 1294 u_int16_t *vlo, u_int16_t *vhi) 1295 { 1296 u_int32_t target = v * EEP_SCALE; 1297 u_int16_t *ep = lp+listSize; 1298 1299 /* 1300 * Check first and last elements for out-of-bounds conditions. 1301 */ 1302 if (target < (u_int32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { 1303 *vlo = *vhi = lp[0]; 1304 return; 1305 } 1306 if (target > (u_int32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { 1307 *vlo = *vhi = ep[-1]; 1308 return; 1309 } 1310 1311 /* look for value being near or between 2 values in list */ 1312 for (; lp < ep; lp++) { 1313 /* 1314 * If value is close to the current value of the list 1315 * then target is not between values, it is one of the values 1316 */ 1317 if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) { 1318 *vlo = *vhi = lp[0]; 1319 return; 1320 } 1321 /* 1322 * Look for value being between current value and next value 1323 * if so return these 2 values 1324 */ 1325 if (target < (u_int32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { 1326 *vlo = lp[0]; 1327 *vhi = lp[1]; 1328 return; 1329 } 1330 } 1331 } 1332 1333 /* 1334 * Find the maximum conformance test limit for the given channel and CTL info 1335 */ 1336 static u_int16_t 1337 ar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower) 1338 { 1339 /* temp array for holding edge channels */ 1340 u_int16_t tempChannelList[NUM_EDGES]; 1341 u_int16_t clo, chi, twiceMaxEdgePower; 1342 int i, numEdges; 1343 1344 /* Get the edge power */ 1345 for (i = 0; i < NUM_EDGES; i++) { 1346 if (pRdEdgesPower[i].rdEdge == 0) 1347 break; 1348 tempChannelList[i] = pRdEdgesPower[i].rdEdge; 1349 } 1350 numEdges = i; 1351 1352 ar5212GetLowerUpperValues(channel, tempChannelList, 1353 numEdges, &clo, &chi); 1354 /* Get the index for the lower channel */ 1355 for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) 1356 ; 1357 /* Is lower channel ever outside the rdEdge? */ 1358 HALASSERT(i != numEdges); 1359 1360 if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { 1361 /* 1362 * If there's an exact channel match or an inband flag set 1363 * on the lower channel use the given rdEdgePower 1364 */ 1365 twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; 1366 HALASSERT(twiceMaxEdgePower > 0); 1367 } else 1368 twiceMaxEdgePower = MAX_RATE_POWER; 1369 return twiceMaxEdgePower; 1370 } 1371 1372 /* 1373 * Returns interpolated or the scaled up interpolated value 1374 */ 1375 static u_int16_t 1376 interpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, 1377 u_int16_t targetLeft, u_int16_t targetRight) 1378 { 1379 u_int16_t rv; 1380 int16_t lRatio; 1381 1382 /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ 1383 if ((targetLeft * targetRight) == 0) 1384 return 0; 1385 1386 if (srcRight != srcLeft) { 1387 /* 1388 * Note the ratio always need to be scaled, 1389 * since it will be a fraction. 1390 */ 1391 lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); 1392 if (lRatio < 0) { 1393 /* Return as Left target if value would be negative */ 1394 rv = targetLeft; 1395 } else if (lRatio > EEP_SCALE) { 1396 /* Return as Right target if Ratio is greater than 100% (SCALE) */ 1397 rv = targetRight; 1398 } else { 1399 rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * 1400 targetLeft) / EEP_SCALE; 1401 } 1402 } else { 1403 rv = targetLeft; 1404 } 1405 return rv; 1406 } 1407 1408 /* 1409 * Return the four rates of target power for the given target power table 1410 * channel, and number of channels 1411 */ 1412 static void 1413 ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan, 1414 TRGT_POWER_INFO *powInfo, 1415 u_int16_t numChannels, TRGT_POWER_INFO *pNewPower) 1416 { 1417 /* temp array for holding target power channels */ 1418 u_int16_t tempChannelList[NUM_TEST_FREQUENCIES]; 1419 u_int16_t clo, chi, ixlo, ixhi; 1420 int i; 1421 1422 /* Copy the target powers into the temp channel list */ 1423 for (i = 0; i < numChannels; i++) 1424 tempChannelList[i] = powInfo[i].testChannel; 1425 1426 ar5212GetLowerUpperValues(chan->ic_freq, tempChannelList, 1427 numChannels, &clo, &chi); 1428 1429 /* Get the indices for the channel */ 1430 ixlo = ixhi = 0; 1431 for (i = 0; i < numChannels; i++) { 1432 if (clo == tempChannelList[i]) { 1433 ixlo = i; 1434 } 1435 if (chi == tempChannelList[i]) { 1436 ixhi = i; 1437 break; 1438 } 1439 } 1440 1441 /* 1442 * Get the lower and upper channels, target powers, 1443 * and interpolate between them. 1444 */ 1445 pNewPower->twicePwr6_24 = interpolate(chan->ic_freq, clo, chi, 1446 powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); 1447 pNewPower->twicePwr36 = interpolate(chan->ic_freq, clo, chi, 1448 powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); 1449 pNewPower->twicePwr48 = interpolate(chan->ic_freq, clo, chi, 1450 powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); 1451 pNewPower->twicePwr54 = interpolate(chan->ic_freq, clo, chi, 1452 powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54); 1453 } 1454 1455 static RD_EDGES_POWER* 1456 findEdgePower(struct ath_hal *ah, u_int ctl) 1457 { 1458 int i; 1459 1460 for (i = 0; i < _numCtls; i++) 1461 if (_ctl[i] == ctl) 1462 return &_rdEdgesPower[i * NUM_EDGES]; 1463 return AH_NULL; 1464 } 1465 1466 /* 1467 * Sets the transmit power in the baseband for the given 1468 * operating channel and mode. 1469 */ 1470 static HAL_BOOL 1471 setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, 1472 int16_t tpcScaleReduction, int16_t powerLimit, 1473 int16_t *pMinPower, int16_t *pMaxPower) 1474 { 1475 u_int16_t ratesArray[16]; 1476 u_int16_t *rpow = ratesArray; 1477 u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck; 1478 int8_t twiceAntennaGain, twiceAntennaReduction; 1479 TRGT_POWER_INFO targetPowerOfdm, targetPowerCck; 1480 RD_EDGES_POWER *rep; 1481 int16_t scaledPower; 1482 u_int8_t cfgCtl; 1483 1484 twiceMaxRDPower = chan->ic_maxregpower * 2; 1485 *pMaxPower = -MAX_RATE_POWER; 1486 *pMinPower = MAX_RATE_POWER; 1487 1488 /* Get conformance test limit maximum for this channel */ 1489 cfgCtl = ath_hal_getctl(ah, chan); 1490 rep = findEdgePower(ah, cfgCtl); 1491 if (rep != AH_NULL) 1492 twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep); 1493 else 1494 twiceMaxEdgePower = MAX_RATE_POWER; 1495 1496 if (IEEE80211_IS_CHAN_G(chan)) { 1497 /* Check for a CCK CTL for 11G CCK powers */ 1498 cfgCtl = (cfgCtl & 0xFC) | 0x01; 1499 rep = findEdgePower(ah, cfgCtl); 1500 if (rep != AH_NULL) 1501 twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep); 1502 else 1503 twiceMaxEdgePowerCck = MAX_RATE_POWER; 1504 } else { 1505 /* Set the 11B cck edge power to the one found before */ 1506 twiceMaxEdgePowerCck = twiceMaxEdgePower; 1507 } 1508 1509 /* Get Antenna Gain reduction */ 1510 if (IEEE80211_IS_CHAN_5GHZ(chan)) { 1511 twiceAntennaGain = antennaGainMax[0]; 1512 } else { 1513 twiceAntennaGain = antennaGainMax[1]; 1514 } 1515 twiceAntennaReduction = 1516 ath_hal_getantennareduction(ah, chan, twiceAntennaGain); 1517 1518 if (IEEE80211_IS_CHAN_OFDM(chan)) { 1519 /* Get final OFDM target powers */ 1520 if (IEEE80211_IS_CHAN_G(chan)) { 1521 /* TODO - add Turbo 2.4 to this mode check */ 1522 ar5212GetTargetPowers(ah, chan, trgtPwr_11g, 1523 numTargetPwr_11g, &targetPowerOfdm); 1524 } else { 1525 ar5212GetTargetPowers(ah, chan, trgtPwr_11a, 1526 numTargetPwr_11a, &targetPowerOfdm); 1527 } 1528 1529 /* Get Maximum OFDM power */ 1530 /* Minimum of target and edge powers */ 1531 scaledPower = AH_MIN(twiceMaxEdgePower, 1532 twiceMaxRDPower - twiceAntennaReduction); 1533 1534 /* 1535 * If turbo is set, reduce power to keep power 1536 * consumption under 2 Watts. Note that we always do 1537 * this unless specially configured. Then we limit 1538 * power only for non-AP operation. 1539 */ 1540 if (IEEE80211_IS_CHAN_TURBO(chan) 1541 #ifdef AH_ENABLE_AP_SUPPORT 1542 && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP 1543 #endif 1544 ) { 1545 /* 1546 * If turbo is set, reduce power to keep power 1547 * consumption under 2 Watts 1548 */ 1549 if (eeversion >= AR_EEPROM_VER3_1) 1550 scaledPower = AH_MIN(scaledPower, 1551 turbo2WMaxPower5); 1552 /* 1553 * EEPROM version 4.0 added an additional 1554 * constraint on 2.4GHz channels. 1555 */ 1556 if (eeversion >= AR_EEPROM_VER4_0 && 1557 IEEE80211_IS_CHAN_2GHZ(chan)) 1558 scaledPower = AH_MIN(scaledPower, 1559 turbo2WMaxPower2); 1560 } 1561 /* Reduce power by max regulatory domain allowed restrictions */ 1562 scaledPower -= (tpcScaleReduction * 2); 1563 scaledPower = (scaledPower < 0) ? 0 : scaledPower; 1564 scaledPower = AH_MIN(scaledPower, powerLimit); 1565 1566 scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24); 1567 1568 /* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */ 1569 rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower; 1570 rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36); 1571 rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48); 1572 rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54); 1573 1574 #ifdef notyet 1575 if (eeversion >= AR_EEPROM_VER4_0) { 1576 /* Setup XR target power from EEPROM */ 1577 rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ? 1578 xrTargetPower2 : xrTargetPower5); 1579 } else { 1580 /* XR uses 6mb power */ 1581 rpow[15] = rpow[0]; 1582 } 1583 #else 1584 rpow[15] = rpow[0]; 1585 #endif 1586 1587 *pMinPower = rpow[7]; 1588 *pMaxPower = rpow[0]; 1589 1590 #if 0 1591 ahp->ah_ofdmTxPower = rpow[0]; 1592 #endif 1593 1594 HALDEBUG(ah, HAL_DEBUG_ANY, 1595 "%s: MaxRD: %d TurboMax: %d MaxCTL: %d " 1596 "TPC_Reduction %d\n", __func__, 1597 twiceMaxRDPower, turbo2WMaxPower5, 1598 twiceMaxEdgePower, tpcScaleReduction * 2); 1599 } 1600 1601 if (IEEE80211_IS_CHAN_CCK(chan)) { 1602 /* Get final CCK target powers */ 1603 ar5212GetTargetPowers(ah, chan, trgtPwr_11b, 1604 numTargetPwr_11b, &targetPowerCck); 1605 1606 /* Reduce power by max regulatory domain allowed restrictions */ 1607 scaledPower = AH_MIN(twiceMaxEdgePowerCck, 1608 twiceMaxRDPower - twiceAntennaReduction); 1609 1610 scaledPower -= (tpcScaleReduction * 2); 1611 scaledPower = (scaledPower < 0) ? 0 : scaledPower; 1612 scaledPower = AH_MIN(scaledPower, powerLimit); 1613 1614 rpow[8] = (scaledPower < 1) ? 1 : scaledPower; 1615 1616 /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */ 1617 rpow[8] = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24); 1618 rpow[9] = AH_MIN(scaledPower, targetPowerCck.twicePwr36); 1619 rpow[10] = rpow[9]; 1620 rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48); 1621 rpow[12] = rpow[11]; 1622 rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54); 1623 rpow[14] = rpow[13]; 1624 1625 /* Set min/max power based off OFDM values or initialization */ 1626 if (rpow[13] < *pMinPower) 1627 *pMinPower = rpow[13]; 1628 if (rpow[9] > *pMaxPower) 1629 *pMaxPower = rpow[9]; 1630 1631 } 1632 #if 0 1633 ahp->ah_tx6PowerInHalfDbm = *pMaxPower; 1634 #endif 1635 return AH_TRUE; 1636 } 1637 1638 void* 1639 ath_hal_malloc(size_t size) 1640 { 1641 return calloc(1, size); 1642 } 1643 1644 void 1645 ath_hal_free(void* p) 1646 { 1647 return free(p); 1648 } 1649 1650 void 1651 ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap) 1652 { 1653 vprintf(fmt, ap); 1654 } 1655 1656 void 1657 ath_hal_printf(struct ath_hal *ah, const char* fmt, ...) 1658 { 1659 va_list ap; 1660 va_start(ap, fmt); 1661 ath_hal_vprintf(ah, fmt, ap); 1662 va_end(ap); 1663 } 1664 1665 void 1666 HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) 1667 { 1668 if (ath_hal_debug & mask) { 1669 __va_list ap; 1670 va_start(ap, fmt); 1671 ath_hal_vprintf(ah, fmt, ap); 1672 va_end(ap); 1673 } 1674 } 1675