1 /*
2 * Device driver for Specialix range (SLXOS) of serial line multiplexors.
3 * SLXOS configuration and debug interface
4 *
5 * Copyright (C) 1990, 1992 Specialix International,
6 * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
7 * Copyright (C) 1995, Peter Wemm
8 *
9 * Derived from: SunOS 4.x version
10 *
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 * 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.
22 *
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.
27 */
28
29 #ifndef lint
30 static const char rcsid[] =
31 "$FreeBSD$";
32 #endif /* not lint */
33
34 #include <ctype.h>
35 #include <err.h>
36 #include <fcntl.h>
37 #include <paths.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/stat.h>
44 #include <sys/ioctl.h>
45 #include <sys/tty.h>
46
47 #define SI_DEBUG
48 #include <dev/si/si.h>
49 #include <dev/si/sivar.h>
50
51 struct lv {
52 char *lv_name;
53 int lv_bit;
54 } lv[] = {
55 {"entry", DBG_ENTRY},
56 {"open", DBG_OPEN},
57 {"close", DBG_CLOSE},
58 {"read", DBG_READ},
59 {"write", DBG_WRITE},
60 {"param", DBG_PARAM},
61 {"modem", DBG_MODEM},
62 {"select", DBG_SELECT},
63 {"optim", DBG_OPTIM},
64 {"intr", DBG_INTR},
65 {"start", DBG_START},
66 {"lstart", DBG_LSTART},
67 {"ioctl", DBG_IOCTL},
68 {"fail", DBG_FAIL},
69 {"autoboot", DBG_AUTOBOOT},
70 {"download", DBG_DOWNLOAD},
71 {"drain", DBG_DRAIN},
72 {"poll", DBG_POLL},
73 {0, 0}
74 };
75
76 static int alldev = 0;
77
78 void ccb_stat(int, char **);
79 void port_stat(int, char **);
80 void debug(int, char **);
81 void dostat(void);
82 int getnum(char *);
83 int islevel(char *);
84 int lvls2bits(char *);
85 void mstate(int, char **);
86 void nport(int, char **);
87 void onoff(int, char **, int, char *, char *, int);
88 int opencontrol(void);
89 void prlevels(int);
90 void prusage(int, int);
91 void rxint(int, char **);
92 void txint(int, char **);
93
94 struct opt {
95 char *o_name;
96 void (*o_func)(int, char **);
97 } opt[] = {
98 {"debug", debug},
99 {"rxint_throttle", rxint},
100 {"int_throttle", txint},
101 {"nport", nport},
102 {"mstate", mstate},
103 {"ccbstat", ccb_stat},
104 {"portstat", port_stat},
105 {0, 0}
106 };
107
108 struct stat_list {
109 void (*st_func)(int, char **);
110 } stat_list[] = {
111 {mstate},
112 {0}
113 };
114
115 #define U_DEBUG 0
116 #define U_TXINT 1
117 #define U_RXINT 2
118 #define U_NPORT 3
119 #define U_MSTATE 4
120 #define U_STAT_CCB 5
121 #define U_STAT_PORT 6
122
123 #define U_MAX 7
124 #define U_ALL -1
125 char *usage[] = {
126 "debug [[add|del|set debug_levels] | [off]]\n",
127 "int_throttle [newvalue]\n",
128 "rxint_throttle [newvalue]\n",
129 "nport\n",
130 "mstate\n",
131 "ccbstat\n",
132 "portstat\n",
133 0
134 };
135
136 int ctlfd;
137 char *Devname;
138 struct si_tcsi tc;
139
140 int
main(int argc,char ** argv)141 main(int argc, char **argv)
142 {
143 struct opt *op;
144 void (*func)(int, char **) = NULL;
145
146 if (argc < 2)
147 prusage(U_ALL, 1);
148 Devname = argv[1];
149 if (strcmp(Devname, "-") == 0) {
150 alldev = 1;
151 } else {
152 sidev_t dev;
153 int n;
154 int card, port;
155
156 n = sscanf(Devname, "%d:%d", &card, &port);
157 if (n != 2)
158 errx(1, "Devname must be in form card:port. eg: 0:7");
159 dev.sid_card = card;
160 dev.sid_port = port;
161 tc.tc_dev = dev;
162 }
163 ctlfd = opencontrol();
164 if (argc == 2) {
165 dostat();
166 exit(0);
167 }
168
169 argc--; argv++;
170 for (op = opt; op->o_name; op++) {
171 if (strcmp(argv[1], op->o_name) == 0) {
172 func = op->o_func;
173 break;
174 }
175 }
176 if (func == NULL)
177 prusage(U_ALL, 1);
178
179 argc -= 2;
180 argv += 2;
181 (*func)(argc, argv);
182 exit(0);
183 }
184
185 int
opencontrol(void)186 opencontrol(void)
187 {
188 int fd;
189
190 fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
191 if (fd < 0)
192 err(1, "open on %s", CONTROLDEV);
193 return(fd);
194 }
195
196 /*
197 * Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
198 * Don't print the DEBUG usage string unless explicity requested.
199 */
200 void
prusage(int strn,int eflag)201 prusage(int strn, int eflag)
202 {
203 char **cp;
204
205 if (strn == U_ALL) {
206 fprintf(stderr, "usage: sicontrol %s", usage[1]);
207 fprintf(stderr, " sicontrol %s", usage[2]);
208 fprintf(stderr, " sicontrol %s", usage[3]);
209 fprintf(stderr, " sicontrol devname %s", usage[4]);
210 for (cp = &usage[5]; *cp; cp++)
211 fprintf(stderr, " sicontrol devname %s", *cp);
212 }
213 else if (strn >= 0 && strn <= U_MAX)
214 fprintf(stderr, "usage: sicontrol devname %s", usage[strn]);
215 else
216 fprintf(stderr, "sicontrol: usage ???\n");
217 exit(eflag);
218 }
219
220 /* print port status */
221 void
dostat(void)222 dostat(void)
223 {
224 char *av[1], *acp;
225 struct stat_list *stp;
226 struct si_tcsi stc;
227 int donefirst = 0;
228
229 printf("%s: ", alldev ? "ALL" : Devname);
230 acp = malloc(strlen(Devname) + 3);
231 memset(acp, ' ', strlen(Devname));
232 strcat(acp, " ");
233 stc = tc;
234 for (stp = stat_list; stp->st_func != NULL; stp++) {
235 if (donefirst)
236 fputs(acp, stdout);
237 else
238 donefirst++;
239 av[0] = NULL;
240 tc = stc;
241 (*stp->st_func)(-1, av);
242 }
243 }
244
245 /*
246 * debug
247 * debug [[set|add|del debug_lvls] | [off]]
248 */
249 void
debug(int ac,char ** av)250 debug(int ac, char **av)
251 {
252 int level;
253
254 if (ac > 2)
255 prusage(U_DEBUG, 1);
256 if (alldev) {
257 if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
258 err(1, "TCSIGDBG_ALL on %s", Devname);
259 } else {
260 if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
261 err(1, "TCSIGDBG_LEVEL on %s", Devname);
262 }
263
264 switch (ac) {
265 case 0:
266 printf("%s: debug levels - ", Devname);
267 prlevels(tc.tc_dbglvl);
268 return;
269 case 1:
270 if (strcmp(av[0], "off") == 0) {
271 tc.tc_dbglvl = 0;
272 break;
273 }
274 prusage(U_DEBUG, 1);
275 /* no return */
276 case 2:
277 level = lvls2bits(av[1]);
278 if (strcmp(av[0], "add") == 0)
279 tc.tc_dbglvl |= level;
280 else if (strcmp(av[0], "del") == 0)
281 tc.tc_dbglvl &= ~level;
282 else if (strcmp(av[0], "set") == 0)
283 tc.tc_dbglvl = level;
284 else
285 prusage(U_DEBUG, 1);
286 }
287 if (alldev) {
288 if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
289 err(1, "TCSISDBG_ALL on %s", Devname);
290 } else {
291 if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
292 err(1, "TCSISDBG_LEVEL on %s", Devname);
293 }
294 }
295
296 void
rxint(int ac,char ** av)297 rxint(int ac, char **av)
298 {
299 tc.tc_port = 0;
300 switch (ac) {
301 case 0:
302 printf("%s: ", Devname);
303 case -1:
304 if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
305 err(1, "TCSIGRXIT");
306 printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
307 break;
308 case 1:
309 tc.tc_int = getnum(av[0]) / 10;
310 if (tc.tc_int == 0)
311 tc.tc_int = 1;
312 if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
313 err(1, "TCSIRXIT on %s at %d msec",
314 Devname, tc.tc_int*10);
315 break;
316 default:
317 prusage(U_RXINT, 1);
318 }
319 }
320
321 void
txint(int ac,char ** av)322 txint(int ac, char **av)
323 {
324
325 tc.tc_port = 0;
326 switch (ac) {
327 case 0:
328 printf("%s: ", Devname);
329 case -1:
330 if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
331 err(1, "TCSIGIT");
332 printf("aggregate interrupt throttle: %d\n", tc.tc_int);
333 break;
334 case 1:
335 tc.tc_int = getnum(av[0]);
336 if (ioctl(ctlfd, TCSIIT, &tc) < 0)
337 err(1, "TCSIIT on %s at %d", Devname, tc.tc_int);
338 break;
339 default:
340 prusage(U_TXINT, 1);
341 }
342 }
343
344 void
onoff(int ac,char ** av,int cmd,char * cmdstr,char * prstr,int usage)345 onoff(int ac, char **av, int cmd, char *cmdstr, char *prstr, int usage)
346 {
347 if (ac > 1)
348 prusage(usage, 1);
349 if (ac == 1) {
350 if (strcmp(av[0], "on") == 0)
351 tc.tc_int = 1;
352 else if (strcmp(av[0], "off") == 0)
353 tc.tc_int = 0;
354 else
355 prusage(usage, 1);
356 } else
357 tc.tc_int = -1;
358 if (ioctl(ctlfd, cmd, &tc) < 0)
359 err(1, "%s on %s", cmdstr, Devname);
360 switch (ac) {
361 case 0:
362 printf("%s: ", Devname);
363 case -1:
364 printf("%s ", prstr);
365 if (tc.tc_int)
366 printf("on\n");
367 else
368 printf("off\n");
369 }
370 }
371
372 void
mstate(int ac,char ** av)373 mstate(int ac, char **av)
374 {
375 switch (ac) {
376 case 0:
377 printf("%s: ", Devname);
378 case -1:
379 break;
380 default:
381 prusage(U_MSTATE, 1);
382 }
383 if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
384 err(1, "TCSISTATE on %s", Devname);
385 printf("modem bits state - (0x%x)", tc.tc_int);
386 if (tc.tc_int & IP_DCD) printf(" DCD");
387 if (tc.tc_int & IP_DTR) printf(" DTR");
388 if (tc.tc_int & IP_RTS) printf(" RTS");
389 printf("\n");
390 }
391
392 void
nport(int ac,char ** av)393 nport(int ac, char **av)
394 {
395 int ports;
396
397 if (ac != 0)
398 prusage(U_NPORT, 1);
399 if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
400 err(1, "TCSIPORTS on %s", Devname);
401 printf("SLXOS: total of %d ports\n", ports);
402 }
403
s_stat(int stat)404 const char *s_stat(int stat)
405 {
406 switch (stat) {
407 case IDLE_OPEN: return "IDLE_OPEN";
408 case LOPEN: return "LOPEN";
409 case MOPEN: return "MOPEN";
410 case MPEND: return "MPEND";
411 case CONFIG: return "CONFIG";
412 case CLOSE: return "CLOSE";
413 case SBREAK: return "SBREAK";
414 case EBREAK: return "EBREAK";
415 case IDLE_CLOSE:return "IDLE_CLOSE";
416 case IDLE_BREAK:return "IDLE_BREAK";
417 case FCLOSE: return "FCLOSE";
418 case RESUME: return "RESUME";
419 case WFLUSH: return "WFLUSH";
420 case RFLUSH: return "RFLUSH";
421 default: return "??";
422 }
423 }
s_mr1(int mr1)424 const char *s_mr1(int mr1)
425 {
426 static char msg[200];
427
428 sprintf(msg, "%dbit, %s, parity:[", 5 + (mr1 & MR1_8_BITS), mr1 & MR1_ODD ? "odd" : "even");
429 if (mr1 & MR1_WITH)
430 strcat(msg, "with;");
431 if (mr1 & MR1_FORCE)
432 strcat(msg, "force;");
433 if (mr1 & MR1_NONE)
434 strcat(msg, "none;");
435 if (mr1 & MR1_SPECIAL)
436 strcat(msg, "special;");
437 strcpy(msg + strlen(msg) - 1, "]");
438 sprintf(msg + strlen(msg), ", err: %s", mr1 & MR1_BLOCK ? "block" : "none");
439 sprintf(msg + strlen(msg), ", cts: %s", mr1 & MR1_CTSCONT ? "auto" : "none");
440 return (msg);
441 }
s_mr2(int mr2)442 const char *s_mr2(int mr2)
443 {
444 static char msg[200];
445
446 switch (mr2 & 0xf) {
447 case MR2_1_STOP: strcpy(msg, "1stop"); break;
448 case MR2_2_STOP: strcpy(msg, "2stop"); break;
449 default: sprintf(msg, "??stop (0x%x)", mr2 & 0xf); break;
450 }
451 if (mr2 & MR2_RTSCONT) strcat(msg, ", rtscont");
452 if (mr2 & MR2_CTSCONT) strcat(msg, ", ctscont");
453 switch (mr2 & 0xc0) {
454 case MR2_NORMAL: strcat(msg, ", mode:normal"); break;
455 case MR2_AUTO: strcat(msg, ", mode:auto"); break;
456 case MR2_LOCAL: strcat(msg, ", mode:local"); break;
457 case MR2_REMOTE: strcat(msg, ", mode:remote"); break;
458 }
459 return (msg);
460 }
s_clk(int clk)461 const char *s_clk(int clk)
462 {
463 switch (clk & 0xf) {
464 case 0x0: return "75";
465 case 0x1: return "110/115200";
466 case 0x2: return "38400";
467 case 0x3: return "150";
468 case 0x4: return "300";
469 case 0x5: return "600";
470 case 0x6: return "1200";
471 case 0x7: return "2000";
472 case 0x8: return "2400";
473 case 0x9: return "4800";
474 case 0xa: return "7200";
475 case 0xb: return "9600";
476 case 0xc: return "19200";
477 case 0xd: return "57600";
478 case 0xe: return "?0xe";
479 case 0xf: return "?0xf";
480 }
481 return ("gcc sucks");
482 }
s_op(int op)483 const char *s_op(int op)
484 {
485 static char msg[200];
486
487 sprintf(msg, "cts:%s", (op & OP_CTS) ? "on" : "off");
488 sprintf(msg + strlen(msg), ", dsr:%s", (op & OP_DSR) ? "on" : "off");
489 return (msg);
490 }
491
s_ip(int ip)492 const char *s_ip(int ip)
493 {
494 static char msg[200];
495
496 sprintf(msg, "rts:%s", (ip & IP_RTS) ? "on" : "off");
497 sprintf(msg + strlen(msg), ", dcd:%s", (ip & IP_DCD) ? "on" : "off");
498 sprintf(msg + strlen(msg), ", dtr:%s", (ip & IP_DTR) ? "on" : "off");
499 sprintf(msg + strlen(msg), ", ri:%s", (ip & IP_RI) ? "on" : "off");
500 return (msg);
501 }
502
s_state(int state)503 const char *s_state(int state)
504 {
505 return (state & ST_BREAK ? "break:on" : "break:off");
506 }
507
s_prtcl(int pr)508 const char *s_prtcl(int pr)
509 {
510 static char msg[200];
511
512 sprintf(msg, "tx xon any:%s", (pr & SP_TANY) ? "on" : "off");
513 sprintf(msg + strlen(msg), ", tx xon/xoff:%s", (pr & SP_TXEN) ? "on" : "off");
514 sprintf(msg + strlen(msg), ", cooking:%s", (pr & SP_CEN) ? "on" : "off");
515 sprintf(msg + strlen(msg), ", rx xon/xoff:%s", (pr & SP_RXEN) ? "on" : "off");
516 sprintf(msg + strlen(msg), ", dcd/dsr check:%s", (pr & SP_DCEN) ? "on" : "off");
517 sprintf(msg + strlen(msg), ", parity check:%s", (pr & SP_PAEN) ? "on" : "off");
518 return (msg);
519 }
s_break(int br)520 const char *s_break(int br)
521 {
522 static char msg[200];
523
524 sprintf(msg, "ignore rx brk:%s", (br & BR_IGN) ? "on" : "off");
525 sprintf(msg + strlen(msg), ", brk interrupt:%s", (br & BR_INT) ? "on" : "off");
526 sprintf(msg + strlen(msg), ", parmrking:%s", (br & BR_PARMRK) ? "on" : "off");
527 sprintf(msg + strlen(msg), ", parign:%s", (br & BR_PARIGN) ? "on" : "off");
528 return (msg);
529 }
530
531 const char *
s_xstat(int xs)532 s_xstat(int xs)
533 {
534 static char msg[200];
535
536 msg[0] = 0;
537 /* MTA definitions, not TA */
538 if (xs & 0x01) strcat(msg, "TION "); /* Tx interrupts on (MTA only) */
539 if (xs & 0x02) strcat(msg, "RTSEN "); /* RTS FLOW enabled (MTA only) */
540 if (xs & 0x04) strcat(msg, "RTSLOW "); /* XOFF received (TA only) */
541 if (xs & 0x08) strcat(msg, "RXEN "); /* Rx XON/XOFF enabled */
542 if (xs & 0x10) strcat(msg, "ANYXO "); /* XOFF pending/sent or RTS dropped */
543 if (xs & 0x20) strcat(msg, "RXSE "); /* Rx XOFF sent */
544 if (xs & 0x40) strcat(msg, "NPEND "); /* Rx XON pending or XOFF pending */
545 if (xs & 0x40) strcat(msg, "FPEND "); /* Rx XOFF pending */
546 return (msg);
547 }
548
549 const char *
s_cstat(int cs)550 s_cstat(int cs)
551 {
552 static char msg[200];
553
554 msg[0] = 0;
555 /* MTA definitions, not TA */
556 if (cs & 0x01) strcat(msg, "TEMR "); /* Tx empty requested (MTA only) */
557 if (cs & 0x02) strcat(msg, "TEMA "); /* Tx empty acked (MTA only) */
558 if (cs & 0x04) strcat(msg, "EN "); /* Cooking enabled (on MTA means port is also || */
559 if (cs & 0x08) strcat(msg, "HIGH "); /* Buffer previously hit high water */
560 if (cs & 0x10) strcat(msg, "CTSEN "); /* CTS automatic flow-control enabled */
561 if (cs & 0x20) strcat(msg, "DCDEN "); /* DCD/DTR checking enabled */
562 if (cs & 0x40) strcat(msg, "BREAK "); /* Break detected */
563 if (cs & 0x80) strcat(msg, "RTSEN "); /* RTS automatic flow control enabled (MTA only) */
564 return (msg);
565 }
566
567 void
ccb_stat(int ac,char ** av)568 ccb_stat(int ac, char **av)
569 {
570 struct si_pstat sip;
571 #define CCB sip.tc_ccb
572
573 if (ac != 0)
574 prusage(U_STAT_CCB, 1);
575 sip.tc_dev = tc.tc_dev;
576 if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
577 err(1, "TCSI_CCB on %s", Devname);
578 printf("%s: ", Devname);
579
580 /* WORD next - Next Channel */
581 /* WORD addr_uart - Uart address */
582 /* WORD module - address of module struct */
583 printf("\tuart_type 0x%x\n", CCB.type); /* BYTE type - Uart type */
584 /* BYTE fill - */
585 printf("\tx_status 0x%x %s\n", CCB.x_status, s_xstat(CCB.x_status)); /* BYTE x_status - XON / XOFF status */
586 printf("\tc_status 0x%x %s\n", CCB.c_status, s_cstat(CCB.c_status)); /* BYTE c_status - cooking status */
587 printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos); /* BYTE hi_rxipos - stuff into rx buff */
588 printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos); /* BYTE hi_rxopos - stuff out of rx buffer */
589 printf("\thi_txopos 0x%x\n", CCB.hi_txopos); /* BYTE hi_txopos - Stuff into tx ptr */
590 printf("\thi_txipos 0x%x\n", CCB.hi_txipos); /* BYTE hi_txipos - ditto out */
591 printf("\thi_stat 0x%x %s\n", CCB.hi_stat, s_stat(CCB.hi_stat));/* BYTE hi_stat - Command register */
592 printf("\tdsr_bit 0x%x\n", CCB.dsr_bit); /* BYTE dsr_bit - Magic bit for DSR */
593 printf("\ttxon 0x%x\n", CCB.txon); /* BYTE txon - TX XON char */
594 printf("\ttxoff 0x%x\n", CCB.txoff); /* BYTE txoff - ditto XOFF */
595 printf("\trxon 0x%x\n", CCB.rxon); /* BYTE rxon - RX XON char */
596 printf("\trxoff 0x%x\n", CCB.rxoff); /* BYTE rxoff - ditto XOFF */
597 printf("\thi_mr1 0x%x %s\n", CCB.hi_mr1, s_mr1(CCB.hi_mr1)); /* BYTE hi_mr1 - mode 1 image */
598 printf("\thi_mr2 0x%x %s\n", CCB.hi_mr2, s_mr2(CCB.hi_mr2)); /* BYTE hi_mr2 - mode 2 image */
599 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 */
600 printf("\thi_op 0x%x %s\n", CCB.hi_op, s_op(CCB.hi_op)); /* BYTE hi_op - Op control */
601 printf("\thi_ip 0x%x %s\n", CCB.hi_ip, s_ip(CCB.hi_ip)); /* BYTE hi_ip - Input pins */
602 printf("\thi_state 0x%x %s\n", CCB.hi_state, s_state(CCB.hi_state)); /* BYTE hi_state - status */
603 printf("\thi_prtcl 0x%x %s\n", CCB.hi_prtcl, s_prtcl(CCB.hi_prtcl)); /* BYTE hi_prtcl - Protocol */
604 printf("\thi_txon 0x%x\n", CCB.hi_txon); /* BYTE hi_txon - host copy tx xon stuff */
605 printf("\thi_txoff 0x%x\n", CCB.hi_txoff); /* BYTE hi_txoff - */
606 printf("\thi_rxon 0x%x\n", CCB.hi_rxon); /* BYTE hi_rxon - */
607 printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff); /* BYTE hi_rxoff - */
608 printf("\tclose_prev 0x%x\n", CCB.close_prev); /* BYTE close_prev - Was channel previously closed */
609 printf("\thi_break 0x%x %s\n", CCB.hi_break, s_break(CCB.hi_break)); /* BYTE hi_break - host copy break process */
610 printf("\tbreak_state 0x%x\n", CCB.break_state); /* BYTE break_state - local copy ditto */
611 printf("\thi_mask 0x%x\n", CCB.hi_mask); /* BYTE hi_mask - Mask for CS7 etc. */
612 printf("\tmask_z280 0x%x\n", CCB.mask_z280); /* BYTE mask_z280 - Z280's copy */
613 /* BYTE res[0x60 - 36] - */
614 /* BYTE hi_txbuf[SLXOS_BUFFERSIZE] - */
615 /* BYTE hi_rxbuf[SLXOS_BUFFERSIZE] - */
616 /* BYTE res1[0xA0] - */
617 }
618
sp_state(int st)619 const char *sp_state(int st)
620 {
621
622 if (st & SS_LSTART)
623 return("lstart ");
624 else
625 return("");
626 }
627
628 void
port_stat(int ac,char ** av)629 port_stat(int ac, char **av)
630 {
631 struct si_pstat sip;
632 #define PRT sip.tc_siport
633
634 if (ac != 0)
635 prusage(U_STAT_PORT, 1);
636 sip.tc_dev = tc.tc_dev;
637 if (ioctl(ctlfd, TCSI_PORT, &sip) < 0)
638 err(1, "TCSI_PORT on %s", Devname);
639 printf("%s: ", Devname);
640
641 printf("\tsp_pend 0x%x %s\n", PRT.sp_pend, s_stat(PRT.sp_pend));
642 printf("\tsp_last_hi_ip 0x%x %s\n", PRT.sp_last_hi_ip, s_ip(PRT.sp_last_hi_ip));
643 printf("\tsp_state 0x%x %s\n", PRT.sp_state, sp_state(PRT.sp_state));
644 printf("\tsp_delta_overflows 0x%d\n", PRT.sp_delta_overflows);
645 }
646
647 int
islevel(char * tk)648 islevel(char *tk)
649 {
650 struct lv *lvp;
651 char *acp;
652
653 for (acp = tk; *acp; acp++)
654 if (isupper(*acp))
655 *acp = tolower(*acp);
656 for (lvp = lv; lvp->lv_name; lvp++)
657 if (strcmp(lvp->lv_name, tk) == 0)
658 return(lvp->lv_bit);
659 return(0);
660 }
661
662 /*
663 * Convert a string consisting of tokens separated by white space, commas
664 * or `|' into a bitfield - flag any unrecognised tokens.
665 */
666 int
lvls2bits(char * str)667 lvls2bits(char *str)
668 {
669 int i, bits = 0;
670 int errflag = 0;
671 char token[20];
672
673 while (sscanf(str, "%[^,| \t]", token) == 1) {
674 str += strlen(token);
675 while (isspace(*str) || *str==',' || *str=='|')
676 str++;
677 if (strcmp(token, "all") == 0)
678 return(0xffffffff);
679 if ((i = islevel(token)) == 0) {
680 warnx("unknown token '%s'", token);
681 errflag++;
682 } else
683 bits |= i;
684 }
685 if (errflag)
686 exit(1);
687
688 return(bits);
689 }
690
691 int
getnum(char * str)692 getnum(char *str)
693 {
694 int x;
695 char *acp = str;
696
697 x = 0;
698 while (*acp) {
699 if (!isdigit(*acp))
700 errx(1, "%s is not a number", str);
701 x *= 10;
702 x += (*acp - '0');
703 acp++;
704 }
705 return(x);
706 }
707
708 void
prlevels(int x)709 prlevels(int x)
710 {
711 struct lv *lvp;
712
713 switch (x) {
714 case 0:
715 printf("(none)\n");
716 break;
717 case 0xffffffff:
718 printf("all\n");
719 break;
720 default:
721 for (lvp = lv; lvp->lv_name; lvp++)
722 if (x & lvp->lv_bit)
723 printf(" %s", lvp->lv_name);
724 printf("\n");
725 }
726 }
727