1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * Added support for ibmpc term type and improved keyboard support. -Don Ahn 9 * 10 * %sccs.include.386.c% 11 * 12 * @(#)pccons.c 5.6 (Berkeley) 02/26/91 13 */ 14 15 /* 16 * code to work keyboard & display for console 17 */ 18 #include "param.h" 19 #include "conf.h" 20 #include "dir.h" 21 #include "ioctl.h" 22 #include "user.h" 23 #include "proc.h" 24 #include "tty.h" 25 #include "uio.h" 26 #include "machine/isa/isa_device.h" 27 #include "callout.h" 28 #include "systm.h" 29 #include "kernel.h" 30 #include "syslog.h" 31 #include "icu.h" 32 33 struct tty cons; 34 35 struct consoftc { 36 char cs_flags; 37 #define CSF_ACTIVE 0x1 /* timeout active */ 38 #define CSF_POLLING 0x2 /* polling for input */ 39 char cs_lastc; /* last char sent */ 40 int cs_timo; /* timeouts since interrupt */ 41 u_long cs_wedgecnt; /* times restarted */ 42 } consoftc; 43 44 int cnprobe(), cnattach(); 45 46 struct isa_driver cndriver = { 47 cnprobe, cnattach, "cn", 48 }; 49 50 #define COL 80 51 #define ROW 25 52 #define CHR 2 53 #define MONO_BASE 0x3B4 54 #define MONO_BUF 0xB0000 55 #define CGA_BASE 0x3D4 56 #define CGA_BUF 0xB8000 57 #define IOPHYSMEM 0xA0000 58 59 u_char color = 0xe ; 60 static unsigned int addr_6845 = MONO_BASE; 61 u_short *Crtat = (u_short *)MONO_BUF; 62 63 /* 64 * We check the console periodically to make sure 65 * that it hasn't wedged. Unfortunately, if an XOFF 66 * is typed on the console, that can't be distinguished 67 * from more catastrophic failure. 68 */ 69 #define CN_TIMERVAL (hz) /* frequency at which to check cons */ 70 #define CN_TIMO (2*60) /* intervals to allow for output char */ 71 72 int cnstart(); 73 int ttrstrt(); 74 char partab[]; 75 76 /* 77 * Wait for CP to accept last CP command sent 78 * before setting up next command. 79 */ 80 #define waitforlast(timo) { \ 81 if (cnlast) { \ 82 (timo) = 10000; \ 83 do \ 84 uncache((char *)&cnlast->cp_unit); \ 85 while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \ 86 } \ 87 } 88 89 u_char inb(); 90 91 cnprobe(dev) 92 struct isa_device *dev; 93 { 94 u_char c; 95 int again = 0; 96 97 /* Enable interrupts and keyboard controller */ 98 while (inb(0x64)&2); outb(0x64,0x60); 99 while (inb(0x64)&2); outb(0x60,0x4D); 100 101 /* Start keyboard stuff RESET */ 102 while (inb(0x64)&2); /* wait input ready */ 103 outb(0x60,0xFF); /* RESET */ 104 while((c=inb(0x60))!=0xFA) { 105 if ((c == 0xFE) || (c == 0xFF)) { 106 if(!again)printf("KEYBOARD disconnected: RECONNECT \n"); 107 while (inb(0x64)&2); /* wait input ready */ 108 outb(0x60,0xFF); /* RESET */ 109 again = 1; 110 } 111 } 112 /* pick up keyboard reset return code */ 113 while((c=inb(0x60))!=0xAA)nullop(); 114 return 1; 115 } 116 117 cnattach(dev) 118 struct isa_device *dev; 119 { 120 u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR; 121 u_short was; 122 123 /* Crtat initialized to point to MONO buffer */ 124 /* if not present change to CGA_BUF offset */ 125 /* ONLY ADD the difference since locore.s adds */ 126 /* in the remapped offset at the right time */ 127 128 was = *Crtat; 129 *Crtat = (u_short) 0xA55A; 130 if (*Crtat != 0xA55A) 131 printf("<mono>"); 132 else printf("<color>"); 133 *Crtat = was; 134 } 135 136 /*ARGSUSED*/ 137 cnopen(dev, flag) 138 dev_t dev; 139 { 140 register struct tty *tp; 141 int unit = minor(dev); 142 143 tp = &cons; 144 if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 145 return (EBUSY); 146 tp->t_oproc = cnstart; 147 if ((tp->t_state&TS_ISOPEN) == 0) { 148 ttychars(tp); 149 tp->t_state = TS_ISOPEN|TS_CARR_ON; 150 tp->t_flags = EVENP|ECHO|XTABS|CRMOD; 151 splnone(); 152 } 153 return ((*linesw[tp->t_line].l_open)(dev, tp)); 154 } 155 156 157 cnclose(dev) 158 dev_t dev; 159 { 160 (*linesw[cons.t_line].l_close)(&cons); 161 ttyclose(&cons); 162 } 163 164 /*ARGSUSED*/ 165 cnread(dev, uio) 166 dev_t dev; 167 struct uio *uio; 168 { 169 return ((*linesw[cons.t_line].l_read)(&cons, uio)); 170 } 171 172 /*ARGSUSED*/ 173 cnwrite(dev, uio) 174 dev_t dev; 175 struct uio *uio; 176 { 177 return ((*linesw[cons.t_line].l_write)(&cons, uio)); 178 } 179 180 /* 181 * Got a console receive interrupt - 182 * the console processor wants to give us a character. 183 * Catch the character, and see who it goes to. 184 */ 185 cnrint(dev, irq, cpl) 186 dev_t dev; 187 { 188 int c; 189 190 c = sgetc(1); 191 if (c&0x100) return; 192 if (consoftc.cs_flags&CSF_POLLING) 193 return; 194 #ifdef KDB 195 if (kdbrintr(c, &cons)) 196 return; 197 #endif 198 (*linesw[cons.t_line].l_rint)(c&0xff, &cons); 199 } 200 201 cnioctl(dev, cmd, addr, flag) 202 dev_t dev; 203 caddr_t addr; 204 { 205 register struct tty *tp = &cons; 206 register error; 207 208 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 209 if (error >= 0) 210 return error; 211 if ((error = ttioctl(tp, cmd, addr, flag)) < 0) 212 error = ENOTTY; 213 else if (cmd == TIOCSETP || cmd == TIOCSETN) 214 cnparams(tp); 215 return (error); 216 } 217 218 int consintr = 1; 219 /* 220 * Got a console transmission interrupt - 221 * the console processor wants another character. 222 */ 223 cnxint(dev) 224 dev_t dev; 225 { 226 register struct tty *tp; 227 register int unit; 228 229 if (!consintr) 230 return; 231 cons.t_state &= ~TS_BUSY; 232 consoftc.cs_timo = 0; 233 if (cons.t_line) 234 (*linesw[cons.t_line].l_start)(&cons); 235 else 236 cnstart(&cons); 237 } 238 239 cnstart(tp) 240 register struct tty *tp; 241 { 242 register c, s; 243 244 s = spltty(); 245 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 246 goto out; 247 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 248 if (tp->t_state&TS_ASLEEP) { 249 tp->t_state &= ~TS_ASLEEP; 250 wakeup((caddr_t)&tp->t_outq); 251 } 252 if (tp->t_wsel) { 253 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 254 tp->t_wsel = 0; 255 tp->t_state &= ~TS_WCOLL; 256 } 257 } 258 while (tp->t_outq.c_cc != 0) { 259 c = getc(&tp->t_outq) & 0xff; 260 if ((tp->t_flags & (RAW|LITOUT)) == 0) { 261 if (c > 0177) 262 { 263 timeout(ttrstrt, (caddr_t)tp, (c&0177)); 264 tp->t_state |= TS_TIMEOUT; 265 break; 266 } 267 c &= 0177; 268 } 269 splx(s); 270 sput(c,0x7); 271 s = spltty(); 272 } 273 out: 274 splx(s); 275 } 276 277 cnputc(c) 278 char c; 279 { 280 if (c == '\n') 281 sput('\r',0x3); 282 sput(c, 0x3); 283 } 284 285 /* 286 * Print a character on console. 287 */ 288 cnputchar(c, tp) 289 char c; 290 register struct tty *tp; 291 { 292 sput(c,0x2); 293 if (c=='\n') getchar(); 294 } 295 296 297 cngetc() 298 { 299 register int c, s; 300 301 s = spltty(); /* block cnrint while we poll */ 302 c = sgetc(0); 303 if (c == '\r') c = '\n'; 304 splx(s); 305 return (c); 306 } 307 308 cngetchar(tp) 309 register struct tty *tp; 310 { 311 int c; 312 313 c = sgetc(0); 314 return (c&0xff); 315 } 316 317 /* 318 * Set line parameters 319 */ 320 cnparams(tp) 321 register struct tty *tp; 322 { 323 } 324 325 #ifdef KDB 326 /* 327 * Turn input polling on/off (used by debugger). 328 */ 329 cnpoll(onoff) 330 int onoff; 331 { 332 } 333 #endif 334 335 extern int hz; 336 337 sysbeepstop() 338 { 339 /* disable counter 2 */ 340 outb(0x61,inb(0x61)&0xFC); 341 } 342 343 sysbeep() 344 { 345 /* enable counter 2 */ 346 outb(0x61,inb(0x61)|3); 347 /* set command for counter 2, 2 byte write */ 348 outb(0x43,0xB6); 349 /* send 0x637 for 750 HZ */ 350 outb(0x42,0x37); 351 outb(0x42,0x06); 352 timeout(sysbeepstop,0,hz/4); 353 } 354 355 /* cursor() sets an offset (0-1999) into the 80x25 text area */ 356 357 static u_short *crtat = 0; 358 char bg_at = 0x0f; 359 char so_at = 0x70; 360 361 cursor() 362 { int pos = crtat - Crtat; 363 364 outb(addr_6845,14); 365 outb(addr_6845+1,pos >> 8); 366 outb(addr_6845,15); 367 outb(addr_6845+1,pos&0xff); 368 } 369 370 /* sput has support for emulation of the 'ibmpc' termcap entry. */ 371 /* This is a bare-bones implementation of a bare-bones entry */ 372 /* One modification: Change li#24 to li#25 to reflect 25 lines */ 373 374 sput(c, ca) 375 u_char c, ca; 376 { 377 378 static int esc,ebrac,eparm,cx,cy,row,so; 379 380 if (crtat == 0) { 381 u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR, was; 382 unsigned cursorat; 383 384 /* Crtat initialized to point to MONO buffer */ 385 /* if not present change to CGA_BUF offset */ 386 /* ONLY ADD the difference since locore.s adds */ 387 /* in the remapped offset at the right time */ 388 389 was = *cp; 390 *cp = (u_short) 0xA55A; 391 if (*cp != 0xA55A) { 392 addr_6845 = MONO_BASE; 393 } else { 394 *cp = was; 395 addr_6845 = CGA_BASE; 396 Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR; 397 } 398 /* Extract cursor location */ 399 outb(addr_6845,14); 400 cursorat = inb(addr_6845+1)<<8 ; 401 outb(addr_6845,15); 402 cursorat |= inb(addr_6845+1); 403 404 crtat = Crtat + cursorat; 405 fillw((bg_at<<8)|' ', crtat, COL*ROW-cursorat); 406 } 407 switch(c) { 408 case 0x1B: 409 esc = 1; ebrac = 0; eparm = 0; 410 break; 411 412 case '\t': 413 do { 414 *crtat++ = (ca<<8)| ' '; row++ ; 415 } while (row %8); 416 break; 417 418 case '\010': 419 crtat--; row--; 420 if (row < 0) row += COL; /* non-destructive backspace */ 421 break; 422 423 case '\r': 424 crtat -= row ; row = 0; 425 break; 426 427 case '\n': 428 crtat += COL ; 429 break; 430 431 default: 432 if (esc) { 433 if (ebrac) { 434 switch(c) { 435 case 'm': /* no support for standout */ 436 if (!cx) so = 0; 437 else so = 1; 438 esc = 0; ebrac = 0; eparm = 0; 439 break; 440 case 'A': /* back one row */ 441 crtat -= COL; 442 esc = 0; ebrac = 0; eparm = 0; 443 break; 444 case 'B': /* down one row */ 445 crtat += COL; 446 esc = 0; ebrac = 0; eparm = 0; 447 break; 448 case 'C': /* right cursor */ 449 crtat++; row++; 450 esc = 0; ebrac = 0; eparm = 0; 451 break; 452 case 'J': /* Clear to end of display */ 453 fillw((bg_at<<8)+' ', crtat, 454 Crtat+COL*ROW-crtat); 455 esc = 0; ebrac = 0; eparm = 0; 456 break; 457 case 'K': /* Clear to EOL */ 458 fillw((bg_at<<8)+' ', crtat, COL-row); 459 esc = 0; ebrac = 0; eparm = 0; 460 break; 461 case 'H': /* Cursor move */ 462 if ((!cx)||(!cy)) { 463 crtat = Crtat; 464 row = 0; 465 } else { 466 crtat = Crtat+(cx-1)*COL+cy-1; 467 row = cy-1; 468 } 469 esc = 0; ebrac = 0; eparm = 0; 470 break; 471 case ';': /* Switch params in cursor def */ 472 eparm = 1; 473 return; 474 default: /* Only numbers valid here */ 475 if ((c >= '0')&&(c <= '9')) { 476 if (eparm) { 477 cy *= 10; 478 cy += c - '0'; 479 } else { 480 cx *= 10; 481 cx += c - '0'; 482 } 483 } else { 484 esc = 0; ebrac = 0; eparm = 0; 485 } 486 return; 487 } 488 break; 489 } else if (c == 'c') { /* Clear screen & home */ 490 fillw((bg_at<<8)+' ', Crtat,COL*ROW); 491 crtat = Crtat; row = 0; 492 esc = 0; ebrac = 0; eparm = 0; 493 } else if (c == '[') { /* Start ESC [ sequence */ 494 ebrac = 1; cx = 0; cy = 0; eparm = 0; 495 } else { /* Invalid, clear state */ 496 esc = 0; ebrac = 0; eparm = 0; 497 } 498 } else { 499 if (c == 7) { 500 sysbeep(); 501 } 502 /* Print only printables */ 503 else /*if (c >= ' ') */ { 504 while(inb(0x3da)&1)nullop(); 505 if (so) { 506 *crtat++ = (so_at<<8)| c; row++ ; 507 } else { 508 *crtat++ = (ca<<8)| c; row++ ; 509 } 510 if (row >= COL) row = 0; 511 break ; 512 } 513 } 514 } 515 if (crtat >= Crtat+COL*(ROW)) { /* scroll check */ 516 bcopy(Crtat+COL,Crtat,COL*(ROW-1)*CHR); 517 fillw ((bg_at<<8)+' ', Crtat+COL*(ROW-1),COL) ; 518 crtat -= COL ; 519 } 520 } 521 522 523 #define L 0x0001 /* locking function */ 524 #define SHF 0x0002 /* keyboard shift */ 525 #define ALT 0x0004 /* alternate shift -- alternate chars */ 526 #define NUM 0x0008 /* numeric shift cursors vs. numeric */ 527 #define CTL 0x0010 /* control shift -- allows ctl function */ 528 #define CPS 0x0020 /* caps shift -- swaps case of letter */ 529 #define ASCII 0x0040 /* ascii code for this key */ 530 #define STP 0x0080 /* stop output */ 531 #define FUNC 0x0100 /* function key */ 532 #define SCROLL 0x0200 /* scroll lock key */ 533 534 unsigned __debug = 0; 535 u_short action[] = { 536 0, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */ 537 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */ 538 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */ 539 ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */ 540 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */ 541 ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */ 542 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */ 543 ALT, ASCII, CPS , FUNC , FUNC , FUNC , FUNC , FUNC , /* scan 56-63 */ 544 FUNC , FUNC , FUNC , FUNC , FUNC , NUM, STP, ASCII, /* scan 64-71 */ 545 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */ 546 ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */ 547 0,0,0,0,0,0,0,0, 548 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 549 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; 550 551 u_char unshift[] = { /* no shift */ 552 0, 033 , '1' , '2' , '3' , '4' , '5' , '6' , /* scan 0- 7 */ 553 '7' , '8' , '9' , '0' , '-' , '=' , 0177 ,'\t' , /* scan 8-15 */ 554 555 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , /* scan 16-23 */ 556 'o' , 'p' , '[' , ']' , '\r' , CTL , 'a' , 's' , /* scan 24-31 */ 557 558 'd' , 'f' , 'g' , 'h' , 'j' , 'k' , 'l' , ';' , /* scan 32-39 */ 559 '\'' , '`' , SHF , '\\' , 'z' , 'x' , 'c' , 'v' , /* scan 40-47 */ 560 561 'b' , 'n' , 'm' , ',' , '.' , '/' , SHF , '*', /* scan 48-55 */ 562 ALT , ' ' , CPS, 1, 2, 3 , 4, 5, /* scan 56-63 */ 563 564 6, 7, 8, 9, 10, NUM, STP, '7', /* scan 64-71 */ 565 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ 566 567 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ 568 0,0,0,0,0,0,0,0, 569 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 570 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; 571 572 u_char shift[] = { /* shift shift */ 573 0, 033 , '!' , '@' , '#' , '$' , '%' , '^' , /* scan 0- 7 */ 574 '&' , '*' , '(' , ')' , '_' , '+' , 0177 ,'\t' , /* scan 8-15 */ 575 'Q' , 'W' , 'E' , 'R' , 'T' , 'Y' , 'U' , 'I' , /* scan 16-23 */ 576 'O' , 'P' , '{' , '}' , '\r' , CTL , 'A' , 'S' , /* scan 24-31 */ 577 'D' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , ':' , /* scan 32-39 */ 578 '"' , '~' , SHF , '|' , 'Z' , 'X' , 'C' , 'V' , /* scan 40-47 */ 579 'B' , 'N' , 'M' , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ 580 ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ 581 0, 0, 0, 0, 0, NUM, STP, '7', /* scan 64-71 */ 582 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */ 583 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */ 584 0,0,0,0,0,0,0,0, 585 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 586 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; 587 588 u_char ctl[] = { /* CTL shift */ 589 0, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */ 590 '&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */ 591 021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */ 592 017 , 020 , 033 , 035 , '\r' , CTL , 001 , 023 , /* scan 24-31 */ 593 004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */ 594 '\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */ 595 002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */ 596 ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */ 597 CPS, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */ 598 0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */ 599 0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */ 600 0, 0, 033, '7' , '4' , '1' , 0, NUM, /* scan 88-95 */ 601 '8' , '5' , '2' , 0, STP, '9' , '6' , '3' , /*scan 96-103*/ 602 '.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/ 603 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ; 604 605 #ifdef notdef 606 struct key { 607 u_short action; /* how this key functions */ 608 char ascii[8]; /* ascii result character indexed by shifts */ 609 }; 610 #endif 611 612 u_char shfts, ctls, alts, caps, num, stp, scroll; 613 614 #define KBSTAT 0x64 /* kbd status port */ 615 #define KBS_INP_BUF_FUL 0x02 /* kbd char ready */ 616 #define KBDATA 0x60 /* kbd data port */ 617 #define KBSTATUSPORT 0x61 /* kbd status */ 618 619 update_led() 620 { 621 while (inb(0x64)&2); /* wait input ready */ 622 outb(0x60,0xED); /* LED Command */ 623 while (inb(0x64)&2); /* wait input ready */ 624 outb(0x60,scroll | 2*num | 4*caps); 625 } 626 627 reset_cpu() { 628 while(1) { 629 while (inb(0x64)&2); /* wait input ready */ 630 outb(0x64,0xFE); /* Reset Command */ 631 DELAY(4000000); 632 while (inb(0x64)&2); /* wait input ready */ 633 outb(0x64,0xFF); /* Keyboard Reset Command */ 634 } 635 /* NOTREACHED */ 636 } 637 638 /* 639 sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until 640 a key is gotten. Otherwise return a 0x100 (256). 641 */ 642 int sgetc(noblock) 643 { 644 u_char dt; unsigned key; 645 loop: 646 /* First see if there is something in the keyboard port */ 647 if (inb(KBSTAT)&1) dt = inb(KBDATA); 648 else { if (noblock) return (0x100); else goto loop; } 649 650 /* Check for cntl-alt-del */ 651 if ((dt == 83)&&ctls&&alts) _exit(); 652 653 /* Check for make/break */ 654 if (dt & 0x80) { 655 /* break */ 656 dt = dt & 0x7f ; 657 switch (action[dt]) { 658 case SHF: shfts = 0; break; 659 case ALT: alts = 0; break; 660 case CTL: ctls = 0; break; 661 case FUNC: 662 /* Toggle debug flags */ 663 key = unshift[dt]; 664 if(__debug & (1<<key)) __debug &= ~(1<<key) ; 665 else __debug |= (1<<key) ; 666 break; 667 } 668 } else { 669 /* make */ 670 dt = dt & 0x7f ; 671 switch (action[dt]) { 672 /* LOCKING KEYS */ 673 case NUM: num ^= 1; update_led(); break; 674 case CPS: caps ^= 1; update_led(); break; 675 case SCROLL: scroll ^= 1; update_led(); break; 676 case STP: stp ^= 1; if(stp) goto loop; break; 677 678 /* NON-LOCKING KEYS */ 679 case SHF: shfts = 1; break; 680 case ALT: alts = 1; break; 681 case CTL: ctls = 1; break; 682 case ASCII: 683 if (shfts) dt = shift[dt]; 684 else if (ctls) dt = ctl[dt]; 685 else dt = unshift[dt]; 686 if (caps && (dt >= 'a' && dt <= 'z')) dt -= 'a' - 'A'; 687 return(dt); 688 } 689 } 690 if (noblock) return (0x100); else goto loop; 691 } 692 693 pg(p,q,r,s,t,u,v,w,x,y,z) char *p; { 694 printf(p,q,r,s,t,u,v,w,x,y,z); 695 printf("\n"); 696 return(getchar()); 697 } 698 699 /* special characters */ 700 #define bs 8 701 #define lf 10 702 #define cr 13 703 #define cntlc 3 704 #define del 0177 705 #define cntld 4 706 707 getchar() 708 { 709 register char thechar; 710 register delay; 711 int x; 712 713 consoftc.cs_flags |= CSF_POLLING; 714 x=splhigh(); 715 sput('>',0x6); 716 /*while (1) {*/ 717 thechar = (char) sgetc(0); 718 consoftc.cs_flags &= ~CSF_POLLING; 719 splx(x); 720 switch (thechar) { 721 default: if (thechar >= ' ') 722 sput(thechar,0x6); 723 return(thechar); 724 case cr: 725 case lf: sput(cr,0x6); 726 sput(lf,0x6); 727 return(lf); 728 case bs: 729 case del: 730 sput(bs,0x6); 731 sput(' ',0x6); 732 sput(bs,0x6); 733 return(thechar); 734 /*case cntlc: 735 sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ; 736 _exit(-2) ; */ 737 case cntld: 738 sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ; 739 return(0); 740 } 741 /*}*/ 742 } 743