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