xref: /csrg-svn/sys/i386/isa/pccons.c (revision 45535)
141053Swilliam /*-
241053Swilliam  * Copyright (c) 1990 The Regents of the University of California.
341053Swilliam  * All rights reserved.
441053Swilliam  *
541053Swilliam  * This code is derived from software contributed to Berkeley by
641053Swilliam  * William Jolitz.
741053Swilliam  *
843589Sdonahn  * Added support for ibmpc term type and improved keyboard support. -Don Ahn
943589Sdonahn  *
1041053Swilliam  * %sccs.include.386.c%
1141053Swilliam  *
12*45535Sbill  *	@(#)pccons.c	5.3 (Berkeley) 11/08/90
1341053Swilliam  */
1441053Swilliam 
1541053Swilliam /*
1641053Swilliam  * code to work keyboard & display for console
1741053Swilliam  */
1841053Swilliam #include "param.h"
1941053Swilliam #include "conf.h"
2041053Swilliam #include "dir.h"
2141053Swilliam #include "ioctl.h"
2241053Swilliam #include "user.h"
2341053Swilliam #include "proc.h"
2441053Swilliam #include "tty.h"
2541053Swilliam #include "uio.h"
26*45535Sbill #include "machine/isa/device.h"
2741053Swilliam #include "callout.h"
2841053Swilliam #include "systm.h"
2941053Swilliam #include "kernel.h"
3041053Swilliam #include "syslog.h"
3141053Swilliam #include "icu.h"
3241053Swilliam 
3341053Swilliam struct	tty cons;
3441053Swilliam 
3541053Swilliam struct	consoftc {
3641053Swilliam 	char	cs_flags;
3741053Swilliam #define	CSF_ACTIVE	0x1	/* timeout active */
3841053Swilliam #define	CSF_POLLING	0x2	/* polling for input */
3941053Swilliam 	char	cs_lastc;	/* last char sent */
4041053Swilliam 	int	cs_timo;	/* timeouts since interrupt */
4141053Swilliam 	u_long	cs_wedgecnt;	/* times restarted */
4241053Swilliam } consoftc;
4341053Swilliam 
4443589Sdonahn int cnprobe(), cnattach();
4543589Sdonahn 
46*45535Sbill struct	isa_driver cndriver = {
4743589Sdonahn 	cnprobe, cnattach, "cn",
4843589Sdonahn };
4943589Sdonahn 
50*45535Sbill #define	COL		80
51*45535Sbill #define	ROW		25
52*45535Sbill #define	CHR		2
53*45535Sbill #define MONO_BASE	0x3B4
54*45535Sbill #define MONO_BUF	0xB0000
55*45535Sbill #define CGA_BASE	0x3D4
56*45535Sbill #define CGA_BUF		0xB8000
57*45535Sbill #define IOPHYSMEM	0xA0000
58*45535Sbill 
59*45535Sbill u_char	color = 0xe ;
60*45535Sbill static unsigned int addr_6845 = MONO_BASE;
61*45535Sbill u_short *Crtat = (u_short *)MONO_BUF;
62*45535Sbill 
6341053Swilliam /*
6441053Swilliam  * We check the console periodically to make sure
6541053Swilliam  * that it hasn't wedged.  Unfortunately, if an XOFF
6641053Swilliam  * is typed on the console, that can't be distinguished
6741053Swilliam  * from more catastrophic failure.
6841053Swilliam  */
6941053Swilliam #define	CN_TIMERVAL	(hz)		/* frequency at which to check cons */
7041053Swilliam #define	CN_TIMO		(2*60)		/* intervals to allow for output char */
7141053Swilliam 
7241053Swilliam int	cnstart();
7341053Swilliam int	ttrstrt();
7441053Swilliam char	partab[];
7541053Swilliam 
7641053Swilliam /*
7741053Swilliam  * Wait for CP to accept last CP command sent
7841053Swilliam  * before setting up next command.
7941053Swilliam  */
8041053Swilliam #define	waitforlast(timo) { \
8141053Swilliam 	if (cnlast) { \
8241053Swilliam 		(timo) = 10000; \
8341053Swilliam 		do \
8441053Swilliam 			uncache((char *)&cnlast->cp_unit); \
8541053Swilliam 		while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \
8641053Swilliam 	} \
8741053Swilliam }
8841053Swilliam 
8941053Swilliam u_char inb();
9041053Swilliam 
9143589Sdonahn cnprobe(dev)
92*45535Sbill struct isa_device *dev;
9343589Sdonahn {
9443589Sdonahn 	u_char c;
9543589Sdonahn 	int again = 0;
9643589Sdonahn 
9743589Sdonahn 	/* Enable interrupts and keyboard controller */
9843589Sdonahn 	while (inb(0x64)&2); outb(0x64,0x60);
9943589Sdonahn 	while (inb(0x64)&2); outb(0x60,0x4D);
10043589Sdonahn 
10143589Sdonahn 	/* Start keyboard stuff RESET */
10243589Sdonahn 	while (inb(0x64)&2);	/* wait input ready */
10343589Sdonahn 	outb(0x60,0xFF);	/* RESET */
10443589Sdonahn 	while((c=inb(0x60))!=0xFA) {
10543589Sdonahn 		if ((c == 0xFE) ||  (c == 0xFF)) {
10643589Sdonahn 			if(!again)printf("KEYBOARD disconnected: RECONNECT \n");
10743589Sdonahn 			while (inb(0x64)&2);	/* wait input ready */
10843589Sdonahn 			outb(0x60,0xFF);	/* RESET */
10943589Sdonahn 			again = 1;
11043589Sdonahn 		}
11143589Sdonahn 	}
11243589Sdonahn 	/* pick up keyboard reset return code */
113*45535Sbill 	while((c=inb(0x60))!=0xAA)nulldev();
11443589Sdonahn 	return 1;
11543589Sdonahn }
11643589Sdonahn 
11743589Sdonahn cnattach(dev)
118*45535Sbill struct isa_device *dev;
11943589Sdonahn {
120*45535Sbill 	u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR;
121*45535Sbill 	u_short was;
122*45535Sbill 
123*45535Sbill 	/* Crtat initialized to point to MONO buffer   */
124*45535Sbill 	/* if not present change to CGA_BUF offset     */
125*45535Sbill 	/* ONLY ADD the difference since locore.s adds */
126*45535Sbill 	/* in the remapped offset at the right time    */
127*45535Sbill 
128*45535Sbill 	was = *Crtat;
129*45535Sbill 	*Crtat = (u_short) 0xA55A;
130*45535Sbill 	if (*Crtat != 0xA55A)
131*45535Sbill 		printf("<mono>");
132*45535Sbill 	else	printf("<color>");
133*45535Sbill 	*Crtat = was;
13443589Sdonahn }
13543589Sdonahn 
13641053Swilliam /*ARGSUSED*/
13741053Swilliam cnopen(dev, flag)
13841053Swilliam 	dev_t dev;
13941053Swilliam {
14041053Swilliam 	register struct tty *tp;
14141053Swilliam 	int unit = minor(dev);
14241053Swilliam 
14341053Swilliam 	tp = &cons;
14441053Swilliam 	if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
14541053Swilliam 		return (EBUSY);
14641053Swilliam 	tp->t_oproc = cnstart;
14741053Swilliam 	if ((tp->t_state&TS_ISOPEN) == 0) {
14841053Swilliam 		ttychars(tp);
14941053Swilliam 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
15041053Swilliam 		tp->t_flags = EVENP|ECHO|XTABS|CRMOD;
15141053Swilliam 		splnone();
15241053Swilliam 	}
15341053Swilliam 	return ((*linesw[tp->t_line].l_open)(dev, tp));
15441053Swilliam }
15541053Swilliam 
15641053Swilliam 
15741053Swilliam cnclose(dev)
15841053Swilliam 	dev_t dev;
15941053Swilliam {
16041053Swilliam 	(*linesw[cons.t_line].l_close)(&cons);
16141053Swilliam 	ttyclose(&cons);
16241053Swilliam }
16341053Swilliam 
16441053Swilliam /*ARGSUSED*/
16541053Swilliam cnread(dev, uio)
16641053Swilliam 	dev_t dev;
16741053Swilliam 	struct uio *uio;
16841053Swilliam {
16941053Swilliam 	return ((*linesw[cons.t_line].l_read)(&cons, uio));
17041053Swilliam }
17141053Swilliam 
17241053Swilliam /*ARGSUSED*/
17341053Swilliam cnwrite(dev, uio)
17441053Swilliam 	dev_t dev;
17541053Swilliam 	struct uio *uio;
17641053Swilliam {
17741053Swilliam 	return ((*linesw[cons.t_line].l_write)(&cons, uio));
17841053Swilliam }
17941053Swilliam 
18041053Swilliam /*
18141053Swilliam  * Got a console receive interrupt -
18241053Swilliam  * the console processor wants to give us a character.
18341053Swilliam  * Catch the character, and see who it goes to.
18441053Swilliam  */
185*45535Sbill cnrint(dev, irq, cpl)
18641053Swilliam 	dev_t dev;
18741053Swilliam {
18841053Swilliam 	int c;
18941053Swilliam 
19041053Swilliam 	c = sgetc(1);
191*45535Sbill 	if (c&0x100) return;
19241053Swilliam 	if (consoftc.cs_flags&CSF_POLLING)
19341053Swilliam 		return;
19441053Swilliam #ifdef KDB
19541053Swilliam 	if (kdbrintr(c, &cons))
19641053Swilliam 		return;
19741053Swilliam #endif
19841053Swilliam 	(*linesw[cons.t_line].l_rint)(c&0xff, &cons);
19941053Swilliam }
20041053Swilliam 
20141053Swilliam cnioctl(dev, cmd, addr, flag)
20241053Swilliam 	dev_t dev;
20341053Swilliam 	caddr_t addr;
20441053Swilliam {
20541053Swilliam 	register struct tty *tp = &cons;
20641053Swilliam 	register error;
20741053Swilliam 
20841053Swilliam 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
20941053Swilliam 	if (error >= 0)
21041053Swilliam 		return error;
21141053Swilliam 	if ((error = ttioctl(tp, cmd, addr, flag)) < 0)
21241053Swilliam 		error = ENOTTY;
21341053Swilliam 	else if (cmd == TIOCSETP || cmd == TIOCSETN)
21441053Swilliam 		cnparams(tp);
21541053Swilliam 	return (error);
21641053Swilliam }
21741053Swilliam 
21841053Swilliam int	consintr = 1;
21941053Swilliam /*
22041053Swilliam  * Got a console transmission interrupt -
22141053Swilliam  * the console processor wants another character.
22241053Swilliam  */
22341053Swilliam cnxint(dev)
22441053Swilliam 	dev_t dev;
22541053Swilliam {
22641053Swilliam 	register struct tty *tp;
22741053Swilliam 	register int unit;
22841053Swilliam 
22941053Swilliam 	if (!consintr)
23041053Swilliam 		return;
23141053Swilliam 	cons.t_state &= ~TS_BUSY;
23241053Swilliam 	consoftc.cs_timo = 0;
23341053Swilliam 	if (cons.t_line)
23441053Swilliam 		(*linesw[cons.t_line].l_start)(&cons);
23541053Swilliam 	else
23641053Swilliam 		cnstart(&cons);
23741053Swilliam }
23841053Swilliam 
23941053Swilliam cnstart(tp)
24041053Swilliam 	register struct tty *tp;
24141053Swilliam {
24241053Swilliam 	register c, s;
24341053Swilliam 
24441053Swilliam 	s = spltty();
24541053Swilliam 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
24641053Swilliam 		goto out;
24741053Swilliam 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
24841053Swilliam 		if (tp->t_state&TS_ASLEEP) {
24941053Swilliam 			tp->t_state &= ~TS_ASLEEP;
25041053Swilliam 			wakeup((caddr_t)&tp->t_outq);
25141053Swilliam 		}
25241053Swilliam 		if (tp->t_wsel) {
25341053Swilliam 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
25441053Swilliam 			tp->t_wsel = 0;
25541053Swilliam 			tp->t_state &= ~TS_WCOLL;
25641053Swilliam 		}
25741053Swilliam 	}
25841053Swilliam 	while (tp->t_outq.c_cc != 0) {
25941053Swilliam 		c = getc(&tp->t_outq) & 0xff;
26041053Swilliam 		if ((tp->t_flags & (RAW|LITOUT)) == 0) {
26141053Swilliam 			if (c > 0177)
26241053Swilliam 			{
26341053Swilliam 				timeout(ttrstrt, (caddr_t)tp, (c&0177));
26441053Swilliam 				tp->t_state |= TS_TIMEOUT;
26541053Swilliam 				break;
26641053Swilliam 			}
26741053Swilliam 			c &= 0177;
26841053Swilliam 		}
26943589Sdonahn 		splx(s);
27043589Sdonahn 		sput(c,0x7);
27143589Sdonahn 		s = spltty();
27241053Swilliam 	}
27341053Swilliam out:
27441053Swilliam 	splx(s);
27541053Swilliam }
27641053Swilliam 
27741053Swilliam cnputc(c)
27841053Swilliam 	char c;
27941053Swilliam {
28041053Swilliam 	if (c == '\n')
28143589Sdonahn 		sput('\r',0x3);
28243589Sdonahn 	sput(c, 0x3);
28341053Swilliam }
28441053Swilliam 
28541053Swilliam /*
28641053Swilliam  * Print a character on console.
28741053Swilliam  */
28841053Swilliam cnputchar(c, tp)
28941053Swilliam 	char c;
29041053Swilliam 	register struct tty *tp;
29141053Swilliam {
29243589Sdonahn 	sput(c,0x2);
29341053Swilliam 	if (c=='\n') getchar();
29441053Swilliam }
29541053Swilliam 
29641053Swilliam 
29741053Swilliam cngetc()
29841053Swilliam {
29941053Swilliam 	register int c, s;
30041053Swilliam 
30141053Swilliam 	s = spltty();		/* block cnrint while we poll */
30243589Sdonahn 	c = sgetc(0);
30343589Sdonahn 	if (c == '\r') c = '\n';
30441053Swilliam 	splx(s);
30541053Swilliam 	return (c);
30641053Swilliam }
30741053Swilliam 
30841053Swilliam cngetchar(tp)
30941053Swilliam 	register struct tty *tp;
31041053Swilliam {
31141053Swilliam 	int c;
31241053Swilliam 
31341053Swilliam 	c = sgetc(0);
31441053Swilliam 	return (c&0xff);
31541053Swilliam }
31641053Swilliam 
31741053Swilliam /*
31841053Swilliam  * Set line parameters
31941053Swilliam  */
32041053Swilliam cnparams(tp)
32141053Swilliam 	register struct tty *tp;
32241053Swilliam {
32341053Swilliam }
32441053Swilliam 
32541053Swilliam #ifdef KDB
32641053Swilliam /*
32741053Swilliam  * Turn input polling on/off (used by debugger).
32841053Swilliam  */
32941053Swilliam cnpoll(onoff)
33041053Swilliam 	int onoff;
33141053Swilliam {
33241053Swilliam }
33341053Swilliam #endif
33441053Swilliam 
33543589Sdonahn extern int hz;
33643589Sdonahn 
33743589Sdonahn sysbeepstop()
33843589Sdonahn {
33943589Sdonahn 	/* disable counter 2 */
34043589Sdonahn 	outb(0x61,inb(0x61)&0xFC);
34143589Sdonahn }
34243589Sdonahn 
34343589Sdonahn sysbeep()
34443589Sdonahn {
34543589Sdonahn 	/* enable counter 2 */
34643589Sdonahn 	outb(0x61,inb(0x61)|3);
34743589Sdonahn 	/* set command for counter 2, 2 byte write */
34843589Sdonahn 	outb(0x43,0xB6);
34943589Sdonahn 	/* send 0x637 for 750 HZ */
35043589Sdonahn 	outb(0x42,0x37);
35143589Sdonahn 	outb(0x42,0x06);
35243589Sdonahn 	timeout(sysbeepstop,0,hz/4);
35343589Sdonahn }
35443589Sdonahn 
355*45535Sbill /* cursor() sets an offset (0-1999) into the 80x25 text area    */
35641053Swilliam 
357*45535Sbill static u_short *crtat = 0;
358*45535Sbill char bg_at = 0x0f;
359*45535Sbill char so_at = 0x70;
36041053Swilliam 
361*45535Sbill cursor()
362*45535Sbill { 	int pos = crtat - Crtat;
36341053Swilliam 
36443589Sdonahn 	outb(addr_6845,14);
36543589Sdonahn 	outb(addr_6845+1,pos >> 8);
36643589Sdonahn 	outb(addr_6845,15);
36743589Sdonahn 	outb(addr_6845+1,pos&0xff);
36843589Sdonahn }
36943589Sdonahn 
37043589Sdonahn /* sput has support for emulation of the 'ibmpc' termcap entry. */
37143589Sdonahn /* This is a bare-bones implementation of a bare-bones entry    */
37243589Sdonahn /* One modification: Change li#24 to li#25 to reflect 25 lines  */
37343589Sdonahn 
37443589Sdonahn sput(c, ca)
37543589Sdonahn u_char c, ca;
37643589Sdonahn {
37743589Sdonahn 
37843589Sdonahn 	static int esc,ebrac,eparm,cx,cy,row,so;
37943589Sdonahn 
38041053Swilliam 	if (crtat == 0) {
381*45535Sbill 		u_short *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR, was;
382*45535Sbill 		unsigned cursorat;
38343589Sdonahn 
38443589Sdonahn 		/* Crtat initialized to point to MONO buffer   */
38543589Sdonahn 		/* if not present change to CGA_BUF offset     */
38643589Sdonahn 		/* ONLY ADD the difference since locore.s adds */
38743589Sdonahn 		/* in the remapped offset at the right time    */
38843589Sdonahn 
389*45535Sbill 		was = *cp;
390*45535Sbill 		*cp = (u_short) 0xA55A;
391*45535Sbill 		if (*cp != 0xA55A) {
392*45535Sbill 			addr_6845 = MONO_BASE;
393*45535Sbill 		} else {
394*45535Sbill 			*cp = was;
395*45535Sbill 			addr_6845 = CGA_BASE;
39643589Sdonahn 			Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR;
397*45535Sbill 		}
398*45535Sbill 		/* Extract cursor location */
399*45535Sbill 		outb(addr_6845,14);
400*45535Sbill 		cursorat = inb(addr_6845+1)<<8 ;
401*45535Sbill 		outb(addr_6845,15);
402*45535Sbill 		cursorat |= inb(addr_6845+1);
403*45535Sbill 
404*45535Sbill 		crtat = Crtat + cursorat;
405*45535Sbill 		fillw((bg_at<<8)|' ', crtat, COL*ROW-cursorat);
40641053Swilliam 	}
40741053Swilliam 	switch(c) {
40843589Sdonahn 	case 0x1B:
40943589Sdonahn 		esc = 1; ebrac = 0; eparm = 0;
41043589Sdonahn 		break;
41141053Swilliam 
41241053Swilliam 	case '\t':
41341053Swilliam 		do {
41441053Swilliam 			*crtat++ = (ca<<8)| ' '; row++ ;
41541053Swilliam 		} while (row %8);
41641053Swilliam 		break;
41741053Swilliam 
41841053Swilliam 	case '\010':
41941053Swilliam 		crtat--; row--;
42043589Sdonahn 		if (row < 0) row += COL;  /* non-destructive backspace */
42141053Swilliam 		break;
42241053Swilliam 
42341053Swilliam 	case '\r':
42443589Sdonahn 		crtat -= row ; row = 0;
42541053Swilliam 		break;
42641053Swilliam 
42741053Swilliam 	case '\n':
42841053Swilliam 		crtat += COL ;
42941053Swilliam 		break;
43041053Swilliam 
43141053Swilliam 	default:
43243589Sdonahn 		if (esc) {
43343589Sdonahn 			if (ebrac) {
43443589Sdonahn 				switch(c) {
43543589Sdonahn 				case 'm': /* no support for standout */
43643589Sdonahn 					if (!cx) so = 0;
43743589Sdonahn 					else so = 1;
43843589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
43943589Sdonahn 					break;
44043589Sdonahn 				case 'A': /* back one row */
44143589Sdonahn 					crtat -= COL;
44243589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
44343589Sdonahn 					break;
44443589Sdonahn 				case 'B': /* down one row */
44543589Sdonahn 					crtat += COL;
44643589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
44743589Sdonahn 					break;
44843589Sdonahn 				case 'C': /* right cursor */
44943589Sdonahn 					crtat++; row++;
45043589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
45143589Sdonahn 					break;
45243589Sdonahn 				case 'J': /* Clear to end of display */
453*45535Sbill 					fillw((bg_at<<8)+' ', crtat,
454*45535Sbill 						Crtat+COL*ROW-crtat);
45543589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
45643589Sdonahn 					break;
45743589Sdonahn 				case 'K': /* Clear to EOL */
458*45535Sbill 					fillw((bg_at<<8)+' ', crtat, COL-row);
45943589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
46043589Sdonahn 					break;
46143589Sdonahn 				case 'H': /* Cursor move */
46243589Sdonahn 					if ((!cx)||(!cy)) {
46343589Sdonahn 						crtat = Crtat;
46443589Sdonahn 						row = 0;
46543589Sdonahn 					} else {
46643589Sdonahn 						crtat = Crtat+(cx-1)*COL+cy-1;
46743589Sdonahn 						row = cy-1;
46843589Sdonahn 					}
46943589Sdonahn 					esc = 0; ebrac = 0; eparm = 0;
47043589Sdonahn 					break;
47143589Sdonahn 				case ';': /* Switch params in cursor def */
47243589Sdonahn 					eparm = 1;
47343589Sdonahn 					return;
47443589Sdonahn 				default: /* Only numbers valid here */
47543589Sdonahn 					if ((c >= '0')&&(c <= '9')) {
47643589Sdonahn 						if (eparm) {
47743589Sdonahn 							cy *= 10;
47843589Sdonahn 							cy += c - '0';
47943589Sdonahn 						} else {
48043589Sdonahn 							cx *= 10;
48143589Sdonahn 							cx += c - '0';
48243589Sdonahn 						}
48343589Sdonahn 					} else {
48443589Sdonahn 						esc = 0; ebrac = 0; eparm = 0;
48543589Sdonahn 					}
48643589Sdonahn 					return;
48743589Sdonahn 				}
48843589Sdonahn 				break;
48943589Sdonahn 			} else if (c == 'c') { /* Clear screen & home */
490*45535Sbill 				fillw((bg_at<<8)+' ', Crtat,COL*ROW);
49143589Sdonahn 				crtat = Crtat; row = 0;
49243589Sdonahn 				esc = 0; ebrac = 0; eparm = 0;
493*45535Sbill 			} else if (c == '[') { /* Start ESC [ sequence */
49443589Sdonahn 				ebrac = 1; cx = 0; cy = 0; eparm = 0;
495*45535Sbill 			} else { /* Invalid, clear state */
49643589Sdonahn 				 esc = 0; ebrac = 0; eparm = 0;
49743589Sdonahn 			}
49843589Sdonahn 		} else {
49943589Sdonahn 			if (c == 7) {
50043589Sdonahn 				sysbeep();
50143589Sdonahn 			}
50243589Sdonahn 			/* Print only printables */
503*45535Sbill 			else /*if (c >= ' ') */ {
504*45535Sbill 				while(inb(0x3da)&1)nulldev();
50543589Sdonahn 				if (so) {
506*45535Sbill 					*crtat++ = (so_at<<8)| c; row++ ;
50743589Sdonahn 				} else {
50843589Sdonahn 					*crtat++ = (ca<<8)| c; row++ ;
50943589Sdonahn 				}
51043589Sdonahn 				if (row >= COL) row = 0;
51143589Sdonahn 				break ;
51243589Sdonahn 			}
51341053Swilliam 		}
51441053Swilliam 	}
51543589Sdonahn 	if (crtat >= Crtat+COL*(ROW)) { /* scroll check */
51643589Sdonahn 		bcopy(Crtat+COL,Crtat,COL*(ROW-1)*CHR);
517*45535Sbill 		fillw ((bg_at<<8)+' ', Crtat+COL*(ROW-1),COL) ;
51843589Sdonahn 		crtat -= COL ;
51943589Sdonahn 	}
52041053Swilliam }
52143589Sdonahn 
52243589Sdonahn 
52341053Swilliam #define	L		0x0001	/* locking function */
52441053Swilliam #define	SHF		0x0002	/* keyboard shift */
52541053Swilliam #define	ALT		0x0004	/* alternate shift -- alternate chars */
52641053Swilliam #define	NUM		0x0008	/* numeric shift  cursors vs. numeric */
52741053Swilliam #define	CTL		0x0010	/* control shift  -- allows ctl function */
52841053Swilliam #define	CPS		0x0020	/* caps shift -- swaps case of letter */
52941053Swilliam #define	ASCII		0x0040	/* ascii code for this key */
53041053Swilliam #define	STP		0x0080	/* stop output */
53141053Swilliam #define	FUNC		0x0100	/* function key */
53243589Sdonahn #define	SCROLL		0x0200	/* scroll lock key */
53341053Swilliam 
534*45535Sbill unsigned	__debug = 0;
53541053Swilliam u_short action[] = {
53641053Swilliam 0,     ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan  0- 7 */
53741053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan  8-15 */
53841053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 16-23 */
53941053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII,   CTL, ASCII, ASCII,		/* scan 24-31 */
54041053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 32-39 */
54141053Swilliam ASCII, ASCII, SHF  , ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 40-47 */
54241053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,  SHF,  ASCII,		/* scan 48-55 */
54343589Sdonahn   ALT, ASCII, CPS  , FUNC , FUNC , FUNC , FUNC , FUNC ,		/* scan 56-63 */
54443589Sdonahn FUNC , FUNC , FUNC , FUNC , FUNC , NUM, STP, ASCII,		/* scan 64-71 */
54541053Swilliam ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,		/* scan 72-79 */
54641053Swilliam ASCII, ASCII, ASCII, ASCII,     0,     0,     0,     0,		/* scan 80-87 */
54741053Swilliam 0,0,0,0,0,0,0,0,
54841053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
54941053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
55041053Swilliam 
55141053Swilliam u_char unshift[] = {	/* no shift */
55241053Swilliam 0,     033  , '1'  , '2'  , '3'  , '4'  , '5'  , '6'  ,		/* scan  0- 7 */
55341053Swilliam '7'  , '8'  , '9'  , '0'  , '-'  , '='  , 0177 ,'\t'  ,		/* scan  8-15 */
55441053Swilliam 
55541053Swilliam 'q'  , 'w'  , 'e'  , 'r'  , 't'  , 'y'  , 'u'  , 'i'  ,		/* scan 16-23 */
55641053Swilliam 'o'  , 'p'  , '['  , ']'  , '\r' , CTL  , 'a'  , 's'  ,		/* scan 24-31 */
55741053Swilliam 
55841053Swilliam 'd'  , 'f'  , 'g'  , 'h'  , 'j'  , 'k'  , 'l'  , ';'  ,		/* scan 32-39 */
55941053Swilliam '\'' , '`'  , SHF  , '\\' , 'z'  , 'x'  , 'c'  , 'v'  ,		/* scan 40-47 */
56041053Swilliam 
56141053Swilliam 'b'  , 'n'  , 'm'  , ','  , '.'  , '/'  , SHF  ,   '*',		/* scan 48-55 */
56243589Sdonahn ALT  , ' '  , CPS,     1,     2,    3 ,     4,     5,		/* scan 56-63 */
56341053Swilliam 
56443589Sdonahn     6,     7,     8,     9,    10, NUM, STP,   '7',		/* scan 64-71 */
56541053Swilliam   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',		/* scan 72-79 */
56641053Swilliam 
56741053Swilliam   '2',   '3',   '0',   '.',     0,     0,     0,     0,		/* scan 80-87 */
56841053Swilliam 0,0,0,0,0,0,0,0,
56941053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
57041053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
57141053Swilliam 
57241053Swilliam u_char shift[] = {	/* shift shift */
57341053Swilliam 0,     033  , '!'  , '@'  , '#'  , '$'  , '%'  , '^'  ,		/* scan  0- 7 */
57441053Swilliam '&'  , '*'  , '('  , ')'  , '_'  , '+'  , 0177 ,'\t'  ,		/* scan  8-15 */
57541053Swilliam 'Q'  , 'W'  , 'E'  , 'R'  , 'T'  , 'Y'  , 'U'  , 'I'  ,		/* scan 16-23 */
57641053Swilliam 'O'  , 'P'  , '{'  , '}'  , '\r' , CTL  , 'A'  , 'S'  ,		/* scan 24-31 */
57741053Swilliam 'D'  , 'F'  , 'G'  , 'H'  , 'J'  , 'K'  , 'L'  , ':'  ,		/* scan 32-39 */
57841053Swilliam '"'  , '~'  , SHF  , '|'  , 'Z'  , 'X'  , 'C'  , 'V'  ,		/* scan 40-47 */
57941053Swilliam 'B'  , 'N'  , 'M'  , '<'  , '>'  , '?'  , SHF  ,   '*',		/* scan 48-55 */
58043589Sdonahn ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,		/* scan 56-63 */
58143589Sdonahn     0,     0,     0,     0,     0, NUM, STP,   '7',		/* scan 64-71 */
58241053Swilliam   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',		/* scan 72-79 */
58341053Swilliam   '2',   '3',   '0',   '.',     0,     0,     0,     0,		/* scan 80-87 */
58441053Swilliam 0,0,0,0,0,0,0,0,
58541053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
58641053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
58741053Swilliam 
58841053Swilliam u_char ctl[] = {	/* CTL shift */
58941053Swilliam 0,     033  , '!'  , 000  , '#'  , '$'  , '%'  , 036  ,		/* scan  0- 7 */
59041053Swilliam '&'  , '*'  , '('  , ')'  , 037  , '+'  , 034  ,'\177',		/* scan  8-15 */
59141053Swilliam 021  , 027  , 005  , 022  , 024  , 031  , 025  , 011  ,		/* scan 16-23 */
59241053Swilliam 017  , 020  , 033  , 035  , '\r' , CTL  , 001  , 023  ,		/* scan 24-31 */
59341053Swilliam 004  , 006  , 007  , 010  , 012  , 013  , 014  , ';'  ,		/* scan 32-39 */
59441053Swilliam '\'' , '`'  , SHF  , 034  , 032  , 030  , 003  , 026  ,		/* scan 40-47 */
59541053Swilliam 002  , 016  , 015  , '<'  , '>'  , '?'  , SHF  ,   '*',		/* scan 48-55 */
59643589Sdonahn ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,		/* scan 56-63 */
59743589Sdonahn CPS,     0,     0,     0,     0,     0,     0,     0,		/* scan 64-71 */
59841053Swilliam     0,     0,     0,     0,     0,     0,     0,     0,		/* scan 72-79 */
59941053Swilliam     0,     0,     0,     0,     0,     0,     0,     0,		/* scan 80-87 */
60043589Sdonahn     0,     0,   033, '7'  , '4'  , '1'  ,     0, NUM,		/* scan 88-95 */
60143589Sdonahn '8'  , '5'  , '2'  ,     0, STP, '9'  , '6'  , '3'  ,		/*scan  96-103*/
60241053Swilliam '.'  ,     0, '*'  , '-'  , '+'  ,     0,     0,     0,		/*scan 104-111*/
60341053Swilliam 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,	} ;
60441053Swilliam 
60541053Swilliam #ifdef notdef
60641053Swilliam struct key {
60741053Swilliam 	u_short action;		/* how this key functions */
60841053Swilliam 	char	ascii[8];	/* ascii result character indexed by shifts */
60941053Swilliam };
61041053Swilliam #endif
61141053Swilliam 
61243589Sdonahn u_char shfts, ctls, alts, caps, num, stp, scroll;
61341053Swilliam 
61443589Sdonahn #define	KBSTAT		0x64	/* kbd status port */
61543589Sdonahn #define	KBS_INP_BUF_FUL	0x02	/* kbd char ready */
61643589Sdonahn #define	KBDATA		0x60	/* kbd data port */
61741053Swilliam #define	KBSTATUSPORT	0x61	/* kbd status */
61841053Swilliam 
61943589Sdonahn update_led()
62043589Sdonahn {
62143589Sdonahn 	while (inb(0x64)&2);	/* wait input ready */
62243589Sdonahn 	outb(0x60,0xED);	/* LED Command */
62343589Sdonahn 	while (inb(0x64)&2);	/* wait input ready */
62443589Sdonahn 	outb(0x60,scroll | 2*num | 4*caps);
62543589Sdonahn }
62641053Swilliam 
627*45535Sbill reset_cpu() {
628*45535Sbill 	while(1) {
629*45535Sbill 		while (inb(0x64)&2);	/* wait input ready */
630*45535Sbill 		outb(0x64,0xFE);	/* Reset Command */
631*45535Sbill 		DELAY(4000000);
632*45535Sbill 		while (inb(0x64)&2);	/* wait input ready */
633*45535Sbill 		outb(0x64,0xFF);	/* Keyboard Reset Command */
634*45535Sbill 	}
635*45535Sbill 	/* NOTREACHED */
636*45535Sbill }
637*45535Sbill 
63843589Sdonahn /*
63943589Sdonahn sgetc(noblock) : get a character from the keyboard. If noblock = 0 wait until
64043589Sdonahn a key is gotten.  Otherwise return a 0x100 (256).
64143589Sdonahn */
64243589Sdonahn int sgetc(noblock)
64343589Sdonahn {
64443589Sdonahn 	u_char dt; unsigned key;
64541053Swilliam loop:
64643589Sdonahn 	/* First see if there is something in the keyboard port */
64743589Sdonahn 	if (inb(KBSTAT)&1) dt = inb(KBDATA);
64843589Sdonahn 	else { if (noblock) return (0x100); else goto loop; }
64941053Swilliam 
65043589Sdonahn 	/* Check for cntl-alt-del */
65143589Sdonahn 	if ((dt == 83)&&ctls&&alts) _exit();
65241053Swilliam 
65343589Sdonahn 	/* Check for make/break */
65443589Sdonahn 	if (dt & 0x80) {
65543589Sdonahn 		/* break */
65643589Sdonahn 		dt = dt & 0x7f ;
65743589Sdonahn 		switch (action[dt]) {
65843589Sdonahn 		case SHF: shfts = 0; break;
65943589Sdonahn 		case ALT: alts = 0; break;
66043589Sdonahn 		case CTL: ctls = 0; break;
66143589Sdonahn 		case FUNC:
66243589Sdonahn 			/* Toggle debug flags */
66343589Sdonahn 			key = unshift[dt];
66443589Sdonahn 			if(__debug & (1<<key)) __debug &= ~(1<<key) ;
66543589Sdonahn 			else __debug |= (1<<key) ;
66643589Sdonahn 			break;
66741053Swilliam 		}
66843589Sdonahn 	} else {
66943589Sdonahn 		/* make */
67043589Sdonahn 		dt = dt & 0x7f ;
67143589Sdonahn 		switch (action[dt]) {
67243589Sdonahn 		/* LOCKING KEYS */
67343589Sdonahn 		case NUM: num ^= 1; update_led(); break;
67443589Sdonahn 		case CPS: caps ^= 1; update_led(); break;
67543589Sdonahn 		case SCROLL: scroll ^= 1; update_led(); break;
67643589Sdonahn 		case STP: stp ^= 1; if(stp) goto loop; break;
67743589Sdonahn 
67843589Sdonahn 		/* NON-LOCKING KEYS */
67943589Sdonahn 		case SHF: shfts = 1; break;
68043589Sdonahn 		case ALT: alts = 1; break;
68143589Sdonahn 		case CTL: ctls = 1; break;
68243589Sdonahn 		case ASCII:
68343589Sdonahn 			if (shfts) dt = shift[dt];
68443589Sdonahn 			else if (ctls) dt = ctl[dt];
68543589Sdonahn 			else dt = unshift[dt];
68643589Sdonahn 			if (caps && (dt >= 'a' && dt <= 'z')) dt -= 'a' - 'A';
68743589Sdonahn 			return(dt);
68843589Sdonahn 		}
68941053Swilliam 	}
69043589Sdonahn 	if (noblock) return (0x100); else goto loop;
69141053Swilliam }
69241053Swilliam 
69341053Swilliam pg(p,q,r,s,t,u,v,w,x,y,z) char *p; {
69441053Swilliam 	printf(p,q,r,s,t,u,v,w,x,y,z);
69541053Swilliam 	printf("\n");
69641053Swilliam 	return(getchar());
69741053Swilliam }
69841053Swilliam 
69941053Swilliam /* special characters */
70041053Swilliam #define bs	8
70141053Swilliam #define lf	10
70241053Swilliam #define cr	13
70341053Swilliam #define cntlc	3
70441053Swilliam #define del	0177
70541053Swilliam #define cntld	4
70641053Swilliam 
70741053Swilliam getchar()
70841053Swilliam {
70941053Swilliam 	register char thechar;
71041053Swilliam 	register delay;
71141053Swilliam 	int x;
71241053Swilliam 
71341053Swilliam 	consoftc.cs_flags |= CSF_POLLING;
71441053Swilliam 	x=splhigh();
71543589Sdonahn 	sput('>',0x6);
716*45535Sbill 	/*while (1) {*/
71741053Swilliam 		thechar = (char) sgetc(0);
71843589Sdonahn 		consoftc.cs_flags &= ~CSF_POLLING;
71943589Sdonahn 		splx(x);
72041053Swilliam 		switch (thechar) {
72141053Swilliam 		    default: if (thechar >= ' ')
72243589Sdonahn 			     	sput(thechar,0x6);
72341053Swilliam 			     return(thechar);
72441053Swilliam 		    case cr:
72543589Sdonahn 		    case lf: sput(cr,0x6);
72643589Sdonahn 			     sput(lf,0x6);
72741053Swilliam 			     return(lf);
72841053Swilliam 		    case bs:
72941053Swilliam 		    case del:
73043589Sdonahn 			     sput(bs,0x6);
73143589Sdonahn 			     sput(' ',0x6);
73243589Sdonahn 			     sput(bs,0x6);
73341053Swilliam 			     return(thechar);
73443589Sdonahn 		    /*case cntlc:
73541053Swilliam 			     sput('^',0xe) ; sput('C',0xe) ; sput('\r',0xe) ; sput('\n',0xe) ;
73643589Sdonahn 			     _exit(-2) ; */
73741053Swilliam 		    case cntld:
73843589Sdonahn 			     sput('^',0x6) ; sput('D',0x6) ; sput('\r',0x6) ; sput('\n',0x6) ;
73941053Swilliam 			     return(0);
74041053Swilliam 		}
741*45535Sbill 	/*}*/
74241053Swilliam }
743