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