]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sbin/atm/atmconfig/diag.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sbin / atm / atmconfig / diag.c
1 /*
2  * Copyright (c) 2001-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  */
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/sysctl.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <sys/queue.h>
37 #include <net/if.h>
38 #include <net/if_mib.h>
39 #include <net/if_types.h>
40 #include <net/if_atm.h>
41 #include <net/if_media.h>
42 #include <netnatm/natm.h>
43 #include <dev/utopia/utopia.h>
44 #include <dev/utopia/suni.h>
45 #include <dev/utopia/idtphy.h>
46
47 #include "atmconfig.h"
48 #include "private.h"
49 #include "diag.h"
50
51 static void diag_list(int, char *[]);
52 static void diag_config(int, char *[]);
53 static void diag_vcc(int, char *[]);
54 static void diag_phy_show(int, char *[]);
55 static void diag_phy_set(int, char *[]);
56 static void diag_phy_print(int, char *[]);
57 static void diag_phy_stats(int, char *[]);
58 static void diag_stats(int, char *[]);
59
60 const struct cmdtab diag_phy_tab[] = {
61         { "show",       NULL,           diag_phy_show },
62         { "set",        NULL,           diag_phy_set },
63         { "stats",      NULL,           diag_phy_stats },
64         { "print",      NULL,           diag_phy_print },
65         { NULL,         NULL,           NULL },
66 };
67
68 const struct cmdtab diag_tab[] = {
69         { "list",       NULL,           diag_list },
70         { "config",     NULL,           diag_config },
71         { "phy",        diag_phy_tab,   NULL },
72         { "stats",      NULL,           diag_stats },
73         { "vcc",        NULL,           diag_vcc },
74         { NULL,         NULL,           NULL }
75 };
76
77 static const struct utopia_print suni_lite[] = { SUNI_PRINT_LITE };
78 static const struct utopia_print suni_ultra[] = { SUNI_PRINT_ULTRA };
79 static const struct utopia_print suni_622[] = { SUNI_PRINT_622 };
80 static const struct utopia_print idt77105[] = { IDTPHY_PRINT_77105 };
81 static const struct utopia_print idt77155[] = { IDTPHY_PRINT_77155 };
82
83 static const struct {
84         const struct utopia_print *tab;
85         u_int len;
86         u_int type;
87 } phy_print[] = {
88         { suni_lite, sizeof(suni_lite) / sizeof(suni_lite[0]),
89           UTP_TYPE_SUNI_LITE },
90         { suni_ultra, sizeof(suni_ultra) / sizeof(suni_ultra[0]),
91           UTP_TYPE_SUNI_ULTRA },
92         { suni_622, sizeof(suni_622) / sizeof(suni_622[0]),
93           UTP_TYPE_SUNI_622 },
94         { idt77105, sizeof(idt77105) / sizeof(idt77105[0]),
95           UTP_TYPE_IDT77105 },
96         { idt77155, sizeof(idt77155) / sizeof(idt77155[0]),
97           UTP_TYPE_IDT77155 },
98 };
99
100 static const u_int utopia_addreg[] = { UTP_REG_ADD };
101
102 /*
103  * Driver statistics printing
104  */
105 static const char *const print_stats_pca200e[] = {
106         "cmd_queue_full:",
107         "get_stat_errors:",
108         "clr_stat_errors:",
109         "get_prom_errors:",
110         "suni_reg_errors:",
111         "tx_queue_full:",
112         "tx_queue_almost_full:",
113         "tx_pdu2big:",
114         "tx_too_many_segs:",
115         "tx_retry:",
116         "fix_empty:",
117         "fix_addr_copy:",
118         "fix_addr_noext:",
119         "fix_addr_ext:",
120         "fix_len_noext:",
121         "fix_len_copy:",
122         "fix_len:",
123         "rx_badvc:",
124         "rx_closed:",
125         NULL
126 };
127 static const char *const print_stats_he[] = {
128         "tdprq_full:",
129         "hbuf_error:",
130         "crc_error:",
131         "len_error:",
132         "flow_closed:",
133         "flow_drop:",
134         "tpd_no_mem:",
135         "rx_seg:",
136         "empty_hbuf:",
137         "short_aal5:",
138         "badlen_aal5:",
139         "bug_bad_isw:",
140         "bug_no_irq_upd:",
141         "itype_tbrq:",
142         "itype_tpd:",
143         "itype_rbps:",
144         "itype_rbpl:",
145         "itype_rbrq:",
146         "itype_rbrqt:",
147         "itype_unknown:",
148         "itype_phys:",
149         "itype_err:",
150         "defrag:",
151         "mcc:",
152         "oec:",
153         "dcc:",
154         "cec:",
155         "no_rcv_mbuf:",
156         NULL
157 };
158 static const char *const print_stats_eni[] = {
159         "ttrash:",
160         "mfixaddr:",
161         "mfixlen:",
162         "mfixfail:",
163         "txmbovr:",
164         "dmaovr:",
165         "txoutspace:",
166         "txdtqout:",
167         "launch:",
168         "hwpull:",
169         "swadd:",
170         "rxqnotus:",
171         "rxqus:",
172         "rxdrqout:",
173         "rxmbufout:",
174         "txnomap:",
175         "vtrash:",
176         "otrash:",
177         NULL
178 };
179
180 static const char *const print_stats_idt77211[] = {
181         "need_copy:",
182         "copy_failed:",
183         "out_of_tbds:",
184         "no_txmaps:",
185         "tx_load_err:",
186         "tx_qfull:",
187         NULL
188 };
189 static const char *const print_stats_idt77252[] = {
190         "raw_cells:",
191         "raw_no_vcc:",
192         "raw_no_buf:",
193         "tx_qfull:",
194         "tx_out_of_tbds:",
195         "tx_out_of_maps:",
196         "tx_load_err:",
197         NULL
198 };
199 static const char *const print_stats_virtual[] = {
200         "dummy:",
201         NULL
202 };
203 static const char *const *const print_stats[] = {
204         [ATM_DEVICE_UNKNOWN] =          NULL,
205         [ATM_DEVICE_PCA200E] =          print_stats_pca200e,
206         [ATM_DEVICE_HE155] =            print_stats_he,
207         [ATM_DEVICE_HE622] =            print_stats_he,
208         [ATM_DEVICE_ENI155P] =          print_stats_eni,
209         [ATM_DEVICE_ADP155P] =          print_stats_eni,
210         [ATM_DEVICE_FORELE25] =         print_stats_idt77211,
211         [ATM_DEVICE_FORELE155] =        print_stats_idt77211,
212         [ATM_DEVICE_NICSTAR25] =        print_stats_idt77211,
213         [ATM_DEVICE_NICSTAR155] =       print_stats_idt77211,
214         [ATM_DEVICE_IDTABR25] =         print_stats_idt77252,
215         [ATM_DEVICE_IDTABR155] =        print_stats_idt77252,
216         [ATM_DEVICE_PROATM25] =         print_stats_idt77252,
217         [ATM_DEVICE_PROATM155] =        print_stats_idt77252,
218         [ATM_DEVICE_VIRTUAL] =          print_stats_virtual,
219 };
220
221 struct diagif_list diagif_list = TAILQ_HEAD_INITIALIZER(diagif_list);
222
223 /*
224  * Fetch a phy sysctl
225  */
226 static int
227 phy_fetch(const char *ifname, const char *var, void *val, size_t len,
228     int err_fatal)
229 {
230         char *str;
231
232         if (asprintf(&str, "hw.atm.%s.phy_%s", ifname, var) == -1)
233                 err(1, NULL);
234         if (sysctlbyname(str, val, &len, NULL, 0) == -1) {
235                 if (err_fatal || errno != ENOENT)
236                         err(1, "%s", str);
237                 free(str);
238                 return (-1);
239         }
240         free(str);
241         return (0);
242 }
243
244 /*
245  * Fetch the list of all ATM network interfaces and their MIBs.
246  */
247 void
248 diagif_fetch(void)
249 {
250         size_t len;
251         int count;
252         int name[6];
253         struct ifmibdata mib;
254         struct ifatm_mib atm;
255         int idx;
256         struct diagif *d;
257
258         while ((d = TAILQ_FIRST(&diagif_list)) != NULL) {
259                 if (d->vtab != NULL)
260                         free(d->vtab);
261                 TAILQ_REMOVE(&diagif_list, d, link);
262                 free(d);
263         }
264
265         len = sizeof(count);
266         if (sysctlbyname("net.link.generic.system.ifcount", &count, &len,
267             NULL, 0) == -1)
268                 err(1, "ifcount");
269
270         name[0] = CTL_NET;
271         name[1] = PF_LINK;
272         name[2] = NETLINK_GENERIC;
273         name[3] = IFMIB_IFDATA;
274
275         for (idx = 1; idx <= count; idx++) {
276                 name[4] = idx;
277                 name[5] = IFDATA_GENERAL;
278                 len = sizeof(mib);
279                 if (sysctl(name, 6, &mib, &len, NULL, 0) == -1)
280                         err(1, "interface %d: general mib", idx);
281                 if (mib.ifmd_data.ifi_type == IFT_ATM) {
282                         name[5] = IFDATA_LINKSPECIFIC;
283                         len = sizeof(atm);
284                         if (sysctl(name, 6, &atm, &len, NULL, 0) == -1)
285                                 err(1, "interface %d: ATM mib", idx);
286
287                         d = malloc(sizeof(*d));
288                         if (d == NULL)
289                                 err(1, NULL);
290                         bzero(d, sizeof(*d));
291                         d->mib = atm;
292                         d->index = idx;
293                         strcpy(d->ifname, mib.ifmd_name);
294                         TAILQ_INSERT_TAIL(&diagif_list, d, link);
295
296                         if (phy_fetch(d->ifname, "type", &d->phy_type,
297                             sizeof(d->phy_type), 0) == 0) {
298                                 d->phy_present = 1;
299                                 phy_fetch(d->ifname, "loopback",
300                                     &d->phy_loopback,
301                                     sizeof(d->phy_loopback), 1);
302                                 phy_fetch(d->ifname, "name", &d->phy_name,
303                                     sizeof(d->phy_name), 1);
304                                 phy_fetch(d->ifname, "state", &d->phy_state,
305                                     sizeof(d->phy_state), 1);
306                                 phy_fetch(d->ifname, "carrier", &d->phy_carrier,
307                                     sizeof(d->phy_carrier), 1);
308                         }
309                 }
310         }
311 }
312
313 /*
314  * "<radix><bit>STRING\011<mask><pattern>STRING\012<mask><radix>STRING"
315  */
316 static char *
317 printb8(uint32_t val, const char *descr)
318 {
319         static char buffer[1000];
320         char *ptr;
321         int tmp = 0;
322         u_char mask, pattern;
323
324         if (*descr++ == '\010')
325                 sprintf(buffer, "%#o", val);
326         else
327                 sprintf(buffer, "%#x", val);
328         ptr = buffer + strlen(buffer);
329
330         *ptr++ = '<';
331         while (*descr) {
332                 if (*descr == '\11') {
333                         descr++;
334                         mask = *descr++;
335                         pattern = *descr++;
336                         if ((val & mask) == pattern) {
337                                 if (tmp++)
338                                         *ptr++ = ',';
339                                 while (*descr >= ' ')
340                                         *ptr++ = *descr++;
341                         } else {
342                                 while (*descr >= ' ')
343                                         descr++;
344                         }
345                 } else if (*descr == '\12') {
346                         descr++;
347                         mask = *descr++;
348                         pattern = *descr++;
349                         if (tmp++)
350                                 *ptr++ = ',';
351                         while (*descr >= ' ')
352                                 *ptr++ = *descr++;
353                         *ptr++ = '=';
354                         if (pattern == 8)
355                                 sprintf(ptr, "%#o",
356                                     (val & mask) >> (ffs(mask)-1));
357                         else if (pattern == 10)
358                                 sprintf(ptr, "%u",
359                                     (val & mask) >> (ffs(mask)-1));
360                         else
361                                 sprintf(ptr, "%#x",
362                                     (val & mask) >> (ffs(mask)-1));
363                         ptr += strlen(ptr);
364                 } else {
365                         if (val & (1 << (*descr++ - 1))) {
366                                 if (tmp++)
367                                         *ptr++ = ',';
368                                 while (*descr >= ' ')
369                                         *ptr++ = *descr++;
370                         } else {
371                                 while (*descr >= ' ')
372                                         descr++;
373                         }
374                 }
375         }
376         *ptr++ = '>';
377         *ptr++ = '\0';
378
379         return (buffer);
380 }
381
382 /*
383  * "<radix><bit>STRING<bit>STRING"
384  */
385 static char *
386 printb(uint32_t val, const char *descr)
387 {
388         static char buffer[1000];
389         char *ptr;
390         int tmp = 0;
391
392         if (*descr++ == '\010')
393                 sprintf(buffer, "%#o", val);
394         else
395                 sprintf(buffer, "%#x", val);
396         ptr = buffer + strlen(buffer);
397
398         *ptr++ = '<';
399         while (*descr) {
400                 if (val & (1 << (*descr++ - 1))) {
401                         if (tmp++)
402                                 *ptr++ = ',';
403                         while (*descr > ' ')
404                                 *ptr++ = *descr++;
405                 } else {
406                         while (*descr > ' ')
407                                 descr++;
408                 }
409         }
410         *ptr++ = '>';
411         *ptr++ = '\0';
412
413         return (buffer);
414 }
415
416
417 static void
418 diag_loop(int argc, char *argv[], const char *text,
419     void (*func)(const struct diagif *))
420 {
421         int i;
422         struct diagif *aif;
423
424         heading_init();
425         if (argc > 0) {
426                 for (i = 0; i < argc; i++) {
427                         TAILQ_FOREACH(aif, &diagif_list, link) {
428                                 if (strcmp(argv[i], aif->ifname) == 0) {
429                                         heading("%s", text);
430                                         (*func)(aif);
431                                         break;
432                                 }
433                         }
434                         if (aif == NULL)
435                                 warnx("%s: no such ATM interface", argv[i]);
436                 }
437         } else {
438                 TAILQ_FOREACH(aif, &diagif_list, link) {
439                         heading("%s", text);
440                         (*func)(aif);
441                 }
442         }
443 }
444
445 /*
446  * Print the config line for the given interface
447  */
448 static void
449 config_line1(const struct diagif *aif)
450 {
451         printf("%-6u%-9s%-8u%-5u%-6u%-5u%-6u%02x:%02x:%02x:%02x:%02x:%02x\n",
452             aif->index, aif->ifname, aif->mib.pcr, (1 << aif->mib.vpi_bits) - 1,
453             (1 << aif->mib.vci_bits) - 1, aif->mib.max_vpcs, aif->mib.max_vccs,
454             aif->mib.esi[0], aif->mib.esi[1], aif->mib.esi[2],
455             aif->mib.esi[3], aif->mib.esi[4], aif->mib.esi[5]);
456 }
457
458 static void
459 config_line2(const struct diagif *aif)
460 {
461         u_int d, i;
462
463         static const struct {
464                 const char *dev;
465                 const char *vendor;
466         } devs[] = {
467                 ATM_DEVICE_NAMES
468         };
469         static const struct {
470                 u_int   media;
471                 const char *const name;
472         } medias[] = IFM_SUBTYPE_ATM_DESCRIPTIONS;
473
474         for (i = 0; medias[i].name; i++)
475                 if (aif->mib.media == medias[i].media)
476                         break;
477
478         if ((d = aif->mib.device) >= sizeof(devs) / sizeof(devs[0]))
479                 d = 0;
480
481         printf("%-6u%-9s%-12.11s%-13.12s%-8u%-6x%-6x %s\n", aif->index,
482             aif->ifname, devs[d].vendor, devs[d].dev, aif->mib.serial,
483             aif->mib.hw_version, aif->mib.sw_version,
484             medias[i].name ? medias[i].name : "unknown");
485 }
486
487 static void
488 diag_config(int argc, char *argv[])
489 {
490         int opt;
491
492         static int hardware;
493         static int atm;
494
495         static const struct option opts[] = {
496             { "hardware", OPT_SIMPLE, &hardware },
497             { "atm", OPT_SIMPLE, &atm },
498             { NULL, 0, NULL }
499         };
500
501         static const char config_text1[] =
502             "Interface              Max        Max\n"
503             "Index Name     PCR     VPI  VCI   VPCs VCCs  ESI\n";
504         static const char config_text2[] =
505             "Interface                                       Version\n"
506             "Index Name     Vendor      Card         "
507             "Serial  HW    SW     Media\n";
508
509         while ((opt = parse_options(&argc, &argv, opts)) != -1)
510                 switch (opt) {
511                 }
512
513         diagif_fetch();
514         if (TAILQ_EMPTY(&diagif_list))
515                 errx(1, "no ATM interfaces found");
516
517         if (!atm && !hardware)
518                 atm = 1;
519
520         if (atm)
521                 diag_loop(argc, argv, config_text1, config_line1);
522         if (hardware)
523                 diag_loop(argc, argv, config_text2, config_line2);
524
525 }
526
527 static void
528 diag_list(int argc, char *argv[])
529 {
530         int opt;
531         struct diagif *aif;
532
533         static const struct option opts[] = {
534             { NULL, 0, NULL }
535         };
536
537         while ((opt = parse_options(&argc, &argv, opts)) != -1)
538                 switch (opt) {
539                 }
540
541         if (argc > 0)
542                 errx(1, "no arguments required for 'diag list'");
543
544         diagif_fetch();
545         if (TAILQ_EMPTY(&diagif_list))
546                 errx(1, "no ATM interfaces found");
547
548         TAILQ_FOREACH(aif, &diagif_list, link)
549                 printf("%s ", aif->ifname);
550         printf("\n");
551 }
552
553 /*
554  * Print the config line for the given interface
555  */
556 static void
557 phy_show_line(const struct diagif *aif)
558 {
559         printf("%-6u%-9s", aif->index, aif->ifname);
560         if (aif->phy_present)
561                 printf("%-5u%-25s0x%-9x", aif->phy_type,
562                     aif->phy_name, aif->phy_loopback);
563         printf("\n");
564 }
565
566 static void
567 diag_phy_show(int argc, char *argv[])
568 {
569         int opt;
570
571         static const struct option opts[] = {
572             { NULL, 0, NULL }
573         };
574
575         static const char phy_show_text[] = 
576             "Interface      Phy\n"
577             "Index Name     Type Name                     Loopback State\n";
578
579         while ((opt = parse_options(&argc, &argv, opts)) != -1)
580                 switch (opt) {
581                 }
582
583         diagif_fetch();
584         if (TAILQ_EMPTY(&diagif_list))
585                 errx(1, "no ATM interfaces found");
586
587         diag_loop(argc, argv, phy_show_text, phy_show_line);
588 }
589
590 /*
591  * Make sure the interface exists and has a phy
592  */
593 static struct diagif *
594 diagif_get_phy(const char *arg)
595 {
596         struct diagif *aif;
597
598         diagif_fetch();
599         TAILQ_FOREACH(aif, &diagif_list, link)
600                 if (strcmp(aif->ifname, arg) == 0)
601                         break;
602         if (aif == NULL)
603                 errx(1, "no such interface: %s", arg);
604         if (!aif->phy_present)
605                 errx(1, "interface %s has no phy", arg);
606
607         return (aif);
608 }
609
610 static void
611 diag_phy_set(int argc, char *argv[])
612 {
613         int opt;
614         uint8_t reg[3];
615         u_long res;
616         char *end;
617         char *str;
618
619         static const struct option opts[] = {
620             { NULL, 0, NULL }
621         };
622
623         while ((opt = parse_options(&argc, &argv, opts)) != -1)
624                 switch (opt) {
625                 }
626
627         if (argc != 4)
628                 errx(1, "missing arguments for 'diag phy set'");
629
630         errno = 0;
631         res = strtoul(argv[1], &end, 0);
632         if (errno != 0)
633                 err(1, "register number");
634         if (*end != '\0')
635                 errx(1, "malformed register number '%s'", argv[1]);
636         if (res > 0xff)
637                 errx(1, "register number too large");
638         reg[0] = res;
639
640         errno = 0;
641         res = strtoul(argv[2], &end, 0);
642         if (errno != 0)
643                 err(1, "mask");
644         if (*end != '\0')
645                 errx(1, "malformed mask '%s'", argv[1]);
646         if (res > 0xff)
647                 errx(1, "mask too large");
648         reg[1] = res;
649
650         errno = 0;
651         res = strtoul(argv[3], &end, 0);
652         if (errno != 0)
653                 err(1, "value");
654         if (*end != '\0')
655                 errx(1, "malformed value '%s'", argv[1]);
656         if (res > 0xff)
657                 errx(1, "value too large");
658         reg[2] = res;
659
660         (void)diagif_get_phy(argv[0]);
661
662         if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1)
663                 err(1, NULL);
664
665         if (sysctlbyname(str, NULL, NULL, reg, 3 * sizeof(uint8_t)))
666                 err(1, "%s", str);
667
668         free(str);
669 }
670
671 static void
672 diag_phy_print(int argc, char *argv[])
673 {
674         int opt;
675         char *str;
676         size_t len, len1;
677         uint8_t *regs;
678         u_int type, i;
679         const struct utopia_print *p;
680
681         static int numeric;
682
683         static const struct option opts[] = {
684             { "numeric", OPT_SIMPLE, &numeric },
685             { NULL, 0, NULL }
686         };
687
688         while ((opt = parse_options(&argc, &argv, opts)) != -1)
689                 switch (opt) {
690                 }
691
692         if (argc != 1)
693                 errx(1, "need device name for 'diag phy print'");
694
695         (void)diagif_get_phy(argv[0]);
696
697         if (asprintf(&str, "hw.atm.%s.phy_regs", argv[0]) == -1)
698                 err(1, NULL);
699         len = 0;
700         if (sysctlbyname(str, NULL, &len, NULL, 0))
701                 err(1, "'%s' not found", str);
702
703         regs = malloc(len);
704         if (regs == NULL)
705                 err(1, NULL);
706
707         if (sysctlbyname(str, regs, &len, NULL, 0))
708                 err(1, "'%s' not found", str);
709         free(str);
710
711         if (numeric) {
712                 for (i = 0; i < len; i++) {
713                         if (i % 16 == 0)
714                                 printf("%02x: ", i);
715                         if (i % 16 == 8)
716                                 printf(" ");
717                         printf(" %02x", regs[i]);
718                         if (i % 16 == 15)
719                                 printf("\n");
720                 }
721                 if (i % 16 != 0)
722                         printf("\n");
723         } else {
724                 if (asprintf(&str, "hw.atm.%s.phy_type", argv[0]) == -1)
725                         err(1, NULL);
726                 len1 = sizeof(type);
727                 if (sysctlbyname(str, &type, &len1, NULL, 0))
728                         err(1, "'%s' not found", str);
729                 free(str);
730
731                 for (i = 0; i < sizeof(phy_print) / sizeof(phy_print[0]); i++)
732                         if (type == phy_print[i].type)
733                                 break;
734                 if (i == sizeof(phy_print) / sizeof(phy_print[0]))
735                         errx(1, "unknown PHY chip type %u\n", type);
736
737                 for (p = phy_print[i].tab;
738                     p < phy_print[i].tab + phy_print[i].len;
739                     p++) {
740                         if (p->reg + utopia_addreg[p->type] > len)
741                                 /* don't have this register */
742                                 continue;
743
744                         printf("%s:%*s", p->name, 40 - (int)strlen(p->name),"");
745
746                         switch (p->type) {
747
748                           case UTP_REGT_BITS:
749                                 printf("%s\n", printb8(regs[p->reg], p->fmt));
750                                 break;
751                         
752                           case UTP_REGT_INT8:
753                                 printf("%#x\n", regs[p->reg]);
754                                 break;
755
756                           case UTP_REGT_INT10BITS:
757                                 printf("%#x %s\n", regs[p->reg] |
758                                     ((regs[p->reg + 1] & 0x3) << 8),
759                                     printb8(regs[p->reg + 1], p->fmt));
760                                 break;
761
762                           case UTP_REGT_INT12:
763                                 printf("%#x\n", regs[p->reg] |
764                                     ((regs[p->reg + 1] & 0xf) << 8));
765                                 break;
766
767                           case UTP_REGT_INT16:
768                                 printf("%#x\n", regs[p->reg] |
769                                     (regs[p->reg + 1] << 8));
770                                 break;
771
772                           case UTP_REGT_INT19:
773                                 printf("%#x\n", regs[p->reg] |
774                                     (regs[p->reg + 1] << 8) |
775                                     ((regs[p->reg + 2] & 0x7) << 16));
776                                 break;
777
778                           case UTP_REGT_INT20:
779                                 printf("%#x\n", regs[p->reg] |
780                                     (regs[p->reg + 1] << 8) |
781                                     ((regs[p->reg + 2] & 0xf) << 16));
782                                 break;
783
784                           case UTP_REGT_INT21:
785                                 printf("%#x\n", regs[p->reg] |
786                                     (regs[p->reg + 1] << 8) |
787                                     ((regs[p->reg + 2] & 0x1f) << 16));
788                                 break;
789
790                           default:
791                                 abort();
792                         }
793                 }
794         }
795         free(regs);
796 }
797
798 static void
799 diag_phy_stats(int argc, char *argv[])
800 {
801         int opt;
802         size_t len;
803         char *str;
804         struct utopia_stats1 stats1;
805         u_int foo;
806
807         static int clear;
808
809         static const struct option opts[] = {
810             { "clear", OPT_SIMPLE, &clear },
811             { NULL, 0, NULL }
812         };
813
814         while ((opt = parse_options(&argc, &argv, opts)) != -1)
815                 switch (opt) {
816                 }
817
818         if (argc != 1)
819                 errx(1, "need device name for 'diag phy stats'");
820
821         (void)diagif_get_phy(argv[0]);
822
823         if (asprintf(&str, "hw.atm.%s.phy_stats", argv[0]) == -1)
824                 err(1, NULL);
825
826         len = sizeof(stats1);
827         if (sysctlbyname(str, &stats1, &len,
828             clear ? &foo : NULL, clear ? sizeof(foo) : 0))
829                 err(1, "'%s' not found", str);
830         if (len < sizeof(stats1.version))
831                 errx(1, "phy statistics too short %zu", len);
832
833         switch (stats1.version) {
834
835           case 1:
836                 if (len != sizeof(stats1))
837                         errx(1, "bad phy stats length %zu (expecting %zu)",
838                             len, sizeof(stats1));
839                 break;
840
841           default:
842                 errx(1, "unknown phy stats version %u", stats1.version);
843         }
844
845         free(str);
846
847         printf("rx_sbip:        %llu\n", (unsigned long long)stats1.rx_sbip);
848         printf("rx_lbip:        %llu\n", (unsigned long long)stats1.rx_lbip);
849         printf("rx_lfebe:       %llu\n", (unsigned long long)stats1.rx_lfebe);
850         printf("rx_pbip:        %llu\n", (unsigned long long)stats1.rx_pbip);
851         printf("rx_pfebe:       %llu\n", (unsigned long long)stats1.rx_pfebe);
852         printf("rx_cells:       %llu\n", (unsigned long long)stats1.rx_cells);
853         printf("rx_corr:        %llu\n", (unsigned long long)stats1.rx_corr);
854         printf("rx_uncorr:      %llu\n", (unsigned long long)stats1.rx_uncorr);
855         printf("rx_symerr:      %llu\n", (unsigned long long)stats1.rx_symerr);
856         printf("tx_cells:       %llu\n", (unsigned long long)stats1.tx_cells);
857 }
858
859 /*
860  * Fetch the table of open vccs
861  */
862 void
863 diagif_fetch_vcc(struct diagif *aif, int fd)
864 {
865         struct ifreq ifr;
866
867         if (aif->vtab != NULL)
868                 return;
869
870         strncpy(ifr.ifr_name, aif->ifname, IFNAMSIZ);
871         ifr.ifr_name[IFNAMSIZ - 1] = '\0';
872
873         aif->vtab = malloc(sizeof(*aif->vtab) + sizeof(aif->vtab->vccs[0]) *
874             aif->mib.max_vccs);
875         if (aif->vtab == NULL)
876                 err(1, NULL);
877         ifr.ifr_data = (caddr_t)aif->vtab;
878
879         if (ioctl(fd, SIOCATMGVCCS, &ifr) == -1)
880                 err(1, "SIOCATMGVCCS");
881 }
882
883 /*
884  * Print the VCC table for this interface.
885  */
886 static void
887 print_channel(const struct diagif *aif)
888 {
889         const struct atmio_vcc *v;
890
891         static const char *const aal_tab[] = {
892                 [ATMIO_AAL_0] = "0",
893                 [ATMIO_AAL_34] = "3/4",
894                 [ATMIO_AAL_5] = "5",
895                 [ATMIO_AAL_RAW] = "raw",
896         };
897         static const char *const traffic_tab[] = {
898                 [ATMIO_TRAFFIC_UBR] = "ubr",
899                 [ATMIO_TRAFFIC_CBR] = "cbr",
900                 [ATMIO_TRAFFIC_ABR] = "abr",
901                 [ATMIO_TRAFFIC_VBR] = "vbr",
902         };
903
904         for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
905                 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
906                     v->vpi, v->vci);
907
908                 if (v->aal >= sizeof(aal_tab)/sizeof(aal_tab[0]) ||
909                     aal_tab[v->aal] == NULL)
910                         printf("bad ");
911                 else
912                         printf("%-4s", aal_tab[v->aal]);
913
914                 if (v->traffic >= sizeof(traffic_tab)/sizeof(traffic_tab[0]) ||
915                     traffic_tab[v->traffic] == NULL)
916                         printf("bad     ");
917                 else
918                         printf("%-8s", traffic_tab[v->traffic]);
919
920                 printf("%-6u%-6u%s\n", v->rmtu, v->tmtu,
921                     printb(v->flags, ATMIO_FLAGS));
922         }
923 }
924
925 /*
926  * Print the VCC table for this interface, traffic parameters.
927  */
928 static void
929 print_traffic(const struct diagif *aif)
930 {
931         const struct atmio_vcc *v;
932
933         for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
934                 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
935                     v->vpi, v->vci);
936
937                 switch (v->traffic) {
938
939                   case ATMIO_TRAFFIC_CBR:
940                         printf("%u", v->tparam.pcr);
941                         break;
942
943                   case ATMIO_TRAFFIC_UBR:
944                         printf("%-8u                %u", v->tparam.pcr,
945                             v->tparam.mcr);
946                         break;
947
948                   case ATMIO_TRAFFIC_VBR:
949                         printf("%-8u%-8u%-8u", v->tparam.pcr, v->tparam.scr,
950                             v->tparam.mbs);
951                         break;
952
953                   case ATMIO_TRAFFIC_ABR:
954                         printf("%-8u                %-8u",
955                             v->tparam.pcr, v->tparam.mcr);
956                         break;
957                 }
958                 printf("\n");
959         }
960 }
961
962 /*
963  * Print the VCC table for this interface, ABR traffic parameters.
964  */
965 static void
966 print_abr(const struct diagif *aif)
967 {
968         const struct atmio_vcc *v;
969
970         for (v = aif->vtab->vccs; v < &aif->vtab->vccs[aif->vtab->count]; v++) {
971                 printf("%-6u%-9s%-4u%-6u", aif->index, aif->ifname,
972                     v->vpi, v->vci);
973
974                 if (v->traffic == ATMIO_TRAFFIC_ABR) {
975                         printf("%-8u%-8u%-4u%-4u%-5u%-5u%-5u%u",
976                             v->tparam.icr, v->tparam.tbe, v->tparam.nrm,
977                             v->tparam.trm, v->tparam.adtf, v->tparam.rif,
978                             v->tparam.rdf, v->tparam.cdf);
979                 }
980                 printf("\n");
981         }
982 }
983
984 static void
985 diag_vcc_loop(void (*func)(const struct diagif *), const char *text,
986     int argc, char *argv[], int fd)
987 {
988         struct diagif *aif;
989
990         heading_init();
991         if (argc == 0) {
992                 TAILQ_FOREACH(aif, &diagif_list, link) {
993                         diagif_fetch_vcc(aif, fd);
994                         if (aif->vtab->count != 0) {
995                                 heading("%s", text);
996                                 (*func)(aif);
997                         }
998                 }
999
1000         } else {
1001                 for (optind = 0; optind < argc; optind++) {
1002                         TAILQ_FOREACH(aif, &diagif_list, link)
1003                                 if (strcmp(aif->ifname, argv[optind]) == 0) {
1004                                         diagif_fetch_vcc(aif, fd);
1005                                         if (aif->vtab->count != 0) {
1006                                                 heading("%s", text);
1007                                                 (*func)(aif);
1008                                         }
1009                                         break;
1010                                 }
1011                         if (aif == NULL)
1012                                 warnx("no such interface '%s'", argv[optind]);
1013                 }
1014         }
1015 }
1016
1017 static void
1018 diag_vcc(int argc, char *argv[])
1019 {
1020         int opt, fd;
1021
1022         static int channel, traffic, abr;
1023         static const struct option opts[] = {
1024             { "abr", OPT_SIMPLE, &abr },
1025             { "channel", OPT_SIMPLE, &channel },
1026             { "traffic", OPT_SIMPLE, &traffic },
1027             { NULL, 0, NULL }
1028         };
1029         static const char head_channel[] =
1030             "Interface\n"
1031             "Index Name     VPI VCI   AAL Traffic RxMTU TxMTU Flags\n";
1032         static const char head_traffic[] =
1033             "Interface                Traffic parameters\n"
1034             "Index Name     VPI VCI   PCR     SCR     MBS     MCR\n";
1035         static const char head_abr[] =
1036             "Interface                ABR traffic parameters\n"
1037             "Index Name     VPI VCI   ICR     TBE     NRM TRM ADTF RIF  RDF  "
1038             "CDF\n";
1039
1040         while ((opt = parse_options(&argc, &argv, opts)) != -1)
1041                 switch (opt) {
1042                 }
1043
1044         fd = socket(PF_NATM, SOCK_STREAM, PROTO_NATMAAL5);
1045         if (fd < 0)
1046                 err(1, "socket");
1047
1048         diagif_fetch();
1049         if (TAILQ_EMPTY(&diagif_list))
1050                 errx(1, "no ATM interfaces found");
1051
1052         if (!channel && !traffic && !abr)
1053                 channel = 1;
1054
1055         if (channel)
1056                 diag_vcc_loop(print_channel, head_channel, argc, argv, fd);
1057         if (traffic)
1058                 diag_vcc_loop(print_traffic, head_traffic, argc, argv, fd);
1059         if (abr)
1060                 diag_vcc_loop(print_abr, head_abr, argc, argv, fd);
1061 }
1062
1063 /*
1064  * Print driver-internal statistics
1065  */
1066 static void
1067 diag_stats(int argc, char *argv[])
1068 {
1069         int opt;
1070         char *str;
1071         size_t len;
1072         uint32_t *stats;
1073         struct diagif *aif;
1074         u_int i;
1075
1076         static const struct option opts[] = {
1077             { NULL, 0, NULL }
1078         };
1079
1080         while ((opt = parse_options(&argc, &argv, opts)) != -1)
1081                 switch (opt) {
1082                 }
1083
1084         if (argc != 1)
1085                 errx(1, "need one arg for 'diag stats'");
1086
1087         diagif_fetch();
1088         TAILQ_FOREACH(aif, &diagif_list, link)
1089                 if (strcmp(aif->ifname, argv[0]) == 0)
1090                         break;
1091
1092         if (aif == NULL)
1093                 errx(1, "interface '%s' not found", argv[0]);
1094
1095         if (asprintf(&str, "hw.atm.%s.istats", argv[0]) == -1)
1096                 err(1, NULL);
1097         len = 0;
1098         if (sysctlbyname(str, NULL, &len, NULL, 0))
1099                 err(1, "'%s' not found", str);
1100
1101         stats = malloc(len);
1102         if (stats == NULL)
1103                 err(1, NULL);
1104
1105         if (sysctlbyname(str, stats, &len, NULL, 0))
1106                 err(1, "'%s' not found", str);
1107         free(str);
1108
1109         if (aif->mib.device >= sizeof(print_stats) / sizeof(print_stats[0]) ||
1110             print_stats[aif->mib.device] == NULL)
1111                 errx(1, "unknown stats format (%u)", aif->mib.device);
1112
1113         for (i = 0; print_stats[aif->mib.device][i] != NULL; i++) {
1114                 if (i * sizeof(uint32_t) >= len)
1115                         errx(1, "debug info too short (version mismatch?)");
1116                 printf("%-22s%u\n", print_stats[aif->mib.device][i], stats[i]);
1117         }
1118         free(stats);
1119
1120         if (i != len / sizeof(uint32_t))
1121                 errx(1, "debug info too long (version mismatch?)");
1122 }