1 /* $NetBSD: wsdisplay.c,v 1.103 2006/10/13 16:53:35 dogcow Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Christopher G. Demetriou 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.103 2006/10/13 16:53:35 dogcow Exp $"); 35 36 #include "opt_wsdisplay_compat.h" 37 #include "opt_wsmsgattrs.h" 38 #include "opt_compat_netbsd.h" 39 #include "wskbd.h" 40 #include "wsmux.h" 41 #include "wsdisplay.h" 42 43 #include <sys/param.h> 44 #include <sys/conf.h> 45 #include <sys/device.h> 46 #include <sys/ioctl.h> 47 #include <sys/poll.h> 48 #include <sys/kernel.h> 49 #include <sys/proc.h> 50 #include <sys/malloc.h> 51 #include <sys/syslog.h> 52 #include <sys/systm.h> 53 #include <sys/tty.h> 54 #include <sys/signalvar.h> 55 #include <sys/errno.h> 56 #include <sys/fcntl.h> 57 #include <sys/vnode.h> 58 #include <sys/kauth.h> 59 60 #include <dev/wscons/wseventvar.h> 61 #include <dev/wscons/wsmuxvar.h> 62 #include <dev/wscons/wsconsio.h> 63 #include <dev/wscons/wsdisplayvar.h> 64 #include <dev/wscons/wsksymvar.h> 65 #include <dev/wscons/wsksymdef.h> 66 #include <dev/wscons/wsemulvar.h> 67 #include <dev/wscons/wscons_callbacks.h> 68 #include <dev/cons.h> 69 70 struct wsscreen_internal { 71 const struct wsdisplay_emulops *emulops; 72 void *emulcookie; 73 74 const struct wsscreen_descr *scrdata; 75 76 const struct wsemul_ops *wsemul; 77 void *wsemulcookie; 78 }; 79 80 struct wsscreen { 81 struct wsscreen_internal *scr_dconf; 82 83 struct tty *scr_tty; 84 int scr_hold_screen; /* hold tty output */ 85 86 int scr_flags; 87 #define SCR_OPEN 1 /* is it open? */ 88 #define SCR_WAITACTIVE 2 /* someone waiting on activation */ 89 #define SCR_GRAPHICS 4 /* graphics mode, no text (emulation) output */ 90 #define SCR_DUMBFB 8 /* in use as a dumb fb (iff SCR_GRAPHICS) */ 91 const struct wscons_syncops *scr_syncops; 92 void *scr_synccookie; 93 94 #ifdef WSDISPLAY_COMPAT_RAWKBD 95 int scr_rawkbd; 96 #endif 97 98 struct wsdisplay_softc *sc; 99 }; 100 101 struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, 102 const char *, 103 const struct wsscreen_descr *, void *, 104 int, int, long); 105 void wsscreen_detach(struct wsscreen *); 106 int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *, const char *); 107 static void wsdisplay_shutdownhook(void *); 108 static void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int); 109 static void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *); 110 int wsdisplay_delscreen(struct wsdisplay_softc *, int, int); 111 112 #define WSDISPLAY_MAXSCREEN 8 113 114 struct wsdisplay_softc { 115 struct device sc_dv; 116 117 const struct wsdisplay_accessops *sc_accessops; 118 void *sc_accesscookie; 119 120 const struct wsscreen_list *sc_scrdata; 121 #ifdef WSDISPLAY_SCROLLSUPPORT 122 struct wsdisplay_scroll_data sc_scroll_values; 123 #endif 124 125 struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN]; 126 int sc_focusidx; /* available only if sc_focus isn't null */ 127 struct wsscreen *sc_focus; 128 129 struct wseventvar evar; 130 131 int sc_isconsole; 132 133 int sc_flags; 134 #define SC_SWITCHPENDING 1 135 int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */ 136 137 #if NWSKBD > 0 138 struct wsevsrc *sc_input; 139 #ifdef WSDISPLAY_COMPAT_RAWKBD 140 int sc_rawkbd; 141 #endif 142 #endif /* NWSKBD > 0 */ 143 }; 144 145 #ifdef WSDISPLAY_SCROLLSUPPORT 146 147 struct wsdisplay_scroll_data wsdisplay_default_scroll_values = { 148 WSDISPLAY_SCROLL_DOALL, 149 25, 150 2, 151 }; 152 #endif 153 154 extern struct cfdriver wsdisplay_cd; 155 156 /* Autoconfiguration definitions. */ 157 static int wsdisplay_emul_match(struct device *, struct cfdata *, void *); 158 static void wsdisplay_emul_attach(struct device *, struct device *, void *); 159 static int wsdisplay_noemul_match(struct device *, struct cfdata *, void *); 160 static void wsdisplay_noemul_attach(struct device *, struct device *, void *); 161 162 CFATTACH_DECL(wsdisplay_emul, sizeof (struct wsdisplay_softc), 163 wsdisplay_emul_match, wsdisplay_emul_attach, NULL, NULL); 164 165 CFATTACH_DECL(wsdisplay_noemul, sizeof (struct wsdisplay_softc), 166 wsdisplay_noemul_match, wsdisplay_noemul_attach, NULL, NULL); 167 168 dev_type_open(wsdisplayopen); 169 dev_type_close(wsdisplayclose); 170 dev_type_read(wsdisplayread); 171 dev_type_write(wsdisplaywrite); 172 dev_type_ioctl(wsdisplayioctl); 173 dev_type_stop(wsdisplaystop); 174 dev_type_tty(wsdisplaytty); 175 dev_type_poll(wsdisplaypoll); 176 dev_type_mmap(wsdisplaymmap); 177 dev_type_kqfilter(wsdisplaykqfilter); 178 179 const struct cdevsw wsdisplay_cdevsw = { 180 wsdisplayopen, wsdisplayclose, wsdisplayread, wsdisplaywrite, 181 wsdisplayioctl, wsdisplaystop, wsdisplaytty, wsdisplaypoll, 182 wsdisplaymmap, wsdisplaykqfilter, D_TTY 183 }; 184 185 static void wsdisplaystart(struct tty *); 186 static int wsdisplayparam(struct tty *, struct termios *); 187 188 189 #define WSDISPLAYUNIT(dev) (minor(dev) >> 8) 190 #define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff) 191 #define ISWSDISPLAYSTAT(dev) (WSDISPLAYSCREEN(dev) == 254) 192 #define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255) 193 #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen)) 194 195 #define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL) 196 #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL) 197 198 static void wsdisplay_common_attach(struct wsdisplay_softc *sc, 199 int console, int kbdmux, const struct wsscreen_list *, 200 const struct wsdisplay_accessops *accessops, 201 void *accesscookie); 202 203 #ifdef WSDISPLAY_COMPAT_RAWKBD 204 int wsdisplay_update_rawkbd(struct wsdisplay_softc *, 205 struct wsscreen *); 206 #endif 207 208 static int wsdisplay_console_initted; 209 static int wsdisplay_console_attached; 210 static struct wsdisplay_softc *wsdisplay_console_device; 211 static struct wsscreen_internal wsdisplay_console_conf; 212 213 static int wsdisplay_getc_dummy(dev_t); 214 static void wsdisplay_pollc(dev_t, int); 215 216 static int wsdisplay_cons_pollmode; 217 static void (*wsdisplay_cons_kbd_pollc)(dev_t, int); 218 219 static struct consdev wsdisplay_cons = { 220 NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, 221 wsdisplay_pollc, NULL, NULL, NULL, NODEV, CN_NORMAL 222 }; 223 224 #ifndef WSDISPLAY_DEFAULTSCREENS 225 # define WSDISPLAY_DEFAULTSCREENS 0 226 #endif 227 int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; 228 229 int wsdisplay_switch1(void *, int, int); 230 int wsdisplay_switch2(void *, int, int); 231 int wsdisplay_switch3(void *, int, int); 232 233 int wsdisplay_clearonclose; 234 235 struct wsscreen * 236 wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul, 237 const struct wsscreen_descr *type, void *cookie, int ccol, 238 int crow, long defattr) 239 { 240 struct wsscreen_internal *dconf; 241 struct wsscreen *scr; 242 243 scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_WAITOK); 244 if (!scr) 245 return (NULL); 246 247 if (console) { 248 dconf = &wsdisplay_console_conf; 249 /* 250 * If there's an emulation, tell it about the callback argument. 251 * The other stuff is already there. 252 */ 253 if (dconf->wsemul != NULL) 254 (*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0); 255 } else { /* not console */ 256 dconf = malloc(sizeof(struct wsscreen_internal), 257 M_DEVBUF, M_NOWAIT); 258 dconf->emulops = type->textops; 259 dconf->emulcookie = cookie; 260 if (dconf->emulops) { 261 dconf->wsemul = wsemul_pick(emul); 262 if (dconf->wsemul == NULL) { 263 free(dconf, M_DEVBUF); 264 free(scr, M_DEVBUF); 265 return (NULL); 266 } 267 dconf->wsemulcookie = 268 (*dconf->wsemul->attach)(0, type, cookie, 269 ccol, crow, scr, defattr); 270 } else 271 dconf->wsemul = NULL; 272 dconf->scrdata = type; 273 } 274 275 scr->scr_dconf = dconf; 276 277 scr->scr_tty = ttymalloc(); 278 tty_attach(scr->scr_tty); 279 scr->scr_hold_screen = 0; 280 if (WSSCREEN_HAS_EMULATOR(scr)) 281 scr->scr_flags = 0; 282 else 283 scr->scr_flags = SCR_GRAPHICS; 284 285 scr->scr_syncops = 0; 286 scr->sc = sc; 287 #ifdef WSDISPLAY_COMPAT_RAWKBD 288 scr->scr_rawkbd = 0; 289 #endif 290 return (scr); 291 } 292 293 void 294 wsscreen_detach(struct wsscreen *scr) 295 { 296 u_int ccol, crow; /* XXX */ 297 298 if (WSSCREEN_HAS_TTY(scr)) { 299 tty_detach(scr->scr_tty); 300 ttyfree(scr->scr_tty); 301 } 302 if (WSSCREEN_HAS_EMULATOR(scr)) 303 (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie, 304 &ccol, &crow); 305 free(scr->scr_dconf, M_DEVBUF); 306 free(scr, M_DEVBUF); 307 } 308 309 const struct wsscreen_descr * 310 wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name) 311 { 312 int i; 313 const struct wsscreen_descr *scr; 314 315 KASSERT(scrdata->nscreens > 0); 316 317 if (name == NULL) 318 return (scrdata->screens[0]); 319 320 for (i = 0; i < scrdata->nscreens; i++) { 321 scr = scrdata->screens[i]; 322 if (!strcmp(name, scr->name)) 323 return (scr); 324 } 325 326 return (0); 327 } 328 329 /* 330 * print info about attached screen 331 */ 332 static void 333 wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count) 334 { 335 printf("%s: screen %d", sc->sc_dv.dv_xname, idx); 336 if (count > 1) 337 printf("-%d", idx + (count-1)); 338 printf(" added (%s", sc->sc_scr[idx]->scr_dconf->scrdata->name); 339 if (WSSCREEN_HAS_EMULATOR(sc->sc_scr[idx])) { 340 printf(", %s emulation", 341 sc->sc_scr[idx]->scr_dconf->wsemul->name); 342 } 343 printf(")\n"); 344 } 345 346 int 347 wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx, 348 const char *screentype, const char *emul) 349 { 350 const struct wsscreen_descr *scrdesc; 351 int error; 352 void *cookie; 353 int ccol, crow; 354 long defattr; 355 struct wsscreen *scr; 356 int s; 357 358 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 359 return (EINVAL); 360 if (sc->sc_scr[idx] != NULL) 361 return (EBUSY); 362 363 scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype); 364 if (!scrdesc) 365 return (ENXIO); 366 error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie, 367 scrdesc, &cookie, &ccol, &crow, &defattr); 368 if (error) 369 return (error); 370 371 scr = wsscreen_attach(sc, 0, emul, scrdesc, 372 cookie, ccol, crow, defattr); 373 if (scr == NULL) { 374 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 375 cookie); 376 return (ENXIO); 377 } 378 379 sc->sc_scr[idx] = scr; 380 381 /* if no screen has focus yet, activate the first we get */ 382 s = spltty(); 383 if (!sc->sc_focus) { 384 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 385 scr->scr_dconf->emulcookie, 386 0, 0, 0); 387 sc->sc_focusidx = idx; 388 sc->sc_focus = scr; 389 } 390 splx(s); 391 return (0); 392 } 393 394 static void 395 wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr) 396 { 397 int maj, mn, idx; 398 399 /* hangup */ 400 if (WSSCREEN_HAS_TTY(scr)) { 401 struct tty *tp = scr->scr_tty; 402 (*tp->t_linesw->l_modem)(tp, 0); 403 } 404 405 /* locate the major number */ 406 maj = cdevsw_lookup_major(&wsdisplay_cdevsw); 407 /* locate the screen index */ 408 for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++) 409 if (scr == sc->sc_scr[idx]) 410 break; 411 #ifdef DIAGNOSTIC 412 if (idx == WSDISPLAY_MAXSCREEN) 413 panic("wsdisplay_forceclose: bad screen"); 414 #endif 415 416 /* nuke the vnodes */ 417 mn = WSDISPLAYMINOR(device_unit(&sc->sc_dv), idx); 418 vdevgone(maj, mn, mn, VCHR); 419 } 420 421 #ifdef WSDISPLAY_SCROLLSUPPORT 422 void 423 wsdisplay_scroll(void *arg, int op) 424 { 425 struct wsdisplay_softc *sc = arg; 426 int lines; 427 428 if (op == WSDISPLAY_SCROLL_RESET) 429 lines = 0; 430 else { 431 lines = (op & WSDISPLAY_SCROLL_LOW) ? 432 sc->sc_scroll_values.slowlines : 433 sc->sc_scroll_values.fastlines; 434 if (op & WSDISPLAY_SCROLL_BACKWARD) 435 lines = -(lines); 436 } 437 438 if (sc->sc_accessops->scroll) { 439 (*sc->sc_accessops->scroll)(sc->sc_accesscookie, 440 sc->sc_focus->scr_dconf->emulcookie, lines); 441 } 442 } 443 #endif 444 445 int 446 wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags) 447 { 448 struct wsscreen *scr; 449 int s; 450 void *cookie; 451 452 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 453 return (EINVAL); 454 if ((scr = sc->sc_scr[idx]) == NULL) 455 return (ENXIO); 456 457 if (scr->scr_dconf == &wsdisplay_console_conf || 458 scr->scr_syncops || 459 ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE))) 460 return(EBUSY); 461 462 wsdisplay_closescreen(sc, scr); 463 464 /* 465 * delete pointers, so neither device entries 466 * nor keyboard input can reference it anymore 467 */ 468 s = spltty(); 469 if (sc->sc_focus == scr) { 470 sc->sc_focus = 0; 471 #ifdef WSDISPLAY_COMPAT_RAWKBD 472 wsdisplay_update_rawkbd(sc, 0); 473 #endif 474 } 475 sc->sc_scr[idx] = 0; 476 splx(s); 477 478 /* 479 * Wake up processes waiting for the screen to 480 * be activated. Sleepers must check whether 481 * the screen still exists. 482 */ 483 if (scr->scr_flags & SCR_WAITACTIVE) 484 wakeup(scr); 485 486 /* save a reference to the graphics screen */ 487 cookie = scr->scr_dconf->emulcookie; 488 489 wsscreen_detach(scr); 490 491 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 492 cookie); 493 494 printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx); 495 return (0); 496 } 497 498 /* 499 * Autoconfiguration functions. 500 */ 501 int 502 wsdisplay_emul_match(struct device *parent __unused, struct cfdata *match, 503 void *aux) 504 { 505 struct wsemuldisplaydev_attach_args *ap = aux; 506 507 if (match->wsemuldisplaydevcf_console != 508 WSEMULDISPLAYDEVCF_CONSOLE_UNK) { 509 /* 510 * If console-ness of device specified, either match 511 * exactly (at high priority), or fail. 512 */ 513 if (match->wsemuldisplaydevcf_console != 0 && 514 ap->console != 0) 515 return (10); 516 else 517 return (0); 518 } 519 520 /* If console-ness unspecified, it wins. */ 521 return (1); 522 } 523 524 void 525 wsdisplay_emul_attach(struct device *parent __unused, struct device *self, 526 void *aux) 527 { 528 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; 529 struct wsemuldisplaydev_attach_args *ap = aux; 530 531 /* Don't allow more than one console to attach */ 532 if (wsdisplay_console_attached && ap->console) 533 ap->console = 0; 534 535 wsdisplay_common_attach(sc, ap->console, 536 device_cfdata(&sc->sc_dv)->wsemuldisplaydevcf_kbdmux, ap->scrdata, 537 ap->accessops, ap->accesscookie); 538 539 if (ap->console) { 540 int maj; 541 542 /* locate the major number */ 543 maj = cdevsw_lookup_major(&wsdisplay_cdevsw); 544 545 cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(device_unit(self), 546 0)); 547 } 548 } 549 550 /* Print function (for parent devices). */ 551 int 552 wsemuldisplaydevprint(void *aux __unused, const char *pnp) 553 { 554 #if 0 /* -Wunused */ 555 struct wsemuldisplaydev_attach_args *ap = aux; 556 #endif 557 558 if (pnp) 559 aprint_normal("wsdisplay at %s", pnp); 560 #if 0 /* don't bother; it's ugly */ 561 aprint_normal(" console %d", ap->console); 562 #endif 563 564 return (UNCONF); 565 } 566 567 int 568 wsdisplay_noemul_match(struct device *parent __unused, 569 struct cfdata *match __unused, void *aux __unused) 570 { 571 #if 0 /* -Wunused */ 572 struct wsdisplaydev_attach_args *ap = aux; 573 #endif 574 575 /* Always match. */ 576 return (1); 577 } 578 579 void 580 wsdisplay_noemul_attach(struct device *parent __unused, struct device *self, 581 void *aux) 582 { 583 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; 584 struct wsdisplaydev_attach_args *ap = aux; 585 586 wsdisplay_common_attach(sc, 0, 587 device_cfdata(&sc->sc_dv)->wsemuldisplaydevcf_kbdmux, NULL, 588 ap->accessops, ap->accesscookie); 589 } 590 591 /* Print function (for parent devices). */ 592 int 593 wsdisplaydevprint(void *aux __unused, const char *pnp) 594 { 595 #if 0 /* -Wunused */ 596 struct wsdisplaydev_attach_args *ap = aux; 597 #endif 598 599 if (pnp) 600 aprint_normal("wsdisplay at %s", pnp); 601 602 return (UNCONF); 603 } 604 605 static void 606 wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, 607 const struct wsscreen_list *scrdata, 608 const struct wsdisplay_accessops *accessops, 609 void *accesscookie) 610 { 611 static int hookset; 612 int i, start=0; 613 #if NWSKBD > 0 614 struct wsevsrc *kme; 615 #if NWSMUX > 0 616 struct wsmux_softc *mux; 617 618 if (kbdmux >= 0) 619 mux = wsmux_getmux(kbdmux); 620 else 621 mux = wsmux_create("dmux", device_unit(&sc->sc_dv)); 622 /* XXX panic()ing isn't nice, but attach cannot fail */ 623 if (mux == NULL) 624 panic("wsdisplay_common_attach: no memory"); 625 sc->sc_input = &mux->sc_base; 626 mux->sc_base.me_dispdv = &sc->sc_dv; 627 printf(" kbdmux %d", kbdmux); 628 #else 629 if (kbdmux >= 0) 630 printf(" (kbdmux ignored)"); 631 #endif 632 #endif 633 634 sc->sc_isconsole = console; 635 636 if (console) { 637 KASSERT(wsdisplay_console_initted); 638 KASSERT(wsdisplay_console_device == NULL); 639 640 sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0); 641 wsdisplay_console_device = sc; 642 643 printf(": console (%s, %s emulation)", 644 wsdisplay_console_conf.scrdata->name, 645 wsdisplay_console_conf.wsemul->name); 646 647 #if NWSKBD > 0 648 kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input); 649 if (kme != NULL) 650 printf(", using %s", kme->me_dv.dv_xname); 651 #if NWSMUX == 0 652 sc->sc_input = kme; 653 #endif 654 #endif 655 656 sc->sc_focusidx = 0; 657 sc->sc_focus = sc->sc_scr[0]; 658 start = 1; 659 660 wsdisplay_console_attached = 1; 661 } 662 printf("\n"); 663 664 #if NWSKBD > 0 && NWSMUX > 0 665 wsmux_set_display(mux, &sc->sc_dv); 666 #endif 667 668 sc->sc_accessops = accessops; 669 sc->sc_accesscookie = accesscookie; 670 sc->sc_scrdata = scrdata; 671 672 #ifdef WSDISPLAY_SCROLLSUPPORT 673 sc->sc_scroll_values = wsdisplay_default_scroll_values; 674 #endif 675 676 /* 677 * Set up a number of virtual screens if wanted. The 678 * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code 679 * is for special cases like installation kernels. 680 */ 681 for (i = start; i < wsdisplay_defaultscreens; i++) { 682 if (wsdisplay_addscreen(sc, i, 0, 0)) 683 break; 684 } 685 686 if (i > start) 687 wsdisplay_addscreen_print(sc, start, i-start); 688 689 if (hookset == 0) 690 shutdownhook_establish(wsdisplay_shutdownhook, NULL); 691 hookset = 1; 692 } 693 694 void 695 wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, 696 int ccol, int crow, long defattr) 697 { 698 const struct wsemul_ops *wsemul; 699 700 KASSERT(!wsdisplay_console_initted); 701 KASSERT(type->nrows > 0); 702 KASSERT(type->ncols > 0); 703 KASSERT(crow < type->nrows); 704 KASSERT(ccol < type->ncols); 705 706 wsdisplay_console_conf.emulops = type->textops; 707 wsdisplay_console_conf.emulcookie = cookie; 708 wsdisplay_console_conf.scrdata = type; 709 710 wsemul = wsemul_pick(0); /* default */ 711 wsdisplay_console_conf.wsemul = wsemul; 712 wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, 713 ccol, crow, 714 defattr); 715 716 cn_tab = &wsdisplay_cons; 717 wsdisplay_console_initted = 1; 718 } 719 720 /* 721 * Tty and cdevsw functions. 722 */ 723 int 724 wsdisplayopen(dev_t dev, int flag __unused, int mode __unused, struct lwp *l) 725 { 726 struct wsdisplay_softc *sc; 727 struct tty *tp; 728 int newopen, error; 729 struct wsscreen *scr; 730 731 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 732 if (sc == NULL) /* make sure it was attached */ 733 return (ENXIO); 734 735 if (ISWSDISPLAYSTAT(dev)) { 736 wsevent_init(&sc->evar, l->l_proc); 737 return (0); 738 } 739 740 if (ISWSDISPLAYCTL(dev)) 741 return (0); 742 743 if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) 744 return (ENXIO); 745 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 746 return (ENXIO); 747 748 if (WSSCREEN_HAS_TTY(scr)) { 749 tp = scr->scr_tty; 750 tp->t_oproc = wsdisplaystart; 751 tp->t_param = wsdisplayparam; 752 tp->t_dev = dev; 753 newopen = (tp->t_state & TS_ISOPEN) == 0; 754 755 if (kauth_authorize_device_tty(l->l_cred, 756 KAUTH_DEVICE_TTY_OPEN, tp)) 757 return (EBUSY); 758 759 if (newopen) { 760 ttychars(tp); 761 tp->t_iflag = TTYDEF_IFLAG; 762 tp->t_oflag = TTYDEF_OFLAG; 763 tp->t_cflag = TTYDEF_CFLAG; 764 tp->t_lflag = TTYDEF_LFLAG; 765 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 766 wsdisplayparam(tp, &tp->t_termios); 767 ttsetwater(tp); 768 } 769 tp->t_state |= TS_CARR_ON; 770 771 error = ((*tp->t_linesw->l_open)(dev, tp)); 772 if (error) 773 return (error); 774 775 if (newopen && WSSCREEN_HAS_EMULATOR(scr)) { 776 /* set window sizes as appropriate, and reset 777 the emulation */ 778 tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows; 779 tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols; 780 781 /* wsdisplay_set_emulation() */ 782 } 783 } 784 785 scr->scr_flags |= SCR_OPEN; 786 return (0); 787 } 788 789 int 790 wsdisplayclose(dev_t dev, int flag, int mode __unused, struct lwp *l) 791 { 792 struct wsdisplay_softc *sc; 793 struct tty *tp; 794 struct wsscreen *scr; 795 796 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 797 798 if (ISWSDISPLAYSTAT(dev)) { 799 wsevent_fini(&sc->evar); 800 return (0); 801 } 802 803 if (ISWSDISPLAYCTL(dev)) 804 return (0); 805 806 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 807 return (0); 808 809 if (WSSCREEN_HAS_TTY(scr)) { 810 if (scr->scr_hold_screen) { 811 int s; 812 813 /* XXX RESET KEYBOARD LEDS, etc. */ 814 s = spltty(); /* avoid conflict with keyboard */ 815 wsdisplay_kbdholdscreen((struct device *)sc, 0); 816 splx(s); 817 } 818 tp = scr->scr_tty; 819 (*tp->t_linesw->l_close)(tp, flag); 820 ttyclose(tp); 821 } 822 823 if (scr->scr_syncops) 824 (*scr->scr_syncops->destroy)(scr->scr_synccookie); 825 826 if (WSSCREEN_HAS_EMULATOR(scr)) { 827 scr->scr_flags &= ~SCR_GRAPHICS; 828 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 829 WSEMUL_RESET); 830 if (wsdisplay_clearonclose) 831 (*scr->scr_dconf->wsemul->reset) 832 (scr->scr_dconf->wsemulcookie, 833 WSEMUL_CLEARSCREEN); 834 } 835 836 #ifdef WSDISPLAY_COMPAT_RAWKBD 837 if (scr->scr_rawkbd) { 838 int kbmode = WSKBD_TRANSLATED; 839 (void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, 840 (caddr_t)&kbmode, 0, l); 841 } 842 #else 843 do { if (&l) {} } while (/* CONSTCOND */ 0); /* shut up -Wunused */ 844 #endif 845 846 scr->scr_flags &= ~SCR_OPEN; 847 848 return (0); 849 } 850 851 int 852 wsdisplayread(dev_t dev, struct uio *uio, int flag) 853 { 854 struct wsdisplay_softc *sc; 855 struct tty *tp; 856 struct wsscreen *scr; 857 int error; 858 859 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 860 861 if (ISWSDISPLAYSTAT(dev)) { 862 error = wsevent_read(&sc->evar, uio, flag); 863 return (error); 864 } 865 866 if (ISWSDISPLAYCTL(dev)) 867 return (0); 868 869 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 870 return (ENXIO); 871 872 if (!WSSCREEN_HAS_TTY(scr)) 873 return (ENODEV); 874 875 tp = scr->scr_tty; 876 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 877 } 878 879 int 880 wsdisplaywrite(dev_t dev, struct uio *uio, int flag) 881 { 882 struct wsdisplay_softc *sc; 883 struct tty *tp; 884 struct wsscreen *scr; 885 886 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 887 888 if (ISWSDISPLAYSTAT(dev)) { 889 return (0); 890 } 891 892 if (ISWSDISPLAYCTL(dev)) 893 return (0); 894 895 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 896 return (ENXIO); 897 898 if (!WSSCREEN_HAS_TTY(scr)) 899 return (ENODEV); 900 901 tp = scr->scr_tty; 902 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 903 } 904 905 int 906 wsdisplaypoll(dev_t dev, int events, struct lwp *l) 907 { 908 struct wsdisplay_softc *sc; 909 struct tty *tp; 910 struct wsscreen *scr; 911 912 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 913 914 if (ISWSDISPLAYSTAT(dev)) 915 return (wsevent_poll(&sc->evar, events, l)); 916 917 if (ISWSDISPLAYCTL(dev)) 918 return (0); 919 920 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 921 return (POLLHUP); 922 923 if (!WSSCREEN_HAS_TTY(scr)) 924 return (POLLERR); 925 926 tp = scr->scr_tty; 927 return ((*tp->t_linesw->l_poll)(tp, events, l)); 928 } 929 930 int 931 wsdisplaykqfilter(dev, kn) 932 dev_t dev; 933 struct knote *kn; 934 { 935 struct wsdisplay_softc *sc = 936 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 937 struct wsscreen *scr; 938 939 if (ISWSDISPLAYCTL(dev)) 940 return (1); 941 942 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 943 return (1); 944 945 946 if (WSSCREEN_HAS_TTY(scr)) 947 return (ttykqfilter(dev, kn)); 948 else 949 return (1); 950 } 951 952 struct tty * 953 wsdisplaytty(dev_t dev) 954 { 955 struct wsdisplay_softc *sc; 956 struct wsscreen *scr; 957 958 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 959 960 if (ISWSDISPLAYSTAT(dev)) 961 panic("wsdisplaytty() on status device"); 962 963 if (ISWSDISPLAYCTL(dev)) 964 panic("wsdisplaytty() on ctl device"); 965 966 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 967 return NULL; 968 969 return (scr->scr_tty); 970 } 971 972 int 973 wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l) 974 { 975 struct wsdisplay_softc *sc; 976 struct tty *tp; 977 int error; 978 struct wsscreen *scr; 979 980 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 981 982 #ifdef WSDISPLAY_COMPAT_USL 983 error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, l); 984 if (error != EPASSTHROUGH) 985 return (error); 986 #endif 987 988 if (ISWSDISPLAYSTAT(dev)) 989 return (wsdisplay_stat_ioctl(sc, cmd, data, flag, l)); 990 991 if (ISWSDISPLAYCTL(dev)) 992 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, l)); 993 994 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 995 return (ENXIO); 996 997 if (WSSCREEN_HAS_TTY(scr)) { 998 tp = scr->scr_tty; 999 1000 /* printf("disc\n"); */ 1001 /* do the line discipline ioctls first */ 1002 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 1003 if (error != EPASSTHROUGH) 1004 return (error); 1005 1006 /* printf("tty\n"); */ 1007 /* then the tty ioctls */ 1008 error = ttioctl(tp, cmd, data, flag, l); 1009 if (error != EPASSTHROUGH) 1010 return (error); 1011 } 1012 1013 #ifdef WSDISPLAY_COMPAT_USL 1014 error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, l); 1015 if (error != EPASSTHROUGH) 1016 return (error); 1017 #endif 1018 1019 return (wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, l)); 1020 } 1021 1022 int 1023 wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp) 1024 { 1025 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1026 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1027 sc->sc_focus->scr_dconf->emulcookie, 1028 cmd, (caddr_t)dp, 0, NULL)); 1029 } 1030 1031 int 1032 wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, 1033 u_long cmd, caddr_t data, int flag, struct lwp *l) 1034 { 1035 int error; 1036 char namebuf[16]; 1037 struct wsdisplay_font fd; 1038 #ifdef WSDISPLAY_SCROLLSUPPORT 1039 struct wsdisplay_scroll_data *ksdp, *usdp; 1040 #endif 1041 1042 #if NWSKBD > 0 1043 struct wsevsrc *inp; 1044 1045 #ifdef WSDISPLAY_COMPAT_RAWKBD 1046 switch (cmd) { 1047 case WSKBDIO_SETMODE: 1048 scr->scr_rawkbd = (*(int *)data == WSKBD_RAW); 1049 return (wsdisplay_update_rawkbd(sc, scr)); 1050 case WSKBDIO_GETMODE: 1051 *(int *)data = (scr->scr_rawkbd ? 1052 WSKBD_RAW : WSKBD_TRANSLATED); 1053 return (0); 1054 } 1055 #endif 1056 inp = sc->sc_input; 1057 if (inp == NULL) 1058 return (ENXIO); 1059 error = wsevsrc_display_ioctl(inp, cmd, data, flag, l); 1060 if (error != EPASSTHROUGH) 1061 return (error); 1062 #endif /* NWSKBD > 0 */ 1063 1064 switch (cmd) { 1065 case WSDISPLAYIO_GMODE: 1066 if (scr->scr_flags & SCR_GRAPHICS) { 1067 if (scr->scr_flags & SCR_DUMBFB) 1068 *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB; 1069 else 1070 *(u_int *)data = WSDISPLAYIO_MODE_MAPPED; 1071 } else 1072 *(u_int *)data = WSDISPLAYIO_MODE_EMUL; 1073 return (0); 1074 1075 case WSDISPLAYIO_SMODE: 1076 #define d (*(int *)data) 1077 if (d != WSDISPLAYIO_MODE_EMUL && 1078 d != WSDISPLAYIO_MODE_MAPPED && 1079 d != WSDISPLAYIO_MODE_DUMBFB) 1080 return (EINVAL); 1081 1082 if (WSSCREEN_HAS_EMULATOR(scr)) { 1083 scr->scr_flags &= ~SCR_GRAPHICS; 1084 if (d == WSDISPLAYIO_MODE_MAPPED || 1085 d == WSDISPLAYIO_MODE_DUMBFB) 1086 scr->scr_flags |= SCR_GRAPHICS | 1087 ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0); 1088 } else if (d == WSDISPLAYIO_MODE_EMUL) 1089 return (EINVAL); 1090 1091 (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1092 scr->scr_dconf->emulcookie, cmd, data, flag, l); 1093 1094 return (0); 1095 #undef d 1096 1097 #ifdef WSDISPLAY_SCROLLSUPPORT 1098 #define SETSCROLLLINES(dstp, srcp, dfltp) \ 1099 do { \ 1100 (dstp)->fastlines = ((srcp)->which & \ 1101 WSDISPLAY_SCROLL_DOFASTLINES) ? \ 1102 (srcp)->fastlines : (dfltp)->fastlines; \ 1103 (dstp)->slowlines = ((srcp)->which & \ 1104 WSDISPLAY_SCROLL_DOSLOWLINES) ? \ 1105 (srcp)->slowlines : (dfltp)->slowlines; \ 1106 (dstp)->which = WSDISPLAY_SCROLL_DOALL; \ 1107 } while (0) 1108 1109 1110 case WSDISPLAYIO_DSSCROLL: 1111 usdp = (struct wsdisplay_scroll_data *)data; 1112 ksdp = &sc->sc_scroll_values; 1113 SETSCROLLLINES(ksdp, usdp, ksdp); 1114 return (0); 1115 1116 case WSDISPLAYIO_DGSCROLL: 1117 usdp = (struct wsdisplay_scroll_data *)data; 1118 ksdp = &sc->sc_scroll_values; 1119 SETSCROLLLINES(usdp, ksdp, ksdp); 1120 return (0); 1121 #else 1122 case WSDISPLAYIO_DSSCROLL: 1123 case WSDISPLAYIO_DGSCROLL: 1124 return ENODEV; 1125 #endif 1126 1127 case WSDISPLAYIO_SFONT: 1128 #define d ((struct wsdisplay_usefontdata *)data) 1129 if (!sc->sc_accessops->load_font) 1130 return (EINVAL); 1131 if (d->name) { 1132 error = copyinstr(d->name, namebuf, sizeof(namebuf), 0); 1133 if (error) 1134 return (error); 1135 fd.name = namebuf; 1136 } else 1137 fd.name = 0; 1138 fd.data = 0; 1139 error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 1140 scr->scr_dconf->emulcookie, &fd); 1141 if (!error && WSSCREEN_HAS_EMULATOR(scr)) 1142 (*scr->scr_dconf->wsemul->reset) 1143 (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT); 1144 return (error); 1145 #undef d 1146 1147 #ifdef WSDISPLAY_CUSTOM_OUTPUT 1148 case WSDISPLAYIO_GMSGATTRS: 1149 #define d ((struct wsdisplay_msgattrs *)data) 1150 (*scr->scr_dconf->wsemul->getmsgattrs) 1151 (scr->scr_dconf->wsemulcookie, d); 1152 return (0); 1153 #undef d 1154 1155 case WSDISPLAYIO_SMSGATTRS: { 1156 #define d ((struct wsdisplay_msgattrs *)data) 1157 int i; 1158 for (i = 0; i < WSDISPLAY_MAXSCREEN; i++) 1159 if (sc->sc_scr[i] != NULL) 1160 (*sc->sc_scr[i]->scr_dconf->wsemul->setmsgattrs) 1161 (sc->sc_scr[i]->scr_dconf->wsemulcookie, 1162 sc->sc_scr[i]->scr_dconf->scrdata, 1163 d); 1164 } 1165 return (0); 1166 #undef d 1167 #else 1168 case WSDISPLAYIO_GMSGATTRS: 1169 case WSDISPLAYIO_SMSGATTRS: 1170 return (ENODEV); 1171 #endif 1172 } 1173 1174 /* check ioctls for display */ 1175 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1176 scr->scr_dconf->emulcookie, cmd, data, flag, l)); 1177 } 1178 1179 int 1180 wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1181 int flag __unused, struct lwp *l __unused) 1182 { 1183 switch (cmd) { 1184 case WSDISPLAYIO_GETACTIVESCREEN: 1185 *(int*)data = wsdisplay_getactivescreen(sc); 1186 return (0); 1187 } 1188 1189 return (EPASSTHROUGH); 1190 } 1191 1192 int 1193 wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1194 int flag, struct lwp *l) 1195 { 1196 int error; 1197 char *type, typebuf[16], *emul, emulbuf[16]; 1198 void *tbuf; 1199 u_int fontsz; 1200 #if defined(COMPAT_14) && NWSKBD > 0 1201 struct wsmux_device wsmuxdata; 1202 #endif 1203 #if NWSKBD > 0 1204 struct wsevsrc *inp; 1205 #endif 1206 1207 switch (cmd) { 1208 case WSDISPLAYIO_ADDSCREEN: 1209 #define d ((struct wsdisplay_addscreendata *)data) 1210 if (d->screentype) { 1211 error = copyinstr(d->screentype, typebuf, 1212 sizeof(typebuf), 0); 1213 if (error) 1214 return (error); 1215 type = typebuf; 1216 } else 1217 type = 0; 1218 if (d->emul) { 1219 error = copyinstr(d->emul, emulbuf, sizeof(emulbuf),0); 1220 if (error) 1221 return (error); 1222 emul = emulbuf; 1223 } else 1224 emul = 0; 1225 1226 if ((error = wsdisplay_addscreen(sc, d->idx, type, emul)) == 0) 1227 wsdisplay_addscreen_print(sc, d->idx, 0); 1228 return (error); 1229 #undef d 1230 case WSDISPLAYIO_DELSCREEN: 1231 #define d ((struct wsdisplay_delscreendata *)data) 1232 return (wsdisplay_delscreen(sc, d->idx, d->flags)); 1233 #undef d 1234 case WSDISPLAYIO_LDFONT: 1235 #define d ((struct wsdisplay_font *)data) 1236 if (!sc->sc_accessops->load_font) 1237 return (EINVAL); 1238 if (d->name) { 1239 error = copyinstr(d->name, typebuf, sizeof(typebuf), 0); 1240 if (error) 1241 return (error); 1242 d->name = typebuf; 1243 } else 1244 d->name = "loaded"; /* ??? */ 1245 fontsz = d->fontheight * d->stride * d->numchars; 1246 if (fontsz > WSDISPLAY_MAXFONTSZ) 1247 return (EINVAL); 1248 1249 tbuf = malloc(fontsz, M_DEVBUF, M_WAITOK); 1250 error = copyin(d->data, tbuf, fontsz); 1251 if (error) { 1252 free(tbuf, M_DEVBUF); 1253 return (error); 1254 } 1255 d->data = tbuf; 1256 error = 1257 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); 1258 free(tbuf, M_DEVBUF); 1259 #undef d 1260 return (error); 1261 1262 #if NWSKBD > 0 1263 #ifdef COMPAT_14 1264 case _O_WSDISPLAYIO_SETKEYBOARD: 1265 #define d ((struct wsdisplay_kbddata *)data) 1266 inp = sc->sc_input; 1267 if (inp == NULL) 1268 return (ENXIO); 1269 switch (d->op) { 1270 case _O_WSDISPLAY_KBD_ADD: 1271 if (d->idx == -1) { 1272 d->idx = wskbd_pickfree(); 1273 if (d->idx == -1) 1274 return (ENXIO); 1275 } 1276 wsmuxdata.type = WSMUX_KBD; 1277 wsmuxdata.idx = d->idx; 1278 return (wsevsrc_ioctl(inp, WSMUX_ADD_DEVICE, 1279 &wsmuxdata, flag, l)); 1280 case _O_WSDISPLAY_KBD_DEL: 1281 wsmuxdata.type = WSMUX_KBD; 1282 wsmuxdata.idx = d->idx; 1283 return (wsevsrc_ioctl(inp, WSMUX_REMOVE_DEVICE, 1284 &wsmuxdata, flag, l)); 1285 default: 1286 return (EINVAL); 1287 } 1288 #undef d 1289 #endif 1290 1291 case WSMUXIO_ADD_DEVICE: 1292 #define d ((struct wsmux_device *)data) 1293 if (d->idx == -1 && d->type == WSMUX_KBD) 1294 d->idx = wskbd_pickfree(); 1295 #undef d 1296 /* fall into */ 1297 case WSMUXIO_INJECTEVENT: 1298 case WSMUXIO_REMOVE_DEVICE: 1299 case WSMUXIO_LIST_DEVICES: 1300 inp = sc->sc_input; 1301 if (inp == NULL) 1302 return (ENXIO); 1303 return (wsevsrc_ioctl(inp, cmd, data, flag, l)); 1304 #endif /* NWSKBD > 0 */ 1305 1306 } 1307 return (EPASSTHROUGH); 1308 } 1309 1310 int 1311 wsdisplay_stat_inject(struct device *dev, u_int type, int value) 1312 { 1313 struct wsdisplay_softc *sc = (struct wsdisplay_softc *) dev; 1314 struct wseventvar *evar; 1315 struct wscons_event event; 1316 1317 evar = &sc->evar; 1318 1319 if (evar == NULL) 1320 return (0); 1321 1322 if (evar->q == NULL) 1323 return (1); 1324 1325 event.type = type; 1326 event.value = value; 1327 if (wsevent_inject(evar, &event, 1) != 0) { 1328 log(LOG_WARNING, "wsdisplay: event queue overflow\n"); 1329 return (1); 1330 } 1331 1332 return (0); 1333 } 1334 1335 paddr_t 1336 wsdisplaymmap(dev_t dev, off_t offset, int prot) 1337 { 1338 struct wsdisplay_softc *sc = 1339 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 1340 struct wsscreen *scr; 1341 1342 if (ISWSDISPLAYSTAT(dev)) 1343 return (-1); 1344 1345 if (ISWSDISPLAYCTL(dev)) 1346 return (-1); 1347 1348 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 1349 return (-1); 1350 1351 if (!(scr->scr_flags & SCR_GRAPHICS)) 1352 return (-1); 1353 1354 /* pass mmap to display */ 1355 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, 1356 scr->scr_dconf->emulcookie, offset, prot)); 1357 } 1358 1359 void 1360 wsdisplaystart(struct tty *tp) 1361 { 1362 struct wsdisplay_softc *sc; 1363 struct wsscreen *scr; 1364 int s, n; 1365 u_char *tbuf; 1366 1367 s = spltty(); 1368 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 1369 splx(s); 1370 return; 1371 } 1372 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(tp->t_dev)); 1373 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { 1374 splx(s); 1375 return; 1376 } 1377 1378 if (scr->scr_hold_screen) { 1379 tp->t_state |= TS_TIMEOUT; 1380 splx(s); 1381 return; 1382 } 1383 tp->t_state |= TS_BUSY; 1384 splx(s); 1385 1386 /* 1387 * Drain output from ring buffer. 1388 * The output will normally be in one contiguous chunk, but when the 1389 * ring wraps, it will be in two pieces.. one at the end of the ring, 1390 * the other at the start. For performance, rather than loop here, 1391 * we output one chunk, see if there's another one, and if so, output 1392 * it too. 1393 */ 1394 1395 n = ndqb(&tp->t_outq, 0); 1396 tbuf = tp->t_outq.c_cf; 1397 1398 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1399 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1400 (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie, 1401 tbuf, n, 0); 1402 } 1403 ndflush(&tp->t_outq, n); 1404 1405 if ((n = ndqb(&tp->t_outq, 0)) > 0) { 1406 tbuf = tp->t_outq.c_cf; 1407 1408 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1409 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1410 (*scr->scr_dconf->wsemul->output) 1411 (scr->scr_dconf->wsemulcookie, tbuf, n, 0); 1412 } 1413 ndflush(&tp->t_outq, n); 1414 } 1415 1416 s = spltty(); 1417 tp->t_state &= ~TS_BUSY; 1418 /* Come back if there's more to do */ 1419 if (tp->t_outq.c_cc) { 1420 tp->t_state |= TS_TIMEOUT; 1421 callout_reset(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1, 1422 ttrstrt, tp); 1423 } 1424 if (tp->t_outq.c_cc <= tp->t_lowat) { 1425 if (tp->t_state&TS_ASLEEP) { 1426 tp->t_state &= ~TS_ASLEEP; 1427 wakeup(&tp->t_outq); 1428 } 1429 selwakeup(&tp->t_wsel); 1430 } 1431 splx(s); 1432 } 1433 1434 void 1435 wsdisplaystop(struct tty *tp, int flag __unused) 1436 { 1437 int s; 1438 1439 s = spltty(); 1440 if (ISSET(tp->t_state, TS_BUSY)) 1441 if (!ISSET(tp->t_state, TS_TTSTOP)) 1442 SET(tp->t_state, TS_FLUSH); 1443 splx(s); 1444 } 1445 1446 /* Set line parameters. */ 1447 int 1448 wsdisplayparam(struct tty *tp, struct termios *t) 1449 { 1450 1451 tp->t_ispeed = t->c_ispeed; 1452 tp->t_ospeed = t->c_ospeed; 1453 tp->t_cflag = t->c_cflag; 1454 return 0; 1455 } 1456 1457 /* 1458 * Callbacks for the emulation code. 1459 */ 1460 void 1461 wsdisplay_emulbell(void *v) 1462 { 1463 struct wsscreen *scr = v; 1464 1465 if (scr == NULL) /* console, before real attach */ 1466 return; 1467 1468 if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ 1469 return; 1470 1471 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, 1472 FWRITE, NULL); 1473 } 1474 1475 void 1476 wsdisplay_emulinput(void *v, const u_char *data, u_int count) 1477 { 1478 struct wsscreen *scr = v; 1479 struct tty *tp; 1480 1481 if (v == NULL) /* console, before real attach */ 1482 return; 1483 1484 if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ 1485 return; 1486 if (!WSSCREEN_HAS_TTY(scr)) 1487 return; 1488 1489 tp = scr->scr_tty; 1490 while (count-- > 0) 1491 (*tp->t_linesw->l_rint)(*data++, tp); 1492 } 1493 1494 /* 1495 * Calls from the keyboard interface. 1496 */ 1497 void 1498 wsdisplay_kbdinput(struct device *dev, keysym_t ks) 1499 { 1500 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1501 struct wsscreen *scr; 1502 const char *dp; 1503 int count; 1504 struct tty *tp; 1505 1506 KASSERT(sc != NULL); 1507 1508 scr = sc->sc_focus; 1509 1510 if (!scr || !WSSCREEN_HAS_TTY(scr)) 1511 return; 1512 1513 tp = scr->scr_tty; 1514 1515 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1516 (*tp->t_linesw->l_rint)(KS_VALUE(ks), tp); 1517 else if (WSSCREEN_HAS_EMULATOR(scr)) { 1518 count = (*scr->scr_dconf->wsemul->translate) 1519 (scr->scr_dconf->wsemulcookie, ks, &dp); 1520 while (count-- > 0) 1521 (*tp->t_linesw->l_rint)(*dp++, tp); 1522 } 1523 } 1524 1525 #if defined(WSDISPLAY_COMPAT_RAWKBD) 1526 int 1527 wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) 1528 { 1529 #if NWSKBD > 0 1530 int s, raw, data, error; 1531 struct wsevsrc *inp; 1532 1533 s = spltty(); 1534 1535 raw = (scr ? scr->scr_rawkbd : 0); 1536 1537 if (scr != sc->sc_focus || 1538 sc->sc_rawkbd == raw) { 1539 splx(s); 1540 return (0); 1541 } 1542 1543 data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; 1544 inp = sc->sc_input; 1545 if (inp == NULL) { 1546 splx(s); 1547 return (ENXIO); 1548 } 1549 error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0); 1550 if (!error) 1551 sc->sc_rawkbd = raw; 1552 splx(s); 1553 return (error); 1554 #else 1555 return (0); 1556 #endif 1557 } 1558 #endif 1559 1560 int 1561 wsdisplay_switch3(void *arg, int error, int waitok) 1562 { 1563 struct wsdisplay_softc *sc = arg; 1564 int no; 1565 struct wsscreen *scr; 1566 1567 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1568 printf("wsdisplay_switch3: not switching\n"); 1569 return (EINVAL); 1570 } 1571 1572 no = sc->sc_screenwanted; 1573 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1574 panic("wsdisplay_switch3: invalid screen %d", no); 1575 scr = sc->sc_scr[no]; 1576 if (!scr) { 1577 printf("wsdisplay_switch3: screen %d disappeared\n", no); 1578 error = ENXIO; 1579 } 1580 1581 if (error) { 1582 /* try to recover, avoid recursion */ 1583 1584 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1585 printf("wsdisplay_switch3: giving up\n"); 1586 sc->sc_focus = 0; 1587 #ifdef WSDISPLAY_COMPAT_RAWKBD 1588 wsdisplay_update_rawkbd(sc, 0); 1589 #endif 1590 sc->sc_flags &= ~SC_SWITCHPENDING; 1591 return (error); 1592 } 1593 1594 sc->sc_screenwanted = sc->sc_oldscreen; 1595 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1596 return (wsdisplay_switch1(arg, 0, waitok)); 1597 } 1598 1599 sc->sc_flags &= ~SC_SWITCHPENDING; 1600 1601 if (!error && (scr->scr_flags & SCR_WAITACTIVE)) 1602 wakeup(scr); 1603 return (error); 1604 } 1605 1606 int 1607 wsdisplay_switch2(void *arg, int error, int waitok) 1608 { 1609 struct wsdisplay_softc *sc = arg; 1610 int no; 1611 struct wsscreen *scr; 1612 1613 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1614 printf("wsdisplay_switch2: not switching\n"); 1615 return (EINVAL); 1616 } 1617 1618 no = sc->sc_screenwanted; 1619 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1620 panic("wsdisplay_switch2: invalid screen %d", no); 1621 scr = sc->sc_scr[no]; 1622 if (!scr) { 1623 printf("wsdisplay_switch2: screen %d disappeared\n", no); 1624 error = ENXIO; 1625 } 1626 1627 if (error) { 1628 /* try to recover, avoid recursion */ 1629 1630 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1631 printf("wsdisplay_switch2: giving up\n"); 1632 sc->sc_focus = 0; 1633 sc->sc_flags &= ~SC_SWITCHPENDING; 1634 return (error); 1635 } 1636 1637 sc->sc_screenwanted = sc->sc_oldscreen; 1638 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1639 return (wsdisplay_switch1(arg, 0, waitok)); 1640 } 1641 1642 sc->sc_focusidx = no; 1643 sc->sc_focus = scr; 1644 1645 #ifdef WSDISPLAY_COMPAT_RAWKBD 1646 (void) wsdisplay_update_rawkbd(sc, scr); 1647 #endif 1648 /* keyboard map??? */ 1649 1650 #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3) 1651 if (scr->scr_syncops) { 1652 error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, 1653 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); 1654 if (error == EAGAIN) { 1655 /* switch will be done asynchronously */ 1656 return (0); 1657 } 1658 } 1659 1660 return (wsdisplay_switch3(sc, error, waitok)); 1661 } 1662 1663 int 1664 wsdisplay_switch1(void *arg, int error, int waitok) 1665 { 1666 struct wsdisplay_softc *sc = arg; 1667 int no; 1668 struct wsscreen *scr; 1669 1670 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1671 printf("wsdisplay_switch1: not switching\n"); 1672 return (EINVAL); 1673 } 1674 1675 no = sc->sc_screenwanted; 1676 if (no == WSDISPLAY_NULLSCREEN) { 1677 sc->sc_flags &= ~SC_SWITCHPENDING; 1678 if (!error) { 1679 sc->sc_focus = 0; 1680 } 1681 wakeup(sc); 1682 return (error); 1683 } 1684 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1685 panic("wsdisplay_switch1: invalid screen %d", no); 1686 scr = sc->sc_scr[no]; 1687 if (!scr) { 1688 printf("wsdisplay_switch1: screen %d disappeared\n", no); 1689 error = ENXIO; 1690 } 1691 1692 if (error) { 1693 sc->sc_flags &= ~SC_SWITCHPENDING; 1694 return (error); 1695 } 1696 1697 #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2) 1698 error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 1699 scr->scr_dconf->emulcookie, 1700 waitok, 1701 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); 1702 if (error == EAGAIN) { 1703 /* switch will be done asynchronously */ 1704 return (0); 1705 } 1706 1707 return (wsdisplay_switch2(sc, error, waitok)); 1708 } 1709 1710 int 1711 wsdisplay_switch(struct device *dev, int no, int waitok) 1712 { 1713 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1714 int s, res = 0; 1715 struct wsscreen *scr; 1716 1717 if (no != WSDISPLAY_NULLSCREEN) { 1718 if ((no < 0 || no >= WSDISPLAY_MAXSCREEN)) 1719 return (EINVAL); 1720 if (sc->sc_scr[no] == NULL) 1721 return (ENXIO); 1722 } 1723 1724 wsdisplay_stat_inject(dev, WSCONS_EVENT_SCREEN_SWITCH, no); 1725 1726 s = spltty(); 1727 1728 if ((sc->sc_focus && no == sc->sc_focusidx) || 1729 (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) { 1730 splx(s); 1731 return (0); 1732 } 1733 1734 if (sc->sc_flags & SC_SWITCHPENDING) { 1735 splx(s); 1736 return (EBUSY); 1737 } 1738 1739 sc->sc_flags |= SC_SWITCHPENDING; 1740 sc->sc_screenwanted = no; 1741 1742 splx(s); 1743 1744 scr = sc->sc_focus; 1745 if (!scr) { 1746 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1747 return (wsdisplay_switch1(sc, 0, waitok)); 1748 } else 1749 sc->sc_oldscreen = sc->sc_focusidx; 1750 1751 #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) 1752 if (scr->scr_syncops) { 1753 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, 1754 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); 1755 if (res == EAGAIN) { 1756 /* switch will be done asynchronously */ 1757 return (0); 1758 } 1759 } else if (scr->scr_flags & SCR_GRAPHICS) { 1760 /* no way to save state */ 1761 res = EBUSY; 1762 } 1763 1764 return (wsdisplay_switch1(sc, res, waitok)); 1765 } 1766 1767 void 1768 wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) 1769 { 1770 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1771 struct wsscreen *scr; 1772 1773 KASSERT(sc != NULL); 1774 scr = sc->sc_focus; 1775 1776 if (!scr) 1777 return; 1778 1779 switch (op) { 1780 case WSDISPLAY_RESETEMUL: 1781 if (!WSSCREEN_HAS_EMULATOR(scr)) 1782 break; 1783 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 1784 WSEMUL_RESET); 1785 break; 1786 case WSDISPLAY_RESETCLOSE: 1787 wsdisplay_closescreen(sc, scr); 1788 break; 1789 } 1790 } 1791 1792 /* 1793 * Interface for (external) VT switch / process synchronization code 1794 */ 1795 int 1796 wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, 1797 void *cookie) 1798 { 1799 if (scr->scr_syncops) { 1800 /* 1801 * The screen is already claimed. 1802 * Check if the owner is still alive. 1803 */ 1804 if ((*scr->scr_syncops->check)(scr->scr_synccookie)) 1805 return (EBUSY); 1806 } 1807 scr->scr_syncops = ops; 1808 scr->scr_synccookie = cookie; 1809 return (0); 1810 } 1811 1812 int 1813 wsscreen_detach_sync(struct wsscreen *scr) 1814 { 1815 if (!scr->scr_syncops) 1816 return (EINVAL); 1817 scr->scr_syncops = 0; 1818 return (0); 1819 } 1820 1821 int 1822 wsscreen_lookup_sync(struct wsscreen *scr, 1823 const struct wscons_syncops *ops, /* used as ID */ 1824 void **cookiep) 1825 { 1826 if (!scr->scr_syncops || ops != scr->scr_syncops) 1827 return (EINVAL); 1828 *cookiep = scr->scr_synccookie; 1829 return (0); 1830 } 1831 1832 /* 1833 * Interface to virtual screen stuff 1834 */ 1835 int 1836 wsdisplay_maxscreenidx(struct wsdisplay_softc *sc __unused) 1837 { 1838 return (WSDISPLAY_MAXSCREEN - 1); 1839 } 1840 1841 int 1842 wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) 1843 { 1844 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 1845 return (EINVAL); 1846 if (!sc->sc_scr[idx]) 1847 return (ENXIO); 1848 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); 1849 } 1850 1851 int 1852 wsdisplay_getactivescreen(struct wsdisplay_softc *sc) 1853 { 1854 return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); 1855 } 1856 1857 int 1858 wsscreen_switchwait(struct wsdisplay_softc *sc, int no) 1859 { 1860 struct wsscreen *scr; 1861 int s, res = 0; 1862 1863 if (no == WSDISPLAY_NULLSCREEN) { 1864 s = spltty(); 1865 while (sc->sc_focus && res == 0) { 1866 res = tsleep(sc, PCATCH, "wswait", 0); 1867 } 1868 splx(s); 1869 return (res); 1870 } 1871 1872 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1873 return (ENXIO); 1874 scr = sc->sc_scr[no]; 1875 if (!scr) 1876 return (ENXIO); 1877 1878 s = spltty(); 1879 if (scr != sc->sc_focus) { 1880 scr->scr_flags |= SCR_WAITACTIVE; 1881 res = tsleep(scr, PCATCH, "wswait", 0); 1882 if (scr != sc->sc_scr[no]) 1883 res = ENXIO; /* disappeared in the meantime */ 1884 else 1885 scr->scr_flags &= ~SCR_WAITACTIVE; 1886 } 1887 splx(s); 1888 return (res); 1889 } 1890 1891 void 1892 wsdisplay_kbdholdscreen(struct device *dev, int hold) 1893 { 1894 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1895 struct wsscreen *scr; 1896 1897 scr = sc->sc_focus; 1898 1899 if (hold) 1900 scr->scr_hold_screen = 1; 1901 else { 1902 scr->scr_hold_screen = 0; 1903 callout_reset(&scr->scr_tty->t_rstrt_ch, 0, 1904 ttrstrt, scr->scr_tty); /* "immediate" */ 1905 } 1906 } 1907 1908 #if NWSKBD > 0 1909 void 1910 wsdisplay_set_console_kbd(struct wsevsrc *src) 1911 { 1912 if (wsdisplay_console_device == NULL) { 1913 src->me_dispdv = NULL; 1914 return; 1915 } 1916 #if NWSMUX > 0 1917 if (wsmux_attach_sc((struct wsmux_softc *) 1918 wsdisplay_console_device->sc_input, src)) { 1919 src->me_dispdv = NULL; 1920 return; 1921 } 1922 #else 1923 wsdisplay_console_device->sc_input = src; 1924 #endif 1925 src->me_dispdv = &wsdisplay_console_device->sc_dv; 1926 } 1927 #endif /* NWSKBD > 0 */ 1928 1929 /* 1930 * Console interface. 1931 */ 1932 void 1933 wsdisplay_cnputc(dev_t dev __unused, int i) 1934 { 1935 struct wsscreen_internal *dc; 1936 u_char c = i; 1937 1938 if (!wsdisplay_console_initted) 1939 return; 1940 1941 if ((wsdisplay_console_device != NULL) && 1942 (wsdisplay_console_device->sc_scr[0] != NULL) && 1943 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) 1944 return; 1945 1946 dc = &wsdisplay_console_conf; 1947 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); 1948 } 1949 1950 static int 1951 wsdisplay_getc_dummy(dev_t dev __unused) 1952 { 1953 /* panic? */ 1954 return (0); 1955 } 1956 1957 static void 1958 wsdisplay_pollc(dev_t dev __unused, int on) 1959 { 1960 1961 wsdisplay_cons_pollmode = on; 1962 1963 /* notify to fb drivers */ 1964 if (wsdisplay_console_device != NULL && 1965 wsdisplay_console_device->sc_accessops->pollc != NULL) 1966 (*wsdisplay_console_device->sc_accessops->pollc) 1967 (wsdisplay_console_device->sc_accesscookie, on); 1968 1969 /* notify to kbd drivers */ 1970 if (wsdisplay_cons_kbd_pollc) 1971 (*wsdisplay_cons_kbd_pollc)(NODEV, on); 1972 } 1973 1974 void 1975 wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), 1976 void (*bell)(dev_t, u_int, u_int, u_int)) 1977 { 1978 wsdisplay_cons.cn_getc = get; 1979 wsdisplay_cons.cn_bell = bell; 1980 wsdisplay_cons_kbd_pollc = poll; 1981 } 1982 1983 void 1984 wsdisplay_unset_cons_kbd(void) 1985 { 1986 wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; 1987 wsdisplay_cons.cn_bell = NULL; 1988 wsdisplay_cons_kbd_pollc = 0; 1989 } 1990 1991 /* 1992 * Switch the console display to it's first screen. 1993 */ 1994 void 1995 wsdisplay_switchtoconsole(void) 1996 { 1997 struct wsdisplay_softc *sc; 1998 struct wsscreen *scr; 1999 2000 if (wsdisplay_console_device != NULL) { 2001 sc = wsdisplay_console_device; 2002 if ((scr = sc->sc_scr[0]) == NULL) 2003 return; 2004 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 2005 scr->scr_dconf->emulcookie, 2006 0, NULL, NULL); 2007 } 2008 } 2009 2010 /* 2011 * Switch the console at shutdown. 2012 */ 2013 static void 2014 wsdisplay_shutdownhook(void *arg __unused) 2015 { 2016 2017 wsdisplay_switchtoconsole(); 2018 } 2019