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