1185743Ssam/*-
2185743Ssam * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3185743Ssam * All rights reserved.
4185743Ssam *
5185743Ssam * Redistribution and use in source and binary forms, with or without
6185743Ssam * modification, are permitted provided that the following conditions
7185743Ssam * are met:
8185743Ssam * 1. Redistributions of source code must retain the above copyright
9185743Ssam *    notice, this list of conditions and the following disclaimer,
10185743Ssam *    without modification.
11185743Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12185743Ssam *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13185743Ssam *    redistribution must be conditioned upon including a substantially
14185743Ssam *    similar Disclaimer requirement for further binary redistribution.
15185743Ssam *
16185743Ssam * NO WARRANTY
17185743Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18185743Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19185743Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20185743Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21185743Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22185743Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23185743Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24185743Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25185743Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26185743Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27185743Ssam * THE POSSIBILITY OF SUCH DAMAGES.
28185743Ssam *
29185743Ssam * $FreeBSD$
30185743Ssam */
31185743Ssam#include "diag.h"
32185743Ssam
33185743Ssam#include <getopt.h>
34185743Ssam#include <stdlib.h>
35185743Ssam#include <string.h>
36185743Ssam
37185743Ssam#include "ah.h"
38185743Ssam#include "ah_internal.h"
39185743Ssam#include "ah_eeprom.h"
40185743Ssam#include "ah_eeprom_v1.h"
41185743Ssam#include "ah_eeprom_v3.h"
42185743Ssam#include "ah_eeprom_v14.h"
43185743Ssam#include "ar5212/ar5212reg.h"
44185743Ssam#define	IS_5112(ah) \
45185743Ssam	(((ah)->ah_analog5GhzRev&0xf0) >= AR_RAD5112_SREV_MAJOR \
46185743Ssam	 && ((ah)->ah_analog5GhzRev&0xf0) < AR_RAD2316_SREV_MAJOR )
47185743Ssam#define	IS_2316(ah) \
48185743Ssam	((ah)->ah_macVersion == AR_SREV_2415)
49185743Ssam#define	IS_2413(ah) \
50185743Ssam	((ah)->ah_macVersion == AR_SREV_2413 || IS_2316(ah))
51185743Ssam#define IS_5424(ah) \
52185743Ssam	((ah)->ah_macVersion == AR_SREV_5424 || \
53185743Ssam	((ah)->ah_macVersion == AR_SREV_5413 && \
54185743Ssam	  (ah)->ah_macRev <= AR_SREV_D2PLUS_MS))
55185743Ssam#define IS_5413(ah) \
56185743Ssam	((ah)->ah_macVersion == AR_SREV_5413 || IS_5424(ah))
57185743Ssam
58185743Ssam#ifndef MAX
59185743Ssam#define	MAX(a,b)	((a) > (b) ? (a) : (b))
60185743Ssam#endif
61185743Ssam
62185743Ssamstatic void printPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n);
63185743Ssamstatic void printPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n);
64185743Ssamstatic void printRevs(FILE *fd, const HAL_REVS *revs);
65185743Ssam
66185743Ssamstatic void
67185743Ssamusage(const char *progname)
68185743Ssam{
69185743Ssam	fprintf(stderr, "usage: %s [-v] [-i dev]\n", progname);
70185743Ssam	exit(1);
71185743Ssam}
72185743Ssam
73185743Ssamint
74185743Ssammain(int argc, char *argv[])
75185743Ssam{
76185743Ssam	int s, i, verbose = 0, c;
77185743Ssam	struct ath_diag atd;
78185743Ssam	const char *ifname;
79185743Ssam	HAL_REVS revs;
80185743Ssam	u_int16_t pcdacTable[MAX(PWR_TABLE_SIZE,PWR_TABLE_SIZE_2413)];
81218057Sadrian	u_int16_t ratesArray[37];
82185743Ssam	u_int nrates, npcdac;
83185743Ssam
84185743Ssam	s = socket(AF_INET, SOCK_DGRAM, 0);
85185743Ssam	if (s < 0)
86185743Ssam		err(1, "socket");
87185743Ssam	ifname = getenv("ATH");
88185743Ssam	if (!ifname)
89185743Ssam		ifname = ATH_DEFAULT;
90185743Ssam	while ((c = getopt(argc, argv, "i:v")) != -1)
91185743Ssam		switch (c) {
92185743Ssam		case 'i':
93185743Ssam			ifname = optarg;
94185743Ssam			break;
95185743Ssam		case 'v':
96185743Ssam			verbose++;
97185743Ssam			break;
98185743Ssam		default:
99185743Ssam			usage(argv[0]);
100185743Ssam		}
101185743Ssam	strncpy(atd.ad_name, ifname, sizeof (atd.ad_name));
102185743Ssam
103185743Ssam	atd.ad_id = HAL_DIAG_REVS;
104185743Ssam	atd.ad_out_data = (caddr_t) &revs;
105185743Ssam	atd.ad_out_size = sizeof(revs);
106185743Ssam	if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
107185743Ssam		err(1, atd.ad_name);
108185743Ssam
109185743Ssam	if (verbose)
110185743Ssam		printRevs(stdout, &revs);
111185743Ssam
112185743Ssam	atd.ad_id = HAL_DIAG_TXRATES;
113185743Ssam	atd.ad_out_data = (caddr_t) ratesArray;
114185743Ssam	atd.ad_out_size = sizeof(ratesArray);
115185743Ssam	if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
116185743Ssam		err(1, atd.ad_name);
117185743Ssam	nrates = sizeof(ratesArray) / sizeof(u_int16_t);
118185743Ssam
119185743Ssam	atd.ad_id = HAL_DIAG_PCDAC;
120185743Ssam	atd.ad_out_data = (caddr_t) pcdacTable;
121185743Ssam	atd.ad_out_size = sizeof(pcdacTable);
122185743Ssam	if (ioctl(s, SIOCGATHDIAG, &atd) < 0)
123185743Ssam		err(1, atd.ad_name);
124185743Ssam	if (IS_2413(&revs) || IS_5413(&revs))
125185743Ssam		npcdac = PWR_TABLE_SIZE_2413;
126185743Ssam	else
127185743Ssam		npcdac = PWR_TABLE_SIZE;
128185743Ssam
129185743Ssam	printf("PCDAC table:\n");
130185743Ssam	printPcdacTable(stdout, pcdacTable, npcdac);
131185743Ssam
132185743Ssam	printf("Power per rate table:\n");
133185743Ssam	printPowerPerRate(stdout, ratesArray, nrates);
134185743Ssam
135185743Ssam	return 0;
136185743Ssam}
137185743Ssam
138185743Ssamstatic void
139185743SsamprintPcdacTable(FILE *fd, u_int16_t pcdac[], u_int n)
140185743Ssam{
141185743Ssam	int i, halfRates = n/2;
142185743Ssam
143185743Ssam	for (i = 0; i < halfRates; i += 2)
144185743Ssam		fprintf(fd, "[%2u] %04x %04x [%2u] %04x %04x\n",
145185743Ssam			i, pcdac[2*i + 1], pcdac[2*i],
146185743Ssam			i+1, pcdac[2*(i+1) + 1], pcdac[2*(i+1)]);
147185743Ssam}
148185743Ssam
149185743Ssamstatic void
150185743SsamprintPowerPerRate(FILE *fd, u_int16_t ratesArray[], u_int n)
151185743Ssam{
152185743Ssam	const char *rateString[] = {
153185743Ssam		" 6mb OFDM", " 9mb OFDM", "12mb OFDM", "18mb OFDM",
154185743Ssam		"24mb OFDM", "36mb OFDM", "48mb OFDM", "54mb OFDM",
155185743Ssam		"1L   CCK ", "2L   CCK ", "2S   CCK ", "5.5L CCK ",
156185743Ssam		"5.5S CCK ", "11L  CCK ", "11S  CCK ", "XR       "
157185743Ssam	};
158185743Ssam	int i, halfRates = n/2;
159185743Ssam
160185743Ssam	for (i = 0; i < halfRates; i++)
161185743Ssam		fprintf(fd, " %s %3d.%1d dBm | %s %3d.%1d dBm\n",
162185743Ssam			 rateString[i], ratesArray[i]/2,
163185743Ssam			 (ratesArray[i] %2) * 5,
164185743Ssam			 rateString[i + halfRates],
165185743Ssam			 ratesArray[i + halfRates]/2,
166185743Ssam			 (ratesArray[i + halfRates] %2) *5);
167185743Ssam}
168185743Ssam
169185743Ssamstatic void
170185743SsamprintRevs(FILE *fd, const HAL_REVS *revs)
171185743Ssam{
172185743Ssam	const char *rfbackend;
173185743Ssam
174185743Ssam	fprintf(fd, "PCI device id 0x%x subvendor id 0x%x\n",
175185743Ssam		revs->ah_devid, revs->ah_subvendorid);
176185743Ssam	fprintf(fd, "mac %d.%d phy %d.%d"
177185743Ssam		, revs->ah_macVersion, revs->ah_macRev
178185743Ssam		, revs->ah_phyRev >> 4, revs->ah_phyRev & 0xf
179185743Ssam	);
180185743Ssam	rfbackend = IS_5413(revs) ? "5413" :
181185743Ssam		    IS_2413(revs) ? "2413" :
182185743Ssam		    IS_5112(revs) ? "5112" :
183185743Ssam				    "5111";
184185743Ssam	if (revs->ah_analog5GhzRev && revs->ah_analog2GhzRev)
185185743Ssam		fprintf(fd, " 5ghz radio %d.%d 2ghz radio %d.%d (%s)\n"
186185743Ssam			, revs->ah_analog5GhzRev >> 4
187185743Ssam			, revs->ah_analog5GhzRev & 0xf
188185743Ssam			, revs->ah_analog2GhzRev >> 4
189185743Ssam			, revs->ah_analog2GhzRev & 0xf
190185743Ssam			, rfbackend
191185743Ssam		);
192185743Ssam	else
193185743Ssam		fprintf(fd, " radio %d.%d (%s)\n"
194185743Ssam			, revs->ah_analog5GhzRev >> 4
195185743Ssam			, revs->ah_analog5GhzRev & 0xf
196185743Ssam			, rfbackend
197185743Ssam		);
198185743Ssam}
199