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 * 4. Neither the name of Advanced Methods and Tools, nor Specialix
20 * International may be used to endorse or promote products derived from
21 * this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
26 * NO EVENT SHALL THE AUTHORS BE LIABLE.
30 static const char rcsid[] =
41 #include <sys/types.h>
42 #include <sys/param.h>
44 #include <sys/ioctl.h>
48 #include <dev/si/si.h>
49 #include <dev/si/sivar.h>
62 {"select", DBG_SELECT},
66 {"lstart", DBG_LSTART},
69 {"autoboot", DBG_AUTOBOOT},
70 {"download", DBG_DOWNLOAD},
76 static int alldev = 0;
78 void ccb_stat(int, char **);
79 void debug(int, char **);
83 int lvls2bits(char *);
84 void mstate(int, char **);
85 void nport(int, char **);
86 void onoff(int, char **, int, char *, char *, int);
87 int opencontrol(void);
89 void prusage(int, int);
90 void rxint(int, char **);
91 void tty_stat(int, char **);
92 void txint(int, char **);
96 void (*o_func)(int, char **);
99 {"rxint_throttle", rxint},
100 {"int_throttle", txint},
103 {"ccbstat", ccb_stat},
104 {"ttystat", tty_stat},
109 void (*st_func)(int, char **);
126 "debug [[add|del|set debug_levels] | [off]]\n",
127 "int_throttle [newvalue]\n",
128 "rxint_throttle [newvalue]\n",
141 main(int argc, char **argv)
144 void (*func)(int, char **) = NULL;
149 if (strcmp(Devname, "-") == 0) {
155 if (strchr(Devname, '/') == NULL) {
156 char *acp = malloc(6 + strlen(Devname));
157 strcpy(acp, _PATH_DEV);
158 strcat(acp, Devname);
161 if (stat(Devname, &st) < 0)
162 errx(1, "can't stat %s", Devname);
164 dev.sid_card = SI_CARD(minor(st.st_rdev));
165 dev.sid_port = SI_PORT(minor(st.st_rdev));
167 errx(1, "Sorry, code missing to parse device name into card/port");
171 ctlfd = opencontrol();
178 for (op = opt; op->o_name; op++) {
179 if (strcmp(argv[1], op->o_name) == 0) {
198 fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
200 err(1, "open on %s", CONTROLDEV);
205 * Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
206 * Don't print the DEBUG usage string unless explicity requested.
209 prusage(int strn, int eflag)
214 fprintf(stderr, "usage: sicontrol %s", usage[1]);
215 fprintf(stderr, " sicontrol %s", usage[2]);
216 fprintf(stderr, " sicontrol %s", usage[3]);
217 fprintf(stderr, " sicontrol devname %s", usage[4]);
218 for (cp = &usage[5]; *cp; cp++)
219 fprintf(stderr, " sicontrol devname %s", *cp);
221 else if (strn >= 0 && strn <= U_MAX)
222 fprintf(stderr, "usage: sicontrol devname %s", usage[strn]);
224 fprintf(stderr, "sicontrol: usage ???\n");
228 /* print port status */
233 struct stat_list *stp;
237 printf("%s: ", alldev ? "ALL" : Devname);
238 acp = malloc(strlen(Devname) + 3);
239 memset(acp, ' ', strlen(Devname));
242 for (stp = stat_list; stp->st_func != NULL; stp++) {
249 (*stp->st_func)(-1, av);
255 * debug [[set|add|del debug_lvls] | [off]]
258 debug(int ac, char **av)
265 if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
266 err(1, "TCSIGDBG_ALL on %s", Devname);
268 if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
269 err(1, "TCSIGDBG_LEVEL on %s", Devname);
274 printf("%s: debug levels - ", Devname);
275 prlevels(tc.tc_dbglvl);
278 if (strcmp(av[0], "off") == 0) {
285 level = lvls2bits(av[1]);
286 if (strcmp(av[0], "add") == 0)
287 tc.tc_dbglvl |= level;
288 else if (strcmp(av[0], "del") == 0)
289 tc.tc_dbglvl &= ~level;
290 else if (strcmp(av[0], "set") == 0)
291 tc.tc_dbglvl = level;
296 if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
297 err(1, "TCSISDBG_ALL on %s", Devname);
299 if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
300 err(1, "TCSISDBG_LEVEL on %s", Devname);
305 rxint(int ac, char **av)
310 printf("%s: ", Devname);
312 if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
314 printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
317 tc.tc_int = getnum(av[0]) / 10;
320 if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
321 err(1, "TCSIRXIT on %s at %d msec",
322 Devname, tc.tc_int*10);
330 txint(int ac, char **av)
336 printf("%s: ", Devname);
338 if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
340 printf("aggregate interrupt throttle: %d\n", tc.tc_int);
343 tc.tc_int = getnum(av[0]);
344 if (ioctl(ctlfd, TCSIIT, &tc) < 0)
345 err(1, "TCSIIT on %s at %d", Devname, tc.tc_int);
353 onoff(int ac, char **av, int cmd, char *cmdstr, char *prstr, int usage)
358 if (strcmp(av[0], "on") == 0)
360 else if (strcmp(av[0], "off") == 0)
366 if (ioctl(ctlfd, cmd, &tc) < 0)
367 err(1, "%s on %s", cmdstr, Devname);
370 printf("%s: ", Devname);
372 printf("%s ", prstr);
381 mstate(int ac, char **av)
385 printf("%s: ", Devname);
389 prusage(U_MSTATE, 1);
391 if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
392 err(1, "TCSISTATE on %s", Devname);
393 printf("modem bits state - (0x%x)", tc.tc_int);
394 if (tc.tc_int & IP_DCD) printf(" DCD");
395 if (tc.tc_int & IP_DTR) printf(" DTR");
396 if (tc.tc_int & IP_RTS) printf(" RTS");
401 nport(int ac, char **av)
407 if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
408 err(1, "TCSIPORTS on %s", Devname);
409 printf("SLXOS: total of %d ports\n", ports);
413 ccb_stat(int ac, char **av)
416 #define CCB sip.tc_ccb
419 prusage(U_STAT_CCB, 1);
420 sip.tc_dev = tc.tc_dev;
421 if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
422 err(1, "TCSI_CCB on %s", Devname);
423 printf("%s: ", Devname);
425 /* WORD next - Next Channel */
426 /* WORD addr_uart - Uart address */
427 /* WORD module - address of module struct */
428 printf("\tuart_type 0x%x\n", CCB.type); /* BYTE type - Uart type */
430 printf("\tx_status 0x%x\n", CCB.x_status); /* BYTE x_status - XON / XOFF status */
431 printf("\tc_status 0x%x\n", CCB.c_status); /* BYTE c_status - cooking status */
432 printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos); /* BYTE hi_rxipos - stuff into rx buff */
433 printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos); /* BYTE hi_rxopos - stuff out of rx buffer */
434 printf("\thi_txopos 0x%x\n", CCB.hi_txopos); /* BYTE hi_txopos - Stuff into tx ptr */
435 printf("\thi_txipos 0x%x\n", CCB.hi_txipos); /* BYTE hi_txipos - ditto out */
436 printf("\thi_stat 0x%x\n", CCB.hi_stat); /* BYTE hi_stat - Command register */
437 printf("\tdsr_bit 0x%x\n", CCB.dsr_bit); /* BYTE dsr_bit - Magic bit for DSR */
438 printf("\ttxon 0x%x\n", CCB.txon); /* BYTE txon - TX XON char */
439 printf("\ttxoff 0x%x\n", CCB.txoff); /* BYTE txoff - ditto XOFF */
440 printf("\trxon 0x%x\n", CCB.rxon); /* BYTE rxon - RX XON char */
441 printf("\trxoff 0x%x\n", CCB.rxoff); /* BYTE rxoff - ditto XOFF */
442 printf("\thi_mr1 0x%x\n", CCB.hi_mr1); /* BYTE hi_mr1 - mode 1 image */
443 printf("\thi_mr2 0x%x\n", CCB.hi_mr2); /* BYTE hi_mr2 - mode 2 image */
444 printf("\thi_csr 0x%x\n", CCB.hi_csr); /* BYTE hi_csr - clock register */
445 printf("\thi_op 0x%x\n", CCB.hi_op); /* BYTE hi_op - Op control */
446 printf("\thi_ip 0x%x\n", CCB.hi_ip); /* BYTE hi_ip - Input pins */
447 printf("\thi_state 0x%x\n", CCB.hi_state); /* BYTE hi_state - status */
448 printf("\thi_prtcl 0x%x\n", CCB.hi_prtcl); /* BYTE hi_prtcl - Protocol */
449 printf("\thi_txon 0x%x\n", CCB.hi_txon); /* BYTE hi_txon - host copy tx xon stuff */
450 printf("\thi_txoff 0x%x\n", CCB.hi_txoff); /* BYTE hi_txoff - */
451 printf("\thi_rxon 0x%x\n", CCB.hi_rxon); /* BYTE hi_rxon - */
452 printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff); /* BYTE hi_rxoff - */
453 printf("\tclose_prev 0x%x\n", CCB.close_prev); /* BYTE close_prev - Was channel previously closed */
454 printf("\thi_break 0x%x\n", CCB.hi_break); /* BYTE hi_break - host copy break process */
455 printf("\tbreak_state 0x%x\n", CCB.break_state); /* BYTE break_state - local copy ditto */
456 printf("\thi_mask 0x%x\n", CCB.hi_mask); /* BYTE hi_mask - Mask for CS7 etc. */
457 printf("\tmask_z280 0x%x\n", CCB.mask_z280); /* BYTE mask_z280 - Z280's copy */
458 /* BYTE res[0x60 - 36] - */
459 /* BYTE hi_txbuf[SLXOS_BUFFERSIZE] - */
460 /* BYTE hi_rxbuf[SLXOS_BUFFERSIZE] - */
461 /* BYTE res1[0xA0] - */
465 tty_stat(int ac, char **av)
468 #define TTY sip.tc_tty
471 prusage(U_STAT_TTY, 1);
472 sip.tc_dev = tc.tc_dev;
473 if (ioctl(ctlfd, TCSI_TTY, &sip) < 0)
474 err(1, "TCSI_TTY on %s", Devname);
475 printf("%s: ", Devname);
477 printf("\tt_outq.c_cc %d.\n", TTY.t_outq.c_cc); /* struct clist t_outq */
478 printf("\tt_dev 0x%x\n", TTY.t_dev); /* dev_t t_dev */
479 printf("\tt_flags 0x%x\n", TTY.t_flags); /* int t_flags */
480 printf("\tt_state 0x%x\n", TTY.t_state); /* int t_state */
481 printf("\tt_ihiwat %d.\n", TTY.t_ihiwat); /* int t_ihiwat */
482 printf("\tt_ilowat %d.\n", TTY.t_ilowat); /* int t_ilowat */
483 printf("\tt_ohiwat %d.\n", TTY.t_ohiwat); /* int t_ohiwat */
484 printf("\tt_olowat %d.\n", TTY.t_olowat); /* int t_olowat */
485 printf("\tt_iflag 0x%x\n", TTY.t_iflag); /* t_iflag */
486 printf("\tt_oflag 0x%x\n", TTY.t_oflag); /* t_oflag */
487 printf("\tt_cflag 0x%x\n", TTY.t_cflag); /* t_cflag */
488 printf("\tt_lflag 0x%x\n", TTY.t_lflag); /* t_lflag */
489 printf("\tt_cc %p\n", (void *)TTY.t_cc); /* t_cc */
490 printf("\tt_termios.c_ispeed 0x%x\n", TTY.t_termios.c_ispeed); /* t_termios.c_ispeed */
491 printf("\tt_termios.c_ospeed 0x%x\n", TTY.t_termios.c_ospeed); /* t_termios.c_ospeed */
500 for (acp = tk; *acp; acp++)
502 *acp = tolower(*acp);
503 for (lvp = lv; lvp->lv_name; lvp++)
504 if (strcmp(lvp->lv_name, tk) == 0)
510 * Convert a string consisting of tokens separated by white space, commas
511 * or `|' into a bitfield - flag any unrecognised tokens.
520 while (sscanf(str, "%[^,| \t]", token) == 1) {
521 str += strlen(token);
522 while (isspace(*str) || *str==',' || *str=='|')
524 if (strcmp(token, "all") == 0)
526 if ((i = islevel(token)) == 0) {
527 warnx("unknown token '%s'", token);
547 errx(1, "%s is not a number", str);
568 for (lvp = lv; lvp->lv_name; lvp++)
570 printf(" %s", lvp->lv_name);