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