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