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