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