17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*c7e4935fSss150715 * Common Development and Distribution License (the "License"). 6*c7e4935fSss150715 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*c7e4935fSss150715 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Synchronous loop-back test program 307c478bd9Sstevel@tonic-gate * For installation verification of synchronous lines and facilities 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <sys/time.h> 387c478bd9Sstevel@tonic-gate #include <sys/file.h> 397c478bd9Sstevel@tonic-gate #include <stdio.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <string.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <sys/stream.h> 457c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 467c478bd9Sstevel@tonic-gate #include <sys/poll.h> 477c478bd9Sstevel@tonic-gate #include <sys/ser_sync.h> 487c478bd9Sstevel@tonic-gate #include <libdlpi.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static void Usage(void); 517c478bd9Sstevel@tonic-gate static void quiet_period(void); 527c478bd9Sstevel@tonic-gate static void first_packet(); 537c478bd9Sstevel@tonic-gate static void many_packets(); 547c478bd9Sstevel@tonic-gate static void printhex(char *cp, int len); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static unsigned int speed = 9600; 577c478bd9Sstevel@tonic-gate static int reccount = 100; 587c478bd9Sstevel@tonic-gate static int reclen = 100; 597c478bd9Sstevel@tonic-gate static char loopstr[MAX_INPUT]; 607c478bd9Sstevel@tonic-gate static int looptype = 0; 617c478bd9Sstevel@tonic-gate static int loopchange = 0; 627c478bd9Sstevel@tonic-gate static int clockchange = 0; 637c478bd9Sstevel@tonic-gate static int cfd, dfd; /* control and data descriptors */ 647c478bd9Sstevel@tonic-gate static int data = -1; 657c478bd9Sstevel@tonic-gate static int verbose = 0; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static char *yesno[] = { 687c478bd9Sstevel@tonic-gate "no", 697c478bd9Sstevel@tonic-gate "yes", 707c478bd9Sstevel@tonic-gate "silent", 717c478bd9Sstevel@tonic-gate 0, 727c478bd9Sstevel@tonic-gate }; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static char *txnames[] = { 757c478bd9Sstevel@tonic-gate "txc", 767c478bd9Sstevel@tonic-gate "rxc", 777c478bd9Sstevel@tonic-gate "baud", 787c478bd9Sstevel@tonic-gate "pll", 797c478bd9Sstevel@tonic-gate "sysclk", 807c478bd9Sstevel@tonic-gate "-txc", 817c478bd9Sstevel@tonic-gate 0, 827c478bd9Sstevel@tonic-gate }; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate static char *rxnames[] = { 857c478bd9Sstevel@tonic-gate "rxc", 867c478bd9Sstevel@tonic-gate "txc", 877c478bd9Sstevel@tonic-gate "baud", 887c478bd9Sstevel@tonic-gate "pll", 897c478bd9Sstevel@tonic-gate "sysclk", 907c478bd9Sstevel@tonic-gate "-rxc", 917c478bd9Sstevel@tonic-gate 0, 927c478bd9Sstevel@tonic-gate }; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate #define MAXPACKET 4096 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate int 977c478bd9Sstevel@tonic-gate main(int argc, char **argv) 987c478bd9Sstevel@tonic-gate { 99*c7e4935fSss150715 char *portname; 100*c7e4935fSss150715 char dnambuf[MAXPATHLEN], *cp; 101*c7e4935fSss150715 char device[DLPI_LINKNAME_MAX]; 1027c478bd9Sstevel@tonic-gate struct scc_mode sm; 1037c478bd9Sstevel@tonic-gate struct strioctl sioc; 104*c7e4935fSss150715 uint_t ppa; 1057c478bd9Sstevel@tonic-gate char *devstr = "/dev/"; 1067c478bd9Sstevel@tonic-gate int devstrlen; 107*c7e4935fSss150715 int retval; 108*c7e4935fSss150715 dlpi_handle_t dh; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate argc--; 1117c478bd9Sstevel@tonic-gate argv++; 1127c478bd9Sstevel@tonic-gate while (argc > 0 && argv[0][0] == '-') 1137c478bd9Sstevel@tonic-gate switch (argv[0][1]) { 1147c478bd9Sstevel@tonic-gate case 'c': /* rec count */ 1157c478bd9Sstevel@tonic-gate if (argc < 2) 1167c478bd9Sstevel@tonic-gate Usage(); 1177c478bd9Sstevel@tonic-gate reccount = atoi(argv[1]); 1187c478bd9Sstevel@tonic-gate argc -= 2; 1197c478bd9Sstevel@tonic-gate argv += 2; 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate case 'd': 1227c478bd9Sstevel@tonic-gate if (sscanf(argv[1], "%x", (uint_t *)&data) != 1) 1237c478bd9Sstevel@tonic-gate Usage(); 1247c478bd9Sstevel@tonic-gate argc -= 2; 1257c478bd9Sstevel@tonic-gate argv += 2; 1267c478bd9Sstevel@tonic-gate break; 1277c478bd9Sstevel@tonic-gate case 'l': /* rec length */ 1287c478bd9Sstevel@tonic-gate if (argc < 2) 1297c478bd9Sstevel@tonic-gate Usage(); 1307c478bd9Sstevel@tonic-gate reclen = atoi(argv[1]); 1317c478bd9Sstevel@tonic-gate argc -= 2; 1327c478bd9Sstevel@tonic-gate argv += 2; 1337c478bd9Sstevel@tonic-gate break; 1347c478bd9Sstevel@tonic-gate case 's': /* line speed */ 1357c478bd9Sstevel@tonic-gate if (argc < 2) 1367c478bd9Sstevel@tonic-gate Usage(); 1377c478bd9Sstevel@tonic-gate speed = atoi(argv[1]); 1387c478bd9Sstevel@tonic-gate argc -= 2; 1397c478bd9Sstevel@tonic-gate argv += 2; 1407c478bd9Sstevel@tonic-gate break; 1417c478bd9Sstevel@tonic-gate case 't': /* test type */ 1427c478bd9Sstevel@tonic-gate if (argc < 2) 1437c478bd9Sstevel@tonic-gate Usage(); 1447c478bd9Sstevel@tonic-gate looptype = atoi(argv[1]); 1457c478bd9Sstevel@tonic-gate argc -= 2; 1467c478bd9Sstevel@tonic-gate argv += 2; 1477c478bd9Sstevel@tonic-gate break; 1487c478bd9Sstevel@tonic-gate case 'v': 1497c478bd9Sstevel@tonic-gate verbose = 1; 1507c478bd9Sstevel@tonic-gate argc--; 1517c478bd9Sstevel@tonic-gate argv++; 1527c478bd9Sstevel@tonic-gate break; 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate if (argc != 1) 1557c478bd9Sstevel@tonic-gate Usage(); 1567c478bd9Sstevel@tonic-gate portname = argv[0]; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate devstrlen = strlen(devstr); 1597c478bd9Sstevel@tonic-gate if (strncmp(devstr, portname, devstrlen) != 0) { 1607c478bd9Sstevel@tonic-gate if (snprintf(dnambuf, sizeof (dnambuf), "%s%s", devstr, 1617c478bd9Sstevel@tonic-gate portname) >= sizeof (dnambuf)) { 1627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1637c478bd9Sstevel@tonic-gate "syncloop: invalid device name (too long) %s\n", 1647c478bd9Sstevel@tonic-gate portname); 1657c478bd9Sstevel@tonic-gate exit(1); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate dfd = open(dnambuf, O_RDWR); 1707c478bd9Sstevel@tonic-gate if (dfd < 0) { 1717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "syncloop: cannot open %s\n", dnambuf); 1727c478bd9Sstevel@tonic-gate perror(dnambuf); 1737c478bd9Sstevel@tonic-gate exit(1); 1747c478bd9Sstevel@tonic-gate } 175*c7e4935fSss150715 176*c7e4935fSss150715 cp = portname; 177*c7e4935fSss150715 while (*cp) /* find the end of the name */ 178*c7e4935fSss150715 cp++; 179*c7e4935fSss150715 cp--; 180*c7e4935fSss150715 if (!isdigit(*cp)) { 1817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1827c478bd9Sstevel@tonic-gate "syncloop: %s missing minor device number\n", portname); 1837c478bd9Sstevel@tonic-gate exit(1); 1847c478bd9Sstevel@tonic-gate } 185*c7e4935fSss150715 186*c7e4935fSss150715 if (strlen(portname) >= DLPI_LINKNAME_MAX) { 187*c7e4935fSss150715 (void) fprintf(stderr, 188*c7e4935fSss150715 "syncloop: invalid device name (too long) %s\n", 1897c478bd9Sstevel@tonic-gate portname); 1907c478bd9Sstevel@tonic-gate exit(1); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 193*c7e4935fSss150715 if ((retval = dlpi_open(portname, &dh, DLPI_SERIAL)) != DLPI_SUCCESS) { 194*c7e4935fSss150715 (void) fprintf(stderr, "syncloop: dlpi_open %s: %s\n", portname, 195*c7e4935fSss150715 dlpi_strerror(retval)); 1967c478bd9Sstevel@tonic-gate exit(1); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 199*c7e4935fSss150715 (void) dlpi_parselink(portname, device, &ppa); 200*c7e4935fSss150715 2017c478bd9Sstevel@tonic-gate if (reclen < 0 || reclen > MAXPACKET) { 2027c478bd9Sstevel@tonic-gate (void) printf("invalid packet length: %d\n", reclen); 2037c478bd9Sstevel@tonic-gate exit(1); 2047c478bd9Sstevel@tonic-gate } 205*c7e4935fSss150715 (void) printf("[ Data device: %s | Control device: %s, ppa=%u ]\n", 206*c7e4935fSss150715 dnambuf, device, ppa); 207*c7e4935fSss150715 208*c7e4935fSss150715 cfd = dlpi_fd(dh); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETMODE; 2117c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 2127c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 2137c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 2147c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 2157c478bd9Sstevel@tonic-gate perror("S_IOCGETMODE"); 216*c7e4935fSss150715 (void) fprintf(stderr, "syncloop: can't get sync mode info " 217*c7e4935fSss150715 "for %s\n", portname); 2187c478bd9Sstevel@tonic-gate exit(1); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate while (looptype < 1 || looptype > 4) { 2217c478bd9Sstevel@tonic-gate (void) printf("Enter test type:\n"); 2227c478bd9Sstevel@tonic-gate (void) printf("1: Internal Test\n"); 2237c478bd9Sstevel@tonic-gate (void) printf( 2247c478bd9Sstevel@tonic-gate " (internal data loop, internal clocking)\n"); 2257c478bd9Sstevel@tonic-gate (void) printf("2: Test using loopback plugs\n"); 2267c478bd9Sstevel@tonic-gate (void) printf( 2277c478bd9Sstevel@tonic-gate " (external data loop, internal clocking)\n"); 2287c478bd9Sstevel@tonic-gate (void) printf("3: Test using local or remote modem loopback\n"); 2297c478bd9Sstevel@tonic-gate (void) printf( 2307c478bd9Sstevel@tonic-gate " (external data loop, external clocking)\n"); 2317c478bd9Sstevel@tonic-gate (void) printf("4: Other, previously set, special mode\n"); 2327c478bd9Sstevel@tonic-gate (void) printf("> "); (void) fflush(stdout); 2337c478bd9Sstevel@tonic-gate (void) fgets(loopstr, sizeof (loopstr), stdin); 2347c478bd9Sstevel@tonic-gate (void) sscanf(loopstr, "%d", &looptype); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate switch (looptype) { 2377c478bd9Sstevel@tonic-gate case 1: 2387c478bd9Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_BAUD) || 2397c478bd9Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_BAUD)) 2407c478bd9Sstevel@tonic-gate clockchange++; 2417c478bd9Sstevel@tonic-gate sm.sm_txclock = TXC_IS_BAUD; 2427c478bd9Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_BAUD; 2437c478bd9Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) == 0) 2447c478bd9Sstevel@tonic-gate loopchange++; 2457c478bd9Sstevel@tonic-gate sm.sm_config |= CONN_LPBK; 2467c478bd9Sstevel@tonic-gate break; 2477c478bd9Sstevel@tonic-gate case 2: 2487c478bd9Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_BAUD) || 2497c478bd9Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_RXC)) 2507c478bd9Sstevel@tonic-gate clockchange++; 2517c478bd9Sstevel@tonic-gate sm.sm_txclock = TXC_IS_BAUD; 2527c478bd9Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_RXC; 2537c478bd9Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) != 0) 2547c478bd9Sstevel@tonic-gate loopchange++; 2557c478bd9Sstevel@tonic-gate sm.sm_config &= ~CONN_LPBK; 2567c478bd9Sstevel@tonic-gate break; 2577c478bd9Sstevel@tonic-gate case 3: 2587c478bd9Sstevel@tonic-gate if ((sm.sm_txclock != TXC_IS_TXC) || 2597c478bd9Sstevel@tonic-gate (sm.sm_rxclock != RXC_IS_RXC)) 2607c478bd9Sstevel@tonic-gate clockchange++; 2617c478bd9Sstevel@tonic-gate sm.sm_txclock = TXC_IS_TXC; 2627c478bd9Sstevel@tonic-gate sm.sm_rxclock = RXC_IS_RXC; 2637c478bd9Sstevel@tonic-gate if ((sm.sm_config & CONN_LPBK) != 0) 2647c478bd9Sstevel@tonic-gate loopchange++; 2657c478bd9Sstevel@tonic-gate sm.sm_config &= ~CONN_LPBK; 2667c478bd9Sstevel@tonic-gate break; 2677c478bd9Sstevel@tonic-gate case 4: 2687c478bd9Sstevel@tonic-gate goto no_params; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate sm.sm_baudrate = speed; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCSETMODE; 2747c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 2757c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 2767c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 2777c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 2787c478bd9Sstevel@tonic-gate perror("S_IOCSETMODE"); 2797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 280*c7e4935fSss150715 "syncloop: can't set sync mode info for %s\n", portname); 2817c478bd9Sstevel@tonic-gate exit(1); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate no_params: 2857c478bd9Sstevel@tonic-gate /* report state */ 2867c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETMODE; 2877c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 2887c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct scc_mode); 2897c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&sm; 2907c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 2917c478bd9Sstevel@tonic-gate perror("S_IOCGETMODE"); 292*c7e4935fSss150715 (void) fprintf(stderr, "syncloop: can't get sync mode info " 293*c7e4935fSss150715 "for %s\n", portname); 2947c478bd9Sstevel@tonic-gate exit(1); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate (void) printf("speed=%d, loopback=%s, nrzi=%s, txc=%s, rxc=%s\n", 2977c478bd9Sstevel@tonic-gate sm.sm_baudrate, 2987c478bd9Sstevel@tonic-gate yesno[((int)(sm.sm_config & CONN_LPBK) > 0)], 2997c478bd9Sstevel@tonic-gate yesno[((int)(sm.sm_config & CONN_NRZI) > 0)], 3007c478bd9Sstevel@tonic-gate txnames[sm.sm_txclock], 3017c478bd9Sstevel@tonic-gate rxnames[sm.sm_rxclock]); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate quiet_period(); 3047c478bd9Sstevel@tonic-gate first_packet(); 3057c478bd9Sstevel@tonic-gate many_packets(); 3067c478bd9Sstevel@tonic-gate return (0); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate static void 3107c478bd9Sstevel@tonic-gate Usage() 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate (void) printf("Usage: syncloop [ options ] portname\n"); 3137c478bd9Sstevel@tonic-gate (void) printf("Options: -c packet_count\n"); 3147c478bd9Sstevel@tonic-gate (void) printf(" -l packet_length\n"); 3157c478bd9Sstevel@tonic-gate (void) printf(" -s line_speed\n"); 3167c478bd9Sstevel@tonic-gate (void) printf(" -t test_type\n"); 3177c478bd9Sstevel@tonic-gate (void) printf(" -d hex_data_byte\n"); 3187c478bd9Sstevel@tonic-gate exit(1); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate static int zero_time = 0; 3227c478bd9Sstevel@tonic-gate static int short_time = 1000; 3237c478bd9Sstevel@tonic-gate static int long_time = 4000; 3247c478bd9Sstevel@tonic-gate static char bigbuf[4096]; 3257c478bd9Sstevel@tonic-gate static char packet[MAXPACKET]; 3267c478bd9Sstevel@tonic-gate static struct pollfd pfd; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate static void 3297c478bd9Sstevel@tonic-gate quiet_period() 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate (void) printf("[ checking for quiet line ]\n"); 3327c478bd9Sstevel@tonic-gate pfd.fd = dfd; 3337c478bd9Sstevel@tonic-gate pfd.events = POLLIN; 3347c478bd9Sstevel@tonic-gate pfd.revents = 0; 3357c478bd9Sstevel@tonic-gate while (poll(&pfd, 1, short_time) == 1) { 3367c478bd9Sstevel@tonic-gate (void) read(dfd, bigbuf, sizeof (bigbuf)); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate if (poll(&pfd, 1, long_time) == 1) { 3397c478bd9Sstevel@tonic-gate (void) printf("packet received but none sent!\n"); 3407c478bd9Sstevel@tonic-gate (void) printf("quiesce other end before starting syncloop\n"); 3417c478bd9Sstevel@tonic-gate exit(1); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate static void 3467c478bd9Sstevel@tonic-gate first_packet() 3477c478bd9Sstevel@tonic-gate { 3487c478bd9Sstevel@tonic-gate int i, len; 3497c478bd9Sstevel@tonic-gate int pollret; 3507c478bd9Sstevel@tonic-gate struct strioctl sioc; 3517c478bd9Sstevel@tonic-gate struct sl_stats start_stats, end_stats; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate for (i = 0; i < reclen; i++) 3547c478bd9Sstevel@tonic-gate packet[i] = (data == -1) ? rand() : data; 3557c478bd9Sstevel@tonic-gate (void) printf("[ Trying first packet ]\n"); 3567c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 3577c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 3587c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 3597c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&start_stats; 3607c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 3617c478bd9Sstevel@tonic-gate perror("S_IOCGETSTATS"); 3627c478bd9Sstevel@tonic-gate exit(1); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate for (i = 0; i < 5; i++) { 3667c478bd9Sstevel@tonic-gate if (write(dfd, packet, reclen) != reclen) { 3677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3687c478bd9Sstevel@tonic-gate "packet write failed, errno %d\n", 3697c478bd9Sstevel@tonic-gate errno); 3707c478bd9Sstevel@tonic-gate exit(1); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate pfd.fd = dfd; 3737c478bd9Sstevel@tonic-gate pfd.events = POLLIN; 3747c478bd9Sstevel@tonic-gate pollret = poll(&pfd, 1, long_time); 3757c478bd9Sstevel@tonic-gate if (pollret < 0) perror("poll"); 3767c478bd9Sstevel@tonic-gate if (pollret == 0) 3777c478bd9Sstevel@tonic-gate (void) printf("poll: nothing to read.\n"); 3787c478bd9Sstevel@tonic-gate if (pollret == 1) { 3797c478bd9Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 3807c478bd9Sstevel@tonic-gate if (len == reclen && memcmp(packet, bigbuf, len) == 0) 3817c478bd9Sstevel@tonic-gate return; /* success */ 3827c478bd9Sstevel@tonic-gate else { 3837c478bd9Sstevel@tonic-gate (void) printf("len %d should be %d\n", 3847c478bd9Sstevel@tonic-gate len, reclen); 3857c478bd9Sstevel@tonic-gate if (verbose) { 3867c478bd9Sstevel@tonic-gate (void) printf(" "); 3877c478bd9Sstevel@tonic-gate printhex(bigbuf, len); 3887c478bd9Sstevel@tonic-gate (void) printf("\nshould be "); 3897c478bd9Sstevel@tonic-gate printhex(packet, reclen); 3907c478bd9Sstevel@tonic-gate (void) printf("\n"); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate (void) printf("Loopback has TOTALLY FAILED - "); 3967c478bd9Sstevel@tonic-gate (void) printf("no packets returned after 5 attempts\n"); 3977c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 3987c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 3997c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 4007c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&end_stats; 4017c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 4027c478bd9Sstevel@tonic-gate perror("S_IOCGETSTATS"); 4037c478bd9Sstevel@tonic-gate exit(1); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate if (start_stats.opack == end_stats.opack) 4067c478bd9Sstevel@tonic-gate (void) printf( 4077c478bd9Sstevel@tonic-gate "No packets transmitted - no transmit clock present\n"); 4087c478bd9Sstevel@tonic-gate exit(1); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate static void 4127c478bd9Sstevel@tonic-gate many_packets() 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate struct strioctl sioc; 4157c478bd9Sstevel@tonic-gate struct sl_stats start_stats, end_stats; 4167c478bd9Sstevel@tonic-gate struct timeval start_time, end_time; 4177c478bd9Sstevel@tonic-gate int baddata = 0; 4187c478bd9Sstevel@tonic-gate float secs, speed; 4197c478bd9Sstevel@tonic-gate int i, len; 4207c478bd9Sstevel@tonic-gate int incount = 0; 4217c478bd9Sstevel@tonic-gate long prev_sec = -1; 4227c478bd9Sstevel@tonic-gate int pollret; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate (void) printf("[ Trying many packets ]\n"); 4257c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 4267c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 4277c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 4287c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&start_stats; 4297c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 4307c478bd9Sstevel@tonic-gate perror("S_IOCGETSTATS"); 4317c478bd9Sstevel@tonic-gate exit(1); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate (void) gettimeofday(&start_time, 0); 4347c478bd9Sstevel@tonic-gate end_time = start_time; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate i = 0; 4377c478bd9Sstevel@tonic-gate while (i < reccount) { 4387c478bd9Sstevel@tonic-gate if (end_time.tv_sec != prev_sec) { 4397c478bd9Sstevel@tonic-gate prev_sec = end_time.tv_sec; 4407c478bd9Sstevel@tonic-gate (void) printf("\r %d ", incount); 4417c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate pfd.fd = dfd; 4447c478bd9Sstevel@tonic-gate pfd.events = POLLIN; 4457c478bd9Sstevel@tonic-gate while (pollret = poll(&pfd, 1, zero_time)) { 4467c478bd9Sstevel@tonic-gate if (pollret < 0) 4477c478bd9Sstevel@tonic-gate perror("poll"); 4487c478bd9Sstevel@tonic-gate else { 4497c478bd9Sstevel@tonic-gate (void) lseek(dfd, (long)0, 0); 4507c478bd9Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 4517c478bd9Sstevel@tonic-gate if (len != reclen || 4527c478bd9Sstevel@tonic-gate memcmp(packet, bigbuf, len) != 0) { 4537c478bd9Sstevel@tonic-gate (void) printf("len %d should be %d\n", 4547c478bd9Sstevel@tonic-gate len, reclen); 4557c478bd9Sstevel@tonic-gate if (verbose) { 4567c478bd9Sstevel@tonic-gate (void) printf(" "); 4577c478bd9Sstevel@tonic-gate printhex(bigbuf, len); 4587c478bd9Sstevel@tonic-gate (void) printf("\nshould be "); 4597c478bd9Sstevel@tonic-gate printhex(packet, reclen); 4607c478bd9Sstevel@tonic-gate (void) printf("\n"); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate baddata++; 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate incount++; 4657c478bd9Sstevel@tonic-gate (void) gettimeofday(&end_time, 0); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate pfd.fd = dfd; 4697c478bd9Sstevel@tonic-gate pfd.events = POLLIN|POLLOUT; 4707c478bd9Sstevel@tonic-gate pollret = poll(&pfd, 1, long_time); 4717c478bd9Sstevel@tonic-gate if (pollret < 0) 4727c478bd9Sstevel@tonic-gate perror("poll"); 4737c478bd9Sstevel@tonic-gate if (pollret == 0) 4747c478bd9Sstevel@tonic-gate (void) printf("poll: nothing to read or write.\n"); 4757c478bd9Sstevel@tonic-gate if (pollret == 1) { 4767c478bd9Sstevel@tonic-gate if (pfd.revents & POLLOUT) { 4777c478bd9Sstevel@tonic-gate (void) write(dfd, packet, reclen); 4787c478bd9Sstevel@tonic-gate i++; 4797c478bd9Sstevel@tonic-gate } else if (!(pfd.revents & POLLIN)) { 4807c478bd9Sstevel@tonic-gate (void) printf("OUTPUT HAS LOCKED UP!!!\n"); 4817c478bd9Sstevel@tonic-gate break; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate pfd.fd = dfd; 4867c478bd9Sstevel@tonic-gate pfd.events = POLLIN; 4877c478bd9Sstevel@tonic-gate while ((incount < reccount) && (poll(&pfd, 1, long_time) == 1)) { 4887c478bd9Sstevel@tonic-gate if (end_time.tv_sec != prev_sec) { 4897c478bd9Sstevel@tonic-gate prev_sec = end_time.tv_sec; 4907c478bd9Sstevel@tonic-gate (void) printf("\r %d ", incount); 4917c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate len = read(dfd, bigbuf, reclen); 4947c478bd9Sstevel@tonic-gate if (len != reclen || memcmp(packet, bigbuf, len) != 0) { 4957c478bd9Sstevel@tonic-gate (void) printf("len %d should be %d\n", len, reclen); 4967c478bd9Sstevel@tonic-gate if (verbose) { 4977c478bd9Sstevel@tonic-gate (void) printf(" "); 4987c478bd9Sstevel@tonic-gate printhex(bigbuf, len); 4997c478bd9Sstevel@tonic-gate (void) printf("\nshould be "); 5007c478bd9Sstevel@tonic-gate printhex(packet, reclen); 5017c478bd9Sstevel@tonic-gate (void) printf("\n"); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate baddata++; 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate incount++; 5067c478bd9Sstevel@tonic-gate (void) gettimeofday(&end_time, 0); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate (void) printf("\r %d \n", incount); 5097c478bd9Sstevel@tonic-gate if (baddata) 5107c478bd9Sstevel@tonic-gate (void) printf("%d packets with wrong data received!\n", 5117c478bd9Sstevel@tonic-gate baddata); 5127c478bd9Sstevel@tonic-gate sioc.ic_cmd = S_IOCGETSTATS; 5137c478bd9Sstevel@tonic-gate sioc.ic_timout = -1; 5147c478bd9Sstevel@tonic-gate sioc.ic_len = sizeof (struct sl_stats); 5157c478bd9Sstevel@tonic-gate sioc.ic_dp = (char *)&end_stats; 5167c478bd9Sstevel@tonic-gate if (ioctl(cfd, I_STR, &sioc) < 0) { 5177c478bd9Sstevel@tonic-gate perror("S_IOCGETSTATS"); 5187c478bd9Sstevel@tonic-gate exit(1); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate end_stats.ipack -= start_stats.ipack; 5217c478bd9Sstevel@tonic-gate end_stats.opack -= start_stats.opack; 5227c478bd9Sstevel@tonic-gate end_stats.abort -= start_stats.abort; 5237c478bd9Sstevel@tonic-gate end_stats.crc -= start_stats.crc; 5247c478bd9Sstevel@tonic-gate end_stats.overrun -= start_stats.overrun; 5257c478bd9Sstevel@tonic-gate end_stats.underrun -= start_stats.underrun; 5267c478bd9Sstevel@tonic-gate end_stats.ierror -= start_stats.ierror; 5277c478bd9Sstevel@tonic-gate end_stats.oerror -= start_stats.oerror; 5287c478bd9Sstevel@tonic-gate if (reccount > end_stats.opack) 5297c478bd9Sstevel@tonic-gate (void) printf("%d packets lost in outbound queueing\n", 5307c478bd9Sstevel@tonic-gate reccount - end_stats.opack); 5317c478bd9Sstevel@tonic-gate if (incount < end_stats.ipack && incount < reccount) 5327c478bd9Sstevel@tonic-gate (void) printf("%d packets lost in inbound queueing\n", 5337c478bd9Sstevel@tonic-gate end_stats.ipack - incount); 5347c478bd9Sstevel@tonic-gate (void) printf("%d packets sent, %d received\n", reccount, incount); 5357c478bd9Sstevel@tonic-gate (void) printf("CRC errors Aborts Overruns Underruns "); 5367c478bd9Sstevel@tonic-gate (void) printf(" In <-Drops-> Out\n%9d %9d %9d %9d %12d %12d\n", 5377c478bd9Sstevel@tonic-gate end_stats.crc, end_stats.abort, 5387c478bd9Sstevel@tonic-gate end_stats.overrun, end_stats.underrun, 5397c478bd9Sstevel@tonic-gate end_stats.ierror, end_stats.oerror); 5407c478bd9Sstevel@tonic-gate secs = (float)(end_time.tv_usec - start_time.tv_usec) / 1000000.0; 5417c478bd9Sstevel@tonic-gate secs += (float)(end_time.tv_sec - start_time.tv_sec); 5427c478bd9Sstevel@tonic-gate if (secs) { 5437c478bd9Sstevel@tonic-gate speed = 8 * incount * (4 + reclen) / secs; 5447c478bd9Sstevel@tonic-gate (void) printf("estimated line speed = %d bps\n", (int)speed); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate static void 5497c478bd9Sstevel@tonic-gate printhex(char *cp, int len) 5507c478bd9Sstevel@tonic-gate { 5517c478bd9Sstevel@tonic-gate char c, *hex = "0123456789ABCDEF"; 5527c478bd9Sstevel@tonic-gate int i; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 5557c478bd9Sstevel@tonic-gate c = *cp++; 5567c478bd9Sstevel@tonic-gate (void) putchar(hex[(c >> 4) & 0xF]); 5577c478bd9Sstevel@tonic-gate (void) putchar(hex[c & 0xF]); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate } 560