--- embedtools/src/athctl.c 2010/10/23 01:50:49 1.1.2.2 +++ embedtools/src/athctl.c 2010/10/25 14:46:30 1.1.2.4 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ - * $Id: athctl.c,v 1.1.2.2 2010/10/23 01:50:49 misho Exp $ + * $Id: athctl.c,v 1.1.2.4 2010/10/25 14:46:30 misho Exp $ * *************************************************************************/ #include "global.h" @@ -19,12 +19,24 @@ Usage() { printf( "athCtl is tool for Atheros WiFi cards managment \n" "=== %s === %s@%s ===\n\n" - " Syntax: athctl [options] [exec_file]\n\n" + " Syntax: athctl [options] [[0xMemory_Address] new_value]\n" + " athctl [-v] -t [-i ]\n" + " athctl [-v] -c [-i ]\n" + " athctl [-v] -d [-i ]\n" + " athctl [-v] -r <0xoffset> <0xMemory_Address>\n" + " athctl [-v] -w <0xoffset> <0xMemory_Address> \n" + " athctl [-v] -s <0xMemory_Address>\n" + " athctl [-v] -w <0xMemory_Address>\n" + "\n" "\t-v\t\tVerbose ...\n" "\t-t\t\tGet current Atheros maximum range in meters\n" "\t-i \tApply to this Atheros interface number (like ath0 == 0)\n" "\t-d \tMode distance, meters to target\n" "\t-c \tMode distance, mS timeouts correction\n" + "\t-s \tDump EEPROM to file\n" + "\t-u \tUpdate EEPROM from file\n" + "\t-r \tRead EEPROM word from PCI mapped memory address\n" + "\t-w \tWrite EEPROM word to PCI mapped memory address\n" "\n", compiled, compiledby, compilehost); } @@ -127,15 +139,154 @@ calcTimeout(int ifid, int cor) return timeout[0]; } + + +static inline void * +devOpen(u_long baseaddr) +{ + int fd; + void *basemem; + + fd = open("/dev/mem", O_RDWR); + if (fd == -1) { + printf("Error:: open device #%d - %s\n", errno, strerror(errno)); + return NULL; + } + basemem = mmap(NULL, ATH_PCI_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, baseaddr); + if (basemem == MAP_FAILED) { + printf("Error:: map device #%d - %s\n", errno, strerror(errno)); + close(fd); + return NULL; + } else + close(fd); + + return basemem; +} + +static inline void +devClose(void *basemem) +{ + if (basemem) + munmap(basemem, ATH_PCI_MEM_SIZE); +} + +static inline short +readWord(u_char *mem, u_long offset) +{ + register int timeout = ATH_ACCESS_TIMEOUT; + u_long stat; + + ATH_OUT(mem, AR5211_EEPROM_CONF, 0); + usleep(ATH_ACCESS_WAIT); + /* enable eeprom access */ + ATH_OUT(mem, AR5211_EEPROM_COMD, ATH_IN(mem, AR5211_EEPROM_COMD) | AR5211_EEPROM_COMD_RESET); + usleep(ATH_ACCESS_WAIT); + /* set address */ + ATH_OUT(mem, AR5211_EEPROM_ADDR, offset); + usleep(ATH_ACCESS_WAIT); + /* enable eeprom read access */ + ATH_OUT(mem, AR5211_EEPROM_COMD, ATH_IN(mem, AR5211_EEPROM_COMD) | AR5211_EEPROM_COMD_READ); + usleep(ATH_ACCESS_WAIT); + + while (timeout--) { + usleep(1); + stat = ATH_IN(mem, AR5211_EEPROM_STATUS); + if (stat & AR5211_EEPROM_STAT_RDDONE) { + if (stat & AR5211_EEPROM_STAT_RDERR) { + printf("Error:: EEPROM read failed!\n"); + return -1; + } + + stat = ATH_IN(mem, AR5211_EEPROM_DATA); + return stat & 0x0000ffff; + } + } + + printf("Error:: EEPROM read timeout!\n"); + return 0; +} + +static inline short +writeWord(u_char *mem, u_long offset, u_short newval) +{ + register int i = ATH_WRITE_RETRY, timeout; + u_long pcicfg, stat; + u_short chk; + + /* enable pci write access */ + pcicfg = ATH_IN(mem, AR5K_PCICFG); + ATH_OUT(mem, AR5K_PCICFG, (pcicfg & ~AR5K_PCICFG_SPWR_DN)); + usleep(ATH_ACCESS_WAITDOWN); + ATH_OUT(mem, AR5K_PCICFG, pcicfg | AR5K_PCICFG_EEAE /* | 0x2 */); + usleep(ATH_ACCESS_WAITPCI); + ATH_OUT(mem, AR5211_EEPROM_STATUS, 0); + usleep(ATH_ACCESS_WAITPCI); + /* ATH_OUT(mem, AR5211_EEPROM_CONF, 1); */ + ATH_OUT(mem, AR5211_EEPROM_CONF, 0); + + do { + /* enable eeprom write access */ + ATH_OUT(mem, AR5211_EEPROM_COMD, AR5211_EEPROM_COMD_RESET); + usleep(ATH_ACCESS_WAITDOWN); + ATH_OUT(mem, AR5211_EEPROM_DATA, newval); + usleep(ATH_ACCESS_WAIT); + ATH_OUT(mem, AR5211_EEPROM_ADDR, offset); + usleep(ATH_ACCESS_WAIT); + ATH_OUT(mem, AR5211_EEPROM_COMD, AR5211_EEPROM_COMD_WRITE); + usleep(ATH_ACCESS_WAIT); + + for (timeout = ATH_ACCESS_TIMEOUT; timeout; timeout--) { + stat = ATH_IN(mem, AR5211_EEPROM_STATUS); + if (stat & 0xc) { + if (stat & AR5211_EEPROM_STAT_WRERR) { + printf("Error:: EEPROM write failed!\n"); + return -1; + } + + ATH_OUT(mem, AR5211_EEPROM_STATUS, 0); + usleep(ATH_ACCESS_WAIT * 2); + break; + } + usleep(ATH_ACCESS_WAIT * 2); + } + + chk = readWord(mem, offset); + if (chk == (u_short) -1) + return -1; + if (chk == newval) + return 1; + if (i) + printf("Warning:: Retrying EEPROM write ...\n"); + } while (--i); + + printf("Error:: EEPROM write timeout!\n"); + return 0; +} + +/* +static int +readEEPROM() +{ + register u_long i; + + printf("Reading EEPROM ...\n"); + for (i = 0; i < ATH_EEPROM_SIZE / 2; i++) { + } +} +*/ + // ---------------------------------------------------- int main(int argc, char **argv) { - char ch, mode = 0; + char ch, szName[MAXPATHLEN] = { 0 }, mode = 0; int ret = 0, dist = 0, cor = 0, ino = 0; + u_long offset = 0, baseaddr = (u_long) -1; + u_short newval = 0; + void *basemem = NULL; - while ((ch = getopt(argc, argv, "hvti:d:c:")) != -1) + while ((ch = getopt(argc, argv, "hvtr:w:i:d:c:u:s:")) != -1) switch (ch) { case 'v': Verbose++; @@ -162,6 +313,22 @@ main(int argc, char **argv) mode |= 1; cor = strtol(optarg, NULL, 0); break; + case 's': + mode = 0x10; + strlcpy(szName, optarg, MAXPATHLEN); + break; + case 'u': + mode = 0x20; + strlcpy(szName, optarg, MAXPATHLEN); + break; + case 'r': + mode = 4; + offset = strtoul(optarg, NULL, 0); + break; + case 'w': + mode = 8; + offset = strtoul(optarg, NULL, 0); + break; case 'h': default: Usage(); @@ -169,10 +336,23 @@ main(int argc, char **argv) } argc -= optind; argv += optind; + if (argc && *argv) + baseaddr = strtoul(*argv, NULL, 0); if (!mode) { printf("Error:: not selected mode for operation ...\n"); return 1; } + if (mode > 3 && baseaddr == (u_long) -1) { + printf("Error:: in this mode for operation, must give memory mapped address ...\n"); + return 1; + } + if (mode & 8) { + if (!argv[1]) { + printf("Error:: in write word mode, must give memory mapped address and new value ...\n"); + return 1; + } else + newval = (u_short) strtoul(argv[1], NULL, 0); + } if (mode & 1) if ((ret = calcDistance(ino, dist, cor)) < 1) @@ -186,6 +366,25 @@ main(int argc, char **argv) else printf("~%d\n", ret); } + } + + if (mode & 4) { + if (!(basemem = devOpen(baseaddr))) + return 2; + if ((ret = readWord(basemem, offset)) < 1) { + devClose(basemem); + return 3; + } + devClose(basemem); + } + if (mode & 8) { + if (!(basemem = devOpen(baseaddr))) + return 2; + if ((ret = writeWord(basemem, offset, newval)) < 1) { + devClose(basemem); + return 3; + } + devClose(basemem); } return 0;