1 /* $NetBSD: wsdisplay.c,v 1.85 2005/09/06 21:40:45 kleink 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.85 2005/09/06 21:40:45 kleink 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 /* Internal macros, functions, and variables. */ 190 #define SET(t, f) (t) |= (f) 191 #define CLR(t, f) (t) &= ~(f) 192 #define ISSET(t, f) ((t) & (f)) 193 194 #define WSDISPLAYUNIT(dev) (minor(dev) >> 8) 195 #define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff) 196 #define ISWSDISPLAYSTAT(dev) (WSDISPLAYSCREEN(dev) == 254) 197 #define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255) 198 #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen)) 199 200 #define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL) 201 #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL) 202 203 static void wsdisplay_common_attach(struct wsdisplay_softc *sc, 204 int console, int kbdmux, const struct wsscreen_list *, 205 const struct wsdisplay_accessops *accessops, 206 void *accesscookie); 207 208 #ifdef WSDISPLAY_COMPAT_RAWKBD 209 int wsdisplay_update_rawkbd(struct wsdisplay_softc *, 210 struct wsscreen *); 211 #endif 212 213 static int wsdisplay_console_initted; 214 static struct wsdisplay_softc *wsdisplay_console_device; 215 static struct wsscreen_internal wsdisplay_console_conf; 216 217 static int wsdisplay_getc_dummy(dev_t); 218 static void wsdisplay_pollc(dev_t, int); 219 220 static int wsdisplay_cons_pollmode; 221 static void (*wsdisplay_cons_kbd_pollc)(dev_t, int); 222 223 static struct consdev wsdisplay_cons = { 224 NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, 225 wsdisplay_pollc, NULL, NULL, NULL, NODEV, CN_NORMAL 226 }; 227 228 #ifndef WSDISPLAY_DEFAULTSCREENS 229 # define WSDISPLAY_DEFAULTSCREENS 0 230 #endif 231 int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; 232 233 int wsdisplay_switch1(void *, int, int); 234 int wsdisplay_switch2(void *, int, int); 235 int wsdisplay_switch3(void *, int, int); 236 237 int wsdisplay_clearonclose; 238 239 struct wsscreen * 240 wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul, 241 const struct wsscreen_descr *type, void *cookie, int ccol, 242 int crow, long defattr) 243 { 244 struct wsscreen_internal *dconf; 245 struct wsscreen *scr; 246 247 scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_WAITOK); 248 if (!scr) 249 return (NULL); 250 251 if (console) { 252 dconf = &wsdisplay_console_conf; 253 /* 254 * If there's an emulation, tell it about the callback argument. 255 * The other stuff is already there. 256 */ 257 if (dconf->wsemul != NULL) 258 (*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0); 259 } else { /* not console */ 260 dconf = malloc(sizeof(struct wsscreen_internal), 261 M_DEVBUF, M_NOWAIT); 262 dconf->emulops = type->textops; 263 dconf->emulcookie = cookie; 264 if (dconf->emulops) { 265 dconf->wsemul = wsemul_pick(emul); 266 if (dconf->wsemul == NULL) { 267 free(dconf, M_DEVBUF); 268 free(scr, M_DEVBUF); 269 return (NULL); 270 } 271 dconf->wsemulcookie = 272 (*dconf->wsemul->attach)(0, type, cookie, 273 ccol, crow, scr, defattr); 274 } else 275 dconf->wsemul = NULL; 276 dconf->scrdata = type; 277 } 278 279 scr->scr_dconf = dconf; 280 281 scr->scr_tty = ttymalloc(); 282 tty_attach(scr->scr_tty); 283 scr->scr_hold_screen = 0; 284 if (WSSCREEN_HAS_EMULATOR(scr)) 285 scr->scr_flags = 0; 286 else 287 scr->scr_flags = SCR_GRAPHICS; 288 289 scr->scr_syncops = 0; 290 scr->sc = sc; 291 #ifdef WSDISPLAY_COMPAT_RAWKBD 292 scr->scr_rawkbd = 0; 293 #endif 294 return (scr); 295 } 296 297 void 298 wsscreen_detach(struct wsscreen *scr) 299 { 300 u_int ccol, crow; /* XXX */ 301 302 if (WSSCREEN_HAS_TTY(scr)) { 303 tty_detach(scr->scr_tty); 304 ttyfree(scr->scr_tty); 305 } 306 if (WSSCREEN_HAS_EMULATOR(scr)) 307 (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie, 308 &ccol, &crow); 309 free(scr->scr_dconf, M_DEVBUF); 310 free(scr, M_DEVBUF); 311 } 312 313 const struct wsscreen_descr * 314 wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name) 315 { 316 int i; 317 const struct wsscreen_descr *scr; 318 319 KASSERT(scrdata->nscreens > 0); 320 321 if (name == NULL) 322 return (scrdata->screens[0]); 323 324 for (i = 0; i < scrdata->nscreens; i++) { 325 scr = scrdata->screens[i]; 326 if (!strcmp(name, scr->name)) 327 return (scr); 328 } 329 330 return (0); 331 } 332 333 /* 334 * print info about attached screen 335 */ 336 static void 337 wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count) 338 { 339 printf("%s: screen %d", sc->sc_dv.dv_xname, idx); 340 if (count > 1) 341 printf("-%d", idx + (count-1)); 342 printf(" added (%s", sc->sc_scr[idx]->scr_dconf->scrdata->name); 343 if (WSSCREEN_HAS_EMULATOR(sc->sc_scr[idx])) { 344 printf(", %s emulation", 345 sc->sc_scr[idx]->scr_dconf->wsemul->name); 346 } 347 printf(")\n"); 348 } 349 350 int 351 wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx, 352 const char *screentype, const char *emul) 353 { 354 const struct wsscreen_descr *scrdesc; 355 int error; 356 void *cookie; 357 int ccol, crow; 358 long defattr; 359 struct wsscreen *scr; 360 int s; 361 362 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 363 return (EINVAL); 364 if (sc->sc_scr[idx] != NULL) 365 return (EBUSY); 366 367 scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype); 368 if (!scrdesc) 369 return (ENXIO); 370 error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie, 371 scrdesc, &cookie, &ccol, &crow, &defattr); 372 if (error) 373 return (error); 374 375 scr = wsscreen_attach(sc, 0, emul, scrdesc, 376 cookie, ccol, crow, defattr); 377 if (scr == NULL) { 378 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 379 cookie); 380 return (ENXIO); 381 } 382 383 sc->sc_scr[idx] = scr; 384 385 /* if no screen has focus yet, activate the first we get */ 386 s = spltty(); 387 if (!sc->sc_focus) { 388 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 389 scr->scr_dconf->emulcookie, 390 0, 0, 0); 391 sc->sc_focusidx = idx; 392 sc->sc_focus = scr; 393 } 394 splx(s); 395 return (0); 396 } 397 398 static void 399 wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr) 400 { 401 int maj, mn, idx; 402 403 /* hangup */ 404 if (WSSCREEN_HAS_TTY(scr)) { 405 struct tty *tp = scr->scr_tty; 406 (*tp->t_linesw->l_modem)(tp, 0); 407 } 408 409 /* locate the major number */ 410 maj = cdevsw_lookup_major(&wsdisplay_cdevsw); 411 /* locate the screen index */ 412 for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++) 413 if (scr == sc->sc_scr[idx]) 414 break; 415 #ifdef DIAGNOSTIC 416 if (idx == WSDISPLAY_MAXSCREEN) 417 panic("wsdisplay_forceclose: bad screen"); 418 #endif 419 420 /* nuke the vnodes */ 421 mn = WSDISPLAYMINOR(sc->sc_dv.dv_unit, idx); 422 vdevgone(maj, mn, mn, VCHR); 423 } 424 425 #ifdef WSDISPLAY_SCROLLSUPPORT 426 void 427 wsdisplay_scroll(void *arg, int op) 428 { 429 struct wsdisplay_softc *sc = arg; 430 int lines; 431 432 if (op == WSDISPLAY_SCROLL_RESET) 433 lines = 0; 434 else { 435 lines = (op & WSDISPLAY_SCROLL_LOW) ? 436 sc->sc_scroll_values.slowlines : 437 sc->sc_scroll_values.fastlines; 438 if (op & WSDISPLAY_SCROLL_BACKWARD) 439 lines = -(lines); 440 } 441 442 if (sc->sc_accessops->scroll) { 443 (*sc->sc_accessops->scroll)(sc->sc_accesscookie, 444 sc->sc_focus->scr_dconf->emulcookie, lines); 445 } 446 } 447 #endif 448 449 int 450 wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags) 451 { 452 struct wsscreen *scr; 453 int s; 454 void *cookie; 455 456 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 457 return (EINVAL); 458 if ((scr = sc->sc_scr[idx]) == NULL) 459 return (ENXIO); 460 461 if (scr->scr_dconf == &wsdisplay_console_conf || 462 scr->scr_syncops || 463 ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE))) 464 return(EBUSY); 465 466 wsdisplay_closescreen(sc, scr); 467 468 /* 469 * delete pointers, so neither device entries 470 * nor keyboard input can reference it anymore 471 */ 472 s = spltty(); 473 if (sc->sc_focus == scr) { 474 sc->sc_focus = 0; 475 #ifdef WSDISPLAY_COMPAT_RAWKBD 476 wsdisplay_update_rawkbd(sc, 0); 477 #endif 478 } 479 sc->sc_scr[idx] = 0; 480 splx(s); 481 482 /* 483 * Wake up processes waiting for the screen to 484 * be activated. Sleepers must check whether 485 * the screen still exists. 486 */ 487 if (scr->scr_flags & SCR_WAITACTIVE) 488 wakeup(scr); 489 490 /* save a reference to the graphics screen */ 491 cookie = scr->scr_dconf->emulcookie; 492 493 wsscreen_detach(scr); 494 495 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 496 cookie); 497 498 printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx); 499 return (0); 500 } 501 502 /* 503 * Autoconfiguration functions. 504 */ 505 int 506 wsdisplay_emul_match(struct device *parent, struct cfdata *match, void *aux) 507 { 508 struct wsemuldisplaydev_attach_args *ap = aux; 509 510 if (match->wsemuldisplaydevcf_console != 511 WSEMULDISPLAYDEVCF_CONSOLE_UNK) { 512 /* 513 * If console-ness of device specified, either match 514 * exactly (at high priority), or fail. 515 */ 516 if (match->wsemuldisplaydevcf_console != 0 && 517 ap->console != 0) 518 return (10); 519 else 520 return (0); 521 } 522 523 /* If console-ness unspecified, it wins. */ 524 return (1); 525 } 526 527 void 528 wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux) 529 { 530 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; 531 struct wsemuldisplaydev_attach_args *ap = aux; 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 printf("\n"); 656 657 #if NWSKBD > 0 && NWSMUX > 0 658 wsmux_set_display(mux, &sc->sc_dv); 659 #endif 660 661 sc->sc_accessops = accessops; 662 sc->sc_accesscookie = accesscookie; 663 sc->sc_scrdata = scrdata; 664 665 #ifdef WSDISPLAY_SCROLLSUPPORT 666 sc->sc_scroll_values = wsdisplay_default_scroll_values; 667 #endif 668 669 /* 670 * Set up a number of virtual screens if wanted. The 671 * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code 672 * is for special cases like installation kernels. 673 */ 674 for (i = start; i < wsdisplay_defaultscreens; i++) { 675 if (wsdisplay_addscreen(sc, i, 0, 0)) 676 break; 677 } 678 679 if (i > start) 680 wsdisplay_addscreen_print(sc, start, i-start); 681 682 if (hookset == 0) 683 shutdownhook_establish(wsdisplay_shutdownhook, NULL); 684 hookset = 1; 685 } 686 687 void 688 wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, 689 int ccol, int crow, long defattr) 690 { 691 const struct wsemul_ops *wsemul; 692 693 KASSERT(!wsdisplay_console_initted); 694 KASSERT(type->nrows > 0); 695 KASSERT(type->ncols > 0); 696 KASSERT(crow < type->nrows); 697 KASSERT(ccol < type->ncols); 698 699 wsdisplay_console_conf.emulops = type->textops; 700 wsdisplay_console_conf.emulcookie = cookie; 701 wsdisplay_console_conf.scrdata = type; 702 703 wsemul = wsemul_pick(0); /* default */ 704 wsdisplay_console_conf.wsemul = wsemul; 705 wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, 706 ccol, crow, 707 defattr); 708 709 cn_tab = &wsdisplay_cons; 710 wsdisplay_console_initted = 1; 711 } 712 713 /* 714 * Tty and cdevsw functions. 715 */ 716 int 717 wsdisplayopen(dev_t dev, int flag, int mode, struct proc *p) 718 { 719 struct wsdisplay_softc *sc; 720 struct tty *tp; 721 int newopen, error; 722 struct wsscreen *scr; 723 724 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 725 if (sc == NULL) /* make sure it was attached */ 726 return (ENXIO); 727 728 if (ISWSDISPLAYSTAT(dev)) { 729 wsevent_init(&sc->evar); 730 sc->evar.io = p; 731 return (0); 732 } 733 734 if (ISWSDISPLAYCTL(dev)) 735 return (0); 736 737 if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) 738 return (ENXIO); 739 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 740 return (ENXIO); 741 742 if (WSSCREEN_HAS_TTY(scr)) { 743 tp = scr->scr_tty; 744 tp->t_oproc = wsdisplaystart; 745 tp->t_param = wsdisplayparam; 746 tp->t_dev = dev; 747 newopen = (tp->t_state & TS_ISOPEN) == 0; 748 if (newopen) { 749 ttychars(tp); 750 tp->t_iflag = TTYDEF_IFLAG; 751 tp->t_oflag = TTYDEF_OFLAG; 752 tp->t_cflag = TTYDEF_CFLAG; 753 tp->t_lflag = TTYDEF_LFLAG; 754 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 755 wsdisplayparam(tp, &tp->t_termios); 756 ttsetwater(tp); 757 } else if ((tp->t_state & TS_XCLUDE) != 0 && 758 suser(p->p_ucred, &p->p_acflag) != 0) 759 return EBUSY; 760 tp->t_state |= TS_CARR_ON; 761 762 error = ((*tp->t_linesw->l_open)(dev, tp)); 763 if (error) 764 return (error); 765 766 if (newopen && WSSCREEN_HAS_EMULATOR(scr)) { 767 /* set window sizes as appropriate, and reset 768 the emulation */ 769 tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows; 770 tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols; 771 772 /* wsdisplay_set_emulation() */ 773 } 774 } 775 776 scr->scr_flags |= SCR_OPEN; 777 return (0); 778 } 779 780 int 781 wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p) 782 { 783 struct wsdisplay_softc *sc; 784 struct tty *tp; 785 struct wsscreen *scr; 786 787 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 788 789 if (ISWSDISPLAYSTAT(dev)) { 790 wsevent_fini(&sc->evar); 791 return (0); 792 } 793 794 if (ISWSDISPLAYCTL(dev)) 795 return (0); 796 797 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 798 return (0); 799 800 if (WSSCREEN_HAS_TTY(scr)) { 801 if (scr->scr_hold_screen) { 802 int s; 803 804 /* XXX RESET KEYBOARD LEDS, etc. */ 805 s = spltty(); /* avoid conflict with keyboard */ 806 wsdisplay_kbdholdscreen((struct device *)sc, 0); 807 splx(s); 808 } 809 tp = scr->scr_tty; 810 (*tp->t_linesw->l_close)(tp, flag); 811 ttyclose(tp); 812 } 813 814 if (scr->scr_syncops) 815 (*scr->scr_syncops->destroy)(scr->scr_synccookie); 816 817 if (WSSCREEN_HAS_EMULATOR(scr)) { 818 scr->scr_flags &= ~SCR_GRAPHICS; 819 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 820 WSEMUL_RESET); 821 if (wsdisplay_clearonclose) 822 (*scr->scr_dconf->wsemul->reset) 823 (scr->scr_dconf->wsemulcookie, 824 WSEMUL_CLEARSCREEN); 825 } 826 827 #ifdef WSDISPLAY_COMPAT_RAWKBD 828 if (scr->scr_rawkbd) { 829 int kbmode = WSKBD_TRANSLATED; 830 (void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, 831 (caddr_t)&kbmode, 0, p); 832 } 833 #endif 834 835 scr->scr_flags &= ~SCR_OPEN; 836 837 return (0); 838 } 839 840 int 841 wsdisplayread(dev_t dev, struct uio *uio, int flag) 842 { 843 struct wsdisplay_softc *sc; 844 struct tty *tp; 845 struct wsscreen *scr; 846 int error; 847 848 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 849 850 if (ISWSDISPLAYSTAT(dev)) { 851 error = wsevent_read(&sc->evar, uio, flag); 852 return (error); 853 } 854 855 if (ISWSDISPLAYCTL(dev)) 856 return (0); 857 858 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 859 return (ENXIO); 860 861 if (!WSSCREEN_HAS_TTY(scr)) 862 return (ENODEV); 863 864 tp = scr->scr_tty; 865 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 866 } 867 868 int 869 wsdisplaywrite(dev_t dev, struct uio *uio, int flag) 870 { 871 struct wsdisplay_softc *sc; 872 struct tty *tp; 873 struct wsscreen *scr; 874 875 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 876 877 if (ISWSDISPLAYSTAT(dev)) { 878 return (0); 879 } 880 881 if (ISWSDISPLAYCTL(dev)) 882 return (0); 883 884 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 885 return (ENXIO); 886 887 if (!WSSCREEN_HAS_TTY(scr)) 888 return (ENODEV); 889 890 tp = scr->scr_tty; 891 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 892 } 893 894 int 895 wsdisplaypoll(dev_t dev, int events, struct proc *p) 896 { 897 struct wsdisplay_softc *sc; 898 struct tty *tp; 899 struct wsscreen *scr; 900 901 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 902 903 if (ISWSDISPLAYSTAT(dev)) 904 return (wsevent_poll(&sc->evar, events, p)); 905 906 if (ISWSDISPLAYCTL(dev)) 907 return (0); 908 909 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 910 return (POLLHUP); 911 912 if (!WSSCREEN_HAS_TTY(scr)) 913 return (POLLERR); 914 915 tp = scr->scr_tty; 916 return ((*tp->t_linesw->l_poll)(tp, events, p)); 917 } 918 919 int 920 wsdisplaykqfilter(dev, kn) 921 dev_t dev; 922 struct knote *kn; 923 { 924 struct wsdisplay_softc *sc = 925 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 926 struct wsscreen *scr; 927 928 if (ISWSDISPLAYCTL(dev)) 929 return (1); 930 931 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 932 return (1); 933 934 935 if (WSSCREEN_HAS_TTY(scr)) 936 return (ttykqfilter(dev, kn)); 937 else 938 return (1); 939 } 940 941 struct tty * 942 wsdisplaytty(dev_t dev) 943 { 944 struct wsdisplay_softc *sc; 945 struct wsscreen *scr; 946 947 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 948 949 if (ISWSDISPLAYSTAT(dev)) 950 panic("wsdisplaytty() on status device"); 951 952 if (ISWSDISPLAYCTL(dev)) 953 panic("wsdisplaytty() on ctl device"); 954 955 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 956 return NULL; 957 958 return (scr->scr_tty); 959 } 960 961 int 962 wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 963 { 964 struct wsdisplay_softc *sc; 965 struct tty *tp; 966 int error; 967 struct wsscreen *scr; 968 969 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 970 971 #ifdef WSDISPLAY_COMPAT_USL 972 error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, p); 973 if (error != EPASSTHROUGH) 974 return (error); 975 #endif 976 977 if (ISWSDISPLAYSTAT(dev)) 978 return (wsdisplay_stat_ioctl(sc, cmd, data, flag, p)); 979 980 if (ISWSDISPLAYCTL(dev)) 981 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)); 982 983 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 984 return (ENXIO); 985 986 if (WSSCREEN_HAS_TTY(scr)) { 987 tp = scr->scr_tty; 988 989 /* printf("disc\n"); */ 990 /* do the line discipline ioctls first */ 991 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 992 if (error != EPASSTHROUGH) 993 return (error); 994 995 /* printf("tty\n"); */ 996 /* then the tty ioctls */ 997 error = ttioctl(tp, cmd, data, flag, p); 998 if (error != EPASSTHROUGH) 999 return (error); 1000 } 1001 1002 #ifdef WSDISPLAY_COMPAT_USL 1003 error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p); 1004 if (error != EPASSTHROUGH) 1005 return (error); 1006 #endif 1007 1008 return (wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p)); 1009 } 1010 1011 int 1012 wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp) 1013 { 1014 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1015 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, 1016 (caddr_t)dp, 0, NULL)); 1017 } 1018 1019 int 1020 wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, 1021 u_long cmd, caddr_t data, int flag, struct proc *p) 1022 { 1023 int error; 1024 char namebuf[16]; 1025 struct wsdisplay_font fd; 1026 #ifdef WSDISPLAY_SCROLLSUPPORT 1027 struct wsdisplay_scroll_data *ksdp, *usdp; 1028 #endif 1029 1030 #if NWSKBD > 0 1031 struct wsevsrc *inp; 1032 1033 #ifdef WSDISPLAY_COMPAT_RAWKBD 1034 switch (cmd) { 1035 case WSKBDIO_SETMODE: 1036 scr->scr_rawkbd = (*(int *)data == WSKBD_RAW); 1037 return (wsdisplay_update_rawkbd(sc, scr)); 1038 case WSKBDIO_GETMODE: 1039 *(int *)data = (scr->scr_rawkbd ? 1040 WSKBD_RAW : WSKBD_TRANSLATED); 1041 return (0); 1042 } 1043 #endif 1044 inp = sc->sc_input; 1045 if (inp == NULL) 1046 return (ENXIO); 1047 error = wsevsrc_display_ioctl(inp, cmd, data, flag, p); 1048 if (error != EPASSTHROUGH) 1049 return (error); 1050 #endif /* NWSKBD > 0 */ 1051 1052 switch (cmd) { 1053 case WSDISPLAYIO_GMODE: 1054 if (scr->scr_flags & SCR_GRAPHICS) { 1055 if (scr->scr_flags & SCR_DUMBFB) 1056 *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB; 1057 else 1058 *(u_int *)data = WSDISPLAYIO_MODE_MAPPED; 1059 } else 1060 *(u_int *)data = WSDISPLAYIO_MODE_EMUL; 1061 return (0); 1062 1063 case WSDISPLAYIO_SMODE: 1064 #define d (*(int *)data) 1065 if (d != WSDISPLAYIO_MODE_EMUL && 1066 d != WSDISPLAYIO_MODE_MAPPED && 1067 d != WSDISPLAYIO_MODE_DUMBFB) 1068 return (EINVAL); 1069 1070 if (WSSCREEN_HAS_EMULATOR(scr)) { 1071 scr->scr_flags &= ~SCR_GRAPHICS; 1072 if (d == WSDISPLAYIO_MODE_MAPPED || 1073 d == WSDISPLAYIO_MODE_DUMBFB) 1074 scr->scr_flags |= SCR_GRAPHICS | 1075 ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0); 1076 } else if (d == WSDISPLAYIO_MODE_EMUL) 1077 return (EINVAL); 1078 1079 (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, 1080 flag, p); 1081 1082 return (0); 1083 #undef d 1084 1085 #ifdef WSDISPLAY_SCROLLSUPPORT 1086 #define SETSCROLLLINES(dstp, srcp, dfltp) \ 1087 do { \ 1088 (dstp)->fastlines = ((srcp)->which & \ 1089 WSDISPLAY_SCROLL_DOFASTLINES) ? \ 1090 (srcp)->fastlines : (dfltp)->fastlines; \ 1091 (dstp)->slowlines = ((srcp)->which & \ 1092 WSDISPLAY_SCROLL_DOSLOWLINES) ? \ 1093 (srcp)->slowlines : (dfltp)->slowlines; \ 1094 (dstp)->which = WSDISPLAY_SCROLL_DOALL; \ 1095 } while (0) 1096 1097 1098 case WSDISPLAYIO_DSSCROLL: 1099 usdp = (struct wsdisplay_scroll_data *)data; 1100 ksdp = &sc->sc_scroll_values; 1101 SETSCROLLLINES(ksdp, usdp, ksdp); 1102 return (0); 1103 1104 case WSDISPLAYIO_DGSCROLL: 1105 usdp = (struct wsdisplay_scroll_data *)data; 1106 ksdp = &sc->sc_scroll_values; 1107 SETSCROLLLINES(usdp, ksdp, ksdp); 1108 return (0); 1109 #else 1110 case WSDISPLAYIO_DSSCROLL: 1111 case WSDISPLAYIO_DGSCROLL: 1112 return ENODEV; 1113 #endif 1114 1115 case WSDISPLAYIO_SFONT: 1116 #define d ((struct wsdisplay_usefontdata *)data) 1117 if (!sc->sc_accessops->load_font) 1118 return (EINVAL); 1119 if (d->name) { 1120 error = copyinstr(d->name, namebuf, sizeof(namebuf), 0); 1121 if (error) 1122 return (error); 1123 fd.name = namebuf; 1124 } else 1125 fd.name = 0; 1126 fd.data = 0; 1127 error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 1128 scr->scr_dconf->emulcookie, &fd); 1129 if (!error && WSSCREEN_HAS_EMULATOR(scr)) 1130 (*scr->scr_dconf->wsemul->reset) 1131 (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT); 1132 return (error); 1133 #undef d 1134 1135 #if defined(WSDISPLAY_CHARFUNCS) 1136 case WSDISPLAYIO_GETWSCHAR: 1137 #define d ((struct wsdisplay_char *)data) 1138 if (!sc->sc_accessops->getwschar) 1139 return (EINVAL); 1140 return ((*sc->sc_accessops->getwschar) 1141 (scr->scr_dconf->emulcookie, d)); 1142 #undef d 1143 1144 case WSDISPLAYIO_PUTWSCHAR: 1145 #define d ((struct wsdisplay_char *)data) 1146 if (!sc->sc_accessops->putwschar) 1147 return (EINVAL); 1148 return ((*sc->sc_accessops->putwschar) 1149 (scr->scr_dconf->emulcookie, d)); 1150 #undef d 1151 #else 1152 case WSDISPLAYIO_PUTWSCHAR: 1153 case WSDISPLAYIO_GETWSCHAR: 1154 return ENODEV; 1155 #endif /* WSDISPLAY_CHARFUNCS */ 1156 1157 #ifdef WSDISPLAY_CUSTOM_OUTPUT 1158 case WSDISPLAYIO_GMSGATTRS: 1159 #define d ((struct wsdisplay_msgattrs *)data) 1160 (*scr->scr_dconf->wsemul->getmsgattrs) 1161 (scr->scr_dconf->wsemulcookie, d); 1162 return (0); 1163 #undef d 1164 1165 case WSDISPLAYIO_SMSGATTRS: { 1166 #define d ((struct wsdisplay_msgattrs *)data) 1167 int i; 1168 for (i = 0; i < WSDISPLAY_MAXSCREEN; i++) 1169 if (sc->sc_scr[i] != NULL) 1170 (*sc->sc_scr[i]->scr_dconf->wsemul->setmsgattrs) 1171 (sc->sc_scr[i]->scr_dconf->wsemulcookie, 1172 sc->sc_scr[i]->scr_dconf->scrdata, 1173 d); 1174 } 1175 return (0); 1176 #undef d 1177 #else 1178 case WSDISPLAYIO_GMSGATTRS: 1179 case WSDISPLAYIO_SMSGATTRS: 1180 return (ENODEV); 1181 #endif 1182 1183 #ifdef WSDISPLAY_CUSTOM_BORDER 1184 case WSDISPLAYIO_GBORDER: 1185 if (!sc->sc_accessops->getborder) 1186 return (EINVAL); 1187 *(u_int *)data = (*sc->sc_accessops->getborder) 1188 (scr->scr_dconf->emulcookie); 1189 return (0); 1190 case WSDISPLAYIO_SBORDER: 1191 if (!sc->sc_accessops->setborder) 1192 return (EINVAL); 1193 return (*sc->sc_accessops->setborder) 1194 (scr->scr_dconf->emulcookie, (*(u_int *)data)); 1195 #else /* WSDISPLAY_CUSTOM_BORDER */ 1196 case WSDISPLAYIO_GBORDER: 1197 case WSDISPLAYIO_SBORDER: 1198 return (ENODEV); 1199 #endif /* WSDISPLAY_CUSTOM_BORDER */ 1200 1201 } 1202 1203 /* check ioctls for display */ 1204 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, 1205 flag, p)); 1206 } 1207 1208 int 1209 wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1210 int flag, struct proc *p) 1211 { 1212 switch (cmd) { 1213 case WSDISPLAYIO_GETACTIVESCREEN: 1214 *(int*)data = wsdisplay_getactivescreen(sc); 1215 return (0); 1216 } 1217 1218 return (EPASSTHROUGH); 1219 } 1220 1221 int 1222 wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1223 int flag, struct proc *p) 1224 { 1225 int error; 1226 char *type, typebuf[16], *emul, emulbuf[16]; 1227 void *tbuf; 1228 u_int fontsz; 1229 #if defined(COMPAT_14) && NWSKBD > 0 1230 struct wsmux_device wsmuxdata; 1231 #endif 1232 #if NWSKBD > 0 1233 struct wsevsrc *inp; 1234 #endif 1235 1236 switch (cmd) { 1237 case WSDISPLAYIO_ADDSCREEN: 1238 #define d ((struct wsdisplay_addscreendata *)data) 1239 if (d->screentype) { 1240 error = copyinstr(d->screentype, typebuf, 1241 sizeof(typebuf), 0); 1242 if (error) 1243 return (error); 1244 type = typebuf; 1245 } else 1246 type = 0; 1247 if (d->emul) { 1248 error = copyinstr(d->emul, emulbuf, sizeof(emulbuf),0); 1249 if (error) 1250 return (error); 1251 emul = emulbuf; 1252 } else 1253 emul = 0; 1254 1255 if ((error = wsdisplay_addscreen(sc, d->idx, type, emul)) == 0) 1256 wsdisplay_addscreen_print(sc, d->idx, 0); 1257 return (error); 1258 #undef d 1259 case WSDISPLAYIO_DELSCREEN: 1260 #define d ((struct wsdisplay_delscreendata *)data) 1261 return (wsdisplay_delscreen(sc, d->idx, d->flags)); 1262 #undef d 1263 case WSDISPLAYIO_LDFONT: 1264 #define d ((struct wsdisplay_font *)data) 1265 if (!sc->sc_accessops->load_font) 1266 return (EINVAL); 1267 if (d->name) { 1268 error = copyinstr(d->name, typebuf, sizeof(typebuf), 0); 1269 if (error) 1270 return (error); 1271 d->name = typebuf; 1272 } else 1273 d->name = "loaded"; /* ??? */ 1274 fontsz = d->fontheight * d->stride * d->numchars; 1275 if (fontsz > WSDISPLAY_MAXFONTSZ) 1276 return (EINVAL); 1277 1278 tbuf = malloc(fontsz, M_DEVBUF, M_WAITOK); 1279 error = copyin(d->data, tbuf, fontsz); 1280 if (error) { 1281 free(tbuf, M_DEVBUF); 1282 return (error); 1283 } 1284 d->data = tbuf; 1285 error = 1286 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); 1287 free(tbuf, M_DEVBUF); 1288 #undef d 1289 return (error); 1290 1291 #if NWSKBD > 0 1292 #ifdef COMPAT_14 1293 case _O_WSDISPLAYIO_SETKEYBOARD: 1294 #define d ((struct wsdisplay_kbddata *)data) 1295 inp = sc->sc_input; 1296 if (inp == NULL) 1297 return (ENXIO); 1298 switch (d->op) { 1299 case _O_WSDISPLAY_KBD_ADD: 1300 if (d->idx == -1) { 1301 d->idx = wskbd_pickfree(); 1302 if (d->idx == -1) 1303 return (ENXIO); 1304 } 1305 wsmuxdata.type = WSMUX_KBD; 1306 wsmuxdata.idx = d->idx; 1307 return (wsevsrc_ioctl(inp, WSMUX_ADD_DEVICE, 1308 &wsmuxdata, flag, p)); 1309 case _O_WSDISPLAY_KBD_DEL: 1310 wsmuxdata.type = WSMUX_KBD; 1311 wsmuxdata.idx = d->idx; 1312 return (wsevsrc_ioctl(inp, WSMUX_REMOVE_DEVICE, 1313 &wsmuxdata, flag, p)); 1314 default: 1315 return (EINVAL); 1316 } 1317 #undef d 1318 #endif 1319 1320 case WSMUXIO_ADD_DEVICE: 1321 #define d ((struct wsmux_device *)data) 1322 if (d->idx == -1 && d->type == WSMUX_KBD) 1323 d->idx = wskbd_pickfree(); 1324 #undef d 1325 /* fall into */ 1326 case WSMUXIO_INJECTEVENT: 1327 case WSMUXIO_REMOVE_DEVICE: 1328 case WSMUXIO_LIST_DEVICES: 1329 inp = sc->sc_input; 1330 if (inp == NULL) 1331 return (ENXIO); 1332 return (wsevsrc_ioctl(inp, cmd, data, flag, p)); 1333 #endif /* NWSKBD > 0 */ 1334 1335 } 1336 return (EPASSTHROUGH); 1337 } 1338 1339 int 1340 wsdisplay_stat_inject(struct device *dev, u_int type, int value) 1341 { 1342 struct wsdisplay_softc *sc = (struct wsdisplay_softc *) dev; 1343 struct wseventvar *evar; 1344 struct wscons_event *ev; 1345 struct timeval thistime; 1346 int put; 1347 1348 evar = &sc->evar; 1349 1350 if (evar == NULL) 1351 return (0); 1352 1353 if (evar->q == NULL) 1354 return (1); 1355 1356 put = evar->put; 1357 ev = &evar->q[put]; 1358 put = (put + 1) % WSEVENT_QSIZE; 1359 if (put == evar->get) { 1360 log(LOG_WARNING, "wsdisplay: event queue overflow\n"); 1361 return (1); 1362 } 1363 ev->type = type; 1364 ev->value = value; 1365 microtime(&thistime); 1366 TIMEVAL_TO_TIMESPEC(&thistime, &ev->time); 1367 evar->put = put; 1368 WSEVENT_WAKEUP(evar); 1369 1370 return (0); 1371 } 1372 1373 paddr_t 1374 wsdisplaymmap(dev_t dev, off_t offset, int prot) 1375 { 1376 struct wsdisplay_softc *sc = 1377 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 1378 struct wsscreen *scr; 1379 1380 if (ISWSDISPLAYSTAT(dev)) 1381 return (-1); 1382 1383 if (ISWSDISPLAYCTL(dev)) 1384 return (-1); 1385 1386 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 1387 return (-1); 1388 1389 if (!(scr->scr_flags & SCR_GRAPHICS)) 1390 return (-1); 1391 1392 /* pass mmap to display */ 1393 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot)); 1394 } 1395 1396 void 1397 wsdisplaystart(struct tty *tp) 1398 { 1399 struct wsdisplay_softc *sc; 1400 struct wsscreen *scr; 1401 int s, n; 1402 u_char *tbuf; 1403 1404 s = spltty(); 1405 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 1406 splx(s); 1407 return; 1408 } 1409 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(tp->t_dev)); 1410 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { 1411 splx(s); 1412 return; 1413 } 1414 1415 if (scr->scr_hold_screen) { 1416 tp->t_state |= TS_TIMEOUT; 1417 splx(s); 1418 return; 1419 } 1420 tp->t_state |= TS_BUSY; 1421 splx(s); 1422 1423 /* 1424 * Drain output from ring buffer. 1425 * The output will normally be in one contiguous chunk, but when the 1426 * ring wraps, it will be in two pieces.. one at the end of the ring, 1427 * the other at the start. For performance, rather than loop here, 1428 * we output one chunk, see if there's another one, and if so, output 1429 * it too. 1430 */ 1431 1432 n = ndqb(&tp->t_outq, 0); 1433 tbuf = tp->t_outq.c_cf; 1434 1435 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1436 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1437 (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie, 1438 tbuf, n, 0); 1439 } 1440 ndflush(&tp->t_outq, n); 1441 1442 if ((n = ndqb(&tp->t_outq, 0)) > 0) { 1443 tbuf = tp->t_outq.c_cf; 1444 1445 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1446 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1447 (*scr->scr_dconf->wsemul->output) 1448 (scr->scr_dconf->wsemulcookie, tbuf, n, 0); 1449 } 1450 ndflush(&tp->t_outq, n); 1451 } 1452 1453 s = spltty(); 1454 tp->t_state &= ~TS_BUSY; 1455 /* Come back if there's more to do */ 1456 if (tp->t_outq.c_cc) { 1457 tp->t_state |= TS_TIMEOUT; 1458 callout_reset(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1, 1459 ttrstrt, tp); 1460 } 1461 if (tp->t_outq.c_cc <= tp->t_lowat) { 1462 if (tp->t_state&TS_ASLEEP) { 1463 tp->t_state &= ~TS_ASLEEP; 1464 wakeup(&tp->t_outq); 1465 } 1466 selwakeup(&tp->t_wsel); 1467 } 1468 splx(s); 1469 } 1470 1471 void 1472 wsdisplaystop(struct tty *tp, int flag) 1473 { 1474 int s; 1475 1476 s = spltty(); 1477 if (ISSET(tp->t_state, TS_BUSY)) 1478 if (!ISSET(tp->t_state, TS_TTSTOP)) 1479 SET(tp->t_state, TS_FLUSH); 1480 splx(s); 1481 } 1482 1483 /* Set line parameters. */ 1484 int 1485 wsdisplayparam(struct tty *tp, struct termios *t) 1486 { 1487 1488 tp->t_ispeed = t->c_ispeed; 1489 tp->t_ospeed = t->c_ospeed; 1490 tp->t_cflag = t->c_cflag; 1491 return 0; 1492 } 1493 1494 /* 1495 * Callbacks for the emulation code. 1496 */ 1497 void 1498 wsdisplay_emulbell(void *v) 1499 { 1500 struct wsscreen *scr = v; 1501 1502 if (scr == NULL) /* console, before real attach */ 1503 return; 1504 1505 if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ 1506 return; 1507 1508 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, 1509 FWRITE, NULL); 1510 } 1511 1512 void 1513 wsdisplay_emulinput(void *v, const u_char *data, u_int count) 1514 { 1515 struct wsscreen *scr = v; 1516 struct tty *tp; 1517 1518 if (v == NULL) /* console, before real attach */ 1519 return; 1520 1521 if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ 1522 return; 1523 if (!WSSCREEN_HAS_TTY(scr)) 1524 return; 1525 1526 tp = scr->scr_tty; 1527 while (count-- > 0) 1528 (*tp->t_linesw->l_rint)(*data++, tp); 1529 } 1530 1531 /* 1532 * Calls from the keyboard interface. 1533 */ 1534 void 1535 wsdisplay_kbdinput(struct device *dev, keysym_t ks) 1536 { 1537 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1538 struct wsscreen *scr; 1539 const char *dp; 1540 int count; 1541 struct tty *tp; 1542 1543 KASSERT(sc != NULL); 1544 1545 scr = sc->sc_focus; 1546 1547 if (!scr || !WSSCREEN_HAS_TTY(scr)) 1548 return; 1549 1550 tp = scr->scr_tty; 1551 1552 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1553 (*tp->t_linesw->l_rint)(KS_VALUE(ks), tp); 1554 else if (WSSCREEN_HAS_EMULATOR(scr)) { 1555 count = (*scr->scr_dconf->wsemul->translate) 1556 (scr->scr_dconf->wsemulcookie, ks, &dp); 1557 while (count-- > 0) 1558 (*tp->t_linesw->l_rint)(*dp++, tp); 1559 } 1560 } 1561 1562 #if defined(WSDISPLAY_COMPAT_RAWKBD) 1563 int 1564 wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) 1565 { 1566 #if NWSKBD > 0 1567 int s, raw, data, error; 1568 struct wsevsrc *inp; 1569 1570 s = spltty(); 1571 1572 raw = (scr ? scr->scr_rawkbd : 0); 1573 1574 if (scr != sc->sc_focus || 1575 sc->sc_rawkbd == raw) { 1576 splx(s); 1577 return (0); 1578 } 1579 1580 data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; 1581 inp = sc->sc_input; 1582 if (inp == NULL) 1583 return (ENXIO); 1584 error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0); 1585 if (!error) 1586 sc->sc_rawkbd = raw; 1587 splx(s); 1588 return (error); 1589 #else 1590 return (0); 1591 #endif 1592 } 1593 #endif 1594 1595 int 1596 wsdisplay_switch3(void *arg, int error, int waitok) 1597 { 1598 struct wsdisplay_softc *sc = arg; 1599 int no; 1600 struct wsscreen *scr; 1601 1602 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1603 printf("wsdisplay_switch3: not switching\n"); 1604 return (EINVAL); 1605 } 1606 1607 no = sc->sc_screenwanted; 1608 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1609 panic("wsdisplay_switch3: invalid screen %d", no); 1610 scr = sc->sc_scr[no]; 1611 if (!scr) { 1612 printf("wsdisplay_switch3: screen %d disappeared\n", no); 1613 error = ENXIO; 1614 } 1615 1616 if (error) { 1617 /* try to recover, avoid recursion */ 1618 1619 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1620 printf("wsdisplay_switch3: giving up\n"); 1621 sc->sc_focus = 0; 1622 #ifdef WSDISPLAY_COMPAT_RAWKBD 1623 wsdisplay_update_rawkbd(sc, 0); 1624 #endif 1625 sc->sc_flags &= ~SC_SWITCHPENDING; 1626 return (error); 1627 } 1628 1629 sc->sc_screenwanted = sc->sc_oldscreen; 1630 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1631 return (wsdisplay_switch1(arg, 0, waitok)); 1632 } 1633 1634 sc->sc_flags &= ~SC_SWITCHPENDING; 1635 1636 if (!error && (scr->scr_flags & SCR_WAITACTIVE)) 1637 wakeup(scr); 1638 return (error); 1639 } 1640 1641 int 1642 wsdisplay_switch2(void *arg, int error, int waitok) 1643 { 1644 struct wsdisplay_softc *sc = arg; 1645 int no; 1646 struct wsscreen *scr; 1647 1648 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1649 printf("wsdisplay_switch2: not switching\n"); 1650 return (EINVAL); 1651 } 1652 1653 no = sc->sc_screenwanted; 1654 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1655 panic("wsdisplay_switch2: invalid screen %d", no); 1656 scr = sc->sc_scr[no]; 1657 if (!scr) { 1658 printf("wsdisplay_switch2: screen %d disappeared\n", no); 1659 error = ENXIO; 1660 } 1661 1662 if (error) { 1663 /* try to recover, avoid recursion */ 1664 1665 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1666 printf("wsdisplay_switch2: giving up\n"); 1667 sc->sc_focus = 0; 1668 sc->sc_flags &= ~SC_SWITCHPENDING; 1669 return (error); 1670 } 1671 1672 sc->sc_screenwanted = sc->sc_oldscreen; 1673 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1674 return (wsdisplay_switch1(arg, 0, waitok)); 1675 } 1676 1677 sc->sc_focusidx = no; 1678 sc->sc_focus = scr; 1679 1680 #ifdef WSDISPLAY_COMPAT_RAWKBD 1681 (void) wsdisplay_update_rawkbd(sc, scr); 1682 #endif 1683 /* keyboard map??? */ 1684 1685 #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3) 1686 if (scr->scr_syncops) { 1687 error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, 1688 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); 1689 if (error == EAGAIN) { 1690 /* switch will be done asynchronously */ 1691 return (0); 1692 } 1693 } 1694 1695 return (wsdisplay_switch3(sc, error, waitok)); 1696 } 1697 1698 int 1699 wsdisplay_switch1(void *arg, int error, int waitok) 1700 { 1701 struct wsdisplay_softc *sc = arg; 1702 int no; 1703 struct wsscreen *scr; 1704 1705 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1706 printf("wsdisplay_switch1: not switching\n"); 1707 return (EINVAL); 1708 } 1709 1710 no = sc->sc_screenwanted; 1711 if (no == WSDISPLAY_NULLSCREEN) { 1712 sc->sc_flags &= ~SC_SWITCHPENDING; 1713 if (!error) { 1714 sc->sc_focus = 0; 1715 } 1716 wakeup(sc); 1717 return (error); 1718 } 1719 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1720 panic("wsdisplay_switch1: invalid screen %d", no); 1721 scr = sc->sc_scr[no]; 1722 if (!scr) { 1723 printf("wsdisplay_switch1: screen %d disappeared\n", no); 1724 error = ENXIO; 1725 } 1726 1727 if (error) { 1728 sc->sc_flags &= ~SC_SWITCHPENDING; 1729 return (error); 1730 } 1731 1732 #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2) 1733 error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 1734 scr->scr_dconf->emulcookie, 1735 waitok, 1736 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); 1737 if (error == EAGAIN) { 1738 /* switch will be done asynchronously */ 1739 return (0); 1740 } 1741 1742 return (wsdisplay_switch2(sc, error, waitok)); 1743 } 1744 1745 int 1746 wsdisplay_switch(struct device *dev, int no, int waitok) 1747 { 1748 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1749 int s, res = 0; 1750 struct wsscreen *scr; 1751 1752 if (no != WSDISPLAY_NULLSCREEN) { 1753 if ((no < 0 || no >= WSDISPLAY_MAXSCREEN)) 1754 return (EINVAL); 1755 if (sc->sc_scr[no] == NULL) 1756 return (ENXIO); 1757 } 1758 1759 wsdisplay_stat_inject(dev, WSCONS_EVENT_SCREEN_SWITCH, no); 1760 1761 s = spltty(); 1762 1763 if ((sc->sc_focus && no == sc->sc_focusidx) || 1764 (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) { 1765 splx(s); 1766 return (0); 1767 } 1768 1769 if (sc->sc_flags & SC_SWITCHPENDING) { 1770 splx(s); 1771 return (EBUSY); 1772 } 1773 1774 sc->sc_flags |= SC_SWITCHPENDING; 1775 sc->sc_screenwanted = no; 1776 1777 splx(s); 1778 1779 scr = sc->sc_focus; 1780 if (!scr) { 1781 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1782 return (wsdisplay_switch1(sc, 0, waitok)); 1783 } else 1784 sc->sc_oldscreen = sc->sc_focusidx; 1785 1786 #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) 1787 if (scr->scr_syncops) { 1788 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, 1789 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); 1790 if (res == EAGAIN) { 1791 /* switch will be done asynchronously */ 1792 return (0); 1793 } 1794 } else if (scr->scr_flags & SCR_GRAPHICS) { 1795 /* no way to save state */ 1796 res = EBUSY; 1797 } 1798 1799 return (wsdisplay_switch1(sc, res, waitok)); 1800 } 1801 1802 void 1803 wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) 1804 { 1805 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1806 struct wsscreen *scr; 1807 1808 KASSERT(sc != NULL); 1809 scr = sc->sc_focus; 1810 1811 if (!scr) 1812 return; 1813 1814 switch (op) { 1815 case WSDISPLAY_RESETEMUL: 1816 if (!WSSCREEN_HAS_EMULATOR(scr)) 1817 break; 1818 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 1819 WSEMUL_RESET); 1820 break; 1821 case WSDISPLAY_RESETCLOSE: 1822 wsdisplay_closescreen(sc, scr); 1823 break; 1824 } 1825 } 1826 1827 /* 1828 * Interface for (external) VT switch / process synchronization code 1829 */ 1830 int 1831 wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, 1832 void *cookie) 1833 { 1834 if (scr->scr_syncops) { 1835 /* 1836 * The screen is already claimed. 1837 * Check if the owner is still alive. 1838 */ 1839 if ((*scr->scr_syncops->check)(scr->scr_synccookie)) 1840 return (EBUSY); 1841 } 1842 scr->scr_syncops = ops; 1843 scr->scr_synccookie = cookie; 1844 return (0); 1845 } 1846 1847 int 1848 wsscreen_detach_sync(struct wsscreen *scr) 1849 { 1850 if (!scr->scr_syncops) 1851 return (EINVAL); 1852 scr->scr_syncops = 0; 1853 return (0); 1854 } 1855 1856 int 1857 wsscreen_lookup_sync(struct wsscreen *scr, 1858 const struct wscons_syncops *ops, /* used as ID */ 1859 void **cookiep) 1860 { 1861 if (!scr->scr_syncops || ops != scr->scr_syncops) 1862 return (EINVAL); 1863 *cookiep = scr->scr_synccookie; 1864 return (0); 1865 } 1866 1867 /* 1868 * Interface to virtual screen stuff 1869 */ 1870 int 1871 wsdisplay_maxscreenidx(struct wsdisplay_softc *sc) 1872 { 1873 return (WSDISPLAY_MAXSCREEN - 1); 1874 } 1875 1876 int 1877 wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) 1878 { 1879 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 1880 return (EINVAL); 1881 if (!sc->sc_scr[idx]) 1882 return (ENXIO); 1883 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); 1884 } 1885 1886 int 1887 wsdisplay_getactivescreen(struct wsdisplay_softc *sc) 1888 { 1889 return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); 1890 } 1891 1892 int 1893 wsscreen_switchwait(struct wsdisplay_softc *sc, int no) 1894 { 1895 struct wsscreen *scr; 1896 int s, res = 0; 1897 1898 if (no == WSDISPLAY_NULLSCREEN) { 1899 s = spltty(); 1900 while (sc->sc_focus && res == 0) { 1901 res = tsleep(sc, PCATCH, "wswait", 0); 1902 } 1903 splx(s); 1904 return (res); 1905 } 1906 1907 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1908 return (ENXIO); 1909 scr = sc->sc_scr[no]; 1910 if (!scr) 1911 return (ENXIO); 1912 1913 s = spltty(); 1914 if (scr != sc->sc_focus) { 1915 scr->scr_flags |= SCR_WAITACTIVE; 1916 res = tsleep(scr, PCATCH, "wswait", 0); 1917 if (scr != sc->sc_scr[no]) 1918 res = ENXIO; /* disappeared in the meantime */ 1919 else 1920 scr->scr_flags &= ~SCR_WAITACTIVE; 1921 } 1922 splx(s); 1923 return (res); 1924 } 1925 1926 void 1927 wsdisplay_kbdholdscreen(struct device *dev, int hold) 1928 { 1929 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1930 struct wsscreen *scr; 1931 1932 scr = sc->sc_focus; 1933 1934 if (hold) 1935 scr->scr_hold_screen = 1; 1936 else { 1937 scr->scr_hold_screen = 0; 1938 callout_reset(&scr->scr_tty->t_rstrt_ch, 0, 1939 ttrstrt, scr->scr_tty); /* "immediate" */ 1940 } 1941 } 1942 1943 #if NWSKBD > 0 1944 void 1945 wsdisplay_set_console_kbd(struct wsevsrc *src) 1946 { 1947 if (wsdisplay_console_device == NULL) { 1948 src->me_dispdv = NULL; 1949 return; 1950 } 1951 #if NWSMUX > 0 1952 if (wsmux_attach_sc((struct wsmux_softc *) 1953 wsdisplay_console_device->sc_input, src)) { 1954 src->me_dispdv = NULL; 1955 return; 1956 } 1957 #else 1958 wsdisplay_console_device->sc_input = src; 1959 #endif 1960 src->me_dispdv = &wsdisplay_console_device->sc_dv; 1961 } 1962 #endif /* NWSKBD > 0 */ 1963 1964 /* 1965 * Console interface. 1966 */ 1967 void 1968 wsdisplay_cnputc(dev_t dev, int i) 1969 { 1970 struct wsscreen_internal *dc; 1971 u_char c = i; 1972 1973 if (!wsdisplay_console_initted) 1974 return; 1975 1976 if ((wsdisplay_console_device != NULL) && 1977 (wsdisplay_console_device->sc_scr[0] != NULL) && 1978 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) 1979 return; 1980 1981 dc = &wsdisplay_console_conf; 1982 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); 1983 } 1984 1985 static int 1986 wsdisplay_getc_dummy(dev_t dev) 1987 { 1988 /* panic? */ 1989 return (0); 1990 } 1991 1992 static void 1993 wsdisplay_pollc(dev_t dev, int on) 1994 { 1995 1996 wsdisplay_cons_pollmode = on; 1997 1998 /* notify to fb drivers */ 1999 if (wsdisplay_console_device != NULL && 2000 wsdisplay_console_device->sc_accessops->pollc != NULL) 2001 (*wsdisplay_console_device->sc_accessops->pollc) 2002 (wsdisplay_console_device->sc_accesscookie, on); 2003 2004 /* notify to kbd drivers */ 2005 if (wsdisplay_cons_kbd_pollc) 2006 (*wsdisplay_cons_kbd_pollc)(NODEV, on); 2007 } 2008 2009 void 2010 wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), 2011 void (*bell)(dev_t, u_int, u_int, u_int)) 2012 { 2013 wsdisplay_cons.cn_getc = get; 2014 wsdisplay_cons.cn_bell = bell; 2015 wsdisplay_cons_kbd_pollc = poll; 2016 } 2017 2018 void 2019 wsdisplay_unset_cons_kbd(void) 2020 { 2021 wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; 2022 wsdisplay_cons.cn_bell = NULL; 2023 wsdisplay_cons_kbd_pollc = 0; 2024 } 2025 2026 /* 2027 * Switch the console display to it's first screen. 2028 */ 2029 void 2030 wsdisplay_switchtoconsole(void) 2031 { 2032 struct wsdisplay_softc *sc; 2033 struct wsscreen *scr; 2034 2035 if (wsdisplay_console_device != NULL) { 2036 sc = wsdisplay_console_device; 2037 if ((scr = sc->sc_scr[0]) == NULL) 2038 return; 2039 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 2040 scr->scr_dconf->emulcookie, 2041 0, NULL, NULL); 2042 } 2043 } 2044 2045 /* 2046 * Switch the console at shutdown. 2047 */ 2048 static void 2049 wsdisplay_shutdownhook(void *arg) 2050 { 2051 2052 wsdisplay_switchtoconsole(); 2053 } 2054