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