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