1 /* $NetBSD: wsdisplay.c,v 1.15 1999/01/14 11:40:58 drochner 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 static const char _copyright[] __attribute__ ((unused)) = 34 "Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved."; 35 static const char _rcsid[] __attribute__ ((unused)) = 36 "$NetBSD: wsdisplay.c,v 1.15 1999/01/14 11:40:58 drochner Exp $"; 37 38 #include <sys/param.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/ioctl.h> 42 #include <sys/kernel.h> 43 #include <sys/proc.h> 44 #include <sys/malloc.h> 45 #include <sys/syslog.h> 46 #include <sys/systm.h> 47 #include <sys/tty.h> 48 #include <sys/signalvar.h> 49 #include <sys/errno.h> 50 #include <sys/fcntl.h> 51 #include <sys/vnode.h> 52 53 #include <dev/wscons/wsconsio.h> 54 #include <dev/wscons/wsdisplayvar.h> 55 #include <dev/wscons/wsksymvar.h> 56 #include <dev/wscons/wsksymdef.h> 57 #include <dev/wscons/wsemulvar.h> 58 #include <dev/wscons/wscons_callbacks.h> 59 #include <dev/cons.h> 60 61 #include "opt_wsdisplay_compat.h" 62 63 #include "wsdisplay.h" 64 65 struct wsscreen_internal { 66 const struct wsdisplay_emulops *emulops; 67 void *emulcookie; 68 69 const struct wsscreen_descr *scrdata; 70 71 const struct wsemul_ops *wsemul; 72 void *wsemulcookie; 73 }; 74 75 struct wsscreen { 76 struct wsscreen_internal *scr_dconf; 77 78 struct tty *scr_tty; 79 int scr_hold_screen; /* hold tty output */ 80 81 int scr_flags; 82 #define SCR_OPEN 1 /* is it open? */ 83 #define SCR_WAITACTIVE 2 /* someone waiting on activation */ 84 #define SCR_GRAPHICS 4 /* graphics mode, no text (emulation) output */ 85 const struct wscons_syncops *scr_syncops; 86 void *scr_synccookie; 87 88 #ifdef WSDISPLAY_COMPAT_RAWKBD 89 int scr_rawkbd; 90 #endif 91 92 struct wsdisplay_softc *sc; 93 }; 94 95 struct wsscreen *wsscreen_attach __P((struct wsdisplay_softc *, int, 96 const char *, 97 const struct wsscreen_descr *, void *, 98 int, int, long)); 99 void wsscreen_detach __P((struct wsscreen *)); 100 static const struct wsscreen_descr * 101 wsdisplay_screentype_pick __P((const struct wsscreen_list *, char *)); 102 int wsdisplay_addscreen __P((struct wsdisplay_softc *, int, char *, char *)); 103 int wsdisplay_delscreen __P((struct wsdisplay_softc *, int, int)); 104 105 #define WSDISPLAY_MAXSCREEN 8 106 107 struct wsdisplay_softc { 108 struct device sc_dv; 109 110 const struct wsdisplay_accessops *sc_accessops; 111 void *sc_accesscookie; 112 113 const struct wsscreen_list *sc_scrdata; 114 115 struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN]; 116 int sc_focusidx; 117 struct wsscreen *sc_focus; 118 119 int sc_isconsole; 120 struct device *sc_kbddv; 121 122 int sc_flags; 123 #define SC_SWITCHPENDING 1 124 int sc_screenwanted; /* valid with SC_SWITCHPENDING */ 125 126 #ifdef WSDISPLAY_COMPAT_RAWKBD 127 int sc_rawkbd; 128 #endif 129 }; 130 131 #if NWSDISPLAY > 0 132 extern struct cfdriver wsdisplay_cd; 133 #endif /* NWSDISPLAY > 0 */ 134 135 /* Autoconfiguration definitions. */ 136 static int wsdisplay_emul_match __P((struct device *, struct cfdata *, 137 void *)); 138 static void wsdisplay_emul_attach __P((struct device *, struct device *, 139 void *)); 140 static int wsdisplay_noemul_match __P((struct device *, struct cfdata *, 141 void *)); 142 static void wsdisplay_noemul_attach __P((struct device *, struct device *, 143 void *)); 144 145 struct cfattach wsdisplay_emul_ca = { 146 sizeof (struct wsdisplay_softc), 147 wsdisplay_emul_match, 148 wsdisplay_emul_attach, 149 }; 150 151 struct cfattach wsdisplay_noemul_ca = { 152 sizeof (struct wsdisplay_softc), 153 wsdisplay_noemul_match, 154 wsdisplay_noemul_attach, 155 }; 156 157 /* Exported tty- and cdevsw-related functions. */ 158 cdev_decl(wsdisplay); 159 160 #if NWSDISPLAY > 0 161 static void wsdisplaystart __P((struct tty *)); 162 static int wsdisplayparam __P((struct tty *, struct termios *)); 163 #endif /* NWSDISPLAY > 0 */ 164 165 166 /* Internal macros, functions, and variables. */ 167 #define SET(t, f) (t) |= (f) 168 #define CLR(t, f) (t) &= ~(f) 169 #define ISSET(t, f) ((t) & (f)) 170 171 #define WSDISPLAYUNIT(dev) (minor(dev) >> 8) 172 #define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff) 173 #define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255) 174 #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen)) 175 #define WSDISPLAYBURST (OBUFSIZ - 1) 176 177 #define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL) 178 #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL) 179 180 static void wsdisplay_common_attach __P((struct wsdisplay_softc *sc, 181 int console, const struct wsscreen_list *, 182 const struct wsdisplay_accessops *accessops, 183 void *accesscookie)); 184 185 #ifdef WSDISPLAY_COMPAT_RAWKBD 186 int wsdisplay_update_rawkbd __P((struct wsdisplay_softc *, 187 struct wsscreen *)); 188 #endif 189 190 static int wsdisplay_console_initted; 191 static struct wsdisplay_softc *wsdisplay_console_device; 192 static struct wsscreen_internal wsdisplay_console_conf; 193 194 static int wsdisplay_getc_dummy __P((dev_t)); 195 static void wsdisplay_pollc_dummy __P((dev_t, int)); 196 197 static struct consdev wsdisplay_cons = { 198 NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, 199 wsdisplay_pollc_dummy, NODEV, CN_NORMAL 200 }; 201 202 int wsdisplay_switch1 __P((void *, int)); 203 204 struct wsscreen * 205 wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr) 206 struct wsdisplay_softc *sc; 207 int console; 208 const char *emul; 209 const struct wsscreen_descr *type; 210 void *cookie; 211 int ccol, crow; 212 long defattr; 213 { 214 struct wsscreen_internal *dconf; 215 struct wsscreen *scr; 216 217 scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_WAITOK); 218 if (!scr) 219 return (NULL); 220 221 if (console) { 222 dconf = &wsdisplay_console_conf; 223 /* 224 * If there's an emulation, tell it about the callback argument. 225 * The other stuff is already there. 226 */ 227 if (dconf->wsemul != NULL) 228 (*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0); 229 } else { /* not console */ 230 dconf = malloc(sizeof(struct wsscreen_internal), 231 M_DEVBUF, M_NOWAIT); 232 dconf->emulops = type->textops; 233 dconf->emulcookie = cookie; 234 if (dconf->emulops) { 235 dconf->wsemul = wsemul_pick(emul); 236 if (dconf->wsemul == NULL) { 237 free(dconf, M_DEVBUF); 238 free(scr, M_DEVBUF); 239 return (NULL); 240 } 241 dconf->wsemulcookie = 242 (*dconf->wsemul->attach)(0, type, cookie, 243 ccol, crow, scr, defattr); 244 } else 245 dconf->wsemul = NULL; 246 dconf->scrdata = type; 247 } 248 249 scr->scr_dconf = dconf; 250 251 scr->scr_tty = ttymalloc(); 252 tty_attach(scr->scr_tty); 253 scr->scr_hold_screen = 0; 254 if (WSSCREEN_HAS_EMULATOR(scr)) 255 scr->scr_flags = 0; 256 else 257 scr->scr_flags = SCR_GRAPHICS; 258 259 scr->scr_syncops = 0; 260 scr->sc = sc; 261 #ifdef WSDISPLAY_COMPAT_RAWKBD 262 scr->scr_rawkbd = 0; 263 #endif 264 return (scr); 265 } 266 267 void 268 wsscreen_detach(scr) 269 struct wsscreen *scr; 270 { 271 int ccol, crow; /* XXX */ 272 273 if (WSSCREEN_HAS_TTY(scr)) { 274 tty_detach(scr->scr_tty); 275 ttyfree(scr->scr_tty); 276 } 277 if (WSSCREEN_HAS_EMULATOR(scr)) 278 (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie, 279 &ccol, &crow); 280 free(scr->scr_dconf, M_DEVBUF); 281 free(scr, M_DEVBUF); 282 } 283 284 static const struct wsscreen_descr * 285 wsdisplay_screentype_pick(scrdata, name) 286 const struct wsscreen_list *scrdata; 287 char *name; 288 { 289 int i; 290 const struct wsscreen_descr *scr; 291 292 KASSERT(scrdata->nscreens > 0); 293 294 if (name == NULL) 295 return (scrdata->screens[0]); 296 297 for (i = 0; i < scrdata->nscreens; i++) { 298 scr = scrdata->screens[i]; 299 if (!strcmp(name, scr->name)) 300 return (scr); 301 } 302 303 return (0); 304 } 305 306 int 307 wsdisplay_addscreen(sc, idx, screentype, emul) 308 struct wsdisplay_softc *sc; 309 int idx; 310 char *screentype, *emul; 311 { 312 const struct wsscreen_descr *scrdesc; 313 int error; 314 void *cookie; 315 int ccol, crow; 316 long defattr; 317 struct wsscreen *scr; 318 319 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 320 return (EINVAL); 321 if (sc->sc_scr[idx] != NULL) 322 return (EBUSY); 323 324 scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype); 325 if (!scrdesc) 326 return (ENXIO); 327 error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie, 328 scrdesc, &cookie, &ccol, &crow, &defattr); 329 if (error) 330 return (error); 331 332 scr = wsscreen_attach(sc, 0, emul, scrdesc, 333 cookie, ccol, crow, defattr); 334 if (scr == NULL) { 335 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 336 cookie); 337 return (ENXIO); 338 } 339 340 sc->sc_scr[idx] = scr; 341 342 printf("%s: screen %d added (%s", sc->sc_dv.dv_xname, idx, 343 scrdesc->name); 344 if (WSSCREEN_HAS_EMULATOR(scr)) 345 printf(", %s emulation", scr->scr_dconf->wsemul->name); 346 printf(")\n"); 347 return (0); 348 } 349 350 int 351 wsdisplay_delscreen(sc, idx, flags) 352 struct wsdisplay_softc *sc; 353 int idx, flags; 354 { 355 struct wsscreen *scr; 356 int maj, mn, s; 357 void *cookie; 358 359 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) 360 return (EINVAL); 361 scr = sc->sc_scr[idx]; 362 if (!scr) 363 return (ENXIO); 364 365 if (scr->scr_dconf == &wsdisplay_console_conf || 366 scr->scr_syncops || 367 ((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE))) 368 return(EBUSY); 369 370 /* locate the major number */ 371 for (maj = 0; maj < nchrdev; maj++) 372 if (cdevsw[maj].d_open == wsdisplayopen) 373 break; 374 375 /* nuke the vnodes */ 376 mn = WSDISPLAYMINOR(sc->sc_dv.dv_unit, idx); 377 vdevgone(maj, mn, mn, VCHR); 378 379 /* 380 * delete pointers, so neither device entries 381 * nor keyboard input can reference it anymore 382 */ 383 s = spltty(); 384 if (sc->sc_focus == scr) 385 sc->sc_focus = 0; 386 sc->sc_scr[idx] = 0; 387 splx(s); 388 389 /* 390 * Wake up processes waiting for the screen to 391 * be activated. Sleepers must check whether 392 * the screen still exists. 393 */ 394 if (scr->scr_flags & SCR_WAITACTIVE) 395 wakeup(scr); 396 397 /* save a reference to the graphics screen */ 398 cookie = scr->scr_dconf->emulcookie; 399 400 wsscreen_detach(scr); 401 402 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, 403 cookie); 404 405 printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx); 406 return (0); 407 } 408 409 /* 410 * Autoconfiguration functions. 411 */ 412 int 413 wsdisplay_emul_match(parent, match, aux) 414 struct device *parent; 415 struct cfdata *match; 416 void *aux; 417 { 418 struct wsemuldisplaydev_attach_args *ap = aux; 419 420 if (match->wsemuldisplaydevcf_console != 421 WSEMULDISPLAYDEVCF_CONSOLE_UNK) { 422 /* 423 * If console-ness of device specified, either match 424 * exactly (at high priority), or fail. 425 */ 426 if (match->wsemuldisplaydevcf_console != 0 && 427 ap->console != 0) 428 return (10); 429 else 430 return (0); 431 } 432 433 /* If console-ness unspecified, it wins. */ 434 return (1); 435 } 436 437 void 438 wsdisplay_emul_attach(parent, self, aux) 439 struct device *parent, *self; 440 void *aux; 441 { 442 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; 443 struct wsemuldisplaydev_attach_args *ap = aux; 444 445 wsdisplay_common_attach(sc, ap->console, ap->scrdata, 446 ap->accessops, ap->accesscookie); 447 448 if (ap->console) { 449 int maj; 450 451 /* locate the major number */ 452 for (maj = 0; maj < nchrdev; maj++) 453 if (cdevsw[maj].d_open == wsdisplayopen) 454 break; 455 456 cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(self->dv_unit, 0)); 457 } 458 } 459 460 /* Print function (for parent devices). */ 461 int 462 wsemuldisplaydevprint(aux, pnp) 463 void *aux; 464 const char *pnp; 465 { 466 #if 0 /* -Wunused */ 467 struct wsemuldisplaydev_attach_args *ap = aux; 468 #endif 469 470 if (pnp) 471 printf("wsdisplay at %s", pnp); 472 #if 0 /* don't bother; it's ugly */ 473 printf(" console %d", ap->console); 474 #endif 475 476 return (UNCONF); 477 } 478 479 int 480 wsdisplay_noemul_match(parent, match, aux) 481 struct device *parent; 482 struct cfdata *match; 483 void *aux; 484 { 485 #if 0 /* -Wunused */ 486 struct wsdisplaydev_attach_args *ap = aux; 487 #endif 488 489 /* Always match. */ 490 return (1); 491 } 492 493 void 494 wsdisplay_noemul_attach(parent, self, aux) 495 struct device *parent, *self; 496 void *aux; 497 { 498 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; 499 struct wsdisplaydev_attach_args *ap = aux; 500 501 wsdisplay_common_attach(sc, 0, NULL, ap->accessops, ap->accesscookie); 502 } 503 504 /* Print function (for parent devices). */ 505 int 506 wsdisplaydevprint(aux, pnp) 507 void *aux; 508 const char *pnp; 509 { 510 #if 0 /* -Wunused */ 511 struct wsdisplaydev_attach_args *ap = aux; 512 #endif 513 514 if (pnp) 515 printf("wsdisplay at %s", pnp); 516 517 return (UNCONF); 518 } 519 520 static void 521 wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) 522 struct wsdisplay_softc *sc; 523 int console; 524 const struct wsscreen_list *scrdata; 525 const struct wsdisplay_accessops *accessops; 526 void *accesscookie; 527 { 528 int i = 0; 529 530 if (console) { 531 KASSERT(wsdisplay_console_initted); 532 KASSERT(wsdisplay_console_device == NULL); 533 534 sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0); 535 wsdisplay_console_device = sc; 536 537 printf(": console (%s, %s emulation)", 538 wsdisplay_console_conf.scrdata->name, 539 wsdisplay_console_conf.wsemul->name); 540 541 sc->sc_focusidx = 0; 542 sc->sc_focus = sc->sc_scr[0]; 543 i++; 544 } 545 546 printf("\n"); 547 548 sc->sc_accessops = accessops; 549 sc->sc_accesscookie = accesscookie; 550 sc->sc_scrdata = scrdata; 551 552 sc->sc_isconsole = console; 553 sc->sc_kbddv = NULL; 554 555 wscons_glue_set_callback(); 556 557 /* 558 * Set up a number of virtual screens if possible. The 559 * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code 560 * should go away as soon as we have a userspace utility. 561 */ 562 #ifndef WSDISPLAY_DEFAULTSCREENS 563 #define WSDISPLAY_DEFAULTSCREENS WSDISPLAY_MAXSCREEN 564 #endif 565 for (; i < WSDISPLAY_DEFAULTSCREENS; i++) 566 if (wsdisplay_addscreen(sc, i, 0, 0)) 567 break; 568 } 569 570 void 571 wsdisplay_cnattach(type, cookie, ccol, crow, defattr) 572 const struct wsscreen_descr *type; 573 void *cookie; 574 int ccol, crow; 575 long defattr; 576 { 577 const struct wsemul_ops *wsemul; 578 579 KASSERT(!wsdisplay_console_initted); 580 KASSERT(type->nrows > 0); 581 KASSERT(type->ncols > 0); 582 KASSERT(crow < type->nrows); 583 KASSERT(ccol < type->ncols); 584 585 wsdisplay_console_conf.emulops = type->textops; 586 wsdisplay_console_conf.emulcookie = cookie; 587 wsdisplay_console_conf.scrdata = type; 588 589 wsemul = wsemul_pick(0); /* default */ 590 wsdisplay_console_conf.wsemul = wsemul; 591 wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, 592 ccol, crow, 593 defattr); 594 595 cn_tab = &wsdisplay_cons; 596 597 wsdisplay_console_initted = 1; 598 } 599 600 /* 601 * Tty and cdevsw functions. 602 */ 603 int 604 wsdisplayopen(dev, flag, mode, p) 605 dev_t dev; 606 int flag, mode; 607 struct proc *p; 608 { 609 #if NWSDISPLAY > 0 610 struct wsdisplay_softc *sc; 611 struct tty *tp; 612 int unit, newopen, error; 613 struct wsscreen *scr; 614 615 unit = WSDISPLAYUNIT(dev); 616 if (unit >= wsdisplay_cd.cd_ndevs || /* make sure it was attached */ 617 (sc = wsdisplay_cd.cd_devs[unit]) == NULL) 618 return (ENXIO); 619 620 if (ISWSDISPLAYCTL(dev)) 621 return (0); 622 623 if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) 624 return (ENXIO); 625 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 626 if (!scr) 627 return (ENXIO); 628 629 if (WSSCREEN_HAS_TTY(scr)) { 630 tp = scr->scr_tty; 631 tp->t_oproc = wsdisplaystart; 632 tp->t_param = wsdisplayparam; 633 tp->t_dev = dev; 634 newopen = (tp->t_state & TS_ISOPEN) == 0; 635 if (newopen) { 636 ttychars(tp); 637 tp->t_iflag = TTYDEF_IFLAG; 638 tp->t_oflag = TTYDEF_OFLAG; 639 tp->t_cflag = TTYDEF_CFLAG; 640 tp->t_lflag = TTYDEF_LFLAG; 641 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 642 wsdisplayparam(tp, &tp->t_termios); 643 ttsetwater(tp); 644 } else if ((tp->t_state & TS_XCLUDE) != 0 && 645 p->p_ucred->cr_uid != 0) 646 return EBUSY; 647 tp->t_state |= TS_CARR_ON; 648 649 error = ((*linesw[tp->t_line].l_open)(dev, tp)); 650 if (error) 651 return (error); 652 653 if (newopen && WSSCREEN_HAS_EMULATOR(scr)) { 654 /* set window sizes as appropriate, and reset 655 the emulation */ 656 tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows; 657 tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols; 658 659 /* wsdisplay_set_emulation() */ 660 } 661 } 662 663 scr->scr_flags |= SCR_OPEN; 664 return (0); 665 #else 666 return (ENXIO); 667 #endif /* NWSDISPLAY > 0 */ 668 } 669 670 int 671 wsdisplayclose(dev, flag, mode, p) 672 dev_t dev; 673 int flag, mode; 674 struct proc *p; 675 { 676 #if NWSDISPLAY > 0 677 struct wsdisplay_softc *sc; 678 struct tty *tp; 679 int unit; 680 struct wsscreen *scr; 681 682 unit = WSDISPLAYUNIT(dev); 683 sc = wsdisplay_cd.cd_devs[unit]; 684 685 if (ISWSDISPLAYCTL(dev)) 686 return (0); 687 688 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 689 690 if (WSSCREEN_HAS_TTY(scr)) { 691 if (scr->scr_hold_screen) { 692 int s; 693 694 /* XXX RESET KEYBOARD LEDS, etc. */ 695 s = spltty(); /* avoid conflict with keyboard */ 696 wsdisplay_kbdholdscreen((struct device *)sc, 0); 697 splx(s); 698 } 699 tp = scr->scr_tty; 700 (*linesw[tp->t_line].l_close)(tp, flag); 701 ttyclose(tp); 702 } 703 704 if (scr->scr_syncops) 705 (*scr->scr_syncops->destroy)(scr->scr_synccookie); 706 707 if (WSSCREEN_HAS_EMULATOR(scr)) { 708 scr->scr_flags &= ~SCR_GRAPHICS; 709 if (scr->scr_dconf->wsemul->reset != NULL) 710 (*scr->scr_dconf->wsemul->reset) 711 (scr->scr_dconf->wsemulcookie, WSEMUL_RESET); 712 713 } 714 715 #ifdef WSDISPLAY_COMPAT_RAWKBD 716 if (scr->scr_rawkbd) { 717 int kbmode = WSKBD_TRANSLATED; 718 (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, 719 (caddr_t)&kbmode, 0, p); 720 } 721 #endif 722 723 scr->scr_flags &= ~SCR_OPEN; 724 725 return (0); 726 #else 727 return (ENXIO); 728 #endif /* NWSDISPLAY > 0 */ 729 } 730 731 int 732 wsdisplayread(dev, uio, flag) 733 dev_t dev; 734 struct uio *uio; 735 int flag; 736 { 737 #if NWSDISPLAY > 0 738 struct wsdisplay_softc *sc; 739 struct tty *tp; 740 int unit; 741 struct wsscreen *scr; 742 743 unit = WSDISPLAYUNIT(dev); 744 sc = wsdisplay_cd.cd_devs[unit]; 745 746 if (ISWSDISPLAYCTL(dev)) 747 return (0); 748 749 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 750 751 if (!WSSCREEN_HAS_TTY(scr)) 752 return (ENODEV); 753 754 tp = scr->scr_tty; 755 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 756 #else 757 return (ENXIO); 758 #endif /* NWSDISPLAY > 0 */ 759 } 760 761 int 762 wsdisplaywrite(dev, uio, flag) 763 dev_t dev; 764 struct uio *uio; 765 int flag; 766 { 767 #if NWSDISPLAY > 0 768 struct wsdisplay_softc *sc; 769 struct tty *tp; 770 int unit; 771 struct wsscreen *scr; 772 773 unit = WSDISPLAYUNIT(dev); 774 sc = wsdisplay_cd.cd_devs[unit]; 775 776 if (ISWSDISPLAYCTL(dev)) 777 return (0); 778 779 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 780 781 if (!WSSCREEN_HAS_TTY(scr)) 782 return (ENODEV); 783 784 tp = scr->scr_tty; 785 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 786 #else 787 return (ENXIO); 788 #endif /* NWSDISPLAY > 0 */ 789 } 790 791 struct tty * 792 wsdisplaytty(dev) 793 dev_t dev; 794 { 795 #if NWSDISPLAY > 0 796 struct wsdisplay_softc *sc; 797 int unit; 798 struct wsscreen *scr; 799 800 unit = WSDISPLAYUNIT(dev); 801 sc = wsdisplay_cd.cd_devs[unit]; 802 803 if (ISWSDISPLAYCTL(dev)) 804 panic("wsdisplaytty() on ctl device"); 805 806 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 807 808 return (scr->scr_tty); 809 #else 810 return (NULL); 811 #endif /* NWSDISPLAY > 0 */ 812 } 813 814 int 815 wsdisplayioctl(dev, cmd, data, flag, p) 816 dev_t dev; 817 u_long cmd; 818 caddr_t data; 819 int flag; 820 struct proc *p; 821 { 822 #if NWSDISPLAY > 0 823 struct wsdisplay_softc *sc; 824 struct tty *tp; 825 int unit, error; 826 struct wsscreen *scr; 827 828 unit = WSDISPLAYUNIT(dev); 829 sc = wsdisplay_cd.cd_devs[unit]; 830 831 if (ISWSDISPLAYCTL(dev)) 832 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)); 833 834 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 835 836 if (WSSCREEN_HAS_TTY(scr)) { 837 tp = scr->scr_tty; 838 839 /* printf("disc\n"); */ 840 /* do the line discipline ioctls first */ 841 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 842 if (error >= 0) 843 return error; 844 845 /* printf("tty\n"); */ 846 /* then the tty ioctls */ 847 error = ttioctl(tp, cmd, data, flag, p); 848 if (error >= 0) 849 return error; 850 } 851 852 #ifdef WSDISPLAY_COMPAT_USL 853 error = wsdisplay_usl_ioctl(sc, scr, cmd, data, flag, p); 854 if (error >= 0) 855 return (error); 856 #endif 857 858 error = wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p); 859 return (error != -1 ? error : ENOTTY); 860 #else 861 return (ENXIO); 862 #endif /* NWSDISPLAY > 0 */ 863 } 864 865 int 866 wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p) 867 struct wsdisplay_softc *sc; 868 struct wsscreen *scr; 869 u_long cmd; 870 caddr_t data; 871 int flag; 872 struct proc *p; 873 { 874 int error; 875 char namebuf[16]; 876 struct wsdisplay_font fd; 877 878 if (sc->sc_kbddv != NULL) { 879 /* check ioctls for keyboard */ 880 #ifdef WSDISPLAY_COMPAT_RAWKBD 881 switch (cmd) { 882 case WSKBDIO_SETMODE: 883 scr->scr_rawkbd = (*(int *)data == WSKBD_RAW); 884 return (wsdisplay_update_rawkbd(sc, scr)); 885 case WSKBDIO_GETMODE: 886 *(int *)data = (scr->scr_rawkbd ? 887 WSKBD_RAW : WSKBD_TRANSLATED); 888 return (0); 889 } 890 #endif 891 /* printf("kbdcallback\n"); */ 892 error = wskbd_displayioctl(sc->sc_kbddv, cmd, data, flag, p); 893 if (error >= 0) 894 return error; 895 } 896 897 /* printf("display\n"); */ 898 switch (cmd) { 899 case WSDISPLAYIO_GMODE: 900 *(u_int *)data = (scr->scr_flags & SCR_GRAPHICS ? 901 WSDISPLAYIO_MODE_MAPPED : 902 WSDISPLAYIO_MODE_EMUL); 903 return (0); 904 905 case WSDISPLAYIO_SMODE: 906 #define d (*(int *)data) 907 if (d != WSDISPLAYIO_MODE_EMUL && 908 d != WSDISPLAYIO_MODE_MAPPED) 909 return (EINVAL); 910 911 if (WSSCREEN_HAS_EMULATOR(scr)) { 912 scr->scr_flags &= ~SCR_GRAPHICS; 913 if (d == WSDISPLAYIO_MODE_MAPPED) 914 scr->scr_flags |= SCR_GRAPHICS; 915 } else if (d == WSDISPLAYIO_MODE_EMUL) 916 return (EINVAL); 917 return (0); 918 #undef d 919 920 case WSDISPLAYIO_USEFONT: 921 #define d ((struct wsdisplay_usefontdata *)data) 922 if (!sc->sc_accessops->load_font) 923 return (EINVAL); 924 if (d->name) { 925 error = copyinstr(d->name, namebuf, sizeof(namebuf), 0); 926 if (error) 927 return (error); 928 fd.name = namebuf; 929 } else 930 fd.name = 0; 931 fd.data = 0; 932 error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 933 scr->scr_dconf->emulcookie, &fd); 934 if (!error && WSSCREEN_HAS_EMULATOR(scr) && 935 scr->scr_dconf->wsemul->reset != NULL) 936 (*scr->scr_dconf->wsemul->reset) 937 (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT); 938 return (error); 939 #undef d 940 } 941 942 /* check ioctls for display */ 943 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, 944 flag, p)); 945 } 946 947 int 948 wsdisplay_cfg_ioctl(sc, cmd, data, flag, p) 949 struct wsdisplay_softc *sc; 950 u_long cmd; 951 caddr_t data; 952 int flag; 953 struct proc *p; 954 { 955 int error; 956 char *type, typebuf[16], *emul, emulbuf[16]; 957 void *buf; 958 959 switch (cmd) { 960 case WSDISPLAYIO_ADDSCREEN: 961 #define d ((struct wsdisplay_addscreendata *)data) 962 if (d->screentype) { 963 error = copyinstr(d->screentype, typebuf, 964 sizeof(typebuf), 0); 965 if (error) 966 return (error); 967 type = typebuf; 968 } else 969 type = 0; 970 if (d->emul) { 971 error = copyinstr(d->emul, emulbuf, sizeof(emulbuf), 0); 972 if (error) 973 return (error); 974 emul = emulbuf; 975 } else 976 emul = 0; 977 978 return (wsdisplay_addscreen(sc, d->idx, type, emul)); 979 #undef d 980 case WSDISPLAYIO_DELSCREEN: 981 #define d ((struct wsdisplay_delscreendata *)data) 982 return (wsdisplay_delscreen(sc, d->idx, d->flags)); 983 #undef d 984 case WSDISPLAYIO_LDFONT: 985 #define d ((struct wsdisplay_font *)data) 986 if (!sc->sc_accessops->load_font) 987 return (EINVAL); 988 if (d->name) { 989 error = copyinstr(d->name, typebuf, sizeof(typebuf), 0); 990 if (error) 991 return (error); 992 d->name = typebuf; 993 } else 994 d->name = "loaded"; /* ??? */ 995 buf = malloc(d->fontheight * d->stride * d->numchars, 996 M_DEVBUF, M_WAITOK); 997 error = copyin(d->data, buf, 998 d->fontheight * d->stride * d->numchars); 999 if (error) { 1000 free(buf, M_DEVBUF); 1001 return (error); 1002 } 1003 d->data = buf; 1004 error = 1005 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d); 1006 free(buf, M_DEVBUF); 1007 #undef d 1008 return (error); 1009 } 1010 return (EINVAL); 1011 } 1012 1013 int 1014 wsdisplaymmap(dev, offset, prot) 1015 dev_t dev; 1016 int offset; /* XXX */ 1017 int prot; 1018 { 1019 #if NWSDISPLAY > 0 1020 struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; 1021 struct wsscreen *scr; 1022 1023 if (ISWSDISPLAYCTL(dev)) 1024 return (-1); 1025 1026 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 1027 1028 if (!(scr->scr_flags & SCR_GRAPHICS)) 1029 return (-1); 1030 1031 /* pass mmap to display */ 1032 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot)); 1033 #else 1034 return (-1); 1035 #endif /* NWSDISPLAY > 0 */ 1036 } 1037 1038 int 1039 wsdisplaypoll(dev, events, p) 1040 dev_t dev; 1041 int events; 1042 struct proc *p; 1043 { 1044 #if NWSDISPLAY > 0 1045 struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; 1046 struct wsscreen *scr; 1047 1048 if (ISWSDISPLAYCTL(dev)) 1049 return (0); 1050 1051 scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; 1052 1053 if (WSSCREEN_HAS_TTY(scr)) 1054 return (ttpoll(dev, events, p)); 1055 else 1056 return (0); 1057 #else 1058 return (0); 1059 #endif /* NWSDISPLAY > 0 */ 1060 } 1061 1062 #if NWSDISPLAY > 0 1063 void 1064 wsdisplaystart(tp) 1065 register struct tty *tp; 1066 { 1067 struct wsdisplay_softc *sc; 1068 struct wsscreen *scr; 1069 register int s, n; 1070 u_char buf[WSDISPLAYBURST]; 1071 1072 s = spltty(); 1073 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 1074 splx(s); 1075 return; 1076 } 1077 sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(tp->t_dev)]; 1078 scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]; 1079 if (scr->scr_hold_screen) { 1080 tp->t_state |= TS_TIMEOUT; 1081 splx(s); 1082 return; 1083 } 1084 tp->t_state |= TS_BUSY; 1085 splx(s); 1086 1087 n = q_to_b(&tp->t_outq, buf, sizeof(buf)); 1088 1089 if (!(scr->scr_flags & SCR_GRAPHICS)) { 1090 KASSERT(WSSCREEN_HAS_EMULATOR(scr)); 1091 (*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie, 1092 buf, n, 0); 1093 } 1094 1095 s = spltty(); 1096 tp->t_state &= ~TS_BUSY; 1097 /* Come back if there's more to do */ 1098 if (tp->t_outq.c_cc) { 1099 tp->t_state |= TS_TIMEOUT; 1100 timeout(ttrstrt, tp, (hz > 128) ? (hz / 128) : 1); 1101 } 1102 if (tp->t_outq.c_cc <= tp->t_lowat) { 1103 if (tp->t_state&TS_ASLEEP) { 1104 tp->t_state &= ~TS_ASLEEP; 1105 wakeup((caddr_t)&tp->t_outq); 1106 } 1107 selwakeup(&tp->t_wsel); 1108 } 1109 splx(s); 1110 } 1111 #endif /* NWSDISPLAY > 0 */ 1112 1113 void 1114 wsdisplaystop(tp, flag) 1115 struct tty *tp; 1116 int flag; 1117 { 1118 int s; 1119 1120 s = spltty(); 1121 if (ISSET(tp->t_state, TS_BUSY)) 1122 if (!ISSET(tp->t_state, TS_TTSTOP)) 1123 SET(tp->t_state, TS_FLUSH); 1124 splx(s); 1125 } 1126 1127 #if NWSDISPLAY > 0 1128 /* Set line parameters. */ 1129 int 1130 wsdisplayparam(tp, t) 1131 struct tty *tp; 1132 struct termios *t; 1133 { 1134 1135 tp->t_ispeed = t->c_ispeed; 1136 tp->t_ospeed = t->c_ospeed; 1137 tp->t_cflag = t->c_cflag; 1138 return 0; 1139 } 1140 #endif /* NWSDISPLAY > 0 */ 1141 1142 /* 1143 * Callbacks for the emulation code. 1144 */ 1145 void 1146 wsdisplay_emulbell(v) 1147 void *v; 1148 { 1149 struct wsscreen *scr = v; 1150 1151 if (scr == NULL) /* console, before real attach */ 1152 return; 1153 1154 if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */ 1155 return; 1156 1157 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, 1158 FWRITE, NULL); 1159 } 1160 1161 void 1162 wsdisplay_emulinput(v, data, count) 1163 void *v; 1164 const u_char *data; 1165 u_int count; 1166 { 1167 struct wsscreen *scr = v; 1168 struct tty *tp; 1169 1170 if (v == NULL) /* console, before real attach */ 1171 return; 1172 1173 if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */ 1174 return; 1175 if (!WSSCREEN_HAS_TTY(scr)) 1176 return; 1177 1178 tp = scr->scr_tty; 1179 while (count-- > 0) 1180 (*linesw[tp->t_line].l_rint)(*data++, tp); 1181 }; 1182 1183 /* 1184 * Calls from the keyboard interface. 1185 */ 1186 void 1187 wsdisplay_kbdinput(dev, ks) 1188 struct device *dev; 1189 keysym_t ks; 1190 { 1191 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1192 struct wsscreen *scr; 1193 char *dp; 1194 int count; 1195 struct tty *tp; 1196 1197 KASSERT(sc != NULL); 1198 1199 scr = sc->sc_focus; 1200 1201 if (!scr || !WSSCREEN_HAS_TTY(scr)) 1202 return; 1203 1204 tp = scr->scr_tty; 1205 1206 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1207 (*linesw[tp->t_line].l_rint)(KS_VALUE(ks), tp); 1208 else if (WSSCREEN_HAS_EMULATOR(scr)) { 1209 count = (*scr->scr_dconf->wsemul->translate) 1210 (scr->scr_dconf->wsemulcookie, ks, &dp); 1211 while (count-- > 0) 1212 (*linesw[tp->t_line].l_rint)(*dp++, tp); 1213 } 1214 } 1215 1216 #ifdef WSDISPLAY_COMPAT_RAWKBD 1217 int 1218 wsdisplay_update_rawkbd(sc, scr) 1219 struct wsdisplay_softc *sc; 1220 struct wsscreen *scr; 1221 { 1222 int s, data, error; 1223 s = spltty(); 1224 1225 if (!sc->sc_kbddv || 1226 scr != sc->sc_focus || 1227 sc->sc_rawkbd == scr->scr_rawkbd) { 1228 splx(s); 1229 return (0); 1230 } 1231 1232 data = (scr->scr_rawkbd ? WSKBD_RAW : WSKBD_TRANSLATED); 1233 error = wskbd_displayioctl(sc->sc_kbddv, WSKBDIO_SETMODE, 1234 (caddr_t)&data, 0, 0); 1235 if (!error) 1236 sc->sc_rawkbd = scr->scr_rawkbd; 1237 splx(s); 1238 return (error); 1239 } 1240 #endif 1241 1242 int 1243 wsdisplay_switch1(arg, waitok) 1244 void *arg; 1245 int waitok; 1246 { 1247 struct wsdisplay_softc *sc = arg; 1248 int no; 1249 struct wsscreen *scr; 1250 1251 if (!(sc->sc_flags & SC_SWITCHPENDING)) { 1252 printf("wsdisplay_switchto: not switching\n"); 1253 return (EINVAL); 1254 } 1255 1256 no = sc->sc_screenwanted; 1257 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1258 panic("wsdisplay_switch1: invalid screen %d", no); 1259 scr = sc->sc_scr[no]; 1260 if (!scr) { 1261 printf("wsdisplay_switch1: screen %d disappeared\n", no); 1262 sc->sc_flags &= ~SC_SWITCHPENDING; 1263 return (ENXIO); 1264 } 1265 1266 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, 1267 scr->scr_dconf->emulcookie); 1268 sc->sc_focusidx = no; 1269 sc->sc_focus = scr; 1270 1271 #ifdef WSDISPLAY_COMPAT_RAWKBD 1272 (void) wsdisplay_update_rawkbd(sc, scr); 1273 #endif 1274 /* keyboard map??? */ 1275 1276 if (scr->scr_syncops) { 1277 (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok); 1278 /* XXX error handling */ 1279 } 1280 1281 sc->sc_flags &= ~SC_SWITCHPENDING; 1282 1283 if (scr->scr_flags & SCR_WAITACTIVE) 1284 wakeup(scr); 1285 return (0); 1286 } 1287 1288 int 1289 wsdisplay_switch(dev, no, waitok) 1290 struct device *dev; 1291 int no, waitok; 1292 { 1293 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1294 int s, res = 0; 1295 struct wsscreen *scr; 1296 1297 if (no < 0 || no >= WSDISPLAY_MAXSCREEN || !sc->sc_scr[no]) 1298 return (ENXIO); 1299 1300 s = spltty(); 1301 1302 if (no == sc->sc_focusidx) { 1303 splx(s); 1304 return (0); 1305 } 1306 1307 if (sc->sc_flags & SC_SWITCHPENDING) { 1308 splx(s); 1309 return (EBUSY); 1310 } 1311 1312 sc->sc_flags |= SC_SWITCHPENDING; 1313 sc->sc_screenwanted = no; 1314 1315 splx(s); 1316 1317 scr = sc->sc_focus; 1318 if (!scr) 1319 return (wsdisplay_switch1(sc, waitok)); 1320 1321 #define wsswitch_callback ((void (*) __P((void *, int)))wsdisplay_switch1) 1322 if (scr->scr_syncops) { 1323 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, 1324 wsswitch_callback, sc); 1325 if (res == EAGAIN) { 1326 /* switch will be done asynchronously */ 1327 return (0); 1328 } 1329 } else if (scr->scr_flags & SCR_GRAPHICS) { 1330 /* no way to save state */ 1331 res = EBUSY; 1332 } 1333 1334 if (res) { 1335 sc->sc_flags &= ~SC_SWITCHPENDING; 1336 return (res); 1337 } else 1338 return (wsdisplay_switch1(sc, waitok)); 1339 } 1340 1341 void 1342 wsdisplay_resetemul(dev) 1343 struct device *dev; 1344 { 1345 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1346 struct wsscreen *scr; 1347 1348 KASSERT(sc != NULL); 1349 scr = sc->sc_focus; 1350 1351 if (!scr || !WSSCREEN_HAS_EMULATOR(scr)) 1352 return; 1353 1354 if (scr->scr_dconf->wsemul->reset != NULL) 1355 (*scr->scr_dconf->wsemul->reset) 1356 (scr->scr_dconf->wsemulcookie, WSEMUL_RESET); 1357 } 1358 1359 /* 1360 * Interface for (external) VT switch / process synchronization code 1361 */ 1362 int 1363 wsscreen_attach_sync(scr, ops, cookie) 1364 struct wsscreen *scr; 1365 const struct wscons_syncops *ops; 1366 void *cookie; 1367 { 1368 if (scr->scr_syncops) { 1369 /* 1370 * The screen is already claimed. 1371 * Check if the owner is still alive. 1372 */ 1373 if ((*scr->scr_syncops->check)(scr->scr_synccookie)) 1374 return (EBUSY); 1375 } 1376 scr->scr_syncops = ops; 1377 scr->scr_synccookie = cookie; 1378 return (0); 1379 } 1380 1381 int 1382 wsscreen_detach_sync(scr) 1383 struct wsscreen *scr; 1384 { 1385 if (!scr->scr_syncops) 1386 return (EINVAL); 1387 scr->scr_syncops = 0; 1388 return (0); 1389 } 1390 1391 int 1392 wsscreen_lookup_sync(scr, ops, cookiep) 1393 struct wsscreen *scr; 1394 const struct wscons_syncops *ops; /* used as ID */ 1395 void **cookiep; 1396 { 1397 if (!scr->scr_syncops || ops != scr->scr_syncops) 1398 return (EINVAL); 1399 *cookiep = scr->scr_synccookie; 1400 return (0); 1401 } 1402 1403 /* 1404 * Interface to virtual screen stuff 1405 */ 1406 int 1407 wsdisplay_maxscreenidx(sc) 1408 struct wsdisplay_softc *sc; 1409 { 1410 return (WSDISPLAY_MAXSCREEN - 1); 1411 } 1412 1413 int 1414 wsdisplay_screenstate(sc, idx) 1415 struct wsdisplay_softc *sc; 1416 int idx; 1417 { 1418 if (idx >= WSDISPLAY_MAXSCREEN) 1419 return (EINVAL); 1420 if (!sc->sc_scr[idx]) 1421 return (ENXIO); 1422 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0); 1423 } 1424 1425 int 1426 wsdisplay_getactivescreen(sc) 1427 struct wsdisplay_softc *sc; 1428 { 1429 return (sc->sc_focusidx); 1430 } 1431 1432 int 1433 wsscreen_switchwait(sc, no) 1434 struct wsdisplay_softc *sc; 1435 int no; 1436 { 1437 struct wsscreen *scr; 1438 int s, res = 0; 1439 1440 if (no < 0 || no >= WSDISPLAY_MAXSCREEN) 1441 return (ENXIO); 1442 scr = sc->sc_scr[no]; 1443 if (!scr) 1444 return (ENXIO); 1445 1446 s = spltty(); 1447 if (scr != sc->sc_focus) { 1448 scr->scr_flags |= SCR_WAITACTIVE; 1449 res = tsleep(scr, PCATCH, "wswait", 0); 1450 if (scr != sc->sc_scr[no]) 1451 res = ENXIO; /* disappeared in the meantime */ 1452 else 1453 scr->scr_flags &= ~SCR_WAITACTIVE; 1454 } 1455 splx(s); 1456 return (res); 1457 } 1458 1459 void 1460 wsdisplay_kbdholdscreen(dev, hold) 1461 struct device *dev; 1462 int hold; 1463 { 1464 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; 1465 struct wsscreen *scr; 1466 1467 scr = sc->sc_focus; 1468 1469 if (hold) 1470 scr->scr_hold_screen = 1; 1471 else { 1472 scr->scr_hold_screen = 0; 1473 timeout(ttrstrt, scr->scr_tty, 0); /* "immediate" */ 1474 } 1475 } 1476 1477 /* 1478 * Calls from the glue code. 1479 */ 1480 int 1481 wsdisplay_is_console(dv) 1482 struct device *dv; 1483 { 1484 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dv; 1485 1486 KASSERT(sc != NULL); 1487 return (sc->sc_isconsole); 1488 } 1489 1490 int 1491 wsdisplay_has_emulator(dv) 1492 struct device *dv; 1493 { 1494 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dv; 1495 struct wsscreen *scr; 1496 1497 scr = sc->sc_focus; /* ??? */ 1498 1499 KASSERT(sc != NULL); 1500 KASSERT(scr != NULL); 1501 return (WSSCREEN_HAS_EMULATOR(scr)); /* XXX XXX */ 1502 } 1503 1504 struct device * 1505 wsdisplay_kbd(dv) 1506 struct device *dv; 1507 { 1508 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dv; 1509 1510 KASSERT(sc != NULL); 1511 return (sc->sc_kbddv); 1512 } 1513 1514 void 1515 wsdisplay_set_kbd(dv, kbddv) 1516 struct device *dv, *kbddv; 1517 { 1518 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dv; 1519 1520 KASSERT(sc != NULL); 1521 if (sc->sc_kbddv) { 1522 /* disable old keyboard */ 1523 wskbd_enable(sc->sc_kbddv, 0); 1524 } 1525 if (kbddv) { 1526 /* enable new keyboard */ 1527 wskbd_enable(kbddv, 1); 1528 } 1529 sc->sc_kbddv = kbddv; 1530 } 1531 1532 /* 1533 * Console interface. 1534 */ 1535 void 1536 wsdisplay_cnputc(dev, i) 1537 dev_t dev; 1538 int i; 1539 { 1540 struct wsscreen_internal *dc; 1541 char c = i; 1542 1543 if (!wsdisplay_console_initted) 1544 return; 1545 1546 if (wsdisplay_console_device != NULL && 1547 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) 1548 return; 1549 1550 dc = &wsdisplay_console_conf; 1551 (*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1); 1552 } 1553 1554 static int 1555 wsdisplay_getc_dummy(dev) 1556 dev_t dev; 1557 { 1558 /* panic? */ 1559 return (0); 1560 } 1561 1562 static void 1563 wsdisplay_pollc_dummy(dev, on) 1564 dev_t dev; 1565 int on; 1566 { 1567 } 1568 1569 void 1570 wsdisplay_set_cons_kbd(get, poll) 1571 int (*get) __P((dev_t)); 1572 void (*poll) __P((dev_t, int)); 1573 { 1574 wsdisplay_cons.cn_getc = get; 1575 wsdisplay_cons.cn_pollc = poll; 1576 } 1577