1995-08-13 15:24:23 +00:00
|
|
|
/*
|
|
|
|
* Device driver for Specialix range (SLXOS) of serial line multiplexors.
|
|
|
|
* SLXOS configuration and debug interface
|
|
|
|
*
|
|
|
|
* Copyright (C) 1990, 1992 Specialix International,
|
|
|
|
* Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
|
2008-05-31 06:03:23 +00:00
|
|
|
* Copyright (C) 1995, Peter Wemm
|
1995-08-13 15:24:23 +00:00
|
|
|
*
|
|
|
|
* Derived from: SunOS 4.x version
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notices, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notices, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of Advanced Methods and Tools, nor Specialix
|
|
|
|
* International may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
|
|
|
* NO EVENT SHALL THE AUTHORS BE LIABLE.
|
|
|
|
*/
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
#ifndef lint
|
|
|
|
static const char rcsid[] =
|
1999-08-28 01:35:59 +00:00
|
|
|
"$FreeBSD$";
|
1997-10-15 06:43:54 +00:00
|
|
|
#endif /* not lint */
|
|
|
|
|
1995-08-13 15:24:23 +00:00
|
|
|
#include <ctype.h>
|
1997-10-15 06:43:54 +00:00
|
|
|
#include <err.h>
|
|
|
|
#include <fcntl.h>
|
2000-12-09 09:35:55 +00:00
|
|
|
#include <paths.h>
|
1997-10-15 06:43:54 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1995-08-13 15:24:23 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/tty.h>
|
|
|
|
|
2004-10-02 18:51:37 +00:00
|
|
|
#define SI_DEBUG
|
2000-01-24 08:15:42 +00:00
|
|
|
#include <dev/si/si.h>
|
2004-10-02 18:51:37 +00:00
|
|
|
#include <dev/si/sivar.h>
|
1995-08-13 15:24:23 +00:00
|
|
|
|
|
|
|
struct lv {
|
|
|
|
char *lv_name;
|
|
|
|
int lv_bit;
|
|
|
|
} lv[] = {
|
1997-10-15 06:43:54 +00:00
|
|
|
{"entry", DBG_ENTRY},
|
|
|
|
{"open", DBG_OPEN},
|
|
|
|
{"close", DBG_CLOSE},
|
|
|
|
{"read", DBG_READ},
|
|
|
|
{"write", DBG_WRITE},
|
|
|
|
{"param", DBG_PARAM},
|
|
|
|
{"modem", DBG_MODEM},
|
|
|
|
{"select", DBG_SELECT},
|
|
|
|
{"optim", DBG_OPTIM},
|
|
|
|
{"intr", DBG_INTR},
|
|
|
|
{"start", DBG_START},
|
|
|
|
{"lstart", DBG_LSTART},
|
|
|
|
{"ioctl", DBG_IOCTL},
|
|
|
|
{"fail", DBG_FAIL},
|
|
|
|
{"autoboot", DBG_AUTOBOOT},
|
|
|
|
{"download", DBG_DOWNLOAD},
|
|
|
|
{"drain", DBG_DRAIN},
|
|
|
|
{"poll", DBG_POLL},
|
|
|
|
{0, 0}
|
1995-08-13 15:24:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int alldev = 0;
|
|
|
|
|
2000-01-24 09:14:47 +00:00
|
|
|
void ccb_stat(int, char **);
|
2008-06-06 03:23:34 +00:00
|
|
|
void port_stat(int, char **);
|
2000-01-24 09:14:47 +00:00
|
|
|
void debug(int, char **);
|
|
|
|
void dostat(void);
|
|
|
|
int getnum(char *);
|
|
|
|
int islevel(char *);
|
|
|
|
int lvls2bits(char *);
|
|
|
|
void mstate(int, char **);
|
|
|
|
void nport(int, char **);
|
|
|
|
void onoff(int, char **, int, char *, char *, int);
|
|
|
|
int opencontrol(void);
|
|
|
|
void prlevels(int);
|
|
|
|
void prusage(int, int);
|
|
|
|
void rxint(int, char **);
|
|
|
|
void txint(int, char **);
|
1997-10-15 06:43:54 +00:00
|
|
|
|
1995-08-13 15:24:23 +00:00
|
|
|
struct opt {
|
|
|
|
char *o_name;
|
2000-01-24 09:14:47 +00:00
|
|
|
void (*o_func)(int, char **);
|
1995-08-13 15:24:23 +00:00
|
|
|
} opt[] = {
|
1997-10-15 06:43:54 +00:00
|
|
|
{"debug", debug},
|
|
|
|
{"rxint_throttle", rxint},
|
|
|
|
{"int_throttle", txint},
|
|
|
|
{"nport", nport},
|
|
|
|
{"mstate", mstate},
|
|
|
|
{"ccbstat", ccb_stat},
|
2008-06-06 03:23:34 +00:00
|
|
|
{"portstat", port_stat},
|
1997-10-15 06:43:54 +00:00
|
|
|
{0, 0}
|
1995-08-13 15:24:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct stat_list {
|
2000-01-24 09:14:47 +00:00
|
|
|
void (*st_func)(int, char **);
|
1995-08-13 15:24:23 +00:00
|
|
|
} stat_list[] = {
|
1997-10-15 06:43:54 +00:00
|
|
|
{mstate},
|
|
|
|
{0}
|
1995-08-13 15:24:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define U_DEBUG 0
|
|
|
|
#define U_TXINT 1
|
|
|
|
#define U_RXINT 2
|
1995-10-01 03:13:33 +00:00
|
|
|
#define U_NPORT 3
|
|
|
|
#define U_MSTATE 4
|
1995-08-13 15:24:23 +00:00
|
|
|
#define U_STAT_CCB 5
|
2008-06-06 03:23:34 +00:00
|
|
|
#define U_STAT_PORT 6
|
1995-08-13 15:24:23 +00:00
|
|
|
|
2008-06-09 08:43:27 +00:00
|
|
|
#define U_MAX 7
|
1995-08-13 15:24:23 +00:00
|
|
|
#define U_ALL -1
|
|
|
|
char *usage[] = {
|
|
|
|
"debug [[add|del|set debug_levels] | [off]]\n",
|
|
|
|
"int_throttle [newvalue]\n",
|
|
|
|
"rxint_throttle [newvalue]\n",
|
|
|
|
"nport\n",
|
1995-10-01 03:13:33 +00:00
|
|
|
"mstate\n",
|
1995-08-13 15:24:23 +00:00
|
|
|
"ccbstat\n",
|
2008-06-06 03:23:34 +00:00
|
|
|
"portstat\n",
|
1995-08-13 15:24:23 +00:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
int ctlfd;
|
|
|
|
char *Devname;
|
|
|
|
struct si_tcsi tc;
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
int
|
2000-01-24 09:14:47 +00:00
|
|
|
main(int argc, char **argv)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
struct opt *op;
|
2000-01-24 09:14:47 +00:00
|
|
|
void (*func)(int, char **) = NULL;
|
1995-08-13 15:24:23 +00:00
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
prusage(U_ALL, 1);
|
|
|
|
Devname = argv[1];
|
|
|
|
if (strcmp(Devname, "-") == 0) {
|
|
|
|
alldev = 1;
|
|
|
|
} else {
|
|
|
|
sidev_t dev;
|
2008-06-06 03:23:34 +00:00
|
|
|
int n;
|
|
|
|
int card, port;
|
|
|
|
|
|
|
|
n = sscanf(Devname, "%d:%d", &card, &port);
|
|
|
|
if (n != 2)
|
|
|
|
errx(1, "Devname must be in form card:port. eg: 0:7");
|
|
|
|
dev.sid_card = card;
|
|
|
|
dev.sid_port = port;
|
1995-08-13 15:24:23 +00:00
|
|
|
tc.tc_dev = dev;
|
|
|
|
}
|
|
|
|
ctlfd = opencontrol();
|
|
|
|
if (argc == 2) {
|
|
|
|
dostat();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
argc--; argv++;
|
|
|
|
for (op = opt; op->o_name; op++) {
|
|
|
|
if (strcmp(argv[1], op->o_name) == 0) {
|
|
|
|
func = op->o_func;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (func == NULL)
|
|
|
|
prusage(U_ALL, 1);
|
|
|
|
|
|
|
|
argc -= 2;
|
|
|
|
argv += 2;
|
|
|
|
(*func)(argc, argv);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
int
|
2000-01-24 09:14:47 +00:00
|
|
|
opencontrol(void)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
|
1997-10-15 06:43:54 +00:00
|
|
|
if (fd < 0)
|
|
|
|
err(1, "open on %s", CONTROLDEV);
|
1995-08-13 15:24:23 +00:00
|
|
|
return(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
|
|
|
|
* Don't print the DEBUG usage string unless explicity requested.
|
|
|
|
*/
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
prusage(int strn, int eflag)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
char **cp;
|
|
|
|
|
|
|
|
if (strn == U_ALL) {
|
1997-10-15 06:43:54 +00:00
|
|
|
fprintf(stderr, "usage: sicontrol %s", usage[1]);
|
|
|
|
fprintf(stderr, " sicontrol %s", usage[2]);
|
|
|
|
fprintf(stderr, " sicontrol %s", usage[3]);
|
1995-10-01 03:13:33 +00:00
|
|
|
fprintf(stderr, " sicontrol devname %s", usage[4]);
|
|
|
|
for (cp = &usage[5]; *cp; cp++)
|
|
|
|
fprintf(stderr, " sicontrol devname %s", *cp);
|
1995-08-13 15:24:23 +00:00
|
|
|
}
|
|
|
|
else if (strn >= 0 && strn <= U_MAX)
|
1997-10-15 06:43:54 +00:00
|
|
|
fprintf(stderr, "usage: sicontrol devname %s", usage[strn]);
|
1995-08-13 15:24:23 +00:00
|
|
|
else
|
1995-08-14 01:56:17 +00:00
|
|
|
fprintf(stderr, "sicontrol: usage ???\n");
|
1995-08-13 15:24:23 +00:00
|
|
|
exit(eflag);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print port status */
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
dostat(void)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
char *av[1], *acp;
|
|
|
|
struct stat_list *stp;
|
|
|
|
struct si_tcsi stc;
|
|
|
|
int donefirst = 0;
|
|
|
|
|
|
|
|
printf("%s: ", alldev ? "ALL" : Devname);
|
|
|
|
acp = malloc(strlen(Devname) + 3);
|
|
|
|
memset(acp, ' ', strlen(Devname));
|
|
|
|
strcat(acp, " ");
|
|
|
|
stc = tc;
|
|
|
|
for (stp = stat_list; stp->st_func != NULL; stp++) {
|
|
|
|
if (donefirst)
|
|
|
|
fputs(acp, stdout);
|
|
|
|
else
|
|
|
|
donefirst++;
|
|
|
|
av[0] = NULL;
|
|
|
|
tc = stc;
|
|
|
|
(*stp->st_func)(-1, av);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* debug
|
|
|
|
* debug [[set|add|del debug_lvls] | [off]]
|
|
|
|
*/
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
debug(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
1997-10-15 06:43:54 +00:00
|
|
|
int level;
|
1995-08-13 15:24:23 +00:00
|
|
|
|
|
|
|
if (ac > 2)
|
|
|
|
prusage(U_DEBUG, 1);
|
|
|
|
if (alldev) {
|
|
|
|
if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIGDBG_ALL on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
} else {
|
|
|
|
if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIGDBG_LEVEL on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (ac) {
|
|
|
|
case 0:
|
|
|
|
printf("%s: debug levels - ", Devname);
|
|
|
|
prlevels(tc.tc_dbglvl);
|
|
|
|
return;
|
|
|
|
case 1:
|
|
|
|
if (strcmp(av[0], "off") == 0) {
|
|
|
|
tc.tc_dbglvl = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
prusage(U_DEBUG, 1);
|
|
|
|
/* no return */
|
|
|
|
case 2:
|
|
|
|
level = lvls2bits(av[1]);
|
|
|
|
if (strcmp(av[0], "add") == 0)
|
|
|
|
tc.tc_dbglvl |= level;
|
|
|
|
else if (strcmp(av[0], "del") == 0)
|
|
|
|
tc.tc_dbglvl &= ~level;
|
|
|
|
else if (strcmp(av[0], "set") == 0)
|
|
|
|
tc.tc_dbglvl = level;
|
|
|
|
else
|
|
|
|
prusage(U_DEBUG, 1);
|
|
|
|
}
|
|
|
|
if (alldev) {
|
|
|
|
if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSISDBG_ALL on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
} else {
|
|
|
|
if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSISDBG_LEVEL on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
rxint(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
tc.tc_port = 0;
|
|
|
|
switch (ac) {
|
|
|
|
case 0:
|
|
|
|
printf("%s: ", Devname);
|
|
|
|
case -1:
|
|
|
|
if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIGRXIT");
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
tc.tc_int = getnum(av[0]) / 10;
|
|
|
|
if (tc.tc_int == 0)
|
|
|
|
tc.tc_int = 1;
|
|
|
|
if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIRXIT on %s at %d msec",
|
|
|
|
Devname, tc.tc_int*10);
|
1995-08-13 15:24:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
prusage(U_RXINT, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
txint(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
tc.tc_port = 0;
|
|
|
|
switch (ac) {
|
|
|
|
case 0:
|
|
|
|
printf("%s: ", Devname);
|
|
|
|
case -1:
|
|
|
|
if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIGIT");
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("aggregate interrupt throttle: %d\n", tc.tc_int);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
tc.tc_int = getnum(av[0]);
|
|
|
|
if (ioctl(ctlfd, TCSIIT, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIIT on %s at %d", Devname, tc.tc_int);
|
1995-08-13 15:24:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
prusage(U_TXINT, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
onoff(int ac, char **av, int cmd, char *cmdstr, char *prstr, int usage)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
if (ac > 1)
|
|
|
|
prusage(usage, 1);
|
|
|
|
if (ac == 1) {
|
|
|
|
if (strcmp(av[0], "on") == 0)
|
|
|
|
tc.tc_int = 1;
|
|
|
|
else if (strcmp(av[0], "off") == 0)
|
|
|
|
tc.tc_int = 0;
|
|
|
|
else
|
|
|
|
prusage(usage, 1);
|
|
|
|
} else
|
|
|
|
tc.tc_int = -1;
|
|
|
|
if (ioctl(ctlfd, cmd, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "%s on %s", cmdstr, Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
switch (ac) {
|
|
|
|
case 0:
|
|
|
|
printf("%s: ", Devname);
|
|
|
|
case -1:
|
|
|
|
printf("%s ", prstr);
|
|
|
|
if (tc.tc_int)
|
|
|
|
printf("on\n");
|
|
|
|
else
|
|
|
|
printf("off\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
mstate(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
switch (ac) {
|
|
|
|
case 0:
|
|
|
|
printf("%s: ", Devname);
|
|
|
|
case -1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
prusage(U_MSTATE, 1);
|
|
|
|
}
|
|
|
|
if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSISTATE on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("modem bits state - (0x%x)", tc.tc_int);
|
|
|
|
if (tc.tc_int & IP_DCD) printf(" DCD");
|
|
|
|
if (tc.tc_int & IP_DTR) printf(" DTR");
|
|
|
|
if (tc.tc_int & IP_RTS) printf(" RTS");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
nport(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
int ports;
|
|
|
|
|
|
|
|
if (ac != 0)
|
|
|
|
prusage(U_NPORT, 1);
|
|
|
|
if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSIPORTS on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("SLXOS: total of %d ports\n", ports);
|
|
|
|
}
|
|
|
|
|
2008-06-06 03:23:34 +00:00
|
|
|
const char *s_stat(int stat)
|
|
|
|
{
|
|
|
|
switch (stat) {
|
|
|
|
case IDLE_OPEN: return "IDLE_OPEN";
|
|
|
|
case LOPEN: return "LOPEN";
|
|
|
|
case MOPEN: return "MOPEN";
|
|
|
|
case MPEND: return "MPEND";
|
|
|
|
case CONFIG: return "CONFIG";
|
|
|
|
case CLOSE: return "CLOSE";
|
|
|
|
case SBREAK: return "SBREAK";
|
|
|
|
case EBREAK: return "EBREAK";
|
|
|
|
case IDLE_CLOSE:return "IDLE_CLOSE";
|
|
|
|
case IDLE_BREAK:return "IDLE_BREAK";
|
|
|
|
case FCLOSE: return "FCLOSE";
|
|
|
|
case RESUME: return "RESUME";
|
|
|
|
case WFLUSH: return "WFLUSH";
|
|
|
|
case RFLUSH: return "RFLUSH";
|
|
|
|
default: return "??";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const char *s_mr1(int mr1)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
sprintf(msg, "%dbit, %s, parity:[", 5 + (mr1 & MR1_8_BITS), mr1 & MR1_ODD ? "odd" : "even");
|
|
|
|
if (mr1 & MR1_WITH)
|
|
|
|
strcat(msg, "with;");
|
|
|
|
if (mr1 & MR1_FORCE)
|
|
|
|
strcat(msg, "force;");
|
|
|
|
if (mr1 & MR1_NONE)
|
|
|
|
strcat(msg, "none;");
|
|
|
|
if (mr1 & MR1_SPECIAL)
|
|
|
|
strcat(msg, "special;");
|
|
|
|
strcpy(msg + strlen(msg) - 1, "]");
|
|
|
|
sprintf(msg + strlen(msg), ", err: %s", mr1 & MR1_BLOCK ? "block" : "none");
|
|
|
|
sprintf(msg + strlen(msg), ", cts: %s", mr1 & MR1_CTSCONT ? "auto" : "none");
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
const char *s_mr2(int mr2)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
switch (mr2 & 0xf) {
|
|
|
|
case MR2_1_STOP: strcpy(msg, "1stop"); break;
|
|
|
|
case MR2_2_STOP: strcpy(msg, "2stop"); break;
|
|
|
|
default: sprintf(msg, "??stop (0x%x)", mr2 & 0xf); break;
|
|
|
|
}
|
|
|
|
if (mr2 & MR2_RTSCONT) strcat(msg, ", rtscont");
|
|
|
|
if (mr2 & MR2_CTSCONT) strcat(msg, ", ctscont");
|
|
|
|
switch (mr2 & 0xc0) {
|
|
|
|
case MR2_NORMAL: strcat(msg, ", mode:normal"); break;
|
|
|
|
case MR2_AUTO: strcat(msg, ", mode:auto"); break;
|
|
|
|
case MR2_LOCAL: strcat(msg, ", mode:local"); break;
|
|
|
|
case MR2_REMOTE: strcat(msg, ", mode:remote"); break;
|
|
|
|
}
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
const char *s_clk(int clk)
|
|
|
|
{
|
|
|
|
switch (clk & 0xf) {
|
|
|
|
case 0x0: return "75";
|
|
|
|
case 0x1: return "110/115200";
|
|
|
|
case 0x2: return "38400";
|
|
|
|
case 0x3: return "150";
|
|
|
|
case 0x4: return "300";
|
|
|
|
case 0x5: return "600";
|
|
|
|
case 0x6: return "1200";
|
|
|
|
case 0x7: return "2000";
|
|
|
|
case 0x8: return "2400";
|
|
|
|
case 0x9: return "4800";
|
|
|
|
case 0xa: return "7200";
|
|
|
|
case 0xb: return "9600";
|
|
|
|
case 0xc: return "19200";
|
|
|
|
case 0xd: return "57600";
|
|
|
|
case 0xe: return "?0xe";
|
|
|
|
case 0xf: return "?0xf";
|
|
|
|
}
|
|
|
|
return ("gcc sucks");
|
|
|
|
}
|
|
|
|
const char *s_op(int op)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
sprintf(msg, "cts:%s", (op & OP_CTS) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", dsr:%s", (op & OP_DSR) ? "on" : "off");
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *s_ip(int ip)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
sprintf(msg, "rts:%s", (ip & IP_RTS) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", dcd:%s", (ip & IP_DCD) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", dtr:%s", (ip & IP_DTR) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", ri:%s", (ip & IP_RI) ? "on" : "off");
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *s_state(int state)
|
|
|
|
{
|
|
|
|
return (state & ST_BREAK ? "break:on" : "break:off");
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *s_prtcl(int pr)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
sprintf(msg, "tx xon any:%s", (pr & SP_TANY) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", tx xon/xoff:%s", (pr & SP_TXEN) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", cooking:%s", (pr & SP_CEN) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", rx xon/xoff:%s", (pr & SP_RXEN) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", dcd/dsr check:%s", (pr & SP_DCEN) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", parity check:%s", (pr & SP_PAEN) ? "on" : "off");
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
const char *s_break(int br)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
sprintf(msg, "ignore rx brk:%s", (br & BR_IGN) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", brk interrupt:%s", (br & BR_INT) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", parmrking:%s", (br & BR_PARMRK) ? "on" : "off");
|
|
|
|
sprintf(msg + strlen(msg), ", parign:%s", (br & BR_PARIGN) ? "on" : "off");
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
s_xstat(int xs)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
msg[0] = 0;
|
|
|
|
/* MTA definitions, not TA */
|
|
|
|
if (xs & 0x01) strcat(msg, "TION "); /* Tx interrupts on (MTA only) */
|
|
|
|
if (xs & 0x02) strcat(msg, "RTSEN "); /* RTS FLOW enabled (MTA only) */
|
|
|
|
if (xs & 0x04) strcat(msg, "RTSLOW "); /* XOFF received (TA only) */
|
|
|
|
if (xs & 0x08) strcat(msg, "RXEN "); /* Rx XON/XOFF enabled */
|
|
|
|
if (xs & 0x10) strcat(msg, "ANYXO "); /* XOFF pending/sent or RTS dropped */
|
|
|
|
if (xs & 0x20) strcat(msg, "RXSE "); /* Rx XOFF sent */
|
|
|
|
if (xs & 0x40) strcat(msg, "NPEND "); /* Rx XON pending or XOFF pending */
|
|
|
|
if (xs & 0x40) strcat(msg, "FPEND "); /* Rx XOFF pending */
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
s_cstat(int cs)
|
|
|
|
{
|
|
|
|
static char msg[200];
|
|
|
|
|
|
|
|
msg[0] = 0;
|
|
|
|
/* MTA definitions, not TA */
|
|
|
|
if (cs & 0x01) strcat(msg, "TEMR "); /* Tx empty requested (MTA only) */
|
|
|
|
if (cs & 0x02) strcat(msg, "TEMA "); /* Tx empty acked (MTA only) */
|
|
|
|
if (cs & 0x04) strcat(msg, "EN "); /* Cooking enabled (on MTA means port is also || */
|
|
|
|
if (cs & 0x08) strcat(msg, "HIGH "); /* Buffer previously hit high water */
|
|
|
|
if (cs & 0x10) strcat(msg, "CTSEN "); /* CTS automatic flow-control enabled */
|
|
|
|
if (cs & 0x20) strcat(msg, "DCDEN "); /* DCD/DTR checking enabled */
|
|
|
|
if (cs & 0x40) strcat(msg, "BREAK "); /* Break detected */
|
|
|
|
if (cs & 0x80) strcat(msg, "RTSEN "); /* RTS automatic flow control enabled (MTA only) */
|
|
|
|
return (msg);
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
ccb_stat(int ac, char **av)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
struct si_pstat sip;
|
|
|
|
#define CCB sip.tc_ccb
|
|
|
|
|
|
|
|
if (ac != 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
prusage(U_STAT_CCB, 1);
|
1995-08-13 15:24:23 +00:00
|
|
|
sip.tc_dev = tc.tc_dev;
|
|
|
|
if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
|
1997-10-15 06:43:54 +00:00
|
|
|
err(1, "TCSI_CCB on %s", Devname);
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("%s: ", Devname);
|
|
|
|
|
|
|
|
/* WORD next - Next Channel */
|
|
|
|
/* WORD addr_uart - Uart address */
|
|
|
|
/* WORD module - address of module struct */
|
|
|
|
printf("\tuart_type 0x%x\n", CCB.type); /* BYTE type - Uart type */
|
|
|
|
/* BYTE fill - */
|
2008-06-06 03:23:34 +00:00
|
|
|
printf("\tx_status 0x%x %s\n", CCB.x_status, s_xstat(CCB.x_status)); /* BYTE x_status - XON / XOFF status */
|
|
|
|
printf("\tc_status 0x%x %s\n", CCB.c_status, s_cstat(CCB.c_status)); /* BYTE c_status - cooking status */
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos); /* BYTE hi_rxipos - stuff into rx buff */
|
|
|
|
printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos); /* BYTE hi_rxopos - stuff out of rx buffer */
|
|
|
|
printf("\thi_txopos 0x%x\n", CCB.hi_txopos); /* BYTE hi_txopos - Stuff into tx ptr */
|
|
|
|
printf("\thi_txipos 0x%x\n", CCB.hi_txipos); /* BYTE hi_txipos - ditto out */
|
2008-06-06 03:23:34 +00:00
|
|
|
printf("\thi_stat 0x%x %s\n", CCB.hi_stat, s_stat(CCB.hi_stat));/* BYTE hi_stat - Command register */
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("\tdsr_bit 0x%x\n", CCB.dsr_bit); /* BYTE dsr_bit - Magic bit for DSR */
|
|
|
|
printf("\ttxon 0x%x\n", CCB.txon); /* BYTE txon - TX XON char */
|
|
|
|
printf("\ttxoff 0x%x\n", CCB.txoff); /* BYTE txoff - ditto XOFF */
|
|
|
|
printf("\trxon 0x%x\n", CCB.rxon); /* BYTE rxon - RX XON char */
|
|
|
|
printf("\trxoff 0x%x\n", CCB.rxoff); /* BYTE rxoff - ditto XOFF */
|
2008-06-06 03:23:34 +00:00
|
|
|
printf("\thi_mr1 0x%x %s\n", CCB.hi_mr1, s_mr1(CCB.hi_mr1)); /* BYTE hi_mr1 - mode 1 image */
|
|
|
|
printf("\thi_mr2 0x%x %s\n", CCB.hi_mr2, s_mr2(CCB.hi_mr2)); /* BYTE hi_mr2 - mode 2 image */
|
|
|
|
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 */
|
|
|
|
printf("\thi_op 0x%x %s\n", CCB.hi_op, s_op(CCB.hi_op)); /* BYTE hi_op - Op control */
|
|
|
|
printf("\thi_ip 0x%x %s\n", CCB.hi_ip, s_ip(CCB.hi_ip)); /* BYTE hi_ip - Input pins */
|
|
|
|
printf("\thi_state 0x%x %s\n", CCB.hi_state, s_state(CCB.hi_state)); /* BYTE hi_state - status */
|
|
|
|
printf("\thi_prtcl 0x%x %s\n", CCB.hi_prtcl, s_prtcl(CCB.hi_prtcl)); /* BYTE hi_prtcl - Protocol */
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("\thi_txon 0x%x\n", CCB.hi_txon); /* BYTE hi_txon - host copy tx xon stuff */
|
|
|
|
printf("\thi_txoff 0x%x\n", CCB.hi_txoff); /* BYTE hi_txoff - */
|
|
|
|
printf("\thi_rxon 0x%x\n", CCB.hi_rxon); /* BYTE hi_rxon - */
|
|
|
|
printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff); /* BYTE hi_rxoff - */
|
|
|
|
printf("\tclose_prev 0x%x\n", CCB.close_prev); /* BYTE close_prev - Was channel previously closed */
|
2008-06-06 03:23:34 +00:00
|
|
|
printf("\thi_break 0x%x %s\n", CCB.hi_break, s_break(CCB.hi_break)); /* BYTE hi_break - host copy break process */
|
1995-08-13 15:24:23 +00:00
|
|
|
printf("\tbreak_state 0x%x\n", CCB.break_state); /* BYTE break_state - local copy ditto */
|
|
|
|
printf("\thi_mask 0x%x\n", CCB.hi_mask); /* BYTE hi_mask - Mask for CS7 etc. */
|
|
|
|
printf("\tmask_z280 0x%x\n", CCB.mask_z280); /* BYTE mask_z280 - Z280's copy */
|
|
|
|
/* BYTE res[0x60 - 36] - */
|
|
|
|
/* BYTE hi_txbuf[SLXOS_BUFFERSIZE] - */
|
|
|
|
/* BYTE hi_rxbuf[SLXOS_BUFFERSIZE] - */
|
|
|
|
/* BYTE res1[0xA0] - */
|
|
|
|
}
|
|
|
|
|
2008-06-06 03:23:34 +00:00
|
|
|
const char *sp_state(int st)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (st & SS_LSTART)
|
|
|
|
return("lstart ");
|
|
|
|
else
|
|
|
|
return("");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
port_stat(int ac, char **av)
|
|
|
|
{
|
|
|
|
struct si_pstat sip;
|
|
|
|
#define PRT sip.tc_siport
|
|
|
|
|
|
|
|
if (ac != 0)
|
|
|
|
prusage(U_STAT_PORT, 1);
|
|
|
|
sip.tc_dev = tc.tc_dev;
|
|
|
|
if (ioctl(ctlfd, TCSI_PORT, &sip) < 0)
|
|
|
|
err(1, "TCSI_PORT on %s", Devname);
|
|
|
|
printf("%s: ", Devname);
|
|
|
|
|
|
|
|
printf("\tsp_pend 0x%x %s\n", PRT.sp_pend, s_stat(PRT.sp_pend));
|
|
|
|
printf("\tsp_last_hi_ip 0x%x %s\n", PRT.sp_last_hi_ip, s_ip(PRT.sp_last_hi_ip));
|
|
|
|
printf("\tsp_state 0x%x %s\n", PRT.sp_state, sp_state(PRT.sp_state));
|
|
|
|
printf("\tsp_delta_overflows 0x%d\n", PRT.sp_delta_overflows);
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
int
|
2000-01-24 09:14:47 +00:00
|
|
|
islevel(char *tk)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
2000-01-24 09:14:47 +00:00
|
|
|
struct lv *lvp;
|
|
|
|
char *acp;
|
1995-08-13 15:24:23 +00:00
|
|
|
|
|
|
|
for (acp = tk; *acp; acp++)
|
|
|
|
if (isupper(*acp))
|
|
|
|
*acp = tolower(*acp);
|
|
|
|
for (lvp = lv; lvp->lv_name; lvp++)
|
|
|
|
if (strcmp(lvp->lv_name, tk) == 0)
|
|
|
|
return(lvp->lv_bit);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a string consisting of tokens separated by white space, commas
|
|
|
|
* or `|' into a bitfield - flag any unrecognised tokens.
|
|
|
|
*/
|
1997-10-15 06:43:54 +00:00
|
|
|
int
|
2000-01-24 09:14:47 +00:00
|
|
|
lvls2bits(char *str)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
int i, bits = 0;
|
|
|
|
int errflag = 0;
|
|
|
|
char token[20];
|
|
|
|
|
|
|
|
while (sscanf(str, "%[^,| \t]", token) == 1) {
|
|
|
|
str += strlen(token);
|
|
|
|
while (isspace(*str) || *str==',' || *str=='|')
|
|
|
|
str++;
|
|
|
|
if (strcmp(token, "all") == 0)
|
|
|
|
return(0xffffffff);
|
|
|
|
if ((i = islevel(token)) == 0) {
|
1997-10-15 06:43:54 +00:00
|
|
|
warnx("unknown token '%s'", token);
|
1995-08-13 15:24:23 +00:00
|
|
|
errflag++;
|
|
|
|
} else
|
|
|
|
bits |= i;
|
|
|
|
}
|
|
|
|
if (errflag)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
return(bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
getnum(char *str)
|
|
|
|
{
|
|
|
|
int x;
|
2000-01-24 09:14:47 +00:00
|
|
|
char *acp = str;
|
1995-08-13 15:24:23 +00:00
|
|
|
|
|
|
|
x = 0;
|
|
|
|
while (*acp) {
|
1997-10-15 06:43:54 +00:00
|
|
|
if (!isdigit(*acp))
|
|
|
|
errx(1, "%s is not a number", str);
|
1995-08-13 15:24:23 +00:00
|
|
|
x *= 10;
|
|
|
|
x += (*acp - '0');
|
|
|
|
acp++;
|
|
|
|
}
|
|
|
|
return(x);
|
|
|
|
}
|
|
|
|
|
1997-10-15 06:43:54 +00:00
|
|
|
void
|
2000-01-24 09:14:47 +00:00
|
|
|
prlevels(int x)
|
1995-08-13 15:24:23 +00:00
|
|
|
{
|
|
|
|
struct lv *lvp;
|
|
|
|
|
|
|
|
switch (x) {
|
|
|
|
case 0:
|
|
|
|
printf("(none)\n");
|
|
|
|
break;
|
|
|
|
case 0xffffffff:
|
|
|
|
printf("all\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for (lvp = lv; lvp->lv_name; lvp++)
|
|
|
|
if (x & lvp->lv_bit)
|
|
|
|
printf(" %s", lvp->lv_name);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|