xref: /freebsd/tools/tools/ath/athpow/athpow.c (revision b3e76948)
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