Annotation of embedtools/src/athctl.c, revision 1.2
1.2 ! misho 1: /*************************************************************************
! 2: * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
! 3: * by Michael Pounov <misho@aitbg.com>
! 4: *
! 5: * $Author: misho $
! 6: * $Id: athctl.c,v 1.1.2.12 2010/11/05 01:14:16 misho Exp $
! 7: *
! 8: *************************************************************************/
! 9: #include "global.h"
! 10: #include "athctl.h"
! 11:
! 12:
! 13: int Verbose;
! 14: extern char compiled[], compiledby[], compilehost[];
! 15:
! 16:
! 17: static void
! 18: Usage()
! 19: {
! 20: printf( "athCtl is tool for Atheros WiFi cards managment \n"
! 21: "=== %s === %s@%s ===\n\n"
! 22: " Syntax: athctl [options] [[0xMemory_Address] new_value]\n"
! 23: " athctl [-v] -t [-i <iface_no>]\n"
! 24: " athctl [-v] -c <timeout> [-i <iface_no>]\n"
! 25: " athctl [-v] -d <distance> [-i <iface_no>]\n"
! 26: " athctl [-v] -r <0xoffset> <0xMemory_Address>\n"
! 27: " athctl [-v] -w <0xoffset> <0xMemory_Address> <uint16_value>\n"
! 28: " athctl [-v] -s <file> <0xMemory_Address>\n"
! 29: " athctl [-v] -u <file> <0xMemory_Address>\n"
! 30: " athctl [-v] -R <0xMemory_Address> [new_regdomain]\n"
! 31: "\n"
! 32: "\t-v\t\tVerbose ...\n"
! 33: "\t-t\t\tGet current Atheros maximum range in meters\n"
! 34: "\t-i <iface_no>\tApply to this Atheros interface number (like ath0 == 0)\n"
! 35: "\t-d <distance>\tMode distance, meters to target\n"
! 36: "\t-c <timeout>\tMode distance, mS timeouts correction\n"
! 37: "\t-R\t\tRead or Write EEPROM Regulatory domain\n"
! 38: "\t-s <file>\tDump EEPROM to file\n"
! 39: "\t-u <file>\tUpdate EEPROM from file\n"
! 40: "\t-r <offset>\tRead EEPROM word from PCI mapped memory address\n"
! 41: "\t-w <offset>\tWrite EEPROM word to PCI mapped memory address\n"
! 42: "\n", compiled, compiledby, compilehost);
! 43: }
! 44:
! 45: static int
! 46: calcDistance(int ifid, int dist, int cor)
! 47: {
! 48: int slottime[2], timeout[2];
! 49: size_t len;
! 50: char szStr[STRSIZ];
! 51:
! 52: slottime[0] = 9 + (dist / 300) + (dist % 300 ? 1 : 0);
! 53: timeout[0] = slottime[0] * 2 + 3 + cor;
! 54: VERB(3) printf("Info:: slottime=%d timeout=%d\n", slottime[0], timeout[0]);
! 55:
! 56: memset(szStr, 0, STRSIZ);
! 57: snprintf(szStr, STRSIZ, SC_SLOTTIME, ifid);
! 58: if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
! 59: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 60: return -1;
! 61: } else if (sysctlbyname(szStr, &slottime[1], &len, NULL, 0) == -1) {
! 62: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 63: return -1;
! 64: } else if (sysctlbyname(szStr, NULL, NULL, &slottime[0], sizeof slottime[0]) == -1) {
! 65: printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, slottime[1],
! 66: errno, strerror(errno));
! 67: return -1;
! 68: } else
! 69: VERB(1) printf("Info:: set slottime(%d) from %d to %d ... OK!\n", len,
! 70: slottime[1], slottime[0]);
! 71:
! 72: memset(szStr, 0, STRSIZ);
! 73: snprintf(szStr, STRSIZ, SC_ACKTIMEOUT, ifid);
! 74: if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
! 75: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 76: return -1;
! 77: } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
! 78: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 79: return -1;
! 80: } else if (sysctlbyname(szStr, NULL, NULL, &timeout[0], sizeof timeout[0]) == -1) {
! 81: printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, timeout[1],
! 82: errno, strerror(errno));
! 83: return -1;
! 84: } else
! 85: VERB(1) printf("Info:: set acktimeout(%d) from %d to %d ... OK!\n", len,
! 86: timeout[1], timeout[0]);
! 87:
! 88: memset(szStr, 0, STRSIZ);
! 89: snprintf(szStr, STRSIZ, SC_CTSTIMEOUT, ifid);
! 90: if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
! 91: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 92: return -1;
! 93: } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
! 94: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 95: return -1;
! 96: } else if (sysctlbyname(szStr, NULL, NULL, &timeout[0], sizeof timeout[0]) == -1) {
! 97: printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, timeout[1],
! 98: errno, strerror(errno));
! 99: return -1;
! 100: } else
! 101: VERB(1) printf("Info:: set ctstimeout(%d) from %d to %d ... OK!\n", len,
! 102: timeout[1], timeout[0]);
! 103:
! 104: return timeout[0];
! 105: }
! 106:
! 107:
! 108: static int
! 109: calcTimeout(int ifid, int cor)
! 110: {
! 111: int slottime[2], timeout[2];
! 112: size_t len;
! 113: char szStr[STRSIZ];
! 114:
! 115: memset(szStr, 0, STRSIZ);
! 116: snprintf(szStr, STRSIZ, SC_SLOTTIME, ifid);
! 117: if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
! 118: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 119: return -1;
! 120: } else if (sysctlbyname(szStr, &slottime[1], &len, NULL, 0) == -1) {
! 121: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 122: return -1;
! 123: } else
! 124: VERB(1) printf("Info:: get slottime(%d) %d ... OK!\n", len, slottime[1]);
! 125:
! 126: memset(szStr, 0, STRSIZ);
! 127: snprintf(szStr, STRSIZ, SC_ACKTIMEOUT, ifid);
! 128: if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
! 129: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 130: return -1;
! 131: } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
! 132: printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
! 133: return -1;
! 134: } else
! 135: VERB(1) printf("Info:: get acktimeout(%d) %d ... OK!\n", len, timeout[1]);
! 136:
! 137: slottime[0] = (timeout[1] - 3 - cor) / 2;
! 138: VERB(3) printf("Info:: calculated slottime=%d\n", slottime[0]);
! 139: timeout[0] = (slottime[0] - 10) * 300;
! 140: VERB(3) printf("Info:: calculated timeout=%d\n", timeout[0]);
! 141:
! 142: return timeout[0];
! 143: }
! 144:
! 145:
! 146: static inline void *
! 147: devOpen(u_long baseaddr)
! 148: {
! 149: int fd;
! 150: void *basemem;
! 151:
! 152: fd = open("/dev/mem", O_RDWR);
! 153: if (fd == -1) {
! 154: printf("Error:: open device #%d - %s\n", errno, strerror(errno));
! 155: return NULL;
! 156: }
! 157: basemem = mmap(NULL, ATH_PCI_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, baseaddr);
! 158: if (basemem == MAP_FAILED) {
! 159: printf("Error:: map device #%d - %s\n", errno, strerror(errno));
! 160: close(fd);
! 161: return NULL;
! 162: } else
! 163: close(fd);
! 164:
! 165: return basemem;
! 166: }
! 167:
! 168: static inline void
! 169: devClose(void *basemem)
! 170: {
! 171: if (basemem)
! 172: munmap(basemem, ATH_PCI_MEM_SIZE);
! 173: }
! 174:
! 175: static inline int
! 176: readWord(u_char *mem, u_long offset)
! 177: {
! 178: register int timeout = ATH_ACCESS_TIMEOUT;
! 179: u_long stat;
! 180:
! 181: VERB(9) printf("Reading EEPROM memory %p+%lx ...\n", mem, offset);
! 182: ATH_OUT(mem, AR5211_EEPROM_CONF, 0);
! 183: usleep(ATH_ACCESS_WAIT);
! 184: /* enable eeprom access */
! 185: ATH_OUT(mem, AR5211_EEPROM_COMD, ATH_IN(mem, AR5211_EEPROM_COMD) | AR5211_EEPROM_COMD_RESET);
! 186: usleep(ATH_ACCESS_WAIT);
! 187: /* set address */
! 188: ATH_OUT(mem, AR5211_EEPROM_ADDR, offset);
! 189: usleep(ATH_ACCESS_WAIT);
! 190: /* enable eeprom read access */
! 191: ATH_OUT(mem, AR5211_EEPROM_COMD, ATH_IN(mem, AR5211_EEPROM_COMD) | AR5211_EEPROM_COMD_READ);
! 192: usleep(ATH_ACCESS_WAIT);
! 193:
! 194: while (timeout--) {
! 195: usleep(1);
! 196: stat = ATH_IN(mem, AR5211_EEPROM_STATUS);
! 197: if (stat & AR5211_EEPROM_STAT_RDDONE) {
! 198: if (stat & AR5211_EEPROM_STAT_RDERR) {
! 199: printf("Error:: EEPROM read failed!\n");
! 200: return -1;
! 201: }
! 202:
! 203: stat = ATH_IN(mem, AR5211_EEPROM_DATA);
! 204: return (stat & 0x0000ffff) << 16;
! 205: }
! 206: }
! 207:
! 208: printf("Error:: EEPROM read timeout!\n");
! 209: return -1;
! 210: }
! 211:
! 212: static inline int
! 213: writeWord(u_char *mem, u_long offset, u_short newval)
! 214: {
! 215: register int i = ATH_WRITE_RETRY, timeout;
! 216: u_long pcicfg, stat;
! 217: int chk;
! 218:
! 219: VERB(9) printf("Writing EEPROM memory %p+%lx ...\n", mem, offset);
! 220: /* enable pci write access */
! 221: pcicfg = ATH_IN(mem, AR5K_PCICFG);
! 222: ATH_OUT(mem, AR5K_PCICFG, (pcicfg & ~AR5K_PCICFG_SPWR_DN));
! 223: usleep(ATH_ACCESS_WAITDOWN);
! 224: ATH_OUT(mem, AR5K_PCICFG, pcicfg | AR5K_PCICFG_EEAE /* | 0x2 */);
! 225: usleep(ATH_ACCESS_WAITPCI);
! 226: ATH_OUT(mem, AR5211_EEPROM_STATUS, 0);
! 227: usleep(ATH_ACCESS_WAITPCI);
! 228: /* ATH_OUT(mem, AR5211_EEPROM_CONF, 1); */
! 229: ATH_OUT(mem, AR5211_EEPROM_CONF, 0);
! 230:
! 231: do {
! 232: /* enable eeprom write access */
! 233: ATH_OUT(mem, AR5211_EEPROM_COMD, AR5211_EEPROM_COMD_RESET);
! 234: usleep(ATH_ACCESS_WAITDOWN);
! 235: ATH_OUT(mem, AR5211_EEPROM_DATA, newval);
! 236: usleep(ATH_ACCESS_WAIT);
! 237: ATH_OUT(mem, AR5211_EEPROM_ADDR, offset);
! 238: usleep(ATH_ACCESS_WAIT);
! 239: ATH_OUT(mem, AR5211_EEPROM_COMD, AR5211_EEPROM_COMD_WRITE);
! 240: usleep(ATH_ACCESS_WAIT);
! 241:
! 242: for (timeout = ATH_ACCESS_TIMEOUT; timeout; timeout--) {
! 243: stat = ATH_IN(mem, AR5211_EEPROM_STATUS);
! 244: if (stat & 0xc) {
! 245: if (stat & AR5211_EEPROM_STAT_WRERR) {
! 246: printf("Error:: EEPROM write failed!\n");
! 247: return -1;
! 248: }
! 249:
! 250: ATH_OUT(mem, AR5211_EEPROM_STATUS, 0);
! 251: usleep(ATH_ACCESS_WAIT * 2);
! 252: break;
! 253: }
! 254: usleep(ATH_ACCESS_WAIT * 2);
! 255: }
! 256:
! 257: chk = readWord(mem, offset);
! 258: if (chk == (u_short) -1)
! 259: return -1;
! 260: if ((u_short) (chk >> 16) == newval)
! 261: return chk;
! 262: else
! 263: VERB(1) printf("Write & Read don`t match 0x%04X != 0x%04X\n", newval, (u_short) (chk >> 16));
! 264: if (i)
! 265: printf("Warning:: Retrying EEPROM write ...\n");
! 266: } while (--i);
! 267:
! 268: printf("Error:: EEPROM write timeout!\n");
! 269: return -1;
! 270: }
! 271:
! 272: static int
! 273: dumpFile(const char *csName, u_char *mem)
! 274: {
! 275: register u_long i;
! 276: u_short d1, d2;
! 277: u_char eeprom[ATH_EEPROM_SIZE] = { 0 };
! 278: int f, data;
! 279:
! 280: VERB(2) printf("Reading EEPROM memory %p ::\n", mem);
! 281: for (i = 0; i < ATH_EEPROM_SIZE / 2; i++) {
! 282: if (!(i % 0x40)) {
! 283: if (i)
! 284: printf("]\n");
! 285: printf("0x%04lX [", i * 2);
! 286: }
! 287:
! 288: if ((data = readWord(mem, i)) == -1)
! 289: return -1;
! 290: else {
! 291: d1 = ((u_short)(data >> 16)) / 0x100;
! 292: d2 = ((u_short)(data >> 16)) % 0x100;
! 293:
! 294: VERB(5) printf( "Current value 0x%04X on position 0x%04lX will change 0x%02X 0x%02X\n",
! 295: (u_short) (data >> 16), i, d1, d2);
! 296: }
! 297:
! 298: eeprom[i * 2] = d2;
! 299: eeprom[i * 2 + 1] = d1;
! 300:
! 301: printf(".");
! 302: usleep(ATH_ACCESS_WAITDOWN);
! 303: }
! 304: printf("]\n");
! 305:
! 306: VERB(2) printf("Saving EEPROM to file %s ... ", csName);
! 307: f = open(csName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
! 308: if (f == -1) {
! 309: printf("Failed!\nError:: in create file %s #%d - %s\n", csName,
! 310: errno, strerror(errno));
! 311: return 0;
! 312: }
! 313: if (write(f, eeprom, ATH_EEPROM_SIZE) == -1) {
! 314: printf("Failed!\nError:: in write to file %s #%d - %s\n", csName,
! 315: errno, strerror(errno));
! 316: close(f);
! 317: return 0;
! 318: }
! 319: close(f);
! 320: printf("OK!\n");
! 321: return 1;
! 322: }
! 323:
! 324: static int
! 325: flashFile(const char *csName, u_char *mem)
! 326: {
! 327: register u_long i;
! 328: u_short d1;
! 329: u_char eeprom[ATH_EEPROM_SIZE] = { 0 };
! 330: int f, data;
! 331:
! 332: VERB(2) printf("Reading EEPROM from file %s ... ", csName);
! 333: f = open(csName, O_RDONLY);
! 334: if (f == -1) {
! 335: printf("Failed!\nError:: in open file %s #%d - %s\n", csName,
! 336: errno, strerror(errno));
! 337: return 0;
! 338: }
! 339: if (read(f, eeprom, ATH_EEPROM_SIZE) != ATH_EEPROM_SIZE) {
! 340: printf("Failed!\nError:: failed load image from file %s\n", csName);
! 341: close(f);
! 342: return 0;
! 343: }
! 344: close(f);
! 345: VERB(2) printf("OK!\n");
! 346:
! 347: VERB(2) printf("Writing EEPROM memory %p ::\n", mem);
! 348: for (i = 0; i < ATH_EEPROM_SIZE / 2; i++) {
! 349: if (!(i % 0x40)) {
! 350: if (i)
! 351: printf("]\n");
! 352: printf("0x%04lX [", i * 2);
! 353: }
! 354:
! 355: if ((data = readWord(mem, i)) == -1)
! 356: return -1;
! 357: else
! 358: d1 = eeprom[i * 2 + 1] * 0x100 + eeprom[i * 2];
! 359: VERB(5) printf("eeprom_data=0x%04X read_d1=0x%04X\n", (u_char) (data >> 16), d1);
! 360:
! 361: if (((u_short) (data >> 16)) == d1)
! 362: printf(".");
! 363: else {
! 364:
! 365: if (writeWord(mem, i, d1) < 1)
! 366: printf("!");
! 367: else
! 368: printf("x");
! 369: }
! 370:
! 371: usleep(ATH_ACCESS_WAITDOWN);
! 372: }
! 373: printf("]\n");
! 374:
! 375: return 0;
! 376: }
! 377:
! 378: static int
! 379: regDomain(u_char *mem, u_short newval)
! 380: {
! 381: int ret, data;
! 382:
! 383: if ((data = readWord(mem, ATH_OFFSET_REGDOMAIN)) == -1)
! 384: return -1;
! 385:
! 386: printf("Current value 0x%04X ", (u_short) (data >> 16));
! 387: if (newval != (u_short) -1) {
! 388: printf("will change to 0x%04X\n", newval);
! 389:
! 390: if ((ret = writeWord(mem, ATH_OFFSET_REGDOMAIN, newval)) == -1)
! 391: return -1;
! 392:
! 393: printf("Updated regulatory domain is 0x%04X\n", (u_short) (ret >> 16));
! 394: } else
! 395: printf("\nCurrent regulatory domain is 0x%04X\n", (u_short) (data >> 16));
! 396:
! 397: return 0;
! 398: }
! 399:
! 400: // ----------------------------------------------------
! 401:
! 402: int
! 403: main(int argc, char **argv)
! 404: {
! 405: char ch, szName[MAXPATHLEN] = { 0 }, mode = 0;
! 406: int ret = 0, dist = 0, cor = 0, ino = 0;
! 407: u_long offset = 0, baseaddr = (u_long) -1;
! 408: u_short newval = 0;
! 409: void *basemem = NULL;
! 410:
! 411: while ((ch = getopt(argc, argv, "hvRtr:w:i:d:c:u:s:")) != -1)
! 412: switch (ch) {
! 413: case 'v':
! 414: Verbose++;
! 415: break;
! 416: case 't':
! 417: mode |= 2;
! 418: break;
! 419: case 'i':
! 420: ino = strtol(optarg, NULL, 0);
! 421: if (ino < 0) {
! 422: printf("Error:: in interface number %d\n", ino);
! 423: return 1;
! 424: }
! 425: break;
! 426: case 'd':
! 427: mode |= 1;
! 428: dist = strtol(optarg, NULL, 0);
! 429: if (dist < 1) {
! 430: printf("Error:: in distance meters %d\n", dist);
! 431: return 1;
! 432: }
! 433: break;
! 434: case 'c':
! 435: mode |= 1;
! 436: cor = strtol(optarg, NULL, 0);
! 437: break;
! 438: case 's':
! 439: mode = 0x10;
! 440: strlcpy(szName, optarg, MAXPATHLEN);
! 441: break;
! 442: case 'u':
! 443: mode = 0x20;
! 444: strlcpy(szName, optarg, MAXPATHLEN);
! 445: break;
! 446: case 'R':
! 447: mode = 0x40;
! 448: break;
! 449: case 'r':
! 450: mode = 4;
! 451: offset = strtoul(optarg, NULL, 0);
! 452: break;
! 453: case 'w':
! 454: mode = 8;
! 455: offset = strtoul(optarg, NULL, 0);
! 456: break;
! 457: case 'h':
! 458: default:
! 459: Usage();
! 460: return 1;
! 461: }
! 462: argc -= optind;
! 463: argv += optind;
! 464: if (argc && *argv)
! 465: baseaddr = strtoul(*argv, NULL, 0);
! 466: if (!mode) {
! 467: printf("Error:: not selected mode for operation ...\n");
! 468: return 1;
! 469: }
! 470: if (mode > 3 && baseaddr == (u_long) -1) {
! 471: printf("Error:: in this mode for operation, must give memory mapped address ...\n");
! 472: return 1;
! 473: }
! 474: if (mode & 8) {
! 475: if (!argv[1]) {
! 476: printf("Error:: in write word mode, must give memory mapped address and new value ...\n");
! 477: return 1;
! 478: } else
! 479: newval = (u_short) strtoul(argv[1], NULL, 0);
! 480: }
! 481: if (mode & 0x40) {
! 482: if (argv[1])
! 483: newval = (u_short) strtoul(argv[1], NULL, 0);
! 484: else
! 485: newval = (u_short) -1;
! 486: }
! 487:
! 488: if (mode & 1)
! 489: if ((ret = calcDistance(ino, dist, cor)) < 1)
! 490: return 2;
! 491: if (mode & 2) {
! 492: if ((ret = calcTimeout(ino, cor)) < 1)
! 493: return 2;
! 494: else {
! 495: VERB(1)
! 496: printf("Maximum approximate distance ~%d meters\n", ret);
! 497: else
! 498: printf("~%d\n", ret);
! 499: }
! 500: }
! 501:
! 502: if (mode & 4) {
! 503: if (!(basemem = devOpen(baseaddr)))
! 504: return 2;
! 505: if ((ret = readWord(basemem, offset)) == -1) {
! 506: devClose(basemem);
! 507: return 3;
! 508: } else
! 509: printf("EEPROM readed value 0x%04X\n", (u_short) (ret >> 16));
! 510: devClose(basemem);
! 511: }
! 512: if (mode & 8) {
! 513: if (!(basemem = devOpen(baseaddr)))
! 514: return 2;
! 515: if ((ret = writeWord(basemem, offset, newval)) == -1) {
! 516: devClose(basemem);
! 517: return 3;
! 518: } else
! 519: printf("EEPROM writed value 0x%04X\n", (u_short) (ret >> 16));
! 520: devClose(basemem);
! 521: }
! 522:
! 523: if (mode & 0x10) {
! 524: if (!(basemem = devOpen(baseaddr)))
! 525: return 2;
! 526: if ((ret = dumpFile(szName, basemem)) < 1) {
! 527: devClose(basemem);
! 528: return 3;
! 529: }
! 530: devClose(basemem);
! 531: }
! 532: if (mode & 0x20) {
! 533: if (!(basemem = devOpen(baseaddr)))
! 534: return 2;
! 535: if ((ret = flashFile(szName, basemem)) < 1) {
! 536: devClose(basemem);
! 537: return 3;
! 538: }
! 539: devClose(basemem);
! 540: }
! 541:
! 542: if (mode & 0x40) {
! 543: if (!(basemem = devOpen(baseaddr)))
! 544: return 2;
! 545: if ((ret = regDomain(basemem, newval)) < 1) {
! 546: devClose(basemem);
! 547: return 3;
! 548: }
! 549: devClose(basemem);
! 550: }
! 551:
! 552: return 0;
! 553: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>