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