1118824Sharti/*
2118824Sharti * Copyright (c) 2001-2003
3118824Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4118824Sharti * 	All rights reserved.
5118824Sharti *
6118824Sharti * Redistribution and use in source and binary forms, with or without
7118824Sharti * modification, are permitted provided that the following conditions
8118824Sharti * are met:
9118824Sharti * 1. Redistributions of source code must retain the above copyright
10118824Sharti *    notice, this list of conditions and the following disclaimer.
11118824Sharti * 2. Redistributions in binary form must reproduce the above copyright
12118824Sharti *    notice, this list of conditions and the following disclaimer in the
13118824Sharti *    documentation and/or other materials provided with the distribution.
14118824Sharti *
15118824Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16118824Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17118824Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18118824Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19118824Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20118824Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21118824Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22118824Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23118824Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24118824Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25118824Sharti * SUCH DAMAGE.
26118824Sharti *
27118824Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28118824Sharti */
29118824Sharti#include <sys/cdefs.h>
30118824Sharti__FBSDID("$FreeBSD$");
31118824Sharti
32118824Sharti#include <sys/types.h>
33118824Sharti#include <sys/sysctl.h>
34118824Sharti#include <sys/ioctl.h>
35118824Sharti#include <sys/socket.h>
36118824Sharti#include <sys/queue.h>
37118824Sharti#include <net/if.h>
38118824Sharti#include <net/if_mib.h>
39118824Sharti#include <net/if_types.h>
40118824Sharti#include <net/if_atm.h>
41118824Sharti#include <net/if_media.h>
42118824Sharti#include <netnatm/natm.h>
43118824Sharti#include <dev/utopia/utopia.h>
44118824Sharti#include <dev/utopia/suni.h>
45118824Sharti#include <dev/utopia/idtphy.h>
46118824Sharti
47118824Sharti#include "atmconfig.h"
48118824Sharti#include "private.h"
49118824Sharti#include "diag.h"
50118824Sharti
51118824Shartistatic void diag_list(int, char *[]);
52118824Shartistatic void diag_config(int, char *[]);
53118824Shartistatic void diag_vcc(int, char *[]);
54118824Shartistatic void diag_phy_show(int, char *[]);
55118824Shartistatic void diag_phy_set(int, char *[]);
56118824Shartistatic void diag_phy_print(int, char *[]);
57118824Shartistatic void diag_phy_stats(int, char *[]);
58118824Shartistatic void diag_stats(int, char *[]);
59118824Sharti
60227081Sedstatic const struct cmdtab diag_phy_tab[] = {
61118824Sharti	{ "show",	NULL, 		diag_phy_show },
62118824Sharti	{ "set",	NULL, 		diag_phy_set },
63118824Sharti	{ "stats",	NULL,		diag_phy_stats },
64118824Sharti	{ "print",	NULL,		diag_phy_print },
65118824Sharti	{ NULL,		NULL,		NULL },
66118824Sharti};
67118824Sharti
68118824Sharticonst struct cmdtab diag_tab[] = {
69118824Sharti	{ "list",	NULL,		diag_list },
70118824Sharti	{ "config",	NULL,		diag_config },
71118824Sharti	{ "phy",	diag_phy_tab,	NULL },
72118824Sharti	{ "stats",	NULL,		diag_stats },
73118824Sharti	{ "vcc",	NULL,		diag_vcc },
74118824Sharti	{ NULL, 	NULL, 		NULL }
75118824Sharti};
76118824Sharti
77118824Shartistatic const struct utopia_print suni_lite[] = { SUNI_PRINT_LITE };
78118824Shartistatic const struct utopia_print suni_ultra[] = { SUNI_PRINT_ULTRA };
79118824Shartistatic const struct utopia_print suni_622[] = { SUNI_PRINT_622 };
80118824Shartistatic const struct utopia_print idt77105[] = { IDTPHY_PRINT_77105 };
81118824Shartistatic const struct utopia_print idt77155[] = { IDTPHY_PRINT_77155 };
82118824Sharti
83118824Shartistatic const struct {
84118824Sharti	const struct utopia_print *tab;
85118824Sharti	u_int len;
86118824Sharti	u_int type;
87118824Sharti} phy_print[] = {
88118824Sharti	{ suni_lite, sizeof(suni_lite) / sizeof(suni_lite[0]),
89118824Sharti	  UTP_TYPE_SUNI_LITE },
90118824Sharti	{ suni_ultra, sizeof(suni_ultra) / sizeof(suni_ultra[0]),
91118824Sharti	  UTP_TYPE_SUNI_ULTRA },
92118824Sharti	{ suni_622, sizeof(suni_622) / sizeof(suni_622[0]),
93118824Sharti	  UTP_TYPE_SUNI_622 },
94118824Sharti	{ idt77105, sizeof(idt77105) / sizeof(idt77105[0]),
95118824Sharti	  UTP_TYPE_IDT77105 },
96118824Sharti	{ idt77155, sizeof(idt77155) / sizeof(idt77155[0]),
97118824Sharti	  UTP_TYPE_IDT77155 },
98118824Sharti};
99118824Sharti
100118824Shartistatic const u_int utopia_addreg[] = { UTP_REG_ADD };
101118824Sharti
102118824Sharti/*
103118824Sharti * Driver statistics printing
104118824Sharti */
105118824Shartistatic const char *const print_stats_pca200e[] = {
106118824Sharti	"cmd_queue_full:",
107118824Sharti	"get_stat_errors:",
108118824Sharti	"clr_stat_errors:",
109118824Sharti	"get_prom_errors:",
110118824Sharti	"suni_reg_errors:",
111118824Sharti	"tx_queue_full:",
112118824Sharti	"tx_queue_almost_full:",
113118824Sharti	"tx_pdu2big:",
114118824Sharti	"tx_too_many_segs:",
115118824Sharti	"tx_retry:",
116118824Sharti	"fix_empty:",
117118824Sharti	"fix_addr_copy:",
118118824Sharti	"fix_addr_noext:",
119118824Sharti	"fix_addr_ext:",
120118824Sharti	"fix_len_noext:",
121118824Sharti	"fix_len_copy:",
122118824Sharti	"fix_len:",
123118824Sharti	"rx_badvc:",
124118824Sharti	"rx_closed:",
125118824Sharti	NULL
126118824Sharti};
127118824Shartistatic const char *const print_stats_he[] = {
128118824Sharti	"tdprq_full:",
129118824Sharti	"hbuf_error:",
130118824Sharti	"crc_error:",
131118824Sharti	"len_error:",
132118824Sharti	"flow_closed:",
133118824Sharti	"flow_drop:",
134118824Sharti	"tpd_no_mem:",
135118824Sharti	"rx_seg:",
136118824Sharti	"empty_hbuf:",
137118824Sharti	"short_aal5:",
138118824Sharti	"badlen_aal5:",
139118824Sharti	"bug_bad_isw:",
140118824Sharti	"bug_no_irq_upd:",
141118824Sharti	"itype_tbrq:",
142118824Sharti	"itype_tpd:",
143118824Sharti	"itype_rbps:",
144118824Sharti	"itype_rbpl:",
145118824Sharti	"itype_rbrq:",
146118824Sharti	"itype_rbrqt:",
147118824Sharti	"itype_unknown:",
148118824Sharti	"itype_phys:",
149118824Sharti	"itype_err:",
150118824Sharti	"defrag:",
151118824Sharti	"mcc:",
152118824Sharti	"oec:",
153118824Sharti	"dcc:",
154118824Sharti	"cec:",
155121676Sharti	"no_rcv_mbuf:",
156118824Sharti	NULL
157118824Sharti};
158118824Shartistatic const char *const print_stats_eni[] = {
159118824Sharti	"ttrash:",
160118824Sharti	"mfixaddr:",
161118824Sharti	"mfixlen:",
162118824Sharti	"mfixfail:",
163118824Sharti	"txmbovr:",
164118824Sharti	"dmaovr:",
165118824Sharti	"txoutspace:",
166118824Sharti	"txdtqout:",
167118824Sharti	"launch:",
168118824Sharti	"hwpull:",
169118824Sharti	"swadd:",
170118824Sharti	"rxqnotus:",
171118824Sharti	"rxqus:",
172118824Sharti	"rxdrqout:",
173118824Sharti	"rxmbufout:",
174118824Sharti	"txnomap:",
175118824Sharti	"vtrash:",
176118824Sharti	"otrash:",
177118824Sharti	NULL
178118824Sharti};
179118824Sharti
180118824Shartistatic const char *const print_stats_idt77211[] = {
181118824Sharti	"need_copy:",
182118824Sharti	"copy_failed:",
183118824Sharti	"out_of_tbds:",
184118824Sharti	"no_txmaps:",
185118824Sharti	"tx_load_err:",
186118824Sharti	"tx_qfull:",
187118824Sharti	NULL
188118824Sharti};
189118824Shartistatic const char *const print_stats_idt77252[] = {
190118824Sharti	"raw_cells:",
191118824Sharti	"raw_no_vcc:",
192118824Sharti	"raw_no_buf:",
193118824Sharti	"tx_qfull:",
194118824Sharti	"tx_out_of_tbds:",
195118824Sharti	"tx_out_of_maps:",
196118824Sharti	"tx_load_err:",
197118824Sharti	NULL
198118824Sharti};
199125018Shartistatic const char *const print_stats_virtual[] = {
200125018Sharti	"dummy:",
201125018Sharti	NULL
202125018Sharti};
203118824Shartistatic const char *const *const print_stats[] = {
204118824Sharti	[ATM_DEVICE_UNKNOWN] =		NULL,
205118824Sharti	[ATM_DEVICE_PCA200E] =		print_stats_pca200e,
206118824Sharti	[ATM_DEVICE_HE155] =		print_stats_he,
207118824Sharti	[ATM_DEVICE_HE622] =		print_stats_he,
208118824Sharti	[ATM_DEVICE_ENI155P] =		print_stats_eni,
209118824Sharti	[ATM_DEVICE_ADP155P] =		print_stats_eni,
210118824Sharti	[ATM_DEVICE_FORELE25] =		print_stats_idt77211,
211118824Sharti	[ATM_DEVICE_FORELE155] =	print_stats_idt77211,
212118824Sharti	[ATM_DEVICE_NICSTAR25] =	print_stats_idt77211,
213118824Sharti	[ATM_DEVICE_NICSTAR155] =	print_stats_idt77211,
214118824Sharti	[ATM_DEVICE_IDTABR25] =		print_stats_idt77252,
215118824Sharti	[ATM_DEVICE_IDTABR155] =	print_stats_idt77252,
216118824Sharti	[ATM_DEVICE_PROATM25] =		print_stats_idt77252,
217118824Sharti	[ATM_DEVICE_PROATM155] =	print_stats_idt77252,
218125018Sharti	[ATM_DEVICE_VIRTUAL] =		print_stats_virtual,
219118824Sharti};
220118824Sharti
221118824Shartistruct diagif_list diagif_list = TAILQ_HEAD_INITIALIZER(diagif_list);
222118824Sharti
223118824Sharti/*
224118824Sharti * Fetch a phy sysctl
225118824Sharti */
226125018Shartistatic int
227125018Shartiphy_fetch(const char *ifname, const char *var, void *val, size_t len,
228125018Sharti    int err_fatal)
229118824Sharti{
230118824Sharti	char *str;
231118824Sharti
232118824Sharti	if (asprintf(&str, "hw.atm.%s.phy_%s", ifname, var) == -1)
233118824Sharti		err(1, NULL);
234126643Smarkm	if (sysctlbyname(str, val, &len, NULL, 0) == -1) {
235125018Sharti		if (err_fatal || errno != ENOENT)
236125018Sharti			err(1, "%s", str);
237125018Sharti		free(str);
238125018Sharti		return (-1);
239125018Sharti	}
240118824Sharti	free(str);
241125018Sharti	return (0);
242118824Sharti}
243118824Sharti
244118824Sharti/*
245118824Sharti * Fetch the list of all ATM network interfaces and their MIBs.
246118824Sharti */
247118824Shartivoid
248118824Shartidiagif_fetch(void)
249118824Sharti{
250118824Sharti	size_t len;
251118824Sharti	int count;
252118824Sharti	int name[6];
253118824Sharti	struct ifmibdata mib;
254118824Sharti	struct ifatm_mib atm;
255118824Sharti	int idx;
256118824Sharti	struct diagif *d;
257118824Sharti
258118824Sharti	while ((d = TAILQ_FIRST(&diagif_list)) != NULL) {
259118824Sharti		if (d->vtab != NULL)
260118824Sharti			free(d->vtab);
261118824Sharti		TAILQ_REMOVE(&diagif_list, d, link);
262118824Sharti		free(d);
263118824Sharti	}
264118824Sharti
265118824Sharti	len = sizeof(count);
266118824Sharti	if (sysctlbyname("net.link.generic.system.ifcount", &count, &len,
267118824Sharti	    NULL, 0) == -1)
268118824Sharti		err(1, "ifcount");
269118824Sharti
270118824Sharti	name[0] = CTL_NET;
271118824Sharti	name[1] = PF_LINK;
272118824Sharti	name[2] = NETLINK_GENERIC;
273118824Sharti	name[3] = IFMIB_IFDATA;
274118824Sharti
275118824Sharti	for (idx = 1; idx <= count; idx++) {
276118824Sharti		name[4] = idx;
277118824Sharti		name[5] = IFDATA_GENERAL;
278118824Sharti		len = sizeof(mib);
279118824Sharti		if (sysctl(name, 6, &mib, &len, NULL, 0) == -1)
280118824Sharti			err(1, "interface %d: general mib", idx);
281118824Sharti		if (mib.ifmd_data.ifi_type == IFT_ATM) {
282118824Sharti			name[5] = IFDATA_LINKSPECIFIC;
283118824Sharti			len = sizeof(atm);
284118824Sharti			if (sysctl(name, 6, &atm, &len, NULL, 0) == -1)
285118824Sharti				err(1, "interface %d: ATM mib", idx);
286118824Sharti
287118824Sharti			d = malloc(sizeof(*d));
288118824Sharti			if (d == NULL)
289118824Sharti				err(1, NULL);
290118824Sharti			bzero(d, sizeof(*d));
291118824Sharti			d->mib = atm;
292118824Sharti			d->index = idx;
293118824Sharti			strcpy(d->ifname, mib.ifmd_name);
294118824Sharti			TAILQ_INSERT_TAIL(&diagif_list, d, link);
295118824Sharti
296125018Sharti			if (phy_fetch(d->ifname, "type", &d->phy_type,
297125018Sharti			    sizeof(d->phy_type), 0) == 0) {
298125018Sharti				d->phy_present = 1;
299125018Sharti				phy_fetch(d->ifname, "loopback",
300125018Sharti				    &d->phy_loopback,
301125018Sharti				    sizeof(d->phy_loopback), 1);
302125018Sharti				phy_fetch(d->ifname, "name", &d->phy_name,
303125018Sharti				    sizeof(d->phy_name), 1);
304125018Sharti				phy_fetch(d->ifname, "state", &d->phy_state,
305125018Sharti				    sizeof(d->phy_state), 1);
306125018Sharti				phy_fetch(d->ifname, "carrier", &d->phy_carrier,
307125018Sharti				    sizeof(d->phy_carrier), 1);
308125018Sharti			}
309118824Sharti		}
310118824Sharti	}
311118824Sharti}
312118824Sharti
313118824Sharti/*
314118824Sharti * "<radix><bit>STRING\011<mask><pattern>STRING\012<mask><radix>STRING"
315118824Sharti */
316118824Shartistatic char *
317118824Shartiprintb8(uint32_t val, const char *descr)
318118824Sharti{
319118824Sharti	static char buffer[1000];
320118824Sharti	char *ptr;
321118824Sharti	int tmp = 0;
322118824Sharti	u_char mask, pattern;
323118824Sharti
324118824Sharti	if (*descr++ == '\010')
325118824Sharti		sprintf(buffer, "%#o", val);
326118824Sharti	else
327118824Sharti		sprintf(buffer, "%#x", val);
328118824Sharti	ptr = buffer + strlen(buffer);
329118824Sharti
330118824Sharti	*ptr++ = '<';
331118824Sharti	while (*descr) {
332118824Sharti		if (*descr == '\11') {
333118824Sharti			descr++;
334118824Sharti			mask = *descr++;
335118824Sharti			pattern = *descr++;
336118824Sharti			if ((val & mask) == pattern) {
337118824Sharti				if (tmp++)
338118824Sharti					*ptr++ = ',';
339118824Sharti				while (*descr >= ' ')
340118824Sharti					*ptr++ = *descr++;
341118824Sharti			} else {
342118824Sharti				while (*descr >= ' ')
343118824Sharti					descr++;
344118824Sharti			}
345118824Sharti		} else if (*descr == '\12') {
346118824Sharti			descr++;
347118824Sharti			mask = *descr++;
348118824Sharti			pattern = *descr++;
349118824Sharti			if (tmp++)
350118824Sharti				*ptr++ = ',';
351118824Sharti			while (*descr >= ' ')
352118824Sharti				*ptr++ = *descr++;
353118824Sharti			*ptr++ = '=';
354118824Sharti			if (pattern == 8)
355118824Sharti				sprintf(ptr, "%#o",
356118824Sharti				    (val & mask) >> (ffs(mask)-1));
357118824Sharti			else if (pattern == 10)
358118824Sharti				sprintf(ptr, "%u",
359118824Sharti				    (val & mask) >> (ffs(mask)-1));
360118824Sharti			else
361118824Sharti				sprintf(ptr, "%#x",
362118824Sharti				    (val & mask) >> (ffs(mask)-1));
363118824Sharti			ptr += strlen(ptr);
364118824Sharti		} else {
365118824Sharti			if (val & (1 << (*descr++ - 1))) {
366118824Sharti				if (tmp++)
367118824Sharti					*ptr++ = ',';
368118824Sharti				while (*descr >= ' ')
369118824Sharti					*ptr++ = *descr++;
370118824Sharti			} else {
371118824Sharti				while (*descr >= ' ')
372118824Sharti					descr++;
373118824Sharti			}
374118824Sharti		}
375118824Sharti	}
376118824Sharti	*ptr++ = '>';
377118824Sharti	*ptr++ = '\0';
378118824Sharti
379118824Sharti	return (buffer);
380118824Sharti}
381118824Sharti
382118824Sharti/*
383118824Sharti * "<radix><bit>STRING<bit>STRING"
384118824Sharti */
385118824Shartistatic char *
386118824Shartiprintb(uint32_t val, const char *descr)
387118824Sharti{
388118824Sharti	static char buffer[1000];
389118824Sharti	char *ptr;
390118824Sharti	int tmp = 0;
391118824Sharti
392118824Sharti	if (*descr++ == '\010')
393118824Sharti		sprintf(buffer, "%#o", val);
394118824Sharti	else
395118824Sharti		sprintf(buffer, "%#x", val);
396118824Sharti	ptr = buffer + strlen(buffer);
397118824Sharti
398118824Sharti	*ptr++ = '<';
399118824Sharti	while (*descr) {
400118824Sharti		if (val & (1 << (*descr++ - 1))) {
401118824Sharti			if (tmp++)
402118824Sharti				*ptr++ = ',';
403118824Sharti			while (*descr > ' ')
404118824Sharti				*ptr++ = *descr++;
405118824Sharti		} else {
406118824Sharti			while (*descr > ' ')
407118824Sharti				descr++;
408118824Sharti		}
409118824Sharti	}
410118824Sharti	*ptr++ = '>';
411118824Sharti	*ptr++ = '\0';
412118824Sharti
413118824Sharti	return (buffer);
414118824Sharti}
415118824Sharti
416118824Sharti
417118824Shartistatic void
418118824Shartidiag_loop(int argc, char *argv[], const char *text,
419118824Sharti    void (*func)(const struct diagif *))
420118824Sharti{
421118824Sharti	int i;
422118824Sharti	struct diagif *aif;
423118824Sharti
424118824Sharti	heading_init();
425118824Sharti	if (argc > 0) {
426118824Sharti		for (i = 0; i < argc; i++) {
427118824Sharti			TAILQ_FOREACH(aif, &diagif_list, link) {
428118824Sharti				if (strcmp(argv[i], aif->ifname) == 0) {
429228611Sdim					heading("%s", text);
430118824Sharti					(*func)(aif);
431118824Sharti					break;
432118824Sharti				}
433118824Sharti			}
434118824Sharti			if (aif == NULL)
435118824Sharti				warnx("%s: no such ATM interface", argv[i]);
436118824Sharti		}
437118824Sharti	} else {
438118824Sharti		TAILQ_FOREACH(aif, &diagif_list, link) {
439228611Sdim			heading("%s", text);
440118824Sharti			(*func)(aif);
441118824Sharti		}
442118824Sharti	}
443118824Sharti}
444118824Sharti
445118824Sharti/*
446118824Sharti * Print the config line for the given interface
447118824Sharti */
448118824Shartistatic void
449118824Sharticonfig_line1(const struct diagif *aif)
450118824Sharti{
451118824Sharti	printf("%-6u%-9s%-8u%-5u%-6u%-5u%-6u%02x:%02x:%02x:%02x:%02x:%02x\n",
452118824Sharti	    aif->index, aif->ifname, aif->mib.pcr, (1 << aif->mib.vpi_bits) - 1,
453118824Sharti	    (1 << aif->mib.vci_bits) - 1, aif->mib.max_vpcs, aif->mib.max_vccs,
454118824Sharti	    aif->mib.esi[0], aif->mib.esi[1], aif->mib.esi[2],
455118824Sharti	    aif->mib.esi[3], aif->mib.esi[4], aif->mib.esi[5]);
456118824Sharti}
457118824Sharti
458118824Shartistatic void
459118824Sharticonfig_line2(const struct diagif *aif)
460118824Sharti{
461118824Sharti	u_int d, i;
462118824Sharti
463118824Sharti	static const struct {
464118824Sharti		const char *dev;
465118824Sharti		const char *vendor;
466118824Sharti	} devs[] = {
467118824Sharti		ATM_DEVICE_NAMES
468118824Sharti	};
469118824Sharti	static const struct {
470118824Sharti		u_int	media;
471118824Sharti		const char *const name;
472118824Sharti	} medias[] = IFM_SUBTYPE_ATM_DESCRIPTIONS;
473118824Sharti
474118824Sharti	for (i = 0; medias[i].name; i++)
475118824Sharti		if (aif->mib.media == medias[i].media)
476118824Sharti			break;
477118824Sharti
478118824Sharti	if ((d = aif->mib.device) >= sizeof(devs) / sizeof(devs[0]))
479118824Sharti		d = 0;
480118824Sharti
481118824Sharti	printf("%-6u%-9s%-12.11s%-13.12s%-8u%-6x%-6x %s\n", aif->index,
482118824Sharti	    aif->ifname, devs[d].vendor, devs[d].dev, aif->mib.serial,
483118824Sharti	    aif->mib.hw_version, aif->mib.sw_version,
484118824Sharti	    medias[i].name ? medias[i].name : "unknown");
485118824Sharti}
486118824Sharti
487118824Shartistatic void
488118824Shartidiag_config(int argc, char *argv[])
489118824Sharti{
490118824Sharti	int opt;
491118824Sharti
492118824Sharti	static int hardware;
493118824Sharti	static int atm;
494118824Sharti
495118824Sharti	static const struct option opts[] = {
496118824Sharti	    { "hardware", OPT_SIMPLE, &hardware },
497118824Sharti	    { "atm", OPT_SIMPLE, &atm },
498118824Sharti	    { NULL, 0, NULL }
499118824Sharti	};
500118824Sharti
501118824Sharti	static const char config_text1[] =
502118824Sharti	    "Interface              Max        Max\n"
503132502Sharti	    "Index Name     PCR     VPI  VCI   VPCs VCCs  ESI\n";
504118824Sharti	static const char config_text2[] =
505118824Sharti	    "Interface                                       Version\n"
506118824Sharti	    "Index Name     Vendor      Card         "
507118824Sharti	    "Serial  HW    SW     Media\n";
508118824Sharti
509118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
510118824Sharti		switch (opt) {
511118824Sharti		}
512118824Sharti
513118824Sharti	diagif_fetch();
514118824Sharti	if (TAILQ_EMPTY(&diagif_list))
515118824Sharti		errx(1, "no ATM interfaces found");
516118824Sharti
517118824Sharti	if (!atm && !hardware)
518118824Sharti		atm = 1;
519118824Sharti
520118824Sharti	if (atm)
521118824Sharti		diag_loop(argc, argv, config_text1, config_line1);
522118824Sharti	if (hardware)
523118824Sharti		diag_loop(argc, argv, config_text2, config_line2);
524118824Sharti
525118824Sharti}
526118824Sharti
527118824Shartistatic void
528118824Shartidiag_list(int argc, char *argv[])
529118824Sharti{
530118824Sharti	int opt;
531118824Sharti	struct diagif *aif;
532118824Sharti
533118824Sharti	static const struct option opts[] = {
534118824Sharti	    { NULL, 0, NULL }
535118824Sharti	};
536118824Sharti
537118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
538118824Sharti		switch (opt) {
539118824Sharti		}
540118824Sharti
541118824Sharti	if (argc > 0)
542118824Sharti		errx(1, "no arguments required for 'diag list'");
543118824Sharti
544118824Sharti	diagif_fetch();
545118824Sharti	if (TAILQ_EMPTY(&diagif_list))
546118824Sharti		errx(1, "no ATM interfaces found");
547118824Sharti
548118824Sharti	TAILQ_FOREACH(aif, &diagif_list, link)
549118824Sharti		printf("%s ", aif->ifname);
550118824Sharti	printf("\n");
551118824Sharti}
552118824Sharti
553118824Sharti/*
554118824Sharti * Print the config line for the given interface
555118824Sharti */
556118824Shartistatic void
557118824Shartiphy_show_line(const struct diagif *aif)
558118824Sharti{
559125018Sharti	printf("%-6u%-9s", aif->index, aif->ifname);
560125018Sharti	if (aif->phy_present)
561125018Sharti		printf("%-5u%-25s0x%-9x", aif->phy_type,
562125018Sharti		    aif->phy_name, aif->phy_loopback);
563125018Sharti	printf("\n");
564118824Sharti}
565118824Sharti
566118824Shartistatic void
567118824Shartidiag_phy_show(int argc, char *argv[])
568118824Sharti{
569118824Sharti	int opt;
570118824Sharti
571118824Sharti	static const struct option opts[] = {
572118824Sharti	    { NULL, 0, NULL }
573118824Sharti	};
574118824Sharti
575118824Sharti	static const char phy_show_text[] =
576118824Sharti	    "Interface      Phy\n"
577118824Sharti	    "Index Name     Type Name                     Loopback State\n";
578118824Sharti
579118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
580118824Sharti		switch (opt) {
581118824Sharti		}
582118824Sharti
583118824Sharti	diagif_fetch();
584118824Sharti	if (TAILQ_EMPTY(&diagif_list))
585118824Sharti		errx(1, "no ATM interfaces found");
586118824Sharti
587118824Sharti	diag_loop(argc, argv, phy_show_text, phy_show_line);
588118824Sharti}
589118824Sharti
590125018Sharti/*
591125018Sharti * Make sure the interface exists and has a phy
592125018Sharti */
593125018Shartistatic struct diagif *
594125018Shartidiagif_get_phy(const char *arg)
595125018Sharti{
596125018Sharti	struct diagif *aif;
597125018Sharti
598125018Sharti	diagif_fetch();
599125018Sharti	TAILQ_FOREACH(aif, &diagif_list, link)
600125018Sharti		if (strcmp(aif->ifname, arg) == 0)
601125018Sharti			break;
602125018Sharti	if (aif == NULL)
603125018Sharti		errx(1, "no such interface: %s", arg);
604125018Sharti	if (!aif->phy_present)
605125018Sharti		errx(1, "interface %s has no phy", arg);
606125018Sharti
607125018Sharti	return (aif);
608125018Sharti}
609125018Sharti
610118824Shartistatic void
611118824Shartidiag_phy_set(int argc, char *argv[])
612118824Sharti{
613118824Sharti	int opt;
614118824Sharti	uint8_t reg[3];
615118824Sharti	u_long res;
616118824Sharti	char *end;
617118824Sharti	char *str;
618118824Sharti
619118824Sharti	static const struct option opts[] = {
620118824Sharti	    { NULL, 0, NULL }
621118824Sharti	};
622118824Sharti
623118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
624118824Sharti		switch (opt) {
625118824Sharti		}
626118824Sharti
627118824Sharti	if (argc != 4)
628118824Sharti		errx(1, "missing arguments for 'diag phy set'");
629118824Sharti
630118824Sharti	errno = 0;
631118824Sharti	res = strtoul(argv[1], &end, 0);
632118824Sharti	if (errno != 0)
633118824Sharti		err(1, "register number");
634118824Sharti	if (*end != '\0')
635118824Sharti		errx(1, "malformed register number '%s'", argv[1]);
636118824Sharti	if (res > 0xff)
637118824Sharti		errx(1, "register number too large");
638118824Sharti	reg[0] = res;
639118824Sharti
640118824Sharti	errno = 0;
641118824Sharti	res = strtoul(argv[2], &end, 0);
642118824Sharti	if (errno != 0)
643118824Sharti		err(1, "mask");
644118824Sharti	if (*end != '\0')
645118824Sharti		errx(1, "malformed mask '%s'", argv[1]);
646118824Sharti	if (res > 0xff)
647118824Sharti		errx(1, "mask too large");
648118824Sharti	reg[1] = res;
649118824Sharti
650118824Sharti	errno = 0;
651118824Sharti	res = strtoul(argv[3], &end, 0);
652118824Sharti	if (errno != 0)
653118824Sharti		err(1, "value");
654118824Sharti	if (*end != '\0')
655118824Sharti		errx(1, "malformed value '%s'", argv[1]);
656118824Sharti	if (res > 0xff)
657118824Sharti		errx(1, "value too large");
658118824Sharti	reg[2] = res;
659118824Sharti
660125018Sharti	(void)diagif_get_phy(argv[0]);
661125018Sharti
662118824Sharti	if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1)
663118824Sharti		err(1, NULL);
664118824Sharti
665118824Sharti	if (sysctlbyname(str, NULL, NULL, reg, 3 * sizeof(uint8_t)))
666118824Sharti		err(1, "%s", str);
667118824Sharti
668118824Sharti	free(str);
669118824Sharti}
670118824Sharti
671118824Shartistatic void
672118824Shartidiag_phy_print(int argc, char *argv[])
673118824Sharti{
674118824Sharti	int opt;
675118824Sharti	char *str;
676118824Sharti	size_t len, len1;
677118824Sharti	uint8_t *regs;
678118824Sharti	u_int type, i;
679118824Sharti	const struct utopia_print *p;
680118824Sharti
681118824Sharti	static int numeric;
682118824Sharti
683118824Sharti	static const struct option opts[] = {
684118824Sharti	    { "numeric", OPT_SIMPLE, &numeric },
685118824Sharti	    { NULL, 0, NULL }
686118824Sharti	};
687118824Sharti
688118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
689118824Sharti		switch (opt) {
690118824Sharti		}
691118824Sharti
692118824Sharti	if (argc != 1)
693118824Sharti		errx(1, "need device name for 'diag phy print'");
694118824Sharti
695125018Sharti	(void)diagif_get_phy(argv[0]);
696125018Sharti
697118824Sharti	if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1)
698118824Sharti		err(1, NULL);
699118824Sharti	len = 0;
700118824Sharti	if (sysctlbyname(str, NULL, &len, NULL, 0))
701118824Sharti		err(1, "'%s' not found", str);
702118824Sharti
703118824Sharti	regs = malloc(len);
704118824Sharti	if (regs == NULL)
705118824Sharti		err(1, NULL);
706118824Sharti
707118824Sharti	if (sysctlbyname(str, regs, &len, NULL, 0))
708118824Sharti		err(1, "'%s' not found", str);
709118824Sharti	free(str);
710118824Sharti
711118824Sharti	if (numeric) {
712118824Sharti		for (i = 0; i < len; i++) {
713118824Sharti			if (i % 16 == 0)
714118824Sharti				printf("%02x: ", i);
715118824Sharti			if (i % 16 == 8)
716118824Sharti				printf(" ");
717118824Sharti			printf(" %02x", regs[i]);
718118824Sharti			if (i % 16 == 15)
719118824Sharti				printf("\n");
720118824Sharti		}
721118824Sharti		if (i % 16 != 0)
722118824Sharti			printf("\n");
723118824Sharti	} else {
724118824Sharti		if (asprintf(&str, "hw.atm.%s.phy_type", argv[0]) == -1)
725118824Sharti			err(1, NULL);
726118824Sharti		len1 = sizeof(type);
727118824Sharti		if (sysctlbyname(str, &type, &len1, NULL, 0))
728118824Sharti			err(1, "'%s' not found", str);
729118824Sharti		free(str);
730118824Sharti
731118824Sharti		for (i = 0; i < sizeof(phy_print) / sizeof(phy_print[0]); i++)
732118824Sharti			if (type == phy_print[i].type)
733118824Sharti				break;
734118824Sharti		if (i == sizeof(phy_print) / sizeof(phy_print[0]))
735118824Sharti			errx(1, "unknown PHY chip type %u\n", type);
736118824Sharti
737118824Sharti		for (p = phy_print[i].tab;
738118824Sharti		    p < phy_print[i].tab + phy_print[i].len;
739118824Sharti		    p++) {
740118824Sharti			if (p->reg + utopia_addreg[p->type] > len)
741118824Sharti				/* don't have this register */
742118824Sharti				continue;
743118824Sharti
744118824Sharti			printf("%s:%*s", p->name, 40 - (int)strlen(p->name),"");
745118824Sharti
746118824Sharti			switch (p->type) {
747118824Sharti
748118824Sharti			  case UTP_REGT_BITS:
749118824Sharti				printf("%s\n", printb8(regs[p->reg], p->fmt));
750118824Sharti				break;
751118824Sharti
752118824Sharti			  case UTP_REGT_INT8:
753118824Sharti				printf("%#x\n", regs[p->reg]);
754118824Sharti				break;
755118824Sharti
756118824Sharti			  case UTP_REGT_INT10BITS:
757118824Sharti				printf("%#x %s\n", regs[p->reg] |
758118824Sharti				    ((regs[p->reg + 1] & 0x3) << 8),
759118824Sharti				    printb8(regs[p->reg + 1], p->fmt));
760118824Sharti				break;
761118824Sharti
762118824Sharti			  case UTP_REGT_INT12:
763118824Sharti				printf("%#x\n", regs[p->reg] |
764118824Sharti				    ((regs[p->reg + 1] & 0xf) << 8));
765118824Sharti				break;
766118824Sharti
767118824Sharti			  case UTP_REGT_INT16:
768118824Sharti				printf("%#x\n", regs[p->reg] |
769118824Sharti				    (regs[p->reg + 1] << 8));
770118824Sharti				break;
771118824Sharti
772118824Sharti			  case UTP_REGT_INT19:
773118824Sharti				printf("%#x\n", regs[p->reg] |
774118824Sharti				    (regs[p->reg + 1] << 8) |
775118824Sharti				    ((regs[p->reg + 2] & 0x7) << 16));
776118824Sharti				break;
777118824Sharti
778118824Sharti			  case UTP_REGT_INT20:
779118824Sharti				printf("%#x\n", regs[p->reg] |
780118824Sharti				    (regs[p->reg + 1] << 8) |
781118824Sharti				    ((regs[p->reg + 2] & 0xf) << 16));
782118824Sharti				break;
783118824Sharti
784118824Sharti			  case UTP_REGT_INT21:
785118824Sharti				printf("%#x\n", regs[p->reg] |
786118824Sharti				    (regs[p->reg + 1] << 8) |
787118824Sharti				    ((regs[p->reg + 2] & 0x1f) << 16));
788118824Sharti				break;
789118824Sharti
790118824Sharti			  default:
791118824Sharti				abort();
792118824Sharti			}
793118824Sharti		}
794118824Sharti	}
795118824Sharti	free(regs);
796118824Sharti}
797118824Sharti
798118824Shartistatic void
799118824Shartidiag_phy_stats(int argc, char *argv[])
800118824Sharti{
801118824Sharti	int opt;
802118824Sharti	size_t len;
803118824Sharti	char *str;
804118824Sharti	struct utopia_stats1 stats1;
805118824Sharti	u_int foo;
806118824Sharti
807118824Sharti	static int clear;
808118824Sharti
809118824Sharti	static const struct option opts[] = {
810118824Sharti	    { "clear", OPT_SIMPLE, &clear },
811118824Sharti	    { NULL, 0, NULL }
812118824Sharti	};
813118824Sharti
814118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
815118824Sharti		switch (opt) {
816118824Sharti		}
817118824Sharti
818118824Sharti	if (argc != 1)
819118824Sharti		errx(1, "need device name for 'diag phy stats'");
820118824Sharti
821125018Sharti	(void)diagif_get_phy(argv[0]);
822125018Sharti
823118824Sharti	if (asprintf(&str, "hw.atm.%s.phy_stats", argv[0]) == -1)
824118824Sharti		err(1, NULL);
825118824Sharti
826118824Sharti	len = sizeof(stats1);
827118824Sharti	if (sysctlbyname(str, &stats1, &len,
828118824Sharti	    clear ? &foo : NULL, clear ? sizeof(foo) : 0))
829118824Sharti		err(1, "'%s' not found", str);
830118824Sharti	if (len < sizeof(stats1.version))
831118824Sharti		errx(1, "phy statistics too short %zu", len);
832118824Sharti
833118824Sharti	switch (stats1.version) {
834118824Sharti
835118824Sharti	  case 1:
836118824Sharti		if (len != sizeof(stats1))
837118824Sharti			errx(1, "bad phy stats length %zu (expecting %zu)",
838118824Sharti			    len, sizeof(stats1));
839118824Sharti		break;
840118824Sharti
841118824Sharti	  default:
842118824Sharti		errx(1, "unknown phy stats version %u", stats1.version);
843118824Sharti	}
844118824Sharti
845118824Sharti	free(str);
846118824Sharti
847118824Sharti	printf("rx_sbip:	%llu\n", (unsigned long long)stats1.rx_sbip);
848118824Sharti	printf("rx_lbip:	%llu\n", (unsigned long long)stats1.rx_lbip);
849118824Sharti	printf("rx_lfebe:	%llu\n", (unsigned long long)stats1.rx_lfebe);
850118824Sharti	printf("rx_pbip:	%llu\n", (unsigned long long)stats1.rx_pbip);
851118824Sharti	printf("rx_pfebe:	%llu\n", (unsigned long long)stats1.rx_pfebe);
852118824Sharti	printf("rx_cells:	%llu\n", (unsigned long long)stats1.rx_cells);
853118824Sharti	printf("rx_corr:	%llu\n", (unsigned long long)stats1.rx_corr);
854118824Sharti	printf("rx_uncorr:	%llu\n", (unsigned long long)stats1.rx_uncorr);
855118824Sharti	printf("rx_symerr:	%llu\n", (unsigned long long)stats1.rx_symerr);
856118824Sharti	printf("tx_cells:	%llu\n", (unsigned long long)stats1.tx_cells);
857118824Sharti}
858118824Sharti
859118824Sharti/*
860118824Sharti * Fetch the table of open vccs
861118824Sharti */
862118824Shartivoid
863118824Shartidiagif_fetch_vcc(struct diagif *aif, int fd)
864118824Sharti{
865118824Sharti	struct ifreq ifr;
866118824Sharti
867118824Sharti	if (aif->vtab != NULL)
868118824Sharti		return;
869118824Sharti
870118824Sharti	strncpy(ifr.ifr_name, aif->ifname, IFNAMSIZ);
871168726Smaxim	ifr.ifr_name[IFNAMSIZ - 1] = '\0';
872118824Sharti
873118824Sharti	aif->vtab = malloc(sizeof(*aif->vtab) + sizeof(aif->vtab->vccs[0]) *
874118824Sharti	    aif->mib.max_vccs);
875118824Sharti	if (aif->vtab == NULL)
876118824Sharti		err(1, NULL);
877118824Sharti	ifr.ifr_data = (caddr_t)aif->vtab;
878118824Sharti
879118824Sharti	if (ioctl(fd, SIOCATMGVCCS, &ifr) == -1)
880118824Sharti		err(1, "SIOCATMGVCCS");
881118824Sharti}
882118824Sharti
883118824Sharti/*
884118824Sharti * Print the VCC table for this interface.
885118824Sharti */
886118824Shartistatic void
887118824Shartiprint_channel(const struct diagif *aif)
888118824Sharti{
889118824Sharti	const struct atmio_vcc *v;
890118824Sharti
891118824Sharti	static const char *const aal_tab[] = {
892148718Sstefanf		[ATMIO_AAL_0] = "0",
893148718Sstefanf		[ATMIO_AAL_34] = "3/4",
894148718Sstefanf		[ATMIO_AAL_5] = "5",
895148718Sstefanf		[ATMIO_AAL_RAW] = "raw",
896118824Sharti	};
897118824Sharti	static const char *const traffic_tab[] = {
898148718Sstefanf		[ATMIO_TRAFFIC_UBR] = "ubr",
899148718Sstefanf		[ATMIO_TRAFFIC_CBR] = "cbr",
900148718Sstefanf		[ATMIO_TRAFFIC_ABR] = "abr",
901148718Sstefanf		[ATMIO_TRAFFIC_VBR] = "vbr",
902118824Sharti	};
903118824Sharti
904118824Sharti	for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
905118824Sharti		printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
906118824Sharti		    v->vpi, v->vci);
907118824Sharti
908118824Sharti		if (v->aal >= sizeof(aal_tab)/sizeof(aal_tab[0]) ||
909118824Sharti		    aal_tab[v->aal] == NULL)
910118824Sharti			printf("bad ");
911118824Sharti		else
912118824Sharti			printf("%-4s", aal_tab[v->aal]);
913118824Sharti
914118824Sharti		if (v->traffic >= sizeof(traffic_tab)/sizeof(traffic_tab[0]) ||
915118824Sharti		    traffic_tab[v->traffic] == NULL)
916118824Sharti			printf("bad     ");
917118824Sharti		else
918118824Sharti			printf("%-8s", traffic_tab[v->traffic]);
919118824Sharti
920118824Sharti		printf("%-6u%-6u%s\n", v->rmtu, v->tmtu,
921118824Sharti		    printb(v->flags, ATMIO_FLAGS));
922118824Sharti	}
923118824Sharti}
924118824Sharti
925118824Sharti/*
926118824Sharti * Print the VCC table for this interface, traffic parameters.
927118824Sharti */
928118824Shartistatic void
929118824Shartiprint_traffic(const struct diagif *aif)
930118824Sharti{
931118824Sharti	const struct atmio_vcc *v;
932118824Sharti
933118824Sharti	for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
934118824Sharti		printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
935118824Sharti		    v->vpi, v->vci);
936118824Sharti
937118824Sharti		switch (v->traffic) {
938118824Sharti
939118824Sharti		  case ATMIO_TRAFFIC_CBR:
940118824Sharti			printf("%u", v->tparam.pcr);
941118824Sharti			break;
942118824Sharti
943118824Sharti		  case ATMIO_TRAFFIC_UBR:
944118824Sharti			printf("%-8u                %u", v->tparam.pcr,
945118824Sharti			    v->tparam.mcr);
946118824Sharti			break;
947118824Sharti
948118824Sharti		  case ATMIO_TRAFFIC_VBR:
949118824Sharti			printf("%-8u%-8u%-8u", v->tparam.pcr, v->tparam.scr,
950118824Sharti			    v->tparam.mbs);
951118824Sharti			break;
952118824Sharti
953118824Sharti		  case ATMIO_TRAFFIC_ABR:
954118824Sharti			printf("%-8u                %-8u",
955118824Sharti			    v->tparam.pcr, v->tparam.mcr);
956118824Sharti			break;
957118824Sharti		}
958118824Sharti		printf("\n");
959118824Sharti	}
960118824Sharti}
961118824Sharti
962118824Sharti/*
963118824Sharti * Print the VCC table for this interface, ABR traffic parameters.
964118824Sharti */
965118824Shartistatic void
966118824Shartiprint_abr(const struct diagif *aif)
967118824Sharti{
968118824Sharti	const struct atmio_vcc *v;
969118824Sharti
970118824Sharti	for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
971118824Sharti		printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
972118824Sharti		    v->vpi, v->vci);
973118824Sharti
974118824Sharti		if (v->traffic == ATMIO_TRAFFIC_ABR) {
975118824Sharti			printf("%-8u%-8u%-4u%-4u%-5u%-5u%-5u%u",
976118824Sharti			    v->tparam.icr, v->tparam.tbe, v->tparam.nrm,
977118824Sharti			    v->tparam.trm, v->tparam.adtf, v->tparam.rif,
978118824Sharti			    v->tparam.rdf, v->tparam.cdf);
979118824Sharti		}
980118824Sharti		printf("\n");
981118824Sharti	}
982118824Sharti}
983118824Sharti
984118824Shartistatic void
985118824Shartidiag_vcc_loop(void (*func)(const struct diagif *), const char *text,
986118824Sharti    int argc, char *argv[], int fd)
987118824Sharti{
988118824Sharti	struct diagif *aif;
989118824Sharti
990118824Sharti	heading_init();
991118824Sharti	if (argc == 0) {
992118824Sharti		TAILQ_FOREACH(aif, &diagif_list, link) {
993118824Sharti			diagif_fetch_vcc(aif, fd);
994118824Sharti			if (aif->vtab->count != 0) {
995228611Sdim				heading("%s", text);
996118824Sharti				(*func)(aif);
997118824Sharti			}
998118824Sharti		}
999118824Sharti
1000118824Sharti	} else {
1001118824Sharti		for (optind = 0; optind < argc; optind++) {
1002118824Sharti			TAILQ_FOREACH(aif, &diagif_list, link)
1003118824Sharti				if (strcmp(aif->ifname, argv[optind]) == 0) {
1004118824Sharti					diagif_fetch_vcc(aif, fd);
1005118824Sharti					if (aif->vtab->count != 0) {
1006228611Sdim						heading("%s", text);
1007118824Sharti						(*func)(aif);
1008118824Sharti					}
1009118824Sharti					break;
1010118824Sharti				}
1011118824Sharti			if (aif == NULL)
1012118824Sharti				warnx("no such interface '%s'", argv[optind]);
1013118824Sharti		}
1014118824Sharti	}
1015118824Sharti}
1016118824Sharti
1017118824Shartistatic void
1018118824Shartidiag_vcc(int argc, char *argv[])
1019118824Sharti{
1020118824Sharti	int opt, fd;
1021118824Sharti
1022118824Sharti	static int channel, traffic, abr;
1023118824Sharti	static const struct option opts[] = {
1024118824Sharti	    { "abr", OPT_SIMPLE, &abr },
1025118824Sharti	    { "channel", OPT_SIMPLE, &channel },
1026118824Sharti	    { "traffic", OPT_SIMPLE, &traffic },
1027118824Sharti	    { NULL, 0, NULL }
1028118824Sharti	};
1029118824Sharti	static const char head_channel[] =
1030118824Sharti	    "Interface\n"
1031118824Sharti	    "Index Name     VPI VCI   AAL Traffic RxMTU TxMTU Flags\n";
1032118824Sharti	static const char head_traffic[] =
1033118824Sharti	    "Interface                Traffic parameters\n"
1034118824Sharti	    "Index Name     VPI VCI   PCR     SCR     MBS     MCR\n";
1035118824Sharti	static const char head_abr[] =
1036118824Sharti	    "Interface                ABR traffic parameters\n"
1037118824Sharti	    "Index Name     VPI VCI   ICR     TBE     NRM TRM ADTF RIF  RDF  "
1038118824Sharti	    "CDF\n";
1039118824Sharti
1040118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
1041118824Sharti		switch (opt) {
1042118824Sharti		}
1043118824Sharti
1044118824Sharti	fd = socket(PF_NATM, SOCK_STREAM, PROTO_NATMAAL5);
1045118824Sharti	if (fd < 0)
1046118824Sharti		err(1, "socket");
1047118824Sharti
1048118824Sharti	diagif_fetch();
1049118824Sharti	if (TAILQ_EMPTY(&diagif_list))
1050118824Sharti		errx(1, "no ATM interfaces found");
1051118824Sharti
1052118824Sharti	if (!channel && !traffic && !abr)
1053118824Sharti		channel = 1;
1054118824Sharti
1055118824Sharti	if (channel)
1056118824Sharti		diag_vcc_loop(print_channel, head_channel, argc, argv, fd);
1057118824Sharti	if (traffic)
1058118824Sharti		diag_vcc_loop(print_traffic, head_traffic, argc, argv, fd);
1059118824Sharti	if (abr)
1060118824Sharti		diag_vcc_loop(print_abr, head_abr, argc, argv, fd);
1061118824Sharti}
1062118824Sharti
1063118824Sharti/*
1064118824Sharti * Print driver-internal statistics
1065118824Sharti */
1066118824Shartistatic void
1067118824Shartidiag_stats(int argc, char *argv[])
1068118824Sharti{
1069118824Sharti	int opt;
1070118824Sharti	char *str;
1071118824Sharti	size_t len;
1072118824Sharti	uint32_t *stats;
1073118824Sharti	struct diagif *aif;
1074118824Sharti	u_int i;
1075118824Sharti
1076118824Sharti	static const struct option opts[] = {
1077118824Sharti	    { NULL, 0, NULL }
1078118824Sharti	};
1079118824Sharti
1080118824Sharti	while ((opt = parse_options(&argc, &argv, opts)) != -1)
1081118824Sharti		switch (opt) {
1082118824Sharti		}
1083118824Sharti
1084118824Sharti	if (argc != 1)
1085118824Sharti		errx(1, "need one arg for 'diag stats'");
1086118824Sharti
1087118824Sharti	diagif_fetch();
1088118824Sharti	TAILQ_FOREACH(aif, &diagif_list, link)
1089118824Sharti		if (strcmp(aif->ifname, argv[0]) == 0)
1090118824Sharti			break;
1091118824Sharti
1092118824Sharti	if (aif == NULL)
1093118824Sharti		errx(1, "interface '%s' not found", argv[0]);
1094118824Sharti
1095118824Sharti	if (asprintf(&str, "hw.atm.%s.istats", argv[0]) == -1)
1096118824Sharti		err(1, NULL);
1097118824Sharti	len = 0;
1098118824Sharti	if (sysctlbyname(str, NULL, &len, NULL, 0))
1099118824Sharti		err(1, "'%s' not found", str);
1100118824Sharti
1101118824Sharti	stats = malloc(len);
1102118824Sharti	if (stats == NULL)
1103118824Sharti		err(1, NULL);
1104118824Sharti
1105118824Sharti	if (sysctlbyname(str, stats, &len, NULL, 0))
1106118824Sharti		err(1, "'%s' not found", str);
1107118824Sharti	free(str);
1108118824Sharti
1109118824Sharti	if (aif->mib.device >= sizeof(print_stats) / sizeof(print_stats[0]) ||
1110118824Sharti	    print_stats[aif->mib.device] == NULL)
1111118824Sharti		errx(1, "unknown stats format (%u)", aif->mib.device);
1112118824Sharti
1113118824Sharti	for (i = 0; print_stats[aif->mib.device][i] != NULL; i++) {
1114118824Sharti		if (i * sizeof(uint32_t) >= len)
1115118824Sharti			errx(1, "debug info too short (version mismatch?)");
1116118824Sharti		printf("%-22s%u\n", print_stats[aif->mib.device][i], stats[i]);
1117118824Sharti	}
1118118824Sharti	free(stats);
1119118824Sharti
1120118824Sharti	if (i != len / sizeof(uint32_t))
1121118824Sharti		errx(1, "debug info too long (version mismatch?)");
1122118824Sharti}
1123