Home | History | Annotate | Download | only in usr.sbin
      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  * Initialize and re-initialize synchronous serial clocking and loopback
     30  * options.  Interfaces through the S_IOCGETMODE and S_IOCSETMODE ioctls.
     31  */
     32 
     33 #include <sys/types.h>
     34 #include <ctype.h>
     35 #include <sys/ioctl.h>
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <unistd.h>
     39 #include <string.h>
     40 #include <sys/stream.h>
     41 #include <sys/stropts.h>
     42 #include <fcntl.h>
     43 #include <errno.h>
     44 #include <sys/ser_sync.h>
     45 #include <libdlpi.h>
     46 
     47 static void usage(void);
     48 static int prefix(char *arg, char *pref);
     49 static int lookup(char **table, char *arg);
     50 
     51 static char *yesno[] = {
     52 	"no",
     53 	"yes",
     54 	"silent",
     55 	0,
     56 };
     57 
     58 static char *txnames[] = {
     59 	"txc",
     60 	"rxc",
     61 	"baud",
     62 	"pll",
     63 	"sysclk",
     64 	"-txc",
     65 	0,
     66 };
     67 
     68 static char *rxnames[] = {
     69 	"rxc",
     70 	"txc",
     71 	"baud",
     72 	"pll",
     73 	"sysclk",
     74 	"-rxc",
     75 	0,
     76 };
     77 
     78 #ifdef notdef
     79 static char *txdnames[] = {
     80 	"txd",
     81 	" ",	/* dummy entry, do not remove */
     82 	"-txd",
     83 	0,
     84 };
     85 
     86 static char *rxdnames[] = {
     87 	"rxd",
     88 	"-rxd",
     89 	0,
     90 };
     91 
     92 static char *portab[] = {
     93 	"rs422",
     94 	"v35",
     95 	0,
     96 };
     97 #endif
     98 
     99 #define	equal(a, b)	(strcmp((a), (b)) == 0)
    100 
    101 int
    102 main(int argc, char **argv)
    103 {
    104 	char cnambuf[DLPI_LINKNAME_MAX], device[DLPI_LINKNAME_MAX];
    105 	struct scc_mode sm;
    106 	struct strioctl sioc;
    107 	int fd, speed;
    108 	int retval;
    109 	char *arg, *cp;
    110 	char loopchange = 0;
    111 	char echochange = 0;
    112 	char clockchange = 0;
    113 	uint_t ppa;
    114 	dlpi_handle_t dh;
    115 
    116 	if (argc == 1) {
    117 		usage();
    118 		exit(1);
    119 	}
    120 	argc--;
    121 	argv++;
    122 
    123 	if (strlcpy(cnambuf, argv[0], sizeof (cnambuf)) >=
    124 	    sizeof (cnambuf)) {
    125 		(void) fprintf(stderr,
    126 		    "syncinit: invalid device name (too long) %s\n", argv[0]);
    127 		exit(1);
    128 	}
    129 
    130 	cp = cnambuf;
    131 	while (*cp)			/* find the end of the name */
    132 		cp++;
    133 	cp--;
    134 	if (!isdigit(*cp)) {
    135 		(void) fprintf(stderr,
    136 		    "syncinit: %s missing minor device number\n", cnambuf);
    137 		exit(1);
    138 	}
    139 
    140 	retval = dlpi_open(cnambuf, &dh, DLPI_EXCL|DLPI_SERIAL);
    141 	if (retval != DLPI_SUCCESS) {
    142 		(void) fprintf(stderr, "syncinit: dlpi_open %s: %s\n", cnambuf,
    143 		    dlpi_strerror(retval));
    144 		exit(1);
    145 	}
    146 
    147 	(void) dlpi_parselink(cnambuf, device, &ppa);
    148 	(void) printf("device: %s  ppa: %u\n", device, ppa);
    149 
    150 	fd = dlpi_fd(dh);
    151 
    152 	argc--;
    153 	argv++;
    154 	if (argc) {	/* setting things */
    155 		sioc.ic_cmd = S_IOCGETMODE;
    156 		sioc.ic_timout = -1;
    157 		sioc.ic_len = sizeof (struct scc_mode);
    158 		sioc.ic_dp = (char *)&sm;
    159 
    160 		if (ioctl(fd, I_STR, &sioc) < 0) {
    161 			perror("S_IOCGETMODE");
    162 			(void) fprintf(stderr,
    163 				"syncinit: can't get sync mode info for %s\n",
    164 				cnambuf);
    165 			exit(1);
    166 		}
    167 		while (argc-- > 0) {
    168 			arg = *argv++;
    169 			if (sscanf(arg, "%d", &speed) == 1)
    170 				sm.sm_baudrate = speed;
    171 			else if (strchr(arg, '=')) {
    172 				if (prefix(arg, "loop")) {
    173 					if (lookup(yesno, arg))
    174 						sm.sm_config |= CONN_LPBK;
    175 					else
    176 						sm.sm_config &= ~CONN_LPBK;
    177 					loopchange++;
    178 				} else if (prefix(arg, "echo")) {
    179 					if (lookup(yesno, arg))
    180 						sm.sm_config |= CONN_ECHO;
    181 					else
    182 						sm.sm_config &= ~CONN_ECHO;
    183 					echochange++;
    184 				} else if (prefix(arg, "nrzi")) {
    185 					if (lookup(yesno, arg))
    186 						sm.sm_config |= CONN_NRZI;
    187 					else
    188 						sm.sm_config &= ~CONN_NRZI;
    189 				} else if (prefix(arg, "txc")) {
    190 					sm.sm_txclock = lookup(txnames, arg);
    191 					clockchange++;
    192 				} else if (prefix(arg, "rxc")) {
    193 					sm.sm_rxclock = lookup(rxnames, arg);
    194 					clockchange++;
    195 				} else if (prefix(arg, "speed")) {
    196 					arg = strchr(arg, '=') + 1;
    197 					if (sscanf(arg, "%d", &speed) == 1) {
    198 						sm.sm_baudrate = speed;
    199 					} else
    200 						(void) fprintf(stderr,
    201 						    "syncinit: %s %s\n",
    202 						    "bad speed:", arg);
    203 				}
    204 			} else if (equal(arg, "external")) {
    205 				sm.sm_txclock = TXC_IS_TXC;
    206 				sm.sm_rxclock = RXC_IS_RXC;
    207 				sm.sm_config &= ~CONN_LPBK;
    208 			} else if (equal(arg, "sender")) {
    209 				sm.sm_txclock = TXC_IS_BAUD;
    210 				sm.sm_rxclock = RXC_IS_RXC;
    211 				sm.sm_config &= ~CONN_LPBK;
    212 			} else if (equal(arg, "internal")) {
    213 				sm.sm_txclock = TXC_IS_PLL;
    214 				sm.sm_rxclock = RXC_IS_PLL;
    215 				sm.sm_config &= ~CONN_LPBK;
    216 			} else if (equal(arg, "stop")) {
    217 				sm.sm_baudrate = 0;
    218 			} else
    219 				(void) fprintf(stderr, "Bad arg: %s\n", arg);
    220 		}
    221 
    222 		/*
    223 		 * If we're going to change the state of loopback, and we
    224 		 * don't have our own plans for clock sources, use defaults.
    225 		 */
    226 		if (loopchange && !clockchange) {
    227 			if (sm.sm_config & CONN_LPBK) {
    228 				sm.sm_txclock = TXC_IS_BAUD;
    229 				sm.sm_rxclock = RXC_IS_BAUD;
    230 			} else {
    231 				sm.sm_txclock = TXC_IS_TXC;
    232 				sm.sm_rxclock = RXC_IS_RXC;
    233 			}
    234 		}
    235 		sioc.ic_cmd = S_IOCSETMODE;
    236 		sioc.ic_timout = -1;
    237 		sioc.ic_len = sizeof (struct scc_mode);
    238 		sioc.ic_dp = (char *)&sm;
    239 		if (ioctl(fd, I_STR, &sioc) < 0) {
    240 			perror("S_IOCSETMODE");
    241 			(void) ioctl(fd, S_IOCGETMODE, &sm);
    242 			(void) fprintf(stderr,
    243 				"syncinit: ioctl failure code = %x\n",
    244 				sm.sm_retval);
    245 			exit(1);
    246 		}
    247 	}
    248 
    249 	/* Report State */
    250 	sioc.ic_cmd = S_IOCGETMODE;
    251 	sioc.ic_timout = -1;
    252 	sioc.ic_len = sizeof (struct scc_mode);
    253 	sioc.ic_dp = (char *)&sm;
    254 	if (ioctl(fd, I_STR, &sioc) < 0) {
    255 		perror("S_IOCGETMODE");
    256 		(void) fprintf(stderr,
    257 			"syncinit: can't get sync mode info for %s\n",
    258 			cnambuf);
    259 		exit(1);
    260 	}
    261 	(void) printf(
    262 		"speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n",
    263 		sm.sm_baudrate,
    264 		yesno[((int)(sm.sm_config & CONN_LPBK) > 0)],
    265 		yesno[((int)(sm.sm_config & CONN_ECHO) > 0)],
    266 		yesno[((int)(sm.sm_config & CONN_NRZI) > 0)],
    267 		txnames[sm.sm_txclock],
    268 		rxnames[sm.sm_rxclock]);
    269 	return (0);
    270 }
    271 
    272 static void
    273 usage()
    274 {
    275 	(void) fprintf(stderr, "Usage: syncinit cnambuf \\\n");
    276 	(void) fprintf(stderr, "\t[baudrate] [loopback=[yes|no]] ");
    277 	(void) fprintf(stderr, "[echo=[yes|no]] [nrzi=[yes|no]] \\\n");
    278 	(void) fprintf(stderr, "\t[txc=[txc|rxc|baud|pll]] \\\n");
    279 	(void) fprintf(stderr, "\t[rxc=[rxc|txc|baud|pll]]\n");
    280 	exit(1);
    281 }
    282 
    283 static int
    284 prefix(char *arg, char *pref)
    285 {
    286 	return (strncmp(arg, pref, strlen(pref)) == 0);
    287 }
    288 
    289 static int
    290 lookup(char **table, char *arg)
    291 {
    292 	char *val = strchr(arg, '=') + 1;
    293 	int ival;
    294 
    295 	for (ival = 0; *table != 0; ival++, table++)
    296 		if (equal(*table, val))
    297 			return (ival);
    298 	(void) fprintf(stderr, "syncinit: bad arg: %s\n", arg);
    299 	exit(1);
    300 	/* NOTREACHED */
    301 }
    302