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