1 2 /* 3 * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. 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 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <sys/types.h> 34 #include <err.h> 35 36 typedef enum { 37 AH_FALSE = 0, /* NB: lots of code assumes false is zero */ 38 AH_TRUE = 1, 39 } HAL_BOOL; 40 41 typedef enum { 42 HAL_OK = 0, /* No error */ 43 } HAL_STATUS; 44 45 struct ath_hal; 46 47 #include "ah_eeprom_v14.h" 48 49 void 50 load_eeprom_dump(const char *file, uint16_t *buf) 51 { 52 unsigned int r[8]; 53 FILE *fp; 54 char b[1024]; 55 int i; 56 57 fp = fopen(file, "r"); 58 if (!fp) 59 err(1, "fopen"); 60 61 while (!feof(fp)) { 62 if (fgets(b, 1024, fp) == NULL) 63 break; 64 if (feof(fp)) 65 break; 66 if (strlen(b) > 0) 67 b[strlen(b)-1] = '\0'; 68 if (strlen(b) == 0) 69 break; 70 sscanf(b, "%x: %x %x %x %x %x %x %x %x\n", 71 &i, &r[0], &r[1], &r[2], &r[3], &r[4], 72 &r[5], &r[6], &r[7]); 73 buf[i++] = r[0]; 74 buf[i++] = r[1]; 75 buf[i++] = r[2]; 76 buf[i++] = r[3]; 77 buf[i++] = r[4]; 78 buf[i++] = r[5]; 79 buf[i++] = r[6]; 80 buf[i++] = r[7]; 81 } 82 fclose(fp); 83 } 84 85 static void 86 eeprom_v14_base_print(uint16_t *buf) 87 { 88 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 89 BASE_EEP_HEADER *eh = &eep->ee_base.baseEepHeader; 90 int i; 91 92 printf("| Version: 0x%.4x | Length: 0x%.4x | Checksum: 0x%.4x ", 93 eh->version, eh->length, eh->checksum); 94 printf("| CapFlags: 0x%.2x\n", eh->opCapFlags); 95 96 printf("| eepMisc: 0x%.2x | RegDomain: 0x%.4x 0x%.4x | \n", 97 eh->eepMisc, eh->regDmn[0], eh->regDmn[1]); 98 printf("| MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", 99 eh->macAddr[0], eh->macAddr[1], eh->macAddr[2], 100 eh->macAddr[3], eh->macAddr[4], eh->macAddr[5]); 101 printf("| RxMask: 0x%.2x | TxMask: 0x%.2x | RfSilent: 0x%.4x | btOptions: 0x%.4x |\n", 102 eh->rxMask, eh->txMask, eh->rfSilent, eh->blueToothOptions); 103 printf("| DeviceCap: 0x%.4x | binBuildNumber: %.8x | deviceType: 0x%.2x |\n", 104 eh->deviceCap, eh->binBuildNumber, eh->deviceType); 105 106 printf("| pwdclkind: 0x%.2x | fastClk5g: 0x%.2x | divChain: 0x%.2x | rxGainType: 0x%.2x |\n", 107 (int) eh->pwdclkind, (int) eh->fastClk5g, (int) eh->divChain, 108 (int) eh->rxGainType); 109 110 printf("| dacHiPwrMode_5G: 0x%.2x | openLoopPwrCntl: 0x%.2x | dacLpMode: 0x%.2x\n", 111 (int) eh->dacHiPwrMode_5G, (int) eh->openLoopPwrCntl, (int) eh->dacLpMode); 112 printf("| txGainType: 0x%.2x | rcChainMask: 0x%.2x |\n", 113 (int) eh->txGainType, (int) eh->rcChainMask); 114 115 printf("| desiredScaleCCK: 0x%.2x | pwr_table_offset: 0x%.2x | frac_n_5g: %.2x\n", 116 (int) eh->desiredScaleCCK, (int) eh->pwr_table_offset, (int) eh->frac_n_5g); 117 118 /* because it's convienent */ 119 printf("| antennaGainMax[0]: 0x%.2x antennaGainMax[1]: 0x%.2x |\n", 120 eep->ee_antennaGainMax[0], eep->ee_antennaGainMax[1]); 121 122 printf(" | futureBase:"); 123 for (i = 0; i < sizeof(eh->futureBase) / sizeof(uint8_t); i++) 124 printf(" %.2x", (int) eh->futureBase[i]); 125 printf("\n"); 126 } 127 128 static void 129 eeprom_v14_custdata_print(uint16_t *buf) 130 { 131 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 132 uint8_t *custdata = (uint8_t *) &eep->ee_base.custData; 133 int i; 134 135 printf("\n| Custdata: |\n"); 136 for (i = 0; i < 64; i++) { 137 printf("%s0x%.2x %s", 138 i % 16 == 0 ? "| " : "", 139 custdata[i], 140 i % 16 == 15 ? "|\n" : ""); 141 } 142 } 143 144 static void 145 eeprom_v14_modal_print(uint16_t *buf, int m) 146 { 147 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 148 MODAL_EEP_HEADER *mh = &eep->ee_base.modalHeader[m]; 149 int i; 150 151 printf("| antCtrlCommon: 0x%.8x |\n", mh->antCtrlCommon); 152 printf("| switchSettling: 0x%.2x |\n", mh->switchSettling); 153 printf("| adcDesiredSize: %d |\n| pgaDesiredSize: %.2f dBm |\n", 154 mh->adcDesiredSize, (float) mh->pgaDesiredSize / 2.0); 155 156 printf("| antCtrlChain: 0:0x%.8x 1:0x%.8x 2:0x%.8x |\n", 157 mh->antCtrlChain[0], mh->antCtrlChain[1], mh->antCtrlChain[2]); 158 printf("| antennaGainCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 159 mh->antennaGainCh[0], mh->antennaGainCh[1], mh->antennaGainCh[2]); 160 printf("| txRxAttenCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 161 mh->txRxAttenCh[0], mh->txRxAttenCh[1], mh->txRxAttenCh[2]); 162 printf("| rxTxMarginCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 163 mh->rxTxMarginCh[0], mh->rxTxMarginCh[1], mh->rxTxMarginCh[2]); 164 printf("| noiseFloorThresCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 165 mh->noiseFloorThreshCh[0], mh->noiseFloorThreshCh[1], mh->noiseFloorThreshCh[2]); 166 printf("| xlnaGainCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 167 mh->xlnaGainCh[0], mh->xlnaGainCh[1], mh->xlnaGainCh[2]); 168 printf("| iqCalICh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n| iqCalQCh: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 169 mh->iqCalICh[0], mh->iqCalICh[1], mh->iqCalICh[2], 170 mh->iqCalQCh[0], mh->iqCalQCh[1], mh->iqCalQCh[2]); 171 printf("| bswAtten: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 172 mh->bswAtten[0], mh->bswAtten[1], mh->bswAtten[2]); 173 printf("| bswMargin: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 174 mh->bswMargin[0], mh->bswMargin[1], mh->bswMargin[2]); 175 printf("| xatten2Db: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 176 mh->xatten2Db[0], mh->xatten2Db[1], mh->xatten2Db[2]); 177 printf("| xatten2Margin: 0:0x%.2x 1:0x%.2x 2:0x%.2x |\n", 178 mh->xatten2Margin[0], mh->xatten2Margin[1], mh->xatten2Margin[2]); 179 180 printf("| txEndToXpaOff: 0x%.2x | txEndToRxOn: 0x%.2x | txFrameToXpaOn: 0x%.2x |\n", 181 mh->txEndToXpaOff, mh->txEndToRxOn, mh->txFrameToXpaOn); 182 183 printf("| thres62: 0x%.2x\n", mh->thresh62); 184 185 printf("| xpdGain: 0x%.2x | xpd: 0x%.2x |\n", mh->xpdGain, mh->xpd); 186 printf("| xpaBiasLvlFreq: 0:0x%.4x 1:0x%.4x 2:0x%.4x |\n", 187 mh->xpaBiasLvlFreq[0], mh->xpaBiasLvlFreq[1], mh->xpaBiasLvlFreq[2]); 188 189 printf("| pdGainOverlap: 0x%.2x | ob: 0x%.2x | db: 0x%.2x | xpaBiasLvl: 0x%.2x |\n", 190 mh->pdGainOverlap, mh->ob, mh->db, mh->xpaBiasLvl); 191 192 printf("| pwrDecreaseFor2Chain: 0x%.2x | pwrDecreaseFor3Chain: 0x%.2x | txFrameToDataStart: 0x%.2x | txFrameToPaOn: 0x%.2x |\n", 193 mh->pwrDecreaseFor2Chain, mh->pwrDecreaseFor3Chain, mh->txFrameToDataStart, 194 mh->txFrameToPaOn); 195 196 printf("| ht40PowerIncForPdadc: 0x%.2x |\n", mh->ht40PowerIncForPdadc); 197 198 printf("| swSettleHt40: 0x%.2x |\n", mh->swSettleHt40); 199 200 printf("| ob_ch1: 0x%.2x | db_ch1: 0x%.2x |\n", mh->ob_ch1, mh->db_ch1); 201 202 printf("| flagBits: 0x%.2x | miscBits: 0x%.2x |\n", mh->flagBits, mh->miscBits); 203 204 205 printf("| futureModal: 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x |\n", 206 mh->futureModal[0], 207 mh->futureModal[1], 208 mh->futureModal[2], 209 mh->futureModal[3], 210 mh->futureModal[4], 211 mh->futureModal[5]); 212 213 /* and now, spur channels */ 214 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { 215 printf("| Spur %d: spurChan: 0x%.4x spurRangeLow: 0x%.2x spurRangeHigh: 0x%.2x |\n", 216 i, mh->spurChans[i].spurChan, 217 (int) mh->spurChans[i].spurRangeLow, 218 (int) mh->spurChans[i].spurRangeHigh); 219 } 220 } 221 222 static void 223 eeprom_v14_print_caldata_perfreq_op_loop(CAL_DATA_PER_FREQ_OP_LOOP *f) 224 { 225 int i, j; 226 for (i = 0; i < 2; i++) { 227 printf(" Gain: %d:\n", i); 228 for (j = 0; j < 5; j++) { 229 printf(" %d: pwrPdg: %d, vpdPdg: %d, pcdac: %d, empty: %d\n", 230 j, f->pwrPdg[i][j], f->vpdPdg[i][j], f->pcdac[i][j], f->empty[i][j]); 231 } 232 printf("\n"); 233 } 234 } 235 236 static void 237 eeprom_v14_print_caldata_perfreq(CAL_DATA_PER_FREQ *f) 238 { 239 int i, j; 240 241 for (i = 0; i < AR5416_NUM_PD_GAINS; i++) { 242 printf(" Gain %d: pwr dBm/vpd: ", i); 243 for (j = 0; j < AR5416_PD_GAIN_ICEPTS; j++) { 244 /* These are stored in 0.25dBm increments */ 245 printf("%d:(%.2f/%d) ", j, (float) f->pwrPdg[i][j] / 4.00, 246 f->vpdPdg[i][j]); 247 } 248 printf("\n"); 249 } 250 } 251 252 static void 253 eeprom_v14_calfreqpiers_print(uint16_t *buf) 254 { 255 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 256 int i, n; 257 258 /* 2ghz cal piers */ 259 printf("calFreqPier2G: "); 260 for (i = 0; i < AR5416_NUM_2G_CAL_PIERS; i++) { 261 printf(" 0x%.2x ", eep->ee_base.calFreqPier2G[i]); 262 } 263 printf("|\n"); 264 265 for (i = 0; i < AR5416_NUM_2G_CAL_PIERS; i++) { 266 if (eep->ee_base.calFreqPier2G[i] == 0xff) 267 continue; 268 printf("2Ghz Cal Pier %d\n", i); 269 for (n = 0; n < AR5416_MAX_CHAINS; n++) { 270 printf(" Chain %d:\n", n); 271 if (eep->ee_base.baseEepHeader.openLoopPwrCntl) 272 eeprom_v14_print_caldata_perfreq_op_loop((void *) (&eep->ee_base.calPierData2G[n][i])); 273 else 274 eeprom_v14_print_caldata_perfreq(&eep->ee_base.calPierData2G[n][i]); 275 } 276 } 277 278 printf("\n"); 279 280 /* 5ghz cal piers */ 281 printf("calFreqPier5G: "); 282 for (i = 0; i < AR5416_NUM_5G_CAL_PIERS; i++) { 283 printf(" 0x%.2x ", eep->ee_base.calFreqPier5G[i]); 284 } 285 printf("|\n"); 286 for (i = 0; i < AR5416_NUM_5G_CAL_PIERS; i++) { 287 if (eep->ee_base.calFreqPier5G[i] == 0xff) 288 continue; 289 printf("5Ghz Cal Pier %d\n", i); 290 for (n = 0; n < AR5416_MAX_CHAINS; n++) { 291 printf(" Chain %d:\n", n); 292 if (eep->ee_base.baseEepHeader.openLoopPwrCntl) 293 eeprom_v14_print_caldata_perfreq_op_loop((void *) (&eep->ee_base.calPierData5G[n][i])); 294 else 295 eeprom_v14_print_caldata_perfreq(&eep->ee_base.calPierData5G[n][i]); 296 } 297 } 298 } 299 300 static void 301 eeprom_v14_target_legacy_print(CAL_TARGET_POWER_LEG *l) 302 { 303 int i; 304 if (l->bChannel == 0xff) 305 return; 306 printf(" bChannel: %d;", l->bChannel); 307 for (i = 0; i < 4; i++) { 308 printf(" %.2f", (float) l->tPow2x[i] / 2.0); 309 } 310 printf(" (dBm)\n"); 311 } 312 313 static void 314 eeprom_v14_target_ht_print(CAL_TARGET_POWER_HT *l) 315 { 316 int i; 317 if (l->bChannel == 0xff) 318 return; 319 printf(" bChannel: %d;", l->bChannel); 320 for (i = 0; i < 8; i++) { 321 printf(" %.2f", (float) l->tPow2x[i] / 2.0); 322 } 323 printf(" (dBm)\n"); 324 } 325 326 static void 327 eeprom_v14_print_targets(uint16_t *buf) 328 { 329 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 330 int i; 331 332 /* 2ghz rates */ 333 printf("2Ghz CCK:\n"); 334 for (i = 0; i < AR5416_NUM_2G_CCK_TARGET_POWERS; i++) { 335 eeprom_v14_target_legacy_print(&eep->ee_base.calTargetPowerCck[i]); 336 } 337 printf("2Ghz 11g:\n"); 338 for (i = 0; i < AR5416_NUM_2G_20_TARGET_POWERS; i++) { 339 eeprom_v14_target_legacy_print(&eep->ee_base.calTargetPower2G[i]); 340 } 341 printf("2Ghz HT20:\n"); 342 for (i = 0; i < AR5416_NUM_2G_20_TARGET_POWERS; i++) { 343 eeprom_v14_target_ht_print(&eep->ee_base.calTargetPower2GHT20[i]); 344 } 345 printf("2Ghz HT40:\n"); 346 for (i = 0; i < AR5416_NUM_2G_40_TARGET_POWERS; i++) { 347 eeprom_v14_target_ht_print(&eep->ee_base.calTargetPower2GHT40[i]); 348 } 349 350 /* 5ghz rates */ 351 printf("5Ghz 11a:\n"); 352 for (i = 0; i < AR5416_NUM_5G_20_TARGET_POWERS; i++) { 353 eeprom_v14_target_legacy_print(&eep->ee_base.calTargetPower5G[i]); 354 } 355 printf("5Ghz HT20:\n"); 356 for (i = 0; i < AR5416_NUM_5G_20_TARGET_POWERS; i++) { 357 eeprom_v14_target_ht_print(&eep->ee_base.calTargetPower5GHT20[i]); 358 } 359 printf("5Ghz HT40:\n"); 360 for (i = 0; i < AR5416_NUM_5G_40_TARGET_POWERS; i++) { 361 eeprom_v14_target_ht_print(&eep->ee_base.calTargetPower5GHT40[i]); 362 } 363 364 } 365 366 static void 367 eeprom_v14_ctl_edge_print(CAL_CTL_DATA *ctl) 368 { 369 int i, j; 370 uint8_t pow, flag; 371 372 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 373 printf(" chain %d: ", i); 374 for (j = 0; j < AR5416_NUM_BAND_EDGES; j++) { 375 pow = ctl->ctlEdges[i][j].tPowerFlag & 0x3f; 376 flag = (ctl->ctlEdges[i][j].tPowerFlag & 0xc0) >> 6; 377 printf(" %d:pow=%d,flag=%.2x", j, pow, flag); 378 } 379 printf("\n"); 380 } 381 } 382 383 static void 384 eeprom_v14_ctl_print(uint16_t *buf) 385 { 386 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 387 int i; 388 389 for (i = 0; i < AR5416_NUM_CTLS; i++) { 390 if (eep->ee_base.ctlIndex[i] == 0) 391 continue; 392 printf("| ctlIndex: offset %d, value %d\n", i, eep->ee_base.ctlIndex[i]); 393 eeprom_v14_ctl_edge_print(&eep->ee_base.ctlData[i]); 394 } 395 } 396 397 static void 398 eeprom_v14_print_edges(uint16_t *buf) 399 { 400 HAL_EEPROM_v14 *eep = (HAL_EEPROM_v14 *) buf; 401 int i; 402 403 printf("| eeNumCtls: %d\n", eep->ee_numCtls); 404 for (i = 0; i < NUM_EDGES*eep->ee_numCtls; i++) { 405 /* XXX is flag 8 or 32 bits? */ 406 printf("| edge %2d/%2d: rdEdge: %5d EdgePower: %.2f dBm Flag: 0x%.8x\n", 407 i / NUM_EDGES, i % NUM_EDGES, 408 eep->ee_rdEdgesPower[i].rdEdge, 409 (float) eep->ee_rdEdgesPower[i].twice_rdEdgePower / 2.0, 410 eep->ee_rdEdgesPower[i].flag); 411 412 if (i % NUM_EDGES == (NUM_EDGES -1)) 413 printf("|\n"); 414 } 415 #if 0 416 typedef struct { 417 uint16_t rdEdge; 418 uint16_t twice_rdEdgePower; 419 HAL_BOOL flag; 420 } RD_EDGES_POWER; 421 422 #endif 423 } 424 425 void 426 usage(char *argv[]) 427 { 428 printf("Usage: %s <eeprom dump file>\n", argv[0]); 429 printf("\n"); 430 printf(" The eeprom dump file is a text hexdump of an EEPROM.\n"); 431 printf(" The lines must be formatted as follows:\n"); 432 printf(" 0xAAAA: 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD\n"); 433 printf(" where each line must have exactly eight data bytes.\n"); 434 exit(127); 435 } 436 437 int 438 main(int argc, char *argv[]) 439 { 440 uint16_t *eep = NULL; 441 eep = calloc(4096, sizeof(int16_t)); 442 443 if (argc < 2) 444 usage(argv); 445 446 load_eeprom_dump(argv[1], eep); 447 448 eeprom_v14_base_print(eep); 449 eeprom_v14_custdata_print(eep); 450 451 /* 2.4ghz */ 452 printf("\n2.4ghz:\n"); 453 eeprom_v14_modal_print(eep, 1); 454 /* 5ghz */ 455 printf("\n5ghz:\n"); 456 eeprom_v14_modal_print(eep, 0); 457 printf("\n"); 458 459 eeprom_v14_calfreqpiers_print(eep); 460 printf("\n"); 461 462 eeprom_v14_print_targets(eep); 463 printf("\n"); 464 465 eeprom_v14_ctl_print(eep); 466 printf("\n"); 467 468 eeprom_v14_print_edges(eep); 469 printf("\n"); 470 471 free(eep); 472 exit(0); 473 } 474