xref: /386bsd/usr/src/kernel/pccons/pccons.c (revision a2142627)
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	$Id: pccons.c,v 1.5 94/07/27 16:45:03 bill Exp Locker: bill $
37  */
38 
39 /*
40  * code to work keyboard & display for PC-style console
41  */
42 
43 /* standard ISA/AT configuration: */
44 static char *pc_config =
45 	"pccons	12 (0x60 1 -1 0xb8000 65536).	# console video $Revision: 1.5 $";
46 /* default console device */
47 static char *pc_console_config =
48 	"console default 0.";
49 
50 #include "sys/param.h"
51 #include "sys/ioctl.h"
52 #include "proc.h"
53 #include "sys/file.h"
54 #include "sys/user.h"
55 #include "tty.h"
56 #include "uio.h"
57 #include "isa_driver.h"
58 #include "callout.h"
59 #include "systm.h"
60 #include "kernel.h"
61 #include "sys/syslog.h"
62 #include "isa_irq.h"
63 #include "isa_stdports.h"
64 #include "modconfig.h"
65 #include "machine/icu.h"
66 #include "i8042.h"
67 #include "isa_kbd.h"
68 #include "isa_display.h"
69 
70 #include "prototypes.h"
71 #include "machine/inline/io.h"
72 
73 int pc_xmode;
74 int _debug_mode_;
75 struct	tty pccons;
76 
77 struct	pcconsoftc {
78 	char	cs_flags;
79 #define	CSF_ACTIVE	0x1	/* timeout active */
80 #define	CSF_POLLING	0x2	/* polling for input */
81 	char	cs_lastc;	/* last char sent */
82 	int	cs_timo;	/* timeouts since interrupt */
83 	u_long	cs_wedgecnt;	/* times restarted */
84 } pcconsoftc;
85 
86 struct	kbdsoftc {
87 	char	kbd_flags;
88 #define	KBDF_ACTIVE	0x1	/* timeout active */
89 #define	KBDF_POLLING	0x2	/* polling for input */
90 #define	KBDF_RAW	0x4	/* pass thru scan codes for input */
91 	char	kbd_lastc;	/* last char sent */
92 } kbdsoftc;
93 
94 static struct video_state {
95 	char	esc;	/* seen escape */
96 	char	ebrac;	/* seen escape bracket */
97 	char	eparm;	/* seen escape and parameters */
98 	char	so;	/* in standout mode? */
99 	int 	cx;	/* "x" parameter */
100 	int 	cy;	/* "y" parameter */
101 	int 	row, col;	/* current cursor position */
102 	int 	nrow, ncol;	/* current screen geometry */
103 	char	fg_at, bg_at;	/* normal attributes */
104 	char	so_at;	/* standout attribute */
105 	char	kern_fg_at, kern_bg_at;
106 	char	color;	/* color or mono display */
107 } vs;
108 
109 int pcprobe(struct isa_device *dev);
110 void pcattach(struct isa_device *dev);
111 void pcrint(int dev);
112 
113 struct	isa_driver pcdriver = {
114 	pcprobe, pcattach, pcrint, "pc", &ttymask
115 };
116 
117 /* block cursor so wfj does not go blind on laptop hunting for
118 	the verdamnt cursor -wfj */
119 /* #define	FAT_CURSOR */
120 
121 #define	COL		80
122 #define	ROW		25
123 #define	CHR		2
124 #define MONO_BASE	0x3B4
125 #define MONO_BUF	0xfe0B0000
126 #define CGA_BASE	0x3D4
127 #define CGA_BUF		0xfe0B8000
128 #define IOPHYSMEM	0xA0000
129 
130 static unsigned int addr_6845 = MONO_BASE;
131 u_short *Crtat = (u_short *)MONO_BUF;
132 static openf;
133 
134 char *sgetc(int);
135 static	char	*more_chars;
136 static	int	char_count;
137 
138 /*
139  * We check the console periodically to make sure
140  * that it hasn't wedged.  Unfortunately, if an XOFF
141  * is typed on the console, that can't be distinguished
142  * from more catastrophic failure.
143  */
144 #define	CN_TIMERVAL	(hz)		/* frequency at which to check cons */
145 #define	CN_TIMO		(2*60)		/* intervals to allow for output char */
146 
147 int	pcstart();
148 int	pcparam();
149 char	partab[];
150 
151 extern pcopen(dev_t, int, int, struct proc *);
152 /*
153  * Wait for CP to accept last CP command sent
154  * before setting up next command.
155  */
156 #define	waitforlast(timo) { \
157 	if (pclast) { \
158 		(timo) = 10000; \
159 		do \
160 			uncache((char *)&pclast->cp_unit); \
161 		while ((pclast->cp_unit&CPTAKE) == 0 && --(timo)); \
162 	} \
163 }
164 
165 unsigned kbd_rd(), kbd_cmd_read_param();
166 
167 /*
168  * these are both bad jokes
169  */
170 int
pcprobe(struct isa_device * dev)171 pcprobe(struct isa_device *dev)
172 {
173 	unsigned c;
174 	int again = 0;
175 
176 if(dev->id_unit == 1) {
177 int i;
178 
179 /*outb(0x2fa,0x55);
180 outb(0x3fa,0xaa);
181 outb(0x3fa,0x36);
182 outb(0x3fa,0xe4);
183 outb(0x2fa,0x1b);
184 outb(0x2fa,0x36); */
185 printf("\n[");
186 for(i=0; i < 16; i++) {
187 outb(0x390, i);
188 printf("%x ", inb(0x391));
189 }
190 printf("]\n");
191 outb(0x311, 0x88);
192 DELAY(250);
193 outb(0x311, 0x80);
194 DELAY(2500);
195 while((inb(0x311)&4)==0) ;
196 outb(0x310, 0xf4);
197 while((inb(0x311)&4)==0) ;
198 outb(0x311, 0x90);
199 return(1);
200 }
201 
202 	(void)kbd_drain();
203 	kbd_cmd(K_DISKEY);
204 	kbd_cmd(K_DISAUX);
205 
206 	/* disable interrupts and keyboard controller */
207 	kbd_cmd_write_param(K_WRITE + K__CMDBYTE, DISABLE_CMDBYTE);
208 
209 	/* are we a type 1 or type 2 ? */
210 	if ((kbd_cmd_read_param(K_READ + K__CMDBYTE) & KC8_TRANS) !=  KC8_TRANS)
211 		printf(" type 2 ");
212 
213 	/* Start keyboard stuff RESET */
214 	if ((c = key_cmd(KBC_RESET)) != KBR_RSTDONE && c != KBR_ACK) {
215 		if ((c == KBR_RESEND) ||  (c == KBR_OVERRUN)) {
216 			DELAY(400);
217 		}
218 	}
219 #ifdef nope
220 
221 	/* pick up keyboard reset return code */
222 	if((c = kbd_rd()) != KBR_RSTDONE)
223 		printf("keyboard failed selftest (%x) \n", c);
224 
225 kbd_drain();
226 
227 #endif
228 	kbd_cmd(K_DISKEY);
229 	kbd_cmd(K_ENAAUX);
230 
231 	/* if(aux_cmd(0xff) != KBR_ACK)
232 		printf("!"); */
233 	/* if((c = kbd_rd()) != KBR_RSTDONE)
234 		printf("aux failed selftest (%x) \n", c); */
235 printf("9");
236 	if(aux_cmd(0xf4) != KBR_ACK);
237 
238 	/* enable interrupts and keyboard controller */
239 	kbd_cmd_write_param(K_WRITE + K__CMDBYTE, ENABLE_CMDBYTE);
240 
241 	/* enable interrupts and keyboard controller */
242 	kbd_cmd_write_param(K_WRITE + K__CMDBYTE, 0x47);
243 
244 	printf (" kbd cmd %x %x ", kbd_cmd_read_param(K_READ + K__CMDBYTE),
245 		kbd_cmd_read_param(0xd0));
246 	kbd_cmd(K_DISAUX);
247 	return 1;
248 }
249 
250 void
pcattach(struct isa_device * dev)251 pcattach(struct isa_device *dev)
252 {
253 	u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR;
254 	u_short was;
255 
256 printf("pc0 ");
257 	if (vs.color == 0)
258 		printf("<mono>");
259 	else	printf("<color>");
260 	cursor(0);
261 }
262 
263 int
pcopen(dev_t dev,int flag,int mode,struct proc * p)264 pcopen(dev_t dev, int flag, int mode, struct proc *p)
265 {
266 	register struct tty *tp;
267 
268 	tp = &pccons;
269 	tp->t_oproc = pcstart;
270 	tp->t_stop = 0;
271 	tp->t_param = pcparam;
272 	tp->t_dev = dev;
273 	openf++;
274 	if ((tp->t_state & TS_ISOPEN) == 0) {
275 		tp->t_state |= TS_WOPEN;
276 		ttychars(tp);
277 		tp->t_iflag = TTYDEF_IFLAG;
278 		tp->t_oflag = TTYDEF_OFLAG;
279 		tp->t_cflag = TTYDEF_CFLAG;
280 		tp->t_lflag = TTYDEF_LFLAG;
281 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
282 		pcparam(tp, &tp->t_termios);
283 		ttsetwater(tp);
284 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
285 		return (EBUSY);
286 	tp->t_state |= TS_CARR_ON;
287 	return (ldiscif_open(dev, tp, flag));
288 	/*return ((*linesw[tp->t_line].l_open)(dev, tp, flag));*/
289 }
290 
291 int
pcclose(dev_t dev,int flag,int mode,struct proc * p)292 pcclose(dev_t dev, int flag, int mode, struct proc *p)
293 {
294 struct tty *tp = &pccons;
295 /*extern int xxxcons;*/
296 	/*if (flag & O_NONBLOCK) {		/* XXX */
297 	ldiscif_close(&pccons, flag);
298 	/* (*linesw[pccons.t_line].l_close)(&pccons, flag);*/
299 	ttyclose(&pccons);
300 	tp->t_state |= TS_CARR_ON;	/* XXX: rude X hanging bug fix */
301 	/*}*/
302 	pc_xmode_off();
303 	return(0);
304 }
305 
306 int
pcread(dev_t dev,struct uio * uio,int flag)307 pcread(dev_t dev, struct uio *uio, int flag)
308 {
309 	return (ldiscif_read(&pccons, uio, flag));
310 	/*return ((*linesw[pccons.t_line].l_read)(&pccons, uio, flag));*/
311 }
312 
313 int
pcwrite(dev_t dev,struct uio * uio,int flag)314 pcwrite(dev_t dev, struct uio *uio, int flag)
315 {
316 	return (ldiscif_write(&pccons, uio, flag));
317 	/*return ((*linesw[pccons.t_line].l_write)(&pccons, uio, flag));*/
318 }
319 
320 /*
321  * Got a console receive interrupt -
322  * the console processor wants to give us a character.
323  * Catch the character, and see who it goes to.
324  */
325 void
pcrint(int dev)326 pcrint(int dev)
327 {
328 	int c;
329 	char *cp;
330 
331 if(_debug_mode_) {
332 	(void)inb(KBSTATP);
333 		(void)inb(KBDATAP);
334 printf("*");
335 	return;
336 }
337 	cp = sgetc(1);
338 	if (cp == 0)
339 		return;
340 	if (pcconsoftc.cs_flags & CSF_POLLING)
341 		return;
342 #ifdef KDB
343 	if (kdbrintr(c, &pccons))
344 		return;
345 #endif
346 	if (!openf)
347 		return;
348 	do
349 		ldiscif_rint(*cp++ & 0xff, &pccons);
350 		/*(*linesw[pccons.t_line].l_rint)(*cp++ & 0xff, &pccons);*/
351 	while (*cp);
352 }
353 
354 #define CONSOLE_X_MODE_ON _IO('t',121)
355 #define CONSOLE_X_MODE_OFF _IO('t',122)
356 #define CONSOLE_X_MAP _IOR('t',123,char *)
357 
358 int
pcioctl(dev_t dev,int cmd,caddr_t addr,int flag,struct proc * p)359 pcioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
360 {
361 	register struct tty *tp = &pccons;
362 	register error;
363 
364 	if (cmd == CONSOLE_X_MODE_ON) {
365 		pc_xmode_on ();
366 		return (0);
367 	} else if (cmd == CONSOLE_X_MODE_OFF) {
368 		pc_xmode_off ();
369 		return (0);
370 	}
371 
372 	error = ldiscif_ioctl(tp, cmd, addr, flag, p);
373 	/*error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag);*/
374 	if (error >= 0)
375 		return (error);
376 	error = ttioctl(tp, cmd, addr, flag, p);
377 	if (error >= 0)
378 		return (error);
379 	return (ENOTTY);
380 }
381 
382 int	pcconsintr = 1;
383 /*
384  * Got a console transmission interrupt -
385  * the console processor wants another character.
386  */
pcxint(dev)387 pcxint(dev)
388 	dev_t dev;
389 {
390 	register struct tty *tp;
391 	register int unit;
392 
393 	if (!pcconsintr)
394 		return;
395 	pccons.t_state &= ~TS_BUSY;
396 	pcconsoftc.cs_timo = 0;
397 	if (pccons.t_line)
398 		ldiscif_start(&pccons);
399 		/*(*linesw[pccons.t_line].l_start)(&pccons);*/
400 	else
401 		pcstart(&pccons);
402 }
403 
pcstart(tp)404 pcstart(tp)
405 	register struct tty *tp;
406 {
407 	int c, s;
408 
409 	s = spltty();
410 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
411 		goto out;
412 	do {
413 	if (RB_LEN(&tp->t_out) <= tp->t_lowat) {
414 		if (tp->t_state&TS_ASLEEP) {
415 			tp->t_state &= ~TS_ASLEEP;
416 			wakeup((caddr_t)&tp->t_out);
417 		}
418 		if (tp->t_wsel) {
419 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
420 			tp->t_wsel = 0;
421 			tp->t_state &= ~TS_WCOLL;
422 		}
423 	}
424 	if (RB_LEN(&tp->t_out) == 0)
425 		goto out;
426 	c = getc(&tp->t_out);
427 	tp->t_state |= TS_BUSY;
428 	splx(s);
429 	sput(c, 0);
430 	(void)spltty();
431 	tp->t_state &= ~TS_BUSY;
432 	} while(1);
433 out:
434 	splx(s);
435 }
436 
437 static __color;
438 
439 /* ARGSUSED */
440 void
pccnputc(dev_t dev,unsigned c)441 pccnputc(dev_t dev, unsigned c)
442 {
443 	if (c == '\n')
444 		sput('\r', 1);
445 	sput(c, 1);
446 }
447 
448 /*
449  * Print a character on console.
450  */
pcputchar(c,tp)451 pcputchar(c, tp)
452 	char c;
453 	register struct tty *tp;
454 {
455 	sput(c, 1);
456 	/*if (c=='\n') getchar();*/
457 }
458 
459 
460 /* ARGSUSED */
461 int
pccngetc(dev_t dev)462 pccngetc(dev_t dev)
463 {
464 	register int s;
465 	register char *cp;
466 
467 	if (pc_xmode)
468 		return(0);
469 _debug_mode_ = 1;
470 	s = spltty();		/* block pcrint while we poll */
471 	cp = sgetc(0);
472 	splx(s);
473 _debug_mode_ = 0;
474 	if (cp == 0)
475 {
476 printf("+");
477 		return (0);
478 }
479 	if (*cp == '\r') return('\n');
480 	return (*cp);
481 }
482 
pcgetchar(tp)483 pcgetchar(tp)
484 	register struct tty *tp;
485 {
486 	char *cp;
487 
488 	if (pc_xmode)
489 		return(0);
490 	cp = sgetc(0);
491 	return (*cp&0xff);
492 }
493 
494 /*
495  * Set line parameters
496  */
pcparam(tp,t)497 pcparam(tp, t)
498 	register struct tty *tp;
499 	register struct termios *t;
500 {
501 	register int cflag = t->c_cflag;
502         /* and copy to tty */
503         tp->t_ispeed = t->c_ispeed;
504         tp->t_ospeed = t->c_ospeed;
505         tp->t_cflag = cflag;
506 
507 	return(0);
508 }
509 
510 #ifdef KDB
511 /*
512  * Turn input polling on/off (used by debugger).
513  */
pcpoll(onoff)514 pcpoll(onoff)
515 	int onoff;
516 {
517 }
518 #endif
519 
520 /*
521  * cursor():
522  *   reassigns cursor position, updated by the rescheduling clock
523  *   which is a index (0-1999) into the text area. Note that the
524  *   cursor is a "foreground" character, it's color determined by
525  *   the fg_at attribute. Thus if fg_at is left as 0, (FG_BLACK),
526  *   as when a portion of screen memory is 0, the cursor may dissappear.
527  */
528 
529 static u_short *crtat = 0;
530 
cursor(int a)531 cursor(int a)
532 { 	int pos = crtat - Crtat;
533 
534 	if (!pc_xmode) {
535 	outb(addr_6845, 14);
536 	outb(addr_6845+1, pos>> 8);
537 	outb(addr_6845, 15);
538 	outb(addr_6845+1, pos);
539 #ifdef	FAT_CURSOR
540 	outb(addr_6845, 10);
541 	outb(addr_6845+1, 0);
542 	outb(addr_6845, 11);
543 	outb(addr_6845+1, 18);
544 #endif	FAT_CURSOR
545 	}
546 	if (a == 0)
547 		timeout(cursor, 0, hz/10);
548 }
549 
550 /*
551  * Half-word fill function, like memset.
552  */
553 extern inline void
memsetw(void * toaddr,int pat,size_t maxlength)554 memsetw(void *toaddr, int pat, size_t maxlength) {
555 	void *t = toaddr;
556 
557 	/* construct pattern for fill */
558 	if (pat) {
559 		pat &= 0xffff;
560 		pat |= (pat<<16);
561 	}
562 
563 	/* fill by words first, then any remaining halfwords */
564 	asm volatile ("cld ; repe ; stosl" :
565 	    "=D" (t) : "0" (t), "c" (maxlength / 2), "a" (pat));
566 
567 	asm volatile ("repe ; stosw" :
568 	    "=D" (t) : "0" (t), "c" (maxlength & 1), "a" (pat));
569 }
570 
571 static u_char shift_down, ctrl_down, alt_down, caps, num, scroll;
572 
573 #define	wrtchar(c, at) \
574 	{ char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; }
575 
576 
577 /* translate ANSI color codes to standard pc ones */
578 static char fgansitopc[] =
579 {	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
580 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY};
581 
582 static char bgansitopc[] =
583 {	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
584 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY};
585 
586 /*
587  *   sput has support for emulation of the 'pc3' termcap entry.
588  *   if ka, use kernel attributes.
589  */
sput(c,ka)590 sput(c,  ka)
591 u_char c;
592 u_char ka;
593 {
594 
595 	int sc = 1;	/* do scroll check */
596 	char fg_at, bg_at, at;
597 
598 	if(pc_xmode) return;
599 
600 	if (crtat == 0)
601 	{
602 		u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR, was;
603 		unsigned cursorat;
604 
605 		/* check if mono */
606 		if ((rtcin(0x14) & 0x30) != 0x30) {
607 			/*Crtat = cp;*/
608 			addr_6845 = CGA_BASE;
609 			vs.color=1;
610 		} else {
611 			addr_6845 = MONO_BASE;
612 			vs.color=0;
613 		}
614 #ifdef nope
615 addr_6845 = MONO_BASE;
616 /*Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR;*/
617 #endif
618 		/*
619 		 *   Crtat  initialized  to  point  to  MONO  buffer  if not present
620 		 *   change   to  CGA_BUF  offset  ONLY  ADD  the  difference  since
621 		 *   locore.s adds in the remapped offset at the right time
622 		 */
623 
624 		was = *cp;
625 		*cp = (u_short) 0xA55A;
626 		if (*cp != 0xA55A) {
627 			addr_6845 = MONO_BASE;
628 			vs.color=0;
629 		} else {
630 			*cp = was;
631 			addr_6845 = CGA_BASE;
632 			Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR;
633 			vs.color=1;
634 		}
635 		/* Extract cursor location */
636 		outb(addr_6845,14);
637 		cursorat = inb(addr_6845+1)<<8 ;
638 		outb(addr_6845,15);
639 		cursorat |= inb(addr_6845+1);
640 
641 		crtat = Crtat + cursorat;
642 		vs.ncol = COL;
643 		vs.nrow = ROW;
644 		vs.fg_at = FG_LIGHTGREY;
645 		vs.bg_at = BG_BLACK;
646 
647 		if (vs.color == 0) {
648 			vs.kern_fg_at = FG_INTENSE;
649 			vs.so_at = FG_BLACK | BG_LIGHTGREY;
650 		} else {
651 			vs.kern_fg_at = FG_LIGHTGREY;
652 			vs.so_at = FG_YELLOW | BG_BLACK;
653 		}
654 		vs.kern_bg_at = BG_BLACK;
655 
656 		memsetw(crtat, ((vs.bg_at|vs.fg_at)<<8)|' ', COL*ROW-cursorat);
657 	}
658 
659 	/* which attributes do we use? */
660 	if (ka) {
661 		fg_at = vs.kern_fg_at;
662 		bg_at = vs.kern_bg_at;
663 	} else {
664 		fg_at = vs.fg_at;
665 		bg_at = vs.bg_at;
666 	}
667 	at = fg_at|bg_at;
668 
669 	switch(c) {
670 		int inccol;
671 
672 	case 0x1B:
673 		if(vs.esc)
674 			wrtchar(c, vs.so_at);
675 		vs.esc = 1; vs.ebrac = 0; vs.eparm = 0;
676 		break;
677 
678 	case '\t':
679 		inccol = (8 - vs.col % 8);	/* non-destructive tab */
680 		crtat += inccol;
681 		vs.col += inccol;
682 		break;
683 
684 	case '\010':
685 		crtat--; vs.col--;
686 		if (vs.col < 0) vs.col += vs.ncol;  /* non-destructive backspace */
687 		break;
688 
689 	case '\r':
690 		crtat -=  (crtat - Crtat) % vs.ncol; vs.col = 0;
691 		break;
692 
693 	case '\n':
694 		crtat += vs.ncol ;
695 		break;
696 
697 	default:
698 	bypass:
699 		if (vs.esc) {
700 			if (vs.ebrac) {
701 				switch(c) {
702 					int pos;
703 				case 'm':
704 					if (!vs.cx) vs.so = 0;
705 					else vs.so = 1;
706 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
707 					break;
708 				case 'A': /* back cx rows */
709 					if (vs.cx <= 0) vs.cx = 1;
710 					pos = crtat - Crtat;
711 					pos -= vs.ncol * vs.cx;
712 					if (pos < 0)
713 						pos += vs.nrow * vs.ncol;
714 					crtat = Crtat + pos;
715 					sc = vs.esc = vs.ebrac = vs.eparm = 0;
716 					break;
717 				case 'B': /* down cx rows */
718 					if (vs.cx <= 0) vs.cx = 1;
719 					pos = crtat - Crtat;
720 					pos += vs.ncol * vs.cx;
721 					if (pos >= vs.nrow * vs.ncol)
722 						pos -= vs.nrow * vs.ncol;
723 					crtat = Crtat + pos;
724 					sc = vs.esc = vs.ebrac = vs.eparm = 0;
725 					break;
726 				case 'C': /* right cursor */
727 					if (vs.cx <= 0)
728 						vs.cx = 1;
729 					pos = crtat - Crtat;
730 					pos += vs.cx; vs.col += vs.cx;
731 					if (vs.col >= vs.ncol) {
732 						vs.col -= vs.ncol;
733 						pos -= vs.ncol;     /* cursor stays on same line */
734 					}
735 					crtat = Crtat + pos;
736 					sc = vs.esc = vs.ebrac = vs.eparm = 0;
737 					break;
738 				case 'D': /* left cursor */
739 					if (vs.cx <= 0)
740 						vs.cx = 1;
741 					pos = crtat - Crtat;
742 					pos -= vs.cx; vs.col -= vs.cx;
743 					if (vs.col < 0) {
744 						vs.col += vs.ncol;
745 						pos += vs.ncol;     /* cursor stays on same line */
746 					}
747 					crtat = Crtat + pos;
748 					sc = vs.esc = vs.ebrac = vs.eparm = 0;
749 					break;
750 				case 'J': /* Clear ... */
751 					if (vs.cx == 0)
752 						/* ... to end of display */
753 						memsetw(crtat, (at << 8) + ' ',
754 							Crtat + vs.ncol * vs.nrow - crtat);
755 					else if (vs.cx == 1)
756 						/* ... to next location */
757 						memsetw(Crtat, (at << 8) + ' ',
758 							crtat - Crtat + 1);
759 					else if (vs.cx == 2)
760 						/* ... whole display */
761 						memsetw(Crtat, (at << 8) + ' ',
762 							vs.ncol * vs.nrow);
763 
764 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
765 					break;
766 				case 'K': /* Clear line ... */
767 					if (vs.cx == 0)
768 						/* ... current to EOL */
769 						memsetw(crtat, (at << 8) + ' ',
770 							vs.ncol - (crtat - Crtat) % vs.ncol);
771 					else if (vs.cx == 1)
772 						/* ... beginning to next */
773 						memsetw(crtat - (crtat - Crtat) % vs.ncol,
774 							(at << 8) + ' ',
775 							((crtat - Crtat) % vs.ncol) + 1);
776 					else if (vs.cx == 2)
777 						/* ... entire line */
778 						memsetw(crtat - (crtat - Crtat) % vs.ncol,
779 							(at << 8) + ' ',
780 							vs.ncol);
781 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
782 					break;
783 				case 'f': /* in system V consoles */
784 				case 'H': /* Cursor move */
785 					if ((!vs.cx)||(!vs.cy)) {
786 						crtat = Crtat;
787 						vs.col = 0;
788 					} else {
789 						crtat = Crtat + (vs.cx - 1) * vs.ncol + vs.cy - 1;
790 						vs.col = vs.cy - 1;
791 					}
792 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
793 					break;
794 				case 'S':  /* scroll up cx lines */
795 					if (vs.cx <= 0) vs.cx = 1;
796 					memcpy(Crtat, Crtat+vs.ncol*vs.cx, vs.ncol*(vs.nrow-vs.cx)*CHR);
797 					memsetw(Crtat+vs.ncol*(vs.nrow-vs.cx),
798 						(at <<8)+' ', vs.ncol*vs.cx);
799 					/* crtat -= vs.ncol*vs.cx; /* XXX */
800 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
801 					break;
802 				case 'M': /* delete line. */
803 					vs.row = (crtat - Crtat) / vs.ncol;
804 					if (vs.row + 1 < vs.nrow) {
805 						memcpy(Crtat+vs.ncol*vs.row,
806 							Crtat+vs.ncol*(vs.row+1),
807 						(vs.nrow-(vs.row+1)) * vs.ncol * CHR);
808 					}
809 					memsetw(Crtat+vs.ncol*(vs.nrow-1), (at <<8)+' ', vs.ncol);
810 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
811 					break;
812 				case 'T':  /* scroll down cx lines */
813 					if (vs.cx <= 0) vs.cx = 1;
814 					memmove(Crtat+vs.ncol*vs.cx, Crtat, vs.ncol*(vs.nrow-vs.cx)*CHR);
815 					memsetw(Crtat, (at <<8)+' ',
816 						vs.ncol*vs.cx);
817 					/* crtat += vs.ncol*vs.cx; /* XXX */
818 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
819 					break;
820 				case 'L' : /* insert line */
821 					vs.row = (crtat- Crtat) / vs.ncol;
822 					if (vs.row +1 < vs.nrow) {
823 						memmove (Crtat+vs.ncol*(vs.row+1),
824 						Crtat+vs.ncol*vs.row,
825 						(vs.nrow-(vs.row+1)) * vs.ncol * CHR);
826 					}
827 					memsetw(Crtat+vs.ncol*vs.row, (at <<8)+' ',
828  						vs.ncol);
829 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
830 					break;
831 				case ';': /* Switch params in cursor def */
832 					vs.eparm = 1;
833 					break;
834 				case 'r':
835 					vs.so_at = (vs.cx & 0x0f) | ((vs.cy & 0x0f) << 4);
836 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
837 					break;
838 				case 'x': /* set attributes */
839 					switch (vs.cx) {
840 					case 0:
841 						/* reset to normal attributes */
842 						bg_at = BG_BLACK;
843 						if (ka)
844 							fg_at = vs.color? FG_LIGHTGREY: FG_UNDERLINE;
845 						else
846 							fg_at = FG_LIGHTGREY;
847 						break;
848 					case 1:
849 						/* ansi background */
850 						if (vs.color)
851 							bg_at = bgansitopc[vs.cy & 7];
852 						break;
853 					case 2:
854 						/* ansi foreground */
855 						if (vs.color)
856 							fg_at = fgansitopc[vs.cy & 7];
857 						break;
858 					case 3:
859 						/* pc text attribute */
860 						if (vs.eparm) {
861 							fg_at = vs.cy & 0x8f;
862 							bg_at = vs.cy & 0x70;
863 						}
864 						break;
865 					}
866 					if (ka) {
867 						vs.kern_fg_at = fg_at;
868 						vs.kern_bg_at = bg_at;
869 					} else {
870 						vs.fg_at = fg_at;
871 						vs.bg_at = bg_at;
872 					}
873 					vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
874 					break;
875 
876 				default: /* Only numbers valid here */
877 					if ((c >= '0')&&(c <= '9')) {
878 						if (vs.eparm) {
879 							vs.cy *= 10;
880 							vs.cy += c - '0';
881 						} else {
882 							vs.cx *= 10;
883 							vs.cx += c - '0';
884 						}
885 					} else {
886 						vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
887 					}
888 					break;
889 				}
890 				break;
891 			} else if (c == 'c') { /* Clear screen & home */
892 				memsetw(Crtat, (at << 8) + ' ', vs.ncol*vs.nrow);
893 				crtat = Crtat; vs.col = 0;
894 				vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
895 			} else if (c == '[') { /* Start ESC [ sequence */
896 				vs.ebrac = 1; vs.cx = 0; vs.cy = 0; vs.eparm = 0;
897 			} else { /* Invalid, clear state */
898 				 vs.esc = 0; vs.ebrac = 0; vs.eparm = 0;
899 					wrtchar(c, vs.so_at);
900 			}
901 		} else {
902 			if (c == 7)
903 				sysbeep(0x31b, hz/4);
904 			else {
905 				if (vs.so) {
906 					wrtchar(c, vs.so_at);
907 				} else
908 					wrtchar(c, at);
909 				if (vs.col >= vs.ncol) {
910 					/*crtat -=  (crtat - Crtat) % vs.ncol;*/
911 					vs.col = 0;
912 				}
913 				break ;
914 			}
915 		}
916 	}
917 	if (sc && crtat >= Crtat+vs.ncol*vs.nrow) { /* scroll check */
918 		if (openf) do (void)sgetc(1); while (scroll);
919 		memcpy(Crtat, Crtat+vs.ncol, vs.ncol*(vs.nrow-1)*CHR);
920 		memsetw(Crtat + vs.ncol*(vs.nrow-1), (at << 8) + ' ',
921 			vs.ncol);
922 		crtat -= vs.ncol;
923 	}
924 	if (ka)
925 		cursor(1);
926 }
927 
928 
929 unsigned	__debug = 0; /*0xffe */;
930 static char scantokey[] = {
931 0,
932 120,	/* F9 */
933 0,
934 116,	/* F5 */
935 114,	/* F3 */
936 112,	/* F1 */
937 113,	/* F2 */
938 123,	/* F12 */
939 0,
940 121,	/* F10 */
941 119,	/* F8 */
942 117,	/* F6 */
943 115,	/* F4 */
944 16,	/* TAB */
945 1,	/* ` */
946 0,
947 0,
948 60,	/* ALT (left) */
949 44,	/* SHIFT (left) */
950 0,
951 58,	/* CTRL (left) */
952 17,	/* Q */
953 2,	/* 1 */
954 0,
955 0,
956 0,
957 46,	/* Z */
958 32,	/* S */
959 31,	/* A */
960 18,	/* W */
961 3,	/* 2 */
962 0,
963 0,
964 48,	/* C */
965 47,	/* X */
966 33,	/* D */
967 19,	/* E */
968 5,	/* 4 */
969 4,	/* 3 */
970 0,
971 0,
972 61,	/* SPACE */
973 49,	/* V */
974 34,	/* F */
975 21,	/* T */
976 20,	/* R */
977 6,	/* 5 */
978 0,
979 0,
980 51,	/* N */
981 50,	/* B */
982 36,	/* H */
983 35,	/* G */
984 22,	/* Y */
985 7,	/* 6 */
986 0,
987 0,
988 0,
989 52,	/* M */
990 37,	/* J */
991 23,	/* U */
992 8,	/* 7 */
993 9,	/* 8 */
994 0,
995 0,
996 53,	/* , */
997 38,	/* K */
998 24,	/* I */
999 25,	/* O */
1000 11,	/* 0 */
1001 10,	/* 9 */
1002 0,
1003 0,
1004 54,	/* . */
1005 55,	/* / */
1006 39,	/* L */
1007 40,	/* ; */
1008 26,	/* P */
1009 12,	/* - */
1010 0,
1011 0,
1012 0,
1013 41,	/* " */
1014 0,
1015 27,	/* [ */
1016 13,	/* + */
1017 0,
1018 0,
1019 0,
1020 57,	/* SHIFT (right) */
1021 43,	/* ENTER */
1022 28,	/* ] */
1023 0,
1024 29,	/* \ */
1025 0,
1026 0,
1027 0,
1028 45,	/* na*/
1029 0,
1030 0,
1031 0,
1032 0,
1033 15,	/* backspace */
1034 0,
1035 0,				/* keypad */
1036 93,	/* 1 */
1037 0,
1038 92,	/* 4 */
1039 91,	/* 7 */
1040 0,
1041 0,
1042 0,
1043 99,	/* 0 */
1044 104,	/* . */
1045 98,	/* 2 */
1046 97,	/* 5 */
1047 102,	/* 6 */
1048 96,	/* 8 */
1049 110,	/* ESC */
1050 90,	/* Num Lock */
1051 122,	/* F11 */
1052 106,	/* + */
1053 103,	/* 3 */
1054 105,	/* - */
1055 100,	/* * */
1056 101,	/* 9 */
1057 0,
1058 0,
1059 0,
1060 0,
1061 0,
1062 118,	/* F7 */
1063 };
1064 static char extscantokey[] = {
1065 0,
1066 120,	/* F9 */
1067 0,
1068 116,	/* F5 */
1069 114,	/* F3 */
1070 112,	/* F1 */
1071 113,	/* F2 */
1072 123,	/* F12 */
1073 0,
1074 121,	/* F10 */
1075 119,	/* F8 */
1076 117,	/* F6 */
1077 115,	/* F4 */
1078 16,	/* TAB */
1079 1,	/* ` */
1080 0,
1081 0,
1082  62,	/* ALT (right) */
1083  124,	/* Print Screen */
1084 0,
1085  64,	/* CTRL (right) */
1086 17,	/* Q */
1087 2,	/* 1 */
1088 0,
1089 0,
1090 0,
1091 46,	/* Z */
1092 32,	/* S */
1093 31,	/* A */
1094 18,	/* W */
1095 3,	/* 2 */
1096 0,
1097 0,
1098 48,	/* C */
1099 47,	/* X */
1100 33,	/* D */
1101 19,	/* E */
1102 5,	/* 4 */
1103 4,	/* 3 */
1104 0,
1105 0,
1106 61,	/* SPACE */
1107 49,	/* V */
1108 34,	/* F */
1109 21,	/* T */
1110 20,	/* R */
1111 6,	/* 5 */
1112 0,
1113 0,
1114 51,	/* N */
1115 50,	/* B */
1116 36,	/* H */
1117 35,	/* G */
1118 22,	/* Y */
1119 7,	/* 6 */
1120 0,
1121 0,
1122 0,
1123 52,	/* M */
1124 37,	/* J */
1125 23,	/* U */
1126 8,	/* 7 */
1127 9,	/* 8 */
1128 0,
1129 0,
1130 53,	/* , */
1131 38,	/* K */
1132 24,	/* I */
1133 25,	/* O */
1134 11,	/* 0 */
1135 10,	/* 9 */
1136 0,
1137 0,
1138 54,	/* . */
1139  95,	/* / */
1140 39,	/* L */
1141 40,	/* ; */
1142 26,	/* P */
1143 12,	/* - */
1144 0,
1145 0,
1146 0,
1147 41,	/* " */
1148 0,
1149 27,	/* [ */
1150 13,	/* + */
1151 0,
1152 0,
1153 0,
1154 57,	/* SHIFT (right) */
1155  108,	/* ENTER */
1156 28,	/* ] */
1157 0,
1158 29,	/* \ */
1159 0,
1160 0,
1161 0,
1162 45,	/* na*/
1163 0,
1164 0,
1165 0,
1166 0,
1167 15,	/* backspace */
1168 0,
1169 0,				/* keypad */
1170  81,	/* end */
1171 0,
1172  79,	/* left arrow */
1173  80,	/* home */
1174 0,
1175 0,
1176 0,
1177  75,	/* ins */
1178  76,	/* del */
1179  84,	/* down arrow */
1180 97,	/* 5 */
1181  89,	/* right arrow */
1182  83,	/* up arrow */
1183 110,	/* ESC */
1184 90,	/* Num Lock */
1185 122,	/* F11 */
1186 106,	/* + */
1187  86,	/* page down */
1188 105,	/* - */
1189  124,	/* print screen */
1190  85,	/* page up */
1191 0,
1192 0,
1193 0,
1194 0,
1195 0,
1196 118,	/* F7 */
1197 };
1198 #define	CODE_SIZE	4		/* Use a max of 4 for now... */
1199 typedef struct
1200 {
1201 	u_short	type;
1202 	char	unshift[CODE_SIZE];
1203 	char	shift[CODE_SIZE];
1204 	char	ctrl[CODE_SIZE];
1205 } Scan_def;
1206 
1207 #define	SHIFT		0x0002	/* keyboard shift */
1208 #define	ALT		0x0004	/* alternate shift -- alternate chars */
1209 #define	NUM		0x0008	/* numeric shift  cursors vs. numeric */
1210 #define	CTL		0x0010	/* control shift  -- allows ctl function */
1211 #define	CAPS		0x0020	/* caps shift -- swaps case of letter */
1212 #define	ASCII		0x0040	/* ascii code for this key */
1213 #define	SCROLL		0x0080	/* stop output */
1214 #define	FUNC		0x0100	/* function key */
1215 #define	KP		0x0200	/* Keypad keys */
1216 #define	NONE		0x0400	/* no function */
1217 
1218 static Scan_def	scan_codes[] =
1219 {
1220 	NONE,	"",		"",		"",		/* 0 unused */
1221 	ASCII,	"\033",		"\033",		"\033",		/* 1 ESCape */
1222 	ASCII,	"1",		"!",		"!",		/* 2 1 */
1223 	ASCII,	"2",		"@",		"\000",		/* 3 2 */
1224 	ASCII,	"3",		"#",		"#",		/* 4 3 */
1225 	ASCII,	"4",		"$",		"$",		/* 5 4 */
1226 	ASCII,	"5",		"%",		"%",		/* 6 5 */
1227 	ASCII,	"6",		"^",		"\036",		/* 7 6 */
1228 	ASCII,	"7",		"&",		"&",		/* 8 7 */
1229 	ASCII,	"8",		"*",		"\010",		/* 9 8 */
1230 	ASCII,	"9",		"(",		"(",		/* 10 9 */
1231 	ASCII,	"0",		")",		")",		/* 11 0 */
1232 	ASCII,	"-",		"_",		"\037",		/* 12 - */
1233 	ASCII,	"=",		"+",		"+",		/* 13 = */
1234 	ASCII,	"\177",		"\177",		"\010",		/* 14 backspace */
1235 	ASCII,	"\t",		"\177\t",	"\t",		/* 15 tab */
1236 	ASCII,	"q",		"Q",		"\021",		/* 16 q */
1237 	ASCII,	"w",		"W",		"\027",		/* 17 w */
1238 	ASCII,	"e",		"E",		"\005",		/* 18 e */
1239 	ASCII,	"r",		"R",		"\022",		/* 19 r */
1240 	ASCII,	"t",		"T",		"\024",		/* 20 t */
1241 	ASCII,	"y",		"Y",		"\031",		/* 21 y */
1242 	ASCII,	"u",		"U",		"\025",		/* 22 u */
1243 	ASCII,	"i",		"I",		"\011",		/* 23 i */
1244 	ASCII,	"o",		"O",		"\017",		/* 24 o */
1245 	ASCII,	"p",		"P",		"\020",		/* 25 p */
1246 	ASCII,	"[",		"{",		"\033",		/* 26 [ */
1247 	ASCII,	"]",		"}",		"\035",		/* 27 ] */
1248 	ASCII,	"\r",		"\r",		"\n",		/* 28 return */
1249 	CTL,	"",		"",		"",		/* 29 control */
1250 	ASCII,	"a",		"A",		"\001",		/* 30 a */
1251 	ASCII,	"s",		"S",		"\023",		/* 31 s */
1252 	ASCII,	"d",		"D",		"\004",		/* 32 d */
1253 	ASCII,	"f",		"F",		"\006",		/* 33 f */
1254 	ASCII,	"g",		"G",		"\007",		/* 34 g */
1255 	ASCII,	"h",		"H",		"\010",		/* 35 h */
1256 	ASCII,	"j",		"J",		"\n",		/* 36 j */
1257 	ASCII,	"k",		"K",		"\013",		/* 37 k */
1258 	ASCII,	"l",		"L",		"\014",		/* 38 l */
1259 	ASCII,	";",		":",		";",		/* 39 ; */
1260 	ASCII,	"'",		"\"",		"'",		/* 40 ' */
1261 	ASCII,	"`",		"~",		"`",		/* 41 ` */
1262 	SHIFT,	"",		"",		"",		/* 42 shift */
1263 	ASCII,	"\\",		"|",		"\034",		/* 43 \ */
1264 	ASCII,	"z",		"Z",		"\032",		/* 44 z */
1265 	ASCII,	"x",		"X",		"\030",		/* 45 x */
1266 	ASCII,	"c",		"C",		"\003",		/* 46 c */
1267 	ASCII,	"v",		"V",		"\026",		/* 47 v */
1268 	ASCII,	"b",		"B",		"\002",		/* 48 b */
1269 	ASCII,	"n",		"N",		"\016",		/* 49 n */
1270 	ASCII,	"m",		"M",		"\r",		/* 50 m */
1271 	ASCII,	",",		"<",		"<",		/* 51 , */
1272 	ASCII,	".",		">",		">",		/* 52 . */
1273 	ASCII,	"/",		"?",		"\177",		/* 53 / */
1274 	SHIFT,	"",		"",		"",		/* 54 shift */
1275 	KP,	"*",		"*",		"*",		/* 55 kp * */
1276 	ALT,	"",		"",		"",		/* 56 alt */
1277 	ASCII,	" ",		" ",		" ",		/* 57 space */
1278 	CAPS,	"",		"",		"",		/* 58 caps */
1279 	FUNC,	"\033[M",	"\033[Y",	"\033[k",	/* 59 f1 */
1280 	FUNC,	"\033[N",	"\033[Z",	"\033[l",	/* 60 f2 */
1281 	FUNC,	"\033[O",	"\033[a",	"\033[m",	/* 61 f3 */
1282 	FUNC,	"\033[P",	"\033[b",	"\033[n",	/* 62 f4 */
1283 	FUNC,	"\033[Q",	"\033[c",	"\033[o",	/* 63 f5 */
1284 	FUNC,	"\033[R",	"\033[d",	"\033[p",	/* 64 f6 */
1285 	FUNC,	"\033[S",	"\033[e",	"\033[q",	/* 65 f7 */
1286 	FUNC,	"\033[T",	"\033[f",	"\033[r",	/* 66 f8 */
1287 	FUNC,	"\033[U",	"\033[g",	"\033[s",	/* 67 f9 */
1288 	FUNC,	"\033[V",	"\033[h",	"\033[t",	/* 68 f10 */
1289 	NUM,	"",		"",		"",		/* 69 num lock */
1290 	SCROLL,	"",		"",		"",		/* 70 scroll lock */
1291 	KP,	"7",		"\033[H",	"7",		/* 71 kp 7 */
1292 	KP,	"8",		"\033[A",	"8",		/* 72 kp 8 */
1293 	KP,	"9",		"\033[I",	"9",		/* 73 kp 9 */
1294 	KP,	"-",		"-",		"-",		/* 74 kp - */
1295 	KP,	"4",		"\033[D",	"4",		/* 75 kp 4 */
1296 	KP,	"5",		"\033[E",	"5",		/* 76 kp 5 */
1297 	KP,	"6",		"\033[C",	"6",		/* 77 kp 6 */
1298 	KP,	"+",		"+",		"+",		/* 78 kp + */
1299 	KP,	"1",		"\033[F",	"1",		/* 79 kp 1 */
1300 	KP,	"2",		"\033[B",	"2",		/* 80 kp 2 */
1301 	KP,	"3",		"\033[G",	"3",		/* 81 kp 3 */
1302 	KP,	"0",		"\033[L",	"0",		/* 82 kp 0 */
1303 	KP,	".",		"\177",		".",		/* 83 kp . */
1304 	NONE,	"",		"",		"",		/* 84 0 */
1305 	NONE,	"100",		"",		"",		/* 85 0 */
1306 	NONE,	"101",		"",		"",		/* 86 0 */
1307 	FUNC,	"\033[W",	"\033[i",	"\033[u",	/* 87 f11 */
1308 	FUNC,	"\033[X",	"\033[j",	"\033[v",	/* 88 f12 */
1309 	NONE,	"102",		"",		"",		/* 89 0 */
1310 	NONE,	"103",		"",		"",		/* 90 0 */
1311 	NONE,	"",		"",		"",		/* 91 0 */
1312 	NONE,	"",		"",		"",		/* 92 0 */
1313 	NONE,	"",		"",		"",		/* 93 0 */
1314 	NONE,	"",		"",		"",		/* 94 0 */
1315 	NONE,	"",		"",		"",		/* 95 0 */
1316 	NONE,	"",		"",		"",		/* 96 0 */
1317 	NONE,	"",		"",		"",		/* 97 0 */
1318 	NONE,	"",		"",		"",		/* 98 0 */
1319 	NONE,	"",		"",		"",		/* 99 0 */
1320 	NONE,	"",		"",		"",		/* 100 */
1321 	NONE,	"",		"",		"",		/* 101 */
1322 	NONE,	"",		"",		"",		/* 102 */
1323 	NONE,	"",		"",		"",		/* 103 */
1324 	NONE,	"",		"",		"",		/* 104 */
1325 	NONE,	"",		"",		"",		/* 105 */
1326 	NONE,	"",		"",		"",		/* 106 */
1327 	NONE,	"",		"",		"",		/* 107 */
1328 	NONE,	"",		"",		"",		/* 108 */
1329 	NONE,	"",		"",		"",		/* 109 */
1330 	NONE,	"",		"",		"",		/* 110 */
1331 	NONE,	"",		"",		"",		/* 111 */
1332 	NONE,	"",		"",		"",		/* 112 */
1333 	NONE,	"",		"",		"",		/* 113 */
1334 	NONE,	"",		"",		"",		/* 114 */
1335 	NONE,	"",		"",		"",		/* 115 */
1336 	NONE,	"",		"",		"",		/* 116 */
1337 	NONE,	"",		"",		"",		/* 117 */
1338 	NONE,	"",		"",		"",		/* 118 */
1339 	NONE,	"",		"",		"",		/* 119 */
1340 	NONE,	"",		"",		"",		/* 120 */
1341 	NONE,	"",		"",		"",		/* 121 */
1342 	NONE,	"",		"",		"",		/* 122 */
1343 	NONE,	"",		"",		"",		/* 123 */
1344 	NONE,	"",		"",		"",		/* 124 */
1345 	NONE,	"",		"",		"",		/* 125 */
1346 	NONE,	"",		"",		"",		/* 126 */
1347 	NONE,	"",		"",		"",		/* 127 */
1348 };
1349 
1350 
1351 
update_led()1352 update_led()
1353 {
1354 /*printf("- %x ",	kbd_cmd_read_param(K_READOUTP));
1355 	kbd_drain();
1356 	printf (" kbd %x ", kbd_cmd_read_param(K_READ + K__CMDBYTE));
1357 	kbd_drain();
1358 printf("|");
1359 	kbd_cmd_write_param(K_SIMAUXIN, 0x60);
1360 	kbd_drain();
1361 printf("|");
1362 	while(aux_cmd(0xf4) != KBR_ACK);
1363 	kbd_drain(); */
1364 	key_cmd(KBC_STSIND);			/* LED Command */
1365 	kbd_drain();
1366 	key_cmd(scroll | 2*num | 4*caps);
1367 	kbd_drain();
1368 }
1369 
1370 /*
1371  *   sgetc(noblock):  get  characters  from  the  keyboard.  If
1372  *   noblock  ==  0  wait  until a key is gotten. Otherwise return a
1373  *    if no characters are present 0.
1374  */
1375 char *
sgetc(noblock)1376 sgetc(noblock)
1377 {
1378 	u_char		dt, sts;
1379 	unsigned	key,op;
1380 	static u_char	extended = 0;
1381 	static char	capchar[2];
1382 
1383 	/*
1384 	 *   First see if there is something in the keyboard port
1385 	 */
1386 loop:
1387 	sts = inb(KBSTATP);
1388 	/*if ((sts & (KBS_AUXDIB|KBS_DIB)) == (KBS_AUXDIB|KBS_DIB)) {
1389 		printf("ax: ");
1390 	}
1391 	if (sts & KBS_DIB) {
1392 		printf(".");
1393 	}*/
1394 
1395 	if (sts & KBS_DIB)
1396 		dt = inb(KBDATAP);
1397 	else
1398 	{
1399 		if (noblock)
1400 			return 0;
1401 		else
1402 			goto loop;
1403 	}
1404 
1405 #ifdef futz
1406 	op = kbd_cmd_read_param(0xd0);
1407 	/* if((op & 0x10) == 0)
1408 		printf( "O%x ", op); */
1409 /* "off" on toshiba laptops 4400/4500 (mouse?) */
1410 /* "o7b" on compaq systempro */
1411 	if((op & 0x20) != 0)
1412 		printf( "o%x ", op);
1413 #endif
1414 
1415 	if (pc_xmode) { /* XXX char* what X expects to be returned? */
1416 		if (dt == 69)	/*numlock*/
1417 			pc_xmode = 0;
1418 		capchar[0] = dt;
1419 		capchar[1] = 0;
1420 		return (capchar);
1421 	}
1422 	if (dt == 0xe0)
1423 	{
1424 		extended = 1;
1425 		if (noblock)
1426 			return 0;
1427 		else
1428 			goto loop;
1429 	}
1430 
1431 	/*
1432 	 *   Check for cntl-alt-del
1433 	 */
1434 	if ((dt == 83) && ctrl_down && alt_down)
1435 		cpu_reset();
1436 	if ((dt == 69) && ctrl_down && alt_down)
1437 		pc_xmode = 1;
1438 
1439 #ifdef DDB
1440 	/*
1441 	 *   Check for cntl-alt-esc
1442 	 */
1443 	if ((dt&0x7f) == 1 && ctrl_down && alt_down && _debug_mode_ == 0) {
1444 		if (dt == 0x01) {
1445 			Debugger();
1446 		}
1447 		return (0);
1448 	}
1449 #endif
1450 
1451 #ifdef nope
1452 	if (pc_xmode) { /* XXX char* what X expects to be returned? */
1453 		capchar[0] = dt;
1454 		return (capchar);
1455 	}
1456 #endif
1457 
1458 	/*
1459 	 *   Check for make/break
1460 	 */
1461 	if (dt & 0x80)
1462 	{
1463 		/*
1464 		 *   break
1465 		 */
1466 		dt = dt & 0x7f;
1467 		switch (scan_codes[dt].type)
1468 		{
1469 			case SHIFT:
1470 				shift_down = 0;
1471 				break;
1472 			case ALT:
1473 				alt_down = 0;
1474 				break;
1475 			case CTL:
1476 				ctrl_down = 0;
1477 				break;
1478 		}
1479 	}
1480 	else
1481 	{
1482 		/*
1483 		 *   Make
1484 		 */
1485 		dt = dt & 0x7f;
1486 		switch (scan_codes[dt].type)
1487 		{
1488 			/*
1489 			 *   Locking keys
1490 			 */
1491 			case NUM:
1492 				num ^= 1;
1493 				update_led();
1494 				break;
1495 			case CAPS:
1496 				caps ^= 1;
1497 				update_led();
1498 				break;
1499 			case SCROLL:
1500 				scroll ^= 1;
1501 				update_led();
1502 				break;
1503 
1504 			/*
1505 			 *   Non-locking keys
1506 			 */
1507 			case SHIFT:
1508 				shift_down = 1;
1509 				break;
1510 			case ALT:
1511 				alt_down = 0x80;
1512 				break;
1513 			case CTL:
1514 				ctrl_down = 1;
1515 				break;
1516 			case ASCII:
1517 			case NONE:
1518 			case FUNC:
1519 				if (shift_down)
1520 					more_chars = scan_codes[dt].shift;
1521 				else if (ctrl_down)
1522 					more_chars = scan_codes[dt].ctrl;
1523 				else
1524 					more_chars = scan_codes[dt].unshift;
1525 				/* XXX */
1526 				if (caps && more_chars[1] == 0
1527 					&& (more_chars[0] >= 'a'
1528 						&& more_chars[0] <= 'z')) {
1529 					capchar[0] = *more_chars - ('a' - 'A');
1530 					more_chars = capchar;
1531 				}
1532 				extended = 0;
1533 				return(more_chars);
1534 			case KP:
1535 				if (shift_down || ctrl_down || !num || extended)
1536 					more_chars = scan_codes[dt].shift;
1537 				else
1538 					more_chars = scan_codes[dt].unshift;
1539 				extended = 0;
1540 				return(more_chars);
1541 		}
1542 	}
1543 	extended = 0;
1544 	if (noblock)
1545 		return 0;
1546 	else
1547 		goto loop;
1548 }
1549 
pg(p,q,r,s,t,u,v,w,x,y,z)1550 pg(p,q,r,s,t,u,v,w,x,y,z) char *p; {
1551 	printf(p,q,r,s,t,u,v,w,x,y,z);
1552 	printf("\n");
1553 	return(console_getchar());
1554 }
1555 
1556 /* special characters */
1557 #define bs	8
1558 #define lf	10
1559 #define cr	13
1560 #define cntlc	3
1561 #define del	0177
1562 #define cntld	4
1563 
getchar()1564 getchar()
1565 {
1566 	char	thechar;
1567 	register	delay;
1568 	int		x;
1569 
1570 	pcconsoftc.cs_flags |= CSF_POLLING;
1571 	x = splhigh();
1572 	sput('>', 1);
1573 	/*while (1) {*/
1574 		thechar = *(sgetc(0));
1575 		pcconsoftc.cs_flags &= ~CSF_POLLING;
1576 		splx(x);
1577 		switch (thechar) {
1578 		    default: if (thechar >= ' ')
1579 			     	sput(thechar, 1);
1580 			     return(thechar);
1581 		    case cr:
1582 		    case lf: sput('\r', 1);
1583 		    		sput('\n', 1);
1584 			     return(lf);
1585 		    case bs:
1586 		    case del:
1587 			     sput('\b', 1);
1588 			     sput(' ', 1);
1589 			     sput('\b', 1);
1590 			     return(thechar);
1591 		    case cntlc:
1592 			     sput('^', 1) ; sput('C', 1) ; sput('\r', 1) ; sput('\n', 1) ;
1593 			     cpu_reset();
1594 		    case cntld:
1595 			     sput('^', 1) ; sput('D', 1) ; sput('\r', 1) ; sput('\n', 1) ;
1596 			     return(0);
1597 		}
1598 	/*}*/
1599 }
1600 
1601 #include "machine/stdarg.h"
1602 static nrow;
1603 
1604 #define	DPAUSE 1
1605 void
1606 #ifdef __STDC__
dprintf(unsigned flgs,const char * fmt,...)1607 dprintf(unsigned flgs, const char *fmt, ...)
1608 #else
1609 dprintf(flgs, fmt /*, va_alist */)
1610         char *fmt;
1611 	unsigned flgs;
1612 #endif
1613 {	extern unsigned __debug;
1614 	va_list ap;
1615 
1616 	if((flgs&__debug) > DPAUSE) {
1617 		__color = ffs(flgs&__debug)+1;
1618 		va_start(ap,fmt);
1619 		kprintf(fmt, 1, (struct tty *)0, ap);
1620 		va_end(ap);
1621 	if (flgs&DPAUSE || nrow%24 == 23) {
1622 		int x;
1623 		x = splhigh();
1624 		if (nrow%24 == 23) nrow = 0;
1625 		(void)sgetc(0);
1626 		splx(x);
1627 	}
1628 	}
1629 	__color = 0;
1630 }
1631 
1632 
1633 #include "machine/psl.h"
1634 #include "machine/frame.h"
1635 
pc_xmode_on()1636 pc_xmode_on ()
1637 {
1638     struct syscframe *fp;
1639 
1640     if (pc_xmode)
1641             return;
1642     pc_xmode = 1;
1643 
1644     fp = (struct syscframe *)curproc->p_md.md_regs;
1645     fp->sf_eflags |= PSL_IOPL;
1646 }
1647 
pc_xmode_off()1648 pc_xmode_off ()
1649 {
1650     struct syscframe *fp;
1651 
1652     if (pc_xmode == 0)
1653             return;
1654     pc_xmode = 0;
1655 
1656     fp = (struct syscframe *)curproc->p_md.md_regs;
1657     fp->sf_eflags &= ~PSL_IOPL;
1658 }
1659 
pcmmap(dev_t dev,int offset,int nprot)1660 int pcmmap(dev_t dev, int offset, int nprot)
1661 {
1662 	if (offset > 0x20000)
1663 		return -1;
1664 	return i386_btop((0xa0000 + offset));
1665 }
1666 
1667 int
pcselect(dev_t dev,int rw,struct proc * p)1668 pcselect(dev_t dev, int rw, struct proc *p) {
1669 
1670 	return (ttselect(&pccons, rw, p));
1671 }
1672 
1673 
1674 struct devif pc_devif =
1675 {
1676 	{0}, -1, -2, 0, 0, 0, 0, 0, 0,
1677 	pcopen, pcclose, pcioctl, pcread, pcwrite, pcselect, pcmmap,
1678 	0, 0, 0, 0,
1679 	pccngetc,  pccnputc,
1680 };
1681 
DRIVER_MODCONFIG()1682 DRIVER_MODCONFIG() {
1683 	char *cfg_string = pc_config;
1684 
1685 	if (devif_config(&cfg_string, &pc_devif) == 0)
1686 		return;
1687 
1688 	/* probe for hardware */
1689 	new_isa_configure(&cfg_string, &pcdriver);
1690 }
1691 
CONSOLE_MODCONFIG()1692 CONSOLE_MODCONFIG() {
1693 	char *cfg1 = pc_console_config;
1694 	char *cfg2 = pc_config;
1695 
1696 	if (console_config(&cfg1, &cfg2, &pc_devif) == 0)
1697 		return;
1698 #ifdef unneeded
1699 	/* probe for hardware */
1700 	new_isa_configure(&cfg2, &pcdriver);
1701 #endif
1702 }
1703 
1704 #ifdef DEBUG
1705 /*
1706  *
1707  */
wpl(int x,int y)1708 wpl(int x, int y) {
1709 	short *p = Crtat ;
1710 	int i, clr;
1711 	int sv;
1712 
1713 	asm("lahf" : "=a" (sv));
1714 
1715 	if (sv & 0x8000)
1716 		clr = 3;
1717 	else
1718 		clr = 5;
1719 
1720 	p += (80-17);
1721 
1722 	*p++ =  (clr<<8) + 'A' + y ;
1723 	for (i=15; i >= 0; i--)
1724 		if (x & (1<<i))
1725 		 *p++ =  (clr<<8) + '1' ;
1726 		else
1727 		 *p++ =  (clr<<8) + '0' ;
1728 	if((x & 3) == 1)
1729 		outb(0x21, x & 0xfe);
1730 }
1731 #endif
1732