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