1 /*- 2 * Copyright (c) 1992-1998 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: syscons.c,v 1.313 1999/07/07 13:48:49 yokota Exp $ 29 */ 30 31 #include "sc.h" 32 #include "splash.h" 33 #include "opt_syscons.h" 34 #include "opt_ddb.h" 35 #include "opt_devfs.h" 36 #ifdef __i386__ 37 #include "apm.h" 38 #endif 39 40 #if NSC > 0 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/reboot.h> 44 #include <sys/conf.h> 45 #include <sys/proc.h> 46 #include <sys/signalvar.h> 47 #include <sys/tty.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #ifdef DEVFS 51 #include <sys/devfsext.h> 52 #endif 53 54 #include <machine/clock.h> 55 #include <machine/cons.h> 56 #include <machine/console.h> 57 #include <machine/psl.h> 58 #include <machine/pc/display.h> 59 #ifdef __i386__ 60 #include <machine/apm_bios.h> 61 #include <machine/frame.h> 62 #include <machine/random.h> 63 #endif 64 65 #include <dev/kbd/kbdreg.h> 66 #include <dev/fb/fbreg.h> 67 #include <dev/fb/splashreg.h> 68 #include <dev/syscons/syscons.h> 69 70 #define COLD 0 71 #define WARM 1 72 73 #define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ 74 #define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ 75 76 #define KEYCODE_BS 0x0e /* "<-- Backspace" key, XXX */ 77 78 static default_attr user_default = { 79 SC_NORM_ATTR << 8, 80 SC_NORM_REV_ATTR << 8, 81 }; 82 83 static default_attr kernel_default = { 84 SC_KERNEL_CONS_ATTR << 8, 85 SC_KERNEL_CONS_REV_ATTR << 8, 86 }; 87 88 static int sc_console_unit = -1; 89 static scr_stat *sc_console; 90 #ifdef DEVFS 91 static void *sc_mouse_devfs_token; 92 static void *sc_console_devfs_token; 93 #endif 94 static term_stat kernel_console; 95 static default_attr *current_default; 96 97 static char init_done = COLD; 98 static char shutdown_in_progress = FALSE; 99 static char sc_malloc = FALSE; 100 101 static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ 102 static int run_scrn_saver = FALSE; /* should run the saver? */ 103 static long scrn_blank_time = 0; /* screen saver timeout value */ 104 #if NSPLASH > 0 105 static int scrn_blanked; /* # of blanked screen */ 106 static int sticky_splash = FALSE; 107 108 static void none_saver(sc_softc_t *sc, int blank) { } 109 static void (*current_saver)(sc_softc_t *, int) = none_saver; 110 #endif 111 112 #if !defined(SC_NO_FONT_LOADING) && defined(SC_DFLT_FONT) 113 #include "font.h" 114 #endif 115 116 d_ioctl_t *sc_user_ioctl; 117 118 static bios_values_t bios_value; 119 120 static struct tty sccons[2]; 121 #define SC_MOUSE 128 122 #define SC_CONSOLECTL 255 123 124 #define VIRTUAL_TTY(sc, x) (&((sc)->tty[(x) - (sc)->first_vty])) 125 #define CONSOLE_TTY (&sccons[0]) 126 #define MOUSE_TTY (&sccons[1]) 127 128 #define debugger FALSE 129 130 #ifdef __i386__ 131 #ifdef DDB 132 extern int in_Debugger; 133 #undef debugger 134 #define debugger in_Debugger 135 #endif /* DDB */ 136 #endif /* __i386__ */ 137 138 /* prototypes */ 139 static int scvidprobe(int unit, int flags, int cons); 140 static int sckbdprobe(int unit, int flags, int cons); 141 static void scmeminit(void *arg); 142 static int scdevtounit(dev_t dev); 143 static kbd_callback_func_t sckbdevent; 144 static int scparam(struct tty *tp, struct termios *t); 145 static void scstart(struct tty *tp); 146 static void scmousestart(struct tty *tp); 147 static void scinit(int unit, int flags); 148 #if __i386__ 149 static void scterm(int unit, int flags); 150 #endif 151 static void scshutdown(int howto, void *arg); 152 static u_int scgetc(sc_softc_t *sc, u_int flags); 153 #define SCGETC_CN 1 154 #define SCGETC_NONBLOCK 2 155 static int sccngetch(int flags); 156 static void sccnupdate(scr_stat *scp); 157 static scr_stat *alloc_scp(sc_softc_t *sc, int vty); 158 static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp); 159 static timeout_t scrn_timer; 160 static int and_region(int *s1, int *e1, int s2, int e2); 161 static void scrn_update(scr_stat *scp, int show_cursor); 162 163 #if NSPLASH > 0 164 static int scsplash_callback(int event, void *arg); 165 static void scsplash_saver(sc_softc_t *sc, int show); 166 static int add_scrn_saver(void (*this_saver)(sc_softc_t *, int)); 167 static int remove_scrn_saver(void (*this_saver)(sc_softc_t *, int)); 168 static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border); 169 static int restore_scrn_saver_mode(scr_stat *scp, int changemode); 170 static void stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int)); 171 static int wait_scrn_saver_stop(sc_softc_t *sc); 172 #define scsplash_stick(stick) (sticky_splash = (stick)) 173 #else /* !NSPLASH */ 174 #define scsplash_stick(stick) 175 #endif /* NSPLASH */ 176 177 static int switch_scr(sc_softc_t *sc, u_int next_scr); 178 static int do_switch_scr(sc_softc_t *sc, int s); 179 static int vt_proc_alive(scr_stat *scp); 180 static int signal_vt_rel(scr_stat *scp); 181 static int signal_vt_acq(scr_stat *scp); 182 static void exchange_scr(sc_softc_t *sc); 183 static void scan_esc(scr_stat *scp, u_char c); 184 static void ansi_put(scr_stat *scp, u_char *buf, int len); 185 static void draw_cursor_image(scr_stat *scp); 186 static void remove_cursor_image(scr_stat *scp); 187 static void update_cursor_image(scr_stat *scp); 188 static void move_crsr(scr_stat *scp, int x, int y); 189 static int mask2attr(struct term_stat *term); 190 static int save_kbd_state(scr_stat *scp); 191 static int update_kbd_state(scr_stat *scp, int state, int mask); 192 static int update_kbd_leds(scr_stat *scp, int which); 193 static void do_bell(scr_stat *scp, int pitch, int duration); 194 static timeout_t blink_screen; 195 196 #define CDEV_MAJOR 12 197 198 static cn_probe_t sccnprobe; 199 static cn_init_t sccninit; 200 static cn_getc_t sccngetc; 201 static cn_checkc_t sccncheckc; 202 static cn_putc_t sccnputc; 203 static cn_term_t sccnterm; 204 205 #if __alpha__ 206 void sccnattach(void); 207 #endif 208 209 CONS_DRIVER(sc, sccnprobe, sccninit, sccnterm, sccngetc, sccncheckc, sccnputc); 210 211 static d_open_t scopen; 212 static d_close_t scclose; 213 static d_read_t scread; 214 static d_write_t scwrite; 215 static d_ioctl_t scioctl; 216 static d_mmap_t scmmap; 217 218 static struct cdevsw sc_cdevsw = { 219 /* open */ scopen, 220 /* close */ scclose, 221 /* read */ scread, 222 /* write */ scwrite, 223 /* ioctl */ scioctl, 224 /* stop */ nostop, 225 /* reset */ noreset, 226 /* devtotty */ scdevtotty, 227 /* poll */ ttpoll, 228 /* mmap */ scmmap, 229 /* strategy */ nostrategy, 230 /* name */ "sc", 231 /* parms */ noparms, 232 /* maj */ CDEV_MAJOR, 233 /* dump */ nodump, 234 /* psize */ nopsize, 235 /* flags */ D_TTY, 236 /* maxio */ 0, 237 /* bmaj */ -1 238 }; 239 240 int 241 sc_probe_unit(int unit, int flags) 242 { 243 if (!scvidprobe(unit, flags, FALSE)) { 244 if (bootverbose) 245 printf("sc%d: no video adapter is found.\n", unit); 246 return ENXIO; 247 } 248 249 /* syscons will be attached even when there is no keyboard */ 250 sckbdprobe(unit, flags, FALSE); 251 252 return 0; 253 } 254 255 /* probe video adapters, return TRUE if found */ 256 static int 257 scvidprobe(int unit, int flags, int cons) 258 { 259 /* 260 * Access the video adapter driver through the back door! 261 * Video adapter drivers need to be configured before syscons. 262 * However, when syscons is being probed as the low-level console, 263 * they have not been initialized yet. We force them to initialize 264 * themselves here. XXX 265 */ 266 vid_configure(cons ? VIO_PROBE_ONLY : 0); 267 268 return (vid_find_adapter("*", unit) >= 0); 269 } 270 271 /* probe the keyboard, return TRUE if found */ 272 static int 273 sckbdprobe(int unit, int flags, int cons) 274 { 275 /* access the keyboard driver through the backdoor! */ 276 kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0); 277 278 return (kbd_find_keyboard("*", unit) >= 0); 279 } 280 281 static char 282 *adapter_name(video_adapter_t *adp) 283 { 284 static struct { 285 int type; 286 char *name[2]; 287 } names[] = { 288 { KD_MONO, { "MDA", "MDA" } }, 289 { KD_HERCULES, { "Hercules", "Hercules" } }, 290 { KD_CGA, { "CGA", "CGA" } }, 291 { KD_EGA, { "EGA", "EGA (mono)" } }, 292 { KD_VGA, { "VGA", "VGA (mono)" } }, 293 { KD_PC98, { "PC-98x1", "PC-98x1" } }, 294 { KD_TGA, { "TGA", "TGA" } }, 295 { -1, { "Unknown", "Unknown" } }, 296 }; 297 int i; 298 299 for (i = 0; names[i].type != -1; ++i) 300 if (names[i].type == adp->va_type) 301 break; 302 return names[i].name[(adp->va_flags & V_ADP_COLOR) ? 0 : 1]; 303 } 304 305 int 306 sc_attach_unit(int unit, int flags) 307 { 308 sc_softc_t *sc; 309 scr_stat *scp; 310 #ifdef SC_PIXEL_MODE 311 video_info_t info; 312 #endif 313 #ifdef DEVFS 314 int vc; 315 #endif 316 317 scmeminit(NULL); /* XXX */ 318 319 flags &= ~SC_KERNEL_CONSOLE; 320 if (sc_console_unit == unit) 321 flags |= SC_KERNEL_CONSOLE; 322 scinit(unit, flags); 323 sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE); 324 sc->config = flags; 325 scp = sc->console[0]; 326 if (sc_console == NULL) /* sc_console_unit < 0 */ 327 sc_console = scp; 328 329 #ifdef SC_PIXEL_MODE 330 if ((sc->config & SC_VESA800X600) 331 && ((*vidsw[sc->adapter]->get_info)(sc->adp, M_VESA_800x600, &info) == 0)) { 332 #if NSPLASH > 0 333 if (sc->flags & SC_SPLASH_SCRN) 334 splash_term(sc->adp); 335 #endif 336 sc_set_graphics_mode(scp, NULL, M_VESA_800x600); 337 sc_set_pixel_mode(scp, NULL, COL, ROW, 16); 338 sc->initial_mode = M_VESA_800x600; 339 #if NSPLASH > 0 340 /* put up the splash again! */ 341 if (sc->flags & SC_SPLASH_SCRN) 342 splash_init(sc->adp, scsplash_callback, sc); 343 #endif 344 } 345 #endif /* SC_PIXEL_MODE */ 346 347 /* initialize cursor */ 348 if (!ISGRAPHSC(scp)) 349 update_cursor_image(scp); 350 351 /* get screen update going */ 352 scrn_timer(sc); 353 354 /* set up the keyboard */ 355 kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); 356 update_kbd_state(scp, scp->status, LOCK_MASK); 357 358 printf("sc%d: %s <%d virtual consoles, flags=0x%x>\n", 359 unit, adapter_name(sc->adp), sc->vtys, sc->config); 360 if (bootverbose) { 361 printf("sc%d:", unit); 362 if (sc->adapter >= 0) 363 printf(" fb%d", sc->adapter); 364 if (sc->keyboard >= 0) 365 printf(" kbd%d", sc->keyboard); 366 printf("\n"); 367 } 368 369 /* register a shutdown callback for the kernel console */ 370 if (sc_console_unit == unit) 371 at_shutdown(scshutdown, (void *)(uintptr_t)unit, SHUTDOWN_PRE_SYNC); 372 373 /* 374 * syscons's cdevsw must be registered from here. As syscons and 375 * pcvt share the same major number, their cdevsw cannot be 376 * registered at module loading/initialization time or by SYSINIT. 377 */ 378 cdevsw_add(&sc_cdevsw); /* XXX do this just once... */ 379 380 #ifdef DEVFS 381 for (vc = sc->first_vty; vc < sc->first_vty + sc->vtys; vc++) 382 sc->devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, 383 DV_CHR, UID_ROOT, GID_WHEEL, 384 0600, "ttyv%r", vc); 385 if (scp == sc_console) { 386 #ifndef SC_NO_SYSMOUSE 387 sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, 388 DV_CHR, UID_ROOT, GID_WHEEL, 389 0600, "sysmouse"); 390 #endif /* SC_NO_SYSMOUSE */ 391 sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLECTL, 392 DV_CHR, UID_ROOT, GID_WHEEL, 393 0600, "consolectl"); 394 } 395 #endif /* DEVFS */ 396 397 return 0; 398 } 399 400 static void 401 scmeminit(void *arg) 402 { 403 if (sc_malloc) 404 return; 405 sc_malloc = TRUE; 406 407 /* 408 * As soon as malloc() becomes functional, we had better allocate 409 * various buffers for the kernel console. 410 */ 411 412 if (sc_console_unit < 0) 413 return; 414 415 /* copy the temporary buffer to the final buffer */ 416 sc_alloc_scr_buffer(sc_console, FALSE, FALSE); 417 418 #ifndef SC_NO_CUTPASTE 419 /* cut buffer is available only when the mouse pointer is used */ 420 if (ISMOUSEAVAIL(sc_console->sc->adp->va_flags)) 421 sc_alloc_cut_buffer(sc_console, FALSE); 422 #endif 423 424 #ifndef SC_NO_HISTORY 425 /* initialize history buffer & pointers */ 426 sc_alloc_history_buffer(sc_console, 0, 0, FALSE); 427 #endif 428 } 429 430 /* XXX */ 431 SYSINIT(sc_mem, SI_SUB_KMEM, SI_ORDER_ANY, scmeminit, NULL); 432 433 int 434 sc_resume_unit(int unit) 435 { 436 /* XXX should be moved to the keyboard driver? */ 437 sc_softc_t *sc; 438 439 sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0); 440 if (sc->kbd != NULL) 441 kbd_clear_state(sc->kbd); 442 return 0; 443 } 444 445 struct tty 446 *scdevtotty(dev_t dev) 447 { 448 sc_softc_t *sc; 449 int vty = SC_VTY(dev); 450 int unit; 451 452 if (init_done == COLD) 453 return NULL; 454 455 if (vty == SC_CONSOLECTL) 456 return CONSOLE_TTY; 457 #ifndef SC_NO_SYSMOUSE 458 if (vty == SC_MOUSE) 459 return MOUSE_TTY; 460 #endif 461 462 unit = scdevtounit(dev); 463 sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0); 464 if (sc == NULL) 465 return NULL; 466 return VIRTUAL_TTY(sc, vty); 467 } 468 469 static int 470 scdevtounit(dev_t dev) 471 { 472 int vty = SC_VTY(dev); 473 474 if (vty == SC_CONSOLECTL) 475 return ((sc_console != NULL) ? sc_console->sc->unit : -1); 476 else if (vty == SC_MOUSE) 477 return -1; 478 else if ((vty < 0) || (vty >= MAXCONS*sc_max_unit())) 479 return -1; 480 else 481 return vty/MAXCONS; 482 } 483 484 int 485 scopen(dev_t dev, int flag, int mode, struct proc *p) 486 { 487 struct tty *tp = scdevtotty(dev); 488 int unit = scdevtounit(dev); 489 sc_softc_t *sc; 490 keyarg_t key; 491 int error; 492 493 if (!tp) 494 return(ENXIO); 495 496 DPRINTF(5, ("scopen: dev:%d,%d, unit:%d, vty:%d\n", 497 major(dev), minor(dev), unit, SC_VTY(dev))); 498 499 /* sc == NULL, if SC_VTY(dev) == SC_MOUSE */ 500 sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0); 501 502 tp->t_oproc = (SC_VTY(dev) == SC_MOUSE) ? scmousestart : scstart; 503 tp->t_param = scparam; 504 tp->t_dev = dev; 505 if (!(tp->t_state & TS_ISOPEN)) { 506 ttychars(tp); 507 /* Use the current setting of the <-- key as default VERASE. */ 508 /* If the Delete key is preferable, an stty is necessary */ 509 if (sc != NULL) { 510 key.keynum = KEYCODE_BS; 511 kbd_ioctl(sc->kbd, GIO_KEYMAPENT, (caddr_t)&key); 512 tp->t_cc[VERASE] = key.key.map[0]; 513 } 514 tp->t_iflag = TTYDEF_IFLAG; 515 tp->t_oflag = TTYDEF_OFLAG; 516 tp->t_cflag = TTYDEF_CFLAG; 517 tp->t_lflag = TTYDEF_LFLAG; 518 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 519 scparam(tp, &tp->t_termios); 520 (*linesw[tp->t_line].l_modem)(tp, 1); 521 #ifndef SC_NO_SYSMOUSE 522 if (SC_VTY(dev) == SC_MOUSE) 523 sc_mouse_set_level(0); /* XXX */ 524 #endif 525 } 526 else 527 if (tp->t_state & TS_XCLUDE && suser(p)) 528 return(EBUSY); 529 530 error = (*linesw[tp->t_line].l_open)(dev, tp); 531 532 if ((SC_VTY(dev) != SC_CONSOLECTL) && (SC_VTY(dev) != SC_MOUSE)) { 533 /* assert(sc != NULL) */ 534 if (sc->console[SC_VTY(dev) - sc->first_vty] == NULL) { 535 sc->console[SC_VTY(dev) - sc->first_vty] 536 = alloc_scp(sc, SC_VTY(dev)); 537 if (ISGRAPHSC(sc->console[SC_VTY(dev) - sc->first_vty])) 538 sc_set_pixel_mode(sc->console[SC_VTY(dev) - sc->first_vty], 539 NULL, COL, ROW, 16); 540 } 541 if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 542 tp->t_winsize.ws_col 543 = sc->console[SC_VTY(dev) - sc->first_vty]->xsize; 544 tp->t_winsize.ws_row 545 = sc->console[SC_VTY(dev) - sc->first_vty]->ysize; 546 } 547 } 548 return error; 549 } 550 551 int 552 scclose(dev_t dev, int flag, int mode, struct proc *p) 553 { 554 struct tty *tp = scdevtotty(dev); 555 struct scr_stat *scp; 556 int s; 557 558 if (!tp) 559 return(ENXIO); 560 if ((SC_VTY(dev) != SC_CONSOLECTL) && (SC_VTY(dev) != SC_MOUSE)) { 561 scp = sc_get_scr_stat(tp->t_dev); 562 /* were we in the middle of the VT switching process? */ 563 DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit)); 564 s = spltty(); 565 if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit)) 566 cons_unavail = FALSE; 567 if (scp->status & SWITCH_WAIT_REL) { 568 /* assert(scp == scp->sc->cur_scp) */ 569 DPRINTF(5, ("reset WAIT_REL, ")); 570 scp->status &= ~SWITCH_WAIT_REL; 571 do_switch_scr(scp->sc, s); 572 } 573 if (scp->status & SWITCH_WAIT_ACQ) { 574 /* assert(scp == scp->sc->cur_scp) */ 575 DPRINTF(5, ("reset WAIT_ACQ, ")); 576 scp->status &= ~SWITCH_WAIT_ACQ; 577 scp->sc->switch_in_progress = 0; 578 } 579 #if not_yet_done 580 if (scp == &main_console) { 581 scp->pid = 0; 582 scp->proc = NULL; 583 scp->smode.mode = VT_AUTO; 584 } 585 else { 586 sc_vtb_destroy(&scp->vtb); 587 sc_vtb_destroy(&scp->scr); 588 sc_free_history_buffer(scp, scp->ysize); 589 free(scp, M_DEVBUF); 590 sc->console[SC_VTY(dev) - sc->first_vty] = NULL; 591 } 592 #else 593 scp->pid = 0; 594 scp->proc = NULL; 595 scp->smode.mode = VT_AUTO; 596 #endif 597 scp->kbd_mode = K_XLATE; 598 if (scp == scp->sc->cur_scp) 599 kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); 600 DPRINTF(5, ("done.\n")); 601 } 602 spltty(); 603 (*linesw[tp->t_line].l_close)(tp, flag); 604 ttyclose(tp); 605 spl0(); 606 return(0); 607 } 608 609 int 610 scread(dev_t dev, struct uio *uio, int flag) 611 { 612 struct tty *tp = scdevtotty(dev); 613 614 if (!tp) 615 return(ENXIO); 616 sc_touch_scrn_saver(); 617 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 618 } 619 620 int 621 scwrite(dev_t dev, struct uio *uio, int flag) 622 { 623 struct tty *tp = scdevtotty(dev); 624 625 if (!tp) 626 return(ENXIO); 627 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 628 } 629 630 static int 631 sckbdevent(keyboard_t *thiskbd, int event, void *arg) 632 { 633 sc_softc_t *sc; 634 struct tty *cur_tty; 635 int c; 636 size_t len; 637 u_char *cp; 638 639 sc = (sc_softc_t *)arg; 640 /* assert(thiskbd == sc->kbd) */ 641 642 switch (event) { 643 case KBDIO_KEYINPUT: 644 break; 645 case KBDIO_UNLOADING: 646 sc->kbd = NULL; 647 sc->keyboard = -1; 648 kbd_release(thiskbd, (void *)&sc->keyboard); 649 return 0; 650 default: 651 return EINVAL; 652 } 653 654 /* 655 * Loop while there is still input to get from the keyboard. 656 * I don't think this is nessesary, and it doesn't fix 657 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 658 */ 659 while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) { 660 661 cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index); 662 /* XXX */ 663 if (!(cur_tty->t_state & TS_ISOPEN)) 664 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 665 continue; 666 667 switch (KEYFLAGS(c)) { 668 case 0x0000: /* normal key */ 669 (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); 670 break; 671 case FKEY: /* function key, return string */ 672 cp = kbd_get_fkeystr(thiskbd, KEYCHAR(c), &len); 673 if (cp != NULL) { 674 while (len-- > 0) 675 (*linesw[cur_tty->t_line].l_rint)(*cp++, cur_tty); 676 } 677 break; 678 case MKEY: /* meta is active, prepend ESC */ 679 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 680 (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); 681 break; 682 case BKEY: /* backtab fixed sequence (esc [ Z) */ 683 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 684 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 685 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 686 break; 687 } 688 } 689 690 #ifndef SC_NO_CUTPASTE 691 if (sc->cur_scp->status & MOUSE_VISIBLE) { 692 sc_remove_mouse_image(sc->cur_scp); 693 sc->cur_scp->status &= ~MOUSE_VISIBLE; 694 } 695 #endif /* SC_NO_CUTPASTE */ 696 697 return 0; 698 } 699 700 static int 701 scparam(struct tty *tp, struct termios *t) 702 { 703 tp->t_ispeed = t->c_ispeed; 704 tp->t_ospeed = t->c_ospeed; 705 tp->t_cflag = t->c_cflag; 706 return 0; 707 } 708 709 int 710 scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 711 { 712 int error; 713 int i; 714 struct tty *tp; 715 sc_softc_t *sc; 716 scr_stat *scp; 717 int s; 718 719 tp = scdevtotty(dev); 720 if (!tp) 721 return ENXIO; 722 723 /* If there is a user_ioctl function call that first */ 724 if (sc_user_ioctl) { 725 error = (*sc_user_ioctl)(dev, cmd, data, flag, p); 726 if (error != ENOIOCTL) 727 return error; 728 } 729 730 error = sc_vid_ioctl(tp, cmd, data, flag, p); 731 if (error != ENOIOCTL) 732 return error; 733 734 #ifndef SC_NO_HISTORY 735 error = sc_hist_ioctl(tp, cmd, data, flag, p); 736 if (error != ENOIOCTL) 737 return error; 738 #endif 739 740 #ifndef SC_NO_SYSMOUSE 741 error = sc_mouse_ioctl(tp, cmd, data, flag, p); 742 if (error != ENOIOCTL) 743 return error; 744 if (SC_VTY(dev) == SC_MOUSE) { 745 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 746 if (error != ENOIOCTL) 747 return error; 748 error = ttioctl(tp, cmd, data, flag); 749 if (error != ENOIOCTL) 750 return error; 751 return ENOTTY; 752 } 753 #endif 754 755 scp = sc_get_scr_stat(tp->t_dev); 756 /* assert(scp != NULL) */ 757 /* scp is sc_console, if SC_VTY(dev) == SC_CONSOLECTL. */ 758 sc = scp->sc; 759 760 switch (cmd) { /* process console hardware related ioctl's */ 761 762 case GIO_ATTR: /* get current attributes */ 763 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 764 return 0; 765 766 case GIO_COLOR: /* is this a color console ? */ 767 *(int *)data = (sc->adp->va_flags & V_ADP_COLOR) ? 1 : 0; 768 return 0; 769 770 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 771 if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) 772 return EINVAL; 773 s = spltty(); 774 scrn_blank_time = *(int *)data; 775 run_scrn_saver = (scrn_blank_time != 0); 776 splx(s); 777 return 0; 778 779 case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 780 if (!ISGRAPHSC(sc->cur_scp)) 781 remove_cursor_image(sc->cur_scp); 782 if ((*(int*)data) & 0x01) 783 sc->flags |= SC_BLINK_CURSOR; 784 else 785 sc->flags &= ~SC_BLINK_CURSOR; 786 if ((*(int*)data) & 0x02) { 787 sc->flags |= SC_CHAR_CURSOR; 788 } else 789 sc->flags &= ~SC_CHAR_CURSOR; 790 /* 791 * The cursor shape is global property; all virtual consoles 792 * are affected. Update the cursor in the current console... 793 */ 794 if (!ISGRAPHSC(sc->cur_scp)) { 795 s = spltty(); 796 sc_set_cursor_image(sc->cur_scp); 797 draw_cursor_image(sc->cur_scp); 798 splx(s); 799 } 800 return 0; 801 802 case CONS_BELLTYPE: /* set bell type sound/visual */ 803 if ((*(int *)data) & 0x01) 804 sc->flags |= SC_VISUAL_BELL; 805 else 806 sc->flags &= ~SC_VISUAL_BELL; 807 if ((*(int *)data) & 0x02) 808 sc->flags |= SC_QUIET_BELL; 809 else 810 sc->flags &= ~SC_QUIET_BELL; 811 return 0; 812 813 case CONS_GETINFO: /* get current (virtual) console info */ 814 { 815 vid_info_t *ptr = (vid_info_t*)data; 816 if (ptr->size == sizeof(struct vid_info)) { 817 ptr->m_num = sc->cur_scp->index; 818 ptr->mv_col = scp->xpos; 819 ptr->mv_row = scp->ypos; 820 ptr->mv_csz = scp->xsize; 821 ptr->mv_rsz = scp->ysize; 822 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 823 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 824 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 825 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 826 ptr->mv_grfc.fore = 0; /* not supported */ 827 ptr->mv_grfc.back = 0; /* not supported */ 828 ptr->mv_ovscan = scp->border; 829 if (scp == sc->cur_scp) 830 save_kbd_state(scp); 831 ptr->mk_keylock = scp->status & LOCK_MASK; 832 return 0; 833 } 834 return EINVAL; 835 } 836 837 case CONS_GETVERS: /* get version number */ 838 *(int*)data = 0x200; /* version 2.0 */ 839 return 0; 840 841 case CONS_IDLE: /* see if the screen has been idle */ 842 /* 843 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, 844 * the user process may have been writing something on the 845 * screen and syscons is not aware of it. Declare the screen 846 * is NOT idle if it is in one of these modes. But there is 847 * an exception to it; if a screen saver is running in the 848 * graphics mode in the current screen, we should say that the 849 * screen has been idle. 850 */ 851 *(int *)data = (sc->flags & SC_SCRN_IDLE) 852 && (!ISGRAPHSC(sc->cur_scp) 853 || (sc->cur_scp->status & SAVER_RUNNING)); 854 return 0; 855 856 case CONS_SAVERMODE: /* set saver mode */ 857 switch(*(int *)data) { 858 case CONS_USR_SAVER: 859 /* if a LKM screen saver is running, stop it first. */ 860 scsplash_stick(FALSE); 861 saver_mode = *(int *)data; 862 s = spltty(); 863 #if NSPLASH > 0 864 if ((error = wait_scrn_saver_stop(NULL))) { 865 splx(s); 866 return error; 867 } 868 #endif /* NSPLASH */ 869 run_scrn_saver = TRUE; 870 scp->status |= SAVER_RUNNING; 871 scsplash_stick(TRUE); 872 splx(s); 873 break; 874 case CONS_LKM_SAVER: 875 s = spltty(); 876 if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) 877 scp->status &= ~SAVER_RUNNING; 878 saver_mode = *(int *)data; 879 splx(s); 880 break; 881 default: 882 return EINVAL; 883 } 884 return 0; 885 886 case CONS_SAVERSTART: /* immediately start/stop the screen saver */ 887 /* 888 * Note that this ioctl does not guarantee the screen saver 889 * actually starts or stops. It merely attempts to do so... 890 */ 891 s = spltty(); 892 run_scrn_saver = (*(int *)data != 0); 893 if (run_scrn_saver) 894 sc->scrn_time_stamp -= scrn_blank_time; 895 splx(s); 896 return 0; 897 898 case VT_SETMODE: /* set screen switcher mode */ 899 { 900 struct vt_mode *mode; 901 902 mode = (struct vt_mode *)data; 903 DPRINTF(5, ("sc%d: VT_SETMODE ", sc->unit)); 904 if (scp->smode.mode == VT_PROCESS) { 905 if (scp->proc == pfind(scp->pid) && scp->proc != p) { 906 DPRINTF(5, ("error EPERM\n")); 907 return EPERM; 908 } 909 } 910 s = spltty(); 911 if (mode->mode == VT_AUTO) { 912 scp->smode.mode = VT_AUTO; 913 scp->proc = NULL; 914 scp->pid = 0; 915 DPRINTF(5, ("VT_AUTO, ")); 916 if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit)) 917 cons_unavail = FALSE; 918 /* were we in the middle of the vty switching process? */ 919 if (scp->status & SWITCH_WAIT_REL) { 920 /* assert(scp == scp->sc->cur_scp) */ 921 DPRINTF(5, ("reset WAIT_REL, ")); 922 scp->status &= ~SWITCH_WAIT_REL; 923 s = do_switch_scr(sc, s); 924 } 925 if (scp->status & SWITCH_WAIT_ACQ) { 926 /* assert(scp == scp->sc->cur_scp) */ 927 DPRINTF(5, ("reset WAIT_ACQ, ")); 928 scp->status &= ~SWITCH_WAIT_ACQ; 929 sc->switch_in_progress = 0; 930 } 931 } else { 932 if (!ISSIGVALID(mode->relsig) || !ISSIGVALID(mode->acqsig) 933 || !ISSIGVALID(mode->frsig)) { 934 splx(s); 935 DPRINTF(5, ("error EINVAL\n")); 936 return EINVAL; 937 } 938 DPRINTF(5, ("VT_PROCESS %d, ", p->p_pid)); 939 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 940 scp->proc = p; 941 scp->pid = scp->proc->p_pid; 942 if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit)) 943 cons_unavail = TRUE; 944 } 945 splx(s); 946 DPRINTF(5, ("\n")); 947 return 0; 948 } 949 950 case VT_GETMODE: /* get screen switcher mode */ 951 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 952 return 0; 953 954 case VT_RELDISP: /* screen switcher ioctl */ 955 s = spltty(); 956 /* 957 * This must be the current vty which is in the VT_PROCESS 958 * switching mode... 959 */ 960 if ((scp != sc->cur_scp) || (scp->smode.mode != VT_PROCESS)) { 961 splx(s); 962 return EINVAL; 963 } 964 /* ...and this process is controlling it. */ 965 if (scp->proc != p) { 966 splx(s); 967 return EPERM; 968 } 969 error = EINVAL; 970 switch(*(int *)data) { 971 case VT_FALSE: /* user refuses to release screen, abort */ 972 if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) { 973 sc->old_scp->status &= ~SWITCH_WAIT_REL; 974 sc->switch_in_progress = 0; 975 DPRINTF(5, ("sc%d: VT_FALSE\n", sc->unit)); 976 error = 0; 977 } 978 break; 979 980 case VT_TRUE: /* user has released screen, go on */ 981 if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) { 982 scp->status &= ~SWITCH_WAIT_REL; 983 s = do_switch_scr(sc, s); 984 DPRINTF(5, ("sc%d: VT_TRUE\n", sc->unit)); 985 error = 0; 986 } 987 break; 988 989 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 990 if ((scp == sc->new_scp) && (scp->status & SWITCH_WAIT_ACQ)) { 991 scp->status &= ~SWITCH_WAIT_ACQ; 992 sc->switch_in_progress = 0; 993 DPRINTF(5, ("sc%d: VT_ACKACQ\n", sc->unit)); 994 error = 0; 995 } 996 break; 997 998 default: 999 break; 1000 } 1001 splx(s); 1002 return error; 1003 1004 case VT_OPENQRY: /* return free virtual console */ 1005 for (i = sc->first_vty; i < sc->first_vty + sc->vtys; i++) { 1006 tp = VIRTUAL_TTY(sc, i); 1007 if (!(tp->t_state & TS_ISOPEN)) { 1008 *(int *)data = i + 1; 1009 return 0; 1010 } 1011 } 1012 return EINVAL; 1013 1014 case VT_ACTIVATE: /* switch to screen *data */ 1015 s = spltty(); 1016 sc_clean_up(sc->cur_scp); 1017 splx(s); 1018 return switch_scr(sc, *(int *)data - 1); 1019 1020 case VT_WAITACTIVE: /* wait for switch to occur */ 1021 if ((*(int *)data >= sc->first_vty + sc->vtys) 1022 || (*(int *)data < sc->first_vty)) 1023 return EINVAL; 1024 s = spltty(); 1025 error = sc_clean_up(sc->cur_scp); 1026 splx(s); 1027 if (error) 1028 return error; 1029 if (*(int *)data != 0) 1030 scp = sc->console[*(int *)data - 1 - sc->first_vty]; 1031 if (scp == scp->sc->cur_scp) 1032 return 0; 1033 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1034 "waitvt", 0)) == ERESTART) ; 1035 return error; 1036 1037 case VT_GETACTIVE: /* get active vty # */ 1038 *(int *)data = sc->cur_scp->index + 1; 1039 return 0; 1040 1041 case VT_GETINDEX: /* get this vty # */ 1042 *(int *)data = scp->index + 1; 1043 return 0; 1044 1045 case KDENABIO: /* allow io operations */ 1046 error = suser(p); 1047 if (error != 0) 1048 return error; 1049 if (securelevel > 0) 1050 return EPERM; 1051 #ifdef __i386__ 1052 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1053 #endif 1054 return 0; 1055 1056 case KDDISABIO: /* disallow io operations (default) */ 1057 #ifdef __i386__ 1058 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1059 #endif 1060 return 0; 1061 1062 case KDSKBSTATE: /* set keyboard state (locks) */ 1063 if (*(int *)data & ~LOCK_MASK) 1064 return EINVAL; 1065 scp->status &= ~LOCK_MASK; 1066 scp->status |= *(int *)data; 1067 if (scp == sc->cur_scp) 1068 update_kbd_state(scp, scp->status, LOCK_MASK); 1069 return 0; 1070 1071 case KDGKBSTATE: /* get keyboard state (locks) */ 1072 if (scp == sc->cur_scp) 1073 save_kbd_state(scp); 1074 *(int *)data = scp->status & LOCK_MASK; 1075 return 0; 1076 1077 case KDSETREPEAT: /* set keyboard repeat & delay rates (new) */ 1078 error = kbd_ioctl(sc->kbd, cmd, data); 1079 if (error == ENOIOCTL) 1080 error = ENODEV; 1081 return error; 1082 1083 case KDSETRAD: /* set keyboard repeat & delay rates (old) */ 1084 if (*(int *)data & ~0x7f) 1085 return EINVAL; 1086 error = kbd_ioctl(sc->kbd, cmd, data); 1087 if (error == ENOIOCTL) 1088 error = ENODEV; 1089 return error; 1090 1091 case KDSKBMODE: /* set keyboard mode */ 1092 switch (*(int *)data) { 1093 case K_XLATE: /* switch to XLT ascii mode */ 1094 case K_RAW: /* switch to RAW scancode mode */ 1095 case K_CODE: /* switch to CODE mode */ 1096 scp->kbd_mode = *(int *)data; 1097 if (scp == sc->cur_scp) 1098 kbd_ioctl(sc->kbd, cmd, data); 1099 return 0; 1100 default: 1101 return EINVAL; 1102 } 1103 /* NOT REACHED */ 1104 1105 case KDGKBMODE: /* get keyboard mode */ 1106 *(int *)data = scp->kbd_mode; 1107 return 0; 1108 1109 case KDGKBINFO: 1110 error = kbd_ioctl(sc->kbd, cmd, data); 1111 if (error == ENOIOCTL) 1112 error = ENODEV; 1113 return error; 1114 1115 case KDMKTONE: /* sound the bell */ 1116 if (*(int*)data) 1117 do_bell(scp, (*(int*)data)&0xffff, 1118 (((*(int*)data)>>16)&0xffff)*hz/1000); 1119 else 1120 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1121 return 0; 1122 1123 case KIOCSOUND: /* make tone (*data) hz */ 1124 if (scp == sc->cur_scp) { 1125 if (*(int *)data) 1126 return sc_tone(*(int *)data); 1127 else 1128 return sc_tone(0); 1129 } 1130 return 0; 1131 1132 case KDGKBTYPE: /* get keyboard type */ 1133 error = kbd_ioctl(sc->kbd, cmd, data); 1134 if (error == ENOIOCTL) { 1135 /* always return something? XXX */ 1136 *(int *)data = 0; 1137 } 1138 return 0; 1139 1140 case KDSETLED: /* set keyboard LED status */ 1141 if (*(int *)data & ~LED_MASK) /* FIXME: LOCK_MASK? */ 1142 return EINVAL; 1143 scp->status &= ~LED_MASK; 1144 scp->status |= *(int *)data; 1145 if (scp == sc->cur_scp) 1146 update_kbd_leds(scp, scp->status); 1147 return 0; 1148 1149 case KDGETLED: /* get keyboard LED status */ 1150 if (scp == sc->cur_scp) 1151 save_kbd_state(scp); 1152 *(int *)data = scp->status & LED_MASK; 1153 return 0; 1154 1155 case CONS_SETKBD: /* set the new keyboard */ 1156 { 1157 keyboard_t *newkbd; 1158 1159 s = spltty(); 1160 newkbd = kbd_get_keyboard(*(int *)data); 1161 if (newkbd == NULL) { 1162 splx(s); 1163 return EINVAL; 1164 } 1165 error = 0; 1166 if (sc->kbd != newkbd) { 1167 i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit, 1168 (void *)&sc->keyboard, sckbdevent, sc); 1169 /* i == newkbd->kb_index */ 1170 if (i >= 0) { 1171 if (sc->kbd != NULL) { 1172 save_kbd_state(sc->cur_scp); 1173 kbd_release(sc->kbd, (void *)&sc->keyboard); 1174 } 1175 sc->kbd = kbd_get_keyboard(i); /* sc->kbd == newkbd */ 1176 sc->keyboard = i; 1177 kbd_ioctl(sc->kbd, KDSKBMODE, 1178 (caddr_t)&sc->cur_scp->kbd_mode); 1179 update_kbd_state(sc->cur_scp, sc->cur_scp->status, 1180 LOCK_MASK); 1181 } else { 1182 error = EPERM; /* XXX */ 1183 } 1184 } 1185 splx(s); 1186 return error; 1187 } 1188 1189 case CONS_RELKBD: /* release the current keyboard */ 1190 s = spltty(); 1191 error = 0; 1192 if (sc->kbd != NULL) { 1193 save_kbd_state(sc->cur_scp); 1194 error = kbd_release(sc->kbd, (void *)&sc->keyboard); 1195 if (error == 0) { 1196 sc->kbd = NULL; 1197 sc->keyboard = -1; 1198 } 1199 } 1200 splx(s); 1201 return error; 1202 1203 case GIO_SCRNMAP: /* get output translation table */ 1204 bcopy(&sc->scr_map, data, sizeof(sc->scr_map)); 1205 return 0; 1206 1207 case PIO_SCRNMAP: /* set output translation table */ 1208 bcopy(data, &sc->scr_map, sizeof(sc->scr_map)); 1209 for (i=0; i<sizeof(sc->scr_map); i++) { 1210 sc->scr_rmap[sc->scr_map[i]] = i; 1211 } 1212 return 0; 1213 1214 case GIO_KEYMAP: /* get keyboard translation table */ 1215 case PIO_KEYMAP: /* set keyboard translation table */ 1216 case GIO_DEADKEYMAP: /* get accent key translation table */ 1217 case PIO_DEADKEYMAP: /* set accent key translation table */ 1218 case GETFKEY: /* get function key string */ 1219 case SETFKEY: /* set function key string */ 1220 error = kbd_ioctl(sc->kbd, cmd, data); 1221 if (error == ENOIOCTL) 1222 error = ENODEV; 1223 return error; 1224 1225 #ifndef SC_NO_FONT_LOADING 1226 1227 case PIO_FONT8x8: /* set 8x8 dot font */ 1228 if (!ISFONTAVAIL(sc->adp->va_flags)) 1229 return ENXIO; 1230 bcopy(data, sc->font_8, 8*256); 1231 sc->fonts_loaded |= FONT_8; 1232 /* 1233 * FONT KLUDGE 1234 * Always use the font page #0. XXX 1235 * Don't load if the current font size is not 8x8. 1236 */ 1237 if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14)) 1238 copy_font(sc->cur_scp, LOAD, 8, sc->font_8); 1239 return 0; 1240 1241 case GIO_FONT8x8: /* get 8x8 dot font */ 1242 if (!ISFONTAVAIL(sc->adp->va_flags)) 1243 return ENXIO; 1244 if (sc->fonts_loaded & FONT_8) { 1245 bcopy(sc->font_8, data, 8*256); 1246 return 0; 1247 } 1248 else 1249 return ENXIO; 1250 1251 case PIO_FONT8x14: /* set 8x14 dot font */ 1252 if (!ISFONTAVAIL(sc->adp->va_flags)) 1253 return ENXIO; 1254 bcopy(data, sc->font_14, 14*256); 1255 sc->fonts_loaded |= FONT_14; 1256 /* 1257 * FONT KLUDGE 1258 * Always use the font page #0. XXX 1259 * Don't load if the current font size is not 8x14. 1260 */ 1261 if (ISTEXTSC(sc->cur_scp) 1262 && (sc->cur_scp->font_size >= 14) 1263 && (sc->cur_scp->font_size < 16)) 1264 copy_font(sc->cur_scp, LOAD, 14, sc->font_14); 1265 return 0; 1266 1267 case GIO_FONT8x14: /* get 8x14 dot font */ 1268 if (!ISFONTAVAIL(sc->adp->va_flags)) 1269 return ENXIO; 1270 if (sc->fonts_loaded & FONT_14) { 1271 bcopy(sc->font_14, data, 14*256); 1272 return 0; 1273 } 1274 else 1275 return ENXIO; 1276 1277 case PIO_FONT8x16: /* set 8x16 dot font */ 1278 if (!ISFONTAVAIL(sc->adp->va_flags)) 1279 return ENXIO; 1280 bcopy(data, sc->font_16, 16*256); 1281 sc->fonts_loaded |= FONT_16; 1282 /* 1283 * FONT KLUDGE 1284 * Always use the font page #0. XXX 1285 * Don't load if the current font size is not 8x16. 1286 */ 1287 if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16)) 1288 copy_font(sc->cur_scp, LOAD, 16, sc->font_16); 1289 return 0; 1290 1291 case GIO_FONT8x16: /* get 8x16 dot font */ 1292 if (!ISFONTAVAIL(sc->adp->va_flags)) 1293 return ENXIO; 1294 if (sc->fonts_loaded & FONT_16) { 1295 bcopy(sc->font_16, data, 16*256); 1296 return 0; 1297 } 1298 else 1299 return ENXIO; 1300 1301 #endif /* SC_NO_FONT_LOADING */ 1302 1303 default: 1304 break; 1305 } 1306 1307 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1308 if (error != ENOIOCTL) 1309 return(error); 1310 error = ttioctl(tp, cmd, data, flag); 1311 if (error != ENOIOCTL) 1312 return(error); 1313 return(ENOTTY); 1314 } 1315 1316 static void 1317 scstart(struct tty *tp) 1318 { 1319 struct clist *rbp; 1320 int s, len; 1321 u_char buf[PCBURST]; 1322 scr_stat *scp = sc_get_scr_stat(tp->t_dev); 1323 1324 if (scp->status & SLKED || scp->sc->blink_in_progress) 1325 return; 1326 s = spltty(); 1327 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1328 tp->t_state |= TS_BUSY; 1329 rbp = &tp->t_outq; 1330 while (rbp->c_cc) { 1331 len = q_to_b(rbp, buf, PCBURST); 1332 splx(s); 1333 ansi_put(scp, buf, len); 1334 s = spltty(); 1335 } 1336 tp->t_state &= ~TS_BUSY; 1337 ttwwakeup(tp); 1338 } 1339 splx(s); 1340 } 1341 1342 static void 1343 scmousestart(struct tty *tp) 1344 { 1345 struct clist *rbp; 1346 int s; 1347 u_char buf[PCBURST]; 1348 1349 s = spltty(); 1350 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1351 tp->t_state |= TS_BUSY; 1352 rbp = &tp->t_outq; 1353 while (rbp->c_cc) { 1354 q_to_b(rbp, buf, PCBURST); 1355 } 1356 tp->t_state &= ~TS_BUSY; 1357 ttwwakeup(tp); 1358 } 1359 splx(s); 1360 } 1361 1362 static void 1363 sccnprobe(struct consdev *cp) 1364 { 1365 #if __i386__ 1366 int unit; 1367 int flags; 1368 1369 cp->cn_pri = sc_get_cons_priority(&unit, &flags); 1370 1371 /* a video card is always required */ 1372 if (!scvidprobe(unit, flags, TRUE)) 1373 cp->cn_pri = CN_DEAD; 1374 1375 /* syscons will become console even when there is no keyboard */ 1376 sckbdprobe(unit, flags, TRUE); 1377 1378 if (cp->cn_pri == CN_DEAD) 1379 return; 1380 1381 /* initialize required fields */ 1382 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLECTL); 1383 #endif /* __i386__ */ 1384 1385 #if __alpha__ 1386 /* 1387 * alpha use sccnattach() rather than cnprobe()/cninit()/cnterm() 1388 * interface to install the console. Always return CN_DEAD from 1389 * here. 1390 */ 1391 cp->cn_pri = CN_DEAD; 1392 #endif /* __alpha__ */ 1393 } 1394 1395 static void 1396 sccninit(struct consdev *cp) 1397 { 1398 #if __i386__ 1399 int unit; 1400 int flags; 1401 1402 sc_get_cons_priority(&unit, &flags); 1403 scinit(unit, flags | SC_KERNEL_CONSOLE); 1404 sc_console_unit = unit; 1405 sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console[0]; 1406 #endif /* __i386__ */ 1407 1408 #if __alpha__ 1409 /* SHOULDN'T REACH HERE */ 1410 #endif /* __alpha__ */ 1411 } 1412 1413 static void 1414 sccnterm(struct consdev *cp) 1415 { 1416 /* we are not the kernel console any more, release everything */ 1417 1418 if (sc_console_unit < 0) 1419 return; /* shouldn't happen */ 1420 1421 #if __i386__ 1422 #if 0 /* XXX */ 1423 sc_clear_screen(sc_console); 1424 sccnupdate(sc_console); 1425 #endif 1426 scterm(sc_console_unit, SC_KERNEL_CONSOLE); 1427 sc_console_unit = -1; 1428 sc_console = NULL; 1429 #endif /* __i386__ */ 1430 1431 #if __alpha__ 1432 /* do nothing XXX */ 1433 #endif /* __alpha__ */ 1434 } 1435 1436 #ifdef __alpha__ 1437 1438 extern struct consdev *cn_tab; 1439 1440 void 1441 sccnattach(void) 1442 { 1443 static struct consdev consdev; 1444 int unit; 1445 int flags; 1446 1447 bcopy(&sc_consdev, &consdev, sizeof(sc_consdev)); 1448 consdev.cn_pri = sc_get_cons_priority(&unit, &flags); 1449 1450 /* a video card is always required */ 1451 if (!scvidprobe(unit, flags, TRUE)) 1452 consdev.cn_pri = CN_DEAD; 1453 1454 /* alpha doesn't allow the console being without a keyboard... Why? */ 1455 if (!sckbdprobe(unit, flags, TRUE)) 1456 consdev.cn_pri = CN_DEAD; 1457 1458 if (consdev.cn_pri == CN_DEAD) 1459 return; 1460 1461 scinit(unit, flags | SC_KERNEL_CONSOLE); 1462 sc_console_unit = unit; 1463 sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console[0]; 1464 consdev.cn_dev = makedev(CDEV_MAJOR, 0); 1465 cn_tab = &consdev; 1466 } 1467 1468 #endif /* __alpha__ */ 1469 1470 static void 1471 sccnputc(dev_t dev, int c) 1472 { 1473 u_char buf[1]; 1474 scr_stat *scp = sc_console; 1475 term_stat save = scp->term; 1476 struct tty *tp; 1477 int s; 1478 1479 /* assert(sc_console != NULL) */ 1480 1481 #ifndef SC_NO_HISTORY 1482 if (scp == scp->sc->cur_scp && scp->status & SLKED) { 1483 scp->status &= ~SLKED; 1484 update_kbd_state(scp, scp->status, SLKED); 1485 if (scp->status & BUFFER_SAVED) { 1486 if (!sc_hist_restore(scp)) 1487 sc_remove_cutmarking(scp); 1488 scp->status &= ~BUFFER_SAVED; 1489 scp->status |= CURSOR_ENABLED; 1490 draw_cursor_image(scp); 1491 } 1492 tp = VIRTUAL_TTY(scp->sc, scp->index); 1493 if (tp->t_state & TS_ISOPEN) 1494 scstart(tp); 1495 } 1496 #endif /* !SC_NO_HISTORY */ 1497 1498 scp->term = kernel_console; 1499 current_default = &kernel_default; 1500 buf[0] = c; 1501 ansi_put(scp, buf, 1); 1502 kernel_console = scp->term; 1503 current_default = &user_default; 1504 scp->term = save; 1505 1506 s = spltty(); /* block sckbdevent and scrn_timer */ 1507 sccnupdate(scp); 1508 splx(s); 1509 } 1510 1511 static int 1512 sccngetc(dev_t dev) 1513 { 1514 return sccngetch(0); 1515 } 1516 1517 static int 1518 sccncheckc(dev_t dev) 1519 { 1520 return sccngetch(SCGETC_NONBLOCK); 1521 } 1522 1523 static int 1524 sccngetch(int flags) 1525 { 1526 static struct fkeytab fkey; 1527 static int fkeycp; 1528 scr_stat *scp; 1529 u_char *p; 1530 int cur_mode; 1531 int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ 1532 int c; 1533 1534 /* assert(sc_console != NULL) */ 1535 1536 /* 1537 * Stop the screen saver and update the screen if necessary. 1538 * What if we have been running in the screen saver code... XXX 1539 */ 1540 sc_touch_scrn_saver(); 1541 scp = sc_console->sc->cur_scp; /* XXX */ 1542 sccnupdate(scp); 1543 1544 if (fkeycp < fkey.len) { 1545 splx(s); 1546 return fkey.str[fkeycp++]; 1547 } 1548 1549 if (scp->sc->kbd == NULL) { 1550 splx(s); 1551 return -1; 1552 } 1553 1554 /* 1555 * Make sure the keyboard is accessible even when the kbd device 1556 * driver is disabled. 1557 */ 1558 kbd_enable(scp->sc->kbd); 1559 1560 /* we shall always use the keyboard in the XLATE mode here */ 1561 cur_mode = scp->kbd_mode; 1562 scp->kbd_mode = K_XLATE; 1563 kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); 1564 1565 kbd_poll(scp->sc->kbd, TRUE); 1566 c = scgetc(scp->sc, SCGETC_CN | flags); 1567 kbd_poll(scp->sc->kbd, FALSE); 1568 1569 scp->kbd_mode = cur_mode; 1570 kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); 1571 kbd_disable(scp->sc->kbd); 1572 splx(s); 1573 1574 switch (KEYFLAGS(c)) { 1575 case 0: /* normal char */ 1576 return KEYCHAR(c); 1577 case FKEY: /* function key */ 1578 p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp); 1579 fkey.len = fkeycp; 1580 if ((p != NULL) && (fkey.len > 0)) { 1581 bcopy(p, fkey.str, fkey.len); 1582 fkeycp = 1; 1583 return fkey.str[0]; 1584 } 1585 return c; /* XXX */ 1586 case NOKEY: 1587 case ERRKEY: 1588 default: 1589 return -1; 1590 } 1591 /* NOT REACHED */ 1592 } 1593 1594 static void 1595 sccnupdate(scr_stat *scp) 1596 { 1597 /* this is a cut-down version of scrn_timer()... */ 1598 1599 if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress) 1600 return; 1601 1602 if (debugger || panicstr || shutdown_in_progress) { 1603 sc_touch_scrn_saver(); 1604 } else if (scp != scp->sc->cur_scp) { 1605 return; 1606 } 1607 1608 if (!run_scrn_saver) 1609 scp->sc->flags &= ~SC_SCRN_IDLE; 1610 #if NSPLASH > 0 1611 if ((saver_mode != CONS_LKM_SAVER) || !(scp->sc->flags & SC_SCRN_IDLE)) 1612 if (scp->sc->flags & SC_SCRN_BLANKED) 1613 stop_scrn_saver(scp->sc, current_saver); 1614 #endif /* NSPLASH */ 1615 1616 if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress 1617 || scp->sc->switch_in_progress) 1618 return; 1619 /* 1620 * FIXME: unlike scrn_timer(), we call scrn_update() from here even 1621 * when write_in_progress is non-zero. XXX 1622 */ 1623 1624 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 1625 scrn_update(scp, TRUE); 1626 } 1627 1628 scr_stat 1629 *sc_get_scr_stat(dev_t dev) 1630 { 1631 sc_softc_t *sc; 1632 int vty = SC_VTY(dev); 1633 int unit; 1634 1635 if (vty < 0) 1636 return NULL; 1637 if (vty == SC_CONSOLECTL) 1638 return sc_console; 1639 1640 unit = scdevtounit(dev); 1641 sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0); 1642 if (sc == NULL) 1643 return NULL; 1644 if ((sc->first_vty <= vty) && (vty < sc->first_vty + sc->vtys)) 1645 return sc->console[vty - sc->first_vty]; 1646 return NULL; 1647 } 1648 1649 static void 1650 scrn_timer(void *arg) 1651 { 1652 static int kbd_interval = 0; 1653 struct timeval tv; 1654 sc_softc_t *sc; 1655 scr_stat *scp; 1656 int again; 1657 int s; 1658 1659 again = (arg != NULL); 1660 if (arg != NULL) 1661 sc = (sc_softc_t *)arg; 1662 else if (sc_console != NULL) 1663 sc = sc_console->sc; 1664 else 1665 return; 1666 1667 /* don't do anything when we are performing some I/O operations */ 1668 if (sc->font_loading_in_progress || sc->videoio_in_progress) { 1669 if (again) 1670 timeout(scrn_timer, sc, hz / 10); 1671 return; 1672 } 1673 s = spltty(); 1674 1675 if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) { 1676 /* try to allocate a keyboard automatically */ 1677 if (++kbd_interval >= 25) { 1678 sc->keyboard = kbd_allocate("*", -1, (void *)&sc->keyboard, 1679 sckbdevent, sc); 1680 if (sc->keyboard >= 0) { 1681 sc->kbd = kbd_get_keyboard(sc->keyboard); 1682 kbd_ioctl(sc->kbd, KDSKBMODE, 1683 (caddr_t)&sc->cur_scp->kbd_mode); 1684 update_kbd_state(sc->cur_scp, sc->cur_scp->status, 1685 LOCK_MASK); 1686 } 1687 kbd_interval = 0; 1688 } 1689 } 1690 1691 /* find the vty to update */ 1692 scp = sc->cur_scp; 1693 1694 /* should we stop the screen saver? */ 1695 getmicrouptime(&tv); 1696 if (debugger || panicstr || shutdown_in_progress) 1697 sc_touch_scrn_saver(); 1698 if (run_scrn_saver) { 1699 if (tv.tv_sec > sc->scrn_time_stamp + scrn_blank_time) 1700 sc->flags |= SC_SCRN_IDLE; 1701 else 1702 sc->flags &= ~SC_SCRN_IDLE; 1703 } else { 1704 sc->scrn_time_stamp = tv.tv_sec; 1705 sc->flags &= ~SC_SCRN_IDLE; 1706 if (scrn_blank_time > 0) 1707 run_scrn_saver = TRUE; 1708 } 1709 #if NSPLASH > 0 1710 if ((saver_mode != CONS_LKM_SAVER) || !(sc->flags & SC_SCRN_IDLE)) 1711 if (sc->flags & SC_SCRN_BLANKED) 1712 stop_scrn_saver(sc, current_saver); 1713 #endif /* NSPLASH */ 1714 1715 /* should we just return ? */ 1716 if (sc->blink_in_progress || sc->switch_in_progress 1717 || sc->write_in_progress) { 1718 if (again) 1719 timeout(scrn_timer, sc, hz / 10); 1720 splx(s); 1721 return; 1722 } 1723 1724 /* Update the screen */ 1725 scp = sc->cur_scp; /* cur_scp may have changed... */ 1726 if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) 1727 scrn_update(scp, TRUE); 1728 1729 #if NSPLASH > 0 1730 /* should we activate the screen saver? */ 1731 if ((saver_mode == CONS_LKM_SAVER) && (sc->flags & SC_SCRN_IDLE)) 1732 if (!ISGRAPHSC(scp) || (sc->flags & SC_SCRN_BLANKED)) 1733 (*current_saver)(sc, TRUE); 1734 #endif /* NSPLASH */ 1735 1736 if (again) 1737 timeout(scrn_timer, sc, hz / 25); 1738 splx(s); 1739 } 1740 1741 static int 1742 and_region(int *s1, int *e1, int s2, int e2) 1743 { 1744 if (*e1 < s2 || e2 < *s1) 1745 return FALSE; 1746 *s1 = imax(*s1, s2); 1747 *e1 = imin(*e1, e2); 1748 return TRUE; 1749 } 1750 1751 static void 1752 scrn_update(scr_stat *scp, int show_cursor) 1753 { 1754 int start; 1755 int end; 1756 int s; 1757 int e; 1758 1759 /* assert(scp == scp->sc->cur_scp) */ 1760 1761 ++scp->sc->videoio_in_progress; 1762 1763 #ifndef SC_NO_CUTPASTE 1764 /* remove the previous mouse pointer image if necessary */ 1765 if ((scp->status & (MOUSE_VISIBLE | MOUSE_MOVED)) 1766 == (MOUSE_VISIBLE | MOUSE_MOVED)) { 1767 /* FIXME: I don't like this... XXX */ 1768 sc_remove_mouse_image(scp); 1769 if (scp->end >= scp->xsize*scp->ysize) 1770 scp->end = scp->xsize*scp->ysize - 1; 1771 } 1772 #endif /* !SC_NO_CUTPASTE */ 1773 1774 #if 1 1775 /* debug: XXX */ 1776 if (scp->end >= scp->xsize*scp->ysize) { 1777 printf("scrn_update(): scp->end %d > size_of_screen!!\n", scp->end); 1778 scp->end = scp->xsize*scp->ysize - 1; 1779 } 1780 if (scp->start < 0) { 1781 printf("scrn_update(): scp->start %d < 0\n", scp->start); 1782 scp->start = 0; 1783 } 1784 #endif 1785 1786 /* update screen image */ 1787 if (scp->start <= scp->end) { 1788 if (scp->mouse_cut_end >= 0) { 1789 /* there is a marked region for cut & paste */ 1790 if (scp->mouse_cut_start <= scp->mouse_cut_end) { 1791 start = scp->mouse_cut_start; 1792 end = scp->mouse_cut_end; 1793 } else { 1794 start = scp->mouse_cut_end; 1795 end = scp->mouse_cut_start - 1; 1796 } 1797 s = start; 1798 e = end; 1799 /* does the cut-mark region overlap with the update region? */ 1800 if (and_region(&s, &e, scp->start, scp->end)) { 1801 (*scp->rndr->draw)(scp, s, e - s + 1, TRUE); 1802 s = 0; 1803 e = start - 1; 1804 if (and_region(&s, &e, scp->start, scp->end)) 1805 (*scp->rndr->draw)(scp, s, e - s + 1, FALSE); 1806 s = end + 1; 1807 e = scp->xsize*scp->ysize - 1; 1808 if (and_region(&s, &e, scp->start, scp->end)) 1809 (*scp->rndr->draw)(scp, s, e - s + 1, FALSE); 1810 } else { 1811 (*scp->rndr->draw)(scp, scp->start, 1812 scp->end - scp->start + 1, FALSE); 1813 } 1814 } else { 1815 (*scp->rndr->draw)(scp, scp->start, 1816 scp->end - scp->start + 1, FALSE); 1817 } 1818 } 1819 1820 /* we are not to show the cursor and the mouse pointer... */ 1821 if (!show_cursor) { 1822 scp->end = 0; 1823 scp->start = scp->xsize*scp->ysize - 1; 1824 --scp->sc->videoio_in_progress; 1825 return; 1826 } 1827 1828 /* update cursor image */ 1829 if (scp->status & CURSOR_ENABLED) { 1830 /* did cursor move since last time ? */ 1831 if (scp->cursor_pos != scp->cursor_oldpos) { 1832 /* do we need to remove old cursor image ? */ 1833 if (scp->cursor_oldpos < scp->start || 1834 scp->cursor_oldpos > scp->end) { 1835 remove_cursor_image(scp); 1836 } 1837 scp->cursor_oldpos = scp->cursor_pos; 1838 draw_cursor_image(scp); 1839 } 1840 else { 1841 /* cursor didn't move, has it been overwritten ? */ 1842 if (scp->cursor_pos >= scp->start && scp->cursor_pos <= scp->end) { 1843 draw_cursor_image(scp); 1844 } else { 1845 /* if its a blinking cursor, we may have to update it */ 1846 if (scp->sc->flags & SC_BLINK_CURSOR) 1847 (*scp->rndr->blink_cursor)(scp, scp->cursor_pos, 1848 sc_inside_cutmark(scp, 1849 scp->cursor_pos)); 1850 } 1851 } 1852 } 1853 1854 #ifndef SC_NO_CUTPASTE 1855 /* update "pseudo" mouse pointer image */ 1856 if (scp->status & MOUSE_VISIBLE) { 1857 /* did mouse move since last time ? */ 1858 if (scp->status & MOUSE_MOVED) { 1859 /* the previous pointer image has been removed, see above */ 1860 scp->status &= ~MOUSE_MOVED; 1861 sc_draw_mouse_image(scp); 1862 } else { 1863 /* mouse didn't move, has it been overwritten ? */ 1864 if (scp->mouse_pos + scp->xsize + 1 >= scp->start && 1865 scp->mouse_pos <= scp->end) { 1866 sc_draw_mouse_image(scp); 1867 } else if (scp->cursor_pos == scp->mouse_pos || 1868 scp->cursor_pos == scp->mouse_pos + 1 || 1869 scp->cursor_pos == scp->mouse_pos + scp->xsize || 1870 scp->cursor_pos == scp->mouse_pos + scp->xsize + 1) { 1871 sc_draw_mouse_image(scp); 1872 } 1873 } 1874 } 1875 #endif /* SC_NO_CUTPASTE */ 1876 1877 scp->end = 0; 1878 scp->start = scp->xsize*scp->ysize - 1; 1879 1880 --scp->sc->videoio_in_progress; 1881 } 1882 1883 #if NSPLASH > 0 1884 static int 1885 scsplash_callback(int event, void *arg) 1886 { 1887 sc_softc_t *sc; 1888 int error; 1889 1890 sc = (sc_softc_t *)arg; 1891 1892 switch (event) { 1893 case SPLASH_INIT: 1894 if (add_scrn_saver(scsplash_saver) == 0) { 1895 sc->flags &= ~SC_SAVER_FAILED; 1896 run_scrn_saver = TRUE; 1897 if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) { 1898 scsplash_stick(TRUE); 1899 (*current_saver)(sc, TRUE); 1900 } 1901 } 1902 return 0; 1903 1904 case SPLASH_TERM: 1905 if (current_saver == scsplash_saver) { 1906 scsplash_stick(FALSE); 1907 error = remove_scrn_saver(scsplash_saver); 1908 if (error) 1909 return error; 1910 } 1911 return 0; 1912 1913 default: 1914 return EINVAL; 1915 } 1916 } 1917 1918 static void 1919 scsplash_saver(sc_softc_t *sc, int show) 1920 { 1921 static int busy = FALSE; 1922 scr_stat *scp; 1923 1924 if (busy) 1925 return; 1926 busy = TRUE; 1927 1928 scp = sc->cur_scp; 1929 if (show) { 1930 if (!(sc->flags & SC_SAVER_FAILED)) { 1931 if (!(sc->flags & SC_SCRN_BLANKED)) 1932 set_scrn_saver_mode(scp, -1, NULL, 0); 1933 switch (splash(sc->adp, TRUE)) { 1934 case 0: /* succeeded */ 1935 break; 1936 case EAGAIN: /* try later */ 1937 restore_scrn_saver_mode(scp, FALSE); 1938 sc_touch_scrn_saver(); /* XXX */ 1939 break; 1940 default: 1941 sc->flags |= SC_SAVER_FAILED; 1942 scsplash_stick(FALSE); 1943 restore_scrn_saver_mode(scp, TRUE); 1944 printf("scsplash_saver(): failed to put up the image\n"); 1945 break; 1946 } 1947 } 1948 } else if (!sticky_splash) { 1949 if ((sc->flags & SC_SCRN_BLANKED) && (splash(sc->adp, FALSE) == 0)) 1950 restore_scrn_saver_mode(scp, TRUE); 1951 } 1952 busy = FALSE; 1953 } 1954 1955 static int 1956 add_scrn_saver(void (*this_saver)(sc_softc_t *, int)) 1957 { 1958 #if 0 1959 int error; 1960 1961 if (current_saver != none_saver) { 1962 error = remove_scrn_saver(current_saver); 1963 if (error) 1964 return error; 1965 } 1966 #endif 1967 if (current_saver != none_saver) 1968 return EBUSY; 1969 1970 run_scrn_saver = FALSE; 1971 saver_mode = CONS_LKM_SAVER; 1972 current_saver = this_saver; 1973 return 0; 1974 } 1975 1976 static int 1977 remove_scrn_saver(void (*this_saver)(sc_softc_t *, int)) 1978 { 1979 if (current_saver != this_saver) 1980 return EINVAL; 1981 1982 #if 0 1983 /* 1984 * In order to prevent `current_saver' from being called by 1985 * the timeout routine `scrn_timer()' while we manipulate 1986 * the saver list, we shall set `current_saver' to `none_saver' 1987 * before stopping the current saver, rather than blocking by `splXX()'. 1988 */ 1989 current_saver = none_saver; 1990 if (scrn_blanked) 1991 stop_scrn_saver(this_saver); 1992 #endif 1993 1994 /* unblank all blanked screens */ 1995 wait_scrn_saver_stop(NULL); 1996 if (scrn_blanked) 1997 return EBUSY; 1998 1999 current_saver = none_saver; 2000 return 0; 2001 } 2002 2003 static int 2004 set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border) 2005 { 2006 int s; 2007 2008 /* assert(scp == scp->sc->cur_scp) */ 2009 s = spltty(); 2010 if (!ISGRAPHSC(scp)) 2011 remove_cursor_image(scp); 2012 scp->splash_save_mode = scp->mode; 2013 scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE); 2014 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); 2015 scp->status |= (UNKNOWN_MODE | SAVER_RUNNING); 2016 scp->sc->flags |= SC_SCRN_BLANKED; 2017 ++scrn_blanked; 2018 splx(s); 2019 if (mode < 0) 2020 return 0; 2021 scp->mode = mode; 2022 if (set_mode(scp) == 0) { 2023 if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS) 2024 scp->status |= GRAPHICS_MODE; 2025 #ifndef SC_NO_PALETTE_LOADING 2026 if (pal != NULL) 2027 load_palette(scp->sc->adp, pal); 2028 #endif 2029 set_border(scp, border); 2030 return 0; 2031 } else { 2032 s = spltty(); 2033 scp->mode = scp->splash_save_mode; 2034 scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); 2035 scp->status |= scp->splash_save_status; 2036 splx(s); 2037 return 1; 2038 } 2039 } 2040 2041 static int 2042 restore_scrn_saver_mode(scr_stat *scp, int changemode) 2043 { 2044 int mode; 2045 int status; 2046 int s; 2047 2048 /* assert(scp == scp->sc->cur_scp) */ 2049 s = spltty(); 2050 mode = scp->mode; 2051 status = scp->status; 2052 scp->mode = scp->splash_save_mode; 2053 scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); 2054 scp->status |= scp->splash_save_status; 2055 scp->sc->flags &= ~SC_SCRN_BLANKED; 2056 if (!changemode) { 2057 if (!ISGRAPHSC(scp)) 2058 draw_cursor_image(scp); 2059 --scrn_blanked; 2060 splx(s); 2061 return 0; 2062 } 2063 if (set_mode(scp) == 0) { 2064 #ifndef SC_NO_PALETTE_LOADING 2065 load_palette(scp->sc->adp, scp->sc->palette); 2066 #endif 2067 --scrn_blanked; 2068 splx(s); 2069 return 0; 2070 } else { 2071 scp->mode = mode; 2072 scp->status = status; 2073 splx(s); 2074 return 1; 2075 } 2076 } 2077 2078 static void 2079 stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int)) 2080 { 2081 (*saver)(sc, FALSE); 2082 run_scrn_saver = FALSE; 2083 /* the screen saver may have chosen not to stop after all... */ 2084 if (sc->flags & SC_SCRN_BLANKED) 2085 return; 2086 2087 mark_all(sc->cur_scp); 2088 if (sc->delayed_next_scr) 2089 switch_scr(sc, sc->delayed_next_scr - 1); 2090 wakeup((caddr_t)&scrn_blanked); 2091 } 2092 2093 static int 2094 wait_scrn_saver_stop(sc_softc_t *sc) 2095 { 2096 int error = 0; 2097 2098 while (scrn_blanked > 0) { 2099 run_scrn_saver = FALSE; 2100 if (sc && !(sc->flags & SC_SCRN_BLANKED)) { 2101 error = 0; 2102 break; 2103 } 2104 error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); 2105 if ((error != 0) && (error != ERESTART)) 2106 break; 2107 } 2108 run_scrn_saver = FALSE; 2109 return error; 2110 } 2111 #endif /* NSPLASH */ 2112 2113 void 2114 sc_touch_scrn_saver(void) 2115 { 2116 scsplash_stick(FALSE); 2117 run_scrn_saver = FALSE; 2118 } 2119 2120 void 2121 sc_clear_screen(scr_stat *scp) 2122 { 2123 move_crsr(scp, 0, 0); 2124 scp->cursor_oldpos = scp->cursor_pos; 2125 sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], scp->term.cur_color); 2126 mark_all(scp); 2127 sc_remove_cutmarking(scp); 2128 } 2129 2130 static int 2131 switch_scr(sc_softc_t *sc, u_int next_scr) 2132 { 2133 struct tty *tp; 2134 int s; 2135 2136 DPRINTF(5, ("sc0: switch_scr() %d ", next_scr + 1)); 2137 2138 /* delay switch if the screen is blanked or being updated */ 2139 if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress 2140 || sc->blink_in_progress || sc->videoio_in_progress) { 2141 sc->delayed_next_scr = next_scr + 1; 2142 sc_touch_scrn_saver(); 2143 DPRINTF(5, ("switch delayed\n")); 2144 return 0; 2145 } 2146 2147 s = spltty(); 2148 2149 /* we are in the middle of the vty switching process... */ 2150 if (sc->switch_in_progress 2151 && (sc->cur_scp->smode.mode == VT_PROCESS) 2152 && sc->cur_scp->proc) { 2153 if (sc->cur_scp->proc != pfind(sc->cur_scp->pid)) { 2154 /* 2155 * The controlling process has died!!. Do some clean up. 2156 * NOTE:`cur_scp->proc' and `cur_scp->smode.mode' 2157 * are not reset here yet; they will be cleared later. 2158 */ 2159 DPRINTF(5, ("cur_scp controlling process %d died, ", 2160 sc->cur_scp->pid)); 2161 if (sc->cur_scp->status & SWITCH_WAIT_REL) { 2162 /* 2163 * Force the previous switch to finish, but return now 2164 * with error. 2165 */ 2166 DPRINTF(5, ("reset WAIT_REL, ")); 2167 sc->cur_scp->status &= ~SWITCH_WAIT_REL; 2168 s = do_switch_scr(sc, s); 2169 splx(s); 2170 DPRINTF(5, ("finishing previous switch\n")); 2171 return EINVAL; 2172 } else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) { 2173 /* let's assume screen switch has been completed. */ 2174 DPRINTF(5, ("reset WAIT_ACQ, ")); 2175 sc->cur_scp->status &= ~SWITCH_WAIT_ACQ; 2176 sc->switch_in_progress = 0; 2177 } else { 2178 /* 2179 * We are in between screen release and acquisition, and 2180 * reached here via scgetc() or scrn_timer() which has 2181 * interrupted exchange_scr(). Don't do anything stupid. 2182 */ 2183 DPRINTF(5, ("waiting nothing, ")); 2184 } 2185 } else { 2186 /* 2187 * The controlling process is alive, but not responding... 2188 * It is either buggy or it may be just taking time. 2189 * The following code is a gross kludge to cope with this 2190 * problem for which there is no clean solution. XXX 2191 */ 2192 if (sc->cur_scp->status & SWITCH_WAIT_REL) { 2193 switch (sc->switch_in_progress++) { 2194 case 1: 2195 break; 2196 case 2: 2197 DPRINTF(5, ("sending relsig again, ")); 2198 signal_vt_rel(sc->cur_scp); 2199 break; 2200 case 3: 2201 break; 2202 case 4: 2203 default: 2204 /* 2205 * Clear the flag and force the previous switch to finish, 2206 * but return now with error. 2207 */ 2208 DPRINTF(5, ("force reset WAIT_REL, ")); 2209 sc->cur_scp->status &= ~SWITCH_WAIT_REL; 2210 s = do_switch_scr(sc, s); 2211 splx(s); 2212 DPRINTF(5, ("force finishing previous switch\n")); 2213 return EINVAL; 2214 } 2215 } else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) { 2216 switch (sc->switch_in_progress++) { 2217 case 1: 2218 break; 2219 case 2: 2220 DPRINTF(5, ("sending acqsig again, ")); 2221 signal_vt_acq(sc->cur_scp); 2222 break; 2223 case 3: 2224 break; 2225 case 4: 2226 default: 2227 /* clear the flag and finish the previous switch */ 2228 DPRINTF(5, ("force reset WAIT_ACQ, ")); 2229 sc->cur_scp->status &= ~SWITCH_WAIT_ACQ; 2230 sc->switch_in_progress = 0; 2231 break; 2232 } 2233 } 2234 } 2235 } 2236 2237 /* 2238 * Return error if an invalid argument is given, or vty switch 2239 * is still in progress. 2240 */ 2241 if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys) 2242 || sc->switch_in_progress) { 2243 splx(s); 2244 do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION); 2245 DPRINTF(5, ("error 1\n")); 2246 return EINVAL; 2247 } 2248 2249 /* 2250 * Don't allow switching away from the graphics mode vty 2251 * if the switch mode is VT_AUTO, unless the next vty is the same 2252 * as the current or the current vty has been closed (but showing). 2253 */ 2254 tp = VIRTUAL_TTY(sc, sc->cur_scp->index); 2255 if ((sc->cur_scp->index != next_scr) 2256 && (tp->t_state & TS_ISOPEN) 2257 && (sc->cur_scp->smode.mode == VT_AUTO) 2258 && ISGRAPHSC(sc->cur_scp)) { 2259 splx(s); 2260 do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION); 2261 DPRINTF(5, ("error, graphics mode\n")); 2262 return EINVAL; 2263 } 2264 2265 /* 2266 * Is the wanted vty open? Don't allow switching to a closed vty. 2267 * Note that we always allow the user to switch to the kernel 2268 * console even if it is closed. 2269 */ 2270 if ((sc_console == NULL) || (next_scr != sc_console->index)) { 2271 tp = VIRTUAL_TTY(sc, next_scr); 2272 if (!(tp->t_state & TS_ISOPEN)) { 2273 splx(s); 2274 do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION); 2275 DPRINTF(5, ("error 2, requested vty isn't open!\n")); 2276 return EINVAL; 2277 } 2278 } 2279 2280 /* this is the start of vty switching process... */ 2281 ++sc->switch_in_progress; 2282 sc->delayed_next_scr = 0; 2283 sc->old_scp = sc->cur_scp; 2284 sc->new_scp = sc->console[next_scr - sc->first_vty]; 2285 if (sc->new_scp == sc->old_scp) { 2286 sc->switch_in_progress = 0; 2287 wakeup((caddr_t)&sc->new_scp->smode); 2288 splx(s); 2289 DPRINTF(5, ("switch done (new == old)\n")); 2290 return 0; 2291 } 2292 2293 /* has controlling process died? */ 2294 vt_proc_alive(sc->old_scp); 2295 vt_proc_alive(sc->new_scp); 2296 2297 /* wait for the controlling process to release the screen, if necessary */ 2298 if (signal_vt_rel(sc->old_scp)) { 2299 splx(s); 2300 return 0; 2301 } 2302 2303 /* go set up the new vty screen */ 2304 splx(s); 2305 exchange_scr(sc); 2306 s = spltty(); 2307 2308 /* wake up processes waiting for this vty */ 2309 wakeup((caddr_t)&sc->cur_scp->smode); 2310 2311 /* wait for the controlling process to acknowledge, if necessary */ 2312 if (signal_vt_acq(sc->cur_scp)) { 2313 splx(s); 2314 return 0; 2315 } 2316 2317 sc->switch_in_progress = 0; 2318 if (sc->unit == sc_console_unit) 2319 cons_unavail = FALSE; 2320 splx(s); 2321 DPRINTF(5, ("switch done\n")); 2322 2323 return 0; 2324 } 2325 2326 static int 2327 do_switch_scr(sc_softc_t *sc, int s) 2328 { 2329 vt_proc_alive(sc->new_scp); 2330 2331 splx(s); 2332 exchange_scr(sc); 2333 s = spltty(); 2334 /* sc->cur_scp == sc->new_scp */ 2335 wakeup((caddr_t)&sc->cur_scp->smode); 2336 2337 /* wait for the controlling process to acknowledge, if necessary */ 2338 if (!signal_vt_acq(sc->cur_scp)) { 2339 sc->switch_in_progress = 0; 2340 if (sc->unit == sc_console_unit) 2341 cons_unavail = FALSE; 2342 } 2343 2344 return s; 2345 } 2346 2347 static int 2348 vt_proc_alive(scr_stat *scp) 2349 { 2350 if (scp->proc) { 2351 if (scp->proc == pfind(scp->pid)) 2352 return TRUE; 2353 scp->proc = NULL; 2354 scp->smode.mode = VT_AUTO; 2355 DPRINTF(5, ("vt controlling process %d died\n", scp->pid)); 2356 } 2357 return FALSE; 2358 } 2359 2360 static int 2361 signal_vt_rel(scr_stat *scp) 2362 { 2363 if (scp->smode.mode != VT_PROCESS) 2364 return FALSE; 2365 scp->status |= SWITCH_WAIT_REL; 2366 psignal(scp->proc, scp->smode.relsig); 2367 DPRINTF(5, ("sending relsig to %d\n", scp->pid)); 2368 return TRUE; 2369 } 2370 2371 static int 2372 signal_vt_acq(scr_stat *scp) 2373 { 2374 if (scp->smode.mode != VT_PROCESS) 2375 return FALSE; 2376 if (scp->sc->unit == sc_console_unit) 2377 cons_unavail = TRUE; 2378 scp->status |= SWITCH_WAIT_ACQ; 2379 psignal(scp->proc, scp->smode.acqsig); 2380 DPRINTF(5, ("sending acqsig to %d\n", scp->pid)); 2381 return TRUE; 2382 } 2383 2384 static void 2385 exchange_scr(sc_softc_t *sc) 2386 { 2387 scr_stat *scp; 2388 2389 /* save the current state of video and keyboard */ 2390 move_crsr(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos); 2391 if (sc->old_scp->kbd_mode == K_XLATE) 2392 save_kbd_state(sc->old_scp); 2393 2394 /* set up the video for the new screen */ 2395 scp = sc->cur_scp = sc->new_scp; 2396 if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp)) 2397 set_mode(scp); 2398 else 2399 sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize, 2400 (void *)sc->adp->va_window, FALSE); 2401 move_crsr(scp, scp->xpos, scp->ypos); 2402 if (!ISGRAPHSC(scp)) 2403 sc_set_cursor_image(scp); 2404 #ifndef SC_NO_PALETTE_LOADING 2405 if (ISGRAPHSC(sc->old_scp)) 2406 load_palette(sc->adp, sc->palette); 2407 #endif 2408 set_border(scp, scp->border); 2409 2410 /* set up the keyboard for the new screen */ 2411 if (sc->old_scp->kbd_mode != scp->kbd_mode) 2412 kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); 2413 update_kbd_state(scp, scp->status, LOCK_MASK); 2414 2415 mark_all(scp); 2416 } 2417 2418 static void 2419 scan_esc(scr_stat *scp, u_char c) 2420 { 2421 static u_char ansi_col[16] = 2422 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2423 sc_softc_t *sc; 2424 int i, n; 2425 int count; 2426 2427 i = n = 0; 2428 sc = scp->sc; 2429 if (scp->term.esc == 1) { /* seen ESC */ 2430 switch (c) { 2431 2432 case '7': /* Save cursor position */ 2433 scp->saved_xpos = scp->xpos; 2434 scp->saved_ypos = scp->ypos; 2435 break; 2436 2437 case '8': /* Restore saved cursor position */ 2438 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2439 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2440 break; 2441 2442 case '[': /* Start ESC [ sequence */ 2443 scp->term.esc = 2; 2444 scp->term.last_param = -1; 2445 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2446 scp->term.param[i] = 1; 2447 scp->term.num_param = 0; 2448 return; 2449 2450 case 'M': /* Move cursor up 1 line, scroll if at top */ 2451 if (scp->ypos > 0) 2452 move_crsr(scp, scp->xpos, scp->ypos - 1); 2453 else { 2454 sc_vtb_ins(&scp->vtb, 0, scp->xsize, 2455 sc->scr_map[0x20], scp->term.cur_color); 2456 mark_all(scp); 2457 } 2458 break; 2459 #if notyet 2460 case 'Q': 2461 scp->term.esc = 4; 2462 return; 2463 #endif 2464 case 'c': /* Clear screen & home */ 2465 sc_clear_screen(scp); 2466 break; 2467 2468 case '(': /* iso-2022: designate 94 character set to G0 */ 2469 scp->term.esc = 5; 2470 return; 2471 } 2472 } 2473 else if (scp->term.esc == 2) { /* seen ESC [ */ 2474 if (c >= '0' && c <= '9') { 2475 if (scp->term.num_param < MAX_ESC_PAR) { 2476 if (scp->term.last_param != scp->term.num_param) { 2477 scp->term.last_param = scp->term.num_param; 2478 scp->term.param[scp->term.num_param] = 0; 2479 } 2480 else 2481 scp->term.param[scp->term.num_param] *= 10; 2482 scp->term.param[scp->term.num_param] += c - '0'; 2483 return; 2484 } 2485 } 2486 scp->term.num_param = scp->term.last_param + 1; 2487 switch (c) { 2488 2489 case ';': 2490 if (scp->term.num_param < MAX_ESC_PAR) 2491 return; 2492 break; 2493 2494 case '=': 2495 scp->term.esc = 3; 2496 scp->term.last_param = -1; 2497 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2498 scp->term.param[i] = 1; 2499 scp->term.num_param = 0; 2500 return; 2501 2502 case 'A': /* up n rows */ 2503 n = scp->term.param[0]; if (n < 1) n = 1; 2504 move_crsr(scp, scp->xpos, scp->ypos - n); 2505 break; 2506 2507 case 'B': /* down n rows */ 2508 n = scp->term.param[0]; if (n < 1) n = 1; 2509 move_crsr(scp, scp->xpos, scp->ypos + n); 2510 break; 2511 2512 case 'C': /* right n columns */ 2513 n = scp->term.param[0]; if (n < 1) n = 1; 2514 move_crsr(scp, scp->xpos + n, scp->ypos); 2515 break; 2516 2517 case 'D': /* left n columns */ 2518 n = scp->term.param[0]; if (n < 1) n = 1; 2519 move_crsr(scp, scp->xpos - n, scp->ypos); 2520 break; 2521 2522 case 'E': /* cursor to start of line n lines down */ 2523 n = scp->term.param[0]; if (n < 1) n = 1; 2524 move_crsr(scp, 0, scp->ypos + n); 2525 break; 2526 2527 case 'F': /* cursor to start of line n lines up */ 2528 n = scp->term.param[0]; if (n < 1) n = 1; 2529 move_crsr(scp, 0, scp->ypos - n); 2530 break; 2531 2532 case 'f': /* Cursor move */ 2533 case 'H': 2534 if (scp->term.num_param == 0) 2535 move_crsr(scp, 0, 0); 2536 else if (scp->term.num_param == 2) 2537 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2538 break; 2539 2540 case 'J': /* Clear all or part of display */ 2541 if (scp->term.num_param == 0) 2542 n = 0; 2543 else 2544 n = scp->term.param[0]; 2545 switch (n) { 2546 case 0: /* clear form cursor to end of display */ 2547 sc_vtb_erase(&scp->vtb, scp->cursor_pos, 2548 scp->xsize * scp->ysize - scp->cursor_pos, 2549 sc->scr_map[0x20], scp->term.cur_color); 2550 mark_for_update(scp, scp->cursor_pos); 2551 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2552 sc_remove_cutmarking(scp); 2553 break; 2554 case 1: /* clear from beginning of display to cursor */ 2555 sc_vtb_erase(&scp->vtb, 0, scp->cursor_pos, 2556 sc->scr_map[0x20], scp->term.cur_color); 2557 mark_for_update(scp, 0); 2558 mark_for_update(scp, scp->cursor_pos); 2559 sc_remove_cutmarking(scp); 2560 break; 2561 case 2: /* clear entire display */ 2562 sc_vtb_clear(&scp->vtb, sc->scr_map[0x20], scp->term.cur_color); 2563 mark_all(scp); 2564 sc_remove_cutmarking(scp); 2565 break; 2566 } 2567 break; 2568 2569 case 'K': /* Clear all or part of line */ 2570 if (scp->term.num_param == 0) 2571 n = 0; 2572 else 2573 n = scp->term.param[0]; 2574 switch (n) { 2575 case 0: /* clear form cursor to end of line */ 2576 sc_vtb_erase(&scp->vtb, scp->cursor_pos, 2577 scp->xsize - scp->xpos, 2578 sc->scr_map[0x20], scp->term.cur_color); 2579 mark_for_update(scp, scp->cursor_pos); 2580 mark_for_update(scp, scp->cursor_pos + 2581 scp->xsize - 1 - scp->xpos); 2582 break; 2583 case 1: /* clear from beginning of line to cursor */ 2584 sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos, 2585 scp->xpos + 1, 2586 sc->scr_map[0x20], scp->term.cur_color); 2587 mark_for_update(scp, scp->ypos * scp->xsize); 2588 mark_for_update(scp, scp->cursor_pos); 2589 break; 2590 case 2: /* clear entire line */ 2591 sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos, 2592 scp->xsize, 2593 sc->scr_map[0x20], scp->term.cur_color); 2594 mark_for_update(scp, scp->ypos * scp->xsize); 2595 mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); 2596 break; 2597 } 2598 break; 2599 2600 case 'L': /* Insert n lines */ 2601 n = scp->term.param[0]; if (n < 1) n = 1; 2602 if (n > scp->ysize - scp->ypos) 2603 n = scp->ysize - scp->ypos; 2604 sc_vtb_ins(&scp->vtb, scp->ypos * scp->xsize, n * scp->xsize, 2605 sc->scr_map[0x20], scp->term.cur_color); 2606 mark_for_update(scp, scp->ypos * scp->xsize); 2607 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2608 break; 2609 2610 case 'M': /* Delete n lines */ 2611 n = scp->term.param[0]; if (n < 1) n = 1; 2612 if (n > scp->ysize - scp->ypos) 2613 n = scp->ysize - scp->ypos; 2614 sc_vtb_delete(&scp->vtb, scp->ypos * scp->xsize, n * scp->xsize, 2615 sc->scr_map[0x20], scp->term.cur_color); 2616 mark_for_update(scp, scp->ypos * scp->xsize); 2617 mark_for_update(scp, scp->xsize * scp->ysize - 1); 2618 break; 2619 2620 case 'P': /* Delete n chars */ 2621 n = scp->term.param[0]; if (n < 1) n = 1; 2622 if (n > scp->xsize - scp->xpos) 2623 n = scp->xsize - scp->xpos; 2624 count = scp->xsize - (scp->xpos + n); 2625 sc_vtb_move(&scp->vtb, scp->cursor_pos + n, scp->cursor_pos, count); 2626 sc_vtb_erase(&scp->vtb, scp->cursor_pos + count, n, 2627 sc->scr_map[0x20], scp->term.cur_color); 2628 mark_for_update(scp, scp->cursor_pos); 2629 mark_for_update(scp, scp->cursor_pos + n + count - 1); 2630 break; 2631 2632 case '@': /* Insert n chars */ 2633 n = scp->term.param[0]; if (n < 1) n = 1; 2634 if (n > scp->xsize - scp->xpos) 2635 n = scp->xsize - scp->xpos; 2636 count = scp->xsize - (scp->xpos + n); 2637 sc_vtb_move(&scp->vtb, scp->cursor_pos, scp->cursor_pos + n, count); 2638 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, 2639 sc->scr_map[0x20], scp->term.cur_color); 2640 mark_for_update(scp, scp->cursor_pos); 2641 mark_for_update(scp, scp->cursor_pos + n + count - 1); 2642 break; 2643 2644 case 'S': /* scroll up n lines */ 2645 n = scp->term.param[0]; if (n < 1) n = 1; 2646 if (n > scp->ysize) 2647 n = scp->ysize; 2648 sc_vtb_delete(&scp->vtb, 0, n * scp->xsize, 2649 sc->scr_map[0x20], scp->term.cur_color); 2650 mark_all(scp); 2651 break; 2652 2653 case 'T': /* scroll down n lines */ 2654 n = scp->term.param[0]; if (n < 1) n = 1; 2655 if (n > scp->ysize) 2656 n = scp->ysize; 2657 sc_vtb_ins(&scp->vtb, 0, n * scp->xsize, 2658 sc->scr_map[0x20], scp->term.cur_color); 2659 mark_all(scp); 2660 break; 2661 2662 case 'X': /* erase n characters in line */ 2663 n = scp->term.param[0]; if (n < 1) n = 1; 2664 if (n > scp->xsize - scp->xpos) 2665 n = scp->xsize - scp->xpos; 2666 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, 2667 sc->scr_map[0x20], scp->term.cur_color); 2668 mark_for_update(scp, scp->cursor_pos); 2669 mark_for_update(scp, scp->cursor_pos + n - 1); 2670 break; 2671 2672 case 'Z': /* move n tabs backwards */ 2673 n = scp->term.param[0]; if (n < 1) n = 1; 2674 if ((i = scp->xpos & 0xf8) == scp->xpos) 2675 i -= 8*n; 2676 else 2677 i -= 8*(n-1); 2678 if (i < 0) 2679 i = 0; 2680 move_crsr(scp, i, scp->ypos); 2681 break; 2682 2683 case '`': /* move cursor to column n */ 2684 n = scp->term.param[0]; if (n < 1) n = 1; 2685 move_crsr(scp, n - 1, scp->ypos); 2686 break; 2687 2688 case 'a': /* move cursor n columns to the right */ 2689 n = scp->term.param[0]; if (n < 1) n = 1; 2690 move_crsr(scp, scp->xpos + n, scp->ypos); 2691 break; 2692 2693 case 'd': /* move cursor to row n */ 2694 n = scp->term.param[0]; if (n < 1) n = 1; 2695 move_crsr(scp, scp->xpos, n - 1); 2696 break; 2697 2698 case 'e': /* move cursor n rows down */ 2699 n = scp->term.param[0]; if (n < 1) n = 1; 2700 move_crsr(scp, scp->xpos, scp->ypos + n); 2701 break; 2702 2703 case 'm': /* change attribute */ 2704 if (scp->term.num_param == 0) { 2705 scp->term.attr_mask = NORMAL_ATTR; 2706 scp->term.cur_attr = 2707 scp->term.cur_color = scp->term.std_color; 2708 break; 2709 } 2710 for (i = 0; i < scp->term.num_param; i++) { 2711 switch (n = scp->term.param[i]) { 2712 case 0: /* back to normal */ 2713 scp->term.attr_mask = NORMAL_ATTR; 2714 scp->term.cur_attr = 2715 scp->term.cur_color = scp->term.std_color; 2716 break; 2717 case 1: /* bold */ 2718 scp->term.attr_mask |= BOLD_ATTR; 2719 scp->term.cur_attr = mask2attr(&scp->term); 2720 break; 2721 case 4: /* underline */ 2722 scp->term.attr_mask |= UNDERLINE_ATTR; 2723 scp->term.cur_attr = mask2attr(&scp->term); 2724 break; 2725 case 5: /* blink */ 2726 scp->term.attr_mask |= BLINK_ATTR; 2727 scp->term.cur_attr = mask2attr(&scp->term); 2728 break; 2729 case 7: /* reverse video */ 2730 scp->term.attr_mask |= REVERSE_ATTR; 2731 scp->term.cur_attr = mask2attr(&scp->term); 2732 break; 2733 case 30: case 31: /* set fg color */ 2734 case 32: case 33: case 34: 2735 case 35: case 36: case 37: 2736 scp->term.attr_mask |= FOREGROUND_CHANGED; 2737 scp->term.cur_color = 2738 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2739 scp->term.cur_attr = mask2attr(&scp->term); 2740 break; 2741 case 40: case 41: /* set bg color */ 2742 case 42: case 43: case 44: 2743 case 45: case 46: case 47: 2744 scp->term.attr_mask |= BACKGROUND_CHANGED; 2745 scp->term.cur_color = 2746 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2747 scp->term.cur_attr = mask2attr(&scp->term); 2748 break; 2749 } 2750 } 2751 break; 2752 2753 case 's': /* Save cursor position */ 2754 scp->saved_xpos = scp->xpos; 2755 scp->saved_ypos = scp->ypos; 2756 break; 2757 2758 case 'u': /* Restore saved cursor position */ 2759 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2760 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2761 break; 2762 2763 case 'x': 2764 if (scp->term.num_param == 0) 2765 n = 0; 2766 else 2767 n = scp->term.param[0]; 2768 switch (n) { 2769 case 0: /* reset attributes */ 2770 scp->term.attr_mask = NORMAL_ATTR; 2771 scp->term.cur_attr = 2772 scp->term.cur_color = scp->term.std_color = 2773 current_default->std_color; 2774 scp->term.rev_color = current_default->rev_color; 2775 break; 2776 case 1: /* set ansi background */ 2777 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2778 scp->term.cur_color = scp->term.std_color = 2779 (scp->term.std_color & 0x0F00) | 2780 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2781 scp->term.cur_attr = mask2attr(&scp->term); 2782 break; 2783 case 2: /* set ansi foreground */ 2784 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2785 scp->term.cur_color = scp->term.std_color = 2786 (scp->term.std_color & 0xF000) | 2787 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2788 scp->term.cur_attr = mask2attr(&scp->term); 2789 break; 2790 case 3: /* set ansi attribute directly */ 2791 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2792 scp->term.cur_color = scp->term.std_color = 2793 (scp->term.param[1]&0xFF)<<8; 2794 scp->term.cur_attr = mask2attr(&scp->term); 2795 break; 2796 case 5: /* set ansi reverse video background */ 2797 scp->term.rev_color = 2798 (scp->term.rev_color & 0x0F00) | 2799 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2800 scp->term.cur_attr = mask2attr(&scp->term); 2801 break; 2802 case 6: /* set ansi reverse video foreground */ 2803 scp->term.rev_color = 2804 (scp->term.rev_color & 0xF000) | 2805 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2806 scp->term.cur_attr = mask2attr(&scp->term); 2807 break; 2808 case 7: /* set ansi reverse video directly */ 2809 scp->term.rev_color = 2810 (scp->term.param[1]&0xFF)<<8; 2811 scp->term.cur_attr = mask2attr(&scp->term); 2812 break; 2813 } 2814 break; 2815 2816 case 'z': /* switch to (virtual) console n */ 2817 if (scp->term.num_param == 1) 2818 switch_scr(sc, scp->term.param[0]); 2819 break; 2820 } 2821 } 2822 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2823 if (c >= '0' && c <= '9') { 2824 if (scp->term.num_param < MAX_ESC_PAR) { 2825 if (scp->term.last_param != scp->term.num_param) { 2826 scp->term.last_param = scp->term.num_param; 2827 scp->term.param[scp->term.num_param] = 0; 2828 } 2829 else 2830 scp->term.param[scp->term.num_param] *= 10; 2831 scp->term.param[scp->term.num_param] += c - '0'; 2832 return; 2833 } 2834 } 2835 scp->term.num_param = scp->term.last_param + 1; 2836 switch (c) { 2837 2838 case ';': 2839 if (scp->term.num_param < MAX_ESC_PAR) 2840 return; 2841 break; 2842 2843 case 'A': /* set display border color */ 2844 if (scp->term.num_param == 1) { 2845 scp->border=scp->term.param[0] & 0xff; 2846 if (scp == sc->cur_scp) 2847 set_border(scp, scp->border); 2848 } 2849 break; 2850 2851 case 'B': /* set bell pitch and duration */ 2852 if (scp->term.num_param == 2) { 2853 scp->bell_pitch = scp->term.param[0]; 2854 scp->bell_duration = scp->term.param[1]; 2855 } 2856 break; 2857 2858 case 'C': /* set cursor type & shape */ 2859 if (!ISGRAPHSC(sc->cur_scp)) 2860 remove_cursor_image(sc->cur_scp); 2861 if (scp->term.num_param == 1) { 2862 if (scp->term.param[0] & 0x01) 2863 sc->flags |= SC_BLINK_CURSOR; 2864 else 2865 sc->flags &= ~SC_BLINK_CURSOR; 2866 if (scp->term.param[0] & 0x02) 2867 sc->flags |= SC_CHAR_CURSOR; 2868 else 2869 sc->flags &= ~SC_CHAR_CURSOR; 2870 } 2871 else if (scp->term.num_param == 2) { 2872 sc->cursor_base = scp->font_size 2873 - (scp->term.param[1] & 0x1F) - 1; 2874 sc->cursor_height = (scp->term.param[1] & 0x1F) 2875 - (scp->term.param[0] & 0x1F) + 1; 2876 } 2877 /* 2878 * The cursor shape is global property; all virtual consoles 2879 * are affected. Update the cursor in the current console... 2880 */ 2881 if (!ISGRAPHSC(sc->cur_scp)) { 2882 i = spltty(); 2883 sc_set_cursor_image(sc->cur_scp); 2884 draw_cursor_image(sc->cur_scp); 2885 splx(i); 2886 } 2887 break; 2888 2889 case 'F': /* set ansi foreground */ 2890 if (scp->term.num_param == 1) { 2891 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2892 scp->term.cur_color = scp->term.std_color = 2893 (scp->term.std_color & 0xF000) 2894 | ((scp->term.param[0] & 0x0F) << 8); 2895 scp->term.cur_attr = mask2attr(&scp->term); 2896 } 2897 break; 2898 2899 case 'G': /* set ansi background */ 2900 if (scp->term.num_param == 1) { 2901 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2902 scp->term.cur_color = scp->term.std_color = 2903 (scp->term.std_color & 0x0F00) 2904 | ((scp->term.param[0] & 0x0F) << 12); 2905 scp->term.cur_attr = mask2attr(&scp->term); 2906 } 2907 break; 2908 2909 case 'H': /* set ansi reverse video foreground */ 2910 if (scp->term.num_param == 1) { 2911 scp->term.rev_color = 2912 (scp->term.rev_color & 0xF000) 2913 | ((scp->term.param[0] & 0x0F) << 8); 2914 scp->term.cur_attr = mask2attr(&scp->term); 2915 } 2916 break; 2917 2918 case 'I': /* set ansi reverse video background */ 2919 if (scp->term.num_param == 1) { 2920 scp->term.rev_color = 2921 (scp->term.rev_color & 0x0F00) 2922 | ((scp->term.param[0] & 0x0F) << 12); 2923 scp->term.cur_attr = mask2attr(&scp->term); 2924 } 2925 break; 2926 } 2927 } 2928 #if notyet 2929 else if (scp->term.esc == 4) { /* seen ESC Q */ 2930 /* to be filled */ 2931 } 2932 #endif 2933 else if (scp->term.esc == 5) { /* seen ESC ( */ 2934 switch (c) { 2935 case 'B': /* iso-2022: desginate ASCII into G0 */ 2936 break; 2937 /* other items to be filled */ 2938 default: 2939 break; 2940 } 2941 } 2942 scp->term.esc = 0; 2943 } 2944 2945 static void 2946 ansi_put(scr_stat *scp, u_char *buf, int len) 2947 { 2948 u_char *ptr = buf; 2949 2950 #if NSPLASH > 0 2951 /* make screensaver happy */ 2952 if (!sticky_splash && scp == scp->sc->cur_scp) 2953 run_scrn_saver = FALSE; 2954 #endif 2955 2956 outloop: 2957 scp->sc->write_in_progress++; 2958 if (scp->term.esc) { 2959 scan_esc(scp, *ptr++); 2960 len--; 2961 } 2962 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2963 vm_offset_t p; 2964 u_char *map; 2965 int cnt; 2966 int attr; 2967 int i; 2968 2969 p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos); 2970 map = scp->sc->scr_map; 2971 attr = scp->term.cur_attr; 2972 2973 cnt = (len <= scp->xsize - scp->xpos) ? len : (scp->xsize - scp->xpos); 2974 i = cnt; 2975 do { 2976 /* 2977 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2978 * pointers in the following to volatile should have no effect, 2979 * but in fact speeds up this inner loop from 26 to 18 cycles 2980 * (+ cache misses) on i486's. 2981 */ 2982 #define UCVP(ucp) ((u_char volatile *)(ucp)) 2983 p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)], attr); 2984 ++ptr; 2985 --i; 2986 } while (i > 0 && PRINTABLE(*ptr)); 2987 2988 len -= cnt - i; 2989 mark_for_update(scp, scp->cursor_pos); 2990 scp->cursor_pos += cnt - i; 2991 mark_for_update(scp, scp->cursor_pos - 1); 2992 scp->xpos += cnt - i; 2993 2994 if (scp->xpos >= scp->xsize) { 2995 scp->xpos = 0; 2996 scp->ypos++; 2997 } 2998 } 2999 else { 3000 switch(*ptr) { 3001 case 0x07: 3002 do_bell(scp, scp->bell_pitch, scp->bell_duration); 3003 break; 3004 3005 case 0x08: /* non-destructive backspace */ 3006 if (scp->cursor_pos > 0) { 3007 mark_for_update(scp, scp->cursor_pos); 3008 scp->cursor_pos--; 3009 mark_for_update(scp, scp->cursor_pos); 3010 if (scp->xpos > 0) 3011 scp->xpos--; 3012 else { 3013 scp->xpos += scp->xsize - 1; 3014 scp->ypos--; 3015 } 3016 } 3017 break; 3018 3019 case 0x09: /* non-destructive tab */ 3020 mark_for_update(scp, scp->cursor_pos); 3021 scp->cursor_pos += (8 - scp->xpos % 8u); 3022 mark_for_update(scp, scp->cursor_pos); 3023 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 3024 scp->xpos = 0; 3025 scp->ypos++; 3026 } 3027 break; 3028 3029 case 0x0a: /* newline, same pos */ 3030 mark_for_update(scp, scp->cursor_pos); 3031 scp->cursor_pos += scp->xsize; 3032 mark_for_update(scp, scp->cursor_pos); 3033 scp->ypos++; 3034 break; 3035 3036 case 0x0c: /* form feed, clears screen */ 3037 sc_clear_screen(scp); 3038 break; 3039 3040 case 0x0d: /* return, return to pos 0 */ 3041 mark_for_update(scp, scp->cursor_pos); 3042 scp->cursor_pos -= scp->xpos; 3043 mark_for_update(scp, scp->cursor_pos); 3044 scp->xpos = 0; 3045 break; 3046 3047 case 0x1b: /* start escape sequence */ 3048 scp->term.esc = 1; 3049 scp->term.num_param = 0; 3050 break; 3051 } 3052 ptr++; len--; 3053 } 3054 /* do we have to scroll ?? */ 3055 if (scp->cursor_pos >= scp->ysize * scp->xsize) { 3056 sc_remove_cutmarking(scp); 3057 #ifndef SC_NO_HISTORY 3058 if (scp->history != NULL) 3059 sc_hist_save_one_line(scp, 0); 3060 #endif 3061 sc_vtb_delete(&scp->vtb, 0, scp->xsize, 3062 scp->sc->scr_map[0x20], scp->term.cur_color); 3063 scp->cursor_pos -= scp->xsize; 3064 scp->ypos--; 3065 mark_all(scp); 3066 } 3067 scp->sc->write_in_progress--; 3068 if (len) 3069 goto outloop; 3070 if (scp->sc->delayed_next_scr) 3071 switch_scr(scp->sc, scp->sc->delayed_next_scr - 1); 3072 } 3073 3074 static void 3075 draw_cursor_image(scr_stat *scp) 3076 { 3077 /* assert(scp == scp->sc->cur_scp); */ 3078 ++scp->sc->videoio_in_progress; 3079 (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, 3080 scp->sc->flags & SC_BLINK_CURSOR, TRUE, 3081 sc_inside_cutmark(scp, scp->cursor_pos)); 3082 --scp->sc->videoio_in_progress; 3083 } 3084 3085 static void 3086 remove_cursor_image(scr_stat *scp) 3087 { 3088 /* assert(scp == scp->sc->cur_scp); */ 3089 ++scp->sc->videoio_in_progress; 3090 (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, 3091 scp->sc->flags & SC_BLINK_CURSOR, FALSE, 3092 sc_inside_cutmark(scp, scp->cursor_oldpos)); 3093 --scp->sc->videoio_in_progress; 3094 } 3095 3096 static void 3097 update_cursor_image(scr_stat *scp) 3098 { 3099 int blink; 3100 3101 if (scp->sc->flags & SC_CHAR_CURSOR) { 3102 scp->cursor_base = scp->sc->cursor_base; 3103 scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size); 3104 } else { 3105 scp->cursor_base = 0; 3106 scp->cursor_height = scp->font_size; 3107 } 3108 blink = scp->sc->flags & SC_BLINK_CURSOR; 3109 3110 /* assert(scp == scp->sc->cur_scp); */ 3111 ++scp->sc->videoio_in_progress; 3112 (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, blink, FALSE, 3113 sc_inside_cutmark(scp, scp->cursor_pos)); 3114 (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, blink); 3115 (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE, 3116 sc_inside_cutmark(scp, scp->cursor_pos)); 3117 --scp->sc->videoio_in_progress; 3118 } 3119 3120 void 3121 sc_set_cursor_image(scr_stat *scp) 3122 { 3123 if (scp->sc->flags & SC_CHAR_CURSOR) { 3124 scp->cursor_base = scp->sc->cursor_base; 3125 scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size); 3126 } else { 3127 scp->cursor_base = 0; 3128 scp->cursor_height = scp->font_size; 3129 } 3130 3131 /* assert(scp == scp->sc->cur_scp); */ 3132 ++scp->sc->videoio_in_progress; 3133 (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, 3134 scp->sc->flags & SC_BLINK_CURSOR); 3135 --scp->sc->videoio_in_progress; 3136 } 3137 3138 static void 3139 move_crsr(scr_stat *scp, int x, int y) 3140 { 3141 if (x < 0) 3142 x = 0; 3143 if (y < 0) 3144 y = 0; 3145 if (x >= scp->xsize) 3146 x = scp->xsize-1; 3147 if (y >= scp->ysize) 3148 y = scp->ysize-1; 3149 scp->xpos = x; 3150 scp->ypos = y; 3151 scp->cursor_pos = scp->ypos * scp->xsize + scp->xpos; 3152 } 3153 3154 static void 3155 scinit(int unit, int flags) 3156 { 3157 /* 3158 * When syscons is being initialized as the kernel console, malloc() 3159 * is not yet functional, because various kernel structures has not been 3160 * fully initialized yet. Therefore, we need to declare the following 3161 * static buffers for the console. This is less than ideal, 3162 * but is necessry evil for the time being. XXX 3163 */ 3164 static scr_stat main_console; 3165 static scr_stat *main_vtys[MAXCONS]; 3166 static struct tty main_tty[MAXCONS]; 3167 static u_short sc_buffer[ROW*COL]; /* XXX */ 3168 #ifdef DEVFS 3169 static void *main_devfs_token[MAXCONS]; 3170 #endif 3171 #ifndef SC_NO_FONT_LOADING 3172 static u_char font_8[256*8]; 3173 static u_char font_14[256*14]; 3174 static u_char font_16[256*16]; 3175 #endif 3176 3177 sc_softc_t *sc; 3178 scr_stat *scp; 3179 video_adapter_t *adp; 3180 int col; 3181 int row; 3182 int i; 3183 3184 /* one time initialization */ 3185 if (init_done == COLD) { 3186 sc_get_bios_values(&bios_value); 3187 current_default = &user_default; 3188 /* kernel console attributes */ 3189 kernel_console.esc = 0; 3190 kernel_console.attr_mask = NORMAL_ATTR; 3191 kernel_console.cur_attr = 3192 kernel_console.cur_color = kernel_console.std_color = 3193 kernel_default.std_color; 3194 kernel_console.rev_color = kernel_default.rev_color; 3195 } 3196 init_done = WARM; 3197 3198 /* 3199 * Allocate resources. Even if we are being called for the second 3200 * time, we must allocate them again, because they might have 3201 * disappeared... 3202 */ 3203 sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE); 3204 adp = NULL; 3205 if (sc->adapter >= 0) { 3206 vid_release(sc->adp, (void *)&sc->adapter); 3207 adp = sc->adp; 3208 sc->adp = NULL; 3209 } 3210 if (sc->keyboard >= 0) { 3211 DPRINTF(5, ("sc%d: releasing kbd%d\n", unit, sc->keyboard)); 3212 i = kbd_release(sc->kbd, (void *)&sc->keyboard); 3213 DPRINTF(5, ("sc%d: kbd_release returned %d\n", unit, i)); 3214 if (sc->kbd != NULL) { 3215 DPRINTF(5, ("sc%d: kbd != NULL!, index:%d, minor:%d, flags:0x%x\n", 3216 unit, sc->kbd->kb_index, sc->kbd->kb_minor, sc->kbd->kb_flags)); 3217 } 3218 sc->kbd = NULL; 3219 } 3220 sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter); 3221 sc->adp = vid_get_adapter(sc->adapter); 3222 /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */ 3223 sc->keyboard = kbd_allocate("*", unit, (void *)&sc->keyboard, 3224 sckbdevent, sc); 3225 DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard)); 3226 sc->kbd = kbd_get_keyboard(sc->keyboard); 3227 if (sc->kbd != NULL) { 3228 DPRINTF(1, ("sc%d: kbd index:%d, minor:%d, flags:0x%x\n", 3229 unit, sc->kbd->kb_index, sc->kbd->kb_minor, sc->kbd->kb_flags)); 3230 } 3231 3232 if (!(sc->flags & SC_INIT_DONE) || (adp != sc->adp)) { 3233 3234 sc->initial_mode = sc->adp->va_initial_mode; 3235 3236 #ifndef SC_NO_FONT_LOADING 3237 if (flags & SC_KERNEL_CONSOLE) { 3238 sc->font_8 = font_8; 3239 sc->font_14 = font_14; 3240 sc->font_16 = font_16; 3241 } else if (sc->font_8 == NULL) { 3242 /* assert(sc_malloc) */ 3243 sc->font_8 = malloc(sizeof(font_8), M_DEVBUF, M_WAITOK); 3244 sc->font_14 = malloc(sizeof(font_14), M_DEVBUF, M_WAITOK); 3245 sc->font_16 = malloc(sizeof(font_16), M_DEVBUF, M_WAITOK); 3246 } 3247 #endif 3248 3249 /* extract the hardware cursor location and hide the cursor for now */ 3250 (*vidsw[sc->adapter]->read_hw_cursor)(sc->adp, &col, &row); 3251 (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, -1, -1); 3252 3253 /* set up the first console */ 3254 sc->first_vty = unit*MAXCONS; 3255 if (flags & SC_KERNEL_CONSOLE) { 3256 sc->vtys = sizeof(main_vtys)/sizeof(main_vtys[0]); 3257 sc->tty = main_tty; 3258 #ifdef DEVFS 3259 sc->devfs_token = main_devfs_token; 3260 #endif 3261 sc->console = main_vtys; 3262 scp = main_vtys[0] = &main_console; 3263 init_scp(sc, sc->first_vty, scp); 3264 sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize, 3265 (void *)sc_buffer, FALSE); 3266 } else { 3267 /* assert(sc_malloc) */ 3268 sc->vtys = MAXCONS; 3269 sc->tty = malloc(sizeof(struct tty)*MAXCONS, M_DEVBUF, M_WAITOK); 3270 bzero(sc->tty, sizeof(struct tty)*MAXCONS); 3271 #ifdef DEVFS 3272 sc->devfs_token = malloc(sizeof(void *)*MAXCONS, 3273 M_DEVBUF, M_WAITOK); 3274 #endif 3275 sc->console = malloc(sizeof(struct scr_stat *)*MAXCONS, 3276 M_DEVBUF, M_WAITOK); 3277 scp = sc->console[0] = alloc_scp(sc, sc->first_vty); 3278 } 3279 sc->cur_scp = scp; 3280 3281 /* copy screen to temporary buffer */ 3282 sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize, 3283 (void *)scp->sc->adp->va_window, FALSE); 3284 if (ISTEXTSC(scp)) 3285 sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize); 3286 3287 /* move cursors to the initial positions */ 3288 scp->mouse_pos = scp->mouse_oldpos = 0; 3289 if (col >= scp->xsize) 3290 col = 0; 3291 if (row >= scp->ysize) 3292 row = scp->ysize - 1; 3293 scp->xpos = col; 3294 scp->ypos = row; 3295 scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col; 3296 if (bios_value.cursor_end < scp->font_size) 3297 sc->cursor_base = scp->font_size - bios_value.cursor_end - 1; 3298 else 3299 sc->cursor_base = 0; 3300 i = bios_value.cursor_end - bios_value.cursor_start + 1; 3301 sc->cursor_height = imin(i, scp->font_size); 3302 if (!ISGRAPHSC(scp)) { 3303 sc_set_cursor_image(scp); 3304 draw_cursor_image(scp); 3305 } 3306 3307 /* save font and palette */ 3308 #ifndef SC_NO_FONT_LOADING 3309 sc->fonts_loaded = 0; 3310 if (ISFONTAVAIL(sc->adp->va_flags)) { 3311 #ifdef SC_DFLT_FONT 3312 bcopy(dflt_font_8, sc->font_8, sizeof(dflt_font_8)); 3313 bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14)); 3314 bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16)); 3315 sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8; 3316 if (scp->font_size < 14) { 3317 copy_font(scp, LOAD, 8, sc->font_8); 3318 } else if (scp->font_size >= 16) { 3319 copy_font(scp, LOAD, 16, sc->font_16); 3320 } else { 3321 copy_font(scp, LOAD, 14, sc->font_14); 3322 } 3323 #else /* !SC_DFLT_FONT */ 3324 if (scp->font_size < 14) { 3325 copy_font(scp, SAVE, 8, sc->font_8); 3326 sc->fonts_loaded = FONT_8; 3327 } else if (scp->font_size >= 16) { 3328 copy_font(scp, SAVE, 16, sc->font_16); 3329 sc->fonts_loaded = FONT_16; 3330 } else { 3331 copy_font(scp, SAVE, 14, sc->font_14); 3332 sc->fonts_loaded = FONT_14; 3333 } 3334 #endif /* SC_DFLT_FONT */ 3335 /* FONT KLUDGE: always use the font page #0. XXX */ 3336 (*vidsw[sc->adapter]->show_font)(sc->adp, 0); 3337 } 3338 #endif /* !SC_NO_FONT_LOADING */ 3339 3340 #ifndef SC_NO_PALETTE_LOADING 3341 save_palette(sc->adp, sc->palette); 3342 #endif 3343 3344 #if NSPLASH > 0 3345 if (!(sc->flags & SC_SPLASH_SCRN) && (flags & SC_KERNEL_CONSOLE)) { 3346 /* we are ready to put up the splash image! */ 3347 splash_init(sc->adp, scsplash_callback, sc); 3348 sc->flags |= SC_SPLASH_SCRN; 3349 } 3350 #endif /* NSPLASH */ 3351 } 3352 3353 /* the rest is not necessary, if we have done it once */ 3354 if (sc->flags & SC_INIT_DONE) 3355 return; 3356 3357 /* clear structures */ 3358 for (i = 1; i < sc->vtys; i++) 3359 sc->console[i] = NULL; 3360 3361 /* initialize mapscrn arrays to a one to one map */ 3362 for (i = 0; i < sizeof(sc->scr_map); i++) 3363 sc->scr_map[i] = sc->scr_rmap[i] = i; 3364 3365 sc->flags |= SC_INIT_DONE; 3366 } 3367 3368 #if __i386__ 3369 static void 3370 scterm(int unit, int flags) 3371 { 3372 sc_softc_t *sc; 3373 3374 sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE); 3375 if (sc == NULL) 3376 return; /* shouldn't happen */ 3377 3378 #if NSPLASH > 0 3379 /* this console is no longer available for the splash screen */ 3380 if (sc->flags & SC_SPLASH_SCRN) { 3381 splash_term(sc->adp); 3382 sc->flags &= ~SC_SPLASH_SCRN; 3383 } 3384 #endif /* NSPLASH */ 3385 3386 #if 0 /* XXX */ 3387 /* move the hardware cursor to the upper-left corner */ 3388 (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, 0, 0); 3389 #endif 3390 3391 /* release the keyboard and the video card */ 3392 if (sc->keyboard >= 0) 3393 kbd_release(sc->kbd, &sc->keyboard); 3394 if (sc->adapter >= 0) 3395 vid_release(sc->adp, &sc->adapter); 3396 3397 /* clear the structure */ 3398 if (!(flags & SC_KERNEL_CONSOLE)) { 3399 free(sc->console, M_DEVBUF); 3400 free(sc->tty, M_DEVBUF); 3401 #ifdef DEVFS 3402 free(sc->devfs_token, M_DEVBUF); 3403 #endif 3404 #ifndef SC_NO_FONT_LOADING 3405 free(sc->font_8, M_DEVBUF); 3406 free(sc->font_14, M_DEVBUF); 3407 free(sc->font_16, M_DEVBUF); 3408 #endif 3409 /* XXX vtb, history */ 3410 } 3411 bzero(sc, sizeof(*sc)); 3412 sc->keyboard = -1; 3413 sc->adapter = -1; 3414 } 3415 #endif 3416 3417 static void 3418 scshutdown(int howto, void *arg) 3419 { 3420 /* assert(sc_console != NULL) */ 3421 3422 sc_touch_scrn_saver(); 3423 if (!cold && sc_console 3424 && sc_console->sc->cur_scp->smode.mode == VT_AUTO 3425 && sc_console->smode.mode == VT_AUTO) 3426 switch_scr(sc_console->sc, sc_console->index); 3427 shutdown_in_progress = TRUE; 3428 } 3429 3430 int 3431 sc_clean_up(scr_stat *scp) 3432 { 3433 #if NSPLASH > 0 3434 int error; 3435 #endif /* NSPLASH */ 3436 3437 sc_touch_scrn_saver(); 3438 #if NSPLASH > 0 3439 if ((error = wait_scrn_saver_stop(scp->sc))) 3440 return error; 3441 #endif /* NSPLASH */ 3442 scp->status &= ~MOUSE_VISIBLE; 3443 sc_remove_cutmarking(scp); 3444 return 0; 3445 } 3446 3447 void 3448 sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard) 3449 { 3450 sc_vtb_t new; 3451 sc_vtb_t old; 3452 int s; 3453 3454 old = scp->vtb; 3455 sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait); 3456 if (!discard && (old.vtb_flags & VTB_VALID)) { 3457 /* retain the current cursor position and buffer contants */ 3458 scp->cursor_oldpos = scp->cursor_pos; 3459 /* 3460 * This works only if the old buffer has the same size as or larger 3461 * than the new one. XXX 3462 */ 3463 sc_vtb_copy(&old, 0, &new, 0, scp->xsize*scp->ysize); 3464 scp->vtb = new; 3465 } else { 3466 /* clear the screen and move the text cursor to the top-left position */ 3467 s = splhigh(); 3468 scp->vtb = new; 3469 sc_clear_screen(scp); 3470 splx(s); 3471 sc_vtb_destroy(&old); 3472 } 3473 3474 #ifndef SC_NO_SYSMOUSE 3475 /* move the mouse cursor at the center of the screen */ 3476 sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 3477 #endif 3478 } 3479 3480 static scr_stat 3481 *alloc_scp(sc_softc_t *sc, int vty) 3482 { 3483 scr_stat *scp; 3484 3485 /* assert(sc_malloc) */ 3486 3487 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3488 init_scp(sc, vty, scp); 3489 3490 sc_alloc_scr_buffer(scp, TRUE, TRUE); 3491 3492 #ifndef SC_NO_SYSMOUSE 3493 if (ISMOUSEAVAIL(sc->adp->va_flags)) 3494 sc_alloc_cut_buffer(scp, TRUE); 3495 #endif 3496 3497 #ifndef SC_NO_HISTORY 3498 sc_alloc_history_buffer(scp, 0, 0, TRUE); 3499 #endif 3500 3501 sc_clear_screen(scp); 3502 return scp; 3503 } 3504 3505 static void 3506 init_scp(sc_softc_t *sc, int vty, scr_stat *scp) 3507 { 3508 video_info_t info; 3509 3510 scp->index = vty; 3511 scp->sc = sc; 3512 scp->status = 0; 3513 scp->mode = sc->initial_mode; 3514 (*vidsw[sc->adapter]->get_info)(sc->adp, scp->mode, &info); 3515 if (info.vi_flags & V_INFO_GRAPHICS) { 3516 scp->status |= GRAPHICS_MODE; 3517 scp->xpixel = info.vi_width; 3518 scp->ypixel = info.vi_height; 3519 scp->xsize = info.vi_width/8; 3520 scp->ysize = info.vi_height/info.vi_cheight; 3521 scp->font_size = FONT_NONE; 3522 scp->font = NULL; 3523 } else { 3524 scp->xsize = info.vi_width; 3525 scp->ysize = info.vi_height; 3526 scp->xpixel = scp->xsize*8; 3527 scp->ypixel = scp->ysize*info.vi_cheight; 3528 if (info.vi_cheight < 14) { 3529 scp->font_size = 8; 3530 #ifndef SC_NO_FONT_LOADING 3531 scp->font = sc->font_8; 3532 #else 3533 scp->font = NULL; 3534 #endif 3535 } else if (info.vi_cheight >= 16) { 3536 scp->font_size = 16; 3537 #ifndef SC_NO_FONT_LOADING 3538 scp->font = sc->font_16; 3539 #else 3540 scp->font = NULL; 3541 #endif 3542 } else { 3543 scp->font_size = 14; 3544 #ifndef SC_NO_FONT_LOADING 3545 scp->font = sc->font_14; 3546 #else 3547 scp->font = NULL; 3548 #endif 3549 } 3550 } 3551 sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE); 3552 sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE); 3553 scp->xoff = scp->yoff = 0; 3554 scp->xpos = scp->ypos = 0; 3555 scp->saved_xpos = scp->saved_ypos = -1; 3556 scp->start = scp->xsize * scp->ysize - 1; 3557 scp->end = 0; 3558 scp->term.esc = 0; 3559 scp->term.attr_mask = NORMAL_ATTR; 3560 scp->term.cur_attr = 3561 scp->term.cur_color = scp->term.std_color = 3562 current_default->std_color; 3563 scp->term.rev_color = current_default->rev_color; 3564 scp->border = BG_BLACK; 3565 scp->cursor_base = sc->cursor_base; 3566 scp->cursor_height = imin(sc->cursor_height, scp->font_size); 3567 scp->mouse_xpos = scp->xoff*8 + scp->xsize*8/2; 3568 scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size/2; 3569 scp->mouse_cut_start = scp->xsize*scp->ysize; 3570 scp->mouse_cut_end = -1; 3571 scp->mouse_signal = 0; 3572 scp->mouse_pid = 0; 3573 scp->mouse_proc = NULL; 3574 scp->kbd_mode = K_XLATE; 3575 scp->bell_pitch = bios_value.bell_pitch; 3576 scp->bell_duration = BELL_DURATION; 3577 scp->status |= (bios_value.shift_state & NLKED); 3578 scp->status |= CURSOR_ENABLED; 3579 scp->pid = 0; 3580 scp->proc = NULL; 3581 scp->smode.mode = VT_AUTO; 3582 scp->history = NULL; 3583 scp->history_pos = 0; 3584 scp->history_size = 0; 3585 3586 /* what if the following call fails... XXX */ 3587 scp->rndr = sc_render_match(scp, scp->sc->adp, 3588 scp->status & (GRAPHICS_MODE | PIXEL_MODE)); 3589 } 3590 3591 /* 3592 * scgetc(flags) - get character from keyboard. 3593 * If flags & SCGETC_CN, then avoid harmful side effects. 3594 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3595 * return NOKEY if there is nothing there. 3596 */ 3597 static u_int 3598 scgetc(sc_softc_t *sc, u_int flags) 3599 { 3600 scr_stat *scp; 3601 struct tty *tp; 3602 u_int c; 3603 int this_scr; 3604 int f; 3605 int i; 3606 3607 if (sc->kbd == NULL) 3608 return NOKEY; 3609 3610 next_code: 3611 #if 1 3612 /* I don't like this, but... XXX */ 3613 if (flags & SCGETC_CN) 3614 sccnupdate(sc->cur_scp); 3615 #endif 3616 scp = sc->cur_scp; 3617 /* first see if there is something in the keyboard port */ 3618 for (;;) { 3619 c = kbd_read_char(sc->kbd, !(flags & SCGETC_NONBLOCK)); 3620 if (c == ERRKEY) { 3621 if (!(flags & SCGETC_CN)) 3622 do_bell(scp, bios_value.bell_pitch, BELL_DURATION); 3623 } else if (c == NOKEY) 3624 return c; 3625 else 3626 break; 3627 } 3628 3629 /* make screensaver happy */ 3630 if (!(c & RELKEY)) 3631 sc_touch_scrn_saver(); 3632 3633 #ifdef __i386__ 3634 if (!(flags & SCGETC_CN)) 3635 /* do the /dev/random device a favour */ 3636 add_keyboard_randomness(c); 3637 #endif 3638 3639 if (scp->kbd_mode != K_XLATE) 3640 return KEYCHAR(c); 3641 3642 /* if scroll-lock pressed allow history browsing */ 3643 if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) { 3644 3645 scp->status &= ~CURSOR_ENABLED; 3646 remove_cursor_image(scp); 3647 3648 #ifndef SC_NO_HISTORY 3649 if (!(scp->status & BUFFER_SAVED)) { 3650 scp->status |= BUFFER_SAVED; 3651 sc_hist_save(scp); 3652 } 3653 switch (c) { 3654 /* FIXME: key codes */ 3655 case SPCLKEY | FKEY | F(49): /* home key */ 3656 sc_remove_cutmarking(scp); 3657 sc_hist_home(scp); 3658 goto next_code; 3659 3660 case SPCLKEY | FKEY | F(57): /* end key */ 3661 sc_remove_cutmarking(scp); 3662 sc_hist_end(scp); 3663 goto next_code; 3664 3665 case SPCLKEY | FKEY | F(50): /* up arrow key */ 3666 sc_remove_cutmarking(scp); 3667 if (sc_hist_up_line(scp)) 3668 if (!(flags & SCGETC_CN)) 3669 do_bell(scp, bios_value.bell_pitch, BELL_DURATION); 3670 goto next_code; 3671 3672 case SPCLKEY | FKEY | F(58): /* down arrow key */ 3673 sc_remove_cutmarking(scp); 3674 if (sc_hist_down_line(scp)) 3675 if (!(flags & SCGETC_CN)) 3676 do_bell(scp, bios_value.bell_pitch, BELL_DURATION); 3677 goto next_code; 3678 3679 case SPCLKEY | FKEY | F(51): /* page up key */ 3680 sc_remove_cutmarking(scp); 3681 for (i=0; i<scp->ysize; i++) 3682 if (sc_hist_up_line(scp)) { 3683 if (!(flags & SCGETC_CN)) 3684 do_bell(scp, bios_value.bell_pitch, BELL_DURATION); 3685 break; 3686 } 3687 goto next_code; 3688 3689 case SPCLKEY | FKEY | F(59): /* page down key */ 3690 sc_remove_cutmarking(scp); 3691 for (i=0; i<scp->ysize; i++) 3692 if (sc_hist_down_line(scp)) { 3693 if (!(flags & SCGETC_CN)) 3694 do_bell(scp, bios_value.bell_pitch, BELL_DURATION); 3695 break; 3696 } 3697 goto next_code; 3698 } 3699 #endif /* SC_NO_HISTORY */ 3700 } 3701 3702 /* 3703 * Process and consume special keys here. Return a plain char code 3704 * or a char code with the META flag or a function key code. 3705 */ 3706 if (c & RELKEY) { 3707 /* key released */ 3708 /* goto next_code */ 3709 } else { 3710 /* key pressed */ 3711 if (c & SPCLKEY) { 3712 c &= ~SPCLKEY; 3713 switch (KEYCHAR(c)) { 3714 /* LOCKING KEYS */ 3715 case NLK: case CLK: case ALK: 3716 break; 3717 case SLK: 3718 kbd_ioctl(sc->kbd, KDGKBSTATE, (caddr_t)&f); 3719 if (f & SLKED) { 3720 scp->status |= SLKED; 3721 } else { 3722 if (scp->status & SLKED) { 3723 scp->status &= ~SLKED; 3724 #ifndef SC_NO_HISTORY 3725 if (scp->status & BUFFER_SAVED) { 3726 if (!sc_hist_restore(scp)) 3727 sc_remove_cutmarking(scp); 3728 scp->status &= ~BUFFER_SAVED; 3729 scp->status |= CURSOR_ENABLED; 3730 draw_cursor_image(scp); 3731 } 3732 tp = VIRTUAL_TTY(sc, scp->index); 3733 if (tp->t_state & TS_ISOPEN) 3734 scstart(tp); 3735 #endif 3736 } 3737 } 3738 break; 3739 3740 /* NON-LOCKING KEYS */ 3741 case NOP: 3742 case LSH: case RSH: case LCTR: case RCTR: 3743 case LALT: case RALT: case ASH: case META: 3744 break; 3745 3746 case BTAB: 3747 if (!(sc->flags & SC_SCRN_BLANKED)) 3748 return c; 3749 break; 3750 3751 case SPSC: 3752 #if NSPLASH > 0 3753 /* force activatation/deactivation of the screen saver */ 3754 if (!(sc->flags & SC_SCRN_BLANKED)) { 3755 run_scrn_saver = TRUE; 3756 sc->scrn_time_stamp -= scrn_blank_time; 3757 } 3758 if (cold) { 3759 /* 3760 * While devices are being probed, the screen saver need 3761 * to be invoked explictly. XXX 3762 */ 3763 if (sc->flags & SC_SCRN_BLANKED) { 3764 scsplash_stick(FALSE); 3765 stop_scrn_saver(sc, current_saver); 3766 } else { 3767 if (!ISGRAPHSC(scp)) { 3768 scsplash_stick(TRUE); 3769 (*current_saver)(sc, TRUE); 3770 } 3771 } 3772 } 3773 #endif /* NSPLASH */ 3774 break; 3775 3776 case RBT: 3777 #ifndef SC_DISABLE_REBOOT 3778 shutdown_nice(); 3779 #endif 3780 break; 3781 3782 #if NAPM > 0 3783 case SUSP: 3784 apm_suspend(PMST_SUSPEND); 3785 break; 3786 case STBY: 3787 apm_suspend(PMST_STANDBY); 3788 break; 3789 #else 3790 case SUSP: 3791 case STBY: 3792 break; 3793 #endif 3794 3795 case DBG: 3796 #ifndef SC_DISABLE_DDBKEY 3797 #ifdef DDB 3798 if (debugger) 3799 break; 3800 /* try to switch to the kernel console screen */ 3801 if (sc_console) { 3802 /* 3803 * TRY to make sure the screen saver is stopped, 3804 * and the screen is updated before switching to 3805 * the vty0. 3806 */ 3807 scrn_timer(NULL); 3808 if (!cold 3809 && sc_console->sc->cur_scp->smode.mode == VT_AUTO 3810 && sc_console->smode.mode == VT_AUTO) 3811 switch_scr(sc_console->sc, sc_console->index); 3812 } 3813 Debugger("manual escape to debugger"); 3814 #else 3815 printf("No debugger in kernel\n"); 3816 #endif 3817 #else /* SC_DISABLE_DDBKEY */ 3818 /* do nothing */ 3819 #endif /* SC_DISABLE_DDBKEY */ 3820 break; 3821 3822 case NEXT: 3823 this_scr = scp->index; 3824 for (i = (this_scr - sc->first_vty + 1)%sc->vtys; 3825 sc->first_vty + i != this_scr; 3826 i = (i + 1)%sc->vtys) { 3827 struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i); 3828 if (tp->t_state & TS_ISOPEN) { 3829 switch_scr(scp->sc, sc->first_vty + i); 3830 break; 3831 } 3832 } 3833 break; 3834 3835 case PREV: 3836 this_scr = scp->index; 3837 for (i = (this_scr - sc->first_vty + sc->vtys - 1)%sc->vtys; 3838 sc->first_vty + i != this_scr; 3839 i = (i + sc->vtys - 1)%sc->vtys) { 3840 struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i); 3841 if (tp->t_state & TS_ISOPEN) { 3842 switch_scr(scp->sc, sc->first_vty + i); 3843 break; 3844 } 3845 } 3846 break; 3847 3848 default: 3849 if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) { 3850 switch_scr(scp->sc, sc->first_vty + KEYCHAR(c) - F_SCR); 3851 break; 3852 } 3853 /* assert(c & FKEY) */ 3854 if (!(sc->flags & SC_SCRN_BLANKED)) 3855 return c; 3856 break; 3857 } 3858 /* goto next_code */ 3859 } else { 3860 /* regular keys (maybe MKEY is set) */ 3861 if (!(sc->flags & SC_SCRN_BLANKED)) 3862 return c; 3863 } 3864 } 3865 3866 goto next_code; 3867 } 3868 3869 int 3870 scmmap(dev_t dev, vm_offset_t offset, int nprot) 3871 { 3872 struct tty *tp; 3873 struct scr_stat *scp; 3874 3875 tp = scdevtotty(dev); 3876 if (!tp) 3877 return ENXIO; 3878 scp = sc_get_scr_stat(tp->t_dev); 3879 return (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, offset, nprot); 3880 } 3881 3882 /* 3883 * Calculate hardware attributes word using logical attributes mask and 3884 * hardware colors 3885 */ 3886 3887 static int 3888 mask2attr(struct term_stat *term) 3889 { 3890 int attr, mask = term->attr_mask; 3891 3892 if (mask & REVERSE_ATTR) { 3893 attr = ((mask & FOREGROUND_CHANGED) ? 3894 ((term->cur_color & 0xF000) >> 4) : 3895 (term->rev_color & 0x0F00)) | 3896 ((mask & BACKGROUND_CHANGED) ? 3897 ((term->cur_color & 0x0F00) << 4) : 3898 (term->rev_color & 0xF000)); 3899 } else 3900 attr = term->cur_color; 3901 3902 /* XXX: underline mapping for Hercules adapter can be better */ 3903 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3904 attr ^= 0x0800; 3905 if (mask & BLINK_ATTR) 3906 attr ^= 0x8000; 3907 3908 return attr; 3909 } 3910 3911 static int 3912 save_kbd_state(scr_stat *scp) 3913 { 3914 int state; 3915 int error; 3916 3917 error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state); 3918 if (error == ENOIOCTL) 3919 error = ENODEV; 3920 if (error == 0) { 3921 scp->status &= ~LOCK_MASK; 3922 scp->status |= state; 3923 } 3924 return error; 3925 } 3926 3927 static int 3928 update_kbd_state(scr_stat *scp, int new_bits, int mask) 3929 { 3930 int state; 3931 int error; 3932 3933 if (mask != LOCK_MASK) { 3934 error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state); 3935 if (error == ENOIOCTL) 3936 error = ENODEV; 3937 if (error) 3938 return error; 3939 state &= ~mask; 3940 state |= new_bits & mask; 3941 } else { 3942 state = new_bits & LOCK_MASK; 3943 } 3944 error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state); 3945 if (error == ENOIOCTL) 3946 error = ENODEV; 3947 return error; 3948 } 3949 3950 static int 3951 update_kbd_leds(scr_stat *scp, int which) 3952 { 3953 int error; 3954 3955 which &= LOCK_MASK; 3956 error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which); 3957 if (error == ENOIOCTL) 3958 error = ENODEV; 3959 return error; 3960 } 3961 3962 int 3963 set_mode(scr_stat *scp) 3964 { 3965 video_info_t info; 3966 3967 /* reject unsupported mode */ 3968 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) 3969 return 1; 3970 3971 /* if this vty is not currently showing, do nothing */ 3972 if (scp != scp->sc->cur_scp) 3973 return 0; 3974 3975 /* setup video hardware for the given mode */ 3976 (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode); 3977 sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize, 3978 (void *)scp->sc->adp->va_window, FALSE); 3979 3980 #ifndef SC_NO_FONT_LOADING 3981 /* load appropriate font */ 3982 if (!(scp->status & GRAPHICS_MODE)) { 3983 if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) { 3984 if (scp->font_size < 14) { 3985 if (scp->sc->fonts_loaded & FONT_8) 3986 copy_font(scp, LOAD, 8, scp->sc->font_8); 3987 } else if (scp->font_size >= 16) { 3988 if (scp->sc->fonts_loaded & FONT_16) 3989 copy_font(scp, LOAD, 16, scp->sc->font_16); 3990 } else { 3991 if (scp->sc->fonts_loaded & FONT_14) 3992 copy_font(scp, LOAD, 14, scp->sc->font_14); 3993 } 3994 /* 3995 * FONT KLUDGE: 3996 * This is an interim kludge to display correct font. 3997 * Always use the font page #0 on the video plane 2. 3998 * Somehow we cannot show the font in other font pages on 3999 * some video cards... XXX 4000 */ 4001 (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, 0); 4002 } 4003 mark_all(scp); 4004 } 4005 #endif /* !SC_NO_FONT_LOADING */ 4006 4007 set_border(scp, scp->border); 4008 sc_set_cursor_image(scp); 4009 4010 return 0; 4011 } 4012 4013 void 4014 set_border(scr_stat *scp, int color) 4015 { 4016 ++scp->sc->videoio_in_progress; 4017 (*scp->rndr->draw_border)(scp, color); 4018 --scp->sc->videoio_in_progress; 4019 } 4020 4021 #ifndef SC_NO_FONT_LOADING 4022 void 4023 copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) 4024 { 4025 /* 4026 * FONT KLUDGE: 4027 * This is an interim kludge to display correct font. 4028 * Always use the font page #0 on the video plane 2. 4029 * Somehow we cannot show the font in other font pages on 4030 * some video cards... XXX 4031 */ 4032 scp->sc->font_loading_in_progress = TRUE; 4033 if (operation == LOAD) { 4034 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, font_size, 4035 buf, 0, 256); 4036 } else if (operation == SAVE) { 4037 (*vidsw[scp->sc->adapter]->save_font)(scp->sc->adp, 0, font_size, 4038 buf, 0, 256); 4039 } 4040 scp->sc->font_loading_in_progress = FALSE; 4041 } 4042 #endif /* !SC_NO_FONT_LOADING */ 4043 4044 #ifndef SC_NO_SYSMOUSE 4045 struct tty 4046 *sc_get_mouse_tty(void) 4047 { 4048 return MOUSE_TTY; 4049 } 4050 #endif /* !SC_NO_SYSMOUSE */ 4051 4052 #ifndef SC_NO_CUTPASTE 4053 void 4054 sc_paste(scr_stat *scp, u_char *p, int count) 4055 { 4056 struct tty *tp; 4057 u_char *rmap; 4058 4059 if (scp->status & MOUSE_VISIBLE) { 4060 tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index); 4061 rmap = scp->sc->scr_rmap; 4062 for (; count > 0; --count) 4063 (*linesw[tp->t_line].l_rint)(rmap[*p++], tp); 4064 } 4065 } 4066 #endif /* SC_NO_CUTPASTE */ 4067 4068 static void 4069 do_bell(scr_stat *scp, int pitch, int duration) 4070 { 4071 if (cold || shutdown_in_progress) 4072 return; 4073 4074 if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) 4075 return; 4076 4077 if (scp->sc->flags & SC_VISUAL_BELL) { 4078 if (scp->sc->blink_in_progress) 4079 return; 4080 scp->sc->blink_in_progress = 3; 4081 if (scp != scp->sc->cur_scp) 4082 scp->sc->blink_in_progress += 2; 4083 blink_screen(scp->sc->cur_scp); 4084 } else { 4085 if (scp != scp->sc->cur_scp) 4086 pitch *= 2; 4087 sysbeep(pitch, duration); 4088 } 4089 } 4090 4091 static void 4092 blink_screen(void *arg) 4093 { 4094 scr_stat *scp = arg; 4095 struct tty *tp; 4096 4097 if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) { 4098 scp->sc->blink_in_progress = 0; 4099 mark_all(scp); 4100 tp = VIRTUAL_TTY(scp->sc, scp->index); 4101 if (tp->t_state & TS_ISOPEN) 4102 scstart(tp); 4103 if (scp->sc->delayed_next_scr) 4104 switch_scr(scp->sc, scp->sc->delayed_next_scr - 1); 4105 } 4106 else { 4107 (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize, 4108 scp->sc->blink_in_progress & 1); 4109 scp->sc->blink_in_progress--; 4110 timeout(blink_screen, scp, hz / 10); 4111 } 4112 } 4113 4114 #endif /* NSC */ 4115