|
|
| version 1.1.2.2, 2010/10/23 01:50:49 | version 1.3.4.1, 2014/01/30 01:03:20 |
|---|---|
| Line 5 | Line 5 |
| * $Author$ | * $Author$ |
| * $Id$ | * $Id$ |
| * | * |
| *************************************************************************/ | ************************************************************************* |
| The ELWIX and AITNET software is distributed under the following | |
| terms: | |
| All of the documentation and software included in the ELWIX and AITNET | |
| Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> | |
| Copyright 2004 - 2014 | |
| by Michael Pounov <misho@elwix.org>. All rights reserved. | |
| Redistribution and use in source and binary forms, with or without | |
| modification, are permitted provided that the following conditions | |
| are met: | |
| 1. Redistributions of source code must retain the above copyright | |
| notice, this list of conditions and the following disclaimer. | |
| 2. Redistributions in binary form must reproduce the above copyright | |
| notice, this list of conditions and the following disclaimer in the | |
| documentation and/or other materials provided with the distribution. | |
| 3. All advertising materials mentioning features or use of this software | |
| must display the following acknowledgement: | |
| This product includes software developed by Michael Pounov <misho@elwix.org> | |
| ELWIX - Embedded LightWeight unIX and its contributors. | |
| 4. Neither the name of AITNET nor the names of its contributors | |
| may be used to endorse or promote products derived from this software | |
| without specific prior written permission. | |
| THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND | |
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| SUCH DAMAGE. | |
| */ | |
| #include "global.h" | #include "global.h" |
| #include "athctl.h" | #include "athctl.h" |
| Line 19 Usage() | Line 56 Usage() |
| { | { |
| printf( "athCtl is tool for Atheros WiFi cards managment \n" | printf( "athCtl is tool for Atheros WiFi cards managment \n" |
| "=== %s === %s@%s ===\n\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 <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-v\t\tVerbose ...\n" |
| "\t-t\t\tGet current Atheros maximum range in meters\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-i <iface_no>\tApply to this Atheros interface number (like ath0 == 0)\n" |
| "\t-d <distance>\tMode distance, meters to target\n" | "\t-d <distance>\tMode distance, meters to target\n" |
| "\t-c <timeout>\tMode distance, mS timeouts correction\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); | "\n", compiled, compiledby, compilehost); |
| } | } |
| Line 127 calcTimeout(int ifid, int cor) | Line 178 calcTimeout(int ifid, int cor) |
| return 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 | int |
| main(int argc, char **argv) | 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; | 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, "hvRtr:w:i:d:c:u:s:")) != -1) |
| switch (ch) { | switch (ch) { |
| case 'v': | case 'v': |
| Verbose++; | Verbose++; |
| Line 162 main(int argc, char **argv) | Line 472 main(int argc, char **argv) |
| mode |= 1; | mode |= 1; |
| cor = strtol(optarg, NULL, 0); | cor = strtol(optarg, NULL, 0); |
| break; | 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': | case 'h': |
| default: | default: |
| Usage(); | Usage(); |
| Line 169 main(int argc, char **argv) | Line 498 main(int argc, char **argv) |
| } | } |
| argc -= optind; | argc -= optind; |
| argv += optind; | argv += optind; |
| if (argc && *argv) | |
| baseaddr = strtoul(*argv, NULL, 0); | |
| if (!mode) { | if (!mode) { |
| printf("Error:: not selected mode for operation ...\n"); | printf("Error:: not selected mode for operation ...\n"); |
| return 1; | 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 (mode & 1) |
| if ((ret = calcDistance(ino, dist, cor)) < 1) | if ((ret = calcDistance(ino, dist, cor)) < 1) |
| Line 186 main(int argc, char **argv) | Line 534 main(int argc, char **argv) |
| else | else |
| printf("~%d\n", ret); | 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; | return 0; |