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