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 #include "diag.h"
30
31 #include <getopt.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "ah.h"
36 #include "ah_internal.h"
37 #include "ah_eeprom.h"
38 #include "ah_eeprom_v1.h"
39 #include "ah_eeprom_v3.h"
40 #include "ah_eeprom_v14.h"
41 #include "ar5212/ar5212reg.h"
42 #define IS_5112(ah) \
43 (((ah)->ah_analog5GhzRev&0xf0) >= AR_RAD5112_SREV_MAJOR \
44 && ((ah)->ah_analog5GhzRev&0xf0) < AR_RAD2316_SREV_MAJOR )
45 #define IS_2316(ah) \
46 ((ah)->ah_macVersion == AR_SREV_2415)
47 #define IS_2413(ah) \
48 ((ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah))
49 #define IS_5424(ah) \
50 ((ah)->ah_macVersion == AR_SREV_5424 || \
51 ((ah)->ah_macVersion == AR_SREV_5413 && \
52 (ah)->ah_macRev <= AR_SREV_D2PLUS_MS))
53 #define IS_5413(ah) \
54 ((ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah))
55
56 #ifndef MAX
57 #define MAX(a,b) ((a) > (b) ? (a) : (b))
58 #endif
59
60 static void printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n);
61 static void printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n);
62 static void printRevs(FILE *fd, const HAL_REVS *revs);
63
64 static void
usage(const char * progname)65 usage(const char *progname)
66 {
67 fprintf(stderr, "usage: %s [-v] [-i dev]\n", progname);
68 exit(1);
69 }
70
71 int
main(int argc,char * argv[])72 main(int argc, char *argv[])
73 {
74 int s, i, verbose = 0, c;
75 struct ath_diag atd;
76 const char *ifname;
77 HAL_REVS revs;
78 u_int16_t pcdacTable[MAX(PWR_TABLE_SIZE,PWR_TABLE_SIZE_2413)];
79 u_int16_t ratesArray[37];
80 u_int nrates, npcdac;
81
82 s = socket(AF_INET, SOCK_DGRAM, 0);
83 if (s < 0)
84 err(1, "socket");
85 ifname = getenv("ATH");
86 if (!ifname)
87 ifname = ATH_DEFAULT;
88 while ((c = getopt(argc, argv, "i:v")) != -1)
89 switch (c) {
90 case 'i':
91 ifname = optarg;
92 break;
93 case 'v':
94 verbose++;
95 break;
96 default:
97 usage(argv[0]);
98 }
99 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
100
101 atd.ad_id = HAL_DIAG_REVS;
102 atd.ad_out_data = (caddr_t) &revs;
103 atd.ad_out_size = sizeof(revs);
104 if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
105 err(1, atd.ad_name);
106
107 if (verbose)
108 printRevs(stdout, &revs);
109
110 atd.ad_id = HAL_DIAG_TXRATES;
111 atd.ad_out_data = (caddr_t) ratesArray;
112 atd.ad_out_size = sizeof(ratesArray);
113 if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
114 err(1, atd.ad_name);
115 nrates = sizeof(ratesArray) / sizeof(u_int16_t);
116
117 atd.ad_id = HAL_DIAG_PCDAC;
118 atd.ad_out_data = (caddr_t) pcdacTable;
119 atd.ad_out_size = sizeof(pcdacTable);
120 if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
121 err(1, atd.ad_name);
122 if (IS_2413(&revs) || IS_5413(&revs))
123 npcdac = PWR_TABLE_SIZE_2413;
124 else
125 npcdac = PWR_TABLE_SIZE;
126
127 printf("PCDAC table:\n");
128 printPcdacTable(stdout, pcdacTable, npcdac);
129
130 printf("Power per rate table:\n");
131 printPowerPerRate(stdout, ratesArray, nrates);
132
133 return 0;
134 }
135
136 static void
printPcdacTable(FILE * fd,u_int16_t pcdac[],u_int n)137 printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n)
138 {
139 int i, halfRates = n/2;
140
141 for (i = 0; i < halfRates; i += 2)
142 fprintf(fd, "[%2u] %04x %04x [%2u] %04x %04x\n",
143 i, pcdac[2*i + 1], pcdac[2*i],
144 i+1, pcdac[2*(i+1) + 1], pcdac[2*(i+1)]);
145 }
146
147 static void
printPowerPerRate(FILE * fd,u_int16_t ratesArray[],u_int n)148 printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n)
149 {
150 const char *rateString[] = {
151 " 6mb OFDM", " 9mb OFDM", "12mb OFDM", "18mb OFDM",
152 "24mb OFDM", "36mb OFDM", "48mb OFDM", "54mb OFDM",
153 "1L CCK ", "2L CCK ", "2S CCK ", "5.5L CCK ",
154 "5.5S CCK ", "11L CCK ", "11S CCK ", "XR "
155 };
156 int i, halfRates = n/2;
157
158 for (i = 0; i < halfRates; i++)
159 fprintf(fd, " %s %3d.%1d dBm | %s %3d.%1d dBm\n",
160 rateString[i], ratesArray[i]/2,
161 (ratesArray[i] %2) * 5,
162 rateString[i + halfRates],
163 ratesArray[i + halfRates]/2,
164 (ratesArray[i + halfRates] %2) *5);
165 }
166
167 static void
printRevs(FILE * fd,const HAL_REVS * revs)168 printRevs(FILE *fd, const HAL_REVS *revs)
169 {
170 const char *rfbackend;
171
172 fprintf(fd, "PCI device id 0x%x subvendor id 0x%x\n",
173 revs->ah_devid, revs->ah_subvendorid);
174 fprintf(fd, "mac %d.%d phy %d.%d"
175 , revs->ah_macVersion, revs->ah_macRev
176 , revs->ah_phyRev >> 4, revs->ah_phyRev & 0xf
177 );
178 rfbackend = IS_5413(revs) ? "5413" :
179 IS_2413(revs) ? "2413" :
180 IS_5112(revs) ? "5112" :
181 "5111";
182 if (revs->ah_analog5GhzRev && revs->ah_analog2GhzRev)
183 fprintf(fd, " 5ghz radio %d.%d 2ghz radio %d.%d (%s)\n"
184 , revs->ah_analog5GhzRev >> 4
185 , revs->ah_analog5GhzRev & 0xf
186 , revs->ah_analog2GhzRev >> 4
187 , revs->ah_analog2GhzRev & 0xf
188 , rfbackend
189 );
190 else
191 fprintf(fd, " radio %d.%d (%s)\n"
192 , revs->ah_analog5GhzRev >> 4
193 , revs->ah_analog5GhzRev & 0xf
194 , rfbackend
195 );
196 }
197