diff --git a/sys/dev/wscons/files.wscons b/sys/dev/wscons/files.wscons index 432a2ea75714..46d14d086c3a 100644 --- a/sys/dev/wscons/files.wscons +++ b/sys/dev/wscons/files.wscons @@ -1,4 +1,4 @@ -# $NetBSD: files.wscons,v 1.22 2001/10/05 22:08:29 eeh Exp $ +# $NetBSD: files.wscons,v 1.23 2001/10/24 14:07:31 augustss Exp $ # # "Workstation Console" glue; attaches frame buffer to emulator & keyboard, @@ -40,7 +40,7 @@ file dev/wscons/wsemul_vt100.c wsdisplay & wsemul_vt100 file dev/wscons/wsemul_vt100_subr.c wsdisplay & wsemul_vt100 file dev/wscons/wsemul_vt100_chars.c wsdisplay & wsemul_vt100 file dev/wscons/wsemul_vt100_keys.c wsdisplay & wsemul_vt100 -file dev/wscons/wsevent.c wskbd | wsmouse +file dev/wscons/wsevent.c wskbd | wsmouse | wsmux file dev/wscons/wskbd.c wskbd needs-flag file dev/wscons/wskbdutil.c wskbd needs-flag file dev/wscons/wsmouse.c wsmouse needs-flag @@ -52,4 +52,4 @@ file dev/wscons/wscons_rinit.c wsrasteremulops file dev/wscons/wscons_rops.c wsrasteremulops defpseudo wsmux -file dev/wscons/wsmux.c wsmux | wsdisplay needs-flag +file dev/wscons/wsmux.c wsmux needs-flag diff --git a/sys/dev/wscons/wscons_callbacks.h b/sys/dev/wscons/wscons_callbacks.h index 2fea27c8cb41..10fd7b3f11f8 100644 --- a/sys/dev/wscons/wscons_callbacks.h +++ b/sys/dev/wscons/wscons_callbacks.h @@ -1,4 +1,4 @@ -/* $NetBSD: wscons_callbacks.h,v 1.14 2001/10/13 15:56:15 augustss Exp $ */ +/* $NetBSD: wscons_callbacks.h,v 1.15 2001/10/24 14:07:32 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -30,10 +30,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 *); +struct device *wsdisplay_set_console_kbd(struct wsevsrc *); /* * Calls to the display interface from the keyboard interface. @@ -57,6 +59,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 *); +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 de834c63e1fc..c2ea67b7dcb0 100644 --- a/sys/dev/wscons/wsconsio.h +++ b/sys/dev/wscons/wsconsio.h @@ -1,4 +1,4 @@ -/* $NetBSD: wsconsio.h,v 1.43 2001/10/02 21:03:05 mycroft Exp $ */ +/* $NetBSD: wsconsio.h,v 1.44 2001/10/24 14:07:32 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -40,7 +40,8 @@ * 0-31 keyboard ioctls (WSKBDIO) * 32-63 mouse ioctls (WSMOUSEIO) * 64-95 display ioctls (WSDISPLAYIO) - * 96-255 reserved for future use + * 96-f127 mux ioctls (WSMUXIO) + * 128-255 reserved for future use */ #include @@ -340,7 +341,7 @@ struct wsdisplay_usefontdata { }; #define WSDISPLAYIO_USEFONT _IOW('W', 80, struct wsdisplay_usefontdata) -/* Replaced by WSMUX_{ADD,REMOVE}_DEVICE */ +/* Obsolete, replaced by WSMUXIO_{ADD,REMOVE}_DEVICE */ struct wsdisplay_kbddata { int op; #define _O_WSDISPLAY_KBD_ADD 0 @@ -365,7 +366,8 @@ struct wsdisplay_param { /* Mapping information retrieval. */ /* Mux ioctls (96 - 127) */ -#define WSMUX_INJECTEVENT _IOW('W', 96, struct wscons_event) +#define WSMUXIO_INJECTEVENT _IOW('W', 96, struct wscons_event) +#define WSMUX_INJECTEVENT WSMUXIO_INJECTEVENT /* XXX compat */ struct wsmux_device { int type; @@ -374,14 +376,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 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 ec89540e00b8..0e40b1759a38 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp $ */ +/* $NetBSD: wsdisplay.c,v 1.56 2001/10/24 14:07:32 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -30,8 +30,14 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_wsdisplay_compat.h" +#include "opt_compat_netbsd.h" +#include "wskbd.h" +#include "wsmux.h" +#include "wsdisplay.h" + #include -__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.56 2001/10/24 14:07:32 augustss Exp $"); #include #include @@ -48,6 +54,8 @@ __KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp #include #include +#include +#include #include #include #include @@ -56,16 +64,6 @@ __KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp #include #include -#include "opt_wsdisplay_compat.h" -#include "opt_compat_netbsd.h" -#include "wskbd.h" -#include "wsmux.h" - -#if NWSKBD > 0 -#include -#include -#endif - struct wsscreen_internal { const struct wsdisplay_emulops *emulops; void *emulcookie; @@ -128,7 +126,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 @@ -562,23 +560,28 @@ wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, static int hookset; int i, start=0; #if NWSKBD > 0 - struct device *dv; - + struct wsevsrc *kme; #if NWSMUX > 0 + struct wsevsrc *inp; + if (kbdmux >= 0) - sc->sc_muxdv = wsmux_getmux(kbdmux); + inp = &wsmux_getmux(kbdmux)->sc_base; else -#endif - sc->sc_muxdv = wsmux_create("dmux", sc->sc_dv.dv_unit); + inp = &wsmux_create("dmux", sc->sc_dv.dv_unit)->sc_base; /* XXX panic()ing isn't nice, but attach cannot fail */ - if (!sc->sc_muxdv) + if (inp == NULL) panic("wsdisplay_common_attach: no memory\n"); - sc->sc_muxdv->sc_displaydv = &sc->sc_dv; + sc->sc_input = inp; + inp->me_dispdv = &sc->sc_dv; + printf(" kbdmux %d", kbdmux); +#else + if (kbdmux >= 0) + printf(" (kbdmux ignored)"); +#endif #endif sc->sc_isconsole = console; - printf(" kbdmux %d", kbdmux); if (console) { KASSERT(wsdisplay_console_initted); KASSERT(wsdisplay_console_device == NULL); @@ -591,8 +594,12 @@ wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux, 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; @@ -755,8 +762,8 @@ wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p) #ifdef WSDISPLAY_COMPAT_RAWKBD if (scr->scr_rawkbd) { int kbmode = WSKBD_TRANSLATED; - (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, - (caddr_t)&kbmode, 0, p); + (void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE, + (caddr_t)&kbmode, 0, p); } #endif @@ -908,6 +915,8 @@ wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, struct wsdisplay_font fd; #if NWSKBD > 0 + struct wsevsrc *inp; + #ifdef WSDISPLAY_COMPAT_RAWKBD switch (cmd) { case WSKBDIO_SETMODE: @@ -919,7 +928,8 @@ wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr, return (0); } #endif - error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag, p); + inp = sc->sc_input; + error = wsevsrc_display_ioctl(inp, cmd, data, flag, p); if (error >= 0) return (error); #endif /* NWSKBD > 0 */ @@ -987,6 +997,9 @@ wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, #if defined(COMPAT_14) && NWSKBD > 0 struct wsmux_device wsmuxdata; #endif +#if NWSKBD > 0 + struct wsevsrc *inp; +#endif switch (cmd) { case WSDISPLAYIO_ADDSCREEN: @@ -1056,31 +1069,30 @@ wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data, } wsmuxdata.type = WSMUX_KBD; wsmuxdata.idx = d->idx; - return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv, - WSMUX_ADD_DEVICE, - (caddr_t)&wsmuxdata, flag, p)); + return (wsevsrc_ioctl(sc->sc_input, WSMUX_ADD_DEVICE, + &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)); + return (wsevsrc_ioctl(sc->sc_input,WSMUX_REMOVE_DEVICE, + &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; + return (wsevsrc_ioctl(inp, cmd, data, flag, p)); #endif /* NWSKBD > 0 */ } @@ -1170,7 +1182,7 @@ wsdisplaystart(struct tty *tp) if (tp->t_outq.c_cc <= tp->t_lowat) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_outq); + wakeup(&tp->t_outq); } selwakeup(&tp->t_wsel); } @@ -1268,11 +1280,14 @@ wsdisplay_kbdinput(struct device *dev, keysym_t ks) } } -#ifdef WSDISPLAY_COMPAT_RAWKBD +#if defined(WSDISPLAY_COMPAT_RAWKBD) int 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); @@ -1284,12 +1299,15 @@ wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr) } 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; + 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 @@ -1638,12 +1656,17 @@ wsdisplay_kbdholdscreen(struct device *dev, int hold) #if NWSKBD > 0 struct device * -wsdisplay_set_console_kbd(struct device *kbddv) +wsdisplay_set_console_kbd(struct wsevsrc *kbd) { - if (!wsdisplay_console_device) - return (0); - if (wskbd_add_mux(kbddv->dv_unit, wsdisplay_console_device->sc_muxdv)) - return (0); + if (wsdisplay_console_device == NULL) + return (NULL); +#if NWSMUX > 0 + if (wskbd_add_mux(kbd->me_dv.dv_unit, + (struct wsmux_softc *)wsdisplay_console_device->sc_input)) + return (NULL); +#else + wsdisplay_console_device->sc_input = kbd; +#endif return (&wsdisplay_console_device->sc_dv); } #endif /* NWSKBD > 0 */ diff --git a/sys/dev/wscons/wsevent.c b/sys/dev/wscons/wsevent.c index cf667cc380c4..db7f56819c82 100644 --- a/sys/dev/wscons/wsevent.c +++ b/sys/dev/wscons/wsevent.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsevent.c,v 1.6 2001/10/13 15:56:16 augustss Exp $ */ +/* $NetBSD: wsevent.c,v 1.7 2001/10/24 14:07:32 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.6 2001/10/13 15:56:16 augustss Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.7 2001/10/24 14:07:32 augustss Exp $"); /* * Copyright (c) 1992, 1993 @@ -100,10 +100,16 @@ void wsevent_init(struct wseventvar *ev) { +#ifdef DIAGNOSTIC + if (ev->q != NULL) { + printf("wsevent_init: already init\n"); + return; + } +#endif 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)); + M_DEVBUF, M_WAITOK); + memset(ev->q, 0, WSEVENT_QSIZE * sizeof(struct wscons_event)); } /* @@ -114,6 +120,31 @@ wsevent_fini(struct wseventvar *ev) { free(ev->q, M_DEVBUF); + ev->q = NULL; +} + +/* + * Allocate a wseventvar. + */ +struct wseventvar * +wsevent_alloc(void) +{ + struct wseventvar *ev; + + ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK); + memset(ev, 0, sizeof *ev); + wsevent_init(ev); + return (ev); +} + +/* + * Deallocate a wseventvar. + */ +void +wsevent_free(struct wseventvar *ev) +{ + wsevent_fini(ev); + free(ev, M_DEVBUF); } /* @@ -137,7 +168,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int 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); @@ -156,7 +187,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) n = howmany(uio->uio_resid, sizeof(struct wscons_event)); if (cnt > n) cnt = n; - error = uiomove((caddr_t)&ev->q[ev->get], + error = uiomove(&ev->q[ev->get], cnt * sizeof(struct wscons_event), uio); n -= cnt; /* @@ -169,7 +200,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) return (error); if (cnt > n) cnt = n; - error = uiomove((caddr_t)&ev->q[0], + error = uiomove(&ev->q[0], cnt * sizeof(struct wscons_event), uio); ev->get = cnt; return (error); diff --git a/sys/dev/wscons/wseventvar.h b/sys/dev/wscons/wseventvar.h index f2c5c21d5a54..ba6284a0b9cf 100644 --- a/sys/dev/wscons/wseventvar.h +++ b/sys/dev/wscons/wseventvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wseventvar.h,v 1.2 2001/10/13 15:56:16 augustss Exp $ */ +/* $NetBSD: wseventvar.h,v 1.3 2001/10/24 14:07:33 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -99,14 +99,16 @@ struct wseventvar { selwakeup(&(ev)->sel); \ if ((ev)->wanted) { \ (ev)->wanted = 0; \ - wakeup((caddr_t)(ev)); \ + wakeup((ev)); \ } \ if ((ev)->async) \ psignal((ev)->io, SIGIO); \ } void wsevent_init(struct wseventvar *); +struct wseventvar *wsevent_alloc(void); void wsevent_fini(struct wseventvar *); +void wsevent_free(struct wseventvar *); int wsevent_read(struct wseventvar *, struct uio *, int); int wsevent_poll(struct wseventvar *, int, struct proc *); diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c index 655c63bc3f39..73d5f4bb6fd5 100644 --- a/sys/dev/wscons/wskbd.c +++ b/sys/dev/wscons/wskbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $ */ +/* $NetBSD: wskbd.c,v 1.48 2001/10/24 14:07:33 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.48 2001/10/24 14:07:33 augustss Exp $"); /* * Copyright (c) 1992, 1993 @@ -87,6 +87,11 @@ __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" +#include "opt_wsdisplay_compat.h" + +#include "wsdisplay.h" +#include "wskbd.h" +#include "wsmux.h" #include #include @@ -111,11 +116,6 @@ __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $"); #include #include -#include "opt_wsdisplay_compat.h" - -#include "wsdisplay.h" -#include "wsmux.h" - #ifdef KGDB #include #endif @@ -127,9 +127,7 @@ int wskbddebug = 0; #define DPRINTF(x) #endif -#if NWSMUX > 0 || NWSDISPLAY > 0 #include -#endif struct wskbd_internal { const struct wskbd_mapdata *t_keymap; @@ -151,7 +149,7 @@ struct wskbd_internal { }; struct wskbd_softc { - struct device sc_dv; + struct wsevsrc sc_base; struct wskbd_internal *id; @@ -160,13 +158,7 @@ struct wskbd_softc { int sc_ledstate; - int sc_ready; /* accepting events */ - 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; @@ -182,10 +174,6 @@ struct wskbd_softc { int sc_refcnt; u_char sc_dying; /* device is being detached */ - -#if NWSMUX > 0 || NWSDISPLAY > 0 - struct wsmux_softc *sc_mux; -#endif }; #define MOD_SHIFT_L (1 << 0) @@ -211,14 +199,18 @@ struct wskbd_softc { #define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0) #define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask)) -int wskbd_match(struct device *, struct cfdata *, void *); -void wskbd_attach(struct device *, struct device *, void *); -int wskbd_detach(struct device *, int); -int wskbd_activate(struct device *, enum devact); +static int wskbd_match(struct device *, struct cfdata *, void *); +static void wskbd_attach(struct device *, struct device *, void *); +static int wskbd_detach(struct device *, int); +static int wskbd_activate(struct device *, enum devact); -static int wskbd_displayioctl - (struct device *, u_long, caddr_t, int, struct proc *p); -int wskbd_set_display(struct device *, struct wsmux_softc *); +static int wskbd_displayioctl(struct device *, u_long, caddr_t, int, + struct proc *); +#if NWSDISPLAY > 0 +static int wskbd_set_display(struct device *, struct wsevsrc *); +#else +#define wskbd_set_display NULL +#endif static inline void update_leds(struct wskbd_internal *); static inline void update_modifier(struct wskbd_internal *, u_int, int, int); @@ -230,10 +222,19 @@ static void change_displayparam(struct wskbd_softc *, int, int, int); static void wskbd_holdscreen(struct wskbd_softc *, int); #endif -int wskbd_do_ioctl(struct wskbd_softc *, u_long, caddr_t, int,struct proc*); +static int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, + struct proc *); -int wskbddoclose(struct device *, int, int, struct proc *); -int wskbddoioctl(struct device *, u_long, caddr_t, int, struct proc *); +#if NWSMUX > 0 +static int wskbd_mux_open(struct wsevsrc *, struct wseventvar *); +static int wskbd_mux_close(struct wsevsrc *); +#else +#define wskbd_mux_open NULL +#define wskbd_mux_close NULL +#endif + +static int wskbd_do_open(struct wskbd_softc *, struct wseventvar *); +static int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *); struct cfattach wskbd_ca = { sizeof (struct wskbd_softc), wskbd_match, wskbd_attach, @@ -274,10 +275,11 @@ struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = { cdev_decl(wskbd); -#if NWSMUX > 0 || NWSDISPLAY > 0 -struct wsmuxops wskbd_muxops = { - wskbdopen, wskbddoclose, wskbddoioctl, wskbd_displayioctl, - wskbd_set_display +#if NWSDISPLAY > 0 || NWSMUX > 0 +struct wssrcops wskbd_srcops = { + WSMUX_KBD, + wskbd_mux_open, wskbd_mux_close, wskbd_do_ioctl, + wskbd_displayioctl, wskbd_set_display }; #endif @@ -345,23 +347,26 @@ 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 (sc->sc_isconsole && mux >= 0) { + /* printf(" (mux %d ignored for console)", mux); */ + mux = -1; } - if (mux != WSKBDDEVCF_MUX_DEFAULT) + if (mux >= 0) printf(" mux %d", mux); +#else + if (sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux >= 0) + printf(" (mux ignored)"); #endif if (ap->console) { @@ -380,7 +385,6 @@ wskbd_attach(struct device *parent, struct device *self, void *aux) sc->sc_accessops = ap->accessops; sc->sc_accesscookie = ap->accesscookie; - sc->sc_ready = 0; /* sanity */ sc->sc_repeating = 0; sc->sc_translating = 1; sc->sc_ledstate = -1; /* force update */ @@ -404,18 +408,21 @@ wskbd_attach(struct device *parent, struct device *self, void *aux) printf(": console keyboard"); #if NWSDISPLAY > 0 - if ((sc->sc_displaydv = wsdisplay_set_console_kbd(self))) - printf(", using %s", sc->sc_displaydv->dv_xname); + sc->sc_base.me_dispdv = wsdisplay_set_console_kbd(&sc->sc_base); + if (sc->sc_base.me_dispdv != NULL) + printf(", using %s", sc->sc_base.me_dispdv->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); + if (mux != WSKBDDEVCF_MUX_DEFAULT) { + 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 @@ -469,10 +476,10 @@ wskbd_repeat(void *v) splx(s); return; } - if (sc->sc_displaydv != NULL) { + if (sc->sc_base.me_dispdv != NULL) { int i; for (i = 0; i < sc->sc_repeating; i++) - wsdisplay_kbdinput(sc->sc_displaydv, + wsdisplay_kbdinput(sc->sc_base.me_dispdv, sc->id->t_symbols[i]); } callout_reset(&sc->sc_repeat_ch, @@ -484,7 +491,10 @@ wskbd_repeat(void *v) int 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); } @@ -503,16 +513,15 @@ wskbd_detach(struct device *self, int flags) struct wseventvar *evar; int maj, mn; int s; -#if NWSMUX > 0 - int mux; - mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux; - if (mux != WSMOUSEDEVCF_MUX_DEFAULT) - wsmux_detach(mux, &sc->sc_dv); +#if NWSMUX > 0 + /* Tell parent mux we're leaving. */ + if (sc->sc_base.me_parent != NULL) + wsmux_detach_sc(&sc->sc_base); #endif - 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. */ @@ -522,7 +531,7 @@ wskbd_detach(struct device *self, int 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); } @@ -545,7 +554,7 @@ 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; - struct timeval xxxtime; + struct timeval thistime; #if NWSDISPLAY > 0 int num, i; #endif @@ -564,9 +573,10 @@ wskbd_input(struct device *dev, u_int type, int value) if (sc->sc_translating) { num = wskbd_translate(sc->id, type, value); if (num > 0) { - if (sc->sc_displaydv != NULL) { + if (sc->sc_base.me_dispdv != NULL) { for (i = 0; i < num; i++) - wsdisplay_kbdinput(sc->sc_displaydv, + wsdisplay_kbdinput( + sc->sc_base.me_dispdv, sc->id->t_symbols[i]); } @@ -585,29 +595,24 @@ wskbd_input(struct device *dev, u_int type, int value) * keystroke is lost (sorry!). */ - /* no one to receive; punt!*/ - if (!sc->sc_ready) + 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 -#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; ev->value = value; - microtime(&xxxtime); - TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time); + microtime(&thistime); + TIMEVAL_TO_TIMESPEC(&thistime, &ev->time); evar->put = put; WSEVENT_WAKEUP(evar); } @@ -620,9 +625,9 @@ wskbd_rawinput(struct device *dev, u_char *buf, int len) struct wskbd_softc *sc = (struct wskbd_softc *)dev; int i; - if (sc->sc_displaydv != NULL) + if (sc->sc_base.me_dispdv != NULL) for (i = 0; i < len; i++) - wsdisplay_kbdinput(sc->sc_displaydv, buf[i]); + wsdisplay_kbdinput(sc->sc_base.me_dispdv, buf[i]); /* this is KS_GROUP_Ascii */ #endif } @@ -634,8 +639,8 @@ 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; @@ -653,56 +658,90 @@ wskbd_holdscreen(struct wskbd_softc *sc, int hold) static int wskbd_enable(struct wskbd_softc *sc, int on) { - int res; + int error; - /* XXX reference count? */ +#if 0 +/* I don't understand the purpose of this code. And it seems to + * break things, so it's out. -- Lennart + */ if (!on && (!sc->sc_translating #if NWSDISPLAY > 0 - || sc->sc_displaydv + || sc->sc_base.me_dispdv #endif )) return (EBUSY); +#endif - res = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); - return (res); + 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_base.me_evp != NULL) + return (EBUSY); + + return wskbd_do_open(sc, evp); +} +#endif + int 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) { + if (sc->sc_base.me_parent != NULL) /* Grab the keyboard out of the greedy hands of the mux. */ - int error = wskbd_rem_mux(unit, sc->sc_mux); - if (error) - return (error); - } + 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 */ + evar = wsevent_alloc(); + sc->sc_base.me_evp = evar; + evar->io = p; + 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_free(evar); + } + return (error); +} + +int +wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp) +{ + sc->sc_base.me_evp = evp; sc->sc_translating = 0; - sc->sc_ready = 1; /* start accepting events */ wskbd_enable(sc, 1); return (0); @@ -711,29 +750,36 @@ wskbdopen(dev_t dev, int flags, int mode, struct proc *p) int wskbdclose(dev_t dev, int flags, int mode, struct proc *p) { - return (wskbddoclose(wskbd_cd.cd_devs[minor(dev)], flags, mode, p)); -} + struct wskbd_softc *sc = + (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)]; + struct wseventvar *evar = sc->sc_base.me_evp; -int -wskbddoclose(struct device *dv, int flags, int mode, struct proc *p) -{ - struct wskbd_softc *sc = (struct wskbd_softc *)dv; - - if (!(flags & FREAD)) { - /* Nothing to do, because open didn't do anything. */ + if (evar == NULL) + /* not open for read */ return (0); - } - sc->sc_ready = 0; /* stop accepting events */ + sc->sc_base.me_evp = NULL; sc->sc_translating = 1; - - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; - wskbd_enable(sc, 0); + wsevent_free(evar); + return (0); } +#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; + wskbd_enable(sc, 0); + + return (0); +} +#endif + int wskbdread(dev_t dev, struct uio *uio, int flags) { @@ -743,8 +789,15 @@ wskbdread(dev_t dev, struct uio *uio, int 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_evp, uio, flags); if (--sc->sc_refcnt < 0) { wakeup(sc); error = EIO; @@ -755,27 +808,27 @@ wskbdread(dev_t dev, struct uio *uio, int flags) int 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(struct device *dv, u_long cmd, caddr_t data, int flag, +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(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; @@ -787,11 +840,15 @@ wskbd_do_ioctl(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, 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 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); } @@ -800,7 +857,7 @@ wskbd_do_ioctl(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, * 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); } @@ -1005,7 +1062,9 @@ 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 @@ -1019,99 +1078,86 @@ wskbd_pickfree(void) for (i = 0; i < wskbd_cd.cd_ndevs; i++) { if ((sc = wskbd_cd.cd_devs[i]) == NULL) continue; - if (sc->sc_displaydv == NULL) + if (sc->sc_base.me_dispdv == NULL) return (i); } return (-1); } -struct device * -wskbd_set_console_display(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(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 disp=%p odisp=%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 = displaydv; error = wskbd_enable(sc, displaydv != NULL); 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); } +#endif /* NWSDISPLAY > 0 */ + +#if NWSMUX > 0 int 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)); + return (wsmux_attach_sc(muxsc, &sc->sc_base)); } - -int -wskbd_rem_mux(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)); -} - -#endif /* NWSDISPLAY > 0 */ +#endif /* * Console interface. @@ -1219,11 +1265,11 @@ change_displayparam(struct wskbd_softc *sc, int param, int updown, int res; struct wsdisplay_param dp; - if (sc->sc_displaydv == NULL) + if (sc->sc_base.me_dispdv == 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 */ @@ -1234,7 +1280,7 @@ change_displayparam(struct wskbd_softc *sc, int param, int updown, 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 @@ -1289,13 +1335,13 @@ internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, case KS_Cmd_Screen7: case KS_Cmd_Screen8: case KS_Cmd_Screen9: - wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0); + wsdisplay_switch(sc->sc_base.me_dispdv, ksym - KS_Cmd_Screen0, 0); return (1); case KS_Cmd_ResetEmul: - wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); + wsdisplay_reset(sc->sc_base.me_dispdv, WSDISPLAY_RESETEMUL); return (1); case KS_Cmd_ResetClose: - wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); + wsdisplay_reset(sc->sc_base.me_dispdv, WSDISPLAY_RESETCLOSE); return (1); case KS_Cmd_BacklightOn: case KS_Cmd_BacklightOff: diff --git a/sys/dev/wscons/wsmouse.c b/sys/dev/wscons/wsmouse.c index e83b2122d4a4..3948b8530c00 100644 --- a/sys/dev/wscons/wsmouse.c +++ b/sys/dev/wscons/wsmouse.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $ */ +/* $NetBSD: wsmouse.c,v 1.17 2001/10/24 14:07:33 augustss Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.17 2001/10/24 14:07:33 augustss Exp $"); /* * Copyright (c) 1992, 1993 @@ -81,6 +81,10 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $" * Mouse driver. */ +#include "wsmouse.h" +#include "wsdisplay.h" +#include "wsmux.h" + #include #include #include @@ -97,14 +101,15 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $" #include #include #include - -#include "wsmouse.h" -#include "wsmux.h" -#include "wsdisplay.h" -#include "wskbd.h" - -#if NWSMUX > 0 #include + +#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 @@ -112,14 +117,11 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $" #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 */ @@ -131,22 +133,24 @@ 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 *, struct cfdata *, void *); -void wsmouse_attach(struct device *, struct device *, void *); -int wsmouse_detach(struct device *, int); -int wsmouse_activate(struct device *, enum devact); +static int wsmouse_match(struct device *, struct cfdata *, void *); +static void wsmouse_attach(struct device *, struct device *, void *); +static int wsmouse_detach(struct device *, int); +static int wsmouse_activate(struct device *, enum devact); -int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t, - int, struct proc *); +static int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t, + int, struct proc *); -int wsmousedoclose(struct device *, int, int, struct proc *); -int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *); +#if NWSMUX > 0 +static int wsmouse_mux_open(struct wsevsrc *, struct wseventvar *); +static int wsmouse_mux_close(struct wsevsrc *); +#endif + +static int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *); + +static int wsmousedoopen(struct wsmouse_softc *, struct wseventvar *); struct cfattach wsmouse_ca = { sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach, @@ -160,8 +164,9 @@ extern struct cfdriver wsmouse_cd; cdev_decl(wsmouse); #if NWSMUX > 0 -struct wsmuxops wsmouse_muxops = { - wsmouseopen, wsmousedoclose, wsmousedoioctl, 0, 0 +struct wssrcops wsmouse_srcops = { + WSMUX_MOUSE, + wsmouse_mux_open, wsmouse_mux_close, wsmousedoioctl, NULL, NULL }; #endif @@ -189,20 +194,25 @@ wsmouse_attach(struct device *parent, struct device *self, void *aux) 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 (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux >= 0) + printf(" (mux ignored)"); #endif printf("\n"); @@ -211,7 +221,10 @@ wsmouse_attach(struct device *parent, struct device *self, void *aux) int 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); } @@ -230,20 +243,16 @@ wsmouse_detach(struct device *self, int flags) 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) + 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. */ @@ -253,7 +262,7 @@ wsmouse_detach(struct device *self, int 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); } @@ -280,17 +289,16 @@ wsmouse_input(struct device *wsmousedev, u_int btns /* 0 is up */, int mb, ub, d, get, put, any; /* - * Discard input if not ready. + * Discard input if not open. */ - if (sc->sc_ready == 0) + evar = sc->sc_base.me_evp; + if (evar == NULL) return; #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)) @@ -423,8 +431,8 @@ out: int 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); @@ -432,6 +440,11 @@ wsmouseopen(dev_t dev, int flags, int mode, struct proc *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); @@ -440,103 +453,89 @@ wsmouseopen(dev_t dev, int flags, int mode, struct proc *p) so ioctl() is possible. */ #if NWSMUX > 0 - if (sc->sc_mux != NULL) { + if (sc->sc_base.me_parent != NULL) /* Grab the mouse out of the greedy hands of the mux. */ - error = wsmouse_rem_mux(unit, sc->sc_mux); - if (error) - return (error); - } + 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 */ + evar = wsevent_alloc(); + sc->sc_base.me_evp = evar; + evar->io = p; - sc->sc_ready = 1; /* start accepting events */ - sc->sc_x = INVALID_X; - sc->sc_y = INVALID_Y; - sc->sc_z = INVALID_Z; - - /* 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_free(evar); } - - return (0); -#else - return (ENXIO); -#endif /* NWSMOUSE > 0 */ + return (error); } int 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 */ -} - -#if NWSMOUSE > 0 -int -wsmousedoclose(struct device *dv, int flags, int mode, struct proc *p) -{ - struct wsmouse_softc *sc = (struct wsmouse_softc *)dv; - - if ((flags & (FREAD | FWRITE)) == FWRITE) - return (0); /* see wsmouseopen() */ + 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_free(evar); - sc->sc_ready = 0; /* stop accepting events */ - wsevent_fini(&sc->sc_events); - sc->sc_events.io = NULL; return (0); } -#endif /* NWSMOUSE > 0 */ + +int +wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp) +{ + sc->sc_base.me_evp = evp; + sc->sc_x = INVALID_X; + sc->sc_y = INVALID_Y; + sc->sc_z = INVALID_Z; + + /* enable the device, and punt if that's not possible */ + return (*sc->sc_accessops->enable)(sc->sc_accesscookie); +} int 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_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 */ } -#if NWSMOUSE > 0 /* A wrapper around the ioctl() workhorse to make reference counting easy. */ int wsmousedoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, @@ -569,11 +568,15 @@ wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, 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 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); } @@ -586,21 +589,40 @@ wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, data, flag, p); return (error != -1 ? error : ENOTTY); } -#endif /* NWSMOUSE > 0 */ int 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_mux_open(struct wsevsrc *me, struct wseventvar *evp) +{ + struct wsmouse_softc *sc = (struct wsmouse_softc *)me; + + if (sc->sc_base.me_evp != NULL) + return (EBUSY); + + return wsmousedoopen(sc, evp); +} + +int +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) { @@ -610,23 +632,9 @@ wsmouse_add_mux(int unit, struct wsmux_softc *muxsc) (sc = wsmouse_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_MOUSE, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wsmouse_muxops)); + return (wsmux_attach_sc(muxsc, &sc->sc_base)); } - -int -wsmouse_rem_mux(int unit, struct wsmux_softc *muxsc) -{ - struct wsmouse_softc *sc; - - if (unit < 0 || unit >= wsmouse_cd.cd_ndevs || - (sc = wsmouse_cd.cd_devs[unit]) == NULL) - return (ENXIO); - - return (wsmux_detach_sc(muxsc, &sc->sc_dv)); -} - -#endif +#endif /* NWSMUX > 0 */ diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c index 0f9f13c87688..3d42648b681f 100644 --- a/sys/dev/wscons/wsmux.c +++ b/sys/dev/wscons/wsmux.c @@ -1,4 +1,9 @@ -/* $NetBSD: wsmux.c,v 1.13 2001/10/21 23:04:57 jmc Exp $ */ +/* + TODO: + use method to get sc of muxee, common code for add&rem + */ + +/* $NetBSD: wsmux.c,v 1.14 2001/10/24 14:07:33 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -36,13 +41,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "wsmux.h" -#include "wsdisplay.h" -#include "wskbd.h" -#include "wsmouse.h" - -#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0) - /* * wscons mux device. * @@ -50,6 +48,11 @@ * a merge point for all the events from the different real devices. */ +#include "wsdisplay.h" +#include "wsmux.h" +#include "wskbd.h" +#include "wsmouse.h" + #include #include #include @@ -78,448 +81,326 @@ int wsmuxdebug = 0; #define DPRINTF(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 *); +static int wsmux_mux_open(struct wsevsrc *, struct wseventvar *); +static int wsmux_mux_close(struct wsevsrc *); -#if NWSMUX > 0 +static void wsmux_do_open(struct wsmux_softc *, struct wseventvar *); + +static void wsmux_do_close(struct wsmux_softc *); +#if NWSDISPLAY > 0 +static int wsmux_set_display(struct device *, struct wsevsrc *); +#else +#define wsmux_set_display NULL +#endif + +static int wsmux_do_displayioctl(struct device *dev, u_long cmd, + caddr_t data, int flag, struct proc *p); +static int wsmux_do_ioctl(struct device *, u_long, caddr_t,int,struct proc *); + +static int wsmux_add_mux(int, struct wsmux_softc *); + +void wsmuxattach(int); #define WSMUXDEV(n) ((n) & 0x7f) #define WSMUXCTL(n) ((n) & 0x80) cdev_decl(wsmux); -void wsmuxattach(int); - -struct wsmuxops wsmux_muxops = { - wsmuxopen, wsmuxdoclose, wsmuxdoioctl, wsmux_displayioctl, +struct wssrcops wsmux_srcops = { + WSMUX_MUX, + wsmux_mux_open, wsmux_mux_close, wsmux_do_ioctl, wsmux_do_displayioctl, wsmux_set_display }; -void wsmux_setmax(int n); - -int nwsmux = 0; -struct wsmux_softc **wsmuxdevs; - -void -wsmux_setmax(int n) -{ - int i; - - if (n >= nwsmux) { - i = nwsmux; - nwsmux = n + 1; - if (i != 0) - wsmuxdevs = realloc(wsmuxdevs, - nwsmux * sizeof (*wsmuxdevs), - M_DEVBUF, M_NOWAIT); - else - wsmuxdevs = malloc(nwsmux * sizeof (*wsmuxdevs), - M_DEVBUF, M_NOWAIT); - if (wsmuxdevs == NULL) - panic("wsmux_setmax: no memory\n"); - for (; i < nwsmux; i++) - wsmuxdevs[i] = 0; - } -} - /* From upper level */ void wsmuxattach(int n) { } +/* Keep track of all muxes that have been allocated */ +static int nwsmux = 0; +static struct wsmux_softc **wsmuxdevs; + /* Return mux n, create if necessary */ struct wsmux_softc * wsmux_getmux(int n) { struct wsmux_softc *sc; + int i; + void *new; - wsmux_setmax(n); - sc = wsmuxdevs[n]; - if (sc == 0) { - sc = wsmux_create("wsmux", n); - if (sc == 0) { - printf("wsmux: attach out of memory\n"); + n = WSMUXDEV(n); /* limit range */ + + /* Make sure there is room for mux n in the table */ + if (n >= nwsmux) { + i = nwsmux; + nwsmux = n + 1; + if (i != 0) + new = realloc(wsmuxdevs, nwsmux * sizeof (*wsmuxdevs), + M_DEVBUF, M_NOWAIT); + else + new = malloc(nwsmux * sizeof (*wsmuxdevs), + M_DEVBUF, M_NOWAIT); + if (new == NULL) { + printf("wsmux_getmux: no memory for mux %d\n", n); return (NULL); } + wsmuxdevs = new; + for (; i < nwsmux; i++) + wsmuxdevs[i] = NULL; + } + + sc = wsmuxdevs[n]; + if (sc == NULL) { + sc = wsmux_create("wsmux", n); + if (sc == NULL) + printf("wsmux: attach out of memory\n"); wsmuxdevs[n] = sc; } return (sc); } -/* From mouse or keyboard. */ -void -wsmux_attach(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)); - sc = wsmux_getmux(n); - 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(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 -} - +/* + * open() of the pseudo device from device table. + */ int wsmuxopen(dev_t dev, int flags, int mode, struct proc *p) { struct wsmux_softc *sc; - struct wsplink *m; - int munit, unit, error, nopen, lasterror; + struct wseventvar *evar; + int minr, unit; - munit = minor(dev); - unit = WSMUXDEV(munit); + minr = minor(dev); + unit = WSMUXDEV(minr); sc = wsmux_getmux(unit); if (sc == NULL) return (ENXIO); - DPRINTF(("wsmuxopen: %s: sc=%p\n", sc->sc_dv.dv_xname, sc)); - if (WSMUXCTL(munit)) { + DPRINTF(("wsmuxopen: %s: sc=%p p=%p\n", sc->sc_base.me_dv.dv_xname, + sc, p)); + + if (WSMUXCTL(minr)) { /* This is the control device which does not allow reads. */ if (flags & FREAD) return (EINVAL); return (0); } + if ((flags & (FREAD | FWRITE)) == FWRITE) + /* Allow write only open */ + return (0); - if (sc->sc_mux) { + if (sc->sc_base.me_parent != NULL) { /* Grab the mux out of the greedy hands of the parent mux. */ - int error = wsmux_rem_mux(unit, sc->sc_mux); - if (error) - return (error); + wsmux_detach_sc(&sc->sc_base); } - if (sc->sc_events.io) + 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 */ + evar = wsevent_alloc(); + evar->io = p; + sc->sc_rawkbd = 0; - 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; - } - } - } - - 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 +wsmux_mux_open(struct wsevsrc *me, struct wseventvar *evar) +{ + struct wsmux_softc *sc = (struct wsmux_softc *)me; + +#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 + + wsmux_do_open(sc, evar); + + return (0); +} + +/* Common part of opening a mux. */ +void +wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar) +{ + struct wsevsrc *me; + + sc->sc_base.me_evp = evar; /* remember event variable, mark as open */ + + /* 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; + } + { + int error = me->me_ops->dopen(me, evar); + if (error) { + DPRINTF(("wsmuxopen: open failed %d\n", error)); + } + } +#else + /* ignore errors, failing children will not be marked open */ + (void)me->me_ops->dopen(me, evar); +#endif + } +} + +/* + * close() of the pseudo device from device table. + */ int wsmuxclose(dev_t dev, int flags, int mode, struct proc *p) { - int munit = minor(dev); + int minr = minor(dev); + struct wsmux_softc *sc = wsmuxdevs[WSMUXDEV(minr)]; + struct wseventvar *evar = sc->sc_base.me_evp; - if (WSMUXCTL(munit)) { + if (WSMUXCTL(minr)) /* control device */ return (0); - } - return wsmuxdoclose(&wsmuxdevs[WSMUXDEV(munit)]->sc_dv, flags, mode, p); + if (evar == NULL) + /* Not open for read */ + return (0); + + sc->sc_base.me_evp = NULL; + wsevent_free(evar); + wsmux_do_close(sc); + return (0); } +/* + * Close of a mux via the parent mux. + */ +int +wsmux_mux_close(struct wsevsrc *me) +{ + me->me_evp = NULL; + wsmux_do_close((struct wsmux_softc *)me); + return (0); +} + +/* Common part of closing a mux. */ +void +wsmux_do_close(struct wsmux_softc *sc) +{ + struct wsevsrc *me; + + DPRINTF(("wsmuxclose: %s: sc=%p\n", sc->sc_base.me_dv.dv_xname, sc)); + + /* 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; + } +#endif + (void)me->me_ops->dclose(me); + me->me_evp = NULL; + } +} + +/* + * read() of the pseudo device from device table. + */ int wsmuxread(dev_t dev, struct uio *uio, int flags) { - int munit = minor(dev); - struct wsmux_softc *sc = wsmuxdevs[WSMUXDEV(munit)]; + int minr = minor(dev); + struct wsmux_softc *sc = wsmuxdevs[WSMUXDEV(minr)]; - if (WSMUXCTL(munit)) { + if (WSMUXCTL(minr)) { /* control device */ return (EINVAL); } - if (!sc->sc_events.io) - return (EACCES); + if (sc->sc_base.me_evp == NULL) { +#ifdef DIAGNOSTIC + /* XXX can we get here? */ + printf("wsmuxread: not open\n"); +#endif + return (EINVAL); + } - return (wsevent_read(&sc->sc_events, uio, flags)); + return (wsevent_read(sc->sc_base.me_evp, uio, flags)); } +/* + * ioctl of the pseudo device from device table. + */ int wsmuxioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - int unit = WSMUXDEV(minor(dev)); + int u = WSMUXDEV(minor(dev)); - return wsmuxdoioctl(&wsmuxdevs[unit]->sc_dv, cmd, data, flag, p); + return wsmux_do_ioctl(&wsmuxdevs[u]->sc_base.me_dv, cmd, data, flag, p); } +/* + * ioctl of a mux via the parent mux, continuation of wsmuxioctl(). + */ int -wsmuxpoll(dev_t dev, int events, struct proc *p) -{ - int munit = minor(dev); - struct wsmux_softc *sc = wsmuxdevs[WSMUXDEV(munit)]; - - if (WSMUXCTL(munit)) { - /* control device */ - return (EINVAL); - } - - if (!sc->sc_events.io) - return (EACCES); - - return (wsevent_poll(&sc->sc_events, events, p)); -} - -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_dv.dv_xname, sc, - muxsc->sc_dv.dv_xname, muxsc)); - - if (sc->sc_mux || sc->sc_events.io) - return (EBUSY); - - /* The mux we are adding must not be an ancestor of itself. */ - for (m = muxsc; m; m = m->sc_mux) - if (m == sc) - return (EINVAL); - - return (wsmux_attach_sc(muxsc, WSMUX_MUX, &sc->sc_dv, &sc->sc_events, - &sc->sc_mux, &wsmux_muxops)); -} - -int -wsmux_rem_mux(int unit, struct wsmux_softc *muxsc) -{ - 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)); -} - -#endif /* NWSMUX > 0 */ - -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); - 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(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(("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 == NULL) - 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 - } - } - } 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; - } - DPRINTF(("wsmux_attach_sc: done sc=%p psp=%p *psp=%p\n", - sc, psp, *psp)); - - return (error); -} - -int -wsmux_detach_sc(struct wsmux_softc *sc, struct device *dsc) -{ - 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 - - for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) { - if (m->sc == dsc) - break; - } -#ifdef DIAGNOSTIC - if (!m) { - printf("wsmux_detach_sc: not found\n"); - return (ENXIO); - } -#endif - if (sc->sc_displaydv) { - 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; - } - - LIST_REMOVE(m, next); - - free(m, M_DEVBUF); - DPRINTF(("wsmux_detach_sc: done sc=%p\n", sc)); - return (0); -} - -int -wsmuxdoclose(struct device *dv, int flags, int mode, 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; - - DPRINTF(("wsmuxclose: %s: sc=%p\n", sc->sc_dv.dv_xname, sc)); - - 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); -} - -int -wsmuxdoioctl(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 timeval xxxtime; + struct timeval thistime; 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: 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) + DPRINTF(("%s: inject\n", sc->sc_base.me_dv.dv_xname)); + + evar = sc->sc_base.me_evp; + if (evar == NULL) /* XXX is this an error? */ return (EACCES); - evar = &sc->sc_events; s = spltty(); get = evar->get; put = evar->put; @@ -532,16 +413,17 @@ wsmuxdoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, put = 0; ev = &evar->q[put]; *ev = *(struct wscons_event *)data; - microtime(&xxxtime); - TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time); + microtime(&thistime); + TIMEVAL_TO_TIMESPEC(&thistime, &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 NWSMUX > 0 #if NWSMOUSE > 0 case WSMUX_MOUSE: return (wsmouse_add_mux(d->idx, sc)); @@ -552,35 +434,32 @@ wsmuxdoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, #endif case WSMUX_MUX: return (wsmux_add_mux(d->idx, sc)); -#endif default: return (EINVAL); } - case WSMUX_REMOVE_DEVICE: - switch (d->type) { -#if NWSMUX > 0 -#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 - 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) { + 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; @@ -588,36 +467,53 @@ wsmuxdoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, #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 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 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_base.me_dispdv == 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) { + DPRINTF(("wsmux_do_ioctl: me=%p\n", me)); +#ifdef DIAGNOSTIC + /* XXX check evp? */ + if (me->me_parent != sc) { + printf("wsmux_do_ioctl: bad child %p\n", me); + continue; } +#endif + DPRINTF(("wsmux_do_ioctl: %s: me=%p dev=%s\n", + sc->sc_base.me_dv.dv_xname, me, me->me_dv.dv_xname)); + error = wsevsrc_ioctl(me, cmd, data, flag, p); + if (!error) + ok = 1; } if (ok) error = 0; @@ -625,16 +521,186 @@ wsmuxdoioctl(struct device *dv, u_long cmd, caddr_t data, int flag, return (error); } +/* + * poll() of the pseudo device from device table. + */ int -wsmux_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, - struct proc *p) +wsmuxpoll(dev_t dev, int events, struct proc *p) +{ + int minr = minor(dev); + struct wsmux_softc *sc = wsmuxdevs[WSMUXDEV(minr)]; + + if (WSMUXCTL(minr)) { + /* control device */ + return (EINVAL); + } + + 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); + memset(sc, 0, 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; + return (sc); +} + +/* Attach me as a child to sc. */ +int +wsmux_attach_sc(struct wsmux_softc *sc, struct wsevsrc *me) +{ + int error; + + if (sc == NULL) + return (EINVAL); + + DPRINTF(("wsmux_attach_sc: %s: type=%d\n", + sc->sc_base.me_dv.dv_xname, 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); + +#if NWSDISPLAY > 0 + if (sc->sc_base.me_dispdv != 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_base.me_dispdv)); + error = 0; + 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: on %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 + } + } + } else +#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 = me->me_ops->dopen(me, sc->sc_base.me_evp); + } else { + DPRINTF(("wsmux_attach_sc: %s not open\n", + sc->sc_base.me_dv.dv_xname)); + error = 0; + } + + if (error) { + me->me_parent = NULL; + CIRCLEQ_REMOVE(&sc->sc_cld, me, me_next); + } + + DPRINTF(("wsmux_attach_sc: done sc=%p, error=%d\n", 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\n", sc->sc_base.me_dv.dv_xname)); + +#ifdef DIAGNOSTIC + if (sc == NULL) { + printf("wsmux_detach_sc: not allocated\n"); + return; + } +#endif + +#if NWSDISPLAY > 0 + if (sc->sc_base.me_dispdv != 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)me->me_ops->dclose(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)); + sc->sc_base.me_dv.dv_xname, sc, cmd)); #ifdef WSDISPLAY_COMPAT_RAWKBD if (cmd == WSKBDIO_SETMODE) { @@ -649,14 +715,18 @@ wsmux_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, */ 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; } @@ -667,52 +737,58 @@ wsmux_displayioctl(struct device *dv, u_long cmd, caddr_t data, int flag, return (error); } +#if NWSDISPLAY > 0 +/* + * Set display of a mux via the parent mux. + */ int -wsmux_set_display(struct device *dv, struct wsmux_softc *muxsc) +wsmux_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 wsmux_softc *nsc = muxsc ? sc : NULL; + struct device *displaydv = muxsc ? muxsc->sc_base.me_dispdv : NULL; struct device *odisplaydv; - struct wsplink *m; + struct wsevsrc *me; int error, ok; 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_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 = displaydv; 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); 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); + 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", - m, m->sc->dv_xname, error)); + 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); + me->me_dv.dv_xname, sc->sc_rawkbd)); + (void)wsevsrc_ioctl(me, WSKBDIO_SETMODE, + &sc->sc_rawkbd, 0, 0); #endif } } @@ -722,9 +798,8 @@ wsmux_set_display(struct device *dv, struct wsmux_softc *muxsc) if (displaydv == NULL) 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 (error); } - -#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 46549c4b19b9..cf909c9ed6af 100644 --- a/sys/dev/wscons/wsmuxvar.h +++ b/sys/dev/wscons/wsmuxvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wsmuxvar.h,v 1.3 2001/10/13 15:56:16 augustss Exp $ */ +/* $NetBSD: wsmuxvar.h,v 1.4 2001/10/24 14:07:33 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -36,52 +36,58 @@ * 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_evp; /* our wseventvar when open */ +#if NWSDISPLAY > 0 + struct device *me_dispdv; /* our display if part of one */ +#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_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 */ #ifdef WSDISPLAY_COMPAT_RAWKBD 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 *); -}; +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 *); -struct wsmux_softc *wsmux_getmux(int); -struct wsmux_softc *wsmux_create(const char *, int); -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); - -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 */