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