diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c index 8006e980dc36..66dc8dc5ef6e 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsdisplay.c,v 1.32 1999/12/01 23:22:59 augustss Exp $ */ +/* $NetBSD: wsdisplay.c,v 1.33 1999/12/06 18:52:23 drochner Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -33,7 +33,7 @@ static const char _copyright[] __attribute__ ((unused)) = "Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved."; static const char _rcsid[] __attribute__ ((unused)) = - "$NetBSD: wsdisplay.c,v 1.32 1999/12/01 23:22:59 augustss Exp $"; + "$NetBSD: wsdisplay.c,v 1.33 1999/12/06 18:52:23 drochner Exp $"; #include #include @@ -199,11 +199,14 @@ static struct wsdisplay_softc *wsdisplay_console_device; static struct wsscreen_internal wsdisplay_console_conf; static int wsdisplay_getc_dummy __P((dev_t)); -static void wsdisplay_pollc_dummy __P((dev_t, int)); +static void wsdisplay_pollc __P((dev_t, int)); + +static int wsdisplay_cons_pollmode; +static void (*wsdisplay_cons_kbd_pollc) __P((dev_t, int)); static struct consdev wsdisplay_cons = { NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, - wsdisplay_pollc_dummy, NODEV, CN_NORMAL + wsdisplay_pollc, NODEV, CN_NORMAL }; #ifndef WSDISPLAY_DEFAULTSCREENS @@ -212,6 +215,7 @@ static struct consdev wsdisplay_cons = { int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; int wsdisplay_switch1 __P((void *, int, int)); +int wsdisplay_switch2 __P((void *, int, int)); int wsdisplay_switch3 __P((void *, int, int)); int wsdisplay_clearonclose; @@ -378,7 +382,8 @@ wsdisplay_addscreen(sc, idx, screentype, emul) s = spltty(); if (!sc->sc_focus) { (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, - scr->scr_dconf->emulcookie); + scr->scr_dconf->emulcookie, + 0, 0, 0); sc->sc_focusidx = idx; sc->sc_focus = scr; } @@ -1405,6 +1410,65 @@ wsdisplay_switch3(arg, error, waitok) return (error); } +int +wsdisplay_switch2(arg, error, waitok) + void *arg; + int error, waitok; +{ + struct wsdisplay_softc *sc = arg; + int no; + struct wsscreen *scr; + + if (!(sc->sc_flags & SC_SWITCHPENDING)) { + printf("wsdisplay_switch2: not switching\n"); + return (EINVAL); + } + + no = sc->sc_screenwanted; + if (no < 0 || no >= WSDISPLAY_MAXSCREEN) + panic("wsdisplay_switch2: invalid screen %d", no); + scr = sc->sc_scr[no]; + if (!scr) { + printf("wsdisplay_switch2: screen %d disappeared\n", no); + error = ENXIO; + } + + if (error) { + /* try to recover, avoid recursion */ + + if (sc->sc_oldscreen == -1) { + printf("wsdisplay_switch2: giving up\n"); + sc->sc_focus = 0; + sc->sc_flags &= ~SC_SWITCHPENDING; + return (error); + } + + sc->sc_screenwanted = sc->sc_oldscreen; + sc->sc_oldscreen = -1; + return (wsdisplay_switch1(arg, 0, waitok)); + } + + sc->sc_focusidx = no; + sc->sc_focus = scr; + +#ifdef WSDISPLAY_COMPAT_RAWKBD + (void) wsdisplay_update_rawkbd(sc, scr); +#endif + /* keyboard map??? */ + +#define wsswitch_cb3 ((void (*) __P((void *, int, int)))wsdisplay_switch3) + if (scr->scr_syncops) { + error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, + sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc); + if (error == EAGAIN) { + /* switch will be done asynchronously */ + return (0); + } + } + + return (wsdisplay_switch3(sc, error, waitok)); +} + int wsdisplay_switch1(arg, error, waitok) void *arg; @@ -1433,27 +1497,17 @@ wsdisplay_switch1(arg, error, waitok) return (error); } - (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, - scr->scr_dconf->emulcookie); - sc->sc_focusidx = no; - sc->sc_focus = scr; - -#ifdef WSDISPLAY_COMPAT_RAWKBD - (void) wsdisplay_update_rawkbd(sc, scr); -#endif - /* keyboard map??? */ - -#define wsswitch_cb3 ((void (*) __P((void *, int, int)))wsdisplay_switch3) - if (scr->scr_syncops) { - error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok, - wsswitch_cb3, sc); - if (error == EAGAIN) { - /* switch will be done asynchronously */ - return (0); - } +#define wsswitch_cb2 ((void (*) __P((void *, int, int)))wsdisplay_switch2) + error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, + scr->scr_dconf->emulcookie, + waitok, + sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc); + if (error == EAGAIN) { + /* switch will be done asynchronously */ + return (0); } - return (wsdisplay_switch3(sc, error, waitok)); + return (wsdisplay_switch2(sc, error, waitok)); } int @@ -1495,7 +1549,7 @@ wsdisplay_switch(dev, no, waitok) #define wsswitch_cb1 ((void (*) __P((void *, int, int)))wsdisplay_switch1) if (scr->scr_syncops) { res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, - wsswitch_cb1, sc); + sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); if (res == EAGAIN) { /* switch will be done asynchronously */ return (0); @@ -1697,10 +1751,15 @@ wsdisplay_getc_dummy(dev) } static void -wsdisplay_pollc_dummy(dev, on) +wsdisplay_pollc(dev, on) dev_t dev; int on; { + + wsdisplay_cons_pollmode = on; + + if (wsdisplay_cons_kbd_pollc) + (*wsdisplay_cons_kbd_pollc)(dev, on); } void @@ -1709,14 +1768,14 @@ wsdisplay_set_cons_kbd(get, poll) void (*poll) __P((dev_t, int)); { wsdisplay_cons.cn_getc = get; - wsdisplay_cons.cn_pollc = poll; + wsdisplay_cons_kbd_pollc = poll; } void wsdisplay_unset_cons_kbd() { wsdisplay_cons.cn_getc = wsdisplay_getc_dummy; - wsdisplay_cons.cn_pollc = wsdisplay_pollc_dummy; + wsdisplay_cons_kbd_pollc = 0; } /* diff --git a/sys/dev/wscons/wsdisplay_compat_usl.c b/sys/dev/wscons/wsdisplay_compat_usl.c index 1ac3758e2203..ed7814e4dffb 100644 --- a/sys/dev/wscons/wsdisplay_compat_usl.c +++ b/sys/dev/wscons/wsdisplay_compat_usl.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsdisplay_compat_usl.c,v 1.10 1999/10/19 00:03:18 mycroft Exp $ */ +/* $NetBSD: wsdisplay_compat_usl.c,v 1.11 1999/12/06 18:52:23 drochner Exp $ */ /* * Copyright (c) 1998 @@ -172,6 +172,10 @@ usl_detachproc(cookie, waitok, callback, cbarg) if (!usl_sync_check(sd)) return (0); + /* we really need a callback */ + if (!callback) + return (EINVAL); + /* * Normally, this is called from the controlling process. * Is is supposed to reply with a VT_RELDISP ioctl(), so @@ -238,6 +242,10 @@ usl_attachproc(cookie, waitok, callback, cbarg) if (!usl_sync_check(sd)) return (0); + /* we really need a callback */ + if (!callback) + return (EINVAL); + sd->s_callback = callback; sd->s_cbarg = cbarg; sd->s_flags |= SF_ATTACHPENDING; diff --git a/sys/dev/wscons/wsdisplayvar.h b/sys/dev/wscons/wsdisplayvar.h index 32fc11afa88b..0f2ad5e3151b 100644 --- a/sys/dev/wscons/wsdisplayvar.h +++ b/sys/dev/wscons/wsdisplayvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wsdisplayvar.h,v 1.13 1999/10/19 00:03:18 mycroft Exp $ */ +/* $NetBSD: wsdisplayvar.h,v 1.14 1999/12/06 18:52:23 drochner Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -107,7 +107,8 @@ struct wsdisplay_accessops { int (*alloc_screen) __P((void *, const struct wsscreen_descr *, void **, int *, int *, long *)); void (*free_screen) __P((void *, void *)); - void (*show_screen) __P((void *, void *)); + int (*show_screen) __P((void *, void *, int, + void (*) (void *, int, int), void *)); int (*load_font) __P((void *, void *, struct wsdisplay_font *)); };