Diff for /embedtools/src/athctl.c between versions 1.1 and 1.2

version 1.1, 2010/10/22 09:16:27 version 1.2, 2011/06/08 12:45:41
Line 0 Line 1
   /*************************************************************************
    * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
    *  by Michael Pounov <misho@aitbg.com>
    *
    * $Author$
    * $Id$
    *
    *************************************************************************/
   #include "global.h"
   #include "athctl.h"
   
   
   int Verbose;
   extern char compiled[], compiledby[], compilehost[];
   
   
   static void
   Usage()
   {
           printf( "athCtl is tool for Atheros WiFi cards managment \n"
                   "=== %s === %s@%s ===\n\n"
                   "  Syntax: athctl [options] [[0xMemory_Address] new_value]\n"
                   "          athctl [-v] -t [-i <iface_no>]\n"
                   "          athctl [-v] -c <timeout> [-i <iface_no>]\n"
                   "          athctl [-v] -d <distance> [-i <iface_no>]\n"
                   "          athctl [-v] -r <0xoffset> <0xMemory_Address>\n"
                   "          athctl [-v] -w <0xoffset> <0xMemory_Address> <uint16_value>\n"
                   "          athctl [-v] -s <file> <0xMemory_Address>\n"
                   "          athctl [-v] -u <file> <0xMemory_Address>\n"
                   "          athctl [-v] -R <0xMemory_Address> [new_regdomain]\n"
                   "\n"
                   "\t-v\t\tVerbose ...\n"
                   "\t-t\t\tGet current Atheros maximum range in meters\n"
                   "\t-i <iface_no>\tApply to this Atheros interface number (like ath0 == 0)\n"
                   "\t-d <distance>\tMode distance, meters to target\n"
                   "\t-c <timeout>\tMode distance, mS timeouts correction\n"
                   "\t-R\t\tRead or Write EEPROM Regulatory domain\n"
                   "\t-s <file>\tDump EEPROM to file\n"
                   "\t-u <file>\tUpdate EEPROM from file\n"
                   "\t-r <offset>\tRead EEPROM word from PCI mapped memory address\n"
                   "\t-w <offset>\tWrite EEPROM word to PCI mapped memory address\n"
                   "\n", compiled, compiledby, compilehost);
   }
   
   static int
   calcDistance(int ifid, int dist, int cor)
   {
           int slottime[2], timeout[2];
           size_t len;
           char szStr[STRSIZ];
   
           slottime[0] = 9 + (dist / 300) + (dist % 300 ? 1 : 0);
           timeout[0] = slottime[0] * 2 + 3 + cor;
           VERB(3) printf("Info:: slottime=%d timeout=%d\n", slottime[0], timeout[0]);
   
           memset(szStr, 0, STRSIZ);
           snprintf(szStr, STRSIZ, SC_SLOTTIME, ifid);
           if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, &slottime[1], &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, NULL, NULL, &slottime[0], sizeof slottime[0]) == -1) {
                   printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, slottime[1], 
                                   errno, strerror(errno));
                   return -1;
           } else
                   VERB(1) printf("Info:: set slottime(%d) from %d to %d ... OK!\n", len, 
                                   slottime[1], slottime[0]);
   
           memset(szStr, 0, STRSIZ);
           snprintf(szStr, STRSIZ, SC_ACKTIMEOUT, ifid);
           if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, NULL, NULL, &timeout[0], sizeof timeout[0]) == -1) {
                   printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, timeout[1], 
                                   errno, strerror(errno));
                   return -1;
           } else
                   VERB(1) printf("Info:: set acktimeout(%d) from %d to %d ... OK!\n", len, 
                                   timeout[1], timeout[0]);
   
           memset(szStr, 0, STRSIZ);
           snprintf(szStr, STRSIZ, SC_CTSTIMEOUT, ifid);
           if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, NULL, NULL, &timeout[0], sizeof timeout[0]) == -1) {
                   printf("Error:: set sysctl %s from %d #%d - %s\n", szStr, timeout[1], 
                                   errno, strerror(errno));
                   return -1;
           } else
                   VERB(1) printf("Info:: set ctstimeout(%d) from %d to %d ... OK!\n", len, 
                                   timeout[1], timeout[0]);
   
           return timeout[0];
   }
   
   
   static int
   calcTimeout(int ifid, int cor)
   {
           int slottime[2], timeout[2];
           size_t len;
           char szStr[STRSIZ];
   
           memset(szStr, 0, STRSIZ);
           snprintf(szStr, STRSIZ, SC_SLOTTIME, ifid);
           if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, &slottime[1], &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else
                   VERB(1) printf("Info:: get slottime(%d) %d ... OK!\n", len, slottime[1]);
   
           memset(szStr, 0, STRSIZ);
           snprintf(szStr, STRSIZ, SC_ACKTIMEOUT, ifid);
           if (sysctlbyname(szStr, NULL, &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else if (sysctlbyname(szStr, &timeout[1], &len, NULL, 0) == -1) {
                   printf("Error:: get sysctl %s #%d - %s\n", szStr, errno, strerror(errno));
                   return -1;
           } else
                   VERB(1) printf("Info:: get acktimeout(%d) %d ... OK!\n", len, timeout[1]);
   
           slottime[0] = (timeout[1] - 3 - cor) / 2;
           VERB(3) printf("Info:: calculated slottime=%d\n", slottime[0]);
           timeout[0] = (slottime[0] - 10) * 300;
           VERB(3) printf("Info:: calculated timeout=%d\n", timeout[0]);
   
           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 int
   readWord(u_char *mem, u_long offset)
   {
           register int timeout = ATH_ACCESS_TIMEOUT;
           u_long stat;
   
           VERB(9) printf("Reading EEPROM memory %p+%lx ...\n", mem, offset);
           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) << 16;
                   }
           }
   
           printf("Error:: EEPROM read timeout!\n");
           return -1;
   }
   
   static inline int
   writeWord(u_char *mem, u_long offset, u_short newval)
   {
           register int i = ATH_WRITE_RETRY, timeout;
           u_long pcicfg, stat;
           int chk;
   
           VERB(9) printf("Writing EEPROM memory %p+%lx ...\n", mem, offset);
           /* 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 ((u_short) (chk >> 16) == newval)
                           return chk;
                   else
                           VERB(1) printf("Write & Read don`t match 0x%04X != 0x%04X\n", newval, (u_short) (chk >> 16));
                   if (i)
                           printf("Warning:: Retrying EEPROM write ...\n");
           } while (--i);
   
           printf("Error:: EEPROM write timeout!\n");
           return -1;
   }
   
   static int
   dumpFile(const char *csName, u_char *mem)
   {
           register u_long i;
           u_short d1, d2;
           u_char eeprom[ATH_EEPROM_SIZE] = { 0 };
           int f, data;
   
           VERB(2) printf("Reading EEPROM memory %p ::\n", mem);
           for (i = 0; i < ATH_EEPROM_SIZE / 2; i++) {
                   if (!(i % 0x40)) {
                           if (i)
                                   printf("]\n");
                           printf("0x%04lX [", i * 2);
                   }
   
                   if ((data = readWord(mem, i)) == -1)
                           return -1;
                   else {
                           d1 = ((u_short)(data >> 16)) / 0x100;
                           d2 = ((u_short)(data >> 16)) % 0x100;
   
                           VERB(5) printf( "Current value 0x%04X on position 0x%04lX will change 0x%02X 0x%02X\n", 
                                           (u_short) (data >> 16), i, d1, d2);
                   }
   
                   eeprom[i * 2] = d2;
                   eeprom[i * 2 + 1] = d1;
   
                   printf(".");
                   usleep(ATH_ACCESS_WAITDOWN);
           }
           printf("]\n");
   
           VERB(2) printf("Saving EEPROM to file %s ... ", csName);
           f = open(csName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
           if (f == -1) {
                   printf("Failed!\nError:: in create file %s #%d - %s\n", csName, 
                                   errno, strerror(errno));
                   return 0;
           }
           if (write(f, eeprom, ATH_EEPROM_SIZE) == -1) {
                   printf("Failed!\nError:: in write to file %s #%d - %s\n", csName, 
                                   errno, strerror(errno));
                   close(f);
                   return 0;
           }
           close(f);
           printf("OK!\n");
           return 1;
   }
   
   static int
   flashFile(const char *csName, u_char *mem)
   {
           register u_long i;
           u_short d1;
           u_char eeprom[ATH_EEPROM_SIZE] = { 0 };
           int f, data;
   
           VERB(2) printf("Reading EEPROM from file %s ... ", csName);
           f = open(csName, O_RDONLY);
           if (f == -1) {
                   printf("Failed!\nError:: in open file %s #%d - %s\n", csName, 
                                   errno, strerror(errno));
                   return 0;
           }
           if (read(f, eeprom, ATH_EEPROM_SIZE) != ATH_EEPROM_SIZE) {
                   printf("Failed!\nError:: failed load image from file %s\n", csName);
                   close(f);
                   return 0;
           }
           close(f);
           VERB(2) printf("OK!\n");
   
           VERB(2) printf("Writing EEPROM memory %p ::\n", mem);
           for (i = 0; i < ATH_EEPROM_SIZE / 2; i++) {
                   if (!(i % 0x40)) {
                           if (i)
                                   printf("]\n");
                           printf("0x%04lX [", i * 2);
                   }
   
                   if ((data = readWord(mem, i)) == -1)
                           return -1;
                   else
                           d1 = eeprom[i * 2 + 1] * 0x100 + eeprom[i * 2];
                   VERB(5) printf("eeprom_data=0x%04X read_d1=0x%04X\n", (u_char) (data >> 16), d1);
   
                   if (((u_short) (data >> 16)) == d1)
                           printf(".");
                   else {
   
                           if (writeWord(mem, i, d1) < 1)
                                   printf("!");
                           else
                                   printf("x");
                   }
   
                   usleep(ATH_ACCESS_WAITDOWN);
           }
           printf("]\n");
   
           return 0;
   }
   
   static int
   regDomain(u_char *mem, u_short newval)
   {
           int ret, data;
   
           if ((data = readWord(mem, ATH_OFFSET_REGDOMAIN)) == -1)
                   return -1;
   
           printf("Current value 0x%04X ", (u_short) (data >> 16));
           if (newval != (u_short) -1) {
                   printf("will change to 0x%04X\n", newval);
   
                   if ((ret = writeWord(mem, ATH_OFFSET_REGDOMAIN, newval)) == -1)
                           return -1;
   
                   printf("Updated regulatory domain is 0x%04X\n", (u_short) (ret >> 16));
           } else
                   printf("\nCurrent regulatory domain is 0x%04X\n", (u_short) (data >> 16));
   
           return 0;
   }
   
   // ----------------------------------------------------
   
   int
   main(int argc, char **argv)
   {
           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, "hvRtr:w:i:d:c:u:s:")) != -1)
                   switch (ch) {
                           case 'v':
                                   Verbose++;
                                   break;
                           case 't':
                                   mode |= 2;
                                   break;
                           case 'i':
                                   ino = strtol(optarg, NULL, 0);
                                   if (ino < 0) {
                                           printf("Error:: in interface number %d\n", ino);
                                           return 1;
                                   }
                                   break;
                           case 'd':
                                   mode |= 1;
                                   dist = strtol(optarg, NULL, 0);
                                   if (dist < 1) {
                                           printf("Error:: in distance meters %d\n", dist);
                                           return 1;
                                   }
                                   break;
                           case 'c':
                                   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 = 0x40;
                                   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();
                                   return 1;
                   }
           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 & 0x40) {
                   if (argv[1])
                           newval = (u_short) strtoul(argv[1], NULL, 0);
                   else
                           newval = (u_short) -1;
           }
   
           if (mode & 1)
                   if ((ret = calcDistance(ino, dist, cor)) < 1)
                           return 2;
           if (mode & 2) {
                   if ((ret = calcTimeout(ino, cor)) < 1)
                           return 2;
                   else {
                           VERB(1)
                                   printf("Maximum approximate distance ~%d meters\n", ret);
                           else
                                   printf("~%d\n", ret);
                   }
           }
   
           if (mode & 4) {
                   if (!(basemem = devOpen(baseaddr)))
                           return 2;
                   if ((ret = readWord(basemem, offset)) == -1) {
                           devClose(basemem);
                           return 3;
                   } else
                           printf("EEPROM readed value 0x%04X\n", (u_short) (ret >> 16));
                   devClose(basemem);
           }
           if (mode & 8) {
                   if (!(basemem = devOpen(baseaddr)))
                           return 2;
                   if ((ret = writeWord(basemem, offset, newval)) == -1) {
                           devClose(basemem);
                           return 3;
                   } else
                           printf("EEPROM writed value 0x%04X\n", (u_short) (ret >> 16));
                   devClose(basemem);
           }
   
           if (mode & 0x10) {
                   if (!(basemem = devOpen(baseaddr)))
                           return 2;
                   if ((ret = dumpFile(szName, basemem)) < 1) {
                           devClose(basemem);
                           return 3;
                   }
                   devClose(basemem);
           }
           if (mode & 0x20) {
                   if (!(basemem = devOpen(baseaddr)))
                           return 2;
                   if ((ret = flashFile(szName, basemem)) < 1) {
                           devClose(basemem);
                           return 3;
                   }
                   devClose(basemem);
           }
   
           if (mode & 0x40) {
                   if (!(basemem = devOpen(baseaddr)))
                           return 2;
                   if ((ret = regDomain(basemem, newval)) < 1) {
                           devClose(basemem);
                           return 3;
                   }
                   devClose(basemem);
           }
   
           return 0;
   }

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>