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