2008-11-07 22:33:13 +03:00
|
|
|
/* $NetBSD: wsdisplay.c,v 1.123 2008/11/07 19:33:13 he Exp $ */
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Christopher G. Demetriou
|
|
|
|
* for the NetBSD Project.
|
|
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 09:17:46 +03:00
|
|
|
#include <sys/cdefs.h>
|
2008-11-07 22:33:13 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.123 2008/11/07 19:33:13 he Exp $");
|
2001-11-13 09:17:46 +03:00
|
|
|
|
2001-10-24 18:07:31 +04:00
|
|
|
#include "opt_wsdisplay_compat.h"
|
Implement support to dynamically change wscons console and kernel colors.
Two new ioctls are added to the wsdisplay device, named WSDISPLAY_GMSGATTRS
and WSDISPLAY_SMSGATTRS, used to retrieve the actual values and set them,
respectively (the name, if you are wondering, comes from "message attributes").
A new emulop is added to the underlying display driver (only vga, for now)
which sets the new attribute for the whole screen, without having to clear
it. This is optional, which means that this also works with other drivers
that don't have this new operation.
Five new kernel options have been added, although only documented in
i386 kernels (for now):
- WSDISPLAY_CUSTOM_OUTPUT, which enables the ioctls described above to
change the colors dynamically from userland. This is enabled by default
in the GENERIC kernel (as well as others) but disabled on all INSTALL*
kernels (as this feature is useless there).
- WS_DEFAULT_COLATTR, WS_DEFAULT_MONOATTR, WS_DEFAULT_BG and WS_DEFAULT_FG,
which specify the default colors for the console at boot time. These have
the same meaning as the (already existing) WS_KERNEL_* variables.
wsconsctl is modified to add msg.default.{attrs,bg,fg} and
msg.kernel.{attrs,bg,fg} to the display part, so that colors can be changed
after boot.
Tested on NetBSD/i386 with vga (and vga in mono mode), and on NetBSD/mac68k.
No objections in tech-kern@.
2004-07-28 16:34:02 +04:00
|
|
|
#include "opt_wsmsgattrs.h"
|
2001-10-24 18:07:31 +04:00
|
|
|
#include "opt_compat_netbsd.h"
|
|
|
|
#include "wskbd.h"
|
|
|
|
#include "wsmux.h"
|
|
|
|
#include "wsdisplay.h"
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/conf.h>
|
|
|
|
#include <sys/device.h>
|
|
|
|
#include <sys/ioctl.h>
|
2005-06-21 18:01:11 +04:00
|
|
|
#include <sys/poll.h>
|
1998-03-22 17:24:02 +03:00
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/syslog.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/tty.h>
|
|
|
|
#include <sys/signalvar.h>
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/fcntl.h>
|
1999-01-09 18:42:34 +03:00
|
|
|
#include <sys/vnode.h>
|
2006-05-15 01:42:26 +04:00
|
|
|
#include <sys/kauth.h>
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2001-10-24 18:07:31 +04:00
|
|
|
#include <dev/wscons/wseventvar.h>
|
|
|
|
#include <dev/wscons/wsmuxvar.h>
|
1998-03-22 17:24:02 +03:00
|
|
|
#include <dev/wscons/wsconsio.h>
|
|
|
|
#include <dev/wscons/wsdisplayvar.h>
|
1998-06-15 21:48:32 +04:00
|
|
|
#include <dev/wscons/wsksymvar.h>
|
|
|
|
#include <dev/wscons/wsksymdef.h>
|
1998-03-22 17:24:02 +03:00
|
|
|
#include <dev/wscons/wsemulvar.h>
|
|
|
|
#include <dev/wscons/wscons_callbacks.h>
|
|
|
|
#include <dev/cons.h>
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
struct wsscreen_internal {
|
1998-03-22 17:24:02 +03:00
|
|
|
const struct wsdisplay_emulops *emulops;
|
|
|
|
void *emulcookie;
|
|
|
|
|
|
|
|
const struct wsscreen_descr *scrdata;
|
|
|
|
|
|
|
|
const struct wsemul_ops *wsemul;
|
|
|
|
void *wsemulcookie;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct wsscreen {
|
1999-01-09 18:42:34 +03:00
|
|
|
struct wsscreen_internal *scr_dconf;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
struct tty *scr_tty;
|
|
|
|
int scr_hold_screen; /* hold tty output */
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
int scr_flags;
|
|
|
|
#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 */
|
2004-07-21 00:28:20 +04:00
|
|
|
#define SCR_DUMBFB 8 /* in use as a dumb fb (iff SCR_GRAPHICS) */
|
1998-06-12 02:13:52 +04:00
|
|
|
const struct wscons_syncops *scr_syncops;
|
|
|
|
void *scr_synccookie;
|
|
|
|
|
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
int scr_rawkbd;
|
|
|
|
#endif
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
};
|
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
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 *);
|
|
|
|
static void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int);
|
|
|
|
static void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *);
|
|
|
|
int wsdisplay_delscreen(struct wsdisplay_softc *, int, int);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
#define WSDISPLAY_MAXSCREEN 8
|
|
|
|
|
|
|
|
struct wsdisplay_softc {
|
2007-10-18 22:09:52 +04:00
|
|
|
device_t sc_dev;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
const struct wsdisplay_accessops *sc_accessops;
|
|
|
|
void *sc_accesscookie;
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
const struct wsscreen_list *sc_scrdata;
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
struct wsdisplay_scroll_data sc_scroll_values;
|
|
|
|
#endif
|
1999-01-09 18:42:34 +03:00
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN];
|
2000-09-10 13:39:57 +04:00
|
|
|
int sc_focusidx; /* available only if sc_focus isn't null */
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *sc_focus;
|
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
struct wseventvar evar;
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
int sc_isconsole;
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
int sc_flags;
|
|
|
|
#define SC_SWITCHPENDING 1
|
2008-02-21 01:33:18 +03:00
|
|
|
#define SC_SWITCHERROR 2
|
|
|
|
#define SC_XATTACHED 4 /* X server active */
|
2008-01-15 00:38:50 +03:00
|
|
|
kmutex_t sc_flagsmtx; /* for flags, might also be used for focus */
|
|
|
|
kcondvar_t sc_flagscv;
|
|
|
|
|
1999-01-26 17:22:14 +03:00
|
|
|
int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */
|
1998-06-12 02:13:52 +04:00
|
|
|
|
1999-05-17 20:53:43 +04:00
|
|
|
#if NWSKBD > 0
|
2001-10-24 18:07:31 +04:00
|
|
|
struct wsevsrc *sc_input;
|
1998-06-12 02:13:52 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
int sc_rawkbd;
|
|
|
|
#endif
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif /* NWSKBD > 0 */
|
1998-03-22 17:24:02 +03:00
|
|
|
};
|
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
|
|
|
|
struct wsdisplay_scroll_data wsdisplay_default_scroll_values = {
|
|
|
|
WSDISPLAY_SCROLL_DOALL,
|
|
|
|
25,
|
|
|
|
2,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
extern struct cfdriver wsdisplay_cd;
|
|
|
|
|
|
|
|
/* Autoconfiguration definitions. */
|
2008-06-11 20:17:01 +04:00
|
|
|
static int wsdisplay_emul_match(device_t , cfdata_t, void *);
|
2007-10-18 22:09:52 +04:00
|
|
|
static void wsdisplay_emul_attach(device_t, device_t, void *);
|
2008-06-11 20:17:01 +04:00
|
|
|
static int wsdisplay_noemul_match(device_t, cfdata_t, void *);
|
2007-10-18 22:09:52 +04:00
|
|
|
static void wsdisplay_noemul_attach(device_t, device_t, void *);
|
2008-02-29 09:13:39 +03:00
|
|
|
static bool wsdisplay_suspend(device_t PMF_FN_PROTO);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
CFATTACH_DECL_NEW(wsdisplay_emul, sizeof (struct wsdisplay_softc),
|
2002-10-02 20:51:16 +04:00
|
|
|
wsdisplay_emul_match, wsdisplay_emul_attach, NULL, NULL);
|
2007-12-09 23:27:42 +03:00
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
CFATTACH_DECL_NEW(wsdisplay_noemul, sizeof (struct wsdisplay_softc),
|
2002-10-02 20:51:16 +04:00
|
|
|
wsdisplay_noemul_match, wsdisplay_noemul_attach, NULL, NULL);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2002-09-06 17:18:43 +04:00
|
|
|
dev_type_open(wsdisplayopen);
|
|
|
|
dev_type_close(wsdisplayclose);
|
|
|
|
dev_type_read(wsdisplayread);
|
|
|
|
dev_type_write(wsdisplaywrite);
|
|
|
|
dev_type_ioctl(wsdisplayioctl);
|
|
|
|
dev_type_stop(wsdisplaystop);
|
|
|
|
dev_type_tty(wsdisplaytty);
|
|
|
|
dev_type_poll(wsdisplaypoll);
|
|
|
|
dev_type_mmap(wsdisplaymmap);
|
2002-10-23 13:10:23 +04:00
|
|
|
dev_type_kqfilter(wsdisplaykqfilter);
|
2002-09-06 17:18:43 +04:00
|
|
|
|
|
|
|
const struct cdevsw wsdisplay_cdevsw = {
|
|
|
|
wsdisplayopen, wsdisplayclose, wsdisplayread, wsdisplaywrite,
|
|
|
|
wsdisplayioctl, wsdisplaystop, wsdisplaytty, wsdisplaypoll,
|
2002-10-23 13:10:23 +04:00
|
|
|
wsdisplaymmap, wsdisplaykqfilter, D_TTY
|
2002-09-06 17:18:43 +04:00
|
|
|
};
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
static void wsdisplaystart(struct tty *);
|
|
|
|
static int wsdisplayparam(struct tty *, struct termios *);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
#define WSDISPLAYUNIT(dev) (minor(dev) >> 8)
|
|
|
|
#define WSDISPLAYSCREEN(dev) (minor(dev) & 0xff)
|
2002-06-27 03:05:33 +04:00
|
|
|
#define ISWSDISPLAYSTAT(dev) (WSDISPLAYSCREEN(dev) == 254)
|
1999-01-09 18:42:34 +03:00
|
|
|
#define ISWSDISPLAYCTL(dev) (WSDISPLAYSCREEN(dev) == 255)
|
1998-04-07 20:06:33 +04:00
|
|
|
#define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen))
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
#define WSSCREEN_HAS_EMULATOR(scr) ((scr)->scr_dconf->wsemul != NULL)
|
|
|
|
#define WSSCREEN_HAS_TTY(scr) ((scr)->scr_tty != NULL)
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
static void wsdisplay_common_attach(struct wsdisplay_softc *sc,
|
2001-10-13 17:35:59 +04:00
|
|
|
int console, int kbdmux, const struct wsscreen_list *,
|
1998-03-22 17:24:02 +03:00
|
|
|
const struct wsdisplay_accessops *accessops,
|
2001-10-13 19:56:15 +04:00
|
|
|
void *accesscookie);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 22:15:27 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
2001-10-13 19:56:15 +04:00
|
|
|
int wsdisplay_update_rawkbd(struct wsdisplay_softc *,
|
|
|
|
struct wsscreen *);
|
1998-06-12 22:15:27 +04:00
|
|
|
#endif
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
static int wsdisplay_console_initted;
|
2006-02-18 21:56:05 +03:00
|
|
|
static int wsdisplay_console_attached;
|
1998-03-22 17:24:02 +03:00
|
|
|
static struct wsdisplay_softc *wsdisplay_console_device;
|
1999-01-09 18:42:34 +03:00
|
|
|
static struct wsscreen_internal wsdisplay_console_conf;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
static int wsdisplay_getc_dummy(dev_t);
|
|
|
|
static void wsdisplay_pollc(dev_t, int);
|
1999-12-06 21:52:23 +03:00
|
|
|
|
|
|
|
static int wsdisplay_cons_pollmode;
|
2001-10-13 19:56:15 +04:00
|
|
|
static void (*wsdisplay_cons_kbd_pollc)(dev_t, int);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
static struct consdev wsdisplay_cons = {
|
|
|
|
NULL, NULL, wsdisplay_getc_dummy, wsdisplay_cnputc,
|
2003-03-06 03:38:26 +03:00
|
|
|
wsdisplay_pollc, NULL, NULL, NULL, NODEV, CN_NORMAL
|
1998-03-22 17:24:02 +03:00
|
|
|
};
|
|
|
|
|
1999-09-16 22:16:51 +04:00
|
|
|
#ifndef WSDISPLAY_DEFAULTSCREENS
|
|
|
|
# define WSDISPLAY_DEFAULTSCREENS 0
|
|
|
|
#endif
|
|
|
|
int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
static int wsdisplay_switch1(device_t, int, int);
|
|
|
|
static void wsdisplay_switch1_cb(void *, int, int);
|
|
|
|
static int wsdisplay_switch2(device_t, int, int);
|
|
|
|
static void wsdisplay_switch2_cb(void *, int, int);
|
|
|
|
static int wsdisplay_switch3(device_t, int, int);
|
|
|
|
static void wsdisplay_switch3_cb(void *, int, int);
|
1998-06-12 02:13:52 +04:00
|
|
|
|
1999-01-17 18:56:33 +03:00
|
|
|
int wsdisplay_clearonclose;
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
struct wsscreen *
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul,
|
|
|
|
const struct wsscreen_descr *type, void *cookie, int ccol,
|
|
|
|
int crow, long defattr)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1999-01-09 18:42:34 +03:00
|
|
|
struct wsscreen_internal *dconf;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
scr = malloc(sizeof(struct wsscreen), M_DEVBUF, M_WAITOK);
|
|
|
|
if (!scr)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
if (console) {
|
|
|
|
dconf = &wsdisplay_console_conf;
|
|
|
|
/*
|
|
|
|
* If there's an emulation, tell it about the callback argument.
|
|
|
|
* The other stuff is already there.
|
|
|
|
*/
|
|
|
|
if (dconf->wsemul != NULL)
|
1998-05-15 00:49:55 +04:00
|
|
|
(*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0);
|
1998-03-22 17:24:02 +03:00
|
|
|
} else { /* not console */
|
1999-01-09 18:42:34 +03:00
|
|
|
dconf = malloc(sizeof(struct wsscreen_internal),
|
1998-03-22 17:24:02 +03:00
|
|
|
M_DEVBUF, M_NOWAIT);
|
|
|
|
dconf->emulops = type->textops;
|
|
|
|
dconf->emulcookie = cookie;
|
|
|
|
if (dconf->emulops) {
|
|
|
|
dconf->wsemul = wsemul_pick(emul);
|
1999-01-09 18:42:34 +03:00
|
|
|
if (dconf->wsemul == NULL) {
|
|
|
|
free(dconf, M_DEVBUF);
|
|
|
|
free(scr, M_DEVBUF);
|
|
|
|
return (NULL);
|
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
dconf->wsemulcookie =
|
|
|
|
(*dconf->wsemul->attach)(0, type, cookie,
|
1998-05-15 00:49:55 +04:00
|
|
|
ccol, crow, scr, defattr);
|
1998-03-22 17:24:02 +03:00
|
|
|
} else
|
|
|
|
dconf->wsemul = NULL;
|
|
|
|
dconf->scrdata = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
scr->scr_dconf = dconf;
|
|
|
|
|
|
|
|
scr->scr_tty = ttymalloc();
|
|
|
|
tty_attach(scr->scr_tty);
|
|
|
|
scr->scr_hold_screen = 0;
|
1998-06-12 02:13:52 +04:00
|
|
|
if (WSSCREEN_HAS_EMULATOR(scr))
|
|
|
|
scr->scr_flags = 0;
|
|
|
|
else
|
|
|
|
scr->scr_flags = SCR_GRAPHICS;
|
|
|
|
|
|
|
|
scr->scr_syncops = 0;
|
1998-03-22 17:24:02 +03:00
|
|
|
scr->sc = sc;
|
1998-06-12 02:13:52 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
scr->scr_rawkbd = 0;
|
|
|
|
#endif
|
1998-03-22 17:24:02 +03:00
|
|
|
return (scr);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_detach(struct wsscreen *scr)
|
1999-01-09 18:42:34 +03:00
|
|
|
{
|
2003-01-20 05:16:55 +03:00
|
|
|
u_int ccol, crow; /* XXX */
|
1999-01-09 18:42:34 +03:00
|
|
|
|
|
|
|
if (WSSCREEN_HAS_TTY(scr)) {
|
|
|
|
tty_detach(scr->scr_tty);
|
|
|
|
ttyfree(scr->scr_tty);
|
|
|
|
}
|
|
|
|
if (WSSCREEN_HAS_EMULATOR(scr))
|
|
|
|
(*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie,
|
|
|
|
&ccol, &crow);
|
|
|
|
free(scr->scr_dconf, M_DEVBUF);
|
|
|
|
free(scr, M_DEVBUF);
|
|
|
|
}
|
|
|
|
|
2000-09-10 15:44:13 +04:00
|
|
|
const struct wsscreen_descr *
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name)
|
1999-01-09 18:42:34 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const struct wsscreen_descr *scr;
|
|
|
|
|
|
|
|
KASSERT(scrdata->nscreens > 0);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
return (scrdata->screens[0]);
|
|
|
|
|
|
|
|
for (i = 0; i < scrdata->nscreens; i++) {
|
|
|
|
scr = scrdata->screens[i];
|
|
|
|
if (!strcmp(name, scr->name))
|
|
|
|
return (scr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-09-16 22:16:51 +04:00
|
|
|
/*
|
|
|
|
* print info about attached screen
|
|
|
|
*/
|
|
|
|
static void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count)
|
1999-09-16 22:16:51 +04:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_verbose_dev(sc->sc_dev, "screen %d", idx);
|
1999-09-16 22:16:51 +04:00
|
|
|
if (count > 1)
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_verbose("-%d", idx + (count-1));
|
|
|
|
aprint_verbose(" added (%s", sc->sc_scr[idx]->scr_dconf->scrdata->name);
|
1999-09-16 22:16:51 +04:00
|
|
|
if (WSSCREEN_HAS_EMULATOR(sc->sc_scr[idx])) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_verbose(", %s emulation",
|
1999-09-16 22:16:51 +04:00
|
|
|
sc->sc_scr[idx]->scr_dconf->wsemul->name);
|
|
|
|
}
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_verbose(")\n");
|
1999-09-16 22:16:51 +04:00
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx,
|
|
|
|
const char *screentype, const char *emul)
|
1999-01-09 18:42:34 +03:00
|
|
|
{
|
|
|
|
const struct wsscreen_descr *scrdesc;
|
|
|
|
int error;
|
|
|
|
void *cookie;
|
|
|
|
int ccol, crow;
|
|
|
|
long defattr;
|
|
|
|
struct wsscreen *scr;
|
1999-03-23 18:56:56 +03:00
|
|
|
int s;
|
1999-01-09 18:42:34 +03:00
|
|
|
|
|
|
|
if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
|
|
|
|
return (EINVAL);
|
|
|
|
if (sc->sc_scr[idx] != NULL)
|
|
|
|
return (EBUSY);
|
|
|
|
|
|
|
|
scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype);
|
|
|
|
if (!scrdesc)
|
|
|
|
return (ENXIO);
|
|
|
|
error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie,
|
|
|
|
scrdesc, &cookie, &ccol, &crow, &defattr);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
scr = wsscreen_attach(sc, 0, emul, scrdesc,
|
|
|
|
cookie, ccol, crow, defattr);
|
|
|
|
if (scr == NULL) {
|
|
|
|
(*sc->sc_accessops->free_screen)(sc->sc_accesscookie,
|
|
|
|
cookie);
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_scr[idx] = scr;
|
|
|
|
|
1999-03-23 18:56:56 +03:00
|
|
|
/* if no screen has focus yet, activate the first we get */
|
|
|
|
s = spltty();
|
|
|
|
if (!sc->sc_focus) {
|
|
|
|
(*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
|
1999-12-06 21:52:23 +03:00
|
|
|
scr->scr_dconf->emulcookie,
|
|
|
|
0, 0, 0);
|
1999-03-23 18:56:56 +03:00
|
|
|
sc->sc_focusidx = idx;
|
|
|
|
sc->sc_focus = scr;
|
|
|
|
}
|
|
|
|
splx(s);
|
1999-01-09 18:42:34 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-01-17 18:56:33 +03:00
|
|
|
static void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr)
|
1999-01-17 18:56:33 +03:00
|
|
|
{
|
|
|
|
int maj, mn, idx;
|
|
|
|
|
|
|
|
/* hangup */
|
|
|
|
if (WSSCREEN_HAS_TTY(scr)) {
|
|
|
|
struct tty *tp = scr->scr_tty;
|
2000-11-02 03:01:44 +03:00
|
|
|
(*tp->t_linesw->l_modem)(tp, 0);
|
1999-01-17 18:56:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* locate the major number */
|
2002-09-06 17:18:43 +04:00
|
|
|
maj = cdevsw_lookup_major(&wsdisplay_cdevsw);
|
1999-01-17 18:56:33 +03:00
|
|
|
/* locate the screen index */
|
|
|
|
for (idx = 0; idx < WSDISPLAY_MAXSCREEN; idx++)
|
|
|
|
if (scr == sc->sc_scr[idx])
|
|
|
|
break;
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (idx == WSDISPLAY_MAXSCREEN)
|
|
|
|
panic("wsdisplay_forceclose: bad screen");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* nuke the vnodes */
|
2007-10-18 22:09:52 +04:00
|
|
|
mn = WSDISPLAYMINOR(device_unit(sc->sc_dev), idx);
|
1999-01-17 18:56:33 +03:00
|
|
|
vdevgone(maj, mn, mn, VCHR);
|
|
|
|
}
|
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
void
|
|
|
|
wsdisplay_scroll(void *arg, int op)
|
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
device_t dv = arg;
|
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
2007-03-05 19:06:52 +03:00
|
|
|
struct wsscreen *scr;
|
2004-05-29 01:42:29 +04:00
|
|
|
int lines;
|
|
|
|
|
2007-03-05 19:06:52 +03:00
|
|
|
scr = sc->sc_focus;
|
|
|
|
|
|
|
|
if (!scr)
|
|
|
|
return;
|
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
if (op == WSDISPLAY_SCROLL_RESET)
|
|
|
|
lines = 0;
|
|
|
|
else {
|
|
|
|
lines = (op & WSDISPLAY_SCROLL_LOW) ?
|
|
|
|
sc->sc_scroll_values.slowlines :
|
|
|
|
sc->sc_scroll_values.fastlines;
|
|
|
|
if (op & WSDISPLAY_SCROLL_BACKWARD)
|
|
|
|
lines = -(lines);
|
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
if (sc->sc_accessops->scroll) {
|
|
|
|
(*sc->sc_accessops->scroll)(sc->sc_accesscookie,
|
|
|
|
sc->sc_focus->scr_dconf->emulcookie, lines);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags)
|
1999-01-09 18:42:34 +03:00
|
|
|
{
|
|
|
|
struct wsscreen *scr;
|
1999-01-17 18:56:33 +03:00
|
|
|
int s;
|
1999-01-09 18:42:34 +03:00
|
|
|
void *cookie;
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
|
|
|
|
return (EINVAL);
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[idx]) == NULL)
|
1999-01-09 18:42:34 +03:00
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
if (scr->scr_dconf == &wsdisplay_console_conf ||
|
|
|
|
scr->scr_syncops ||
|
|
|
|
((scr->scr_flags & SCR_OPEN) && !(flags & WSDISPLAY_DELSCR_FORCE)))
|
|
|
|
return(EBUSY);
|
|
|
|
|
1999-01-17 18:56:33 +03:00
|
|
|
wsdisplay_closescreen(sc, scr);
|
1999-01-09 18:42:34 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* delete pointers, so neither device entries
|
|
|
|
* nor keyboard input can reference it anymore
|
|
|
|
*/
|
|
|
|
s = spltty();
|
1999-01-26 17:22:14 +03:00
|
|
|
if (sc->sc_focus == scr) {
|
1999-01-09 18:42:34 +03:00
|
|
|
sc->sc_focus = 0;
|
1999-01-26 17:22:14 +03:00
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
wsdisplay_update_rawkbd(sc, 0);
|
|
|
|
#endif
|
|
|
|
}
|
1999-01-09 18:42:34 +03:00
|
|
|
sc->sc_scr[idx] = 0;
|
|
|
|
splx(s);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wake up processes waiting for the screen to
|
|
|
|
* be activated. Sleepers must check whether
|
|
|
|
* the screen still exists.
|
|
|
|
*/
|
|
|
|
if (scr->scr_flags & SCR_WAITACTIVE)
|
|
|
|
wakeup(scr);
|
|
|
|
|
|
|
|
/* save a reference to the graphics screen */
|
|
|
|
cookie = scr->scr_dconf->emulcookie;
|
|
|
|
|
|
|
|
wsscreen_detach(scr);
|
|
|
|
|
|
|
|
(*sc->sc_accessops->free_screen)(sc->sc_accesscookie,
|
|
|
|
cookie);
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_verbose_dev(sc->sc_dev, "screen %d deleted\n", idx);
|
1999-01-09 18:42:34 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
/*
|
|
|
|
* Autoconfiguration functions.
|
|
|
|
*/
|
|
|
|
int
|
2008-06-11 20:17:01 +04:00
|
|
|
wsdisplay_emul_match(device_t parent, cfdata_t match, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsemuldisplaydev_attach_args *ap = aux;
|
|
|
|
|
|
|
|
if (match->wsemuldisplaydevcf_console !=
|
|
|
|
WSEMULDISPLAYDEVCF_CONSOLE_UNK) {
|
|
|
|
/*
|
|
|
|
* If console-ness of device specified, either match
|
|
|
|
* exactly (at high priority), or fail.
|
|
|
|
*/
|
|
|
|
if (match->wsemuldisplaydevcf_console != 0 &&
|
|
|
|
ap->console != 0)
|
|
|
|
return (10);
|
|
|
|
else
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If console-ness unspecified, it wins. */
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_emul_attach(device_t parent, device_t self, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(self);
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsemuldisplaydev_attach_args *ap = aux;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
sc->sc_dev = self;
|
|
|
|
|
2006-02-18 21:56:05 +03:00
|
|
|
/* Don't allow more than one console to attach */
|
|
|
|
if (wsdisplay_console_attached && ap->console)
|
|
|
|
ap->console = 0;
|
|
|
|
|
2001-10-13 17:35:59 +04:00
|
|
|
wsdisplay_common_attach(sc, ap->console,
|
2007-10-18 22:09:52 +04:00
|
|
|
device_cfdata(self)->wsemuldisplaydevcf_kbdmux, ap->scrdata,
|
2001-10-13 17:35:59 +04:00
|
|
|
ap->accessops, ap->accesscookie);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
if (ap->console) {
|
|
|
|
int maj;
|
|
|
|
|
|
|
|
/* locate the major number */
|
2002-09-06 17:18:43 +04:00
|
|
|
maj = cdevsw_lookup_major(&wsdisplay_cdevsw);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2006-03-28 21:38:24 +04:00
|
|
|
cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(device_unit(self),
|
|
|
|
0));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print function (for parent devices). */
|
|
|
|
int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsemuldisplaydevprint(void *aux, const char *pnp)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
#if 0 /* -Wunused */
|
|
|
|
struct wsemuldisplaydev_attach_args *ap = aux;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (pnp)
|
2003-01-01 03:10:15 +03:00
|
|
|
aprint_normal("wsdisplay at %s", pnp);
|
1998-03-22 17:24:02 +03:00
|
|
|
#if 0 /* don't bother; it's ugly */
|
2003-01-01 03:10:15 +03:00
|
|
|
aprint_normal(" console %d", ap->console);
|
1998-03-22 17:24:02 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return (UNCONF);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2008-06-11 20:17:01 +04:00
|
|
|
wsdisplay_noemul_match(device_t parent, cfdata_t match, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
#if 0 /* -Wunused */
|
|
|
|
struct wsdisplaydev_attach_args *ap = aux;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Always match. */
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_noemul_attach(device_t parent, device_t self, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(self);
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsdisplaydev_attach_args *ap = aux;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
sc->sc_dev = self;
|
|
|
|
|
2001-10-13 17:35:59 +04:00
|
|
|
wsdisplay_common_attach(sc, 0,
|
2007-10-18 22:09:52 +04:00
|
|
|
device_cfdata(self)->wsemuldisplaydevcf_kbdmux, NULL,
|
2001-10-13 17:35:59 +04:00
|
|
|
ap->accessops, ap->accesscookie);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
2008-01-15 00:38:50 +03:00
|
|
|
static void
|
|
|
|
wsdisplay_swdone_cb(void *arg, int error, int waitok)
|
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = arg;
|
|
|
|
|
|
|
|
mutex_enter(&sc->sc_flagsmtx);
|
|
|
|
KASSERT(sc->sc_flags & SC_SWITCHPENDING);
|
2008-02-21 01:33:18 +03:00
|
|
|
if (error)
|
|
|
|
sc->sc_flags |= SC_SWITCHERROR;
|
2008-01-15 00:38:50 +03:00
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
cv_signal(&sc->sc_flagscv);
|
|
|
|
mutex_exit(&sc->sc_flagsmtx);
|
|
|
|
}
|
|
|
|
|
2008-02-21 01:33:18 +03:00
|
|
|
static int
|
|
|
|
wsdisplay_dosync(struct wsdisplay_softc *sc, int attach)
|
2007-12-09 23:27:42 +03:00
|
|
|
{
|
2008-01-15 00:38:50 +03:00
|
|
|
struct wsscreen *scr;
|
2008-02-21 01:33:18 +03:00
|
|
|
int (*op)(void *, int, void (*)(void *, int, int), void *);
|
2008-01-15 00:38:50 +03:00
|
|
|
int res;
|
2007-12-13 18:14:48 +03:00
|
|
|
|
2008-01-15 00:38:50 +03:00
|
|
|
scr = sc->sc_focus;
|
|
|
|
if (!scr || !scr->scr_syncops)
|
2008-02-21 01:33:18 +03:00
|
|
|
return 0; /* XXX check SCR_GRAPHICS? */
|
2008-01-15 00:38:50 +03:00
|
|
|
|
|
|
|
sc->sc_flags |= SC_SWITCHPENDING;
|
2008-02-21 01:33:18 +03:00
|
|
|
sc->sc_flags &= ~SC_SWITCHERROR;
|
|
|
|
if (attach)
|
|
|
|
op = scr->scr_syncops->attach;
|
|
|
|
else
|
|
|
|
op = scr->scr_syncops->detach;
|
|
|
|
res = (*op)(scr->scr_synccookie, 1, wsdisplay_swdone_cb, sc);
|
|
|
|
if (res == EAGAIN) {
|
|
|
|
/* wait for callback */
|
|
|
|
mutex_enter(&sc->sc_flagsmtx);
|
|
|
|
while (sc->sc_flags & SC_SWITCHPENDING)
|
|
|
|
cv_wait_sig(&sc->sc_flagscv, &sc->sc_flagsmtx);
|
|
|
|
mutex_exit(&sc->sc_flagsmtx);
|
|
|
|
if (sc->sc_flags & SC_SWITCHERROR)
|
|
|
|
return (EIO); /* XXX pass real error */
|
|
|
|
} else {
|
2008-01-15 00:38:50 +03:00
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
2008-02-21 01:33:18 +03:00
|
|
|
if (res)
|
|
|
|
return (res);
|
2008-01-15 00:38:50 +03:00
|
|
|
}
|
2008-02-21 01:33:18 +03:00
|
|
|
if (attach)
|
|
|
|
sc->sc_flags |= SC_XATTACHED;
|
|
|
|
else
|
|
|
|
sc->sc_flags &= ~SC_XATTACHED;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-12-09 23:27:42 +03:00
|
|
|
|
2008-02-21 01:33:18 +03:00
|
|
|
int
|
|
|
|
wsdisplay_handlex(int resume)
|
|
|
|
{
|
|
|
|
int i, res;
|
|
|
|
device_t dv;
|
|
|
|
|
|
|
|
for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) {
|
2008-06-13 03:04:37 +04:00
|
|
|
dv = device_lookup(&wsdisplay_cd, i);
|
2008-02-21 01:33:18 +03:00
|
|
|
if (!dv)
|
|
|
|
continue;
|
|
|
|
res = wsdisplay_dosync(device_private(dv), resume);
|
|
|
|
if (res)
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
return (0);
|
2007-12-09 23:27:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2008-02-29 09:13:39 +03:00
|
|
|
wsdisplay_suspend(device_t dv PMF_FN_ARGS)
|
2007-12-09 23:27:42 +03:00
|
|
|
{
|
2007-12-13 18:14:48 +03:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
2008-02-21 01:33:18 +03:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
struct wsscreen *scr = sc->sc_focus;
|
|
|
|
if (sc->sc_flags & SC_XATTACHED) {
|
|
|
|
KASSERT(scr && scr->scr_syncops);
|
2008-01-15 00:38:50 +03:00
|
|
|
}
|
2008-02-21 01:33:18 +03:00
|
|
|
#endif
|
|
|
|
#if 1
|
|
|
|
/*
|
|
|
|
* XXX X servers should have been detached earlier.
|
|
|
|
* pmf currently ignores our return value and suspends the system
|
|
|
|
* after device suspend failures. We try to avoid bigger damage
|
|
|
|
* and try to detach the X server here. This is not safe because
|
|
|
|
* other parts of the system which the X server deals with
|
|
|
|
* might already be suspended.
|
|
|
|
*/
|
|
|
|
if (sc->sc_flags & SC_XATTACHED) {
|
|
|
|
printf("%s: emergency X server detach\n", device_xname(dv));
|
|
|
|
wsdisplay_dosync(sc, 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (!(sc->sc_flags & SC_XATTACHED));
|
2007-12-09 23:27:42 +03:00
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
/* Print function (for parent devices). */
|
|
|
|
int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplaydevprint(void *aux, const char *pnp)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
#if 0 /* -Wunused */
|
|
|
|
struct wsdisplaydev_attach_args *ap = aux;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (pnp)
|
2003-01-01 03:10:15 +03:00
|
|
|
aprint_normal("wsdisplay at %s", pnp);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
return (UNCONF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux,
|
|
|
|
const struct wsscreen_list *scrdata,
|
|
|
|
const struct wsdisplay_accessops *accessops,
|
|
|
|
void *accesscookie)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1999-09-16 22:16:51 +04:00
|
|
|
int i, start=0;
|
1999-07-29 22:20:02 +04:00
|
|
|
#if NWSKBD > 0
|
2001-10-24 18:07:31 +04:00
|
|
|
struct wsevsrc *kme;
|
2001-10-16 01:51:33 +04:00
|
|
|
#if NWSMUX > 0
|
2002-03-02 11:22:26 +03:00
|
|
|
struct wsmux_softc *mux;
|
2001-10-24 18:07:31 +04:00
|
|
|
|
2001-10-16 01:51:33 +04:00
|
|
|
if (kbdmux >= 0)
|
2002-03-02 11:22:26 +03:00
|
|
|
mux = wsmux_getmux(kbdmux);
|
2001-10-16 01:51:33 +04:00
|
|
|
else
|
2007-10-18 22:09:52 +04:00
|
|
|
mux = wsmux_create("dmux", device_unit(sc->sc_dev));
|
2001-10-13 17:35:59 +04:00
|
|
|
/* XXX panic()ing isn't nice, but attach cannot fail */
|
2002-03-02 11:22:26 +03:00
|
|
|
if (mux == NULL)
|
2002-09-27 19:35:29 +04:00
|
|
|
panic("wsdisplay_common_attach: no memory");
|
2002-03-02 11:22:26 +03:00
|
|
|
sc->sc_input = &mux->sc_base;
|
2007-10-18 22:09:52 +04:00
|
|
|
mux->sc_base.me_dispdv = sc->sc_dev;
|
|
|
|
aprint_normal(" kbdmux %d", kbdmux);
|
2001-10-24 18:07:31 +04:00
|
|
|
#else
|
|
|
|
if (kbdmux >= 0)
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_normal(" (kbdmux ignored)");
|
2001-10-24 18:07:31 +04:00
|
|
|
#endif
|
1999-07-29 22:20:02 +04:00
|
|
|
#endif
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1999-05-15 18:22:46 +04:00
|
|
|
sc->sc_isconsole = console;
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
if (console) {
|
|
|
|
KASSERT(wsdisplay_console_initted);
|
|
|
|
KASSERT(wsdisplay_console_device == NULL);
|
|
|
|
|
1998-05-15 00:49:55 +04:00
|
|
|
sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0);
|
1998-03-22 17:24:02 +03:00
|
|
|
wsdisplay_console_device = sc;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_normal(": console (%s, %s emulation)",
|
1998-03-22 17:24:02 +03:00
|
|
|
wsdisplay_console_conf.scrdata->name,
|
|
|
|
wsdisplay_console_conf.wsemul->name);
|
|
|
|
|
1999-05-17 20:53:43 +04:00
|
|
|
#if NWSKBD > 0
|
2007-10-18 22:09:52 +04:00
|
|
|
kme = wskbd_set_console_display(sc->sc_dev, sc->sc_input);
|
2001-10-24 18:07:31 +04:00
|
|
|
if (kme != NULL)
|
2008-03-25 03:49:19 +03:00
|
|
|
aprint_normal(", using %s", device_xname(kme->me_dv));
|
2001-10-24 18:07:31 +04:00
|
|
|
#if NWSMUX == 0
|
|
|
|
sc->sc_input = kme;
|
|
|
|
#endif
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif
|
1999-05-15 18:22:46 +04:00
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
sc->sc_focusidx = 0;
|
|
|
|
sc->sc_focus = sc->sc_scr[0];
|
1999-09-16 22:16:51 +04:00
|
|
|
start = 1;
|
2006-02-18 21:56:05 +03:00
|
|
|
|
|
|
|
wsdisplay_console_attached = 1;
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_normal("\n");
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2002-03-02 11:22:26 +03:00
|
|
|
#if NWSKBD > 0 && NWSMUX > 0
|
2007-10-18 22:09:52 +04:00
|
|
|
wsmux_set_display(mux, sc->sc_dev);
|
2002-03-02 11:22:26 +03:00
|
|
|
#endif
|
|
|
|
|
2008-02-13 22:01:35 +03:00
|
|
|
mutex_init(&sc->sc_flagsmtx, MUTEX_DEFAULT, IPL_NONE);
|
2008-01-15 00:38:50 +03:00
|
|
|
cv_init(&sc->sc_flagscv, "wssw");
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
sc->sc_accessops = accessops;
|
|
|
|
sc->sc_accesscookie = accesscookie;
|
1999-01-09 18:42:34 +03:00
|
|
|
sc->sc_scrdata = scrdata;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
sc->sc_scroll_values = wsdisplay_default_scroll_values;
|
|
|
|
#endif
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
/*
|
1999-05-15 18:22:46 +04:00
|
|
|
* Set up a number of virtual screens if wanted. The
|
1999-01-09 18:42:34 +03:00
|
|
|
* WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code
|
1999-05-15 18:22:46 +04:00
|
|
|
* is for special cases like installation kernels.
|
1999-01-09 18:42:34 +03:00
|
|
|
*/
|
1999-09-16 22:16:51 +04:00
|
|
|
for (i = start; i < wsdisplay_defaultscreens; i++) {
|
1999-01-09 18:42:34 +03:00
|
|
|
if (wsdisplay_addscreen(sc, i, 0, 0))
|
|
|
|
break;
|
1999-09-16 22:16:51 +04:00
|
|
|
}
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
if (i > start)
|
1999-09-16 22:16:51 +04:00
|
|
|
wsdisplay_addscreen_print(sc, start, i-start);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2008-02-21 01:33:18 +03:00
|
|
|
if (!pmf_device_register(sc->sc_dev, wsdisplay_suspend, NULL))
|
2007-12-09 23:27:42 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie,
|
|
|
|
int ccol, int crow, long defattr)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
const struct wsemul_ops *wsemul;
|
|
|
|
|
2006-11-06 22:51:12 +03:00
|
|
|
KASSERT(wsdisplay_console_initted < 2);
|
|
|
|
KASSERT(type->nrows > 0);
|
|
|
|
KASSERT(type->ncols > 0);
|
|
|
|
KASSERT(crow < type->nrows);
|
|
|
|
KASSERT(ccol < type->ncols);
|
|
|
|
|
|
|
|
wsdisplay_console_conf.emulops = type->textops;
|
|
|
|
wsdisplay_console_conf.emulcookie = cookie;
|
|
|
|
wsdisplay_console_conf.scrdata = type;
|
|
|
|
|
|
|
|
wsemul = wsemul_pick(0); /* default */
|
|
|
|
wsdisplay_console_conf.wsemul = wsemul;
|
|
|
|
wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie,
|
|
|
|
ccol, crow,
|
|
|
|
defattr);
|
|
|
|
|
|
|
|
cn_tab = &wsdisplay_cons;
|
|
|
|
wsdisplay_console_initted = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
wsdisplay_preattach(const struct wsscreen_descr *type, void *cookie,
|
|
|
|
int ccol, int crow, long defattr)
|
|
|
|
{
|
|
|
|
const struct wsemul_ops *wsemul;
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
KASSERT(!wsdisplay_console_initted);
|
|
|
|
KASSERT(type->nrows > 0);
|
|
|
|
KASSERT(type->ncols > 0);
|
|
|
|
KASSERT(crow < type->nrows);
|
|
|
|
KASSERT(ccol < type->ncols);
|
|
|
|
|
|
|
|
wsdisplay_console_conf.emulops = type->textops;
|
|
|
|
wsdisplay_console_conf.emulcookie = cookie;
|
|
|
|
wsdisplay_console_conf.scrdata = type;
|
|
|
|
|
|
|
|
wsemul = wsemul_pick(0); /* default */
|
|
|
|
wsdisplay_console_conf.wsemul = wsemul;
|
|
|
|
wsdisplay_console_conf.wsemulcookie = (*wsemul->cnattach)(type, cookie,
|
1998-05-15 00:49:55 +04:00
|
|
|
ccol, crow,
|
|
|
|
defattr);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
cn_tab = &wsdisplay_cons;
|
|
|
|
wsdisplay_console_initted = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tty and cdevsw functions.
|
|
|
|
*/
|
|
|
|
int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplayopen(dev_t dev, int flag, int mode, struct lwp *l)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
2001-01-04 02:00:24 +03:00
|
|
|
int newopen, error;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
|
|
|
if (sc == NULL) /* make sure it was attached */
|
1998-03-22 17:24:02 +03:00
|
|
|
return (ENXIO);
|
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev)) {
|
2006-02-07 12:13:02 +03:00
|
|
|
wsevent_init(&sc->evar, l->l_proc);
|
2002-06-27 03:05:33 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (WSDISPLAYSCREEN(dev) >= WSDISPLAY_MAXSCREEN)
|
|
|
|
return (ENXIO);
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
1998-03-22 17:24:02 +03:00
|
|
|
return (ENXIO);
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (WSSCREEN_HAS_TTY(scr)) {
|
|
|
|
tp = scr->scr_tty;
|
|
|
|
tp->t_oproc = wsdisplaystart;
|
|
|
|
tp->t_param = wsdisplayparam;
|
|
|
|
tp->t_dev = dev;
|
|
|
|
newopen = (tp->t_state & TS_ISOPEN) == 0;
|
2006-10-01 23:28:43 +04:00
|
|
|
|
|
|
|
if (kauth_authorize_device_tty(l->l_cred,
|
|
|
|
KAUTH_DEVICE_TTY_OPEN, tp))
|
|
|
|
return (EBUSY);
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (newopen) {
|
|
|
|
ttychars(tp);
|
|
|
|
tp->t_iflag = TTYDEF_IFLAG;
|
|
|
|
tp->t_oflag = TTYDEF_OFLAG;
|
|
|
|
tp->t_cflag = TTYDEF_CFLAG;
|
|
|
|
tp->t_lflag = TTYDEF_LFLAG;
|
|
|
|
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
|
|
|
|
wsdisplayparam(tp, &tp->t_termios);
|
|
|
|
ttsetwater(tp);
|
2006-10-01 23:28:43 +04:00
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
tp->t_state |= TS_CARR_ON;
|
|
|
|
|
2000-11-02 03:01:44 +03:00
|
|
|
error = ((*tp->t_linesw->l_open)(dev, tp));
|
1998-06-12 02:13:52 +04:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (newopen && WSSCREEN_HAS_EMULATOR(scr)) {
|
|
|
|
/* set window sizes as appropriate, and reset
|
|
|
|
the emulation */
|
|
|
|
tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows;
|
|
|
|
tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols;
|
|
|
|
|
|
|
|
/* wsdisplay_set_emulation() */
|
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
scr->scr_flags |= SCR_OPEN;
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplayclose(dev_t dev, int flag, int mode, struct lwp *l)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
device_t dv;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
dv = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
|
|
|
sc = device_private(dv);
|
1999-01-09 18:42:34 +03:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev)) {
|
|
|
|
wsevent_fini(&sc->evar);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (WSSCREEN_HAS_TTY(scr)) {
|
1998-03-22 17:24:02 +03:00
|
|
|
if (scr->scr_hold_screen) {
|
|
|
|
int s;
|
|
|
|
|
|
|
|
/* XXX RESET KEYBOARD LEDS, etc. */
|
|
|
|
s = spltty(); /* avoid conflict with keyboard */
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_kbdholdscreen(dv, 0);
|
1998-03-22 17:24:02 +03:00
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
tp = scr->scr_tty;
|
2000-11-02 03:01:44 +03:00
|
|
|
(*tp->t_linesw->l_close)(tp, flag);
|
1998-03-22 17:24:02 +03:00
|
|
|
ttyclose(tp);
|
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
if (scr->scr_syncops)
|
|
|
|
(*scr->scr_syncops->destroy)(scr->scr_synccookie);
|
|
|
|
|
1999-01-14 14:40:58 +03:00
|
|
|
if (WSSCREEN_HAS_EMULATOR(scr)) {
|
1998-06-12 02:13:52 +04:00
|
|
|
scr->scr_flags &= ~SCR_GRAPHICS;
|
1999-01-17 18:56:33 +03:00
|
|
|
(*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
|
|
|
|
WSEMUL_RESET);
|
|
|
|
if (wsdisplay_clearonclose)
|
1999-01-14 14:40:58 +03:00
|
|
|
(*scr->scr_dconf->wsemul->reset)
|
1999-01-17 18:56:33 +03:00
|
|
|
(scr->scr_dconf->wsemulcookie,
|
|
|
|
WSEMUL_CLEARSCREEN);
|
1999-01-14 14:40:58 +03:00
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
if (scr->scr_rawkbd) {
|
|
|
|
int kbmode = WSKBD_TRANSLATED;
|
2001-10-24 18:07:31 +04:00
|
|
|
(void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE,
|
2007-03-04 08:59:00 +03:00
|
|
|
(void *)&kbmode, 0, l);
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
scr->scr_flags &= ~SCR_OPEN;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplayread(dev_t dev, struct uio *uio, int flag)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
|
|
|
struct wsscreen *scr;
|
2002-06-27 03:05:33 +04:00
|
|
|
int error;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
1999-01-09 18:42:34 +03:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev)) {
|
|
|
|
error = wsevent_read(&sc->evar, uio, flag);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (ENXIO);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (!WSSCREEN_HAS_TTY(scr))
|
1998-03-22 17:24:02 +03:00
|
|
|
return (ENODEV);
|
|
|
|
|
|
|
|
tp = scr->scr_tty;
|
2000-11-02 03:01:44 +03:00
|
|
|
return ((*tp->t_linesw->l_read)(tp, uio, flag));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplaywrite(dev_t dev, struct uio *uio, int flag)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
1999-01-09 18:42:34 +03:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev)) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (ENXIO);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (!WSSCREEN_HAS_TTY(scr))
|
1998-03-22 17:24:02 +03:00
|
|
|
return (ENODEV);
|
|
|
|
|
|
|
|
tp = scr->scr_tty;
|
2000-11-02 03:01:44 +03:00
|
|
|
return ((*tp->t_linesw->l_write)(tp, uio, flag));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
2001-05-02 14:32:08 +04:00
|
|
|
int
|
2005-12-11 15:16:03 +03:00
|
|
|
wsdisplaypoll(dev_t dev, int events, struct lwp *l)
|
2001-05-02 14:32:08 +04:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
2001-05-02 14:32:08 +04:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev))
|
2005-12-11 15:16:03 +03:00
|
|
|
return (wsevent_poll(&sc->evar, events, l));
|
2002-06-27 03:05:33 +04:00
|
|
|
|
2001-05-02 14:32:08 +04:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (0);
|
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
2005-06-21 18:01:11 +04:00
|
|
|
return (POLLHUP);
|
2001-05-02 14:32:08 +04:00
|
|
|
|
|
|
|
if (!WSSCREEN_HAS_TTY(scr))
|
2005-06-21 18:01:11 +04:00
|
|
|
return (POLLERR);
|
2001-05-02 14:32:08 +04:00
|
|
|
|
|
|
|
tp = scr->scr_tty;
|
2005-12-11 15:16:03 +03:00
|
|
|
return ((*tp->t_linesw->l_poll)(tp, events, l));
|
2001-05-02 14:32:08 +04:00
|
|
|
}
|
|
|
|
|
2002-10-23 13:10:23 +04:00
|
|
|
int
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplaykqfilter(dev_t dev, struct knote *kn)
|
2002-10-23 13:10:23 +04:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc;
|
2002-10-23 13:10:23 +04:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
2007-10-18 22:09:52 +04:00
|
|
|
|
2002-10-23 13:10:23 +04:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (1);
|
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (1);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2002-10-23 13:10:23 +04:00
|
|
|
|
|
|
|
if (WSSCREEN_HAS_TTY(scr))
|
|
|
|
return (ttykqfilter(dev, kn));
|
|
|
|
else
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
struct tty *
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplaytty(dev_t dev)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
1999-01-09 18:42:34 +03:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev))
|
|
|
|
panic("wsdisplaytty() on status device");
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
panic("wsdisplaytty() on ctl device");
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return NULL;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
return (scr->scr_tty);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2007-03-04 08:59:00 +03:00
|
|
|
wsdisplayioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
device_t dv;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct tty *tp;
|
2001-01-04 02:00:24 +03:00
|
|
|
int error;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
dv = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
|
|
|
sc = device_private(dv);
|
1999-01-09 18:42:34 +03:00
|
|
|
|
1999-10-19 04:03:18 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_USL
|
2007-10-18 22:09:52 +04:00
|
|
|
error = wsdisplay_usl_ioctl1(dv, cmd, data, flag, l);
|
2002-03-17 22:40:26 +03:00
|
|
|
if (error != EPASSTHROUGH)
|
1999-10-19 04:03:18 +04:00
|
|
|
return (error);
|
|
|
|
#endif
|
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev))
|
2005-12-11 15:16:03 +03:00
|
|
|
return (wsdisplay_stat_ioctl(sc, cmd, data, flag, l));
|
2002-06-27 03:05:33 +04:00
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
2005-12-11 15:16:03 +03:00
|
|
|
return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, l));
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (ENXIO);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (WSSCREEN_HAS_TTY(scr)) {
|
1998-03-22 17:24:02 +03:00
|
|
|
tp = scr->scr_tty;
|
|
|
|
|
|
|
|
/* printf("disc\n"); */
|
|
|
|
/* do the line discipline ioctls first */
|
2005-12-11 15:16:03 +03:00
|
|
|
error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
|
2002-03-17 22:40:26 +03:00
|
|
|
if (error != EPASSTHROUGH)
|
1999-07-29 22:20:02 +04:00
|
|
|
return (error);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
/* printf("tty\n"); */
|
|
|
|
/* then the tty ioctls */
|
2005-12-11 15:16:03 +03:00
|
|
|
error = ttioctl(tp, cmd, data, flag, l);
|
2002-03-17 22:40:26 +03:00
|
|
|
if (error != EPASSTHROUGH)
|
1999-07-29 22:20:02 +04:00
|
|
|
return (error);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_USL
|
2005-12-11 15:16:03 +03:00
|
|
|
error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, l);
|
2002-03-17 22:40:26 +03:00
|
|
|
if (error != EPASSTHROUGH)
|
1998-06-12 02:13:52 +04:00
|
|
|
return (error);
|
|
|
|
#endif
|
|
|
|
|
2005-12-11 15:16:03 +03:00
|
|
|
return (wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, l));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
2000-10-01 07:29:12 +04:00
|
|
|
int
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_param(device_t dv, u_long cmd, struct wsdisplay_param *dp)
|
2000-10-01 07:29:12 +04:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
2006-11-06 22:51:12 +03:00
|
|
|
return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
|
2006-04-13 05:15:27 +04:00
|
|
|
sc->sc_focus->scr_dconf->emulcookie,
|
2007-03-04 08:59:00 +03:00
|
|
|
cmd, (void *)dp, 0, NULL));
|
2000-10-01 07:29:12 +04:00
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
|
2007-03-04 08:59:00 +03:00
|
|
|
u_long cmd, void *data, int flag, struct lwp *l)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1998-06-12 02:13:52 +04:00
|
|
|
int error;
|
1999-01-13 19:21:02 +03:00
|
|
|
char namebuf[16];
|
|
|
|
struct wsdisplay_font fd;
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
struct wsdisplay_scroll_data *ksdp, *usdp;
|
|
|
|
#endif
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1999-05-17 20:53:43 +04:00
|
|
|
#if NWSKBD > 0
|
2001-10-24 18:07:31 +04:00
|
|
|
struct wsevsrc *inp;
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
1999-07-29 22:20:02 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case WSKBDIO_SETMODE:
|
|
|
|
scr->scr_rawkbd = (*(int *)data == WSKBD_RAW);
|
|
|
|
return (wsdisplay_update_rawkbd(sc, scr));
|
|
|
|
case WSKBDIO_GETMODE:
|
|
|
|
*(int *)data = (scr->scr_rawkbd ?
|
|
|
|
WSKBD_RAW : WSKBD_TRANSLATED);
|
|
|
|
return (0);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
1999-07-29 22:20:02 +04:00
|
|
|
#endif
|
2001-10-24 18:07:31 +04:00
|
|
|
inp = sc->sc_input;
|
2001-10-28 13:30:22 +03:00
|
|
|
if (inp == NULL)
|
|
|
|
return (ENXIO);
|
2005-12-11 15:16:03 +03:00
|
|
|
error = wsevsrc_display_ioctl(inp, cmd, data, flag, l);
|
2002-03-17 22:40:26 +03:00
|
|
|
if (error != EPASSTHROUGH)
|
1999-07-29 22:20:02 +04:00
|
|
|
return (error);
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif /* NWSKBD > 0 */
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case WSDISPLAYIO_GMODE:
|
2004-07-21 00:28:20 +04:00
|
|
|
if (scr->scr_flags & SCR_GRAPHICS) {
|
|
|
|
if (scr->scr_flags & SCR_DUMBFB)
|
|
|
|
*(u_int *)data = WSDISPLAYIO_MODE_DUMBFB;
|
|
|
|
else
|
|
|
|
*(u_int *)data = WSDISPLAYIO_MODE_MAPPED;
|
|
|
|
} else
|
|
|
|
*(u_int *)data = WSDISPLAYIO_MODE_EMUL;
|
1998-03-22 17:24:02 +03:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
case WSDISPLAYIO_SMODE:
|
1998-06-12 02:13:52 +04:00
|
|
|
#define d (*(int *)data)
|
|
|
|
if (d != WSDISPLAYIO_MODE_EMUL &&
|
2004-07-21 00:28:20 +04:00
|
|
|
d != WSDISPLAYIO_MODE_MAPPED &&
|
|
|
|
d != WSDISPLAYIO_MODE_DUMBFB)
|
1998-03-22 17:24:02 +03:00
|
|
|
return (EINVAL);
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
if (WSSCREEN_HAS_EMULATOR(scr)) {
|
|
|
|
scr->scr_flags &= ~SCR_GRAPHICS;
|
2004-07-21 00:28:20 +04:00
|
|
|
if (d == WSDISPLAYIO_MODE_MAPPED ||
|
|
|
|
d == WSDISPLAYIO_MODE_DUMBFB)
|
|
|
|
scr->scr_flags |= SCR_GRAPHICS |
|
|
|
|
((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0);
|
1998-06-12 02:13:52 +04:00
|
|
|
} else if (d == WSDISPLAYIO_MODE_EMUL)
|
|
|
|
return (EINVAL);
|
2000-12-30 04:41:51 +03:00
|
|
|
|
2006-04-13 05:15:27 +04:00
|
|
|
(void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie, cmd, data, flag, l);
|
2000-12-30 04:41:51 +03:00
|
|
|
|
1998-07-23 18:33:01 +04:00
|
|
|
return (0);
|
1998-06-12 02:13:52 +04:00
|
|
|
#undef d
|
1999-01-13 19:21:02 +03:00
|
|
|
|
2004-05-29 01:42:29 +04:00
|
|
|
#ifdef WSDISPLAY_SCROLLSUPPORT
|
|
|
|
#define SETSCROLLLINES(dstp, srcp, dfltp) \
|
|
|
|
do { \
|
|
|
|
(dstp)->fastlines = ((srcp)->which & \
|
|
|
|
WSDISPLAY_SCROLL_DOFASTLINES) ? \
|
|
|
|
(srcp)->fastlines : (dfltp)->fastlines; \
|
|
|
|
(dstp)->slowlines = ((srcp)->which & \
|
|
|
|
WSDISPLAY_SCROLL_DOSLOWLINES) ? \
|
|
|
|
(srcp)->slowlines : (dfltp)->slowlines; \
|
|
|
|
(dstp)->which = WSDISPLAY_SCROLL_DOALL; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
case WSDISPLAYIO_DSSCROLL:
|
|
|
|
usdp = (struct wsdisplay_scroll_data *)data;
|
|
|
|
ksdp = &sc->sc_scroll_values;
|
|
|
|
SETSCROLLLINES(ksdp, usdp, ksdp);
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case WSDISPLAYIO_DGSCROLL:
|
|
|
|
usdp = (struct wsdisplay_scroll_data *)data;
|
|
|
|
ksdp = &sc->sc_scroll_values;
|
|
|
|
SETSCROLLLINES(usdp, ksdp, ksdp);
|
|
|
|
return (0);
|
2004-06-03 23:04:58 +04:00
|
|
|
#else
|
|
|
|
case WSDISPLAYIO_DSSCROLL:
|
|
|
|
case WSDISPLAYIO_DGSCROLL:
|
|
|
|
return ENODEV;
|
2004-05-29 01:42:29 +04:00
|
|
|
#endif
|
|
|
|
|
2002-04-07 13:25:47 +04:00
|
|
|
case WSDISPLAYIO_SFONT:
|
1999-01-13 19:21:02 +03:00
|
|
|
#define d ((struct wsdisplay_usefontdata *)data)
|
|
|
|
if (!sc->sc_accessops->load_font)
|
1998-03-22 17:24:02 +03:00
|
|
|
return (EINVAL);
|
1999-01-13 19:21:02 +03:00
|
|
|
if (d->name) {
|
|
|
|
error = copyinstr(d->name, namebuf, sizeof(namebuf), 0);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
fd.name = namebuf;
|
|
|
|
} else
|
|
|
|
fd.name = 0;
|
|
|
|
fd.data = 0;
|
|
|
|
error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie, &fd);
|
1999-01-17 18:56:33 +03:00
|
|
|
if (!error && WSSCREEN_HAS_EMULATOR(scr))
|
1999-01-13 19:21:02 +03:00
|
|
|
(*scr->scr_dconf->wsemul->reset)
|
|
|
|
(scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT);
|
1998-03-22 17:24:02 +03:00
|
|
|
return (error);
|
1999-01-13 19:21:02 +03:00
|
|
|
#undef d
|
2002-06-27 03:05:33 +04:00
|
|
|
|
Implement support to dynamically change wscons console and kernel colors.
Two new ioctls are added to the wsdisplay device, named WSDISPLAY_GMSGATTRS
and WSDISPLAY_SMSGATTRS, used to retrieve the actual values and set them,
respectively (the name, if you are wondering, comes from "message attributes").
A new emulop is added to the underlying display driver (only vga, for now)
which sets the new attribute for the whole screen, without having to clear
it. This is optional, which means that this also works with other drivers
that don't have this new operation.
Five new kernel options have been added, although only documented in
i386 kernels (for now):
- WSDISPLAY_CUSTOM_OUTPUT, which enables the ioctls described above to
change the colors dynamically from userland. This is enabled by default
in the GENERIC kernel (as well as others) but disabled on all INSTALL*
kernels (as this feature is useless there).
- WS_DEFAULT_COLATTR, WS_DEFAULT_MONOATTR, WS_DEFAULT_BG and WS_DEFAULT_FG,
which specify the default colors for the console at boot time. These have
the same meaning as the (already existing) WS_KERNEL_* variables.
wsconsctl is modified to add msg.default.{attrs,bg,fg} and
msg.kernel.{attrs,bg,fg} to the display part, so that colors can be changed
after boot.
Tested on NetBSD/i386 with vga (and vga in mono mode), and on NetBSD/mac68k.
No objections in tech-kern@.
2004-07-28 16:34:02 +04:00
|
|
|
#ifdef WSDISPLAY_CUSTOM_OUTPUT
|
|
|
|
case WSDISPLAYIO_GMSGATTRS:
|
|
|
|
#define d ((struct wsdisplay_msgattrs *)data)
|
|
|
|
(*scr->scr_dconf->wsemul->getmsgattrs)
|
|
|
|
(scr->scr_dconf->wsemulcookie, d);
|
|
|
|
return (0);
|
|
|
|
#undef d
|
|
|
|
|
|
|
|
case WSDISPLAYIO_SMSGATTRS: {
|
|
|
|
#define d ((struct wsdisplay_msgattrs *)data)
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < WSDISPLAY_MAXSCREEN; i++)
|
|
|
|
if (sc->sc_scr[i] != NULL)
|
|
|
|
(*sc->sc_scr[i]->scr_dconf->wsemul->setmsgattrs)
|
|
|
|
(sc->sc_scr[i]->scr_dconf->wsemulcookie,
|
|
|
|
sc->sc_scr[i]->scr_dconf->scrdata,
|
|
|
|
d);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
#undef d
|
|
|
|
#else
|
|
|
|
case WSDISPLAYIO_GMSGATTRS:
|
|
|
|
case WSDISPLAYIO_SMSGATTRS:
|
|
|
|
return (ENODEV);
|
|
|
|
#endif
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check ioctls for display */
|
2006-04-13 05:15:27 +04:00
|
|
|
return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie, cmd, data, flag, l));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
int
|
2007-03-04 08:59:00 +03:00
|
|
|
wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, void *data,
|
2006-11-16 04:32:37 +03:00
|
|
|
int flag, struct lwp *l)
|
2002-06-27 03:05:33 +04:00
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
case WSDISPLAYIO_GETACTIVESCREEN:
|
|
|
|
*(int*)data = wsdisplay_getactivescreen(sc);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (EPASSTHROUGH);
|
|
|
|
}
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
int
|
2007-03-04 08:59:00 +03:00
|
|
|
wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, void *data,
|
2005-12-11 15:16:03 +03:00
|
|
|
int flag, struct lwp *l)
|
1999-01-09 18:42:34 +03:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
char *type, typebuf[16], *emul, emulbuf[16];
|
2005-05-30 01:56:35 +04:00
|
|
|
void *tbuf;
|
2001-08-05 15:26:52 +04:00
|
|
|
u_int fontsz;
|
1999-07-29 22:20:02 +04:00
|
|
|
#if defined(COMPAT_14) && NWSKBD > 0
|
|
|
|
struct wsmux_device wsmuxdata;
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif
|
2001-10-24 18:07:31 +04:00
|
|
|
#if NWSKBD > 0
|
|
|
|
struct wsevsrc *inp;
|
|
|
|
#endif
|
1999-01-09 18:42:34 +03:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case WSDISPLAYIO_ADDSCREEN:
|
|
|
|
#define d ((struct wsdisplay_addscreendata *)data)
|
|
|
|
if (d->screentype) {
|
|
|
|
error = copyinstr(d->screentype, typebuf,
|
|
|
|
sizeof(typebuf), 0);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
type = typebuf;
|
|
|
|
} else
|
|
|
|
type = 0;
|
|
|
|
if (d->emul) {
|
1999-07-29 22:20:02 +04:00
|
|
|
error = copyinstr(d->emul, emulbuf, sizeof(emulbuf),0);
|
1999-01-09 18:42:34 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
emul = emulbuf;
|
|
|
|
} else
|
|
|
|
emul = 0;
|
|
|
|
|
1999-09-16 22:16:51 +04:00
|
|
|
if ((error = wsdisplay_addscreen(sc, d->idx, type, emul)) == 0)
|
|
|
|
wsdisplay_addscreen_print(sc, d->idx, 0);
|
|
|
|
return (error);
|
1999-01-09 18:42:34 +03:00
|
|
|
#undef d
|
|
|
|
case WSDISPLAYIO_DELSCREEN:
|
|
|
|
#define d ((struct wsdisplay_delscreendata *)data)
|
|
|
|
return (wsdisplay_delscreen(sc, d->idx, d->flags));
|
|
|
|
#undef d
|
1999-01-13 19:21:02 +03:00
|
|
|
case WSDISPLAYIO_LDFONT:
|
|
|
|
#define d ((struct wsdisplay_font *)data)
|
|
|
|
if (!sc->sc_accessops->load_font)
|
|
|
|
return (EINVAL);
|
|
|
|
if (d->name) {
|
|
|
|
error = copyinstr(d->name, typebuf, sizeof(typebuf), 0);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
d->name = typebuf;
|
|
|
|
} else
|
|
|
|
d->name = "loaded"; /* ??? */
|
2001-08-05 15:26:52 +04:00
|
|
|
fontsz = d->fontheight * d->stride * d->numchars;
|
|
|
|
if (fontsz > WSDISPLAY_MAXFONTSZ)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2005-05-30 01:56:35 +04:00
|
|
|
tbuf = malloc(fontsz, M_DEVBUF, M_WAITOK);
|
|
|
|
error = copyin(d->data, tbuf, fontsz);
|
1999-01-13 19:21:02 +03:00
|
|
|
if (error) {
|
2005-05-30 01:56:35 +04:00
|
|
|
free(tbuf, M_DEVBUF);
|
1999-01-13 19:21:02 +03:00
|
|
|
return (error);
|
|
|
|
}
|
2005-05-30 01:56:35 +04:00
|
|
|
d->data = tbuf;
|
1999-01-13 19:21:02 +03:00
|
|
|
error =
|
|
|
|
(*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d);
|
2005-05-30 01:56:35 +04:00
|
|
|
free(tbuf, M_DEVBUF);
|
1999-01-13 19:21:02 +03:00
|
|
|
#undef d
|
|
|
|
return (error);
|
1999-05-17 20:53:43 +04:00
|
|
|
|
|
|
|
#if NWSKBD > 0
|
1999-07-29 22:20:02 +04:00
|
|
|
#ifdef COMPAT_14
|
|
|
|
case _O_WSDISPLAYIO_SETKEYBOARD:
|
1999-05-15 18:22:46 +04:00
|
|
|
#define d ((struct wsdisplay_kbddata *)data)
|
2001-10-28 13:30:22 +03:00
|
|
|
inp = sc->sc_input;
|
|
|
|
if (inp == NULL)
|
|
|
|
return (ENXIO);
|
1999-05-15 18:22:46 +04:00
|
|
|
switch (d->op) {
|
1999-07-29 22:20:02 +04:00
|
|
|
case _O_WSDISPLAY_KBD_ADD:
|
1999-05-15 18:22:46 +04:00
|
|
|
if (d->idx == -1) {
|
|
|
|
d->idx = wskbd_pickfree();
|
|
|
|
if (d->idx == -1)
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
1999-07-29 22:20:02 +04:00
|
|
|
wsmuxdata.type = WSMUX_KBD;
|
|
|
|
wsmuxdata.idx = d->idx;
|
2001-10-28 13:30:22 +03:00
|
|
|
return (wsevsrc_ioctl(inp, WSMUX_ADD_DEVICE,
|
2005-12-11 15:16:03 +03:00
|
|
|
&wsmuxdata, flag, l));
|
1999-07-29 22:20:02 +04:00
|
|
|
case _O_WSDISPLAY_KBD_DEL:
|
|
|
|
wsmuxdata.type = WSMUX_KBD;
|
|
|
|
wsmuxdata.idx = d->idx;
|
2001-10-28 13:30:22 +03:00
|
|
|
return (wsevsrc_ioctl(inp, WSMUX_REMOVE_DEVICE,
|
2005-12-11 15:16:03 +03:00
|
|
|
&wsmuxdata, flag, l));
|
1999-05-15 18:22:46 +04:00
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
#undef d
|
1999-07-29 22:20:02 +04:00
|
|
|
#endif
|
|
|
|
|
2001-10-24 18:07:31 +04:00
|
|
|
case WSMUXIO_ADD_DEVICE:
|
1999-07-29 22:20:02 +04:00
|
|
|
#define d ((struct wsmux_device *)data)
|
|
|
|
if (d->idx == -1 && d->type == WSMUX_KBD)
|
|
|
|
d->idx = wskbd_pickfree();
|
|
|
|
#undef d
|
|
|
|
/* fall into */
|
2001-10-24 18:07:31 +04:00
|
|
|
case WSMUXIO_INJECTEVENT:
|
|
|
|
case WSMUXIO_REMOVE_DEVICE:
|
|
|
|
case WSMUXIO_LIST_DEVICES:
|
|
|
|
inp = sc->sc_input;
|
2001-10-28 13:30:22 +03:00
|
|
|
if (inp == NULL)
|
|
|
|
return (ENXIO);
|
2005-12-11 15:16:03 +03:00
|
|
|
return (wsevsrc_ioctl(inp, cmd, data, flag, l));
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif /* NWSKBD > 0 */
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
}
|
2002-03-17 22:40:26 +03:00
|
|
|
return (EPASSTHROUGH);
|
1999-01-09 18:42:34 +03:00
|
|
|
}
|
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
int
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_stat_inject(device_t dv, u_int type, int value)
|
2002-06-27 03:05:33 +04:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
2002-06-27 03:05:33 +04:00
|
|
|
struct wseventvar *evar;
|
2006-02-07 12:13:02 +03:00
|
|
|
struct wscons_event event;
|
2002-06-27 03:05:33 +04:00
|
|
|
|
|
|
|
evar = &sc->evar;
|
|
|
|
|
|
|
|
if (evar == NULL)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (evar->q == NULL)
|
|
|
|
return (1);
|
|
|
|
|
2006-02-07 12:13:02 +03:00
|
|
|
event.type = type;
|
|
|
|
event.value = value;
|
|
|
|
if (wsevent_inject(evar, &event, 1) != 0) {
|
2002-06-27 03:05:33 +04:00
|
|
|
log(LOG_WARNING, "wsdisplay: event queue overflow\n");
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2000-06-26 08:55:19 +04:00
|
|
|
paddr_t
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplaymmap(dev_t dev, off_t offset, int prot)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc;
|
1998-06-12 02:13:52 +04:00
|
|
|
struct wsscreen *scr;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
2007-10-18 22:09:52 +04:00
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
if (ISWSDISPLAYSTAT(dev))
|
|
|
|
return (-1);
|
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (ISWSDISPLAYCTL(dev))
|
|
|
|
return (-1);
|
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
|
|
|
|
return (-1);
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
if (!(scr->scr_flags & SCR_GRAPHICS))
|
1998-03-22 17:24:02 +03:00
|
|
|
return (-1);
|
1998-06-12 02:13:52 +04:00
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
/* pass mmap to display */
|
2006-04-13 05:15:27 +04:00
|
|
|
return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie, offset, prot));
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplaystart(struct tty *tp)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct wsscreen *scr;
|
2000-03-30 16:41:09 +04:00
|
|
|
int s, n;
|
2005-05-30 01:56:35 +04:00
|
|
|
u_char *tbuf;
|
2005-02-27 03:26:58 +03:00
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
s = spltty();
|
|
|
|
if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
|
|
|
|
splx(s);
|
|
|
|
return;
|
|
|
|
}
|
2008-06-11 20:17:01 +04:00
|
|
|
sc = device_lookup_private(&wsdisplay_cd, WSDISPLAYUNIT(tp->t_dev));
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)]) == NULL) {
|
|
|
|
splx(s);
|
2005-02-27 03:26:58 +03:00
|
|
|
return;
|
2003-09-21 22:47:59 +04:00
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
if (scr->scr_hold_screen) {
|
|
|
|
tp->t_state |= TS_TIMEOUT;
|
|
|
|
splx(s);
|
|
|
|
return;
|
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
tp->t_state |= TS_BUSY;
|
1998-03-22 17:24:02 +03:00
|
|
|
splx(s);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
1999-02-08 17:48:07 +03:00
|
|
|
/*
|
|
|
|
* Drain output from ring buffer.
|
2005-02-27 03:26:58 +03:00
|
|
|
* The output will normally be in one contiguous chunk, but when the
|
|
|
|
* ring wraps, it will be in two pieces.. one at the end of the ring,
|
|
|
|
* the other at the start. For performance, rather than loop here,
|
|
|
|
* we output one chunk, see if there's another one, and if so, output
|
1999-02-08 17:48:07 +03:00
|
|
|
* it too.
|
|
|
|
*/
|
|
|
|
|
|
|
|
n = ndqb(&tp->t_outq, 0);
|
2005-05-30 01:56:35 +04:00
|
|
|
tbuf = tp->t_outq.c_cf;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-12-15 17:25:59 +03:00
|
|
|
if (!(scr->scr_flags & SCR_GRAPHICS)) {
|
|
|
|
KASSERT(WSSCREEN_HAS_EMULATOR(scr));
|
1998-03-22 17:24:02 +03:00
|
|
|
(*scr->scr_dconf->wsemul->output)(scr->scr_dconf->wsemulcookie,
|
2005-05-30 01:56:35 +04:00
|
|
|
tbuf, n, 0);
|
1999-02-08 17:48:07 +03:00
|
|
|
}
|
|
|
|
ndflush(&tp->t_outq, n);
|
|
|
|
|
|
|
|
if ((n = ndqb(&tp->t_outq, 0)) > 0) {
|
2005-05-30 01:56:35 +04:00
|
|
|
tbuf = tp->t_outq.c_cf;
|
1999-02-08 17:48:07 +03:00
|
|
|
|
|
|
|
if (!(scr->scr_flags & SCR_GRAPHICS)) {
|
|
|
|
KASSERT(WSSCREEN_HAS_EMULATOR(scr));
|
2003-09-21 22:47:59 +04:00
|
|
|
(*scr->scr_dconf->wsemul->output)
|
2005-05-30 01:56:35 +04:00
|
|
|
(scr->scr_dconf->wsemulcookie, tbuf, n, 0);
|
1999-02-08 17:48:07 +03:00
|
|
|
}
|
|
|
|
ndflush(&tp->t_outq, n);
|
1998-12-15 17:25:59 +03:00
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
s = spltty();
|
|
|
|
tp->t_state &= ~TS_BUSY;
|
|
|
|
/* Come back if there's more to do */
|
2007-11-19 21:51:36 +03:00
|
|
|
if (ttypull(tp)) {
|
1998-03-22 17:24:02 +03:00
|
|
|
tp->t_state |= TS_TIMEOUT;
|
2007-10-18 22:54:56 +04:00
|
|
|
callout_schedule(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplaystop(struct tty *tp, int flag)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s = spltty();
|
|
|
|
if (ISSET(tp->t_state, TS_BUSY))
|
|
|
|
if (!ISSET(tp->t_state, TS_TTSTOP))
|
|
|
|
SET(tp->t_state, TS_FLUSH);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set line parameters. */
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplayparam(struct tty *tp, struct termios *t)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
tp->t_ispeed = t->c_ispeed;
|
|
|
|
tp->t_ospeed = t->c_ospeed;
|
|
|
|
tp->t_cflag = t->c_cflag;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Callbacks for the emulation code.
|
|
|
|
*/
|
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_emulbell(void *v)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsscreen *scr = v;
|
|
|
|
|
|
|
|
if (scr == NULL) /* console, before real attach */
|
|
|
|
return;
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (scr->scr_flags & SCR_GRAPHICS) /* can this happen? */
|
1998-03-22 17:24:02 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
(void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL, NULL,
|
|
|
|
FWRITE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_emulinput(void *v, const u_char *data, u_int count)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsscreen *scr = v;
|
|
|
|
struct tty *tp;
|
|
|
|
|
|
|
|
if (v == NULL) /* console, before real attach */
|
|
|
|
return;
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (scr->scr_flags & SCR_GRAPHICS) /* XXX can't happen */
|
|
|
|
return;
|
|
|
|
if (!WSSCREEN_HAS_TTY(scr))
|
1998-03-22 17:24:02 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
tp = scr->scr_tty;
|
|
|
|
while (count-- > 0)
|
2000-11-02 03:01:44 +03:00
|
|
|
(*tp->t_linesw->l_rint)(*data++, tp);
|
2003-01-20 05:16:55 +03:00
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Calls from the keyboard interface.
|
|
|
|
*/
|
|
|
|
void
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_kbdinput(device_t dv, keysym_t ks)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
2005-05-30 01:56:35 +04:00
|
|
|
const char *dp;
|
1998-06-15 21:48:32 +04:00
|
|
|
int count;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct tty *tp;
|
|
|
|
|
|
|
|
KASSERT(sc != NULL);
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
scr = sc->sc_focus;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1999-01-09 18:42:34 +03:00
|
|
|
if (!scr || !WSSCREEN_HAS_TTY(scr))
|
1998-03-22 17:24:02 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
tp = scr->scr_tty;
|
1998-06-15 21:48:32 +04:00
|
|
|
|
|
|
|
if (KS_GROUP(ks) == KS_GROUP_Ascii)
|
2000-11-02 03:01:44 +03:00
|
|
|
(*tp->t_linesw->l_rint)(KS_VALUE(ks), tp);
|
1998-06-15 21:48:32 +04:00
|
|
|
else if (WSSCREEN_HAS_EMULATOR(scr)) {
|
|
|
|
count = (*scr->scr_dconf->wsemul->translate)
|
|
|
|
(scr->scr_dconf->wsemulcookie, ks, &dp);
|
|
|
|
while (count-- > 0)
|
2000-11-02 03:01:44 +03:00
|
|
|
(*tp->t_linesw->l_rint)(*dp++, tp);
|
1998-06-15 21:48:32 +04:00
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
2001-10-24 18:07:31 +04:00
|
|
|
#if defined(WSDISPLAY_COMPAT_RAWKBD)
|
1998-06-12 22:15:27 +04:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr)
|
1998-06-12 22:15:27 +04:00
|
|
|
{
|
2001-10-24 18:07:31 +04:00
|
|
|
#if NWSKBD > 0
|
1999-01-26 17:22:14 +03:00
|
|
|
int s, raw, data, error;
|
2001-10-24 18:07:31 +04:00
|
|
|
struct wsevsrc *inp;
|
|
|
|
|
1998-06-12 22:15:27 +04:00
|
|
|
s = spltty();
|
|
|
|
|
1999-01-26 17:22:14 +03:00
|
|
|
raw = (scr ? scr->scr_rawkbd : 0);
|
|
|
|
|
1999-07-29 22:20:02 +04:00
|
|
|
if (scr != sc->sc_focus ||
|
1999-01-26 17:22:14 +03:00
|
|
|
sc->sc_rawkbd == raw) {
|
1998-06-12 22:15:27 +04:00
|
|
|
splx(s);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1999-07-29 22:20:02 +04:00
|
|
|
data = raw ? WSKBD_RAW : WSKBD_TRANSLATED;
|
2001-10-24 18:07:31 +04:00
|
|
|
inp = sc->sc_input;
|
2006-06-28 20:19:01 +04:00
|
|
|
if (inp == NULL) {
|
|
|
|
splx(s);
|
2001-10-28 13:30:22 +03:00
|
|
|
return (ENXIO);
|
2006-06-28 20:19:01 +04:00
|
|
|
}
|
2006-04-13 00:13:21 +04:00
|
|
|
error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0);
|
1998-06-12 22:15:27 +04:00
|
|
|
if (!error)
|
1999-01-26 17:22:14 +03:00
|
|
|
sc->sc_rawkbd = raw;
|
1998-06-12 22:15:27 +04:00
|
|
|
splx(s);
|
|
|
|
return (error);
|
2001-10-24 18:07:31 +04:00
|
|
|
#else
|
|
|
|
return (0);
|
|
|
|
#endif
|
1998-06-12 22:15:27 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
static void
|
|
|
|
wsdisplay_switch3_cb(void *arg, int error, int waitok)
|
|
|
|
{
|
|
|
|
device_t dv = arg;
|
|
|
|
|
|
|
|
wsdisplay_switch3(dv, error, waitok);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
wsdisplay_switch3(device_t dv, int error, int waitok)
|
1999-01-26 17:22:14 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1999-01-26 17:22:14 +03:00
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch3: not switching\n");
|
1999-01-26 17:22:14 +03:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
no = sc->sc_screenwanted;
|
|
|
|
if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
|
|
|
|
panic("wsdisplay_switch3: invalid screen %d", no);
|
|
|
|
scr = sc->sc_scr[no];
|
|
|
|
if (!scr) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv,
|
|
|
|
"wsdisplay_switch3: screen %d disappeared\n", no);
|
1999-01-26 17:22:14 +03:00
|
|
|
error = ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
/* try to recover, avoid recursion */
|
|
|
|
|
2000-09-10 13:39:57 +04:00
|
|
|
if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch3: giving up\n");
|
1999-01-26 17:22:14 +03:00
|
|
|
sc->sc_focus = 0;
|
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
|
|
|
wsdisplay_update_rawkbd(sc, 0);
|
|
|
|
#endif
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_screenwanted = sc->sc_oldscreen;
|
2000-09-10 13:39:57 +04:00
|
|
|
sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch1(dv, 0, waitok));
|
1999-01-26 17:22:14 +03:00
|
|
|
}
|
|
|
|
|
2008-02-21 01:33:18 +03:00
|
|
|
if (scr->scr_syncops && !error)
|
|
|
|
sc->sc_flags |= SC_XATTACHED;
|
|
|
|
|
1999-01-26 17:22:14 +03:00
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
|
|
|
|
if (!error && (scr->scr_flags & SCR_WAITACTIVE))
|
|
|
|
wakeup(scr);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
static void
|
|
|
|
wsdisplay_switch2_cb(void *arg, int error, int waitok)
|
|
|
|
{
|
|
|
|
device_t dv = arg;
|
|
|
|
|
|
|
|
wsdisplay_switch2(dv, error, waitok);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
wsdisplay_switch2(device_t dv, int error, int waitok)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1998-06-12 02:13:52 +04:00
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch2: not switching\n");
|
1998-06-12 02:13:52 +04:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
no = sc->sc_screenwanted;
|
1998-04-07 17:43:16 +04:00
|
|
|
if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
|
1999-12-06 21:52:23 +03:00
|
|
|
panic("wsdisplay_switch2: invalid screen %d", no);
|
1998-06-12 02:13:52 +04:00
|
|
|
scr = sc->sc_scr[no];
|
|
|
|
if (!scr) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv,
|
|
|
|
"wsdisplay_switch2: screen %d disappeared\n", no);
|
1999-01-26 17:22:14 +03:00
|
|
|
error = ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
1999-12-06 21:52:23 +03:00
|
|
|
/* try to recover, avoid recursion */
|
|
|
|
|
2000-09-10 13:39:57 +04:00
|
|
|
if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch2: giving up\n");
|
1999-12-06 21:52:23 +03:00
|
|
|
sc->sc_focus = 0;
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_screenwanted = sc->sc_oldscreen;
|
2000-09-10 13:39:57 +04:00
|
|
|
sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch1(dv, 0, waitok));
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_focusidx = no;
|
|
|
|
sc->sc_focus = scr;
|
|
|
|
|
|
|
|
#ifdef WSDISPLAY_COMPAT_RAWKBD
|
1998-06-12 22:15:27 +04:00
|
|
|
(void) wsdisplay_update_rawkbd(sc, scr);
|
1998-06-12 02:13:52 +04:00
|
|
|
#endif
|
|
|
|
/* keyboard map??? */
|
|
|
|
|
2008-03-13 02:26:18 +03:00
|
|
|
if (scr->scr_syncops &&
|
|
|
|
!(sc->sc_isconsole && wsdisplay_cons_pollmode)) {
|
1999-01-26 17:22:14 +03:00
|
|
|
error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok,
|
2008-03-13 02:26:18 +03:00
|
|
|
wsdisplay_switch3_cb, dv);
|
1999-01-26 17:22:14 +03:00
|
|
|
if (error == EAGAIN) {
|
|
|
|
/* switch will be done asynchronously */
|
|
|
|
return (0);
|
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
1998-04-07 17:43:16 +04:00
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch3(dv, error, waitok));
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
static void
|
|
|
|
wsdisplay_switch1_cb(void *arg, int error, int waitok)
|
|
|
|
{
|
|
|
|
device_t dv = arg;
|
|
|
|
|
|
|
|
wsdisplay_switch1(dv, error, waitok);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
wsdisplay_switch1(device_t dv, int error, int waitok)
|
1999-12-06 21:52:23 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1999-12-06 21:52:23 +03:00
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch1: not switching\n");
|
1999-12-06 21:52:23 +03:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
no = sc->sc_screenwanted;
|
2000-09-10 13:39:57 +04:00
|
|
|
if (no == WSDISPLAY_NULLSCREEN) {
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
if (!error) {
|
2008-02-21 01:33:18 +03:00
|
|
|
sc->sc_flags &= ~SC_XATTACHED;
|
2000-09-10 13:39:57 +04:00
|
|
|
sc->sc_focus = 0;
|
|
|
|
}
|
|
|
|
wakeup(sc);
|
|
|
|
return (error);
|
|
|
|
}
|
1999-12-06 21:52:23 +03:00
|
|
|
if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
|
|
|
|
panic("wsdisplay_switch1: invalid screen %d", no);
|
|
|
|
scr = sc->sc_scr[no];
|
|
|
|
if (!scr) {
|
2007-10-18 22:09:52 +04:00
|
|
|
aprint_error_dev(dv, "wsdisplay_switch1: screen %d disappeared\n", no);
|
1999-12-06 21:52:23 +03:00
|
|
|
error = ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2008-02-21 01:33:18 +03:00
|
|
|
sc->sc_flags &= ~SC_XATTACHED;
|
|
|
|
|
1999-12-06 21:52:23 +03:00
|
|
|
error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie,
|
|
|
|
waitok,
|
2007-10-18 22:09:52 +04:00
|
|
|
sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsdisplay_switch2_cb, dv);
|
1999-12-06 21:52:23 +03:00
|
|
|
if (error == EAGAIN) {
|
|
|
|
/* switch will be done asynchronously */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch2(dv, error, waitok));
|
1999-12-06 21:52:23 +03:00
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
int
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_switch(device_t dv, int no, int waitok)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1998-06-12 02:13:52 +04:00
|
|
|
int s, res = 0;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2003-09-21 22:47:59 +04:00
|
|
|
if (no != WSDISPLAY_NULLSCREEN) {
|
|
|
|
if ((no < 0 || no >= WSDISPLAY_MAXSCREEN))
|
|
|
|
return (EINVAL);
|
|
|
|
if (sc->sc_scr[no] == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_stat_inject(dv, WSCONS_EVENT_SCREEN_SWITCH, no);
|
2002-06-27 03:05:33 +04:00
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
s = spltty();
|
|
|
|
|
2000-09-10 13:39:57 +04:00
|
|
|
if ((sc->sc_focus && no == sc->sc_focusidx) ||
|
|
|
|
(sc->sc_focus == NULL && no == WSDISPLAY_NULLSCREEN)) {
|
1998-06-12 02:13:52 +04:00
|
|
|
splx(s);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sc->sc_flags & SC_SWITCHPENDING) {
|
|
|
|
splx(s);
|
|
|
|
return (EBUSY);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_flags |= SC_SWITCHPENDING;
|
|
|
|
sc->sc_screenwanted = no;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
splx(s);
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
scr = sc->sc_focus;
|
1999-01-26 17:22:14 +03:00
|
|
|
if (!scr) {
|
2000-09-10 13:39:57 +04:00
|
|
|
sc->sc_oldscreen = WSDISPLAY_NULLSCREEN;
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch1(dv, 0, waitok));
|
1999-01-26 17:22:14 +03:00
|
|
|
} else
|
|
|
|
sc->sc_oldscreen = sc->sc_focusidx;
|
1998-06-12 02:13:52 +04:00
|
|
|
|
|
|
|
if (scr->scr_syncops) {
|
2008-03-13 02:26:18 +03:00
|
|
|
if (!(sc->sc_flags & SC_XATTACHED) ||
|
|
|
|
(sc->sc_isconsole && wsdisplay_cons_pollmode)) {
|
|
|
|
/* nothing to do here */
|
2008-02-21 01:33:18 +03:00
|
|
|
return (wsdisplay_switch1(dv, 0, waitok));
|
2008-03-13 02:26:18 +03:00
|
|
|
}
|
1998-06-12 02:13:52 +04:00
|
|
|
res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok,
|
2008-03-13 02:26:18 +03:00
|
|
|
wsdisplay_switch1_cb, dv);
|
1998-06-12 02:13:52 +04:00
|
|
|
if (res == EAGAIN) {
|
|
|
|
/* switch will be done asynchronously */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
} else if (scr->scr_flags & SCR_GRAPHICS) {
|
|
|
|
/* no way to save state */
|
|
|
|
res = EBUSY;
|
|
|
|
}
|
|
|
|
|
2007-10-18 22:09:52 +04:00
|
|
|
return (wsdisplay_switch1(dv, res, waitok));
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
1999-01-14 14:40:58 +03:00
|
|
|
void
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_reset(device_t dv, enum wsdisplay_resetops op)
|
1999-01-14 14:40:58 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1999-01-14 14:40:58 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
KASSERT(sc != NULL);
|
|
|
|
scr = sc->sc_focus;
|
|
|
|
|
1999-01-17 18:56:33 +03:00
|
|
|
if (!scr)
|
1999-01-14 14:40:58 +03:00
|
|
|
return;
|
|
|
|
|
1999-01-17 18:56:33 +03:00
|
|
|
switch (op) {
|
|
|
|
case WSDISPLAY_RESETEMUL:
|
|
|
|
if (!WSSCREEN_HAS_EMULATOR(scr))
|
|
|
|
break;
|
|
|
|
(*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
|
|
|
|
WSEMUL_RESET);
|
|
|
|
break;
|
|
|
|
case WSDISPLAY_RESETCLOSE:
|
|
|
|
wsdisplay_closescreen(sc, scr);
|
|
|
|
break;
|
|
|
|
}
|
1999-01-14 14:40:58 +03:00
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
/*
|
|
|
|
* Interface for (external) VT switch / process synchronization code
|
|
|
|
*/
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops,
|
|
|
|
void *cookie)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
if (scr->scr_syncops) {
|
|
|
|
/*
|
|
|
|
* The screen is already claimed.
|
|
|
|
* Check if the owner is still alive.
|
|
|
|
*/
|
|
|
|
if ((*scr->scr_syncops->check)(scr->scr_synccookie))
|
|
|
|
return (EBUSY);
|
|
|
|
}
|
|
|
|
scr->scr_syncops = ops;
|
|
|
|
scr->scr_synccookie = cookie;
|
2008-02-21 01:33:18 +03:00
|
|
|
if (scr == scr->sc->sc_focus)
|
|
|
|
scr->sc->sc_flags |= SC_XATTACHED;
|
1998-06-12 02:13:52 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_detach_sync(struct wsscreen *scr)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
if (!scr->scr_syncops)
|
|
|
|
return (EINVAL);
|
|
|
|
scr->scr_syncops = 0;
|
2008-02-21 01:33:18 +03:00
|
|
|
if (scr == scr->sc->sc_focus)
|
|
|
|
scr->sc->sc_flags &= ~SC_XATTACHED;
|
1998-03-22 17:24:02 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_lookup_sync(struct wsscreen *scr,
|
|
|
|
const struct wscons_syncops *ops, /* used as ID */
|
|
|
|
void **cookiep)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
if (!scr->scr_syncops || ops != scr->scr_syncops)
|
|
|
|
return (EINVAL);
|
|
|
|
*cookiep = scr->scr_synccookie;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interface to virtual screen stuff
|
|
|
|
*/
|
|
|
|
int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplay_maxscreenidx(struct wsdisplay_softc *sc)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
return (WSDISPLAY_MAXSCREEN - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
2000-09-10 13:39:57 +04:00
|
|
|
if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN)
|
1998-06-12 02:13:52 +04:00
|
|
|
return (EINVAL);
|
|
|
|
if (!sc->sc_scr[idx])
|
|
|
|
return (ENXIO);
|
|
|
|
return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN) ? EBUSY : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_getactivescreen(struct wsdisplay_softc *sc)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
2000-09-10 13:39:57 +04:00
|
|
|
return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN);
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsscreen_switchwait(struct wsdisplay_softc *sc, int no)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
struct wsscreen *scr;
|
|
|
|
int s, res = 0;
|
|
|
|
|
2000-09-10 13:39:57 +04:00
|
|
|
if (no == WSDISPLAY_NULLSCREEN) {
|
|
|
|
s = spltty();
|
|
|
|
while (sc->sc_focus && res == 0) {
|
|
|
|
res = tsleep(sc, PCATCH, "wswait", 0);
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
if (no < 0 || no >= WSDISPLAY_MAXSCREEN)
|
|
|
|
return (ENXIO);
|
|
|
|
scr = sc->sc_scr[no];
|
|
|
|
if (!scr)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
s = spltty();
|
|
|
|
if (scr != sc->sc_focus) {
|
|
|
|
scr->scr_flags |= SCR_WAITACTIVE;
|
|
|
|
res = tsleep(scr, PCATCH, "wswait", 0);
|
1999-01-09 18:42:34 +03:00
|
|
|
if (scr != sc->sc_scr[no])
|
|
|
|
res = ENXIO; /* disappeared in the meantime */
|
|
|
|
else
|
|
|
|
scr->scr_flags &= ~SCR_WAITACTIVE;
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
void
|
2007-10-18 22:09:52 +04:00
|
|
|
wsdisplay_kbdholdscreen(device_t dv, int hold)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2007-10-18 22:09:52 +04:00
|
|
|
struct wsdisplay_softc *sc = device_private(dv);
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
scr = sc->sc_focus;
|
|
|
|
|
2008-11-07 22:33:13 +03:00
|
|
|
if (!scr)
|
|
|
|
return;
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
if (hold)
|
|
|
|
scr->scr_hold_screen = 1;
|
|
|
|
else {
|
|
|
|
scr->scr_hold_screen = 0;
|
2007-10-18 22:54:56 +04:00
|
|
|
callout_schedule(&scr->scr_tty->t_rstrt_ch, 0);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-17 20:53:43 +04:00
|
|
|
#if NWSKBD > 0
|
2001-11-10 20:14:51 +03:00
|
|
|
void
|
2001-10-27 17:52:57 +04:00
|
|
|
wsdisplay_set_console_kbd(struct wsevsrc *src)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
2001-11-10 20:14:51 +03:00
|
|
|
if (wsdisplay_console_device == NULL) {
|
|
|
|
src->me_dispdv = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2001-10-24 18:07:31 +04:00
|
|
|
#if NWSMUX > 0
|
2001-11-10 20:14:51 +03:00
|
|
|
if (wsmux_attach_sc((struct wsmux_softc *)
|
|
|
|
wsdisplay_console_device->sc_input, src)) {
|
|
|
|
src->me_dispdv = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2001-10-24 18:07:31 +04:00
|
|
|
#else
|
2001-10-27 17:52:57 +04:00
|
|
|
wsdisplay_console_device->sc_input = src;
|
2001-10-24 18:07:31 +04:00
|
|
|
#endif
|
2007-10-18 22:09:52 +04:00
|
|
|
src->me_dispdv = wsdisplay_console_device->sc_dev;
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
1999-05-17 20:53:43 +04:00
|
|
|
#endif /* NWSKBD > 0 */
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Console interface.
|
|
|
|
*/
|
|
|
|
void
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplay_cnputc(dev_t dev, int i)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1999-01-09 18:42:34 +03:00
|
|
|
struct wsscreen_internal *dc;
|
2003-01-20 05:16:55 +03:00
|
|
|
u_char c = i;
|
1998-03-22 17:24:02 +03:00
|
|
|
|
|
|
|
if (!wsdisplay_console_initted)
|
|
|
|
return;
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
if ((wsdisplay_console_device != NULL) &&
|
2003-09-21 22:47:59 +04:00
|
|
|
(wsdisplay_console_device->sc_scr[0] != NULL) &&
|
1998-06-12 02:13:52 +04:00
|
|
|
(wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS))
|
1998-03-22 17:24:02 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
dc = &wsdisplay_console_conf;
|
1998-05-15 00:49:55 +04:00
|
|
|
(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplay_getc_dummy(dev_t dev)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
/* panic? */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-11-16 04:32:37 +03:00
|
|
|
wsdisplay_pollc(dev_t dev, int on)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1999-12-06 21:52:23 +03:00
|
|
|
|
|
|
|
wsdisplay_cons_pollmode = on;
|
|
|
|
|
2000-12-30 04:41:51 +03:00
|
|
|
/* notify to fb drivers */
|
2001-05-18 15:49:21 +04:00
|
|
|
if (wsdisplay_console_device != NULL &&
|
|
|
|
wsdisplay_console_device->sc_accessops->pollc != NULL)
|
|
|
|
(*wsdisplay_console_device->sc_accessops->pollc)
|
|
|
|
(wsdisplay_console_device->sc_accesscookie, on);
|
2000-12-30 04:41:51 +03:00
|
|
|
|
|
|
|
/* notify to kbd drivers */
|
1999-12-06 21:52:23 +03:00
|
|
|
if (wsdisplay_cons_kbd_pollc)
|
2001-05-18 15:49:21 +04:00
|
|
|
(*wsdisplay_cons_kbd_pollc)(NODEV, on);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int),
|
|
|
|
void (*bell)(dev_t, u_int, u_int, u_int))
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
wsdisplay_cons.cn_getc = get;
|
2000-03-07 00:37:16 +03:00
|
|
|
wsdisplay_cons.cn_bell = bell;
|
1999-12-06 21:52:23 +03:00
|
|
|
wsdisplay_cons_kbd_pollc = poll;
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
1999-10-02 02:29:12 +04:00
|
|
|
|
1999-12-02 02:22:57 +03:00
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_unset_cons_kbd(void)
|
1999-12-02 02:22:57 +03:00
|
|
|
{
|
|
|
|
wsdisplay_cons.cn_getc = wsdisplay_getc_dummy;
|
2000-03-07 00:37:16 +03:00
|
|
|
wsdisplay_cons.cn_bell = NULL;
|
1999-12-06 21:52:23 +03:00
|
|
|
wsdisplay_cons_kbd_pollc = 0;
|
1999-12-02 02:22:57 +03:00
|
|
|
}
|