1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * Copyright (c) 1992-1998 S�ren Schmidt 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer as 11 * the first lines of this file unmodified. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_syscons.h" 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/consio.h> 38 39 #if __sparc64__ || __powerpc__ 40 #include <machine/sc_machdep.h> 41 #else 42 #include <machine/pc/display.h> 43 #endif 44 45 #include <dev/syscons/syscons.h> 46 #include <dev/syscons/sctermvar.h> 47 48 #ifndef SC_DUMB_TERMINAL 49 50 #define MAX_ESC_PAR 5 51 52 /* attribute flags */ 53 typedef struct { 54 u_short fg; /* foreground color */ 55 u_short bg; /* background color */ 56 } color_t; 57 58 typedef struct { 59 int flags; 60 #define SCTERM_BUSY (1 << 0) 61 int esc; 62 int num_param; 63 int last_param; 64 int param[MAX_ESC_PAR]; 65 int saved_xpos; 66 int saved_ypos; 67 int attr_mask; /* current logical attr mask */ 68 #define NORMAL_ATTR 0x00 69 #define BLINK_ATTR 0x01 70 #define BOLD_ATTR 0x02 71 #define UNDERLINE_ATTR 0x04 72 #define REVERSE_ATTR 0x08 73 #define FG_CHANGED 0x10 74 #define BG_CHANGED 0x20 75 int cur_attr; /* current hardware attr word */ 76 color_t cur_color; /* current hardware color */ 77 color_t std_color; /* normal hardware color */ 78 color_t rev_color; /* reverse hardware color */ 79 color_t dflt_std_color; /* default normal color */ 80 color_t dflt_rev_color; /* default reverse color */ 81 } term_stat; 82 83 static sc_term_init_t scterm_init; 84 static sc_term_term_t scterm_term; 85 static sc_term_puts_t scterm_puts; 86 static sc_term_ioctl_t scterm_ioctl; 87 static sc_term_reset_t scterm_reset; 88 static sc_term_default_attr_t scterm_default_attr; 89 static sc_term_clear_t scterm_clear; 90 static sc_term_notify_t scterm_notify; 91 static sc_term_input_t scterm_input; 92 93 static sc_term_sw_t sc_term_sc = { 94 { NULL, NULL }, 95 "sc", /* emulator name */ 96 "syscons terminal", /* description */ 97 "*", /* matching renderer, any :-) */ 98 sizeof(term_stat), /* softc size */ 99 0, 100 scterm_init, 101 scterm_term, 102 scterm_puts, 103 scterm_ioctl, 104 scterm_reset, 105 scterm_default_attr, 106 scterm_clear, 107 scterm_notify, 108 scterm_input, 109 }; 110 111 SCTERM_MODULE(sc, sc_term_sc); 112 113 static term_stat reserved_term_stat; 114 static void scterm_scan_esc(scr_stat *scp, term_stat *tcp, 115 u_char c); 116 static int mask2attr(term_stat *tcp); 117 118 static int 119 scterm_init(scr_stat *scp, void **softc, int code) 120 { 121 term_stat *tcp; 122 123 if (*softc == NULL) { 124 if (reserved_term_stat.flags & SCTERM_BUSY) 125 return EINVAL; 126 *softc = &reserved_term_stat; 127 } 128 tcp = *softc; 129 130 switch (code) { 131 case SC_TE_COLD_INIT: 132 bzero(tcp, sizeof(*tcp)); 133 tcp->flags = SCTERM_BUSY; 134 tcp->esc = 0; 135 tcp->saved_xpos = -1; 136 tcp->saved_ypos = -1; 137 tcp->attr_mask = NORMAL_ATTR; 138 /* XXX */ 139 tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f; 140 tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f; 141 tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f; 142 tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f; 143 tcp->std_color = tcp->dflt_std_color; 144 tcp->rev_color = tcp->dflt_rev_color; 145 tcp->cur_color = tcp->std_color; 146 tcp->cur_attr = mask2attr(tcp); 147 ++sc_term_sc.te_refcount; 148 break; 149 150 case SC_TE_WARM_INIT: 151 tcp->esc = 0; 152 tcp->saved_xpos = -1; 153 tcp->saved_ypos = -1; 154 #if 0 155 tcp->std_color = tcp->dflt_std_color; 156 tcp->rev_color = tcp->dflt_rev_color; 157 #endif 158 tcp->cur_color = tcp->std_color; 159 tcp->cur_attr = mask2attr(tcp); 160 break; 161 } 162 163 return 0; 164 } 165 166 static int 167 scterm_term(scr_stat *scp, void **softc) 168 { 169 if (*softc == &reserved_term_stat) { 170 *softc = NULL; 171 bzero(&reserved_term_stat, sizeof(reserved_term_stat)); 172 } 173 --sc_term_sc.te_refcount; 174 return 0; 175 } 176 177 static void 178 scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c) 179 { 180 static u_char ansi_col[16] = { 181 #ifdef __alpha__ 182 /* 183 * DEC is evil. They switch the red and blue attributes in 184 * the palette in the system console. As a simple work-around, 185 * re-map the ANSI colors appropriately. 186 */ 187 FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, 188 FG_RED, FG_MAGENTA, FG_BROWN, FG_LIGHTGREY, 189 FG_DARKGREY, FG_LIGHTBLUE, FG_LIGHTGREEN, FG_LIGHTCYAN, 190 FG_LIGHTRED, FG_LIGHTMAGENTA, FG_YELLOW, FG_WHITE 191 #else 192 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, 193 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, 194 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, 195 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE 196 #endif 197 }; 198 static int cattrs[] = { 199 0, /* block */ 200 CONS_BLINK_CURSOR, /* blinking block */ 201 CONS_CHAR_CURSOR, /* underline */ 202 CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */ 203 CONS_RESET_CURSOR, /* reset to default */ 204 CONS_HIDDEN_CURSOR, /* hide cursor */ 205 }; 206 static int tcattrs[] = { 207 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */ 208 CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */ 209 CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */ 210 }; 211 sc_softc_t *sc; 212 int v0, v1, v2; 213 int i, n; 214 215 i = n = 0; 216 sc = scp->sc; 217 if (tcp->esc == 1) { /* seen ESC */ 218 switch (c) { 219 220 case '7': /* Save cursor position */ 221 tcp->saved_xpos = scp->xpos; 222 tcp->saved_ypos = scp->ypos; 223 break; 224 225 case '8': /* Restore saved cursor position */ 226 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 227 sc_move_cursor(scp, tcp->saved_xpos, 228 tcp->saved_ypos); 229 break; 230 231 case '[': /* Start ESC [ sequence */ 232 tcp->esc = 2; 233 tcp->last_param = -1; 234 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 235 tcp->param[i] = 1; 236 tcp->num_param = 0; 237 return; 238 239 case 'M': /* Move cursor up 1 line, scroll if at top */ 240 sc_term_up_scroll(scp, 1, sc->scr_map[0x20], 241 tcp->cur_attr, 0, 0); 242 break; 243 #if notyet 244 case 'Q': 245 tcp->esc = 4; 246 return; 247 #endif 248 case 'c': /* reset */ 249 tcp->attr_mask = NORMAL_ATTR; 250 tcp->cur_color = tcp->std_color 251 = tcp->dflt_std_color; 252 tcp->rev_color = tcp->dflt_rev_color; 253 tcp->cur_attr = mask2attr(tcp); 254 sc_change_cursor_shape(scp, 255 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1); 256 sc_clear_screen(scp); 257 break; 258 259 case '(': /* iso-2022: designate 94 character set to G0 */ 260 tcp->esc = 5; 261 return; 262 } 263 } else if (tcp->esc == 2) { /* seen ESC [ */ 264 if (c >= '0' && c <= '9') { 265 if (tcp->num_param < MAX_ESC_PAR) { 266 if (tcp->last_param != tcp->num_param) { 267 tcp->last_param = tcp->num_param; 268 tcp->param[tcp->num_param] = 0; 269 } else { 270 tcp->param[tcp->num_param] *= 10; 271 } 272 tcp->param[tcp->num_param] += c - '0'; 273 return; 274 } 275 } 276 tcp->num_param = tcp->last_param + 1; 277 switch (c) { 278 279 case ';': 280 if (tcp->num_param < MAX_ESC_PAR) 281 return; 282 break; 283 284 case '=': 285 tcp->esc = 3; 286 tcp->last_param = -1; 287 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 288 tcp->param[i] = 1; 289 tcp->num_param = 0; 290 return; 291 292 case 'A': /* up n rows */ 293 sc_term_up(scp, tcp->param[0], 0); 294 break; 295 296 case 'B': /* down n rows */ 297 sc_term_down(scp, tcp->param[0], 0); 298 break; 299 300 case 'C': /* right n columns */ 301 sc_term_right(scp, tcp->param[0]); 302 break; 303 304 case 'D': /* left n columns */ 305 sc_term_left(scp, tcp->param[0]); 306 break; 307 308 case 'E': /* cursor to start of line n lines down */ 309 n = tcp->param[0]; 310 if (n < 1) 311 n = 1; 312 sc_move_cursor(scp, 0, scp->ypos + n); 313 break; 314 315 case 'F': /* cursor to start of line n lines up */ 316 n = tcp->param[0]; 317 if (n < 1) 318 n = 1; 319 sc_move_cursor(scp, 0, scp->ypos - n); 320 break; 321 322 case 'f': /* Cursor move */ 323 case 'H': 324 if (tcp->num_param == 0) 325 sc_move_cursor(scp, 0, 0); 326 else if (tcp->num_param == 2) 327 sc_move_cursor(scp, tcp->param[1] - 1, 328 tcp->param[0] - 1); 329 break; 330 331 case 'J': /* Clear all or part of display */ 332 if (tcp->num_param == 0) 333 n = 0; 334 else 335 n = tcp->param[0]; 336 sc_term_clr_eos(scp, n, sc->scr_map[0x20], 337 tcp->cur_attr); 338 break; 339 340 case 'K': /* Clear all or part of line */ 341 if (tcp->num_param == 0) 342 n = 0; 343 else 344 n = tcp->param[0]; 345 sc_term_clr_eol(scp, n, sc->scr_map[0x20], 346 tcp->cur_attr); 347 break; 348 349 case 'L': /* Insert n lines */ 350 sc_term_ins_line(scp, scp->ypos, tcp->param[0], 351 sc->scr_map[0x20], tcp->cur_attr, 0); 352 break; 353 354 case 'M': /* Delete n lines */ 355 sc_term_del_line(scp, scp->ypos, tcp->param[0], 356 sc->scr_map[0x20], tcp->cur_attr, 0); 357 break; 358 359 case 'P': /* Delete n chars */ 360 sc_term_del_char(scp, tcp->param[0], 361 sc->scr_map[0x20], tcp->cur_attr); 362 break; 363 364 case '@': /* Insert n chars */ 365 sc_term_ins_char(scp, tcp->param[0], 366 sc->scr_map[0x20], tcp->cur_attr); 367 break; 368 369 case 'S': /* scroll up n lines */ 370 sc_term_del_line(scp, 0, tcp->param[0], 371 sc->scr_map[0x20], tcp->cur_attr, 0); 372 break; 373 374 case 'T': /* scroll down n lines */ 375 sc_term_ins_line(scp, 0, tcp->param[0], 376 sc->scr_map[0x20], tcp->cur_attr, 0); 377 break; 378 379 case 'X': /* erase n characters in line */ 380 n = tcp->param[0]; 381 if (n < 1) 382 n = 1; 383 if (n > scp->xsize - scp->xpos) 384 n = scp->xsize - scp->xpos; 385 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, 386 sc->scr_map[0x20], tcp->cur_attr); 387 mark_for_update(scp, scp->cursor_pos); 388 mark_for_update(scp, scp->cursor_pos + n - 1); 389 break; 390 391 case 'Z': /* move n tabs backwards */ 392 sc_term_backtab(scp, tcp->param[0]); 393 break; 394 395 case '`': /* move cursor to column n */ 396 sc_term_col(scp, tcp->param[0]); 397 break; 398 399 case 'a': /* move cursor n columns to the right */ 400 sc_term_right(scp, tcp->param[0]); 401 break; 402 403 case 'd': /* move cursor to row n */ 404 sc_term_row(scp, tcp->param[0]); 405 break; 406 407 case 'e': /* move cursor n rows down */ 408 sc_term_down(scp, tcp->param[0], 0); 409 break; 410 411 case 'm': /* change attribute */ 412 if (tcp->num_param == 0) { 413 tcp->attr_mask = NORMAL_ATTR; 414 tcp->cur_color = tcp->std_color; 415 tcp->cur_attr = mask2attr(tcp); 416 break; 417 } 418 for (i = 0; i < tcp->num_param; i++) { 419 switch (n = tcp->param[i]) { 420 case 0: /* back to normal */ 421 tcp->attr_mask = NORMAL_ATTR; 422 tcp->cur_color = tcp->std_color; 423 tcp->cur_attr = mask2attr(tcp); 424 break; 425 case 1: /* bold */ 426 tcp->attr_mask |= BOLD_ATTR; 427 tcp->cur_attr = mask2attr(tcp); 428 break; 429 case 4: /* underline */ 430 tcp->attr_mask |= UNDERLINE_ATTR; 431 tcp->cur_attr = mask2attr(tcp); 432 break; 433 case 5: /* blink */ 434 tcp->attr_mask |= BLINK_ATTR; 435 tcp->cur_attr = mask2attr(tcp); 436 break; 437 case 7: /* reverse */ 438 tcp->attr_mask |= REVERSE_ATTR; 439 tcp->cur_attr = mask2attr(tcp); 440 break; 441 case 22: /* remove bold (or dim) */ 442 tcp->attr_mask &= ~BOLD_ATTR; 443 tcp->cur_attr = mask2attr(tcp); 444 break; 445 case 24: /* remove underline */ 446 tcp->attr_mask &= ~UNDERLINE_ATTR; 447 tcp->cur_attr = mask2attr(tcp); 448 break; 449 case 25: /* remove blink */ 450 tcp->attr_mask &= ~BLINK_ATTR; 451 tcp->cur_attr = mask2attr(tcp); 452 break; 453 case 27: /* remove reverse */ 454 tcp->attr_mask &= ~REVERSE_ATTR; 455 tcp->cur_attr = mask2attr(tcp); 456 break; 457 case 30: case 31: /* set ansi fg color */ 458 case 32: case 33: case 34: 459 case 35: case 36: case 37: 460 tcp->attr_mask |= FG_CHANGED; 461 tcp->cur_color.fg = ansi_col[n - 30]; 462 tcp->cur_attr = mask2attr(tcp); 463 break; 464 case 39: /* restore fg color back to normal */ 465 tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR); 466 tcp->cur_color.fg = tcp->std_color.fg; 467 tcp->cur_attr = mask2attr(tcp); 468 break; 469 case 40: case 41: /* set ansi bg color */ 470 case 42: case 43: case 44: 471 case 45: case 46: case 47: 472 tcp->attr_mask |= BG_CHANGED; 473 tcp->cur_color.bg = ansi_col[n - 40]; 474 tcp->cur_attr = mask2attr(tcp); 475 break; 476 case 49: /* restore bg color back to normal */ 477 tcp->attr_mask &= ~BG_CHANGED; 478 tcp->cur_color.bg = tcp->std_color.bg; 479 tcp->cur_attr = mask2attr(tcp); 480 break; 481 } 482 } 483 break; 484 485 case 's': /* Save cursor position */ 486 tcp->saved_xpos = scp->xpos; 487 tcp->saved_ypos = scp->ypos; 488 break; 489 490 case 'u': /* Restore saved cursor position */ 491 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 492 sc_move_cursor(scp, tcp->saved_xpos, 493 tcp->saved_ypos); 494 break; 495 496 case 'x': 497 if (tcp->num_param == 0) 498 n = 0; 499 else 500 n = tcp->param[0]; 501 switch (n) { 502 case 0: /* reset colors and attributes back to normal */ 503 tcp->attr_mask = NORMAL_ATTR; 504 tcp->cur_color = tcp->std_color 505 = tcp->dflt_std_color; 506 tcp->rev_color = tcp->dflt_rev_color; 507 tcp->cur_attr = mask2attr(tcp); 508 break; 509 case 1: /* set ansi background */ 510 tcp->attr_mask &= ~BG_CHANGED; 511 tcp->cur_color.bg = tcp->std_color.bg 512 = ansi_col[tcp->param[1] & 0x0f]; 513 tcp->cur_attr = mask2attr(tcp); 514 break; 515 case 2: /* set ansi foreground */ 516 tcp->attr_mask &= ~FG_CHANGED; 517 tcp->cur_color.fg = tcp->std_color.fg 518 = ansi_col[tcp->param[1] & 0x0f]; 519 tcp->cur_attr = mask2attr(tcp); 520 break; 521 case 3: /* set adapter attribute directly */ 522 tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED); 523 tcp->cur_color.fg = tcp->std_color.fg 524 = tcp->param[1] & 0x0f; 525 tcp->cur_color.bg = tcp->std_color.bg 526 = (tcp->param[1] >> 4) & 0x0f; 527 tcp->cur_attr = mask2attr(tcp); 528 break; 529 case 5: /* set ansi reverse background */ 530 tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f]; 531 tcp->cur_attr = mask2attr(tcp); 532 break; 533 case 6: /* set ansi reverse foreground */ 534 tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f]; 535 tcp->cur_attr = mask2attr(tcp); 536 break; 537 case 7: /* set adapter reverse attribute directly */ 538 tcp->rev_color.fg = tcp->param[1] & 0x0f; 539 tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f; 540 tcp->cur_attr = mask2attr(tcp); 541 break; 542 } 543 break; 544 545 case 'z': /* switch to (virtual) console n */ 546 if (tcp->num_param == 1) 547 sc_switch_scr(sc, tcp->param[0]); 548 break; 549 } 550 } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */ 551 if (c >= '0' && c <= '9') { 552 if (tcp->num_param < MAX_ESC_PAR) { 553 if (tcp->last_param != tcp->num_param) { 554 tcp->last_param = tcp->num_param; 555 tcp->param[tcp->num_param] = 0; 556 } else { 557 tcp->param[tcp->num_param] *= 10; 558 } 559 tcp->param[tcp->num_param] += c - '0'; 560 return; 561 } 562 } 563 tcp->num_param = tcp->last_param + 1; 564 switch (c) { 565 566 case ';': 567 if (tcp->num_param < MAX_ESC_PAR) 568 return; 569 break; 570 571 case 'A': /* set display border color */ 572 if (tcp->num_param == 1) { 573 scp->border=tcp->param[0] & 0xff; 574 if (scp == sc->cur_scp) 575 sc_set_border(scp, scp->border); 576 } 577 break; 578 579 case 'B': /* set bell pitch and duration */ 580 if (tcp->num_param == 2) { 581 scp->bell_pitch = tcp->param[0]; 582 scp->bell_duration = 583 (tcp->param[1] * hz + 99) / 100; 584 } 585 break; 586 587 case 'C': /* set global/parmanent cursor type & shape */ 588 i = spltty(); 589 n = tcp->num_param; 590 v0 = tcp->param[0]; 591 v1 = tcp->param[1]; 592 v2 = tcp->param[2]; 593 switch (n) { 594 case 1: /* flags only */ 595 if (v0 < sizeof(cattrs)/sizeof(cattrs[0])) 596 v0 = cattrs[v0]; 597 else /* backward compatibility */ 598 v0 = cattrs[v0 & 0x3]; 599 sc_change_cursor_shape(scp, v0, -1, -1); 600 break; 601 case 2: 602 v2 = 0; 603 v0 &= 0x1f; /* backward compatibility */ 604 v1 &= 0x1f; 605 /* FALL THROUGH */ 606 case 3: /* base and height */ 607 if (v2 == 0) /* count from top */ 608 sc_change_cursor_shape(scp, -1, 609 scp->font_size - v1 - 1, 610 v1 - v0 + 1); 611 else if (v2 == 1) /* count from bottom */ 612 sc_change_cursor_shape(scp, -1, 613 v0, v1 - v0 + 1); 614 break; 615 } 616 splx(i); 617 break; 618 619 case 'F': /* set adapter foreground */ 620 if (tcp->num_param == 1) { 621 tcp->attr_mask &= ~FG_CHANGED; 622 tcp->cur_color.fg = tcp->std_color.fg 623 = tcp->param[0] & 0x0f; 624 tcp->cur_attr = mask2attr(tcp); 625 } 626 break; 627 628 case 'G': /* set adapter background */ 629 if (tcp->num_param == 1) { 630 tcp->attr_mask &= ~BG_CHANGED; 631 tcp->cur_color.bg = tcp->std_color.bg 632 = tcp->param[0] & 0x0f; 633 tcp->cur_attr = mask2attr(tcp); 634 } 635 break; 636 637 case 'H': /* set adapter reverse foreground */ 638 if (tcp->num_param == 1) { 639 tcp->rev_color.fg = tcp->param[0] & 0x0f; 640 tcp->cur_attr = mask2attr(tcp); 641 } 642 break; 643 644 case 'I': /* set adapter reverse background */ 645 if (tcp->num_param == 1) { 646 tcp->rev_color.bg = tcp->param[0] & 0x0f; 647 tcp->cur_attr = mask2attr(tcp); 648 } 649 break; 650 651 case 'S': /* set local/temporary cursor type & shape */ 652 i = spltty(); 653 n = tcp->num_param; 654 v0 = tcp->param[0]; 655 switch (n) { 656 case 0: 657 v0 = 0; 658 /* FALL THROUGH */ 659 case 1: 660 if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0])) 661 sc_change_cursor_shape(scp, 662 tcattrs[v0], -1, -1); 663 break; 664 } 665 splx(i); 666 break; 667 } 668 #if notyet 669 } else if (tcp->esc == 4) { /* seen ESC Q */ 670 /* to be filled */ 671 #endif 672 } else if (tcp->esc == 5) { /* seen ESC ( */ 673 switch (c) { 674 case 'B': /* iso-2022: desginate ASCII into G0 */ 675 break; 676 /* other items to be filled */ 677 default: 678 break; 679 } 680 } 681 tcp->esc = 0; 682 } 683 684 static void 685 scterm_puts(scr_stat *scp, u_char *buf, int len) 686 { 687 term_stat *tcp; 688 689 tcp = scp->ts; 690 outloop: 691 scp->sc->write_in_progress++; 692 693 if (tcp->esc) { 694 scterm_scan_esc(scp, tcp, *buf); 695 buf++; 696 len--; 697 } else { 698 switch (*buf) { 699 case 0x1b: 700 tcp->esc = 1; 701 tcp->num_param = 0; 702 buf++; 703 len--; 704 break; 705 default: 706 sc_term_gen_print(scp, &buf, &len, tcp->cur_attr); 707 break; 708 } 709 } 710 711 sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr); 712 713 scp->sc->write_in_progress--; 714 if (len) 715 goto outloop; 716 } 717 718 static int 719 scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data, 720 int flag, struct thread *td) 721 { 722 term_stat *tcp = scp->ts; 723 vid_info_t *vi; 724 725 switch (cmd) { 726 case GIO_ATTR: /* get current attributes */ 727 /* FIXME: */ 728 *(int*)data = (tcp->cur_attr >> 8) & 0xff; 729 return 0; 730 case CONS_GETINFO: /* get current (virtual) console info */ 731 vi = (vid_info_t *)data; 732 if (vi->size != sizeof(struct vid_info)) 733 return EINVAL; 734 vi->mv_norm.fore = tcp->std_color.fg; 735 vi->mv_norm.back = tcp->std_color.bg; 736 vi->mv_rev.fore = tcp->rev_color.fg; 737 vi->mv_rev.back = tcp->rev_color.bg; 738 /* 739 * The other fields are filled by the upper routine. XXX 740 */ 741 return ENOIOCTL; 742 } 743 return ENOIOCTL; 744 } 745 746 static int 747 scterm_reset(scr_stat *scp, int code) 748 { 749 /* FIXME */ 750 return 0; 751 } 752 753 static void 754 scterm_default_attr(scr_stat *scp, int color, int rev_color) 755 { 756 term_stat *tcp = scp->ts; 757 758 tcp->dflt_std_color.fg = color & 0x0f; 759 tcp->dflt_std_color.bg = (color >> 4) & 0x0f; 760 tcp->dflt_rev_color.fg = rev_color & 0x0f; 761 tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f; 762 tcp->std_color = tcp->dflt_std_color; 763 tcp->rev_color = tcp->dflt_rev_color; 764 tcp->cur_color = tcp->std_color; 765 tcp->cur_attr = mask2attr(tcp); 766 } 767 768 static void 769 scterm_clear(scr_stat *scp) 770 { 771 term_stat *tcp = scp->ts; 772 773 sc_move_cursor(scp, 0, 0); 774 sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr); 775 mark_all(scp); 776 } 777 778 static void 779 scterm_notify(scr_stat *scp, int event) 780 { 781 switch (event) { 782 case SC_TE_NOTIFY_VTSWITCH_IN: 783 break; 784 case SC_TE_NOTIFY_VTSWITCH_OUT: 785 break; 786 } 787 } 788 789 static int 790 scterm_input(scr_stat *scp, int c, struct tty *tp) 791 { 792 return FALSE; 793 } 794 795 /* 796 * Calculate hardware attributes word using logical attributes mask and 797 * hardware colors 798 */ 799 800 /* FIXME */ 801 static int 802 mask2attr(term_stat *tcp) 803 { 804 int attr, mask = tcp->attr_mask; 805 806 if (mask & REVERSE_ATTR) { 807 attr = ((mask & FG_CHANGED) ? 808 tcp->cur_color.bg : tcp->rev_color.fg) | 809 (((mask & BG_CHANGED) ? 810 tcp->cur_color.fg : tcp->rev_color.bg) << 4); 811 } else 812 attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4); 813 814 /* XXX: underline mapping for Hercules adapter can be better */ 815 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 816 attr ^= 0x08; 817 if (mask & BLINK_ATTR) 818 attr ^= 0x80; 819 820 return (attr << 8); 821 } 822 823 #endif /* SC_DUMB_TERMINAL */ 824