2006-05-15 01:42:26 +04:00
|
|
|
/* $NetBSD: wsdisplay.c,v 1.98 2006/05/14 21:47:00 elad 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>
|
2006-05-15 01:42:26 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.98 2006/05/14 21:47:00 elad 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_shutdownhook(void *);
|
|
|
|
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 {
|
|
|
|
struct device sc_dv;
|
|
|
|
|
|
|
|
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
|
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. */
|
2001-10-13 19:56:15 +04:00
|
|
|
static int wsdisplay_emul_match(struct device *, struct cfdata *, void *);
|
|
|
|
static void wsdisplay_emul_attach(struct device *, struct device *, void *);
|
|
|
|
static int wsdisplay_noemul_match(struct device *, struct cfdata *, void *);
|
|
|
|
static void wsdisplay_noemul_attach(struct device *, struct device *, void *);
|
1998-03-22 17:24:02 +03:00
|
|
|
|
2002-10-01 05:25:25 +04:00
|
|
|
CFATTACH_DECL(wsdisplay_emul, sizeof (struct wsdisplay_softc),
|
2002-10-02 20:51:16 +04:00
|
|
|
wsdisplay_emul_match, wsdisplay_emul_attach, NULL, NULL);
|
2002-10-01 05:25:25 +04:00
|
|
|
|
|
|
|
CFATTACH_DECL(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;
|
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
int wsdisplay_switch1(void *, int, int);
|
|
|
|
int wsdisplay_switch2(void *, int, int);
|
|
|
|
int wsdisplay_switch3(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
|
|
|
{
|
|
|
|
printf("%s: screen %d", sc->sc_dv.dv_xname, idx);
|
|
|
|
if (count > 1)
|
|
|
|
printf("-%d", idx + (count-1));
|
|
|
|
printf(" added (%s", sc->sc_scr[idx]->scr_dconf->scrdata->name);
|
|
|
|
if (WSSCREEN_HAS_EMULATOR(sc->sc_scr[idx])) {
|
|
|
|
printf(", %s emulation",
|
|
|
|
sc->sc_scr[idx]->scr_dconf->wsemul->name);
|
|
|
|
}
|
|
|
|
printf(")\n");
|
|
|
|
}
|
|
|
|
|
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 */
|
2006-03-28 21:38:24 +04:00
|
|
|
mn = WSDISPLAYMINOR(device_unit(&sc->sc_dv), 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)
|
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = arg;
|
|
|
|
int lines;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
/*
|
|
|
|
* Autoconfiguration functions.
|
|
|
|
*/
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_emul_match(struct device *parent, struct cfdata *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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
|
|
|
|
struct wsemuldisplaydev_attach_args *ap = aux;
|
|
|
|
|
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,
|
2006-03-29 08:16:44 +04:00
|
|
|
device_cfdata(&sc->sc_dv)->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
|
2001-10-13 19:56:15 +04: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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_noemul_match(struct device *parent, struct cfdata *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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_noemul_attach(struct device *parent, struct device *self, void *aux)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
|
|
|
|
struct wsdisplaydev_attach_args *ap = aux;
|
|
|
|
|
2001-10-13 17:35:59 +04:00
|
|
|
wsdisplay_common_attach(sc, 0,
|
2006-03-29 08:16:44 +04:00
|
|
|
device_cfdata(&sc->sc_dv)->wsemuldisplaydevcf_kbdmux, NULL,
|
2001-10-13 17:35:59 +04:00
|
|
|
ap->accessops, ap->accesscookie);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Print function (for parent devices). */
|
|
|
|
int
|
2001-10-13 19:56:15 +04: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-10-02 02:29:12 +04:00
|
|
|
static int hookset;
|
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
|
2006-03-28 21:38:24 +04:00
|
|
|
mux = wsmux_create("dmux", device_unit(&sc->sc_dv));
|
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;
|
|
|
|
mux->sc_base.me_dispdv = &sc->sc_dv;
|
2001-10-24 18:07:31 +04:00
|
|
|
printf(" kbdmux %d", kbdmux);
|
|
|
|
#else
|
|
|
|
if (kbdmux >= 0)
|
|
|
|
printf(" (kbdmux ignored)");
|
|
|
|
#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;
|
|
|
|
|
|
|
|
printf(": console (%s, %s emulation)",
|
|
|
|
wsdisplay_console_conf.scrdata->name,
|
|
|
|
wsdisplay_console_conf.wsemul->name);
|
|
|
|
|
1999-05-17 20:53:43 +04:00
|
|
|
#if NWSKBD > 0
|
2001-10-24 18:07:31 +04:00
|
|
|
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
|
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
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
2002-03-02 11:22:26 +03:00
|
|
|
#if NWSKBD > 0 && NWSMUX > 0
|
|
|
|
wsmux_set_display(mux, &sc->sc_dv);
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
1999-10-02 02:29:12 +04:00
|
|
|
if (hookset == 0)
|
|
|
|
shutdownhook_establish(wsdisplay_shutdownhook, NULL);
|
|
|
|
hookset = 1;
|
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;
|
|
|
|
|
|
|
|
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
|
2005-12-11 15:16:03 +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;
|
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&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;
|
|
|
|
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);
|
|
|
|
} else if ((tp->t_state & TS_XCLUDE) != 0 &&
|
2006-05-15 01:42:26 +04:00
|
|
|
kauth_authorize_generic(l->l_proc->p_cred, KAUTH_GENERIC_ISSUSER,
|
|
|
|
&l->l_proc->p_acflag) != 0)
|
1998-06-12 02:13:52 +04:00
|
|
|
return EBUSY;
|
|
|
|
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
|
2005-12-11 15:16:03 +03:00
|
|
|
wsdisplayclose(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;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
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 */
|
|
|
|
wsdisplay_kbdholdscreen((struct device *)sc, 0);
|
|
|
|
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,
|
2005-12-11 15:16:03 +03:00
|
|
|
(caddr_t)&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
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&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;
|
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&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;
|
|
|
|
|
|
|
|
sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
|
|
|
|
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
|
|
|
|
wsdisplaykqfilter(dev, kn)
|
|
|
|
dev_t dev;
|
|
|
|
struct knote *kn;
|
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc =
|
|
|
|
device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&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
|
2005-12-11 15:16:03 +03:00
|
|
|
wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, 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 error;
|
1998-03-22 17:24:02 +03:00
|
|
|
struct wsscreen *scr;
|
|
|
|
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
1999-01-09 18:42:34 +03:00
|
|
|
|
1999-10-19 04:03:18 +04:00
|
|
|
#ifdef WSDISPLAY_COMPAT_USL
|
2005-12-11 15:16:03 +03:00
|
|
|
error = wsdisplay_usl_ioctl1(sc, 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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp)
|
2000-10-01 07:29:12 +04:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
|
2006-04-13 05:15:27 +04:00
|
|
|
return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
|
|
|
|
sc->sc_focus->scr_dconf->emulcookie,
|
2006-04-12 23:38:22 +04:00
|
|
|
cmd, (caddr_t)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,
|
2005-12-11 15:16:03 +03:00
|
|
|
u_long cmd, caddr_t 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
|
|
|
|
wsdisplay_stat_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
|
2005-12-11 15:16:03 +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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t 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
|
|
|
|
wsdisplay_stat_inject(struct device *dev, u_int type, int value)
|
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *) dev;
|
|
|
|
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
|
|
|
{
|
2001-01-04 02:00:24 +03:00
|
|
|
struct wsdisplay_softc *sc =
|
|
|
|
device_lookup(&wsdisplay_cd, WSDISPLAYUNIT(dev));
|
1998-06-12 02:13:52 +04:00
|
|
|
struct wsscreen *scr;
|
1998-03-22 17:24:02 +03: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;
|
|
|
|
}
|
2001-01-04 02:00:24 +03:00
|
|
|
sc = device_lookup(&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 */
|
|
|
|
if (tp->t_outq.c_cc) {
|
|
|
|
tp->t_state |= TS_TIMEOUT;
|
2000-03-23 10:01:25 +03:00
|
|
|
callout_reset(&tp->t_rstrt_ch, (hz > 128) ? (hz / 128) : 1,
|
|
|
|
ttrstrt, tp);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
if (tp->t_outq.c_cc <= tp->t_lowat) {
|
|
|
|
if (tp->t_state&TS_ASLEEP) {
|
|
|
|
tp->t_state &= ~TS_ASLEEP;
|
2001-10-24 18:07:31 +04:00
|
|
|
wakeup(&tp->t_outq);
|
1998-03-22 17:24:02 +03:00
|
|
|
}
|
|
|
|
selwakeup(&tp->t_wsel);
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-13 19:56:15 +04: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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_kbdinput(struct device *dev, keysym_t ks)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
|
|
|
|
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;
|
2001-10-28 13:30:22 +03:00
|
|
|
if (inp == NULL)
|
|
|
|
return (ENXIO);
|
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
|
|
|
|
|
1998-03-22 17:24:02 +03:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_switch3(void *arg, int error, int waitok)
|
1999-01-26 17:22:14 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = arg;
|
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
|
|
|
printf("wsdisplay_switch3: not switching\n");
|
|
|
|
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) {
|
|
|
|
printf("wsdisplay_switch3: screen %d disappeared\n", no);
|
|
|
|
error = ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
/* try to recover, avoid recursion */
|
|
|
|
|
2000-09-10 13:39:57 +04:00
|
|
|
if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN) {
|
1999-01-26 17:22:14 +03:00
|
|
|
printf("wsdisplay_switch3: giving up\n");
|
|
|
|
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;
|
1999-01-26 17:22:14 +03:00
|
|
|
return (wsdisplay_switch1(arg, 0, waitok));
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
|
|
|
|
if (!error && (scr->scr_flags & SCR_WAITACTIVE))
|
|
|
|
wakeup(scr);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_switch2(void *arg, int error, int waitok)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
1998-06-12 02:13:52 +04:00
|
|
|
struct wsdisplay_softc *sc = arg;
|
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
1999-12-06 21:52:23 +03:00
|
|
|
printf("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) {
|
1999-12-06 21:52:23 +03:00
|
|
|
printf("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) {
|
1999-12-06 21:52:23 +03:00
|
|
|
printf("wsdisplay_switch2: giving up\n");
|
|
|
|
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;
|
1999-12-06 21:52:23 +03:00
|
|
|
return (wsdisplay_switch1(arg, 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??? */
|
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
#define wsswitch_cb3 ((void (*)(void *, int, int))wsdisplay_switch3)
|
1998-06-12 02:13:52 +04:00
|
|
|
if (scr->scr_syncops) {
|
1999-01-26 17:22:14 +03:00
|
|
|
error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok,
|
1999-12-06 21:52:23 +03:00
|
|
|
sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb3, sc);
|
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
|
|
|
|
1999-01-26 17:22:14 +03:00
|
|
|
return (wsdisplay_switch3(sc, error, waitok));
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
1999-12-06 21:52:23 +03:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_switch1(void *arg, int error, int waitok)
|
1999-12-06 21:52:23 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = arg;
|
|
|
|
int no;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_SWITCHPENDING)) {
|
|
|
|
printf("wsdisplay_switch1: not switching\n");
|
|
|
|
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) {
|
|
|
|
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) {
|
|
|
|
printf("wsdisplay_switch1: screen %d disappeared\n", no);
|
|
|
|
error = ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
sc->sc_flags &= ~SC_SWITCHPENDING;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
#define wsswitch_cb2 ((void (*)(void *, int, int))wsdisplay_switch2)
|
1999-12-06 21:52:23 +03:00
|
|
|
error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie,
|
|
|
|
waitok,
|
|
|
|
sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2, sc);
|
|
|
|
if (error == EAGAIN) {
|
|
|
|
/* switch will be done asynchronously */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (wsdisplay_switch2(sc, error, waitok));
|
|
|
|
}
|
|
|
|
|
1998-06-12 02:13:52 +04:00
|
|
|
int
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_switch(struct device *dev, int no, int waitok)
|
1998-06-12 02:13:52 +04:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
|
|
|
|
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
|
|
|
|
2002-06-27 03:05:33 +04:00
|
|
|
wsdisplay_stat_inject(dev, WSCONS_EVENT_SCREEN_SWITCH, no);
|
|
|
|
|
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;
|
1999-01-26 17:22:14 +03:00
|
|
|
return (wsdisplay_switch1(sc, 0, waitok));
|
|
|
|
} else
|
|
|
|
sc->sc_oldscreen = sc->sc_focusidx;
|
1998-06-12 02:13:52 +04:00
|
|
|
|
2001-10-13 19:56:15 +04:00
|
|
|
#define wsswitch_cb1 ((void (*)(void *, int, int))wsdisplay_switch1)
|
1998-06-12 02:13:52 +04:00
|
|
|
if (scr->scr_syncops) {
|
|
|
|
res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok,
|
1999-12-06 21:52:23 +03:00
|
|
|
sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb1, sc);
|
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;
|
|
|
|
}
|
|
|
|
|
1999-01-26 17:22:14 +03:00
|
|
|
return (wsdisplay_switch1(sc, res, waitok));
|
1998-06-12 02:13:52 +04:00
|
|
|
}
|
|
|
|
|
1999-01-14 14:40:58 +03:00
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op)
|
1999-01-14 14:40:58 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
|
|
|
|
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;
|
|
|
|
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;
|
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
|
2001-10-13 19:56:15 +04: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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_kbdholdscreen(struct device *dev, int hold)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
scr = sc->sc_focus;
|
|
|
|
|
|
|
|
if (hold)
|
|
|
|
scr->scr_hold_screen = 1;
|
|
|
|
else {
|
|
|
|
scr->scr_hold_screen = 0;
|
2000-03-23 10:01:25 +03:00
|
|
|
callout_reset(&scr->scr_tty->t_rstrt_ch, 0,
|
|
|
|
ttrstrt, scr->scr_tty); /* "immediate" */
|
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
|
2001-11-10 20:14:51 +03:00
|
|
|
src->me_dispdv = &wsdisplay_console_device->sc_dv;
|
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
|
2001-10-13 19:56:15 +04: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
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_getc_dummy(dev_t dev)
|
1998-03-22 17:24:02 +03:00
|
|
|
{
|
|
|
|
/* panic? */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-13 19:56:15 +04: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
|
|
|
}
|
|
|
|
|
1999-10-02 02:29:12 +04:00
|
|
|
/*
|
1999-10-12 20:47:41 +04:00
|
|
|
* Switch the console display to it's first screen.
|
1999-10-02 02:29:12 +04:00
|
|
|
*/
|
1999-10-12 20:47:41 +04:00
|
|
|
void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_switchtoconsole(void)
|
1999-10-02 02:29:12 +04:00
|
|
|
{
|
2000-12-04 16:22:17 +03:00
|
|
|
struct wsdisplay_softc *sc;
|
|
|
|
struct wsscreen *scr;
|
|
|
|
|
|
|
|
if (wsdisplay_console_device != NULL) {
|
|
|
|
sc = wsdisplay_console_device;
|
2003-09-21 22:47:59 +04:00
|
|
|
if ((scr = sc->sc_scr[0]) == NULL)
|
|
|
|
return;
|
2000-12-04 16:22:17 +03:00
|
|
|
(*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
|
|
|
|
scr->scr_dconf->emulcookie,
|
|
|
|
0, NULL, NULL);
|
|
|
|
}
|
1999-10-02 02:29:12 +04:00
|
|
|
}
|
1999-10-12 20:47:41 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Switch the console at shutdown.
|
|
|
|
*/
|
|
|
|
static void
|
2001-10-13 19:56:15 +04:00
|
|
|
wsdisplay_shutdownhook(void *arg)
|
1999-10-12 20:47:41 +04:00
|
|
|
{
|
2000-12-04 16:22:17 +03:00
|
|
|
|
1999-10-12 20:47:41 +04:00
|
|
|
wsdisplay_switchtoconsole();
|
|
|
|
}
|