110045Speter/*
210045Speter * Device driver for Specialix range (SLXOS) of serial line multiplexors.
310045Speter *	SLXOS configuration and debug interface
410045Speter *
510045Speter * Copyright (C) 1990, 1992 Specialix International,
610045Speter * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
7179450Speter * Copyright (C) 1995, Peter Wemm
810045Speter *
910045Speter * Derived from:	SunOS 4.x version
1010045Speter *
1110045Speter * Redistribution and use in source and binary forms, with or without
1210045Speter * modification, are permitted provided that the following conditions
1310045Speter * are met:
1410045Speter * 1. Redistributions of source code must retain the above copyright
1510045Speter *    notices, this list of conditions and the following disclaimer.
1610045Speter * 2. Redistributions in binary form must reproduce the above copyright
1710045Speter *    notices, this list of conditions and the following disclaimer in the
1810045Speter *    documentation and/or other materials provided with the distribution.
1910045Speter * 4. Neither the name of Advanced Methods and Tools, nor Specialix
2010045Speter *    International may be used to endorse or promote products derived from
2110045Speter *    this software without specific prior written permission.
2210045Speter *
2310045Speter * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
2410045Speter * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2510045Speter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
2610045Speter * NO EVENT SHALL THE AUTHORS BE LIABLE.
2710045Speter */
2810045Speter
2930427Scharnier#ifndef lint
3030427Scharnierstatic const char rcsid[] =
3150479Speter  "$FreeBSD$";
3230427Scharnier#endif /* not lint */
3330427Scharnier
3430427Scharnier#include <ctype.h>
3530427Scharnier#include <err.h>
3630427Scharnier#include <fcntl.h>
3769793Sobrien#include <paths.h>
3810045Speter#include <stdio.h>
3930427Scharnier#include <stdlib.h>
4030427Scharnier#include <string.h>
4110045Speter#include <sys/types.h>
4210045Speter#include <sys/param.h>
4310045Speter#include <sys/stat.h>
4410045Speter#include <sys/ioctl.h>
4510045Speter#include <sys/tty.h>
4610045Speter
47136063Sphk#define SI_DEBUG
4856509Speter#include <dev/si/si.h>
49136063Sphk#include <dev/si/sivar.h>
5010045Speter
5110045Speterstruct lv {
5210045Speter	char	*lv_name;
5310045Speter	int 	lv_bit;
5410045Speter} lv[] = {
5530427Scharnier	{"entry",	DBG_ENTRY},
5630427Scharnier	{"open",	DBG_OPEN},
5730427Scharnier	{"close",	DBG_CLOSE},
5830427Scharnier	{"read",	DBG_READ},
5930427Scharnier	{"write",	DBG_WRITE},
6030427Scharnier	{"param",	DBG_PARAM},
6130427Scharnier	{"modem",	DBG_MODEM},
6230427Scharnier	{"select",	DBG_SELECT},
6330427Scharnier	{"optim",	DBG_OPTIM},
6430427Scharnier	{"intr",	DBG_INTR},
6530427Scharnier	{"start",	DBG_START},
6630427Scharnier	{"lstart",	DBG_LSTART},
6730427Scharnier	{"ioctl",	DBG_IOCTL},
6830427Scharnier	{"fail",	DBG_FAIL},
6930427Scharnier	{"autoboot",	DBG_AUTOBOOT},
7030427Scharnier	{"download",	DBG_DOWNLOAD},
7130427Scharnier	{"drain",	DBG_DRAIN},
7230427Scharnier	{"poll",	DBG_POLL},
7330427Scharnier	{0,		0}
7410045Speter};
7510045Speter
7610045Speterstatic int alldev = 0;
7710045Speter
7856520Spetervoid ccb_stat(int, char **);
79179590Spetervoid port_stat(int, char **);
8056520Spetervoid debug(int, char **);
8156520Spetervoid dostat(void);
8256520Speterint getnum(char *);
8356520Speterint islevel(char *);
8456520Speterint lvls2bits(char *);
8556520Spetervoid mstate(int, char **);
8656520Spetervoid nport(int, char **);
8756520Spetervoid onoff(int, char **, int, char *, char *, int);
8856520Speterint opencontrol(void);
8956520Spetervoid prlevels(int);
9056520Spetervoid prusage(int, int);
9156520Spetervoid rxint(int, char **);
9256520Spetervoid txint(int, char **);
9330427Scharnier
9410045Speterstruct opt {
9510045Speter	char	*o_name;
9656520Speter	void	(*o_func)(int, char **);
9710045Speter} opt[] = {
9830427Scharnier	{"debug",		debug},
9930427Scharnier	{"rxint_throttle",	rxint},
10030427Scharnier	{"int_throttle",	txint},
10130427Scharnier	{"nport",		nport},
10230427Scharnier	{"mstate",		mstate},
10330427Scharnier	{"ccbstat",		ccb_stat},
104179590Speter	{"portstat",		port_stat},
10530427Scharnier	{0,			0}
10610045Speter};
10710045Speter
10810045Speterstruct stat_list {
10956520Speter	void (*st_func)(int, char **);
11010045Speter} stat_list[] = {
11130427Scharnier	{mstate},
11230427Scharnier	{0}
11310045Speter};
11410045Speter
11510045Speter#define	U_DEBUG		0
11610045Speter#define	U_TXINT		1
11710045Speter#define	U_RXINT		2
11811098Speter#define	U_NPORT		3
11911098Speter#define	U_MSTATE	4
12010045Speter#define	U_STAT_CCB	5
121179590Speter#define	U_STAT_PORT	6
12210045Speter
123179668Sed#define	U_MAX		7
12410045Speter#define	U_ALL		-1
12510045Speterchar *usage[] = {
12610045Speter	"debug [[add|del|set debug_levels] | [off]]\n",
12710045Speter	"int_throttle [newvalue]\n",
12810045Speter	"rxint_throttle [newvalue]\n",
12911098Speter	"nport\n",
13010045Speter	"mstate\n",
13110045Speter	"ccbstat\n",
132179590Speter	"portstat\n",
13310045Speter	0
13410045Speter};
13510045Speter
13610045Speterint ctlfd;
13710045Speterchar *Devname;
13810045Speterstruct si_tcsi tc;
13910045Speter
14030427Scharnierint
14156520Spetermain(int argc, char **argv)
14210045Speter{
14310045Speter	struct opt *op;
14456520Speter	void (*func)(int, char **) = NULL;
14510045Speter
14610045Speter	if (argc < 2)
14710045Speter		prusage(U_ALL, 1);
14810045Speter	Devname = argv[1];
14910045Speter	if (strcmp(Devname, "-") == 0) {
15010045Speter		alldev = 1;
15110045Speter	} else {
15210045Speter		sidev_t dev;
153179590Speter		int n;
154179590Speter		int card, port;
15510045Speter
156179590Speter		n = sscanf(Devname, "%d:%d", &card, &port);
157179590Speter		if (n != 2)
158179590Speter			errx(1, "Devname must be in form card:port.  eg: 0:7");
159179590Speter		dev.sid_card = card;
160179590Speter		dev.sid_port = port;
16110045Speter		tc.tc_dev = dev;
16210045Speter	}
16310045Speter	ctlfd = opencontrol();
16410045Speter	if (argc == 2) {
16510045Speter		dostat();
16610045Speter		exit(0);
16710045Speter	}
16810045Speter
16910045Speter	argc--; argv++;
17010045Speter	for (op = opt; op->o_name; op++) {
17110045Speter		if (strcmp(argv[1], op->o_name) == 0) {
17210045Speter			func = op->o_func;
17310045Speter			break;
17410045Speter		}
17510045Speter	}
17610045Speter	if (func == NULL)
17710045Speter		prusage(U_ALL, 1);
17810045Speter
17910045Speter	argc -= 2;
18010045Speter	argv += 2;
18110045Speter	(*func)(argc, argv);
18210045Speter	exit(0);
18310045Speter}
18410045Speter
18530427Scharnierint
18656520Speteropencontrol(void)
18710045Speter{
18810045Speter	int fd;
18910045Speter
19010045Speter	fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
19130427Scharnier	if (fd < 0)
19230427Scharnier		err(1, "open on %s", CONTROLDEV);
19310045Speter	return(fd);
19410045Speter}
19510045Speter
19610045Speter/*
19710045Speter * Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
19810045Speter * Don't print the DEBUG usage string unless explicity requested.
19910045Speter */
20030427Scharniervoid
20156520Speterprusage(int strn, int eflag)
20210045Speter{
20310045Speter	char **cp;
20410045Speter
20510045Speter	if (strn == U_ALL) {
20630427Scharnier		fprintf(stderr, "usage: sicontrol %s", usage[1]);
20730427Scharnier		fprintf(stderr, "       sicontrol %s", usage[2]);
20830427Scharnier		fprintf(stderr, "       sicontrol %s", usage[3]);
20911098Speter		fprintf(stderr, "       sicontrol devname %s", usage[4]);
21011098Speter		for (cp = &usage[5]; *cp; cp++)
21111098Speter			fprintf(stderr, "       sicontrol devname %s", *cp);
21210045Speter	}
21310045Speter	else if (strn >= 0 && strn <= U_MAX)
21430427Scharnier		fprintf(stderr, "usage: sicontrol devname %s", usage[strn]);
21510045Speter	else
21610052Speter		fprintf(stderr, "sicontrol: usage ???\n");
21710045Speter	exit(eflag);
21810045Speter}
21910045Speter
22010045Speter/* print port status */
22130427Scharniervoid
22256520Speterdostat(void)
22310045Speter{
22410045Speter	char *av[1], *acp;
22510045Speter	struct stat_list *stp;
22610045Speter	struct si_tcsi stc;
22710045Speter	int donefirst = 0;
22810045Speter
22910045Speter	printf("%s: ", alldev ? "ALL" : Devname);
23010045Speter	acp = malloc(strlen(Devname) + 3);
23110045Speter	memset(acp, ' ', strlen(Devname));
23210045Speter	strcat(acp, "  ");
23310045Speter	stc = tc;
23410045Speter	for (stp = stat_list; stp->st_func != NULL; stp++) {
23510045Speter		if (donefirst)
23610045Speter			fputs(acp, stdout);
23710045Speter		else
23810045Speter			donefirst++;
23910045Speter		av[0] = NULL;
24010045Speter		tc = stc;
24110045Speter		(*stp->st_func)(-1, av);
24210045Speter	}
24310045Speter}
24410045Speter
24510045Speter/*
24610045Speter * debug
24710045Speter * debug [[set|add|del debug_lvls] | [off]]
24810045Speter */
24930427Scharniervoid
25056520Speterdebug(int ac, char **av)
25110045Speter{
25230427Scharnier	int level;
25310045Speter
25410045Speter	if (ac > 2)
25510045Speter		prusage(U_DEBUG, 1);
25610045Speter	if (alldev) {
25710045Speter		if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
25830427Scharnier			err(1, "TCSIGDBG_ALL on %s", Devname);
25910045Speter	} else {
26010045Speter		if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
26130427Scharnier			err(1, "TCSIGDBG_LEVEL on %s", Devname);
26210045Speter	}
26310045Speter
26410045Speter	switch (ac) {
26510045Speter	case 0:
26610045Speter		printf("%s: debug levels - ", Devname);
26710045Speter		prlevels(tc.tc_dbglvl);
26810045Speter		return;
26910045Speter	case 1:
27010045Speter		if (strcmp(av[0], "off") == 0) {
27110045Speter			tc.tc_dbglvl = 0;
27210045Speter			break;
27310045Speter		}
27410045Speter		prusage(U_DEBUG, 1);
27510045Speter		/* no return */
27610045Speter	case 2:
27710045Speter		level = lvls2bits(av[1]);
27810045Speter		if (strcmp(av[0], "add") == 0)
27910045Speter			tc.tc_dbglvl |= level;
28010045Speter		else if (strcmp(av[0], "del") == 0)
28110045Speter			tc.tc_dbglvl &= ~level;
28210045Speter		else if (strcmp(av[0], "set") == 0)
28310045Speter			tc.tc_dbglvl = level;
28410045Speter		else
28510045Speter			prusage(U_DEBUG, 1);
28610045Speter	}
28710045Speter	if (alldev) {
28810045Speter		if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
28930427Scharnier			err(1, "TCSISDBG_ALL on %s", Devname);
29010045Speter	} else {
29110045Speter		if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
29230427Scharnier			err(1, "TCSISDBG_LEVEL on %s", Devname);
29310045Speter	}
29410045Speter}
29510045Speter
29630427Scharniervoid
29756520Speterrxint(int ac, char **av)
29810045Speter{
29910045Speter	tc.tc_port = 0;
30010045Speter	switch (ac) {
30110045Speter	case 0:
30210045Speter		printf("%s: ", Devname);
30310045Speter	case -1:
30410045Speter		if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
30530427Scharnier			err(1, "TCSIGRXIT");
30610045Speter		printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
30710045Speter		break;
30810045Speter	case 1:
30910045Speter		tc.tc_int = getnum(av[0]) / 10;
31010045Speter		if (tc.tc_int == 0)
31110045Speter			tc.tc_int = 1;
31210045Speter		if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
31330427Scharnier			err(1, "TCSIRXIT on %s at %d msec",
31430427Scharnier				Devname, tc.tc_int*10);
31510045Speter		break;
31610045Speter	default:
31710045Speter		prusage(U_RXINT, 1);
31810045Speter	}
31910045Speter}
32010045Speter
32130427Scharniervoid
32256520Spetertxint(int ac, char **av)
32310045Speter{
32410045Speter
32510045Speter	tc.tc_port = 0;
32610045Speter	switch (ac) {
32710045Speter	case 0:
32810045Speter		printf("%s: ", Devname);
32910045Speter	case -1:
33010045Speter		if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
33130427Scharnier			err(1, "TCSIGIT");
33210045Speter		printf("aggregate interrupt throttle: %d\n", tc.tc_int);
33310045Speter		break;
33410045Speter	case 1:
33510045Speter		tc.tc_int = getnum(av[0]);
33610045Speter		if (ioctl(ctlfd, TCSIIT, &tc) < 0)
33730427Scharnier			err(1, "TCSIIT on %s at %d", Devname, tc.tc_int);
33810045Speter		break;
33910045Speter	default:
34010045Speter		prusage(U_TXINT, 1);
34110045Speter	}
34210045Speter}
34310045Speter
34430427Scharniervoid
34556520Speteronoff(int ac, char **av, int cmd, char *cmdstr, char *prstr, int usage)
34610045Speter{
34710045Speter	if (ac > 1)
34810045Speter		prusage(usage, 1);
34910045Speter	if (ac == 1) {
35010045Speter		if (strcmp(av[0], "on") == 0)
35110045Speter			tc.tc_int = 1;
35210045Speter		else if (strcmp(av[0], "off") == 0)
35310045Speter			tc.tc_int = 0;
35410045Speter		else
35510045Speter			prusage(usage, 1);
35610045Speter	} else
35710045Speter		tc.tc_int = -1;
35810045Speter	if (ioctl(ctlfd, cmd, &tc) < 0)
35930427Scharnier		err(1, "%s on %s", cmdstr, Devname);
36010045Speter	switch (ac) {
36110045Speter	case 0:
36210045Speter		printf("%s: ", Devname);
36310045Speter	case -1:
36410045Speter		printf("%s ", prstr);
36510045Speter		if (tc.tc_int)
36610045Speter			printf("on\n");
36710045Speter		else
36810045Speter			printf("off\n");
36910045Speter	}
37010045Speter}
37110045Speter
37230427Scharniervoid
37356520Spetermstate(int ac, char **av)
37410045Speter{
37510045Speter	switch (ac) {
37610045Speter	case 0:
37710045Speter		printf("%s: ", Devname);
37810045Speter	case -1:
37910045Speter		break;
38010045Speter	default:
38110045Speter		prusage(U_MSTATE, 1);
38210045Speter	}
38310045Speter	if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
38430427Scharnier		err(1, "TCSISTATE on %s", Devname);
38510045Speter	printf("modem bits state - (0x%x)", tc.tc_int);
38610045Speter	if (tc.tc_int & IP_DCD)	printf(" DCD");
38710045Speter	if (tc.tc_int & IP_DTR)	printf(" DTR");
38810045Speter	if (tc.tc_int & IP_RTS)	printf(" RTS");
38910045Speter	printf("\n");
39010045Speter}
39110045Speter
39230427Scharniervoid
39356520Speternport(int ac, char **av)
39410045Speter{
39510045Speter	int ports;
39610045Speter
39710045Speter	if (ac != 0)
39810045Speter		prusage(U_NPORT, 1);
39910045Speter	if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
40030427Scharnier		err(1, "TCSIPORTS on %s", Devname);
40110045Speter	printf("SLXOS: total of %d ports\n", ports);
40210045Speter}
40310045Speter
404179590Speterconst char *s_stat(int stat)
405179590Speter{
406179590Speter	switch (stat) {
407179590Speter	case IDLE_OPEN:	return "IDLE_OPEN";
408179590Speter	case LOPEN:	return "LOPEN";
409179590Speter	case MOPEN:	return "MOPEN";
410179590Speter	case MPEND:	return "MPEND";
411179590Speter	case CONFIG:	return "CONFIG";
412179590Speter	case CLOSE:	return "CLOSE";
413179590Speter	case SBREAK:	return "SBREAK";
414179590Speter	case EBREAK:	return "EBREAK";
415179590Speter	case IDLE_CLOSE:return "IDLE_CLOSE";
416179590Speter	case IDLE_BREAK:return "IDLE_BREAK";
417179590Speter	case FCLOSE:	return "FCLOSE";
418179590Speter	case RESUME:	return "RESUME";
419179590Speter	case WFLUSH:	return "WFLUSH";
420179590Speter	case RFLUSH:	return "RFLUSH";
421179590Speter	default: return "??";
422179590Speter	}
423179590Speter}
424179590Speterconst char *s_mr1(int mr1)
425179590Speter{
426179590Speter	static char msg[200];
427179590Speter
428179590Speter	sprintf(msg, "%dbit, %s, parity:[", 5 + (mr1 & MR1_8_BITS), mr1 & MR1_ODD ? "odd" : "even");
429179590Speter	if (mr1 & MR1_WITH)
430179590Speter		strcat(msg, "with;");
431179590Speter	if (mr1 & MR1_FORCE)
432179590Speter		strcat(msg, "force;");
433179590Speter	if (mr1 & MR1_NONE)
434179590Speter		strcat(msg, "none;");
435179590Speter	if (mr1 & MR1_SPECIAL)
436179590Speter		strcat(msg, "special;");
437179590Speter	strcpy(msg + strlen(msg) - 1, "]");
438179590Speter	sprintf(msg + strlen(msg), ", err: %s", mr1 & MR1_BLOCK ? "block" : "none");
439179590Speter	sprintf(msg + strlen(msg), ", cts: %s", mr1 & MR1_CTSCONT ? "auto" : "none");
440179590Speter	return (msg);
441179590Speter}
442179590Speterconst char *s_mr2(int mr2)
443179590Speter{
444179590Speter	static char msg[200];
445179590Speter
446179590Speter	switch (mr2 & 0xf) {
447179590Speter	case MR2_1_STOP: strcpy(msg, "1stop"); break;
448179590Speter	case MR2_2_STOP: strcpy(msg, "2stop"); break;
449179590Speter	default: sprintf(msg, "??stop (0x%x)", mr2 & 0xf); break;
450179590Speter	}
451179590Speter	if (mr2 & MR2_RTSCONT)	strcat(msg, ", rtscont");
452179590Speter	if (mr2 & MR2_CTSCONT)	strcat(msg, ", ctscont");
453179590Speter	switch (mr2 & 0xc0) {
454179590Speter	case MR2_NORMAL: strcat(msg, ", mode:normal"); break;
455179590Speter	case MR2_AUTO: strcat(msg, ", mode:auto"); break;
456179590Speter	case MR2_LOCAL: strcat(msg, ", mode:local"); break;
457179590Speter	case MR2_REMOTE: strcat(msg, ", mode:remote"); break;
458179590Speter	}
459179590Speter	return (msg);
460179590Speter}
461179590Speterconst char *s_clk(int clk)
462179590Speter{
463179590Speter	switch (clk & 0xf) {
464179590Speter	case 0x0: return "75";
465179590Speter	case 0x1: return "110/115200";
466179590Speter	case 0x2: return "38400";
467179590Speter	case 0x3: return "150";
468179590Speter	case 0x4: return "300";
469179590Speter	case 0x5: return "600";
470179590Speter	case 0x6: return "1200";
471179590Speter	case 0x7: return "2000";
472179590Speter	case 0x8: return "2400";
473179590Speter	case 0x9: return "4800";
474179590Speter	case 0xa: return "7200";
475179590Speter	case 0xb: return "9600";
476179590Speter	case 0xc: return "19200";
477179590Speter	case 0xd: return "57600";
478179590Speter	case 0xe: return "?0xe";
479179590Speter	case 0xf: return "?0xf";
480179590Speter	}
481179590Speter	return ("gcc sucks");
482179590Speter}
483179590Speterconst char *s_op(int op)
484179590Speter{
485179590Speter	static char msg[200];
486179590Speter
487179590Speter	sprintf(msg, "cts:%s", (op & OP_CTS) ? "on" : "off");
488179590Speter	sprintf(msg + strlen(msg), ", dsr:%s", (op & OP_DSR) ? "on" : "off");
489179590Speter	return (msg);
490179590Speter}
491179590Speter
492179590Speterconst char *s_ip(int ip)
493179590Speter{
494179590Speter	static char msg[200];
495179590Speter
496179590Speter	sprintf(msg, "rts:%s", (ip & IP_RTS) ? "on" : "off");
497179590Speter	sprintf(msg + strlen(msg), ", dcd:%s", (ip & IP_DCD) ? "on" : "off");
498179590Speter	sprintf(msg + strlen(msg), ", dtr:%s", (ip & IP_DTR) ? "on" : "off");
499179590Speter	sprintf(msg + strlen(msg), ", ri:%s", (ip & IP_RI) ? "on" : "off");
500179590Speter	return (msg);
501179590Speter}
502179590Speter
503179590Speterconst char *s_state(int state)
504179590Speter{
505179590Speter	return (state & ST_BREAK ? "break:on" : "break:off");
506179590Speter}
507179590Speter
508179590Speterconst char *s_prtcl(int pr)
509179590Speter{
510179590Speter	static char msg[200];
511179590Speter
512179590Speter	sprintf(msg, "tx xon any:%s", (pr & SP_TANY) ? "on" : "off");
513179590Speter	sprintf(msg + strlen(msg), ", tx xon/xoff:%s", (pr & SP_TXEN) ? "on" : "off");
514179590Speter	sprintf(msg + strlen(msg), ", cooking:%s", (pr & SP_CEN) ? "on" : "off");
515179590Speter	sprintf(msg + strlen(msg), ", rx xon/xoff:%s", (pr & SP_RXEN) ? "on" : "off");
516179590Speter	sprintf(msg + strlen(msg), ", dcd/dsr check:%s", (pr & SP_DCEN) ? "on" : "off");
517179590Speter	sprintf(msg + strlen(msg), ", parity check:%s", (pr & SP_PAEN) ? "on" : "off");
518179590Speter	return (msg);
519179590Speter}
520179590Speterconst char *s_break(int br)
521179590Speter{
522179590Speter	static char msg[200];
523179590Speter
524179590Speter	sprintf(msg, "ignore rx brk:%s", (br & BR_IGN) ? "on" : "off");
525179590Speter	sprintf(msg + strlen(msg), ", brk interrupt:%s", (br & BR_INT) ? "on" : "off");
526179590Speter	sprintf(msg + strlen(msg), ", parmrking:%s", (br & BR_PARMRK) ? "on" : "off");
527179590Speter	sprintf(msg + strlen(msg), ", parign:%s", (br & BR_PARIGN) ? "on" : "off");
528179590Speter	return (msg);
529179590Speter}
530179590Speter
531179590Speterconst char *
532179590Speters_xstat(int xs)
533179590Speter{
534179590Speter	static char msg[200];
535179590Speter
536179590Speter	msg[0] = 0;
537179590Speter	/* MTA definitions, not TA */
538179590Speter	if (xs & 0x01) strcat(msg, "TION ");	/* Tx interrupts on (MTA only) */
539179590Speter	if (xs & 0x02) strcat(msg, "RTSEN ");	/* RTS FLOW enabled (MTA only) */
540179590Speter	if (xs & 0x04) strcat(msg, "RTSLOW ");	/* XOFF received (TA only) */
541179590Speter	if (xs & 0x08) strcat(msg, "RXEN ");	/* Rx XON/XOFF enabled */
542179590Speter	if (xs & 0x10) strcat(msg, "ANYXO ");	/* XOFF pending/sent or RTS dropped */
543179590Speter	if (xs & 0x20) strcat(msg, "RXSE ");	/* Rx XOFF sent */
544179590Speter	if (xs & 0x40) strcat(msg, "NPEND ");	/* Rx XON pending or XOFF pending */
545179590Speter	if (xs & 0x40) strcat(msg, "FPEND ");	/* Rx XOFF pending */
546179590Speter	return (msg);
547179590Speter}
548179590Speter
549179590Speterconst char *
550179590Speters_cstat(int cs)
551179590Speter{
552179590Speter	static char msg[200];
553179590Speter
554179590Speter	msg[0] = 0;
555179590Speter	/* MTA definitions, not TA */
556179590Speter	if (cs & 0x01) strcat(msg, "TEMR ");	/* Tx empty requested (MTA only) */
557179590Speter	if (cs & 0x02) strcat(msg, "TEMA ");	/* Tx empty acked (MTA only) */
558179590Speter	if (cs & 0x04) strcat(msg, "EN ");	/* Cooking enabled (on MTA means port is also || */
559179590Speter	if (cs & 0x08) strcat(msg, "HIGH ");	/* Buffer previously hit high water */
560179590Speter	if (cs & 0x10) strcat(msg, "CTSEN ");	/* CTS automatic flow-control enabled */
561179590Speter	if (cs & 0x20) strcat(msg, "DCDEN ");	/* DCD/DTR checking enabled */
562179590Speter	if (cs & 0x40) strcat(msg, "BREAK ");	/* Break detected */
563179590Speter	if (cs & 0x80) strcat(msg, "RTSEN ");	/* RTS automatic flow control enabled (MTA only) */
564179590Speter	return (msg);
565179590Speter}
566179590Speter
56730427Scharniervoid
56856520Speterccb_stat(int ac, char **av)
56910045Speter{
57010045Speter	struct si_pstat sip;
57110045Speter#define	CCB	sip.tc_ccb
57210045Speter
57310045Speter	if (ac != 0)
57430427Scharnier		prusage(U_STAT_CCB, 1);
57510045Speter	sip.tc_dev = tc.tc_dev;
57610045Speter	if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
57730427Scharnier		err(1, "TCSI_CCB on %s", Devname);
57810045Speter	printf("%s: ", Devname);
57910045Speter
58010045Speter							/* WORD	next - Next Channel */
58110045Speter							/* WORD	addr_uart - Uart address */
58210045Speter							/* WORD	module - address of module struct */
58310045Speter	printf("\tuart_type 0x%x\n", CCB.type);		/* BYTE type - Uart type */
58410045Speter							/* BYTE	fill - */
585179590Speter	printf("\tx_status 0x%x %s\n", CCB.x_status, s_xstat(CCB.x_status));	/* BYTE	x_status - XON / XOFF status */
586179590Speter	printf("\tc_status 0x%x %s\n", CCB.c_status, s_cstat(CCB.c_status));	/* BYTE	c_status - cooking status */
58710045Speter	printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos);	/* BYTE	hi_rxipos - stuff into rx buff */
58810045Speter	printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos);	/* BYTE	hi_rxopos - stuff out of rx buffer */
58910045Speter	printf("\thi_txopos 0x%x\n", CCB.hi_txopos);	/* BYTE	hi_txopos - Stuff into tx ptr */
59010045Speter	printf("\thi_txipos 0x%x\n", CCB.hi_txipos);	/* BYTE	hi_txipos - ditto out */
591179590Speter	printf("\thi_stat 0x%x %s\n", CCB.hi_stat, s_stat(CCB.hi_stat));/* BYTE	hi_stat - Command register */
59210045Speter	printf("\tdsr_bit 0x%x\n", CCB.dsr_bit);		/* BYTE	dsr_bit - Magic bit for DSR */
59310045Speter	printf("\ttxon 0x%x\n", CCB.txon);		/* BYTE	txon - TX XON char */
59410045Speter	printf("\ttxoff 0x%x\n", CCB.txoff);		/* BYTE	txoff - ditto XOFF */
59510045Speter	printf("\trxon 0x%x\n", CCB.rxon);		/* BYTE	rxon - RX XON char */
59610045Speter	printf("\trxoff 0x%x\n", CCB.rxoff);		/* BYTE	rxoff - ditto XOFF */
597179590Speter	printf("\thi_mr1 0x%x %s\n", CCB.hi_mr1, s_mr1(CCB.hi_mr1));		/* BYTE	hi_mr1 - mode 1 image */
598179590Speter	printf("\thi_mr2 0x%x %s\n", CCB.hi_mr2, s_mr2(CCB.hi_mr2));		/* BYTE	hi_mr2 - mode 2 image */
599179590Speter        printf("\thi_csr 0x%x in:%s out:%s\n", CCB.hi_csr, s_clk(CCB.hi_csr >> 4), s_clk(CCB.hi_csr));		/* BYTE	hi_csr - clock register */
600179590Speter	printf("\thi_op 0x%x %s\n", CCB.hi_op, s_op(CCB.hi_op));		/* BYTE	hi_op - Op control */
601179590Speter	printf("\thi_ip 0x%x %s\n", CCB.hi_ip, s_ip(CCB.hi_ip));		/* BYTE	hi_ip - Input pins */
602179590Speter	printf("\thi_state 0x%x %s\n", CCB.hi_state, s_state(CCB.hi_state));	/* BYTE	hi_state - status */
603179590Speter	printf("\thi_prtcl 0x%x %s\n", CCB.hi_prtcl, s_prtcl(CCB.hi_prtcl));	/* BYTE	hi_prtcl - Protocol */
60410045Speter	printf("\thi_txon 0x%x\n", CCB.hi_txon);		/* BYTE	hi_txon - host copy tx xon stuff */
60510045Speter	printf("\thi_txoff 0x%x\n", CCB.hi_txoff);	/* BYTE	hi_txoff - */
60610045Speter	printf("\thi_rxon 0x%x\n", CCB.hi_rxon);		/* BYTE	hi_rxon - */
60710045Speter	printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff);	/* BYTE	hi_rxoff - */
60810045Speter	printf("\tclose_prev 0x%x\n", CCB.close_prev);	/* BYTE	close_prev - Was channel previously closed */
609179590Speter	printf("\thi_break 0x%x %s\n", CCB.hi_break, s_break(CCB.hi_break));	/* BYTE	hi_break - host copy break process */
61010045Speter	printf("\tbreak_state 0x%x\n", CCB.break_state);	/* BYTE	break_state - local copy ditto */
61110045Speter	printf("\thi_mask 0x%x\n", CCB.hi_mask);		/* BYTE	hi_mask - Mask for CS7 etc. */
61210045Speter	printf("\tmask_z280 0x%x\n", CCB.mask_z280);	/* BYTE	mask_z280 - Z280's copy */
61310045Speter							/* BYTE	res[0x60 - 36] - */
61410045Speter							/* BYTE	hi_txbuf[SLXOS_BUFFERSIZE] - */
61510045Speter							/* BYTE	hi_rxbuf[SLXOS_BUFFERSIZE] - */
61610045Speter							/* BYTE	res1[0xA0] - */
61710045Speter}
61810045Speter
619179590Speterconst char *sp_state(int st)
620179590Speter{
621179590Speter
622179590Speter	if (st & SS_LSTART)
623179590Speter		return("lstart ");
624179590Speter	else
625179590Speter		return("");
626179590Speter}
627179590Speter
62830427Scharniervoid
629179590Speterport_stat(int ac, char **av)
630179590Speter{
631179590Speter	struct si_pstat sip;
632179590Speter#define	PRT	sip.tc_siport
633179590Speter
634179590Speter	if (ac != 0)
635179590Speter		prusage(U_STAT_PORT, 1);
636179590Speter	sip.tc_dev = tc.tc_dev;
637179590Speter	if (ioctl(ctlfd, TCSI_PORT, &sip) < 0)
638179590Speter		err(1, "TCSI_PORT on %s", Devname);
639179590Speter	printf("%s: ", Devname);
640179590Speter
641179590Speter	printf("\tsp_pend 0x%x %s\n", PRT.sp_pend, s_stat(PRT.sp_pend));
642179590Speter	printf("\tsp_last_hi_ip 0x%x %s\n", PRT.sp_last_hi_ip, s_ip(PRT.sp_last_hi_ip));
643179590Speter	printf("\tsp_state 0x%x %s\n", PRT.sp_state, sp_state(PRT.sp_state));
644179590Speter	printf("\tsp_delta_overflows 0x%d\n", PRT.sp_delta_overflows);
645179590Speter}
646179590Speter
64730427Scharnierint
64856520Speterislevel(char *tk)
64910045Speter{
65056520Speter	struct lv *lvp;
65156520Speter	char *acp;
65210045Speter
65310045Speter	for (acp = tk; *acp; acp++)
65410045Speter		if (isupper(*acp))
65510045Speter			*acp = tolower(*acp);
65610045Speter	for (lvp = lv; lvp->lv_name; lvp++)
65710045Speter		if (strcmp(lvp->lv_name, tk) == 0)
65810045Speter			return(lvp->lv_bit);
65910045Speter	return(0);
66010045Speter}
66110045Speter
66210045Speter/*
66310045Speter * Convert a string consisting of tokens separated by white space, commas
66410045Speter * or `|' into a bitfield - flag any unrecognised tokens.
66510045Speter */
66630427Scharnierint
66756520Speterlvls2bits(char *str)
66810045Speter{
66910045Speter	int i, bits = 0;
67010045Speter	int errflag = 0;
67110045Speter	char token[20];
67210045Speter
67310045Speter	while (sscanf(str, "%[^,| \t]", token) == 1) {
67410045Speter		str += strlen(token);
67510045Speter		while (isspace(*str) || *str==',' || *str=='|')
67610045Speter			str++;
67710045Speter		if (strcmp(token, "all") == 0)
67810045Speter			return(0xffffffff);
67910045Speter		if ((i = islevel(token)) == 0) {
68030427Scharnier			warnx("unknown token '%s'", token);
68110045Speter			errflag++;
68210045Speter		} else
68310045Speter			bits |= i;
68410045Speter	}
68510045Speter	if (errflag)
68610045Speter		exit(1);
68710045Speter
68810045Speter	return(bits);
68910045Speter}
69010045Speter
69110045Speterint
69210045Spetergetnum(char *str)
69310045Speter{
69410045Speter	int x;
69556520Speter	char *acp = str;
69610045Speter
69710045Speter	x = 0;
69810045Speter	while (*acp) {
69930427Scharnier		if (!isdigit(*acp))
70030427Scharnier			errx(1, "%s is not a number", str);
70110045Speter		x *= 10;
70210045Speter		x += (*acp - '0');
70310045Speter		acp++;
70410045Speter	}
70510045Speter	return(x);
70610045Speter}
70710045Speter
70830427Scharniervoid
70956520Speterprlevels(int x)
71010045Speter{
71110045Speter	struct lv *lvp;
71210045Speter
71310045Speter	switch (x) {
71410045Speter	case 0:
71510045Speter		printf("(none)\n");
71610045Speter		break;
71710045Speter	case 0xffffffff:
71810045Speter		printf("all\n");
71910045Speter		break;
72010045Speter	default:
72110045Speter		for (lvp = lv; lvp->lv_name; lvp++)
72210045Speter			if (x & lvp->lv_bit)
72310045Speter				printf(" %s", lvp->lv_name);
72410045Speter		printf("\n");
72510045Speter	}
72610045Speter}
727