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
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
45 #include <sys/types.h>
46 #include <sys/param.h>
48 #include <sys/ioctl.h>
51 #include <dev/serial/si/si.h>
64 {"select", DBG_SELECT
},
68 {"lstart", DBG_LSTART
},
71 {"autoboot", DBG_AUTOBOOT
},
72 {"download", DBG_DOWNLOAD
},
78 static int alldev
= 0;
80 void ccb_stat(int, char **);
81 void debug(int, 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);
91 void prusage(int, int);
92 void rxint(int, char **);
93 void tty_stat(int, char **);
94 void txint(int, char **);
98 void (*o_func
)(int, char **);
101 {"rxint_throttle", rxint
},
102 {"int_throttle", txint
},
105 {"ccbstat", ccb_stat
},
106 {"ttystat", tty_stat
},
111 void (*st_func
)(int, char **);
128 "debug [[add|del|set debug_levels] | [off]]\n",
129 "int_throttle [newvalue]\n",
130 "rxint_throttle [newvalue]\n",
143 main(int argc
, char **argv
)
146 void (*func
)(int, char **) = NULL
;
151 if (strcmp(Devname
, "-") == 0) {
157 if (strchr(Devname
, '/') == NULL
) {
158 char *acp
= malloc(6 + strlen(Devname
));
159 strcpy(acp
, _PATH_DEV
);
160 strcat(acp
, Devname
);
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
));
169 ctlfd
= opencontrol();
176 for (op
= opt
; op
->o_name
; op
++) {
177 if (strcmp(argv
[1], op
->o_name
) == 0) {
196 fd
= open(CONTROLDEV
, O_RDWR
|O_NDELAY
);
198 err(1, "open on %s", CONTROLDEV
);
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.
207 prusage(int strn
, int eflag
)
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
]);
222 fprintf(stderr
, "sicontrol: usage ???\n");
226 /* print port status */
231 struct stat_list
*stp
;
235 printf("%s: ", alldev
? "ALL" : Devname
);
236 acp
= malloc(strlen(Devname
) + 3);
237 memset(acp
, ' ', strlen(Devname
));
240 for (stp
= stat_list
; stp
->st_func
!= NULL
; stp
++) {
247 (*stp
->st_func
)(-1, av
);
253 * debug [[set|add|del debug_lvls] | [off]]
256 debug(int ac
, char **av
)
263 if (ioctl(ctlfd
, TCSIGDBG_ALL
, &tc
.tc_dbglvl
) < 0)
264 err(1, "TCSIGDBG_ALL on %s", Devname
);
266 if (ioctl(ctlfd
, TCSIGDBG_LEVEL
, &tc
) < 0)
267 err(1, "TCSIGDBG_LEVEL on %s", Devname
);
272 printf("%s: debug levels - ", Devname
);
273 prlevels(tc
.tc_dbglvl
);
276 if (strcmp(av
[0], "off") == 0) {
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
;
294 if (ioctl(ctlfd
, TCSISDBG_ALL
, &tc
.tc_dbglvl
) < 0)
295 err(1, "TCSISDBG_ALL on %s", Devname
);
297 if (ioctl(ctlfd
, TCSISDBG_LEVEL
, &tc
) < 0)
298 err(1, "TCSISDBG_LEVEL on %s", Devname
);
303 rxint(int ac
, char **av
)
308 printf("%s: ", Devname
);
310 if (ioctl(ctlfd
, TCSIGRXIT
, &tc
) < 0)
312 printf("RX interrupt throttle: %d msec\n", tc
.tc_int
*10);
315 tc
.tc_int
= getnum(av
[0]) / 10;
318 if (ioctl(ctlfd
, TCSIRXIT
, &tc
) < 0)
319 err(1, "TCSIRXIT on %s at %d msec",
320 Devname
, tc
.tc_int
*10);
328 txint(int ac
, char **av
)
334 printf("%s: ", Devname
);
336 if (ioctl(ctlfd
, TCSIGIT
, &tc
) < 0)
338 printf("aggregate interrupt throttle: %d\n", tc
.tc_int
);
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
);
351 onoff(int ac
, char **av
, int cmd
, char *cmdstr
, char *prstr
, int usage
)
356 if (strcmp(av
[0], "on") == 0)
358 else if (strcmp(av
[0], "off") == 0)
364 if (ioctl(ctlfd
, cmd
, &tc
) < 0)
365 err(1, "%s on %s", cmdstr
, Devname
);
368 printf("%s: ", Devname
);
370 printf("%s ", prstr
);
379 mstate(int ac
, char **av
)
383 printf("%s: ", Devname
);
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");
399 nport(int ac
, char **av
)
405 if (ioctl(ctlfd
, TCSIPORTS
, &ports
) < 0)
406 err(1, "TCSIPORTS on %s", Devname
);
407 printf("SLXOS: total of %d ports\n", ports
);
411 ccb_stat(int ac
, char **av
)
414 #define CCB sip.tc_ccb
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 */
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] - */
463 tty_stat(int ac
, char **av
)
466 #define TTY sip.tc_tty
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 */
498 for (acp
= tk
; *acp
; acp
++)
500 *acp
= tolower(*acp
);
501 for (lvp
= lv
; lvp
->lv_name
; lvp
++)
502 if (strcmp(lvp
->lv_name
, tk
) == 0)
508 * Convert a string consisting of tokens separated by white space, commas
509 * or `|' into a bitfield - flag any unrecognised tokens.
518 while (sscanf(str
, "%[^,| \t]", token
) == 1) {
519 str
+= strlen(token
);
520 while (isspace(*str
) || *str
==',' || *str
=='|')
522 if (strcmp(token
, "all") == 0)
524 if ((i
= islevel(token
)) == 0) {
525 warnx("unknown token '%s'", token
);
545 errx(1, "%s is not a number", str
);
566 for (lvp
= lv
; lvp
->lv_name
; lvp
++)
568 printf(" %s", lvp
->lv_name
);