1 /*- 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: src/tools/tools/ath/athpow/athpow.c,v 1.1 2008/12/07 19:17:33 sam Exp $ 30 */ 31 #include "diag.h" 32 33 #include <getopt.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "ah.h" 38 #include "ah_internal.h" 39 #include "ah_eeprom.h" 40 #include "ah_eeprom_v1.h" 41 #include "ah_eeprom_v3.h" 42 #include "ah_eeprom_v14.h" 43 #include "ar5212/ar5212reg.h" 44 #define IS_5112(ah) \ 45 (((ah)->ah_analog5GhzRev&0xf0) >= AR_RAD5112_SREV_MAJOR \ 46 && ((ah)->ah_analog5GhzRev&0xf0) < AR_RAD2316_SREV_MAJOR ) 47 #define IS_2316(ah) \ 48 ((ah)->ah_macVersion == AR_SREV_2415) 49 #define IS_2413(ah) \ 50 ((ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah)) 51 #define IS_5424(ah) \ 52 ((ah)->ah_macVersion == AR_SREV_5424 || \ 53 ((ah)->ah_macVersion == AR_SREV_5413 && \ 54 (ah)->ah_macRev <= AR_SREV_D2PLUS_MS)) 55 #define IS_5413(ah) \ 56 ((ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah)) 57 58 #ifndef MAX 59 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 60 #endif 61 62 static void printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n); 63 static void printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n); 64 static void printRevs(FILE *fd, const HAL_REVS *revs); 65 66 static void 67 usage(const char *progname) 68 { 69 fprintf(stderr, "usage: %s [-v] [-i dev]\n", progname); 70 exit(1); 71 } 72 73 int 74 main(int argc, char *argv[]) 75 { 76 int s, i, verbose = 0, c; 77 struct ath_diag atd; 78 const char *ifname; 79 HAL_REVS revs; 80 u_int16_t pcdacTable[MAX(PWR_TABLE_SIZE,PWR_TABLE_SIZE_2413)]; 81 u_int16_t ratesArray[16]; 82 u_int nrates, npcdac; 83 84 s = socket(AF_INET, SOCK_DGRAM, 0); 85 if (s < 0) 86 err(1, "socket"); 87 ifname = getenv("ATH"); 88 if (!ifname) 89 ifname = ATH_DEFAULT; 90 while ((c = getopt(argc, argv, "i:v")) != -1) 91 switch (c) { 92 case 'i': 93 ifname = optarg; 94 break; 95 case 'v': 96 verbose++; 97 break; 98 default: 99 usage(argv[0]); 100 } 101 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); 102 103 atd.ad_id = HAL_DIAG_REVS; 104 atd.ad_out_data = (caddr_t) &revs; 105 atd.ad_out_size = sizeof(revs); 106 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 107 err(1, atd.ad_name); 108 109 if (verbose) 110 printRevs(stdout, &revs); 111 112 atd.ad_id = HAL_DIAG_TXRATES; 113 atd.ad_out_data = (caddr_t) ratesArray; 114 atd.ad_out_size = sizeof(ratesArray); 115 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 116 err(1, atd.ad_name); 117 nrates = sizeof(ratesArray) / sizeof(u_int16_t); 118 119 atd.ad_id = HAL_DIAG_PCDAC; 120 atd.ad_out_data = (caddr_t) pcdacTable; 121 atd.ad_out_size = sizeof(pcdacTable); 122 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 123 err(1, atd.ad_name); 124 if (IS_2413(&revs) || IS_5413(&revs)) 125 npcdac = PWR_TABLE_SIZE_2413; 126 else 127 npcdac = PWR_TABLE_SIZE; 128 129 printf("PCDAC table:\n"); 130 printPcdacTable(stdout, pcdacTable, npcdac); 131 132 printf("Power per rate table:\n"); 133 printPowerPerRate(stdout, ratesArray, nrates); 134 135 return 0; 136 } 137 138 static void 139 printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n) 140 { 141 int i, halfRates = n/2; 142 143 for (i = 0; i < halfRates; i += 2) 144 fprintf(fd, "[%2u] %04x %04x [%2u] %04x %04x\n", 145 i, pcdac[2*i + 1], pcdac[2*i], 146 i+1, pcdac[2*(i+1) + 1], pcdac[2*(i+1)]); 147 } 148 149 static void 150 printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n) 151 { 152 const char *rateString[] = { 153 " 6mb OFDM", " 9mb OFDM", "12mb OFDM", "18mb OFDM", 154 "24mb OFDM", "36mb OFDM", "48mb OFDM", "54mb OFDM", 155 "1L CCK ", "2L CCK ", "2S CCK ", "5.5L CCK ", 156 "5.5S CCK ", "11L CCK ", "11S CCK ", "XR " 157 }; 158 int i, halfRates = n/2; 159 160 for (i = 0; i < halfRates; i++) 161 fprintf(fd, " %s %3d.%1d dBm | %s %3d.%1d dBm\n", 162 rateString[i], ratesArray[i]/2, 163 (ratesArray[i] %2) * 5, 164 rateString[i + halfRates], 165 ratesArray[i + halfRates]/2, 166 (ratesArray[i + halfRates] %2) *5); 167 } 168 169 static void 170 printRevs(FILE *fd, const HAL_REVS *revs) 171 { 172 const char *rfbackend; 173 174 fprintf(fd, "PCI device id 0x%x subvendor id 0x%x\n", 175 revs->ah_devid, revs->ah_subvendorid); 176 fprintf(fd, "mac %d.%d phy %d.%d" 177 , revs->ah_macVersion, revs->ah_macRev 178 , revs->ah_phyRev >> 4, revs->ah_phyRev & 0xf 179 ); 180 rfbackend = IS_5413(revs) ? "5413" : 181 IS_2413(revs) ? "2413" : 182 IS_5112(revs) ? "5112" : 183 "5111"; 184 if (revs->ah_analog5GhzRev && revs->ah_analog2GhzRev) 185 fprintf(fd, " 5ghz radio %d.%d 2ghz radio %d.%d (%s)\n" 186 , revs->ah_analog5GhzRev >> 4 187 , revs->ah_analog5GhzRev & 0xf 188 , revs->ah_analog2GhzRev >> 4 189 , revs->ah_analog2GhzRev & 0xf 190 , rfbackend 191 ); 192 else 193 fprintf(fd, " radio %d.%d (%s)\n" 194 , revs->ah_analog5GhzRev >> 4 195 , revs->ah_analog5GhzRev & 0xf 196 , rfbackend 197 ); 198 } 199