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