struct tty's t_dev is a pointer now. Fix warning.
[dragonfly/vkernel-mp.git] / usr.sbin / sicontrol / sicontrol.c
bloba2505462ac0a75cf5c8b802aaad11ec61aefdc32
1 /*
2 * Device driver for Specialix range (SLXOS) of serial line multiplexors.
3 * SLXOS configuration and debug interface
5 * Copyright (C) 1990, 1992 Specialix International,
6 * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
7 * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com>
9 * Derived from: SunOS 4.x version
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notices, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notices, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Andy Rutter of
22 * Advanced Methods and Tools Ltd. based on original information
23 * from Specialix International.
24 * 4. Neither the name of Advanced Methods and Tools, nor Specialix
25 * International may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
31 * NO EVENT SHALL THE AUTHORS BE LIABLE.
33 * $FreeBSD: src/usr.sbin/sicontrol/sicontrol.c,v 1.12.2.1 2000/12/11 01:03:39 obrien Exp $
34 * $DragonFly: src/usr.sbin/sicontrol/sicontrol.c,v 1.5 2006/12/30 18:58:10 swildner Exp $
37 #define _KERNEL_STRUCTURES
38 #include <ctype.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <paths.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/stat.h>
48 #include <sys/ioctl.h>
49 #include <sys/tty.h>
51 #include <dev/serial/si/si.h>
53 struct lv {
54 char *lv_name;
55 int lv_bit;
56 } lv[] = {
57 {"entry", DBG_ENTRY},
58 {"open", DBG_OPEN},
59 {"close", DBG_CLOSE},
60 {"read", DBG_READ},
61 {"write", DBG_WRITE},
62 {"param", DBG_PARAM},
63 {"modem", DBG_MODEM},
64 {"select", DBG_SELECT},
65 {"optim", DBG_OPTIM},
66 {"intr", DBG_INTR},
67 {"start", DBG_START},
68 {"lstart", DBG_LSTART},
69 {"ioctl", DBG_IOCTL},
70 {"fail", DBG_FAIL},
71 {"autoboot", DBG_AUTOBOOT},
72 {"download", DBG_DOWNLOAD},
73 {"drain", DBG_DRAIN},
74 {"poll", DBG_POLL},
75 {0, 0}
78 static int alldev = 0;
80 void ccb_stat(int, char **);
81 void debug(int, char **);
82 void dostat(void);
83 int getnum(char *);
84 int islevel(char *);
85 int lvls2bits(char *);
86 void mstate(int, char **);
87 void nport(int, char **);
88 void onoff(int, char **, int, char *, char *, int);
89 int opencontrol(void);
90 void prlevels(int);
91 void prusage(int, int);
92 void rxint(int, char **);
93 void tty_stat(int, char **);
94 void txint(int, char **);
96 struct opt {
97 char *o_name;
98 void (*o_func)(int, char **);
99 } opt[] = {
100 {"debug", debug},
101 {"rxint_throttle", rxint},
102 {"int_throttle", txint},
103 {"nport", nport},
104 {"mstate", mstate},
105 {"ccbstat", ccb_stat},
106 {"ttystat", tty_stat},
107 {0, 0}
110 struct stat_list {
111 void (*st_func)(int, char **);
112 } stat_list[] = {
113 {mstate},
117 #define U_DEBUG 0
118 #define U_TXINT 1
119 #define U_RXINT 2
120 #define U_NPORT 3
121 #define U_MSTATE 4
122 #define U_STAT_CCB 5
123 #define U_STAT_TTY 6
125 #define U_MAX 7
126 #define U_ALL -1
127 char *usage[] = {
128 "debug [[add|del|set debug_levels] | [off]]\n",
129 "int_throttle [newvalue]\n",
130 "rxint_throttle [newvalue]\n",
131 "nport\n",
132 "mstate\n",
133 "ccbstat\n",
134 "ttystat\n",
138 int ctlfd;
139 char *Devname;
140 struct si_tcsi tc;
143 main(int argc, char **argv)
145 struct opt *op;
146 void (*func)(int, char **) = NULL;
148 if (argc < 2)
149 prusage(U_ALL, 1);
150 Devname = argv[1];
151 if (strcmp(Devname, "-") == 0) {
152 alldev = 1;
153 } else {
154 sidev_t dev;
155 struct stat st;
157 if (strchr(Devname, '/') == NULL) {
158 char *acp = malloc(6 + strlen(Devname));
159 strcpy(acp, _PATH_DEV);
160 strcat(acp, Devname);
161 Devname = acp;
163 if (stat(Devname, &st) < 0)
164 errx(1, "can't stat %s", Devname);
165 dev.sid_card = SI_CARD(minor(st.st_rdev));
166 dev.sid_port = SI_PORT(minor(st.st_rdev));
167 tc.tc_dev = dev;
169 ctlfd = opencontrol();
170 if (argc == 2) {
171 dostat();
172 exit(0);
175 argc--; argv++;
176 for (op = opt; op->o_name; op++) {
177 if (strcmp(argv[1], op->o_name) == 0) {
178 func = op->o_func;
179 break;
182 if (func == NULL)
183 prusage(U_ALL, 1);
185 argc -= 2;
186 argv += 2;
187 (*func)(argc, argv);
188 exit(0);
192 opencontrol(void)
194 int fd;
196 fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
197 if (fd < 0)
198 err(1, "open on %s", CONTROLDEV);
199 return(fd);
203 * Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
204 * Don't print the DEBUG usage string unless explicity requested.
206 void
207 prusage(int strn, int eflag)
209 char **cp;
211 if (strn == U_ALL) {
212 fprintf(stderr, "usage: sicontrol %s", usage[1]);
213 fprintf(stderr, " sicontrol %s", usage[2]);
214 fprintf(stderr, " sicontrol %s", usage[3]);
215 fprintf(stderr, " sicontrol devname %s", usage[4]);
216 for (cp = &usage[5]; *cp; cp++)
217 fprintf(stderr, " sicontrol devname %s", *cp);
219 else if (strn >= 0 && strn <= U_MAX)
220 fprintf(stderr, "usage: sicontrol devname %s", usage[strn]);
221 else
222 fprintf(stderr, "sicontrol: usage ???\n");
223 exit(eflag);
226 /* print port status */
227 void
228 dostat(void)
230 char *av[1], *acp;
231 struct stat_list *stp;
232 struct si_tcsi stc;
233 int donefirst = 0;
235 printf("%s: ", alldev ? "ALL" : Devname);
236 acp = malloc(strlen(Devname) + 3);
237 memset(acp, ' ', strlen(Devname));
238 strcat(acp, " ");
239 stc = tc;
240 for (stp = stat_list; stp->st_func != NULL; stp++) {
241 if (donefirst)
242 fputs(acp, stdout);
243 else
244 donefirst++;
245 av[0] = NULL;
246 tc = stc;
247 (*stp->st_func)(-1, av);
252 * debug
253 * debug [[set|add|del debug_lvls] | [off]]
255 void
256 debug(int ac, char **av)
258 int level;
260 if (ac > 2)
261 prusage(U_DEBUG, 1);
262 if (alldev) {
263 if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
264 err(1, "TCSIGDBG_ALL on %s", Devname);
265 } else {
266 if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
267 err(1, "TCSIGDBG_LEVEL on %s", Devname);
270 switch (ac) {
271 case 0:
272 printf("%s: debug levels - ", Devname);
273 prlevels(tc.tc_dbglvl);
274 return;
275 case 1:
276 if (strcmp(av[0], "off") == 0) {
277 tc.tc_dbglvl = 0;
278 break;
280 prusage(U_DEBUG, 1);
281 /* no return */
282 case 2:
283 level = lvls2bits(av[1]);
284 if (strcmp(av[0], "add") == 0)
285 tc.tc_dbglvl |= level;
286 else if (strcmp(av[0], "del") == 0)
287 tc.tc_dbglvl &= ~level;
288 else if (strcmp(av[0], "set") == 0)
289 tc.tc_dbglvl = level;
290 else
291 prusage(U_DEBUG, 1);
293 if (alldev) {
294 if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
295 err(1, "TCSISDBG_ALL on %s", Devname);
296 } else {
297 if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
298 err(1, "TCSISDBG_LEVEL on %s", Devname);
302 void
303 rxint(int ac, char **av)
305 tc.tc_port = 0;
306 switch (ac) {
307 case 0:
308 printf("%s: ", Devname);
309 case -1:
310 if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
311 err(1, "TCSIGRXIT");
312 printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
313 break;
314 case 1:
315 tc.tc_int = getnum(av[0]) / 10;
316 if (tc.tc_int == 0)
317 tc.tc_int = 1;
318 if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
319 err(1, "TCSIRXIT on %s at %d msec",
320 Devname, tc.tc_int*10);
321 break;
322 default:
323 prusage(U_RXINT, 1);
327 void
328 txint(int ac, char **av)
331 tc.tc_port = 0;
332 switch (ac) {
333 case 0:
334 printf("%s: ", Devname);
335 case -1:
336 if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
337 err(1, "TCSIGIT");
338 printf("aggregate interrupt throttle: %d\n", tc.tc_int);
339 break;
340 case 1:
341 tc.tc_int = getnum(av[0]);
342 if (ioctl(ctlfd, TCSIIT, &tc) < 0)
343 err(1, "TCSIIT on %s at %d", Devname, tc.tc_int);
344 break;
345 default:
346 prusage(U_TXINT, 1);
350 void
351 onoff(int ac, char **av, int cmd, char *cmdstr, char *prstr, int usage)
353 if (ac > 1)
354 prusage(usage, 1);
355 if (ac == 1) {
356 if (strcmp(av[0], "on") == 0)
357 tc.tc_int = 1;
358 else if (strcmp(av[0], "off") == 0)
359 tc.tc_int = 0;
360 else
361 prusage(usage, 1);
362 } else
363 tc.tc_int = -1;
364 if (ioctl(ctlfd, cmd, &tc) < 0)
365 err(1, "%s on %s", cmdstr, Devname);
366 switch (ac) {
367 case 0:
368 printf("%s: ", Devname);
369 case -1:
370 printf("%s ", prstr);
371 if (tc.tc_int)
372 printf("on\n");
373 else
374 printf("off\n");
378 void
379 mstate(int ac, char **av)
381 switch (ac) {
382 case 0:
383 printf("%s: ", Devname);
384 case -1:
385 break;
386 default:
387 prusage(U_MSTATE, 1);
389 if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
390 err(1, "TCSISTATE on %s", Devname);
391 printf("modem bits state - (0x%x)", tc.tc_int);
392 if (tc.tc_int & IP_DCD) printf(" DCD");
393 if (tc.tc_int & IP_DTR) printf(" DTR");
394 if (tc.tc_int & IP_RTS) printf(" RTS");
395 printf("\n");
398 void
399 nport(int ac, char **av)
401 int ports;
403 if (ac != 0)
404 prusage(U_NPORT, 1);
405 if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
406 err(1, "TCSIPORTS on %s", Devname);
407 printf("SLXOS: total of %d ports\n", ports);
410 void
411 ccb_stat(int ac, char **av)
413 struct si_pstat sip;
414 #define CCB sip.tc_ccb
416 if (ac != 0)
417 prusage(U_STAT_CCB, 1);
418 sip.tc_dev = tc.tc_dev;
419 if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
420 err(1, "TCSI_CCB on %s", Devname);
421 printf("%s: ", Devname);
423 /* WORD next - Next Channel */
424 /* WORD addr_uart - Uart address */
425 /* WORD module - address of module struct */
426 printf("\tuart_type 0x%x\n", CCB.type); /* BYTE type - Uart type */
427 /* BYTE fill - */
428 printf("\tx_status 0x%x\n", CCB.x_status); /* BYTE x_status - XON / XOFF status */
429 printf("\tc_status 0x%x\n", CCB.c_status); /* BYTE c_status - cooking status */
430 printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos); /* BYTE hi_rxipos - stuff into rx buff */
431 printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos); /* BYTE hi_rxopos - stuff out of rx buffer */
432 printf("\thi_txopos 0x%x\n", CCB.hi_txopos); /* BYTE hi_txopos - Stuff into tx ptr */
433 printf("\thi_txipos 0x%x\n", CCB.hi_txipos); /* BYTE hi_txipos - ditto out */
434 printf("\thi_stat 0x%x\n", CCB.hi_stat); /* BYTE hi_stat - Command register */
435 printf("\tdsr_bit 0x%x\n", CCB.dsr_bit); /* BYTE dsr_bit - Magic bit for DSR */
436 printf("\ttxon 0x%x\n", CCB.txon); /* BYTE txon - TX XON char */
437 printf("\ttxoff 0x%x\n", CCB.txoff); /* BYTE txoff - ditto XOFF */
438 printf("\trxon 0x%x\n", CCB.rxon); /* BYTE rxon - RX XON char */
439 printf("\trxoff 0x%x\n", CCB.rxoff); /* BYTE rxoff - ditto XOFF */
440 printf("\thi_mr1 0x%x\n", CCB.hi_mr1); /* BYTE hi_mr1 - mode 1 image */
441 printf("\thi_mr2 0x%x\n", CCB.hi_mr2); /* BYTE hi_mr2 - mode 2 image */
442 printf("\thi_csr 0x%x\n", CCB.hi_csr); /* BYTE hi_csr - clock register */
443 printf("\thi_op 0x%x\n", CCB.hi_op); /* BYTE hi_op - Op control */
444 printf("\thi_ip 0x%x\n", CCB.hi_ip); /* BYTE hi_ip - Input pins */
445 printf("\thi_state 0x%x\n", CCB.hi_state); /* BYTE hi_state - status */
446 printf("\thi_prtcl 0x%x\n", CCB.hi_prtcl); /* BYTE hi_prtcl - Protocol */
447 printf("\thi_txon 0x%x\n", CCB.hi_txon); /* BYTE hi_txon - host copy tx xon stuff */
448 printf("\thi_txoff 0x%x\n", CCB.hi_txoff); /* BYTE hi_txoff - */
449 printf("\thi_rxon 0x%x\n", CCB.hi_rxon); /* BYTE hi_rxon - */
450 printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff); /* BYTE hi_rxoff - */
451 printf("\tclose_prev 0x%x\n", CCB.close_prev); /* BYTE close_prev - Was channel previously closed */
452 printf("\thi_break 0x%x\n", CCB.hi_break); /* BYTE hi_break - host copy break process */
453 printf("\tbreak_state 0x%x\n", CCB.break_state); /* BYTE break_state - local copy ditto */
454 printf("\thi_mask 0x%x\n", CCB.hi_mask); /* BYTE hi_mask - Mask for CS7 etc. */
455 printf("\tmask_z280 0x%x\n", CCB.mask_z280); /* BYTE mask_z280 - Z280's copy */
456 /* BYTE res[0x60 - 36] - */
457 /* BYTE hi_txbuf[SLXOS_BUFFERSIZE] - */
458 /* BYTE hi_rxbuf[SLXOS_BUFFERSIZE] - */
459 /* BYTE res1[0xA0] - */
462 void
463 tty_stat(int ac, char **av)
465 struct si_pstat sip;
466 #define TTY sip.tc_tty
468 if (ac != 0)
469 prusage(U_STAT_TTY, 1);
470 sip.tc_dev = tc.tc_dev;
471 if (ioctl(ctlfd, TCSI_TTY, &sip) < 0)
472 err(1, "TCSI_TTY on %s", Devname);
473 printf("%s: ", Devname);
475 printf("\tt_outq.c_cc %d.\n", TTY.t_outq.c_cc); /* struct clist t_outq */
476 printf("\tt_dev %p\n", TTY.t_dev); /* t_dev */
477 printf("\tt_flags 0x%x\n", TTY.t_flags); /* int t_flags */
478 printf("\tt_state 0x%x\n", TTY.t_state); /* int t_state */
479 printf("\tt_ihiwat %d.\n", TTY.t_ihiwat); /* int t_ihiwat */
480 printf("\tt_ilowat %d.\n", TTY.t_ilowat); /* int t_ilowat */
481 printf("\tt_ohiwat %d.\n", TTY.t_ohiwat); /* int t_ohiwat */
482 printf("\tt_olowat %d.\n", TTY.t_olowat); /* int t_olowat */
483 printf("\tt_iflag 0x%x\n", TTY.t_iflag); /* t_iflag */
484 printf("\tt_oflag 0x%x\n", TTY.t_oflag); /* t_oflag */
485 printf("\tt_cflag 0x%x\n", TTY.t_cflag); /* t_cflag */
486 printf("\tt_lflag 0x%x\n", TTY.t_lflag); /* t_lflag */
487 printf("\tt_cc %p\n", (void *)TTY.t_cc); /* t_cc */
488 printf("\tt_termios.c_ispeed 0x%x\n", TTY.t_termios.c_ispeed); /* t_termios.c_ispeed */
489 printf("\tt_termios.c_ospeed 0x%x\n", TTY.t_termios.c_ospeed); /* t_termios.c_ospeed */
493 islevel(char *tk)
495 struct lv *lvp;
496 char *acp;
498 for (acp = tk; *acp; acp++)
499 if (isupper(*acp))
500 *acp = tolower(*acp);
501 for (lvp = lv; lvp->lv_name; lvp++)
502 if (strcmp(lvp->lv_name, tk) == 0)
503 return(lvp->lv_bit);
504 return(0);
508 * Convert a string consisting of tokens separated by white space, commas
509 * or `|' into a bitfield - flag any unrecognised tokens.
512 lvls2bits(char *str)
514 int i, bits = 0;
515 int errflag = 0;
516 char token[20];
518 while (sscanf(str, "%[^,| \t]", token) == 1) {
519 str += strlen(token);
520 while (isspace(*str) || *str==',' || *str=='|')
521 str++;
522 if (strcmp(token, "all") == 0)
523 return(0xffffffff);
524 if ((i = islevel(token)) == 0) {
525 warnx("unknown token '%s'", token);
526 errflag++;
527 } else
528 bits |= i;
530 if (errflag)
531 exit(1);
533 return(bits);
537 getnum(char *str)
539 int x;
540 char *acp = str;
542 x = 0;
543 while (*acp) {
544 if (!isdigit(*acp))
545 errx(1, "%s is not a number", str);
546 x *= 10;
547 x += (*acp - '0');
548 acp++;
550 return(x);
553 void
554 prlevels(int x)
556 struct lv *lvp;
558 switch (x) {
559 case 0:
560 printf("(none)\n");
561 break;
562 case 0xffffffff:
563 printf("all\n");
564 break;
565 default:
566 for (lvp = lv; lvp->lv_name; lvp++)
567 if (x & lvp->lv_bit)
568 printf(" %s", lvp->lv_name);
569 printf("\n");