xref: /original-bsd/sys/i386/isa/pccons.c (revision e718337e)
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.4 (Berkeley) 11/18/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/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)nulldev();
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)nulldev();
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