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