1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Synchronous loop-back test program 31*0Sstevel@tonic-gate * For installation verification of synchronous lines and facilities 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include <sys/types.h> 35*0Sstevel@tonic-gate #include <ctype.h> 36*0Sstevel@tonic-gate #include <sys/ioctl.h> 37*0Sstevel@tonic-gate #include <fcntl.h> 38*0Sstevel@tonic-gate #include <sys/time.h> 39*0Sstevel@tonic-gate #include <sys/file.h> 40*0Sstevel@tonic-gate #include <stdio.h> 41*0Sstevel@tonic-gate #include <stdlib.h> 42*0Sstevel@tonic-gate #include <unistd.h> 43*0Sstevel@tonic-gate #include <string.h> 44*0Sstevel@tonic-gate #include <errno.h> 45*0Sstevel@tonic-gate #include <sys/stream.h> 46*0Sstevel@tonic-gate #include <sys/stropts.h> 47*0Sstevel@tonic-gate #include <sys/poll.h> 48*0Sstevel@tonic-gate #include <sys/ser_sync.h> 49*0Sstevel@tonic-gate #include <libdlpi.h> 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static void Usage(void); 52*0Sstevel@tonic-gate static void quiet_period(void); 53*0Sstevel@tonic-gate static void first_packet(); 54*0Sstevel@tonic-gate static void many_packets(); 55*0Sstevel@tonic-gate static void printhex(char *cp, int len); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate static char *portname = NULL; 58*0Sstevel@tonic-gate static unsigned int speed = 9600; 59*0Sstevel@tonic-gate static int reccount = 100; 60*0Sstevel@tonic-gate static int reclen = 100; 61*0Sstevel@tonic-gate static char loopstr[MAX_INPUT]; 62*0Sstevel@tonic-gate static int looptype = 0; 63*0Sstevel@tonic-gate static int loopchange = 0; 64*0Sstevel@tonic-gate static int clockchange = 0; 65*0Sstevel@tonic-gate static int cfd, dfd; /* control and data descriptors */ 66*0Sstevel@tonic-gate static int data = -1; 67*0Sstevel@tonic-gate static int verbose = 0; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate static char *yesno[] = { 70*0Sstevel@tonic-gate "no", 71*0Sstevel@tonic-gate "yes", 72*0Sstevel@tonic-gate "silent", 73*0Sstevel@tonic-gate 0, 74*0Sstevel@tonic-gate }; 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate static char *txnames[] = { 77*0Sstevel@tonic-gate "txc", 78*0Sstevel@tonic-gate "rxc", 79*0Sstevel@tonic-gate "baud", 80*0Sstevel@tonic-gate "pll", 81*0Sstevel@tonic-gate "sysclk", 82*0Sstevel@tonic-gate "-txc", 83*0Sstevel@tonic-gate 0, 84*0Sstevel@tonic-gate }; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate static char *rxnames[] = { 87*0Sstevel@tonic-gate "rxc", 88*0Sstevel@tonic-gate "txc", 89*0Sstevel@tonic-gate "baud", 90*0Sstevel@tonic-gate "pll", 91*0Sstevel@tonic-gate "sysclk", 92*0Sstevel@tonic-gate "-rxc", 93*0Sstevel@tonic-gate 0, 94*0Sstevel@tonic-gate }; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate #define MAXPACKET 4096 97*0Sstevel@tonic-gate #define MAXWAIT 15 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate int 100*0Sstevel@tonic-gate main(int argc, char **argv) 101*0Sstevel@tonic-gate { 102*0Sstevel@tonic-gate char cnambuf[MAXPATHLEN], dnambuf[MAXPATHLEN], *cp, *cpp; 103*0Sstevel@tonic-gate struct scc_mode sm; 104*0Sstevel@tonic-gate struct strioctl sioc; 105*0Sstevel@tonic-gate ulong_t ppa; 106*0Sstevel@tonic-gate char *devstr = "/dev/"; 107*0Sstevel@tonic-gate int devstrlen; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate argc--; 110*0Sstevel@tonic-gate argv++; 111*0Sstevel@tonic-gate while (argc > 0 && argv[0][0] == '-') 112*0Sstevel@tonic-gate switch (argv[0][1]) { 113*0Sstevel@tonic-gate case 'c': /* rec count */ 114*0Sstevel@tonic-gate if (argc < 2) 115*0Sstevel@tonic-gate Usage(); 116*0Sstevel@tonic-gate reccount = atoi(argv[1]); 117*0Sstevel@tonic-gate argc -= 2; 118*0Sstevel@tonic-gate argv += 2; 119*0Sstevel@tonic-gate break; 120*0Sstevel@tonic-gate case 'd': 121*0Sstevel@tonic-gate if (sscanf(argv[1], "%x", (uint_t *)&data) != 1) 122*0Sstevel@tonic-gate Usage(); 123*0Sstevel@tonic-gate argc -= 2; 124*0Sstevel@tonic-gate argv += 2; 125*0Sstevel@tonic-gate break; 126*0Sstevel@tonic-gate case 'l': /* rec length */ 127*0Sstevel@tonic-gate if (argc < 2) 128*0Sstevel@tonic-gate Usage(); 129*0Sstevel@tonic-gate reclen = atoi(argv[1]); 130*0Sstevel@tonic-gate argc -= 2; 131*0Sstevel@tonic-gate argv += 2; 132*0Sstevel@tonic-gate break; 133*0Sstevel@tonic-gate case 's': /* line speed */ 134*0Sstevel@tonic-gate if (argc < 2) 135*0Sstevel@tonic-gate Usage(); 136*0Sstevel@tonic-gate speed = atoi(argv[1]); 137*0Sstevel@tonic-gate argc -= 2; 138*0Sstevel@tonic-gate argv += 2; 139*0Sstevel@tonic-gate break; 140*0Sstevel@tonic-gate case 't': /* test type */ 141*0Sstevel@tonic-gate if (argc < 2) 142*0Sstevel@tonic-gate Usage(); 143*0Sstevel@tonic-gate looptype = atoi(argv[1]); 144*0Sstevel@tonic-gate argc -= 2; 145*0Sstevel@tonic-gate argv += 2; 146*0Sstevel@tonic-gate break; 147*0Sstevel@tonic-gate case 'v': 148*0Sstevel@tonic-gate verbose = 1; 149*0Sstevel@tonic-gate argc--; 150*0Sstevel@tonic-gate argv++; 151*0Sstevel@tonic-gate break; 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate if (argc != 1) 154*0Sstevel@tonic-gate Usage(); 155*0Sstevel@tonic-gate portname = argv[0]; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate devstrlen = strlen(devstr); 158*0Sstevel@tonic-gate if (strncmp(devstr, portname, devstrlen) != 0) { 159*0Sstevel@tonic-gate if (snprintf(dnambuf, sizeof (dnambuf), "%s%s", devstr, 160*0Sstevel@tonic-gate portname) >= sizeof (dnambuf)) { 161*0Sstevel@tonic-gate (void) fprintf(stderr, 162*0Sstevel@tonic-gate "syncloop: invalid device name (too long) %s\n", 163*0Sstevel@tonic-gate portname); 164*0Sstevel@tonic-gate exit(1); 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate dfd = open(dnambuf, O_RDWR); 169*0Sstevel@tonic-gate if (dfd < 0) { 170*0Sstevel@tonic-gate (void) fprintf(stderr, "syncloop: cannot open %s\n", dnambuf); 171*0Sstevel@tonic-gate perror(dnambuf); 172*0Sstevel@tonic-gate exit(1); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate for (cp = portname; (*cp) && (!isdigit(*cp)); cp++) {} 175*0Sstevel@tonic-gate ppa = strtoul(cp, &cpp, 10); 176*0Sstevel@tonic-gate if (cpp == cp) { 177*0Sstevel@tonic-gate (void) fprintf(stderr, 178*0Sstevel@tonic-gate "syncloop: %s missing minor device number\n", portname); 179*0Sstevel@tonic-gate exit(1); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate *cp = '\0'; /* drop number, leaving name of clone device. */ 182*0Sstevel@tonic-gate /* the following won't fail since cnambuf and dnambuf are same size */ 183*0Sstevel@tonic-gate if (strncmp(devstr, portname, devstrlen) != 0) { 184*0Sstevel@tonic-gate (void) snprintf(cnambuf, sizeof (cnambuf), "%s%s", devstr, 185*0Sstevel@tonic-gate portname); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate cfd = open(cnambuf, O_RDWR); 188*0Sstevel@tonic-gate if (cfd < 0) { 189*0Sstevel@tonic-gate (void) fprintf(stderr, "syncloop: cannot open %s\n", cnambuf); 190*0Sstevel@tonic-gate perror(cnambuf); 191*0Sstevel@tonic-gate exit(1); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate if (dlpi_attach(cfd, MAXWAIT, ppa) != 0) { 195*0Sstevel@tonic-gate perror("syncloop: dlpi_attach"); 196*0Sstevel@tonic-gate exit(1); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate if (reclen < 0 || reclen > MAXPACKET) { 200*0Sstevel@tonic-gate (void) printf("invalid packet length: %d\n", reclen); 201*0Sstevel@tonic-gate exit(1); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate (void) printf("[ Data device: %s | Control device: %s, ppa=%ld ]\n", 204*0Sstevel@tonic-gate dnambuf, cnambuf, ppa); 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETMODE; 207*0Sstevel@tonic-gate sioc.ic_timout = -1; 208*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 209*0Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 210*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 211*0Sstevel@tonic-gate perror("S_IOCGETMODE"); 212*0Sstevel@tonic-gate (void) fprintf(stderr, 213*0Sstevel@tonic-gate "syncloop: can't get sync mode info for %s\n", cnambuf); 214*0Sstevel@tonic-gate exit(1); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate while (looptype < 1 || looptype > 4) { 217*0Sstevel@tonic-gate (void) printf("Enter test type:\n"); 218*0Sstevel@tonic-gate (void) printf("1: Internal Test\n"); 219*0Sstevel@tonic-gate (void) printf( 220*0Sstevel@tonic-gate " (internal data loop, internal clocking)\n"); 221*0Sstevel@tonic-gate (void) printf("2: Test using loopback plugs\n"); 222*0Sstevel@tonic-gate (void) printf( 223*0Sstevel@tonic-gate " (external data loop, internal clocking)\n"); 224*0Sstevel@tonic-gate (void) printf("3: Test using local or remote modem loopback\n"); 225*0Sstevel@tonic-gate (void) printf( 226*0Sstevel@tonic-gate " (external data loop, external clocking)\n"); 227*0Sstevel@tonic-gate (void) printf("4: Other, previously set, special mode\n"); 228*0Sstevel@tonic-gate (void) printf("> "); (void) fflush(stdout); 229*0Sstevel@tonic-gate (void) fgets(loopstr, sizeof (loopstr), stdin); 230*0Sstevel@tonic-gate (void) sscanf(loopstr, "%d", &looptype); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate switch (looptype) { 233*0Sstevel@tonic-gate case 1: 234*0Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_BAUD) || 235*0Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_BAUD)) 236*0Sstevel@tonic-gate clockchange++; 237*0Sstevel@tonic-gate sm.sm_txclock = TXC_IS_BAUD; 238*0Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_BAUD; 239*0Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) == 0) 240*0Sstevel@tonic-gate loopchange++; 241*0Sstevel@tonic-gate sm.sm_config |= CONN_LPBK; 242*0Sstevel@tonic-gate break; 243*0Sstevel@tonic-gate case 2: 244*0Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_BAUD) || 245*0Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_RXC)) 246*0Sstevel@tonic-gate clockchange++; 247*0Sstevel@tonic-gate sm.sm_txclock = TXC_IS_BAUD; 248*0Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_RXC; 249*0Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) != 0) 250*0Sstevel@tonic-gate loopchange++; 251*0Sstevel@tonic-gate sm.sm_config &= ~CONN_LPBK; 252*0Sstevel@tonic-gate break; 253*0Sstevel@tonic-gate case 3: 254*0Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_TXC) || 255*0Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_RXC)) 256*0Sstevel@tonic-gate clockchange++; 257*0Sstevel@tonic-gate sm.sm_txclock = TXC_IS_TXC; 258*0Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_RXC; 259*0Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) != 0) 260*0Sstevel@tonic-gate loopchange++; 261*0Sstevel@tonic-gate sm.sm_config &= ~CONN_LPBK; 262*0Sstevel@tonic-gate break; 263*0Sstevel@tonic-gate case 4: 264*0Sstevel@tonic-gate goto no_params; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate sm.sm_baudrate = speed; 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCSETMODE; 270*0Sstevel@tonic-gate sioc.ic_timout = -1; 271*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 272*0Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 273*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 274*0Sstevel@tonic-gate perror("S_IOCSETMODE"); 275*0Sstevel@tonic-gate (void) fprintf(stderr, 276*0Sstevel@tonic-gate "syncloop: can't set sync mode info for %s\n", cnambuf); 277*0Sstevel@tonic-gate exit(1); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate no_params: 281*0Sstevel@tonic-gate /* report state */ 282*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETMODE; 283*0Sstevel@tonic-gate sioc.ic_timout = -1; 284*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 285*0Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 286*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 287*0Sstevel@tonic-gate perror("S_IOCGETMODE"); 288*0Sstevel@tonic-gate (void) fprintf(stderr, 289*0Sstevel@tonic-gate "syncloop: can't get sync mode info for %s\n", cnambuf); 290*0Sstevel@tonic-gate exit(1); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate (void) printf("speed=%d, loopback=%s, nrzi=%s, txc=%s, rxc=%s\n", 293*0Sstevel@tonic-gate sm.sm_baudrate, 294*0Sstevel@tonic-gate yesno[((int)(sm.sm_config & CONN_LPBK) > 0)], 295*0Sstevel@tonic-gate yesno[((int)(sm.sm_config & CONN_NRZI) > 0)], 296*0Sstevel@tonic-gate txnames[sm.sm_txclock], 297*0Sstevel@tonic-gate rxnames[sm.sm_rxclock]); 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate quiet_period(); 300*0Sstevel@tonic-gate first_packet(); 301*0Sstevel@tonic-gate many_packets(); 302*0Sstevel@tonic-gate return (0); 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate static void 306*0Sstevel@tonic-gate Usage() 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate (void) printf("Usage: syncloop [ options ] portname\n"); 309*0Sstevel@tonic-gate (void) printf("Options: -c packet_count\n"); 310*0Sstevel@tonic-gate (void) printf(" -l packet_length\n"); 311*0Sstevel@tonic-gate (void) printf(" -s line_speed\n"); 312*0Sstevel@tonic-gate (void) printf(" -t test_type\n"); 313*0Sstevel@tonic-gate (void) printf(" -d hex_data_byte\n"); 314*0Sstevel@tonic-gate exit(1); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate static int zero_time = 0; 318*0Sstevel@tonic-gate static int short_time = 1000; 319*0Sstevel@tonic-gate static int long_time = 4000; 320*0Sstevel@tonic-gate static char bigbuf[4096]; 321*0Sstevel@tonic-gate static char packet[MAXPACKET]; 322*0Sstevel@tonic-gate static struct pollfd pfd; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate static void 325*0Sstevel@tonic-gate quiet_period() 326*0Sstevel@tonic-gate { 327*0Sstevel@tonic-gate (void) printf("[ checking for quiet line ]\n"); 328*0Sstevel@tonic-gate pfd.fd = dfd; 329*0Sstevel@tonic-gate pfd.events = POLLIN; 330*0Sstevel@tonic-gate pfd.revents = 0; 331*0Sstevel@tonic-gate while (poll(&pfd, 1, short_time) == 1) { 332*0Sstevel@tonic-gate (void) read(dfd, bigbuf, sizeof (bigbuf)); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate if (poll(&pfd, 1, long_time) == 1) { 335*0Sstevel@tonic-gate (void) printf("packet received but none sent!\n"); 336*0Sstevel@tonic-gate (void) printf("quiesce other end before starting syncloop\n"); 337*0Sstevel@tonic-gate exit(1); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate static void 342*0Sstevel@tonic-gate first_packet() 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate int i, len; 345*0Sstevel@tonic-gate int pollret; 346*0Sstevel@tonic-gate struct strioctl sioc; 347*0Sstevel@tonic-gate struct sl_stats start_stats, end_stats; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate for (i = 0; i < reclen; i++) 350*0Sstevel@tonic-gate packet[i] = (data == -1) ? rand() : data; 351*0Sstevel@tonic-gate (void) printf("[ Trying first packet ]\n"); 352*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 353*0Sstevel@tonic-gate sioc.ic_timout = -1; 354*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 355*0Sstevel@tonic-gate sioc.ic_dp = (char *)&start_stats; 356*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 357*0Sstevel@tonic-gate perror("S_IOCGETSTATS"); 358*0Sstevel@tonic-gate exit(1); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate for (i = 0; i < 5; i++) { 362*0Sstevel@tonic-gate if (write(dfd, packet, reclen) != reclen) { 363*0Sstevel@tonic-gate (void) fprintf(stderr, 364*0Sstevel@tonic-gate "packet write failed, errno %d\n", 365*0Sstevel@tonic-gate errno); 366*0Sstevel@tonic-gate exit(1); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate pfd.fd = dfd; 369*0Sstevel@tonic-gate pfd.events = POLLIN; 370*0Sstevel@tonic-gate pollret = poll(&pfd, 1, long_time); 371*0Sstevel@tonic-gate if (pollret < 0) perror("poll"); 372*0Sstevel@tonic-gate if (pollret == 0) 373*0Sstevel@tonic-gate (void) printf("poll: nothing to read.\n"); 374*0Sstevel@tonic-gate if (pollret == 1) { 375*0Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 376*0Sstevel@tonic-gate if (len == reclen && memcmp(packet, bigbuf, len) == 0) 377*0Sstevel@tonic-gate return; /* success */ 378*0Sstevel@tonic-gate else { 379*0Sstevel@tonic-gate (void) printf("len %d should be %d\n", 380*0Sstevel@tonic-gate len, reclen); 381*0Sstevel@tonic-gate if (verbose) { 382*0Sstevel@tonic-gate (void) printf(" "); 383*0Sstevel@tonic-gate printhex(bigbuf, len); 384*0Sstevel@tonic-gate (void) printf("\nshould be "); 385*0Sstevel@tonic-gate printhex(packet, reclen); 386*0Sstevel@tonic-gate (void) printf("\n"); 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate (void) printf("Loopback has TOTALLY FAILED - "); 392*0Sstevel@tonic-gate (void) printf("no packets returned after 5 attempts\n"); 393*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 394*0Sstevel@tonic-gate sioc.ic_timout = -1; 395*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 396*0Sstevel@tonic-gate sioc.ic_dp = (char *)&end_stats; 397*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 398*0Sstevel@tonic-gate perror("S_IOCGETSTATS"); 399*0Sstevel@tonic-gate exit(1); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate if (start_stats.opack == end_stats.opack) 402*0Sstevel@tonic-gate (void) printf( 403*0Sstevel@tonic-gate "No packets transmitted - no transmit clock present\n"); 404*0Sstevel@tonic-gate exit(1); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate static void 408*0Sstevel@tonic-gate many_packets() 409*0Sstevel@tonic-gate { 410*0Sstevel@tonic-gate struct strioctl sioc; 411*0Sstevel@tonic-gate struct sl_stats start_stats, end_stats; 412*0Sstevel@tonic-gate struct timeval start_time, end_time; 413*0Sstevel@tonic-gate int baddata = 0; 414*0Sstevel@tonic-gate float secs, speed; 415*0Sstevel@tonic-gate int i, len; 416*0Sstevel@tonic-gate int incount = 0; 417*0Sstevel@tonic-gate long prev_sec = -1; 418*0Sstevel@tonic-gate int pollret; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate (void) printf("[ Trying many packets ]\n"); 421*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 422*0Sstevel@tonic-gate sioc.ic_timout = -1; 423*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 424*0Sstevel@tonic-gate sioc.ic_dp = (char *)&start_stats; 425*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 426*0Sstevel@tonic-gate perror("S_IOCGETSTATS"); 427*0Sstevel@tonic-gate exit(1); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate (void) gettimeofday(&start_time, 0); 430*0Sstevel@tonic-gate end_time = start_time; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate i = 0; 433*0Sstevel@tonic-gate while (i < reccount) { 434*0Sstevel@tonic-gate if (end_time.tv_sec != prev_sec) { 435*0Sstevel@tonic-gate prev_sec = end_time.tv_sec; 436*0Sstevel@tonic-gate (void) printf("\r %d ", incount); 437*0Sstevel@tonic-gate (void) fflush(stdout); 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate pfd.fd = dfd; 440*0Sstevel@tonic-gate pfd.events = POLLIN; 441*0Sstevel@tonic-gate while (pollret = poll(&pfd, 1, zero_time)) { 442*0Sstevel@tonic-gate if (pollret < 0) 443*0Sstevel@tonic-gate perror("poll"); 444*0Sstevel@tonic-gate else { 445*0Sstevel@tonic-gate (void) lseek(dfd, (long)0, 0); 446*0Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 447*0Sstevel@tonic-gate if (len != reclen || 448*0Sstevel@tonic-gate memcmp(packet, bigbuf, len) != 0) { 449*0Sstevel@tonic-gate (void) printf("len %d should be %d\n", 450*0Sstevel@tonic-gate len, reclen); 451*0Sstevel@tonic-gate if (verbose) { 452*0Sstevel@tonic-gate (void) printf(" "); 453*0Sstevel@tonic-gate printhex(bigbuf, len); 454*0Sstevel@tonic-gate (void) printf("\nshould be "); 455*0Sstevel@tonic-gate printhex(packet, reclen); 456*0Sstevel@tonic-gate (void) printf("\n"); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate baddata++; 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate incount++; 461*0Sstevel@tonic-gate (void) gettimeofday(&end_time, 0); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate pfd.fd = dfd; 465*0Sstevel@tonic-gate pfd.events = POLLIN|POLLOUT; 466*0Sstevel@tonic-gate pollret = poll(&pfd, 1, long_time); 467*0Sstevel@tonic-gate if (pollret < 0) 468*0Sstevel@tonic-gate perror("poll"); 469*0Sstevel@tonic-gate if (pollret == 0) 470*0Sstevel@tonic-gate (void) printf("poll: nothing to read or write.\n"); 471*0Sstevel@tonic-gate if (pollret == 1) { 472*0Sstevel@tonic-gate if (pfd.revents & POLLOUT) { 473*0Sstevel@tonic-gate (void) write(dfd, packet, reclen); 474*0Sstevel@tonic-gate i++; 475*0Sstevel@tonic-gate } else if (!(pfd.revents & POLLIN)) { 476*0Sstevel@tonic-gate (void) printf("OUTPUT HAS LOCKED UP!!!\n"); 477*0Sstevel@tonic-gate break; 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate pfd.fd = dfd; 482*0Sstevel@tonic-gate pfd.events = POLLIN; 483*0Sstevel@tonic-gate while ((incount < reccount) && (poll(&pfd, 1, long_time) == 1)) { 484*0Sstevel@tonic-gate if (end_time.tv_sec != prev_sec) { 485*0Sstevel@tonic-gate prev_sec = end_time.tv_sec; 486*0Sstevel@tonic-gate (void) printf("\r %d ", incount); 487*0Sstevel@tonic-gate (void) fflush(stdout); 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 490*0Sstevel@tonic-gate if (len != reclen || memcmp(packet, bigbuf, len) != 0) { 491*0Sstevel@tonic-gate (void) printf("len %d should be %d\n", len, reclen); 492*0Sstevel@tonic-gate if (verbose) { 493*0Sstevel@tonic-gate (void) printf(" "); 494*0Sstevel@tonic-gate printhex(bigbuf, len); 495*0Sstevel@tonic-gate (void) printf("\nshould be "); 496*0Sstevel@tonic-gate printhex(packet, reclen); 497*0Sstevel@tonic-gate (void) printf("\n"); 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate baddata++; 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate incount++; 502*0Sstevel@tonic-gate (void) gettimeofday(&end_time, 0); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate (void) printf("\r %d \n", incount); 505*0Sstevel@tonic-gate if (baddata) 506*0Sstevel@tonic-gate (void) printf("%d packets with wrong data received!\n", 507*0Sstevel@tonic-gate baddata); 508*0Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 509*0Sstevel@tonic-gate sioc.ic_timout = -1; 510*0Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 511*0Sstevel@tonic-gate sioc.ic_dp = (char *)&end_stats; 512*0Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 513*0Sstevel@tonic-gate perror("S_IOCGETSTATS"); 514*0Sstevel@tonic-gate exit(1); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate end_stats.ipack -= start_stats.ipack; 517*0Sstevel@tonic-gate end_stats.opack -= start_stats.opack; 518*0Sstevel@tonic-gate end_stats.abort -= start_stats.abort; 519*0Sstevel@tonic-gate end_stats.crc -= start_stats.crc; 520*0Sstevel@tonic-gate end_stats.overrun -= start_stats.overrun; 521*0Sstevel@tonic-gate end_stats.underrun -= start_stats.underrun; 522*0Sstevel@tonic-gate end_stats.ierror -= start_stats.ierror; 523*0Sstevel@tonic-gate end_stats.oerror -= start_stats.oerror; 524*0Sstevel@tonic-gate if (reccount > end_stats.opack) 525*0Sstevel@tonic-gate (void) printf("%d packets lost in outbound queueing\n", 526*0Sstevel@tonic-gate reccount - end_stats.opack); 527*0Sstevel@tonic-gate if (incount < end_stats.ipack && incount < reccount) 528*0Sstevel@tonic-gate (void) printf("%d packets lost in inbound queueing\n", 529*0Sstevel@tonic-gate end_stats.ipack - incount); 530*0Sstevel@tonic-gate (void) printf("%d packets sent, %d received\n", reccount, incount); 531*0Sstevel@tonic-gate (void) printf("CRC errors Aborts Overruns Underruns "); 532*0Sstevel@tonic-gate (void) printf(" In <-Drops-> Out\n%9d %9d %9d %9d %12d %12d\n", 533*0Sstevel@tonic-gate end_stats.crc, end_stats.abort, 534*0Sstevel@tonic-gate end_stats.overrun, end_stats.underrun, 535*0Sstevel@tonic-gate end_stats.ierror, end_stats.oerror); 536*0Sstevel@tonic-gate secs = (float)(end_time.tv_usec - start_time.tv_usec) / 1000000.0; 537*0Sstevel@tonic-gate secs += (float)(end_time.tv_sec - start_time.tv_sec); 538*0Sstevel@tonic-gate if (secs) { 539*0Sstevel@tonic-gate speed = 8 * incount * (4 + reclen) / secs; 540*0Sstevel@tonic-gate (void) printf("estimated line speed = %d bps\n", (int)speed); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate static void 545*0Sstevel@tonic-gate printhex(char *cp, int len) 546*0Sstevel@tonic-gate { 547*0Sstevel@tonic-gate char c, *hex = "0123456789ABCDEF"; 548*0Sstevel@tonic-gate int i; 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate for (i = 0; i < len; i++) { 551*0Sstevel@tonic-gate c = *cp++; 552*0Sstevel@tonic-gate (void) putchar(hex[(c >> 4) & 0xF]); 553*0Sstevel@tonic-gate (void) putchar(hex[c & 0xF]); 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate } 556