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