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