1 /* $NetBSD: wsdisplay.c,v 1.106 2006/11/16 01:33:31 christos 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.106 2006/11/16 01:33:31 christos 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, 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, 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, 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, 569 struct cfdata *match, void *aux) 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, 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, 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 < 2); 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 = 2; 718 } 719 720 void 721 wsdisplay_preattach(const struct wsscreen_descr *type, void *cookie, 722 int ccol, int crow, long defattr) 723 { 724 const struct wsemul_ops *wsemul; 725 726 KASSERT(!wsdisplay_console_initted); 727 KASSERT(type->nrows > 0); 728 KASSERT(type->ncols > 0); 729 KASSERT(crow < type->nrows); 730 KASSERT(ccol < type->ncols); 731 732 wsdisplay_console_conf.emulops = type->textops; 733 wsdisplay_console_conf.emulcookie = cookie; 734 wsdisplay_console_conf.scrdata = type; 735 736 wsemul = wsemul_pick(0); /* default */ 737 wsdisplay_console_conf.wsemul = wsemul; 738 wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, 739 ccol, crow, 740 defattr); 741 742 cn_tab = &wsdisplay_cons; 743 wsdisplay_console_initted = 1; 744 } 745 746 /* 747 * Tty and cdevsw functions. 748 */ 749 int 750 wsdisplayopen(dev_t dev, int flag, int mode, struct lwp *l) 751 { 752 struct wsdisplay_softc *sc; 753 struct tty *tp; 754 int newopen, error; 755 struct wsscreen *scr; 756 757 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 758 if (sc == NULL) /* make sure it was attached */ 759 return (ENXIO); 760 761 if (ISWSDISPLAYSTAT(dev)) { 762 wsevent_init(&sc->evar, l->l_proc); 763 return (0); 764 } 765 766 if (ISWSDISPLAYCTL(dev)) 767 return (0); 768 769 if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) 770 return (ENXIO); 771 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 772 return (ENXIO); 773 774 if (WSSCREEN_HAS_TTY(scr)) { 775 tp = scr->scr_tty; 776 tp->t_oproc = wsdisplaystart; 777 tp->t_param = wsdisplayparam; 778 tp->t_dev = dev; 779 newopen = (tp->t_state & TS_ISOPEN) == 0; 780 781 if (kauth_authorize_device_tty(l->l_cred, 782 KAUTH_DEVICE_TTY_OPEN, tp)) 783 return (EBUSY); 784 785 if (newopen) { 786 ttychars(tp); 787 tp->t_iflag = TTYDEF_IFLAG; 788 tp->t_oflag = TTYDEF_OFLAG; 789 tp->t_cflag = TTYDEF_CFLAG; 790 tp->t_lflag = TTYDEF_LFLAG; 791 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 792 wsdisplayparam(tp, &tp->t_termios); 793 ttsetwater(tp); 794 } 795 tp->t_state |= TS_CARR_ON; 796 797 error = ((*tp->t_linesw->l_open)(dev, tp)); 798 if (error) 799 return (error); 800 801 if (newopen && WSSCREEN_HAS_EMULATOR(scr)) { 802 /* set window sizes as appropriate, and reset 803 the emulation */ 804 tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows; 805 tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols; 806 807 /* wsdisplay_set_emulation() */ 808 } 809 } 810 811 scr->scr_flags |= SCR_OPEN; 812 return (0); 813 } 814 815 int 816 wsdisplayclose(dev_t dev, int flag, int mode, struct lwp *l) 817 { 818 struct wsdisplay_softc *sc; 819 struct tty *tp; 820 struct wsscreen *scr; 821 822 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 823 824 if (ISWSDISPLAYSTAT(dev)) { 825 wsevent_fini(&sc->evar); 826 return (0); 827 } 828 829 if (ISWSDISPLAYCTL(dev)) 830 return (0); 831 832 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 833 return (0); 834 835 if (WSSCREEN_HAS_TTY(scr)) { 836 if (scr->scr_hold_screen) { 837 int s; 838 839 /* XXX RESET KEYBOARD LEDS, etc. */ 840 s = spltty(); /* avoid conflict with keyboard */ 841 wsdisplay_kbdholdscreen((struct device *)sc, 0); 842 splx(s); 843 } 844 tp = scr->scr_tty; 845 (*tp->t_linesw->l_close)(tp, flag); 846 ttyclose(tp); 847 } 848 849 if (scr->scr_syncops) 850 (*scr->scr_syncops->destroy)(scr->scr_synccookie); 851 852 if (WSSCREEN_HAS_EMULATOR(scr)) { 853 scr->scr_flags &= ~SCR_GRAPHICS; 854 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 855 WSEMUL_RESET); 856 if (wsdisplay_clearonclose) 857 (*scr->scr_dconf->wsemul->reset) 858 (scr->scr_dconf->wsemulcookie, 859 WSEMUL_CLEARSCREEN); 860 } 861 862 #ifdef WSDISPLAY_COMPAT_RAWKBD 863 if (scr->scr_rawkbd) { 864 int kbmode = WSKBD_TRANSLATED; 865 (void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, 866 (caddr_t)&kbmode, 0, l); 867 } 868 #endif 869 870 scr->scr_flags &= ~SCR_OPEN; 871 872 return (0); 873 } 874 875 int 876 wsdisplayread(dev_t dev, struct uio *uio, int flag) 877 { 878 struct wsdisplay_softc *sc; 879 struct tty *tp; 880 struct wsscreen *scr; 881 int error; 882 883 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 884 885 if (ISWSDISPLAYSTAT(dev)) { 886 error = wsevent_read(&sc->evar, uio, flag); 887 return (error); 888 } 889 890 if (ISWSDISPLAYCTL(dev)) 891 return (0); 892 893 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 894 return (ENXIO); 895 896 if (!WSSCREEN_HAS_TTY(scr)) 897 return (ENODEV); 898 899 tp = scr->scr_tty; 900 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 901 } 902 903 int 904 wsdisplaywrite(dev_t dev, struct uio *uio, int flag) 905 { 906 struct wsdisplay_softc *sc; 907 struct tty *tp; 908 struct wsscreen *scr; 909 910 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 911 912 if (ISWSDISPLAYSTAT(dev)) { 913 return (0); 914 } 915 916 if (ISWSDISPLAYCTL(dev)) 917 return (0); 918 919 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 920 return (ENXIO); 921 922 if (!WSSCREEN_HAS_TTY(scr)) 923 return (ENODEV); 924 925 tp = scr->scr_tty; 926 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 927 } 928 929 int 930 wsdisplaypoll(dev_t dev, int events, struct lwp *l) 931 { 932 struct wsdisplay_softc *sc; 933 struct tty *tp; 934 struct wsscreen *scr; 935 936 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 937 938 if (ISWSDISPLAYSTAT(dev)) 939 return (wsevent_poll(&sc->evar, events, l)); 940 941 if (ISWSDISPLAYCTL(dev)) 942 return (0); 943 944 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 945 return (POLLHUP); 946 947 if (!WSSCREEN_HAS_TTY(scr)) 948 return (POLLERR); 949 950 tp = scr->scr_tty; 951 return ((*tp->t_linesw->l_poll)(tp, events, l)); 952 } 953 954 int 955 wsdisplaykqfilter(dev, kn) 956 dev_t dev; 957 struct knote *kn; 958 { 959 struct wsdisplay_softc *sc = 960 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 961 struct wsscreen *scr; 962 963 if (ISWSDISPLAYCTL(dev)) 964 return (1); 965 966 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 967 return (1); 968 969 970 if (WSSCREEN_HAS_TTY(scr)) 971 return (ttykqfilter(dev, kn)); 972 else 973 return (1); 974 } 975 976 struct tty * 977 wsdisplaytty(dev_t dev) 978 { 979 struct wsdisplay_softc *sc; 980 struct wsscreen *scr; 981 982 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 983 984 if (ISWSDISPLAYSTAT(dev)) 985 panic("wsdisplaytty() on status device"); 986 987 if (ISWSDISPLAYCTL(dev)) 988 panic("wsdisplaytty() on ctl device"); 989 990 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 991 return NULL; 992 993 return (scr->scr_tty); 994 } 995 996 int 997 wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l) 998 { 999 struct wsdisplay_softc *sc; 1000 struct tty *tp; 1001 int error; 1002 struct wsscreen *scr; 1003 1004 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 1005 1006 #ifdef WSDISPLAY_COMPAT_USL 1007 error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, l); 1008 if (error != EPASSTHROUGH) 1009 return (error); 1010 #endif 1011 1012 if (ISWSDISPLAYSTAT(dev)) 1013 return (wsdisplay_stat_ioctl(sc, cmd, data, flag, l)); 1014 1015 if (ISWSDISPLAYCTL(dev)) 1016 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, l)); 1017 1018 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 1019 return (ENXIO); 1020 1021 if (WSSCREEN_HAS_TTY(scr)) { 1022 tp = scr->scr_tty; 1023 1024 /* printf("disc\n"); */ 1025 /* do the line discipline ioctls first */ 1026 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 1027 if (error != EPASSTHROUGH) 1028 return (error); 1029 1030 /* printf("tty\n"); */ 1031 /* then the tty ioctls */ 1032 error = ttioctl(tp, cmd, data, flag, l); 1033 if (error != EPASSTHROUGH) 1034 return (error); 1035 } 1036 1037 #ifdef WSDISPLAY_COMPAT_USL 1038 error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, l); 1039 if (error != EPASSTHROUGH) 1040 return (error); 1041 #endif 1042 1043 return (wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, l)); 1044 } 1045 1046 int 1047 wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp) 1048 { 1049 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1050 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1051 sc->sc_focus->scr_dconf->emulcookie, 1052 cmd, (caddr_t)dp, 0, NULL)); 1053 } 1054 1055 int 1056 wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, 1057 u_long cmd, caddr_t data, int flag, struct lwp *l) 1058 { 1059 int error; 1060 char namebuf[16]; 1061 struct wsdisplay_font fd; 1062 #ifdef WSDISPLAY_SCROLLSUPPORT 1063 struct wsdisplay_scroll_data *ksdp, *usdp; 1064 #endif 1065 1066 #if NWSKBD > 0 1067 struct wsevsrc *inp; 1068 1069 #ifdef WSDISPLAY_COMPAT_RAWKBD 1070 switch (cmd) { 1071 case WSKBDIO_SETMODE: 1072 scr->scr_rawkbd = (*(int *)data == WSKBD_RAW); 1073 return (wsdisplay_update_rawkbd(sc, scr)); 1074 case WSKBDIO_GETMODE: 1075 *(int *)data = (scr->scr_rawkbd ? 1076 WSKBD_RAW : WSKBD_TRANSLATED); 1077 return (0); 1078 } 1079 #endif 1080 inp = sc->sc_input; 1081 if (inp == NULL) 1082 return (ENXIO); 1083 error = wsevsrc_display_ioctl(inp, cmd, data, flag, l); 1084 if (error != EPASSTHROUGH) 1085 return (error); 1086 #endif /* NWSKBD > 0 */ 1087 1088 switch (cmd) { 1089 case WSDISPLAYIO_GMODE: 1090 if (scr->scr_flags & SCR_GRAPHICS) { 1091 if (scr->scr_flags & SCR_DUMBFB) 1092 *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB; 1093 else 1094 *(u_int *)data = WSDISPLAYIO_MODE_MAPPED; 1095 } else 1096 *(u_int *)data = WSDISPLAYIO_MODE_EMUL; 1097 return (0); 1098 1099 case WSDISPLAYIO_SMODE: 1100 #define d (*(int *)data) 1101 if (d != WSDISPLAYIO_MODE_EMUL && 1102 d != WSDISPLAYIO_MODE_MAPPED && 1103 d != WSDISPLAYIO_MODE_DUMBFB) 1104 return (EINVAL); 1105 1106 if (WSSCREEN_HAS_EMULATOR(scr)) { 1107 scr->scr_flags &= ~SCR_GRAPHICS; 1108 if (d == WSDISPLAYIO_MODE_MAPPED || 1109 d == WSDISPLAYIO_MODE_DUMBFB) 1110 scr->scr_flags |= SCR_GRAPHICS | 1111 ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0); 1112 } else if (d == WSDISPLAYIO_MODE_EMUL) 1113 return (EINVAL); 1114 1115 (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1116 scr->scr_dconf->emulcookie, cmd, data, flag, l); 1117 1118 return (0); 1119 #undef d 1120 1121 #ifdef WSDISPLAY_SCROLLSUPPORT 1122 #define SETSCROLLLINES(dstp, srcp, dfltp) \ 1123 do { \ 1124 (dstp)->fastlines = ((srcp)->which & \ 1125 WSDISPLAY_SCROLL_DOFASTLINES) ? \ 1126 (srcp)->fastlines : (dfltp)->fastlines; \ 1127 (dstp)->slowlines = ((srcp)->which & \ 1128 WSDISPLAY_SCROLL_DOSLOWLINES) ? \ 1129 (srcp)->slowlines : (dfltp)->slowlines; \ 1130 (dstp)->which = WSDISPLAY_SCROLL_DOALL; \ 1131 } while (0) 1132 1133 1134 case WSDISPLAYIO_DSSCROLL: 1135 usdp = (struct wsdisplay_scroll_data *)data; 1136 ksdp = &sc->sc_scroll_values; 1137 SETSCROLLLINES(ksdp, usdp, ksdp); 1138 return (0); 1139 1140 case WSDISPLAYIO_DGSCROLL: 1141 usdp = (struct wsdisplay_scroll_data *)data; 1142 ksdp = &sc->sc_scroll_values; 1143 SETSCROLLLINES(usdp, ksdp, ksdp); 1144 return (0); 1145 #else 1146 case WSDISPLAYIO_DSSCROLL: 1147 case WSDISPLAYIO_DGSCROLL: 1148 return ENODEV; 1149 #endif 1150 1151 case WSDISPLAYIO_SFONT: 1152 #define d ((struct wsdisplay_usefontdata *)data) 1153 if (!sc->sc_accessops->load_font) 1154 return (EINVAL); 1155 if (d->name) { 1156 error = copyinstr(d->name, namebuf, sizeof(namebuf), 0); 1157 if (error) 1158 return (error); 1159 fd.name = namebuf; 1160 } else 1161 fd.name = 0; 1162 fd.data = 0; 1163 error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 1164 scr->scr_dconf->emulcookie, &fd); 1165 if (!error && WSSCREEN_HAS_EMULATOR(scr)) 1166 (*scr->scr_dconf->wsemul->reset) 1167 (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT); 1168 return (error); 1169 #undef d 1170 1171 #ifdef WSDISPLAY_CUSTOM_OUTPUT 1172 case WSDISPLAYIO_GMSGATTRS: 1173 #define d ((struct wsdisplay_msgattrs *)data) 1174 (*scr->scr_dconf->wsemul->getmsgattrs) 1175 (scr->scr_dconf->wsemulcookie, d); 1176 return (0); 1177 #undef d 1178 1179 case WSDISPLAYIO_SMSGATTRS: { 1180 #define d ((struct wsdisplay_msgattrs *)data) 1181 int i; 1182 for (i = 0; i < WSDISPLAY_MAXSCREEN; i++) 1183 if (sc->sc_scr[i] != NULL) 1184 (*sc->sc_scr[i]->scr_dconf->wsemul->setmsgattrs) 1185 (sc->sc_scr[i]->scr_dconf->wsemulcookie, 1186 sc->sc_scr[i]->scr_dconf->scrdata, 1187 d); 1188 } 1189 return (0); 1190 #undef d 1191 #else 1192 case WSDISPLAYIO_GMSGATTRS: 1193 case WSDISPLAYIO_SMSGATTRS: 1194 return (ENODEV); 1195 #endif 1196 } 1197 1198 /* check ioctls for display */ 1199 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1200 scr->scr_dconf->emulcookie, cmd, data, flag, l)); 1201 } 1202 1203 int 1204 wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1205 int flag, struct lwp *l) 1206 { 1207 switch (cmd) { 1208 case WSDISPLAYIO_GETACTIVESCREEN: 1209 *(int*)data = wsdisplay_getactivescreen(sc); 1210 return (0); 1211 } 1212 1213 return (EPASSTHROUGH); 1214 } 1215 1216 int 1217 wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1218 int flag, struct lwp *l) 1219 { 1220 int error; 1221 char *type, typebuf[16], *emul, emulbuf[16]; 1222 void *tbuf; 1223 u_int fontsz; 1224 #if defined(COMPAT_14) && NWSKBD > 0 1225 struct wsmux_device wsmuxdata; 1226 #endif 1227 #if NWSKBD > 0 1228 struct wsevsrc *inp; 1229 #endif 1230 1231 switch (cmd) { 1232 case WSDISPLAYIO_ADDSCREEN: 1233 #define d ((struct wsdisplay_addscreendata *)data) 1234 if (d->screentype) { 1235 error = copyinstr(d->screentype, typebuf, 1236 sizeof(typebuf), 0); 1237 if (error) 1238 return (error); 1239 type = typebuf; 1240 } else 1241 type = 0; 1242 if (d->emul) { 1243 error = copyinstr(d->emul, emulbuf, sizeof(emulbuf),0); 1244 if (error) 1245 return (error); 1246 emul = emulbuf; 1247 } else 1248 emul = 0; 1249 1250 if ((error = wsdisplay_addscreen(sc, d->idx, type, emul)) == 0) 1251 wsdisplay_addscreen_print(sc, d->idx, 0); 1252 return (error); 1253 #undef d 1254 case WSDISPLAYIO_DELSCREEN: 1255 #define d ((struct wsdisplay_delscreendata *)data) 1256 return (wsdisplay_delscreen(sc, d->idx, d->flags)); 1257 #undef d 1258 case WSDISPLAYIO_LDFONT: 1259 #define d ((struct wsdisplay_font *)data) 1260 if (!sc->sc_accessops->load_font) 1261 return (EINVAL); 1262 if (d->name) { 1263 error = copyinstr(d->name, typebuf, sizeof(typebuf), 0); 1264 if (error) 1265 return (error); 1266 d->name = typebuf; 1267 } else 1268 d->name = "loaded"; /* ??? */ 1269 fontsz = d->fontheight * d->stride * d->numchars; 1270 if (fontsz > WSDISPLAY_MAXFONTSZ) 1271 return (EINVAL); 1272 1273 tbuf = malloc(fontsz, M_DEVBUF, M_WAITOK); 1274 error = copyin(d->data, tbuf, fontsz); 1275 if (error) { 1276 free(tbuf, M_DEVBUF); 1277 return (error); 1278 } 1279 d->data = tbuf; 1280 error = 1281 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); 1282 free(tbuf, M_DEVBUF); 1283 #undef d 1284 return (error); 1285 1286 #if NWSKBD > 0 1287 #ifdef COMPAT_14 1288 case _O_WSDISPLAYIO_SETKEYBOARD: 1289 #define d ((struct wsdisplay_kbddata *)data) 1290 inp = sc->sc_input; 1291 if (inp == NULL) 1292 return (ENXIO); 1293 switch (d->op) { 1294 case _O_WSDISPLAY_KBD_ADD: 1295 if (d->idx == -1) { 1296 d->idx = wskbd_pickfree(); 1297 if (d->idx == -1) 1298 return (ENXIO); 1299 } 1300 wsmuxdata.type = WSMUX_KBD; 1301 wsmuxdata.idx = d->idx; 1302 return (wsevsrc_ioctl(inp, WSMUX_ADD_DEVICE, 1303 &wsmuxdata, flag, l)); 1304 case _O_WSDISPLAY_KBD_DEL: 1305 wsmuxdata.type = WSMUX_KBD; 1306 wsmuxdata.idx = d->idx; 1307 return (wsevsrc_ioctl(inp, WSMUX_REMOVE_DEVICE, 1308 &wsmuxdata, flag, l)); 1309 default: 1310 return (EINVAL); 1311 } 1312 #undef d 1313 #endif 1314 1315 case WSMUXIO_ADD_DEVICE: 1316 #define d ((struct wsmux_device *)data) 1317 if (d->idx == -1 && d->type == WSMUX_KBD) 1318 d->idx = wskbd_pickfree(); 1319 #undef d 1320 /* fall into */ 1321 case WSMUXIO_INJECTEVENT: 1322 case WSMUXIO_REMOVE_DEVICE: 1323 case WSMUXIO_LIST_DEVICES: 1324 inp = sc->sc_input; 1325 if (inp == NULL) 1326 return (ENXIO); 1327 return (wsevsrc_ioctl(inp, cmd, data, flag, l)); 1328 #endif /* NWSKBD > 0 */ 1329 1330 } 1331 return (EPASSTHROUGH); 1332 } 1333 1334 int 1335 wsdisplay_stat_inject(struct device *dev, u_int type, int value) 1336 { 1337 struct wsdisplay_softc *sc = (struct wsdisplay_softc *) dev; 1338 struct wseventvar *evar; 1339 struct wscons_event event; 1340 1341 evar = &sc->evar; 1342 1343 if (evar == NULL) 1344 return (0); 1345 1346 if (evar->q == NULL) 1347 return (1); 1348 1349 event.type = type; 1350 event.value = value; 1351 if (wsevent_inject(evar, &event, 1) != 0) { 1352 log(LOG_WARNING, "wsdisplay: event queue overflow\n"); 1353 return (1); 1354 } 1355 1356 return (0); 1357 } 1358 1359 paddr_t 1360 wsdisplaymmap(dev_t dev, off_t offset, int prot) 1361 { 1362 struct wsdisplay_softc *sc = 1363 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 1364 struct wsscreen *scr; 1365 1366 if (ISWSDISPLAYSTAT(dev)) 1367 return (-1); 1368 1369 if (ISWSDISPLAYCTL(dev)) 1370 return (-1); 1371 1372 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 1373 return (-1); 1374 1375 if (!(scr->scr_flags & SCR_GRAPHICS)) 1376 return (-1); 1377 1378 /* pass mmap to display */ 1379 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, 1380 scr->scr_dconf->emulcookie, offset, prot)); 1381 } 1382 1383 void 1384 wsdisplaystart(struct tty *tp) 1385 { 1386 struct wsdisplay_softc *sc; 1387 struct wsscreen *scr; 1388 int s, n; 1389 u_char *tbuf; 1390 1391 s = spltty(); 1392 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 1393 splx(s); 1394 return; 1395 } 1396 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(tp->t_dev)); 1397 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { 1398 splx(s); 1399 return; 1400 } 1401 1402 if (scr->scr_hold_screen) { 1403 tp->t_state |= TS_TIMEOUT; 1404 splx(s); 1405 return; 1406 } 1407 tp->t_state |= TS_BUSY; 1408 splx(s); 1409 1410 /* 1411 * Drain output from ring buffer. 1412 * The output will normally be in one contiguous chunk, but when the 1413 * ring wraps, it will be in two pieces.. one at the end of the ring, 1414 * the other at the start. For performance, rather than loop here, 1415 * we output one chunk, see if there's another one, and if so, output 1416 * it too. 1417 */ 1418 1419 n = ndqb(&tp->t_outq, 0); 1420 tbuf = tp->t_outq.c_cf; 1421 1422 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1423 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1424 (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie, 1425 tbuf, n, 0); 1426 } 1427 ndflush(&tp->t_outq, n); 1428 1429 if ((n = ndqb(&tp->t_outq, 0)) > 0) { 1430 tbuf = tp->t_outq.c_cf; 1431 1432 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1433 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1434 (*scr->scr_dconf->wsemul->output) 1435 (scr->scr_dconf->wsemulcookie, tbuf, n, 0); 1436 } 1437 ndflush(&tp->t_outq, n); 1438 } 1439 1440 s = spltty(); 1441 tp->t_state &= ~TS_BUSY; 1442 /* Come back if there's more to do */ 1443 if (tp->t_outq.c_cc) { 1444 tp->t_state |= TS_TIMEOUT; 1445 callout_reset(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1, 1446 ttrstrt, tp); 1447 } 1448 if (tp->t_outq.c_cc <= tp->t_lowat) { 1449 if (tp->t_state&TS_ASLEEP) { 1450 tp->t_state &= ~TS_ASLEEP; 1451 wakeup(&tp->t_outq); 1452 } 1453 selwakeup(&tp->t_wsel); 1454 } 1455 splx(s); 1456 } 1457 1458 void 1459 wsdisplaystop(struct tty *tp, int flag) 1460 { 1461 int s; 1462 1463 s = spltty(); 1464 if (ISSET(tp->t_state, TS_BUSY)) 1465 if (!ISSET(tp->t_state, TS_TTSTOP)) 1466 SET(tp->t_state, TS_FLUSH); 1467 splx(s); 1468 } 1469 1470 /* Set line parameters. */ 1471 int 1472 wsdisplayparam(struct tty *tp, struct termios *t) 1473 { 1474 1475 tp->t_ispeed = t->c_ispeed; 1476 tp->t_ospeed = t->c_ospeed; 1477 tp->t_cflag = t->c_cflag; 1478 return 0; 1479 } 1480 1481 /* 1482 * Callbacks for the emulation code. 1483 */ 1484 void 1485 wsdisplay_emulbell(void *v) 1486 { 1487 struct wsscreen *scr = v; 1488 1489 if (scr == NULL) /* console, before real attach */ 1490 return; 1491 1492 if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ 1493 return; 1494 1495 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, 1496 FWRITE, NULL); 1497 } 1498 1499 void 1500 wsdisplay_emulinput(void *v, const u_char *data, u_int count) 1501 { 1502 struct wsscreen *scr = v; 1503 struct tty *tp; 1504 1505 if (v == NULL) /* console, before real attach */ 1506 return; 1507 1508 if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ 1509 return; 1510 if (!WSSCREEN_HAS_TTY(scr)) 1511 return; 1512 1513 tp = scr->scr_tty; 1514 while (count-- > 0) 1515 (*tp->t_linesw->l_rint)(*data++, tp); 1516 } 1517 1518 /* 1519 * Calls from the keyboard interface. 1520 */ 1521 void 1522 wsdisplay_kbdinput(struct device *dev, keysym_t ks) 1523 { 1524 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1525 struct wsscreen *scr; 1526 const char *dp; 1527 int count; 1528 struct tty *tp; 1529 1530 KASSERT(sc != NULL); 1531 1532 scr = sc->sc_focus; 1533 1534 if (!scr || !WSSCREEN_HAS_TTY(scr)) 1535 return; 1536 1537 tp = scr->scr_tty; 1538 1539 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1540 (*tp->t_linesw->l_rint)(KS_VALUE(ks), tp); 1541 else if (WSSCREEN_HAS_EMULATOR(scr)) { 1542 count = (*scr->scr_dconf->wsemul->translate) 1543 (scr->scr_dconf->wsemulcookie, ks, &dp); 1544 while (count-- > 0) 1545 (*tp->t_linesw->l_rint)(*dp++, tp); 1546 } 1547 } 1548 1549 #if defined(WSDISPLAY_COMPAT_RAWKBD) 1550 int 1551 wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) 1552 { 1553 #if NWSKBD > 0 1554 int s, raw, data, error; 1555 struct wsevsrc *inp; 1556 1557 s = spltty(); 1558 1559 raw = (scr ? scr->scr_rawkbd : 0); 1560 1561 if (scr != sc->sc_focus || 1562 sc->sc_rawkbd == raw) { 1563 splx(s); 1564 return (0); 1565 } 1566 1567 data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; 1568 inp = sc->sc_input; 1569 if (inp == NULL) { 1570 splx(s); 1571 return (ENXIO); 1572 } 1573 error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0); 1574 if (!error) 1575 sc->sc_rawkbd = raw; 1576 splx(s); 1577 return (error); 1578 #else 1579 return (0); 1580 #endif 1581 } 1582 #endif 1583 1584 int 1585 wsdisplay_switch3(void *arg, int error, int waitok) 1586 { 1587 struct wsdisplay_softc *sc = arg; 1588 int no; 1589 struct wsscreen *scr; 1590 1591 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1592 printf("wsdisplay_switch3: not switching\n"); 1593 return (EINVAL); 1594 } 1595 1596 no = sc->sc_screenwanted; 1597 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1598 panic("wsdisplay_switch3: invalid screen %d", no); 1599 scr = sc->sc_scr[no]; 1600 if (!scr) { 1601 printf("wsdisplay_switch3: screen %d disappeared\n", no); 1602 error = ENXIO; 1603 } 1604 1605 if (error) { 1606 /* try to recover, avoid recursion */ 1607 1608 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1609 printf("wsdisplay_switch3: giving up\n"); 1610 sc->sc_focus = 0; 1611 #ifdef WSDISPLAY_COMPAT_RAWKBD 1612 wsdisplay_update_rawkbd(sc, 0); 1613 #endif 1614 sc->sc_flags &= ~SC_SWITCHPENDING; 1615 return (error); 1616 } 1617 1618 sc->sc_screenwanted = sc->sc_oldscreen; 1619 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1620 return (wsdisplay_switch1(arg, 0, waitok)); 1621 } 1622 1623 sc->sc_flags &= ~SC_SWITCHPENDING; 1624 1625 if (!error && (scr->scr_flags & SCR_WAITACTIVE)) 1626 wakeup(scr); 1627 return (error); 1628 } 1629 1630 int 1631 wsdisplay_switch2(void *arg, int error, int waitok) 1632 { 1633 struct wsdisplay_softc *sc = arg; 1634 int no; 1635 struct wsscreen *scr; 1636 1637 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1638 printf("wsdisplay_switch2: not switching\n"); 1639 return (EINVAL); 1640 } 1641 1642 no = sc->sc_screenwanted; 1643 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1644 panic("wsdisplay_switch2: invalid screen %d", no); 1645 scr = sc->sc_scr[no]; 1646 if (!scr) { 1647 printf("wsdisplay_switch2: screen %d disappeared\n", no); 1648 error = ENXIO; 1649 } 1650 1651 if (error) { 1652 /* try to recover, avoid recursion */ 1653 1654 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1655 printf("wsdisplay_switch2: giving up\n"); 1656 sc->sc_focus = 0; 1657 sc->sc_flags &= ~SC_SWITCHPENDING; 1658 return (error); 1659 } 1660 1661 sc->sc_screenwanted = sc->sc_oldscreen; 1662 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1663 return (wsdisplay_switch1(arg, 0, waitok)); 1664 } 1665 1666 sc->sc_focusidx = no; 1667 sc->sc_focus = scr; 1668 1669 #ifdef WSDISPLAY_COMPAT_RAWKBD 1670 (void) wsdisplay_update_rawkbd(sc, scr); 1671 #endif 1672 /* keyboard map??? */ 1673 1674 #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3) 1675 if (scr->scr_syncops) { 1676 error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, 1677 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); 1678 if (error == EAGAIN) { 1679 /* switch will be done asynchronously */ 1680 return (0); 1681 } 1682 } 1683 1684 return (wsdisplay_switch3(sc, error, waitok)); 1685 } 1686 1687 int 1688 wsdisplay_switch1(void *arg, int error, int waitok) 1689 { 1690 struct wsdisplay_softc *sc = arg; 1691 int no; 1692 struct wsscreen *scr; 1693 1694 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1695 printf("wsdisplay_switch1: not switching\n"); 1696 return (EINVAL); 1697 } 1698 1699 no = sc->sc_screenwanted; 1700 if (no == WSDISPLAY_NULLSCREEN) { 1701 sc->sc_flags &= ~SC_SWITCHPENDING; 1702 if (!error) { 1703 sc->sc_focus = 0; 1704 } 1705 wakeup(sc); 1706 return (error); 1707 } 1708 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1709 panic("wsdisplay_switch1: invalid screen %d", no); 1710 scr = sc->sc_scr[no]; 1711 if (!scr) { 1712 printf("wsdisplay_switch1: screen %d disappeared\n", no); 1713 error = ENXIO; 1714 } 1715 1716 if (error) { 1717 sc->sc_flags &= ~SC_SWITCHPENDING; 1718 return (error); 1719 } 1720 1721 #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2) 1722 error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 1723 scr->scr_dconf->emulcookie, 1724 waitok, 1725 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); 1726 if (error == EAGAIN) { 1727 /* switch will be done asynchronously */ 1728 return (0); 1729 } 1730 1731 return (wsdisplay_switch2(sc, error, waitok)); 1732 } 1733 1734 int 1735 wsdisplay_switch(struct device *dev, int no, int waitok) 1736 { 1737 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1738 int s, res = 0; 1739 struct wsscreen *scr; 1740 1741 if (no != WSDISPLAY_NULLSCREEN) { 1742 if ((no < 0 || no >= WSDISPLAY_MAXSCREEN)) 1743 return (EINVAL); 1744 if (sc->sc_scr[no] == NULL) 1745 return (ENXIO); 1746 } 1747 1748 wsdisplay_stat_inject(dev, WSCONS_EVENT_SCREEN_SWITCH, no); 1749 1750 s = spltty(); 1751 1752 if ((sc->sc_focus && no == sc->sc_focusidx) || 1753 (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) { 1754 splx(s); 1755 return (0); 1756 } 1757 1758 if (sc->sc_flags & SC_SWITCHPENDING) { 1759 splx(s); 1760 return (EBUSY); 1761 } 1762 1763 sc->sc_flags |= SC_SWITCHPENDING; 1764 sc->sc_screenwanted = no; 1765 1766 splx(s); 1767 1768 scr = sc->sc_focus; 1769 if (!scr) { 1770 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1771 return (wsdisplay_switch1(sc, 0, waitok)); 1772 } else 1773 sc->sc_oldscreen = sc->sc_focusidx; 1774 1775 #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) 1776 if (scr->scr_syncops) { 1777 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, 1778 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); 1779 if (res == EAGAIN) { 1780 /* switch will be done asynchronously */ 1781 return (0); 1782 } 1783 } else if (scr->scr_flags & SCR_GRAPHICS) { 1784 /* no way to save state */ 1785 res = EBUSY; 1786 } 1787 1788 return (wsdisplay_switch1(sc, res, waitok)); 1789 } 1790 1791 void 1792 wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) 1793 { 1794 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1795 struct wsscreen *scr; 1796 1797 KASSERT(sc != NULL); 1798 scr = sc->sc_focus; 1799 1800 if (!scr) 1801 return; 1802 1803 switch (op) { 1804 case WSDISPLAY_RESETEMUL: 1805 if (!WSSCREEN_HAS_EMULATOR(scr)) 1806 break; 1807 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 1808 WSEMUL_RESET); 1809 break; 1810 case WSDISPLAY_RESETCLOSE: 1811 wsdisplay_closescreen(sc, scr); 1812 break; 1813 } 1814 } 1815 1816 /* 1817 * Interface for (external) VT switch / process synchronization code 1818 */ 1819 int 1820 wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, 1821 void *cookie) 1822 { 1823 if (scr->scr_syncops) { 1824 /* 1825 * The screen is already claimed. 1826 * Check if the owner is still alive. 1827 */ 1828 if ((*scr->scr_syncops->check)(scr->scr_synccookie)) 1829 return (EBUSY); 1830 } 1831 scr->scr_syncops = ops; 1832 scr->scr_synccookie = cookie; 1833 return (0); 1834 } 1835 1836 int 1837 wsscreen_detach_sync(struct wsscreen *scr) 1838 { 1839 if (!scr->scr_syncops) 1840 return (EINVAL); 1841 scr->scr_syncops = 0; 1842 return (0); 1843 } 1844 1845 int 1846 wsscreen_lookup_sync(struct wsscreen *scr, 1847 const struct wscons_syncops *ops, /* used as ID */ 1848 void **cookiep) 1849 { 1850 if (!scr->scr_syncops || ops != scr->scr_syncops) 1851 return (EINVAL); 1852 *cookiep = scr->scr_synccookie; 1853 return (0); 1854 } 1855 1856 /* 1857 * Interface to virtual screen stuff 1858 */ 1859 int 1860 wsdisplay_maxscreenidx(struct wsdisplay_softc *sc) 1861 { 1862 return (WSDISPLAY_MAXSCREEN - 1); 1863 } 1864 1865 int 1866 wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) 1867 { 1868 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 1869 return (EINVAL); 1870 if (!sc->sc_scr[idx]) 1871 return (ENXIO); 1872 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); 1873 } 1874 1875 int 1876 wsdisplay_getactivescreen(struct wsdisplay_softc *sc) 1877 { 1878 return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); 1879 } 1880 1881 int 1882 wsscreen_switchwait(struct wsdisplay_softc *sc, int no) 1883 { 1884 struct wsscreen *scr; 1885 int s, res = 0; 1886 1887 if (no == WSDISPLAY_NULLSCREEN) { 1888 s = spltty(); 1889 while (sc->sc_focus && res == 0) { 1890 res = tsleep(sc, PCATCH, "wswait", 0); 1891 } 1892 splx(s); 1893 return (res); 1894 } 1895 1896 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1897 return (ENXIO); 1898 scr = sc->sc_scr[no]; 1899 if (!scr) 1900 return (ENXIO); 1901 1902 s = spltty(); 1903 if (scr != sc->sc_focus) { 1904 scr->scr_flags |= SCR_WAITACTIVE; 1905 res = tsleep(scr, PCATCH, "wswait", 0); 1906 if (scr != sc->sc_scr[no]) 1907 res = ENXIO; /* disappeared in the meantime */ 1908 else 1909 scr->scr_flags &= ~SCR_WAITACTIVE; 1910 } 1911 splx(s); 1912 return (res); 1913 } 1914 1915 void 1916 wsdisplay_kbdholdscreen(struct device *dev, int hold) 1917 { 1918 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1919 struct wsscreen *scr; 1920 1921 scr = sc->sc_focus; 1922 1923 if (hold) 1924 scr->scr_hold_screen = 1; 1925 else { 1926 scr->scr_hold_screen = 0; 1927 callout_reset(&scr->scr_tty->t_rstrt_ch, 0, 1928 ttrstrt, scr->scr_tty); /* "immediate" */ 1929 } 1930 } 1931 1932 #if NWSKBD > 0 1933 void 1934 wsdisplay_set_console_kbd(struct wsevsrc *src) 1935 { 1936 if (wsdisplay_console_device == NULL) { 1937 src->me_dispdv = NULL; 1938 return; 1939 } 1940 #if NWSMUX > 0 1941 if (wsmux_attach_sc((struct wsmux_softc *) 1942 wsdisplay_console_device->sc_input, src)) { 1943 src->me_dispdv = NULL; 1944 return; 1945 } 1946 #else 1947 wsdisplay_console_device->sc_input = src; 1948 #endif 1949 src->me_dispdv = &wsdisplay_console_device->sc_dv; 1950 } 1951 #endif /* NWSKBD > 0 */ 1952 1953 /* 1954 * Console interface. 1955 */ 1956 void 1957 wsdisplay_cnputc(dev_t dev, int i) 1958 { 1959 struct wsscreen_internal *dc; 1960 u_char c = i; 1961 1962 if (!wsdisplay_console_initted) 1963 return; 1964 1965 if ((wsdisplay_console_device != NULL) && 1966 (wsdisplay_console_device->sc_scr[0] != NULL) && 1967 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) 1968 return; 1969 1970 dc = &wsdisplay_console_conf; 1971 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); 1972 } 1973 1974 static int 1975 wsdisplay_getc_dummy(dev_t dev) 1976 { 1977 /* panic? */ 1978 return (0); 1979 } 1980 1981 static void 1982 wsdisplay_pollc(dev_t dev, int on) 1983 { 1984 1985 wsdisplay_cons_pollmode = on; 1986 1987 /* notify to fb drivers */ 1988 if (wsdisplay_console_device != NULL && 1989 wsdisplay_console_device->sc_accessops->pollc != NULL) 1990 (*wsdisplay_console_device->sc_accessops->pollc) 1991 (wsdisplay_console_device->sc_accesscookie, on); 1992 1993 /* notify to kbd drivers */ 1994 if (wsdisplay_cons_kbd_pollc) 1995 (*wsdisplay_cons_kbd_pollc)(NODEV, on); 1996 } 1997 1998 void 1999 wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), 2000 void (*bell)(dev_t, u_int, u_int, u_int)) 2001 { 2002 wsdisplay_cons.cn_getc = get; 2003 wsdisplay_cons.cn_bell = bell; 2004 wsdisplay_cons_kbd_pollc = poll; 2005 } 2006 2007 void 2008 wsdisplay_unset_cons_kbd(void) 2009 { 2010 wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; 2011 wsdisplay_cons.cn_bell = NULL; 2012 wsdisplay_cons_kbd_pollc = 0; 2013 } 2014 2015 /* 2016 * Switch the console display to it's first screen. 2017 */ 2018 void 2019 wsdisplay_switchtoconsole(void) 2020 { 2021 struct wsdisplay_softc *sc; 2022 struct wsscreen *scr; 2023 2024 if (wsdisplay_console_device != NULL) { 2025 sc = wsdisplay_console_device; 2026 if ((scr = sc->sc_scr[0]) == NULL) 2027 return; 2028 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 2029 scr->scr_dconf->emulcookie, 2030 0, NULL, NULL); 2031 } 2032 } 2033 2034 /* 2035 * Switch the console at shutdown. 2036 */ 2037 static void 2038 wsdisplay_shutdownhook(void *arg) 2039 { 2040 2041 wsdisplay_switchtoconsole(); 2042 } 2043