1 /* $NetBSD: wsdisplay.c,v 1.88 2006/02/07 09:13:02 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.88 2006/02/07 09:13:02 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/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 lwp *l) 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, l->l_proc); 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 suser(l->l_proc->p_ucred, &l->l_proc->p_acflag) != 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 lwp *l) 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, l); 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 lwp *l) 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, l)); 904 905 if (ISWSDISPLAYCTL(dev)) 906 return (0); 907 908 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 909 return (POLLHUP); 910 911 if (!WSSCREEN_HAS_TTY(scr)) 912 return (POLLERR); 913 914 tp = scr->scr_tty; 915 return ((*tp->t_linesw->l_poll)(tp, events, l)); 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 lwp *l) 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, l); 972 if (error != EPASSTHROUGH) 973 return (error); 974 #endif 975 976 if (ISWSDISPLAYSTAT(dev)) 977 return (wsdisplay_stat_ioctl(sc, cmd, data, flag, l)); 978 979 if (ISWSDISPLAYCTL(dev)) 980 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, l)); 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, l); 991 if (error != EPASSTHROUGH) 992 return (error); 993 994 /* printf("tty\n"); */ 995 /* then the tty ioctls */ 996 error = ttioctl(tp, cmd, data, flag, l); 997 if (error != EPASSTHROUGH) 998 return (error); 999 } 1000 1001 #ifdef WSDISPLAY_COMPAT_USL 1002 error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, l); 1003 if (error != EPASSTHROUGH) 1004 return (error); 1005 #endif 1006 1007 return (wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, l)); 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 lwp *l) 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, l); 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, l); 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, l)); 1205 } 1206 1207 int 1208 wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, 1209 int flag, struct lwp *l) 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 lwp *l) 1223 { 1224 int error; 1225 char *type, typebuf[16], *emul, emulbuf[16]; 1226 void *tbuf; 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 tbuf = malloc(fontsz, M_DEVBUF, M_WAITOK); 1278 error = copyin(d->data, tbuf, fontsz); 1279 if (error) { 1280 free(tbuf, M_DEVBUF); 1281 return (error); 1282 } 1283 d->data = tbuf; 1284 error = 1285 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); 1286 free(tbuf, 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, l)); 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, l)); 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, l)); 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 event; 1344 1345 evar = &sc->evar; 1346 1347 if (evar == NULL) 1348 return (0); 1349 1350 if (evar->q == NULL) 1351 return (1); 1352 1353 event.type = type; 1354 event.value = value; 1355 if (wsevent_inject(evar, &event, 1) != 0) { 1356 log(LOG_WARNING, "wsdisplay: event queue overflow\n"); 1357 return (1); 1358 } 1359 1360 return (0); 1361 } 1362 1363 paddr_t 1364 wsdisplaymmap(dev_t dev, off_t offset, int prot) 1365 { 1366 struct wsdisplay_softc *sc = 1367 device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev)); 1368 struct wsscreen *scr; 1369 1370 if (ISWSDISPLAYSTAT(dev)) 1371 return (-1); 1372 1373 if (ISWSDISPLAYCTL(dev)) 1374 return (-1); 1375 1376 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) 1377 return (-1); 1378 1379 if (!(scr->scr_flags & SCR_GRAPHICS)) 1380 return (-1); 1381 1382 /* pass mmap to display */ 1383 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot)); 1384 } 1385 1386 void 1387 wsdisplaystart(struct tty *tp) 1388 { 1389 struct wsdisplay_softc *sc; 1390 struct wsscreen *scr; 1391 int s, n; 1392 u_char *tbuf; 1393 1394 s = spltty(); 1395 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 1396 splx(s); 1397 return; 1398 } 1399 sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(tp->t_dev)); 1400 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { 1401 splx(s); 1402 return; 1403 } 1404 1405 if (scr->scr_hold_screen) { 1406 tp->t_state |= TS_TIMEOUT; 1407 splx(s); 1408 return; 1409 } 1410 tp->t_state |= TS_BUSY; 1411 splx(s); 1412 1413 /* 1414 * Drain output from ring buffer. 1415 * The output will normally be in one contiguous chunk, but when the 1416 * ring wraps, it will be in two pieces.. one at the end of the ring, 1417 * the other at the start. For performance, rather than loop here, 1418 * we output one chunk, see if there's another one, and if so, output 1419 * it too. 1420 */ 1421 1422 n = ndqb(&tp->t_outq, 0); 1423 tbuf = tp->t_outq.c_cf; 1424 1425 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1426 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1427 (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie, 1428 tbuf, n, 0); 1429 } 1430 ndflush(&tp->t_outq, n); 1431 1432 if ((n = ndqb(&tp->t_outq, 0)) > 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) 1438 (scr->scr_dconf->wsemulcookie, tbuf, n, 0); 1439 } 1440 ndflush(&tp->t_outq, n); 1441 } 1442 1443 s = spltty(); 1444 tp->t_state &= ~TS_BUSY; 1445 /* Come back if there's more to do */ 1446 if (tp->t_outq.c_cc) { 1447 tp->t_state |= TS_TIMEOUT; 1448 callout_reset(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1, 1449 ttrstrt, tp); 1450 } 1451 if (tp->t_outq.c_cc <= tp->t_lowat) { 1452 if (tp->t_state&TS_ASLEEP) { 1453 tp->t_state &= ~TS_ASLEEP; 1454 wakeup(&tp->t_outq); 1455 } 1456 selwakeup(&tp->t_wsel); 1457 } 1458 splx(s); 1459 } 1460 1461 void 1462 wsdisplaystop(struct tty *tp, int flag) 1463 { 1464 int s; 1465 1466 s = spltty(); 1467 if (ISSET(tp->t_state, TS_BUSY)) 1468 if (!ISSET(tp->t_state, TS_TTSTOP)) 1469 SET(tp->t_state, TS_FLUSH); 1470 splx(s); 1471 } 1472 1473 /* Set line parameters. */ 1474 int 1475 wsdisplayparam(struct tty *tp, struct termios *t) 1476 { 1477 1478 tp->t_ispeed = t->c_ispeed; 1479 tp->t_ospeed = t->c_ospeed; 1480 tp->t_cflag = t->c_cflag; 1481 return 0; 1482 } 1483 1484 /* 1485 * Callbacks for the emulation code. 1486 */ 1487 void 1488 wsdisplay_emulbell(void *v) 1489 { 1490 struct wsscreen *scr = v; 1491 1492 if (scr == NULL) /* console, before real attach */ 1493 return; 1494 1495 if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ 1496 return; 1497 1498 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, 1499 FWRITE, NULL); 1500 } 1501 1502 void 1503 wsdisplay_emulinput(void *v, const u_char *data, u_int count) 1504 { 1505 struct wsscreen *scr = v; 1506 struct tty *tp; 1507 1508 if (v == NULL) /* console, before real attach */ 1509 return; 1510 1511 if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ 1512 return; 1513 if (!WSSCREEN_HAS_TTY(scr)) 1514 return; 1515 1516 tp = scr->scr_tty; 1517 while (count-- > 0) 1518 (*tp->t_linesw->l_rint)(*data++, tp); 1519 } 1520 1521 /* 1522 * Calls from the keyboard interface. 1523 */ 1524 void 1525 wsdisplay_kbdinput(struct device *dev, keysym_t ks) 1526 { 1527 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1528 struct wsscreen *scr; 1529 const char *dp; 1530 int count; 1531 struct tty *tp; 1532 1533 KASSERT(sc != NULL); 1534 1535 scr = sc->sc_focus; 1536 1537 if (!scr || !WSSCREEN_HAS_TTY(scr)) 1538 return; 1539 1540 tp = scr->scr_tty; 1541 1542 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1543 (*tp->t_linesw->l_rint)(KS_VALUE(ks), tp); 1544 else if (WSSCREEN_HAS_EMULATOR(scr)) { 1545 count = (*scr->scr_dconf->wsemul->translate) 1546 (scr->scr_dconf->wsemulcookie, ks, &dp); 1547 while (count-- > 0) 1548 (*tp->t_linesw->l_rint)(*dp++, tp); 1549 } 1550 } 1551 1552 #if defined(WSDISPLAY_COMPAT_RAWKBD) 1553 int 1554 wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) 1555 { 1556 #if NWSKBD > 0 1557 int s, raw, data, error; 1558 struct wsevsrc *inp; 1559 1560 s = spltty(); 1561 1562 raw = (scr ? scr->scr_rawkbd : 0); 1563 1564 if (scr != sc->sc_focus || 1565 sc->sc_rawkbd == raw) { 1566 splx(s); 1567 return (0); 1568 } 1569 1570 data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; 1571 inp = sc->sc_input; 1572 if (inp == NULL) 1573 return (ENXIO); 1574 error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0); 1575 if (!error) 1576 sc->sc_rawkbd = raw; 1577 splx(s); 1578 return (error); 1579 #else 1580 return (0); 1581 #endif 1582 } 1583 #endif 1584 1585 int 1586 wsdisplay_switch3(void *arg, int error, int waitok) 1587 { 1588 struct wsdisplay_softc *sc = arg; 1589 int no; 1590 struct wsscreen *scr; 1591 1592 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1593 printf("wsdisplay_switch3: not switching\n"); 1594 return (EINVAL); 1595 } 1596 1597 no = sc->sc_screenwanted; 1598 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1599 panic("wsdisplay_switch3: invalid screen %d", no); 1600 scr = sc->sc_scr[no]; 1601 if (!scr) { 1602 printf("wsdisplay_switch3: screen %d disappeared\n", no); 1603 error = ENXIO; 1604 } 1605 1606 if (error) { 1607 /* try to recover, avoid recursion */ 1608 1609 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1610 printf("wsdisplay_switch3: giving up\n"); 1611 sc->sc_focus = 0; 1612 #ifdef WSDISPLAY_COMPAT_RAWKBD 1613 wsdisplay_update_rawkbd(sc, 0); 1614 #endif 1615 sc->sc_flags &= ~SC_SWITCHPENDING; 1616 return (error); 1617 } 1618 1619 sc->sc_screenwanted = sc->sc_oldscreen; 1620 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1621 return (wsdisplay_switch1(arg, 0, waitok)); 1622 } 1623 1624 sc->sc_flags &= ~SC_SWITCHPENDING; 1625 1626 if (!error && (scr->scr_flags & SCR_WAITACTIVE)) 1627 wakeup(scr); 1628 return (error); 1629 } 1630 1631 int 1632 wsdisplay_switch2(void *arg, int error, int waitok) 1633 { 1634 struct wsdisplay_softc *sc = arg; 1635 int no; 1636 struct wsscreen *scr; 1637 1638 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1639 printf("wsdisplay_switch2: not switching\n"); 1640 return (EINVAL); 1641 } 1642 1643 no = sc->sc_screenwanted; 1644 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1645 panic("wsdisplay_switch2: invalid screen %d", no); 1646 scr = sc->sc_scr[no]; 1647 if (!scr) { 1648 printf("wsdisplay_switch2: screen %d disappeared\n", no); 1649 error = ENXIO; 1650 } 1651 1652 if (error) { 1653 /* try to recover, avoid recursion */ 1654 1655 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) { 1656 printf("wsdisplay_switch2: giving up\n"); 1657 sc->sc_focus = 0; 1658 sc->sc_flags &= ~SC_SWITCHPENDING; 1659 return (error); 1660 } 1661 1662 sc->sc_screenwanted = sc->sc_oldscreen; 1663 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1664 return (wsdisplay_switch1(arg, 0, waitok)); 1665 } 1666 1667 sc->sc_focusidx = no; 1668 sc->sc_focus = scr; 1669 1670 #ifdef WSDISPLAY_COMPAT_RAWKBD 1671 (void) wsdisplay_update_rawkbd(sc, scr); 1672 #endif 1673 /* keyboard map??? */ 1674 1675 #define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3) 1676 if (scr->scr_syncops) { 1677 error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, 1678 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); 1679 if (error == EAGAIN) { 1680 /* switch will be done asynchronously */ 1681 return (0); 1682 } 1683 } 1684 1685 return (wsdisplay_switch3(sc, error, waitok)); 1686 } 1687 1688 int 1689 wsdisplay_switch1(void *arg, int error, int waitok) 1690 { 1691 struct wsdisplay_softc *sc = arg; 1692 int no; 1693 struct wsscreen *scr; 1694 1695 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1696 printf("wsdisplay_switch1: not switching\n"); 1697 return (EINVAL); 1698 } 1699 1700 no = sc->sc_screenwanted; 1701 if (no == WSDISPLAY_NULLSCREEN) { 1702 sc->sc_flags &= ~SC_SWITCHPENDING; 1703 if (!error) { 1704 sc->sc_focus = 0; 1705 } 1706 wakeup(sc); 1707 return (error); 1708 } 1709 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1710 panic("wsdisplay_switch1: invalid screen %d", no); 1711 scr = sc->sc_scr[no]; 1712 if (!scr) { 1713 printf("wsdisplay_switch1: screen %d disappeared\n", no); 1714 error = ENXIO; 1715 } 1716 1717 if (error) { 1718 sc->sc_flags &= ~SC_SWITCHPENDING; 1719 return (error); 1720 } 1721 1722 #define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2) 1723 error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 1724 scr->scr_dconf->emulcookie, 1725 waitok, 1726 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); 1727 if (error == EAGAIN) { 1728 /* switch will be done asynchronously */ 1729 return (0); 1730 } 1731 1732 return (wsdisplay_switch2(sc, error, waitok)); 1733 } 1734 1735 int 1736 wsdisplay_switch(struct device *dev, int no, int waitok) 1737 { 1738 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1739 int s, res = 0; 1740 struct wsscreen *scr; 1741 1742 if (no != WSDISPLAY_NULLSCREEN) { 1743 if ((no < 0 || no >= WSDISPLAY_MAXSCREEN)) 1744 return (EINVAL); 1745 if (sc->sc_scr[no] == NULL) 1746 return (ENXIO); 1747 } 1748 1749 wsdisplay_stat_inject(dev, WSCONS_EVENT_SCREEN_SWITCH, no); 1750 1751 s = spltty(); 1752 1753 if ((sc->sc_focus && no == sc->sc_focusidx) || 1754 (sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) { 1755 splx(s); 1756 return (0); 1757 } 1758 1759 if (sc->sc_flags & SC_SWITCHPENDING) { 1760 splx(s); 1761 return (EBUSY); 1762 } 1763 1764 sc->sc_flags |= SC_SWITCHPENDING; 1765 sc->sc_screenwanted = no; 1766 1767 splx(s); 1768 1769 scr = sc->sc_focus; 1770 if (!scr) { 1771 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN; 1772 return (wsdisplay_switch1(sc, 0, waitok)); 1773 } else 1774 sc->sc_oldscreen = sc->sc_focusidx; 1775 1776 #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) 1777 if (scr->scr_syncops) { 1778 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, 1779 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); 1780 if (res == EAGAIN) { 1781 /* switch will be done asynchronously */ 1782 return (0); 1783 } 1784 } else if (scr->scr_flags & SCR_GRAPHICS) { 1785 /* no way to save state */ 1786 res = EBUSY; 1787 } 1788 1789 return (wsdisplay_switch1(sc, res, waitok)); 1790 } 1791 1792 void 1793 wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) 1794 { 1795 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1796 struct wsscreen *scr; 1797 1798 KASSERT(sc != NULL); 1799 scr = sc->sc_focus; 1800 1801 if (!scr) 1802 return; 1803 1804 switch (op) { 1805 case WSDISPLAY_RESETEMUL: 1806 if (!WSSCREEN_HAS_EMULATOR(scr)) 1807 break; 1808 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, 1809 WSEMUL_RESET); 1810 break; 1811 case WSDISPLAY_RESETCLOSE: 1812 wsdisplay_closescreen(sc, scr); 1813 break; 1814 } 1815 } 1816 1817 /* 1818 * Interface for (external) VT switch / process synchronization code 1819 */ 1820 int 1821 wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, 1822 void *cookie) 1823 { 1824 if (scr->scr_syncops) { 1825 /* 1826 * The screen is already claimed. 1827 * Check if the owner is still alive. 1828 */ 1829 if ((*scr->scr_syncops->check)(scr->scr_synccookie)) 1830 return (EBUSY); 1831 } 1832 scr->scr_syncops = ops; 1833 scr->scr_synccookie = cookie; 1834 return (0); 1835 } 1836 1837 int 1838 wsscreen_detach_sync(struct wsscreen *scr) 1839 { 1840 if (!scr->scr_syncops) 1841 return (EINVAL); 1842 scr->scr_syncops = 0; 1843 return (0); 1844 } 1845 1846 int 1847 wsscreen_lookup_sync(struct wsscreen *scr, 1848 const struct wscons_syncops *ops, /* used as ID */ 1849 void **cookiep) 1850 { 1851 if (!scr->scr_syncops || ops != scr->scr_syncops) 1852 return (EINVAL); 1853 *cookiep = scr->scr_synccookie; 1854 return (0); 1855 } 1856 1857 /* 1858 * Interface to virtual screen stuff 1859 */ 1860 int 1861 wsdisplay_maxscreenidx(struct wsdisplay_softc *sc) 1862 { 1863 return (WSDISPLAY_MAXSCREEN - 1); 1864 } 1865 1866 int 1867 wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) 1868 { 1869 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 1870 return (EINVAL); 1871 if (!sc->sc_scr[idx]) 1872 return (ENXIO); 1873 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); 1874 } 1875 1876 int 1877 wsdisplay_getactivescreen(struct wsdisplay_softc *sc) 1878 { 1879 return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); 1880 } 1881 1882 int 1883 wsscreen_switchwait(struct wsdisplay_softc *sc, int no) 1884 { 1885 struct wsscreen *scr; 1886 int s, res = 0; 1887 1888 if (no == WSDISPLAY_NULLSCREEN) { 1889 s = spltty(); 1890 while (sc->sc_focus && res == 0) { 1891 res = tsleep(sc, PCATCH, "wswait", 0); 1892 } 1893 splx(s); 1894 return (res); 1895 } 1896 1897 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1898 return (ENXIO); 1899 scr = sc->sc_scr[no]; 1900 if (!scr) 1901 return (ENXIO); 1902 1903 s = spltty(); 1904 if (scr != sc->sc_focus) { 1905 scr->scr_flags |= SCR_WAITACTIVE; 1906 res = tsleep(scr, PCATCH, "wswait", 0); 1907 if (scr != sc->sc_scr[no]) 1908 res = ENXIO; /* disappeared in the meantime */ 1909 else 1910 scr->scr_flags &= ~SCR_WAITACTIVE; 1911 } 1912 splx(s); 1913 return (res); 1914 } 1915 1916 void 1917 wsdisplay_kbdholdscreen(struct device *dev, int hold) 1918 { 1919 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1920 struct wsscreen *scr; 1921 1922 scr = sc->sc_focus; 1923 1924 if (hold) 1925 scr->scr_hold_screen = 1; 1926 else { 1927 scr->scr_hold_screen = 0; 1928 callout_reset(&scr->scr_tty->t_rstrt_ch, 0, 1929 ttrstrt, scr->scr_tty); /* "immediate" */ 1930 } 1931 } 1932 1933 #if NWSKBD > 0 1934 void 1935 wsdisplay_set_console_kbd(struct wsevsrc *src) 1936 { 1937 if (wsdisplay_console_device == NULL) { 1938 src->me_dispdv = NULL; 1939 return; 1940 } 1941 #if NWSMUX > 0 1942 if (wsmux_attach_sc((struct wsmux_softc *) 1943 wsdisplay_console_device->sc_input, src)) { 1944 src->me_dispdv = NULL; 1945 return; 1946 } 1947 #else 1948 wsdisplay_console_device->sc_input = src; 1949 #endif 1950 src->me_dispdv = &wsdisplay_console_device->sc_dv; 1951 } 1952 #endif /* NWSKBD > 0 */ 1953 1954 /* 1955 * Console interface. 1956 */ 1957 void 1958 wsdisplay_cnputc(dev_t dev, int i) 1959 { 1960 struct wsscreen_internal *dc; 1961 u_char c = i; 1962 1963 if (!wsdisplay_console_initted) 1964 return; 1965 1966 if ((wsdisplay_console_device != NULL) && 1967 (wsdisplay_console_device->sc_scr[0] != NULL) && 1968 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) 1969 return; 1970 1971 dc = &wsdisplay_console_conf; 1972 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); 1973 } 1974 1975 static int 1976 wsdisplay_getc_dummy(dev_t dev) 1977 { 1978 /* panic? */ 1979 return (0); 1980 } 1981 1982 static void 1983 wsdisplay_pollc(dev_t dev, int on) 1984 { 1985 1986 wsdisplay_cons_pollmode = on; 1987 1988 /* notify to fb drivers */ 1989 if (wsdisplay_console_device != NULL && 1990 wsdisplay_console_device->sc_accessops->pollc != NULL) 1991 (*wsdisplay_console_device->sc_accessops->pollc) 1992 (wsdisplay_console_device->sc_accesscookie, on); 1993 1994 /* notify to kbd drivers */ 1995 if (wsdisplay_cons_kbd_pollc) 1996 (*wsdisplay_cons_kbd_pollc)(NODEV, on); 1997 } 1998 1999 void 2000 wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), 2001 void (*bell)(dev_t, u_int, u_int, u_int)) 2002 { 2003 wsdisplay_cons.cn_getc = get; 2004 wsdisplay_cons.cn_bell = bell; 2005 wsdisplay_cons_kbd_pollc = poll; 2006 } 2007 2008 void 2009 wsdisplay_unset_cons_kbd(void) 2010 { 2011 wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; 2012 wsdisplay_cons.cn_bell = NULL; 2013 wsdisplay_cons_kbd_pollc = 0; 2014 } 2015 2016 /* 2017 * Switch the console display to it's first screen. 2018 */ 2019 void 2020 wsdisplay_switchtoconsole(void) 2021 { 2022 struct wsdisplay_softc *sc; 2023 struct wsscreen *scr; 2024 2025 if (wsdisplay_console_device != NULL) { 2026 sc = wsdisplay_console_device; 2027 if ((scr = sc->sc_scr[0]) == NULL) 2028 return; 2029 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 2030 scr->scr_dconf->emulcookie, 2031 0, NULL, NULL); 2032 } 2033 } 2034 2035 /* 2036 * Switch the console at shutdown. 2037 */ 2038 static void 2039 wsdisplay_shutdownhook(void *arg) 2040 { 2041 2042 wsdisplay_switchtoconsole(); 2043 } 2044