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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Initialize and re-initialize synchronous serial clocking and loopback
30 * options. Interfaces through the S_IOCGETMODE and S_IOCSETMODE ioctls.
33 #include <sys/types.h>
35 #include <sys/ioctl.h>
40 #include <sys/stream.h>
41 #include <sys/stropts.h>
44 #include <sys/ser_sync.h>
47 static void usage(void);
48 static int prefix(char *arg
, char *pref
);
49 static int lookup(char **table
, char *arg
);
51 static char *yesno
[] = {
58 static char *txnames
[] = {
68 static char *rxnames
[] = {
79 static char *txdnames
[] = {
81 " ", /* dummy entry, do not remove */
86 static char *rxdnames
[] = {
92 static char *portab
[] = {
99 #define equal(a, b) (strcmp((a), (b)) == 0)
102 main(int argc
, char **argv
)
104 char cnambuf
[DLPI_LINKNAME_MAX
], device
[DLPI_LINKNAME_MAX
];
106 struct strioctl sioc
;
112 char clockchange
= 0;
123 if (strlcpy(cnambuf
, argv
[0], sizeof (cnambuf
)) >=
125 (void) fprintf(stderr
,
126 "syncinit: invalid device name (too long) %s\n", argv
[0]);
131 while (*cp
) /* find the end of the name */
135 (void) fprintf(stderr
,
136 "syncinit: %s missing minor device number\n", cnambuf
);
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
));
147 (void) dlpi_parselink(cnambuf
, device
, &ppa
);
148 (void) printf("device: %s ppa: %u\n", device
, ppa
);
154 if (argc
) { /* setting things */
155 sioc
.ic_cmd
= S_IOCGETMODE
;
157 sioc
.ic_len
= sizeof (struct scc_mode
);
158 sioc
.ic_dp
= (char *)&sm
;
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",
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
;
176 sm
.sm_config
&= ~CONN_LPBK
;
178 } else if (prefix(arg
, "echo")) {
179 if (lookup(yesno
, arg
))
180 sm
.sm_config
|= CONN_ECHO
;
182 sm
.sm_config
&= ~CONN_ECHO
;
184 } else if (prefix(arg
, "nrzi")) {
185 if (lookup(yesno
, arg
))
186 sm
.sm_config
|= CONN_NRZI
;
188 sm
.sm_config
&= ~CONN_NRZI
;
189 } else if (prefix(arg
, "txc")) {
190 sm
.sm_txclock
= lookup(txnames
, arg
);
192 } else if (prefix(arg
, "rxc")) {
193 sm
.sm_rxclock
= lookup(rxnames
, arg
);
195 } else if (prefix(arg
, "speed")) {
196 arg
= strchr(arg
, '=') + 1;
197 if (sscanf(arg
, "%d", &speed
) == 1) {
198 sm
.sm_baudrate
= speed
;
200 (void) fprintf(stderr
,
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")) {
219 (void) fprintf(stderr
, "Bad arg: %s\n", arg
);
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.
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
;
231 sm
.sm_txclock
= TXC_IS_TXC
;
232 sm
.sm_rxclock
= RXC_IS_RXC
;
235 sioc
.ic_cmd
= S_IOCSETMODE
;
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",
250 sioc
.ic_cmd
= S_IOCGETMODE
;
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",
262 "speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n",
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
]);
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");
284 prefix(char *arg
, char *pref
)
286 return (strncmp(arg
, pref
, strlen(pref
)) == 0);
290 lookup(char **table
, char *arg
)
292 char *val
= strchr(arg
, '=') + 1;
295 for (ival
= 0; *table
!= 0; ival
++, table
++)
296 if (equal(*table
, val
))
298 (void) fprintf(stderr
, "syncinit: bad arg: %s\n", arg
);