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