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 30static 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 51struct 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 76static int alldev = 0; 77 78void ccb_stat(int, char **); 79void port_stat(int, char **); 80void debug(int, char **); 81void dostat(void); 82int getnum(char *); 83int islevel(char *); 84int lvls2bits(char *); 85void mstate(int, char **); 86void nport(int, char **); 87void onoff(int, char **, int, char *, char *, int); 88int opencontrol(void); 89void prlevels(int); 90void prusage(int, int); 91void rxint(int, char **); 92void txint(int, char **); 93 94struct 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 108struct 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 125char *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 136int ctlfd; 137char *Devname; 138struct si_tcsi tc; 139 140int 141main(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 185int 186opencontrol(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 */ 200void 201prusage(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 */ 221void 222dostat(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 */ 249void 250debug(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 296void 297rxint(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 321void 322txint(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 344void 345onoff(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 372void 373mstate(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 392void 393nport(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 404const 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} 424const 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} 442const 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} 461const 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} 483const 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 492const 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 503const char *s_state(int state) 504{ 505 return (state & ST_BREAK ? "break:on" : "break:off"); 506} 507 508const 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} 520const 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 531const char * 532s_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 549const char * 550s_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 567void 568ccb_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 619const char *sp_state(int st) 620{ 621 622 if (st & SS_LSTART) 623 return("lstart "); 624 else 625 return(""); 626} 627 628void 629port_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 647int 648islevel(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 */ 666int 667lvls2bits(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 691int 692getnum(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 708void 709prlevels(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