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