xref: /dragonfly/tools/tools/ath/athpow/athpow.c (revision c8860c9a)
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, MERCHANTABILITY
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