xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/syncinit.c (revision 3628:98d9a6c27bd3)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3628Sss150715  * Common Development and Distribution License (the "License").
6*3628Sss150715  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3628Sss150715  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Initialize and re-initialize synchronous serial clocking and loopback
300Sstevel@tonic-gate  * options.  Interfaces through the S_IOCGETMODE and S_IOCSETMODE ioctls.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <sys/types.h>
340Sstevel@tonic-gate #include <ctype.h>
350Sstevel@tonic-gate #include <sys/ioctl.h>
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <unistd.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <sys/stream.h>
410Sstevel@tonic-gate #include <sys/stropts.h>
420Sstevel@tonic-gate #include <fcntl.h>
430Sstevel@tonic-gate #include <errno.h>
440Sstevel@tonic-gate #include <sys/ser_sync.h>
450Sstevel@tonic-gate #include <libdlpi.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static void usage(void);
480Sstevel@tonic-gate static int prefix(char *arg, char *pref);
490Sstevel@tonic-gate static int lookup(char **table, char *arg);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate static char *yesno[] = {
520Sstevel@tonic-gate 	"no",
530Sstevel@tonic-gate 	"yes",
540Sstevel@tonic-gate 	"silent",
550Sstevel@tonic-gate 	0,
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate static char *txnames[] = {
590Sstevel@tonic-gate 	"txc",
600Sstevel@tonic-gate 	"rxc",
610Sstevel@tonic-gate 	"baud",
620Sstevel@tonic-gate 	"pll",
630Sstevel@tonic-gate 	"sysclk",
640Sstevel@tonic-gate 	"-txc",
650Sstevel@tonic-gate 	0,
660Sstevel@tonic-gate };
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static char *rxnames[] = {
690Sstevel@tonic-gate 	"rxc",
700Sstevel@tonic-gate 	"txc",
710Sstevel@tonic-gate 	"baud",
720Sstevel@tonic-gate 	"pll",
730Sstevel@tonic-gate 	"sysclk",
740Sstevel@tonic-gate 	"-rxc",
750Sstevel@tonic-gate 	0,
760Sstevel@tonic-gate };
770Sstevel@tonic-gate 
780Sstevel@tonic-gate #ifdef notdef
790Sstevel@tonic-gate static char *txdnames[] = {
800Sstevel@tonic-gate 	"txd",
810Sstevel@tonic-gate 	" ",	/* dummy entry, do not remove */
820Sstevel@tonic-gate 	"-txd",
830Sstevel@tonic-gate 	0,
840Sstevel@tonic-gate };
850Sstevel@tonic-gate 
860Sstevel@tonic-gate static char *rxdnames[] = {
870Sstevel@tonic-gate 	"rxd",
880Sstevel@tonic-gate 	"-rxd",
890Sstevel@tonic-gate 	0,
900Sstevel@tonic-gate };
910Sstevel@tonic-gate 
920Sstevel@tonic-gate static char *portab[] = {
930Sstevel@tonic-gate 	"rs422",
940Sstevel@tonic-gate 	"v35",
950Sstevel@tonic-gate 	0,
960Sstevel@tonic-gate };
970Sstevel@tonic-gate #endif
980Sstevel@tonic-gate 
990Sstevel@tonic-gate #define	equal(a, b)	(strcmp((a), (b)) == 0)
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate int
main(int argc,char ** argv)1020Sstevel@tonic-gate main(int argc, char **argv)
1030Sstevel@tonic-gate {
104*3628Sss150715 	char cnambuf[DLPI_LINKNAME_MAX], device[DLPI_LINKNAME_MAX];
1050Sstevel@tonic-gate 	struct scc_mode sm;
1060Sstevel@tonic-gate 	struct strioctl sioc;
1070Sstevel@tonic-gate 	int fd, speed;
108*3628Sss150715 	int retval;
1090Sstevel@tonic-gate 	char *arg, *cp;
1100Sstevel@tonic-gate 	char loopchange = 0;
1110Sstevel@tonic-gate 	char echochange = 0;
1120Sstevel@tonic-gate 	char clockchange = 0;
113*3628Sss150715 	uint_t ppa;
114*3628Sss150715 	dlpi_handle_t dh;
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	if (argc == 1) {
1170Sstevel@tonic-gate 		usage();
1180Sstevel@tonic-gate 		exit(1);
1190Sstevel@tonic-gate 	}
1200Sstevel@tonic-gate 	argc--;
1210Sstevel@tonic-gate 	argv++;
122*3628Sss150715 
123*3628Sss150715 	if (strlcpy(cnambuf, argv[0], sizeof (cnambuf)) >=
124*3628Sss150715 	    sizeof (cnambuf)) {
125*3628Sss150715 		(void) fprintf(stderr,
126*3628Sss150715 		    "syncinit: invalid device name (too long) %s\n", argv[0]);
127*3628Sss150715 		exit(1);
1280Sstevel@tonic-gate 	}
129*3628Sss150715 
1300Sstevel@tonic-gate 	cp = cnambuf;
1310Sstevel@tonic-gate 	while (*cp)			/* find the end of the name */
1320Sstevel@tonic-gate 		cp++;
1330Sstevel@tonic-gate 	cp--;
1340Sstevel@tonic-gate 	if (!isdigit(*cp)) {
1350Sstevel@tonic-gate 		(void) fprintf(stderr,
136*3628Sss150715 		    "syncinit: %s missing minor device number\n", cnambuf);
1370Sstevel@tonic-gate 		exit(1);
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
140*3628Sss150715 	retval = dlpi_open(cnambuf, &dh, DLPI_EXCL|DLPI_SERIAL);
141*3628Sss150715 	if (retval != DLPI_SUCCESS) {
142*3628Sss150715 		(void) fprintf(stderr, "syncinit: dlpi_open %s: %s\n", cnambuf,
143*3628Sss150715 		    dlpi_strerror(retval));
1440Sstevel@tonic-gate 		exit(1);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 
147*3628Sss150715 	(void) dlpi_parselink(cnambuf, device, &ppa);
148*3628Sss150715 	(void) printf("device: %s  ppa: %u\n", device, ppa);
149*3628Sss150715 
150*3628Sss150715 	fd = dlpi_fd(dh);
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	argc--;
1530Sstevel@tonic-gate 	argv++;
1540Sstevel@tonic-gate 	if (argc) {	/* setting things */
1550Sstevel@tonic-gate 		sioc.ic_cmd = S_IOCGETMODE;
1560Sstevel@tonic-gate 		sioc.ic_timout = -1;
1570Sstevel@tonic-gate 		sioc.ic_len = sizeof (struct scc_mode);
1580Sstevel@tonic-gate 		sioc.ic_dp = (char *)&sm;
159*3628Sss150715 
1600Sstevel@tonic-gate 		if (ioctl(fd, I_STR, &sioc) < 0) {
1610Sstevel@tonic-gate 			perror("S_IOCGETMODE");
1620Sstevel@tonic-gate 			(void) fprintf(stderr,
1630Sstevel@tonic-gate 				"syncinit: can't get sync mode info for %s\n",
1640Sstevel@tonic-gate 				cnambuf);
1650Sstevel@tonic-gate 			exit(1);
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 		while (argc-- > 0) {
1680Sstevel@tonic-gate 			arg = *argv++;
1690Sstevel@tonic-gate 			if (sscanf(arg, "%d", &speed) == 1)
1700Sstevel@tonic-gate 				sm.sm_baudrate = speed;
1710Sstevel@tonic-gate 			else if (strchr(arg, '=')) {
1720Sstevel@tonic-gate 				if (prefix(arg, "loop")) {
1730Sstevel@tonic-gate 					if (lookup(yesno, arg))
1740Sstevel@tonic-gate 						sm.sm_config |= CONN_LPBK;
1750Sstevel@tonic-gate 					else
1760Sstevel@tonic-gate 						sm.sm_config &= ~CONN_LPBK;
1770Sstevel@tonic-gate 					loopchange++;
1780Sstevel@tonic-gate 				} else if (prefix(arg, "echo")) {
1790Sstevel@tonic-gate 					if (lookup(yesno, arg))
1800Sstevel@tonic-gate 						sm.sm_config |= CONN_ECHO;
1810Sstevel@tonic-gate 					else
1820Sstevel@tonic-gate 						sm.sm_config &= ~CONN_ECHO;
1830Sstevel@tonic-gate 					echochange++;
1840Sstevel@tonic-gate 				} else if (prefix(arg, "nrzi")) {
1850Sstevel@tonic-gate 					if (lookup(yesno, arg))
1860Sstevel@tonic-gate 						sm.sm_config |= CONN_NRZI;
1870Sstevel@tonic-gate 					else
1880Sstevel@tonic-gate 						sm.sm_config &= ~CONN_NRZI;
1890Sstevel@tonic-gate 				} else if (prefix(arg, "txc")) {
1900Sstevel@tonic-gate 					sm.sm_txclock = lookup(txnames, arg);
1910Sstevel@tonic-gate 					clockchange++;
1920Sstevel@tonic-gate 				} else if (prefix(arg, "rxc")) {
1930Sstevel@tonic-gate 					sm.sm_rxclock = lookup(rxnames, arg);
1940Sstevel@tonic-gate 					clockchange++;
1950Sstevel@tonic-gate 				} else if (prefix(arg, "speed")) {
1960Sstevel@tonic-gate 					arg = strchr(arg, '=') + 1;
1970Sstevel@tonic-gate 					if (sscanf(arg, "%d", &speed) == 1) {
1980Sstevel@tonic-gate 						sm.sm_baudrate = speed;
1990Sstevel@tonic-gate 					} else
2000Sstevel@tonic-gate 						(void) fprintf(stderr,
2010Sstevel@tonic-gate 						    "syncinit: %s %s\n",
2020Sstevel@tonic-gate 						    "bad speed:", arg);
2030Sstevel@tonic-gate 				}
2040Sstevel@tonic-gate 			} else if (equal(arg, "external")) {
2050Sstevel@tonic-gate 				sm.sm_txclock = TXC_IS_TXC;
2060Sstevel@tonic-gate 				sm.sm_rxclock = RXC_IS_RXC;
2070Sstevel@tonic-gate 				sm.sm_config &= ~CONN_LPBK;
2080Sstevel@tonic-gate 			} else if (equal(arg, "sender")) {
2090Sstevel@tonic-gate 				sm.sm_txclock = TXC_IS_BAUD;
2100Sstevel@tonic-gate 				sm.sm_rxclock = RXC_IS_RXC;
2110Sstevel@tonic-gate 				sm.sm_config &= ~CONN_LPBK;
2120Sstevel@tonic-gate 			} else if (equal(arg, "internal")) {
2130Sstevel@tonic-gate 				sm.sm_txclock = TXC_IS_PLL;
2140Sstevel@tonic-gate 				sm.sm_rxclock = RXC_IS_PLL;
2150Sstevel@tonic-gate 				sm.sm_config &= ~CONN_LPBK;
2160Sstevel@tonic-gate 			} else if (equal(arg, "stop")) {
2170Sstevel@tonic-gate 				sm.sm_baudrate = 0;
2180Sstevel@tonic-gate 			} else
2190Sstevel@tonic-gate 				(void) fprintf(stderr, "Bad arg: %s\n", arg);
2200Sstevel@tonic-gate 		}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 		/*
2230Sstevel@tonic-gate 		 * If we're going to change the state of loopback, and we
2240Sstevel@tonic-gate 		 * don't have our own plans for clock sources, use defaults.
2250Sstevel@tonic-gate 		 */
2260Sstevel@tonic-gate 		if (loopchange && !clockchange) {
2270Sstevel@tonic-gate 			if (sm.sm_config & CONN_LPBK) {
2280Sstevel@tonic-gate 				sm.sm_txclock = TXC_IS_BAUD;
2290Sstevel@tonic-gate 				sm.sm_rxclock = RXC_IS_BAUD;
2300Sstevel@tonic-gate 			} else {
2310Sstevel@tonic-gate 				sm.sm_txclock = TXC_IS_TXC;
2320Sstevel@tonic-gate 				sm.sm_rxclock = RXC_IS_RXC;
2330Sstevel@tonic-gate 			}
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 		sioc.ic_cmd = S_IOCSETMODE;
2360Sstevel@tonic-gate 		sioc.ic_timout = -1;
2370Sstevel@tonic-gate 		sioc.ic_len = sizeof (struct scc_mode);
2380Sstevel@tonic-gate 		sioc.ic_dp = (char *)&sm;
2390Sstevel@tonic-gate 		if (ioctl(fd, I_STR, &sioc) < 0) {
2400Sstevel@tonic-gate 			perror("S_IOCSETMODE");
2410Sstevel@tonic-gate 			(void) ioctl(fd, S_IOCGETMODE, &sm);
2420Sstevel@tonic-gate 			(void) fprintf(stderr,
2430Sstevel@tonic-gate 				"syncinit: ioctl failure code = %x\n",
2440Sstevel@tonic-gate 				sm.sm_retval);
2450Sstevel@tonic-gate 			exit(1);
2460Sstevel@tonic-gate 		}
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/* Report State */
2500Sstevel@tonic-gate 	sioc.ic_cmd = S_IOCGETMODE;
2510Sstevel@tonic-gate 	sioc.ic_timout = -1;
2520Sstevel@tonic-gate 	sioc.ic_len = sizeof (struct scc_mode);
2530Sstevel@tonic-gate 	sioc.ic_dp = (char *)&sm;
2540Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &sioc) < 0) {
2550Sstevel@tonic-gate 		perror("S_IOCGETMODE");
2560Sstevel@tonic-gate 		(void) fprintf(stderr,
2570Sstevel@tonic-gate 			"syncinit: can't get sync mode info for %s\n",
2580Sstevel@tonic-gate 			cnambuf);
2590Sstevel@tonic-gate 		exit(1);
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	(void) printf(
262*3628Sss150715 		"speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n",
2630Sstevel@tonic-gate 		sm.sm_baudrate,
2640Sstevel@tonic-gate 		yesno[((int)(sm.sm_config & CONN_LPBK) > 0)],
2650Sstevel@tonic-gate 		yesno[((int)(sm.sm_config & CONN_ECHO) > 0)],
2660Sstevel@tonic-gate 		yesno[((int)(sm.sm_config & CONN_NRZI) > 0)],
2670Sstevel@tonic-gate 		txnames[sm.sm_txclock],
2680Sstevel@tonic-gate 		rxnames[sm.sm_rxclock]);
2690Sstevel@tonic-gate 	return (0);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate static void
usage()2730Sstevel@tonic-gate usage()
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: syncinit cnambuf \\\n");
2760Sstevel@tonic-gate 	(void) fprintf(stderr, "\t[baudrate] [loopback=[yes|no]] ");
2770Sstevel@tonic-gate 	(void) fprintf(stderr, "[echo=[yes|no]] [nrzi=[yes|no]] \\\n");
2780Sstevel@tonic-gate 	(void) fprintf(stderr, "\t[txc=[txc|rxc|baud|pll]] \\\n");
2790Sstevel@tonic-gate 	(void) fprintf(stderr, "\t[rxc=[rxc|txc|baud|pll]]\n");
2800Sstevel@tonic-gate 	exit(1);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate static int
prefix(char * arg,char * pref)2840Sstevel@tonic-gate prefix(char *arg, char *pref)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	return (strncmp(arg, pref, strlen(pref)) == 0);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate static int
lookup(char ** table,char * arg)2900Sstevel@tonic-gate lookup(char **table, char *arg)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate 	char *val = strchr(arg, '=') + 1;
2930Sstevel@tonic-gate 	int ival;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	for (ival = 0; *table != 0; ival++, table++)
2960Sstevel@tonic-gate 		if (equal(*table, val))
2970Sstevel@tonic-gate 			return (ival);
2980Sstevel@tonic-gate 	(void) fprintf(stderr, "syncinit: bad arg: %s\n", arg);
2990Sstevel@tonic-gate 	exit(1);
3000Sstevel@tonic-gate 	/* NOTREACHED */
3010Sstevel@tonic-gate }
302