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