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