1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)kbd.c 7.1 (Berkeley) 07/13/92 12 * 13 * from: $Header: kbd.c,v 1.15 92/07/09 07:59:27 torek Exp $ (LBL) 14 */ 15 16 /* 17 * Keyboard driver (/dev/kbd -- note that we do not have minor numbers 18 * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and 19 * passes them up to the appropriate reader. 20 */ 21 22 #include "sys/param.h" 23 #include "sys/conf.h" 24 #include "sys/device.h" 25 #include "sys/ioctl.h" 26 #include "sys/kernel.h" 27 #include "sys/proc.h" 28 #include "sys/syslog.h" 29 #include "sys/systm.h" 30 #include "sys/tty.h" 31 32 #include "machine/autoconf.h" 33 34 #include "vuid_event.h" 35 #include "event_var.h" 36 #include "kbd.h" 37 #include "kbio.h" 38 39 /* 40 * Sun keyboard definitions (from Sprite). 41 * These apply to type 2, 3 and 4 keyboards. 42 */ 43 #define KEY_CODE(c) ((c) & KBD_KEYMASK) /* keyboard code index */ 44 #define KEY_UP(c) ((c) & KBD_UP) /* true => key went up */ 45 46 /* 47 * Each KEY_CODE(x) can be translated via the tables below. 48 * The result is either a valid ASCII value in [0..0x7f] or is one 49 * of the following `magic' values saying something interesting 50 * happened. If LSHIFT or RSHIFT has changed state the next 51 * lookup should come from the appropriate table; if ALLUP is 52 * sent all keys (including both shifts and the control key) are 53 * now up, and the next byte is the keyboard ID code. 54 * 55 * These tables ignore all function keys (on the theory that if you 56 * want these keys, you should use a window system). Note that 57 * `caps lock' is just mapped as `ignore' (so there!). (Only the 58 * type 3 and 4 keyboards have a caps lock key anyway.) 59 */ 60 #define KEY_MAGIC 0x80 /* flag => magic value */ 61 #define KEY_IGNORE 0x80 62 #define KEY_L1 KEY_IGNORE 63 #define KEY_CAPSLOCK KEY_IGNORE 64 #define KEY_LSHIFT 0x81 65 #define KEY_RSHIFT 0x82 66 #define KEY_CONTROL 0x83 67 #define KEY_ALLUP 0x84 /* all keys are now up; also reset */ 68 69 /* 70 * Decode tables for type 2, 3, and 4 keyboards 71 * (stolen from Sprite; see also kbd.h). 72 */ 73 static const u_char kbd_unshifted[] = { 74 /* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE, 75 /* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 76 /* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 77 /* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 78 /* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 79 /* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 80 /* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 81 /* 28 */ KEY_IGNORE, '\033', '1', '2', 82 /* 32 */ '3', '4', '5', '6', 83 /* 36 */ '7', '8', '9', '0', 84 /* 40 */ '-', '=', '`', '\b', 85 /* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 86 /* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 87 /* 52 */ KEY_IGNORE, '\t', 'q', 'w', 88 /* 56 */ 'e', 'r', 't', 'y', 89 /* 60 */ 'u', 'i', 'o', 'p', 90 /* 64 */ '[', ']', '\177', KEY_IGNORE, 91 /* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 92 /* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 93 /* 76 */ KEY_CONTROL, 'a', 's', 'd', 94 /* 80 */ 'f', 'g', 'h', 'j', 95 /* 84 */ 'k', 'l', ';', '\'', 96 /* 88 */ '\\', '\r', KEY_IGNORE, KEY_IGNORE, 97 /* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 98 /* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT, 99 /* 100 */ 'z', 'x', 'c', 'v', 100 /* 104 */ 'b', 'n', 'm', ',', 101 /* 108 */ '.', '/', KEY_RSHIFT, '\n', 102 /* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 103 /* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK, 104 /* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE, 105 /* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP, 106 }; 107 108 static const u_char kbd_shifted[] = { 109 /* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE, 110 /* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 111 /* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 112 /* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 113 /* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 114 /* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 115 /* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 116 /* 28 */ KEY_IGNORE, '\033', '!', '@', 117 /* 32 */ '#', '$', '%', '^', 118 /* 36 */ '&', '*', '(', ')', 119 /* 40 */ '_', '+', '~', '\b', 120 /* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 121 /* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 122 /* 52 */ KEY_IGNORE, '\t', 'Q', 'W', 123 /* 56 */ 'E', 'R', 'T', 'Y', 124 /* 60 */ 'U', 'I', 'O', 'P', 125 /* 64 */ '{', '}', '\177', KEY_IGNORE, 126 /* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 127 /* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 128 /* 76 */ KEY_CONTROL, 'A', 'S', 'D', 129 /* 80 */ 'F', 'G', 'H', 'J', 130 /* 84 */ 'K', 'L', ':', '"', 131 /* 88 */ '|', '\r', KEY_IGNORE, KEY_IGNORE, 132 /* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 133 /* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT, 134 /* 100 */ 'Z', 'X', 'C', 'V', 135 /* 104 */ 'B', 'N', 'M', '<', 136 /* 108 */ '>', '?', KEY_RSHIFT, '\n', 137 /* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 138 /* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK, 139 /* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE, 140 /* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP, 141 }; 142 143 /* 144 * We need to remember the state of the keyboard's shift and control 145 * keys, and we need a per-type translation table. 146 */ 147 struct kbd_state { 148 const u_char *kbd_unshifted; /* unshifted keys */ 149 const u_char *kbd_shifted; /* shifted keys */ 150 const u_char *kbd_cur; /* current keys (either of the preceding) */ 151 union { 152 char c[2]; /* left and right shift keys */ 153 short s; /* true => either shift key */ 154 } kbd_shift; 155 #define kbd_lshift kbd_shift.c[0] 156 #define kbd_rshift kbd_shift.c[1] 157 #define kbd_anyshift kbd_shift.s 158 char kbd_control; /* true => ctrl down */ 159 char kbd_click; /* true => keyclick enabled */ 160 char kbd_takeid; /* take next byte as ID */ 161 u_char kbd_id; /* a place to store the ID */ 162 }; 163 164 /* 165 * Keyboard driver state. The ascii and kbd links go up and down and 166 * we just sit in the middle doing translation. Note that it is possible 167 * to get just one of the two links, in which case /dev/kbd is unavailable. 168 * The downlink supplies us with `internal' open and close routines which 169 * will enable dataflow across the downlink. We promise to call open when 170 * we are willing to take keystrokes, and to call close when we are not. 171 * If /dev/kbd is not the console tty input source, we do this whenever 172 * /dev/kbd is in use; otherwise we just leave it open forever. 173 */ 174 struct kbd_softc { 175 struct tty *k_cons; /* uplink for ASCII data to console */ 176 struct tty *k_kbd; /* downlink for output to keyboard */ 177 void (*k_open) __P((struct tty *)); /* enable dataflow */ 178 void (*k_close) __P((struct tty *)); /* disable dataflow */ 179 int k_evmode; /* set if we should produce events */ 180 struct kbd_state k_state; /* ASCII decode state */ 181 struct evvar k_events; /* event queue state */ 182 } kbd_softc; 183 184 /* Prototypes */ 185 void kbd_ascii(struct tty *); 186 void kbd_serial(struct tty *, void (*)(), void (*)()); 187 static void kbd_getid(void *); 188 void kbd_reset(struct kbd_state *); 189 static int kbd_translate(int, struct kbd_state *); 190 void kbd_rint(int); 191 int kbdopen(dev_t, int, int, struct proc *); 192 int kbdclose(dev_t, int, int, struct proc *); 193 int kbdread(dev_t, struct uio *, int); 194 int kbdwrite(dev_t, struct uio *, int); 195 int kbdioctl(dev_t, int, caddr_t, int, struct proc *); 196 int kbdselect(dev_t, int, struct proc *); 197 int kbd_docmd(int, int); 198 199 /* 200 * Attach the console keyboard ASCII (up-link) interface. 201 * This happens before kbd_serial. 202 */ 203 void 204 kbd_ascii(struct tty *tp) 205 { 206 207 kbd_softc.k_cons = tp; 208 } 209 210 /* 211 * Attach the console keyboard serial (down-link) interface. 212 * We pick up the initial keyboard clock state here as well. 213 */ 214 void 215 kbd_serial(struct tty *tp, void (*iopen)(), void (*iclose)()) 216 { 217 register struct kbd_softc *k; 218 register char *cp; 219 220 k = &kbd_softc; 221 k->k_kbd = tp; 222 k->k_open = iopen; 223 k->k_close = iclose; 224 225 cp = getpropstring(optionsnode, "keyboard-click?"); 226 if (cp && strcmp(cp, "true") == 0) 227 k->k_state.kbd_click = 1; 228 229 if (k->k_cons) { 230 /* 231 * We supply keys for /dev/console. Before we can 232 * do so, we have to ``open'' the line. We also need 233 * the type, got by sending a RESET down the line ... 234 * but clists are not yet set up, so we use a timeout 235 * to try constantly until we can get the ID. (gag) 236 */ 237 (*iopen)(tp); /* never to be closed */ 238 kbd_getid(NULL); 239 } 240 } 241 242 /* 243 * Initial keyboard reset, to obtain ID and thus a translation table. 244 * We have to try again and again until the tty subsystem works. 245 */ 246 static void 247 kbd_getid(void *arg) 248 { 249 register struct kbd_softc *k; 250 register struct tty *tp; 251 register int retry; 252 extern int cold; /* XXX */ 253 254 k = &kbd_softc; 255 if (k->k_state.kbd_cur != NULL) 256 return; 257 tp = k->k_kbd; 258 if (cold || ttyoutput(KBD_CMD_RESET, tp) >= 0) 259 retry = 1; 260 else { 261 (*tp->t_oproc)(tp); 262 retry = 2 * hz; 263 } 264 timeout(kbd_getid, NULL, retry); 265 } 266 267 void 268 kbd_reset(register struct kbd_state *ks) 269 { 270 /* 271 * On first identification, wake up anyone waiting for type 272 * and set up the table pointers. 273 */ 274 if (ks->kbd_unshifted == NULL) { 275 wakeup((caddr_t)ks); 276 ks->kbd_unshifted = kbd_unshifted; 277 ks->kbd_shifted = kbd_shifted; 278 ks->kbd_cur = ks->kbd_unshifted; 279 } 280 281 /* Restore keyclick, if necessary */ 282 switch (ks->kbd_id) { 283 284 case KB_SUN2: 285 /* Type 2 keyboards don't support keyclick */ 286 break; 287 288 case KB_SUN3: 289 /* Type 3 keyboards come up with keyclick on */ 290 if (!ks->kbd_click) 291 (void) kbd_docmd(KBD_CMD_NOCLICK, 0); 292 break; 293 294 case KB_SUN4: 295 /* Type 4 keyboards come up with keyclick off */ 296 if (ks->kbd_click) 297 (void) kbd_docmd(KBD_CMD_CLICK, 0); 298 break; 299 } 300 } 301 302 /* 303 * Turn keyboard up/down codes into ASCII. 304 */ 305 static int 306 kbd_translate(register int c, register struct kbd_state *ks) 307 { 308 register int down; 309 310 if (ks->kbd_cur == NULL) { 311 /* 312 * Do not know how to translate yet. 313 * We will find out when a RESET comes along. 314 */ 315 return (-1); 316 } 317 down = !KEY_UP(c); 318 c = ks->kbd_cur[KEY_CODE(c)]; 319 if (c & KEY_MAGIC) { 320 switch (c) { 321 322 case KEY_LSHIFT: 323 ks->kbd_lshift = down; 324 break; 325 326 case KEY_RSHIFT: 327 ks->kbd_rshift = down; 328 break; 329 330 case KEY_ALLUP: 331 ks->kbd_anyshift = 0; 332 ks->kbd_control = 0; 333 break; 334 335 case KEY_CONTROL: 336 ks->kbd_control = down; 337 /* FALLTHROUGH */ 338 339 case KEY_IGNORE: 340 return (-1); 341 342 default: 343 panic("kbd_translate"); 344 } 345 if (ks->kbd_anyshift) 346 ks->kbd_cur = ks->kbd_shifted; 347 else 348 ks->kbd_cur = ks->kbd_unshifted; 349 return (-1); 350 } 351 if (!down) 352 return (-1); 353 if (ks->kbd_control) { 354 /* control space and unshifted control atsign return null */ 355 if (c == ' ' || c == '2') 356 return (0); 357 /* unshifted control hat */ 358 if (c == '6') 359 return ('^' & 0x1f); 360 /* standard controls */ 361 if (c >= '@' && c < 0x7f) 362 return (c & 0x1f); 363 } 364 return (c); 365 } 366 367 void 368 kbd_rint(register int c) 369 { 370 register struct kbd_softc *k = &kbd_softc; 371 register struct firm_event *fe; 372 register int put; 373 374 /* 375 * Reset keyboard after serial port overrun, so we can resynch. 376 * The printf below should be shortened and/or replaced with a 377 * call to log() after this is tested (and how will we test it?!). 378 */ 379 if (c & (TTY_FE|TTY_PE)) { 380 printf("keyboard input parity or framing error (0x%x)\n", c); 381 (void) ttyoutput(KBD_CMD_RESET, k->k_kbd); 382 (*k->k_kbd->t_oproc)(k->k_kbd); 383 return; 384 } 385 386 /* Read the keyboard id if we read a KBD_RESET last time */ 387 if (k->k_state.kbd_takeid) { 388 k->k_state.kbd_takeid = 0; 389 k->k_state.kbd_id = c; 390 kbd_reset(&k->k_state); 391 return; 392 } 393 394 /* If we have been reset, setup to grab the keyboard id next time */ 395 if (c == KBD_RESET) { 396 k->k_state.kbd_takeid = 1; 397 return; 398 } 399 400 /* 401 * If /dev/kbd is not connected in event mode, but we are sending 402 * data to /dev/console, translate and send upstream. Note that 403 * we will get this while opening /dev/kbd if it is not already 404 * open and we do not know its type. 405 */ 406 if (!k->k_evmode) { 407 c = kbd_translate(c, &k->k_state); 408 if (c >= 0 && k->k_cons != NULL) 409 ttyinput(c, k->k_cons); 410 return; 411 } 412 413 /* 414 * IDLEs confuse the MIT X11R4 server badly, so we must drop them. 415 * This is bad as it means the server will not automatically resync 416 * on all-up IDLEs, but I did not drop them before, and the server 417 * goes crazy when it comes time to blank the screen.... 418 */ 419 if (c == KBD_IDLE) 420 return; 421 422 /* 423 * Keyboard is generating events. Turn this keystroke into an 424 * event and put it in the queue. If the queue is full, the 425 * keystroke is lost (sorry!). 426 */ 427 put = k->k_events.ev_put; 428 fe = &k->k_events.ev_q[put]; 429 put = (put + 1) % EV_QSIZE; 430 if (put == k->k_events.ev_get) { 431 log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */ 432 return; 433 } 434 fe->id = KEY_CODE(c); 435 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 436 fe->time = time; 437 k->k_events.ev_put = put; 438 EV_WAKEUP(&k->k_events); 439 } 440 441 int 442 kbdopen(dev_t dev, int flags, int mode, struct proc *p) 443 { 444 int s, error; 445 446 if (kbd_softc.k_events.ev_io) 447 return (EBUSY); 448 kbd_softc.k_events.ev_io = p; 449 /* 450 * If no console keyboard, tell the device to open up, maybe for 451 * the first time. Then make sure we know what kind of keyboard 452 * it is. 453 */ 454 if (kbd_softc.k_cons == NULL) 455 (*kbd_softc.k_open)(kbd_softc.k_kbd); 456 error = 0; 457 s = spltty(); 458 if (kbd_softc.k_state.kbd_cur == NULL) { 459 (void) ttyoutput(KBD_CMD_RESET, kbd_softc.k_kbd); 460 error = tsleep((caddr_t)&kbd_softc.k_state, PZERO | PCATCH, 461 devopn, hz); 462 if (error == EWOULDBLOCK) /* no response */ 463 error = ENXIO; 464 } 465 splx(s); 466 if (error) { 467 kbd_softc.k_events.ev_io = NULL; 468 return (error); 469 } 470 ev_init(&kbd_softc.k_events); 471 return (0); 472 } 473 474 int 475 kbdclose(dev_t dev, int flags, int mode, struct proc *p) 476 { 477 478 /* 479 * Turn off event mode, dump the queue, and close the keyboard 480 * unless it is supplying console input. 481 */ 482 kbd_softc.k_evmode = 0; 483 ev_fini(&kbd_softc.k_events); 484 if (kbd_softc.k_cons == NULL) 485 (*kbd_softc.k_close)(kbd_softc.k_kbd); 486 kbd_softc.k_events.ev_io = NULL; 487 return (0); 488 } 489 490 int 491 kbdread(dev_t dev, struct uio *uio, int flags) 492 { 493 494 return (ev_read(&kbd_softc.k_events, uio, flags)); 495 } 496 497 /* this routine should not exist, but is convenient to write here for now */ 498 int 499 kbdwrite(dev_t dev, struct uio *uio, int flags) 500 { 501 502 return (EOPNOTSUPP); 503 } 504 505 int 506 kbdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p) 507 { 508 register struct kbd_softc *k = &kbd_softc; 509 510 switch (cmd) { 511 512 case KIOCTRANS: 513 if (*(int *)data == TR_UNTRANS_EVENT) 514 return (0); 515 break; 516 517 case KIOCGTRANS: 518 /* 519 * Get translation mode 520 */ 521 *(int *)data = TR_UNTRANS_EVENT; 522 return (0); 523 524 case KIOCGETKEY: 525 if (((struct kiockey *)data)->kio_station == 118) { 526 /* 527 * This is X11 asking if a type 3 keyboard is 528 * really a type 3 keyboard. Say yes. 529 */ 530 ((struct kiockey *)data)->kio_entry = HOLE; 531 return (0); 532 } 533 break; 534 535 case KIOCCMD: 536 /* 537 * ``unimplemented commands are ignored'' (blech) 538 * so cannot check return value from kbd_docmd 539 */ 540 #ifdef notyet 541 while (kbd_docmd(*(int *)data, 1) == ENOSPC) /*ERESTART?*/ 542 (void) sleep((caddr_t)&lbolt, TTOPRI); 543 #else 544 (void) kbd_docmd(*(int *)data, 1); 545 #endif 546 return (0); 547 548 case KIOCTYPE: 549 *(int *)data = k->k_state.kbd_id; 550 return (0); 551 552 case KIOCSDIRECT: 553 k->k_evmode = *(int *)data; 554 return (0); 555 556 case FIONBIO: /* we will remove this someday (soon???) */ 557 return (0); 558 559 case FIOASYNC: 560 k->k_events.ev_async = *(int *)data != 0; 561 return (0); 562 563 case TIOCSPGRP: 564 if (*(int *)data != k->k_events.ev_io->p_pgid) 565 return (EPERM); 566 return (0); 567 568 default: 569 return (ENOTTY); 570 } 571 572 /* 573 * We identified the ioctl, but we do not handle it. 574 */ 575 return (EOPNOTSUPP); /* misuse, but what the heck */ 576 } 577 578 int 579 kbdselect(dev_t dev, int rw, struct proc *p) 580 { 581 582 return (ev_select(&kbd_softc.k_events, rw, p)); 583 } 584 585 /* 586 * Execute a keyboard command; return 0 on success. 587 * If `isuser', force a small delay before output if output queue 588 * is flooding. (The keyboard runs at 1200 baud, or 120 cps.) 589 */ 590 int 591 kbd_docmd(int cmd, int isuser) 592 { 593 register struct tty *tp = kbd_softc.k_kbd; 594 register struct kbd_softc *k = &kbd_softc; 595 int s; 596 597 if (tp == NULL) 598 return (ENXIO); /* ??? */ 599 switch (cmd) { 600 601 case KBD_CMD_BELL: 602 case KBD_CMD_NOBELL: 603 /* Supported by type 2, 3, and 4 keyboards */ 604 break; 605 606 case KBD_CMD_CLICK: 607 /* Unsupported by type 2 keyboards */ 608 if (k->k_state.kbd_id != KB_SUN2) { 609 k->k_state.kbd_click = 1; 610 break; 611 } 612 return (EINVAL); 613 614 case KBD_CMD_NOCLICK: 615 /* Unsupported by type 2 keyboards */ 616 if (k->k_state.kbd_id != KB_SUN2) { 617 k->k_state.kbd_click = 0; 618 break; 619 } 620 return (EINVAL); 621 622 default: 623 return (EINVAL); /* ENOTTY? EOPNOTSUPP? */ 624 } 625 626 if (isuser) { 627 s = spltty(); 628 if (tp->t_outq.c_cc > 120) 629 (void) tsleep((caddr_t)&lbolt, TTIPRI, 630 ttyout, 0); 631 splx(s); 632 } 633 if (ttyoutput(cmd, tp) >= 0) 634 return (ENOSPC); /* ERESTART? */ 635 (*tp->t_oproc)(tp); 636 return (0); 637 } 638