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