xref: /csrg-svn/sys/hp/dev/ite.c (revision 68159)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1988 University of Utah.
363148Sbostic  * Copyright (c) 1990, 1993
463148Sbostic  *	The Regents of the University of California.  All rights reserved.
541480Smckusick  *
641480Smckusick  * This code is derived from software contributed to Berkeley by
741480Smckusick  * the Systems Programming Group of the University of Utah Computer
841480Smckusick  * Science Department.
941480Smckusick  *
1041480Smckusick  * %sccs.include.redist.c%
1141480Smckusick  *
1257311Shibler  * from: Utah $Hdr: ite.c 1.28 92/12/20$
1341480Smckusick  *
14*68159Scgd  *	@(#)ite.c	8.3 (Berkeley) 01/09/95
1541480Smckusick  */
1641480Smckusick 
1741480Smckusick /*
1841480Smckusick  * Bit-mapped display terminal emulator machine independent code.
1941480Smckusick  * This is a very rudimentary.  Much more can be abstracted out of
2041480Smckusick  * the hardware dependent routines.
2141480Smckusick  */
2241480Smckusick #include "ite.h"
2341480Smckusick #if NITE > 0
2441480Smckusick 
2541480Smckusick #include "grf.h"
2641480Smckusick 
2741480Smckusick #undef NITE
2841480Smckusick #define NITE	NGRF
2941480Smckusick 
3056504Sbostic #include <sys/param.h>
3156504Sbostic #include <sys/conf.h>
3256504Sbostic #include <sys/proc.h>
3356504Sbostic #include <sys/ioctl.h>
3456504Sbostic #include <sys/tty.h>
3556504Sbostic #include <sys/systm.h>
3656504Sbostic #include <sys/malloc.h>
3741480Smckusick 
3856504Sbostic #include <hp/dev/grfioctl.h>
3956504Sbostic #include <hp/dev/grfvar.h>
4056504Sbostic #include <hp/dev/itevar.h>
4156504Sbostic #include <hp/dev/kbdmap.h>
4241480Smckusick 
4341480Smckusick #define set_attr(ip, attr)	((ip)->attribute |= (attr))
4441480Smckusick #define clr_attr(ip, attr)	((ip)->attribute &= ~(attr))
4541480Smckusick 
4641480Smckusick /*
4757311Shibler  * No need to raise SPL above the HIL (the only thing that can
4857311Shibler  * affect our state.
4957311Shibler  */
5057311Shibler #include <hp/dev/hilreg.h>
5157311Shibler #define splite()		splhil()
5257311Shibler 
5357311Shibler /*
5441480Smckusick  * # of chars are output in a single itestart() call.
5541480Smckusick  * If this is too big, user processes will be blocked out for
5641480Smckusick  * long periods of time while we are emptying the queue in itestart().
5741480Smckusick  * If it is too small, console output will be very ragged.
5841480Smckusick  */
5941480Smckusick int	iteburst = 64;
6041480Smckusick 
6141480Smckusick int	nite = NITE;
6241480Smckusick struct  tty *kbd_tty = NULL;
6341480Smckusick struct	tty ite_tty[NITE];
6441480Smckusick struct  ite_softc ite_softc[NITE];
6541480Smckusick 
6657311Shibler void	itestart(), iterestart();
6741480Smckusick extern	struct tty *constty;
6841480Smckusick 
6941480Smckusick /*
7041480Smckusick  * Primary attribute buffer to be used by the first bitmapped console
7141480Smckusick  * found. Secondary displays alloc the attribute buffer as needed.
7241480Smckusick  * Size is based on a 68x128 display, which is currently our largest.
7341480Smckusick  */
7441480Smckusick u_char  console_attributes[0x2200];
7541480Smckusick 
7657311Shibler #define ite_erasecursor(ip, sp)	{ \
7757311Shibler 	if ((ip)->flags & ITE_CURSORON) \
7857311Shibler 		(*(sp)->ite_cursor)((ip), ERASE_CURSOR); \
7957311Shibler }
8057311Shibler #define ite_drawcursor(ip, sp) { \
8157311Shibler 	if ((ip)->flags & ITE_CURSORON) \
8257311Shibler 		(*(sp)->ite_cursor)((ip), DRAW_CURSOR); \
8357311Shibler }
8457311Shibler #define ite_movecursor(ip, sp) { \
8557311Shibler 	if ((ip)->flags & ITE_CURSORON) \
8657311Shibler 		(*(sp)->ite_cursor)((ip), MOVE_CURSOR); \
8757311Shibler }
8857311Shibler 
8941480Smckusick /*
9041480Smckusick  * Perform functions necessary to setup device as a terminal emulator.
9141480Smckusick  */
iteon(dev,flag)9241480Smckusick iteon(dev, flag)
9341480Smckusick 	dev_t dev;
9465645Sbostic 	int flag;
9541480Smckusick {
9641480Smckusick 	int unit = UNIT(dev);
9741480Smckusick 	struct tty *tp = &ite_tty[unit];
9841480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
9941480Smckusick 
10041480Smckusick 	if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0)
10141480Smckusick 		return(ENXIO);
10241480Smckusick 	/* force ite active, overriding graphics mode */
10341480Smckusick 	if (flag & 1) {
10441480Smckusick 		ip->flags |= ITE_ACTIVE;
10541480Smckusick 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
10641480Smckusick 	}
10741480Smckusick 	/* leave graphics mode */
10841480Smckusick 	if (flag & 2) {
10941480Smckusick 		ip->flags &= ~ITE_INGRF;
11041480Smckusick 		if ((ip->flags & ITE_ACTIVE) == 0)
11141480Smckusick 			return(0);
11241480Smckusick 	}
11341480Smckusick 	ip->flags |= ITE_ACTIVE;
11441480Smckusick 	if (ip->flags & ITE_INGRF)
11541480Smckusick 		return(0);
11641480Smckusick 	if (kbd_tty == NULL || kbd_tty == tp) {
11741480Smckusick 		kbd_tty = tp;
11853923Shibler 		kbdenable(unit);
11941480Smckusick 	}
12041480Smckusick 	iteinit(dev);
12141480Smckusick 	return(0);
12241480Smckusick }
12341480Smckusick 
iteinit(dev)12441480Smckusick iteinit(dev)
12541480Smckusick      dev_t dev;
12641480Smckusick {
12741480Smckusick 	int unit = UNIT(dev);
12841480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
12941480Smckusick 
13041480Smckusick 	if (ip->flags & ITE_INITED)
13141480Smckusick 		return;
13241480Smckusick 
13341480Smckusick 	ip->curx = 0;
13441480Smckusick 	ip->cury = 0;
13541480Smckusick 	ip->cursorx = 0;
13641480Smckusick 	ip->cursory = 0;
13741480Smckusick 
13853923Shibler 	(*ip->isw->ite_init)(ip);
13957311Shibler 	ip->flags |= ITE_CURSORON;
14057311Shibler 	ite_drawcursor(ip, ip->isw);
14141480Smckusick 
14241480Smckusick 	ip->attribute = 0;
14341480Smckusick 	if (ip->attrbuf == NULL)
14441480Smckusick 		ip->attrbuf = (u_char *)
14541480Smckusick 			malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK);
14641480Smckusick 	bzero(ip->attrbuf, (ip->rows * ip->cols));
14741480Smckusick 
14841480Smckusick 	ip->imode = 0;
14941480Smckusick 	ip->flags |= ITE_INITED;
15041480Smckusick }
15141480Smckusick 
15241480Smckusick /*
15341480Smckusick  * "Shut down" device as terminal emulator.
15441480Smckusick  * Note that we do not deinit the console device unless forced.
15541480Smckusick  * Deinit'ing the console every time leads to a very active
15641480Smckusick  * screen when processing /etc/rc.
15741480Smckusick  */
iteoff(dev,flag)15841480Smckusick iteoff(dev, flag)
15941480Smckusick 	dev_t dev;
16065645Sbostic 	int flag;
16141480Smckusick {
16241480Smckusick 	register struct ite_softc *ip = &ite_softc[UNIT(dev)];
16341480Smckusick 
16458052Shibler 	if (flag & 2) {
16541480Smckusick 		ip->flags |= ITE_INGRF;
16658052Shibler 		ip->flags &= ~ITE_CURSORON;
16758052Shibler 	}
16841480Smckusick 	if ((ip->flags & ITE_ACTIVE) == 0)
16941480Smckusick 		return;
17041480Smckusick 	if ((flag & 1) ||
17158052Shibler 	    (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
17253923Shibler 		(*ip->isw->ite_deinit)(ip);
17341480Smckusick 	if ((flag & 2) == 0)
17441480Smckusick 		ip->flags &= ~ITE_ACTIVE;
17541480Smckusick }
17641480Smckusick 
17749132Skarels /* ARGSUSED */
17849132Skarels #ifdef __STDC__
iteopen(dev_t dev,int mode,int devtype,struct proc * p)17949132Skarels iteopen(dev_t dev, int mode, int devtype, struct proc *p)
18049132Skarels #else
18149132Skarels iteopen(dev, mode, devtype, p)
18241480Smckusick 	dev_t dev;
18349132Skarels 	int mode, devtype;
18449132Skarels 	struct proc *p;
18549132Skarels #endif
18641480Smckusick {
18741480Smckusick 	int unit = UNIT(dev);
18841480Smckusick 	register struct tty *tp = &ite_tty[unit];
18941480Smckusick 	register struct ite_softc *ip = &ite_softc[unit];
19041480Smckusick 	register int error;
19141480Smckusick 	int first = 0;
19241480Smckusick 
19343409Shibler 	if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
19449132Skarels 	    && p->p_ucred->cr_uid != 0)
19541480Smckusick 		return (EBUSY);
19641480Smckusick 	if ((ip->flags & ITE_ACTIVE) == 0) {
19741480Smckusick 		error = iteon(dev, 0);
19841480Smckusick 		if (error)
19941480Smckusick 			return (error);
20041480Smckusick 		first = 1;
20141480Smckusick 	}
20241480Smckusick 	tp->t_oproc = itestart;
20341480Smckusick 	tp->t_param = NULL;
20441480Smckusick 	tp->t_dev = dev;
20541480Smckusick 	if ((tp->t_state&TS_ISOPEN) == 0) {
20641480Smckusick 		ttychars(tp);
20741480Smckusick 		tp->t_iflag = TTYDEF_IFLAG;
20841480Smckusick 		tp->t_oflag = TTYDEF_OFLAG;
20941480Smckusick 		tp->t_cflag = CS8|CREAD;
21041480Smckusick 		tp->t_lflag = TTYDEF_LFLAG;
21141480Smckusick 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
21241480Smckusick 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
21341480Smckusick 		ttsetwater(tp);
21441480Smckusick 	}
21541480Smckusick 	error = (*linesw[tp->t_line].l_open)(dev, tp);
21641480Smckusick 	if (error == 0) {
21741480Smckusick 		tp->t_winsize.ws_row = ip->rows;
21841480Smckusick 		tp->t_winsize.ws_col = ip->cols;
21941480Smckusick 	} else if (first)
22041480Smckusick 		iteoff(dev, 0);
22141480Smckusick 	return (error);
22241480Smckusick }
22341480Smckusick 
22441480Smckusick /*ARGSUSED*/
iteclose(dev,flag,mode,p)22549750Smarc iteclose(dev, flag, mode, p)
22641480Smckusick 	dev_t dev;
22749750Smarc 	int flag, mode;
22849750Smarc 	struct proc *p;
22941480Smckusick {
23041480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
23141480Smckusick 
23249750Smarc 	(*linesw[tp->t_line].l_close)(tp, flag);
23341480Smckusick 	ttyclose(tp);
23441480Smckusick 	iteoff(dev, 0);
23541480Smckusick 	return(0);
23641480Smckusick }
23741480Smckusick 
iteread(dev,uio,flag)23841480Smckusick iteread(dev, uio, flag)
23941480Smckusick 	dev_t dev;
24041480Smckusick 	struct uio *uio;
24165645Sbostic 	int flag;
24241480Smckusick {
24341480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
24441480Smckusick 
24541480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
24641480Smckusick }
24741480Smckusick 
itewrite(dev,uio,flag)24841480Smckusick itewrite(dev, uio, flag)
24941480Smckusick 	dev_t dev;
25041480Smckusick 	struct uio *uio;
25165645Sbostic 	int flag;
25241480Smckusick {
25341480Smckusick 	int unit = UNIT(dev);
25441480Smckusick 	register struct tty *tp = &ite_tty[unit];
25541480Smckusick 
25641480Smckusick 	if ((ite_softc[unit].flags & ITE_ISCONS) && constty &&
25741480Smckusick 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
25841480Smckusick 		tp = constty;
25941480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
26041480Smckusick }
26141480Smckusick 
iteioctl(dev,cmd,addr,flag,p)26252417Smckusick iteioctl(dev, cmd, addr, flag, p)
26341480Smckusick 	dev_t dev;
264*68159Scgd 	u_long cmd;
26541480Smckusick 	caddr_t addr;
26652417Smckusick 	int flag;
26752417Smckusick 	struct proc *p;
26841480Smckusick {
26941480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
27041480Smckusick 	int error;
27141480Smckusick 
27252417Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
27341480Smckusick 	if (error >= 0)
27441480Smckusick 		return (error);
27541480Smckusick 	error = ttioctl(tp, cmd, addr, flag);
27641480Smckusick 	if (error >= 0)
27741480Smckusick 		return (error);
27841480Smckusick 	return (ENOTTY);
27941480Smckusick }
28041480Smckusick 
28152390Smckusick void
iterestart(tp)28257311Shibler iterestart(tp)
28357311Shibler 	register struct tty *tp;
28457311Shibler {
28557311Shibler 	register int s = splite();
28657311Shibler 
28757311Shibler 	tp->t_state &= ~TS_TIMEOUT;
28857311Shibler 	itestart(tp);
28957311Shibler 	splx(s);
29057311Shibler }
29157311Shibler 
29257311Shibler void
itestart(tp)29341480Smckusick itestart(tp)
29441480Smckusick 	register struct tty *tp;
29541480Smckusick {
29641480Smckusick 	register int cc, s;
29758052Shibler 	int hiwat = 0, hadcursor = 0;
29857311Shibler 	struct ite_softc *ip;
29941480Smckusick 
30057311Shibler 	/*
30157311Shibler 	 * (Potentially) lower priority.  We only need to protect ourselves
30257311Shibler 	 * from keyboard interrupts since that is all that can affect the
30357311Shibler 	 * state of our tty (kernel printf doesn't go through this routine).
30457311Shibler 	 */
30557311Shibler 	s = splite();
30641480Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
30741480Smckusick 		splx(s);
30841480Smckusick 		return;
30941480Smckusick 	}
31041480Smckusick 	tp->t_state |= TS_BUSY;
31141480Smckusick 	cc = tp->t_outq.c_cc;
31241480Smckusick 	if (cc <= tp->t_lowat) {
31341480Smckusick 		if (tp->t_state & TS_ASLEEP) {
31441480Smckusick 			tp->t_state &= ~TS_ASLEEP;
31552390Smckusick 			wakeup((caddr_t)&tp->t_outq);
31641480Smckusick 		}
31752530Storek 		selwakeup(&tp->t_wsel);
31841480Smckusick 	}
31941480Smckusick 	/*
32057311Shibler 	 * Handle common (?) case
32141480Smckusick 	 */
32257311Shibler 	if (cc == 1) {
32357311Shibler 		iteputchar(getc(&tp->t_outq), tp->t_dev);
32457311Shibler 	} else if (cc) {
32541480Smckusick 		/*
32657311Shibler 		 * Limit the amount of output we do in one burst
32757311Shibler 		 * to prevent hogging the CPU.
32841480Smckusick 		 */
32957311Shibler 		if (cc > iteburst) {
33057311Shibler 			hiwat++;
33157311Shibler 			cc = iteburst;
33257311Shibler 		}
33357311Shibler 		/*
33457311Shibler 		 * Turn off cursor while we output multiple characters.
33557311Shibler 		 * Saves a lot of expensive window move operations.
33657311Shibler 		 */
33757311Shibler 		ip = &ite_softc[UNIT(tp->t_dev)];
33858052Shibler 		if (ip->flags & ITE_CURSORON) {
33958052Shibler 			ite_erasecursor(ip, ip->isw);
34058052Shibler 			ip->flags &= ~ITE_CURSORON;
34158052Shibler 			hadcursor = 1;
34258052Shibler 		}
34357311Shibler 		while (--cc >= 0)
34457311Shibler 			iteputchar(getc(&tp->t_outq), tp->t_dev);
34558052Shibler 		if (hadcursor) {
34658052Shibler 			ip->flags |= ITE_CURSORON;
34758052Shibler 			ite_drawcursor(ip, ip->isw);
34858052Shibler 		}
34957311Shibler 		if (hiwat) {
35057311Shibler 			tp->t_state |= TS_TIMEOUT;
35157311Shibler 			timeout(iterestart, tp, 1);
35257311Shibler 		}
35341480Smckusick 	}
35441480Smckusick 	tp->t_state &= ~TS_BUSY;
35541480Smckusick 	splx(s);
35641480Smckusick }
35741480Smckusick 
itefilter(stat,c)35841480Smckusick itefilter(stat, c)
35965645Sbostic 	register char stat, c;
36041480Smckusick {
36141480Smckusick 	static int capsmode = 0;
36241480Smckusick 	static int metamode = 0;
36341480Smckusick   	register char code, *str;
36441480Smckusick 
36541480Smckusick 	if (kbd_tty == NULL)
36641480Smckusick 		return;
36741480Smckusick 
36841480Smckusick 	switch (c & 0xFF) {
36941480Smckusick 	case KBD_CAPSLOCK:
37041480Smckusick 		capsmode = !capsmode;
37141480Smckusick 		return;
37241480Smckusick 
37341480Smckusick 	case KBD_EXT_LEFT_DOWN:
37441480Smckusick 	case KBD_EXT_RIGHT_DOWN:
37541480Smckusick 		metamode = 1;
37641480Smckusick 		return;
37741480Smckusick 
37841480Smckusick 	case KBD_EXT_LEFT_UP:
37941480Smckusick 	case KBD_EXT_RIGHT_UP:
38041480Smckusick 		metamode = 0;
38141480Smckusick 		return;
38241480Smckusick 	}
38341480Smckusick 
38441480Smckusick 	c &= KBD_CHARMASK;
38541480Smckusick 	switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
38641480Smckusick 
38741480Smckusick 	case KBD_KEY:
38841480Smckusick 	        if (!capsmode) {
38941480Smckusick 			code = kbd_keymap[c];
39041480Smckusick 			break;
39141480Smckusick 		}
39265645Sbostic 		/* FALLTHROUGH */
39341480Smckusick 
39441480Smckusick 	case KBD_SHIFT:
39541480Smckusick 		code = kbd_shiftmap[c];
39641480Smckusick 		break;
39741480Smckusick 
39841480Smckusick 	case KBD_CTRL:
39941480Smckusick 		code = kbd_ctrlmap[c];
40041480Smckusick 		break;
40141480Smckusick 
40241480Smckusick 	case KBD_CTRLSHIFT:
40341480Smckusick 		code = kbd_ctrlshiftmap[c];
40441480Smckusick 		break;
40541480Smckusick         }
40641480Smckusick 
40741480Smckusick 	if (code == NULL && (str = kbd_stringmap[c]) != NULL) {
40841480Smckusick 		while (*str)
40941480Smckusick 			(*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
41041480Smckusick 	} else {
41141480Smckusick 		if (metamode)
41241480Smckusick 			code |= 0x80;
41341480Smckusick 		(*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
41441480Smckusick 	}
41541480Smckusick }
41641480Smckusick 
iteputchar(c,dev)41741480Smckusick iteputchar(c, dev)
41841480Smckusick 	register int c;
41941480Smckusick 	dev_t dev;
42041480Smckusick {
42141480Smckusick 	int unit = UNIT(dev);
42241480Smckusick 	register struct ite_softc *ip = &ite_softc[unit];
42353923Shibler 	register struct itesw *sp = ip->isw;
42441480Smckusick 	register int n;
42541480Smckusick 
42641480Smckusick 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
42741480Smckusick 	  	return;
42841480Smckusick 
42941480Smckusick 	if (ip->escape) {
43041480Smckusick doesc:
43141480Smckusick 		switch (ip->escape) {
43241480Smckusick 
43341480Smckusick 		case '&':			/* Next can be a,d, or s */
43441480Smckusick 			if (ip->fpd++) {
43541480Smckusick 				ip->escape = c;
43641480Smckusick 				ip->fpd = 0;
43741480Smckusick 			}
43841480Smckusick 			return;
43941480Smckusick 
44041480Smckusick 		case 'a':				/* cursor change */
44141480Smckusick 			switch (c) {
44241480Smckusick 
44341480Smckusick 			case 'Y':			/* Only y coord. */
44455069Spendry 				ip->cury = min(ip->pos, ip->rows-1);
44541480Smckusick 				ip->pos = 0;
44641480Smckusick 				ip->escape = 0;
44757311Shibler 				ite_movecursor(ip, sp);
44841480Smckusick 				clr_attr(ip, ATTR_INV);
44941480Smckusick 				break;
45041480Smckusick 
45141480Smckusick 			case 'y':			/* y coord first */
45255069Spendry 				ip->cury = min(ip->pos, ip->rows-1);
45341480Smckusick 				ip->pos = 0;
45441480Smckusick 				ip->fpd = 0;
45541480Smckusick 				break;
45641480Smckusick 
45741480Smckusick 			case 'C':			/* x coord */
45855069Spendry 				ip->curx = min(ip->pos, ip->cols-1);
45941480Smckusick 				ip->pos = 0;
46041480Smckusick 				ip->escape = 0;
46157311Shibler 				ite_movecursor(ip, sp);
46241480Smckusick 				clr_attr(ip, ATTR_INV);
46341480Smckusick 				break;
46441480Smckusick 
46541480Smckusick 			default:	     /* Possibly a 3 digit number. */
46641480Smckusick 				if (c >= '0' && c <= '9' && ip->fpd < 3) {
46741480Smckusick 					ip->pos = ip->pos * 10 + (c - '0');
46841480Smckusick 					ip->fpd++;
46941480Smckusick 				} else {
47041480Smckusick 					ip->pos = 0;
47141480Smckusick 					ip->escape = 0;
47241480Smckusick 				}
47341480Smckusick 				break;
47441480Smckusick 			}
47541480Smckusick 			return;
47641480Smckusick 
47741480Smckusick 		case 'd':				/* attribute change */
47841480Smckusick 			switch (c) {
47941480Smckusick 
48041480Smckusick 			case 'B':
48141480Smckusick 				set_attr(ip, ATTR_INV);
48241480Smckusick 				break;
48341480Smckusick 		        case 'D':
48441480Smckusick 				/* XXX: we don't do anything for underline */
48541480Smckusick 				set_attr(ip, ATTR_UL);
48641480Smckusick 				break;
48741480Smckusick 		        case '@':
48841480Smckusick 				clr_attr(ip, ATTR_ALL);
48941480Smckusick 				break;
49041480Smckusick 			}
49141480Smckusick 			ip->escape = 0;
49241480Smckusick 			return;
49341480Smckusick 
49441480Smckusick 		case 's':				/* keypad control */
49541480Smckusick 			switch (ip->fpd) {
49641480Smckusick 
49741480Smckusick 			case 0:
49841480Smckusick 				ip->hold = c;
49941480Smckusick 				ip->fpd++;
50041480Smckusick 				return;
50141480Smckusick 
50241480Smckusick 			case 1:
50341480Smckusick 				if (c == 'A') {
50441480Smckusick 					switch (ip->hold) {
50541480Smckusick 
50641480Smckusick 					case '0':
50741480Smckusick 						clr_attr(ip, ATTR_KPAD);
50841480Smckusick 						break;
50941480Smckusick 					case '1':
51041480Smckusick 						set_attr(ip, ATTR_KPAD);
51141480Smckusick 						break;
51241480Smckusick 					}
51341480Smckusick 				}
51441480Smckusick 				ip->hold = 0;
51541480Smckusick 			}
51641480Smckusick 			ip->escape = 0;
51741480Smckusick 			return;
51841480Smckusick 
51941480Smckusick 		case 'i':			/* back tab */
52041480Smckusick 			if (ip->curx > TABSIZE) {
52141480Smckusick 				n = ip->curx - (ip->curx & (TABSIZE - 1));
52241480Smckusick 				ip->curx -= n;
52341480Smckusick 			} else
52441480Smckusick 				ip->curx = 0;
52557311Shibler 			ite_movecursor(ip, sp);
52641480Smckusick 			ip->escape = 0;
52741480Smckusick 			return;
52841480Smckusick 
52941480Smckusick 		case '3':			/* clear all tabs */
53041480Smckusick 			goto ignore;
53141480Smckusick 
53241480Smckusick 		case 'K':			/* clear_eol */
53341480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, ip->curx);
53441480Smckusick 			ip->escape = 0;
53541480Smckusick 			return;
53641480Smckusick 
53741480Smckusick 		case 'J':			/* clear_eos */
53841480Smckusick 			ite_clrtoeos(ip, sp);
53941480Smckusick 			ip->escape = 0;
54041480Smckusick 			return;
54141480Smckusick 
54241480Smckusick 		case 'B':			/* cursor down 1 line */
54341480Smckusick 			if (++ip->cury == ip->rows) {
54441480Smckusick 				--ip->cury;
54557311Shibler 				ite_erasecursor(ip, sp);
54641480Smckusick 				(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
54741480Smckusick 				ite_clrtoeol(ip, sp, ip->cury, 0);
54841480Smckusick 			}
54941480Smckusick 			else
55057311Shibler 				ite_movecursor(ip, sp);
55141480Smckusick 			clr_attr(ip, ATTR_INV);
55241480Smckusick 			ip->escape = 0;
55341480Smckusick 			return;
55441480Smckusick 
55541480Smckusick 		case 'C':			/* cursor forward 1 char */
55641480Smckusick 			ip->escape = 0;
55741480Smckusick 			itecheckwrap(ip, sp);
55841480Smckusick 			return;
55941480Smckusick 
56041480Smckusick 		case 'A':			/* cursor up 1 line */
56141480Smckusick 			if (ip->cury > 0) {
56241480Smckusick 				ip->cury--;
56357311Shibler 				ite_movecursor(ip, sp);
56441480Smckusick 			}
56541480Smckusick 			ip->escape = 0;
56641480Smckusick 			clr_attr(ip, ATTR_INV);
56741480Smckusick 			return;
56841480Smckusick 
56941480Smckusick 		case 'P':			/* delete character */
57041480Smckusick 			ite_dchar(ip, sp);
57141480Smckusick 			ip->escape = 0;
57241480Smckusick 			return;
57341480Smckusick 
57441480Smckusick 		case 'M':			/* delete line */
57541480Smckusick 			ite_dline(ip, sp);
57641480Smckusick 			ip->escape = 0;
57741480Smckusick 			return;
57841480Smckusick 
57941480Smckusick 		case 'Q':			/* enter insert mode */
58041480Smckusick 			ip->imode = 1;
58141480Smckusick 			ip->escape = 0;
58241480Smckusick 			return;
58341480Smckusick 
58441480Smckusick 		case 'R':			/* exit insert mode */
58541480Smckusick 			ip->imode = 0;
58641480Smckusick 			ip->escape = 0;
58741480Smckusick 			return;
58841480Smckusick 
58941480Smckusick 		case 'L':			/* insert blank line */
59041480Smckusick 			ite_iline(ip, sp);
59141480Smckusick 			ip->escape = 0;
59241480Smckusick 			return;
59341480Smckusick 
59441480Smckusick 		case 'h':			/* home key */
59541480Smckusick 			ip->cury = ip->curx = 0;
59657311Shibler 			ite_movecursor(ip, sp);
59741480Smckusick 			ip->escape = 0;
59841480Smckusick 			return;
59941480Smckusick 
60041480Smckusick 		case 'D':			/* left arrow key */
60141480Smckusick 			if (ip->curx > 0) {
60241480Smckusick 				ip->curx--;
60357311Shibler 				ite_movecursor(ip, sp);
60441480Smckusick 			}
60541480Smckusick 			ip->escape = 0;
60641480Smckusick 			return;
60741480Smckusick 
60841480Smckusick 		case '1':			/* set tab in all rows */
60941480Smckusick 			goto ignore;
61041480Smckusick 
61141480Smckusick 		case ESC:
61241480Smckusick 			if ((ip->escape = c) == ESC)
61341480Smckusick 				break;
61441480Smckusick 			ip->fpd = 0;
61541480Smckusick 			goto doesc;
61641480Smckusick 
61741480Smckusick 		default:
61841480Smckusick ignore:
61941480Smckusick 			ip->escape = 0;
62041480Smckusick 			return;
62141480Smckusick 
62241480Smckusick 		}
62341480Smckusick 	}
62441480Smckusick 
62541480Smckusick 	switch (c &= 0x7F) {
62641480Smckusick 
62741480Smckusick 	case '\n':
62841480Smckusick 
62941480Smckusick 		if (++ip->cury == ip->rows) {
63041480Smckusick 			--ip->cury;
63157311Shibler 			ite_erasecursor(ip, sp);
63241480Smckusick 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
63341480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, 0);
63457311Shibler 		} else
63557311Shibler 			ite_movecursor(ip, sp);
63641480Smckusick 		clr_attr(ip, ATTR_INV);
63741480Smckusick 		break;
63841480Smckusick 
63941480Smckusick 	case '\r':
64041480Smckusick 		if (ip->curx) {
64141480Smckusick 			ip->curx = 0;
64257311Shibler 			ite_movecursor(ip, sp);
64341480Smckusick 		}
64441480Smckusick 		break;
64541480Smckusick 
64641480Smckusick 	case '\b':
64741480Smckusick 		if (--ip->curx < 0)
64841480Smckusick 			ip->curx = 0;
64941480Smckusick 		else
65057311Shibler 			ite_movecursor(ip, sp);
65141480Smckusick 		break;
65241480Smckusick 
65341480Smckusick 	case '\t':
65441480Smckusick 		if (ip->curx < TABEND(unit)) {
65541480Smckusick 			n = TABSIZE - (ip->curx & (TABSIZE - 1));
65641480Smckusick 			ip->curx += n;
65757311Shibler 			ite_movecursor(ip, sp);
65841480Smckusick 		} else
65941480Smckusick 			itecheckwrap(ip, sp);
66041480Smckusick 		break;
66141480Smckusick 
66241480Smckusick 	case CTRL('G'):
66341480Smckusick 		if (&ite_tty[unit] == kbd_tty)
66453923Shibler 			kbdbell(unit);
66541480Smckusick 		break;
66641480Smckusick 
66741480Smckusick 	case ESC:
66841480Smckusick 		ip->escape = ESC;
66941480Smckusick 		break;
67041480Smckusick 
67141480Smckusick 	default:
67241480Smckusick 		if (c < ' ' || c == DEL)
67341480Smckusick 			break;
67441480Smckusick 		if (ip->imode)
67541480Smckusick 			ite_ichar(ip, sp);
67641480Smckusick 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
67741480Smckusick 			attrset(ip, ATTR_INV);
67841480Smckusick 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
67957311Shibler 		} else
68041480Smckusick 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
68157311Shibler 		ite_drawcursor(ip, sp);
68241480Smckusick 		itecheckwrap(ip, sp);
68341480Smckusick 		break;
68441480Smckusick 	}
68541480Smckusick }
68641480Smckusick 
itecheckwrap(ip,sp)68741480Smckusick itecheckwrap(ip, sp)
68841480Smckusick      register struct ite_softc *ip;
68941480Smckusick      register struct itesw *sp;
69041480Smckusick {
69141480Smckusick 	if (++ip->curx == ip->cols) {
69241480Smckusick 		ip->curx = 0;
69341480Smckusick 		clr_attr(ip, ATTR_INV);
69441480Smckusick 		if (++ip->cury == ip->rows) {
69541480Smckusick 			--ip->cury;
69657311Shibler 			ite_erasecursor(ip, sp);
69741480Smckusick 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
69841480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, 0);
69941480Smckusick 			return;
70041480Smckusick 		}
70141480Smckusick 	}
70257311Shibler 	ite_movecursor(ip, sp);
70341480Smckusick }
70441480Smckusick 
ite_dchar(ip,sp)70541480Smckusick ite_dchar(ip, sp)
70641480Smckusick      register struct ite_softc *ip;
70741480Smckusick      register struct itesw *sp;
70841480Smckusick {
70957311Shibler 	if (ip->curx < ip->cols - 1) {
71057311Shibler 		ite_erasecursor(ip, sp);
71157311Shibler 		(*sp->ite_scroll)(ip, ip->cury, ip->curx + 1, 1, SCROLL_LEFT);
71257311Shibler 		attrmov(ip, ip->cury, ip->curx + 1, ip->cury, ip->curx,
71357311Shibler 			1, ip->cols - ip->curx - 1);
71457311Shibler 	}
71541480Smckusick 	attrclr(ip, ip->cury, ip->cols - 1, 1, 1);
71641480Smckusick 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - 1, ATTR_NOR);
71757311Shibler 	ite_drawcursor(ip, sp);
71841480Smckusick }
71941480Smckusick 
ite_ichar(ip,sp)72041480Smckusick ite_ichar(ip, sp)
72141480Smckusick      register struct ite_softc *ip;
72241480Smckusick      register struct itesw *sp;
72341480Smckusick {
72457311Shibler 	if (ip->curx < ip->cols - 1) {
72557311Shibler 		ite_erasecursor(ip, sp);
72657311Shibler 		(*sp->ite_scroll)(ip, ip->cury, ip->curx, 1, SCROLL_RIGHT);
72757311Shibler 		attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + 1,
72857311Shibler 			1, ip->cols - ip->curx - 1);
72957311Shibler 	}
73041480Smckusick 	attrclr(ip, ip->cury, ip->curx, 1, 1);
73141480Smckusick 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->curx, ATTR_NOR);
73257311Shibler 	ite_drawcursor(ip, sp);
73341480Smckusick }
73441480Smckusick 
ite_dline(ip,sp)73541480Smckusick ite_dline(ip, sp)
73641480Smckusick      register struct ite_softc *ip;
73741480Smckusick      register struct itesw *sp;
73841480Smckusick {
73957311Shibler 	if (ip->cury < ip->rows - 1) {
74057311Shibler 		ite_erasecursor(ip, sp);
74157311Shibler 		(*sp->ite_scroll)(ip, ip->cury + 1, 0, 1, SCROLL_UP);
74257311Shibler 		attrmov(ip, ip->cury + 1, 0, ip->cury, 0,
74357311Shibler 			ip->rows - ip->cury - 1, ip->cols);
74457311Shibler 	}
74541480Smckusick 	ite_clrtoeol(ip, sp, ip->rows - 1, 0);
74641480Smckusick }
74741480Smckusick 
ite_iline(ip,sp)74841480Smckusick ite_iline(ip, sp)
74941480Smckusick      register struct ite_softc *ip;
75041480Smckusick      register struct itesw *sp;
75141480Smckusick {
75257311Shibler 	if (ip->cury < ip->rows - 1) {
75357311Shibler 		ite_erasecursor(ip, sp);
75457311Shibler 		(*sp->ite_scroll)(ip, ip->cury, 0, 1, SCROLL_DOWN);
75557311Shibler 		attrmov(ip, ip->cury, 0, ip->cury + 1, 0,
75657311Shibler 			ip->rows - ip->cury - 1, ip->cols);
75757311Shibler 	}
75841480Smckusick 	ite_clrtoeol(ip, sp, ip->cury, 0);
75941480Smckusick }
76041480Smckusick 
ite_clrtoeol(ip,sp,y,x)76141480Smckusick ite_clrtoeol(ip, sp, y, x)
76241480Smckusick      register struct ite_softc *ip;
76341480Smckusick      register struct itesw *sp;
76441480Smckusick      register int y, x;
76541480Smckusick {
76641480Smckusick 	(*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
76741480Smckusick 	attrclr(ip, y, x, 1, ip->cols - x);
76857311Shibler 	ite_drawcursor(ip, sp);
76941480Smckusick }
77041480Smckusick 
ite_clrtoeos(ip,sp)77141480Smckusick ite_clrtoeos(ip, sp)
77241480Smckusick      register struct ite_softc *ip;
77341480Smckusick      register struct itesw *sp;
77441480Smckusick {
77541480Smckusick 	(*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
77641480Smckusick 	attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
77757311Shibler 	ite_drawcursor(ip, sp);
77841480Smckusick }
77941480Smckusick 
78041480Smckusick /*
78141480Smckusick  * Console functions
78241480Smckusick  */
78356504Sbostic #include <hp/dev/cons.h>
78453923Shibler #ifdef hp300
78556504Sbostic #include <hp/dev/grfreg.h>
78653923Shibler #endif
78741480Smckusick 
78841480Smckusick #ifdef DEBUG
78941480Smckusick /*
79041480Smckusick  * Minimum ITE number at which to start looking for a console.
79141480Smckusick  * Setting to 0 will do normal search, 1 will skip first ITE device,
79241480Smckusick  * NITE will skip ITEs and use serial port.
79341480Smckusick  */
79441480Smckusick int	whichconsole = 0;
79541480Smckusick #endif
79641480Smckusick 
79741480Smckusick itecnprobe(cp)
79841480Smckusick 	struct consdev *cp;
79941480Smckusick {
80041480Smckusick 	register struct ite_softc *ip;
80153923Shibler 	int i, sw, maj, unit, pri;
80241480Smckusick 
80341480Smckusick 	/* locate the major number */
80441480Smckusick 	for (maj = 0; maj < nchrdev; maj++)
80541480Smckusick 		if (cdevsw[maj].d_open == iteopen)
80641480Smckusick 			break;
80741480Smckusick 
80841480Smckusick 	/* urk! */
80941480Smckusick 	grfconfig();
81041480Smckusick 
81141480Smckusick 	/* check all the individual displays and find the best */
81241480Smckusick 	unit = -1;
81341480Smckusick 	pri = CN_DEAD;
81441480Smckusick 	for (i = 0; i < NITE; i++) {
81541480Smckusick 		struct grf_softc *gp = &grf_softc[i];
81641480Smckusick 
81741480Smckusick 		ip = &ite_softc[i];
81841480Smckusick 		if ((gp->g_flags & GF_ALIVE) == 0)
81941480Smckusick 			continue;
82041480Smckusick 		ip->flags = (ITE_ALIVE|ITE_CONSOLE);
82141480Smckusick 
82253923Shibler 		/* locate the proper switch table. */
82353923Shibler 		for (sw = 0; sw < nitesw; sw++)
82453923Shibler 			if (itesw[sw].ite_hwid == gp->g_sw->gd_hwid)
82553923Shibler 				break;
82641480Smckusick 
82753923Shibler 		if (sw == nitesw)
82853923Shibler 			continue;
82941480Smckusick #ifdef DEBUG
83041480Smckusick 		if (i < whichconsole)
83141480Smckusick 			continue;
83241480Smckusick #endif
83353923Shibler 		ip->isw = &itesw[sw];
83453923Shibler 		ip->grf = gp;
83553923Shibler #ifdef hp300
83641480Smckusick 		if ((int)gp->g_display.gd_regaddr == GRFIADDR) {
83741480Smckusick 			pri = CN_INTERNAL;
83841480Smckusick 			unit = i;
83941480Smckusick 		} else if (unit < 0) {
84041480Smckusick 			pri = CN_NORMAL;
84141480Smckusick 			unit = i;
84241480Smckusick 		}
84353923Shibler #endif
84453923Shibler #ifdef hp800
84553923Shibler 		/* XXX use the first one for now */
84653923Shibler 		if (unit < 0) {
84753923Shibler 			pri = CN_INTERNAL;
84853923Shibler 			unit = i;
84953923Shibler 		}
85053923Shibler #endif
85141480Smckusick 	}
85241480Smckusick 
85341480Smckusick 	/* initialize required fields */
85441480Smckusick 	cp->cn_dev = makedev(maj, unit);
85541480Smckusick 	cp->cn_tp = &ite_tty[unit];
85641480Smckusick 	cp->cn_pri = pri;
85741480Smckusick }
85841480Smckusick 
85941480Smckusick itecninit(cp)
86041480Smckusick 	struct consdev *cp;
86141480Smckusick {
86241480Smckusick 	int unit = UNIT(cp->cn_dev);
86341480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
86441480Smckusick 
86541480Smckusick 	ip->attrbuf = console_attributes;
86641480Smckusick 	iteinit(cp->cn_dev);
86741480Smckusick 	ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
86841480Smckusick 	kbd_tty = &ite_tty[unit];
86941480Smckusick }
87041480Smckusick 
87141480Smckusick /*ARGSUSED*/
itecngetc(dev)87241480Smckusick itecngetc(dev)
87341480Smckusick 	dev_t dev;
87441480Smckusick {
87541480Smckusick 	register int c;
87641480Smckusick 	int stat;
87741480Smckusick 
87853923Shibler 	c = kbdgetc(0, &stat);	/* XXX always read from keyboard 0 for now */
87941480Smckusick 	switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
88041480Smckusick 	case KBD_SHIFT:
88141480Smckusick 		c = kbd_shiftmap[c & KBD_CHARMASK];
88241480Smckusick 		break;
88341480Smckusick 	case KBD_CTRL:
88441480Smckusick 		c = kbd_ctrlmap[c & KBD_CHARMASK];
88541480Smckusick 		break;
88641480Smckusick 	case KBD_KEY:
88741480Smckusick 		c = kbd_keymap[c & KBD_CHARMASK];
88841480Smckusick 		break;
88941480Smckusick 	default:
89041480Smckusick 		c = 0;
89141480Smckusick 		break;
89241480Smckusick 	}
89341480Smckusick 	return(c);
89441480Smckusick }
89541480Smckusick 
itecnputc(dev,c)89641480Smckusick itecnputc(dev, c)
89741480Smckusick 	dev_t dev;
89841480Smckusick 	int c;
89941480Smckusick {
90041480Smckusick 	static int paniced = 0;
90141480Smckusick 	struct ite_softc *ip = &ite_softc[UNIT(dev)];
90241480Smckusick 
90341480Smckusick 	if (panicstr && !paniced &&
90441480Smckusick 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
90541480Smckusick 		(void) iteon(dev, 3);
90641480Smckusick 		paniced = 1;
90741480Smckusick 	}
90841480Smckusick 	iteputchar(c, dev);
90941480Smckusick }
91041480Smckusick #endif
911