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