diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2005-05-15 11:29:16 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2005-05-15 11:29:16 +0000 |
commit | e4ddca087cd9e76ce899c0b7980d802c4b72d54b (patch) | |
tree | d94f7a56579c717080dc242b5525b0898990a003 /sys | |
parent | db19eabbc0715bf1c47d38f4bb677afbbf751347 (diff) |
Partial sync to the NetBSD wscons code, bringing a better wsmux behaviour
and bugfixes (the kqueue code, /dev/wsmuxctl and screen border color changes
have not been picked), keeping local changes.
Tested by many on alpha/cats/hp300/i386/macppc/sparc/sparc64/zaurus if not more.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 10 | ||||
-rw-r--r-- | sys/dev/wscons/files.wscons | 20 | ||||
-rw-r--r-- | sys/dev/wscons/wscons_callbacks.h | 13 | ||||
-rw-r--r-- | sys/dev/wscons/wsconsio.h | 38 | ||||
-rw-r--r-- | sys/dev/wscons/wsdisplay.c | 623 | ||||
-rw-r--r-- | sys/dev/wscons/wsdisplayvar.h | 8 | ||||
-rw-r--r-- | sys/dev/wscons/wsevent.c | 40 | ||||
-rw-r--r-- | sys/dev/wscons/wskbd.c | 703 | ||||
-rw-r--r-- | sys/dev/wscons/wsksymdef.h | 3 | ||||
-rw-r--r-- | sys/dev/wscons/wsmouse.c | 365 | ||||
-rw-r--r-- | sys/dev/wscons/wsmux.c | 1003 | ||||
-rw-r--r-- | sys/dev/wscons/wsmuxvar.h | 101 |
12 files changed, 1446 insertions, 1481 deletions
diff --git a/sys/conf/files b/sys/conf/files index 1f91d849951..1f85465e988 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.336 2005/05/10 01:16:31 brad Exp $ +# $OpenBSD: files,v 1.337 2005/05/15 11:29:12 miod Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -73,10 +73,10 @@ define ax88190 # AX88190-family Ethernet controllers # a wscons output device; used later, but needs to be near the top for # common file (e.g. vga) definitions. -define wsdisplaydev {} -define wsemuldisplaydev {[console = -1]} -define wskbddev {[console = -1], [mux = -1]} -define wsmousedev {[mux = -1]} +define wsdisplaydev {[mux = 1]} +define wsemuldisplaydev {[console = -1], [mux = 1]} +define wskbddev {[console = -1], [mux = 1]} +define wsmousedev {[mux = 0]} define wsrasteremulops # i2c device attributes diff --git a/sys/dev/wscons/files.wscons b/sys/dev/wscons/files.wscons index f8fd1d21220..fe6daa2fce9 100644 --- a/sys/dev/wscons/files.wscons +++ b/sys/dev/wscons/files.wscons @@ -1,5 +1,5 @@ -# $OpenBSD: files.wscons,v 1.8 2005/03/08 20:00:25 tdeval Exp $ -# $NetBSD: files.wscons,v 1.19 1999/12/12 08:17:28 scottr Exp $ +# $OpenBSD: files.wscons,v 1.9 2005/05/15 11:29:15 miod Exp $ +# $NetBSD: files.wscons,v 1.34 2005/05/04 01:52:16 augustss Exp $ # # "Workstation Console" glue; attaches frame buffer to emulator & keyboard, @@ -22,7 +22,7 @@ attach wskbd at wskbddev device wsmouse attach wsmouse at wsmousedev -file dev/wscons/wsdisplay.c wsdisplay needs-flag +file dev/wscons/wsdisplay.c wsdisplay needs-flag file dev/wscons/wsdisplay_compat_usl.c wsdisplay & wsdisplay_compat_usl file dev/wscons/wsemulconf.c wsdisplay file dev/wscons/wsemul_dumb.c wsdisplay & wsemul_dumb @@ -30,10 +30,11 @@ file dev/wscons/wsemul_vt100.c wsdisplay & !wsemul_no_vt100 file dev/wscons/wsemul_vt100_subr.c wsdisplay & !wsemul_no_vt100 file dev/wscons/wsemul_vt100_chars.c wsdisplay & !wsemul_no_vt100 file dev/wscons/wsemul_vt100_keys.c wsdisplay & !wsemul_no_vt100 -file dev/wscons/wsevent.c wskbd | wsmouse -file dev/wscons/wskbd.c wskbd needs-flag -file dev/wscons/wskbdutil.c wskbd needs-flag -file dev/wscons/wsmouse.c wsmouse needs-flag +file dev/wscons/wsevent.c wsdisplay | wskbd | + wsmouse | wsmux +file dev/wscons/wskbd.c wskbd needs-flag +file dev/wscons/wskbdutil.c wskbd +file dev/wscons/wsmouse.c wsmouse needs-flag file dev/rcons/raster_op.c wsrasteremulops file dev/rcons/raster_text.c wsrasteremulops @@ -43,7 +44,8 @@ file dev/wscons/wscons_gallant19.c wsrasteremulops file dev/wscons/wscons_font8x16.c wsrasteremulops pseudo-device wsmux -file dev/wscons/wsmux.c wsmux | wsdisplay needs-flag +file dev/wscons/wsmux.c wsmux needs-flag define wsemul_sun -file dev/wscons/wsemul_sun.c wsdisplay & wsemul_sun needs-flag +file dev/wscons/wsemul_sun.c wsdisplay & + wsemul_sun needs-flag diff --git a/sys/dev/wscons/wscons_callbacks.h b/sys/dev/wscons/wscons_callbacks.h index 916291eea47..4f2dd2eef35 100644 --- a/sys/dev/wscons/wscons_callbacks.h +++ b/sys/dev/wscons/wscons_callbacks.h @@ -1,5 +1,5 @@ -/* $OpenBSD: wscons_callbacks.h,v 1.5 2002/03/14 03:16:08 millert Exp $ */ -/* $NetBSD: wscons_callbacks.h,v 1.12 2000/03/06 21:37:16 thorpej Exp $ */ +/* $OpenBSD: wscons_callbacks.h,v 1.6 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wscons_callbacks.h,v 1.16 2001/11/10 17:14:51 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -31,10 +31,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +struct wsevsrc; + /* * Calls to the display interface from the glue code. */ -struct device *wsdisplay_set_console_kbd(struct device *); +void wsdisplay_set_console_kbd(struct wsevsrc *); /* * Calls to the display interface from the keyboard interface. @@ -58,6 +60,5 @@ int wsdisplay_param(struct device*, u_long, struct wsdisplay_param*); /* * Calls to the keyboard interface from the glue code. */ -struct wsmux_softc; -struct device *wskbd_set_console_display(struct device *, struct wsmux_softc *); -int wskbd_pickfree(void); +struct wsevsrc *wskbd_set_console_display(struct device *, struct wsevsrc *); +int wskbd_pickfree(void); diff --git a/sys/dev/wscons/wsconsio.h b/sys/dev/wscons/wsconsio.h index f72ec904c47..c8b2996375c 100644 --- a/sys/dev/wscons/wsconsio.h +++ b/sys/dev/wscons/wsconsio.h @@ -1,5 +1,5 @@ -/* $OpenBSD: wsconsio.h,v 1.35 2005/04/22 11:59:11 miod Exp $ */ -/* $NetBSD: wsconsio.h,v 1.31.2.1 2000/07/07 09:49:17 hannken Exp $ */ +/* $OpenBSD: wsconsio.h,v 1.36 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsconsio.h,v 1.74 2005/04/28 07:15:44 martin Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -41,12 +41,14 @@ * 0-31 keyboard ioctls (WSKBDIO) * 32-63 mouse ioctls (WSMOUSEIO) * 64-95 display ioctls (WSDISPLAYIO) - * 96-255 reserved for future use + * 96-127 mux ioctls (WSMUXIO) + * 128-255 reserved for future use */ #include <sys/types.h> #include <sys/ioccom.h> #include <dev/wscons/wsksymvar.h> + #include <sys/pciio.h> #define WSSCREEN_NAME_SIZE 16 @@ -412,15 +414,6 @@ struct wsdisplay_delscreendata { /* Display information: number of bytes per row, may be same as pixels */ #define WSDISPLAYIO_LINEBYTES _IOR('W', 95, u_int) -/* Replaced by WSMUX_{ADD,REMOVE}_DEVICE */ -struct wsdisplay_kbddata { - int op; -#define _O_WSDISPLAY_KBD_ADD 0 -#define _O_WSDISPLAY_KBD_DEL 1 - int idx; -}; -#define _O_WSDISPLAYIO_SETKEYBOARD _IOWR('W', 87, struct wsdisplay_kbddata) - /* Mouse console support */ #define WSDISPLAYIO_WSMOUSED _IOW('W', 88, struct wscons_event) @@ -436,11 +429,17 @@ struct wsdisplay_param { #define WSDISPLAYIO_GETPARAM _IOWR('W', 89, struct wsdisplay_param) #define WSDISPLAYIO_SETPARAM _IOWR('W', 90, struct wsdisplay_param) +#define WSDISPLAYIO_GPCIID _IOR('W', 91, struct pcisel) + /* XXX NOT YET DEFINED */ /* Mapping information retrieval. */ -/* Mux ioctls (96 - 127) */ -#define WSMUX_INJECTEVENT _IOW('W', 96, struct wscons_event) +/* + * Mux ioctls (96 - 127) + */ + +#define WSMUXIO_INJECTEVENT _IOW('W', 96, struct wscons_event) +#define WSMUX_INJECTEVENT WSMUXIO_INJECTEVENT /* XXX compat */ struct wsmux_device { int type; @@ -449,16 +448,17 @@ struct wsmux_device { #define WSMUX_MUX 3 int idx; }; -#define WSMUX_ADD_DEVICE _IOW('W', 97, struct wsmux_device) -#define WSMUX_REMOVE_DEVICE _IOW('W', 98, struct wsmux_device) +#define WSMUXIO_ADD_DEVICE _IOW('W', 97, struct wsmux_device) +#define WSMUX_ADD_DEVICE WSMUXIO_ADD_DEVICE /* XXX compat */ +#define WSMUXIO_REMOVE_DEVICE _IOW('W', 98, struct wsmux_device) +#define WSMUX_REMOVE_DEVICE WSMUXIO_REMOVE_DEVICE /* XXX compat */ #define WSMUX_MAXDEV 32 struct wsmux_device_list { int ndevices; struct wsmux_device devices[WSMUX_MAXDEV]; }; -#define WSMUX_LIST_DEVICES _IOWR('W', 99, struct wsmux_device_list) - -#define WSDISPLAYIO_GPCIID _IOR('W', 91, struct pcisel) +#define WSMUXIO_LIST_DEVICES _IOWR('W', 99, struct wsmux_device_list) +#define WSMUX_LIST_DEVICES WSMUXIO_LIST_DEVICES /* XXX compat */ #endif /* _DEV_WSCONS_WSCONSIO_H_ */ diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c index e3e6a309111..23197024fc2 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wsdisplay.c,v 1.56 2004/11/05 09:38:04 miod Exp $ */ -/* $NetBSD: wsdisplay.c,v 1.37.4.1 2000/06/30 16:27:53 simonb Exp $ */ +/* $OpenBSD: wsdisplay.c,v 1.57 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -61,6 +61,7 @@ #include <dev/ic/pcdisplay.h> +#include "wsdisplay.h" #include "wskbd.h" #include "wsmouse.h" #include "wsmux.h" @@ -71,8 +72,8 @@ #endif #if NWSMOUSE > 0 -#include "wsmousevar.h" -#endif /* NWSMOUSE > 0 */ +#include <dev/wscons/wsmousevar.h> +#endif #include "wsmoused.h" @@ -100,7 +101,7 @@ struct wsscreen { #define SCR_OPEN 1 /* is it open? */ #define SCR_WAITACTIVE 2 /* someone waiting on activation */ #define SCR_GRAPHICS 4 /* graphics mode, no text (emulation) output */ -#define SCR_DUMBFB 8 /* in use as dumb framebuffer (iff SCR_GRAPHICS) */ +#define SCR_DUMBFB 8 /* in use as dumb fb (iff SCR_GRAPHICS) */ const struct wscons_syncops *scr_syncops; void *scr_synccookie; @@ -141,16 +142,18 @@ struct wsscreen { #endif /* WSMOUSED_SUPPORT */ }; -struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, - const char *, const struct wsscreen_descr *, void *, int, int, long); -void wsscreen_detach(struct wsscreen *); -int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *, const char *); -int wsdisplay_getscreen(struct wsdisplay_softc *, struct wsdisplay_addscreendata *); -void wsdisplay_shutdownhook(void *); -void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int); -void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *); -int wsdisplay_delscreen(struct wsdisplay_softc *, int, int); -void wsdisplay_burner(void *v); +struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, const char *, + const struct wsscreen_descr *, void *, int, int, long); +void wsscreen_detach(struct wsscreen *); +int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *, + const char *); +int wsdisplay_getscreen(struct wsdisplay_softc *, + struct wsdisplay_addscreendata *); +void wsdisplay_shutdownhook(void *); +void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int); +void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *); +int wsdisplay_delscreen(struct wsdisplay_softc *, int, int); +void wsdisplay_burner(void *v); struct wsdisplay_softc { struct device sc_dv; @@ -164,6 +167,8 @@ struct wsdisplay_softc { int sc_focusidx; /* available only if sc_focus isn't null */ struct wsscreen *sc_focus; + struct wseventvar sc_evar; + struct timeout sc_burner; int sc_burnoutintvl; int sc_burninintvl; @@ -180,7 +185,7 @@ struct wsdisplay_softc { int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */ #if NWSKBD > 0 - struct wsmux_softc *sc_muxdv; + struct wsevsrc *sc_input; #ifdef WSDISPLAY_COMPAT_RAWKBD int sc_rawkbd; #endif @@ -193,15 +198,12 @@ struct wsdisplay_softc { }; extern struct cfdriver wsdisplay_cd; -#if NWSMUX > 0 -extern struct wsmux_softc **wsmuxdevs; -#endif /* NWSMUX > 0 */ /* Autoconfiguration definitions. */ -int wsdisplay_emul_match(struct device *, void *, void *); -void wsdisplay_emul_attach(struct device *, struct device *, void *); -int wsdisplay_noemul_match(struct device *, void *, void *); -void wsdisplay_noemul_attach(struct device *, struct device *, void *); +int wsdisplay_emul_match(struct device *, void *, void *); +void wsdisplay_emul_attach(struct device *, struct device *, void *); +int wsdisplay_noemul_match(struct device *, void *, void *); +void wsdisplay_noemul_attach(struct device *, struct device *, void *); struct cfdriver wsdisplay_cd = { NULL, "wsdisplay", DV_TTY @@ -217,9 +219,8 @@ struct cfattach wsdisplay_noemul_ca = { wsdisplay_noemul_attach, }; -void wsdisplaystart(struct tty *); -int wsdisplayparam(struct tty *, struct termios *); - +void wsdisplaystart(struct tty *); +int wsdisplayparam(struct tty *, struct termios *); /* Internal macros, functions, and variables. */ #define WSDISPLAYUNIT(dev) (minor(dev) >> 8) @@ -230,24 +231,24 @@ int wsdisplayparam(struct tty *, struct termios *); #define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL) #define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL) -void wsdisplay_common_attach(struct wsdisplay_softc *sc, - int console, const struct wsscreen_list *, +void wsdisplay_common_attach(struct wsdisplay_softc *sc, + int console, int mux, const struct wsscreen_list *, const struct wsdisplay_accessops *accessops, void *accesscookie); #ifdef WSDISPLAY_COMPAT_RAWKBD -int wsdisplay_update_rawkbd(struct wsdisplay_softc *, struct wsscreen *); +int wsdisplay_update_rawkbd(struct wsdisplay_softc *, struct wsscreen *); #endif -int wsdisplay_console_initted; +int wsdisplay_console_initted; struct wsdisplay_softc *wsdisplay_console_device; struct wsscreen_internal wsdisplay_console_conf; -int wsdisplay_getc_dummy(dev_t); -void wsdisplay_pollc(dev_t, int); +int wsdisplay_getc_dummy(dev_t); +void wsdisplay_pollc(dev_t, int); -int wsdisplay_cons_pollmode; -void (*wsdisplay_cons_kbd_pollc)(dev_t, int); +int wsdisplay_cons_pollmode; +void (*wsdisplay_cons_kbd_pollc)(dev_t, int); struct consdev wsdisplay_cons = { NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc, @@ -255,15 +256,15 @@ struct consdev wsdisplay_cons = { }; #ifndef WSDISPLAY_DEFAULTSCREENS -# define WSDISPLAY_DEFAULTSCREENS 1 +#define WSDISPLAY_DEFAULTSCREENS 1 #endif -int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; +int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS; -int wsdisplay_switch1(void *, int, int); -int wsdisplay_switch2(void *, int, int); -int wsdisplay_switch3(void *, int, int); +int wsdisplay_switch1(void *, int, int); +int wsdisplay_switch2(void *, int, int); +int wsdisplay_switch3(void *, int, int); -int wsdisplay_clearonclose; +int wsdisplay_clearonclose; #ifdef WSMOUSED_SUPPORT char *Copybuffer; @@ -272,21 +273,16 @@ char Paste_avail; #endif struct wsscreen * -wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr) - struct wsdisplay_softc *sc; - int console; - const char *emul; - const struct wsscreen_descr *type; - void *cookie; - int ccol, crow; - long defattr; +wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul, + const struct wsscreen_descr *type, void *cookie, int ccol, int crow, + long defattr) { struct wsscreen_internal *dconf; struct wsscreen *scr; scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_NOWAIT); if (!scr) - return (scr); + return (NULL); if (console) { dconf = &wsdisplay_console_conf; @@ -298,7 +294,7 @@ wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr) (*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0); } else { /* not console */ dconf = malloc(sizeof(struct wsscreen_internal), - M_DEVBUF, M_NOWAIT); + M_DEVBUF, M_NOWAIT); if (dconf == NULL) { free(scr, M_DEVBUF); return (NULL); @@ -313,8 +309,8 @@ wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr) return (NULL); } dconf->wsemulcookie = - (*dconf->wsemul->attach)(0, type, cookie, - ccol, crow, scr, defattr); + (*dconf->wsemul->attach)(0, type, cookie, + ccol, crow, scr, defattr); } else dconf->wsemul = NULL; dconf->scrdata = type; @@ -341,8 +337,7 @@ wsscreen_attach(sc, console, emul, type, cookie, ccol, crow, defattr) } void -wsscreen_detach(scr) - struct wsscreen *scr; +wsscreen_detach(struct wsscreen *scr) { int ccol, crow; /* XXX */ @@ -352,15 +347,13 @@ wsscreen_detach(scr) } if (WSSCREEN_HAS_EMULATOR(scr)) (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie, - &ccol, &crow); + &ccol, &crow); free(scr->scr_dconf, M_DEVBUF); free(scr, M_DEVBUF); } const struct wsscreen_descr * -wsdisplay_screentype_pick(scrdata, name) - const struct wsscreen_list *scrdata; - const char *name; +wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name) { int i; const struct wsscreen_descr *scr; @@ -383,9 +376,7 @@ wsdisplay_screentype_pick(scrdata, name) * print info about attached screen */ void -wsdisplay_addscreen_print(sc, idx, count) - struct wsdisplay_softc *sc; - int idx, count; +wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count) { printf("%s: screen %d", sc->sc_dv.dv_xname, idx); if (count > 1) @@ -393,16 +384,14 @@ wsdisplay_addscreen_print(sc, idx, count) printf(" added (%s", sc->sc_scr[idx]->scr_dconf->scrdata->name); if (WSSCREEN_HAS_EMULATOR(sc->sc_scr[idx])) { printf(", %s emulation", - sc->sc_scr[idx]->scr_dconf->wsemul->name); + sc->sc_scr[idx]->scr_dconf->wsemul->name); } printf(")\n"); } int -wsdisplay_addscreen(sc, idx, screentype, emul) - struct wsdisplay_softc *sc; - int idx; - const char *screentype, *emul; +wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx, + const char *screentype, const char *emul) { const struct wsscreen_descr *scrdesc; int error; @@ -421,15 +410,14 @@ wsdisplay_addscreen(sc, idx, screentype, emul) if (!scrdesc) return (ENXIO); error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie, - scrdesc, &cookie, &ccol, &crow, &defattr); + scrdesc, &cookie, &ccol, &crow, &defattr); if (error) return (error); scr = wsscreen_attach(sc, 0, emul, scrdesc, - cookie, ccol, crow, defattr); + cookie, ccol, crow, defattr); if (scr == NULL) { - (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, - cookie); + (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie); return (ENXIO); } @@ -439,8 +427,7 @@ wsdisplay_addscreen(sc, idx, screentype, emul) s = spltty(); if (!sc->sc_focus) { (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, - scr->scr_dconf->emulcookie, - 0, 0, 0); + scr->scr_dconf->emulcookie, 0, 0, 0); sc->sc_focusidx = idx; sc->sc_focus = scr; } @@ -453,9 +440,8 @@ wsdisplay_addscreen(sc, idx, screentype, emul) } int -wsdisplay_getscreen(sc, sd) - struct wsdisplay_softc *sc; - struct wsdisplay_addscreendata *sd; +wsdisplay_getscreen(struct wsdisplay_softc *sc, + struct wsdisplay_addscreendata *sd) { struct wsscreen *scr; @@ -477,9 +463,7 @@ wsdisplay_getscreen(sc, sd) } void -wsdisplay_closescreen(sc, scr) - struct wsdisplay_softc *sc; - struct wsscreen *scr; +wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr) { int maj, mn, idx; @@ -508,9 +492,7 @@ wsdisplay_closescreen(sc, scr) } int -wsdisplay_delscreen(sc, idx, flags) - struct wsdisplay_softc *sc; - int idx, flags; +wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags) { struct wsscreen *scr; int s; @@ -518,8 +500,7 @@ wsdisplay_delscreen(sc, idx, flags) if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); - scr = sc->sc_scr[idx]; - if (!scr) + if ((scr = sc->sc_scr[idx]) == NULL) return (ENXIO); if (scr->scr_dconf == &wsdisplay_console_conf || @@ -556,8 +537,7 @@ wsdisplay_delscreen(sc, idx, flags) wsscreen_detach(scr); - (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, - cookie); + (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie); printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx); return (0); @@ -567,22 +547,17 @@ wsdisplay_delscreen(sc, idx, flags) * Autoconfiguration functions. */ int -wsdisplay_emul_match(parent, match, aux) - struct device *parent; - void *match; - void *aux; +wsdisplay_emul_match(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct wsemuldisplaydev_attach_args *ap = aux; - if (cf->wsemuldisplaydevcf_console != - WSEMULDISPLAYDEVCF_CONSOLE_UNK) { + if (cf->wsemuldisplaydevcf_console != WSEMULDISPLAYDEVCF_CONSOLE_UNK) { /* * If console-ness of device specified, either match * exactly (at high priority), or fail. */ - if (cf->wsemuldisplaydevcf_console != 0 && - ap->console != 0) + if (cf->wsemuldisplaydevcf_console != 0 && ap->console != 0) return (10); else return (0); @@ -593,15 +568,14 @@ wsdisplay_emul_match(parent, match, aux) } void -wsdisplay_emul_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; struct wsemuldisplaydev_attach_args *ap = aux; - wsdisplay_common_attach(sc, ap->console, ap->scrdata, - ap->accessops, ap->accesscookie); + wsdisplay_common_attach(sc, ap->console, + sc->sc_dv.dv_cfdata->wsemuldisplaydevcf_mux, ap->scrdata, + ap->accessops, ap->accesscookie); if (ap->console && cn_tab == &wsdisplay_cons) { int maj; @@ -617,9 +591,7 @@ wsdisplay_emul_attach(parent, self, aux) /* Print function (for parent devices). */ int -wsemuldisplaydevprint(aux, pnp) - void *aux; - const char *pnp; +wsemuldisplaydevprint(void *aux, const char *pnp) { #if 0 /* -Wunused */ struct wsemuldisplaydev_attach_args *ap = aux; @@ -635,10 +607,7 @@ wsemuldisplaydevprint(aux, pnp) } int -wsdisplay_noemul_match(parent, match, aux) - struct device *parent; - void *match; - void *aux; +wsdisplay_noemul_match(struct device *parent, void *match, void *aux) { #if 0 /* -Wunused */ struct wsdisplaydev_attach_args *ap = aux; @@ -649,21 +618,19 @@ wsdisplay_noemul_match(parent, match, aux) } void -wsdisplay_noemul_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +wsdisplay_noemul_attach(struct device *parent, struct device *self, void *aux) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self; struct wsdisplaydev_attach_args *ap = aux; - wsdisplay_common_attach(sc, 0, NULL, ap->accessops, ap->accesscookie); + wsdisplay_common_attach(sc, 0, + sc->sc_dv.dv_cfdata->wsemuldisplaydevcf_mux, NULL, + ap->accessops, ap->accesscookie); } /* Print function (for parent devices). */ int -wsdisplaydevprint(aux, pnp) - void *aux; - const char *pnp; +wsdisplaydevprint(void *aux, const char *pnp) { #if 0 /* -Wunused */ struct wsdisplaydev_attach_args *ap = aux; @@ -676,23 +643,35 @@ wsdisplaydevprint(aux, pnp) } void -wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) - struct wsdisplay_softc *sc; - int console; - const struct wsscreen_list *scrdata; - const struct wsdisplay_accessops *accessops; - void *accesscookie; +wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, + const struct wsscreen_list *scrdata, + const struct wsdisplay_accessops *accessops, void *accesscookie) { static int hookset = 0; int i, start = 0; #if NWSKBD > 0 - struct device *dv; + struct wsevsrc *kme; +#if NWSMUX > 0 + struct wsmux_softc *mux; - sc->sc_muxdv = wsmux_create("dmux", sc->sc_dv.dv_unit); - if (!sc->sc_muxdv) + if (kbdmux >= 0) + mux = wsmux_getmux(kbdmux); + else + mux = wsmux_create("dmux", sc->sc_dv.dv_unit); + /* XXX panic()ing isn't nice, but attach cannot fail */ + if (mux == NULL) panic("wsdisplay_common_attach: no memory"); - sc->sc_muxdv->sc_displaydv = &sc->sc_dv; + sc->sc_input = &mux->sc_base; + mux->sc_displaydv = &sc->sc_dv; + if (kbdmux >= 0) + printf(" mux %d", kbdmux); +#else +#if 0 /* not worth keeping, especially since the default value is not -1... */ + if (kbdmux >= 0) + printf(" (mux ignored)"); #endif +#endif /* NWSMUX > 0 */ +#endif /* NWSKBD > 0 */ sc->sc_isconsole = console; @@ -710,8 +689,12 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) wsdisplay_console_conf.wsemul->name); #if NWSKBD > 0 - if ((dv = wskbd_set_console_display(&sc->sc_dv, sc->sc_muxdv))) - printf(", using %s", dv->dv_xname); + kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input); + if (kme != NULL) + printf(", using %s", kme->me_dv.dv_xname); +#if NWSMUX == 0 + sc->sc_input = kme; +#endif #endif sc->sc_focusidx = 0; @@ -720,6 +703,10 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) } printf("\n"); +#if NWSKBD > 0 && NWSMUX > 0 + wsmux_set_display(mux, &sc->sc_dv); +#endif + sc->sc_accessops = accessops; sc->sc_accesscookie = accesscookie; sc->sc_scrdata = scrdata; @@ -738,7 +725,7 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) wsdisplay_addscreen_print(sc, start, i-start); sc->sc_burnoutintvl = (hz * WSDISPLAY_DEFBURNOUT) / 1000; - sc->sc_burninintvl = (hz * WSDISPLAY_DEFBURNIN ) / 1000; + sc->sc_burninintvl = (hz * WSDISPLAY_DEFBURNIN ) / 1000; sc->sc_burnflags = 0; /* off by default */ timeout_set(&sc->sc_burner, wsdisplay_burner, sc); sc->sc_burnout = sc->sc_burnoutintvl; @@ -750,11 +737,8 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie) } void -wsdisplay_cnattach(type, cookie, ccol, crow, defattr) - const struct wsscreen_descr *type; - void *cookie; - int ccol, crow; - long defattr; +wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol, + int crow, long defattr) { const struct wsemul_ops *wsemul; @@ -770,9 +754,8 @@ wsdisplay_cnattach(type, cookie, ccol, crow, defattr) wsemul = wsemul_pick(""); /* default */ wsdisplay_console_conf.wsemul = wsemul; - wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie, - ccol, crow, - defattr); + wsdisplay_console_conf.wsemulcookie = + (*wsemul->cnattach)(type, cookie, ccol, crow, defattr); cn_tab = &wsdisplay_cons; @@ -783,10 +766,7 @@ wsdisplay_cnattach(type, cookie, ccol, crow, defattr) * Tty and cdevsw functions. */ int -wsdisplayopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; +wsdisplayopen(dev_t dev, int flag, int mode, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; @@ -803,8 +783,7 @@ wsdisplayopen(dev, flag, mode, p) if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN) return (ENXIO); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; - if (!scr) + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { @@ -846,10 +825,7 @@ wsdisplayopen(dev, flag, mode, p) } int -wsdisplayclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; +wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; @@ -862,7 +838,8 @@ wsdisplayclose(dev, flag, mode, p) if (ISWSDISPLAYCTL(dev)) return (0); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { if (scr->scr_hold_screen) { @@ -895,7 +872,7 @@ wsdisplayclose(dev, flag, mode, p) if (scr->scr_rawkbd) { int kbmode = WSKBD_TRANSLATED; (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, - (caddr_t)&kbmode, 0, p); + (caddr_t)&kbmode, 0, p); } #endif @@ -912,10 +889,7 @@ wsdisplayclose(dev, flag, mode, p) } int -wsdisplayread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; +wsdisplayread(dev_t dev, struct uio *uio, int flag) { struct wsdisplay_softc *sc; struct tty *tp; @@ -928,7 +902,8 @@ wsdisplayread(dev, uio, flag) if (ISWSDISPLAYCTL(dev)) return (0); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (ENXIO); if (!WSSCREEN_HAS_TTY(scr)) return (ENODEV); @@ -938,10 +913,7 @@ wsdisplayread(dev, uio, flag) } int -wsdisplaywrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; +wsdisplaywrite(dev_t dev, struct uio *uio, int flag) { struct wsdisplay_softc *sc; struct tty *tp; @@ -954,7 +926,8 @@ wsdisplaywrite(dev, uio, flag) if (ISWSDISPLAYCTL(dev)) return (0); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (ENXIO); if (!WSSCREEN_HAS_TTY(scr)) return (ENODEV); @@ -964,8 +937,7 @@ wsdisplaywrite(dev, uio, flag) } struct tty * -wsdisplaytty(dev) - dev_t dev; +wsdisplaytty(dev_t dev) { struct wsdisplay_softc *sc; int unit; @@ -977,18 +949,14 @@ wsdisplaytty(dev) if (ISWSDISPLAYCTL(dev)) panic("wsdisplaytty() on ctl device"); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (NULL); return (scr->scr_tty); } int -wsdisplayioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct wsdisplay_softc *sc; struct tty *tp; @@ -1007,7 +975,8 @@ wsdisplayioctl(dev, cmd, data, flag, p) if (ISWSDISPLAYCTL(dev)) return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (ENXIO); if (WSSCREEN_HAS_TTY(scr)) { tp = scr->scr_tty; @@ -1036,28 +1005,23 @@ wsdisplayioctl(dev, cmd, data, flag, p) } int -wsdisplay_param(dev, cmd, dp) - struct device *dev; - u_long cmd; - struct wsdisplay_param *dp; +wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; + return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, - (caddr_t)dp, 0, NULL)); + (caddr_t)dp, 0, NULL)); } int -wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p) - struct wsdisplay_softc *sc; - struct wsscreen *scr; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, + u_long cmd, caddr_t data, int flag, struct proc *p) { int error; #if NWSKBD > 0 + struct wsevsrc *inp; + #ifdef WSDISPLAY_COMPAT_RAWKBD switch (cmd) { case WSKBDIO_SETMODE: @@ -1069,7 +1033,10 @@ wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p) return (0); } #endif - error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag, p); + inp = sc->sc_input; + if (inp == NULL) + return (ENXIO); + error = wsevsrc_display_ioctl(inp, cmd, data, flag, p); if (error >= 0) return (error); #endif /* NWSKBD > 0 */ @@ -1214,18 +1181,14 @@ wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p) } int -wsdisplay_cfg_ioctl(sc, cmd, data, flag, p) - struct wsdisplay_softc *sc; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, + int flag, struct proc *p) { int error; void *buf; size_t fontsz; -#if defined(COMPAT_14) && NWSKBD > 0 - struct wsmux_device wsmuxdata; +#if NWSKBD > 0 + struct wsevsrc *inp; #endif switch (cmd) { @@ -1286,43 +1249,19 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p) #undef d #if NWSKBD > 0 -#ifdef COMPAT_14 - case _O_WSDISPLAYIO_SETKEYBOARD: -#define d ((struct wsdisplay_kbddata *)data) - switch (d->op) { - case _O_WSDISPLAY_KBD_ADD: - if (d->idx == -1) { - d->idx = wskbd_pickfree(); - if (d->idx == -1) - return (ENXIO); - } - wsmuxdata.type = WSMUX_KBD; - wsmuxdata.idx = d->idx; - return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv, - WSMUX_ADD_DEVICE, - (caddr_t)&wsmuxdata, flag, p)); - case _O_WSDISPLAY_KBD_DEL: - wsmuxdata.type = WSMUX_KBD; - wsmuxdata.idx = d->idx; - return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv, - WSMUX_REMOVE_DEVICE, - (caddr_t)&wsmuxdata, flag, p)); - default: - return (EINVAL); - } -#undef d -#endif - - case WSMUX_ADD_DEVICE: + case WSMUXIO_ADD_DEVICE: #define d ((struct wsmux_device *)data) if (d->idx == -1 && d->type == WSMUX_KBD) d->idx = wskbd_pickfree(); #undef d /* fall into */ - case WSMUX_INJECTEVENT: - case WSMUX_REMOVE_DEVICE: - case WSMUX_LIST_DEVICES: - return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag,p)); + case WSMUXIO_INJECTEVENT: + case WSMUXIO_REMOVE_DEVICE: + case WSMUXIO_LIST_DEVICES: + inp = sc->sc_input; + if (inp == NULL) + return (ENXIO); + return (wsevsrc_ioctl(inp, cmd, data, flag,p)); #endif /* NWSKBD > 0 */ } @@ -1330,10 +1269,7 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p) } paddr_t -wsdisplaymmap(dev, offset, prot) - dev_t dev; - off_t offset; - int prot; +wsdisplaymmap(dev_t dev, off_t offset, int prot) { struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; struct wsscreen *scr; @@ -1341,7 +1277,8 @@ wsdisplaymmap(dev, offset, prot) if (ISWSDISPLAYCTL(dev)) return (-1); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (-1); if (!(scr->scr_flags & SCR_GRAPHICS)) return (-1); @@ -1351,10 +1288,7 @@ wsdisplaymmap(dev, offset, prot) } int -wsdisplaypoll(dev, events, p) - dev_t dev; - int events; - struct proc *p; +wsdisplaypoll(dev_t dev, int events, struct proc *p) { struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; struct wsscreen *scr; @@ -1362,18 +1296,17 @@ wsdisplaypoll(dev, events, p) if (ISWSDISPLAYCTL(dev)) return (0); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (ENXIO); - if (WSSCREEN_HAS_TTY(scr)) - return (ttpoll(dev, events, p)); - else - return (0); + if (!WSSCREEN_HAS_TTY(scr)) + return (ENODEV); + + return (ttpoll(dev, events, p)); } int -wsdisplaykqfilter(dev, kn) - dev_t dev; - struct knote *kn; +wsdisplaykqfilter(dev_t dev, struct knote *kn) { struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; struct wsscreen *scr; @@ -1381,7 +1314,8 @@ wsdisplaykqfilter(dev, kn) if (ISWSDISPLAYCTL(dev)) return (1); - scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL) + return (1); if (WSSCREEN_HAS_TTY(scr)) return (ttkqfilter(dev, kn)); @@ -1390,8 +1324,7 @@ wsdisplaykqfilter(dev, kn) } void -wsdisplaystart(tp) - struct tty *tp; +wsdisplaystart(struct tty *tp) { struct wsdisplay_softc *sc; struct wsscreen *scr; @@ -1411,7 +1344,10 @@ wsdisplaystart(tp) if (tp->t_outq.c_cc == 0 && tp->t_wsel.si_selpid == 0) goto low; - scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]; + if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) { + splx(s); + return; + } if (scr->scr_hold_screen) { tp->t_state |= TS_TIMEOUT; splx(s); @@ -1463,13 +1399,14 @@ wsdisplaystart(tp) s = spltty(); tp->t_state &= ~TS_BUSY; - - tp->t_state |= TS_TIMEOUT; - timeout_add(&tp->t_rstrt_to, (hz > 128) ? (hz / 128) : 1); - + /* Come back if there's more to do */ + if (tp->t_outq.c_cc) { + tp->t_state |= TS_TIMEOUT; + timeout_add(&tp->t_rstrt_to, (hz > 128) ? (hz / 128) : 1); + } if (tp->t_outq.c_cc <= tp->t_lowat) { low: - if (tp->t_state&TS_ASLEEP) { + if (tp->t_state & TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } @@ -1479,9 +1416,7 @@ low: } int -wsdisplaystop(tp, flag) - struct tty *tp; - int flag; +wsdisplaystop(struct tty *tp, int flag) { int s; @@ -1496,9 +1431,7 @@ wsdisplaystop(tp, flag) /* Set line parameters. */ int -wsdisplayparam(tp, t) - struct tty *tp; - struct termios *t; +wsdisplayparam(struct tty *tp, struct termios *t) { tp->t_ispeed = t->c_ispeed; @@ -1511,8 +1444,7 @@ wsdisplayparam(tp, t) * Callbacks for the emulation code. */ void -wsdisplay_emulbell(v) - void *v; +wsdisplay_emulbell(void *v) { struct wsscreen *scr = v; @@ -1523,14 +1455,11 @@ wsdisplay_emulbell(v) return; (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL, - FWRITE, NULL); + FWRITE, NULL); } void -wsdisplay_emulinput(v, data, count) - void *v; - const u_char *data; - u_int count; +wsdisplay_emulinput(void *v, const u_char *data, u_int count) { struct wsscreen *scr = v; struct tty *tp; @@ -1552,9 +1481,7 @@ wsdisplay_emulinput(v, data, count) * Calls from the keyboard interface. */ void -wsdisplay_kbdinput(dev, ks) - struct device *dev; - keysym_t ks; +wsdisplay_kbdinput(struct device *dev, keysym_t ks) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; @@ -1583,35 +1510,40 @@ wsdisplay_kbdinput(dev, ks) #ifdef WSDISPLAY_COMPAT_RAWKBD int -wsdisplay_update_rawkbd(sc, scr) - struct wsdisplay_softc *sc; - struct wsscreen *scr; +wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) { +#if NWSKBD > 0 int s, raw, data, error; + struct wsevsrc *inp; + s = spltty(); raw = (scr ? scr->scr_rawkbd : 0); - if (scr != sc->sc_focus || - sc->sc_rawkbd == raw) { + if (scr != sc->sc_focus || sc->sc_rawkbd == raw) { splx(s); return (0); } data = raw ? WSKBD_RAW : WSKBD_TRANSLATED; - error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, WSKBDIO_SETMODE, - (caddr_t)&data, 0, 0); + inp = sc->sc_input; + if (inp == NULL) { + splx(s); + return (ENXIO); + } + error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0); if (!error) sc->sc_rawkbd = raw; splx(s); return (error); +#else + return (0); +#endif } #endif int -wsdisplay_switch3(arg, error, waitok) - void *arg; - int error, waitok; +wsdisplay_switch3(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; @@ -1640,7 +1572,7 @@ wsdisplay_switch3(arg, error, waitok) #ifdef WSDISPLAY_COMPAT_RAWKBD wsdisplay_update_rawkbd(sc, 0); #endif - sc->sc_flags &= ~SC_SWITCHPENDING; + sc->sc_flags &= ~SC_SWITCHPENDING; return (error); } @@ -1657,9 +1589,7 @@ wsdisplay_switch3(arg, error, waitok) } int -wsdisplay_switch2(arg, error, waitok) - void *arg; - int error, waitok; +wsdisplay_switch2(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; @@ -1705,7 +1635,8 @@ wsdisplay_switch2(arg, error, waitok) #define wsswitch_cb3 ((void (*)(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); + sc->sc_isconsole && wsdisplay_cons_pollmode ? + 0 : wsswitch_cb3, sc); if (error == EAGAIN) { /* switch will be done asynchronously */ return (0); @@ -1716,9 +1647,7 @@ wsdisplay_switch2(arg, error, waitok) } int -wsdisplay_switch1(arg, error, waitok) - void *arg; - int error, waitok; +wsdisplay_switch1(void *arg, int error, int waitok) { struct wsdisplay_softc *sc = arg; int no; @@ -1753,9 +1682,8 @@ wsdisplay_switch1(arg, error, waitok) #define wsswitch_cb2 ((void (*)(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); + 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); @@ -1765,18 +1693,18 @@ wsdisplay_switch1(arg, error, waitok) } int -wsdisplay_switch(dev, no, waitok) - struct device *dev; - int no, waitok; +wsdisplay_switch(struct device *dev, int no, int waitok) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; int s, res = 0; struct wsscreen *scr; - - if (no != WSDISPLAY_NULLSCREEN && - (no < 0 || no >= WSDISPLAY_MAXSCREEN || !sc->sc_scr[no])) - return (ENXIO); + if (no != WSDISPLAY_NULLSCREEN) { + if (no < 0 || no >= WSDISPLAY_MAXSCREEN) + return (EINVAL); + if (sc->sc_scr[no] == NULL) + return (ENXIO); + } s = spltty(); @@ -1818,7 +1746,6 @@ wsdisplay_switch(dev, no, waitok) * SCR_GRAPHICS when X-Window stops. In this case, the first of the * three following 'if' statements is evaluated. * We handle wsmoused(8) events the WSDISPLAYIO_SMODE ioctl. - * */ if (!(scr->scr_flags & SCR_GRAPHICS) && @@ -1850,7 +1777,8 @@ wsdisplay_switch(dev, no, waitok) #define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1) if (scr->scr_syncops) { res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok, - sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc); + sc->sc_isconsole && wsdisplay_cons_pollmode ? + 0 : wsswitch_cb1, sc); if (res == EAGAIN) { /* switch will be done asynchronously */ return (0); @@ -1864,9 +1792,7 @@ wsdisplay_switch(dev, no, waitok) } void -wsdisplay_reset(dev, op) - struct device *dev; - enum wsdisplay_resetops op; +wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; @@ -1882,7 +1808,7 @@ wsdisplay_reset(dev, op) if (!WSSCREEN_HAS_EMULATOR(scr)) break; (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie, - WSEMUL_RESET); + WSEMUL_RESET); break; case WSDISPLAY_RESETCLOSE: wsdisplay_closescreen(sc, scr); @@ -1894,10 +1820,8 @@ wsdisplay_reset(dev, op) * Interface for (external) VT switch / process synchronization code */ int -wsscreen_attach_sync(scr, ops, cookie) - struct wsscreen *scr; - const struct wscons_syncops *ops; - void *cookie; +wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops, + void *cookie) { if (scr->scr_syncops) { /* @@ -1913,8 +1837,7 @@ wsscreen_attach_sync(scr, ops, cookie) } int -wsscreen_detach_sync(scr) - struct wsscreen *scr; +wsscreen_detach_sync(struct wsscreen *scr) { if (!scr->scr_syncops) return (EINVAL); @@ -1923,10 +1846,9 @@ wsscreen_detach_sync(scr) } int -wsscreen_lookup_sync(scr, ops, cookiep) - struct wsscreen *scr; - const struct wscons_syncops *ops; /* used as ID */ - void **cookiep; +wsscreen_lookup_sync(struct wsscreen *scr, + const struct wscons_syncops *ops, /* used as ID */ + void **cookiep) { if (!scr->scr_syncops || ops != scr->scr_syncops) return (EINVAL); @@ -1938,16 +1860,13 @@ wsscreen_lookup_sync(scr, ops, cookiep) * Interface to virtual screen stuff */ int -wsdisplay_maxscreenidx(sc) - struct wsdisplay_softc *sc; +wsdisplay_maxscreenidx(struct wsdisplay_softc *sc) { return (WSDISPLAY_MAXSCREEN - 1); } int -wsdisplay_screenstate(sc, idx) - struct wsdisplay_softc *sc; - int idx; +wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx) { if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN) return (EINVAL); @@ -1957,16 +1876,13 @@ wsdisplay_screenstate(sc, idx) } int -wsdisplay_getactivescreen(sc) - struct wsdisplay_softc *sc; +wsdisplay_getactivescreen(struct wsdisplay_softc *sc) { return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN); } int -wsscreen_switchwait(sc, no) - struct wsdisplay_softc *sc; - int no; +wsscreen_switchwait(struct wsdisplay_softc *sc, int no) { struct wsscreen *scr; int s, res = 0; @@ -2000,9 +1916,7 @@ wsscreen_switchwait(sc, no) } void -wsdisplay_kbdholdscreen(dev, hold) - struct device *dev; - int hold; +wsdisplay_kbdholdscreen(struct device *dev, int hold) { struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev; struct wsscreen *scr; @@ -2018,15 +1932,23 @@ wsdisplay_kbdholdscreen(dev, hold) } #if NWSKBD > 0 -struct device * -wsdisplay_set_console_kbd(kbddv) - struct device *kbddv; +void +wsdisplay_set_console_kbd(struct wsevsrc *src) { - if (!wsdisplay_console_device) - return (0); - if (wskbd_add_mux(kbddv->dv_unit, wsdisplay_console_device->sc_muxdv)) - return (0); - return (&wsdisplay_console_device->sc_dv); + if (wsdisplay_console_device == NULL) { + src->me_dispdv = NULL; + return; + } +#if NWSMUX > 0 + if (wsmux_attach_sc((struct wsmux_softc *) + wsdisplay_console_device->sc_input, src)) { + src->me_dispdv = NULL; + return; + } +#else + wsdisplay_console_device->sc_input = src; +#endif + src->me_dispdv = &wsdisplay_console_device->sc_dv; } #endif /* NWSKBD > 0 */ @@ -2034,9 +1956,7 @@ wsdisplay_set_console_kbd(kbddv) * Console interface. */ void -wsdisplay_cnputc(dev, i) - dev_t dev; - int i; +wsdisplay_cnputc(dev_t dev, int i) { struct wsscreen_internal *dc; char c = i; @@ -2045,6 +1965,7 @@ wsdisplay_cnputc(dev, i) return; if (wsdisplay_console_device != NULL && + (wsdisplay_console_device->sc_scr[0] != NULL) && (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS)) return; @@ -2054,29 +1975,23 @@ wsdisplay_cnputc(dev, i) } int -wsdisplay_getc_dummy(dev) - dev_t dev; +wsdisplay_getc_dummy(dev_t dev) { /* panic? */ return (0); } void -wsdisplay_pollc(dev, on) - dev_t dev; - int on; +wsdisplay_pollc(dev_t dev, int on) { - struct wsdisplay_softc *sc = NULL; - int unit = WSDISPLAYUNIT(dev); - - if (unit < wsdisplay_cd.cd_ndevs) - sc = wsdisplay_cd.cd_devs[unit]; wsdisplay_cons_pollmode = on; /* notify to fb drivers */ - if (sc != NULL && sc->sc_accessops->pollc != NULL) - (*sc->sc_accessops->pollc)(sc->sc_accesscookie, on); + if (wsdisplay_console_device != NULL && + wsdisplay_console_device->sc_accessops->pollc != NULL) + (*wsdisplay_console_device->sc_accessops->pollc) + (wsdisplay_console_device->sc_accesscookie, on); /* notify to kbd drivers */ if (wsdisplay_cons_kbd_pollc) @@ -2084,10 +1999,8 @@ wsdisplay_pollc(dev, on) } void -wsdisplay_set_cons_kbd(get, poll, bell) - int (*get)(dev_t); - void (*poll)(dev_t, int); - void (*bell)(dev_t, u_int, u_int, u_int); +wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int), + void (*bell)(dev_t, u_int, u_int, u_int)) { wsdisplay_cons.cn_getc = get; wsdisplay_cons.cn_bell = bell; @@ -2113,16 +2026,15 @@ wsdisplay_switchtoconsole() if (wsdisplay_console_device != NULL) { sc = wsdisplay_console_device; - scr = sc->sc_scr[0]; + if ((scr = sc->sc_scr[0]) == NULL) + return; (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, scr->scr_dconf->emulcookie, 0, NULL, NULL); } } void -wsscrollback(arg, op) - void *arg; - int op; +wsscrollback(void *arg, int op) { struct wsdisplay_softc *sc = arg; int lines; @@ -2142,9 +2054,7 @@ wsscrollback(arg, op) } void -wsdisplay_burn(v, flags) - void *v; - u_int flags; +wsdisplay_burn(void *v, u_int flags) { struct wsdisplay_softc *sc = v; @@ -2159,8 +2069,7 @@ wsdisplay_burn(v, flags) } void -wsdisplay_burner(v) - void *v; +wsdisplay_burner(void *v) { struct wsdisplay_softc *sc = v; int s; @@ -2183,8 +2092,7 @@ wsdisplay_burner(v) * Switch the console at shutdown. */ void -wsdisplay_shutdownhook(arg) - void *arg; +wsdisplay_shutdownhook(void *arg) { wsdisplay_switchtoconsole(); } @@ -2202,7 +2110,7 @@ static struct wsdisplay_softc *sc = NULL; */ int wsmoused(struct wsdisplay_softc *ws_sc, u_long cmd, caddr_t data, - int flag, struct proc *p) + int flag, struct proc *p) { int error = -1; struct wscons_event mouse_event = *(struct wscons_event *)data; @@ -2555,7 +2463,8 @@ static const int charClass[256] = { /* d n~ o` o' o^ o~ o: -: */ 48, 48, 48, 48, 48, 48, 48, 248, /* o/ u` u' u^ u: y' P y: */ - 48, 48, 48, 48, 48, 48, 48, 48}; + 48, 48, 48, 48, 48, 48, 48, 48 +}; /* * Find the first blank beginning after the current cursor position diff --git a/sys/dev/wscons/wsdisplayvar.h b/sys/dev/wscons/wsdisplayvar.h index 3b13326aa62..0a8e2e9f0cc 100644 --- a/sys/dev/wscons/wsdisplayvar.h +++ b/sys/dev/wscons/wsdisplayvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: wsdisplayvar.h,v 1.14 2002/07/25 19:03:25 miod Exp $ */ -/* $NetBSD: wsdisplayvar.h,v 1.14.4.1 2000/06/30 16:27:53 simonb Exp $ */ +/* $OpenBSD: wsdisplayvar.h,v 1.15 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsdisplayvar.h,v 1.30 2005/02/04 02:10:49 perry Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -163,6 +163,10 @@ struct wsemuldisplaydev_attach_args { #define WSEMULDISPLAYDEVCF_CONSOLE 0 #define wsemuldisplaydevcf_console cf_loc[WSEMULDISPLAYDEVCF_CONSOLE] /* spec'd as console? */ #define WSEMULDISPLAYDEVCF_CONSOLE_UNK -1 +#define WSDISPLAYDEVCF_MUX 0 +#define wsdisplaydevcf_mux cf_loc[WSDISPLAYDEVCF_MUX] +#define WSEMULDISPLAYDEVCF_MUX 1 +#define wsemuldisplaydevcf_mux cf_loc[WSEMULDISPLAYDEVCF_MUX] struct wscons_syncops { int (*detach)(void *, int, void (*)(void *, int, int), void *); diff --git a/sys/dev/wscons/wsevent.c b/sys/dev/wscons/wsevent.c index 2d2948e96d9..627663f90ca 100644 --- a/sys/dev/wscons/wsevent.c +++ b/sys/dev/wscons/wsevent.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wsevent.c,v 1.3 2003/06/02 23:28:04 millert Exp $ */ -/* $NetBSD: wsevent.c,v 1.5 2000/03/30 12:45:44 augustss Exp $ */ +/* $OpenBSD: wsevent.c,v 1.4 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsevent.c,v 1.16 2003/08/07 16:31:29 agc Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -93,25 +93,35 @@ * Initialize a wscons_event queue. */ void -wsevent_init(ev) - struct wseventvar *ev; +wsevent_init(struct wseventvar *ev) { + if (ev->q != NULL) { +#ifdef DIAGNOSTIC + printf("wsevent_init: already initialized\n"); +#endif + return; + } ev->get = ev->put = 0; ev->q = malloc((u_long)WSEVENT_QSIZE * sizeof(struct wscons_event), M_DEVBUF, M_WAITOK); - memset((caddr_t)ev->q, 0, WSEVENT_QSIZE * sizeof(struct wscons_event)); + bzero((caddr_t)ev->q, WSEVENT_QSIZE * sizeof(struct wscons_event)); } /* * Tear down a wscons_event queue. */ void -wsevent_fini(ev) - struct wseventvar *ev; +wsevent_fini(struct wseventvar *ev) { - + if (ev->q == NULL) { +#ifdef DIAGNOSTIC + printf("wsevent_fini: already invoked\n"); +#endif + return; + } free(ev->q, M_DEVBUF); + ev->q = NULL; } /* @@ -119,10 +129,7 @@ wsevent_fini(ev) * (User cannot write an event queue.) */ int -wsevent_read(ev, uio, flags) - struct wseventvar *ev; - struct uio *uio; - int flags; +wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) { int s, n, cnt, error; @@ -138,7 +145,7 @@ wsevent_read(ev, uio, flags) return (EWOULDBLOCK); } ev->wanted = 1; - error = tsleep((caddr_t)ev, PWSEVENT | PCATCH, + error = tsleep(ev, PWSEVENT | PCATCH, "wsevent_read", 0); if (error) { splx(s); @@ -177,15 +184,12 @@ wsevent_read(ev, uio, flags) } int -wsevent_poll(ev, events, p) - struct wseventvar *ev; - int events; - struct proc *p; +wsevent_poll(struct wseventvar *ev, int events, struct proc *p) { int revents = 0; int s = splwsevent(); - if (events & (POLLIN | POLLRDNORM)) { + if (events & (POLLIN | POLLRDNORM)) { if (ev->get != ev->put) revents |= events & (POLLIN | POLLRDNORM); else diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c index 21894d8077c..c011d8958c0 100644 --- a/sys/dev/wscons/wskbd.c +++ b/sys/dev/wscons/wskbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wskbd.c,v 1.41 2004/06/24 19:35:24 tholo Exp $ */ -/* $NetBSD: wskbd.c,v 1.38 2000/03/23 07:01:47 thorpej Exp $ */ +/* $OpenBSD: wskbd.c,v 1.42 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -34,8 +34,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> - /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -103,9 +101,9 @@ #include <dev/wscons/wskbdvar.h> #include <dev/wscons/wsksymdef.h> #include <dev/wscons/wsksymvar.h> +#include <dev/wscons/wsdisplayvar.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wscons_callbacks.h> -#include <dev/wscons/wsdisplayvar.h> #include "wsdisplay.h" #include "wsmux.h" @@ -131,7 +129,7 @@ struct wskbd_internal { int t_composelen; /* remaining entries in t_composebuf */ keysym_t t_composebuf[2]; - int t_flags; + int t_flags; #define WSKFL_METAESC 1 #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */ @@ -141,7 +139,7 @@ struct wskbd_internal { }; struct wskbd_softc { - struct device sc_dv; + struct wsevsrc sc_base; struct wskbd_internal *id; @@ -150,12 +148,7 @@ struct wskbd_softc { int sc_ledstate; - struct wseventvar sc_events; /* event queue state */ - int sc_isconsole; -#if NWSDISPLAY > 0 - struct device *sc_displaydv; -#endif struct wskbd_bell_data sc_bell_data; struct wskbd_keyrepeat_data sc_keyrepeat_data; @@ -163,19 +156,17 @@ struct wskbd_softc { int sc_repeating; /* we've called timeout() */ int sc_repkey; struct timeout sc_repeat_ch; + u_int sc_repeat_type; + int sc_repeat_value; int sc_translating; /* xlate to chars for emulation */ int sc_maplen; /* number of entries in sc_map */ struct wscons_keymap *sc_map; /* current translation map */ - kbd_t sc_layout; /* current layout */ + kbd_t sc_layout; /* current layout */ - int sc_refcnt; - u_char sc_dying; /* device is being detached */ - -#if NWSMUX > 0 || NWSDISPLAY > 0 - struct wsmux_softc *sc_mux; -#endif + int sc_refcnt; + u_char sc_dying; /* device is being detached */ }; #define MOD_SHIFT_L (1 << 0) @@ -199,7 +190,6 @@ struct wskbd_softc { #define MOD_ANYCONTROL (MOD_CONTROL_L | MOD_CONTROL_R) #define MOD_ANYMETA (MOD_META_L | MOD_META_R) - /* these should result in precise 0 or 1, see wskbd_translate() XXX */ #define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0) #define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask)) @@ -210,26 +200,37 @@ void wskbd_attach(struct device *, struct device *, void *); int wskbd_detach(struct device *, int); int wskbd_activate(struct device *, enum devact); -int wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *p); -int wskbd_set_display(struct device *, struct wsmux_softc *); -int wskbd_isset_display(struct device *); +int wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *); +#if NWSDISPLAY > 0 +int wskbd_set_display(struct device *, struct wsevsrc *); +#else +#define wskbd_set_display NULL +#endif -inline void update_leds(struct wskbd_internal *); -inline void update_modifier(struct wskbd_internal *, u_int, int, int); -int internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t); -int wskbd_translate(struct wskbd_internal *, u_int, int); -int wskbd_enable(struct wskbd_softc *, int); +void update_leds(struct wskbd_internal *); +void update_modifier(struct wskbd_internal *, u_int, int, int); +int internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t); +int wskbd_translate(struct wskbd_internal *, u_int, int); +int wskbd_enable(struct wskbd_softc *, int); #if NWSDISPLAY > 0 -void change_displayparam(struct wskbd_softc *, int, int, int); -void wskbd_holdscreen(struct wskbd_softc *, int); +void change_displayparam(struct wskbd_softc *, int, int, int); +void wskbd_holdscreen(struct wskbd_softc *, int); #endif -int wskbd_do_ioctl(struct wskbd_softc *, u_long, caddr_t, - int, struct proc *); +int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, + struct proc *); +void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value); + +#if NWSMUX > 0 +int wskbd_mux_open(struct wsevsrc *, struct wseventvar *); +int wskbd_mux_close(struct wsevsrc *); +#else +#define wskbd_mux_open NULL +#define wskbd_mux_close NULL +#endif -int wskbddoclose(struct device *, int, int, struct proc *); -int wskbddoioctl(struct device *, u_long, caddr_t, int, - struct proc *); +int wskbd_do_open(struct wskbd_softc *, struct wseventvar *); +int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *); struct cfdriver wskbd_cd = { NULL, "wskbd", DV_TTY @@ -240,8 +241,6 @@ struct cfattach wskbd_ca = { wskbd_detach, wskbd_activate }; -extern struct cfdriver wskbd_cd; - extern int kbd_reset; #ifndef WSKBD_DEFAULT_BELL_PITCH @@ -275,9 +274,10 @@ struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = { }; #if NWSMUX > 0 || NWSDISPLAY > 0 -struct wsmuxops wskbd_muxops = { - wskbdopen, wskbddoclose, wskbddoioctl, wskbd_displayioctl, - wskbd_set_display, wskbd_isset_display +struct wssrcops wskbd_srcops = { + WSMUX_KBD, + wskbd_mux_open, wskbd_mux_close, wskbd_do_ioctl, + wskbd_displayioctl, wskbd_set_display }; #endif @@ -289,14 +289,11 @@ static int wskbd_console_initted; static struct wskbd_softc *wskbd_console_device; static struct wskbd_internal wskbd_console_data; -void wskbd_update_layout(struct wskbd_internal *, kbd_t); +void wskbd_update_layout(struct wskbd_internal *, kbd_t); void -wskbd_update_layout(id, enc) - struct wskbd_internal *id; - kbd_t enc; +wskbd_update_layout(struct wskbd_internal *id, kbd_t enc) { - if (enc & KB_METAESC) id->t_flags |= WSKFL_METAESC; else @@ -307,9 +304,7 @@ wskbd_update_layout(id, enc) * Print function (for parent devices). */ int -wskbddevprint(aux, pnp) - void *aux; - const char *pnp; +wskbddevprint(void *aux, const char *pnp) { #if 0 struct wskbddev_attach_args *ap = aux; @@ -325,10 +320,7 @@ wskbddevprint(aux, pnp) } int -wskbd_match(parent, match, aux) - struct device *parent; - void *match; - void *aux; +wskbd_match(struct device *parent, void *match, void *aux) { struct cfdata *cf = match; struct wskbddev_attach_args *ap = aux; @@ -349,36 +341,40 @@ wskbd_match(parent, match, aux) } void -wskbd_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +wskbd_attach(struct device *parent, struct device *self, void *aux) { struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wskbddev_attach_args *ap = aux; -#if NWSMUX > 0 || NWSDISPLAY > 0 - int mux; +#if NWSMUX > 0 + int mux, error; #endif -#if NWSDISPLAY > 0 - sc->sc_displaydv = NULL; -#endif sc->sc_isconsole = ap->console; #if NWSMUX > 0 || NWSDISPLAY > 0 - mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux; - if (sc->sc_isconsole && mux != WSKBDDEVCF_MUX_DEFAULT) { - printf(" (mux %d ignored for console)", mux); - mux = WSKBDDEVCF_MUX_DEFAULT; + sc->sc_base.me_ops = &wskbd_srcops; +#endif +#if NWSMUX > 0 + mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; + if (ap->console) { + /* Ignore mux for console; it always goes to the console mux. */ + /* printf(" (mux %d ignored for console)", mux); */ + mux = -1; } - if (mux != WSKBDDEVCF_MUX_DEFAULT) + if (mux >= 0) printf(" mux %d", mux); +#else +#if 0 /* not worth keeping, especially since the default value is not -1... */ + if (sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux >= 0) + printf(" (mux ignored)"); #endif +#endif /* NWSMUX > 0 */ if (ap->console) { sc->id = &wskbd_console_data; } else { sc->id = malloc(sizeof(struct wskbd_internal), - M_DEVBUF, M_WAITOK); + M_DEVBUF, M_WAITOK); bzero(sc->id, sizeof(struct wskbd_internal)); sc->id->t_keymap = ap->keymap; wskbd_update_layout(sc->id, ap->keymap->layout); @@ -392,13 +388,12 @@ wskbd_attach(parent, self, aux) sc->sc_accessops = ap->accessops; sc->sc_accesscookie = ap->accesscookie; - sc->sc_events.io = NULL; /* sanity */ sc->sc_repeating = 0; sc->sc_translating = 1; sc->sc_ledstate = -1; /* force update */ if (wskbd_load_keymap(sc->id->t_keymap, - &sc->sc_map, &sc->sc_maplen) != 0) + &sc->sc_map, &sc->sc_maplen) != 0) panic("cannot load keymap"); sc->sc_layout = sc->id->t_keymap->layout; @@ -416,27 +411,26 @@ wskbd_attach(parent, self, aux) printf(": console keyboard"); #if NWSDISPLAY > 0 - if ((sc->sc_displaydv = wsdisplay_set_console_kbd(self))) + wsdisplay_set_console_kbd(&sc->sc_base); /* sets me_dispdv */ + if (sc->sc_displaydv != NULL) printf(", using %s", sc->sc_displaydv->dv_xname); #endif } printf("\n"); #if NWSMUX > 0 - if (mux != WSKBDDEVCF_MUX_DEFAULT) { - wsmux_attach(mux, WSMUX_KBD, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wskbd_muxops); - wsdisplay_set_console_kbd(self); + if (mux >= 0) { + error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); + if (error) + printf("%s: attach error=%d\n", + sc->sc_base.me_dv.dv_xname, error); } #endif - } void -wskbd_cnattach(consops, conscookie, mapdata) - const struct wskbd_consops *consops; - void *conscookie; - const struct wskbd_mapdata *mapdata; +wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie, + const struct wskbd_mapdata *mapdata) { KASSERT(!wskbd_console_initted); @@ -473,8 +467,7 @@ wskbd_cndetach() #if NWSDISPLAY > 0 void -wskbd_repeat(v) - void *v; +wskbd_repeat(void *v) { struct wskbd_softc *sc = (struct wskbd_softc *)v; int s = spltty(); @@ -487,24 +480,33 @@ wskbd_repeat(v) splx(s); return; } - if (sc->sc_displaydv != NULL) { - int i; - for (i = 0; i < sc->sc_repeating; i++) - wsdisplay_kbdinput(sc->sc_displaydv, - sc->id->t_symbols[i]); + if (sc->sc_translating) { + /* deliver keys */ + if (sc->sc_base.me_dispdv != NULL) { + int i; + for (i = 0; i < sc->sc_repeating; i++) + wsdisplay_kbdinput(sc->sc_base.me_dispdv, + sc->id->t_symbols[i]); + } + } else { + /* queue event */ + wskbd_deliver_event(sc, sc->sc_repeat_type, + sc->sc_repeat_value); } - timeout_add(&sc->sc_repeat_ch, - (hz * sc->sc_keyrepeat_data.delN) / 1000); + if (sc->sc_keyrepeat_data.delN != 0) + timeout_add(&sc->sc_repeat_ch, + (hz * sc->sc_keyrepeat_data.delN) / 1000); splx(s); } #endif int -wskbd_activate(self, act) - struct device *self; - enum devact act; +wskbd_activate(struct device *self, enum devact act) { - /* XXX should we do something more? */ + struct wskbd_softc *sc = (struct wskbd_softc *)self; + + if (act == DVACT_DEACTIVATE) + sc->sc_dying = 1; return (0); } @@ -517,24 +519,17 @@ wskbd_activate(self, act) * vnode and return (which will deallocate the softc). */ int -wskbd_detach(self, flags) - struct device *self; - int flags; +wskbd_detach(struct device *self, int flags) { struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wseventvar *evar; int maj, mn; int s; -#if NWSMUX > 0 - int mux; -#endif - - sc->sc_dying = 1; #if NWSMUX > 0 - mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux; - if (mux != WSKBDDEVCF_MUX_DEFAULT) - wsmux_detach(mux, &sc->sc_dv); + /* Tell parent mux we're leaving. */ + if (sc->sc_base.me_parent != NULL) + wsmux_detach_sc(&sc->sc_base); #endif #if NWSDISPLAY > 0 @@ -549,8 +544,8 @@ wskbd_detach(self, flags) wskbd_console_device = NULL; } - evar = &sc->sc_events; - if (evar->io) { + evar = sc->sc_base.me_evp; + if (evar != NULL && evar->io != NULL) { s = spltty(); if (--sc->sc_refcnt >= 0) { /* Wake everyone by generating a dummy event. */ @@ -560,7 +555,7 @@ wskbd_detach(self, flags) /* Wait for processes to go away. */ if (tsleep(sc, PZERO, "wskdet", hz * 60)) printf("wskbd_detach: %s didn't detach\n", - sc->sc_dv.dv_xname); + sc->sc_base.me_dv.dv_xname); } splx(s); } @@ -578,22 +573,21 @@ wskbd_detach(self, flags) } void -wskbd_input(dev, type, value) - struct device *dev; - u_int type; - int value; +wskbd_input(struct device *dev, u_int type, int value) { struct wskbd_softc *sc = (struct wskbd_softc *)dev; - struct wscons_event *ev; - struct wseventvar *evar; #if NWSDISPLAY > 0 int num, i; #endif - int put; #if NWSDISPLAY > 0 + if (sc->sc_repeating) { + sc->sc_repeating = 0; + timeout_del(&sc->sc_repeat_ch); + } + /* - * If /dev/wskbd is not connected in event mode translate and + * If /dev/wskbdN is not connected in event mode translate and * send upstream. */ if (sc->sc_translating) { @@ -601,49 +595,74 @@ wskbd_input(dev, type, value) wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD); num = wskbd_translate(sc->id, type, value); if (num > 0) { - if (sc->sc_displaydv != NULL) { + if (sc->sc_base.me_dispdv != NULL) { /* XXX - Shift_R+PGUP(release) emits PrtSc */ if (sc->id->t_symbols[0] != KS_Print_Screen) { - wsscrollback(sc->sc_displaydv, + wsscrollback(sc->sc_base.me_dispdv, WSDISPLAY_SCROLL_RESET); } for (i = 0; i < num; i++) { - wsdisplay_kbdinput(sc->sc_displaydv, + wsdisplay_kbdinput(sc->sc_base.me_dispdv, sc->id->t_symbols[i]); } } - sc->sc_repeating = num; - timeout_add(&sc->sc_repeat_ch, - (hz * sc->sc_keyrepeat_data.del1) / 1000); + if (sc->sc_keyrepeat_data.del1 != 0) { + sc->sc_repeating = num; + timeout_add(&sc->sc_repeat_ch, + (hz * sc->sc_keyrepeat_data.del1) / 1000); + } } return; } #endif - /* - * Keyboard is generating events. Turn this keystroke into an - * event and put it in the queue. If the queue is full, the - * keystroke is lost (sorry!). - */ + wskbd_deliver_event(sc, type, value); + +#if NWSDISPLAY > 0 + /* Repeat key presses if enabled. */ + if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) { + sc->sc_repeat_type = type; + sc->sc_repeat_value = value; + sc->sc_repeating = 1; + timeout_add(&sc->sc_repeat_ch, + (hz * sc->sc_keyrepeat_data.del1) / 1000); + } +#endif +} - /* no one to receive; punt!*/ - if (sc->sc_events.io == NULL) +/* + * Keyboard is generating events. Turn this keystroke into an + * event and put it in the queue. If the queue is full, the + * keystroke is lost (sorry!). + */ +void +wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) +{ + struct wseventvar *evar; + struct wscons_event *ev; + int put; + + evar = sc->sc_base.me_evp; + + if (evar == NULL) { + DPRINTF(("wskbd_input: not open\n")); return; + } -#if NWSMUX > 0 - if (sc->sc_mux) - evar = &sc->sc_mux->sc_events; - else +#ifdef DIAGNOSTIC + if (evar->q == NULL) { + printf("wskbd_input: evar->q=NULL\n"); + return; + } #endif - evar = &sc->sc_events; put = evar->put; ev = &evar->q[put]; put = (put + 1) % WSEVENT_QSIZE; if (put == evar->get) { log(LOG_WARNING, "%s: event queue overflow\n", - sc->sc_dv.dv_xname); + sc->sc_base.me_dv.dv_xname); return; } ev->type = type; @@ -655,17 +674,15 @@ wskbd_input(dev, type, value) #ifdef WSDISPLAY_COMPAT_RAWKBD void -wskbd_rawinput(dev, buf, len) - struct device *dev; - u_char *buf; - int len; +wskbd_rawinput(struct device *dev, u_char *buf, int len) { #if NWSDISPLAY > 0 struct wskbd_softc *sc = (struct wskbd_softc *)dev; int i; - for (i = 0; i < len; i++) - wsdisplay_kbdinput(sc->sc_displaydv, buf[i]); + if (sc->sc_base.me_dispdv != NULL) + for (i = 0; i < len; i++) + wsdisplay_kbdinput(sc->sc_base.me_dispdv, buf[i]); /* this is KS_GROUP_Ascii */ #endif } @@ -673,14 +690,12 @@ wskbd_rawinput(dev, buf, len) #if NWSDISPLAY > 0 void -wskbd_holdscreen(sc, hold) - struct wskbd_softc *sc; - int hold; +wskbd_holdscreen(struct wskbd_softc *sc, int hold) { int new_state; - if (sc->sc_displaydv != NULL) { - wsdisplay_kbdholdscreen(sc->sc_displaydv, hold); + if (sc->sc_base.me_dispdv != NULL) { + wsdisplay_kbdholdscreen(sc->sc_base.me_dispdv, hold); new_state = sc->sc_ledstate; if (hold) new_state |= WSKBD_LED_SCROLL; @@ -696,99 +711,136 @@ wskbd_holdscreen(sc, hold) #endif int -wskbd_enable(sc, on) - struct wskbd_softc *sc; - int on; +wskbd_enable(struct wskbd_softc *sc, int on) { - int res; + int error; - /* XXX reference count? */ - if (!on && (!sc->sc_translating #if NWSDISPLAY > 0 - || sc->sc_displaydv + if (sc->sc_base.me_dispdv != NULL) + return (0); + + /* Always cancel auto repeat when fiddling with the kbd. */ + if (sc->sc_repeating) { + sc->sc_repeating = 0; + timeout_del(&sc->sc_repeat_ch); + } #endif - )) + + error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); + DPRINTF(("wskbd_enable: sc=%p on=%d res=%d\n", sc, on, error)); + return (error); +} + +#if NWSMUX > 0 +int +wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp) +{ + struct wskbd_softc *sc = (struct wskbd_softc *)me; + + if (sc->sc_dying) + return (EIO); + + if (sc->sc_base.me_evp != NULL) return (EBUSY); - res = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); - return (res); + return (wskbd_do_open(sc, evp)); } +#endif int -wskbdopen(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +wskbdopen(dev_t dev, int flags, int mode, struct proc *p) { struct wskbd_softc *sc; - int unit; + struct wseventvar *evar; + int unit, error; unit = minor(dev); if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */ (sc = wskbd_cd.cd_devs[unit]) == NULL) return (ENXIO); +#if NWSMUX > 0 + DPRINTF(("wskbdopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname, + sc->sc_base.me_parent, p)); +#endif + if (sc->sc_dying) return (EIO); - if (!(flags & FREAD)) { + if ((flags & (FREAD | FWRITE)) == FWRITE) { /* Not opening for read, only ioctl is available. */ return (0); } #if NWSMUX > 0 - if (sc->sc_mux) - return (EBUSY); + if (sc->sc_base.me_parent != NULL) { + /* Grab the keyboard out of the greedy hands of the mux. */ + DPRINTF(("wskbdopen: detach\n")); + wsmux_detach_sc(&sc->sc_base); + } #endif - if (sc->sc_events.io) /* and that it's not in use */ + if (sc->sc_base.me_evp != NULL) return (EBUSY); - sc->sc_events.io = p; - wsevent_init(&sc->sc_events); /* may cause sleep */ - - sc->sc_translating = 0; + evar = &sc->sc_base.me_evar; + wsevent_init(evar); + evar->io = p; - wskbd_enable(sc, 1); - return (0); + error = wskbd_do_open(sc, evar); + if (error) { + DPRINTF(("wskbdopen: %s open failed\n", + sc->sc_base.me_dv.dv_xname)); + sc->sc_base.me_evp = NULL; + wsevent_fini(evar); + } + return (error); } int -wskbdclose(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp) { - return (wskbddoclose(wskbd_cd.cd_devs[minor(dev)], flags, mode, p)); + sc->sc_base.me_evp = evp; + sc->sc_translating = 0; + + return (wskbd_enable(sc, 1)); } int -wskbddoclose(dv, flags, mode, p) - struct device *dv; - int flags, mode; - struct proc *p; +wskbdclose(dev_t dev, int flags, int mode, struct proc *p) { - struct wskbd_softc *sc = (struct wskbd_softc *)dv; + struct wskbd_softc *sc = + (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)]; + struct wseventvar *evar = sc->sc_base.me_evp; - if (!(flags & FREAD)) { - /* Nothing to do, because open didn't do anything. */ + if (evar == NULL) + /* not open for read */ return (0); - } + sc->sc_base.me_evp = NULL; sc->sc_translating = 1; + (void)wskbd_enable(sc, 0); + wsevent_fini(evar); + + return (0); +} - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; +#if NWSMUX > 0 +int +wskbd_mux_close(struct wsevsrc *me) +{ + struct wskbd_softc *sc = (struct wskbd_softc *)me; + + sc->sc_base.me_evp = NULL; + sc->sc_translating = 1; + (void)wskbd_enable(sc, 0); - wskbd_enable(sc, 0); return (0); } +#endif int -wskbdread(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; +wskbdread(dev_t dev, struct uio *uio, int flags) { struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; int error; @@ -796,8 +848,15 @@ wskbdread(dev, uio, flags) if (sc->sc_dying) return (EIO); +#ifdef DIAGNOSTIC + if (sc->sc_base.me_evp == NULL) { + printf("wskbdread: evp == NULL\n"); + return (EINVAL); + } +#endif + sc->sc_refcnt++; - error = wsevent_read(&sc->sc_events, uio, flags); + error = wsevent_read(&sc->sc_base.me_evar, uio, flags); if (--sc->sc_refcnt < 0) { wakeup(sc); error = EIO; @@ -806,42 +865,29 @@ wskbdread(dev, uio, flags) } int -wskbdioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - return (wskbddoioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p)); + return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p)); } /* A wrapper around the ioctl() workhorse to make reference counting easy. */ int -wskbddoioctl(dv, cmd, data, flag, p) - struct device *dv; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, + struct proc *p) { struct wskbd_softc *sc = (struct wskbd_softc *)dv; int error; sc->sc_refcnt++; - error = wskbd_do_ioctl(sc, cmd, data, flag, p); + error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p); if (--sc->sc_refcnt < 0) wakeup(sc); return (error); } int -wskbd_do_ioctl(sc, cmd, data, flag, p) - struct wskbd_softc *sc; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, + struct proc *p) { int error; @@ -853,11 +899,23 @@ wskbd_do_ioctl(sc, cmd, data, flag, p) return (0); case FIOASYNC: - sc->sc_events.async = *(int *)data != 0; + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + sc->sc_base.me_evp->async = *(int *)data != 0; return (0); + case FIOSETOWN: + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + if (-*(int *)data != sc->sc_base.me_evp->io->p_pgid && + *(int *)data != sc->sc_base.me_evp->io->p_pid) + return (EPERM); + return (0); + case TIOCSPGRP: - if (*(int *)data != sc->sc_events.io->p_pgid) + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + if (*(int *)data != sc->sc_base.me_evp->io->p_pgid) return (EPERM); return (0); } @@ -866,7 +924,7 @@ wskbd_do_ioctl(sc, cmd, data, flag, p) * Try the keyboard driver for WSKBDIO ioctls. It returns -1 * if it didn't recognize the request. */ - error = wskbd_displayioctl((struct device *)sc, cmd, data, flag, p); + error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p); return (error != -1 ? error : ENOTTY); } @@ -875,12 +933,8 @@ wskbd_do_ioctl(sc, cmd, data, flag, p) * Some of these have no real effect in raw mode, however. */ int -wskbd_displayioctl(dev, cmd, data, flag, p) - struct device *dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag, + struct proc *p) { struct wskbd_softc *sc = (struct wskbd_softc *)dev; struct wskbd_bell_data *ubdp, *kbdp; @@ -961,11 +1015,6 @@ getbell: kkdp = &sc->sc_keyrepeat_data; setkeyrepeat: ukdp = (struct wskbd_keyrepeat_data *)data; - if ((ukdp->which & WSKBD_KEYREPEAT_DODEL1 && - (hz * ukdp->del1) / 1000 <= 0) || - (ukdp->which & WSKBD_KEYREPEAT_DODELN && - (hz * ukdp->delN) / 1000 <= 0)) - return (EINVAL); SETKEYREPEAT(kkdp, ukdp, kkdp); return (0); @@ -995,7 +1044,8 @@ getkeyrepeat: umdp = (struct wskbd_map_data *)data; if (umdp->maplen > WSKBDIO_MAXMAPLEN) return (EINVAL); - len = umdp->maplen*sizeof(struct wscons_keymap); + + len = umdp->maplen * sizeof(struct wscons_keymap); buf = malloc(len, M_TEMP, M_WAITOK); error = copyin(umdp->map, buf, len); if (error == 0) { @@ -1035,11 +1085,11 @@ getkeyrepeat: return (EINVAL); } else { md = *(sc->id->t_keymap); /* structure assignment */ - md.layout = enc; - error = wskbd_load_keymap(&md, &sc->sc_map, - &sc->sc_maplen); - if (error) - return(error); + md.layout = enc; + error = wskbd_load_keymap(&md, &sc->sc_map, + &sc->sc_maplen); + if (error) + return(error); } sc->sc_layout = enc; wskbd_update_layout(sc->id, enc); @@ -1075,14 +1125,13 @@ getkeyrepeat: } int -wskbdpoll(dev, events, p) - dev_t dev; - int events; - struct proc *p; +wskbdpoll(dev_t dev, int events, struct proc *p) { struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; - return (wsevent_poll(&sc->sc_events, events, p)); + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + return (wsevent_poll(sc->sc_base.me_evp, events, p)); } #if NWSDISPLAY > 0 @@ -1102,120 +1151,86 @@ wskbd_pickfree() return (-1); } -struct device * -wskbd_set_console_display(displaydv, muxsc) - struct device *displaydv; - struct wsmux_softc *muxsc; +struct wsevsrc * +wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me) { struct wskbd_softc *sc = wskbd_console_device; - if (!sc) - return (0); - sc->sc_displaydv = displaydv; - (void)wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wskbd_muxops); - return (&sc->sc_dv); + if (sc == NULL) + return (NULL); + sc->sc_base.me_dispdv = displaydv; +#if NWSMUX > 0 + (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base); +#endif + return (&sc->sc_base); } int -wskbd_set_display(dv, muxsc) - struct device *dv; - struct wsmux_softc *muxsc; +wskbd_set_display(struct device *dv, struct wsevsrc *me) { struct wskbd_softc *sc = (struct wskbd_softc *)dv; - struct device *displaydv = muxsc ? muxsc->sc_displaydv : 0; + struct device *displaydv = me != NULL ? me->me_dispdv : NULL; struct device *odisplaydv; int error; - DPRINTF(("wskbd_set_display: %s mux=%p disp=%p odisp=%p cons=%d\n", - dv->dv_xname, muxsc, sc->sc_displaydv, displaydv, + DPRINTF(("wskbd_set_display: %s me=%p odisp=%p disp=%p cons=%d\n", + dv->dv_xname, me, sc->sc_base.me_dispdv, displaydv, sc->sc_isconsole)); if (sc->sc_isconsole) return (EBUSY); - if (displaydv) { - if (sc->sc_displaydv) + if (displaydv != NULL) { + if (sc->sc_base.me_dispdv != NULL) return (EBUSY); } else { - if (sc->sc_displaydv == NULL) + if (sc->sc_base.me_dispdv == NULL) return (ENXIO); } - odisplaydv = sc->sc_displaydv; - sc->sc_displaydv = displaydv; - + odisplaydv = sc->sc_base.me_dispdv; + sc->sc_base.me_dispdv = NULL; error = wskbd_enable(sc, displaydv != NULL); + sc->sc_base.me_dispdv = displaydv; if (error) { - sc->sc_displaydv = odisplaydv; + sc->sc_base.me_dispdv = odisplaydv; return (error); } if (displaydv) printf("%s: connecting to %s\n", - sc->sc_dv.dv_xname, displaydv->dv_xname); + sc->sc_base.me_dv.dv_xname, displaydv->dv_xname); else printf("%s: disconnecting from %s\n", - sc->sc_dv.dv_xname, odisplaydv->dv_xname); + sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname); return (0); } -int -wskbd_isset_display(dv) - struct device *dv; -{ - struct wskbd_softc *sc = (struct wskbd_softc *)dv; - - if (sc->sc_displaydv != NULL) - return (1); - - return (0); -} +#endif /* NWSDISPLAY > 0 */ +#if NWSMUX > 0 int -wskbd_add_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; +wskbd_add_mux(int unit, struct wsmux_softc *muxsc) { struct wskbd_softc *sc; - DPRINTF(("wskbd_add_mux: %d %s %p\n", unit, muxsc->sc_dv.dv_xname, - muxsc->sc_displaydv)); if (unit < 0 || unit >= wskbd_cd.cd_ndevs || (sc = wskbd_cd.cd_devs[unit]) == NULL) return (ENXIO); - if (sc->sc_mux || sc->sc_events.io) + if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) return (EBUSY); - return (wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wskbd_muxops)); -} - -int -wskbd_rem_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; -{ - struct wskbd_softc *sc; - - DPRINTF(("wskbd_rem_mux: %d %s\n", unit, muxsc->sc_dv.dv_xname)); - if (unit < 0 || unit >= wskbd_cd.cd_ndevs || - (sc = wskbd_cd.cd_devs[unit]) == NULL) - return (ENXIO); - - return (wsmux_detach_sc(muxsc, &sc->sc_dv)); + return (wsmux_attach_sc(muxsc, &sc->sc_base)); } - -#endif /* NWSDISPLAY > 0 */ +#endif /* * Console interface. */ int -wskbd_cngetc(dev) - dev_t dev; +wskbd_cngetc(dev_t dev) { static int num = 0; static int pos; @@ -1233,7 +1248,8 @@ wskbd_cngetc(dev) for(;;) { if (num-- > 0) { ks = wskbd_console_data.t_symbols[pos++]; - return (KS_VALUE(ks)); + if (KS_GROUP(ks) == KS_GROUP_Ascii) + return (KS_VALUE(ks)); } else { (*wskbd_console_data.t_consops->getc) (wskbd_console_data.t_consaccesscookie, @@ -1245,9 +1261,7 @@ wskbd_cngetc(dev) } void -wskbd_cnpollc(dev, poll) - dev_t dev; - int poll; +wskbd_cnpollc(dev_t dev, int poll) { if (!wskbd_console_initted) @@ -1262,9 +1276,7 @@ wskbd_cnpollc(dev, poll) } void -wskbd_cnbell(dev, pitch, period, volume) - dev_t dev; - u_int pitch, period, volume; +wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume) { if (!wskbd_console_initted) return; @@ -1275,9 +1287,8 @@ wskbd_cnbell(dev, pitch, period, volume) volume); } -inline void -update_leds(id) - struct wskbd_internal *id; +void +update_leds(struct wskbd_internal *id) { int new_state; @@ -1298,12 +1309,8 @@ update_leds(id) } } -inline void -update_modifier(id, type, toggle, mask) - struct wskbd_internal *id; - u_int type; - int toggle; - int mask; +void +update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask) { if (toggle) { if (type == WSCONS_EVENT_KEY_DOWN) @@ -1318,18 +1325,14 @@ update_modifier(id, type, toggle, mask) #if NWSDISPLAY > 0 void -change_displayparam(sc, param, updown, wraparound) - struct wskbd_softc *sc; - int param, updown, wraparound; +change_displayparam(struct wskbd_softc *sc, int param, int updown, + int wraparound) { int res; struct wsdisplay_param dp; - if (sc->sc_displaydv == NULL) - return; - dp.param = param; - res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp); + res = wsdisplay_param(sc->sc_base.me_dispdv, WSDISPLAYIO_GETPARAM, &dp); if (res == EINVAL) return; /* no such parameter */ @@ -1340,15 +1343,13 @@ change_displayparam(sc, param, updown, wraparound) else if (dp.curval < dp.min) dp.curval = wraparound ? dp.max : dp.min; - wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp); + wsdisplay_param(sc->sc_base.me_dispdv, WSDISPLAYIO_SETPARAM, &dp); } #endif int -internal_command(sc, type, ksym, ksym2) - struct wskbd_softc *sc; - u_int *type; - keysym_t ksym, ksym2; +internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, + keysym_t ksym2) { switch (ksym) { case KS_Cmd: @@ -1394,17 +1395,21 @@ internal_command(sc, type, ksym, ksym2) !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)) return (0); - switch (ksym) { #ifdef DDB - case KS_Cmd_Debugger: + if (ksym == KS_Cmd_Debugger) { if (sc->sc_isconsole && db_console) Debugger(); /* discard this key (ddb discarded command modifiers) */ *type = WSCONS_EVENT_KEY_UP; return (1); + } #endif #if NWSDISPLAY > 0 + if (sc->sc_base.me_dispdv == NULL) + return (0); + + switch (ksym) { case KS_Cmd_Screen0: case KS_Cmd_Screen1: case KS_Cmd_Screen2: @@ -1417,17 +1422,13 @@ internal_command(sc, type, ksym, ksym2) case KS_Cmd_Screen9: case KS_Cmd_Screen10: case KS_Cmd_Screen11: - if (sc->sc_displaydv != NULL) - wsdisplay_switch(sc->sc_displaydv, - ksym - KS_Cmd_Screen0, 0); + wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0); return (1); case KS_Cmd_ResetEmul: - if (sc->sc_displaydv != NULL) - wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); + wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); return (1); case KS_Cmd_ResetClose: - if (sc->sc_displaydv != NULL) - wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); + wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); return (1); #if defined(__i386__) || defined(__amd64__) case KS_Cmd_KbdReset: @@ -1441,22 +1442,22 @@ internal_command(sc, type, ksym, ksym2) case KS_Cmd_BacklightOff: case KS_Cmd_BacklightToggle: change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT, - ksym == KS_Cmd_BacklightOff ? -1 : 1, - ksym == KS_Cmd_BacklightToggle ? 1 : 0); + ksym == KS_Cmd_BacklightOff ? -1 : 1, + ksym == KS_Cmd_BacklightToggle ? 1 : 0); return (1); case KS_Cmd_BrightnessUp: case KS_Cmd_BrightnessDown: case KS_Cmd_BrightnessRotate: change_displayparam(sc, WSDISPLAYIO_PARAM_BRIGHTNESS, - ksym == KS_Cmd_BrightnessDown ? -1 : 1, - ksym == KS_Cmd_BrightnessRotate ? 1 : 0); + ksym == KS_Cmd_BrightnessDown ? -1 : 1, + ksym == KS_Cmd_BrightnessRotate ? 1 : 0); return (1); case KS_Cmd_ContrastUp: case KS_Cmd_ContrastDown: case KS_Cmd_ContrastRotate: change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST, - ksym == KS_Cmd_ContrastDown ? -1 : 1, - ksym == KS_Cmd_ContrastRotate ? 1 : 0); + ksym == KS_Cmd_ContrastDown ? -1 : 1, + ksym == KS_Cmd_ContrastRotate ? 1 : 0); return (1); #endif } @@ -1464,10 +1465,7 @@ internal_command(sc, type, ksym, ksym2) } int -wskbd_translate(id, type, value) - struct wskbd_internal *id; - u_int type; - int value; +wskbd_translate(struct wskbd_internal *id, u_int type, int value) { struct wskbd_softc *sc = id->t_sc; keysym_t ksym, res, *group; @@ -1475,11 +1473,11 @@ wskbd_translate(id, type, value) int gindex, iscommand = 0; if (type == WSCONS_EVENT_ALL_KEYS_UP) { - id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R - | MOD_CONTROL_L | MOD_CONTROL_R - | MOD_META_L | MOD_META_R - | MOD_MODESHIFT | MOD_MODELOCK - | MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); + id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | + MOD_CONTROL_L | MOD_CONTROL_R | + MOD_META_L | MOD_META_R | + MOD_MODESHIFT | MOD_MODELOCK | + MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); update_leds(id); return (0); } @@ -1501,7 +1499,7 @@ wskbd_translate(id, type, value) /* if this key has a command, process it first */ if (sc != NULL && kp->command != KS_voidSymbol) iscommand = internal_command(sc, &type, kp->command, - kp->group1[0]); + kp->group1[0]); /* Now update modifiers */ switch (kp->group1[0]) { @@ -1561,7 +1559,8 @@ wskbd_translate(id, type, value) if (sc != NULL && sc->sc_repeating && ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) || (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))) - return (0); + return (0); + break; #endif } @@ -1678,7 +1677,7 @@ wskbd_translate(id, type, value) id->t_symbols[1] = res; return (2); } else - res |= 0x80; + res |= 0x80; } } diff --git a/sys/dev/wscons/wsksymdef.h b/sys/dev/wscons/wsksymdef.h index 18ef6e95d9b..903a12ce43d 100644 --- a/sys/dev/wscons/wsksymdef.h +++ b/sys/dev/wscons/wsksymdef.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsksymdef.h,v 1.27 2005/05/12 09:26:48 miod Exp $ */ +/* $OpenBSD: wsksymdef.h,v 1.28 2005/05/15 11:29:15 miod Exp $ */ /* $NetBSD: wsksymdef.h,v 1.34.4.1 2000/07/07 09:49:54 hannken Exp $ */ /*- @@ -673,6 +673,7 @@ #define KB_ENCODING(e) ((e) & 0x0000ff00) #define KB_VARIANT(e) ((e) & 0xffff00ff) +#define KB_NONE 0x0000 #define KB_USER 0x0100 #define KB_US 0x0200 #define KB_DE 0x0300 diff --git a/sys/dev/wscons/wsmouse.c b/sys/dev/wscons/wsmouse.c index ebbef486705..917414e6bd6 100644 --- a/sys/dev/wscons/wsmouse.c +++ b/sys/dev/wscons/wsmouse.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wsmouse.c,v 1.13 2004/06/24 19:35:24 tholo Exp $ */ -/* $NetBSD: wsmouse.c,v 1.12 2000/05/01 07:36:58 takemura Exp $ */ +/* $OpenBSD: wsmouse.c,v 1.14 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsmouse.c,v 1.35 2005/02/27 00:27:52 perry Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -96,13 +96,19 @@ #include <dev/wscons/wsdisplayvar.h> #include <dev/rndvar.h> -#include "wsmouse.h" #include "wsmux.h" #include "wsdisplay.h" #include "wskbd.h" -#if NWSMUX > 0 #include <dev/wscons/wsmuxvar.h> + +#if defined(WSMUX_DEBUG) && NWSMUX > 0 +#define DPRINTF(x) if (wsmuxdebug) printf x +#define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x +extern int wsmuxdebug; +#else +#define DPRINTF(x) +#define DPRINTFN(n,x) #endif #define INVALID_X INT_MAX @@ -110,14 +116,11 @@ #define INVALID_Z INT_MAX struct wsmouse_softc { - struct device sc_dv; + struct wsevsrc sc_base; const struct wsmouse_accessops *sc_accessops; void *sc_accesscookie; - int sc_ready; /* accepting events */ - struct wseventvar sc_events; /* event queue state */ - u_int sc_mb; /* mouse button state */ u_int sc_ub; /* user button state */ int sc_dx; /* delta-x */ @@ -129,10 +132,6 @@ struct wsmouse_softc { int sc_refcnt; u_char sc_dying; /* device is being detached */ - -#if NWSMUX > 0 - struct wsmux_softc *sc_mux; -#endif }; int wsmouse_match(struct device *, void *, void *); @@ -143,9 +142,14 @@ int wsmouse_activate(struct device *, enum devact); int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t, int, struct proc *); -int wsmousedoclose(struct device *, int, int, struct proc *); +#if NWSMUX > 0 +int wsmouse_mux_open(struct wsevsrc *, struct wseventvar *); +int wsmouse_mux_close(struct wsevsrc *); +#endif + int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *); +int wsmousedoopen(struct wsmouse_softc *, struct wseventvar *); struct cfdriver wsmouse_cd = { NULL, "wsmouse", DV_TTY @@ -156,13 +160,10 @@ struct cfattach wsmouse_ca = { wsmouse_detach, wsmouse_activate }; -#if NWSMOUSE > 0 -extern struct cfdriver wsmouse_cd; -#endif /* NWSMOUSE > 0 */ - #if NWSMUX > 0 -struct wsmuxops wsmouse_muxops = { - wsmouseopen, wsmousedoclose, wsmousedoioctl, 0, 0, 0 +struct wssrcops wsmouse_srcops = { + WSMUX_MOUSE, + wsmouse_mux_open, wsmouse_mux_close, wsmousedoioctl, NULL, NULL }; #endif @@ -170,9 +171,7 @@ struct wsmuxops wsmouse_muxops = { * Print function (for parent devices). */ int -wsmousedevprint(aux, pnp) - void *aux; - const char *pnp; +wsmousedevprint(void *aux, const char *pnp) { if (pnp) @@ -181,47 +180,50 @@ wsmousedevprint(aux, pnp) } int -wsmouse_match(parent, match, aux) - struct device *parent; - void *match; - void *aux; +wsmouse_match(struct device *parent, void *match, void *aux) { return (1); } void -wsmouse_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +wsmouse_attach(struct device *parent, struct device *self, void *aux) { - struct wsmouse_softc *sc = (struct wsmouse_softc *)self; + struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wsmousedev_attach_args *ap = aux; #if NWSMUX > 0 - int mux; + int mux, error; #endif sc->sc_accessops = ap->accessops; sc->sc_accesscookie = ap->accesscookie; - sc->sc_ready = 0; /* sanity */ #if NWSMUX > 0 - mux = sc->sc_dv.dv_cfdata->wsmousedevcf_mux; - if (mux != WSMOUSEDEVCF_MUX_DEFAULT) { - wsmux_attach(mux, WSMUX_MOUSE, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wsmouse_muxops); - printf(" mux %d", mux); + sc->sc_base.me_ops = &wsmouse_srcops; + mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux; + if (mux >= 0) { + error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); + if (error) + printf(" attach error=%d", error); + else + printf(" mux %d", mux); } +#else +#if 0 /* not worth keeping, especially since the default value is not -1... */ + if (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux >= 0) + printf(" (mux ignored)"); #endif +#endif /* NWSMUX > 0 */ printf("\n"); } int -wsmouse_activate(self, act) - struct device *self; - enum devact act; +wsmouse_activate(struct device *self, enum devact act) { - /* XXX should we do something more? */ + struct wsmouse_softc *sc = (struct wsmouse_softc *)self; + + if (act == DVACT_DEACTIVATE) + sc->sc_dying = 1; return (0); } @@ -234,28 +236,24 @@ wsmouse_activate(self, act) * vnode and return (which will deallocate the softc). */ int -wsmouse_detach(self, flags) - struct device *self; - int flags; +wsmouse_detach(struct device *self, int flags) { struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wseventvar *evar; int maj, mn; int s; -#if NWSMUX > 0 - int mux; -#endif - - sc->sc_dying = 1; #if NWSMUX > 0 - mux = sc->sc_dv.dv_cfdata->wsmousedevcf_mux; - if (mux != WSMOUSEDEVCF_MUX_DEFAULT) - wsmux_detach(mux, &sc->sc_dv); + /* Tell parent mux we're leaving. */ + if (sc->sc_base.me_parent != NULL) { + DPRINTF(("wsmouse_detach:\n")); + wsmux_detach_sc(&sc->sc_base); + } #endif - evar = &sc->sc_events; - if (evar->io) { + /* If we're open ... */ + evar = sc->sc_base.me_evp; + if (evar != NULL && evar->io != NULL) { s = spltty(); if (--sc->sc_refcnt >= 0) { /* Wake everyone by generating a dummy event. */ @@ -265,7 +263,7 @@ wsmouse_detach(self, flags) /* Wait for processes to go away. */ if (tsleep(sc, PZERO, "wsmdet", hz * 60)) printf("wsmouse_detach: %s didn't detach\n", - sc->sc_dv.dv_xname); + sc->sc_base.me_dv.dv_xname); } splx(s); } @@ -283,31 +281,34 @@ wsmouse_detach(self, flags) } void -wsmouse_input(wsmousedev, btns, x, y, z, flags) - struct device *wsmousedev; - u_int btns; /* 0 is up */ - int x, y, z; - u_int flags; +wsmouse_input(struct device *wsmousedev, u_int btns, /* 0 is up */ + int x, int y, int z, u_int flags) { struct wsmouse_softc *sc = (struct wsmouse_softc *)wsmousedev; struct wscons_event *ev; struct wseventvar *evar; int mb, ub, d, get, put, any; - /* - * Discard input if not ready. - */ - if (sc->sc_ready == 0) + add_mouse_randomness(x ^ y ^ z ^ btns); + + /* + * Discard input if not ready. + */ + evar = sc->sc_base.me_evp; + if (evar == NULL) return; - add_mouse_randomness(x ^ y ^ z ^ btns); +#ifdef DIAGNOSTIC + if (evar->q == NULL) { + printf("wsmouse_input: evar->q=NULL\n"); + return; + } +#endif #if NWSMUX > 0 - if (sc->sc_mux) - evar = &sc->sc_mux->sc_events; - else + DPRINTFN(5,("wsmouse_input: %s mux=%p, evar=%p\n", + sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent, evar)); #endif - evar = &sc->sc_events; sc->sc_mb = btns; if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X)) @@ -429,30 +430,35 @@ wsmouse_input(wsmousedev, btns, x, y, z, flags) /* XXX fake wscons_event notifying wsmoused(8) to close mouse device */ if (flags & WSMOUSE_INPUT_WSMOUSED_CLOSE) { - NEXT; - ev->type = WSCONS_EVENT_WSMOUSED_CLOSE; - ev->value = 0; - TIMESTAMP; - ADVANCE; + NEXT; + ev->type = WSCONS_EVENT_WSMOUSED_CLOSE; + ev->value = 0; + TIMESTAMP; + ADVANCE; } +#undef TIMESTAMP +#undef ADVANCE +#undef NEXT + out: if (any) { sc->sc_ub = ub; evar->put = put; WSEVENT_WAKEUP(evar); /* wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_MOUSE); */ +#if NWSMUX > 0 + DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n", + sc->sc_base.me_dv.dv_xname, evar)); +#endif } } int -wsmouseopen(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +wsmouseopen(dev_t dev, int flags, int mode, struct proc *p) { -#if NWSMOUSE > 0 struct wsmouse_softc *sc; + struct wseventvar *evar; int error, unit; unit = minor(dev); @@ -460,6 +466,11 @@ wsmouseopen(dev, flags, mode, p) (sc = wsmouse_cd.cd_devs[unit]) == NULL) return (ENXIO); +#if NWSMUX > 0 + DPRINTF(("wsmouseopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname, + sc->sc_base.me_parent, p)); +#endif + if (sc->sc_dying) return (EIO); @@ -467,122 +478,88 @@ wsmouseopen(dev, flags, mode, p) return (0); /* always allow open for write so ioctl() is possible. */ -#if NWSMUX > 0 - if (sc->sc_mux) - return (EBUSY); -#endif - - if (sc->sc_events.io) /* and that it's not in use */ + if (sc->sc_base.me_evp != NULL) return (EBUSY); - sc->sc_events.io = p; - wsevent_init(&sc->sc_events); /* may cause sleep */ - - sc->sc_ready = 1; /* start accepting events */ - sc->sc_x = INVALID_X; - sc->sc_y = INVALID_Y; - sc->sc_z = INVALID_Z; + evar = &sc->sc_base.me_evar; + wsevent_init(evar); + evar->io = p; - /* enable the device, and punt if that's not possible */ - error = (*sc->sc_accessops->enable)(sc->sc_accesscookie); + error = wsmousedoopen(sc, evar); if (error) { - sc->sc_ready = 0; /* stop accepting events */ - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; - return (error); + DPRINTF(("wsmouseopen: %s open failed\n", + sc->sc_base.me_dv.dv_xname)); + sc->sc_base.me_evp = NULL; + wsevent_fini(evar); } - - return (0); -#else - return (ENXIO); -#endif /* NWSMOUSE > 0 */ + return (error); } int -wsmouseclose(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +wsmouseclose(dev_t dev, int flags, int mode, struct proc *p) { -#if NWSMOUSE > 0 - return (wsmousedoclose(wsmouse_cd.cd_devs[minor(dev)], - flags, mode, p)); -#else - return (ENXIO); -#endif /* NWSMOUSE > 0 */ + struct wsmouse_softc *sc = + (struct wsmouse_softc *)wsmouse_cd.cd_devs[minor(dev)]; + struct wseventvar *evar = sc->sc_base.me_evp; + + if (evar == NULL) + /* not open for read */ + return (0); + sc->sc_base.me_evp = NULL; + (*sc->sc_accessops->disable)(sc->sc_accesscookie); + wsevent_fini(evar); + + return (0); } -#if NWSMOUSE > 0 int -wsmousedoclose(dv, flags, mode, p) - struct device *dv; - int flags, mode; - struct proc *p; +wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp) { - struct wsmouse_softc *sc = (struct wsmouse_softc *)dv; - - if ((flags & (FREAD | FWRITE)) == FWRITE) - return (0); /* see wsmouseopen() */ - - (*sc->sc_accessops->disable)(sc->sc_accesscookie); + sc->sc_base.me_evp = evp; + sc->sc_x = INVALID_X; + sc->sc_y = INVALID_Y; + sc->sc_z = INVALID_Z; - sc->sc_ready = 0; /* stop accepting events */ - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; - return (0); + /* enable the device, and punt if that's not possible */ + return (*sc->sc_accessops->enable)(sc->sc_accesscookie); } -#endif /* NWSMOUSE > 0 */ int -wsmouseread(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; +wsmouseread(dev_t dev, struct uio *uio, int flags) { -#if NWSMOUSE > 0 struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)]; int error; if (sc->sc_dying) return (EIO); +#ifdef DIAGNOSTIC + if (sc->sc_base.me_evp == NULL) { + printf("wsmouseread: evp == NULL\n"); + return (EINVAL); + } +#endif + sc->sc_refcnt++; - error = wsevent_read(&sc->sc_events, uio, flags); + error = wsevent_read(sc->sc_base.me_evp, uio, flags); if (--sc->sc_refcnt < 0) { wakeup(sc); error = EIO; } return (error); -#else - return (ENXIO); -#endif /* NWSMOUSE > 0 */ } int -wsmouseioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { -#if NWSMOUSE > 0 return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)], - cmd, data, flag, p)); -#else - return (ENXIO); -#endif /* NWSMOUSE > 0 */ + cmd, data, flag, p)); } -#if NWSMOUSE > 0 /* A wrapper around the ioctl() workhorse to make reference counting easy. */ int -wsmousedoioctl(dv, cmd, data, flag, p) - struct device *dv; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsmousedoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, + struct proc *p) { struct wsmouse_softc *sc = (struct wsmouse_softc *)dv; int error; @@ -595,12 +572,8 @@ wsmousedoioctl(dv, cmd, data, flag, p) } int -wsmouse_do_ioctl(sc, cmd, data, flag, p) - struct wsmouse_softc *sc; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, int flag, + struct proc *p) { int error; @@ -615,11 +588,23 @@ wsmouse_do_ioctl(sc, cmd, data, flag, p) return (0); case FIOASYNC: - sc->sc_events.async = *(int *)data != 0; + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + sc->sc_base.me_evp->async = *(int *)data != 0; + return (0); + + case FIOSETOWN: + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + if (-*(int *)data != sc->sc_base.me_evp->io->p_pgid + && *(int *)data != sc->sc_base.me_evp->io->p_pid) + return (EPERM); return (0); case TIOCSPGRP: - if (*(int *)data != sc->sc_events.io->p_pgid) + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + if (*(int *)data != sc->sc_base.me_evp->io->p_pgid) return (EPERM); return (0); } @@ -632,46 +617,42 @@ wsmouse_do_ioctl(sc, cmd, data, flag, p) data, flag, p); return (error != -1 ? error : ENOTTY); } -#endif /* NWSMOUSE > 0 */ int -wsmousepoll(dev, events, p) - dev_t dev; - int events; - struct proc *p; +wsmousepoll(dev_t dev, int events, struct proc *p) { -#if NWSMOUSE > 0 struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)]; - return (wsevent_poll(&sc->sc_events, events, p)); -#else - return (0); -#endif /* NWSMOUSE > 0 */ + if (sc->sc_base.me_evp == NULL) + return (EINVAL); + return (wsevent_poll(sc->sc_base.me_evp, events, p)); } #if NWSMUX > 0 int -wsmouse_add_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; +wsmouse_mux_open(struct wsevsrc *me, struct wseventvar *evp) { - struct wsmouse_softc *sc; - - if (unit < 0 || unit >= wsmouse_cd.cd_ndevs || - (sc = wsmouse_cd.cd_devs[unit]) == NULL) - return (ENXIO); + struct wsmouse_softc *sc = (struct wsmouse_softc *)me; - if (sc->sc_mux || sc->sc_events.io) + if (sc->sc_base.me_evp != NULL) return (EBUSY); - return (wsmux_attach_sc(muxsc, WSMUX_MOUSE, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wsmouse_muxops)); + return wsmousedoopen(sc, evp); } int -wsmouse_rem_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; +wsmouse_mux_close(struct wsevsrc *me) +{ + struct wsmouse_softc *sc = (struct wsmouse_softc *)me; + + sc->sc_base.me_evp = NULL; + (*sc->sc_accessops->disable)(sc->sc_accesscookie); + + return (0); +} + +int +wsmouse_add_mux(int unit, struct wsmux_softc *muxsc) { struct wsmouse_softc *sc; @@ -679,7 +660,9 @@ wsmouse_rem_mux(unit, muxsc) (sc = wsmouse_cd.cd_devs[unit]) == NULL) return (ENXIO); - return (wsmux_detach_sc(muxsc, &sc->sc_dv)); -} + if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) + return (EBUSY); -#endif + return (wsmux_attach_sc(muxsc, &sc->sc_base)); +} +#endif /* NWSMUX > 0 */ diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c index 56118d9907f..ba2cd448657 100644 --- a/sys/dev/wscons/wsmux.c +++ b/sys/dev/wscons/wsmux.c @@ -1,8 +1,8 @@ -/* $OpenBSD: wsmux.c,v 1.12 2004/06/24 19:35:24 tholo Exp $ */ -/* $NetBSD: wsmux.c,v 1.9 2000/05/28 10:33:14 takemura Exp $ */ +/* $OpenBSD: wsmux.c,v 1.13 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */ /* - * Copyright (c) 1998 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 2005 The NetBSD Foundation, Inc. * All rights reserved. * * Author: Lennart Augustsson <augustss@carlstedt.se> @@ -41,8 +41,6 @@ #include "wsdisplay.h" #include "wskbd.h" -#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0) - /* * wscons mux device. * @@ -65,482 +63,332 @@ #include <sys/device.h> #include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsksymdef.h> #include <dev/wscons/wseventvar.h> #include <dev/wscons/wscons_callbacks.h> #include <dev/wscons/wsmuxvar.h> #ifdef WSMUX_DEBUG #define DPRINTF(x) if (wsmuxdebug) printf x +#define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x int wsmuxdebug = 0; #else #define DPRINTF(x) +#define DPRINTFN(n,x) #endif -struct wsplink { - LIST_ENTRY(wsplink) next; - int type; - struct wsmux_softc *mux; /* our mux device */ - /* The rest of the fields reflect a value in the multiplexee. */ - struct device *sc; /* softc */ - struct wseventvar *sc_mevents; /* event var */ - struct wsmux_softc **sc_muxp; /* pointer to us */ - struct wsmuxops *sc_ops; -}; +/* + * The wsmux pseudo device is used to multiplex events from several wsmouse, + * wskbd, and/or wsmux devices together. + * The devices connected together form a tree with muxes in the interior + * and real devices (mouse and kbd) at the leaves. The special case of + * a tree with one node (mux or other) is supported as well. + * Only the device at the root of the tree can be opened (if a non-root + * device is opened the subtree rooted at that point is severed from the + * containing tree). When the root is opened it allocates a wseventvar + * struct which all the nodes in the tree will send their events too. + * An ioctl() performed on the root is propagated to all the nodes. + * There are also ioctl() operations to add and remove nodes from a tree. + */ -int wsmuxdoclose(struct device *, int, int, struct proc *); -int wsmux_set_display(struct device *, struct wsmux_softc *); -int wsmux_isset_display(struct device *); +int wsmux_mux_open(struct wsevsrc *, struct wseventvar *); +int wsmux_mux_close(struct wsevsrc *); -#if NWSMUX > 0 -void wsmuxattach(int); +void wsmux_do_open(struct wsmux_softc *, struct wseventvar *); -struct wsmuxops wsmux_muxops = { - wsmuxopen, wsmuxdoclose, wsmuxdoioctl, wsmux_displayioctl, - wsmux_set_display, wsmux_isset_display +void wsmux_do_close(struct wsmux_softc *); +#if NWSDISPLAY > 0 +int wsmux_evsrc_set_display(struct device *, struct wsevsrc *); +#else +#define wsmux_evsrc_set_display NULL +#endif + +int wsmux_do_displayioctl(struct device *dev, u_long cmd, caddr_t data, + int flag, struct proc *p); +int wsmux_do_ioctl(struct device *, u_long, caddr_t,int,struct proc *); + +int wsmux_add_mux(int, struct wsmux_softc *); + +void wsmuxattach(int); + +struct wssrcops wsmux_srcops = { + WSMUX_MUX, + wsmux_mux_open, wsmux_mux_close, wsmux_do_ioctl, wsmux_do_displayioctl, + wsmux_evsrc_set_display }; -void wsmux_setmax(int n); +/* From upper level */ +void +wsmuxattach(int n) +{ +} +/* Keep track of all muxes that have been allocated */ int nwsmux = 0; struct wsmux_softc **wsmuxdevs = NULL; -void -wsmux_setmax(n) - int n; +/* Return mux n, create if necessary */ +struct wsmux_softc * +wsmux_getmux(int n) { + struct wsmux_softc *sc; + struct wsmux_softc **new, **old; int i; - struct wsmux_softc **wsmuxdevs_tmp = NULL; + /* Make sure there is room for mux n in the table */ if (n >= nwsmux) { - if (wsmuxdevs != NULL) { - wsmuxdevs_tmp = malloc(nwsmux * sizeof(*wsmuxdevs_tmp), - M_DEVBUF, M_NOWAIT); - if (wsmuxdevs_tmp == 0) - panic("wsmux_setmax: no mem"); - for (i = 0; i < nwsmux; i++) - wsmuxdevs_tmp[i] = wsmuxdevs[i]; - free(wsmuxdevs, M_DEVBUF); - } - - wsmuxdevs = malloc((n + 1) * sizeof(*wsmuxdevs), - M_DEVBUF, M_NOWAIT); - if (wsmuxdevs == NULL) - panic("wsmux_setmax: no memory"); - memset(wsmuxdevs, 0, (n + 1) * sizeof(*wsmuxdevs)); - if (wsmuxdevs_tmp != NULL) { - for (i = 0; i < nwsmux; i++) - wsmuxdevs[i] = wsmuxdevs_tmp[i]; - free(wsmuxdevs_tmp, M_DEVBUF); + old = wsmuxdevs; + new = (struct wsmux_softc **) + malloc((n + 1) * sizeof (*wsmuxdevs), M_DEVBUF, M_NOWAIT); + if (new == NULL) { + printf("wsmux_getmux: no memory for mux %d\n", n); + return (NULL); } + if (old != NULL) + bcopy(old, new, nwsmux * sizeof(*wsmuxdevs)); + for (i = nwsmux; i < (n + 1); i++) + new[i] = NULL; + wsmuxdevs = new; nwsmux = n + 1; + if (old != NULL) + free(old, M_DEVBUF); } -} -/* From upper level */ -void -wsmuxattach(n) - int n; -{ - int i; - - wsmux_setmax(n); /* Make sure we have room for all muxes. */ - - /* Make sure all muxes are there. */ - for (i = 0; i < nwsmux; i++) - if (wsmuxdevs[i] == NULL) - wsmuxdevs[i] = wsmux_create("wsmux", i); -} - -/* From mouse or keyboard. */ -void -wsmux_attach(n, type, dsc, ev, psp, ops) - int n; - int type; - struct device *dsc; - struct wseventvar *ev; - struct wsmux_softc **psp; - struct wsmuxops *ops; -{ - struct wsmux_softc *sc; - int error; - - DPRINTF(("wsmux_attach: n=%d\n", n)); - wsmux_setmax(n); sc = wsmuxdevs[n]; - if (sc == 0) { + if (sc == NULL) { sc = wsmux_create("wsmux", n); - if (sc == 0) { + if (sc == NULL) printf("wsmux: attach out of memory\n"); - return; - } wsmuxdevs[n] = sc; } - error = wsmux_attach_sc(sc, type, dsc, ev, psp, ops); - if (error) - printf("wsmux_attach: error=%d\n", error); -} - -/* From mouse or keyboard. */ -void -wsmux_detach(n, dsc) - int n; - struct device *dsc; -{ -#ifdef DIAGNOSTIC - int error; - - if (n >= nwsmux || n < 0) { - printf("wsmux_detach: detach is out of range\n"); - return; - } - if ((error = wsmux_detach_sc(wsmuxdevs[n], dsc))) - printf("wsmux_detach: error=%d\n", error); -#else - (void)wsmux_detach_sc(wsmuxdevs[n], dsc); -#endif + return (sc); } +/* + * open() of the pseudo device from device table. + */ int -wsmuxopen(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +wsmuxopen(dev_t dev, int flags, int mode, struct proc *p) { struct wsmux_softc *sc; - struct wsplink *m; - int unit, error, nopen, lasterror; + struct wseventvar *evar; + int unit; unit = minor(dev); - if (unit >= nwsmux || /* make sure it was attached */ - (sc = wsmuxdevs[unit]) == NULL) + sc = wsmux_getmux(unit); + if (sc == NULL) return (ENXIO); - DPRINTF(("wsmuxopen: %s: sc=%p\n", sc->sc_dv.dv_xname, sc)); - if (!(flags & FREAD)) { + DPRINTF(("wsmuxopen: %s: sc=%p p=%p\n", sc->sc_base.me_dv.dv_xname, sc, p)); + + if ((flags & (FREAD | FWRITE)) == FWRITE) { /* Not opening for read, only ioctl is available. */ return (0); } - if (sc->sc_events.io) + if (sc->sc_base.me_parent != NULL) { + /* Grab the mux out of the greedy hands of the parent mux. */ + DPRINTF(("wsmuxopen: detach\n")); + wsmux_detach_sc(&sc->sc_base); + } + + if (sc->sc_base.me_evp != NULL) + /* Already open. */ return (EBUSY); - sc->sc_events.io = p; - sc->sc_flags = flags; - sc->sc_mode = mode; - sc->sc_p = p; - wsevent_init(&sc->sc_events); /* may cause sleep */ - - nopen = 0; - lasterror = 0; - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - if (!m->sc_mevents->io && !*m->sc_muxp) { - DPRINTF(("wsmuxopen: %s: m=%p dev=%s\n", - sc->sc_dv.dv_xname, m, m->sc->dv_xname)); - error = m->sc_ops->dopen(makedev(0, m->sc->dv_unit), - flags, mode, p); - if (error) { - /* Ignore opens that fail */ - lasterror = error; - DPRINTF(("wsmuxopen: open failed %d\n", - error)); - } else { - nopen++; - *m->sc_muxp = sc; - } - } - } + evar = &sc->sc_base.me_evar; + wsevent_init(evar); + evar->io = p; +#ifdef WSDISPLAY_COMPAT_RAWKBD + sc->sc_rawkbd = 0; +#endif - if (nopen == 0 && lasterror != 0) { - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; - return (lasterror); - } + wsmux_do_open(sc, evar); return (0); } +/* + * Open of a mux via the parent mux. + */ int -wsmuxclose(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; -{ - return wsmuxdoclose(&wsmuxdevs[minor(dev)]->sc_dv, flags, mode, p); -} - -int -wsmuxread(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; +wsmux_mux_open(struct wsevsrc *me, struct wseventvar *evar) { - struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; + struct wsmux_softc *sc = (struct wsmux_softc *)me; - if (!sc->sc_events.io) - return (EACCES); +#ifdef DIAGNOSTIC + if (sc->sc_base.me_evp != NULL) { + printf("wsmux_mux_open: busy\n"); + return (EBUSY); + } + if (sc->sc_base.me_parent == NULL) { + printf("wsmux_mux_open: no parent\n"); + return (EINVAL); + } +#endif - return (wsevent_read(&sc->sc_events, uio, flags)); -} + wsmux_do_open(sc, evar); -int -wsmuxioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - return wsmuxdoioctl(&wsmuxdevs[minor(dev)]->sc_dv, cmd, data, flag, p); + return (0); } -int -wsmuxpoll(dev, events, p) - dev_t dev; - int events; - struct proc *p; +/* Common part of opening a mux. */ +void +wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar) { - struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; + struct wsevsrc *me; + int error; - if (!sc->sc_events.io) - return (EACCES); + sc->sc_base.me_evp = evar; /* remember event variable, mark as open */ - return (wsevent_poll(&sc->sc_events, events, p)); + /* Open all children. */ + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { + DPRINTF(("wsmuxopen: %s: m=%p dev=%s\n", + sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname)); +#ifdef DIAGNOSTIC + if (me->me_evp != NULL) { + printf("wsmuxopen: dev already in use\n"); + continue; + } + if (me->me_parent != sc) { + printf("wsmux_do_open: bad child=%p\n", me); + continue; + } + error = wsevsrc_open(me, evar); + if (error) { + DPRINTF(("wsmuxopen: open failed %d\n", error)); + } +#else + /* ignore errors, failing children will not be marked open */ + (void)wsevsrc_open(me, evar); +#endif + } } +/* + * close() of the pseudo device from device table. + */ int -wsmux_add_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; +wsmuxclose(dev_t dev, int flags, int mode, struct proc *p) { - struct wsmux_softc *sc, *m; - - if (unit < 0 || unit >= nwsmux || (sc = wsmuxdevs[unit]) == NULL) - return (ENXIO); - - DPRINTF(("wsmux_add_mux: %s to %s\n", sc->sc_dv.dv_xname, - muxsc->sc_dv.dv_xname)); - - if (sc->sc_mux || sc->sc_events.io) - return (EBUSY); + struct wsmux_softc *sc = + (struct wsmux_softc *)wsmuxdevs[minor(dev)]; + struct wseventvar *evar = sc->sc_base.me_evp; - /* The mux we are adding must not be an ancestor of it. */ - for (m = muxsc->sc_mux; m; m = m->sc_mux) - if (m == sc) - return (EINVAL); + if (evar == NULL) + /* Not open for read */ + return (0); - return (wsmux_attach_sc(muxsc, WSMUX_MUX, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wsmux_muxops)); + wsmux_do_close(sc); + sc->sc_base.me_evp = NULL; + wsevent_fini(evar); + return (0); } +/* + * Close of a mux via the parent mux. + */ int -wsmux_rem_mux(unit, muxsc) - int unit; - struct wsmux_softc *muxsc; +wsmux_mux_close(struct wsevsrc *me) { - struct wsmux_softc *sc; - - if (unit < 0 || unit >= nwsmux || (sc = wsmuxdevs[unit]) == NULL) - return (ENXIO); - - DPRINTF(("wsmux_rem_mux: %s from %s\n", sc->sc_dv.dv_xname, - muxsc->sc_dv.dv_xname)); - - return (wsmux_detach_sc(muxsc, &sc->sc_dv)); + me->me_evp = NULL; + wsmux_do_close((struct wsmux_softc *)me); + return (0); } -#endif /* NWSMUX > 0 */ - -struct wsmux_softc * -wsmux_create(name, unit) - const char *name; - int unit; +/* Common part of closing a mux. */ +void +wsmux_do_close(struct wsmux_softc *sc) { - struct wsmux_softc *sc; + struct wsevsrc *me; - DPRINTF(("wsmux_create: allocating\n")); - sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); - if (!sc) - return (0); - memset(sc, 0, sizeof *sc); - LIST_INIT(&sc->sc_reals); - snprintf(sc->sc_dv.dv_xname, sizeof sc->sc_dv.dv_xname, - "%s%d", name, unit); - sc->sc_dv.dv_unit = unit; - return (sc); -} - -int -wsmux_attach_sc(sc, type, dsc, ev, psp, ops) - struct wsmux_softc *sc; - int type; - struct device *dsc; - struct wseventvar *ev; - struct wsmux_softc **psp; - struct wsmuxops *ops; -{ - struct wsplink *m; - int error; + DPRINTF(("wsmuxclose: %s: sc=%p\n", sc->sc_base.me_dv.dv_xname, sc)); - DPRINTF(("wsmux_attach_sc: %s: type=%d dsc=%p, *psp=%p\n", - sc->sc_dv.dv_xname, type, dsc, *psp)); - m = malloc(sizeof *m, M_DEVBUF, M_NOWAIT); - if (m == 0) - return (ENOMEM); - m->type = type; - m->mux = sc; - m->sc = dsc; - m->sc_mevents = ev; - m->sc_muxp = psp; - m->sc_ops = ops; - LIST_INSERT_HEAD(&sc->sc_reals, m, next); - - if (sc->sc_displaydv) { - /* This is a display mux, so attach the new device to it. */ - DPRINTF(("wsmux_attach_sc: %s: set display %p\n", - sc->sc_dv.dv_xname, sc->sc_displaydv)); - error = 0; - if (m->sc_ops->dsetdisplay) { - error = m->sc_ops->dsetdisplay(m->sc, sc); - /* Ignore that the console already has a display. */ - if (error == EBUSY) - error = 0; - if (!error) { - *m->sc_muxp = sc; -#ifdef WSDISPLAY_COMPAT_RAWKBD - DPRINTF(("wsmux_attach_sc: on %s set rawkbd=%d\n", - m->sc->dv_xname, sc->sc_rawkbd)); - (void)m->sc_ops->dioctl(m->sc, - WSKBDIO_SETMODE, - (caddr_t)&sc->sc_rawkbd, - 0, 0); -#endif - } + /* Close all the children. */ + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { + DPRINTF(("wsmuxclose %s: m=%p dev=%s\n", + sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname)); +#ifdef DIAGNOSTIC + if (me->me_parent != sc) { + printf("wsmuxclose: bad child=%p\n", me); + continue; } - } else if (sc->sc_events.io) { - /* Mux is open, so open the new subdevice */ - DPRINTF(("wsmux_attach_sc: %s: calling open of %s\n", - sc->sc_dv.dv_xname, m->sc->dv_xname)); - /* mux already open, join in */ - error = m->sc_ops->dopen(makedev(0, m->sc->dv_unit), - sc->sc_flags, sc->sc_mode, sc->sc_p); - if (!error) - *m->sc_muxp = sc; - } else { - DPRINTF(("wsmux_attach_sc: %s not open\n", - sc->sc_dv.dv_xname)); - error = 0; +#endif + (void)wsevsrc_close(me); + me->me_evp = NULL; } - DPRINTF(("wsmux_attach_sc: done sc=%p psp=%p *psp=%p\n", - sc, psp, *psp)); - - return (error); } +/* + * read() of the pseudo device from device table. + */ int -wsmux_detach_sc(sc, dsc) - struct wsmux_softc *sc; - struct device *dsc; +wsmuxread(dev_t dev, struct uio *uio, int flags) { - struct wsplink *m; - int error = 0; - - DPRINTF(("wsmux_detach_sc: %s: dsc=%p\n", sc->sc_dv.dv_xname, dsc)); -#ifdef DIAGNOSTIC - if (sc == 0) { - printf("wsmux_detach_sc: not allocated\n"); - return (ENXIO); - } -#endif + struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; + struct wseventvar *evar; + int error; - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - if (m->sc == dsc) - break; - } + evar = sc->sc_base.me_evp; + if (evar == NULL) { #ifdef DIAGNOSTIC - if (!m) { - printf("wsmux_detach_sc: not found\n"); - return (ENXIO); - } + /* XXX can we get here? */ + printf("wsmuxread: not open\n"); #endif - if (sc->sc_displaydv || - (m->sc_ops->dissetdisplay && m->sc_ops->dissetdisplay(m->sc))) { - if (m->sc_ops->dsetdisplay) - error = m->sc_ops->dsetdisplay(m->sc, 0); - if (error) - return (error); - *m->sc_muxp = 0; - } else if (*m->sc_muxp) { - DPRINTF(("wsmux_detach_sc: close\n")); - /* mux device is open, so close multiplexee */ - m->sc_ops->dclose(m->sc, FREAD, 0, 0); - *m->sc_muxp = 0; + return (EINVAL); } - LIST_REMOVE(m, next); - - free(m, M_DEVBUF); - DPRINTF(("wsmux_detach_sc: done sc=%p\n", sc)); - return (0); + DPRINTFN(5,("wsmuxread: %s event read evar=%p\n", + sc->sc_base.me_dv.dv_xname, evar)); + error = wsevent_read(evar, uio, flags); + DPRINTFN(5,("wsmuxread: %s event read ==> error=%d\n", + sc->sc_base.me_dv.dv_xname, error)); + return (error); } -int wsmuxdoclose(dv, flags, mode, p) - struct device *dv; - int flags, mode; - struct proc *p; +/* + * ioctl of the pseudo device from device table. + */ +int +wsmuxioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - struct wsmux_softc *sc = (struct wsmux_softc *)dv; - struct wsplink *m; - - DPRINTF(("wsmuxclose: %s: sc=%p\n", sc->sc_dv.dv_xname, sc)); - if (!(flags & FREAD)) { - /* Nothing to do, because open didn't do anything. */ - return (0); - } - - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - if (*m->sc_muxp == sc) { - DPRINTF(("wsmuxclose %s: m=%p dev=%s\n", - sc->sc_dv.dv_xname, m, m->sc->dv_xname)); - m->sc_ops->dclose(m->sc, flags, mode, p); - *m->sc_muxp = 0; - } - } - - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; - - return (0); + return wsmux_do_ioctl(&wsmuxdevs[minor(dev)]->sc_base.me_dv, cmd, data, flag, p); } +/* + * ioctl of a mux via the parent mux, continuation of wsmuxioctl(). + */ int -wsmuxdoioctl(dv, cmd, data, flag, p) - struct device *dv; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, + struct proc *p) { struct wsmux_softc *sc = (struct wsmux_softc *)dv; - struct wsplink *m; + struct wsevsrc *me; int error, ok; int s, put, get, n; struct wseventvar *evar; struct wscons_event *ev; struct wsmux_device_list *l; - DPRINTF(("wsmuxdoioctl: %s: sc=%p, cmd=%08lx\n", - sc->sc_dv.dv_xname, sc, cmd)); + DPRINTF(("wsmux_do_ioctl: %s: enter sc=%p, cmd=%08lx\n", + sc->sc_base.me_dv.dv_xname, sc, cmd)); switch (cmd) { - case WSMUX_INJECTEVENT: + case WSMUXIO_INJECTEVENT: /* Inject an event, e.g., from moused. */ - if (!sc->sc_events.io) - return (EACCES); + DPRINTF(("%s: inject\n", sc->sc_base.me_dv.dv_xname)); + + evar = sc->sc_base.me_evp; + if (evar == NULL) { + /* No event sink, so ignore it. */ + DPRINTF(("wsmux_do_ioctl: event ignored\n")); + return (0); + } - evar = &sc->sc_events; s = spltty(); get = evar->get; put = evar->put; + ev = &evar->q[put]; if (++put % WSEVENT_QSIZE == get) { put--; splx(s); @@ -548,15 +396,16 @@ wsmuxdoioctl(dv, cmd, data, flag, p) } if (put >= WSEVENT_QSIZE) put = 0; - ev = &evar->q[put]; *ev = *(struct wscons_event *)data; nanotime(&ev->time); evar->put = put; WSEVENT_WAKEUP(evar); splx(s); return (0); - case WSMUX_ADD_DEVICE: + case WSMUXIO_ADD_DEVICE: #define d ((struct wsmux_device *)data) + DPRINTF(("%s: add type=%d, no=%d\n", sc->sc_base.me_dv.dv_xname, + d->type, d->idx)); switch (d->type) { #if NWSMOUSE > 0 case WSMUX_MOUSE: @@ -566,38 +415,35 @@ wsmuxdoioctl(dv, cmd, data, flag, p) case WSMUX_KBD: return (wskbd_add_mux(d->idx, sc)); #endif -#if NWSMUX > 0 case WSMUX_MUX: return (wsmux_add_mux(d->idx, sc)); -#endif default: return (EINVAL); } - case WSMUX_REMOVE_DEVICE: - switch (d->type) { -#if NWSMOUSE > 0 - case WSMUX_MOUSE: - return (wsmouse_rem_mux(d->idx, sc)); -#endif -#if NWSKBD > 0 - case WSMUX_KBD: - return (wskbd_rem_mux(d->idx, sc)); -#endif -#if NWSMUX > 0 - case WSMUX_MUX: - return (wsmux_rem_mux(d->idx, sc)); -#endif - default: - return (EINVAL); + case WSMUXIO_REMOVE_DEVICE: + DPRINTF(("%s: rem type=%d, no=%d\n", sc->sc_base.me_dv.dv_xname, + d->type, d->idx)); + /* Locate the device */ + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { + if (me->me_ops->type == d->type && + me->me_dv.dv_unit == d->idx) { + DPRINTF(("wsmux_do_ioctl: detach\n")); + wsmux_detach_sc(me); + return (0); + } } + return (EINVAL); #undef d - case WSMUX_LIST_DEVICES: + + case WSMUXIO_LIST_DEVICES: + DPRINTF(("%s: list\n", sc->sc_base.me_dv.dv_xname)); l = (struct wsmux_device_list *)data; - for (n = 0, m = LIST_FIRST(&sc->sc_reals); - n < WSMUX_MAXDEV && m != NULL; - m = LIST_NEXT(m, next)) { - l->devices[n].type = m->type; - l->devices[n].idx = m->sc->dv_unit; + n = 0; + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { + if (n >= WSMUX_MAXDEV) + break; + l->devices[n].type = me->me_ops->type; + l->devices[n].idx = me->me_dv.dv_unit; n++; } l->ndevices = n; @@ -605,79 +451,285 @@ wsmuxdoioctl(dv, cmd, data, flag, p) #ifdef WSDISPLAY_COMPAT_RAWKBD case WSKBDIO_SETMODE: sc->sc_rawkbd = *(int *)data; - DPRINTF(("wsmuxdoioctl: save rawkbd = %d\n", sc->sc_rawkbd)); + DPRINTF(("wsmux_do_ioctl: save rawkbd = %d\n", sc->sc_rawkbd)); break; #endif + case FIONBIO: + DPRINTF(("%s: FIONBIO\n", sc->sc_base.me_dv.dv_xname)); + return (0); + case FIOASYNC: - sc->sc_events.async = *(int *)data != 0; + DPRINTF(("%s: FIOASYNC\n", sc->sc_base.me_dv.dv_xname)); + evar = sc->sc_base.me_evp; + if (evar == NULL) + return (EINVAL); + evar->async = *(int *)data != 0; + return (0); + case FIOSETOWN: + DPRINTF(("%s: FIOSETOWN\n", sc->sc_base.me_dv.dv_xname)); + evar = sc->sc_base.me_evp; + if (evar == NULL) + return (EINVAL); + if (-*(int *)data != evar->io->p_pgid + && *(int *)data != evar->io->p_pid) + return (EPERM); return (0); case TIOCSPGRP: - if (*(int *)data != sc->sc_events.io->p_pgid) + DPRINTF(("%s: TIOCSPGRP\n", sc->sc_base.me_dv.dv_xname)); + evar = sc->sc_base.me_evp; + if (evar == NULL) + return (EINVAL); + if (*(int *)data != evar->io->p_pgid) return (EPERM); return (0); default: + DPRINTF(("%s: unknown\n", sc->sc_base.me_dv.dv_xname)); break; } - if (sc->sc_events.io == NULL && sc->sc_displaydv == NULL) + if (sc->sc_base.me_evp == NULL +#if NWSDISPLAY > 0 + && sc->sc_displaydv == NULL +#endif + ) return (EACCES); /* Return 0 if any of the ioctl() succeeds, otherwise the last error */ error = 0; ok = 0; - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - DPRINTF(("wsmuxdoioctl: m=%p *m->sc_muxp=%p sc=%p\n", - m, *m->sc_muxp, sc)); - if (*m->sc_muxp == sc) { - DPRINTF(("wsmuxdoioctl: %s: m=%p dev=%s\n", - sc->sc_dv.dv_xname, m, m->sc->dv_xname)); - error = m->sc_ops->dioctl(m->sc, cmd, data, flag, p); - if (!error) - ok = 1; + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { +#ifdef DIAGNOSTIC + /* XXX check evp? */ + if (me->me_parent != sc) { + printf("wsmux_do_ioctl: bad child %p\n", me); + continue; } +#endif + error = wsevsrc_ioctl(me, cmd, data, flag, p); + DPRINTF(("wsmux_do_ioctl: %s: me=%p dev=%s ==> %d\n", + sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname, + error)); + if (!error) + ok = 1; } - if (ok) + if (ok) { error = 0; + if (cmd == WSKBDIO_SETENCODING) { + sc->sc_kbd_layout = *((kbd_t *)data); + } + + } return (error); } +/* + * poll() of the pseudo device from device table. + */ +int +wsmuxpoll(dev_t dev, int events, struct proc *p) +{ + struct wsmux_softc *sc = wsmuxdevs[minor(dev)]; + + if (sc->sc_base.me_evp == NULL) { +#ifdef DIAGNOSTIC + printf("wsmuxpoll: not open\n"); +#endif + return (EACCES); + } + + return (wsevent_poll(sc->sc_base.me_evp, events, p)); +} + +/* + * Add mux unit as a child to muxsc. + */ +int +wsmux_add_mux(int unit, struct wsmux_softc *muxsc) +{ + struct wsmux_softc *sc, *m; + + sc = wsmux_getmux(unit); + if (sc == NULL) + return (ENXIO); + + DPRINTF(("wsmux_add_mux: %s(%p) to %s(%p)\n", + sc->sc_base.me_dv.dv_xname, sc, muxsc->sc_base.me_dv.dv_xname, + muxsc)); + + if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) + return (EBUSY); + + /* The mux we are adding must not be an ancestor of itself. */ + for (m = muxsc; m != NULL ; m = m->sc_base.me_parent) + if (m == sc) + return (EINVAL); + + return (wsmux_attach_sc(muxsc, &sc->sc_base)); +} + +/* Create a new mux softc. */ +struct wsmux_softc * +wsmux_create(const char *name, int unit) +{ + struct wsmux_softc *sc; + + DPRINTF(("wsmux_create: allocating\n")); + sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); + if (sc == NULL) + return (NULL); + bzero(sc, sizeof *sc); + CIRCLEQ_INIT(&sc->sc_cld); + snprintf(sc->sc_base.me_dv.dv_xname, sizeof sc->sc_base.me_dv.dv_xname, + "%s%d", name, unit); + sc->sc_base.me_dv.dv_unit = unit; + sc->sc_base.me_ops = &wsmux_srcops; + sc->sc_kbd_layout = KB_NONE; + return (sc); +} + +/* Attach me as a child to sc. */ int -wsmux_displayioctl(dv, cmd, data, flag, p) - struct device *dv; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; +wsmux_attach_sc(struct wsmux_softc *sc, struct wsevsrc *me) +{ + int error; + + if (sc == NULL) + return (EINVAL); + + DPRINTF(("wsmux_attach_sc: %s(%p): type=%d\n", + sc->sc_base.me_dv.dv_xname, sc, me->me_ops->type)); + +#ifdef DIAGNOSTIC + if (me->me_parent != NULL) { + printf("wsmux_attach_sc: busy\n"); + return (EBUSY); + } +#endif + me->me_parent = sc; + CIRCLEQ_INSERT_TAIL(&sc->sc_cld, me, me_next); + + error = 0; +#if NWSDISPLAY > 0 + if (sc->sc_displaydv != NULL) { + /* This is a display mux, so attach the new device to it. */ + DPRINTF(("wsmux_attach_sc: %s: set display %p\n", + sc->sc_base.me_dv.dv_xname, sc->sc_displaydv)); + if (me->me_ops->dsetdisplay != NULL) { + error = wsevsrc_set_display(me, &sc->sc_base); + /* Ignore that the console already has a display. */ + if (error == EBUSY) + error = 0; + if (!error) { +#ifdef WSDISPLAY_COMPAT_RAWKBD + DPRINTF(("wsmux_attach_sc: %s set rawkbd=%d\n", + me->me_dv.dv_xname, sc->sc_rawkbd)); + (void)wsevsrc_ioctl(me, WSKBDIO_SETMODE, + &sc->sc_rawkbd, 0, 0); +#endif + if (sc->sc_kbd_layout != KB_NONE) + (void)wsevsrc_ioctl(me, + WSKBDIO_SETENCODING, + &sc->sc_kbd_layout, FWRITE, 0); + } + } + } +#endif + if (sc->sc_base.me_evp != NULL) { + /* Mux is open, so open the new subdevice */ + DPRINTF(("wsmux_attach_sc: %s: calling open of %s\n", + sc->sc_base.me_dv.dv_xname, me->me_dv.dv_xname)); + error = wsevsrc_open(me, sc->sc_base.me_evp); + } else { + DPRINTF(("wsmux_attach_sc: %s not open\n", + sc->sc_base.me_dv.dv_xname)); + } + + if (error) { + me->me_parent = NULL; + CIRCLEQ_REMOVE(&sc->sc_cld, me, me_next); + } + + DPRINTF(("wsmux_attach_sc: %s(%p) done, error=%d\n", + sc->sc_base.me_dv.dv_xname, sc, error)); + return (error); +} + +/* Remove me from the parent. */ +void +wsmux_detach_sc(struct wsevsrc *me) +{ + struct wsmux_softc *sc = me->me_parent; + + DPRINTF(("wsmux_detach_sc: %s(%p) parent=%p\n", + me->me_dv.dv_xname, me, sc)); + +#ifdef DIAGNOSTIC + if (sc == NULL) { + printf("wsmux_detach_sc: %s has no parent\n", + me->me_dv.dv_xname); + return; + } +#endif + +#if NWSDISPLAY > 0 + if (sc->sc_displaydv != NULL) { + if (me->me_ops->dsetdisplay != NULL) + /* ignore error, there's nothing we can do */ + (void)wsevsrc_set_display(me, NULL); + } else +#endif + if (me->me_evp != NULL) { + DPRINTF(("wsmux_detach_sc: close\n")); + /* mux device is open, so close multiplexee */ + (void)wsevsrc_close(me); + } + + CIRCLEQ_REMOVE(&sc->sc_cld, me, me_next); + me->me_parent = NULL; + + DPRINTF(("wsmux_detach_sc: done sc=%p\n", sc)); +} + +/* + * Display ioctl() of a mux via the parent mux. + */ +int +wsmux_do_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, + struct proc *p) { struct wsmux_softc *sc = (struct wsmux_softc *)dv; - struct wsplink *m; + struct wsevsrc *me; int error, ok; - DPRINTF(("wsmux_displayioctl: %s: sc=%p, cmd=%08lx\n", - sc->sc_dv.dv_xname, sc, cmd)); + DPRINTF(("wsmux_displayioctl: %s: sc=%p, cmd=%08lx\n", + sc->sc_base.me_dv.dv_xname, sc, cmd)); #ifdef WSDISPLAY_COMPAT_RAWKBD if (cmd == WSKBDIO_SETMODE) { sc->sc_rawkbd = *(int *)data; DPRINTF(("wsmux_displayioctl: rawkbd = %d\n", sc->sc_rawkbd)); - } + } #endif - /* + /* * Return 0 if any of the ioctl() succeeds, otherwise the last error. * Return -1 if no mux component accepts the ioctl. */ error = -1; ok = 0; - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - DPRINTF(("wsmux_displayioctl: m=%p sc=%p sc_muxp=%p\n", - m, sc, *m->sc_muxp)); - if (m->sc_ops->ddispioctl && *m->sc_muxp == sc) { - error = m->sc_ops->ddispioctl(m->sc, cmd, data, - flag, p); - DPRINTF(("wsmux_displayioctl: m=%p dev=%s ==> %d\n", - m, m->sc->dv_xname, error)); + CIRCLEQ_FOREACH(me, &sc->sc_cld, me_next) { + DPRINTF(("wsmux_displayioctl: me=%p\n", me)); +#ifdef DIAGNOSTIC + if (me->me_parent != sc) { + printf("wsmux_displayioctl: bad child %p\n", me); + continue; + } +#endif + if (me->me_ops->ddispioctl != NULL) { + error = wsevsrc_display_ioctl(me, cmd, data, flag, p); + DPRINTF(("wsmux_displayioctl: me=%p dev=%s ==> %d\n", + me, me->me_dv.dv_xname, error)); if (!error) ok = 1; } @@ -688,54 +740,67 @@ wsmux_displayioctl(dv, cmd, data, flag, p) return (error); } +#if NWSDISPLAY > 0 +/* + * Set display of a mux via the parent mux. + */ int -wsmux_set_display(dv, muxsc) - struct device *dv; - struct wsmux_softc *muxsc; +wsmux_evsrc_set_display(struct device *dv, struct wsevsrc *ame) { + struct wsmux_softc *muxsc = (struct wsmux_softc *)ame; struct wsmux_softc *sc = (struct wsmux_softc *)dv; - struct wsmux_softc *nsc = muxsc ? sc : 0; - struct device *displaydv = muxsc ? muxsc->sc_displaydv : 0; - struct device *odisplaydv; - struct wsplink *m; - int error, ok; + struct device *displaydv = muxsc ? muxsc->sc_displaydv : NULL; DPRINTF(("wsmux_set_display: %s: displaydv=%p\n", - sc->sc_dv.dv_xname, displaydv)); + sc->sc_base.me_dv.dv_xname, displaydv)); - if (displaydv) { - if (sc->sc_displaydv) + if (displaydv != NULL) { + if (sc->sc_displaydv != NULL) return (EBUSY); } else { if (sc->sc_displaydv == NULL) return (ENXIO); } + return wsmux_set_display(sc, displaydv); +} + +int +wsmux_set_display(struct wsmux_softc *sc, struct device *displaydv) +{ + struct device *odisplaydv; + struct wsevsrc *me; + struct wsmux_softc *nsc = displaydv ? sc : NULL; + int error, ok; + odisplaydv = sc->sc_displaydv; sc->sc_displaydv = displaydv; - if (displaydv) - printf("%s: connecting to %s\n", - sc->sc_dv.dv_xname, displaydv->dv_xname); + if (displaydv) { + DPRINTF(("%s: connecting to %s\n", + sc->sc_base.me_dv.dv_xname, displaydv->dv_xname)); + } ok = 0; error = 0; - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - if (m->sc_ops->dsetdisplay && - (nsc ? m->sc_mevents->io == 0 && *m->sc_muxp == 0 : - *m->sc_muxp == sc)) { - error = m->sc_ops->dsetdisplay(m->sc, nsc); - DPRINTF(("wsmux_set_display: m=%p dev=%s error=%d\n", - m, m->sc->dv_xname, error)); + CIRCLEQ_FOREACH(me, &sc->sc_cld,me_next) { +#ifdef DIAGNOSTIC + if (me->me_parent != sc) { + printf("wsmux_set_display: bad child parent %p\n", me); + continue; + } +#endif + if (me->me_ops->dsetdisplay != NULL) { + error = wsevsrc_set_display(me, &nsc->sc_base); + DPRINTF(("wsmux_set_display: m=%p dev=%s error=%d\n", + me, me->me_dv.dv_xname, error)); if (!error) { ok = 1; - *m->sc_muxp = nsc; #ifdef WSDISPLAY_COMPAT_RAWKBD - DPRINTF(("wsmux_set_display: on %s set rawkbd=%d\n", - m->sc->dv_xname, sc->sc_rawkbd)); - (void)m->sc_ops->dioctl(m->sc, - WSKBDIO_SETMODE, - (caddr_t)&sc->sc_rawkbd, - 0, 0); + DPRINTF(("wsmux_set_display: %s set rawkbd=%d\n" +, + me->me_dv.dv_xname, sc->sc_rawkbd)); + (void)wsevsrc_ioctl(me, WSKBDIO_SETMODE, + &sc->sc_rawkbd, 0, 0); #endif } } @@ -743,23 +808,11 @@ wsmux_set_display(dv, muxsc) if (ok) error = 0; - if (displaydv == NULL) - printf("%s: disconnecting from %s\n", - sc->sc_dv.dv_xname, odisplaydv->dv_xname); + if (displaydv == NULL) { + DPRINTF(("%s: disconnecting from %s\n", + sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname)); + } return (error); } - -int -wsmux_isset_display(dv) - struct device *dv; -{ - struct wsmux_softc *sc = (struct wsmux_softc *)dv; - - if (sc->sc_displaydv != NULL) - return (1); - - return (0); -} - -#endif /* NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0) */ +#endif /* NWSDISPLAY > 0 */ diff --git a/sys/dev/wscons/wsmuxvar.h b/sys/dev/wscons/wsmuxvar.h index 56a783482e3..fc7c01e4535 100644 --- a/sys/dev/wscons/wsmuxvar.h +++ b/sys/dev/wscons/wsmuxvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: wsmuxvar.h,v 1.5 2002/03/14 01:27:03 millert Exp $ */ -/* $NetBSD: wsmuxvar.h,v 1.1 1999/07/29 18:20:43 augustss Exp $ */ +/* $OpenBSD: wsmuxvar.h,v 1.6 2005/05/15 11:29:15 miod Exp $ */ +/* $NetBSD: wsmuxvar.h,v 1.10 2005/04/30 03:47:12 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,62 +37,71 @@ * POSSIBILITY OF SUCH DAMAGE. */ -struct wsdisplay_softc; -struct wsplink; +/* + * A ws event source, i.e., wskbd, wsmouse, or wsmux. + */ +struct wsevsrc { + struct device me_dv; + const struct wssrcops *me_ops; /* method pointers */ + struct wseventvar me_evar; /* wseventvar opened directly */ + struct wseventvar *me_evp; /* our wseventvar when open */ +#if NWSDISPLAY > 0 + struct device *me_dispdv; /* our display if part of one */ +#define sc_displaydv sc_base.me_dispdv +#endif +#if NWSMUX > 0 + struct wsmux_softc *me_parent; /* parent mux device */ + CIRCLEQ_ENTRY(wsevsrc) me_next; /* sibling pointers */ +#endif +}; + +/* + * Methods that can be performed on an events source. Usually called + * from a wsmux. + */ +struct wssrcops { + int type; /* device type: WSMUX_{MOUSE,KBD,MUX} */ + int (*dopen)(struct wsevsrc *, struct wseventvar *); + int (*dclose)(struct wsevsrc *); + int (*dioctl)(struct device *, u_long, caddr_t, int, struct proc *); + int (*ddispioctl)(struct device *, u_long, caddr_t, int, struct proc *); + int (*dsetdisplay)(struct device *, struct wsevsrc *); +}; + +#define wsevsrc_open(me, evp) \ + ((me)->me_ops->dopen((me), evp)) +#define wsevsrc_close(me) \ + ((me)->me_ops->dclose((me))) +#define wsevsrc_ioctl(me, cmd, data, flag, p) \ + ((me)->me_ops->dioctl(&(me)->me_dv, cmd, (caddr_t)data, flag, p)) +#define wsevsrc_display_ioctl(me, cmd, data, flag, p) \ + ((me)->me_ops->ddispioctl(&(me)->me_dv, cmd, (caddr_t)data, flag, p)) +#define wsevsrc_set_display(me, arg) \ + ((me)->me_ops->dsetdisplay(&(me)->me_dv, arg)) +#if NWSMUX > 0 struct wsmux_softc { - struct device sc_dv; - struct wseventvar sc_events; /* event queue state */ - int sc_flags, sc_mode; /* open flags */ + struct wsevsrc sc_base; struct proc *sc_p; /* open proc */ - LIST_HEAD(, wsplink) sc_reals; /* list of real devices */ - struct wsmux_softc *sc_mux; /* if part of another mux */ - struct device *sc_displaydv; /* our display if part of one */ + CIRCLEQ_HEAD(, wsevsrc) sc_cld; /* list of children */ + u_int32_t sc_kbd_layout; /* current layout of keyboard */ #ifdef WSDISPLAY_COMPAT_RAWKBD - int sc_rawkbd; /* A hack to remember the kbd mode */ + int sc_rawkbd; /* A hack to remember the kbd mode */ #endif }; -struct wsmuxops { - int (*dopen)(dev_t, int, int, struct proc *); - int (*dclose)(struct device *, int, int, struct proc *); - int (*dioctl)(struct device *, u_long, caddr_t, int, - struct proc *); - int (*ddispioctl)(struct device *, u_long, caddr_t, int, - struct proc *); - int (*dsetdisplay)(struct device *, struct wsmux_softc *); - int (*dissetdisplay)(struct device *); -}; - - /* * configure defines */ -#define WSKBDDEVCF_MUX_DEFAULT -1 #define WSMOUSEDEVCF_MUX 0 -#define WSMOUSEDEVCF_MUX_DEFAULT -1 - -struct wsmux_softc *wsmux_create(const char *name, int no); -int wsmux_attach_sc( - struct wsmux_softc *, - int, struct device *, struct wseventvar *, - struct wsmux_softc **, - struct wsmuxops *); -int wsmux_detach_sc(struct wsmux_softc *, struct device *); -void wsmux_attach( - int, int, struct device *, struct wseventvar *, - struct wsmux_softc **, - struct wsmuxops *); -void wsmux_detach(int, struct device *); -int wsmux_displayioctl(struct device *dev, u_long cmd, - caddr_t data, int flag, struct proc *p); +struct wsmux_softc *wsmux_getmux(int); +struct wsmux_softc *wsmux_create(const char *, int); +int wsmux_attach_sc(struct wsmux_softc *, struct wsevsrc *); +void wsmux_detach_sc(struct wsevsrc *); +int wsmux_set_display(struct wsmux_softc *, struct device *); -int wsmuxdoioctl(struct device *, u_long, caddr_t,int,struct proc *); - -int wsmux_add_mux(int, struct wsmux_softc *); -int wsmux_rem_mux(int, struct wsmux_softc *); int wskbd_add_mux(int, struct wsmux_softc *); -int wskbd_rem_mux(int, struct wsmux_softc *); int wsmouse_add_mux(int, struct wsmux_softc *); -int wsmouse_rem_mux(int, struct wsmux_softc *); + +#endif /* NWSMUX > 0 */ |