date and time created 90/11/08 18:44:18 by bill
[unix-history] / usr / src / sys / i386 / isa / pccons.c
CommitLineData
febf7236
WN
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 *
50fc34ca
DA
8 * Added support for ibmpc term type and improved keyboard support. -Don Ahn
9 *
febf7236
WN
10 * %sccs.include.386.c%
11 *
50fc34ca 12 * @(#)pccons.c 5.2 (Berkeley) %G%
febf7236
WN
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"
50fc34ca 26#include "machine/device.h"
febf7236
WN
27#include "callout.h"
28#include "systm.h"
29#include "kernel.h"
30#include "syslog.h"
31#include "icu.h"
32
33struct tty cons;
34
35struct 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
50fc34ca
DA
44int cnprobe(), cnattach();
45
46struct driver cndriver = {
47 cnprobe, cnattach, "cn",
48};
49
febf7236
WN
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
59int cnstart();
60int ttrstrt();
61char 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
76u_char inb();
77
50fc34ca
DA
78cnprobe(dev)
79struct 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
105cnattach(dev)
106struct device *dev;
107{
108 INTREN(IRQ1);
109}
110
febf7236
WN
111/*ARGSUSED*/
112cnopen(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;
febf7236
WN
126 splnone();
127 }
128 return ((*linesw[tp->t_line].l_open)(dev, tp));
129}
130
131
132cnclose(dev)
133 dev_t dev;
134{
135 (*linesw[cons.t_line].l_close)(&cons);
136 ttyclose(&cons);
137 INTRDIS(IRQ1);
138}
139
140/*ARGSUSED*/
141cnread(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*/
149cnwrite(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 */
161cnrint(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
177cnioctl(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
194int consintr = 1;
195/*
196 * Got a console transmission interrupt -
197 * the console processor wants another character.
198 */
199cnxint(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
215cnstart(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 }
50fc34ca
DA
245 splx(s);
246 sput(c,0x7);
247 s = spltty();
febf7236
WN
248 }
249out:
250 splx(s);
251}
252
253cnputc(c)
254 char c;
255{
febf7236 256 if (c == '\n')
50fc34ca
DA
257 sput('\r',0x3);
258 sput(c, 0x3);
febf7236
WN
259}
260
261/*
262 * Print a character on console.
263 */
264cnputchar(c, tp)
265 char c;
266 register struct tty *tp;
267{
50fc34ca 268 sput(c,0x2);
febf7236
WN
269 if (c=='\n') getchar();
270}
271
272
273cngetc()
274{
275 register int c, s;
276
277 s = spltty(); /* block cnrint while we poll */
50fc34ca
DA
278 c = sgetc(0);
279 if (c == '\r') c = '\n';
febf7236
WN
280 splx(s);
281 return (c);
282}
283
284cngetchar(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 */
296cnparams(tp)
297 register struct tty *tp;
298{
299}
300
301#ifdef KDB
302/*
303 * Turn input polling on/off (used by debugger).
304 */
305cnpoll(onoff)
306 int onoff;
307{
308}
309#endif
310
50fc34ca
DA
311extern int hz;
312
313sysbeepstop()
314{
315 /* disable counter 2 */
316 outb(0x61,inb(0x61)&0xFC);
317}
318
319sysbeep()
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
febf7236
WN
331#define COL 80
332#define ROW 25
333#define CHR 2
50fc34ca
DA
334#define MONO_BASE 0x3B4
335#define MONO_BUF 0xB0000
336#define CGA_BASE 0x3D4
337#define CGA_BUF 0xB8000
338#define IOPHYSMEM 0xA0000
febf7236 339
febf7236 340u_char color = 0xe ;
50fc34ca
DA
341static unsigned int addr_6845;
342u_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
350cursor(pos)
351int 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
364sput(c, ca)
365u_char c, ca;
366{
febf7236 367
50fc34ca
DA
368 static int esc,ebrac,eparm,cx,cy,row,so;
369 static u_short *crtat = 0;
370 int s;
febf7236 371
50fc34ca
DA
372 s = splnone();
373
374/*
375 if(inb(0x64)&1)sgetc(1);
376*/
febf7236 377 if (crtat == 0) {
50fc34ca
DA
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);
febf7236 390 }
febf7236 391 switch(c) {
50fc34ca
DA
392 case 0x1B:
393 esc = 1; ebrac = 0; eparm = 0;
394 break;
febf7236
WN
395
396 case '\t':
397 do {
398 *crtat++ = (ca<<8)| ' '; row++ ;
399 } while (row %8);
400 break;
401
402 case '\010':
403 crtat--; row--;
50fc34ca 404 if (row < 0) row += COL; /* non-destructive backspace */
febf7236
WN
405 break;
406
407 case '\r':
50fc34ca 408 crtat -= row ; row = 0;
febf7236
WN
409 break;
410
411 case '\n':
febf7236
WN
412 crtat += COL ;
413 break;
414
415 default:
50fc34ca
DA
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 }
febf7236 497 }
febf7236 498 }
50fc34ca
DA
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);
febf7236 506}
50fc34ca
DA
507
508
509
febf7236
WN
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 */
50fc34ca 519#define SCROLL 0x0200 /* scroll lock key */
febf7236 520
50fc34ca 521unsigned __debug = 0 ;
febf7236
WN
522u_short action[] = {
5230, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 0- 7 */
524ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 8-15 */
525ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 16-23 */
526ASCII, ASCII, ASCII, ASCII, ASCII, CTL, ASCII, ASCII, /* scan 24-31 */
527ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 32-39 */
528ASCII, ASCII, SHF , ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 40-47 */
529ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, SHF, ASCII, /* scan 48-55 */
50fc34ca
DA
530 ALT, ASCII, CPS , FUNC , FUNC , FUNC , FUNC , FUNC , /* scan 56-63 */
531FUNC , FUNC , FUNC , FUNC , FUNC , NUM, STP, ASCII, /* scan 64-71 */
febf7236
WN
532ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, /* scan 72-79 */
533ASCII, ASCII, ASCII, ASCII, 0, 0, 0, 0, /* scan 80-87 */
5340,0,0,0,0,0,0,0,
5350,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
5360,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
537
538u_char unshift[] = { /* no shift */
5390, 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 */
50fc34ca 549ALT , ' ' , CPS, 1, 2, 3 , 4, 5, /* scan 56-63 */
febf7236 550
50fc34ca 551 6, 7, 8, 9, 10, NUM, STP, '7', /* scan 64-71 */
febf7236
WN
552 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
553
554 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
5550,0,0,0,0,0,0,0,
5560,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
5570,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
558
559u_char shift[] = { /* shift shift */
5600, 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 */
50fc34ca
DA
567ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */
568 0, 0, 0, 0, 0, NUM, STP, '7', /* scan 64-71 */
febf7236
WN
569 '8', '9', '-', '4', '5', '6', '+', '1', /* scan 72-79 */
570 '2', '3', '0', '.', 0, 0, 0, 0, /* scan 80-87 */
5710,0,0,0,0,0,0,0,
5720,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
5730,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
574
575u_char ctl[] = { /* CTL shift */
5760, 033 , '!' , 000 , '#' , '$' , '%' , 036 , /* scan 0- 7 */
577'&' , '*' , '(' , ')' , 037 , '+' , 034 ,'\177', /* scan 8-15 */
578021 , 027 , 005 , 022 , 024 , 031 , 025 , 011 , /* scan 16-23 */
579017 , 020 , 033 , 035 , '\r' , CTL , 001 , 023 , /* scan 24-31 */
580004 , 006 , 007 , 010 , 012 , 013 , 014 , ';' , /* scan 32-39 */
581'\'' , '`' , SHF , 034 , 032 , 030 , 003 , 026 , /* scan 40-47 */
582002 , 016 , 015 , '<' , '>' , '?' , SHF , '*', /* scan 48-55 */
50fc34ca
DA
583ALT , ' ' , CPS, 0, 0, ' ' , 0, 0, /* scan 56-63 */
584CPS, 0, 0, 0, 0, 0, 0, 0, /* scan 64-71 */
febf7236
WN
585 0, 0, 0, 0, 0, 0, 0, 0, /* scan 72-79 */
586 0, 0, 0, 0, 0, 0, 0, 0, /* scan 80-87 */
50fc34ca
DA
587 0, 0, 033, '7' , '4' , '1' , 0, NUM, /* scan 88-95 */
588'8' , '5' , '2' , 0, STP, '9' , '6' , '3' , /*scan 96-103*/
febf7236
WN
589'.' , 0, '*' , '-' , '+' , 0, 0, 0, /*scan 104-111*/
5900,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, } ;
591
592#ifdef notdef
593struct key {
594 u_short action; /* how this key functions */
595 char ascii[8]; /* ascii result character indexed by shifts */
596};
597#endif
598
50fc34ca 599u_char shfts, ctls, alts, caps, num, stp, scroll;
febf7236 600
50fc34ca
DA
601#define KBSTAT 0x64 /* kbd status port */
602#define KBS_INP_BUF_FUL 0x02 /* kbd char ready */
603#define KBDATA 0x60 /* kbd data port */
febf7236
WN
604#define KBSTATUSPORT 0x61 /* kbd status */
605
50fc34ca
DA
606update_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}
febf7236 613
50fc34ca
DA
614/*
615sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until
616a key is gotten. Otherwise return a 0x100 (256).
617*/
618int sgetc(noblock)
619{
620 u_char dt; unsigned key;
febf7236 621loop:
50fc34ca
DA
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);
febf7236 664 }
febf7236 665 }
50fc34ca 666 if (noblock) return (0x100); else goto loop;
febf7236
WN
667}
668
669pg(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
683getchar()
684{
685 register char thechar;
686 register delay;
687 int x;
688
689 consoftc.cs_flags |= CSF_POLLING;
690 x=splhigh();
50fc34ca 691 sput('>',0x6);
febf7236
WN
692 while (1) {
693 thechar = (char) sgetc(0);
50fc34ca
DA
694 consoftc.cs_flags &= ~CSF_POLLING;
695 splx(x);
febf7236
WN
696 switch (thechar) {
697 default: if (thechar >= ' ')
50fc34ca 698 sput(thechar,0x6);
febf7236
WN
699 return(thechar);
700 case cr:
50fc34ca
DA
701 case lf: sput(cr,0x6);
702 sput(lf,0x6);
febf7236
WN
703 return(lf);
704 case bs:
705 case del:
50fc34ca
DA
706 sput(bs,0x6);
707 sput(' ',0x6);
708 sput(bs,0x6);
febf7236 709 return(thechar);
50fc34ca 710 /*case cntlc:
febf7236 711 sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ;
50fc34ca 712 _exit(-2) ; */
febf7236 713 case cntld:
50fc34ca 714 sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ;
febf7236
WN
715 return(0);
716 }
717 }
718}