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