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