xref: /original-bsd/sys/hp/dev/ite.c (revision 3b43aa51)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: ite.c 1.28 92/12/20$
13  *
14  *	@(#)ite.c	7.15 (Berkeley) 12/27/92
15  */
16 
17 /*
18  * Bit-mapped display terminal emulator machine independent code.
19  * This is a very rudimentary.  Much more can be abstracted out of
20  * the hardware dependent routines.
21  */
22 #include "ite.h"
23 #if NITE > 0
24 
25 #include "grf.h"
26 
27 #undef NITE
28 #define NITE	NGRF
29 
30 #include <sys/param.h>
31 #include <sys/conf.h>
32 #include <sys/proc.h>
33 #include <sys/ioctl.h>
34 #include <sys/tty.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 
38 #include <hp/dev/grfioctl.h>
39 #include <hp/dev/grfvar.h>
40 #include <hp/dev/itevar.h>
41 #include <hp/dev/kbdmap.h>
42 
43 #define set_attr(ip, attr)	((ip)->attribute |= (attr))
44 #define clr_attr(ip, attr)	((ip)->attribute &= ~(attr))
45 
46 /*
47  * No need to raise SPL above the HIL (the only thing that can
48  * affect our state.
49  */
50 #include <hp/dev/hilreg.h>
51 #define splite()		splhil()
52 
53 /*
54  * # of chars are output in a single itestart() call.
55  * If this is too big, user processes will be blocked out for
56  * long periods of time while we are emptying the queue in itestart().
57  * If it is too small, console output will be very ragged.
58  */
59 int	iteburst = 64;
60 
61 int	nite = NITE;
62 struct  tty *kbd_tty = NULL;
63 struct	tty ite_tty[NITE];
64 struct  ite_softc ite_softc[NITE];
65 
66 void	itestart(), iterestart();
67 extern	struct tty *constty;
68 
69 /*
70  * Primary attribute buffer to be used by the first bitmapped console
71  * found. Secondary displays alloc the attribute buffer as needed.
72  * Size is based on a 68x128 display, which is currently our largest.
73  */
74 u_char  console_attributes[0x2200];
75 
76 #define ite_erasecursor(ip, sp)	{ \
77 	if ((ip)->flags & ITE_CURSORON) \
78 		(*(sp)->ite_cursor)((ip), ERASE_CURSOR); \
79 }
80 #define ite_drawcursor(ip, sp) { \
81 	if ((ip)->flags & ITE_CURSORON) \
82 		(*(sp)->ite_cursor)((ip), DRAW_CURSOR); \
83 }
84 #define ite_movecursor(ip, sp) { \
85 	if ((ip)->flags & ITE_CURSORON) \
86 		(*(sp)->ite_cursor)((ip), MOVE_CURSOR); \
87 }
88 
89 /*
90  * Perform functions necessary to setup device as a terminal emulator.
91  */
92 iteon(dev, flag)
93 	dev_t dev;
94 {
95 	int unit = UNIT(dev);
96 	struct tty *tp = &ite_tty[unit];
97 	struct ite_softc *ip = &ite_softc[unit];
98 
99 	if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0)
100 		return(ENXIO);
101 	/* force ite active, overriding graphics mode */
102 	if (flag & 1) {
103 		ip->flags |= ITE_ACTIVE;
104 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
105 	}
106 	/* leave graphics mode */
107 	if (flag & 2) {
108 		ip->flags &= ~ITE_INGRF;
109 		if ((ip->flags & ITE_ACTIVE) == 0)
110 			return(0);
111 	}
112 	ip->flags |= ITE_ACTIVE;
113 	if (ip->flags & ITE_INGRF)
114 		return(0);
115 	if (kbd_tty == NULL || kbd_tty == tp) {
116 		kbd_tty = tp;
117 		kbdenable(unit);
118 	}
119 	iteinit(dev);
120 	return(0);
121 }
122 
123 iteinit(dev)
124      dev_t dev;
125 {
126 	int unit = UNIT(dev);
127 	struct ite_softc *ip = &ite_softc[unit];
128 
129 	if (ip->flags & ITE_INITED)
130 		return;
131 
132 	ip->curx = 0;
133 	ip->cury = 0;
134 	ip->cursorx = 0;
135 	ip->cursory = 0;
136 
137 	(*ip->isw->ite_init)(ip);
138 	ip->flags |= ITE_CURSORON;
139 	ite_drawcursor(ip, ip->isw);
140 
141 	ip->attribute = 0;
142 	if (ip->attrbuf == NULL)
143 		ip->attrbuf = (u_char *)
144 			malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK);
145 	bzero(ip->attrbuf, (ip->rows * ip->cols));
146 
147 	ip->imode = 0;
148 	ip->flags |= ITE_INITED;
149 }
150 
151 /*
152  * "Shut down" device as terminal emulator.
153  * Note that we do not deinit the console device unless forced.
154  * Deinit'ing the console every time leads to a very active
155  * screen when processing /etc/rc.
156  */
157 iteoff(dev, flag)
158 	dev_t dev;
159 {
160 	register struct ite_softc *ip = &ite_softc[UNIT(dev)];
161 
162 	if (flag & 2)
163 		ip->flags |= ITE_INGRF;
164 	if ((ip->flags & ITE_ACTIVE) == 0)
165 		return;
166 	if ((flag & 1) ||
167 	    (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED) {
168 		(*ip->isw->ite_deinit)(ip);
169 		ip->flags &= ~ITE_CURSORON;
170 	}
171 	if ((flag & 2) == 0)
172 		ip->flags &= ~ITE_ACTIVE;
173 }
174 
175 /* ARGSUSED */
176 #ifdef __STDC__
177 iteopen(dev_t dev, int mode, int devtype, struct proc *p)
178 #else
179 iteopen(dev, mode, devtype, p)
180 	dev_t dev;
181 	int mode, devtype;
182 	struct proc *p;
183 #endif
184 {
185 	int unit = UNIT(dev);
186 	register struct tty *tp = &ite_tty[unit];
187 	register struct ite_softc *ip = &ite_softc[unit];
188 	register int error;
189 	int first = 0;
190 
191 	if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
192 	    && p->p_ucred->cr_uid != 0)
193 		return (EBUSY);
194 	if ((ip->flags & ITE_ACTIVE) == 0) {
195 		error = iteon(dev, 0);
196 		if (error)
197 			return (error);
198 		first = 1;
199 	}
200 	tp->t_oproc = itestart;
201 	tp->t_param = NULL;
202 	tp->t_dev = dev;
203 	if ((tp->t_state&TS_ISOPEN) == 0) {
204 		ttychars(tp);
205 		tp->t_iflag = TTYDEF_IFLAG;
206 		tp->t_oflag = TTYDEF_OFLAG;
207 		tp->t_cflag = CS8|CREAD;
208 		tp->t_lflag = TTYDEF_LFLAG;
209 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
210 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
211 		ttsetwater(tp);
212 	}
213 	error = (*linesw[tp->t_line].l_open)(dev, tp);
214 	if (error == 0) {
215 		tp->t_winsize.ws_row = ip->rows;
216 		tp->t_winsize.ws_col = ip->cols;
217 	} else if (first)
218 		iteoff(dev, 0);
219 	return (error);
220 }
221 
222 /*ARGSUSED*/
223 iteclose(dev, flag, mode, p)
224 	dev_t dev;
225 	int flag, mode;
226 	struct proc *p;
227 {
228 	register struct tty *tp = &ite_tty[UNIT(dev)];
229 
230 	(*linesw[tp->t_line].l_close)(tp, flag);
231 	ttyclose(tp);
232 	iteoff(dev, 0);
233 	return(0);
234 }
235 
236 iteread(dev, uio, flag)
237 	dev_t dev;
238 	struct uio *uio;
239 {
240 	register struct tty *tp = &ite_tty[UNIT(dev)];
241 
242 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
243 }
244 
245 itewrite(dev, uio, flag)
246 	dev_t dev;
247 	struct uio *uio;
248 {
249 	int unit = UNIT(dev);
250 	register struct tty *tp = &ite_tty[unit];
251 
252 	if ((ite_softc[unit].flags & ITE_ISCONS) && constty &&
253 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
254 		tp = constty;
255 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
256 }
257 
258 iteioctl(dev, cmd, addr, flag, p)
259 	dev_t dev;
260 	int cmd;
261 	caddr_t addr;
262 	int flag;
263 	struct proc *p;
264 {
265 	register struct tty *tp = &ite_tty[UNIT(dev)];
266 	int error;
267 
268 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
269 	if (error >= 0)
270 		return (error);
271 	error = ttioctl(tp, cmd, addr, flag);
272 	if (error >= 0)
273 		return (error);
274 	return (ENOTTY);
275 }
276 
277 void
278 iterestart(tp)
279 	register struct tty *tp;
280 {
281 	register int s = splite();
282 
283 	tp->t_state &= ~TS_TIMEOUT;
284 	itestart(tp);
285 	splx(s);
286 }
287 
288 void
289 itestart(tp)
290 	register struct tty *tp;
291 {
292 	register int cc, s;
293 	int hiwat = 0;
294 	struct ite_softc *ip;
295 
296 	/*
297 	 * (Potentially) lower priority.  We only need to protect ourselves
298 	 * from keyboard interrupts since that is all that can affect the
299 	 * state of our tty (kernel printf doesn't go through this routine).
300 	 */
301 	s = splite();
302 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
303 		splx(s);
304 		return;
305 	}
306 	tp->t_state |= TS_BUSY;
307 	cc = tp->t_outq.c_cc;
308 	if (cc <= tp->t_lowat) {
309 		if (tp->t_state & TS_ASLEEP) {
310 			tp->t_state &= ~TS_ASLEEP;
311 			wakeup((caddr_t)&tp->t_outq);
312 		}
313 		selwakeup(&tp->t_wsel);
314 	}
315 	/*
316 	 * Handle common (?) case
317 	 */
318 	if (cc == 1) {
319 		iteputchar(getc(&tp->t_outq), tp->t_dev);
320 	} else if (cc) {
321 		/*
322 		 * Limit the amount of output we do in one burst
323 		 * to prevent hogging the CPU.
324 		 */
325 		if (cc > iteburst) {
326 			hiwat++;
327 			cc = iteburst;
328 		}
329 		/*
330 		 * Turn off cursor while we output multiple characters.
331 		 * Saves a lot of expensive window move operations.
332 		 */
333 		ip = &ite_softc[UNIT(tp->t_dev)];
334 		ite_erasecursor(ip, ip->isw);
335 		ip->flags &= ~ITE_CURSORON;
336 		while (--cc >= 0)
337 			iteputchar(getc(&tp->t_outq), tp->t_dev);
338 		ip->flags |= ITE_CURSORON;
339 		ite_drawcursor(ip, ip->isw);
340 		if (hiwat) {
341 			tp->t_state |= TS_TIMEOUT;
342 			timeout(iterestart, tp, 1);
343 		}
344 	}
345 	tp->t_state &= ~TS_BUSY;
346 	splx(s);
347 }
348 
349 itefilter(stat, c)
350      register char stat, c;
351 {
352 	static int capsmode = 0;
353 	static int metamode = 0;
354   	register char code, *str;
355 
356 	if (kbd_tty == NULL)
357 		return;
358 
359 	switch (c & 0xFF) {
360 	case KBD_CAPSLOCK:
361 		capsmode = !capsmode;
362 		return;
363 
364 	case KBD_EXT_LEFT_DOWN:
365 	case KBD_EXT_RIGHT_DOWN:
366 		metamode = 1;
367 		return;
368 
369 	case KBD_EXT_LEFT_UP:
370 	case KBD_EXT_RIGHT_UP:
371 		metamode = 0;
372 		return;
373 	}
374 
375 	c &= KBD_CHARMASK;
376 	switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
377 
378 	case KBD_KEY:
379 	        if (!capsmode) {
380 			code = kbd_keymap[c];
381 			break;
382 		}
383 		/* fall into... */
384 
385 	case KBD_SHIFT:
386 		code = kbd_shiftmap[c];
387 		break;
388 
389 	case KBD_CTRL:
390 		code = kbd_ctrlmap[c];
391 		break;
392 
393 	case KBD_CTRLSHIFT:
394 		code = kbd_ctrlshiftmap[c];
395 		break;
396         }
397 
398 	if (code == NULL && (str = kbd_stringmap[c]) != NULL) {
399 		while (*str)
400 			(*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
401 	} else {
402 		if (metamode)
403 			code |= 0x80;
404 		(*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
405 	}
406 }
407 
408 iteputchar(c, dev)
409 	register int c;
410 	dev_t dev;
411 {
412 	int unit = UNIT(dev);
413 	register struct ite_softc *ip = &ite_softc[unit];
414 	register struct itesw *sp = ip->isw;
415 	register int n;
416 
417 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
418 	  	return;
419 
420 	if (ip->escape) {
421 doesc:
422 		switch (ip->escape) {
423 
424 		case '&':			/* Next can be a,d, or s */
425 			if (ip->fpd++) {
426 				ip->escape = c;
427 				ip->fpd = 0;
428 			}
429 			return;
430 
431 		case 'a':				/* cursor change */
432 			switch (c) {
433 
434 			case 'Y':			/* Only y coord. */
435 				ip->cury = min(ip->pos, ip->rows-1);
436 				ip->pos = 0;
437 				ip->escape = 0;
438 				ite_movecursor(ip, sp);
439 				clr_attr(ip, ATTR_INV);
440 				break;
441 
442 			case 'y':			/* y coord first */
443 				ip->cury = min(ip->pos, ip->rows-1);
444 				ip->pos = 0;
445 				ip->fpd = 0;
446 				break;
447 
448 			case 'C':			/* x coord */
449 				ip->curx = min(ip->pos, ip->cols-1);
450 				ip->pos = 0;
451 				ip->escape = 0;
452 				ite_movecursor(ip, sp);
453 				clr_attr(ip, ATTR_INV);
454 				break;
455 
456 			default:	     /* Possibly a 3 digit number. */
457 				if (c >= '0' && c <= '9' && ip->fpd < 3) {
458 					ip->pos = ip->pos * 10 + (c - '0');
459 					ip->fpd++;
460 				} else {
461 					ip->pos = 0;
462 					ip->escape = 0;
463 				}
464 				break;
465 			}
466 			return;
467 
468 		case 'd':				/* attribute change */
469 			switch (c) {
470 
471 			case 'B':
472 				set_attr(ip, ATTR_INV);
473 				break;
474 		        case 'D':
475 				/* XXX: we don't do anything for underline */
476 				set_attr(ip, ATTR_UL);
477 				break;
478 		        case '@':
479 				clr_attr(ip, ATTR_ALL);
480 				break;
481 			}
482 			ip->escape = 0;
483 			return;
484 
485 		case 's':				/* keypad control */
486 			switch (ip->fpd) {
487 
488 			case 0:
489 				ip->hold = c;
490 				ip->fpd++;
491 				return;
492 
493 			case 1:
494 				if (c == 'A') {
495 					switch (ip->hold) {
496 
497 					case '0':
498 						clr_attr(ip, ATTR_KPAD);
499 						break;
500 					case '1':
501 						set_attr(ip, ATTR_KPAD);
502 						break;
503 					}
504 				}
505 				ip->hold = 0;
506 			}
507 			ip->escape = 0;
508 			return;
509 
510 		case 'i':			/* back tab */
511 			if (ip->curx > TABSIZE) {
512 				n = ip->curx - (ip->curx & (TABSIZE - 1));
513 				ip->curx -= n;
514 			} else
515 				ip->curx = 0;
516 			ite_movecursor(ip, sp);
517 			ip->escape = 0;
518 			return;
519 
520 		case '3':			/* clear all tabs */
521 			goto ignore;
522 
523 		case 'K':			/* clear_eol */
524 			ite_clrtoeol(ip, sp, ip->cury, ip->curx);
525 			ip->escape = 0;
526 			return;
527 
528 		case 'J':			/* clear_eos */
529 			ite_clrtoeos(ip, sp);
530 			ip->escape = 0;
531 			return;
532 
533 		case 'B':			/* cursor down 1 line */
534 			if (++ip->cury == ip->rows) {
535 				--ip->cury;
536 				ite_erasecursor(ip, sp);
537 				(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
538 				ite_clrtoeol(ip, sp, ip->cury, 0);
539 			}
540 			else
541 				ite_movecursor(ip, sp);
542 			clr_attr(ip, ATTR_INV);
543 			ip->escape = 0;
544 			return;
545 
546 		case 'C':			/* cursor forward 1 char */
547 			ip->escape = 0;
548 			itecheckwrap(ip, sp);
549 			return;
550 
551 		case 'A':			/* cursor up 1 line */
552 			if (ip->cury > 0) {
553 				ip->cury--;
554 				ite_movecursor(ip, sp);
555 			}
556 			ip->escape = 0;
557 			clr_attr(ip, ATTR_INV);
558 			return;
559 
560 		case 'P':			/* delete character */
561 			ite_dchar(ip, sp);
562 			ip->escape = 0;
563 			return;
564 
565 		case 'M':			/* delete line */
566 			ite_dline(ip, sp);
567 			ip->escape = 0;
568 			return;
569 
570 		case 'Q':			/* enter insert mode */
571 			ip->imode = 1;
572 			ip->escape = 0;
573 			return;
574 
575 		case 'R':			/* exit insert mode */
576 			ip->imode = 0;
577 			ip->escape = 0;
578 			return;
579 
580 		case 'L':			/* insert blank line */
581 			ite_iline(ip, sp);
582 			ip->escape = 0;
583 			return;
584 
585 		case 'h':			/* home key */
586 			ip->cury = ip->curx = 0;
587 			ite_movecursor(ip, sp);
588 			ip->escape = 0;
589 			return;
590 
591 		case 'D':			/* left arrow key */
592 			if (ip->curx > 0) {
593 				ip->curx--;
594 				ite_movecursor(ip, sp);
595 			}
596 			ip->escape = 0;
597 			return;
598 
599 		case '1':			/* set tab in all rows */
600 			goto ignore;
601 
602 		case ESC:
603 			if ((ip->escape = c) == ESC)
604 				break;
605 			ip->fpd = 0;
606 			goto doesc;
607 
608 		default:
609 ignore:
610 			ip->escape = 0;
611 			return;
612 
613 		}
614 	}
615 
616 	switch (c &= 0x7F) {
617 
618 	case '\n':
619 
620 		if (++ip->cury == ip->rows) {
621 			--ip->cury;
622 			ite_erasecursor(ip, sp);
623 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
624 			ite_clrtoeol(ip, sp, ip->cury, 0);
625 		} else
626 			ite_movecursor(ip, sp);
627 		clr_attr(ip, ATTR_INV);
628 		break;
629 
630 	case '\r':
631 		if (ip->curx) {
632 			ip->curx = 0;
633 			ite_movecursor(ip, sp);
634 		}
635 		break;
636 
637 	case '\b':
638 		if (--ip->curx < 0)
639 			ip->curx = 0;
640 		else
641 			ite_movecursor(ip, sp);
642 		break;
643 
644 	case '\t':
645 		if (ip->curx < TABEND(unit)) {
646 			n = TABSIZE - (ip->curx & (TABSIZE - 1));
647 			ip->curx += n;
648 			ite_movecursor(ip, sp);
649 		} else
650 			itecheckwrap(ip, sp);
651 		break;
652 
653 	case CTRL('G'):
654 		if (&ite_tty[unit] == kbd_tty)
655 			kbdbell(unit);
656 		break;
657 
658 	case ESC:
659 		ip->escape = ESC;
660 		break;
661 
662 	default:
663 		if (c < ' ' || c == DEL)
664 			break;
665 		if (ip->imode)
666 			ite_ichar(ip, sp);
667 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
668 			attrset(ip, ATTR_INV);
669 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
670 		} else
671 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
672 		ite_drawcursor(ip, sp);
673 		itecheckwrap(ip, sp);
674 		break;
675 	}
676 }
677 
678 itecheckwrap(ip, sp)
679      register struct ite_softc *ip;
680      register struct itesw *sp;
681 {
682 	if (++ip->curx == ip->cols) {
683 		ip->curx = 0;
684 		clr_attr(ip, ATTR_INV);
685 		if (++ip->cury == ip->rows) {
686 			--ip->cury;
687 			ite_erasecursor(ip, sp);
688 			(*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
689 			ite_clrtoeol(ip, sp, ip->cury, 0);
690 			return;
691 		}
692 	}
693 	ite_movecursor(ip, sp);
694 }
695 
696 ite_dchar(ip, sp)
697      register struct ite_softc *ip;
698      register struct itesw *sp;
699 {
700 	if (ip->curx < ip->cols - 1) {
701 		ite_erasecursor(ip, sp);
702 		(*sp->ite_scroll)(ip, ip->cury, ip->curx + 1, 1, SCROLL_LEFT);
703 		attrmov(ip, ip->cury, ip->curx + 1, ip->cury, ip->curx,
704 			1, ip->cols - ip->curx - 1);
705 	}
706 	attrclr(ip, ip->cury, ip->cols - 1, 1, 1);
707 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - 1, ATTR_NOR);
708 	ite_drawcursor(ip, sp);
709 }
710 
711 ite_ichar(ip, sp)
712      register struct ite_softc *ip;
713      register struct itesw *sp;
714 {
715 	if (ip->curx < ip->cols - 1) {
716 		ite_erasecursor(ip, sp);
717 		(*sp->ite_scroll)(ip, ip->cury, ip->curx, 1, SCROLL_RIGHT);
718 		attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + 1,
719 			1, ip->cols - ip->curx - 1);
720 	}
721 	attrclr(ip, ip->cury, ip->curx, 1, 1);
722 	(*sp->ite_putc)(ip, ' ', ip->cury, ip->curx, ATTR_NOR);
723 	ite_drawcursor(ip, sp);
724 }
725 
726 ite_dline(ip, sp)
727      register struct ite_softc *ip;
728      register struct itesw *sp;
729 {
730 	if (ip->cury < ip->rows - 1) {
731 		ite_erasecursor(ip, sp);
732 		(*sp->ite_scroll)(ip, ip->cury + 1, 0, 1, SCROLL_UP);
733 		attrmov(ip, ip->cury + 1, 0, ip->cury, 0,
734 			ip->rows - ip->cury - 1, ip->cols);
735 	}
736 	ite_clrtoeol(ip, sp, ip->rows - 1, 0);
737 }
738 
739 ite_iline(ip, sp)
740      register struct ite_softc *ip;
741      register struct itesw *sp;
742 {
743 	if (ip->cury < ip->rows - 1) {
744 		ite_erasecursor(ip, sp);
745 		(*sp->ite_scroll)(ip, ip->cury, 0, 1, SCROLL_DOWN);
746 		attrmov(ip, ip->cury, 0, ip->cury + 1, 0,
747 			ip->rows - ip->cury - 1, ip->cols);
748 	}
749 	ite_clrtoeol(ip, sp, ip->cury, 0);
750 }
751 
752 ite_clrtoeol(ip, sp, y, x)
753      register struct ite_softc *ip;
754      register struct itesw *sp;
755      register int y, x;
756 {
757 	(*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
758 	attrclr(ip, y, x, 1, ip->cols - x);
759 	ite_drawcursor(ip, sp);
760 }
761 
762 ite_clrtoeos(ip, sp)
763      register struct ite_softc *ip;
764      register struct itesw *sp;
765 {
766 	(*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
767 	attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
768 	ite_drawcursor(ip, sp);
769 }
770 
771 /*
772  * Console functions
773  */
774 #include <hp/dev/cons.h>
775 #ifdef hp300
776 #include <hp/dev/grfreg.h>
777 #endif
778 
779 #ifdef DEBUG
780 /*
781  * Minimum ITE number at which to start looking for a console.
782  * Setting to 0 will do normal search, 1 will skip first ITE device,
783  * NITE will skip ITEs and use serial port.
784  */
785 int	whichconsole = 0;
786 #endif
787 
788 itecnprobe(cp)
789 	struct consdev *cp;
790 {
791 	register struct ite_softc *ip;
792 	int i, sw, maj, unit, pri;
793 
794 	/* locate the major number */
795 	for (maj = 0; maj < nchrdev; maj++)
796 		if (cdevsw[maj].d_open == iteopen)
797 			break;
798 
799 	/* urk! */
800 	grfconfig();
801 
802 	/* check all the individual displays and find the best */
803 	unit = -1;
804 	pri = CN_DEAD;
805 	for (i = 0; i < NITE; i++) {
806 		struct grf_softc *gp = &grf_softc[i];
807 
808 		ip = &ite_softc[i];
809 		if ((gp->g_flags & GF_ALIVE) == 0)
810 			continue;
811 		ip->flags = (ITE_ALIVE|ITE_CONSOLE);
812 
813 		/* locate the proper switch table. */
814 		for (sw = 0; sw < nitesw; sw++)
815 			if (itesw[sw].ite_hwid == gp->g_sw->gd_hwid)
816 				break;
817 
818 		if (sw == nitesw)
819 			continue;
820 #ifdef DEBUG
821 		if (i < whichconsole)
822 			continue;
823 #endif
824 		ip->isw = &itesw[sw];
825 		ip->grf = gp;
826 #ifdef hp300
827 		if ((int)gp->g_display.gd_regaddr == GRFIADDR) {
828 			pri = CN_INTERNAL;
829 			unit = i;
830 		} else if (unit < 0) {
831 			pri = CN_NORMAL;
832 			unit = i;
833 		}
834 #endif
835 #ifdef hp800
836 		/* XXX use the first one for now */
837 		if (unit < 0) {
838 			pri = CN_INTERNAL;
839 			unit = i;
840 		}
841 #endif
842 	}
843 
844 	/* initialize required fields */
845 	cp->cn_dev = makedev(maj, unit);
846 	cp->cn_tp = &ite_tty[unit];
847 	cp->cn_pri = pri;
848 }
849 
850 itecninit(cp)
851 	struct consdev *cp;
852 {
853 	int unit = UNIT(cp->cn_dev);
854 	struct ite_softc *ip = &ite_softc[unit];
855 
856 	ip->attrbuf = console_attributes;
857 	iteinit(cp->cn_dev);
858 	ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
859 	kbd_tty = &ite_tty[unit];
860 }
861 
862 /*ARGSUSED*/
863 itecngetc(dev)
864 	dev_t dev;
865 {
866 	register int c;
867 	int stat;
868 
869 	c = kbdgetc(0, &stat);	/* XXX always read from keyboard 0 for now */
870 	switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
871 	case KBD_SHIFT:
872 		c = kbd_shiftmap[c & KBD_CHARMASK];
873 		break;
874 	case KBD_CTRL:
875 		c = kbd_ctrlmap[c & KBD_CHARMASK];
876 		break;
877 	case KBD_KEY:
878 		c = kbd_keymap[c & KBD_CHARMASK];
879 		break;
880 	default:
881 		c = 0;
882 		break;
883 	}
884 	return(c);
885 }
886 
887 itecnputc(dev, c)
888 	dev_t dev;
889 	int c;
890 {
891 	static int paniced = 0;
892 	struct ite_softc *ip = &ite_softc[UNIT(dev)];
893 
894 	if (panicstr && !paniced &&
895 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
896 		(void) iteon(dev, 3);
897 		paniced = 1;
898 	}
899 	iteputchar(c, dev);
900 }
901 #endif
902