1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Display synchronous serial line statistics 30 */ 31 32 #include <sys/types.h> 33 #include <ctype.h> 34 #include <unistd.h> 35 #include <sys/ioctl.h> 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <sys/stream.h> 40 #include <sys/stropts.h> 41 #include <fcntl.h> 42 #include <sys/ser_sync.h> 43 #include <libdlpi.h> 44 45 static struct scc_mode sm; 46 static struct sl_stats st; 47 48 static void usage(void); 49 static void sample(int count, int period); 50 51 static char sername[DLPI_LINKNAME_MAX]; 52 static int fd; 53 54 int 55 main(int argc, char **argv) 56 { 57 char *cp; 58 char serdevice[DLPI_LINKNAME_MAX]; 59 int do_clear = 0; 60 int period = 0; 61 int isize, osize; 62 int count; 63 int retval; 64 struct strioctl sioc; 65 uint_t ppa; 66 dlpi_handle_t dh; 67 68 if (argc == 1) { 69 usage(); 70 exit(1); 71 } 72 argc--; /* skip the command name */ 73 argv++; 74 75 /* 76 * The following loop processes command line arguments. 77 * If the argument begins with a '-', it is trated as an option. 78 * The only option currently implemented is "-c" (clears statistics). 79 * If the argument begins with a numeral, it is treated as an interval. 80 * Intervals must be positive integers greater than zero. 81 * Any argument that survives this is treated as a device name to be 82 * found under /dev. 83 */ 84 while (argc > 0) { 85 if (argv[0][0] == '-') { 86 if (argc == 1) { 87 usage(); 88 exit(1); 89 } 90 if (argv[0][1] != 'c') { 91 usage(); 92 exit(1); 93 } 94 do_clear = 1; 95 } else if ((argv[0][0] >= '0') && (argv[0][0] <= '9')) { 96 period = atoi(*argv); 97 if (period == 0) { 98 (void) fprintf(stderr, 99 "syncstat: bad interval: %s\n", *argv); 100 exit(1); 101 } 102 } else { 103 if (snprintf(sername, sizeof (sername), "%s", 104 *argv) >= sizeof (sername)) { 105 (void) fprintf(stderr, "syncstat: invalid " 106 "device name (too long) %s\n", *argv); 107 exit(1); 108 } 109 } 110 argc--; 111 argv++; 112 } 113 114 for (cp = sername; (*cp) && (!isdigit(*cp)); cp++) {} 115 if (*cp == '\0') { /* hit the end without finding a number */ 116 (void) fprintf(stderr, 117 "syncstat: %s missing minor device number\n", sername); 118 exit(1); 119 } 120 121 if ((retval = dlpi_open(sername, &dh, DLPI_SERIAL)) != DLPI_SUCCESS) { 122 (void) fprintf(stderr, "syncstat: dlpi_open %s: %s\n", sername, 123 dlpi_strerror(retval)); 124 exit(1); 125 } 126 127 (void) dlpi_parselink(sername, serdevice, &ppa); 128 (void) printf("syncstat: control device: %s, ppa=%u\n", serdevice, ppa); 129 130 fd = dlpi_fd(dh); 131 sioc.ic_cmd = S_IOCGETMODE; 132 sioc.ic_timout = -1; 133 sioc.ic_len = sizeof (struct scc_mode); 134 sioc.ic_dp = (char *)&sm; 135 if (ioctl(fd, I_STR, &sioc) < 0) { 136 perror("S_IOCGETMODE"); 137 (void) fprintf(stderr, 138 "syncstat: can't get sync mode info for %s\n", sername); 139 exit(1); 140 } 141 if (do_clear) { 142 sioc.ic_cmd = S_IOCCLRSTATS; 143 sioc.ic_timout = -1; 144 sioc.ic_len = sizeof (struct sl_stats); 145 sioc.ic_dp = (char *)&st; 146 if (ioctl(fd, I_STR, &sioc) < 0) { 147 perror("S_IOCCLRSTATS"); 148 (void) fprintf(stderr, 149 "syncstat: can't clear stats for %s\n", sername); 150 exit(1); 151 } 152 } 153 154 sioc.ic_cmd = S_IOCGETSTATS; 155 sioc.ic_timout = -1; 156 sioc.ic_len = sizeof (struct sl_stats); 157 sioc.ic_dp = (char *)&st; 158 if (ioctl(fd, I_STR, &sioc) < 0) { 159 perror("S_IOCGETSTATS"); 160 (void) fprintf(stderr, "syncstat: can't get stats for %s\n", 161 sername); 162 exit(1); 163 } 164 if (period) { 165 if (sm.sm_baudrate == 0) { 166 (void) fprintf(stderr, "syncstat: baud rate not set\n"); 167 exit(1); 168 } 169 for (count = 0; ; count++) { 170 (void) fflush(stdout); 171 (void) sleep(period); 172 sample(count, period); 173 } 174 } 175 isize = osize = 0; 176 if (st.opack) 177 osize = st.ochar / st.opack; 178 if (st.ipack) 179 isize = st.ichar / st.ipack; 180 (void) printf(" speed ipkts opkts undrun ovrrun abort " 181 "crc isize osize\n"); 182 (void) printf(" %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", sm.sm_baudrate, 183 st.ipack, st.opack, st.underrun, st.overrun, st.abort, st.crc, 184 isize, osize); 185 return (0); 186 } 187 188 static void 189 sample(int count, int period) 190 { 191 struct sl_stats nst; 192 struct strioctl sioc; 193 int iutil, outil; 194 195 sioc.ic_cmd = S_IOCGETSTATS; 196 sioc.ic_timout = -1; 197 sioc.ic_len = sizeof (struct sl_stats); 198 sioc.ic_dp = (char *)&nst; 199 if (ioctl(fd, I_STR, &sioc) < 0) { 200 perror("S_IOCGETSTATS"); 201 (void) fprintf(stderr, "syncstat: can't get stats for %s\n", 202 sername); 203 exit(1); 204 } 205 206 st.ipack = nst.ipack - st.ipack; 207 st.opack = nst.opack - st.opack; 208 st.ichar = nst.ichar - st.ichar; 209 st.ochar = nst.ochar - st.ochar; 210 st.crc = nst.crc - st.crc; 211 st.overrun = nst.overrun - st.overrun; 212 st.underrun = nst.underrun - st.underrun; 213 st.abort = nst.abort - st.abort; 214 iutil = 8 * st.ichar / period; 215 iutil = 100 * iutil / sm.sm_baudrate; 216 outil = 8 * st.ochar / period; 217 outil = 100 * outil / sm.sm_baudrate; 218 if ((count % 20) == 0) 219 (void) printf(" ipkts opkts undrun ovrrun abort " 220 "crc iutil outil\n"); 221 (void) printf(" %7d %7d %7d %7d %7d %7d %6d%% %6d%%\n", st.ipack, 222 st.opack, st.underrun, st.overrun, st.abort, st.crc, iutil, outil); 223 224 st = nst; 225 } 226 227 static void 228 usage() 229 { 230 (void) fprintf(stderr, "Usage: syncstat [-c] device [period]\n"); 231 } 232