xref: /original-bsd/sys/i386/isa/pccons.c (revision 68d9582f)
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 and Don Ahn.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)pccons.c	5.14 (Berkeley) 05/20/92
11  */
12 
13 /*
14  * code to work keyboard & display for PC-style console
15  */
16 #include "param.h"
17 #include "conf.h"
18 #include "ioctl.h"
19 #include "proc.h"
20 #include "user.h"
21 #include "tty.h"
22 #include "uio.h"
23 #include "i386/isa/isa_device.h"
24 #include "callout.h"
25 #include "systm.h"
26 #include "kernel.h"
27 #include "syslog.h"
28 #include "i386/isa/icu.h"
29 #include "i386/i386/cons.h"
30 
31 struct	tty pccons;
32 
33 struct	pcconsoftc {
34 	char	cs_flags;
35 #define	CSF_ACTIVE	0x1	/* timeout active */
36 #define	CSF_POLLING	0x2	/* polling for input */
37 	char	cs_lastc;	/* last char sent */
38 	int	cs_timo;	/* timeouts since interrupt */
39 	u_long	cs_wedgecnt;	/* times restarted */
40 } pcconsoftc;
41 
42 int pcprobe(), pcattach();
43 
44 struct	isa_driver pcdriver = {
45 	pcprobe, pcattach, "pc",
46 };
47 
48 #define	COL		80
49 #define	ROW		25
50 #define	CHR		2
51 #define MONO_BASE	0x3B4
52 #define MONO_BUF	0xfe0B0000
53 #define CGA_BASE	0x3D4
54 #define CGA_BUF		0xfe0B8000
55 #define IOPHYSMEM	0xA0000
56 
57 u_char	color = 0xe ;
58 static unsigned int addr_6845 = MONO_BASE;
59 u_short *Crtat = (u_short *)MONO_BUF;
60 static openf;
61 
62 /*
63  * We check the console periodically to make sure
64  * that it hasn't wedged.  Unfortunately, if an XOFF
65  * is typed on the console, that can't be distinguished
66  * from more catastrophic failure.
67  */
68 #define	CN_TIMERVAL	(hz)		/* frequency at which to check cons */
69 #define	CN_TIMO		(2*60)		/* intervals to allow for output char */
70 
71 int	pcstart();
72 int	pcparam();
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 (pclast) { \
82 		(timo) = 10000; \
83 		do \
84 			uncache((char *)&pclast->cp_unit); \
85 		while ((pclast->cp_unit&CPTAKE) == 0 && --(timo)); \
86 	} \
87 }
88 
89 u_char inb();
90 
91 pcprobe(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);
114 	return 1;
115 }
116 
117 pcattach(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 	cursor();
135 }
136 
137 /* ARGSUSED */
138 #ifdef __STDC__
139 pcopen(dev_t dev, int flag, int mode, struct proc *p)
140 #else
141 pcopen(dev, flag, mode, p)
142 	dev_t dev;
143 	int flag, mode;
144 	struct proc *p;
145 #endif
146 {
147 	register struct tty *tp;
148 
149 	tp = &pccons;
150 	tp->t_oproc = pcstart;
151 	tp->t_param = pcparam;
152 	tp->t_dev = dev;
153 	openf++;
154 	if ((tp->t_state & TS_ISOPEN) == 0) {
155 		tp->t_state |= TS_WOPEN;
156 		ttychars(tp);
157 		tp->t_iflag = TTYDEF_IFLAG;
158 		tp->t_oflag = TTYDEF_OFLAG;
159 		tp->t_cflag = TTYDEF_CFLAG;
160 		tp->t_lflag = TTYDEF_LFLAG;
161 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
162 		pcparam(tp, &tp->t_termios);
163 		ttsetwater(tp);
164 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
165 		return (EBUSY);
166 	tp->t_state |= TS_CARR_ON;
167 	return ((*linesw[tp->t_line].l_open)(dev, tp));
168 }
169 
170 pcclose(dev, flag, mode, p)
171 	dev_t dev;
172 	int flag, mode;
173 	struct proc *p;
174 {
175 	(*linesw[pccons.t_line].l_close)(&pccons, flag);
176 	ttyclose(&pccons);
177 	return(0);
178 }
179 
180 /*ARGSUSED*/
181 pcread(dev, uio, flag)
182 	dev_t dev;
183 	struct uio *uio;
184 {
185 	return ((*linesw[pccons.t_line].l_read)(&pccons, uio, flag));
186 }
187 
188 /*ARGSUSED*/
189 pcwrite(dev, uio, flag)
190 	dev_t dev;
191 	struct uio *uio;
192 {
193 	return ((*linesw[pccons.t_line].l_write)(&pccons, uio, flag));
194 }
195 
196 /*
197  * Got a console receive interrupt -
198  * the console processor wants to give us a character.
199  * Catch the character, and see who it goes to.
200  */
201 pcrint(dev, irq, cpl)
202 	dev_t dev;
203 {
204 	int c;
205 
206 	c = sgetc(1);
207 	if (c&0x100) return;
208 	if (pcconsoftc.cs_flags&CSF_POLLING)
209 		return;
210 #ifdef KDB
211 	if (kdbrintr(c, &pccons))
212 		return;
213 #endif
214 	if (openf) /* 386bsd */
215 		(*linesw[pccons.t_line].l_rint)(c&0xff, &pccons);
216 }
217 
218 pcioctl(dev, cmd, data, flag, p)
219 	dev_t dev;
220 	int cmd, flag;
221 	caddr_t data;
222 	struct proc *p;
223 {
224 	register struct tty *tp = &pccons;
225 	register error;
226 
227 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
228 	if (error >= 0)
229 		return (error);
230 	error = ttioctl(tp, cmd, data, flag);
231 	if (error >= 0)
232 		return (error);
233 	return (ENOTTY);
234 }
235 
236 int	pcconsintr = 1;
237 /*
238  * Got a console transmission interrupt -
239  * the console processor wants another character.
240  */
241 pcxint(dev)
242 	dev_t dev;
243 {
244 	register struct tty *tp;
245 	register int unit;
246 
247 	if (!pcconsintr)
248 		return;
249 	pccons.t_state &= ~TS_BUSY;
250 	pcconsoftc.cs_timo = 0;
251 	if (pccons.t_line)
252 		(*linesw[pccons.t_line].l_start)(&pccons);
253 	else
254 		pcstart(&pccons);
255 }
256 
257 pcstart(tp)
258 	register struct tty *tp;
259 {
260 	register c, s;
261 
262 	s = spltty();
263 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
264 		goto out;
265 	do {
266 		if (tp->t_outq.c_cc <= tp->t_lowat) {
267 			if (tp->t_state&TS_ASLEEP) {
268 				tp->t_state &= ~TS_ASLEEP;
269 				wakeup((caddr_t)&tp->t_outq);
270 			}
271 			selwakeup(&tp->t_wsel);
272 		}
273 		if (tp->t_outq.c_cc == 0)
274 			goto out;
275 		c = getc(&tp->t_outq);
276 		splx(s);
277 		sput(c, 0x7);
278 		s = spltty();
279 	} while(1);
280 out:
281 	splx(s);
282 }
283 
284 pccnprobe(cp)
285 	struct consdev *cp;
286 {
287 	int maj;
288 	extern int pcopen();
289 
290 	/* locate the major number */
291 	for (maj = 0; maj < nchrdev; maj++)
292 		if (cdevsw[maj].d_open == pcopen)
293 			break;
294 
295 	/* initialize required fields */
296 	cp->cn_dev = makedev(maj, 0);
297 	cp->cn_tp = &pccons;
298 	cp->cn_pri = CN_INTERNAL;
299 }
300 
301 /* ARGSUSED */
302 pccninit(cp)
303 	struct consdev *cp;
304 {
305 	/*
306 	 * For now, don't screw with it.
307 	 */
308 	/* crtat = 0; */
309 }
310 
311 static __color;
312 
313 /* ARGSUSED */
314 pccnputc(dev, c)
315 	dev_t dev;
316 	char c;
317 {
318 	int clr = __color;
319 
320 	if (clr == 0)
321 		clr = 0x30;
322 	else
323 		clr |= 0x60;
324 	if (c == '\n')
325 		sput('\r', clr);
326 	sput(c, clr);
327 }
328 
329 /*
330  * Print a character on console.
331  */
332 pcputchar(c, tp)
333 	char c;
334 	register struct tty *tp;
335 {
336 	sput(c,0x2);
337 	if (c=='\n') getchar();
338 }
339 
340 
341 /* ARGSUSED */
342 pccngetc(dev)
343 	dev_t dev;
344 {
345 	register int c, s;
346 
347 	s = spltty();		/* block pcrint while we poll */
348 	c = sgetc(0);
349 	if (c == '\r') c = '\n';
350 	splx(s);
351 	return (c);
352 }
353 
354 pcgetchar(tp)
355 	register struct tty *tp;
356 {
357 	int c;
358 
359 	c = sgetc(0);
360 	return (c&0xff);
361 }
362 
363 /*
364  * Set line parameters
365  */
366 pcparam(tp, t)
367 	register struct tty *tp;
368 	register struct termios *t;
369 {
370 	register int cflag = t->c_cflag;
371         /* and copy to tty */
372         tp->t_ispeed = t->c_ispeed;
373         tp->t_ospeed = t->c_ospeed;
374         tp->t_cflag = cflag;
375 
376 	return(0);
377 }
378 
379 #ifdef KDB
380 /*
381  * Turn input polling on/off (used by debugger).
382  */
383 pcpoll(onoff)
384 	int onoff;
385 {
386 }
387 #endif
388 
389 extern int hz;
390 
391 static beeping;
392 sysbeepstop()
393 {
394 	/* disable counter 2 */
395 	outb(0x61,inb(0x61)&0xFC);
396 	beeping = 0;
397 }
398 
399 sysbeep()
400 {
401 
402 	/* enable counter 2 */
403 	outb(0x61,inb(0x61)|3);
404 	/* set command for counter 2, 2 byte write */
405 	outb(0x43,0xB6);
406 	/* send 0x637 for 750 HZ */
407 	outb(0x42,0x37);
408 	outb(0x42,0x06);
409 	if(!beeping)timeout(sysbeepstop,0,hz/4);
410 	beeping = 1;
411 }
412 
413 /* cursor() sets an offset (0-1999) into the 80x25 text area    */
414 
415 static u_short *crtat = 0;
416 char bg_at = 0x0f;
417 char so_at = 0x70;
418 
419 cursor()
420 { 	int pos = crtat - Crtat;
421 
422 	outb(addr_6845,14);
423 	outb(addr_6845+1,pos >> 8);
424 	outb(addr_6845,15);
425 	outb(addr_6845+1,pos&0xff);
426 	timeout(cursor,0,hz/10);
427 }
428 
429 u_char shfts, ctls, alts, caps, num, stp, scroll;
430 
431 /*
432  * Compensate for abysmally stupid frame buffer aribitration with macro
433  */
434 #define	wrtchar(c) { do *crtat = (c); while ((c) != *crtat); crtat++; row++; }
435 
436 /* sput has support for emulation of the 'ibmpc' termcap entry. */
437 /* This is a bare-bones implementation of a bare-bones entry    */
438 /* One modification: Change li#24 to li#25 to reflect 25 lines  */
439 
440 sput(c, ca)
441 u_char c, ca;
442 {
443 
444 	static int esc,ebrac,eparm,cx,cy,row,so;
445 
446 	if (crtat == 0) {
447 		u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR, was;
448 		unsigned cursorat;
449 
450 		/* Crtat initialized to point to MONO buffer   */
451 		/* if not present change to CGA_BUF offset     */
452 		/* ONLY ADD the difference since locore.s adds */
453 		/* in the remapped offset at the right time    */
454 
455 		was = *cp;
456 		*cp = (u_short) 0xA55A;
457 		if (*cp != 0xA55A) {
458 			addr_6845 = MONO_BASE;
459 		} else {
460 			*cp = was;
461 			addr_6845 = CGA_BASE;
462 			Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR;
463 		}
464 		/* Extract cursor location */
465 		outb(addr_6845,14);
466 		cursorat = inb(addr_6845+1)<<8 ;
467 		outb(addr_6845,15);
468 		cursorat |= inb(addr_6845+1);
469 
470 		crtat = Crtat + cursorat;
471 		fillw((bg_at<<8)|' ', crtat, COL*ROW-cursorat);
472 	}
473 	switch(c) {
474 	case 0x1B:
475 		esc = 1; ebrac = 0; eparm = 0;
476 		break;
477 
478 	case '\t':
479 		do {
480 			wrtchar((ca<<8)| ' ');
481 		} while (row % 8);
482 		break;
483 
484 	case '\010':
485 		crtat--; row--;
486 		if (row < 0) row += COL;  /* non-destructive backspace */
487 		break;
488 
489 	case '\r':
490 		crtat -= row ; row = 0;
491 		break;
492 
493 	case '\n':
494 		crtat += COL ;
495 		break;
496 
497 	default:
498 		if (esc) {
499 			if (ebrac) {
500 				switch(c) {
501 				case 'm': /* no support for standout */
502 					if (!cx) so = 0;
503 					else so = 1;
504 					esc = 0; ebrac = 0; eparm = 0;
505 					break;
506 				case 'A': /* back one row */
507 					crtat -= COL;
508 					esc = 0; ebrac = 0; eparm = 0;
509 					break;
510 				case 'B': /* down one row */
511 					crtat += COL;
512 					esc = 0; ebrac = 0; eparm = 0;
513 					break;
514 				case 'C': /* right cursor */
515 					crtat++; row++;
516 					esc = 0; ebrac = 0; eparm = 0;
517 					break;
518 				case 'J': /* Clear to end of display */
519 					fillw((bg_at<<8)+' ', crtat,
520 						Crtat+COL*ROW-crtat);
521 					esc = 0; ebrac = 0; eparm = 0;
522 					break;
523 				case 'K': /* Clear to EOL */
524 					fillw((bg_at<<8)+' ', crtat,
525 						COL-(crtat-Crtat)%COL);
526 					esc = 0; ebrac = 0; eparm = 0;
527 					break;
528 				case 'H': /* Cursor move */
529 					if ((!cx)||(!cy)) {
530 						crtat = Crtat;
531 						row = 0;
532 					} else {
533 						crtat = Crtat+(cx-1)*COL+cy-1;
534 						row = cy-1;
535 					}
536 					esc = 0; ebrac = 0; eparm = 0;
537 					break;
538 				case ';': /* Switch params in cursor def */
539 					eparm = 1;
540 					return;
541 				default: /* Only numbers valid here */
542 					if ((c >= '0')&&(c <= '9')) {
543 						if (eparm) {
544 							cy *= 10;
545 							cy += c - '0';
546 						} else {
547 							cx *= 10;
548 							cx += c - '0';
549 						}
550 					} else {
551 						esc = 0; ebrac = 0; eparm = 0;
552 					}
553 					return;
554 				}
555 				break;
556 			} else if (c == 'c') { /* Clear screen & home */
557 				fillw((bg_at<<8)+' ', Crtat,COL*ROW);
558 				crtat = Crtat; row = 0;
559 				esc = 0; ebrac = 0; eparm = 0;
560 			} else if (c == '[') { /* Start ESC [ sequence */
561 				ebrac = 1; cx = 0; cy = 0; eparm = 0;
562 			} else { /* Invalid, clear state */
563 				 esc = 0; ebrac = 0; eparm = 0;
564 			}
565 		} else {
566 			if (c == 7)
567 				sysbeep();
568 			/* Print only printables */
569 			else /*if (c >= ' ') */ {
570 				if (so) {
571 					wrtchar((so_at<<8)| c);
572 				} else {
573 					wrtchar((ca<<8)| c);
574 				}
575 				if (row >= COL) row = 0;
576 				break ;
577 			}
578 		}
579 	}
580 	if (crtat >= Crtat+COL*(ROW)) { /* scroll check */
581 		if (openf) do sgetc(1); while (scroll);
582 		bcopy(Crtat+COL,Crtat,COL*(ROW-1)*CHR);
583 		fillw ((bg_at<<8) + ' ', Crtat+COL*(ROW-1),COL) ;
584 		crtat -= COL ;
585 	}
586 }
587 
588 #define	L		0x0001	/* locking function */
589 #define	SHF		0x0002	/* keyboard shift */
590 #define	ALT		0x0004	/* alternate shift -- alternate chars */
591 #define	NUM		0x0008	/* numeric shift  cursors vs. numeric */
592 #define	CTL		0x0010	/* control shift  -- allows ctl function */
593 #define	CPS		0x0020	/* caps shift -- swaps case of letter */
594 #define	ASCII		0x0040	/* ascii code for this key */
595 #define	STP		0x0080	/* stop output */
596 #define	FUNC		0x0100	/* function key */
597 #define	SCROLL		0x0200	/* scroll lock key */
598 
599 unsigned	__debug = 0; /*0xffe */;
600 u_short action[] = {
601 0,     ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan  0- 7 */
602 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan  8-15 */
603 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 16-23 */
604 ASCII, ASCII, ASCII, ASCII, ASCII,   CTL, ASCII, ASCII,		/* scan 24-31 */
605 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 32-39 */
606 ASCII, ASCII, SHF  , ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 40-47 */
607 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,  SHF,  ASCII,		/* scan 48-55 */
608   ALT, ASCII, CPS  , FUNC , FUNC , FUNC , FUNC , FUNC ,		/* scan 56-63 */
609 FUNC , FUNC , FUNC , FUNC , FUNC , NUM, SCROLL, ASCII,		/* scan 64-71 */
610 ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 72-79 */
611 ASCII, ASCII, ASCII, ASCII,     0,     0,     0,     0,		/* scan 80-87 */
612 0,0,0,0,0,0,0,0,
613 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
614 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
615 
616 u_char unshift[] = {	/* no shift */
617 0,     033  , '1'  , '2'  , '3'  , '4'  , '5'  , '6'  ,		/* scan  0- 7 */
618 '7'  , '8'  , '9'  , '0'  , '-'  , '='  , 0177 ,'\t'  ,		/* scan  8-15 */
619 
620 'q'  , 'w'  , 'e'  , 'r'  , 't'  , 'y'  , 'u'  , 'i'  ,		/* scan 16-23 */
621 'o'  , 'p'  , '['  , ']'  , '\r' , CTL  , 'a'  , 's'  ,		/* scan 24-31 */
622 
623 'd'  , 'f'  , 'g'  , 'h'  , 'j'  , 'k'  , 'l'  , ';'  ,		/* scan 32-39 */
624 '\'' , '`'  , SHF  , '\\' , 'z'  , 'x'  , 'c'  , 'v'  ,		/* scan 40-47 */
625 
626 'b'  , 'n'  , 'm'  , ','  , '.'  , '/'  , SHF  ,   '*',		/* scan 48-55 */
627 ALT  , ' '  , CPS,     1,     2,    3 ,     4,     5,		/* scan 56-63 */
628 
629     6,     7,     8,     9,    10, NUM, STP,   '7',		/* scan 64-71 */
630   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',		/* scan 72-79 */
631 
632   '2',   '3',   '0',   '.',     0,     0,     0,     0,		/* scan 80-87 */
633 0,0,0,0,0,0,0,0,
634 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
635 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
636 
637 u_char shift[] = {	/* shift shift */
638 0,     033  , '!'  , '@'  , '#'  , '$'  , '%'  , '^'  ,		/* scan  0- 7 */
639 '&'  , '*'  , '('  , ')'  , '_'  , '+'  , 0177 ,'\t'  ,		/* scan  8-15 */
640 'Q'  , 'W'  , 'E'  , 'R'  , 'T'  , 'Y'  , 'U'  , 'I'  ,		/* scan 16-23 */
641 'O'  , 'P'  , '{'  , '}'  , '\r' , CTL  , 'A'  , 'S'  ,		/* scan 24-31 */
642 'D'  , 'F'  , 'G'  , 'H'  , 'J'  , 'K'  , 'L'  , ':'  ,		/* scan 32-39 */
643 '"'  , '~'  , SHF  , '|'  , 'Z'  , 'X'  , 'C'  , 'V'  ,		/* scan 40-47 */
644 'B'  , 'N'  , 'M'  , '<'  , '>'  , '?'  , SHF  ,   '*',		/* scan 48-55 */
645 ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,		/* scan 56-63 */
646     0,     0,     0,     0,     0, NUM, STP,   '7',		/* scan 64-71 */
647   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',		/* scan 72-79 */
648   '2',   '3',   '0',   '.',     0,     0,     0,     0,		/* scan 80-87 */
649 0,0,0,0,0,0,0,0,
650 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
651 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
652 
653 u_char ctl[] = {	/* CTL shift */
654 0,     033  , '!'  , 000  , '#'  , '$'  , '%'  , 036  ,		/* scan  0- 7 */
655 '&'  , '*'  , '('  , ')'  , 037  , '+'  , 034  ,'\177',		/* scan  8-15 */
656 021  , 027  , 005  , 022  , 024  , 031  , 025  , 011  ,		/* scan 16-23 */
657 017  , 020  , 033  , 035  , '\r' , CTL  , 001  , 023  ,		/* scan 24-31 */
658 004  , 006  , 007  , 010  , 012  , 013  , 014  , ';'  ,		/* scan 32-39 */
659 '\'' , '`'  , SHF  , 034  , 032  , 030  , 003  , 026  ,		/* scan 40-47 */
660 002  , 016  , 015  , '<'  , '>'  , '?'  , SHF  ,   '*',		/* scan 48-55 */
661 ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,		/* scan 56-63 */
662 CPS,     0,     0,     0,     0,     0,     0,     0,		/* scan 64-71 */
663     0,     0,     0,     0,     0,     0,     0,     0,		/* scan 72-79 */
664     0,     0,     0,     0,     0,     0,     0,     0,		/* scan 80-87 */
665     0,     0,   033, '7'  , '4'  , '1'  ,     0, NUM,		/* scan 88-95 */
666 '8'  , '5'  , '2'  ,     0, STP, '9'  , '6'  , '3'  ,		/*scan  96-103*/
667 '.'  ,     0, '*'  , '-'  , '+'  ,     0,     0,     0,		/*scan 104-111*/
668 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
669 
670 #ifdef notdef
671 struct key {
672 	u_short action;		/* how this key functions */
673 	char	ascii[8];	/* ascii result character indexed by shifts */
674 };
675 #endif
676 
677 
678 #define	KBSTAT		0x64	/* kbd status port */
679 #define	KBS_INP_BUF_FUL	0x02	/* kbd char ready */
680 #define	KBDATA		0x60	/* kbd data port */
681 #define	KBSTATUSPORT	0x61	/* kbd status */
682 
683 update_led()
684 {
685 	while (inb(0x64)&2);	/* wait input ready */
686 	outb(0x60,0xED);	/* LED Command */
687 	while (inb(0x64)&2);	/* wait input ready */
688 	outb(0x60,scroll | 2*num | 4*caps);
689 }
690 
691 reset_cpu() {
692 	while(1) {
693 		while (inb(0x64)&2);	/* wait input ready */
694 		outb(0x64,0xFE);	/* Reset Command */
695 		DELAY(4000000);
696 		while (inb(0x64)&2);	/* wait input ready */
697 		outb(0x64,0xFF);	/* Keyboard Reset Command */
698 	}
699 	/* NOTREACHED */
700 }
701 
702 /*
703 sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until
704 a key is gotten.  Otherwise return a 0x100 (256).
705 */
706 int sgetc(noblock)
707 {
708 	u_char dt; unsigned key;
709 loop:
710 	/* First see if there is something in the keyboard port */
711 	if (inb(KBSTAT)&1) dt = inb(KBDATA);
712 	else { if (noblock) return (0x100); else goto loop; }
713 
714 	/* Check for cntl-alt-del */
715 	if ((dt == 83)&&ctls&&alts) _exit();
716 
717 	/* Check for make/break */
718 	if (dt & 0x80) {
719 		/* break */
720 		dt = dt & 0x7f ;
721 		switch (action[dt]) {
722 		case SHF: shfts = 0; break;
723 		case ALT: alts = 0; break;
724 		case CTL: ctls = 0; break;
725 		case FUNC:
726 			/* Toggle debug flags */
727 			key = unshift[dt];
728 			if(__debug & (1<<key)) __debug &= ~(1<<key) ;
729 			else __debug |= (1<<key) ;
730 			break;
731 		}
732 	} else {
733 		/* make */
734 		dt = dt & 0x7f ;
735 		switch (action[dt]) {
736 		/* LOCKING KEYS */
737 		case NUM: num ^= 1; update_led(); break;
738 		case CPS: caps ^= 1; update_led(); break;
739 		case SCROLL: scroll ^= 1; update_led(); break;
740 		case STP: stp ^= 1; if(stp) goto loop; break;
741 
742 		/* NON-LOCKING KEYS */
743 		case SHF: shfts = 1; break;
744 		case ALT: alts = 1; break;
745 		case CTL: ctls = 1; break;
746 		case ASCII:
747 			if (shfts) dt = shift[dt];
748 			else if (ctls) dt = ctl[dt];
749 			else dt = unshift[dt];
750 			if (caps && (dt >= 'a' && dt <= 'z')) dt -= 'a' - 'A';
751 			return(dt);
752 		}
753 	}
754 	if (noblock) return (0x100); else goto loop;
755 }
756 
757 pg(p,q,r,s,t,u,v,w,x,y,z) char *p; {
758 	printf(p,q,r,s,t,u,v,w,x,y,z);
759 	printf("\n");
760 	return(getchar());
761 }
762 
763 /* special characters */
764 #define bs	8
765 #define lf	10
766 #define cr	13
767 #define cntlc	3
768 #define del	0177
769 #define cntld	4
770 
771 getchar()
772 {
773 	register char thechar;
774 	register delay;
775 	int x;
776 
777 	pcconsoftc.cs_flags |= CSF_POLLING;
778 	x=splhigh();
779 	sput('>',0x6);
780 	/*while (1) {*/
781 		thechar = (char) sgetc(0);
782 		pcconsoftc.cs_flags &= ~CSF_POLLING;
783 		splx(x);
784 		switch (thechar) {
785 		    default: if (thechar >= ' ')
786 			     	sput(thechar,0x6);
787 			     return(thechar);
788 		    case cr:
789 		    case lf: sput(cr,0x6);
790 			     sput(lf,0x6);
791 			     return(lf);
792 		    case bs:
793 		    case del:
794 			     sput(bs,0x6);
795 			     sput(' ',0x6);
796 			     sput(bs,0x6);
797 			     return(thechar);
798 		    /*case cntlc:
799 			     sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ;
800 			     _exit(-2) ; */
801 		    case cntld:
802 			     sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ;
803 			     return(0);
804 		}
805 	/*}*/
806 }
807 
808 #include "machine/dbg.h"
809 #include "machine/stdarg.h"
810 static nrow;
811 
812 void
813 #ifdef __STDC__
814 dprintf(unsigned flgs, const char *fmt, ...)
815 #else
816 dprintf(flgs, fmt /*, va_alist */)
817         char *fmt;
818 	unsigned flgs;
819 #endif
820 {	extern unsigned __debug;
821 	va_list ap;
822 
823 	if((flgs&__debug) > DPAUSE) {
824 		__color = ffs(flgs&__debug)+1;
825 		va_start(ap,fmt);
826 		kprintf(fmt, 1, (struct tty *)0, ap);
827 		va_end(ap);
828 	if (flgs&DPAUSE || nrow%24 == 23) {
829 		int x;
830 		x = splhigh();
831 		if (nrow%24 == 23) nrow = 0;
832 		sgetc(0);
833 		splx(x);
834 	}
835 	}
836 	__color = 0;
837 }
838 
839 consinit() {}
840