xref: /netbsd-src/sys/arch/x68k/dev/ite.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: ite.c,v 1.71 2024/01/07 07:58:33 isaki Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * from: Utah $Hdr: ite.c 1.1 90/07/09$
37  *
38  *	@(#)ite.c	7.6 (Berkeley) 5/16/91
39  */
40 
41 /*
42  * ite - bitmaped terminal.
43  * Supports VT200, a few terminal features will be unavailable until
44  * the system actually probes the device (i.e. not after consinit())
45  */
46 
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: ite.c,v 1.71 2024/01/07 07:58:33 isaki Exp $");
49 
50 #include "ite.h"
51 #if NITE > 0
52 
53 #include "bell.h"
54 #include "kbd.h"
55 
56 #include "opt_ite.h"
57 
58 #include <sys/param.h>
59 #include <sys/conf.h>
60 #include <sys/proc.h>
61 #include <sys/ioctl.h>
62 #include <sys/tty.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
65 #include <sys/malloc.h>
66 #include <sys/kauth.h>
67 #include <sys/device_impl.h>	/* XXX autoconf abuse */
68 
69 #include <machine/cpu.h>
70 #include <machine/kbio.h>
71 #include <machine/bus.h>
72 #include <machine/autoconf.h>
73 #include <machine/grfioctl.h>
74 #include <machine/iteioctl.h>
75 
76 #include <arch/x68k/dev/grfvar.h>
77 #include <arch/x68k/dev/itevar.h>
78 #include <arch/x68k/dev/kbdmap.h>
79 #include <arch/x68k/dev/mfp.h>
80 
81 #include "ioconf.h"
82 
83 #if NBELL > 0
84 void opm_bell(void);
85 #endif
86 
87 #define SUBR_INIT(ip)		ip->isw->ite_init(ip)
88 #define SUBR_DEINIT(ip)		ip->isw->ite_deinit(ip)
89 #define SUBR_PUTC(ip,c,dy,dx,m)	ip->isw->ite_putc(ip,c,dy,dx,m)
90 #define SUBR_CURSOR(ip,flg)	ip->isw->ite_cursor(ip,flg)
91 #define SUBR_CLEAR(ip,sy,sx,h,w)	ip->isw->ite_clear(ip,sy,sx,h,w)
92 #define SUBR_SCROLL(ip,sy,sx,count,dir)	\
93     ip->isw->ite_scroll(ip,sy,sx,count,dir)
94 
95 struct consdev;
96 
97 static inline void itesendch(int);
98 static inline void alignment_display(struct ite_softc *);
99 static inline void snap_cury(struct ite_softc *);
100 static inline void ite_dnchar(struct ite_softc *, int);
101 static void ite_inchar(struct ite_softc *,	int);
102 static inline void ite_clrtoeol(struct ite_softc *);
103 static inline void ite_clrtobol(struct ite_softc *);
104 static inline void ite_clrline(struct ite_softc *);
105 static inline void ite_clrtoeos(struct ite_softc *);
106 static inline void ite_clrtobos(struct ite_softc *);
107 static inline void ite_clrscreen(struct ite_softc *);
108 static inline void ite_dnline(struct ite_softc *, int);
109 static inline void ite_inline(struct ite_softc *, int);
110 static inline void ite_index(struct ite_softc *);
111 static inline void ite_lf(struct ite_softc *);
112 static inline void ite_crlf(struct ite_softc *);
113 static inline void ite_cr(struct ite_softc *);
114 static inline void ite_rlf(struct ite_softc *);
115 static void iteprecheckwrap(struct ite_softc *);
116 static void itecheckwrap(struct ite_softc *);
117 static int ite_argnum(struct ite_softc *);
118 static int ite_zargnum(struct ite_softc *);
119 static void ite_sendstr(struct ite_softc *, const char *);
120 static inline int atoi(const char *);
121 static struct ite_softc *getitesp(dev_t);
122 
123 static struct itesw itesw[] = {
124 	{0,	tv_init,	tv_deinit,	0,
125 	 0,	0,		0}
126 };
127 
128 /*
129  * # of chars are output in a single itestart() call.
130  * If this is too big, user processes will be blocked out for
131  * long periods of time while we are emptying the queue in itestart().
132  * If it is too small, console output will be very ragged.
133  */
134 #define ITEBURST 64
135 
136 struct	tty *ite_tty[NITE];
137 
138 static struct ite_softc *kbd_ite = NULL;
139 static struct ite_softc con_itesoftc;
140 static struct device con_itedev;
141 
142 static struct tty *kbd_tty = NULL;
143 
144 static int start_repeat_timeo = 20;	/* /100: initial timeout till pressed
145 						 key repeats */
146 static int next_repeat_timeo  = 3;	/* /100: timeout when repeating for
147 						 next char */
148 
149 static u_char cons_tabs[MAX_TABS];
150 
151 static void itestart(struct tty *);
152 
153 static void iteputchar(int, struct ite_softc *);
154 static void ite_putstr(const u_char *, int, dev_t);
155 
156 static int itematch(device_t, cfdata_t, void *);
157 static void iteattach(device_t, device_t, void *);
158 
159 CFATTACH_DECL_NEW(ite, sizeof(struct ite_softc),
160     itematch, iteattach, NULL, NULL);
161 
162 static dev_type_open(iteopen);
163 static dev_type_close(iteclose);
164 static dev_type_read(iteread);
165 static dev_type_write(itewrite);
166 static dev_type_ioctl(iteioctl);
167 static dev_type_tty(itetty);
168 static dev_type_poll(itepoll);
169 
170 const struct cdevsw ite_cdevsw = {
171 	.d_open = iteopen,
172 	.d_close = iteclose,
173 	.d_read = iteread,
174 	.d_write = itewrite,
175 	.d_ioctl = iteioctl,
176 	.d_stop = nostop,
177 	.d_tty = itetty,
178 	.d_poll = itepoll,
179 	.d_mmap = nommap,
180 	.d_kqfilter = ttykqfilter,
181 	.d_discard = nodiscard,
182 	.d_flag = D_TTY
183 };
184 
185 static int
186 itematch(device_t parent, cfdata_t cf, void *aux)
187 {
188 	struct grf_softc *gp;
189 
190 	gp = aux;
191 	if (cf->cf_loc[GRFCF_GRFADDR] != gp->g_cfaddr)
192 		return 0;
193 
194 	return 1;
195 }
196 
197 /*
198  * iteinit() is the standard entry point for initialization of
199  * an ite device, it is also called from ite_cninit().
200  */
201 static void
202 iteattach(device_t parent, device_t self, void *aux)
203 {
204 	struct ite_softc *ip;
205 	struct grf_softc *gp;
206 
207 	gp = aux;
208 	ip = device_private(self);
209 	ip->device = self;
210 	if(con_itesoftc.grf != NULL
211 		/*&& con_itesoftc.grf->g_unit == gp->g_unit*/) {
212 		/*
213 		 * console reinit copy params over.
214 		 * and console always gets keyboard
215 		 */
216 		memcpy(&ip->grf, &con_itesoftc.grf,
217 		    (char *)&ip[1] - (char *)&ip->grf);
218 		con_itesoftc.grf = NULL;
219 		kbd_ite = ip;
220 	}
221 	ip->grf = gp;
222 	iteinit(device_unit(self)); /* XXX */
223 	aprint_normal(": rows %d cols %d", ip->rows, ip->cols);
224 	if (kbd_ite == NULL)
225 		kbd_ite = ip;
226 	aprint_normal("\n");
227 }
228 
229 static struct ite_softc *
230 getitesp(dev_t dev)
231 {
232 
233 	if (x68k_realconfig && con_itesoftc.grf == NULL)
234 		return device_lookup_private(&ite_cd, UNIT(dev));
235 
236 	if (con_itesoftc.grf == NULL)
237 		panic("no ite_softc for console");
238 	return &con_itesoftc;
239 }
240 
241 void
242 iteinit(dev_t dev)
243 {
244 	struct ite_softc *ip;
245 
246 	ip = getitesp(dev);
247 
248 	if (ip->flags & ITE_INITED)
249 		return;
250 	memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
251 
252 	ip->curx = 0;
253 	ip->cury = 0;
254 	ip->cursorx = 0;
255 	ip->cursory = 0;
256 
257 	ip->isw = &itesw[device_unit(ip->device)]; /* XXX */
258 	SUBR_INIT(ip);
259 	SUBR_CURSOR(ip, DRAW_CURSOR);
260 	if (ip->tabs == NULL)
261 		ip->tabs = malloc(MAX_TABS * sizeof(u_char),
262 		    M_DEVBUF, M_WAITOK);
263 	ite_reset(ip);
264 	ip->flags |= ITE_INITED;
265 }
266 
267 void
268 ite_config_console(void)
269 {
270 	struct grf_softc *gp = &congrf;
271 
272 	if (con_itesoftc.grf != NULL)
273 		return;
274 	con_itesoftc.grf = gp;
275 	con_itesoftc.tabs = cons_tabs;
276 	con_itesoftc.device = &con_itedev;
277 }
278 
279 /*
280  * Perform functions necessary to setup device as a terminal emulator.
281  */
282 int
283 iteon(dev_t dev, int flag)
284 {
285 	int unit = UNIT(dev);
286 	struct ite_softc *ip;
287 
288 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
289 	    (ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
290 		return ENXIO;
291 	/* force ite active, overriding graphics mode */
292 	if ((flag & 1) != 0) {
293 		ip->flags |= ITE_ACTIVE;
294 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
295 	}
296 	/* leave graphics mode */
297 	if ((flag & 2) != 0) {
298 		ip->flags &= ~ITE_INGRF;
299 		if ((ip->flags & ITE_ACTIVE) == 0)
300 			return 0;
301 	}
302 	ip->flags |= ITE_ACTIVE;
303 	if ((ip->flags & ITE_INGRF) != 0)
304 		return 0;
305 	iteinit(dev);
306 	if ((flag & 2) != 0)
307 		ite_reset(ip);
308 #if NKBD > 0
309 	mfp_send_usart(0x49);	/* XXX */
310 #endif
311 	return 0;
312 }
313 
314 /*
315  * "Shut down" device as terminal emulator.
316  * Note that we do not deinit the console device unless forced.
317  * Deinit'ing the console every time leads to a very active
318  * screen when processing /etc/rc.
319  */
320 void
321 iteoff(dev_t dev, int flag)
322 {
323 	int unit = UNIT(dev);
324 	struct ite_softc *ip;
325 
326 	/* XXX check whether when call from grf.c */
327 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
328 	    (ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
329 		return;
330 	if ((flag & 2) != 0)
331 		ip->flags |= ITE_INGRF;
332 
333 	if ((ip->flags & ITE_ACTIVE) == 0)
334 		return;
335 	if ((flag & 1) != 0 ||
336 	    (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
337 		SUBR_DEINIT(ip);
338 
339 	/*
340 	 * XXX When the system is rebooted with "reboot", init(8)
341 	 * kills the last process to have the console open.
342 	 * If we don't revent the ITE_ACTIVE bit from being
343 	 * cleared, we will never see messages printed during
344 	 * the process of rebooting.
345 	 */
346 	if ((flag & 2) == 0 && (ip->flags & ITE_ISCONS) == 0) {
347 		ip->flags &= ~ITE_ACTIVE;
348 #if NKBD > 0
349 		mfp_send_usart(0x48);	/* XXX */
350 #endif
351 	}
352 }
353 
354 /*
355  * standard entry points to the device.
356  */
357 
358 /* ARGSUSED */
359 static int
360 iteopen(dev_t dev, int mode, int devtype, struct lwp *l)
361 {
362 	int unit = UNIT(dev);
363 	struct tty *tp;
364 	struct ite_softc *ip;
365 	int error;
366 	int first = 0;
367 
368 	if (unit >= ite_cd.cd_ndevs || (ip = getitesp(dev)) == NULL)
369 		return ENXIO;
370 	if (ite_tty[unit] == NULL) {
371 		tp = ite_tty[unit] = tty_alloc();
372 		tty_attach(tp);
373 	} else
374 		tp = ite_tty[unit];
375 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
376 		return EBUSY;
377 	if ((ip->flags & ITE_ACTIVE) == 0) {
378 		error = iteon(dev, 0);
379 		if (error)
380 			return error;
381 		first = 1;
382 	}
383 	tp->t_oproc = itestart;
384 	tp->t_param = NULL;
385 	tp->t_dev = dev;
386 	if ((tp->t_state&TS_ISOPEN) == 0) {
387 		ttychars(tp);
388 		tp->t_iflag = TTYDEF_IFLAG;
389 		tp->t_oflag = TTYDEF_OFLAG;
390 		tp->t_cflag = TTYDEF_CFLAG;
391 		tp->t_lflag = TTYDEF_LFLAG;
392 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
393 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
394 		ttsetwater(tp);
395 	}
396 	error = (*tp->t_linesw->l_open)(dev, tp);
397 	if (error == 0) {
398 		tp->t_winsize.ws_row = ip->rows;
399 		tp->t_winsize.ws_col = ip->cols;
400 	} else if (first)
401 		iteoff(dev, 0);
402 	return error;
403 }
404 
405 /*ARGSUSED*/
406 static int
407 iteclose(dev_t dev, int flag, int mode, struct lwp *l)
408 {
409 	struct tty *tp = ite_tty[UNIT(dev)];
410 
411 	(*tp->t_linesw->l_close)(tp, flag);
412 	ttyclose(tp);
413 	iteoff(dev, 0);
414 #if 0
415 	tty_free(tp);
416 	ite_tty[UNIT(dev)] = NULL;
417 #endif
418 	return 0;
419 }
420 
421 static int
422 iteread(dev_t dev, struct uio *uio, int flag)
423 {
424 	struct tty *tp = ite_tty[UNIT(dev)];
425 
426 	return (*tp->t_linesw->l_read)(tp, uio, flag);
427 }
428 
429 static int
430 itewrite(dev_t dev, struct uio *uio, int flag)
431 {
432 	struct tty *tp = ite_tty[UNIT(dev)];
433 
434 	return (*tp->t_linesw->l_write)(tp, uio, flag);
435 }
436 
437 static int
438 itepoll(dev_t dev, int events, struct lwp *l)
439 {
440 	struct tty *tp = ite_tty[UNIT(dev)];
441 
442 	return (*tp->t_linesw->l_poll)(tp, events, l);
443 }
444 
445 static struct tty *
446 itetty(dev_t dev)
447 {
448 
449 	return ite_tty[UNIT(dev)];
450 }
451 
452 static int
453 iteioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
454 {
455 	struct iterepeat *irp;
456 	struct tty *tp = ite_tty[UNIT(dev)];
457 	int error;
458 
459 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, addr, flag, l);
460 	if (error != EPASSTHROUGH)
461 		return error;
462 
463 	error = ttioctl(tp, cmd, addr, flag, l);
464 	if (error != EPASSTHROUGH)
465 		return error;
466 
467 	switch (cmd) {
468 	case ITEIOCSKMAP:
469 		if (addr == NULL)
470 			return EFAULT;
471 		memcpy(&kbdmap, addr, sizeof(struct kbdmap));
472 		return 0;
473 
474 	case ITEIOCGKMAP:
475 		if (addr == NULL)
476 			return EFAULT;
477 		memcpy(addr, &kbdmap, sizeof(struct kbdmap));
478 		return 0;
479 
480 	case ITEIOCGREPT:
481 		irp = (struct iterepeat *)addr;
482 		irp->start = start_repeat_timeo;
483 		irp->next = next_repeat_timeo;
484 
485 	case ITEIOCSREPT:
486 		irp = (struct iterepeat *)addr;
487 		if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
488 			return(EINVAL);
489 		start_repeat_timeo = irp->start;
490 		next_repeat_timeo = irp->next;
491 #if x68k
492 	case ITELOADFONT:
493 		if (addr != NULL) {
494 			memcpy(kern_font, addr, 4096 /*sizeof(kernel_font)*/);
495 			ite_set_glyph();
496 			return 0;
497 		} else
498 			return EFAULT;
499 
500 	case ITETVCTRL:
501 		if (addr != NULL && *(uint8_t *)addr < 0x40) {
502 			return mfp_send_usart(*(uint8_t *)addr);
503 		} else {
504 			return EFAULT;
505 		}
506 #endif
507 	}
508 	return EPASSTHROUGH;
509 }
510 
511 static void
512 itestart(struct tty *tp)
513 {
514 	struct clist *rbp;
515 	uint8_t buf[ITEBURST];
516 	int s, len;
517 
518 	getitesp(tp->t_dev);
519 	/*
520 	 * (Potentially) lower priority.  We only need to protect ourselves
521 	 * from keyboard interrupts since that is all that can affect the
522 	 * state of our tty (kernel printf doesn't go through this routine).
523 	 */
524 	s = spltty();
525 	if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) != 0)
526 		goto out;
527 	tp->t_state |= TS_BUSY;
528 	rbp = &tp->t_outq;
529 	len = q_to_b(rbp, buf, ITEBURST);
530 	/*splx(s);*/
531 
532 	/* Here is a really good place to implement pre/jumpscroll() */
533 	ite_putstr(buf, len, tp->t_dev);
534 
535 	/*s = spltty();*/
536 	tp->t_state &= ~TS_BUSY;
537 	/* we have characters remaining. */
538 	if (ttypull(tp)) {
539 		tp->t_state |= TS_TIMEOUT;
540 		callout_schedule(&tp->t_rstrt_ch, 1);
541 	}
542  out:
543 	splx(s);
544 }
545 
546 /* XXX called after changes made in underlying grf layer. */
547 /* I want to nuke this */
548 void
549 ite_reinit(dev_t dev)
550 {
551 	struct ite_softc *ip;
552 	int unit = UNIT(dev);
553 
554 	/* XXX check whether when call from grf.c */
555 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
556 	    (ip = getitesp(dev)) == NULL)
557 		return;
558 
559 	ip->flags &= ~ITE_INITED;
560 	iteinit(dev);
561 }
562 
563 void
564 ite_reset(struct ite_softc *ip)
565 {
566 	int i;
567 
568 	ip->curx = 0;
569 	ip->cury = 0;
570 	ip->attribute = 0;
571 	ip->save_curx = 0;
572 	ip->save_cury = 0;
573 	ip->save_attribute = 0;
574 	ip->ap = ip->argbuf;
575 	ip->emul_level = EMUL_VT300_8;
576 	ip->eightbit_C1 = 0;
577 	ip->top_margin = 0;
578 	ip->bottom_margin = ip->rows - 1;
579 	ip->inside_margins = 0; /* origin mode == absolute */
580 	ip->linefeed_newline = 0;
581 	ip->auto_wrap = 1;
582 	ip->cursor_appmode = 0;
583 	ip->keypad_appmode = 0;
584 	ip->imode = 0;
585 	ip->key_repeat = 1;
586 	ip->G0 = CSET_ASCII;
587 	ip->G1 = CSET_JIS1983;
588 	ip->G2 = CSET_JISKANA;
589 	ip->G3 = CSET_JIS1990;
590 	ip->GL = &ip->G0;
591 	ip->GR = &ip->G1;
592 	ip->save_GL = 0;
593 	ip->save_char = 0;
594 	ip->fgcolor = 7;
595 	ip->bgcolor = 0;
596 	for (i = 0; i < ip->cols; i++)
597 		ip->tabs[i] = ((i & 7) == 0);
598 	/* XXX clear screen */
599 	SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
600 	attrclr(ip, 0, 0, ip->rows, ip->cols);
601 }
602 
603 /* Used in console at startup only */
604 int
605 ite_cnfilter(u_char c)
606 {
607 	static u_char mod = 0;
608 	struct key key;
609 	uint8_t code, up, mask;
610 	int s;
611 
612 	up = c & 0x80 ? 1 : 0;
613 	c &= 0x7f;
614 	code = 0;
615 
616 	s = spltty();
617 
618 	mask = 0;
619 	if (c >= KBD_LEFT_ALT &&
620 	    !(c >= 0x63 && c <= 0x6c)) {	/* 0x63: F1, 0x6c:F10 */
621 		switch (c) {
622 		case KBD_LEFT_SHIFT:
623 			mask = KBD_MOD_SHIFT;
624 			break;
625 
626 		case KBD_LEFT_ALT:
627 			mask = KBD_MOD_LALT;
628 			break;
629 
630 		case KBD_RIGHT_ALT:
631 			mask = KBD_MOD_RALT;
632 			break;
633 
634 		case KBD_LEFT_META:
635 			mask = KBD_MOD_LMETA;
636 			break;
637 
638 		case KBD_RIGHT_META:
639 			mask = KBD_MOD_RMETA;
640 			break;
641 
642 		case KBD_CAPS_LOCK:
643 			/*
644 			 * capslock already behaves `right', don't need to
645 			 * keep track of the state in here.
646 			 */
647 			mask = KBD_MOD_CAPS;
648 			break;
649 
650 		case KBD_CTRL:
651 			mask = KBD_MOD_CTRL;
652 			break;
653 
654 		case KBD_RECONNECT:
655 			/* ite got 0xff */
656 			if (up)
657 				kbd_setLED();
658 			break;
659 		}
660 		if (mask & KBD_MOD_CAPS) {
661 			if (!up) {
662 				mod ^= KBD_MOD_CAPS;
663 				kbdled ^= LED_CAPS_LOCK;
664 				kbd_setLED();
665 			}
666 		} else if (up)
667 			mod &= ~mask;
668 		else
669 			mod |= mask;
670 		splx(s);
671 		return -1;
672 	}
673 
674 	if (up) {
675 		splx(s);
676 		return -1;
677 	}
678 
679 	/* translate modifiers */
680 	if ((mod & KBD_MOD_SHIFT) != 0) {
681 		if ((mod & KBD_MOD_ALT) != 0)
682 			key = kbdmap.alt_shift_keys[c];
683 		else
684 			key = kbdmap.shift_keys[c];
685 	} else if ((mod & KBD_MOD_ALT) != 0)
686 		key = kbdmap.alt_keys[c];
687 	else {
688 		key = kbdmap.keys[c];
689 		/* if CAPS and key is CAPable (no pun intended) */
690 		if ((mod & KBD_MOD_CAPS) != 0 &&
691 		    (key.mode & KBD_MODE_CAPS) != 0)
692 			key = kbdmap.shift_keys[c];
693 	}
694 	code = key.code;
695 
696 	/* if string return */
697 	if ((key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) != 0) {
698 		splx(s);
699 		return -1;
700 	}
701 	/* handle dead keys */
702 	if ((key.mode & KBD_MODE_DEAD) != 0) {
703 		splx(s);
704 		return -1;
705 	}
706 	if ((mod & KBD_MOD_CTRL) != 0)
707 		code &= 0x1f;
708 	if ((mod & KBD_MOD_META) != 0)
709 		code |= 0x80;
710 
711 	/* do console mapping. */
712 	code = code == '\r' ? '\n' : code;
713 
714 	splx(s);
715 	return code;
716 }
717 
718 /* And now the old stuff. */
719 static inline void
720 itesendch(int ch)
721 {
722 
723 	(*kbd_tty->t_linesw->l_rint)(ch, kbd_tty);
724 }
725 
726 void
727 ite_filter(u_char c)
728 {
729 	static uint16_t mod = 0;
730 	uint8_t code, *str;
731 	uint16_t up, mask;
732 	struct key key;
733 	int s, i;
734 
735 	if (kbd_ite == NULL ||
736 	    (kbd_tty = ite_tty[device_unit(kbd_ite->device)]) == NULL)
737 		return;
738 
739 	/* have to make sure we're at spltty in here */
740 	s = spltty();
741 
742 	up = c & 0x80 ? 1 : 0;
743 	c &= 0x7f;
744 	code = 0;
745 
746 	mask = 0;
747 	if (c >= KBD_LEFT_ALT &&
748 	    !(c >= 0x63 && c <= 0x6c)) {	/* 0x63: F1, 0x6c:F10 */
749 		switch (c) {
750 		case KBD_LEFT_SHIFT:
751 			mask = KBD_MOD_SHIFT;
752 			break;
753 
754 		case KBD_LEFT_ALT:
755 			mask = KBD_MOD_LALT;
756 			break;
757 
758 		case KBD_RIGHT_ALT:
759 			mask = KBD_MOD_RALT;
760 			break;
761 
762 		case KBD_LEFT_META:
763 			mask = KBD_MOD_LMETA;
764 			break;
765 
766 		case KBD_RIGHT_META:
767 			mask = KBD_MOD_RMETA;
768 			break;
769 
770 		case KBD_CAPS_LOCK:
771 			/*
772 			 * capslock already behaves `right', don't need to keep
773 			 * track of the state in here.
774 			 */
775 			mask = KBD_MOD_CAPS;
776 			break;
777 
778 		case KBD_CTRL:
779 			mask = KBD_MOD_CTRL;
780 			break;
781 
782 		case KBD_OPT1:
783 			mask = KBD_MOD_OPT1;
784 			break;
785 
786 		case KBD_OPT2:
787 			mask = KBD_MOD_OPT2;
788 			break;
789 
790 		case KBD_RECONNECT:
791 			if (up) { /* ite got 0xff */
792 				kbd_setLED();
793 			}
794 			break;
795 		}
796 
797 		if ((mask & KBD_MOD_CAPS) != 0) {
798 			if (!up) {
799 				mod ^= KBD_MOD_CAPS;
800 				kbdled ^= LED_CAPS_LOCK;
801 				kbd_setLED();
802 			}
803 		} else if (up) {
804 			mod &= ~mask;
805 		} else
806 			mod |= mask;
807 
808 		/*
809 		 * return even if it wasn't a modifier key, the other
810 		 * codes up here are either special (like reset warning),
811 		 * or not yet defined
812 		 */
813 		splx(s);
814 		return;
815 	}
816 
817 	if (up) {
818 		splx(s);
819 		return;
820 	}
821 
822 	/*
823 	 * intercept LAlt-LMeta-F1 here to switch back to original ascii-keymap.
824 	 * this should probably be configurable..
825 	 */
826 	if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x63) {
827 		memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
828 		splx(s);
829 		return;
830 	}
831 
832 	/* translate modifiers */
833 	if ((mod & KBD_MOD_SHIFT) != 0) {
834 		if ((mod & KBD_MOD_ALT) != 0)
835 			key = kbdmap.alt_shift_keys[c];
836 		else
837 			key = kbdmap.shift_keys[c];
838 	} else if ((mod & KBD_MOD_ALT) != 0)
839 		key = kbdmap.alt_keys[c];
840 	else {
841 		key = kbdmap.keys[c];
842 		/* if CAPS and key is CAPable (no pun intended) */
843 		if ((mod & KBD_MOD_CAPS) != 0 &&
844 		    (key.mode & KBD_MODE_CAPS) != 0)
845 			key = kbdmap.shift_keys[c];
846 		else if ((mod & KBD_MOD_OPT2) != 0 &&
847 		         (key.mode & KBD_MODE_KPAD) != 0)
848 			key = kbdmap.shift_keys[c];
849 	}
850 	code = key.code;
851 
852 	/* handle dead keys */
853 	if ((key.mode & KBD_MODE_DEAD) != 0) {
854 		splx(s);
855 		return;
856 	}
857 	/* if not string, apply META and CTRL modifiers */
858 	if ((key.mode & KBD_MODE_STRING) == 0 &&
859 	    ((key.mode & KBD_MODE_KPAD) == 0 ||
860 	     (kbd_ite != NULL && kbd_ite->keypad_appmode == 0))) {
861 		if ((mod & KBD_MOD_CTRL) != 0 &&
862 		    (code == ' ' || (code >= '@' && code <= 'z')))
863 			code &= 0x1f;
864 		if ((mod & KBD_MOD_META) != 0)
865 			code |= 0x80;
866 	} else if ((key.mode & KBD_MODE_KPAD) != 0 &&
867 	       (kbd_ite != NULL && kbd_ite->keypad_appmode != 0)) {
868 		static const char * const in = "0123456789-+.\r()/*";
869 		static const char * const out = "pqrstuvwxymlnMPQRS";
870 		char *cp = strchr(in, code);
871 
872 		/*
873 		 * keypad-appmode sends SS3 followed by the above
874 		 * translated character
875 		 */
876 		(*kbd_tty->t_linesw->l_rint)(27, kbd_tty);
877 		(*kbd_tty->t_linesw->l_rint)('O', kbd_tty);
878 		(*kbd_tty->t_linesw->l_rint)(out[cp - in], kbd_tty);
879 		splx(s);
880 		return;
881 	} else {
882 		/* *NO* I don't like this.... */
883 		static u_char app_cursor[] = {
884 		  3, 27, 'O', 'A',
885 		  3, 27, 'O', 'B',
886 		  3, 27, 'O', 'C',
887 		  3, 27, 'O', 'D'
888 		};
889 
890 		str = kbdmap.strings + code;
891 		/*
892 		 * if this is a cursor key, AND it has the default
893 		 * keymap setting, AND we're in app-cursor mode, switch
894 		 * to the above table. This is *nasty* !
895 		 */
896 		if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode != 0 &&
897 		    memcmp(str, "\x03\x1b[", 3) == 0 &&
898 		    strchr("ABCD", str[3]) != 0)
899 			str = app_cursor + 4 * (str[3] - 'A');
900 
901 		/*
902 		 * using a length-byte instead of 0-termination allows
903 		 * to embed \0 into strings, although this is not used
904 		 * in the default keymap
905 		 */
906 		for (i = *str++; i; i--)
907 			(*kbd_tty->t_linesw->l_rint)(*str++, kbd_tty);
908 		splx(s);
909 		return;
910 	}
911 	(*kbd_tty->t_linesw->l_rint)(code, kbd_tty);
912 
913 	splx(s);
914 	return;
915 }
916 
917 /* helper functions, makes the code below more readable */
918 static inline void
919 ite_sendstr(struct ite_softc *ip, const char *str)
920 {
921 
922 	while (*str != 0)
923 		itesendch(*str++);
924 }
925 
926 static inline void
927 alignment_display(struct ite_softc *ip)
928 {
929 	int i, j;
930 
931 	for (j = 0; j < ip->rows; j++)
932 		for (i = 0; i < ip->cols; i++)
933 			SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
934 	attrclr(ip, 0, 0, ip->rows, ip->cols);
935 }
936 
937 static inline void
938 snap_cury(struct ite_softc *ip)
939 {
940 
941 	if (ip->inside_margins != 0) {
942 		if (ip->cury < ip->top_margin)
943 			ip->cury = ip->top_margin;
944 		if (ip->cury > ip->bottom_margin)
945 			ip->cury = ip->bottom_margin;
946 	}
947 }
948 
949 static inline void
950 ite_dnchar(struct ite_softc *ip, int n)
951 {
952 
953 	n = uimin(n, ip->cols - ip->curx);
954 	if (n < ip->cols - ip->curx) {
955 		SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
956 		attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
957 		    1, ip->cols - ip->curx - n);
958 		attrclr(ip, ip->cury, ip->cols - n, 1, n);
959 	}
960 	while (n-- > 0)
961 		SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
962 }
963 
964 static void
965 ite_inchar(struct ite_softc *ip, int n)
966 {
967 	int c = ip->save_char;
968 
969 	ip->save_char = 0;
970 	n = uimin(n, ip->cols - ip->curx);
971 	if (n < ip->cols - ip->curx) {
972 		SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
973 		attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
974 		    1, ip->cols - ip->curx - n);
975 		attrclr(ip, ip->cury, ip->curx, 1, n);
976 	}
977 	while (n-- != 0)
978 		SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
979 	ip->save_char = c;
980 }
981 
982 static inline void
983 ite_clrtoeol(struct ite_softc *ip)
984 {
985 	int y = ip->cury, x = ip->curx;
986 
987 	if (ip->cols - x > 0) {
988 		SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
989 		attrclr(ip, y, x, 1, ip->cols - x);
990 	}
991 }
992 
993 static inline void
994 ite_clrtobol(struct ite_softc *ip)
995 {
996 	int y = ip->cury, x = uimin(ip->curx + 1, ip->cols);
997 
998 	SUBR_CLEAR(ip, y, 0, 1, x);
999 	attrclr(ip, y, 0, 1, x);
1000 }
1001 
1002 static inline void
1003 ite_clrline(struct ite_softc *ip)
1004 {
1005 	int y = ip->cury;
1006 
1007 	SUBR_CLEAR(ip, y, 0, 1, ip->cols);
1008 	attrclr(ip, y, 0, 1, ip->cols);
1009 }
1010 
1011 static inline void
1012 ite_clrtoeos(struct ite_softc *ip)
1013 {
1014 
1015 	ite_clrtoeol(ip);
1016 	if (ip->cury < ip->rows - 1) {
1017 		SUBR_CLEAR(ip, ip->cury + 1, 0,
1018 		    ip->rows - 1 - ip->cury, ip->cols);
1019 		attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
1020 	}
1021 }
1022 
1023 static inline void
1024 ite_clrtobos(struct ite_softc *ip)
1025 {
1026 
1027 	ite_clrtobol(ip);
1028 	if (ip->cury > 0) {
1029 		SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
1030 		attrclr(ip, 0, 0, ip->cury, ip->cols);
1031 	}
1032 }
1033 
1034 static inline void
1035 ite_clrscreen(struct ite_softc *ip)
1036 {
1037 
1038 	SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
1039 	attrclr(ip, 0, 0, ip->rows, ip->cols);
1040 }
1041 
1042 static inline void
1043 ite_dnline(struct ite_softc *ip, int n)
1044 {
1045 
1046 	/*
1047 	 * interesting.. if the cursor is outside the scrolling
1048 	 * region, this command is simply ignored..
1049 	 */
1050 	if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1051 		return;
1052 
1053 	n = uimin(n, ip->bottom_margin + 1 - ip->cury);
1054 	if (n <= ip->bottom_margin - ip->cury) {
1055 		SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
1056 		attrmov(ip, ip->cury + n, 0, ip->cury, 0,
1057 		    ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1058 	}
1059 	SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1060 	attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1061 }
1062 
1063 static inline void
1064 ite_inline(struct ite_softc *ip, int n)
1065 {
1066 
1067 	/*
1068 	 * interesting.. if the cursor is outside the scrolling
1069 	 * region, this command is simply ignored..
1070 	 */
1071 	if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1072 		return;
1073 
1074 	if (n <= 0)
1075 		n = 1;
1076 	else
1077 		n = uimin(n, ip->bottom_margin + 1 - ip->cury);
1078 	if (n <= ip->bottom_margin  - ip->cury) {
1079 		SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
1080 		attrmov(ip, ip->cury, 0, ip->cury + n, 0,
1081 		    ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1082 	}
1083 	SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
1084 	attrclr(ip, ip->cury, 0, n, ip->cols);
1085 	ip->curx = 0;
1086 }
1087 
1088 static inline void
1089 ite_index(struct ite_softc *ip)
1090 {
1091 
1092 	++ip->cury;
1093 	if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
1094 		ip->cury--;
1095 		SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1096 		ite_clrline(ip);
1097 	}
1098 	/*clr_attr(ip, ATTR_INV);*/
1099 }
1100 
1101 static inline void
1102 ite_lf(struct ite_softc *ip)
1103 {
1104 
1105 	++ip->cury;
1106 	if (ip->cury > ip->bottom_margin) {
1107 		ip->cury--;
1108 		SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1109 		ite_clrline(ip);
1110 	}
1111 	/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
1112 	/*clr_attr(ip, ATTR_INV);*/
1113 	/* reset character set ... thanks for mohta. */
1114 	ip->G0 = CSET_ASCII;
1115 	ip->G1 = CSET_JIS1983;
1116 	ip->G2 = CSET_JISKANA;
1117 	ip->G3 = CSET_JIS1990;
1118 	ip->GL = &ip->G0;
1119 	ip->GR = &ip->G1;
1120 	ip->save_GL = 0;
1121 	ip->save_char = 0;
1122 }
1123 
1124 static inline void
1125 ite_crlf(struct ite_softc *ip)
1126 {
1127 
1128 	ip->curx = 0;
1129 	ite_lf(ip);
1130 }
1131 
1132 static inline void
1133 ite_cr(struct ite_softc *ip)
1134 {
1135 
1136 	if (ip->curx != 0) {
1137 		ip->curx = 0;
1138 	}
1139 }
1140 
1141 static inline void
1142 ite_rlf(struct ite_softc *ip)
1143 {
1144 
1145 	ip->cury--;
1146 	if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
1147 		ip->cury++;
1148 		SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
1149 		ite_clrline(ip);
1150 	}
1151 	clr_attr(ip, ATTR_INV);
1152 }
1153 
1154 static inline int
1155 atoi(const char *cp)
1156 {
1157 	int n;
1158 
1159 	for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1160 		n = n * 10 + *cp - '0';
1161 	return n;
1162 }
1163 
1164 static inline int
1165 ite_argnum(struct ite_softc *ip)
1166 {
1167 	char ch;
1168 	int n;
1169 
1170 	/* convert argument string into number */
1171 	if (ip->ap == ip->argbuf)
1172 		return 1;
1173 	ch = *ip->ap;
1174 	*ip->ap = 0;
1175 	n = atoi(ip->argbuf);
1176 	*ip->ap = ch;
1177 
1178 	return n;
1179 }
1180 
1181 static inline int
1182 ite_zargnum(struct ite_softc *ip)
1183 {
1184 	char ch;
1185 	int n;
1186 
1187 	/* convert argument string into number */
1188 	if (ip->ap == ip->argbuf)
1189 		return 0;
1190 	ch = *ip->ap;
1191 	*ip->ap = 0;	/* terminate string */
1192 	n = atoi(ip->argbuf);
1193 	*ip->ap = ch;
1194 
1195 	return n;	/* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1196 }
1197 
1198 static void
1199 ite_putstr(const u_char *s, int len, dev_t dev)
1200 {
1201 	struct ite_softc *ip;
1202 	int i;
1203 
1204 	ip = getitesp(dev);
1205 
1206 	/* XXX avoid problems */
1207 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1208 		return;
1209 
1210 	SUBR_CURSOR(ip, START_CURSOROPT);
1211 	for (i = 0; i < len; i++)
1212 		if (s[i] != 0)
1213 			iteputchar(s[i], ip);
1214 	SUBR_CURSOR(ip, END_CURSOROPT);
1215 }
1216 
1217 static void
1218 iteputchar(int c, struct ite_softc *ip)
1219 {
1220 	int n, x, y;
1221 	char *cp;
1222 
1223 	if (c >= 0x20 && ip->escape != 0) {
1224 		switch (ip->escape) {
1225 
1226 		case ESC:
1227 			switch (c) {
1228 			/*
1229 			 * first 7bit equivalents for the 8bit control
1230 			 * characters
1231 			 */
1232 
1233 			case 'D':
1234 				c = IND;
1235 				ip->escape = 0;
1236 				break;
1237 				/*
1238 				 * and fall into the next switch below
1239 				 * (same for all `break')
1240 				 */
1241 
1242 			case 'E':
1243 				/* next line */
1244 				c = NEL;
1245 				ip->escape = 0;
1246 				break;
1247 
1248 			case 'H':
1249 				/* set TAB at current col */
1250 				c = HTS;
1251 				ip->escape = 0;
1252 				break;
1253 
1254 			case 'M':
1255 				/* reverse index */
1256 				c = RI;
1257 				ip->escape = 0;
1258 				break;
1259 
1260 			case 'N':
1261 				/* single shift G2 */
1262 				c = SS2;
1263 				ip->escape = 0;
1264 				break;
1265 
1266 			case 'O':
1267 				/* single shift G3 */
1268 				c = SS3;
1269 				ip->escape = 0;
1270 				break;
1271 
1272 			case 'P':
1273 				/* DCS detected */
1274 				c = DCS;
1275 				ip->escape = 0;
1276 				break;
1277 
1278 			case '[':
1279 				c = CSI;
1280 				ip->escape = 0;
1281 				break;
1282 
1283 			case '\\':
1284 				/* String Terminator */
1285 				c = ST;
1286 				ip->escape = 0;
1287 				break;
1288 
1289 			case ']':
1290 				c = OSC;
1291 				ip->escape = 0;
1292 				break;
1293 
1294 			case '^':
1295 				c = PM;
1296 				ip->escape = 0;
1297 				break;
1298 
1299 			case '_':
1300 				c = APC;
1301 				ip->escape = 0;
1302 				break;
1303 
1304 			/* introduces 7/8bit control */
1305 			case ' ':
1306 				/* can be followed by either F or G */
1307 				ip->escape = ' ';
1308 				break;
1309 
1310 			/* a lot of character set selections, not yet used... */
1311 			/* 94-character sets: */
1312 			case '(':	/* G0 */
1313 			case ')':	/* G1 */
1314 				ip->escape = c;
1315 				return;
1316 
1317 			case '*':	/* G2 */
1318 			case '+':	/* G3 */
1319 			case 'B':	/* ASCII */
1320 			case 'A':	/* ISO latin 1 */
1321 			case '<':	/* user preferred suplemental */
1322 			case '0':	/* DEC special graphics */
1323 
1324 			/* 96-character sets: */
1325 			case '-':	/* G1 */
1326 			case '.':	/* G2 */
1327 			case '/':	/* G3 */
1328 
1329 			/* national character sets: */
1330 			case '4':	/* dutch */
1331 			case '5':
1332 			case 'C':	/* finnish */
1333 			case 'R':	/* french */
1334 			case 'Q':	/* french canadian */
1335 			case 'K':	/* german */
1336 			case 'Y':	/* italian */
1337 			case '6':	/* norwegian/danish */
1338 			/* note: %5 and %6 are not supported (two chars..) */
1339 
1340 				ip->escape = 0;
1341 				/* just ignore for now */
1342 				return;
1343 
1344 			/* 94-multibyte character sets designate */
1345 			case '$':
1346 				ip->escape = '$';
1347 				return;
1348 
1349 			/* locking shift modes */
1350 			case '`':
1351 				ip->GR = &ip->G1;
1352 				ip->escape = 0;
1353 				return;
1354 
1355 			case 'n':
1356 				ip->GL = &ip->G2;
1357 				ip->escape = 0;
1358 				return;
1359 
1360 			case '}':
1361 				ip->GR = &ip->G2;
1362 				ip->escape = 0;
1363 				return;
1364 
1365 			case 'o':
1366 				ip->GL = &ip->G3;
1367 				ip->escape = 0;
1368 				return;
1369 
1370 			case '|':
1371 				ip->GR = &ip->G3;
1372 				ip->escape = 0;
1373 				return;
1374 
1375 			case '~':
1376 				ip->GR = &ip->G1;
1377 				ip->escape = 0;
1378 				return;
1379 
1380 			/* font width/height control */
1381 			case '#':
1382 				ip->escape = '#';
1383 				return;
1384 
1385 			case 'c':
1386 				/* hard terminal reset .. */
1387 				ite_reset(ip);
1388 				SUBR_CURSOR(ip, MOVE_CURSOR);
1389 				ip->escape = 0;
1390 				return;
1391 
1392 			case '7':
1393 				/* save cursor */
1394 				ip->save_curx = ip->curx;
1395 				ip->save_cury = ip->cury;
1396 				ip->save_attribute = ip->attribute;
1397 				ip->sc_om = ip->inside_margins;
1398 				ip->sc_G0 = ip->G0;
1399 				ip->sc_G1 = ip->G1;
1400 				ip->sc_G2 = ip->G2;
1401 				ip->sc_G3 = ip->G3;
1402 				ip->sc_GL = ip->GL;
1403 				ip->sc_GR = ip->GR;
1404 				ip->escape = 0;
1405 				return;
1406 
1407 			case '8':
1408 				/* restore cursor */
1409 				ip->curx = ip->save_curx;
1410 				ip->cury = ip->save_cury;
1411 				ip->attribute = ip->save_attribute;
1412 				ip->inside_margins = ip->sc_om;
1413 				ip->G0 = ip->sc_G0;
1414 				ip->G1 = ip->sc_G1;
1415 				ip->G2 = ip->sc_G2;
1416 				ip->G3 = ip->sc_G3;
1417 				ip->GL = ip->sc_GL;
1418 				ip->GR = ip->sc_GR;
1419 				SUBR_CURSOR(ip, MOVE_CURSOR);
1420 				ip->escape = 0;
1421 				return;
1422 
1423 			case '=':
1424 				/* keypad application mode */
1425 				ip->keypad_appmode = 1;
1426 				ip->escape = 0;
1427 				return;
1428 
1429 			case '>':
1430 				/* keypad numeric mode */
1431 				ip->keypad_appmode = 0;
1432 				ip->escape = 0;
1433 				return;
1434 
1435 			case 'Z':	/* request ID */
1436 				if (ip->emul_level == EMUL_VT100) {
1437 					/* XXX not clean */
1438 					ite_sendstr(ip, "\033[61;0c");
1439 				} else {
1440 					/* XXX not clean */
1441 					ite_sendstr(ip, "\033[63;0c");
1442 				}
1443 				ip->escape = 0;
1444 				return;
1445 
1446 			/* default catch all for not recognized ESC sequences */
1447 			default:
1448 				ip->escape = 0;
1449 				return;
1450 			}
1451 			break;
1452 
1453 		case '(': /* designate G0 */
1454 			switch (c) {
1455 			case 'B': /* USASCII */
1456 				ip->G0 = CSET_ASCII;
1457 				ip->escape = 0;
1458 				return;
1459 			case 'I':
1460 				ip->G0 = CSET_JISKANA;
1461 				ip->escape = 0;
1462 				return;
1463 			case 'J':
1464 				ip->G0 = CSET_JISROMA;
1465 				ip->escape = 0;
1466 				return;
1467 			case '0': /* DEC special graphics */
1468 				ip->G0 = CSET_DECGRAPH;
1469 				ip->escape = 0;
1470 				return;
1471 			case 'A': /* British or ISO-Latin-1 */
1472 			case 'H': /* Swedish */
1473 			case 'K': /* German */
1474 			case 'R': /* French */
1475 			case 'Y': /* Italian */
1476 			case 'Z': /* Spanish */
1477 			default:
1478 				/* not supported */
1479 				ip->escape = 0;
1480 				return;
1481 			}
1482 
1483 		case ')': /* designate G1 */
1484 			ip->escape = 0;
1485 			return;
1486 
1487 		case '$': /* 94-multibyte character set */
1488 			switch (c) {
1489 			case '@':
1490 				ip->G0 = CSET_JIS1978;
1491 				ip->escape = 0;
1492 				return;
1493 			case 'B':
1494 				ip->G0 = CSET_JIS1983;
1495 				ip->escape = 0;
1496 				return;
1497 			case 'D':
1498 				ip->G0 = CSET_JIS1990;
1499 				ip->escape = 0;
1500 				return;
1501 			default:
1502 				/* not supported */
1503 				ip->escape = 0;
1504 				return;
1505 			}
1506 
1507 		case ' ':
1508 			switch (c) {
1509 			case 'F':
1510 				ip->eightbit_C1 = 0;
1511 				ip->escape = 0;
1512 				return;
1513 
1514 			case 'G':
1515 				ip->eightbit_C1 = 1;
1516 				ip->escape = 0;
1517 				return;
1518 
1519 			default:
1520 				/* not supported */
1521 				ip->escape = 0;
1522 				return;
1523 			}
1524 			break;
1525 
1526 		case '#':
1527 			switch (c) {
1528 			case '5':
1529 				/* single height, single width */
1530 				ip->escape = 0;
1531 				return;
1532 
1533 			case '6':
1534 				/* double width, single height */
1535 				ip->escape = 0;
1536 				return;
1537 
1538 			case '3':
1539 				/* top half */
1540 				ip->escape = 0;
1541 				return;
1542 
1543 			case '4':
1544 				/* bottom half */
1545 				ip->escape = 0;
1546 				return;
1547 
1548 			case '8':
1549 				/* screen alignment pattern... */
1550 				alignment_display(ip);
1551 				ip->escape = 0;
1552 				return;
1553 
1554 			default:
1555 				ip->escape = 0;
1556 				return;
1557 			}
1558 			break;
1559 
1560 		case CSI:
1561 			/* the biggie... */
1562 			switch (c) {
1563 			case '0':
1564 			case '1':
1565 			case '2':
1566 			case '3':
1567 			case '4':
1568 			case '5':
1569 			case '6':
1570 			case '7':
1571 			case '8':
1572 			case '9':
1573 			case ';':
1574 			case '\"':
1575 			case '$':
1576 			case '>':
1577 				if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1578 					*ip->ap++ = c;
1579 				return;
1580 
1581 			case 'p':
1582 				*ip->ap = 0;
1583 				if (!strncmp(ip->argbuf, "61\"", 3))
1584 					ip->emul_level = EMUL_VT100;
1585 				else if (!strncmp(ip->argbuf, "63;1\"", 5) ||
1586 					 !strncmp(ip->argbuf, "62;1\"", 5))
1587 					ip->emul_level = EMUL_VT300_7;
1588 				else
1589 					ip->emul_level = EMUL_VT300_8;
1590 				ip->escape = 0;
1591 				return;
1592 
1593 			case '?':
1594 				*ip->ap = 0;
1595 				ip->escape = '?';
1596 				ip->ap = ip->argbuf;
1597 				return;
1598 
1599 			case 'c':
1600 				/* device attributes */
1601 				*ip->ap = 0;
1602 				if (ip->argbuf[0] == '>') {
1603 					ite_sendstr(ip, "\033[>24;0;0;0c");
1604 				} else {
1605 					switch (ite_zargnum(ip)) {
1606 					case 0:
1607 						/*
1608 						 * primary DA request, send
1609 						 * primary DA response
1610 						 */
1611 						if (ip->emul_level ==
1612 						    EMUL_VT100)
1613 							ite_sendstr(ip,
1614 							    "\033[?1;1c");
1615 						else
1616 							ite_sendstr(ip,
1617 							    "\033[63;0c");
1618 						break;
1619 					}
1620 				}
1621 				ip->escape = 0;
1622 				return;
1623 
1624 			case 'n':
1625 				switch (ite_zargnum(ip)) {
1626 				case 5:
1627 					/* no malfunction */
1628 					ite_sendstr(ip, "\033[0n");
1629 					break;
1630 				case 6:
1631 					/* cursor position report */
1632 					snprintf(ip->argbuf, sizeof(ip->argbuf),
1633 					    "\033[%d;%dR",
1634 					     ip->cury + 1, ip->curx + 1);
1635 					ite_sendstr(ip, ip->argbuf);
1636 					break;
1637 				}
1638 				ip->escape = 0;
1639 				return;
1640 
1641 			case 'x':
1642 				switch (ite_zargnum(ip)) {
1643 				case 0:
1644 					/* Fake some terminal parameters.  */
1645 					ite_sendstr(ip,
1646 					    "\033[2;1;1;112;112;1;0x");
1647 					break;
1648 				case 1:
1649 					ite_sendstr(ip,
1650 					    "\033[3;1;1;112;112;1;0x");
1651 					break;
1652 				}
1653 				ip->escape = 0;
1654 				return;
1655 
1656 			case 'g':
1657 				/* clear tabs */
1658 				switch (ite_zargnum(ip)) {
1659 				case 0:
1660 					if (ip->curx < ip->cols)
1661 						ip->tabs[ip->curx] = 0;
1662 					break;
1663 				case 3:
1664 					for (n = 0; n < ip->cols; n++)
1665 						ip->tabs[n] = 0;
1666 					break;
1667 
1668 				default:
1669 					/* ignore */
1670 					break;
1671 				}
1672 				ip->escape = 0;
1673 				return;
1674 
1675 			case 'h': /* set mode */
1676 			case 'l': /* reset mode */
1677 				n = ite_zargnum(ip);
1678 				switch (n) {
1679 				case 4:
1680 					/* insert/replace mode */
1681 					ip->imode = (c == 'h');
1682 					break;
1683 				case 20:
1684 					ip->linefeed_newline = (c == 'h');
1685 					break;
1686 				}
1687 				ip->escape = 0;
1688 				return;
1689 
1690 			case 'M':
1691 				/* delete line */
1692 				ite_dnline(ip, ite_argnum(ip));
1693 				ip->escape = 0;
1694 				return;
1695 
1696 			case 'L':
1697 				/* insert line */
1698 				ite_inline(ip, ite_argnum(ip));
1699 				ip->escape = 0;
1700 				return;
1701 
1702 			case 'P':
1703 				/* delete char */
1704 				ite_dnchar(ip, ite_argnum(ip));
1705 				ip->escape = 0;
1706 				return;
1707 
1708 			case '@':
1709 				/* insert char(s) */
1710 				ite_inchar(ip, ite_argnum(ip));
1711 				ip->escape = 0;
1712 				return;
1713 
1714 			case '!':
1715 				/* soft terminal reset */
1716 				ip->escape = 0; /* XXX */
1717 				return;
1718 
1719 			case 'G':
1720 				/*
1721 				 * this one was *not* in my vt320 manual but
1722 				 * in a vt320 termcap entry.. who is right?
1723 				 * It's supposed to set the horizontal cursor
1724 				 * position.
1725 				 */
1726 				*ip->ap = 0;
1727 				x = atoi(ip->argbuf);
1728 				if (x != 0)
1729 					x--;
1730 				ip->curx = uimin(x, ip->cols - 1);
1731 				ip->escape = 0;
1732 				SUBR_CURSOR(ip, MOVE_CURSOR);
1733 				clr_attr(ip, ATTR_INV);
1734 				return;
1735 
1736 			case 'd':
1737 				/*
1738 				 * same thing here, this one's for setting
1739 				 * the absolute vertical cursor position.
1740 				 * Not documented...
1741 				 */
1742 				*ip->ap = 0;
1743 				y = atoi(ip->argbuf);
1744 				if (y)
1745 					y--;
1746 				if (ip->inside_margins)
1747 					y += ip->top_margin;
1748 				ip->cury = uimin(y, ip->rows - 1);
1749 				ip->escape = 0;
1750 				snap_cury(ip);
1751 				SUBR_CURSOR(ip, MOVE_CURSOR);
1752 				clr_attr(ip, ATTR_INV);
1753 				return;
1754 
1755 			case 'H':
1756 			case 'f':
1757 				*ip->ap = 0;
1758 				y = atoi(ip->argbuf);
1759 				x = 0;
1760 				cp = strchr(ip->argbuf, ';');
1761 				if (cp != NULL)
1762 					x = atoi(cp + 1);
1763 				if (x != 0)
1764 					x--;
1765 				if (y != 0)
1766 					y--;
1767 				if (ip->inside_margins != 0)
1768 					y += ip->top_margin;
1769 				ip->cury = uimin(y, ip->rows - 1);
1770 				ip->curx = uimin(x, ip->cols - 1);
1771 				ip->escape = 0;
1772 				snap_cury(ip);
1773 				SUBR_CURSOR(ip, MOVE_CURSOR);
1774 				/*clr_attr(ip, ATTR_INV);*/
1775 				return;
1776 
1777 			case 'A':
1778 				/* cursor up */
1779 				n = ite_argnum(ip);
1780 				n = ip->cury - (n ? n : 1);
1781 				if (n < 0)
1782 					n = 0;
1783 				if (ip->inside_margins)
1784 					n = uimax(ip->top_margin, n);
1785 				else if (n == ip->top_margin - 1)
1786 					/*
1787 					 * allow scrolling outside region,
1788 					 * but don't scroll out of active
1789 					 * region without explicit CUP
1790 					 */
1791 					n = ip->top_margin;
1792 				ip->cury = n;
1793 				ip->escape = 0;
1794 				SUBR_CURSOR(ip, MOVE_CURSOR);
1795 				clr_attr(ip, ATTR_INV);
1796 				return;
1797 
1798 			case 'B':
1799 				/* cursor down */
1800 				n = ite_argnum(ip);
1801 				n = ip->cury + (n ? n : 1);
1802 				n = uimin(ip->rows - 1, n);
1803 #if 0
1804 				if (ip->inside_margins)
1805 #endif
1806 					n = uimin(ip->bottom_margin, n);
1807 #if 0
1808 				else if (n == ip->bottom_margin + 1)
1809 					/*
1810 					 * allow scrolling outside region,
1811 					 * but don't scroll out of active
1812 					 * region without explicit CUP
1813 					 */
1814 					n = ip->bottom_margin;
1815 #endif
1816 				ip->cury = n;
1817 				ip->escape = 0;
1818 				SUBR_CURSOR(ip, MOVE_CURSOR);
1819 				clr_attr(ip, ATTR_INV);
1820 				return;
1821 
1822 			case 'C':
1823 				/* cursor forward */
1824 				n = ite_argnum(ip);
1825 				n = n ? n : 1;
1826 				ip->curx = uimin(ip->curx + n, ip->cols - 1);
1827 				ip->escape = 0;
1828 				SUBR_CURSOR(ip, MOVE_CURSOR);
1829 				clr_attr(ip, ATTR_INV);
1830 				return;
1831 
1832 			case 'D':
1833 				/* cursor backward */
1834 				n = ite_argnum(ip);
1835 				n = n ? n : 1;
1836 				n = ip->curx - n;
1837 				ip->curx = n >= 0 ? n : 0;
1838 				ip->escape = 0;
1839 				SUBR_CURSOR(ip, MOVE_CURSOR);
1840 				clr_attr(ip, ATTR_INV);
1841 				return;
1842 
1843 			case 'J':
1844 				/* erase screen */
1845 				*ip->ap = 0;
1846 				n = ite_zargnum(ip);
1847 				if (n == 0)
1848 					ite_clrtoeos(ip);
1849 				else if (n == 1)
1850 					ite_clrtobos(ip);
1851 				else if (n == 2)
1852 					ite_clrscreen(ip);
1853 				ip->escape = 0;
1854 				return;
1855 
1856 			case 'K':
1857 				/* erase line */
1858 				n = ite_zargnum(ip);
1859 				if (n == 0)
1860 					ite_clrtoeol(ip);
1861 				else if (n == 1)
1862 					ite_clrtobol(ip);
1863 				else if (n == 2)
1864 					ite_clrline(ip);
1865 				ip->escape = 0;
1866 				return;
1867 
1868 			case 'S':
1869 				/* scroll up */
1870 				n = ite_zargnum(ip);
1871 				if (n <= 0)
1872 					n = 1;
1873 				else if (n > ip->rows-1)
1874 					n = ip->rows-1;
1875 				SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
1876 				ip->escape = 0;
1877 				return;
1878 
1879 			case 'T':
1880 				/* scroll down */
1881 				n = ite_zargnum(ip);
1882 				if (n <= 0)
1883 					n = 1;
1884 				else if (n > ip->rows-1)
1885 					n = ip->rows-1;
1886 				SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
1887 				ip->escape = 0;
1888 				return;
1889 
1890 			case 'X':
1891 				/* erase character */
1892 				n = ite_argnum(ip) - 1;
1893 				n = uimin(n, ip->cols - 1 - ip->curx);
1894 				for (; n >= 0; n--) {
1895 					attrclr(ip, ip->cury, ip->curx + n,
1896 					    1, 1);
1897 					SUBR_PUTC(ip, ' ',
1898 					    ip->cury, ip->curx + n, ATTR_NOR);
1899 				}
1900 				ip->escape = 0;
1901 				return;
1902 
1903 			case '}': case '`':
1904 				/* status line control */
1905 				ip->escape = 0;
1906 				return;
1907 
1908 			case 'r':
1909 				/* set scrolling region */
1910 				ip->escape = 0;
1911 				*ip->ap = 0;
1912 				x = atoi(ip->argbuf);
1913 				x = x ? x : 1;
1914 				y = ip->rows;
1915 				cp = strchr(ip->argbuf, ';');
1916 				if (cp) {
1917 					y = atoi(cp + 1);
1918 					y = y ? y : ip->rows;
1919 				}
1920 				if (y <= x)
1921 					return;
1922 				x--;
1923 				y--;
1924 				ip->top_margin = uimin(x, ip->rows - 2);
1925 				ip->bottom_margin = uimin(y, ip->rows - 1);
1926 				if (ip->inside_margins) {
1927 					ip->cury = ip->top_margin;
1928 				} else
1929 					ip->cury = 0;
1930 				ip->curx = 0;
1931 				return;
1932 
1933 			case 'm':
1934 				/* big attribute setter/resetter */
1935 			{
1936 				char *c_p;
1937 
1938 				*ip->ap = 0;
1939 				/* kludge to make CSIm work (== CSI0m) */
1940 				if (ip->ap == ip->argbuf)
1941 					ip->ap++;
1942 				for (c_p = ip->argbuf; c_p < ip->ap; ) {
1943 					switch (*c_p) {
1944 					case 0:
1945 					case '0':
1946 						clr_attr(ip, ATTR_ALL);
1947 						ip->fgcolor = 7;
1948 						ip->bgcolor = 0;
1949 						c_p++;
1950 						break;
1951 
1952 					case '1':
1953 						set_attr(ip, ATTR_BOLD);
1954 						c_p++;
1955 						break;
1956 
1957 					case '2':
1958 						switch (c_p[1]) {
1959 						case '2':
1960 							clr_attr(ip, ATTR_BOLD);
1961 							c_p += 2;
1962 							break;
1963 
1964 						case '4':
1965 							clr_attr(ip, ATTR_UL);
1966 							c_p += 2;
1967 							break;
1968 
1969 						case '5':
1970 							clr_attr(ip,
1971 							    ATTR_BLINK);
1972 							c_p += 2;
1973 							break;
1974 
1975 						case '7':
1976 							clr_attr(ip, ATTR_INV);
1977 							c_p += 2;
1978 							break;
1979 
1980 						default:
1981 							c_p++;
1982 							break;
1983 						}
1984 						break;
1985 
1986 					case '3':
1987 						switch (c_p[1]) {
1988 						case '0':
1989 						case '1':
1990 						case '2':
1991 						case '3':
1992 						case '4':
1993 						case '5':
1994 						case '6':
1995 						case '7':
1996 							/* foreground colors */
1997 							ip->fgcolor =
1998 							    c_p[1] - '0';
1999 							c_p += 2;
2000 							break;
2001 						default:
2002 							c_p++;
2003 							break;
2004 						}
2005 						break;
2006 
2007 					case '4':
2008 						switch (c_p[1]) {
2009 						case '0':
2010 						case '1':
2011 						case '2':
2012 						case '3':
2013 						case '4':
2014 						case '5':
2015 						case '6':
2016 						case '7':
2017 							/* background colors */
2018 							ip->bgcolor =
2019 							    c_p[1] - '0';
2020 							c_p += 2;
2021 							break;
2022 						default:
2023 							set_attr(ip, ATTR_UL);
2024 							c_p++;
2025 							break;
2026 						}
2027 						break;
2028 
2029 					case '5':
2030 						set_attr(ip, ATTR_BLINK);
2031 						c_p++;
2032 						break;
2033 
2034 					case '7':
2035 						set_attr(ip, ATTR_INV);
2036 						c_p++;
2037 						break;
2038 
2039 					default:
2040 						c_p++;
2041 						break;
2042 					}
2043 				}
2044 
2045 			}
2046 				ip->escape = 0;
2047 				return;
2048 
2049 			case 'u':
2050 				/* DECRQTSR */
2051 				ite_sendstr(ip, "\033P\033\\");
2052 				ip->escape = 0;
2053 				return;
2054 
2055 			default:
2056 				ip->escape = 0;
2057 				return;
2058 			}
2059 			break;
2060 
2061 		case '?':	/* CSI ? */
2062 			switch (c) {
2063 			case '0':
2064 			case '1':
2065 			case '2':
2066 			case '3':
2067 			case '4':
2068 			case '5':
2069 			case '6':
2070 			case '7':
2071 			case '8':
2072 			case '9':
2073 			case ';':
2074 			case '\"':
2075 			case '$':
2076 				/*
2077 				 * Don't fill the last character; it's needed.
2078 				 */
2079 				/* XXX yeah, where ?? */
2080 				if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
2081 					*ip->ap++ = c;
2082 				return;
2083 
2084 			case 'n':
2085 				/* Terminal Reports */
2086 				*ip->ap = 0;
2087 				if (ip->ap == &ip->argbuf[2]) {
2088 					if (!strncmp(ip->argbuf, "15", 2))
2089 						/* printer status: no printer */
2090 						ite_sendstr(ip, "\033[13n");
2091 					else if (!strncmp(ip->argbuf, "25", 2))
2092 						/* udk status */
2093 						ite_sendstr(ip, "\033[20n");
2094 					else if (!strncmp(ip->argbuf, "26", 2))
2095 						/* keyboard dialect: US */
2096 						ite_sendstr(ip, "\033[27;1n");
2097 				}
2098 				ip->escape = 0;
2099 				return;
2100 
2101 			case 'h': /* set dec private modes */
2102 			case 'l': /* reset dec private modes */
2103 				n = ite_zargnum(ip);
2104 				switch (n) {
2105 				case 1:
2106 					/* CKM - cursor key mode */
2107 					ip->cursor_appmode = (c == 'h');
2108 					break;
2109 
2110 				case 3:
2111 					/* 132/80 columns (132 == 'h') */
2112 					break;
2113 
2114 				case 4: /* smooth scroll */
2115 					break;
2116 
2117 				case 5:
2118 					/*
2119 					 * light background (=='h') /
2120 					 * dark background (=='l')
2121 					 */
2122 					break;
2123 
2124 				case 6: /* origin mode */
2125 					ip->inside_margins = (c == 'h');
2126 #if 0
2127 					ip->curx = 0;
2128 					ip->cury = ip->inside_margins ?
2129 					    ip->top_margin : 0;
2130 					SUBR_CURSOR(ip, MOVE_CURSOR);
2131 #endif
2132 					break;
2133 
2134 				case 7: /* auto wraparound */
2135 					ip->auto_wrap = (c == 'h');
2136 					break;
2137 
2138 				case 8: /* keyboard repeat */
2139 					ip->key_repeat = (c == 'h');
2140 					break;
2141 
2142 				case 20: /* newline mode */
2143 					ip->linefeed_newline = (c == 'h');
2144 					break;
2145 
2146 				case 25: /* cursor on/off */
2147 					SUBR_CURSOR(ip, (c == 'h') ?
2148 					    DRAW_CURSOR : ERASE_CURSOR);
2149 					break;
2150 				}
2151 				ip->escape = 0;
2152 				return;
2153 
2154 			case 'K':
2155 				/* selective erase in line */
2156 			case 'J':
2157 				/* selective erase in display */
2158 
2159 			default:
2160 				ip->escape = 0;
2161 				return;
2162 			}
2163 			break;
2164 
2165 		default:
2166 			ip->escape = 0;
2167 			return;
2168 		}
2169 	}
2170 
2171 	switch (c) {
2172 	case 0x00:	/* NUL */
2173 	case 0x01:	/* SOH */
2174 	case 0x02:	/* STX */
2175 	case 0x03:	/* ETX */
2176 	case 0x04:	/* EOT */
2177 	case 0x05:	/* ENQ */
2178 	case 0x06:	/* ACK */
2179 		break;
2180 
2181 	case BEL:
2182 #if NBELL > 0
2183 		if (kbd_ite && ite_tty[device_unit(kbd_ite->device)])
2184 			opm_bell();
2185 #endif
2186 		break;
2187 
2188 	case BS:
2189 		if (--ip->curx < 0)
2190 			ip->curx = 0;
2191 		else
2192 			SUBR_CURSOR(ip, MOVE_CURSOR);
2193 		break;
2194 
2195 	case HT:
2196 		for (n = ip->curx + 1; n < ip->cols; n++) {
2197 			if (ip->tabs[n]) {
2198 				ip->curx = n;
2199 				SUBR_CURSOR(ip, MOVE_CURSOR);
2200 				break;
2201 			}
2202 		}
2203 		break;
2204 
2205 	case VT:	/* VT is treated like LF */
2206 	case FF:	/* so is FF */
2207 	case LF:
2208 		/*
2209 		 * cr->crlf distinction is done here, on output,
2210 		 * not on input!
2211 		 */
2212 		if (ip->linefeed_newline)
2213 			ite_crlf(ip);
2214 		else
2215 			ite_lf(ip);
2216 		break;
2217 
2218 	case CR:
2219 		ite_cr(ip);
2220 		break;
2221 
2222 	case SO:
2223 		ip->GL = &ip->G1;
2224 		break;
2225 
2226 	case SI:
2227 		ip->GL = &ip->G0;
2228 		break;
2229 
2230 	case 0x10:	/* DLE */
2231 	case 0x11:	/* DC1/XON */
2232 	case 0x12:	/* DC2 */
2233 	case 0x13:	/* DC3/XOFF */
2234 	case 0x14:	/* DC4 */
2235 	case 0x15:	/* NAK */
2236 	case 0x16:	/* SYN */
2237 	case 0x17:	/* ETB */
2238 		break;
2239 
2240 	case CAN:
2241 		ip->escape = 0;	/* cancel any escape sequence in progress */
2242 		break;
2243 
2244 	case 0x19:	/* EM */
2245 		break;
2246 
2247 	case SUB:
2248 		ip->escape = 0;	/* dito, but see below */
2249 		/* should also display a reverse question mark!! */
2250 		break;
2251 
2252 	case ESC:
2253 		ip->escape = ESC;
2254 		break;
2255 
2256 	case 0x1c:	/* FS */
2257 	case 0x1d:	/* GS */
2258 	case 0x1e:	/* RS */
2259 	case 0x1f:	/* US */
2260 		break;
2261 
2262 	/* now it gets weird.. 8bit control sequences.. */
2263 	case IND:	/* index: move cursor down, scroll */
2264 		ite_index(ip);
2265 		break;
2266 
2267 	case NEL:	/* next line. next line, first pos. */
2268 		ite_crlf(ip);
2269 		break;
2270 
2271 	case HTS:	/* set horizontal tab */
2272 		if (ip->curx < ip->cols)
2273 			ip->tabs[ip->curx] = 1;
2274 		break;
2275 
2276 	case RI:	/* reverse index */
2277 		ite_rlf(ip);
2278 		break;
2279 
2280 	case SS2:	/* go into G2 for one character */
2281 		ip->save_GL = ip->GR;	/* GL XXX EUC */
2282 		ip->GR = &ip->G2;	/* GL XXX */
2283 		break;
2284 
2285 	case SS3:	/* go into G3 for one character */
2286 		ip->save_GL = ip->GR;	/* GL XXX EUC */
2287 		ip->GR = &ip->G3;	/* GL XXX */
2288 		break;
2289 
2290 	case DCS:	/* device control string introducer */
2291 		ip->escape = DCS;
2292 		ip->ap = ip->argbuf;
2293 		break;
2294 
2295 	case CSI:	/* control sequence introducer */
2296 		ip->escape = CSI;
2297 		ip->ap = ip->argbuf;
2298 		break;
2299 
2300 	case ST:	/* string terminator */
2301 		/* ignore, if not used as terminator */
2302 		break;
2303 
2304 	case OSC:	/* introduces OS command. */
2305 		/* Ignore everything upto ST */
2306 		ip->escape = OSC;
2307 		break;
2308 
2309 	case PM:	/* privacy message */
2310 		/* ignore everything upto ST */
2311 		ip->escape = PM;
2312 		break;
2313 
2314 	case APC:	/* application program command */
2315 		/* ignore everything upto ST */
2316 		ip->escape = APC;
2317 		break;
2318 
2319 	case DEL:
2320 		break;
2321 
2322 	default:
2323 		if (ip->save_char == 0 &&
2324 		    (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI) != 0) {
2325 			ip->save_char = c;
2326 			break;
2327 		}
2328 		if (ip->imode != 0)
2329 			ite_inchar(ip, ip->save_char ? 2 : 1);
2330 		iteprecheckwrap(ip);
2331 #ifdef DO_WEIRD_ATTRIBUTES
2332 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2333 			attrset(ip, ATTR_INV);
2334 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2335 		}
2336 		else
2337 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2338 #else
2339 		SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2340 #endif
2341 		/*SUBR_CURSOR(ip, DRAW_CURSOR);*/
2342 		itecheckwrap(ip);
2343 		if (ip->save_char) {
2344 			itecheckwrap(ip);
2345 			ip->save_char = 0;
2346 		}
2347 		if (ip->save_GL) {
2348 			/*
2349 			 * reset single shift
2350 			 */
2351 			ip->GR = ip->save_GL;
2352 			ip->save_GL = 0;
2353 		}
2354 		break;
2355 	}
2356 }
2357 
2358 static void
2359 iteprecheckwrap(struct ite_softc *ip)
2360 {
2361 
2362 	if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
2363 		ip->curx = 0;
2364 		clr_attr(ip, ATTR_INV);
2365 		if (++ip->cury >= ip->bottom_margin + 1) {
2366 			ip->cury = ip->bottom_margin;
2367 			/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2368 			SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2369 			ite_clrtoeol(ip);
2370 		} /*else
2371 			SUBR_CURSOR(ip, MOVE_CURSOR);*/
2372 	}
2373 }
2374 
2375 static void
2376 itecheckwrap(struct ite_softc *ip)
2377 {
2378 
2379 #if 0
2380 	if (++ip->curx == ip->cols) {
2381 		if (ip->auto_wrap) {
2382 			ip->curx = 0;
2383 			clr_attr(ip, ATTR_INV);
2384 			if (++ip->cury >= ip->bottom_margin + 1) {
2385 				ip->cury = ip->bottom_margin;
2386 				SUBR_CURSOR(ip, MOVE_CURSOR);
2387 				SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1,
2388 				    SCROLL_UP);
2389 				ite_clrtoeol(ip);
2390 				return;
2391 			}
2392 		} else
2393 			/* stay there if no autowrap.. */
2394 			ip->curx--;
2395 	}
2396 #else
2397 	if (ip->curx < ip->cols) {
2398 		ip->curx++;
2399 		/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2400 	}
2401 #endif
2402 }
2403 
2404 /*
2405  * A convertion table from DEC special graphics characters to ASCII characters.
2406  * Mostly for box drawing on sysinst(8).
2407  */
2408 const uint8_t ite_decgraph2ascii[128] = {
2409 	/* same as ASCII from 0x00 to 0x5e */
2410 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
2411 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
2412 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
2413 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
2414 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
2415 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
2416 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
2417 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
2418 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
2419 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
2420 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
2421 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
2422 
2423 	/* special graphics characters from 0x5f to 0x7e */
2424 	' ',	/* 0x5f NBSP */
2425 	'*',	/* 0x60 diamond */
2426 	' ',	/* 0x61 medium shade */
2427 	' ',	/* 0x62 HT */
2428 	' ',	/* 0x63 FF */
2429 	' ',	/* 0x64 CR */
2430 	' ',	/* 0x65 LF */
2431 	' ',	/* 0x66 degree symbol */
2432 	' ',	/* 0x67 plus-minus sign */
2433 	' ',	/* 0x68 NL */
2434 	' ',	/* 0x69 VT */
2435 	'+',	/* 0x6a box drawings up left */
2436 	'+',	/* 0x6b box drawings down left */
2437 	'+',	/* 0x6c box drawings down right */
2438 	'+',	/* 0x6d box drawings up right */
2439 	'+',	/* 0x6e box drawings vertical horizontal */
2440 	'~',	/* 0x6f scan line 1 */
2441 	'-',	/* 0x70 scan line 3 */
2442 	'-',	/* 0x71 scan line 5 */
2443 	'-',	/* 0x72 scan line 7 */
2444 	'_',	/* 0x73 scan line 9 */
2445 	'+',	/* 0x74 box drawings vertical right */
2446 	'+',	/* 0x75 box drawings vertical left */
2447 	'+',	/* 0x76 box drawings horizontal up */
2448 	'+',	/* 0x77 box drawings horizontal down */
2449 	'|',	/* 0x78 box drawings vertical */
2450 	'<',	/* 0x79 less than or equal to */
2451 	'>',	/* 0x7a greater than or equal to */
2452 	' ',	/* 0x7b pi */
2453 	' ',	/* 0x7c not equal */
2454 	' ',	/* 0x7d pound sign */
2455 	'.',	/* 0x7e middle dot */
2456 	/* end of special graphics characters */
2457 	0x7f
2458 };
2459 
2460 #endif
2461 
2462 #if NITE > 0 && NKBD > 0
2463 
2464 /*
2465  * Console functions
2466  */
2467 #include <dev/cons.h>
2468 extern void kbdenable(int);
2469 extern int kbdcngetc(void);
2470 
2471 /*
2472  * Return a priority in consdev->cn_pri field highest wins.  This function
2473  * is called before any devices have been probed.
2474  */
2475 void
2476 itecnprobe(struct consdev *cd)
2477 {
2478 	int maj;
2479 
2480 	/* locate the major number */
2481 	maj = cdevsw_lookup_major(&ite_cdevsw);
2482 
2483 	/*
2484 	 * return priority of the best ite (already picked from attach)
2485 	 * or CN_DEAD.
2486 	 */
2487 	if (con_itesoftc.grf == NULL)
2488 		cd->cn_pri = CN_DEAD;
2489 	else {
2490 		con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2491 		/*
2492 		 * hardcode the minor number.
2493 		 * currently we support only one ITE, it is enough for now.
2494 		 */
2495 		con_itesoftc.isw = &itesw[0];
2496 		cd->cn_pri = CN_INTERNAL;
2497 		cd->cn_dev = makedev(maj, 0);
2498 	}
2499 }
2500 
2501 void
2502 itecninit(struct consdev *cd)
2503 {
2504 	struct ite_softc *ip;
2505 
2506 	ip = getitesp(cd->cn_dev);
2507 	iteinit(cd->cn_dev);	       /* init console unit */
2508 	ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2509 	kbdenable(0);
2510 	mfp_send_usart(0x49);
2511 }
2512 
2513 /*
2514  * itecnfinish() is called in ite_init() when the device is
2515  * being probed in the normal fashion, thus we can finish setting
2516  * up this ite now that the system is more functional.
2517  */
2518 void
2519 itecnfinish(struct ite_softc *ip)
2520 {
2521 	static int done;
2522 
2523 	if (done)
2524 		return;
2525 	done = 1;
2526 }
2527 
2528 /*ARGSUSED*/
2529 int
2530 itecngetc(dev_t dev)
2531 {
2532 	int c;
2533 
2534 	do {
2535 		c = kbdcngetc();
2536 		c = ite_cnfilter(c);
2537 	} while (c == -1);
2538 	return (c);
2539 }
2540 
2541 void
2542 itecnputc(dev_t dev, int c)
2543 {
2544 	static int paniced = 0;
2545 	struct ite_softc *ip = getitesp(dev);
2546 	char ch = c;
2547 #ifdef ITE_KERNEL_ATTR
2548 	short save_attribute;
2549 #endif
2550 
2551 	if (panicstr && !paniced &&
2552 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2553 		(void) iteon(dev, 3);
2554 		paniced = 1;
2555 	}
2556 #ifdef ITE_KERNEL_ATTR
2557 	save_attribute = ip->attribute;
2558 	ip->attribute = ITE_KERNEL_ATTR;
2559 #endif
2560 	ite_putstr(&ch, 1, dev);
2561 #ifdef ITE_KERNEL_ATTR
2562 	ip->attribute = save_attribute;
2563 #endif
2564 }
2565 #endif
2566