xref: /csrg-svn/sys/hp/dev/ite.c (revision 58052)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1988 University of Utah.
341480Smckusick  * Copyright (c) 1990 The Regents of the University of California.
441480Smckusick  * 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*58052Shibler  *	@(#)ite.c	7.16 (Berkeley) 02/18/93
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  */
9241480Smckusick iteon(dev, flag)
9341480Smckusick 	dev_t dev;
9441480Smckusick {
9541480Smckusick 	int unit = UNIT(dev);
9641480Smckusick 	struct tty *tp = &ite_tty[unit];
9741480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
9841480Smckusick 
9941480Smckusick 	if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0)
10041480Smckusick 		return(ENXIO);
10141480Smckusick 	/* force ite active, overriding graphics mode */
10241480Smckusick 	if (flag & 1) {
10341480Smckusick 		ip->flags |= ITE_ACTIVE;
10441480Smckusick 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
10541480Smckusick 	}
10641480Smckusick 	/* leave graphics mode */
10741480Smckusick 	if (flag & 2) {
10841480Smckusick 		ip->flags &= ~ITE_INGRF;
10941480Smckusick 		if ((ip->flags & ITE_ACTIVE) == 0)
11041480Smckusick 			return(0);
11141480Smckusick 	}
11241480Smckusick 	ip->flags |= ITE_ACTIVE;
11341480Smckusick 	if (ip->flags & ITE_INGRF)
11441480Smckusick 		return(0);
11541480Smckusick 	if (kbd_tty == NULL || kbd_tty == tp) {
11641480Smckusick 		kbd_tty = tp;
11753923Shibler 		kbdenable(unit);
11841480Smckusick 	}
11941480Smckusick 	iteinit(dev);
12041480Smckusick 	return(0);
12141480Smckusick }
12241480Smckusick 
12341480Smckusick iteinit(dev)
12441480Smckusick      dev_t dev;
12541480Smckusick {
12641480Smckusick 	int unit = UNIT(dev);
12741480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
12841480Smckusick 
12941480Smckusick 	if (ip->flags & ITE_INITED)
13041480Smckusick 		return;
13141480Smckusick 
13241480Smckusick 	ip->curx = 0;
13341480Smckusick 	ip->cury = 0;
13441480Smckusick 	ip->cursorx = 0;
13541480Smckusick 	ip->cursory = 0;
13641480Smckusick 
13753923Shibler 	(*ip->isw->ite_init)(ip);
13857311Shibler 	ip->flags |= ITE_CURSORON;
13957311Shibler 	ite_drawcursor(ip, ip->isw);
14041480Smckusick 
14141480Smckusick 	ip->attribute = 0;
14241480Smckusick 	if (ip->attrbuf == NULL)
14341480Smckusick 		ip->attrbuf = (u_char *)
14441480Smckusick 			malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK);
14541480Smckusick 	bzero(ip->attrbuf, (ip->rows * ip->cols));
14641480Smckusick 
14741480Smckusick 	ip->imode = 0;
14841480Smckusick 	ip->flags |= ITE_INITED;
14941480Smckusick }
15041480Smckusick 
15141480Smckusick /*
15241480Smckusick  * "Shut down" device as terminal emulator.
15341480Smckusick  * Note that we do not deinit the console device unless forced.
15441480Smckusick  * Deinit'ing the console every time leads to a very active
15541480Smckusick  * screen when processing /etc/rc.
15641480Smckusick  */
15741480Smckusick iteoff(dev, flag)
15841480Smckusick 	dev_t dev;
15941480Smckusick {
16041480Smckusick 	register struct ite_softc *ip = &ite_softc[UNIT(dev)];
16141480Smckusick 
162*58052Shibler 	if (flag & 2) {
16341480Smckusick 		ip->flags |= ITE_INGRF;
164*58052Shibler 		ip->flags &= ~ITE_CURSORON;
165*58052Shibler 	}
16641480Smckusick 	if ((ip->flags & ITE_ACTIVE) == 0)
16741480Smckusick 		return;
16841480Smckusick 	if ((flag & 1) ||
169*58052Shibler 	    (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
17053923Shibler 		(*ip->isw->ite_deinit)(ip);
17141480Smckusick 	if ((flag & 2) == 0)
17241480Smckusick 		ip->flags &= ~ITE_ACTIVE;
17341480Smckusick }
17441480Smckusick 
17549132Skarels /* ARGSUSED */
17649132Skarels #ifdef __STDC__
17749132Skarels iteopen(dev_t dev, int mode, int devtype, struct proc *p)
17849132Skarels #else
17949132Skarels iteopen(dev, mode, devtype, p)
18041480Smckusick 	dev_t dev;
18149132Skarels 	int mode, devtype;
18249132Skarels 	struct proc *p;
18349132Skarels #endif
18441480Smckusick {
18541480Smckusick 	int unit = UNIT(dev);
18641480Smckusick 	register struct tty *tp = &ite_tty[unit];
18741480Smckusick 	register struct ite_softc *ip = &ite_softc[unit];
18841480Smckusick 	register int error;
18941480Smckusick 	int first = 0;
19041480Smckusick 
19143409Shibler 	if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
19249132Skarels 	    && p->p_ucred->cr_uid != 0)
19341480Smckusick 		return (EBUSY);
19441480Smckusick 	if ((ip->flags & ITE_ACTIVE) == 0) {
19541480Smckusick 		error = iteon(dev, 0);
19641480Smckusick 		if (error)
19741480Smckusick 			return (error);
19841480Smckusick 		first = 1;
19941480Smckusick 	}
20041480Smckusick 	tp->t_oproc = itestart;
20141480Smckusick 	tp->t_param = NULL;
20241480Smckusick 	tp->t_dev = dev;
20341480Smckusick 	if ((tp->t_state&TS_ISOPEN) == 0) {
20441480Smckusick 		ttychars(tp);
20541480Smckusick 		tp->t_iflag = TTYDEF_IFLAG;
20641480Smckusick 		tp->t_oflag = TTYDEF_OFLAG;
20741480Smckusick 		tp->t_cflag = CS8|CREAD;
20841480Smckusick 		tp->t_lflag = TTYDEF_LFLAG;
20941480Smckusick 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
21041480Smckusick 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
21141480Smckusick 		ttsetwater(tp);
21241480Smckusick 	}
21341480Smckusick 	error = (*linesw[tp->t_line].l_open)(dev, tp);
21441480Smckusick 	if (error == 0) {
21541480Smckusick 		tp->t_winsize.ws_row = ip->rows;
21641480Smckusick 		tp->t_winsize.ws_col = ip->cols;
21741480Smckusick 	} else if (first)
21841480Smckusick 		iteoff(dev, 0);
21941480Smckusick 	return (error);
22041480Smckusick }
22141480Smckusick 
22241480Smckusick /*ARGSUSED*/
22349750Smarc iteclose(dev, flag, mode, p)
22441480Smckusick 	dev_t dev;
22549750Smarc 	int flag, mode;
22649750Smarc 	struct proc *p;
22741480Smckusick {
22841480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
22941480Smckusick 
23049750Smarc 	(*linesw[tp->t_line].l_close)(tp, flag);
23141480Smckusick 	ttyclose(tp);
23241480Smckusick 	iteoff(dev, 0);
23341480Smckusick 	return(0);
23441480Smckusick }
23541480Smckusick 
23641480Smckusick iteread(dev, uio, flag)
23741480Smckusick 	dev_t dev;
23841480Smckusick 	struct uio *uio;
23941480Smckusick {
24041480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
24141480Smckusick 
24241480Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
24341480Smckusick }
24441480Smckusick 
24541480Smckusick itewrite(dev, uio, flag)
24641480Smckusick 	dev_t dev;
24741480Smckusick 	struct uio *uio;
24841480Smckusick {
24941480Smckusick 	int unit = UNIT(dev);
25041480Smckusick 	register struct tty *tp = &ite_tty[unit];
25141480Smckusick 
25241480Smckusick 	if ((ite_softc[unit].flags & ITE_ISCONS) && constty &&
25341480Smckusick 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
25441480Smckusick 		tp = constty;
25541480Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
25641480Smckusick }
25741480Smckusick 
25852417Smckusick iteioctl(dev, cmd, addr, flag, p)
25941480Smckusick 	dev_t dev;
26052417Smckusick 	int cmd;
26141480Smckusick 	caddr_t addr;
26252417Smckusick 	int flag;
26352417Smckusick 	struct proc *p;
26441480Smckusick {
26541480Smckusick 	register struct tty *tp = &ite_tty[UNIT(dev)];
26641480Smckusick 	int error;
26741480Smckusick 
26852417Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
26941480Smckusick 	if (error >= 0)
27041480Smckusick 		return (error);
27141480Smckusick 	error = ttioctl(tp, cmd, addr, flag);
27241480Smckusick 	if (error >= 0)
27341480Smckusick 		return (error);
27441480Smckusick 	return (ENOTTY);
27541480Smckusick }
27641480Smckusick 
27752390Smckusick void
27857311Shibler iterestart(tp)
27957311Shibler 	register struct tty *tp;
28057311Shibler {
28157311Shibler 	register int s = splite();
28257311Shibler 
28357311Shibler 	tp->t_state &= ~TS_TIMEOUT;
28457311Shibler 	itestart(tp);
28557311Shibler 	splx(s);
28657311Shibler }
28757311Shibler 
28857311Shibler void
28941480Smckusick itestart(tp)
29041480Smckusick 	register struct tty *tp;
29141480Smckusick {
29241480Smckusick 	register int cc, s;
293*58052Shibler 	int hiwat = 0, hadcursor = 0;
29457311Shibler 	struct ite_softc *ip;
29541480Smckusick 
29657311Shibler 	/*
29757311Shibler 	 * (Potentially) lower priority.  We only need to protect ourselves
29857311Shibler 	 * from keyboard interrupts since that is all that can affect the
29957311Shibler 	 * state of our tty (kernel printf doesn't go through this routine).
30057311Shibler 	 */
30157311Shibler 	s = splite();
30241480Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
30341480Smckusick 		splx(s);
30441480Smckusick 		return;
30541480Smckusick 	}
30641480Smckusick 	tp->t_state |= TS_BUSY;
30741480Smckusick 	cc = tp->t_outq.c_cc;
30841480Smckusick 	if (cc <= tp->t_lowat) {
30941480Smckusick 		if (tp->t_state & TS_ASLEEP) {
31041480Smckusick 			tp->t_state &= ~TS_ASLEEP;
31152390Smckusick 			wakeup((caddr_t)&tp->t_outq);
31241480Smckusick 		}
31352530Storek 		selwakeup(&tp->t_wsel);
31441480Smckusick 	}
31541480Smckusick 	/*
31657311Shibler 	 * Handle common (?) case
31741480Smckusick 	 */
31857311Shibler 	if (cc == 1) {
31957311Shibler 		iteputchar(getc(&tp->t_outq), tp->t_dev);
32057311Shibler 	} else if (cc) {
32141480Smckusick 		/*
32257311Shibler 		 * Limit the amount of output we do in one burst
32357311Shibler 		 * to prevent hogging the CPU.
32441480Smckusick 		 */
32557311Shibler 		if (cc > iteburst) {
32657311Shibler 			hiwat++;
32757311Shibler 			cc = iteburst;
32857311Shibler 		}
32957311Shibler 		/*
33057311Shibler 		 * Turn off cursor while we output multiple characters.
33157311Shibler 		 * Saves a lot of expensive window move operations.
33257311Shibler 		 */
33357311Shibler 		ip = &ite_softc[UNIT(tp->t_dev)];
334*58052Shibler 		if (ip->flags & ITE_CURSORON) {
335*58052Shibler 			ite_erasecursor(ip, ip->isw);
336*58052Shibler 			ip->flags &= ~ITE_CURSORON;
337*58052Shibler 			hadcursor = 1;
338*58052Shibler 		}
33957311Shibler 		while (--cc >= 0)
34057311Shibler 			iteputchar(getc(&tp->t_outq), tp->t_dev);
341*58052Shibler 		if (hadcursor) {
342*58052Shibler 			ip->flags |= ITE_CURSORON;
343*58052Shibler 			ite_drawcursor(ip, ip->isw);
344*58052Shibler 		}
34557311Shibler 		if (hiwat) {
34657311Shibler 			tp->t_state |= TS_TIMEOUT;
34757311Shibler 			timeout(iterestart, tp, 1);
34857311Shibler 		}
34941480Smckusick 	}
35041480Smckusick 	tp->t_state &= ~TS_BUSY;
35141480Smckusick 	splx(s);
35241480Smckusick }
35341480Smckusick 
35441480Smckusick itefilter(stat, c)
35541480Smckusick      register char stat, c;
35641480Smckusick {
35741480Smckusick 	static int capsmode = 0;
35841480Smckusick 	static int metamode = 0;
35941480Smckusick   	register char code, *str;
36041480Smckusick 
36141480Smckusick 	if (kbd_tty == NULL)
36241480Smckusick 		return;
36341480Smckusick 
36441480Smckusick 	switch (c & 0xFF) {
36541480Smckusick 	case KBD_CAPSLOCK:
36641480Smckusick 		capsmode = !capsmode;
36741480Smckusick 		return;
36841480Smckusick 
36941480Smckusick 	case KBD_EXT_LEFT_DOWN:
37041480Smckusick 	case KBD_EXT_RIGHT_DOWN:
37141480Smckusick 		metamode = 1;
37241480Smckusick 		return;
37341480Smckusick 
37441480Smckusick 	case KBD_EXT_LEFT_UP:
37541480Smckusick 	case KBD_EXT_RIGHT_UP:
37641480Smckusick 		metamode = 0;
37741480Smckusick 		return;
37841480Smckusick 	}
37941480Smckusick 
38041480Smckusick 	c &= KBD_CHARMASK;
38141480Smckusick 	switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
38241480Smckusick 
38341480Smckusick 	case KBD_KEY:
38441480Smckusick 	        if (!capsmode) {
38541480Smckusick 			code = kbd_keymap[c];
38641480Smckusick 			break;
38741480Smckusick 		}
38841480Smckusick 		/* fall into... */
38941480Smckusick 
39041480Smckusick 	case KBD_SHIFT:
39141480Smckusick 		code = kbd_shiftmap[c];
39241480Smckusick 		break;
39341480Smckusick 
39441480Smckusick 	case KBD_CTRL:
39541480Smckusick 		code = kbd_ctrlmap[c];
39641480Smckusick 		break;
39741480Smckusick 
39841480Smckusick 	case KBD_CTRLSHIFT:
39941480Smckusick 		code = kbd_ctrlshiftmap[c];
40041480Smckusick 		break;
40141480Smckusick         }
40241480Smckusick 
40341480Smckusick 	if (code == NULL && (str = kbd_stringmap[c]) != NULL) {
40441480Smckusick 		while (*str)
40541480Smckusick 			(*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
40641480Smckusick 	} else {
40741480Smckusick 		if (metamode)
40841480Smckusick 			code |= 0x80;
40941480Smckusick 		(*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
41041480Smckusick 	}
41141480Smckusick }
41241480Smckusick 
41341480Smckusick iteputchar(c, dev)
41441480Smckusick 	register int c;
41541480Smckusick 	dev_t dev;
41641480Smckusick {
41741480Smckusick 	int unit = UNIT(dev);
41841480Smckusick 	register struct ite_softc *ip = &ite_softc[unit];
41953923Shibler 	register struct itesw *sp = ip->isw;
42041480Smckusick 	register int n;
42141480Smckusick 
42241480Smckusick 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
42341480Smckusick 	  	return;
42441480Smckusick 
42541480Smckusick 	if (ip->escape) {
42641480Smckusick doesc:
42741480Smckusick 		switch (ip->escape) {
42841480Smckusick 
42941480Smckusick 		case '&':			/* Next can be a,d, or s */
43041480Smckusick 			if (ip->fpd++) {
43141480Smckusick 				ip->escape = c;
43241480Smckusick 				ip->fpd = 0;
43341480Smckusick 			}
43441480Smckusick 			return;
43541480Smckusick 
43641480Smckusick 		case 'a':				/* cursor change */
43741480Smckusick 			switch (c) {
43841480Smckusick 
43941480Smckusick 			case 'Y':			/* Only y coord. */
44055069Spendry 				ip->cury = min(ip->pos, ip->rows-1);
44141480Smckusick 				ip->pos = 0;
44241480Smckusick 				ip->escape = 0;
44357311Shibler 				ite_movecursor(ip, sp);
44441480Smckusick 				clr_attr(ip, ATTR_INV);
44541480Smckusick 				break;
44641480Smckusick 
44741480Smckusick 			case 'y':			/* y coord first */
44855069Spendry 				ip->cury = min(ip->pos, ip->rows-1);
44941480Smckusick 				ip->pos = 0;
45041480Smckusick 				ip->fpd = 0;
45141480Smckusick 				break;
45241480Smckusick 
45341480Smckusick 			case 'C':			/* x coord */
45455069Spendry 				ip->curx = min(ip->pos, ip->cols-1);
45541480Smckusick 				ip->pos = 0;
45641480Smckusick 				ip->escape = 0;
45757311Shibler 				ite_movecursor(ip, sp);
45841480Smckusick 				clr_attr(ip, ATTR_INV);
45941480Smckusick 				break;
46041480Smckusick 
46141480Smckusick 			default:	     /* Possibly a 3 digit number. */
46241480Smckusick 				if (c >= '0' && c <= '9' && ip->fpd < 3) {
46341480Smckusick 					ip->pos = ip->pos * 10 + (c - '0');
46441480Smckusick 					ip->fpd++;
46541480Smckusick 				} else {
46641480Smckusick 					ip->pos = 0;
46741480Smckusick 					ip->escape = 0;
46841480Smckusick 				}
46941480Smckusick 				break;
47041480Smckusick 			}
47141480Smckusick 			return;
47241480Smckusick 
47341480Smckusick 		case 'd':				/* attribute change */
47441480Smckusick 			switch (c) {
47541480Smckusick 
47641480Smckusick 			case 'B':
47741480Smckusick 				set_attr(ip, ATTR_INV);
47841480Smckusick 				break;
47941480Smckusick 		        case 'D':
48041480Smckusick 				/* XXX: we don't do anything for underline */
48141480Smckusick 				set_attr(ip, ATTR_UL);
48241480Smckusick 				break;
48341480Smckusick 		        case '@':
48441480Smckusick 				clr_attr(ip, ATTR_ALL);
48541480Smckusick 				break;
48641480Smckusick 			}
48741480Smckusick 			ip->escape = 0;
48841480Smckusick 			return;
48941480Smckusick 
49041480Smckusick 		case 's':				/* keypad control */
49141480Smckusick 			switch (ip->fpd) {
49241480Smckusick 
49341480Smckusick 			case 0:
49441480Smckusick 				ip->hold = c;
49541480Smckusick 				ip->fpd++;
49641480Smckusick 				return;
49741480Smckusick 
49841480Smckusick 			case 1:
49941480Smckusick 				if (c == 'A') {
50041480Smckusick 					switch (ip->hold) {
50141480Smckusick 
50241480Smckusick 					case '0':
50341480Smckusick 						clr_attr(ip, ATTR_KPAD);
50441480Smckusick 						break;
50541480Smckusick 					case '1':
50641480Smckusick 						set_attr(ip, ATTR_KPAD);
50741480Smckusick 						break;
50841480Smckusick 					}
50941480Smckusick 				}
51041480Smckusick 				ip->hold = 0;
51141480Smckusick 			}
51241480Smckusick 			ip->escape = 0;
51341480Smckusick 			return;
51441480Smckusick 
51541480Smckusick 		case 'i':			/* back tab */
51641480Smckusick 			if (ip->curx > TABSIZE) {
51741480Smckusick 				n = ip->curx - (ip->curx & (TABSIZE - 1));
51841480Smckusick 				ip->curx -= n;
51941480Smckusick 			} else
52041480Smckusick 				ip->curx = 0;
52157311Shibler 			ite_movecursor(ip, sp);
52241480Smckusick 			ip->escape = 0;
52341480Smckusick 			return;
52441480Smckusick 
52541480Smckusick 		case '3':			/* clear all tabs */
52641480Smckusick 			goto ignore;
52741480Smckusick 
52841480Smckusick 		case 'K':			/* clear_eol */
52941480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, ip->curx);
53041480Smckusick 			ip->escape = 0;
53141480Smckusick 			return;
53241480Smckusick 
53341480Smckusick 		case 'J':			/* clear_eos */
53441480Smckusick 			ite_clrtoeos(ip, sp);
53541480Smckusick 			ip->escape = 0;
53641480Smckusick 			return;
53741480Smckusick 
53841480Smckusick 		case 'B':			/* cursor down 1 line */
53941480Smckusick 			if (++ip->cury == ip->rows) {
54041480Smckusick 				--ip->cury;
54157311Shibler 				ite_erasecursor(ip, sp);
54241480Smckusick 				(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
54341480Smckusick 				ite_clrtoeol(ip, sp, ip->cury, 0);
54441480Smckusick 			}
54541480Smckusick 			else
54657311Shibler 				ite_movecursor(ip, sp);
54741480Smckusick 			clr_attr(ip, ATTR_INV);
54841480Smckusick 			ip->escape = 0;
54941480Smckusick 			return;
55041480Smckusick 
55141480Smckusick 		case 'C':			/* cursor forward 1 char */
55241480Smckusick 			ip->escape = 0;
55341480Smckusick 			itecheckwrap(ip, sp);
55441480Smckusick 			return;
55541480Smckusick 
55641480Smckusick 		case 'A':			/* cursor up 1 line */
55741480Smckusick 			if (ip->cury > 0) {
55841480Smckusick 				ip->cury--;
55957311Shibler 				ite_movecursor(ip, sp);
56041480Smckusick 			}
56141480Smckusick 			ip->escape = 0;
56241480Smckusick 			clr_attr(ip, ATTR_INV);
56341480Smckusick 			return;
56441480Smckusick 
56541480Smckusick 		case 'P':			/* delete character */
56641480Smckusick 			ite_dchar(ip, sp);
56741480Smckusick 			ip->escape = 0;
56841480Smckusick 			return;
56941480Smckusick 
57041480Smckusick 		case 'M':			/* delete line */
57141480Smckusick 			ite_dline(ip, sp);
57241480Smckusick 			ip->escape = 0;
57341480Smckusick 			return;
57441480Smckusick 
57541480Smckusick 		case 'Q':			/* enter insert mode */
57641480Smckusick 			ip->imode = 1;
57741480Smckusick 			ip->escape = 0;
57841480Smckusick 			return;
57941480Smckusick 
58041480Smckusick 		case 'R':			/* exit insert mode */
58141480Smckusick 			ip->imode = 0;
58241480Smckusick 			ip->escape = 0;
58341480Smckusick 			return;
58441480Smckusick 
58541480Smckusick 		case 'L':			/* insert blank line */
58641480Smckusick 			ite_iline(ip, sp);
58741480Smckusick 			ip->escape = 0;
58841480Smckusick 			return;
58941480Smckusick 
59041480Smckusick 		case 'h':			/* home key */
59141480Smckusick 			ip->cury = ip->curx = 0;
59257311Shibler 			ite_movecursor(ip, sp);
59341480Smckusick 			ip->escape = 0;
59441480Smckusick 			return;
59541480Smckusick 
59641480Smckusick 		case 'D':			/* left arrow key */
59741480Smckusick 			if (ip->curx > 0) {
59841480Smckusick 				ip->curx--;
59957311Shibler 				ite_movecursor(ip, sp);
60041480Smckusick 			}
60141480Smckusick 			ip->escape = 0;
60241480Smckusick 			return;
60341480Smckusick 
60441480Smckusick 		case '1':			/* set tab in all rows */
60541480Smckusick 			goto ignore;
60641480Smckusick 
60741480Smckusick 		case ESC:
60841480Smckusick 			if ((ip->escape = c) == ESC)
60941480Smckusick 				break;
61041480Smckusick 			ip->fpd = 0;
61141480Smckusick 			goto doesc;
61241480Smckusick 
61341480Smckusick 		default:
61441480Smckusick ignore:
61541480Smckusick 			ip->escape = 0;
61641480Smckusick 			return;
61741480Smckusick 
61841480Smckusick 		}
61941480Smckusick 	}
62041480Smckusick 
62141480Smckusick 	switch (c &= 0x7F) {
62241480Smckusick 
62341480Smckusick 	case '\n':
62441480Smckusick 
62541480Smckusick 		if (++ip->cury == ip->rows) {
62641480Smckusick 			--ip->cury;
62757311Shibler 			ite_erasecursor(ip, sp);
62841480Smckusick 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
62941480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, 0);
63057311Shibler 		} else
63157311Shibler 			ite_movecursor(ip, sp);
63241480Smckusick 		clr_attr(ip, ATTR_INV);
63341480Smckusick 		break;
63441480Smckusick 
63541480Smckusick 	case '\r':
63641480Smckusick 		if (ip->curx) {
63741480Smckusick 			ip->curx = 0;
63857311Shibler 			ite_movecursor(ip, sp);
63941480Smckusick 		}
64041480Smckusick 		break;
64141480Smckusick 
64241480Smckusick 	case '\b':
64341480Smckusick 		if (--ip->curx < 0)
64441480Smckusick 			ip->curx = 0;
64541480Smckusick 		else
64657311Shibler 			ite_movecursor(ip, sp);
64741480Smckusick 		break;
64841480Smckusick 
64941480Smckusick 	case '\t':
65041480Smckusick 		if (ip->curx < TABEND(unit)) {
65141480Smckusick 			n = TABSIZE - (ip->curx & (TABSIZE - 1));
65241480Smckusick 			ip->curx += n;
65357311Shibler 			ite_movecursor(ip, sp);
65441480Smckusick 		} else
65541480Smckusick 			itecheckwrap(ip, sp);
65641480Smckusick 		break;
65741480Smckusick 
65841480Smckusick 	case CTRL('G'):
65941480Smckusick 		if (&ite_tty[unit] == kbd_tty)
66053923Shibler 			kbdbell(unit);
66141480Smckusick 		break;
66241480Smckusick 
66341480Smckusick 	case ESC:
66441480Smckusick 		ip->escape = ESC;
66541480Smckusick 		break;
66641480Smckusick 
66741480Smckusick 	default:
66841480Smckusick 		if (c < ' ' || c == DEL)
66941480Smckusick 			break;
67041480Smckusick 		if (ip->imode)
67141480Smckusick 			ite_ichar(ip, sp);
67241480Smckusick 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
67341480Smckusick 			attrset(ip, ATTR_INV);
67441480Smckusick 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
67557311Shibler 		} else
67641480Smckusick 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
67757311Shibler 		ite_drawcursor(ip, sp);
67841480Smckusick 		itecheckwrap(ip, sp);
67941480Smckusick 		break;
68041480Smckusick 	}
68141480Smckusick }
68241480Smckusick 
68341480Smckusick itecheckwrap(ip, sp)
68441480Smckusick      register struct ite_softc *ip;
68541480Smckusick      register struct itesw *sp;
68641480Smckusick {
68741480Smckusick 	if (++ip->curx == ip->cols) {
68841480Smckusick 		ip->curx = 0;
68941480Smckusick 		clr_attr(ip, ATTR_INV);
69041480Smckusick 		if (++ip->cury == ip->rows) {
69141480Smckusick 			--ip->cury;
69257311Shibler 			ite_erasecursor(ip, sp);
69341480Smckusick 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
69441480Smckusick 			ite_clrtoeol(ip, sp, ip->cury, 0);
69541480Smckusick 			return;
69641480Smckusick 		}
69741480Smckusick 	}
69857311Shibler 	ite_movecursor(ip, sp);
69941480Smckusick }
70041480Smckusick 
70141480Smckusick ite_dchar(ip, sp)
70241480Smckusick      register struct ite_softc *ip;
70341480Smckusick      register struct itesw *sp;
70441480Smckusick {
70557311Shibler 	if (ip->curx < ip->cols - 1) {
70657311Shibler 		ite_erasecursor(ip, sp);
70757311Shibler 		(*sp->ite_scroll)(ip, ip->cury, ip->curx + 1, 1, SCROLL_LEFT);
70857311Shibler 		attrmov(ip, ip->cury, ip->curx + 1, ip->cury, ip->curx,
70957311Shibler 			1, ip->cols - ip->curx - 1);
71057311Shibler 	}
71141480Smckusick 	attrclr(ip, ip->cury, ip->cols - 1, 1, 1);
71241480Smckusick 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - 1, ATTR_NOR);
71357311Shibler 	ite_drawcursor(ip, sp);
71441480Smckusick }
71541480Smckusick 
71641480Smckusick ite_ichar(ip, sp)
71741480Smckusick      register struct ite_softc *ip;
71841480Smckusick      register struct itesw *sp;
71941480Smckusick {
72057311Shibler 	if (ip->curx < ip->cols - 1) {
72157311Shibler 		ite_erasecursor(ip, sp);
72257311Shibler 		(*sp->ite_scroll)(ip, ip->cury, ip->curx, 1, SCROLL_RIGHT);
72357311Shibler 		attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + 1,
72457311Shibler 			1, ip->cols - ip->curx - 1);
72557311Shibler 	}
72641480Smckusick 	attrclr(ip, ip->cury, ip->curx, 1, 1);
72741480Smckusick 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->curx, ATTR_NOR);
72857311Shibler 	ite_drawcursor(ip, sp);
72941480Smckusick }
73041480Smckusick 
73141480Smckusick ite_dline(ip, sp)
73241480Smckusick      register struct ite_softc *ip;
73341480Smckusick      register struct itesw *sp;
73441480Smckusick {
73557311Shibler 	if (ip->cury < ip->rows - 1) {
73657311Shibler 		ite_erasecursor(ip, sp);
73757311Shibler 		(*sp->ite_scroll)(ip, ip->cury + 1, 0, 1, SCROLL_UP);
73857311Shibler 		attrmov(ip, ip->cury + 1, 0, ip->cury, 0,
73957311Shibler 			ip->rows - ip->cury - 1, ip->cols);
74057311Shibler 	}
74141480Smckusick 	ite_clrtoeol(ip, sp, ip->rows - 1, 0);
74241480Smckusick }
74341480Smckusick 
74441480Smckusick ite_iline(ip, sp)
74541480Smckusick      register struct ite_softc *ip;
74641480Smckusick      register struct itesw *sp;
74741480Smckusick {
74857311Shibler 	if (ip->cury < ip->rows - 1) {
74957311Shibler 		ite_erasecursor(ip, sp);
75057311Shibler 		(*sp->ite_scroll)(ip, ip->cury, 0, 1, SCROLL_DOWN);
75157311Shibler 		attrmov(ip, ip->cury, 0, ip->cury + 1, 0,
75257311Shibler 			ip->rows - ip->cury - 1, ip->cols);
75357311Shibler 	}
75441480Smckusick 	ite_clrtoeol(ip, sp, ip->cury, 0);
75541480Smckusick }
75641480Smckusick 
75741480Smckusick ite_clrtoeol(ip, sp, y, x)
75841480Smckusick      register struct ite_softc *ip;
75941480Smckusick      register struct itesw *sp;
76041480Smckusick      register int y, x;
76141480Smckusick {
76241480Smckusick 	(*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
76341480Smckusick 	attrclr(ip, y, x, 1, ip->cols - x);
76457311Shibler 	ite_drawcursor(ip, sp);
76541480Smckusick }
76641480Smckusick 
76741480Smckusick ite_clrtoeos(ip, sp)
76841480Smckusick      register struct ite_softc *ip;
76941480Smckusick      register struct itesw *sp;
77041480Smckusick {
77141480Smckusick 	(*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
77241480Smckusick 	attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
77357311Shibler 	ite_drawcursor(ip, sp);
77441480Smckusick }
77541480Smckusick 
77641480Smckusick /*
77741480Smckusick  * Console functions
77841480Smckusick  */
77956504Sbostic #include <hp/dev/cons.h>
78053923Shibler #ifdef hp300
78156504Sbostic #include <hp/dev/grfreg.h>
78253923Shibler #endif
78341480Smckusick 
78441480Smckusick #ifdef DEBUG
78541480Smckusick /*
78641480Smckusick  * Minimum ITE number at which to start looking for a console.
78741480Smckusick  * Setting to 0 will do normal search, 1 will skip first ITE device,
78841480Smckusick  * NITE will skip ITEs and use serial port.
78941480Smckusick  */
79041480Smckusick int	whichconsole = 0;
79141480Smckusick #endif
79241480Smckusick 
79341480Smckusick itecnprobe(cp)
79441480Smckusick 	struct consdev *cp;
79541480Smckusick {
79641480Smckusick 	register struct ite_softc *ip;
79753923Shibler 	int i, sw, maj, unit, pri;
79841480Smckusick 
79941480Smckusick 	/* locate the major number */
80041480Smckusick 	for (maj = 0; maj < nchrdev; maj++)
80141480Smckusick 		if (cdevsw[maj].d_open == iteopen)
80241480Smckusick 			break;
80341480Smckusick 
80441480Smckusick 	/* urk! */
80541480Smckusick 	grfconfig();
80641480Smckusick 
80741480Smckusick 	/* check all the individual displays and find the best */
80841480Smckusick 	unit = -1;
80941480Smckusick 	pri = CN_DEAD;
81041480Smckusick 	for (i = 0; i < NITE; i++) {
81141480Smckusick 		struct grf_softc *gp = &grf_softc[i];
81241480Smckusick 
81341480Smckusick 		ip = &ite_softc[i];
81441480Smckusick 		if ((gp->g_flags & GF_ALIVE) == 0)
81541480Smckusick 			continue;
81641480Smckusick 		ip->flags = (ITE_ALIVE|ITE_CONSOLE);
81741480Smckusick 
81853923Shibler 		/* locate the proper switch table. */
81953923Shibler 		for (sw = 0; sw < nitesw; sw++)
82053923Shibler 			if (itesw[sw].ite_hwid == gp->g_sw->gd_hwid)
82153923Shibler 				break;
82241480Smckusick 
82353923Shibler 		if (sw == nitesw)
82453923Shibler 			continue;
82541480Smckusick #ifdef DEBUG
82641480Smckusick 		if (i < whichconsole)
82741480Smckusick 			continue;
82841480Smckusick #endif
82953923Shibler 		ip->isw = &itesw[sw];
83053923Shibler 		ip->grf = gp;
83153923Shibler #ifdef hp300
83241480Smckusick 		if ((int)gp->g_display.gd_regaddr == GRFIADDR) {
83341480Smckusick 			pri = CN_INTERNAL;
83441480Smckusick 			unit = i;
83541480Smckusick 		} else if (unit < 0) {
83641480Smckusick 			pri = CN_NORMAL;
83741480Smckusick 			unit = i;
83841480Smckusick 		}
83953923Shibler #endif
84053923Shibler #ifdef hp800
84153923Shibler 		/* XXX use the first one for now */
84253923Shibler 		if (unit < 0) {
84353923Shibler 			pri = CN_INTERNAL;
84453923Shibler 			unit = i;
84553923Shibler 		}
84653923Shibler #endif
84741480Smckusick 	}
84841480Smckusick 
84941480Smckusick 	/* initialize required fields */
85041480Smckusick 	cp->cn_dev = makedev(maj, unit);
85141480Smckusick 	cp->cn_tp = &ite_tty[unit];
85241480Smckusick 	cp->cn_pri = pri;
85341480Smckusick }
85441480Smckusick 
85541480Smckusick itecninit(cp)
85641480Smckusick 	struct consdev *cp;
85741480Smckusick {
85841480Smckusick 	int unit = UNIT(cp->cn_dev);
85941480Smckusick 	struct ite_softc *ip = &ite_softc[unit];
86041480Smckusick 
86141480Smckusick 	ip->attrbuf = console_attributes;
86241480Smckusick 	iteinit(cp->cn_dev);
86341480Smckusick 	ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
86441480Smckusick 	kbd_tty = &ite_tty[unit];
86541480Smckusick }
86641480Smckusick 
86741480Smckusick /*ARGSUSED*/
86841480Smckusick itecngetc(dev)
86941480Smckusick 	dev_t dev;
87041480Smckusick {
87141480Smckusick 	register int c;
87241480Smckusick 	int stat;
87341480Smckusick 
87453923Shibler 	c = kbdgetc(0, &stat);	/* XXX always read from keyboard 0 for now */
87541480Smckusick 	switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
87641480Smckusick 	case KBD_SHIFT:
87741480Smckusick 		c = kbd_shiftmap[c & KBD_CHARMASK];
87841480Smckusick 		break;
87941480Smckusick 	case KBD_CTRL:
88041480Smckusick 		c = kbd_ctrlmap[c & KBD_CHARMASK];
88141480Smckusick 		break;
88241480Smckusick 	case KBD_KEY:
88341480Smckusick 		c = kbd_keymap[c & KBD_CHARMASK];
88441480Smckusick 		break;
88541480Smckusick 	default:
88641480Smckusick 		c = 0;
88741480Smckusick 		break;
88841480Smckusick 	}
88941480Smckusick 	return(c);
89041480Smckusick }
89141480Smckusick 
89241480Smckusick itecnputc(dev, c)
89341480Smckusick 	dev_t dev;
89441480Smckusick 	int c;
89541480Smckusick {
89641480Smckusick 	static int paniced = 0;
89741480Smckusick 	struct ite_softc *ip = &ite_softc[UNIT(dev)];
89841480Smckusick 
89941480Smckusick 	if (panicstr && !paniced &&
90041480Smckusick 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
90141480Smckusick 		(void) iteon(dev, 3);
90241480Smckusick 		paniced = 1;
90341480Smckusick 	}
90441480Smckusick 	iteputchar(c, dev);
90541480Smckusick }
90641480Smckusick #endif
907