summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1999-06-22 14:14:06 +0000
committeryokota <yokota@FreeBSD.org>1999-06-22 14:14:06 +0000
commit4f4eb0cfe54e001639240b3b63551c42280cdcc0 (patch)
tree75738e04df5c55c7d14fd6fb083ab1062bd92a85 /sys/dev
parentd252fb51781d3bcdc1697ebd89678c9a00d94124 (diff)
downloadFreeBSD-src-4f4eb0cfe54e001639240b3b63551c42280cdcc0.zip
FreeBSD-src-4f4eb0cfe54e001639240b3b63551c42280cdcc0.tar.gz
The second phase of syscons reorganization.
- Split syscons source code into manageable chunks and reorganize some of complicated functions. - Many static variables are moved to the softc structure. - Added a new key function, PREV. When this key is pressed, the vty immediately before the current vty will become foreground. Analogue to PREV, which is usually assigned to the PrntScrn key. PR: kern/10113 Submitted by: Christian Weisgerber <naddy@mips.rhein-neckar.de> - Modified the kernel console input function sccngetc() so that it handles function keys properly. - Reorganized the screen update routine. - VT switching code is reorganized. It now should be slightly more robust than before. - Added the DEVICE_RESUME function so that syscons no longer hooks the APM resume event directly. - New kernel configuration options: SC_NO_CUTPASTE, SC_NO_FONT_LOADING, SC_NO_HISTORY and SC_NO_SYSMOUSE. Various parts of syscons can be omitted so that the kernel size is reduced. SC_PIXEL_MODE Made the VESA 800x600 mode an option, rather than a standard part of syscons. SC_DISABLE_DDBKEY Disables the `debug' key combination. SC_ALT_MOUSE_IMAGE Inverse the character cell at the mouse cursor position in the text console, rather than drawing an arrow on the screen. Submitted by: Nick Hibma (n_hibma@FreeBSD.ORG) SC_DFLT_FONT makeoptions "SC_DFLT_FONT=_font_name_" Include the named font as the default font of syscons. 16-line, 14-line and 8-line font data will be compiled in. This option replaces the existing STD8X16FONT option, which loads 16-line font data only. - The VGA driver is split into /sys/dev/fb/vga.c and /sys/isa/vga_isa.c. - The video driver provides a set of ioctl commands to manipulate the frame buffer. - New kernel configuration option: VGA_WIDTH90 Enables 90 column modes: 90x25, 90x30, 90x43, 90x50, 90x60. These modes are mot always supported by the video card. PR: i386/7510 Submitted by: kbyanc@freedomnet.com and alexv@sui.gda.itesm.mx. - The header file machine/console.h is reorganized; its contents is now split into sys/fbio.h, sys/kbio.h (a new file) and sys/consio.h (another new file). machine/console.h is still maintained for compatibility reasons. - Kernel console selection/installation routines are fixed and slightly rebumped so that it should now be possible to switch between the interanl kernel console (sc or vt) and a remote kernel console (sio) again, as it was in 2.x, 3.0 and 3.1. - Screen savers and splash screen decoders Because of the header file reorganization described above, screen savers and splash screen decoders are slightly modified. After this update, /sys/modules/syscons/saver.h is no longer necessary and is removed.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fb/fb.c473
-rw-r--r--sys/dev/fb/fbreg.h65
-rw-r--r--sys/dev/fb/splash.c15
-rw-r--r--sys/dev/fb/splash_bmp.c5
-rw-r--r--sys/dev/fb/splash_pcx.c5
-rw-r--r--sys/dev/fb/splashreg.h5
-rw-r--r--sys/dev/fb/vga.c3041
-rw-r--r--sys/dev/fb/vgareg.h34
-rw-r--r--sys/dev/sio/sio.c15
-rw-r--r--sys/dev/syscons/blank/blank_saver.c71
-rw-r--r--sys/dev/syscons/daemon/daemon_saver.c103
-rw-r--r--sys/dev/syscons/fade/fade_saver.c69
-rw-r--r--sys/dev/syscons/fire/fire_saver.c9
-rw-r--r--sys/dev/syscons/green/green_saver.c82
-rw-r--r--sys/dev/syscons/logo/logo_saver.c10
-rw-r--r--sys/dev/syscons/rain/rain_saver.c8
-rw-r--r--sys/dev/syscons/scgfbrndr.c829
-rw-r--r--sys/dev/syscons/schistory.c222
-rw-r--r--sys/dev/syscons/scmouse.c1083
-rw-r--r--sys/dev/syscons/scvesactl.c9
-rw-r--r--sys/dev/syscons/scvgarndr.c829
-rw-r--r--sys/dev/syscons/scvidctl.c474
-rw-r--r--sys/dev/syscons/scvtb.c283
-rw-r--r--sys/dev/syscons/snake/snake_saver.c56
-rw-r--r--sys/dev/syscons/star/star_saver.c49
-rw-r--r--sys/dev/syscons/syscons.c4167
-rw-r--r--sys/dev/syscons/syscons.h411
-rw-r--r--sys/dev/syscons/warp/warp_saver.c9
28 files changed, 9585 insertions, 2846 deletions
diff --git a/sys/dev/fb/fb.c b/sys/dev/fb/fb.c
index a1d5f11..e10b75b 100644
--- a/sys/dev/fb/fb.c
+++ b/sys/dev/fb/fb.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: fb.c,v 1.4 1999/05/30 16:51:23 phk Exp $
+ * $Id: fb.c,v 1.5 1999/05/31 11:24:38 phk Exp $
*/
#include "fb.h"
@@ -34,10 +34,14 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/fbio.h>
-#include <machine/console.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
#include <dev/fb/fbreg.h>
@@ -49,6 +53,7 @@
* when necessary.
*/
+static int vid_malloc;
static int adapters = 1;
static video_adapter_t *adp_ini;
static video_adapter_t **adapter = &adp_ini;
@@ -56,48 +61,69 @@ static video_switch_t *vidsw_ini;
video_switch_t **vidsw = &vidsw_ini;
#ifdef FB_INSTALL_CDEV
-
-#define ARRAY_DELTA 4
-
static struct cdevsw *vidcdevsw_ini;
static struct cdevsw **vidcdevsw = &vidcdevsw_ini;
+#endif
-static void
+#define ARRAY_DELTA 4
+
+static int
vid_realloc_array(void)
{
video_adapter_t **new_adp;
video_switch_t **new_vidsw;
+#ifdef FB_INSTALL_CDEV
struct cdevsw **new_cdevsw;
+#endif
int newsize;
int s;
+ if (!vid_malloc)
+ return ENOMEM;
+
s = spltty();
newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK);
new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF, M_WAITOK);
+#ifdef FB_INSTALL_CDEV
new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_WAITOK);
+#endif
bzero(new_adp, sizeof(*new_adp)*newsize);
bzero(new_vidsw, sizeof(*new_vidsw)*newsize);
- bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
+#ifdef FB_INSTALL_CDEV
+ bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
+#endif
if (adapters > 1) {
free(adapter, M_DEVBUF);
free(vidsw, M_DEVBUF);
+#ifdef FB_INSTALL_CDEV
free(vidcdevsw, M_DEVBUF);
+#endif
}
adapter = new_adp;
vidsw = new_vidsw;
+#ifdef FB_INSTALL_CDEV
vidcdevsw = new_cdevsw;
+#endif
adapters = newsize;
splx(s);
if (bootverbose)
printf("fb: new array size %d\n", adapters);
+
+ return 0;
}
-#endif /* FB_INSTALL_CDEV */
+static void
+vid_malloc_init(void *arg)
+{
+ vid_malloc = TRUE;
+}
+
+SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
/*
* Low-level frame buffer driver functions
@@ -120,20 +146,22 @@ vid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
int
vid_register(video_adapter_t *adp)
{
- video_driver_t **list;
- video_driver_t *p;
+ const video_driver_t **list;
+ const video_driver_t *p;
int index;
for (index = 0; index < adapters; ++index) {
if (adapter[index] == NULL)
break;
}
- if (index >= adapters)
- return -1;
+ if (index >= adapters) {
+ if (vid_realloc_array())
+ return -1;
+ }
adp->va_index = index;
adp->va_token = NULL;
- list = (video_driver_t **)videodriver_set.ls_items;
+ list = (const video_driver_t **)videodriver_set.ls_items;
while ((p = *list++) != NULL) {
if (strcmp(p->name, adp->va_name) == 0) {
adapter[index] = adp;
@@ -162,10 +190,10 @@ vid_unregister(video_adapter_t *adp)
video_switch_t
*vid_get_switch(char *name)
{
- video_driver_t **list;
- video_driver_t *p;
+ const video_driver_t **list;
+ const video_driver_t *p;
- list = (video_driver_t **)videodriver_set.ls_items;
+ list = (const video_driver_t **)videodriver_set.ls_items;
while ((p = *list++) != NULL) {
if (strcmp(p->name, name) == 0)
return p->vidsw;
@@ -251,10 +279,10 @@ video_adapter_t
int
vid_configure(int flags)
{
- video_driver_t **list;
- video_driver_t *p;
+ const video_driver_t **list;
+ const video_driver_t *p;
- list = (video_driver_t **)videodriver_set.ls_items;
+ list = (const video_driver_t **)videodriver_set.ls_items;
while ((p = *list++) != NULL) {
if (p->configure != NULL)
(*p->configure)(flags);
@@ -269,27 +297,73 @@ vid_configure(int flags)
* appropriate subdrivers.
*/
-#define DRIVER_NAME "fb"
+#define FB_DRIVER_NAME "fb"
#ifdef FB_INSTALL_CDEV
+#if experimental
+
+static devclass_t fb_devclass;
+
+static int fbprobe(device_t dev);
+static int fbattach(device_t dev);
+
+static device_method_t fb_methods[] = {
+ DEVMETHOD(device_probe, fbprobe),
+ DEVMETHOD(device_attach, fbattach),
+
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ { 0, 0 }
+};
+
+static driver_t fb_driver = {
+ FB_DRIVER_NAME,
+ fb_methods,
+ 0,
+};
+
+static int
+fbprobe(device_t dev)
+{
+ int unit;
+
+ unit = device_get_unit(dev);
+ if (unit >= adapters)
+ return ENXIO;
+ if (adapter[unit] == NULL)
+ return ENXIO;
+
+ device_set_desc(dev, "generic frame buffer");
+ return 0;
+}
+
+static int
+fbattach(device_t dev)
+{
+ printf("fbattach: about to attach children\n");
+ bus_generic_attach(dev);
+ return 0;
+}
+
+#endif /* experimental */
+
#define FB_UNIT(dev) minor(dev)
#define FB_MKMINOR(unit) (u)
-#if notyet
-
static d_open_t fbopen;
static d_close_t fbclose;
+static d_read_t fbread;
+static d_write_t fbwrite;
static d_ioctl_t fbioctl;
static d_mmap_t fbmmap;
-#define CDEV_MAJOR 141 /* XXX */
+#define CDEV_MAJOR 123 /* XXX */
static struct cdevsw fb_cdevsw = {
/* open */ fbopen,
/* close */ fbclose,
- /* read */ noread,
- /* write */ nowrite,
+ /* read */ fbread,
+ /* write */ fbwrite,
/* ioctl */ fbioctl,
/* stop */ nostop,
/* reset */ noreset,
@@ -297,7 +371,7 @@ static struct cdevsw fb_cdevsw = {
/* poll */ nopoll,
/* mmap */ fbmmap,
/* strategy */ nostrategy,
- /* name */ DRIVER_NAME,
+ /* name */ FB_DRIVER_NAME,
/* parms */ noparms,
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
@@ -320,10 +394,8 @@ vfbattach(void *arg)
PSEUDO_SET(vfbattach, fb);
-#endif /* notyet */
-
int
-fb_attach(dev_t dev, video_adapter *adp, struct cdevsw *cdevsw)
+fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
{
int s;
@@ -339,15 +411,12 @@ fb_attach(dev_t dev, video_adapter *adp, struct cdevsw *cdevsw)
/* XXX: DEVFS? */
- if (adp->va_index + 1 >= adapters)
- vid_realloc_array();
-
printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
return 0;
}
int
-fb_detach(dev_t dev, video_adapter *adp, struct cdevsw *cdevsw)
+fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
{
int s;
@@ -364,6 +433,165 @@ fb_detach(dev_t dev, video_adapter *adp, struct cdevsw *cdevsw)
return 0;
}
+static int
+fbopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (unit >= adapters)
+ return ENXIO;
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_open)(makedev(0, adapter[unit]->va_minor),
+ flag, mode, p);
+}
+
+static int
+fbclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_close)(makedev(0, adapter[unit]->va_minor),
+ flag, mode, p);
+}
+
+static int
+fbread(dev_t dev, struct uio *uio, int flag)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_read)(makedev(0, adapter[unit]->va_minor),
+ uio, flag);
+}
+
+static int
+fbwrite(dev_t dev, struct uio *uio, int flag)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_write)(makedev(0, adapter[unit]->va_minor),
+ uio, flag);
+}
+
+static int
+fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_ioctl)(makedev(0, adapter[unit]->va_minor),
+ cmd, arg, flag, p);
+}
+
+static int
+fbmmap(dev_t dev, vm_offset_t offset, int nprot)
+{
+ int unit;
+
+ unit = FB_UNIT(dev);
+ if (vidcdevsw[unit] == NULL)
+ return ENXIO;
+ return (*vidcdevsw[unit]->d_mmap)(makedev(0, adapter[unit]->va_minor),
+ offset, nprot);
+}
+
+#if experimental
+DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass,
+ CDEV_MAJOR, NOMAJ, fb_cdevsw, 0, 0);
+#endif
+
+/*
+ * Generic frame buffer cdev driver functions
+ * Frame buffer subdrivers may call these functions to implement common
+ * driver functions.
+ */
+
+int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
+ struct proc *p)
+{
+ int s;
+
+ s = spltty();
+ if (!(sc->gfb_flags & FB_OPEN))
+ sc->gfb_flags |= FB_OPEN;
+ splx(s);
+ return 0;
+}
+
+int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
+ struct proc *p)
+{
+ int s;
+
+ s = spltty();
+ sc->gfb_flags &= ~FB_OPEN;
+ splx(s);
+ return 0;
+}
+
+int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
+ int flag)
+{
+ int size;
+ int offset;
+ int error;
+ int len;
+
+ error = 0;
+ size = adp->va_buffer_size/adp->va_info.vi_planes;
+ while (uio->uio_resid > 0) {
+ if (uio->uio_offset >= size)
+ break;
+ offset = uio->uio_offset%adp->va_window_size;
+ len = imin(uio->uio_resid, size - uio->uio_offset);
+ len = imin(len, adp->va_window_size - offset);
+ if (len <= 0)
+ break;
+ (*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
+ error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
+ if (error)
+ break;
+ }
+ return error;
+}
+
+int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
+ int flag)
+{
+ return ENODEV;
+}
+
+int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
+ caddr_t arg, int flag, struct proc *p)
+{
+ int error;
+
+ if (adp == NULL) /* XXX */
+ return ENXIO;
+ error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
+ if (error == ENOIOCTL)
+ error = ENODEV;
+ return error;
+}
+
+int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
+ int prot)
+{
+ return (*vidsw[adp->va_index]->mmap)(adp, offset, prot);
+}
+
#endif /* FB_INSTALL_CDEV */
static char
@@ -379,6 +607,7 @@ static char
{ KD_EGA, "EGA" },
{ KD_VGA, "VGA" },
{ KD_PC98, "PC-98x1" },
+ { KD_TGA, "TGA" },
{ -1, "Unknown" },
};
int i;
@@ -389,6 +618,12 @@ static char
return names[i].name;
}
+/*
+ * Generic low-level frame buffer functions
+ * The low-level functions in the frame buffer subdriver may use these
+ * functions.
+ */
+
void
fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
{
@@ -396,19 +631,19 @@ fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
return;
printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
- DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
+ FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
adapter_name(adp->va_type), adp->va_type, adp->va_flags);
printf("%s%d: port:0x%x-0x%x, crtc:0x%x, mem:0x%x 0x%x\n",
- DRIVER_NAME, adp->va_index,
+ FB_DRIVER_NAME, adp->va_index,
adp->va_io_base, adp->va_io_base + adp->va_io_size - 1,
adp->va_crtc_addr, adp->va_mem_base, adp->va_mem_size);
printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
- DRIVER_NAME, adp->va_index,
+ FB_DRIVER_NAME, adp->va_index,
adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
- printf("%s%d: window:0x%x size:%dk gran:%dk, buf:0x%x size:%dk\n",
- DRIVER_NAME, adp->va_index,
- adp->va_window, (int)adp->va_window_size/1024,
- (int)adp->va_window_gran/1024, adp->va_buffer,
+ printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
+ FB_DRIVER_NAME, adp->va_index,
+ (void *)adp->va_window, (int)adp->va_window_size/1024,
+ (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
(int)adp->va_buffer_size/1024);
}
@@ -432,3 +667,161 @@ fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
info->vi_cwidth, info->vi_cheight);
printf("win:0x%x\n", info->vi_window);
}
+
+int
+fb_type(int adp_type)
+{
+ static struct {
+ int fb_type;
+ int va_type;
+ } types[] = {
+ { FBTYPE_MDA, KD_MONO },
+ { FBTYPE_HERCULES, KD_HERCULES },
+ { FBTYPE_CGA, KD_CGA },
+ { FBTYPE_EGA, KD_EGA },
+ { FBTYPE_VGA, KD_VGA },
+ { FBTYPE_PC98, KD_PC98 },
+ { FBTYPE_TGA, KD_TGA },
+ };
+ int i;
+
+ for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
+ if (types[i].va_type == adp_type)
+ return types[i].fb_type;
+ }
+ return -1;
+}
+
+int
+fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
+{
+ int error;
+ int s;
+
+ /* assert(adp != NULL) */
+
+ error = 0;
+ s = spltty();
+
+ switch (cmd) {
+
+ case FBIO_ADAPTER: /* get video adapter index */
+ *(int *)arg = adp->va_index;
+ break;
+
+ case FBIO_ADPTYPE: /* get video adapter type */
+ *(int *)arg = adp->va_type;
+ break;
+
+ case FBIO_ADPINFO: /* get video adapter info */
+ ((video_adapter_info_t *)arg)->va_index = adp->va_index;
+ ((video_adapter_info_t *)arg)->va_type = adp->va_type;
+ bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
+ imin(strlen(adp->va_name) + 1,
+ sizeof(((video_adapter_info_t *)arg)->va_name)));
+ ((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
+ ((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
+ ((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
+ ((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
+ ((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
+ ((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
+ ((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
+ ((video_adapter_info_t *)arg)->va_window
+ = vtophys(adp->va_window);
+ ((video_adapter_info_t *)arg)->va_window_size
+ = adp->va_window_size;
+ ((video_adapter_info_t *)arg)->va_window_gran
+ = adp->va_window_gran;
+ ((video_adapter_info_t *)arg)->va_window_orig
+ = adp->va_window_orig;
+ ((video_adapter_info_t *)arg)->va_unused0
+ = (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
+ ((video_adapter_info_t *)arg)->va_buffer_size
+ = adp->va_buffer_size;
+ ((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
+ ((video_adapter_info_t *)arg)->va_initial_mode
+ = adp->va_initial_mode;
+ ((video_adapter_info_t *)arg)->va_initial_bios_mode
+ = adp->va_initial_bios_mode;
+ ((video_adapter_info_t *)arg)->va_line_width
+ = adp->va_line_width;
+ ((video_adapter_info_t *)arg)->va_disp_start.x
+ = adp->va_disp_start.x;
+ ((video_adapter_info_t *)arg)->va_disp_start.y
+ = adp->va_disp_start.y;
+ break;
+
+ case FBIO_MODEINFO: /* get mode information */
+ error = (*vidsw[adp->va_index]->get_info)(adp,
+ ((video_info_t *)arg)->vi_mode,
+ (video_info_t *)arg);
+ if (error)
+ error = ENODEV;
+ break;
+
+ case FBIO_FINDMODE: /* find a matching video mode */
+ error = (*vidsw[adp->va_index]->query_mode)(adp,
+ (video_info_t *)arg);
+ if (error < 0) {
+ error = EINVAL;
+ } else {
+ error = (*vidsw[adp->va_index]->get_info)(adp,
+ error, (video_info_t *)arg);
+ if (error)
+ error = ENODEV; /* shouldn't happen */
+ }
+ break;
+
+ case FBIO_GETMODE: /* get video mode */
+ *(int *)arg = adp->va_mode;
+ break;
+
+ case FBIO_SETMODE: /* set video mode */
+ error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
+ if (error)
+ error = ENODEV; /* EINVAL? */
+ break;
+
+ case FBIO_GETWINORG: /* get frame buffer window origin */
+ *(u_int *)arg = adp->va_window_orig;
+ break;
+
+ case FBIO_GETDISPSTART: /* get display start address */
+ ((video_display_start_t *)arg)->x = adp->va_disp_start.x;
+ ((video_display_start_t *)arg)->y = adp->va_disp_start.y;
+ break;
+
+ case FBIO_GETLINEWIDTH: /* get scan line width in bytes */
+ *(u_int *)arg = adp->va_line_width;
+ break;
+
+ case FBIO_GETPALETTE: /* get color palette */
+ case FBIO_SETPALETTE: /* set color palette */
+ /* XXX */
+
+ case FBIOPUTCMAP:
+ case FBIOGETCMAP:
+ /* XXX */
+
+ case FBIO_SETWINORG: /* set frame buffer window origin */
+ case FBIO_SETDISPSTART: /* set display start address */
+ case FBIO_SETLINEWIDTH: /* set scan line width in pixel */
+
+ case FBIOGTYPE:
+ case FBIOGATTR:
+ case FBIOSVIDEO:
+ case FBIOGVIDEO:
+ case FBIOSCURSOR:
+ case FBIOGCURSOR:
+ case FBIOSCURPOS:
+ case FBIOGCURPOS:
+ case FBIOGCURMAX:
+
+ default:
+ error = ENODEV;
+ break;
+ }
+
+ splx(s);
+ return error;
+}
diff --git a/sys/dev/fb/fbreg.h b/sys/dev/fb/fbreg.h
index 561ac57..ff13bd8 100644
--- a/sys/dev/fb/fbreg.h
+++ b/sys/dev/fb/fbreg.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: fbreg.h,v 1.2 1999/01/19 11:31:11 yokota Exp $
+ * $Id: fbreg.h,v 1.3 1999/04/12 13:34:56 des Exp $
*/
#ifndef _DEV_FB_FBREG_H_
@@ -35,15 +35,22 @@
/* some macros */
#ifdef __i386__
-#define bcopy_toio(s, d, c) generic_bcopy((void *)(s), (void *)(d), c)
-#define bcopy_fromio(s, d, c) generic_bcopy((void *)(s), (void *)(d), c)
-#define bzero_io(d, c) generic_bzero((void *)(d), c)
+#define bcopy_io(s, d, c) generic_bcopy((void *)(s), (void *)(d), (c))
+#define bcopy_toio(s, d, c) generic_bcopy((void *)(s), (void *)(d), (c))
+#define bcopy_fromio(s, d, c) generic_bcopy((void *)(s), (void *)(d), (c))
+#define bzero_io(d, c) generic_bzero((void *)(d), (c))
+#define fill_io(p, d, c) fill((p), (void *)(d), (c))
+#define fillw_io(p, d, c) fillw((p), (void *)(d), (c))
void generic_bcopy(const void *s, void *d, size_t c);
void generic_bzero(void *d, size_t c);
#else /* !__i386__ */
-#define bcopy_toio(s, d, c) memcpy_toio(d, s, c)
-#define bcopy_fromio(s, d, c) memcpy_fromio(d, s, c)
-#define bzero_io(d, c) memset_io(d, 0, c)
+#define bcopy_io(s, d, c) memcpy_io((d), (s), (c))
+#define bcopy_toio(s, d, c) memcpy_toio((d), (void *)(s), (c))
+#define bcopy_fromio(s, d, c) memcpy_fromio((void *)(d), (s), (c))
+#define bzero_io(d, c) memset_io((d), 0, (c))
+#define fill_io(p, d, c) memset_io((d), (p), (c))
+#define fillw(p, d, c) memsetw((d), (p), (c))
+#define fillw_io(p, d, c) memsetw_io((d), (p), (c))
#endif /* !__i386__ */
/* video function table */
@@ -68,12 +75,16 @@ typedef int vi_set_hw_cursor_t(video_adapter_t *adp, int col, int row);
typedef int vi_set_hw_cursor_shape_t(video_adapter_t *adp, int base,
int height, int celsize, int blink);
typedef int vi_blank_display_t(video_adapter_t *adp, int mode);
-#define V_DISPLAY_POWER_ON 0
-#define V_DISPLAY_SUSPEND 1
-#define V_DISPLAY_SUSPEND1 1
-#define V_DISPLAY_SUSPEND2 2
-#define V_DISPLAY_POWER_OFF 3
-typedef int vi_mmap_t(video_adapter_t *adp, vm_offset_t offset);
+#define V_DISPLAY_ON 0
+#define V_DISPLAY_BLANK 1
+#define V_DISPLAY_STAND_BY 2
+#define V_DISPLAY_SUSPEND 3
+typedef int vi_mmap_t(video_adapter_t *adp, vm_offset_t offset, int prot);
+typedef int vi_ioctl_t(video_adapter_t *adp, u_long cmd, caddr_t data);
+typedef int vi_clear_t(video_adapter_t *adp);
+typedef int vi_fill_rect_t(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+typedef int vi_bitblt_t(video_adapter_t *adp,...);
typedef int vi_diag_t(video_adapter_t *adp, int level);
typedef struct video_switch {
@@ -96,6 +107,12 @@ typedef struct video_switch {
vi_set_hw_cursor_shape_t *set_hw_cursor_shape;
vi_blank_display_t *blank_display;
vi_mmap_t *mmap;
+ vi_ioctl_t *ioctl;
+ vi_clear_t *clear;
+ vi_fill_rect_t *fill_rect;
+ vi_bitblt_t *bitblt;
+ int (*reserved1)(void);
+ int (*reserved2)(void);
vi_diag_t *diag;
} video_switch_t;
@@ -158,6 +175,26 @@ int fb_attach(dev_t dev, video_adapter_t *adp,
int fb_detach(dev_t dev, video_adapter_t *adp,
struct cdevsw *cdevsw);
+/* generic frame buffer cdev driver functions */
+
+typedef struct genfb_softc {
+ int gfb_flags; /* flag/status bits */
+#define FB_OPEN (1 << 0)
+} genfb_softc_t;
+
+int genfbopen(genfb_softc_t *sc, video_adapter_t *adp,
+ int flag, int mode, struct proc *p);
+int genfbclose(genfb_softc_t *sc, video_adapter_t *adp,
+ int flag, int mode, struct proc *p);
+int genfbread(genfb_softc_t *sc, video_adapter_t *adp,
+ struct uio *uio, int flag);
+int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp,
+ struct uio *uio, int flag);
+int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp,
+ u_long cmd, caddr_t arg, int flag, struct proc *p);
+int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp,
+ vm_offset_t offset, int prot);
+
#endif /* FB_INSTALL_CDEV */
/* generic low-level driver functions */
@@ -165,6 +202,8 @@ int fb_detach(dev_t dev, video_adapter_t *adp,
void fb_dump_adp_info(char *driver, video_adapter_t *adp, int level);
void fb_dump_mode_info(char *driver, video_adapter_t *adp,
video_info_t *info, int level);
+int fb_type(int adp_type);
+int fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg);
#endif /* KERNEL */
diff --git a/sys/dev/fb/splash.c b/sys/dev/fb/splash.c
index e8f9cf2..40f1d01 100644
--- a/sys/dev/fb/splash.c
+++ b/sys/dev/fb/splash.c
@@ -35,8 +35,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/linker.h>
-
-#include <machine/console.h>
+#include <sys/fbio.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/splashreg.h>
@@ -51,7 +50,8 @@ static splash_decoder_t **decoder_set;
#define DECODER_ARRAY_DELTA 4
/* console driver callback */
-static int (*splash_callback)(int);
+static int (*splash_callback)(int, void *);
+static void *splash_arg;
static int
splash_find_data(splash_decoder_t *decoder)
@@ -98,7 +98,7 @@ splash_new(splash_decoder_t *decoder)
{
splash_decoder = decoder;
if (splash_callback != NULL)
- (*splash_callback)(SPLASH_INIT);
+ (*splash_callback)(SPLASH_INIT, splash_arg);
}
int
@@ -159,12 +159,13 @@ splash_unregister(splash_decoder_t *decoder)
}
int
-splash_init(video_adapter_t *adp, int (*callback)(int))
+splash_init(video_adapter_t *adp, int (*callback)(int, void *), void *arg)
{
int i;
splash_adp = adp;
splash_callback = callback;
+ splash_arg = arg;
splash_decoder = NULL;
for (i = 0; i < decoders; ++i) {
@@ -187,9 +188,11 @@ splash_term(video_adapter_t *adp)
{
int error = 0;
+ if (splash_adp != adp)
+ return EINVAL;
if (splash_decoder != NULL) {
if (splash_callback != NULL)
- error = (*splash_callback)(SPLASH_TERM);
+ error = (*splash_callback)(SPLASH_TERM, splash_arg);
if (error == 0)
error = (*splash_decoder->term)(adp);
if (error == 0)
diff --git a/sys/dev/fb/splash_bmp.c b/sys/dev/fb/splash_bmp.c
index 44ac914..6de5a28 100644
--- a/sys/dev/fb/splash_bmp.c
+++ b/sys/dev/fb/splash_bmp.c
@@ -24,15 +24,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: splash_bmp.c,v 1.7 1999/03/29 15:13:53 yokota Exp $
+ * $Id: splash_bmp.c,v 1.8 1999/06/16 14:04:45 yokota Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/linker.h>
-
-#include <machine/console.h>
+#include <sys/fbio.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/splashreg.h>
diff --git a/sys/dev/fb/splash_pcx.c b/sys/dev/fb/splash_pcx.c
index 3066bb3..5423295 100644
--- a/sys/dev/fb/splash_pcx.c
+++ b/sys/dev/fb/splash_pcx.c
@@ -27,15 +27,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * $Id: splash_pcx.c,v 1.1 1999/04/12 13:39:11 des Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/linker.h>
-
-#include <machine/console.h>
+#include <sys/fbio.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/splashreg.h>
diff --git a/sys/dev/fb/splashreg.h b/sys/dev/fb/splashreg.h
index fb78534..a34a3b9 100644
--- a/sys/dev/fb/splashreg.h
+++ b/sys/dev/fb/splashreg.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: splashreg.h,v 1.1 1999/01/09 02:44:49 yokota Exp $
+ * $Id: splashreg.h,v 1.2 1999/01/11 03:06:28 yokota Exp $
*/
#ifndef _DEV_FB_SPLASHREG_H_
@@ -91,7 +91,8 @@ int splash_register(splash_decoder_t *decoder);
int splash_unregister(splash_decoder_t *decoder);
/* entry points for the console driver */
-int splash_init(video_adapter_t *adp, int (*callback)(int));
+int splash_init(video_adapter_t *adp, int (*callback)(int, void *),
+ void *arg);
int splash_term(video_adapter_t *adp);
int splash(video_adapter_t *adp, int on);
diff --git a/sys/dev/fb/vga.c b/sys/dev/fb/vga.c
new file mode 100644
index 0000000..91f99e9
--- /dev/null
+++ b/sys/dev/fb/vga.c
@@ -0,0 +1,3041 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * Copyright (c) 1992-1998 Søren Schmidt
+ * 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 as
+ * the first lines of this file unmodified.
+ * 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. 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 AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id: $
+ */
+
+#include "vga.h"
+#include "opt_vga.h"
+#include "opt_fb.h"
+#include "opt_syscons.h" /* should be removed in the future, XXX */
+
+#if NVGA > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/fbio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/md_var.h>
+#include <machine/pc/bios.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/vgareg.h>
+
+#include <isa/isareg.h>
+
+#ifndef VGA_DEBUG
+#define VGA_DEBUG 0
+#endif
+
+int
+vga_probe_unit(int unit, video_adapter_t *buf, int flags)
+{
+ video_adapter_t *adp;
+ video_switch_t *sw;
+ int error;
+
+ sw = vid_get_switch(VGA_DRIVER_NAME);
+ if (sw == NULL)
+ return 0;
+ error = (*sw->probe)(unit, &adp, NULL, flags);
+ if (error)
+ return error;
+ bcopy(adp, buf, sizeof(*buf));
+ return 0;
+}
+
+int
+vga_attach_unit(int unit, vga_softc_t *sc, int flags)
+{
+ video_switch_t *sw;
+ int error;
+
+ sw = vid_get_switch(VGA_DRIVER_NAME);
+ if (sw == NULL)
+ return ENXIO;
+
+ error = (*sw->probe)(unit, &sc->adp, NULL, flags);
+ if (error)
+ return error;
+ return (*sw->init)(unit, sc->adp, flags);
+}
+
+/* cdev driver functions */
+
+#ifdef FB_INSTALL_CDEV
+
+int
+vga_open(dev_t dev, vga_softc_t *sc, int flag, int mode, struct proc *p)
+{
+ if (sc == NULL)
+ return ENXIO;
+ if (mode & (O_CREAT | O_APPEND | O_TRUNC))
+ return ENODEV;
+
+ return genfbopen(&sc->gensc, sc->adp, flag, mode, p);
+}
+
+int
+vga_close(dev_t dev, vga_softc_t *sc, int flag, int mode, struct proc *p)
+{
+ return genfbclose(&sc->gensc, sc->adp, flag, mode, p);
+}
+
+int
+vga_read(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
+{
+ return genfbread(&sc->gensc, sc->adp, uio, flag);
+}
+
+int
+vga_write(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
+{
+ return genfbread(&sc->gensc, sc->adp, uio, flag);
+}
+
+int
+vga_ioctl(dev_t dev, vga_softc_t *sc, u_long cmd, caddr_t arg, int flag,
+ struct proc *p)
+{
+ return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, p);
+}
+
+int
+vga_mmap(dev_t dev, vga_softc_t *sc, vm_offset_t offset, int prot)
+{
+ return genfbmmap(&sc->gensc, sc->adp, offset, prot);
+}
+
+#endif /* FB_INSTALL_CDEV */
+
+/* LOW-LEVEL */
+
+#include <machine/clock.h>
+#include <machine/pc/vesa.h>
+
+#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
+#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
+#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
+
+/* for compatibility with old kernel options */
+#ifdef SC_ALT_SEQACCESS
+#undef SC_ALT_SEQACCESS
+#undef VGA_ALT_SEQACCESS
+#define VGA_ALT_SEQACCESS 1
+#endif
+
+#ifdef SLOW_VGA
+#undef SLOW_VGA
+#undef VGA_SLOW_IOACCESS
+#define VGA_SLOW_IOACCESS 1
+#endif
+
+/* architecture dependent option */
+#ifdef __alpha__
+#define VGA_NO_BIOS 1
+#endif
+
+/* this should really be in `rtc.h' */
+#define RTC_EQUIPMENT 0x14
+
+/* various sizes */
+#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)
+#define V_MODE_PARAM_SIZE 64
+
+/* video adapter state buffer */
+struct adp_state {
+ int sig;
+#define V_STATE_SIG 0x736f6962
+ u_char regs[V_MODE_PARAM_SIZE];
+};
+typedef struct adp_state adp_state_t;
+
+/* video adapter information */
+#define DCC_MONO 0
+#define DCC_CGA40 1
+#define DCC_CGA80 2
+#define DCC_EGAMONO 3
+#define DCC_EGA40 4
+#define DCC_EGA80 5
+
+/*
+ * NOTE: `va_window' should have a virtual address, but is initialized
+ * with a physical address in the following table, as verify_adapter()
+ * will perform address conversion at run-time.
+ */
+static video_adapter_t adapter_init_value[] = {
+ /* DCC_MONO */
+ { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
+ 0, 0, 0, 0, 7, 0, },
+ /* DCC_CGA40 */
+ { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
+ 0, 0, 0, 0, 3, 0, },
+ /* DCC_CGA80 */
+ { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
+ 0, 0, 0, 0, 3, 0, },
+ /* DCC_EGAMONO */
+ { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC,
+ EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
+ 0, 0, 0, 0, 7, 0, },
+ /* DCC_EGA40 */
+ { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
+ EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
+ 0, 0, 0, 0, 3, 0, },
+ /* DCC_EGA80 */
+ { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
+ EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
+ 0, 0, 0, 0, 3, 0, },
+};
+
+static video_adapter_t biosadapter[2];
+static int biosadapters = 0;
+
+/* video driver declarations */
+static int vga_configure(int flags);
+ int (*vga_sub_configure)(int flags);
+static int vga_nop(void);
+static int vga_error(void);
+static vi_probe_t vga_probe;
+static vi_init_t vga_init;
+static vi_get_info_t vga_get_info;
+static vi_query_mode_t vga_query_mode;
+static vi_set_mode_t vga_set_mode;
+static vi_save_font_t vga_save_font;
+static vi_load_font_t vga_load_font;
+static vi_show_font_t vga_show_font;
+static vi_save_palette_t vga_save_palette;
+static vi_load_palette_t vga_load_palette;
+static vi_set_border_t vga_set_border;
+static vi_save_state_t vga_save_state;
+static vi_load_state_t vga_load_state;
+static vi_set_win_org_t vga_set_origin;
+static vi_read_hw_cursor_t vga_read_hw_cursor;
+static vi_set_hw_cursor_t vga_set_hw_cursor;
+static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;
+static vi_blank_display_t vga_blank_display;
+static vi_mmap_t vga_mmap_buf;
+static vi_ioctl_t vga_dev_ioctl;
+#ifndef VGA_NO_MODE_CHANGE
+static vi_clear_t vga_clear;
+static vi_fill_rect_t vga_fill_rect;
+static vi_bitblt_t vga_bitblt;
+#else /* VGA_NO_MODE_CHANGE */
+#define vga_clear (vi_clear_t *)vga_error
+#define vga_fill_rect (vi_fill_rect_t *)vga_error
+#define vga_bitblt (vi_bitblt_t *)vga_error
+#endif
+static vi_diag_t vga_diag;
+
+static video_switch_t vgavidsw = {
+ vga_probe,
+ vga_init,
+ vga_get_info,
+ vga_query_mode,
+ vga_set_mode,
+ vga_save_font,
+ vga_load_font,
+ vga_show_font,
+ vga_save_palette,
+ vga_load_palette,
+ vga_set_border,
+ vga_save_state,
+ vga_load_state,
+ vga_set_origin,
+ vga_read_hw_cursor,
+ vga_set_hw_cursor,
+ vga_set_hw_cursor_shape,
+ vga_blank_display,
+ vga_mmap_buf,
+ vga_dev_ioctl,
+ vga_clear,
+ vga_fill_rect,
+ vga_bitblt,
+ vga_error,
+ vga_error,
+ vga_diag,
+};
+
+VIDEO_DRIVER(mda, vgavidsw, NULL);
+VIDEO_DRIVER(cga, vgavidsw, NULL);
+VIDEO_DRIVER(ega, vgavidsw, NULL);
+VIDEO_DRIVER(vga, vgavidsw, vga_configure);
+
+/* VGA BIOS standard video modes */
+#define EOT (-1)
+#define NA (-2)
+
+static video_info_t bios_vmode[] = {
+ /* CGA */
+ { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ /* EGA */
+ { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ /* VGA */
+ { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ /* MDA */
+ { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ /* EGA */
+ { M_ENH_B80x43, 0, 80, 43, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ /* VGA */
+ { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+
+#ifndef VGA_NO_MODE_CHANGE
+
+#ifdef VGA_WIDTH90
+ { M_VGA_M90x25, 0, 90, 25, 8, 16, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C90x25, V_INFO_COLOR, 90, 25, 8, 16, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M90x30, 0, 90, 30, 8, 16, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C90x30, V_INFO_COLOR, 90, 30, 8, 16, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M90x43, 0, 90, 43, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C90x43, V_INFO_COLOR, 90, 43, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M90x50, 0, 90, 50, 8, 8, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C90x50, V_INFO_COLOR, 90, 50, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_M90x60, 0, 90, 60, 8, 8, 2, 1,
+ MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+ { M_VGA_C90x60, V_INFO_COLOR, 90, 60, 8, 8, 4, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
+#endif /* VGA_WIDTH90 */
+
+ /* CGA */
+ { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
+ { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
+ { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1,
+ CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
+ /* EGA */
+ { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
+ V_INFO_MM_PLANAR },
+ { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ /* VGA */
+ { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
+ V_INFO_MM_PLANAR },
+ { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+ { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+#endif /* VGA_NO_MODE_CHANGE */
+
+ { EOT },
+};
+
+static int vga_init_done = FALSE;
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+static u_char *video_mode_ptr = NULL; /* EGA/VGA */
+static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */
+#endif
+static u_char *mode_map[V_MODE_MAP_SIZE];
+static adp_state_t adpstate;
+static adp_state_t adpstate2;
+static int rows_offset = 1;
+
+/* local macros and functions */
+#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
+
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+static void map_mode_table(u_char *map[], u_char *table, int max);
+#endif
+static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max,
+ int color);
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+static int map_mode_num(int mode);
+#endif
+static int map_gen_mode_num(int type, int color, int mode);
+static int map_bios_mode_num(int type, int color, int bios_mode);
+static u_char *get_mode_param(int mode);
+#ifndef VGA_NO_BIOS
+static void fill_adapter_param(int code, video_adapter_t *adp);
+#endif
+static int verify_adapter(video_adapter_t *adp);
+static void update_adapter_info(video_adapter_t *adp, video_info_t *info);
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+#define COMP_IDENTICAL 0
+#define COMP_SIMILAR 1
+#define COMP_DIFFERENT 2
+static int comp_adpregs(u_char *buf1, u_char *buf2);
+#endif
+static int probe_adapters(void);
+static int set_line_length(video_adapter_t *adp, int pixel);
+static int set_display_start(video_adapter_t *adp, int x, int y);
+static void filll_io(int val, vm_offset_t d, size_t size);
+
+#ifndef VGA_NO_MODE_CHANGE
+#ifdef VGA_WIDTH90
+static void set_width90(adp_state_t *params);
+#endif
+#endif /* !VGA_NO_MODE_CHANGE */
+
+#ifndef VGA_NO_FONT_LOADING
+#define PARAM_BUFSIZE 6
+static void set_font_mode(video_adapter_t *adp, u_char *buf);
+static void set_normal_mode(video_adapter_t *adp, u_char *buf);
+#endif
+
+#ifndef VGA_NO_MODE_CHANGE
+static void planar_fill(video_adapter_t *adp, int val);
+static void packed_fill(video_adapter_t *adp, int val);
+static void direct_fill(video_adapter_t *adp, int val);
+#ifdef notyet
+static void planar_fill_rect(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+static void packed_fill_rect(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+static void direct_fill_rect16(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+static void direct_fill_rect24(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+static void direct_fill_rect32(video_adapter_t *adp, int val, int x, int y,
+ int cx, int cy);
+#endif /* notyet */
+#endif /* !VGA_NO_MODE_CHANGE */
+
+static void dump_buffer(u_char *buf, size_t len);
+
+#define ISMAPPED(pa, width) \
+ (((pa) <= (u_long)0x1000 - (width)) \
+ || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))
+
+#define prologue(adp, flag, err) \
+ if (!vga_init_done || !((adp)->va_flags & (flag))) \
+ return (err)
+
+/* a backdoor for the console driver */
+static int
+vga_configure(int flags)
+{
+ int i;
+
+ probe_adapters();
+ for (i = 0; i < biosadapters; ++i) {
+ if (!probe_done(&biosadapter[i]))
+ continue;
+ biosadapter[i].va_flags |= V_ADP_INITIALIZED;
+ if (!config_done(&biosadapter[i])) {
+ if (vid_register(&biosadapter[i]) < 0)
+ continue;
+ biosadapter[i].va_flags |= V_ADP_REGISTERED;
+ }
+ }
+ if (vga_sub_configure != NULL)
+ (*vga_sub_configure)(flags);
+
+ return biosadapters;
+}
+
+/* local subroutines */
+
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+/* construct the mode parameter map */
+static void
+map_mode_table(u_char *map[], u_char *table, int max)
+{
+ int i;
+
+ for(i = 0; i < max; ++i)
+ map[i] = table + i*V_MODE_PARAM_SIZE;
+ for(; i < V_MODE_MAP_SIZE; ++i)
+ map[i] = NULL;
+}
+#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
+
+static void
+clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color)
+{
+ video_info_t info;
+ int i;
+
+ /*
+ * NOTE: we don't touch `bios_vmode[]' because it is shared
+ * by all adapters.
+ */
+ for(i = 0; i < max; ++i) {
+ if (vga_get_info(adp, i, &info))
+ continue;
+ if ((info.vi_flags & V_INFO_COLOR) != color)
+ map[i] = NULL;
+ }
+}
+
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+/* map the non-standard video mode to a known mode number */
+static int
+map_mode_num(int mode)
+{
+ static struct {
+ int from;
+ int to;
+ } mode_map[] = {
+ { M_ENH_B80x43, M_ENH_B80x25 },
+ { M_ENH_C80x43, M_ENH_C80x25 },
+ { M_VGA_M80x30, M_VGA_M80x25 },
+ { M_VGA_C80x30, M_VGA_C80x25 },
+ { M_VGA_M80x50, M_VGA_M80x25 },
+ { M_VGA_C80x50, M_VGA_C80x25 },
+ { M_VGA_M80x60, M_VGA_M80x25 },
+ { M_VGA_C80x60, M_VGA_C80x25 },
+#ifdef VGA_WIDTH90
+ { M_VGA_M90x25, M_VGA_M80x25 },
+ { M_VGA_C90x25, M_VGA_C80x25 },
+ { M_VGA_M90x30, M_VGA_M80x25 },
+ { M_VGA_C90x30, M_VGA_C80x25 },
+ { M_VGA_M90x43, M_ENH_B80x25 },
+ { M_VGA_C90x43, M_ENH_C80x25 },
+ { M_VGA_M90x50, M_VGA_M80x25 },
+ { M_VGA_C90x50, M_VGA_C80x25 },
+ { M_VGA_M90x60, M_VGA_M80x25 },
+ { M_VGA_C90x60, M_VGA_C80x25 },
+#endif
+ { M_VGA_MODEX, M_VGA_CG320 },
+ };
+ int i;
+
+ for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
+ if (mode_map[i].from == mode)
+ return mode_map[i].to;
+ }
+ return mode;
+}
+#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
+
+/* map a generic video mode to a known mode number */
+static int
+map_gen_mode_num(int type, int color, int mode)
+{
+ static struct {
+ int from;
+ int to_color;
+ int to_mono;
+ } mode_map[] = {
+ { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, },
+ { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, },
+ { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, },
+ { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, },
+ };
+ int i;
+
+ if (mode == M_TEXT_80x25) {
+ switch (type) {
+
+ case KD_VGA:
+ if (color)
+ return M_VGA_C80x25;
+ else
+ return M_VGA_M80x25;
+ break;
+
+ case KD_EGA:
+ if (color)
+ return M_ENH_C80x25;
+ else
+ return M_EGAMONO80x25;
+ break;
+
+ case KD_CGA:
+ return M_C80x25;
+
+ case KD_MONO:
+ case KD_HERCULES:
+ return M_EGAMONO80x25; /* XXX: this name is confusing */
+
+ default:
+ return -1;
+ }
+ }
+
+ for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
+ if (mode_map[i].from == mode)
+ return ((color) ? mode_map[i].to_color : mode_map[i].to_mono);
+ }
+ return mode;
+}
+
+/* turn the BIOS video number into our video mode number */
+static int
+map_bios_mode_num(int type, int color, int bios_mode)
+{
+ static int cga_modes[7] = {
+ M_B40x25, M_C40x25, /* 0, 1 */
+ M_B80x25, M_C80x25, /* 2, 3 */
+ M_BG320, M_CG320,
+ M_BG640,
+ };
+ static int ega_modes[17] = {
+ M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */
+ M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */
+ M_BG320, M_CG320,
+ M_BG640,
+ M_EGAMONO80x25, /* 7 */
+ 8, 9, 10, 11, 12,
+ M_CG320_D,
+ M_CG640_E,
+ M_ENHMONOAPA2, /* XXX: video momery > 64K */
+ M_ENH_CG640, /* XXX: video momery > 64K */
+ };
+ static int vga_modes[20] = {
+ M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */
+ M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */
+ M_BG320, M_CG320,
+ M_BG640,
+ M_VGA_M80x25, /* 7 */
+ 8, 9, 10, 11, 12,
+ M_CG320_D,
+ M_CG640_E,
+ M_ENHMONOAPA2,
+ M_ENH_CG640,
+ M_BG640x480, M_CG640x480,
+ M_VGA_CG320,
+ };
+
+ switch (type) {
+
+ case KD_VGA:
+ if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
+ return vga_modes[bios_mode];
+ else if (color)
+ return M_VGA_C80x25;
+ else
+ return M_VGA_M80x25;
+ break;
+
+ case KD_EGA:
+ if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
+ return ega_modes[bios_mode];
+ else if (color)
+ return M_ENH_C80x25;
+ else
+ return M_EGAMONO80x25;
+ break;
+
+ case KD_CGA:
+ if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
+ return cga_modes[bios_mode];
+ else
+ return M_C80x25;
+ break;
+
+ case KD_MONO:
+ case KD_HERCULES:
+ return M_EGAMONO80x25; /* XXX: this name is confusing */
+
+ default:
+ break;
+ }
+ return -1;
+}
+
+/* look up a parameter table entry */
+static u_char
+*get_mode_param(int mode)
+{
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ if (mode >= V_MODE_MAP_SIZE)
+ mode = map_mode_num(mode);
+#endif
+ if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
+ return mode_map[mode];
+ else
+ return NULL;
+}
+
+#ifndef VGA_NO_BIOS
+static void
+fill_adapter_param(int code, video_adapter_t *adp)
+{
+ static struct {
+ int primary;
+ int secondary;
+ } dcc[] = {
+ { DCC_MONO, DCC_EGA40 /* CGA monitor */ },
+ { DCC_MONO, DCC_EGA80 /* CGA monitor */ },
+ { DCC_MONO, DCC_EGA80 /* CGA emulation */ },
+ { DCC_MONO, DCC_EGA80 },
+ { DCC_CGA40, DCC_EGAMONO },
+ { DCC_CGA80, DCC_EGAMONO },
+ { DCC_EGA40 /* CGA monitor */, DCC_MONO},
+ { DCC_EGA80 /* CGA monitor */, DCC_MONO},
+ { DCC_EGA80 /* CGA emulation */,DCC_MONO },
+ { DCC_EGA80, DCC_MONO },
+ { DCC_EGAMONO, DCC_CGA40 },
+ { DCC_EGAMONO, DCC_CGA40 },
+ };
+
+ if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
+ adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
+ adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
+ } else {
+ adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
+ adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
+ }
+}
+#endif /* VGA_NO_BIOS */
+
+static int
+verify_adapter(video_adapter_t *adp)
+{
+ vm_offset_t buf;
+ u_int16_t v;
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ u_int32_t p;
+#endif
+
+ buf = BIOS_PADDRTOVADDR(adp->va_window);
+ v = readw(buf);
+ writew(buf, 0xA55A);
+ if (readw(buf) != 0xA55A)
+ return ENXIO;
+ writew(buf, v);
+
+ switch (adp->va_type) {
+
+ case KD_EGA:
+ outb(adp->va_crtc_addr, 7);
+ if (inb(adp->va_crtc_addr) == 7) {
+ adp->va_type = KD_VGA;
+ adp->va_name = "vga";
+ adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
+ }
+ adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER;
+ /* the color adapter may be in the 40x25 mode... XXX */
+
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ /* get the BIOS video mode pointer */
+ p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
+ p = BIOS_SADDRTOLADDR(p);
+ if (ISMAPPED(p, sizeof(u_int32_t))) {
+ p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
+ p = BIOS_SADDRTOLADDR(p);
+ if (ISMAPPED(p, V_MODE_PARAM_SIZE))
+ video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
+ }
+#endif
+ break;
+
+ case KD_CGA:
+ adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
+ /* may be in the 40x25 mode... XXX */
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ /* get the BIOS video mode pointer */
+ p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
+ p = BIOS_SADDRTOLADDR(p);
+ video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
+#endif
+ break;
+
+ case KD_MONO:
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ /* get the BIOS video mode pointer */
+ p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
+ p = BIOS_SADDRTOLADDR(p);
+ video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
+#endif
+ break;
+ }
+
+ return 0;
+}
+
+static void
+update_adapter_info(video_adapter_t *adp, video_info_t *info)
+{
+ adp->va_flags &= ~V_ADP_COLOR;
+ adp->va_flags |=
+ (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
+ adp->va_crtc_addr =
+ (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
+ adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
+ adp->va_window_size = info->vi_window_size;
+ adp->va_window_gran = info->vi_window_gran;
+ adp->va_window_orig = 0;
+ /* XXX */
+ adp->va_buffer = info->vi_buffer;
+ adp->va_buffer_size = info->vi_buffer_size;
+ if (info->vi_flags & V_INFO_GRAPHICS) {
+ switch (info->vi_depth/info->vi_planes) {
+ case 1:
+ adp->va_line_width = info->vi_width/8;
+ break;
+ case 2:
+ adp->va_line_width = info->vi_width/4;
+ break;
+ case 4:
+ adp->va_line_width = info->vi_width/2;
+ break;
+ case 8:
+ default: /* shouldn't happen */
+ adp->va_line_width = info->vi_width;
+ break;
+ }
+ } else {
+ adp->va_line_width = info->vi_width;
+ }
+ adp->va_disp_start.x = 0;
+ adp->va_disp_start.y = 0;
+ bcopy(info, &adp->va_info, sizeof(adp->va_info));
+}
+
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+/* compare two parameter table entries */
+static int
+comp_adpregs(u_char *buf1, u_char *buf2)
+{
+ static struct {
+ u_char mask;
+ } params[V_MODE_PARAM_SIZE] = {
+ {0xff}, {0x00}, {0xff}, /* COLS}, ROWS}, POINTS */
+ {0x00}, {0x00}, /* page length */
+ {0xfe}, {0xff}, {0xff}, {0xff}, /* sequencer registers */
+ {0xf3}, /* misc register */
+ {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, /* CRTC */
+ {0xff}, {0xff}, {0xff}, {0x7f}, {0xff},
+ {0x00}, {0x00}, {0x00}, {0x00}, {0x00},
+ {0x00}, {0xff}, {0x7f}, {0xff}, {0xff},
+ {0x7f}, {0xff}, {0xff}, {0xef}, {0xff},
+ {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* attribute controller regs */
+ {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
+ {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
+ {0xff}, {0xff}, {0xff}, {0xff}, {0xf0},
+ {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* GDC register */
+ {0xff}, {0xff}, {0xff}, {0xff},
+ };
+ int identical = TRUE;
+ int i;
+
+ if ((buf1 == NULL) || (buf2 == NULL))
+ return COMP_DIFFERENT;
+
+ for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
+ if (params[i].mask == 0) /* don't care */
+ continue;
+ if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
+ return COMP_DIFFERENT;
+ if (buf1[i] != buf2[i])
+ identical = FALSE;
+ }
+ return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
+}
+#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
+
+/* probe video adapters and return the number of detected adapters */
+static int
+probe_adapters(void)
+{
+ video_adapter_t *adp;
+ video_info_t info;
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ u_char *mp;
+#endif
+ int i;
+
+ /* do this test only once */
+ if (vga_init_done)
+ return biosadapters;
+ vga_init_done = TRUE;
+
+ /*
+ * Locate display adapters.
+ * The AT architecture supports upto two adapters. `syscons' allows
+ * the following combinations of adapters:
+ * 1) MDA + CGA
+ * 2) MDA + EGA/VGA color
+ * 3) CGA + EGA/VGA mono
+ * Note that `syscons' doesn't bother with MCGA as it is only
+ * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
+ * thus, they are not running FreeBSD!
+ * When there are two adapaters in the system, one becomes `primary'
+ * and the other `secondary'. The EGA adapter has a set of DIP
+ * switches on board for this information and the EGA BIOS copies
+ * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88).
+ * The VGA BIOS has more sophisticated mechanism and has this
+ * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
+ * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
+ */
+
+ /*
+ * Check rtc and BIOS data area.
+ * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
+ * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are
+ * zeros for EGA and VGA. However, the EGA/VGA BIOS sets
+ * these bits in BIOSDATA_EQUIPMENT according to the monitor
+ * type detected.
+ */
+#ifndef VGA_NO_BIOS
+ switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */
+ case 0:
+ /* EGA/VGA */
+ fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
+ biosadapter);
+ break;
+ case 1:
+ /* CGA 40x25 */
+ /* FIXME: switch to the 80x25 mode? XXX */
+ biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
+ biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
+ break;
+ case 2:
+ /* CGA 80x25 */
+ biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
+ biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
+ break;
+ case 3:
+ /* MDA */
+ biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
+ biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
+ break;
+ }
+#else
+ /* assume EGA/VGA? XXX */
+ biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80];
+ biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
+#endif /* VGA_NO_BIOS */
+
+ biosadapters = 0;
+ if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) {
+ ++biosadapters;
+ biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED;
+ biosadapter[V_ADP_SECONDARY].va_mode =
+ biosadapter[V_ADP_SECONDARY].va_initial_mode =
+ map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type,
+ biosadapter[V_ADP_SECONDARY].va_flags
+ & V_ADP_COLOR,
+ biosadapter[V_ADP_SECONDARY].va_initial_bios_mode);
+ } else {
+ biosadapter[V_ADP_SECONDARY].va_type = -1;
+ }
+ if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) {
+ ++biosadapters;
+ biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED;
+#ifndef VGA_NO_BIOS
+ biosadapter[V_ADP_PRIMARY].va_initial_bios_mode =
+ readb(BIOS_PADDRTOVADDR(0x449));
+#else
+ biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */
+#endif
+ biosadapter[V_ADP_PRIMARY].va_mode =
+ biosadapter[V_ADP_PRIMARY].va_initial_mode =
+ map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type,
+ biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
+ biosadapter[V_ADP_PRIMARY].va_initial_bios_mode);
+ } else {
+ biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY];
+ biosadapter[V_ADP_SECONDARY].va_type = -1;
+ }
+ if (biosadapters == 0)
+ return biosadapters;
+ biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY;
+ biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY;
+
+#if 0 /* we don't need these... */
+ fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...);
+ fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...);
+#endif
+
+#if notyet
+ /*
+ * We cannot have two video adapter of the same type; there must be
+ * only one of color or mono adapter, or one each of them.
+ */
+ if (biosadapters > 1) {
+ if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags)
+ & V_ADP_COLOR))
+ /* we have two mono or color adapters!! */
+ return (biosadapters = 0);
+ }
+#endif
+
+ /*
+ * Ensure a zero start address. This is mainly to recover after
+ * switching from pcvt using userconfig(). The registers are w/o
+ * for old hardware so it's too hard to relocate the active screen
+ * memory.
+ * This must be done before vga_save_state() for VGA.
+ */
+ outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12);
+ outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
+ outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13);
+ outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
+
+ /* the video mode parameter table in EGA/VGA BIOS */
+ /* NOTE: there can be only one EGA/VGA, wheather color or mono,
+ * recognized by the video BIOS.
+ */
+ if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
+ (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
+ adp = &biosadapter[V_ADP_PRIMARY];
+ } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
+ (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
+ adp = &biosadapter[V_ADP_SECONDARY];
+ } else {
+ adp = NULL;
+ }
+ bzero(mode_map, sizeof(mode_map));
+ if (adp != NULL) {
+ if (adp->va_type == KD_VGA) {
+ vga_save_state(adp, &adpstate, sizeof(adpstate));
+#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
+ mode_map[adp->va_initial_mode] = adpstate.regs;
+ rows_offset = 1;
+#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
+ if (video_mode_ptr == NULL) {
+ mode_map[adp->va_initial_mode] = adpstate.regs;
+ rows_offset = 1;
+ } else {
+ /* discard the table if we are not familiar with it... */
+ map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
+ mp = get_mode_param(adp->va_initial_mode);
+ if (mp != NULL)
+ bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
+ switch (comp_adpregs(adpstate.regs, mp)) {
+ case COMP_IDENTICAL:
+ /*
+ * OK, this parameter table looks reasonably familiar
+ * to us...
+ */
+ /*
+ * This is a kludge for Toshiba DynaBook SS433
+ * whose BIOS video mode table entry has the actual #
+ * of rows at the offset 1; BIOSes from other
+ * manufacturers store the # of rows - 1 there. XXX
+ */
+ rows_offset = adpstate.regs[1] + 1 - mp[1];
+ break;
+
+ case COMP_SIMILAR:
+ /*
+ * Not exactly the same, but similar enough to be
+ * trusted. However, use the saved register values
+ * for the initial mode and other modes which are
+ * based on the initial mode.
+ */
+ mode_map[adp->va_initial_mode] = adpstate.regs;
+ rows_offset = adpstate.regs[1] + 1 - mp[1];
+ adpstate.regs[1] -= rows_offset - 1;
+ break;
+
+ case COMP_DIFFERENT:
+ default:
+ /*
+ * Don't use the paramter table in BIOS. It doesn't
+ * look familiar to us. Video mode switching is allowed
+ * only if the new mode is the same as or based on
+ * the initial mode.
+ */
+ video_mode_ptr = NULL;
+ bzero(mode_map, sizeof(mode_map));
+ mode_map[adp->va_initial_mode] = adpstate.regs;
+ rows_offset = 1;
+ break;
+ }
+ }
+#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
+
+#ifndef VGA_NO_MODE_CHANGE
+ adp->va_flags |= V_ADP_MODECHANGE;
+#endif
+#ifndef VGA_NO_FONT_LOADING
+ adp->va_flags |= V_ADP_FONT;
+#endif
+ } else if (adp->va_type == KD_EGA) {
+#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
+ rows_offset = 1;
+#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
+ if (video_mode_ptr == NULL) {
+ rows_offset = 1;
+ } else {
+ map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
+ /* XXX how can one validate the EGA table... */
+ mp = get_mode_param(adp->va_initial_mode);
+ if (mp != NULL) {
+ adp->va_flags |= V_ADP_MODECHANGE;
+#ifndef VGA_NO_FONT_LOADING
+ adp->va_flags |= V_ADP_FONT;
+#endif
+ rows_offset = 1;
+ } else {
+ /*
+ * This is serious. We will not be able to switch video
+ * modes at all...
+ */
+ video_mode_ptr = NULL;
+ bzero(mode_map, sizeof(mode_map));
+ rows_offset = 1;
+ }
+ }
+#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
+ }
+ }
+
+ /* remove conflicting modes if we have more than one adapter */
+ if (biosadapters > 1) {
+ for (i = 0; i < biosadapters; ++i) {
+ if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE))
+ continue;
+ clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1,
+ (biosadapter[i].va_flags & V_ADP_COLOR) ?
+ V_INFO_COLOR : 0);
+ if ((biosadapter[i].va_type == KD_VGA)
+ || (biosadapter[i].va_type == KD_EGA)) {
+ biosadapter[i].va_io_base =
+ (biosadapter[i].va_flags & V_ADP_COLOR) ?
+ IO_VGA : IO_MDA;
+ biosadapter[i].va_io_size = 32;
+ }
+ }
+ }
+
+ /* buffer address */
+ vga_get_info(&biosadapter[V_ADP_PRIMARY],
+ biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
+ info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
+ update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info);
+
+ if (biosadapters > 1) {
+ vga_get_info(&biosadapter[V_ADP_SECONDARY],
+ biosadapter[V_ADP_SECONDARY].va_initial_mode, &info);
+ info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
+ update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info);
+ }
+
+ /*
+ * XXX: we should verify the following values for the primary adapter...
+ * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
+ * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
+ * ? 0 : V_ADP_COLOR;
+ * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
+ * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
+ * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
+ * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
+ */
+
+ return biosadapters;
+}
+
+/* set the scan line length in pixel */
+static int
+set_line_length(video_adapter_t *adp, int pixel)
+{
+ u_char *mp;
+ int ppw; /* pixels per word */
+ int bpl; /* bytes per line */
+ int count;
+
+ if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA))
+ return ENODEV;
+ mp = get_mode_param(adp->va_mode);
+ if (mp == NULL)
+ return EINVAL;
+
+ switch (adp->va_info.vi_mem_model) {
+ case V_INFO_MM_PLANAR:
+ ppw = 16/(adp->va_info.vi_depth/adp->va_info.vi_planes);
+ count = (pixel + ppw - 1)/ppw/2;
+ bpl = ((pixel + ppw - 1)/ppw/2)*4;
+ break;
+ case V_INFO_MM_PACKED:
+ count = (pixel + 7)/8;
+ bpl = ((pixel + 7)/8)*8;
+ break;
+ case V_INFO_MM_TEXT:
+ count = (pixel + 7)/8; /* columns */
+ bpl = (pixel + 7)/8; /* columns */
+ break;
+ default:
+ return ENODEV;
+ }
+
+ if (mp[10 + 0x17] & 0x40) /* CRTC mode control reg */
+ count *= 2; /* byte mode */
+ outb(adp->va_crtc_addr, 0x13);
+ outb(adp->va_crtc_addr + 1, count);
+ adp->va_line_width = bpl;
+
+ return 0;
+}
+
+static int
+set_display_start(video_adapter_t *adp, int x, int y)
+{
+ int off; /* byte offset (graphics mode)/word offset (text mode) */
+ int poff; /* pixel offset */
+ int roff; /* row offset */
+ int ppb; /* pixels per byte */
+
+ if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA))
+ x &= ~7;
+ if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
+ ppb = 8/(adp->va_info.vi_depth/adp->va_info.vi_planes);
+ off = y*adp->va_line_width + x/ppb;
+ roff = 0;
+ poff = x%ppb;
+ } else {
+ if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) {
+ outb(TSIDX, 1);
+ if (inb(TSREG) & 1)
+ ppb = 9;
+ else
+ ppb = 8;
+ } else {
+ ppb = 8;
+ }
+ off = y/adp->va_info.vi_cheight*adp->va_line_width + x/ppb;
+ roff = y%adp->va_info.vi_cheight;
+ /* FIXME: is this correct? XXX */
+ if (ppb == 8)
+ poff = x%ppb;
+ else
+ poff = (x + 8)%ppb;
+ }
+
+ /* start address */
+ outb(adp->va_crtc_addr, 0xc); /* high */
+ outb(adp->va_crtc_addr + 1, off >> 8);
+ outb(adp->va_crtc_addr, 0xd); /* low */
+ outb(adp->va_crtc_addr + 1, off & 0xff);
+
+ /* horizontal pel pan */
+ if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) {
+ inb(adp->va_crtc_addr + 6);
+ outb(ATC, 0x13 | 0x20);
+ outb(ATC, poff);
+ inb(adp->va_crtc_addr + 6);
+ outb(ATC, 0x20);
+ }
+
+ /* preset raw scan */
+ outb(adp->va_crtc_addr, 8);
+ outb(adp->va_crtc_addr + 1, roff);
+
+ adp->va_disp_start.x = x;
+ adp->va_disp_start.y = y;
+ return 0;
+}
+
+#ifdef __i386__ /* XXX */
+static void
+fill(int val, void *d, size_t size)
+{
+ u_char *p = d;
+
+ while (size-- > 0)
+ *p++ = val;
+}
+#endif /* __i386__ */
+
+static void
+filll_io(int val, vm_offset_t d, size_t size)
+{
+ while (size-- > 0) {
+ writel(d, val);
+ d += sizeof(u_int32_t);
+ }
+}
+
+/* entry points */
+
+static int
+vga_nop(void)
+{
+ return 0;
+}
+
+static int
+vga_error(void)
+{
+ return ENODEV;
+}
+
+static int
+vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
+{
+ probe_adapters();
+ if (unit >= biosadapters)
+ return ENXIO;
+
+ *adpp = &biosadapter[unit];
+
+ return 0;
+}
+
+static int
+vga_init(int unit, video_adapter_t *adp, int flags)
+{
+ if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp))
+ return ENXIO;
+
+ if (!init_done(adp)) {
+ /* nothing to do really... */
+ adp->va_flags |= V_ADP_INITIALIZED;
+ }
+
+ if (!config_done(adp)) {
+ if (vid_register(adp) < 0)
+ return ENXIO;
+ adp->va_flags |= V_ADP_REGISTERED;
+ }
+ if (vga_sub_configure != NULL)
+ (*vga_sub_configure)(0);
+
+ return 0;
+}
+
+/*
+ * get_info():
+ * Return the video_info structure of the requested video mode.
+ *
+ * all adapters
+ */
+static int
+vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+ int i;
+
+ if (!vga_init_done)
+ return ENXIO;
+
+ mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
+#ifndef VGA_NO_MODE_CHANGE
+ if (adp->va_flags & V_ADP_MODECHANGE) {
+ /*
+ * If the parameter table entry for this mode is not found,
+ * the mode is not supported...
+ */
+ if (get_mode_param(mode) == NULL)
+ return EINVAL;
+ } else
+#endif /* VGA_NO_MODE_CHANGE */
+ {
+ /*
+ * Even if we don't support video mode switching on this adapter,
+ * the information on the initial (thus current) video mode
+ * should be made available.
+ */
+ if (mode != adp->va_initial_mode)
+ return EINVAL;
+ }
+
+ for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+ if (bios_vmode[i].vi_mode == NA)
+ continue;
+ if (mode == bios_vmode[i].vi_mode) {
+ *info = bios_vmode[i];
+ /* XXX */
+ info->vi_buffer_size = info->vi_window_size*info->vi_planes;
+ return 0;
+ }
+ }
+ return EINVAL;
+}
+
+/*
+ * query_mode():
+ * Find a video mode matching the requested parameters.
+ * Fields filled with 0 are considered "don't care" fields and
+ * match any modes.
+ *
+ * all adapters
+ */
+static int
+vga_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+ video_info_t buf;
+ int i;
+
+ if (!vga_init_done)
+ return -1;
+
+ for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+ if (bios_vmode[i].vi_mode == NA)
+ continue;
+
+ if ((info->vi_width != 0)
+ && (info->vi_width != bios_vmode[i].vi_width))
+ continue;
+ if ((info->vi_height != 0)
+ && (info->vi_height != bios_vmode[i].vi_height))
+ continue;
+ if ((info->vi_cwidth != 0)
+ && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
+ continue;
+ if ((info->vi_cheight != 0)
+ && (info->vi_cheight != bios_vmode[i].vi_cheight))
+ continue;
+ if ((info->vi_depth != 0)
+ && (info->vi_depth != bios_vmode[i].vi_depth))
+ continue;
+ if ((info->vi_planes != 0)
+ && (info->vi_planes != bios_vmode[i].vi_planes))
+ continue;
+ /* XXX: should check pixel format, memory model */
+ if ((info->vi_flags != 0)
+ && (info->vi_flags != bios_vmode[i].vi_flags))
+ continue;
+
+ /* verify if this mode is supported on this adapter */
+ if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf))
+ continue;
+ return bios_vmode[i].vi_mode;
+ }
+ return -1;
+}
+
+/*
+ * set_mode():
+ * Change the video mode.
+ *
+ * EGA/VGA
+ */
+
+#ifndef VGA_NO_MODE_CHANGE
+#ifdef VGA_WIDTH90
+static void
+set_width90(adp_state_t *params)
+{
+ /*
+ * Based on code submitted by Kelly Yancey (kbyanc@freedomnet.com)
+ * and alexv@sui.gda.itesm.mx.
+ */
+ params->regs[5] |= 1; /* toggle 8 pixel wide fonts */
+ params->regs[10+0x0] = 0x6b;
+ params->regs[10+0x1] = 0x59;
+ params->regs[10+0x2] = 0x5a;
+ params->regs[10+0x3] = 0x8e;
+ params->regs[10+0x4] = 0x5e;
+ params->regs[10+0x5] = 0x8a;
+ params->regs[10+0x13] = 45;
+ params->regs[35+0x13] = 0;
+}
+#endif /* VGA_WIDTH90 */
+#endif /* !VGA_NO_MODE_CHANGE */
+
+static int
+vga_set_mode(video_adapter_t *adp, int mode)
+{
+#ifndef VGA_NO_MODE_CHANGE
+ video_info_t info;
+ adp_state_t params;
+
+ prologue(adp, V_ADP_MODECHANGE, ENODEV);
+
+ mode = map_gen_mode_num(adp->va_type,
+ adp->va_flags & V_ADP_COLOR, mode);
+ if (vga_get_info(adp, mode, &info))
+ return EINVAL;
+
+#if VGA_DEBUG > 1
+ printf("vga_set_mode(): setting mode %d\n", mode);
+#endif
+
+ params.sig = V_STATE_SIG;
+ bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
+
+ switch (mode) {
+#ifdef VGA_WIDTH90
+ case M_VGA_C90x60: case M_VGA_M90x60:
+ set_width90(&params);
+ /* FALL THROUGH */
+#endif
+ case M_VGA_C80x60: case M_VGA_M80x60:
+ params.regs[2] = 0x08;
+ params.regs[19] = 0x47;
+ goto special_480l;
+
+#ifdef VGA_WIDTH90
+ case M_VGA_C90x30: case M_VGA_M90x30:
+ set_width90(&params);
+ /* FALL THROUGH */
+#endif
+ case M_VGA_C80x30: case M_VGA_M80x30:
+ params.regs[19] = 0x4f;
+special_480l:
+ params.regs[9] |= 0xc0;
+ params.regs[16] = 0x08;
+ params.regs[17] = 0x3e;
+ params.regs[26] = 0xea;
+ params.regs[28] = 0xdf;
+ params.regs[31] = 0xe7;
+ params.regs[32] = 0x04;
+ goto setup_mode;
+
+#ifdef VGA_WIDTH90
+ case M_VGA_C90x43: case M_VGA_M90x43:
+ set_width90(&params);
+ /* FALL THROUGH */
+#endif
+ case M_ENH_C80x43: case M_ENH_B80x43:
+ params.regs[28] = 87;
+ goto special_80x50;
+
+#ifdef VGA_WIDTH90
+ case M_VGA_C90x50: case M_VGA_M90x50:
+ set_width90(&params);
+ /* FALL THROUGH */
+#endif
+ case M_VGA_C80x50: case M_VGA_M80x50:
+special_80x50:
+ params.regs[2] = 8;
+ params.regs[19] = 7;
+ goto setup_mode;
+
+#ifdef VGA_WIDTH90
+ case M_VGA_C90x25: case M_VGA_M90x25:
+ set_width90(&params);
+ /* FALL THROUGH */
+#endif
+ case M_VGA_C40x25: case M_VGA_C80x25:
+ case M_VGA_M80x25:
+ case M_B40x25: case M_C40x25:
+ case M_B80x25: case M_C80x25:
+ case M_ENH_B40x25: case M_ENH_C40x25:
+ case M_ENH_B80x25: case M_ENH_C80x25:
+ case M_EGAMONO80x25:
+
+setup_mode:
+ vga_load_state(adp, &params);
+ break;
+
+ case M_VGA_MODEX:
+ /* "unchain" the VGA mode */
+ params.regs[5-1+0x04] &= 0xf7;
+ params.regs[5-1+0x04] |= 0x04;
+ /* turn off doubleword mode */
+ params.regs[10+0x14] &= 0xbf;
+ /* turn off word adressing */
+ params.regs[10+0x17] |= 0x40;
+ /* set logical screen width */
+ params.regs[10+0x13] = 80;
+ /* set 240 lines */
+ params.regs[10+0x11] = 0x2c;
+ params.regs[10+0x06] = 0x0d;
+ params.regs[10+0x07] = 0x3e;
+ params.regs[10+0x10] = 0xea;
+ params.regs[10+0x11] = 0xac;
+ params.regs[10+0x12] = 0xdf;
+ params.regs[10+0x15] = 0xe7;
+ params.regs[10+0x16] = 0x06;
+ /* set vertical sync polarity to reflect aspect ratio */
+ params.regs[9] = 0xe3;
+ goto setup_grmode;
+
+ case M_BG320: case M_CG320: case M_BG640:
+ case M_CG320_D: case M_CG640_E:
+ case M_CG640x350: case M_ENH_CG640:
+ case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
+
+setup_grmode:
+ vga_load_state(adp, &params);
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ adp->va_mode = mode;
+ info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
+ update_adapter_info(adp, &info);
+
+ /* move hardware cursor out of the way */
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
+
+ return 0;
+#else /* VGA_NO_MODE_CHANGE */
+ return ENODEV;
+#endif /* VGA_NO_MODE_CHANGE */
+}
+
+#ifndef VGA_NO_FONT_LOADING
+
+static void
+set_font_mode(video_adapter_t *adp, u_char *buf)
+{
+ u_char *mp;
+ int s;
+
+ s = splhigh();
+
+ /* save register values */
+ if (adp->va_type == KD_VGA) {
+ outb(TSIDX, 0x02); buf[0] = inb(TSREG);
+ outb(TSIDX, 0x04); buf[1] = inb(TSREG);
+ outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
+ outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
+ outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
+ inb(adp->va_crtc_addr + 6);
+ outb(ATC, 0x10); buf[5] = inb(ATC + 1);
+ } else /* if (adp->va_type == KD_EGA) */ {
+ /*
+ * EGA cannot be read; copy parameters from the mode parameter
+ * table.
+ */
+ mp = get_mode_param(adp->va_mode);
+ buf[0] = mp[5 + 0x02 - 1];
+ buf[1] = mp[5 + 0x04 - 1];
+ buf[2] = mp[55 + 0x04];
+ buf[3] = mp[55 + 0x05];
+ buf[4] = mp[55 + 0x06];
+ buf[5] = mp[35 + 0x10];
+ }
+
+ /* setup vga for loading fonts */
+ inb(adp->va_crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
+ inb(adp->va_crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x20); /* enable palette */
+
+#if VGA_SLOW_IOACCESS
+#ifdef VGA_ALT_SEQACCESS
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+#endif
+ outb(TSIDX, 0x02); outb(TSREG, 0x04);
+ outb(TSIDX, 0x04); outb(TSREG, 0x07);
+#ifdef VGA_ALT_SEQACCESS
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+#endif
+ outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
+ outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
+ outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
+#else /* VGA_SLOW_IOACCESS */
+#ifdef VGA_ALT_SEQACCESS
+ outw(TSIDX, 0x0100);
+#endif
+ outw(TSIDX, 0x0402);
+ outw(TSIDX, 0x0704);
+#ifdef VGA_ALT_SEQACCESS
+ outw(TSIDX, 0x0300);
+#endif
+ outw(GDCIDX, 0x0204);
+ outw(GDCIDX, 0x0005);
+ outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */
+#endif /* VGA_SLOW_IOACCESS */
+
+ splx(s);
+}
+
+static void
+set_normal_mode(video_adapter_t *adp, u_char *buf)
+{
+ int s;
+
+ s = splhigh();
+
+ /* setup vga for normal operation mode again */
+ inb(adp->va_crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x10); outb(ATC, buf[5]);
+ inb(adp->va_crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x20); /* enable palette */
+
+#if VGA_SLOW_IOACCESS
+#ifdef VGA_ALT_SEQACCESS
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+#endif
+ outb(TSIDX, 0x02); outb(TSREG, buf[0]);
+ outb(TSIDX, 0x04); outb(TSREG, buf[1]);
+#ifdef VGA_ALT_SEQACCESS
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+#endif
+ outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
+ outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
+ if (adp->va_crtc_addr == MONO_CRTC) {
+ outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
+ } else {
+ outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
+ }
+#else /* VGA_SLOW_IOACCESS */
+#ifdef VGA_ALT_SEQACCESS
+ outw(TSIDX, 0x0100);
+#endif
+ outw(TSIDX, 0x0002 | (buf[0] << 8));
+ outw(TSIDX, 0x0004 | (buf[1] << 8));
+#ifdef VGA_ALT_SEQACCESS
+ outw(TSIDX, 0x0300);
+#endif
+ outw(GDCIDX, 0x0004 | (buf[2] << 8));
+ outw(GDCIDX, 0x0005 | (buf[3] << 8));
+ if (adp->va_crtc_addr == MONO_CRTC)
+ outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
+ else
+ outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
+#endif /* VGA_SLOW_IOACCESS */
+
+ splx(s);
+}
+
+#endif /* VGA_NO_FONT_LOADING */
+
+/*
+ * save_font():
+ * Read the font data in the requested font page from the video adapter.
+ *
+ * EGA/VGA
+ */
+static int
+vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
+ int ch, int count)
+{
+#ifndef VGA_NO_FONT_LOADING
+ u_char buf[PARAM_BUFSIZE];
+ u_int32_t segment;
+ int c;
+#ifdef VGA_ALT_SEQACCESS
+ int s;
+ u_char val = 0;
+#endif
+
+ prologue(adp, V_ADP_FONT, ENODEV);
+
+ if (fontsize < 14) {
+ /* FONT_8 */
+ fontsize = 8;
+ } else if (fontsize >= 32) {
+ fontsize = 32;
+ } else if (fontsize >= 16) {
+ /* FONT_16 */
+ fontsize = 16;
+ } else {
+ /* FONT_14 */
+ fontsize = 14;
+ }
+
+ if (page < 0 || page >= 8)
+ return EINVAL;
+ segment = FONT_BUF + 0x4000*page;
+ if (page > 3)
+ segment -= 0xe000;
+
+#ifdef VGA_ALT_SEQACCESS
+ if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
+ s = splhigh();
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+ outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
+ outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+ splx(s);
+ }
+#endif
+
+ set_font_mode(adp, buf);
+ if (fontsize == 32) {
+ bcopy_fromio(segment + ch*32, data, fontsize*count);
+ } else {
+ for (c = ch; count > 0; ++c, --count) {
+ bcopy_fromio(segment + c*32, data, fontsize);
+ data += fontsize;
+ }
+ }
+ set_normal_mode(adp, buf);
+
+#ifdef VGA_ALT_SEQACCESS
+ if (adp->va_type == KD_VGA) {
+ s = splhigh();
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+ outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+ splx(s);
+ }
+#endif
+
+ return 0;
+#else /* VGA_NO_FONT_LOADING */
+ return ENODEV;
+#endif /* VGA_NO_FONT_LOADING */
+}
+
+/*
+ * load_font():
+ * Set the font data in the requested font page.
+ * NOTE: it appears that some recent video adapters do not support
+ * the font page other than 0... XXX
+ *
+ * EGA/VGA
+ */
+static int
+vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
+ int ch, int count)
+{
+#ifndef VGA_NO_FONT_LOADING
+ u_char buf[PARAM_BUFSIZE];
+ u_int32_t segment;
+ int c;
+#ifdef VGA_ALT_SEQACCESS
+ int s;
+ u_char val = 0;
+#endif
+
+ prologue(adp, V_ADP_FONT, ENODEV);
+
+ if (fontsize < 14) {
+ /* FONT_8 */
+ fontsize = 8;
+ } else if (fontsize >= 32) {
+ fontsize = 32;
+ } else if (fontsize >= 16) {
+ /* FONT_16 */
+ fontsize = 16;
+ } else {
+ /* FONT_14 */
+ fontsize = 14;
+ }
+
+ if (page < 0 || page >= 8)
+ return EINVAL;
+ segment = FONT_BUF + 0x4000*page;
+ if (page > 3)
+ segment -= 0xe000;
+
+#ifdef VGA_ALT_SEQACCESS
+ if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
+ s = splhigh();
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+ outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
+ outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+ splx(s);
+ }
+#endif
+
+ set_font_mode(adp, buf);
+ if (fontsize == 32) {
+ bcopy_toio(data, segment + ch*32, fontsize*count);
+ } else {
+ for (c = ch; count > 0; ++c, --count) {
+ bcopy_toio(data, segment + c*32, fontsize);
+ data += fontsize;
+ }
+ }
+ set_normal_mode(adp, buf);
+
+#ifdef VGA_ALT_SEQACCESS
+ if (adp->va_type == KD_VGA) {
+ s = splhigh();
+ outb(TSIDX, 0x00); outb(TSREG, 0x01);
+ outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
+ outb(TSIDX, 0x00); outb(TSREG, 0x03);
+ splx(s);
+ }
+#endif
+
+ return 0;
+#else /* VGA_NO_FONT_LOADING */
+ return ENODEV;
+#endif /* VGA_NO_FONT_LOADING */
+}
+
+/*
+ * show_font():
+ * Activate the requested font page.
+ * NOTE: it appears that some recent video adapters do not support
+ * the font page other than 0... XXX
+ *
+ * EGA/VGA
+ */
+static int
+vga_show_font(video_adapter_t *adp, int page)
+{
+#ifndef VGA_NO_FONT_LOADING
+ static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
+ int s;
+
+ prologue(adp, V_ADP_FONT, ENODEV);
+ if (page < 0 || page >= 8)
+ return EINVAL;
+
+ s = splhigh();
+ outb(TSIDX, 0x03); outb(TSREG, cg[page]);
+ splx(s);
+
+ return 0;
+#else /* VGA_NO_FONT_LOADING */
+ return ENODEV;
+#endif /* VGA_NO_FONT_LOADING */
+}
+
+/*
+ * save_palette():
+ * Read DAC values. The values have expressed in 8 bits.
+ *
+ * VGA
+ */
+static int
+vga_save_palette(video_adapter_t *adp, u_char *palette)
+{
+ int i;
+
+ prologue(adp, V_ADP_PALETTE, ENODEV);
+
+ /*
+ * We store 8 bit values in the palette buffer, while the standard
+ * VGA has 6 bit DAC .
+ */
+ outb(PALRADR, 0x00);
+ for (i = 0; i < 256*3; ++i)
+ palette[i] = inb(PALDATA) << 2;
+ inb(adp->va_crtc_addr + 6); /* reset flip/flop */
+ return 0;
+}
+
+static int
+vga_save_palette2(video_adapter_t *adp, int base, int count,
+ u_char *r, u_char *g, u_char *b)
+{
+ int i;
+
+ prologue(adp, V_ADP_PALETTE, ENODEV);
+
+ outb(PALRADR, base);
+ for (i = 0; i < count; ++i) {
+ r[i] = inb(PALDATA) << 2;
+ g[i] = inb(PALDATA) << 2;
+ b[i] = inb(PALDATA) << 2;
+ }
+ inb(adp->va_crtc_addr + 6); /* reset flip/flop */
+ return 0;
+}
+
+/*
+ * load_palette():
+ * Set DAC values.
+ *
+ * VGA
+ */
+static int
+vga_load_palette(video_adapter_t *adp, u_char *palette)
+{
+ int i;
+
+ prologue(adp, V_ADP_PALETTE, ENODEV);
+
+ outb(PIXMASK, 0xff); /* no pixelmask */
+ outb(PALWADR, 0x00);
+ for (i = 0; i < 256*3; ++i)
+ outb(PALDATA, palette[i] >> 2);
+ inb(adp->va_crtc_addr + 6); /* reset flip/flop */
+ outb(ATC, 0x20); /* enable palette */
+ return 0;
+}
+
+static int
+vga_load_palette2(video_adapter_t *adp, int base, int count,
+ u_char *r, u_char *g, u_char *b)
+{
+ int i;
+
+ prologue(adp, V_ADP_PALETTE, ENODEV);
+
+ outb(PIXMASK, 0xff); /* no pixelmask */
+ outb(PALWADR, base);
+ for (i = 0; i < count; ++i) {
+ outb(PALDATA, r[i] >> 2);
+ outb(PALDATA, g[i] >> 2);
+ outb(PALDATA, b[i] >> 2);
+ }
+ inb(adp->va_crtc_addr + 6); /* reset flip/flop */
+ outb(ATC, 0x20); /* enable palette */
+ return 0;
+}
+
+/*
+ * set_border():
+ * Change the border color.
+ *
+ * CGA/EGA/VGA
+ */
+static int
+vga_set_border(video_adapter_t *adp, int color)
+{
+ prologue(adp, V_ADP_BORDER, ENODEV);
+
+ switch (adp->va_type) {
+ case KD_EGA:
+ case KD_VGA:
+ inb(adp->va_crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x31); outb(ATC, color & 0xff);
+ break;
+ case KD_CGA:
+ outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */
+ break;
+ case KD_MONO:
+ case KD_HERCULES:
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * save_state():
+ * Read video register values.
+ * NOTE: this function only reads the standard EGA/VGA registers.
+ * any extra/extended registers of SVGA adapters are not saved.
+ *
+ * VGA
+ */
+static int
+vga_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+ video_info_t info;
+ u_char *buf;
+ int crtc_addr;
+ int i, j;
+ int s;
+
+ if (size == 0) {
+ /* return the required buffer size */
+ prologue(adp, V_ADP_STATESAVE, 0);
+ return sizeof(adp_state_t);
+ } else {
+ prologue(adp, V_ADP_STATESAVE, ENODEV);
+ if (size < sizeof(adp_state_t))
+ return EINVAL;
+ }
+
+ ((adp_state_t *)p)->sig = V_STATE_SIG;
+ buf = ((adp_state_t *)p)->regs;
+ bzero(buf, V_MODE_PARAM_SIZE);
+ crtc_addr = adp->va_crtc_addr;
+
+ s = splhigh();
+
+ outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
+ for (i = 0, j = 5; i < 4; i++) {
+ outb(TSIDX, i + 1);
+ buf[j++] = inb(TSREG);
+ }
+ buf[9] = inb(MISC + 10); /* dot-clock */
+ outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
+
+ for (i = 0, j = 10; i < 25; i++) { /* crtc */
+ outb(crtc_addr, i);
+ buf[j++] = inb(crtc_addr + 1);
+ }
+ for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */
+ inb(crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, i);
+ buf[j++] = inb(ATC + 1);
+ }
+ for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */
+ outb(GDCIDX, i);
+ buf[j++] = inb(GDCREG);
+ }
+ inb(crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x20); /* enable palette */
+
+ splx(s);
+
+#if 1
+ if (vga_get_info(adp, adp->va_mode, &info) == 0) {
+ if (info.vi_flags & V_INFO_GRAPHICS) {
+ buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
+ buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
+ } else {
+ buf[0] = info.vi_width; /* COLS */
+ buf[1] = info.vi_height - 1; /* ROWS */
+ }
+ buf[2] = info.vi_cheight; /* POINTS */
+ } else {
+ /* XXX: shouldn't be happening... */
+ printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
+ adp->va_unit, adp->va_name);
+ }
+#else
+ buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */
+ buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */
+ buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */
+ buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
+ buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
+#endif
+
+ return 0;
+}
+
+/*
+ * load_state():
+ * Set video registers at once.
+ * NOTE: this function only updates the standard EGA/VGA registers.
+ * any extra/extended registers of SVGA adapters are not changed.
+ *
+ * EGA/VGA
+ */
+static int
+vga_load_state(video_adapter_t *adp, void *p)
+{
+ u_char *buf;
+ int crtc_addr;
+ int s;
+ int i;
+
+ prologue(adp, V_ADP_STATELOAD, ENODEV);
+ if (((adp_state_t *)p)->sig != V_STATE_SIG)
+ return EINVAL;
+
+ buf = ((adp_state_t *)p)->regs;
+ crtc_addr = adp->va_crtc_addr;
+
+#if VGA_DEBUG > 1
+ dump_buffer(buf, V_MODE_PARAM_SIZE);
+#endif
+
+ s = splhigh();
+
+ outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
+ for (i = 0; i < 4; ++i) { /* program sequencer */
+ outb(TSIDX, i + 1);
+ outb(TSREG, buf[i + 5]);
+ }
+ outb(MISC, buf[9]); /* set dot-clock */
+ outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
+ outb(crtc_addr, 0x11);
+ outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
+ for (i = 0; i < 25; ++i) { /* program crtc */
+ outb(crtc_addr, i);
+ outb(crtc_addr + 1, buf[i + 10]);
+ }
+ inb(crtc_addr+6); /* reset flip-flop */
+ for (i = 0; i < 20; ++i) { /* program attribute ctrl */
+ outb(ATC, i);
+ outb(ATC, buf[i + 35]);
+ }
+ for (i = 0; i < 9; ++i) { /* program graph data ctrl */
+ outb(GDCIDX, i);
+ outb(GDCREG, buf[i + 55]);
+ }
+ inb(crtc_addr + 6); /* reset flip-flop */
+ outb(ATC, 0x20); /* enable palette */
+
+#if notyet /* a temporary workaround for kernel panic, XXX */
+#ifndef VGA_NO_BIOS
+ if (adp->va_unit == V_ADP_PRIMARY) {
+ writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */
+ writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
+ writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */
+#if 0
+ writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
+ writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
+#endif
+ }
+#endif /* VGA_NO_BIOS */
+#endif /* notyet */
+
+ splx(s);
+ return 0;
+}
+
+/*
+ * set_origin():
+ * Change the origin (window mapping) of the banked frame buffer.
+ */
+static int
+vga_set_origin(video_adapter_t *adp, off_t offset)
+{
+ /*
+ * The standard video modes do not require window mapping;
+ * always return error.
+ */
+ return ENODEV;
+}
+
+/*
+ * read_hw_cursor():
+ * Read the position of the hardware text cursor.
+ *
+ * all adapters
+ */
+static int
+vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+ u_int16_t off;
+ int s;
+
+ if (!vga_init_done)
+ return ENXIO;
+
+ if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
+ return ENODEV;
+
+ s = spltty();
+ outb(adp->va_crtc_addr, 14);
+ off = inb(adp->va_crtc_addr + 1);
+ outb(adp->va_crtc_addr, 15);
+ off = (off << 8) | inb(adp->va_crtc_addr + 1);
+ splx(s);
+
+ *row = off / adp->va_info.vi_width;
+ *col = off % adp->va_info.vi_width;
+
+ return 0;
+}
+
+/*
+ * set_hw_cursor():
+ * Move the hardware text cursor. If col and row are both -1,
+ * the cursor won't be shown.
+ *
+ * all adapters
+ */
+static int
+vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+ u_int16_t off;
+ int s;
+
+ if (!vga_init_done)
+ return ENXIO;
+
+ if ((col == -1) && (row == -1)) {
+ off = -1;
+ } else {
+ if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
+ return ENODEV;
+ off = row*adp->va_info.vi_width + col;
+ }
+
+ s = spltty();
+ outb(adp->va_crtc_addr, 14);
+ outb(adp->va_crtc_addr + 1, off >> 8);
+ outb(adp->va_crtc_addr, 15);
+ outb(adp->va_crtc_addr + 1, off & 0x00ff);
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * set_hw_cursor_shape():
+ * Change the shape of the hardware text cursor. If the height is
+ * zero or negative, the cursor won't be shown.
+ *
+ * all adapters
+ */
+static int
+vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+ int celsize, int blink)
+{
+ int s;
+
+ if (!vga_init_done)
+ return ENXIO;
+
+ s = spltty();
+ switch (adp->va_type) {
+ case KD_VGA:
+ case KD_CGA:
+ case KD_MONO:
+ case KD_HERCULES:
+ default:
+ if (height <= 0) {
+ /* make the cursor invisible */
+ outb(adp->va_crtc_addr, 10);
+ outb(adp->va_crtc_addr + 1, 32);
+ outb(adp->va_crtc_addr, 11);
+ outb(adp->va_crtc_addr + 1, 0);
+ } else {
+ outb(adp->va_crtc_addr, 10);
+ outb(adp->va_crtc_addr + 1, celsize - base - height);
+ outb(adp->va_crtc_addr, 11);
+ outb(adp->va_crtc_addr + 1, celsize - base - 1);
+ }
+ break;
+ case KD_EGA:
+ if (height <= 0) {
+ /* make the cursor invisible */
+ outb(adp->va_crtc_addr, 10);
+ outb(adp->va_crtc_addr + 1, celsize);
+ outb(adp->va_crtc_addr, 11);
+ outb(adp->va_crtc_addr + 1, 0);
+ } else {
+ outb(adp->va_crtc_addr, 10);
+ outb(adp->va_crtc_addr + 1, celsize - base - height);
+ outb(adp->va_crtc_addr, 11);
+ outb(adp->va_crtc_addr + 1, celsize - base);
+ }
+ break;
+ }
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * blank_display()
+ * Put the display in power save/power off mode.
+ *
+ * all adapters
+ */
+static int
+vga_blank_display(video_adapter_t *adp, int mode)
+{
+ u_char val;
+ int s;
+
+ s = splhigh();
+ switch (adp->va_type) {
+ case KD_VGA:
+ switch (mode) {
+ case V_DISPLAY_SUSPEND:
+ case V_DISPLAY_STAND_BY:
+ outb(TSIDX, 0x01);
+ val = inb(TSREG);
+ outb(TSIDX, 0x01);
+ outb(TSREG, val | 0x20);
+ outb(adp->va_crtc_addr, 0x17);
+ val = inb(adp->va_crtc_addr + 1);
+ outb(adp->va_crtc_addr + 1, val & ~0x80);
+ break;
+ case V_DISPLAY_BLANK:
+ outb(TSIDX, 0x01);
+ val = inb(TSREG);
+ outb(TSIDX, 0x01);
+ outb(TSREG, val | 0x20);
+ break;
+ case V_DISPLAY_ON:
+ outb(TSIDX, 0x01);
+ val = inb(TSREG);
+ outb(TSIDX, 0x01);
+ outb(TSREG, val & 0xDF);
+ outb(adp->va_crtc_addr, 0x17);
+ val = inb(adp->va_crtc_addr + 1);
+ outb(adp->va_crtc_addr + 1, val | 0x80);
+ break;
+ }
+ break;
+
+ case KD_EGA:
+ /* no support yet */
+ return ENODEV;
+
+ case KD_CGA:
+ switch (mode) {
+ case V_DISPLAY_SUSPEND:
+ case V_DISPLAY_STAND_BY:
+ case V_DISPLAY_BLANK:
+ outb(adp->va_crtc_addr + 4, 0x25);
+ break;
+ case V_DISPLAY_ON:
+ outb(adp->va_crtc_addr + 4, 0x2d);
+ break;
+ }
+ break;
+
+ case KD_MONO:
+ case KD_HERCULES:
+ switch (mode) {
+ case V_DISPLAY_SUSPEND:
+ case V_DISPLAY_STAND_BY:
+ case V_DISPLAY_BLANK:
+ outb(adp->va_crtc_addr + 4, 0x21);
+ break;
+ case V_DISPLAY_ON:
+ outb(adp->va_crtc_addr + 4, 0x29);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * mmap():
+ * Mmap frame buffer.
+ *
+ * all adapters
+ */
+static int
+vga_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot)
+{
+ if (adp->va_info.vi_flags & V_INFO_LINEAR)
+ return -1;
+
+#if VGA_DEBUG > 0
+ printf("vga_mmap_buf(): window:0x%x, offset:0x%x\n",
+ adp->va_info.vi_window, offset);
+#endif
+
+ /* XXX: is this correct? */
+ if (offset > adp->va_window_size - PAGE_SIZE)
+ return -1;
+
+#ifdef __i386__
+ return i386_btop(adp->va_info.vi_window + offset);
+#endif
+#ifdef __alpha__
+ return alpha_btop(adp->va_info.vi_window + offset);
+#endif
+}
+
+#ifndef VGA_NO_MODE_CHANGE
+
+static void
+planar_fill(video_adapter_t *adp, int val)
+{
+ int length;
+ int at; /* position in the frame buffer */
+ int l;
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
+ at = 0;
+ length = adp->va_line_width*adp->va_info.vi_height;
+ while (length > 0) {
+ l = imin(length, adp->va_window_size);
+ (*vidsw[adp->va_index]->set_win_org)(adp, at);
+ bzero_io(adp->va_window, l);
+ length -= l;
+ at += l;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+packed_fill(video_adapter_t *adp, int val)
+{
+ int length;
+ int at; /* position in the frame buffer */
+ int l;
+
+ at = 0;
+ length = adp->va_line_width*adp->va_info.vi_height;
+ while (length > 0) {
+ l = imin(length, adp->va_window_size);
+ (*vidsw[adp->va_index]->set_win_org)(adp, at);
+ fill_io(val, adp->va_window, l);
+ length -= l;
+ at += l;
+ }
+}
+
+static void
+direct_fill(video_adapter_t *adp, int val)
+{
+ int length;
+ int at; /* position in the frame buffer */
+ int l;
+
+ at = 0;
+ length = adp->va_line_width*adp->va_info.vi_height;
+ while (length > 0) {
+ l = imin(length, adp->va_window_size);
+ (*vidsw[adp->va_index]->set_win_org)(adp, at);
+ switch (adp->va_info.vi_pixel_size) {
+ case sizeof(u_int16_t):
+ fillw_io(val, adp->va_window, l/sizeof(u_int16_t));
+ break;
+ case 3:
+ /* FIXME */
+ break;
+ case sizeof(u_int32_t):
+ filll_io(val, adp->va_window, l/sizeof(u_int32_t));
+ break;
+ }
+ length -= l;
+ at += l;
+ }
+}
+
+static int
+vga_clear(video_adapter_t *adp)
+{
+ switch (adp->va_info.vi_mem_model) {
+ case V_INFO_MM_TEXT:
+ /* do nothing? XXX */
+ break;
+ case V_INFO_MM_PLANAR:
+ planar_fill(adp, 0);
+ break;
+ case V_INFO_MM_PACKED:
+ packed_fill(adp, 0);
+ break;
+ case V_INFO_MM_DIRECT:
+ direct_fill(adp, 0);
+ break;
+ }
+ return 0;
+}
+
+#ifdef notyet
+static void
+planar_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ int banksize;
+ int bank;
+ int pos;
+ int offset; /* offset within window */
+ int bx;
+ int l;
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
+
+ banksize = adp->va_window_size;
+ bank = -1;
+ while (cy > 0) {
+ pos = adp->va_line_width*y + x/8;
+ if (bank != pos/banksize) {
+ (*vidsw[adp->va_index]->set_win_org)(adp, pos);
+ bank = pos/banksize;
+ }
+ offset = pos%banksize;
+ bx = (x + cx)/8 - x/8;
+ if (x % 8) {
+ outw(GDCIDX, ((0xff00 >> (x % 8)) & 0xff00) | 0x08);
+ writeb(adp->va_window + offset, 0);
+ ++offset;
+ --bx;
+ if (offset >= banksize) {
+ offset = 0;
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ }
+ outw(GDCIDX, 0xff08); /* bit mask */
+ }
+ while (bx > 0) {
+ l = imin(bx, banksize);
+ bzero_io(adp->va_window + offset, l);
+ offset += l;
+ bx -= l;
+ if (offset >= banksize) {
+ offset = 0;
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ }
+ }
+ if ((x + cx) % 8) {
+ outw(GDCIDX, (~(0xff00 >> ((x + cx) % 8)) & 0xff00) | 0x08);
+ writeb(adp->va_window + offset, 0);
+ ++offset;
+ if (offset >= banksize) {
+ offset = 0;
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ }
+ outw(GDCIDX, 0xff08); /* bit mask */
+ }
+ ++y;
+ --cy;
+ }
+
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+packed_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ int banksize;
+ int bank;
+ int pos;
+ int offset; /* offset within window */
+ int end;
+
+ banksize = adp->va_window_size;
+ bank = -1;
+ cx *= adp->va_info.vi_pixel_size;
+ while (cy > 0) {
+ pos = adp->va_line_width*y + x*adp->va_info.vi_pixel_size;
+ if (bank != pos/banksize) {
+ (*vidsw[adp->va_index]->set_win_org)(adp, pos);
+ bank = pos/banksize;
+ }
+ offset = pos%banksize;
+ end = imin(offset + cx, banksize);
+ fill_io(val, adp->va_window + offset,
+ (end - offset)/adp->va_info.vi_pixel_size);
+ /* the line may cross the window boundary */
+ if (offset + cx > banksize) {
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ end = offset + cx - banksize;
+ fill_io(val, adp->va_window, end/adp->va_info.vi_pixel_size);
+ }
+ ++y;
+ --cy;
+ }
+}
+
+static void
+direct_fill_rect16(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ int banksize;
+ int bank;
+ int pos;
+ int offset; /* offset within window */
+ int end;
+
+ /*
+ * XXX: the function assumes that banksize is a muliple of
+ * sizeof(u_int16_t).
+ */
+ banksize = adp->va_window_size;
+ bank = -1;
+ cx *= sizeof(u_int16_t);
+ while (cy > 0) {
+ pos = adp->va_line_width*y + x*sizeof(u_int16_t);
+ if (bank != pos/banksize) {
+ (*vidsw[adp->va_index]->set_win_org)(adp, pos);
+ bank = pos/banksize;
+ }
+ offset = pos%banksize;
+ end = imin(offset + cx, banksize);
+ fillw_io(val, adp->va_window + offset,
+ (end - offset)/sizeof(u_int16_t));
+ /* the line may cross the window boundary */
+ if (offset + cx > banksize) {
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ end = offset + cx - banksize;
+ fillw_io(val, adp->va_window, end/sizeof(u_int16_t));
+ }
+ ++y;
+ --cy;
+ }
+}
+
+static void
+direct_fill_rect24(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ int banksize;
+ int bank;
+ int pos;
+ int offset; /* offset within window */
+ int end;
+ int i;
+ int j;
+ u_int8_t b[3];
+
+ b[0] = val & 0x0000ff;
+ b[1] = (val >> 8) & 0x0000ff;
+ b[2] = (val >> 16) & 0x0000ff;
+ banksize = adp->va_window_size;
+ bank = -1;
+ cx *= 3;
+ while (cy > 0) {
+ pos = adp->va_line_width*y + x*3;
+ if (bank != pos/banksize) {
+ (*vidsw[adp->va_index]->set_win_org)(adp, pos);
+ bank = pos/banksize;
+ }
+ offset = pos%banksize;
+ end = imin(offset + cx, banksize);
+ for (i = 0, j = offset; j < end; i = (++i)%3, ++j) {
+ writeb(adp->va_window + j, b[i]);
+ }
+ /* the line may cross the window boundary */
+ if (offset + cx >= banksize) {
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ j = 0;
+ end = offset + cx - banksize;
+ for (; j < end; i = (++i)%3, ++j) {
+ writeb(adp->va_window + j, b[i]);
+ }
+ }
+ ++y;
+ --cy;
+ }
+}
+
+static void
+direct_fill_rect32(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ int banksize;
+ int bank;
+ int pos;
+ int offset; /* offset within window */
+ int end;
+
+ /*
+ * XXX: the function assumes that banksize is a muliple of
+ * sizeof(u_int32_t).
+ */
+ banksize = adp->va_window_size;
+ bank = -1;
+ cx *= sizeof(u_int32_t);
+ while (cy > 0) {
+ pos = adp->va_line_width*y + x*sizeof(u_int32_t);
+ if (bank != pos/banksize) {
+ (*vidsw[adp->va_index]->set_win_org)(adp, pos);
+ bank = pos/banksize;
+ }
+ offset = pos%banksize;
+ end = imin(offset + cx, banksize);
+ filll_io(val, adp->va_window + offset,
+ (end - offset)/sizeof(u_int32_t));
+ /* the line may cross the window boundary */
+ if (offset + cx > banksize) {
+ ++bank; /* next bank */
+ (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
+ end = offset + cx - banksize;
+ filll_io(val, adp->va_window, end/sizeof(u_int32_t));
+ }
+ ++y;
+ --cy;
+ }
+}
+
+static int
+vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ switch (adp->va_info.vi_mem_model) {
+ case V_INFO_MM_TEXT:
+ /* do nothing? XXX */
+ break;
+ case V_INFO_MM_PLANAR:
+ planar_fill_rect(adp, val, x, y, cx, cy);
+ break;
+ case V_INFO_MM_PACKED:
+ packed_fill_rect(adp, val, x, y, cx, cy);
+ break;
+ case V_INFO_MM_DIRECT:
+ switch (adp->va_info.vi_pixel_size) {
+ case sizeof(u_int16_t):
+ direct_fill_rect16(adp, val, x, y, cx, cy);
+ break;
+ case 3:
+ direct_fill_rect24(adp, val, x, y, cx, cy);
+ break;
+ case sizeof(u_int32_t):
+ direct_fill_rect32(adp, val, x, y, cx, cy);
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+#else /* !notyet */
+static int
+vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ return ENODEV;
+}
+#endif /* notyet */
+
+static int
+vga_bitblt(video_adapter_t *adp,...)
+{
+ /* FIXME */
+ return ENODEV;
+}
+
+#endif /* !VGA_NO_MODE_CHANGE */
+
+static int
+get_palette(video_adapter_t *adp, int base, int count,
+ u_char *red, u_char *green, u_char *blue, u_char *trans)
+{
+ u_char *r;
+ u_char *g;
+ u_char *b;
+
+ if ((base < 0) || (base >= 256) || (base + count > 256))
+ return EINVAL;
+
+ r = malloc(count*3, M_DEVBUF, M_WAITOK);
+ g = r + count;
+ b = g + count;
+ if (vga_save_palette2(adp, base, count, r, g, b))
+ return ENODEV;
+ copyout(r, red, count);
+ copyout(g, green, count);
+ copyout(b, blue, count);
+ if (trans != NULL) {
+ bzero(r, count);
+ copyout(r, trans, count);
+ }
+ free(r, M_DEVBUF);
+
+ return 0;
+}
+
+static int
+set_palette(video_adapter_t *adp, int base, int count,
+ u_char *red, u_char *green, u_char *blue, u_char *trans)
+{
+ u_char *r;
+ u_char *g;
+ u_char *b;
+ int err;
+
+ if ((base < 0) || (base >= 256) || (base + count > 256))
+ return EINVAL;
+
+ r = malloc(count*3, M_DEVBUF, M_WAITOK);
+ g = r + count;
+ b = g + count;
+ copyin(red, r, count);
+ copyin(green, g, count);
+ copyin(blue, b, count);
+ err = vga_load_palette2(adp, base, count, r, g, b);
+ free(r, M_DEVBUF);
+
+ return (err ? ENODEV : 0);
+}
+
+static int
+vga_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
+{
+ switch (cmd) {
+ case FBIO_GETWINORG: /* get frame buffer window origin */
+ *(u_int *)arg = 0;
+ return 0;
+
+ case FBIO_SETWINORG: /* set frame buffer window origin */
+ return ENODEV;
+
+ case FBIO_SETDISPSTART: /* set display start address */
+ return (set_display_start(adp,
+ ((video_display_start_t *)arg)->x,
+ ((video_display_start_t *)arg)->y)
+ ? ENODEV : 0);
+
+ case FBIO_SETLINEWIDTH: /* set scan line length in pixel */
+ return (set_line_length(adp, *(u_int *)arg) ? ENODEV : 0);
+
+ case FBIO_GETPALETTE: /* get color palette */
+ return get_palette(adp, ((video_color_palette_t *)arg)->index,
+ ((video_color_palette_t *)arg)->count,
+ ((video_color_palette_t *)arg)->red,
+ ((video_color_palette_t *)arg)->green,
+ ((video_color_palette_t *)arg)->blue,
+ ((video_color_palette_t *)arg)->transparent);
+
+ case FBIO_SETPALETTE: /* set color palette */
+ return set_palette(adp, ((video_color_palette_t *)arg)->index,
+ ((video_color_palette_t *)arg)->count,
+ ((video_color_palette_t *)arg)->red,
+ ((video_color_palette_t *)arg)->green,
+ ((video_color_palette_t *)arg)->blue,
+ ((video_color_palette_t *)arg)->transparent);
+
+ case FBIOGTYPE: /* get frame buffer type info. */
+ ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type);
+ ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height;
+ ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width;
+ ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth;
+ if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8))
+ ((struct fbtype *)arg)->fb_cmsize = 0;
+ else
+ ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth;
+ ((struct fbtype *)arg)->fb_size = adp->va_buffer_size;
+ return 0;
+
+ case FBIOGETCMAP: /* get color palette */
+ return get_palette(adp, ((struct fbcmap *)arg)->index,
+ ((struct fbcmap *)arg)->count,
+ ((struct fbcmap *)arg)->red,
+ ((struct fbcmap *)arg)->green,
+ ((struct fbcmap *)arg)->blue, NULL);
+
+ case FBIOPUTCMAP: /* set color palette */
+ return set_palette(adp, ((struct fbcmap *)arg)->index,
+ ((struct fbcmap *)arg)->count,
+ ((struct fbcmap *)arg)->red,
+ ((struct fbcmap *)arg)->green,
+ ((struct fbcmap *)arg)->blue, NULL);
+
+ default:
+ return fb_commonioctl(adp, cmd, arg);
+ }
+}
+
+static void
+dump_buffer(u_char *buf, size_t len)
+{
+ int i;
+
+ for(i = 0; i < len;) {
+ printf("%02x ", buf[i]);
+ if ((++i % 16) == 0)
+ printf("\n");
+ }
+}
+
+/*
+ * diag():
+ * Print some information about the video adapter and video modes,
+ * with requested level of details.
+ *
+ * all adapters
+ */
+static int
+vga_diag(video_adapter_t *adp, int level)
+{
+ u_char *mp;
+#if FB_DEBUG > 1
+ video_info_t info;
+ int i;
+#endif
+
+ if (!vga_init_done)
+ return ENXIO;
+
+#if FB_DEBUG > 1
+#ifndef VGA_NO_BIOS
+ printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n",
+ rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488)));
+ printf("vga: CRTC:0x%x, video option:0x%02x, ",
+ readw(BIOS_PADDRTOVADDR(0x463)),
+ readb(BIOS_PADDRTOVADDR(0x487)));
+ printf("rows:%d, cols:%d, font height:%d\n",
+ readb(BIOS_PADDRTOVADDR(0x44a)),
+ readb(BIOS_PADDRTOVADDR(0x484)) + 1,
+ readb(BIOS_PADDRTOVADDR(0x485)));
+#endif /* VGA_NO_BIOS */
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ printf("vga: param table EGA/VGA:%p", video_mode_ptr);
+ printf(", CGA/MDA:%p\n", video_mode_ptr2);
+ printf("vga: rows_offset:%d\n", rows_offset);
+#endif
+#endif /* FB_DEBUG > 1 */
+
+ fb_dump_adp_info(VGA_DRIVER_NAME, adp, level);
+
+#if FB_DEBUG > 1
+ if (adp->va_flags & V_ADP_MODECHANGE) {
+ for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+ if (bios_vmode[i].vi_mode == NA)
+ continue;
+ if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
+ continue;
+ fb_dump_mode_info(VGA_DRIVER_NAME, adp, &bios_vmode[i], level);
+ }
+ } else {
+ vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */
+ fb_dump_mode_info(VGA_DRIVER_NAME, adp, &info, level);
+ }
+#endif /* FB_DEBUG > 1 */
+
+ if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA))
+ return 0;
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ if (video_mode_ptr == NULL)
+ printf("vga%d: %s: WARNING: video mode switching is not "
+ "fully supported on this adapter\n",
+ adp->va_unit, adp->va_name);
+#endif
+ if (level <= 0)
+ return 0;
+
+ if (adp->va_type == KD_VGA) {
+ printf("VGA parameters upon power-up\n");
+ dump_buffer(adpstate.regs, sizeof(adpstate.regs));
+ printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
+ dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
+ }
+
+ mp = get_mode_param(adp->va_initial_mode);
+ if (mp == NULL) /* this shouldn't be happening */
+ return 0;
+ printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode);
+ dump_buffer(mp, V_MODE_PARAM_SIZE);
+
+ return 0;
+}
+
+#endif /* NVGA > 0 */
diff --git a/sys/dev/fb/vgareg.h b/sys/dev/fb/vgareg.h
index 841408e..e9e9eb2 100644
--- a/sys/dev/fb/vgareg.h
+++ b/sys/dev/fb/vgareg.h
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id:$
+ * $Id: vgareg.h,v 1.1 1999/01/09 02:44:49 yokota Exp $
*/
#ifndef _DEV_FB_VGAREG_H_
@@ -60,8 +60,38 @@
#define GDCIDX (IO_VGA + 0x0E) /* graph data controller idx */
#define GDCREG (IO_VGA + 0x0F) /* graph data controller data */
+#define VGA_DRIVER_NAME "vga"
+#define VGA_UNIT(dev) minor(dev)
+#define VGA_MKMINOR(unit) (unit)
+
#ifdef KERNEL
-extern int (*vga_sub_configure)(int flags);
+
+struct video_adapter;
+typedef struct vga_softc {
+ struct video_adapter *adp;
+#ifdef FB_INSTALL_CDEV
+ genfb_softc_t gensc;
#endif
+} vga_softc_t;
+
+int vga_probe_unit(int unit, struct video_adapter *adp, int flags);
+int vga_attach_unit(int unit, vga_softc_t *sc, int flags);
+
+#ifdef FB_INSTALL_CDEV
+int vga_open(dev_t dev, vga_softc_t *sc, int flag, int mode,
+ struct proc *p);
+int vga_close(dev_t dev, vga_softc_t *sc, int flag, int mode,
+ struct proc *p);
+int vga_read(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag);
+int vga_write(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag);
+int vga_ioctl(dev_t dev, vga_softc_t *sc, u_long cmd, caddr_t arg,
+ int flag, struct proc *p);
+int vga_mmap(dev_t dev, vga_softc_t *sc, vm_offset_t offset,
+ int prot);
+#endif
+
+extern int (*vga_sub_configure)(int flags);
+
+#endif /* KERNEL */
#endif /* _DEV_FB_VGAREG_H_ */
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index c3be310..6c17bc1 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: sio.c,v 1.248 1999/06/19 08:14:56 grog Exp $
+ * $Id: sio.c,v 1.249 1999/06/20 13:10:09 peter Exp $
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
* from: i386/isa sio.c,v 1.234
*/
@@ -2656,7 +2656,7 @@ static cn_checkc_t siocncheckc;
static cn_getc_t siocngetc;
static cn_putc_t siocnputc;
-CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc);
+CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc);
/* To get the GDB related variables */
#if DDB > 0
@@ -2855,7 +2855,6 @@ siocnprobe(cp)
cp->cn_pri = COM_FORCECONSOLE(flags)
|| boothowto & RB_SERIAL
? CN_REMOTE : CN_NORMAL;
- printf("sio%d: system console\n", unit);
siocniobase = iobase;
siocnunit = unit;
}
@@ -2897,10 +2896,7 @@ siocnprobe(cp)
#ifdef __alpha__
-struct consdev siocons = {
- NULL, NULL, siocngetc, siocncheckc, siocnputc,
- NULL, 0, CN_NORMAL,
-};
+CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc);
extern struct consdev *cn_tab;
@@ -2915,6 +2911,8 @@ siocnattach(port, speed)
siocniobase = port;
comdefaultrate = speed;
+ sio_consdev.cn_pri = CN_NORMAL;
+ sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0);
s = spltty();
@@ -2938,8 +2936,7 @@ siocnattach(port, speed)
siocnopen(&sp, siocniobase, comdefaultrate);
splx(s);
- siocons.cn_dev = makedev(CDEV_MAJOR, 0);
- cn_tab = &siocons;
+ cn_tab = &sio_consdev;
return 0;
}
diff --git a/sys/dev/syscons/blank/blank_saver.c b/sys/dev/syscons/blank/blank_saver.c
index 89dd199..2979c0d 100644
--- a/sys/dev/syscons/blank/blank_saver.c
+++ b/sys/dev/syscons/blank/blank_saver.c
@@ -25,82 +25,35 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: blank_saver.c,v 1.14 1998/11/04 03:49:38 peter Exp $
+ * $Id: blank_saver.c,v 1.15 1999/01/11 03:18:44 yokota Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <dev/fb/vgareg.h>
-
-#include <i386/isa/isa.h>
-
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static int
blank_saver(video_adapter_t *adp, int blank)
{
- u_char val;
- if (blank) {
- switch (adp->va_type) {
- case KD_VGA:
- outb(TSIDX, 0x01); val = inb(TSREG);
- outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(adp->va_crtc_addr + 4, 0x25);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(adp->va_crtc_addr + 4, 0x21);
- break;
- default:
- break;
- }
- }
- else {
- switch (adp->va_type) {
- case KD_VGA:
- outb(TSIDX, 0x01); val = inb(TSREG);
- outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(adp->va_crtc_addr + 4, 0x2d);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(adp->va_crtc_addr + 4, 0x29);
- break;
- default:
- break;
- }
- }
+ (*vidsw[adp->va_index]->blank_display)(adp,
+ (blank) ? V_DISPLAY_BLANK
+ : V_DISPLAY_ON);
return 0;
}
static int
blank_init(video_adapter_t *adp)
{
- switch (adp->va_type) {
- case KD_MONO:
- case KD_HERCULES:
- case KD_CGA:
- case KD_VGA:
- break;
- case KD_EGA:
- /* EGA is yet to be supported */
- default:
- return ENODEV;
- }
- return 0;
+ if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0)
+ return 0;
+ return ENODEV;
}
static int
diff --git a/sys/dev/syscons/daemon/daemon_saver.c b/sys/dev/syscons/daemon/daemon_saver.c
index 423e6c7..ebedfaa 100644
--- a/sys/dev/syscons/daemon/daemon_saver.c
+++ b/sys/dev/syscons/daemon/daemon_saver.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: daemon_saver.c,v 1.14 1999/01/17 14:25:08 yokota Exp $
+ * $Id: daemon_saver.c,v 1.15 1999/02/05 12:40:15 des Exp $
*/
#include <sys/param.h>
@@ -34,21 +34,20 @@
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <machine/md_var.h>
#include <machine/pc/display.h>
-#include <saver.h>
-
-#define CONSOLE_VECT(x, y) \
- (window + (y)*cur_console->xsize + (x))
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
#define DAEMON_MAX_WIDTH 32
#define DAEMON_MAX_HEIGHT 19
static char *message;
static int messagelen;
-static u_short *window;
static int blanked;
/* Who is the author of this ASCII pic? */
@@ -119,20 +118,23 @@ xflip_symbol(char symbol)
}
static void
-clear_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff,
+clear_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
int xlen, int ylen)
{
int y;
if (xlen <= 0)
return;
- for (y = yoff; y < ylen; y++)
- fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
- CONSOLE_VECT(xpos + xoff, ypos + y), xlen - xoff);
+ for (y = yoff; y < ylen; y++) {
+ sc_vtb_erase(&sc->cur_scp->scr,
+ (ypos + y)*sc->cur_scp->xsize + xpos + xoff,
+ xlen - xoff,
+ sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
+ }
}
static void
-draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff,
+draw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
int xlen, int ylen)
{
int x, y;
@@ -148,41 +150,60 @@ draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff,
continue;
for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) {
switch (daemon_attr[y][px]) {
+#ifndef PC98
case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break;
case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break;
case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break;
case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break;
default: attr = (FG_WHITE|BG_BLACK)<<8; break;
+#else /* PC98 */
+ case 'R': attr = (FG_RED|BG_BLACK)<<8; break;
+ case 'Y': attr = (FG_BROWN|BG_BLACK)<<8; break;
+ case 'B': attr = (FG_BLUE|BG_BLACK)<<8; break;
+ case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
+ case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break;
+ default: attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
+#endif /* PC98 */
}
if (dxdir < 0) { /* Moving left */
- *CONSOLE_VECT(xpos + x, ypos + y) =
- scr_map[daemon_pic[y][px]]|attr;
+ sc_vtb_putc(&sc->cur_scp->scr,
+ (ypos + y)*sc->cur_scp->xsize
+ + xpos + x,
+ sc->scr_map[daemon_pic[y][px]],
+ attr);
} else { /* Moving right */
- *CONSOLE_VECT(xpos + DAEMON_MAX_WIDTH - px - 1, ypos + y) =
- scr_map[xflip_symbol(daemon_pic[y][px])]|attr;
+ sc_vtb_putc(&sc->cur_scp->scr,
+ (ypos + y)*sc->cur_scp->xsize
+ + xpos + DAEMON_MAX_WIDTH
+ - px - 1,
+ sc->scr_map[xflip_symbol(daemon_pic[y][px])],
+ attr);
}
}
}
}
static void
-clear_string(int xpos, int ypos, int xoff, char *s, int len)
+clear_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
{
if (len <= 0)
return;
- fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
- CONSOLE_VECT(xpos + xoff, ypos), len - xoff);
+ sc_vtb_erase(&sc->cur_scp->scr,
+ ypos*sc->cur_scp->xsize + xpos + xoff, len - xoff,
+ sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
}
static void
-draw_string(int xpos, int ypos, int xoff, char *s, int len)
+draw_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
{
int x;
- for (x = xoff; x < len; x++)
- *CONSOLE_VECT(xpos + x, ypos) =
- scr_map[s[x]]|(FG_LIGHTGREEN|BG_BLACK)<<8;
+ for (x = xoff; x < len; x++) {
+ sc_vtb_putc(&sc->cur_scp->scr,
+ ypos*sc->cur_scp->xsize + xpos + x,
+ sc->scr_map[s[x]], (FG_LIGHTGREEN | BG_BLACK) << 8);
+ }
}
static int
@@ -195,17 +216,30 @@ daemon_saver(video_adapter_t *adp, int blank)
static int moved_daemon = 0;
static int xoff, yoff, toff;
static int xlen, ylen, tlen;
- scr_stat *scp = cur_console;
+ sc_softc_t *sc;
+ scr_stat *scp;
int min, max;
+ sc = sc_find_softc(adp, NULL);
+ if (sc == NULL)
+ return EAGAIN;
+ scp = sc->cur_scp;
+
if (blank) {
if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
return EAGAIN;
if (blanked == 0) {
- window = (u_short *)adp->va_window;
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) & ~0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
/* clear the screen and set the border color */
- fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
- window, scp->xsize * scp->ysize);
+ sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
set_border(scp, 0);
xlen = ylen = tlen = 0;
}
@@ -213,8 +247,8 @@ daemon_saver(video_adapter_t *adp, int blank)
return 0;
blanked = 1;
- clear_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
- clear_string(txpos, typos, toff, (char *)message, tlen);
+ clear_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
+ clear_string(sc, txpos, typos, toff, (char *)message, tlen);
if (++moved_daemon) {
/*
@@ -319,9 +353,16 @@ daemon_saver(video_adapter_t *adp, int blank)
else if (txpos + tlen > scp->xsize)
tlen = scp->xsize - txpos;
- draw_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
- draw_string(txpos, typos, toff, (char *)message, tlen);
+ draw_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
+ draw_string(sc, txpos, typos, toff, (char *)message, tlen);
} else {
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) | 0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
blanked = 0;
}
return 0;
diff --git a/sys/dev/syscons/fade/fade_saver.c b/sys/dev/syscons/fade/fade_saver.c
index 70d36c9..4a44c85 100644
--- a/sys/dev/syscons/fade/fade_saver.c
+++ b/sys/dev/syscons/fade/fade_saver.c
@@ -25,17 +25,19 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: fade_saver.c,v 1.15 1998/11/04 03:49:38 peter Exp $
+ * $Id: fade_saver.c,v 1.16 1999/01/11 03:18:46 yokota Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <i386/isa/isa.h>
-
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static u_char palette[256*3];
static int blanked;
@@ -49,11 +51,10 @@ fade_saver(video_adapter_t *adp, int blank)
if (blank) {
blanked = TRUE;
- switch (adp->va_type) {
- case KD_VGA:
+ if (ISPALAVAIL(adp->va_flags)) {
if (count <= 0)
save_palette(adp, palette);
- if (count < 64) {
+ if (count < 256) {
pal[0] = pal[1] = pal[2] = 0;
for (i = 3; i < 256*3; i++) {
if (palette[i] - count > 60)
@@ -64,39 +65,17 @@ fade_saver(video_adapter_t *adp, int blank)
load_palette(adp, pal);
count++;
}
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(adp->va_crtc_addr + 4, 0x25);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(adp->va_crtc_addr + 4, 0x21);
- break;
- default:
- break;
+ } else {
+ (*vidsw[adp->va_index]->blank_display)(adp,
+ V_DISPLAY_BLANK);
}
- }
- else {
- switch (adp->va_type) {
- case KD_VGA:
+ } else {
+ if (ISPALAVAIL(adp->va_flags)) {
load_palette(adp, palette);
count = 0;
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(adp->va_crtc_addr + 4, 0x2d);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(adp->va_crtc_addr + 4, 0x29);
- break;
- default:
- break;
+ } else {
+ (*vidsw[adp->va_index]->blank_display)(adp,
+ V_DISPLAY_ON);
}
blanked = FALSE;
}
@@ -106,21 +85,9 @@ fade_saver(video_adapter_t *adp, int blank)
static int
fade_init(video_adapter_t *adp)
{
- switch (adp->va_type) {
- case KD_MONO:
- case KD_HERCULES:
- case KD_CGA:
- /*
- * `fade' saver is not fully implemented for MDA and CGA.
- * It simply blanks the display instead.
- */
- case KD_VGA:
- break;
- case KD_EGA:
- /* EGA is yet to be supported */
- default:
+ if (!ISPALAVAIL(adp->va_flags)
+ && (*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) != 0)
return ENODEV;
- }
blanked = FALSE;
return 0;
}
diff --git a/sys/dev/syscons/fire/fire_saver.c b/sys/dev/syscons/fire/fire_saver.c
index aea36a9..db4b80b 100644
--- a/sys/dev/syscons/fire/fire_saver.c
+++ b/sys/dev/syscons/fire/fire_saver.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: fire_saver.c,v 1.2.2.1 1999/05/10 15:20:30 des Exp $
+ * $Id: fire_saver.c,v 1.4 1999/05/10 15:25:50 des Exp $
*/
/*
@@ -38,11 +38,14 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/syslog.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <machine/md_var.h>
#include <machine/random.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
#define X_SIZE 320
#define Y_SIZE 200
diff --git a/sys/dev/syscons/green/green_saver.c b/sys/dev/syscons/green/green_saver.c
index 9decd72..103154b 100644
--- a/sys/dev/syscons/green/green_saver.c
+++ b/sys/dev/syscons/green/green_saver.c
@@ -25,93 +25,35 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: green_saver.c,v 1.14 1998/11/04 03:49:38 peter Exp $
+ * $Id: green_saver.c,v 1.15 1999/01/11 03:18:48 yokota Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <dev/fb/vgareg.h>
-
-#include <i386/isa/isa.h>
-
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static int
green_saver(video_adapter_t *adp, int blank)
{
- int crtc_addr;
- u_char val;
-
- crtc_addr = adp->va_crtc_addr;
- if (blank) {
- switch (adp->va_type) {
- case KD_VGA:
- outb(TSIDX, 0x01); val = inb(TSREG);
- outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
- outb(crtc_addr, 0x17); val = inb(crtc_addr + 1);
- outb(crtc_addr + 1, val & ~0x80);
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(crtc_addr + 4, 0x25);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(crtc_addr + 4, 0x21);
- break;
- default:
- break;
- }
- }
- else {
- switch (adp->va_type) {
- case KD_VGA:
- outb(TSIDX, 0x01); val = inb(TSREG);
- outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
- outb(crtc_addr, 0x17); val = inb(crtc_addr + 1);
- outb(crtc_addr + 1, val | 0x80);
- break;
- case KD_EGA:
- /* not yet done XXX */
- break;
- case KD_CGA:
- outb(crtc_addr + 4, 0x2d);
- break;
- case KD_MONO:
- case KD_HERCULES:
- outb(crtc_addr + 4, 0x29);
- break;
- default:
- break;
- }
- }
+ (*vidsw[adp->va_index]->blank_display)(adp,
+ (blank) ? V_DISPLAY_STAND_BY
+ : V_DISPLAY_ON);
return 0;
}
static int
green_init(video_adapter_t *adp)
{
- switch (adp->va_type) {
- case KD_MONO:
- case KD_HERCULES:
- case KD_CGA:
- /*
- * `green' saver is not fully implemented for MDA and CGA.
- * It simply blanks the display instead.
- */
- case KD_VGA:
- break;
- case KD_EGA:
- /* EGA is yet to be supported */
- default:
- return ENODEV;
- }
- return 0;
+ if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0)
+ return 0;
+ return ENODEV;
}
static int
diff --git a/sys/dev/syscons/logo/logo_saver.c b/sys/dev/syscons/logo/logo_saver.c
index b6a46ac..24da964 100644
--- a/sys/dev/syscons/logo/logo_saver.c
+++ b/sys/dev/syscons/logo/logo_saver.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: logo_saver.c,v 1.5 1999/02/05 12:40:15 des Exp $
+ * $Id: logo_saver.c,v 1.6 1999/04/12 13:34:57 des Exp $
*/
#include <sys/param.h>
@@ -33,8 +33,12 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/syslog.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static u_char *vid;
static int banksize, scrmode, bpsl, scrw, scrh;
@@ -104,6 +108,7 @@ logo_saver(video_adapter_t *adp, int blank)
#endif
blanked++;
vid = (u_char *)adp->va_window;
+ banksize = adp->va_window_size;
bpsl = adp->va_line_width;
splx(pl);
for (i = 0; i < bpsl*scrh; i += banksize) {
@@ -132,7 +137,6 @@ logo_init(video_adapter_t *adp)
return ENODEV;
}
- banksize = info.vi_window_size;
scrw = info.vi_width;
scrh = info.vi_height;
blanked = 0;
diff --git a/sys/dev/syscons/rain/rain_saver.c b/sys/dev/syscons/rain/rain_saver.c
index 9aa7370..200dc59 100644
--- a/sys/dev/syscons/rain/rain_saver.c
+++ b/sys/dev/syscons/rain/rain_saver.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rain_saver.c,v 1.2 1999/01/11 03:18:50 yokota Exp $
+ * $Id: rain_saver.c,v 1.3 1999/04/12 13:34:57 des Exp $
*/
#include <sys/param.h>
@@ -33,10 +33,14 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/syslog.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
#include <machine/random.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static u_char *vid;
diff --git a/sys/dev/syscons/scgfbrndr.c b/sys/dev/syscons/scgfbrndr.c
new file mode 100644
index 0000000..16c40e2
--- /dev/null
+++ b/sys/dev/syscons/scgfbrndr.c
@@ -0,0 +1,829 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id:$
+ */
+
+#include "sc.h"
+#include "vga.h"
+#include "opt_syscons.h"
+#include "opt_vga.h"
+
+#if NSC > 0 && NVGA > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <machine/console.h>
+#include <machine/md_var.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/vgareg.h>
+#include <dev/syscons/syscons.h>
+
+#include <isa/isareg.h>
+
+#ifndef SC_MOUSE_CHAR
+#define SC_MOUSE_CHAR (0xd0)
+#endif
+
+#ifndef SC_RENDER_DEBUG
+#define SC_RENDER_DEBUG 0
+#endif
+
+static vr_clear_t vga_txtclear;
+static vr_draw_border_t vga_txtborder;
+static vr_draw_t vga_txtdraw;
+static vr_set_cursor_t vga_txtcursor_shape;
+static vr_draw_cursor_t vga_txtcursor;
+static vr_blink_cursor_t vga_txtblink;
+#ifndef SC_NO_CUTPASTE
+static vr_draw_mouse_t vga_txtmouse;
+#else
+#define vga_txtmouse (vr_draw_mouse_t *)vga_nop
+#endif
+
+#ifdef SC_PIXEL_MODE
+static vr_clear_t vga_pxlclear;
+static vr_draw_border_t vga_pxlborder;
+static vr_draw_t vga_egadraw;
+static vr_draw_t vga_vgadraw;
+static vr_set_cursor_t vga_pxlcursor_shape;
+static vr_draw_cursor_t vga_pxlcursor;
+static vr_blink_cursor_t vga_pxlblink;
+#ifndef SC_NO_CUTPASTE
+static vr_draw_mouse_t vga_pxlmouse;
+#else
+#define vga_pxlmouse (vr_draw_mouse_t *)vga_nop
+#endif
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+static vr_draw_border_t vga_grborder;
+#endif
+
+static void vga_nop(scr_stat *scp, ...);
+
+static sc_rndr_sw_t txtrndrsw = {
+ vga_txtclear,
+ vga_txtborder,
+ vga_txtdraw,
+ vga_txtcursor_shape,
+ vga_txtcursor,
+ vga_txtblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_txtmouse,
+};
+RENDERER(mda, 0, txtrndrsw);
+RENDERER(cga, 0, txtrndrsw);
+RENDERER(ega, 0, txtrndrsw);
+RENDERER(vga, 0, txtrndrsw);
+
+#ifdef SC_PIXEL_MODE
+static sc_rndr_sw_t egarndrsw = {
+ vga_pxlclear,
+ vga_pxlborder,
+ vga_egadraw,
+ vga_pxlcursor_shape,
+ vga_pxlcursor,
+ vga_pxlblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_pxlmouse,
+};
+RENDERER(ega, PIXEL_MODE, egarndrsw);
+
+static sc_rndr_sw_t vgarndrsw = {
+ vga_pxlclear,
+ vga_pxlborder,
+ vga_vgadraw,
+ vga_pxlcursor_shape,
+ vga_pxlcursor,
+ vga_pxlblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_pxlmouse,
+};
+RENDERER(vga, PIXEL_MODE, vgarndrsw);
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+static sc_rndr_sw_t grrndrsw = {
+ (vr_clear_t *)vga_nop,
+ vga_grborder,
+ (vr_draw_t *)vga_nop,
+ (vr_set_cursor_t *)vga_nop,
+ (vr_draw_cursor_t *)vga_nop,
+ (vr_blink_cursor_t *)vga_nop,
+ (vr_set_mouse_t *)vga_nop,
+ (vr_draw_mouse_t *)vga_nop,
+};
+RENDERER(cga, GRAPHICS_MODE, grrndrsw);
+RENDERER(ega, GRAPHICS_MODE, grrndrsw);
+RENDERER(vga, GRAPHICS_MODE, grrndrsw);
+#endif /* SC_NO_MODE_CHANGE */
+
+#ifndef SC_NO_CUTPASTE
+static u_short mouse_and_mask[16] = {
+ 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
+ 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
+};
+static u_short mouse_or_mask[16] = {
+ 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
+ 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
+};
+#endif
+
+static void
+vga_nop(scr_stat *scp, ...)
+{
+}
+
+/* text mode renderer */
+
+static void
+vga_txtclear(scr_stat *scp, int c, int attr)
+{
+ sc_vtb_clear(&scp->scr, c, attr);
+}
+
+static void
+vga_txtborder(scr_stat *scp, int color)
+{
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+}
+
+static void
+vga_txtdraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t p;
+ int c;
+ int a;
+
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+
+ if (flip) {
+ for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) {
+ c = sc_vtb_getc(&scp->vtb, from);
+ a = sc_vtb_geta(&scp->vtb, from);
+ a = (a & 0x8800) | ((a & 0x7000) >> 4)
+ | ((a & 0x0700) << 4);
+ p = sc_vtb_putchar(&scp->scr, p, c, a);
+ }
+ } else {
+ sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
+ }
+}
+
+static void
+vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
+{
+ if (base < 0 || base >= scp->font_size)
+ return;
+ /* the caller may set height <= 0 in order to disable the cursor */
+#if 0
+ scp->cursor_base = base;
+ scp->cursor_height = height;
+#endif
+ (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
+ base, height,
+ scp->font_size, blink);
+}
+
+static void
+vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
+{
+ video_adapter_t *adp;
+ int cursor_attr;
+
+ if (scp->cursor_height <= 0) /* the text cursor is disabled */
+ return;
+
+ adp = scp->sc->adp;
+ if (blink) {
+ scp->status |= VR_CURSOR_BLINK;
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp,
+ at%scp->xsize,
+ at/scp->xsize);
+ } else {
+ if (scp->status & VR_CURSOR_ON)
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp,
+ -1, -1);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ } else {
+ scp->status &= ~VR_CURSOR_BLINK;
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ cursor_attr = sc_vtb_geta(&scp->vtb, at);
+ scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
+ scp->cursor_saveunder_attr = cursor_attr;
+ if ((cursor_attr & 0x7000) == 0x7000) {
+ cursor_attr &= 0x8f00;
+ if ((cursor_attr & 0x0700) == 0)
+ cursor_attr |= 0x0700;
+ } else {
+ cursor_attr |= 0x7000;
+ if ((cursor_attr & 0x0700) == 0x0700)
+ cursor_attr &= 0xf000;
+ }
+ if (flip)
+ cursor_attr = (cursor_attr & 0x8800)
+ | ((cursor_attr & 0x7000) >> 4)
+ | ((cursor_attr & 0x0700) << 4);
+ sc_vtb_putc(&scp->scr, at,
+ sc_vtb_getc(&scp->scr, at),
+ cursor_attr);
+ } else {
+ cursor_attr = scp->cursor_saveunder_attr;
+ if (flip)
+ cursor_attr = (cursor_attr & 0x8800)
+ | ((cursor_attr & 0x7000) >> 4)
+ | ((cursor_attr & 0x0700) << 4);
+ if (scp->status & VR_CURSOR_ON)
+ sc_vtb_putc(&scp->scr, at,
+ scp->cursor_saveunder_char,
+ cursor_attr);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ }
+}
+
+static void
+vga_txtblink(scr_stat *scp, int at, int flip)
+{
+}
+
+#ifndef SC_NO_CUTPASTE
+
+static void
+draw_txtmouse(scr_stat *scp, int x, int y)
+{
+#ifndef SC_ALT_MOUSE_IMAGE
+ u_char font_buf[128];
+ u_short cursor[32];
+ int pos;
+ int xoffset, yoffset;
+ int crtc_addr;
+ int i;
+
+ /* prepare mousepointer char's bitmaps */
+ pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+ bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos)*scp->font_size,
+ &font_buf[0], scp->font_size);
+ bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos + 1)*scp->font_size,
+ &font_buf[32], scp->font_size);
+ bcopy(scp->font
+ + sc_vtb_getc(&scp->vtb, pos + scp->xsize)*scp->font_size,
+ &font_buf[64], scp->font_size);
+ bcopy(scp->font
+ + sc_vtb_getc(&scp->vtb, pos + scp->xsize + 1)*scp->font_size,
+ &font_buf[96], scp->font_size);
+ for (i = 0; i < scp->font_size; ++i) {
+ cursor[i] = font_buf[i]<<8 | font_buf[i+32];
+ cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
+ }
+
+ /* now and-or in the mousepointer image */
+ xoffset = x%8;
+ yoffset = y%scp->font_size;
+ for (i = 0; i < 16; ++i) {
+ cursor[i + yoffset] =
+ (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
+ | (mouse_or_mask[i] >> xoffset);
+ }
+ for (i = 0; i < scp->font_size; ++i) {
+ font_buf[i] = (cursor[i] & 0xff00) >> 8;
+ font_buf[i + 32] = cursor[i] & 0xff;
+ font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
+ font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
+ }
+
+#if 1
+ /* wait for vertical retrace to avoid jitter on some videocards */
+ crtc_addr = scp->sc->adp->va_crtc_addr;
+ while (!(inb(crtc_addr + 6) & 0x08)) /* idle */ ;
+#endif
+ (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
+ SC_MOUSE_CHAR, 4);
+
+ sc_vtb_putc(&scp->scr, pos, SC_MOUSE_CHAR, sc_vtb_geta(&scp->scr, pos));
+ /* FIXME: may be out of range! */
+ sc_vtb_putc(&scp->scr, pos + scp->xsize, SC_MOUSE_CHAR + 2,
+ sc_vtb_geta(&scp->scr, pos + scp->xsize));
+ if (x < (scp->xsize - 1)*8) {
+ sc_vtb_putc(&scp->scr, pos + 1, SC_MOUSE_CHAR + 1,
+ sc_vtb_geta(&scp->scr, pos + 1));
+ sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, SC_MOUSE_CHAR + 3,
+ sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
+ }
+#else /* SC_ALT_MOUSE_IMAGE */
+ /* Red, magenta and brown are mapped to green to to keep it readable */
+ static const int col_conv[16] = {
+ 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
+ };
+ int pos;
+ int color;
+ int a;
+
+ pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+ a = sc_vtb_geta(&scp->scr, pos);
+ if (scp->sc->adp->va_flags & V_ADP_COLOR)
+ color = (col_conv[(a & 0xf000) >> 12] << 12)
+ | ((a & 0x0f00) | 0x0800);
+ else
+ color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
+ sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
+#endif /* SC_ALT_MOUSE_IMAGE */
+}
+
+static void
+remove_txtmouse(scr_stat *scp, int x, int y)
+{
+}
+
+static void
+vga_txtmouse(scr_stat *scp, int x, int y, int on)
+{
+ if (on)
+ draw_txtmouse(scp, x, y);
+ else
+ remove_txtmouse(scp, x, y);
+}
+
+#endif /* SC_NO_CUTPASTE */
+
+#ifdef SC_PIXEL_MODE
+
+/* pixel (raster text) mode renderer */
+
+static void
+vga_pxlclear(scr_stat *scp, int c, int attr)
+{
+ vm_offset_t p;
+ int line_width;
+ int lines;
+ int i;
+
+ /* XXX: we are just filling the screen with the background color... */
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, ((attr & 0xf000) >> 4) | 0x00); /* set/reset */
+ line_width = scp->sc->adp->va_line_width;
+ lines = scp->ysize*scp->font_size;
+ p = scp->sc->adp->va_window + line_width*scp->yoff*scp->font_size
+ + scp->xoff;
+ for (i = 0; i < lines; ++i) {
+ bzero_io((void *)p, scp->xsize);
+ p += line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlborder(scr_stat *scp, int color)
+{
+ vm_offset_t p;
+ int line_width;
+ int i;
+
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
+ line_width = scp->sc->adp->va_line_width;
+ p = scp->sc->adp->va_window;
+ if (scp->yoff > 0) {
+ bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
+ bzero_io((void *)(p + line_width*(scp->yoff + scp->ysize)
+ *scp->font_size),
+ line_width*(scp->ypixel
+ - (scp->yoff + scp->ysize)*scp->font_size));
+ }
+ if (scp->xoff > 0) {
+ for (i = 0; i < scp->ysize*scp->font_size; ++i) {
+ bzero_io((void *)(p + line_width
+ *(scp->yoff*scp->font_size + i)),
+ scp->xoff);
+ bzero_io((void *)(p + line_width
+ *(scp->yoff*scp->font_size + i)
+ + scp->xoff + scp->xsize),
+ scp->xpixel/8 - scp->xoff - scp->xsize);
+ }
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_egadraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t d;
+ vm_offset_t e;
+ u_char *f;
+ u_short bg;
+ u_short col1, col2;
+ int line_width;
+ int i, j;
+ int a;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (from%scp->xsize)
+ + scp->font_size*line_width*(from/scp->xsize);
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ bg = -1;
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+ for (i = from; count-- > 0; ++i) {
+ a = sc_vtb_geta(&scp->vtb, i);
+ if (flip) {
+ col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
+ col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
+ } else {
+ col1 = (a & 0x0f00);
+ col2 = (a & 0xf000) >> 4;
+ }
+ /* set background color in EGA/VGA latch */
+ if (bg != col2) {
+ bg = col2;
+ outw(GDCIDX, bg | 0x00); /* set/reset */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ }
+ /* foreground color */
+ outw(GDCIDX, col1 | 0x00); /* set/reset */
+ e = d;
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
+ for (j = 0; j < scp->font_size; ++j, ++f) {
+ outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
+ writeb(e, 0);
+ e += line_width;
+ }
+ ++d;
+ if ((i % scp->xsize) == scp->xsize - 1)
+ d += scp->xoff*2
+ + (scp->font_size - 1)*line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+}
+
+static void
+vga_vgadraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t d;
+ vm_offset_t e;
+ u_char *f;
+ u_short bg;
+ u_short col1, col2;
+ int line_width;
+ int i, j;
+ int a;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (from%scp->xsize)
+ + scp->font_size*line_width*(from/scp->xsize);
+
+ outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ bg = -1;
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+ for (i = from; count-- > 0; ++i) {
+ a = sc_vtb_geta(&scp->vtb, i);
+ if (flip) {
+ col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
+ col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
+ } else {
+ col1 = (a & 0x0f00);
+ col2 = (a & 0xf000) >> 4;
+ }
+ /* set background color in EGA/VGA latch */
+ if (bg != col2) {
+ bg = col2;
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, bg | 0x00); /* set/reset */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
+ }
+ /* foreground color */
+ outw(GDCIDX, col1 | 0x00); /* set/reset */
+ e = d;
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
+ for (j = 0; j < scp->font_size; ++j, ++f) {
+ writeb(e, *f);
+ e += line_width;
+ }
+ ++d;
+ if ((i % scp->xsize) == scp->xsize - 1)
+ d += scp->xoff*2
+ + (scp->font_size - 1)*line_width;
+ }
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
+{
+ if (base < 0 || base >= scp->font_size)
+ return;
+ /* the caller may set height <= 0 in order to disable the cursor */
+#if 0
+ scp->cursor_base = base;
+ scp->cursor_height = height;
+#endif
+}
+
+static void
+draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
+{
+ vm_offset_t d;
+ u_char *f;
+ int line_width;
+ int height;
+ int col;
+ int a;
+ int i;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (at%scp->xsize)
+ + scp->font_size*line_width*(at/scp->xsize)
+ + (scp->font_size - scp->cursor_base - 1)*line_width;
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ /* set background color in EGA/VGA latch */
+ a = sc_vtb_geta(&scp->vtb, at);
+ if (flip)
+ col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
+ else
+ col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
+ outw(GDCIDX, col | 0x00); /* set/reset */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ /* foreground color */
+ if (flip)
+ col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
+ else
+ col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
+ outw(GDCIDX, col | 0x00); /* set/reset */
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
+ + scp->font_size - scp->cursor_base - 1]);
+ height = imin(scp->cursor_height, scp->font_size);
+ for (i = 0; i < height; ++i, --f) {
+ outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
+ writeb(d, 0);
+ d -= line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+}
+
+static void
+vga_pxlcursor(scr_stat *scp, int at, int blink, int on, int flip)
+{
+ if (scp->cursor_height <= 0) /* the text cursor is disabled */
+ return;
+
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ draw_pxlcursor(scp, at, on, flip);
+ } else {
+ if (scp->status & VR_CURSOR_ON)
+ draw_pxlcursor(scp, at, on, flip);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ if (blink)
+ scp->status |= VR_CURSOR_BLINK;
+ else
+ scp->status &= ~VR_CURSOR_BLINK;
+}
+
+static void
+vga_pxlblink(scr_stat *scp, int at, int flip)
+{
+ static int blinkrate = 0;
+
+ if (!(scp->status & VR_CURSOR_BLINK))
+ return;
+ if (!(++blinkrate & 4))
+ return;
+ blinkrate = 0;
+ scp->status ^= VR_CURSOR_ON;
+ draw_pxlcursor(scp, at, scp->status & VR_CURSOR_ON, flip);
+}
+
+#ifndef SC_NO_CUTPASTE
+
+static void
+draw_pxlmouse(scr_stat *scp, int x, int y)
+{
+ vm_offset_t p;
+ int line_width;
+ int xoff, yoff;
+ int ymax;
+ u_short m;
+ int i, j;
+
+ line_width = scp->sc->adp->va_line_width;
+ xoff = (x - scp->xoff*8)%8;
+ yoff = y - (y/line_width)*line_width;
+ ymax = imin(y + 16, scp->ypixel);
+
+ outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0x0002); /* color compare */
+ outw(GDCIDX, 0x0007); /* color don't care */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
+ p = scp->sc->adp->va_window + line_width*y + x/8;
+ if (x < scp->xpixel - 16) {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = ~(mouse_and_mask[j] >> xoff);
+#ifdef __i386__
+ *(u_char *)p &= m >> 8;
+ *(u_char *)(p + 1) &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+ writeb(p + 1, readb(p + 1) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ } else {
+ xoff += 8;
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = ~(mouse_and_mask[j] >> xoff);
+#ifdef __i386__
+ *(u_char *)p &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
+ p = scp->sc->adp->va_window + line_width*y + x/8;
+ if (x < scp->xpixel - 16) {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = mouse_or_mask[j] >> xoff;
+#ifdef __i386__
+ *(u_char *)p &= m >> 8;
+ *(u_char *)(p + 1) &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+ writeb(p + 1, readb(p + 1) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ } else {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = mouse_or_mask[j] >> xoff;
+#ifdef __i386__
+ *(u_char *)p &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+}
+
+static void
+remove_pxlmouse(scr_stat *scp, int x, int y)
+{
+ vm_offset_t p;
+ int col, row;
+ int pos;
+ int line_width;
+ int ymax;
+ int i;
+
+ /* erase the mouse cursor image */
+ col = x/8 - scp->xoff;
+ row = y/scp->font_size - scp->yoff;
+ pos = row*scp->xsize + col;
+ i = (col < scp->xsize - 1) ? 2 : 1;
+ (*scp->rndr->draw)(scp, pos, i, FALSE);
+ if (row < scp->ysize - 1)
+ (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
+
+ /* paint border if necessary */
+ line_width = scp->sc->adp->va_line_width;
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (scp->border << 8) | 0x00); /* set/reset */
+ if (row == scp->ysize - 1) {
+ i = (scp->ysize + scp->yoff)*scp->font_size;
+ ymax = imin(i + scp->font_size, scp->ypixel);
+ p = scp->sc->adp->va_window + i*line_width + scp->xoff + col;
+ if (col < scp->xsize - 1) {
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ writeb(p + 1, 0);
+ p += line_width;
+ }
+ } else {
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ p += line_width;
+ }
+ }
+ }
+ if ((col == scp->xsize - 1) && (scp->xoff > 0)) {
+ i = (row + scp->yoff)*scp->font_size;
+ ymax = imin(i + scp->font_size*2, scp->ypixel);
+ p = scp->sc->adp->va_window + i*line_width
+ + scp->xoff + scp->xsize;
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlmouse(scr_stat *scp, int x, int y, int on)
+{
+ if (on)
+ draw_pxlmouse(scp, x, y);
+ else
+ remove_pxlmouse(scp, x, y);
+}
+
+#endif /* SC_NO_CUTPASTE */
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+
+/* graphics mode renderer */
+
+static void
+vga_grborder(scr_stat *scp, int color)
+{
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+}
+
+#endif
+
+#endif /* NSC > 0 && NVGA > 0 */
diff --git a/sys/dev/syscons/schistory.c b/sys/dev/syscons/schistory.c
new file mode 100644
index 0000000..765733c
--- /dev/null
+++ b/sys/dev/syscons/schistory.c
@@ -0,0 +1,222 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * Copyright (c) 1992-1998 Søren Schmidt
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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. 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 AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id:$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#ifndef SC_NO_HISTORY
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/console.h>
+
+#include <dev/syscons/syscons.h>
+
+#if !defined(SC_MAX_HISTORY_SIZE)
+#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS * NSC)
+#endif
+
+#if !defined(SC_HISTORY_SIZE)
+#define SC_HISTORY_SIZE (ROW * 4)
+#endif
+
+#if (SC_HISTORY_SIZE * MAXCONS * NSC) > SC_MAX_HISTORY_SIZE
+#undef SC_MAX_HISTORY_SIZE
+#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS * NSC)
+#endif
+
+/* local variables */
+static int extra_history_size
+ = SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE*MAXCONS;
+
+/* local functions */
+static void history_to_screen(scr_stat *scp);
+
+/* allocate a history buffer */
+int
+sc_alloc_history_buffer(scr_stat *scp, int lines, int wait)
+{
+ /*
+ * syscons unconditionally allocates buffers upto
+ * SC_HISTORY_SIZE lines or scp->ysize lines, whichever
+ * is larger. A value greater than that is allowed,
+ * subject to extra_history_size.
+ */
+ sc_vtb_t *history;
+ int cur_lines; /* current buffer size */
+ int min_lines; /* guaranteed buffer size */
+
+ if (lines <= 0)
+ lines = SC_HISTORY_SIZE; /* use the default value */
+ lines = imax(lines, scp->ysize);
+ min_lines = imax(SC_HISTORY_SIZE, scp->ysize);
+
+ history = scp->history;
+ scp->history = NULL;
+ if (history == NULL) {
+ cur_lines = 0;
+ } else {
+ cur_lines = sc_vtb_rows(history);
+ if (cur_lines > min_lines)
+ extra_history_size += cur_lines - min_lines;
+ sc_vtb_destroy(history);
+ }
+
+ if (lines > min_lines)
+ extra_history_size -= lines - min_lines;
+ history = (sc_vtb_t *)malloc(sizeof(*history),
+ M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+ if (history != NULL)
+ sc_vtb_init(history, VTB_RINGBUFFER, scp->xsize, lines,
+ NULL, wait);
+ scp->history_pos = 0;
+ scp->history = history;
+
+ return 0;
+}
+
+/* copy entire screen into the top of the history buffer */
+void
+sc_hist_save(scr_stat *scp)
+{
+ sc_vtb_append(&scp->vtb, 0, scp->history, scp->xsize*scp->ysize);
+ scp->history_pos = sc_vtb_tail(scp->history);
+}
+
+/* restore the screen by copying from the history buffer */
+int
+sc_hist_restore(scr_stat *scp)
+{
+ int ret;
+
+ if (scp->history_pos != sc_vtb_tail(scp->history)) {
+ scp->history_pos = sc_vtb_tail(scp->history);
+ history_to_screen(scp);
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ sc_vtb_seek(scp->history, sc_vtb_pos(scp->history,
+ sc_vtb_tail(scp->history),
+ -scp->xsize*scp->ysize));
+ return ret;
+}
+
+/* copy screen-full of saved lines */
+static void
+history_to_screen(scr_stat *scp)
+{
+ int pos;
+ int i;
+
+ pos = scp->history_pos;
+ for (i = 1; i <= scp->ysize; ++i) {
+ pos = sc_vtb_pos(scp->history, pos, -scp->xsize);
+ sc_vtb_copy(scp->history, pos,
+ &scp->vtb, scp->xsize*(scp->ysize - i),
+ scp->xsize);
+ }
+ mark_all(scp);
+}
+
+/* go to the tail of the history buffer */
+void
+sc_hist_home(scr_stat *scp)
+{
+ scp->history_pos = sc_vtb_tail(scp->history);
+ history_to_screen(scp);
+}
+
+/* go to the top of the history buffer */
+void
+sc_hist_end(scr_stat *scp)
+{
+ scp->history_pos = sc_vtb_pos(scp->history, sc_vtb_tail(scp->history),
+ scp->xsize*scp->ysize);
+ history_to_screen(scp);
+}
+
+/* move one line up */
+int
+sc_hist_up_line(scr_stat *scp)
+{
+ if (sc_vtb_pos(scp->history, scp->history_pos, -(scp->xsize*scp->ysize))
+ == sc_vtb_tail(scp->history))
+ return -1;
+ scp->history_pos = sc_vtb_pos(scp->history, scp->history_pos,
+ -scp->xsize);
+ history_to_screen(scp);
+ return 0;
+}
+
+/* move one line down */
+int
+sc_hist_down_line(scr_stat *scp)
+{
+ if (scp->history_pos == sc_vtb_tail(scp->history))
+ return -1;
+ scp->history_pos = sc_vtb_pos(scp->history, scp->history_pos,
+ scp->xsize);
+ history_to_screen(scp);
+ return 0;
+}
+
+int
+sc_hist_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
+ struct proc *p)
+{
+ scr_stat *scp;
+
+ switch (cmd) {
+
+ case CONS_HISTORY: /* set history size */
+ scp = sc_get_scr_stat(tp->t_dev);
+ if (*(int *)data <= 0)
+ return EINVAL;
+ if (scp->status & BUFFER_SAVED)
+ return EBUSY;
+ return sc_alloc_history_buffer(scp,
+ imax(*(int *)data, scp->ysize),
+ TRUE);
+ }
+
+ return ENOIOCTL;
+}
+
+#endif /* SC_NO_HISTORY */
+
+#endif /* NSC */
diff --git a/sys/dev/syscons/scmouse.c b/sys/dev/syscons/scmouse.c
new file mode 100644
index 0000000..8d8dc67
--- /dev/null
+++ b/sys/dev/syscons/scmouse.c
@@ -0,0 +1,1083 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id:$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/signalvar.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/console.h>
+#include <machine/mouse.h>
+
+#include <dev/syscons/syscons.h>
+
+#define SC_WAKEUP_DELTA 20
+
+/* for backward compatibility */
+#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)
+
+typedef struct old_mouse_data {
+ int x;
+ int y;
+ int buttons;
+} old_mouse_data_t;
+
+typedef struct old_mouse_info {
+ int operation;
+ union {
+ struct old_mouse_data data;
+ struct mouse_mode mode;
+ } u;
+} old_mouse_info_t;
+
+/* local variables */
+#ifndef SC_NO_SYSMOUSE
+static int mouse_level; /* sysmouse protocol level */
+static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };
+static int cut_buffer_size;
+static u_char *cut_buffer;
+#endif /* SC_NO_SYSMOUE */
+
+/* local functions */
+#ifndef SC_NO_SYSMOUSE
+static void set_mouse_pos(scr_stat *scp);
+#ifndef SC_NO_CUTPASTE
+static int skip_spc_right(scr_stat *scp, int p);
+static int skip_spc_left(scr_stat *scp, int p);
+static void mouse_cut(scr_stat *scp);
+static void mouse_cut_start(scr_stat *scp);
+static void mouse_cut_end(scr_stat *scp);
+static void mouse_cut_word(scr_stat *scp);
+static void mouse_cut_line(scr_stat *scp);
+static void mouse_cut_extend(scr_stat *scp);
+static void mouse_paste(scr_stat *scp);
+#endif /* SC_NO_CUTPASTE */
+#endif /* SC_NO_SYSMOUE */
+
+#ifndef SC_NO_CUTPASTE
+/* allocate a cut buffer */
+void
+sc_alloc_cut_buffer(scr_stat *scp, int wait)
+{
+ u_char *p;
+
+ if ((cut_buffer == NULL)
+ || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
+ p = cut_buffer;
+ cut_buffer = NULL;
+ if (p != NULL)
+ free(p, M_DEVBUF);
+ cut_buffer_size = scp->xsize * scp->ysize + 1;
+ p = (u_char *)malloc(cut_buffer_size,
+ M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+ if (p != NULL)
+ p[0] = '\0';
+ cut_buffer = p;
+ }
+}
+#endif /* SC_NO_CUTPASTE */
+
+#ifndef SC_NO_SYSMOUSE
+
+/* modify the sysmouse software level */
+void
+sc_mouse_set_level(int level)
+{
+ mouse_level = level;
+}
+
+/* move mouse */
+void
+sc_mouse_move(scr_stat *scp, int x, int y)
+{
+ int s;
+
+ s = spltty();
+ scp->mouse_xpos = x;
+ scp->mouse_ypos = y;
+ scp->mouse_pos = scp->mouse_oldpos =
+ (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+ splx(s);
+}
+
+/* adjust mouse position */
+static void
+set_mouse_pos(scr_stat *scp)
+{
+ static int last_xpos = -1, last_ypos = -1;
+
+ if (scp->mouse_xpos < scp->xoff*8)
+ scp->mouse_xpos = scp->xoff*8;
+ if (scp->mouse_ypos < scp->yoff*scp->font_size)
+ scp->mouse_ypos = scp->yoff*scp->font_size;
+ if (ISGRAPHSC(scp)) {
+ if (scp->mouse_xpos > scp->xpixel-1)
+ scp->mouse_xpos = scp->xpixel-1;
+ if (scp->mouse_ypos > scp->ypixel-1)
+ scp->mouse_ypos = scp->ypixel-1;
+ return;
+ } else {
+ if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1)
+ scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1;
+ if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1)
+ scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1;
+ }
+
+ if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
+ scp->status |= MOUSE_MOVED;
+ scp->mouse_pos =
+ (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize
+ + scp->mouse_xpos/8 - scp->xoff;
+#ifndef SC_NO_CUTPASTE
+ if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
+ mouse_cut(scp);
+#endif
+ }
+}
+
+#ifndef SC_NO_CUTPASTE
+
+void
+sc_draw_mouse_image(scr_stat *scp)
+{
+ if (ISGRAPHSC(scp))
+ return;
+
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
+ scp->mouse_oldpos = scp->mouse_pos;
+ --scp->sc->videoio_in_progress;
+}
+
+void
+sc_remove_mouse_image(scr_stat *scp)
+{
+ int size;
+ int i;
+
+ if (ISGRAPHSC(scp))
+ return;
+
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_mouse)(scp,
+ (scp->mouse_oldpos%scp->xsize + scp->xoff)*8,
+ (scp->mouse_oldpos/scp->xsize + scp->yoff)
+ * scp->font_size,
+ FALSE);
+ size = scp->xsize*scp->ysize;
+ i = scp->mouse_oldpos;
+ mark_for_update(scp, i);
+ mark_for_update(scp, i);
+#ifndef PC98
+ if (i + scp->xsize + 1 < size) {
+ mark_for_update(scp, i + scp->xsize + 1);
+ } else if (i + scp->xsize < size) {
+ mark_for_update(scp, i + scp->xsize);
+ } else if (i + 1 < size) {
+ mark_for_update(scp, i + 1);
+ }
+#endif /* PC98 */
+ --scp->sc->videoio_in_progress;
+}
+
+int
+sc_inside_cutmark(scr_stat *scp, int pos)
+{
+ int start;
+ int end;
+
+ if (scp->mouse_cut_end < 0)
+ return FALSE;
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ start = scp->mouse_cut_start;
+ end = scp->mouse_cut_end;
+ } else {
+ start = scp->mouse_cut_end;
+ end = scp->mouse_cut_start - 1;
+ }
+ return ((start <= pos) && (pos <= end));
+}
+
+void
+sc_remove_cutmarking(scr_stat *scp)
+{
+ int s;
+
+ s = spltty();
+ if (scp->mouse_cut_end >= 0) {
+ mark_for_update(scp, scp->mouse_cut_start);
+ mark_for_update(scp, scp->mouse_cut_end);
+ }
+ scp->mouse_cut_start = scp->xsize*scp->ysize;
+ scp->mouse_cut_end = -1;
+ splx(s);
+ scp->status &= ~MOUSE_CUTTING;
+}
+
+void
+sc_remove_all_cutmarkings(sc_softc_t *sc)
+{
+ int i;
+
+ /* delete cut markings in all vtys */
+ for (i = 0; i < sc->vtys; ++i) {
+ if (sc->console[i] == NULL)
+ continue;
+ sc_remove_cutmarking(sc->console[i]);
+ }
+}
+
+void
+sc_remove_all_mouse(sc_softc_t *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->vtys; ++i) {
+ if (sc->console[i] == NULL)
+ continue;
+ if (sc->console[i]->status & MOUSE_VISIBLE) {
+ sc->console[i]->status &= ~MOUSE_VISIBLE;
+ mark_all(sc->console[i]);
+ }
+ }
+}
+
+#define isspace(c) (((c) & 0xff) == ' ')
+
+/* skip spaces to right */
+static int
+skip_spc_right(scr_stat *scp, int p)
+{
+ int c;
+ int i;
+
+ for (i = p % scp->xsize; i < scp->xsize; ++i) {
+ c = sc_vtb_getc(&scp->vtb, p);
+ if (!isspace(c))
+ break;
+ ++p;
+ }
+ return i;
+}
+
+/* skip spaces to left */
+static int
+skip_spc_left(scr_stat *scp, int p)
+{
+ int c;
+ int i;
+
+ for (i = p-- % scp->xsize - 1; i >= 0; --i) {
+ c = sc_vtb_getc(&scp->vtb, p);
+ if (!isspace(c))
+ break;
+ --p;
+ }
+ return i;
+}
+
+/* copy marked region to the cut buffer */
+static void
+mouse_cut(scr_stat *scp)
+{
+ int start;
+ int end;
+ int from;
+ int to;
+ int blank;
+ int c;
+ int p;
+ int s;
+ int i;
+
+ start = scp->mouse_cut_start;
+ end = scp->mouse_cut_end;
+ if (scp->mouse_pos >= start) {
+ from = start;
+ to = end = scp->mouse_pos;
+ } else {
+ from = end = scp->mouse_pos;
+ to = start - 1;
+ }
+ for (p = from, i = blank = 0; p <= to; ++p) {
+ cut_buffer[i] = sc_vtb_getc(&scp->vtb, p);
+ /* remember the position of the last non-space char */
+ if (!isspace(cut_buffer[i++]))
+ blank = i; /* the first space after the last non-space */
+ /* trim trailing blank when crossing lines */
+ if ((p % scp->xsize) == (scp->xsize - 1)) {
+ cut_buffer[blank] = '\r';
+ i = blank + 1;
+ }
+ }
+ cut_buffer[i] = '\0';
+
+ /* scan towards the end of the last line */
+ --p;
+ for (i = p % scp->xsize; i < scp->xsize; ++i) {
+ c = sc_vtb_getc(&scp->vtb, p);
+ if (!isspace(c))
+ break;
+ ++p;
+ }
+ /* if there is nothing but blank chars, trim them, but mark towards eol */
+ if (i >= scp->xsize) {
+ if (end >= start)
+ to = end = p - 1;
+ else
+ to = start = p;
+ cut_buffer[blank++] = '\r';
+ cut_buffer[blank] = '\0';
+ }
+
+ /* remove the current marking */
+ s = spltty();
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ mark_for_update(scp, scp->mouse_cut_start);
+ mark_for_update(scp, scp->mouse_cut_end);
+ } else if (scp->mouse_cut_end >= 0) {
+ mark_for_update(scp, scp->mouse_cut_end);
+ mark_for_update(scp, scp->mouse_cut_start);
+ }
+
+ /* mark the new region */
+ scp->mouse_cut_start = start;
+ scp->mouse_cut_end = end;
+ mark_for_update(scp, from);
+ mark_for_update(scp, to);
+ splx(s);
+}
+
+/* a mouse button is pressed, start cut operation */
+static void
+mouse_cut_start(scr_stat *scp)
+{
+ int i;
+ int j;
+ int s;
+
+ if (scp->status & MOUSE_VISIBLE) {
+ i = scp->mouse_cut_start;
+ j = scp->mouse_cut_end;
+ sc_remove_all_cutmarkings(scp->sc);
+ if (scp->mouse_pos == i && i == j) {
+ cut_buffer[0] = '\0';
+ } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
+ /* if the pointer is on trailing blank chars, mark towards eol */
+ i = skip_spc_left(scp, scp->mouse_pos) + 1;
+ s = spltty();
+ scp->mouse_cut_start =
+ (scp->mouse_pos / scp->xsize) * scp->xsize + i;
+ scp->mouse_cut_end =
+ (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1;
+ splx(s);
+ cut_buffer[0] = '\r';
+ cut_buffer[1] = '\0';
+ scp->status |= MOUSE_CUTTING;
+ } else {
+ s = spltty();
+ scp->mouse_cut_start = scp->mouse_pos;
+ scp->mouse_cut_end = scp->mouse_cut_start;
+ splx(s);
+ cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start);
+ cut_buffer[1] = '\0';
+ scp->status |= MOUSE_CUTTING;
+ }
+ mark_all(scp); /* this is probably overkill XXX */
+ }
+}
+
+/* end of cut operation */
+static void
+mouse_cut_end(scr_stat *scp)
+{
+ if (scp->status & MOUSE_VISIBLE)
+ scp->status &= ~MOUSE_CUTTING;
+}
+
+/* copy a word under the mouse pointer */
+static void
+mouse_cut_word(scr_stat *scp)
+{
+ int start;
+ int end;
+ int sol;
+ int eol;
+ int c;
+ int s;
+ int i;
+ int j;
+
+ /*
+ * Because we don't have locale information in the kernel,
+ * we only distinguish space char and non-space chars. Punctuation
+ * chars, symbols and other regular chars are all treated alike.
+ */
+ if (scp->status & MOUSE_VISIBLE) {
+ /* remove the current cut mark */
+ s = spltty();
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ mark_for_update(scp, scp->mouse_cut_start);
+ mark_for_update(scp, scp->mouse_cut_end);
+ } else if (scp->mouse_cut_end >= 0) {
+ mark_for_update(scp, scp->mouse_cut_end);
+ mark_for_update(scp, scp->mouse_cut_start);
+ }
+ scp->mouse_cut_start = scp->xsize*scp->ysize;
+ scp->mouse_cut_end = -1;
+ splx(s);
+
+ sol = (scp->mouse_pos / scp->xsize) * scp->xsize;
+ eol = sol + scp->xsize;
+ c = sc_vtb_getc(&scp->vtb, scp->mouse_pos);
+ if (isspace(c)) {
+ /* blank space */
+ for (j = scp->mouse_pos; j >= sol; --j) {
+ c = sc_vtb_getc(&scp->vtb, j);
+ if (!isspace(c))
+ break;
+ }
+ start = ++j;
+ for (j = scp->mouse_pos; j < eol; ++j) {
+ c = sc_vtb_getc(&scp->vtb, j);
+ if (!isspace(c))
+ break;
+ }
+ end = j - 1;
+ } else {
+ /* non-space word */
+ for (j = scp->mouse_pos; j >= sol; --j) {
+ c = sc_vtb_getc(&scp->vtb, j);
+ if (isspace(c))
+ break;
+ }
+ start = ++j;
+ for (j = scp->mouse_pos; j < eol; ++j) {
+ c = sc_vtb_getc(&scp->vtb, j);
+ if (isspace(c))
+ break;
+ }
+ end = j - 1;
+ }
+
+ /* copy the found word */
+ for (i = 0, j = start; j <= end; ++j)
+ cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
+ cut_buffer[i] = '\0';
+ scp->status |= MOUSE_CUTTING;
+
+ /* mark the region */
+ s = spltty();
+ scp->mouse_cut_start = start;
+ scp->mouse_cut_end = end;
+ mark_for_update(scp, start);
+ mark_for_update(scp, end);
+ splx(s);
+ }
+}
+
+/* copy a line under the mouse pointer */
+static void
+mouse_cut_line(scr_stat *scp)
+{
+ int s;
+ int i;
+ int j;
+
+ if (scp->status & MOUSE_VISIBLE) {
+ /* remove the current cut mark */
+ s = spltty();
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ mark_for_update(scp, scp->mouse_cut_start);
+ mark_for_update(scp, scp->mouse_cut_end);
+ } else if (scp->mouse_cut_end >= 0) {
+ mark_for_update(scp, scp->mouse_cut_end);
+ mark_for_update(scp, scp->mouse_cut_start);
+ }
+
+ /* mark the entire line */
+ scp->mouse_cut_start =
+ (scp->mouse_pos / scp->xsize) * scp->xsize;
+ scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1;
+ mark_for_update(scp, scp->mouse_cut_start);
+ mark_for_update(scp, scp->mouse_cut_end);
+ splx(s);
+
+ /* copy the line into the cut buffer */
+ for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j)
+ cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
+ cut_buffer[i++] = '\r';
+ cut_buffer[i] = '\0';
+ scp->status |= MOUSE_CUTTING;
+ }
+}
+
+/* extend the marked region to the mouse pointer position */
+static void
+mouse_cut_extend(scr_stat *scp)
+{
+ int start;
+ int end;
+ int s;
+
+ if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
+ && (scp->mouse_cut_end >= 0)) {
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ start = scp->mouse_cut_start;
+ end = scp->mouse_cut_end;
+ } else {
+ start = scp->mouse_cut_end;
+ end = scp->mouse_cut_start - 1;
+ }
+ s = spltty();
+ if (scp->mouse_pos > end) {
+ scp->mouse_cut_start = start;
+ scp->mouse_cut_end = end;
+ } else if (scp->mouse_pos < start) {
+ scp->mouse_cut_start = end + 1;
+ scp->mouse_cut_end = start;
+ } else {
+ if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) {
+ scp->mouse_cut_start = start;
+ scp->mouse_cut_end = end;
+ } else {
+ scp->mouse_cut_start = end + 1;
+ scp->mouse_cut_end = start;
+ }
+ }
+ splx(s);
+ mouse_cut(scp);
+ scp->status |= MOUSE_CUTTING;
+ }
+}
+
+/* paste cut buffer contents into the current vty */
+static void
+mouse_paste(scr_stat *scp)
+{
+ if (scp->status & MOUSE_VISIBLE)
+ sc_paste(scp, cut_buffer, strlen(cut_buffer));
+}
+
+#endif /* SC_NO_CUTPASTE */
+
+int
+sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
+ struct proc *p)
+{
+
+ scr_stat *scp;
+ int s;
+ int i;
+
+ /* scp == NULL, if tp == sc_get_mouse_tty() (/dev/sysmouse) */
+ scp = sc_get_scr_stat(tp->t_dev);
+
+ switch (cmd) {
+
+ case CONS_MOUSECTL: /* control mouse arrow */
+ case OLD_CONS_MOUSECTL:
+ {
+ /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
+ static int butmap[8] = {
+ MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
+ MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
+ MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
+ MOUSE_MSC_BUTTON3UP,
+ MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
+ MOUSE_MSC_BUTTON2UP,
+ MOUSE_MSC_BUTTON1UP,
+ 0,
+ };
+ mouse_info_t *mouse = (mouse_info_t*)data;
+ mouse_info_t buf;
+ scr_stat *cur_scp;
+ struct tty *mtty;
+
+ if (scp == NULL)
+ return ENOTTY;
+
+ if (cmd == OLD_CONS_MOUSECTL) {
+ static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+ old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
+
+ mouse = &buf;
+ mouse->operation = old_mouse->operation;
+ switch (mouse->operation) {
+ case MOUSE_MODE:
+ mouse->u.mode = old_mouse->u.mode;
+ break;
+ case MOUSE_SHOW:
+ case MOUSE_HIDE:
+ break;
+ case MOUSE_MOVEABS:
+ case MOUSE_MOVEREL:
+ case MOUSE_ACTION:
+ mouse->u.data.x = old_mouse->u.data.x;
+ mouse->u.data.y = old_mouse->u.data.y;
+ mouse->u.data.z = 0;
+ mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
+ break;
+ case MOUSE_GETINFO:
+ old_mouse->u.data.x = scp->mouse_xpos;
+ old_mouse->u.data.y = scp->mouse_ypos;
+ old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
+ break;
+ default:
+ return EINVAL;
+ }
+ }
+
+ cur_scp = scp->sc->cur_scp;
+
+ switch (mouse->operation) {
+ case MOUSE_MODE:
+ if (ISSIGVALID(mouse->u.mode.signal)) {
+ scp->mouse_signal = mouse->u.mode.signal;
+ scp->mouse_proc = p;
+ scp->mouse_pid = p->p_pid;
+ }
+ else {
+ scp->mouse_signal = 0;
+ scp->mouse_proc = NULL;
+ scp->mouse_pid = 0;
+ }
+ return 0;
+
+ case MOUSE_SHOW:
+ if (!ISMOUSEAVAIL(scp->sc->adp->va_flags))
+ return EINVAL;
+ s = spltty();
+ if (!(scp->sc->flags & SC_MOUSE_ENABLED)) {
+ scp->sc->flags |= SC_MOUSE_ENABLED;
+ if (!ISGRAPHSC(cur_scp)) {
+ cur_scp->status |= MOUSE_VISIBLE;
+ mark_all(cur_scp);
+ }
+ splx(s);
+ return 0;
+ } else {
+ splx(s);
+ return EINVAL;
+ }
+ break;
+#if 0
+ if (!(scp->status & MOUSE_ENABLED)) {
+ scp->mouse_oldpos = scp->mouse_pos;
+ scp->status |= MOUSE_ENABLED;
+ if (!ISGRAPHSC(scp))
+ scp->status |= MOUSE_VISIBLE;
+ splx(s);
+ mark_all(scp);
+ return 0;
+ } else {
+ splx(s);
+ return EINVAL;
+ }
+ break;
+#endif
+
+ case MOUSE_HIDE:
+ s = spltty();
+ if (scp->sc->flags & SC_MOUSE_ENABLED) {
+ scp->sc->flags &= ~SC_MOUSE_ENABLED;
+ sc_remove_all_mouse(scp->sc);
+ splx(s);
+ return 0;
+ } else {
+ splx(s);
+ return EINVAL;
+ }
+ break;
+#if 0
+ if (scp->status & MOUSE_ENABLED) {
+ scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
+ mark_all(scp);
+ splx(s);
+ return 0;
+ } else {
+ splx(s);
+ return EINVAL;
+ }
+ break;
+#endif
+
+ case MOUSE_MOVEABS:
+ s = spltty();
+ scp->mouse_xpos = mouse->u.data.x;
+ scp->mouse_ypos = mouse->u.data.y;
+ set_mouse_pos(scp);
+ splx(s);
+ break;
+
+ case MOUSE_MOVEREL:
+ s = spltty();
+ scp->mouse_xpos += mouse->u.data.x;
+ scp->mouse_ypos += mouse->u.data.y;
+ set_mouse_pos(scp);
+ splx(s);
+ break;
+
+ case MOUSE_GETINFO:
+ mouse->u.data.x = scp->mouse_xpos;
+ mouse->u.data.y = scp->mouse_ypos;
+ mouse->u.data.z = 0;
+ mouse->u.data.buttons = scp->mouse_buttons;
+ return 0;
+
+ case MOUSE_ACTION:
+ case MOUSE_MOTION_EVENT:
+ /* send out mouse event on /dev/sysmouse */
+#if 0
+ /* this should maybe only be settable from /dev/consolectl SOS */
+ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
+ return ENOTTY;
+#endif
+ mouse_status.dx += mouse->u.data.x;
+ mouse_status.dy += mouse->u.data.y;
+ mouse_status.dz += mouse->u.data.z;
+ if (mouse->operation == MOUSE_ACTION)
+ mouse_status.button = mouse->u.data.buttons;
+ mouse_status.flags |=
+ ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
+ MOUSE_POSCHANGED : 0)
+ | (mouse_status.obutton ^ mouse_status.button);
+ if (mouse_status.flags == 0)
+ return 0;
+
+ mtty = sc_get_mouse_tty();
+ if (mtty->t_state & TS_ISOPEN) {
+ u_char buf[MOUSE_SYS_PACKETSIZE];
+
+ /* the first five bytes are compatible with MouseSystems' */
+ buf[0] = MOUSE_MSC_SYNC
+ | butmap[mouse_status.button & MOUSE_STDBUTTONS];
+ i = imax(imin(mouse->u.data.x, 255), -256);
+ buf[1] = i >> 1;
+ buf[3] = i - buf[1];
+ i = -imax(imin(mouse->u.data.y, 255), -256);
+ buf[2] = i >> 1;
+ buf[4] = i - buf[2];
+ for (i = 0; i < MOUSE_MSC_PACKETSIZE; i++)
+ (*linesw[mtty->t_line].l_rint)(buf[i], mtty);
+ if (mouse_level >= 1) { /* extended part */
+ i = imax(imin(mouse->u.data.z, 127), -128);
+ buf[5] = (i >> 1) & 0x7f;
+ buf[6] = (i - (i >> 1)) & 0x7f;
+ /* buttons 4-10 */
+ buf[7] = (~mouse_status.button >> 3) & 0x7f;
+ for (i = MOUSE_MSC_PACKETSIZE;
+ i < MOUSE_SYS_PACKETSIZE; i++)
+ (*linesw[mtty->t_line].l_rint)(buf[i], mtty);
+ }
+ }
+
+ if (cur_scp->mouse_signal) {
+ cur_scp->mouse_buttons = mouse->u.data.buttons;
+ /* has controlling process died? */
+ if (cur_scp->mouse_proc &&
+ (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
+ cur_scp->mouse_signal = 0;
+ cur_scp->mouse_proc = NULL;
+ cur_scp->mouse_pid = 0;
+ }
+ else
+ psignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
+ break;
+ }
+
+ /*
+ * If any buttons are down or the mouse has moved a lot,
+ * stop the screen saver.
+ */
+ if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons)
+ || (mouse->u.data.x*mouse->u.data.x
+ + mouse->u.data.y*mouse->u.data.y
+ >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) {
+ sc_touch_scrn_saver();
+ }
+
+ if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
+ break;
+
+#ifndef SC_NO_CUTPASTE
+ if (cur_scp->sc->flags & SC_MOUSE_ENABLED)
+ cur_scp->status |= MOUSE_VISIBLE;
+
+ if (mouse->operation == MOUSE_ACTION) {
+ /* process button presses */
+ if (cur_scp->mouse_buttons ^ mouse->u.data.buttons) {
+ cur_scp->mouse_buttons = mouse->u.data.buttons;
+ if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)
+ mouse_cut_start(cur_scp);
+ else
+ mouse_cut_end(cur_scp);
+ if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN ||
+ cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN)
+ mouse_paste(cur_scp);
+ }
+ }
+#else /* SC_NO_CUTPASTE */
+ if (mouse->operation == MOUSE_ACTION)
+ cur_scp->mouse_buttons = mouse->u.data.buttons;
+#endif /* SC_NO_CUTPASTE */
+
+ if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
+ s = spltty();
+ cur_scp->mouse_xpos += mouse->u.data.x;
+ cur_scp->mouse_ypos += mouse->u.data.y;
+ set_mouse_pos(cur_scp);
+ splx(s);
+ }
+ break;
+
+ case MOUSE_BUTTON_EVENT:
+ if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
+ return EINVAL;
+ if (mouse->u.event.value < 0)
+ return EINVAL;
+#if 0
+ /* this should maybe only be settable from /dev/consolectl SOS */
+ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
+ return ENOTTY;
+#endif
+ if (mouse->u.event.value > 0) {
+ cur_scp->mouse_buttons |= mouse->u.event.id;
+ mouse_status.button |= mouse->u.event.id;
+ } else {
+ cur_scp->mouse_buttons &= ~mouse->u.event.id;
+ mouse_status.button &= ~mouse->u.event.id;
+ }
+ mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
+ if (mouse_status.flags == 0)
+ return 0;
+
+ mtty = sc_get_mouse_tty();
+ if (mtty->t_state & TS_ISOPEN) {
+ u_char buf[MOUSE_SYS_PACKETSIZE];
+
+ buf[0] = MOUSE_MSC_SYNC
+ | butmap[mouse_status.button & MOUSE_STDBUTTONS];
+ buf[7] = (~mouse_status.button >> 3) & 0x7f;
+ buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
+ for (i = 0;
+ i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
+ : MOUSE_MSC_PACKETSIZE); i++)
+ (*linesw[mtty->t_line].l_rint)(buf[i], mtty);
+ }
+
+ if (cur_scp->mouse_signal) {
+ if (cur_scp->mouse_proc &&
+ (cur_scp->mouse_proc != pfind(cur_scp->mouse_pid))){
+ cur_scp->mouse_signal = 0;
+ cur_scp->mouse_proc = NULL;
+ cur_scp->mouse_pid = 0;
+ }
+ else
+ psignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
+ break;
+ }
+
+ /* if a button is held down, stop the screen saver */
+ if (mouse->u.event.value > 0)
+ sc_touch_scrn_saver();
+
+ if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
+ break;
+
+#ifndef SC_NO_CUTPASTE
+ if (cur_scp->sc->flags & SC_MOUSE_ENABLED)
+ cur_scp->status |= MOUSE_VISIBLE;
+
+ switch (mouse->u.event.id) {
+ case MOUSE_BUTTON1DOWN:
+ switch (mouse->u.event.value % 4) {
+ case 0: /* up */
+ mouse_cut_end(cur_scp);
+ break;
+ case 1: /* single click: start cut operation */
+ mouse_cut_start(cur_scp);
+ break;
+ case 2: /* double click: cut a word */
+ mouse_cut_word(cur_scp);
+ mouse_cut_end(cur_scp);
+ break;
+ case 3: /* triple click: cut a line */
+ mouse_cut_line(cur_scp);
+ mouse_cut_end(cur_scp);
+ break;
+ }
+ break;
+ case MOUSE_BUTTON2DOWN:
+ switch (mouse->u.event.value) {
+ case 0: /* up */
+ break;
+ default:
+ mouse_paste(cur_scp);
+ break;
+ }
+ break;
+ case MOUSE_BUTTON3DOWN:
+ switch (mouse->u.event.value) {
+ case 0: /* up */
+ if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN))
+ mouse_cut_end(cur_scp);
+ break;
+ default:
+ mouse_cut_extend(cur_scp);
+ break;
+ }
+ break;
+ }
+#endif /* SC_NO_CUTPASTE */
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+ }
+
+ /* MOUSE_XXX: /dev/sysmouse ioctls */
+ case MOUSE_GETHWINFO: /* get device information */
+ {
+ mousehw_t *hw = (mousehw_t *)data;
+
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ hw->buttons = 10; /* XXX unknown */
+ hw->iftype = MOUSE_IF_SYSMOUSE;
+ hw->type = MOUSE_MOUSE;
+ hw->model = MOUSE_MODEL_GENERIC;
+ hw->hwid = 0;
+ return 0;
+ }
+
+ case MOUSE_GETMODE: /* get protocol/mode */
+ {
+ mousemode_t *mode = (mousemode_t *)data;
+
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ mode->level = mouse_level;
+ switch (mode->level) {
+ case 0:
+ /* at this level, sysmouse emulates MouseSystems protocol */
+ mode->protocol = MOUSE_PROTO_MSC;
+ mode->rate = -1; /* unknown */
+ mode->resolution = -1; /* unknown */
+ mode->accelfactor = 0; /* disabled */
+ mode->packetsize = MOUSE_MSC_PACKETSIZE;
+ mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
+ mode->syncmask[1] = MOUSE_MSC_SYNC;
+ break;
+
+ case 1:
+ /* at this level, sysmouse uses its own protocol */
+ mode->protocol = MOUSE_PROTO_SYSMOUSE;
+ mode->rate = -1;
+ mode->resolution = -1;
+ mode->accelfactor = 0;
+ mode->packetsize = MOUSE_SYS_PACKETSIZE;
+ mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
+ mode->syncmask[1] = MOUSE_SYS_SYNC;
+ break;
+ }
+ return 0;
+ }
+
+ case MOUSE_SETMODE: /* set protocol/mode */
+ {
+ mousemode_t *mode = (mousemode_t *)data;
+
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ if ((mode->level < 0) || (mode->level > 1))
+ return EINVAL;
+ sc_mouse_set_level(mode->level);
+ return 0;
+ }
+
+ case MOUSE_GETLEVEL: /* get operation level */
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ *(int *)data = mouse_level;
+ return 0;
+
+ case MOUSE_SETLEVEL: /* set operation level */
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ if ((*(int *)data < 0) || (*(int *)data > 1))
+ return EINVAL;
+ sc_mouse_set_level(*(int *)data);
+ return 0;
+
+ case MOUSE_GETSTATUS: /* get accumulated mouse events */
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ s = spltty();
+ *(mousestatus_t *)data = mouse_status;
+ mouse_status.flags = 0;
+ mouse_status.obutton = mouse_status.button;
+ mouse_status.dx = 0;
+ mouse_status.dy = 0;
+ mouse_status.dz = 0;
+ splx(s);
+ return 0;
+
+#if notyet
+ case MOUSE_GETVARS: /* get internal mouse variables */
+ case MOUSE_SETVARS: /* set internal mouse variables */
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ return ENODEV;
+#endif
+
+ case MOUSE_READSTATE: /* read status from the device */
+ case MOUSE_READDATA: /* read data from the device */
+ if (tp != sc_get_mouse_tty())
+ return ENOTTY;
+ return ENODEV;
+ }
+
+ return ENOIOCTL;
+}
+
+#endif /* SC_NO_SYSMOUSE */
+
+#endif /* NSC */
diff --git a/sys/dev/syscons/scvesactl.c b/sys/dev/syscons/scvesactl.c
index b71f071..114c5ec 100644
--- a/sys/dev/syscons/scvesactl.c
+++ b/sys/dev/syscons/scvesactl.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: scvesactl.c,v 1.9 1999/01/11 03:18:26 yokota Exp $
+ * $Id: scvesactl.c,v 1.10 1999/06/01 18:17:31 jlemon Exp $
*/
#include "sc.h"
@@ -44,7 +44,6 @@
#include <sys/tty.h>
#include <sys/kernel.h>
-#include <machine/apm_bios.h>
#include <machine/console.h>
#include <machine/pc/vesa.h>
@@ -71,7 +70,7 @@ vesa_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_TEXT_132x25: case SW_TEXT_132x30:
case SW_TEXT_132x43: case SW_TEXT_132x50:
case SW_TEXT_132x60:
- if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
+ if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
@@ -81,7 +80,7 @@ vesa_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_VESA_C132x43:
case SW_VESA_C132x50:
case SW_VESA_C132x60:
- if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
+ if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
mode = (cmd & 0xff) + M_VESA_BASE;
return sc_set_text_mode(scp, tp, mode, 0, 0, 0);
@@ -107,7 +106,7 @@ vesa_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_VESA_1280x1024: case SW_VESA_CG1280x1024:
case SW_VESA_32K_1280: case SW_VESA_64K_1280:
case SW_VESA_FULL_1280:
- if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
+ if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
mode = (cmd & 0xff) + M_VESA_BASE;
return sc_set_graphics_mode(scp, tp, mode);
diff --git a/sys/dev/syscons/scvgarndr.c b/sys/dev/syscons/scvgarndr.c
new file mode 100644
index 0000000..16c40e2
--- /dev/null
+++ b/sys/dev/syscons/scvgarndr.c
@@ -0,0 +1,829 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id:$
+ */
+
+#include "sc.h"
+#include "vga.h"
+#include "opt_syscons.h"
+#include "opt_vga.h"
+
+#if NSC > 0 && NVGA > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <machine/console.h>
+#include <machine/md_var.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/vgareg.h>
+#include <dev/syscons/syscons.h>
+
+#include <isa/isareg.h>
+
+#ifndef SC_MOUSE_CHAR
+#define SC_MOUSE_CHAR (0xd0)
+#endif
+
+#ifndef SC_RENDER_DEBUG
+#define SC_RENDER_DEBUG 0
+#endif
+
+static vr_clear_t vga_txtclear;
+static vr_draw_border_t vga_txtborder;
+static vr_draw_t vga_txtdraw;
+static vr_set_cursor_t vga_txtcursor_shape;
+static vr_draw_cursor_t vga_txtcursor;
+static vr_blink_cursor_t vga_txtblink;
+#ifndef SC_NO_CUTPASTE
+static vr_draw_mouse_t vga_txtmouse;
+#else
+#define vga_txtmouse (vr_draw_mouse_t *)vga_nop
+#endif
+
+#ifdef SC_PIXEL_MODE
+static vr_clear_t vga_pxlclear;
+static vr_draw_border_t vga_pxlborder;
+static vr_draw_t vga_egadraw;
+static vr_draw_t vga_vgadraw;
+static vr_set_cursor_t vga_pxlcursor_shape;
+static vr_draw_cursor_t vga_pxlcursor;
+static vr_blink_cursor_t vga_pxlblink;
+#ifndef SC_NO_CUTPASTE
+static vr_draw_mouse_t vga_pxlmouse;
+#else
+#define vga_pxlmouse (vr_draw_mouse_t *)vga_nop
+#endif
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+static vr_draw_border_t vga_grborder;
+#endif
+
+static void vga_nop(scr_stat *scp, ...);
+
+static sc_rndr_sw_t txtrndrsw = {
+ vga_txtclear,
+ vga_txtborder,
+ vga_txtdraw,
+ vga_txtcursor_shape,
+ vga_txtcursor,
+ vga_txtblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_txtmouse,
+};
+RENDERER(mda, 0, txtrndrsw);
+RENDERER(cga, 0, txtrndrsw);
+RENDERER(ega, 0, txtrndrsw);
+RENDERER(vga, 0, txtrndrsw);
+
+#ifdef SC_PIXEL_MODE
+static sc_rndr_sw_t egarndrsw = {
+ vga_pxlclear,
+ vga_pxlborder,
+ vga_egadraw,
+ vga_pxlcursor_shape,
+ vga_pxlcursor,
+ vga_pxlblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_pxlmouse,
+};
+RENDERER(ega, PIXEL_MODE, egarndrsw);
+
+static sc_rndr_sw_t vgarndrsw = {
+ vga_pxlclear,
+ vga_pxlborder,
+ vga_vgadraw,
+ vga_pxlcursor_shape,
+ vga_pxlcursor,
+ vga_pxlblink,
+ (vr_set_mouse_t *)vga_nop,
+ vga_pxlmouse,
+};
+RENDERER(vga, PIXEL_MODE, vgarndrsw);
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+static sc_rndr_sw_t grrndrsw = {
+ (vr_clear_t *)vga_nop,
+ vga_grborder,
+ (vr_draw_t *)vga_nop,
+ (vr_set_cursor_t *)vga_nop,
+ (vr_draw_cursor_t *)vga_nop,
+ (vr_blink_cursor_t *)vga_nop,
+ (vr_set_mouse_t *)vga_nop,
+ (vr_draw_mouse_t *)vga_nop,
+};
+RENDERER(cga, GRAPHICS_MODE, grrndrsw);
+RENDERER(ega, GRAPHICS_MODE, grrndrsw);
+RENDERER(vga, GRAPHICS_MODE, grrndrsw);
+#endif /* SC_NO_MODE_CHANGE */
+
+#ifndef SC_NO_CUTPASTE
+static u_short mouse_and_mask[16] = {
+ 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
+ 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
+};
+static u_short mouse_or_mask[16] = {
+ 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
+ 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
+};
+#endif
+
+static void
+vga_nop(scr_stat *scp, ...)
+{
+}
+
+/* text mode renderer */
+
+static void
+vga_txtclear(scr_stat *scp, int c, int attr)
+{
+ sc_vtb_clear(&scp->scr, c, attr);
+}
+
+static void
+vga_txtborder(scr_stat *scp, int color)
+{
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+}
+
+static void
+vga_txtdraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t p;
+ int c;
+ int a;
+
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+
+ if (flip) {
+ for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) {
+ c = sc_vtb_getc(&scp->vtb, from);
+ a = sc_vtb_geta(&scp->vtb, from);
+ a = (a & 0x8800) | ((a & 0x7000) >> 4)
+ | ((a & 0x0700) << 4);
+ p = sc_vtb_putchar(&scp->scr, p, c, a);
+ }
+ } else {
+ sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
+ }
+}
+
+static void
+vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
+{
+ if (base < 0 || base >= scp->font_size)
+ return;
+ /* the caller may set height <= 0 in order to disable the cursor */
+#if 0
+ scp->cursor_base = base;
+ scp->cursor_height = height;
+#endif
+ (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
+ base, height,
+ scp->font_size, blink);
+}
+
+static void
+vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
+{
+ video_adapter_t *adp;
+ int cursor_attr;
+
+ if (scp->cursor_height <= 0) /* the text cursor is disabled */
+ return;
+
+ adp = scp->sc->adp;
+ if (blink) {
+ scp->status |= VR_CURSOR_BLINK;
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp,
+ at%scp->xsize,
+ at/scp->xsize);
+ } else {
+ if (scp->status & VR_CURSOR_ON)
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp,
+ -1, -1);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ } else {
+ scp->status &= ~VR_CURSOR_BLINK;
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ cursor_attr = sc_vtb_geta(&scp->vtb, at);
+ scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
+ scp->cursor_saveunder_attr = cursor_attr;
+ if ((cursor_attr & 0x7000) == 0x7000) {
+ cursor_attr &= 0x8f00;
+ if ((cursor_attr & 0x0700) == 0)
+ cursor_attr |= 0x0700;
+ } else {
+ cursor_attr |= 0x7000;
+ if ((cursor_attr & 0x0700) == 0x0700)
+ cursor_attr &= 0xf000;
+ }
+ if (flip)
+ cursor_attr = (cursor_attr & 0x8800)
+ | ((cursor_attr & 0x7000) >> 4)
+ | ((cursor_attr & 0x0700) << 4);
+ sc_vtb_putc(&scp->scr, at,
+ sc_vtb_getc(&scp->scr, at),
+ cursor_attr);
+ } else {
+ cursor_attr = scp->cursor_saveunder_attr;
+ if (flip)
+ cursor_attr = (cursor_attr & 0x8800)
+ | ((cursor_attr & 0x7000) >> 4)
+ | ((cursor_attr & 0x0700) << 4);
+ if (scp->status & VR_CURSOR_ON)
+ sc_vtb_putc(&scp->scr, at,
+ scp->cursor_saveunder_char,
+ cursor_attr);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ }
+}
+
+static void
+vga_txtblink(scr_stat *scp, int at, int flip)
+{
+}
+
+#ifndef SC_NO_CUTPASTE
+
+static void
+draw_txtmouse(scr_stat *scp, int x, int y)
+{
+#ifndef SC_ALT_MOUSE_IMAGE
+ u_char font_buf[128];
+ u_short cursor[32];
+ int pos;
+ int xoffset, yoffset;
+ int crtc_addr;
+ int i;
+
+ /* prepare mousepointer char's bitmaps */
+ pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+ bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos)*scp->font_size,
+ &font_buf[0], scp->font_size);
+ bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos + 1)*scp->font_size,
+ &font_buf[32], scp->font_size);
+ bcopy(scp->font
+ + sc_vtb_getc(&scp->vtb, pos + scp->xsize)*scp->font_size,
+ &font_buf[64], scp->font_size);
+ bcopy(scp->font
+ + sc_vtb_getc(&scp->vtb, pos + scp->xsize + 1)*scp->font_size,
+ &font_buf[96], scp->font_size);
+ for (i = 0; i < scp->font_size; ++i) {
+ cursor[i] = font_buf[i]<<8 | font_buf[i+32];
+ cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
+ }
+
+ /* now and-or in the mousepointer image */
+ xoffset = x%8;
+ yoffset = y%scp->font_size;
+ for (i = 0; i < 16; ++i) {
+ cursor[i + yoffset] =
+ (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
+ | (mouse_or_mask[i] >> xoffset);
+ }
+ for (i = 0; i < scp->font_size; ++i) {
+ font_buf[i] = (cursor[i] & 0xff00) >> 8;
+ font_buf[i + 32] = cursor[i] & 0xff;
+ font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
+ font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
+ }
+
+#if 1
+ /* wait for vertical retrace to avoid jitter on some videocards */
+ crtc_addr = scp->sc->adp->va_crtc_addr;
+ while (!(inb(crtc_addr + 6) & 0x08)) /* idle */ ;
+#endif
+ (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
+ SC_MOUSE_CHAR, 4);
+
+ sc_vtb_putc(&scp->scr, pos, SC_MOUSE_CHAR, sc_vtb_geta(&scp->scr, pos));
+ /* FIXME: may be out of range! */
+ sc_vtb_putc(&scp->scr, pos + scp->xsize, SC_MOUSE_CHAR + 2,
+ sc_vtb_geta(&scp->scr, pos + scp->xsize));
+ if (x < (scp->xsize - 1)*8) {
+ sc_vtb_putc(&scp->scr, pos + 1, SC_MOUSE_CHAR + 1,
+ sc_vtb_geta(&scp->scr, pos + 1));
+ sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, SC_MOUSE_CHAR + 3,
+ sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
+ }
+#else /* SC_ALT_MOUSE_IMAGE */
+ /* Red, magenta and brown are mapped to green to to keep it readable */
+ static const int col_conv[16] = {
+ 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
+ };
+ int pos;
+ int color;
+ int a;
+
+ pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+ a = sc_vtb_geta(&scp->scr, pos);
+ if (scp->sc->adp->va_flags & V_ADP_COLOR)
+ color = (col_conv[(a & 0xf000) >> 12] << 12)
+ | ((a & 0x0f00) | 0x0800);
+ else
+ color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
+ sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
+#endif /* SC_ALT_MOUSE_IMAGE */
+}
+
+static void
+remove_txtmouse(scr_stat *scp, int x, int y)
+{
+}
+
+static void
+vga_txtmouse(scr_stat *scp, int x, int y, int on)
+{
+ if (on)
+ draw_txtmouse(scp, x, y);
+ else
+ remove_txtmouse(scp, x, y);
+}
+
+#endif /* SC_NO_CUTPASTE */
+
+#ifdef SC_PIXEL_MODE
+
+/* pixel (raster text) mode renderer */
+
+static void
+vga_pxlclear(scr_stat *scp, int c, int attr)
+{
+ vm_offset_t p;
+ int line_width;
+ int lines;
+ int i;
+
+ /* XXX: we are just filling the screen with the background color... */
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, ((attr & 0xf000) >> 4) | 0x00); /* set/reset */
+ line_width = scp->sc->adp->va_line_width;
+ lines = scp->ysize*scp->font_size;
+ p = scp->sc->adp->va_window + line_width*scp->yoff*scp->font_size
+ + scp->xoff;
+ for (i = 0; i < lines; ++i) {
+ bzero_io((void *)p, scp->xsize);
+ p += line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlborder(scr_stat *scp, int color)
+{
+ vm_offset_t p;
+ int line_width;
+ int i;
+
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
+ line_width = scp->sc->adp->va_line_width;
+ p = scp->sc->adp->va_window;
+ if (scp->yoff > 0) {
+ bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
+ bzero_io((void *)(p + line_width*(scp->yoff + scp->ysize)
+ *scp->font_size),
+ line_width*(scp->ypixel
+ - (scp->yoff + scp->ysize)*scp->font_size));
+ }
+ if (scp->xoff > 0) {
+ for (i = 0; i < scp->ysize*scp->font_size; ++i) {
+ bzero_io((void *)(p + line_width
+ *(scp->yoff*scp->font_size + i)),
+ scp->xoff);
+ bzero_io((void *)(p + line_width
+ *(scp->yoff*scp->font_size + i)
+ + scp->xoff + scp->xsize),
+ scp->xpixel/8 - scp->xoff - scp->xsize);
+ }
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_egadraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t d;
+ vm_offset_t e;
+ u_char *f;
+ u_short bg;
+ u_short col1, col2;
+ int line_width;
+ int i, j;
+ int a;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (from%scp->xsize)
+ + scp->font_size*line_width*(from/scp->xsize);
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ bg = -1;
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+ for (i = from; count-- > 0; ++i) {
+ a = sc_vtb_geta(&scp->vtb, i);
+ if (flip) {
+ col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
+ col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
+ } else {
+ col1 = (a & 0x0f00);
+ col2 = (a & 0xf000) >> 4;
+ }
+ /* set background color in EGA/VGA latch */
+ if (bg != col2) {
+ bg = col2;
+ outw(GDCIDX, bg | 0x00); /* set/reset */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ }
+ /* foreground color */
+ outw(GDCIDX, col1 | 0x00); /* set/reset */
+ e = d;
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
+ for (j = 0; j < scp->font_size; ++j, ++f) {
+ outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
+ writeb(e, 0);
+ e += line_width;
+ }
+ ++d;
+ if ((i % scp->xsize) == scp->xsize - 1)
+ d += scp->xoff*2
+ + (scp->font_size - 1)*line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+}
+
+static void
+vga_vgadraw(scr_stat *scp, int from, int count, int flip)
+{
+ vm_offset_t d;
+ vm_offset_t e;
+ u_char *f;
+ u_short bg;
+ u_short col1, col2;
+ int line_width;
+ int i, j;
+ int a;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (from%scp->xsize)
+ + scp->font_size*line_width*(from/scp->xsize);
+
+ outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ bg = -1;
+ if (from + count > scp->xsize*scp->ysize)
+ count = scp->xsize*scp->ysize - from;
+ for (i = from; count-- > 0; ++i) {
+ a = sc_vtb_geta(&scp->vtb, i);
+ if (flip) {
+ col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
+ col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
+ } else {
+ col1 = (a & 0x0f00);
+ col2 = (a & 0xf000) >> 4;
+ }
+ /* set background color in EGA/VGA latch */
+ if (bg != col2) {
+ bg = col2;
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, bg | 0x00); /* set/reset */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
+ }
+ /* foreground color */
+ outw(GDCIDX, col1 | 0x00); /* set/reset */
+ e = d;
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
+ for (j = 0; j < scp->font_size; ++j, ++f) {
+ writeb(e, *f);
+ e += line_width;
+ }
+ ++d;
+ if ((i % scp->xsize) == scp->xsize - 1)
+ d += scp->xoff*2
+ + (scp->font_size - 1)*line_width;
+ }
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
+{
+ if (base < 0 || base >= scp->font_size)
+ return;
+ /* the caller may set height <= 0 in order to disable the cursor */
+#if 0
+ scp->cursor_base = base;
+ scp->cursor_height = height;
+#endif
+}
+
+static void
+draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
+{
+ vm_offset_t d;
+ u_char *f;
+ int line_width;
+ int height;
+ int col;
+ int a;
+ int i;
+ u_char c;
+
+ line_width = scp->sc->adp->va_line_width;
+ d = scp->sc->adp->va_window
+ + scp->xoff
+ + scp->yoff*scp->font_size*line_width
+ + (at%scp->xsize)
+ + scp->font_size*line_width*(at/scp->xsize)
+ + (scp->font_size - scp->cursor_base - 1)*line_width;
+
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ /* set background color in EGA/VGA latch */
+ a = sc_vtb_geta(&scp->vtb, at);
+ if (flip)
+ col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
+ else
+ col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
+ outw(GDCIDX, col | 0x00); /* set/reset */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ writeb(d, 0);
+ c = readb(d); /* set bg color in the latch */
+ /* foreground color */
+ if (flip)
+ col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
+ else
+ col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
+ outw(GDCIDX, col | 0x00); /* set/reset */
+ f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
+ + scp->font_size - scp->cursor_base - 1]);
+ height = imin(scp->cursor_height, scp->font_size);
+ for (i = 0; i < height; ++i, --f) {
+ outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
+ writeb(d, 0);
+ d -= line_width;
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+}
+
+static void
+vga_pxlcursor(scr_stat *scp, int at, int blink, int on, int flip)
+{
+ if (scp->cursor_height <= 0) /* the text cursor is disabled */
+ return;
+
+ if (on) {
+ scp->status |= VR_CURSOR_ON;
+ draw_pxlcursor(scp, at, on, flip);
+ } else {
+ if (scp->status & VR_CURSOR_ON)
+ draw_pxlcursor(scp, at, on, flip);
+ scp->status &= ~VR_CURSOR_ON;
+ }
+ if (blink)
+ scp->status |= VR_CURSOR_BLINK;
+ else
+ scp->status &= ~VR_CURSOR_BLINK;
+}
+
+static void
+vga_pxlblink(scr_stat *scp, int at, int flip)
+{
+ static int blinkrate = 0;
+
+ if (!(scp->status & VR_CURSOR_BLINK))
+ return;
+ if (!(++blinkrate & 4))
+ return;
+ blinkrate = 0;
+ scp->status ^= VR_CURSOR_ON;
+ draw_pxlcursor(scp, at, scp->status & VR_CURSOR_ON, flip);
+}
+
+#ifndef SC_NO_CUTPASTE
+
+static void
+draw_pxlmouse(scr_stat *scp, int x, int y)
+{
+ vm_offset_t p;
+ int line_width;
+ int xoff, yoff;
+ int ymax;
+ u_short m;
+ int i, j;
+
+ line_width = scp->sc->adp->va_line_width;
+ xoff = (x - scp->xoff*8)%8;
+ yoff = y - (y/line_width)*line_width;
+ ymax = imin(y + 16, scp->ypixel);
+
+ outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+ outw(GDCIDX, 0x0002); /* color compare */
+ outw(GDCIDX, 0x0007); /* color don't care */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
+ p = scp->sc->adp->va_window + line_width*y + x/8;
+ if (x < scp->xpixel - 16) {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = ~(mouse_and_mask[j] >> xoff);
+#ifdef __i386__
+ *(u_char *)p &= m >> 8;
+ *(u_char *)(p + 1) &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+ writeb(p + 1, readb(p + 1) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ } else {
+ xoff += 8;
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = ~(mouse_and_mask[j] >> xoff);
+#ifdef __i386__
+ *(u_char *)p &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
+ p = scp->sc->adp->va_window + line_width*y + x/8;
+ if (x < scp->xpixel - 16) {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = mouse_or_mask[j] >> xoff;
+#ifdef __i386__
+ *(u_char *)p &= m >> 8;
+ *(u_char *)(p + 1) &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+ writeb(p + 1, readb(p + 1) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ } else {
+ for (i = y, j = 0; i < ymax; ++i, ++j) {
+ m = mouse_or_mask[j] >> xoff;
+#ifdef __i386__
+ *(u_char *)p &= m;
+#elif defined(__alpha__)
+ writeb(p, readb(p) & (m >> 8));
+#endif
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+}
+
+static void
+remove_pxlmouse(scr_stat *scp, int x, int y)
+{
+ vm_offset_t p;
+ int col, row;
+ int pos;
+ int line_width;
+ int ymax;
+ int i;
+
+ /* erase the mouse cursor image */
+ col = x/8 - scp->xoff;
+ row = y/scp->font_size - scp->yoff;
+ pos = row*scp->xsize + col;
+ i = (col < scp->xsize - 1) ? 2 : 1;
+ (*scp->rndr->draw)(scp, pos, i, FALSE);
+ if (row < scp->ysize - 1)
+ (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
+
+ /* paint border if necessary */
+ line_width = scp->sc->adp->va_line_width;
+ outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
+ outw(GDCIDX, 0x0003); /* data rotate/function select */
+ outw(GDCIDX, 0x0f01); /* set/reset enable */
+ outw(GDCIDX, 0xff08); /* bit mask */
+ outw(GDCIDX, (scp->border << 8) | 0x00); /* set/reset */
+ if (row == scp->ysize - 1) {
+ i = (scp->ysize + scp->yoff)*scp->font_size;
+ ymax = imin(i + scp->font_size, scp->ypixel);
+ p = scp->sc->adp->va_window + i*line_width + scp->xoff + col;
+ if (col < scp->xsize - 1) {
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ writeb(p + 1, 0);
+ p += line_width;
+ }
+ } else {
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ p += line_width;
+ }
+ }
+ }
+ if ((col == scp->xsize - 1) && (scp->xoff > 0)) {
+ i = (row + scp->yoff)*scp->font_size;
+ ymax = imin(i + scp->font_size*2, scp->ypixel);
+ p = scp->sc->adp->va_window + i*line_width
+ + scp->xoff + scp->xsize;
+ for (; i < ymax; ++i) {
+ writeb(p, 0);
+ p += line_width;
+ }
+ }
+ outw(GDCIDX, 0x0000); /* set/reset */
+ outw(GDCIDX, 0x0001); /* set/reset enable */
+}
+
+static void
+vga_pxlmouse(scr_stat *scp, int x, int y, int on)
+{
+ if (on)
+ draw_pxlmouse(scp, x, y);
+ else
+ remove_pxlmouse(scp, x, y);
+}
+
+#endif /* SC_NO_CUTPASTE */
+#endif /* SC_PIXEL_MODE */
+
+#ifndef SC_NO_MODE_CHANGE
+
+/* graphics mode renderer */
+
+static void
+vga_grborder(scr_stat *scp, int color)
+{
+ (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+}
+
+#endif
+
+#endif /* NSC > 0 && NVGA > 0 */
diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c
index 732f386c..f84b14d 100644
--- a/sys/dev/syscons/scvidctl.c
+++ b/sys/dev/syscons/scvidctl.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: scvidctl.c,v 1.7 1999/01/19 11:31:16 yokota Exp $
+ * $Id: $
*/
#include "sc.h"
@@ -37,19 +37,21 @@
#include <sys/tty.h>
#include <sys/kernel.h>
-#ifdef __i386__
-#include <machine/apm_bios.h>
-#endif
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
#include <machine/console.h>
#include <dev/fb/fbreg.h>
#include <dev/syscons/syscons.h>
/* for compatibility with previous versions */
+/* 3.0-RELEASE used the following structure */
typedef struct old_video_adapter {
int va_index;
int va_type;
int va_flags;
+/* flag bits are the same as the -CURRENT
#define V_ADP_COLOR (1<<0)
#define V_ADP_MODECHANGE (1<<1)
#define V_ADP_STATESAVE (1<<2)
@@ -58,6 +60,7 @@ typedef struct old_video_adapter {
#define V_ADP_PALETTE (1<<5)
#define V_ADP_BORDER (1<<6)
#define V_ADP_VESA (1<<7)
+*/
int va_crtc_addr;
u_int va_window; /* virtual address */
size_t va_window_size;
@@ -71,39 +74,100 @@ typedef struct old_video_adapter {
#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t)
-/* variables */
-extern scr_stat *cur_console;
-extern int fonts_loaded;
-extern int sc_history_size;
-extern u_char palette[];
+/* 3.1-RELEASE used the following structure */
+typedef struct old_video_adapter_info {
+ int va_index;
+ int va_type;
+ char va_name[16];
+ int va_unit;
+ int va_flags;
+ int va_io_base;
+ int va_io_size;
+ int va_crtc_addr;
+ int va_mem_base;
+ int va_mem_size;
+ u_int va_window; /* virtual address */
+ size_t va_window_size;
+ size_t va_window_gran;
+ u_int va_buffer;;
+ size_t va_buffer_size;
+ int va_initial_mode;
+ int va_initial_bios_mode;
+ int va_mode;
+ int va_line_width;
+} old_video_adapter_info_t;
+
+#define OLD_CONS_ADPINFO2 _IOWR('c', 101, old_video_adapter_info_t)
+
+/* 3.0-RELEASE and 3.1-RELEASE used the following structure */
+typedef struct old_video_info {
+ int vi_mode;
+ int vi_flags;
+/* flag bits are the same as the -CURRENT
+#define V_INFO_COLOR (1<<0)
+#define V_INFO_GRAPHICS (1<<1)
+#define V_INFO_LINEAR (1<<2)
+#define V_INFO_VESA (1<<3)
+*/
+ int vi_width;
+ int vi_height;
+ int vi_cwidth;
+ int vi_cheight;
+ int vi_depth;
+ int vi_planes;
+ u_int vi_window; /* physical address */
+ size_t vi_window_size;
+ size_t vi_window_gran;
+ u_int vi_buffer; /* physical address */
+ size_t vi_buffer_size;
+} old_video_info_t;
+
+#define OLD_CONS_MODEINFO _IOWR('c', 102, old_video_info_t)
+#define OLD_CONS_FINDMODE _IOWR('c', 103, old_video_info_t)
int
sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
int fontsize)
{
video_info_t info;
+ sc_rndr_sw_t *rndr;
+ u_char *font;
int error;
int s;
- int i;
- if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info))
+ if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
return ENODEV;
-
+
/* adjust argument values */
if (fontsize <= 0)
fontsize = info.vi_cheight;
if (fontsize < 14) {
fontsize = 8;
- if (!(fonts_loaded & FONT_8))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_8))
return EINVAL;
+ font = scp->sc->font_8;
+#else
+ font = NULL;
+#endif
} else if (fontsize >= 16) {
fontsize = 16;
- if (!(fonts_loaded & FONT_16))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_16))
return EINVAL;
+ font = scp->sc->font_16;
+#else
+ font = NULL;
+#endif
} else {
fontsize = 14;
- if (!(fonts_loaded & FONT_14))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_14))
return EINVAL;
+ font = scp->sc->font_14;
+#else
+ font = NULL;
+#endif
}
if ((xsize <= 0) || (xsize > info.vi_width))
xsize = info.vi_width;
@@ -117,12 +181,13 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
return error;
}
+ rndr = sc_render_match(scp, scp->sc->adp, 0);
+ if (rndr == NULL) {
+ splx(s);
+ return ENODEV;
+ }
+
/* set up scp */
- if (scp->history != NULL)
- i = imax(scp->history_size / scp->xsize
- - imax(sc_history_size, scp->ysize), 0);
- else
- i = 0;
/*
* This is a kludge to fend off scrn_update() while we
* muck around with scp. XXX
@@ -130,22 +195,27 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
scp->status |= UNKNOWN_MODE;
scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
scp->mode = mode;
- scp->font_size = fontsize;
scp->xsize = xsize;
scp->ysize = ysize;
scp->xoff = 0;
scp->yoff = 0;
scp->xpixel = scp->xsize*8;
scp->ypixel = scp->ysize*fontsize;
+ scp->font = font;
+ scp->font_size = fontsize;
/* allocate buffers */
sc_alloc_scr_buffer(scp, TRUE, TRUE);
- if (ISMOUSEAVAIL(scp->adp->va_flags))
- sc_alloc_cut_buffer(scp, FALSE);
- sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+#ifndef SC_NO_CUTPASTE
+ sc_alloc_cut_buffer(scp, FALSE);
+#endif
+#ifndef SC_NO_HISTORY
+ sc_alloc_history_buffer(scp, 0, FALSE);
+#endif
+ scp->rndr = rndr;
splx(s);
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_mode(scp);
scp->status &= ~UNKNOWN_MODE;
@@ -164,11 +234,15 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
int
sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
{
+#ifdef SC_NO_MODE_CHANGE
+ return ENODEV;
+#else
video_info_t info;
+ sc_rndr_sw_t *rndr;
int error;
int s;
- if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info))
+ if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
return ENODEV;
/* stop screen saver, etc */
@@ -178,22 +252,32 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
return error;
}
+ rndr = sc_render_match(scp, scp->sc->adp, GRAPHICS_MODE);
+ if (rndr == NULL) {
+ splx(s);
+ return ENODEV;
+ }
+
/* set up scp */
scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE);
scp->status &= ~PIXEL_MODE;
scp->mode = mode;
+ scp->xsize = info.vi_width/8;
+ scp->ysize = info.vi_height/info.vi_cheight;
scp->xoff = 0;
scp->yoff = 0;
scp->xpixel = info.vi_width;
scp->ypixel = info.vi_height;
- scp->xsize = info.vi_width/8;
- scp->ysize = info.vi_height/info.vi_cheight;
+ scp->font = NULL;
scp->font_size = FONT_NONE;
+#ifndef SC_NO_SYSMOUSE
/* move the mouse cursor at the center of the screen */
- sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
+ sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
+#endif
+ scp->rndr = rndr;
splx(s);
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_mode(scp);
/* clear_graphics();*/
scp->status &= ~UNKNOWN_MODE;
@@ -208,18 +292,23 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
}
return 0;
+#endif /* SC_NO_MODE_CHANGE */
}
int
sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
int fontsize)
{
+#ifndef SC_PIXEL_MODE
+ return ENODEV;
+#else
video_info_t info;
+ sc_rndr_sw_t *rndr;
+ u_char *font;
int error;
int s;
- int i;
- if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info))
+ if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info))
return ENODEV; /* this shouldn't happen */
#ifdef SC_VIDEO_DEBUG
@@ -234,16 +323,31 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
fontsize = info.vi_cheight;
if (fontsize < 14) {
fontsize = 8;
- if (!(fonts_loaded & FONT_8))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_8))
return EINVAL;
+ font = scp->sc->font_8;
+#else
+ font = NULL;
+#endif
} else if (fontsize >= 16) {
fontsize = 16;
- if (!(fonts_loaded & FONT_16))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_16))
return EINVAL;
+ font = scp->sc->font_16;
+#else
+ font = NULL;
+#endif
} else {
fontsize = 14;
- if (!(fonts_loaded & FONT_14))
+#ifndef SC_NO_FONT_LOADING
+ if (!(scp->sc->fonts_loaded & FONT_14))
return EINVAL;
+ font = scp->sc->font_14;
+#else
+ font = NULL;
+#endif
}
if (xsize <= 0)
xsize = info.vi_width/8;
@@ -254,8 +358,8 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
if (scp->scr_buf != NULL) {
printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
scp->mode, xsize, ysize, fontsize);
- printf("set_pixel_mode(): window:%x, %dx%d, xoff:%d, yoff:%d\n",
- scp->adp->va_window, info.vi_width, info.vi_height,
+ printf("set_pixel_mode(): window:%p, %dx%d, xoff:%d, yoff:%d\n",
+ (void *)scp->sc->adp->va_window, info.vi_width, info.vi_height,
(info.vi_width/8 - xsize)/2,
(info.vi_height/fontsize - ysize)/2);
}
@@ -283,29 +387,37 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
return error;
}
+ rndr = sc_render_match(scp, scp->sc->adp, PIXEL_MODE);
+ if (rndr == NULL) {
+ splx(s);
+ return ENODEV;
+ }
+
/* set up scp */
- if (scp->history != NULL)
- i = imax(scp->history_size / scp->xsize
- - imax(sc_history_size, scp->ysize), 0);
- else
- i = 0;
scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
- scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED);
+ scp->status &= ~GRAPHICS_MODE;
scp->xsize = xsize;
scp->ysize = ysize;
- scp->font_size = fontsize;
scp->xoff = (scp->xpixel/8 - xsize)/2;
scp->yoff = (scp->ypixel/fontsize - ysize)/2;
+ scp->font = font;
+ scp->font_size = fontsize;
/* allocate buffers */
sc_alloc_scr_buffer(scp, TRUE, TRUE);
- if (ISMOUSEAVAIL(scp->adp->va_flags))
- sc_alloc_cut_buffer(scp, FALSE);
- sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+#ifndef SC_NO_CUTPASTE
+ sc_alloc_cut_buffer(scp, FALSE);
+#endif
+#ifndef SC_NO_HISTORY
+ sc_alloc_history_buffer(scp, 0, FALSE);
+#endif
+ scp->rndr = rndr;
splx(s);
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp) {
set_border(scp, scp->border);
+ sc_set_cursor_image(scp);
+ }
scp->status &= ~UNKNOWN_MODE;
@@ -323,99 +435,182 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
}
return 0;
+#endif /* SC_PIXEL_MODE */
+}
+
+sc_rndr_sw_t
+*sc_render_match(scr_stat *scp, video_adapter_t *adp, int mode)
+{
+ const sc_renderer_t **list;
+ const sc_renderer_t *p;
+
+ list = (const sc_renderer_t **)scrndr_set.ls_items;
+ while ((p = *list++) != NULL) {
+ if ((strcmp(p->name, adp->va_name) == 0)
+ && (mode == p->mode)) {
+ scp->status &= ~(VR_CURSOR_ON | VR_CURSOR_BLINK);
+ return p->rndrsw;
+ }
+ }
+
+ return NULL;
}
+#define fb_ioctl(a, c, d) \
+ (((a) == NULL) ? ENODEV : \
+ (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d)))
+
int
sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
{
scr_stat *scp;
+ video_adapter_t *adp;
+ video_info_t info;
+ video_adapter_info_t adp_info;
int error;
int s;
scp = sc_get_scr_stat(tp->t_dev);
+ if (scp == NULL) /* tp == SC_MOUSE */
+ return ENOIOCTL;
+ adp = scp->sc->adp;
+ if (adp == NULL) /* shouldn't happen??? */
+ return ENODEV;
switch (cmd) {
- case CONS_CURRENT: /* get current adapter type */
- if (scp->adp == NULL)
- return ENODEV;
- *(int *)data = scp->adp->va_type;
- return 0;
-
case CONS_CURRENTADP: /* get current adapter index */
- *(int *)data = scp->ad;
- return 0;
+ case FBIO_ADAPTER:
+ return fb_ioctl(adp, FBIO_ADAPTER, data);
- case OLD_CONS_ADPINFO: /* adapter information */
- if (scp->adp == NULL)
- return ENODEV;
- ((old_video_adapter_t *)data)->va_index = scp->adp->va_index;
- ((old_video_adapter_t *)data)->va_type = scp->adp->va_type;
- ((old_video_adapter_t *)data)->va_flags = scp->adp->va_flags;
- ((old_video_adapter_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr;
- ((old_video_adapter_t *)data)->va_window = scp->adp->va_window;
- ((old_video_adapter_t *)data)->va_window_size
- = scp->adp->va_window_size;
- ((old_video_adapter_t *)data)->va_window_gran
- = scp->adp->va_window_gran;
- ((old_video_adapter_t *)data)->va_buffer = scp->adp->va_buffer;
- ((old_video_adapter_t *)data)->va_buffer_size
- = scp->adp->va_buffer_size;
- ((old_video_adapter_t *)data)->va_mode = scp->adp->va_mode;
- ((old_video_adapter_t *)data)->va_initial_mode
- = scp->adp->va_initial_mode;
+ case CONS_CURRENT: /* get current adapter type */
+ case FBIO_ADPTYPE:
+ return fb_ioctl(adp, FBIO_ADPTYPE, data);
+
+ case OLD_CONS_ADPINFO: /* adapter information (old interface) */
+ if (((old_video_adapter_t *)data)->va_index >= 0) {
+ adp = vid_get_adapter(((old_video_adapter_t *)data)->va_index);
+ if (adp == NULL)
+ return ENODEV;
+ }
+ ((old_video_adapter_t *)data)->va_index = adp->va_index;
+ ((old_video_adapter_t *)data)->va_type = adp->va_type;
+ ((old_video_adapter_t *)data)->va_flags = adp->va_flags;
+ ((old_video_adapter_t *)data)->va_crtc_addr = adp->va_crtc_addr;
+ ((old_video_adapter_t *)data)->va_window = adp->va_window;
+ ((old_video_adapter_t *)data)->va_window_size = adp->va_window_size;
+ ((old_video_adapter_t *)data)->va_window_gran = adp->va_window_gran;
+ ((old_video_adapter_t *)data)->va_buffer = adp->va_buffer;
+ ((old_video_adapter_t *)data)->va_buffer_size = adp->va_buffer_size;
+ ((old_video_adapter_t *)data)->va_mode = adp->va_mode;
+ ((old_video_adapter_t *)data)->va_initial_mode = adp->va_initial_mode;
((old_video_adapter_t *)data)->va_initial_bios_mode
- = scp->adp->va_initial_bios_mode;
+ = adp->va_initial_bios_mode;
return 0;
+ case OLD_CONS_ADPINFO2: /* adapter information (yet another old I/F) */
+ adp_info.va_index = ((old_video_adapter_info_t *)data)->va_index;
+ if (adp_info.va_index >= 0) {
+ adp = vid_get_adapter(adp_info.va_index);
+ if (adp == NULL)
+ return ENODEV;
+ }
+ error = fb_ioctl(adp, FBIO_ADPINFO, &adp_info);
+ if (error == 0)
+ bcopy(&adp_info, data, sizeof(old_video_adapter_info_t));
+ return error;
+
case CONS_ADPINFO: /* adapter information */
- if (scp->adp == NULL)
- return ENODEV;
- ((video_adapter_info_t *)data)->va_index = scp->adp->va_index;
- ((video_adapter_info_t *)data)->va_type = scp->adp->va_type;
- bcopy(scp->adp->va_name, ((video_adapter_info_t *)data)->va_name,
- imin(strlen(scp->adp->va_name) + 1,
- sizeof(((video_adapter_info_t *)data)->va_name)));
- ((video_adapter_info_t *)data)->va_unit = scp->adp->va_unit;
- ((video_adapter_info_t *)data)->va_flags = scp->adp->va_flags;
- ((video_adapter_info_t *)data)->va_io_base = scp->adp->va_io_base;
- ((video_adapter_info_t *)data)->va_io_size = scp->adp->va_io_size;
- ((video_adapter_info_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr;
- ((video_adapter_info_t *)data)->va_mem_base = scp->adp->va_mem_base;
- ((video_adapter_info_t *)data)->va_mem_size = scp->adp->va_mem_size;
- ((video_adapter_info_t *)data)->va_window = scp->adp->va_window;
- ((video_adapter_info_t *)data)->va_window_size
- = scp->adp->va_window_size;
- ((video_adapter_info_t *)data)->va_window_gran
- = scp->adp->va_window_gran;
- ((video_adapter_info_t *)data)->va_buffer = scp->adp->va_buffer;
- ((video_adapter_info_t *)data)->va_buffer_size
- = scp->adp->va_buffer_size;
- ((video_adapter_info_t *)data)->va_mode = scp->adp->va_mode;
- ((video_adapter_info_t *)data)->va_initial_mode
- = scp->adp->va_initial_mode;
- ((video_adapter_info_t *)data)->va_initial_bios_mode
- = scp->adp->va_initial_bios_mode;
- ((video_adapter_info_t *)data)->va_line_width = scp->adp->va_line_width;
- return 0;
+ case FBIO_ADPINFO:
+ if (((video_adapter_info_t *)data)->va_index >= 0) {
+ adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index);
+ if (adp == NULL)
+ return ENODEV;
+ }
+ return fb_ioctl(adp, FBIO_ADPINFO, data);
case CONS_GET: /* get current video mode */
+ case FBIO_GETMODE:
*(int *)data = scp->mode;
return 0;
+#ifndef SC_NO_MODE_CHANGE
+ case FBIO_SETMODE: /* set video mode */
+ if (!(adp->va_flags & V_ADP_MODECHANGE))
+ return ENODEV;
+ info.vi_mode = *(int *)data;
+ error = fb_ioctl(adp, FBIO_MODEINFO, &info);
+ if (error)
+ return error;
+ if (info.vi_flags & V_INFO_GRAPHICS)
+ return sc_set_graphics_mode(scp, tp, *(int *)data);
+ else
+ return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0);
+#endif /* SC_NO_MODE_CHANGE */
+
+ case OLD_CONS_MODEINFO: /* get mode information (old infterface) */
+ info.vi_mode = ((old_video_info_t *)data)->vi_mode;
+ error = fb_ioctl(adp, FBIO_MODEINFO, &info);
+ if (error == 0)
+ bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
+ return error;
+
case CONS_MODEINFO: /* get mode information */
- return ((*vidsw[scp->ad]->get_info)(scp->adp,
- ((video_info_t *)data)->vi_mode, (video_info_t *)data)
- ? ENODEV : 0);
+ case FBIO_MODEINFO:
+ return fb_ioctl(adp, FBIO_MODEINFO, data);
+
+ case OLD_CONS_FINDMODE: /* find a matching video mode (old interface) */
+ bzero(&info, sizeof(info));
+ bcopy((old_video_info_t *)data, &info, sizeof(old_video_info_t));
+ error = fb_ioctl(adp, FBIO_FINDMODE, &info);
+ if (error == 0)
+ bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
+ return error;
case CONS_FINDMODE: /* find a matching video mode */
- return ((*vidsw[scp->ad]->query_mode)(scp->adp, (video_info_t *)data)
- ? ENODEV : 0);
-
- case CONS_SETWINORG:
- return ((*vidsw[scp->ad]->set_win_org)(scp->adp, *(u_int *)data)
- ? ENODEV : 0);
+ case FBIO_FINDMODE:
+ return fb_ioctl(adp, FBIO_FINDMODE, data);
+
+ case CONS_SETWINORG: /* set frame buffer window origin */
+ case FBIO_SETWINORG:
+ if (scp != scp->sc->cur_scp)
+ return ENODEV; /* XXX */
+ return fb_ioctl(adp, FBIO_SETWINORG, data);
+
+ case FBIO_GETWINORG: /* get frame buffer window origin */
+ if (scp != scp->sc->cur_scp)
+ return ENODEV; /* XXX */
+ return fb_ioctl(adp, FBIO_GETWINORG, data);
+
+ case FBIO_GETDISPSTART:
+ case FBIO_SETDISPSTART:
+ case FBIO_GETLINEWIDTH:
+ case FBIO_SETLINEWIDTH:
+ if (scp != scp->sc->cur_scp)
+ return ENODEV; /* XXX */
+ return fb_ioctl(adp, cmd, data);
+
+ /* XXX */
+ case FBIO_GETPALETTE:
+ case FBIO_SETPALETTE:
+ case FBIOPUTCMAP:
+ case FBIOGETCMAP:
+ return ENODEV;
+ case FBIOGTYPE:
+ case FBIOGATTR:
+ case FBIOSVIDEO:
+ case FBIOGVIDEO:
+ case FBIOSCURSOR:
+ case FBIOGCURSOR:
+ case FBIOSCURPOS:
+ case FBIOGCURPOS:
+ case FBIOGCURMAX:
+ if (scp != scp->sc->cur_scp)
+ return ENODEV; /* XXX */
+ return fb_ioctl(adp, cmd, data);
+
+#ifndef SC_NO_MODE_CHANGE
/* generic text modes */
case SW_TEXT_80x25: case SW_TEXT_80x30:
case SW_TEXT_80x43: case SW_TEXT_80x50:
@@ -428,6 +623,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_VGA_C80x30: case SW_VGA_M80x30:
case SW_VGA_C80x50: case SW_VGA_M80x50:
case SW_VGA_C80x60: case SW_VGA_M80x60:
+ case SW_VGA_C90x25: case SW_VGA_M90x25:
+ case SW_VGA_C90x30: case SW_VGA_M90x30:
+ case SW_VGA_C90x43: case SW_VGA_M90x43:
+ case SW_VGA_C90x50: case SW_VGA_M90x50:
+ case SW_VGA_C90x60: case SW_VGA_M90x60:
case SW_B40x25: case SW_C40x25:
case SW_B80x25: case SW_C80x25:
case SW_ENH_B40x25: case SW_ENH_C40x25:
@@ -440,7 +640,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_PC98_80x25:
case SW_PC98_80x30:
#endif
- if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
+ if (!(adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
@@ -450,9 +650,10 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_CG640x350: case SW_ENH_CG640:
case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
case SW_VGA_MODEX:
- if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
+ if (!(adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
return sc_set_graphics_mode(scp, tp, cmd & 0xff);
+#endif /* SC_NO_MODE_CHANGE */
case KDSETMODE: /* set current mode of this (virtual) console */
switch (*(int *)data) {
@@ -465,24 +666,31 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
/* restore fonts & palette ! */
#if 0
- if (ISFONTAVAIL(scp->adp->va_flags)
+#ifndef SC_NO_FONT_LOADING
+ if (ISFONTAVAIL(adp->va_flags)
&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
/*
* FONT KLUDGE
* Don't load fonts for now... XXX
*/
- if (fonts_loaded & FONT_8)
- copy_font(scp, LOAD, 8, font_8);
- if (fonts_loaded & FONT_14)
- copy_font(scp, LOAD, 14, font_14);
- if (fonts_loaded & FONT_16)
- copy_font(scp, LOAD, 16, font_16);
+ if (scp->sc->fonts_loaded & FONT_8)
+ copy_font(scp, LOAD, 8, scp->sc->font_8);
+ if (scp->sc->fonts_loaded & FONT_14)
+ copy_font(scp, LOAD, 14, scp->sc->font_14);
+ if (scp->sc->fonts_loaded & FONT_16)
+ copy_font(scp, LOAD, 16, scp->sc->font_16);
}
+#endif /* SC_NO_FONT_LOADING */
#endif
- load_palette(scp->adp, palette);
+#ifndef SC_NO_PALETTE_LOADING
+ load_palette(adp, scp->sc->palette);
+#endif
+
+#ifndef PC98
/* move hardware cursor out of the way */
- (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1);
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
+#endif
/* FALL THROUGH */
@@ -502,20 +710,21 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
scp->status |= UNKNOWN_MODE;
splx(s);
/* no restore fonts & palette */
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_mode(scp);
sc_clear_screen(scp);
scp->status &= ~UNKNOWN_MODE;
#else /* PC98 */
scp->status &= ~UNKNOWN_MODE;
/* no restore fonts & palette */
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_mode(scp);
sc_clear_screen(scp);
splx(s);
#endif /* PC98 */
return 0;
+#ifdef SC_PIXEL_MODE
case KD_PIXEL: /* pixel (raster) display */
if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
return EINVAL;
@@ -529,13 +738,16 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
}
scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
splx(s);
- if (scp == cur_console) {
+ if (scp == scp->sc->cur_scp) {
set_mode(scp);
- load_palette(scp->adp, palette);
+#ifndef SC_NO_PALETTE_LOADING
+ load_palette(adp, scp->sc->palette);
+#endif
}
sc_clear_screen(scp);
scp->status &= ~UNKNOWN_MODE;
return 0;
+#endif /* SC_PIXEL_MODE */
case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */
s = spltty();
@@ -546,7 +758,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
scp->status |= UNKNOWN_MODE;
splx(s);
#ifdef PC98
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_mode(scp);
#endif
return 0;
@@ -556,11 +768,13 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
}
/* NOT REACHED */
+#ifdef SC_PIXEL_MODE
case KDRASTER: /* set pixel (raster) display mode */
if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
return ENODEV;
return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1],
((int *)data)[2]);
+#endif /* SC_PIXEL_MODE */
case KDGETMODE: /* get current mode of this (virtual) console */
/*
@@ -572,7 +786,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case KDSBORDER: /* set border color of this (virtual) console */
scp->border = *data;
- if (scp == cur_console)
+ if (scp == scp->sc->cur_scp)
set_border(scp, scp->border);
return 0;
}
diff --git a/sys/dev/syscons/scvtb.c b/sys/dev/syscons/scvtb.c
new file mode 100644
index 0000000..a7d1a71
--- /dev/null
+++ b/sys/dev/syscons/scvtb.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ *
+ * $Id:$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/console.h>
+#include <machine/md_var.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#define vtb_wrap(vtb, at, offset) \
+ (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
+
+void
+sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
+{
+ vtb->vtb_flags = 0;
+ vtb->vtb_type = type;
+ vtb->vtb_cols = cols;
+ vtb->vtb_rows = rows;
+ vtb->vtb_size = cols*rows;
+ vtb->vtb_buffer = NULL;
+ vtb->vtb_tail = 0;
+
+ switch (type) {
+ case VTB_MEMORY:
+ case VTB_RINGBUFFER:
+ if ((buf == NULL) && (cols*rows != 0)) {
+ vtb->vtb_buffer =
+ (vm_offset_t)malloc(cols*rows*sizeof(u_int16_t),
+ M_DEVBUF,
+ (wait) ? M_WAITOK : M_NOWAIT);
+ if (vtb->vtb_buffer != NULL)
+ bzero((void *)sc_vtb_pointer(vtb, 0),
+ cols*rows*sizeof(u_int16_t));
+ } else {
+ vtb->vtb_buffer = (vm_offset_t)buf;
+ }
+ vtb->vtb_flags |= VTB_VALID;
+ break;
+ case VTB_FRAMEBUFFER:
+ vtb->vtb_buffer = (vm_offset_t)buf;
+ vtb->vtb_flags |= VTB_VALID;
+ break;
+ default:
+ break;
+ }
+}
+
+void
+sc_vtb_destroy(sc_vtb_t *vtb)
+{
+ vm_offset_t p;
+
+ vtb->vtb_flags = 0;
+ vtb->vtb_cols = 0;
+ vtb->vtb_rows = 0;
+ vtb->vtb_size = 0;
+ vtb->vtb_tail = 0;
+
+ p = vtb->vtb_buffer;
+ vtb->vtb_buffer = NULL;
+ switch (vtb->vtb_type) {
+ case VTB_MEMORY:
+ case VTB_RINGBUFFER:
+ if (p != NULL)
+ free((void *)p, M_DEVBUF);
+ break;
+ default:
+ break;
+ }
+ vtb->vtb_type = VTB_INVALID;
+}
+
+size_t
+sc_vtb_size(int cols, int rows)
+{
+ return (size_t)(cols*rows*sizeof(u_int16_t));
+}
+
+int
+sc_vtb_getc(sc_vtb_t *vtb, int at)
+{
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff);
+ else
+ return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff);
+}
+
+int
+sc_vtb_geta(sc_vtb_t *vtb, int at)
+{
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ return (readw(sc_vtb_pointer(vtb, at)) & 0xff00);
+ else
+ return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0xff00);
+}
+
+void
+sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
+{
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ writew(sc_vtb_pointer(vtb, at), a | c);
+ else
+ *(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
+}
+
+vm_offset_t
+sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
+{
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ writew(p, a | c);
+ else
+ *(u_int16_t *)p = a | c;
+ return (p + sizeof(u_int16_t));
+}
+
+vm_offset_t
+sc_vtb_pointer(sc_vtb_t *vtb, int at)
+{
+ return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
+}
+
+int
+sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
+{
+ return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
+}
+
+void
+sc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
+{
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ fillw_io(attr | c, sc_vtb_pointer(vtb, 0), vtb->vtb_size);
+ else
+ fillw(attr | c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size);
+}
+
+void
+sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
+{
+ /* XXX if both are VTB_VRAMEBUFFER... */
+ if (vtb2->vtb_type == VTB_FRAMEBUFFER) {
+ bcopy_toio(sc_vtb_pointer(vtb1, from),
+ sc_vtb_pointer(vtb2, to),
+ count*sizeof(u_int16_t));
+ } else if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
+ bcopy_fromio(sc_vtb_pointer(vtb1, from),
+ sc_vtb_pointer(vtb2, to),
+ count*sizeof(u_int16_t));
+ } else {
+ bcopy((void *)sc_vtb_pointer(vtb1, from),
+ (void *)sc_vtb_pointer(vtb2, to),
+ count*sizeof(u_int16_t));
+ }
+}
+
+void
+sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
+{
+ int len;
+
+ if (vtb2->vtb_type != VTB_RINGBUFFER)
+ return;
+
+ while (count > 0) {
+ len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
+ if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
+ bcopy_fromio(sc_vtb_pointer(vtb1, from),
+ sc_vtb_pointer(vtb2, vtb2->vtb_tail),
+ len*sizeof(u_int16_t));
+ } else {
+ bcopy((void *)sc_vtb_pointer(vtb1, from),
+ (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail),
+ len*sizeof(u_int16_t));
+ }
+ from += len;
+ count -= len;
+ vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
+ }
+}
+
+void
+sc_vtb_seek(sc_vtb_t *vtb, int pos)
+{
+ vtb->vtb_tail = pos%vtb->vtb_size;
+}
+
+void
+sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
+{
+ if (at + count > vtb->vtb_size)
+ count = vtb->vtb_size - at;
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
+ else
+ fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
+}
+
+void
+sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
+{
+ int len;
+
+ if (at + count > vtb->vtb_size)
+ count = vtb->vtb_size - at;
+ len = vtb->vtb_size - at - count;
+ if (len > 0) {
+ if (vtb->vtb_type == VTB_FRAMEBUFFER) {
+ bcopy_io(sc_vtb_pointer(vtb, at + count),
+ sc_vtb_pointer(vtb, at),
+ len*sizeof(u_int16_t));
+ } else {
+ bcopy((void *)sc_vtb_pointer(vtb, at + count),
+ (void *)sc_vtb_pointer(vtb, at),
+ len*sizeof(u_int16_t));
+ }
+ }
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ fillw_io(attr | c, sc_vtb_pointer(vtb, at + len),
+ vtb->vtb_size - at - len);
+ else
+ fillw(attr | c, (void *)sc_vtb_pointer(vtb, at + len),
+ vtb->vtb_size - at - len);
+}
+
+void
+sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
+{
+ if (at + count > vtb->vtb_size) {
+ count = vtb->vtb_size - at;
+ } else {
+ if (vtb->vtb_type == VTB_FRAMEBUFFER) {
+ bcopy_io(sc_vtb_pointer(vtb, at),
+ sc_vtb_pointer(vtb, at + count),
+ (vtb->vtb_size - at - count)*sizeof(u_int16_t));
+ } else {
+ bcopy((void *)sc_vtb_pointer(vtb, at),
+ (void *)sc_vtb_pointer(vtb, at + count),
+ (vtb->vtb_size - at - count)*sizeof(u_int16_t));
+ }
+ }
+ if (vtb->vtb_type == VTB_FRAMEBUFFER)
+ fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
+ else
+ fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
+}
+
+#endif /* NSC */
diff --git a/sys/dev/syscons/snake/snake_saver.c b/sys/dev/syscons/snake/snake_saver.c
index ef64741..51e1746 100644
--- a/sys/dev/syscons/snake/snake_saver.c
+++ b/sys/dev/syscons/snake/snake_saver.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: snake_saver.c,v 1.22 1999/01/17 14:25:19 yokota Exp $
+ * $Id: snake_saver.c,v 1.23 1999/02/05 12:40:15 des Exp $
*/
#include <sys/param.h>
@@ -34,16 +34,18 @@
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <machine/md_var.h>
#include <machine/pc/display.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static char *message;
-static u_char **messagep;
+static int *messagep;
static int messagelen;
-static u_short *window;
static int blanked;
static int
@@ -51,36 +53,50 @@ snake_saver(video_adapter_t *adp, int blank)
{
static int dirx, diry;
int f;
- scr_stat *scp = cur_console;
+ sc_softc_t *sc;
+ scr_stat *scp;
/* XXX hack for minimal changes. */
#define save message
#define savs messagep
+ sc = sc_find_softc(adp, NULL);
+ if (sc == NULL)
+ return EAGAIN;
+ scp = sc->cur_scp;
+
if (blank) {
if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
return EAGAIN;
if (blanked <= 0) {
- window = (u_short *)adp->va_window;
- fillw(((FG_LIGHTGREY|BG_BLACK)<<8) | scr_map[0x20],
- window, scp->xsize * scp->ysize);
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) & ~0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
+ sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
set_border(scp, 0);
dirx = (scp->xpos ? 1 : -1);
diry = (scp->ypos ?
scp->xsize : -scp->xsize);
for (f=0; f< messagelen; f++)
- savs[f] = (u_char *)window + 2 *
- (scp->xpos+scp->ypos*scp->xsize);
- *(savs[0]) = scr_map[*save];
+ savs[f] = scp->xpos + scp->ypos*scp->xsize;
+ sc_vtb_putc(&scp->scr, savs[0], sc->scr_map[*save],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
blanked = 1;
}
if (blanked++ < 4)
return 0;
blanked = 1;
- *(savs[messagelen-1]) = scr_map[0x20];
+ sc_vtb_putc(&scp->scr, savs[messagelen - 1], sc->scr_map[0x20],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
for (f=messagelen-1; f > 0; f--)
savs[f] = savs[f-1];
- f = (savs[0] - (u_char *)window) / 2;
+ f = savs[0];
if ((f % scp->xsize) == 0 ||
(f % scp->xsize) == scp->xsize - 1 ||
(random() % 50) == 0)
@@ -89,11 +105,19 @@ snake_saver(video_adapter_t *adp, int blank)
(f / scp->xsize) == scp->ysize - 1 ||
(random() % 20) == 0)
diry = -diry;
- savs[0] += 2*dirx + 2*diry;
+ savs[0] += dirx + diry;
for (f=messagelen-1; f>=0; f--)
- *(savs[f]) = scr_map[save[f]];
+ sc_vtb_putc(&scp->scr, savs[f], sc->scr_map[save[f]],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
}
else {
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) | 0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
blanked = 0;
}
return 0;
diff --git a/sys/dev/syscons/star/star_saver.c b/sys/dev/syscons/star/star_saver.c
index aaa23fb..56408dc 100644
--- a/sys/dev/syscons/star/star_saver.c
+++ b/sys/dev/syscons/star/star_saver.c
@@ -25,22 +25,24 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: star_saver.c,v 1.19 1999/01/17 14:25:19 yokota Exp $
+ * $Id: star_saver.c,v 1.20 1999/02/05 12:40:16 des Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <machine/md_var.h>
#include <machine/pc/display.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
#define NUM_STARS 50
-static u_short *window;
static int blanked;
/*
@@ -50,21 +52,39 @@ static int blanked;
static int
star_saver(video_adapter_t *adp, int blank)
{
- scr_stat *scp = cur_console;
+ sc_softc_t *sc;
+ scr_stat *scp;
int cell, i;
char pattern[] = {"...........++++*** "};
+#ifndef PC98
char colors[] = {FG_DARKGREY, FG_LIGHTGREY,
FG_WHITE, FG_LIGHTCYAN};
+#else
+ char colors[] = {FG_BLUE, FG_LIGHTGREY,
+ FG_LIGHTGREY, FG_CYAN};
+#endif /* PC98 */
static u_short stars[NUM_STARS][2];
+ sc = sc_find_softc(adp, NULL);
+ if (sc == NULL)
+ return EAGAIN;
+ scp = sc->cur_scp;
+
if (blank) {
if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
return EAGAIN;
if (!blanked) {
- window = (u_short *)adp->va_window;
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) & ~0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
/* clear the screen and set the border color */
- fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
- window, scp->xsize * scp->ysize);
+ sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
+ (FG_LIGHTGREY | BG_BLACK) << 8);
+ (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
set_border(scp, 0);
blanked = TRUE;
for(i=0; i<NUM_STARS; i++) {
@@ -74,15 +94,22 @@ star_saver(video_adapter_t *adp, int blank)
}
}
cell = random() % NUM_STARS;
- *((u_short*)(window + stars[cell][0])) =
- scr_map[pattern[stars[cell][1]]] |
- colors[random()%sizeof(colors)] << 8;
+ sc_vtb_putc(&scp->scr, stars[cell][0],
+ sc->scr_map[pattern[stars[cell][1]]],
+ colors[random()%sizeof(colors)] << 8);
if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) {
stars[cell][0] = random() % (scp->xsize*scp->ysize);
stars[cell][1] = 0;
}
}
else {
+#ifdef PC98
+ if (epson_machine_id == 0x20) {
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) | 0x08);
+ outb(0x43f, 0x40);
+ }
+#endif /* PC98 */
blanked = FALSE;
}
return 0;
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index df527fc..937dcbc 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -30,15 +30,12 @@
#include "sc.h"
#include "splash.h"
-#ifdef __i386__
-#include "apm.h"
-#endif
+#include "opt_syscons.h"
#include "opt_ddb.h"
#include "opt_devfs.h"
#ifdef __i386__
-#include "opt_vesa.h"
+#include "apm.h"
#endif
-#include "opt_syscons.h"
#if NSC > 0
#include <sys/param.h>
@@ -54,308 +51,158 @@
#include <sys/devfsext.h>
#endif
-#include <machine/bootinfo.h>
#include <machine/clock.h>
#include <machine/cons.h>
#include <machine/console.h>
-#include <machine/mouse.h>
-#include <machine/md_var.h>
#include <machine/psl.h>
-#include <machine/frame.h>
#include <machine/pc/display.h>
#ifdef __i386__
-#include <machine/pc/vesa.h>
#include <machine/apm_bios.h>
+#include <machine/frame.h>
#include <machine/random.h>
#endif
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
#include <dev/kbd/kbdreg.h>
#include <dev/fb/fbreg.h>
-#include <dev/fb/vgareg.h>
#include <dev/fb/splashreg.h>
#include <dev/syscons/syscons.h>
-#ifndef __i386__
-#include <isa/isareg.h>
-#else
-#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
-#include <i386/isa/timerreg.h>
-#endif
-
-#if !defined(MAXCONS)
-#define MAXCONS 16
-#endif
-
-#if !defined(SC_MAX_HISTORY_SIZE)
-#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
-#endif
-
-#if !defined(SC_HISTORY_SIZE)
-#define SC_HISTORY_SIZE (ROW * 4)
-#endif
-
-#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
-#undef SC_MAX_HISTORY_SIZE
-#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
-#endif
-
-#if !defined(SC_MOUSE_CHAR)
-#define SC_MOUSE_CHAR (0xd0)
-#endif
-
#define COLD 0
#define WARM 1
#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */
#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */
-/* for backward compatibility */
-#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t)
-
-typedef struct old_mouse_data {
- int x;
- int y;
- int buttons;
-} old_mouse_data_t;
-
-typedef struct old_mouse_info {
- int operation;
- union {
- struct old_mouse_data data;
- struct mouse_mode mode;
- } u;
-} old_mouse_info_t;
+#define KEYCODE_BS 0x0e /* "<-- Backspace" key, XXX */
static default_attr user_default = {
- (FG_LIGHTGREY | BG_BLACK) << 8,
- (FG_BLACK | BG_LIGHTGREY) << 8
+ SC_NORM_ATTR << 8,
+ SC_NORM_REV_ATTR << 8,
};
static default_attr kernel_default = {
- (FG_WHITE | BG_BLACK) << 8,
- (FG_BLACK | BG_LIGHTGREY) << 8
+ SC_KERNEL_CONS_ATTR << 8,
+ SC_KERNEL_CONS_REV_ATTR << 8,
};
-static scr_stat main_console;
-static scr_stat *console[MAXCONS];
+static int sc_console_unit = -1;
+static scr_stat *sc_console;
#ifdef DEVFS
-static void *sc_devfs_token[MAXCONS];
static void *sc_mouse_devfs_token;
static void *sc_console_devfs_token;
#endif
- scr_stat *cur_console;
-static scr_stat *new_scp, *old_scp;
static term_stat kernel_console;
static default_attr *current_default;
-static int sc_flags;
+
static char init_done = COLD;
-static u_short sc_buffer[ROW*COL];
static char shutdown_in_progress = FALSE;
-static char font_loading_in_progress = FALSE;
-static char switch_in_progress = FALSE;
-static char write_in_progress = FALSE;
-static char blink_in_progress = FALSE;
-static int blinkrate = 0;
-static int adapter = -1;
-static int keyboard = -1;
-static keyboard_t *kbd;
-static int delayed_next_scr = FALSE;
-static long scrn_blank_time = 0; /* screen saver timeout value */
-static int scrn_blanked = FALSE; /* screen saver active flag */
-static long scrn_time_stamp;
+static char sc_malloc = FALSE;
+
static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */
static int run_scrn_saver = FALSE; /* should run the saver? */
-static int scrn_idle = FALSE; /* about to run the saver */
-#if NSPLASH > 0
-static int scrn_saver_failed;
-#endif
- u_char scr_map[256];
- u_char scr_rmap[256];
-static int initial_video_mode; /* initial video mode # */
- int fonts_loaded = 0
-#ifdef STD8X16FONT
- | FONT_16
-#endif
- ;
+static long scrn_blank_time = 0; /* screen saver timeout value */
+static int scrn_blanked; /* # of blanked screen */
+static int sticky_splash = FALSE;
- u_char font_8[256*8];
- u_char font_14[256*14];
-#ifdef STD8X16FONT
-extern
+static void none_saver(sc_softc_t *sc, int blank) { }
+static void (*current_saver)(sc_softc_t *, int) = none_saver;
+
+#if !defined(SC_NO_FONT_LOADING) && defined(SC_DFLT_FONT)
+#include "font.h"
#endif
- u_char font_16[256*16];
- u_char palette[256*3];
-static u_char *cut_buffer;
-static int cut_buffer_size;
-static int mouse_level; /* sysmouse protocol level */
-static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 };
-static u_short mouse_and_mask[16] = {
- 0xc000, 0xe000, 0xf000, 0xf800,
- 0xfc00, 0xfe00, 0xff00, 0xff80,
- 0xfe00, 0x1e00, 0x1f00, 0x0f00,
- 0x0f00, 0x0000, 0x0000, 0x0000
- };
-static u_short mouse_or_mask[16] = {
- 0x0000, 0x4000, 0x6000, 0x7000,
- 0x7800, 0x7c00, 0x7e00, 0x6800,
- 0x0c00, 0x0c00, 0x0600, 0x0600,
- 0x0000, 0x0000, 0x0000, 0x0000
- };
-
- int sc_history_size = SC_HISTORY_SIZE;
-static int extra_history_size =
- SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
-
-static void none_saver(int blank) { }
-static void (*current_saver)(int blank) = none_saver;
+
d_ioctl_t *sc_user_ioctl;
-static int sticky_splash = FALSE;
-static struct {
- u_int8_t cursor_start;
- u_int8_t cursor_end;
- u_int8_t shift_state;
- } bios_value;
-
-/* OS specific stuff */
-#ifdef not_yet_done
-#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x]))
-struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))
-struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))
-struct tty *sccons[MAXCONS+2];
-#else
-#define VIRTUAL_TTY(x) &sccons[x]
-#define CONSOLE_TTY &sccons[MAXCONS]
-#define MOUSE_TTY &sccons[MAXCONS+1]
-static struct tty sccons[MAXCONS+2];
-#endif
+static bios_values_t bios_value;
+
+static struct tty sccons[2];
#define SC_MOUSE 128
-#define SC_CONSOLE 255
-static const int nsccons = MAXCONS+2;
-
-#define WRAPHIST(scp, pointer, offset) \
- ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \
- + (offset)) % (scp)->history_size))
-#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
-
-/* some useful macros */
-#define kbd_read_char(kbd, wait) \
- (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))
-#define kbd_check_char(kbd) \
- (*kbdsw[(kbd)->kb_index]->check_char)((kbd))
-#define kbd_enable(kbd) \
- (*kbdsw[(kbd)->kb_index]->enable)((kbd))
-#define kbd_disable(kbd) \
- (*kbdsw[(kbd)->kb_index]->disable)((kbd))
-#define kbd_lock(kbd, lockf) \
- (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf))
-#define kbd_ioctl(kbd, cmd, arg) \
- (((kbd) == NULL) ? \
- ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg)))
-#define kbd_clear_state(kbd) \
- (*kbdsw[(kbd)->kb_index]->clear_state)((kbd))
-#define kbd_get_fkeystr(kbd, fkey, len) \
- (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len))
-#define kbd_poll(kbd, on) \
- (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
+#define SC_CONSOLECTL 255
+
+#define VIRTUAL_TTY(sc, x) (&((sc)->tty[(x) - (sc)->first_vty]))
+#define CONSOLE_TTY (&sccons[0])
+#define MOUSE_TTY (&sccons[1])
+
+#define debugger FALSE
+
+#ifdef __i386__
+#ifdef DDB
+extern int in_Debugger;
+#undef debugger
+#define debugger in_Debugger
+#endif /* DDB */
+#endif /* __i386__ */
/* prototypes */
-static kbd_callback_func_t sckbdevent;
-static int scparam(struct tty *tp, struct termios *t);
static int scvidprobe(int unit, int flags, int cons);
static int sckbdprobe(int unit, int flags, int cons);
+static void scmeminit(void *arg);
+static int scdevtounit(dev_t dev);
+static kbd_callback_func_t sckbdevent;
+static int scparam(struct tty *tp, struct termios *t);
static void scstart(struct tty *tp);
static void scmousestart(struct tty *tp);
-static void scinit(void);
+static void scinit(int unit, int flags);
+static void scterm(int unit, int flags);
static void scshutdown(int howto, void *arg);
-static u_int scgetc(keyboard_t *kbd, u_int flags);
+static u_int scgetc(sc_softc_t *sc, u_int flags);
#define SCGETC_CN 1
#define SCGETC_NONBLOCK 2
static int sccngetch(int flags);
static void sccnupdate(scr_stat *scp);
-static scr_stat *alloc_scp(void);
-static void init_scp(scr_stat *scp);
-static void get_bios_values(void);
-static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
-static int get_scr_num(void);
+static scr_stat *alloc_scp(sc_softc_t *sc, int vty);
+static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp);
static timeout_t scrn_timer;
+static int and_region(int *s1, int *e1, int s2, int e2);
static void scrn_update(scr_stat *scp, int show_cursor);
+
#if NSPLASH > 0
-static int scsplash_callback(int);
-static void scsplash_saver(int show);
-static int add_scrn_saver(void (*this_saver)(int));
-static int remove_scrn_saver(void (*this_saver)(int));
+static int scsplash_callback(int event, void *arg);
+static void scsplash_saver(sc_softc_t *sc, int show);
+static int add_scrn_saver(void (*this_saver)(sc_softc_t *, int));
+static int remove_scrn_saver(void (*this_saver)(sc_softc_t *, int));
static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border);
static int restore_scrn_saver_mode(scr_stat *scp, int changemode);
-static void stop_scrn_saver(void (*saver)(int));
-static int wait_scrn_saver_stop(void);
+static void stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int));
+static int wait_scrn_saver_stop(sc_softc_t *sc);
#define scsplash_stick(stick) (sticky_splash = (stick))
#else /* !NSPLASH */
-#define stop_scrn_saver(saver)
-#define wait_scrn_saver_stop() 0
#define scsplash_stick(stick)
#endif /* NSPLASH */
-static int switch_scr(scr_stat *scp, u_int next_scr);
-static void exchange_scr(void);
+
+static int switch_scr(sc_softc_t *sc, u_int next_scr);
+static int do_switch_scr(sc_softc_t *sc, int s);
+static int vt_proc_alive(scr_stat *scp);
+static int signal_vt_rel(scr_stat *scp);
+static int signal_vt_acq(scr_stat *scp);
+static void exchange_scr(sc_softc_t *sc);
static void scan_esc(scr_stat *scp, u_char c);
static void ansi_put(scr_stat *scp, u_char *buf, int len);
-static void draw_cursor_image(scr_stat *scp);
-static void remove_cursor_image(scr_stat *scp);
+static void draw_cursor_image(scr_stat *scp);
+static void remove_cursor_image(scr_stat *scp);
+static void update_cursor_image(scr_stat *scp);
static void move_crsr(scr_stat *scp, int x, int y);
-static void history_to_screen(scr_stat *scp);
-static int history_up_line(scr_stat *scp);
-static int history_down_line(scr_stat *scp);
static int mask2attr(struct term_stat *term);
static int save_kbd_state(scr_stat *scp);
-static int update_kbd_state(int state, int mask);
-static int update_kbd_leds(int which);
-static void set_destructive_cursor(scr_stat *scp);
-static void set_mouse_pos(scr_stat *scp);
-static int skip_spc_right(scr_stat *scp, u_short *p);
-static int skip_spc_left(scr_stat *scp, u_short *p);
-static void mouse_cut(scr_stat *scp);
-static void mouse_cut_start(scr_stat *scp);
-static void mouse_cut_end(scr_stat *scp);
-static void mouse_cut_word(scr_stat *scp);
-static void mouse_cut_line(scr_stat *scp);
-static void mouse_cut_extend(scr_stat *scp);
-static void mouse_paste(scr_stat *scp);
-static void draw_mouse_image(scr_stat *scp);
-static void remove_mouse_image(scr_stat *scp);
-static void draw_cutmarking(scr_stat *scp);
-static void remove_cutmarking(scr_stat *scp);
+static int update_kbd_state(scr_stat *scp, int state, int mask);
+static int update_kbd_leds(scr_stat *scp, int which);
static void do_bell(scr_stat *scp, int pitch, int duration);
static timeout_t blink_screen;
#define CDEV_MAJOR 12
-#ifdef __i386__
-
static cn_probe_t sccnprobe;
static cn_init_t sccninit;
static cn_getc_t sccngetc;
static cn_checkc_t sccncheckc;
static cn_putc_t sccnputc;
+static cn_term_t sccnterm;
-CONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc);
-
-#else /* !__i386__ */
-
-static cn_getc_t sccngetc;
-static cn_checkc_t sccncheckc;
-static cn_putc_t sccnputc;
-
-struct consdev sc_cons = {
- NULL, NULL, sccngetc, sccncheckc, sccnputc,
- NULL, 0, CN_NORMAL,
-};
+#if __alpha__
+void sccnattach(void);
+#endif
-#endif /* __i386__ */
+CONS_DRIVER(sc, sccnprobe, sccninit, sccnterm, sccngetc, sccncheckc, sccnputc);
static d_open_t scopen;
static d_close_t scclose;
@@ -386,118 +233,6 @@ static struct cdevsw sc_cdevsw = {
/* bmaj */ -1
};
-#ifdef __i386__
-
-#define fillw_io(p, b, c) fillw((p), (void *)(b), (c))
-
-#endif
-
-#ifdef __alpha__
-
-static void
-fillw(int pat, void *base, size_t cnt)
-{
- u_short *sp = base;
- while (cnt--)
- *sp++ = pat;
-}
-
-static void
-fillw_io(int pat, u_int32_t base, size_t cnt)
-{
- while (cnt--) {
- writew(base, pat);
- base += 2;
- }
-}
-
-#endif
-
-static void
-draw_cursor_image(scr_stat *scp)
-{
- u_short cursor_image;
- vm_offset_t ptr;
- u_short prev_image;
-
- if (ISPIXELSC(scp)) {
- sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf,
- scp->cursor_pos - scp->scr_buf, 1);
- return;
- }
-
- ptr = scp->adp->va_window + 2*(scp->cursor_pos - scp->scr_buf);
-
- /* do we have a destructive cursor ? */
- if (sc_flags & CHAR_CURSOR) {
- prev_image = scp->cursor_saveunder;
- cursor_image = readw(ptr) & 0x00ff;
- if (cursor_image == DEAD_CHAR)
- cursor_image = prev_image & 0x00ff;
- cursor_image |= *(scp->cursor_pos) & 0xff00;
- scp->cursor_saveunder = cursor_image;
- /* update the cursor bitmap if the char under the cursor has changed */
- if (prev_image != cursor_image)
- set_destructive_cursor(scp);
- /* modify cursor_image */
- if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){
- /*
- * When the mouse pointer is at the same position as the cursor,
- * the cursor bitmap needs to be updated even if the char under
- * the cursor hasn't changed, because the mouse pionter may
- * have moved by a few dots within the cursor cel.
- */
- if ((prev_image == cursor_image)
- && (cursor_image != *(scp->cursor_pos)))
- set_destructive_cursor(scp);
- cursor_image &= 0xff00;
- cursor_image |= DEAD_CHAR;
- }
- } else {
- cursor_image = (readw(ptr) & 0x00ff) | (*(scp->cursor_pos) & 0xff00);
- scp->cursor_saveunder = cursor_image;
- if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){
- if ((cursor_image & 0x7000) == 0x7000) {
- cursor_image &= 0x8fff;
- if(!(cursor_image & 0x0700))
- cursor_image |= 0x0700;
- } else {
- cursor_image |= 0x7000;
- if ((cursor_image & 0x0700) == 0x0700)
- cursor_image &= 0xf0ff;
- }
- }
- }
- writew(ptr, cursor_image);
-}
-
-static void
-remove_cursor_image(scr_stat *scp)
-{
- if (ISPIXELSC(scp))
- sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf,
- scp->cursor_oldpos - scp->scr_buf, 0);
- else
- writew(scp->adp->va_window + 2*(scp->cursor_oldpos - scp->scr_buf),
- scp->cursor_saveunder);
-}
-
-static void
-move_crsr(scr_stat *scp, int x, int y)
-{
- if (x < 0)
- x = 0;
- if (y < 0)
- y = 0;
- if (x >= scp->xsize)
- x = scp->xsize-1;
- if (y >= scp->ysize)
- y = scp->ysize-1;
- scp->xpos = x;
- scp->ypos = y;
- scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;
-}
-
int
sc_probe_unit(int unit, int flags)
{
@@ -514,8 +249,6 @@ sc_probe_unit(int unit, int flags)
static int
scvidprobe(int unit, int flags, int cons)
{
- video_adapter_t *adp;
-
/*
* Access the video adapter driver through the back door!
* Video adapter drivers need to be configured before syscons.
@@ -525,17 +258,7 @@ scvidprobe(int unit, int flags, int cons)
*/
vid_configure(cons ? VIO_PROBE_ONLY : 0);
- /* allocate a frame buffer */
- if (adapter < 0) {
- adapter = vid_allocate("*", -1, (void *)&adapter);
- if (adapter < 0)
- return FALSE;
- }
- adp = vid_get_adapter(adapter); /* shouldn't fail */
-
- initial_video_mode = adp->va_initial_mode;
-
- return TRUE;
+ return (vid_find_adapter("*", unit) >= 0);
}
/* probe the keyboard, return TRUE if found */
@@ -545,169 +268,241 @@ sckbdprobe(int unit, int flags, int cons)
/* access the keyboard driver through the backdoor! */
kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0);
- /* allocate a keyboard and register the keyboard event handler */
- if (keyboard < 0) {
- keyboard = kbd_allocate("*", -1, (void *)&keyboard, sckbdevent, NULL);
- if (keyboard < 0)
- return FALSE;
- }
- kbd = kbd_get_keyboard(keyboard); /* shouldn't fail */
-
- return TRUE;
-}
+ return (kbd_find_keyboard("*", unit) >= 0);
+}
+
+static char
+*adapter_name(video_adapter_t *adp)
+{
+ static struct {
+ int type;
+ char *name[2];
+ } names[] = {
+ { KD_MONO, { "MDA", "MDA" } },
+ { KD_HERCULES, { "Hercules", "Hercules" } },
+ { KD_CGA, { "CGA", "CGA" } },
+ { KD_EGA, { "EGA", "EGA (mono)" } },
+ { KD_VGA, { "VGA", "VGA (mono)" } },
+ { KD_PC98, { "PC-98x1", "PC-98x1" } },
+ { KD_TGA, { "TGA", "TGA" } },
+ { -1, { "Unknown", "Unknown" } },
+ };
+ int i;
-#if NAPM > 0
-static int
-scresume(void *dummy)
-{
- if (kbd != NULL)
- kbd_clear_state(kbd);
- return 0;
+ for (i = 0; names[i].type != -1; ++i)
+ if (names[i].type == adp->va_type)
+ break;
+ return names[i].name[(adp->va_flags & V_ADP_COLOR) ? 0 : 1];
}
-#endif
int
sc_attach_unit(int unit, int flags)
{
+ sc_softc_t *sc;
scr_stat *scp;
-#if defined(VESA)
+#ifdef SC_PIXEL_MODE
video_info_t info;
#endif
#ifdef DEVFS
int vc;
#endif
- scinit();
- scp = console[0];
- sc_flags = flags;
- if (!ISFONTAVAIL(scp->adp->va_flags))
- sc_flags &= ~CHAR_CURSOR;
-
- /* copy temporary buffer to final buffer */
- scp->scr_buf = NULL;
- sc_alloc_scr_buffer(scp, FALSE, FALSE);
- bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
-
- /* cut buffer is available only when the mouse pointer is used */
- if (ISMOUSEAVAIL(scp->adp->va_flags))
- sc_alloc_cut_buffer(scp, FALSE);
-
- /* initialize history buffer & pointers */
- sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
-
-#if defined(VESA)
- if ((sc_flags & VESA800X600)
- && ((*vidsw[scp->ad]->get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
+ scmeminit(NULL); /* XXX */
+
+ flags &= ~SC_KERNEL_CONSOLE;
+ if (sc_console_unit == unit)
+ flags |= SC_KERNEL_CONSOLE;
+ scinit(unit, flags);
+ sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
+ sc->config = flags;
+ scp = sc->console[0];
+ if (sc_console == NULL) /* sc_console_unit < 0 */
+ sc_console = scp;
+
+#ifdef SC_PIXEL_MODE
+ if ((sc->config & SC_VESA800X600)
+ && ((*vidsw[sc->adapter]->get_info)(sc->adp, M_VESA_800x600, &info) == 0)) {
#if NSPLASH > 0
- splash_term(scp->adp);
+ if (sc->flags & SC_SPLASH_SCRN)
+ splash_term(sc->adp);
#endif
sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
- initial_video_mode = M_VESA_800x600;
+ sc->initial_mode = M_VESA_800x600;
#if NSPLASH > 0
/* put up the splash again! */
- splash_init(scp->adp, scsplash_callback);
+ if (sc->flags & SC_SPLASH_SCRN)
+ splash_init(sc->adp, scsplash_callback, sc);
#endif
}
-#endif /* VESA */
+#endif /* SC_PIXEL_MODE */
- /* initialize cursor stuff */
+ /* initialize cursor */
if (!ISGRAPHSC(scp))
- draw_cursor_image(scp);
+ update_cursor_image(scp);
/* get screen update going */
- scrn_timer((void *)TRUE);
+ scrn_timer(sc);
/* set up the keyboard */
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
- update_kbd_state(scp->status, LOCK_MASK);
+ kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
+ update_kbd_state(scp, scp->status, LOCK_MASK);
+ printf("sc%d: %s <%d virtual consoles, flags=0x%x>\n",
+ unit, adapter_name(sc->adp), sc->vtys, sc->config);
if (bootverbose) {
printf("sc%d:", unit);
- if (adapter >= 0)
- printf(" fb%d", adapter);
- if (keyboard >= 0)
- printf(" kbd%d", keyboard);
+ if (sc->adapter >= 0)
+ printf(" fb%d", sc->adapter);
+ if (sc->keyboard >= 0)
+ printf(" kbd%d", sc->keyboard);
printf("\n");
}
- printf("sc%d: ", unit);
- switch(scp->adp->va_type) {
- case KD_VGA:
- printf("VGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono");
- break;
- case KD_EGA:
- printf("EGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono");
- break;
- case KD_CGA:
- printf("CGA");
- break;
- case KD_MONO:
- case KD_HERCULES:
- default:
- printf("MDA/Hercules");
- break;
- }
- printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags);
-
-#if NAPM > 0
- scp->r_hook.ah_fun = scresume;
- scp->r_hook.ah_arg = NULL;
- scp->r_hook.ah_name = "system keyboard";
- scp->r_hook.ah_order = APM_MID_ORDER;
- apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);
-#endif
- at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC);
+ /* register a shutdown callback for the kernel console */
+ if (sc_console_unit == unit)
+ at_shutdown(scshutdown, (void *)unit, SHUTDOWN_PRE_SYNC);
- cdevsw_add(&sc_cdevsw);
+ /*
+ * syscons's cdevsw must be registered from here. As syscons and
+ * pcvt share the same major number, their cdevsw cannot be
+ * registered at module loading/initialization time or by SYSINIT.
+ */
+ cdevsw_add(&sc_cdevsw); /* XXX do this just once... */
#ifdef DEVFS
- for (vc = 0; vc < MAXCONS; vc++)
- sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR,
- UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc);
- sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR,
- UID_ROOT, GID_WHEEL, 0600, "sysmouse");
- sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR,
- UID_ROOT, GID_WHEEL, 0600, "consolectl");
+ for (vc = sc->first_vty; vc < sc->first_vty + sc->vtys; vc++)
+ sc->devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc,
+ DV_CHR, UID_ROOT, GID_WHEEL,
+ 0600, "ttyv%r", vc);
+ if (scp == sc_console) {
+#ifndef SC_NO_SYSMOUSE
+ sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE,
+ DV_CHR, UID_ROOT, GID_WHEEL,
+ 0600, "sysmouse");
+#endif /* SC_NO_SYSMOUSE */
+ sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLECTL,
+ DV_CHR, UID_ROOT, GID_WHEEL,
+ 0600, "consolectl");
+ }
+#endif /* DEVFS */
+
+ return 0;
+}
+
+static void
+scmeminit(void *arg)
+{
+ if (sc_malloc)
+ return;
+ sc_malloc = TRUE;
+
+ /*
+ * As soon as malloc() becomes functional, we had better allocate
+ * various buffers for the kernel console.
+ */
+
+ if (sc_console_unit < 0)
+ return;
+
+ /* copy the temporary buffer to the final buffer */
+ sc_alloc_scr_buffer(sc_console, FALSE, FALSE);
+
+#ifndef SC_NO_CUTPASTE
+ /* cut buffer is available only when the mouse pointer is used */
+ if (ISMOUSEAVAIL(sc_console->sc->adp->va_flags))
+ sc_alloc_cut_buffer(sc_console, FALSE);
#endif
+
+#ifndef SC_NO_HISTORY
+ /* initialize history buffer & pointers */
+ sc_alloc_history_buffer(sc_console, 0, FALSE);
+#endif
+}
+
+/* XXX */
+SYSINIT(sc_mem, SI_SUB_KMEM, SI_ORDER_ANY, scmeminit, NULL);
+
+int
+sc_resume_unit(int unit)
+{
+ /* XXX should be moved to the keyboard driver? */
+ sc_softc_t *sc;
+
+ sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
+ if (sc->kbd != NULL)
+ kbd_clear_state(sc->kbd);
return 0;
}
struct tty
*scdevtotty(dev_t dev)
{
- int unit = minor(dev);
+ sc_softc_t *sc;
+ int vty = SC_VTY(dev);
+ int unit;
if (init_done == COLD)
- return(NULL);
- if (unit == SC_CONSOLE)
+ return NULL;
+
+ if (vty == SC_CONSOLECTL)
return CONSOLE_TTY;
- if (unit == SC_MOUSE)
+#ifndef SC_NO_SYSMOUSE
+ if (vty == SC_MOUSE)
return MOUSE_TTY;
- if (unit >= MAXCONS || unit < 0)
- return(NULL);
- return VIRTUAL_TTY(unit);
+#endif
+
+ unit = scdevtounit(dev);
+ sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
+ if (sc == NULL)
+ return NULL;
+ return VIRTUAL_TTY(sc, vty);
+}
+
+static int
+scdevtounit(dev_t dev)
+{
+ int vty = SC_VTY(dev);
+
+ if (vty == SC_CONSOLECTL)
+ return ((sc_console != NULL) ? sc_console->sc->unit : -1);
+ else if (vty == SC_MOUSE)
+ return -1;
+ else if ((vty < 0) || (vty >= MAXCONS*sc_max_unit()))
+ return -1;
+ else
+ return vty/MAXCONS;
}
int
scopen(dev_t dev, int flag, int mode, struct proc *p)
{
struct tty *tp = scdevtotty(dev);
+ int unit = scdevtounit(dev);
+ sc_softc_t *sc;
keyarg_t key;
if (!tp)
return(ENXIO);
- tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart;
+ DPRINTF(5, ("scopen: dev:%d, unit:%d, vty:%d\n",
+ dev, unit, SC_VTY(dev)));
+
+ /* sc == NULL, if SC_VTY(dev) == SC_MOUSE */
+ sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
+
+ tp->t_oproc = (SC_VTY(dev) == SC_MOUSE) ? scmousestart : scstart;
tp->t_param = scparam;
tp->t_dev = dev;
if (!(tp->t_state & TS_ISOPEN)) {
ttychars(tp);
/* Use the current setting of the <-- key as default VERASE. */
/* If the Delete key is preferable, an stty is necessary */
- key.keynum = 0x0e; /* how do we know this magic number... XXX */
- kbd_ioctl(kbd, GIO_KEYMAPENT, (caddr_t)&key);
- tp->t_cc[VERASE] = key.key.map[0];
+ if (sc != NULL) {
+ key.keynum = KEYCODE_BS;
+ kbd_ioctl(sc->kbd, GIO_KEYMAPENT, (caddr_t)&key);
+ tp->t_cc[VERASE] = key.key.map[0];
+ }
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_cflag = TTYDEF_CFLAG;
@@ -715,20 +510,29 @@ scopen(dev_t dev, int flag, int mode, struct proc *p)
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
scparam(tp, &tp->t_termios);
(*linesw[tp->t_line].l_modem)(tp, 1);
- if (minor(dev) == SC_MOUSE)
- mouse_level = 0; /* XXX */
+#ifndef SC_NO_SYSMOUSE
+ if (SC_VTY(dev) == SC_MOUSE)
+ sc_mouse_set_level(0); /* XXX */
+#endif
}
else
if (tp->t_state & TS_XCLUDE && suser(p))
return(EBUSY);
- if (minor(dev) < MAXCONS && !console[minor(dev)]) {
- console[minor(dev)] = alloc_scp();
- if (ISGRAPHSC(console[minor(dev)]))
- sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
- }
- if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
- tp->t_winsize.ws_col = console[minor(dev)]->xsize;
- tp->t_winsize.ws_row = console[minor(dev)]->ysize;
+ if ((SC_VTY(dev) != SC_CONSOLECTL) && (SC_VTY(dev) != SC_MOUSE)) {
+ /* assert(sc != NULL) */
+ if (sc->console[SC_VTY(dev) - sc->first_vty] == NULL) {
+ sc->console[SC_VTY(dev) - sc->first_vty]
+ = alloc_scp(sc, SC_VTY(dev));
+ if (ISGRAPHSC(sc->console[SC_VTY(dev) - sc->first_vty]))
+ sc_set_pixel_mode(sc->console[SC_VTY(dev) - sc->first_vty],
+ NULL, COL, ROW, 16);
+ }
+ if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
+ tp->t_winsize.ws_col
+ = sc->console[SC_VTY(dev) - sc->first_vty]->xsize;
+ tp->t_winsize.ws_row
+ = sc->console[SC_VTY(dev) - sc->first_vty]->ysize;
+ }
}
return ((*linesw[tp->t_line].l_open)(dev, tp));
}
@@ -738,13 +542,29 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
{
struct tty *tp = scdevtotty(dev);
struct scr_stat *scp;
+ int s;
if (!tp)
return(ENXIO);
- if (minor(dev) < MAXCONS) {
+ if ((SC_VTY(dev) != SC_CONSOLECTL) && (SC_VTY(dev) != SC_MOUSE)) {
scp = sc_get_scr_stat(tp->t_dev);
- if (scp->status & SWITCH_WAIT_ACQ)
- wakeup((caddr_t)&scp->smode);
+ /* were we in the middle of the VT switching process? */
+ DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit));
+ s = spltty();
+ if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit))
+ cons_unavail = FALSE;
+ if (scp->status & SWITCH_WAIT_REL) {
+ /* assert(scp == scp->sc->cur_scp) */
+ DPRINTF(5, ("reset WAIT_REL, "));
+ scp->status &= ~SWITCH_WAIT_REL;
+ do_switch_scr(scp->sc, s);
+ }
+ if (scp->status & SWITCH_WAIT_ACQ) {
+ /* assert(scp == scp->sc->cur_scp) */
+ DPRINTF(5, ("reset WAIT_ACQ, "));
+ scp->status &= ~SWITCH_WAIT_ACQ;
+ scp->sc->switch_in_progress = 0;
+ }
#if not_yet_done
if (scp == &main_console) {
scp->pid = 0;
@@ -752,22 +572,25 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
scp->smode.mode = VT_AUTO;
}
else {
- free(scp->scr_buf, M_DEVBUF);
+ sc_vtb_destroy(&scp->vtb);
+ sc_vtb_destroy(&scp->scr);
if (scp->history != NULL) {
+ /* XXX not quite correct */
+ sc_vtb_destroy(scp->history);
free(scp->history, M_DEVBUF);
- if (scp->history_size / scp->xsize
- > imax(sc_history_size, scp->ysize))
- extra_history_size += scp->history_size / scp->xsize
- - imax(sc_history_size, scp->ysize);
}
free(scp, M_DEVBUF);
- console[minor(dev)] = NULL;
+ sc->console[SC_VTY(dev) - sc->first_vty] = NULL;
}
#else
scp->pid = 0;
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
#endif
+ scp->kbd_mode = K_XLATE;
+ if (scp == scp->sc->cur_scp)
+ kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
+ DPRINTF(5, ("done.\n"));
}
spltty();
(*linesw[tp->t_line].l_close)(tp, flag);
@@ -800,19 +623,21 @@ scwrite(dev_t dev, struct uio *uio, int flag)
static int
sckbdevent(keyboard_t *thiskbd, int event, void *arg)
{
- static struct tty *cur_tty;
+ sc_softc_t *sc;
+ struct tty *cur_tty;
int c;
size_t len;
u_char *cp;
- /* assert(thiskbd == kbd) */
+ sc = (sc_softc_t *)arg;
+ /* assert(thiskbd == sc->kbd) */
switch (event) {
case KBDIO_KEYINPUT:
break;
case KBDIO_UNLOADING:
- kbd = NULL;
- kbd_release(thiskbd, (void *)&keyboard);
+ sc->kbd = NULL;
+ kbd_release(thiskbd, (void *)&sc->keyboard);
return 0;
default:
return EINVAL;
@@ -823,9 +648,10 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
* I don't think this is nessesary, and it doesn't fix
* the Xaccel-2.1 keyboard hang, but it can't hurt. XXX
*/
- while ((c = scgetc(thiskbd, SCGETC_NONBLOCK)) != NOKEY) {
+ while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) {
- cur_tty = VIRTUAL_TTY(get_scr_num());
+ cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index);
+ /* XXX */
if (!(cur_tty->t_state & TS_ISOPEN))
if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN))
continue;
@@ -853,10 +679,12 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
}
}
- if (cur_console->status & MOUSE_VISIBLE) {
- remove_mouse_image(cur_console);
- cur_console->status &= ~MOUSE_VISIBLE;
+#ifndef SC_NO_CUTPASTE
+ if (sc->cur_scp->status & MOUSE_VISIBLE) {
+ sc_remove_mouse_image(sc->cur_scp);
+ sc->cur_scp->status &= ~MOUSE_VISIBLE;
}
+#endif /* SC_NO_CUTPASTE */
return 0;
}
@@ -873,17 +701,16 @@ scparam(struct tty *tp, struct termios *t)
int
scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
- u_int delta_ehs;
int error;
int i;
struct tty *tp;
+ sc_softc_t *sc;
scr_stat *scp;
int s;
tp = scdevtotty(dev);
if (!tp)
return ENXIO;
- scp = sc_get_scr_stat(tp->t_dev);
/* If there is a user_ioctl function call that first */
if (sc_user_ioctl) {
@@ -896,6 +723,32 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
if (error != ENOIOCTL)
return error;
+#ifndef SC_NO_HISTORY
+ error = sc_hist_ioctl(tp, cmd, data, flag, p);
+ if (error != ENOIOCTL)
+ return error;
+#endif
+
+#ifndef SC_NO_SYSMOUSE
+ error = sc_mouse_ioctl(tp, cmd, data, flag, p);
+ if (error != ENOIOCTL)
+ return error;
+ if (SC_VTY(dev) == SC_MOUSE) {
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error != ENOIOCTL)
+ return error;
+ error = ttioctl(tp, cmd, data, flag);
+ if (error != ENOIOCTL)
+ return error;
+ return ENOTTY;
+ }
+#endif
+
+ scp = sc_get_scr_stat(tp->t_dev);
+ /* assert(scp != NULL) */
+ /* scp is sc_console, if SC_VTY(dev) == SC_CONSOLECTL. */
+ sc = scp->sc;
+
switch (cmd) { /* process console hardware related ioctl's */
case GIO_ATTR: /* get current attributes */
@@ -903,7 +756,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return 0;
case GIO_COLOR: /* is this a color console ? */
- *(int *)data = (scp->adp->va_flags & V_ADP_COLOR) ? 1 : 0;
+ *(int *)data = (sc->adp->va_flags & V_ADP_COLOR) ? 1 : 0;
return 0;
case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
@@ -916,461 +769,44 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return 0;
case CONS_CURSORTYPE: /* set cursor type blink/noblink */
+ if (!ISGRAPHSC(sc->cur_scp))
+ remove_cursor_image(sc->cur_scp);
if ((*(int*)data) & 0x01)
- sc_flags |= BLINK_CURSOR;
+ sc->flags |= SC_BLINK_CURSOR;
else
- sc_flags &= ~BLINK_CURSOR;
+ sc->flags &= ~SC_BLINK_CURSOR;
if ((*(int*)data) & 0x02) {
- if (!ISFONTAVAIL(scp->adp->va_flags))
- return ENXIO;
- sc_flags |= CHAR_CURSOR;
+ sc->flags |= SC_CHAR_CURSOR;
} else
- sc_flags &= ~CHAR_CURSOR;
+ sc->flags &= ~SC_CHAR_CURSOR;
/*
* The cursor shape is global property; all virtual consoles
* are affected. Update the cursor in the current console...
*/
- if (!ISGRAPHSC(cur_console)) {
+ if (!ISGRAPHSC(sc->cur_scp)) {
s = spltty();
- remove_cursor_image(cur_console);
- if (sc_flags & CHAR_CURSOR)
- set_destructive_cursor(cur_console);
- draw_cursor_image(cur_console);
+ sc_set_cursor_image(sc->cur_scp);
+ draw_cursor_image(sc->cur_scp);
splx(s);
}
return 0;
case CONS_BELLTYPE: /* set bell type sound/visual */
if ((*(int *)data) & 0x01)
- sc_flags |= VISUAL_BELL;
+ sc->flags |= SC_VISUAL_BELL;
else
- sc_flags &= ~VISUAL_BELL;
+ sc->flags &= ~SC_VISUAL_BELL;
if ((*(int *)data) & 0x02)
- sc_flags |= QUIET_BELL;
- else
- sc_flags &= ~QUIET_BELL;
- return 0;
-
- case CONS_HISTORY: /* set history size */
- if (*(int *)data > 0) {
- int lines; /* buffer size to allocate */
- int lines0; /* current buffer size */
-
- lines = imax(*(int *)data, scp->ysize);
- lines0 = (scp->history != NULL) ?
- scp->history_size / scp->xsize : scp->ysize;
- if (lines0 > imax(sc_history_size, scp->ysize))
- delta_ehs = lines0 - imax(sc_history_size, scp->ysize);
- else
- delta_ehs = 0;
- /*
- * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
- * lines or scp->ysize lines, whichever is larger. A value
- * greater than that is allowed, subject to extra_history_size.
- */
- if (lines > imax(sc_history_size, scp->ysize))
- if (lines - imax(sc_history_size, scp->ysize) >
- extra_history_size + delta_ehs)
- return EINVAL;
- if (cur_console->status & BUFFER_SAVED)
- return EBUSY;
- sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE);
- return 0;
- }
+ sc->flags |= SC_QUIET_BELL;
else
- return EINVAL;
-
- case CONS_MOUSECTL: /* control mouse arrow */
- case OLD_CONS_MOUSECTL:
- {
- /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
- static int butmap[8] = {
- MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
- MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
- MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
- MOUSE_MSC_BUTTON3UP,
- MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
- MOUSE_MSC_BUTTON2UP,
- MOUSE_MSC_BUTTON1UP,
- 0,
- };
- mouse_info_t *mouse = (mouse_info_t*)data;
- mouse_info_t buf;
-
- /* FIXME: */
- if (!ISMOUSEAVAIL(scp->adp->va_flags))
- return ENODEV;
-
- if (cmd == OLD_CONS_MOUSECTL) {
- static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
- old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
-
- mouse = &buf;
- mouse->operation = old_mouse->operation;
- switch (mouse->operation) {
- case MOUSE_MODE:
- mouse->u.mode = old_mouse->u.mode;
- break;
- case MOUSE_SHOW:
- case MOUSE_HIDE:
- break;
- case MOUSE_MOVEABS:
- case MOUSE_MOVEREL:
- case MOUSE_ACTION:
- mouse->u.data.x = old_mouse->u.data.x;
- mouse->u.data.y = old_mouse->u.data.y;
- mouse->u.data.z = 0;
- mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
- break;
- case MOUSE_GETINFO:
- old_mouse->u.data.x = scp->mouse_xpos;
- old_mouse->u.data.y = scp->mouse_ypos;
- old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
- break;
- default:
- return EINVAL;
- }
- }
-
- switch (mouse->operation) {
- case MOUSE_MODE:
- if (ISSIGVALID(mouse->u.mode.signal)) {
- scp->mouse_signal = mouse->u.mode.signal;
- scp->mouse_proc = p;
- scp->mouse_pid = p->p_pid;
- }
- else {
- scp->mouse_signal = 0;
- scp->mouse_proc = NULL;
- scp->mouse_pid = 0;
- }
- return 0;
-
- case MOUSE_SHOW:
- if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
- scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
- scp->mouse_oldpos = scp->mouse_pos;
- mark_all(scp);
- return 0;
- }
- else
- return EINVAL;
- break;
-
- case MOUSE_HIDE:
- if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
- scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
- mark_all(scp);
- return 0;
- }
- else
- return EINVAL;
- break;
-
- case MOUSE_MOVEABS:
- scp->mouse_xpos = mouse->u.data.x;
- scp->mouse_ypos = mouse->u.data.y;
- set_mouse_pos(scp);
- break;
-
- case MOUSE_MOVEREL:
- scp->mouse_xpos += mouse->u.data.x;
- scp->mouse_ypos += mouse->u.data.y;
- set_mouse_pos(scp);
- break;
-
- case MOUSE_GETINFO:
- mouse->u.data.x = scp->mouse_xpos;
- mouse->u.data.y = scp->mouse_ypos;
- mouse->u.data.z = 0;
- mouse->u.data.buttons = scp->mouse_buttons;
- return 0;
-
- case MOUSE_ACTION:
- case MOUSE_MOTION_EVENT:
- /* this should maybe only be settable from /dev/consolectl SOS */
- /* send out mouse event on /dev/sysmouse */
-
- mouse_status.dx += mouse->u.data.x;
- mouse_status.dy += mouse->u.data.y;
- mouse_status.dz += mouse->u.data.z;
- if (mouse->operation == MOUSE_ACTION)
- mouse_status.button = mouse->u.data.buttons;
- mouse_status.flags |=
- ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
- MOUSE_POSCHANGED : 0)
- | (mouse_status.obutton ^ mouse_status.button);
- if (mouse_status.flags == 0)
- return 0;
-
- if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
- cur_console->status |= MOUSE_VISIBLE;
-
- if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
- u_char buf[MOUSE_SYS_PACKETSIZE];
- int j;
-
- /* the first five bytes are compatible with MouseSystems' */
- buf[0] = MOUSE_MSC_SYNC
- | butmap[mouse_status.button & MOUSE_STDBUTTONS];
- j = imax(imin(mouse->u.data.x, 255), -256);
- buf[1] = j >> 1;
- buf[3] = j - buf[1];
- j = -imax(imin(mouse->u.data.y, 255), -256);
- buf[2] = j >> 1;
- buf[4] = j - buf[2];
- for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++)
- (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
- if (mouse_level >= 1) { /* extended part */
- j = imax(imin(mouse->u.data.z, 127), -128);
- buf[5] = (j >> 1) & 0x7f;
- buf[6] = (j - (j >> 1)) & 0x7f;
- /* buttons 4-10 */
- buf[7] = (~mouse_status.button >> 3) & 0x7f;
- for (j = MOUSE_MSC_PACKETSIZE;
- j < MOUSE_SYS_PACKETSIZE; j++)
- (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
- }
- }
-
- if (cur_console->mouse_signal) {
- cur_console->mouse_buttons = mouse->u.data.buttons;
- /* has controlling process died? */
- if (cur_console->mouse_proc &&
- (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
- cur_console->mouse_signal = 0;
- cur_console->mouse_proc = NULL;
- cur_console->mouse_pid = 0;
- }
- else
- psignal(cur_console->mouse_proc, cur_console->mouse_signal);
- }
- else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
- /* process button presses */
- if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) &&
- ISTEXTSC(cur_console)) {
- cur_console->mouse_buttons = mouse->u.data.buttons;
- if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
- mouse_cut_start(cur_console);
- else
- mouse_cut_end(cur_console);
- if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN ||
- cur_console->mouse_buttons & MOUSE_BUTTON3DOWN)
- mouse_paste(cur_console);
- }
- }
-
- if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
- cur_console->mouse_xpos += mouse->u.data.x;
- cur_console->mouse_ypos += mouse->u.data.y;
- set_mouse_pos(cur_console);
- }
-
- break;
-
- case MOUSE_BUTTON_EVENT:
- if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
- return EINVAL;
- if (mouse->u.event.value < 0)
- return EINVAL;
-
- if (mouse->u.event.value > 0) {
- cur_console->mouse_buttons |= mouse->u.event.id;
- mouse_status.button |= mouse->u.event.id;
- } else {
- cur_console->mouse_buttons &= ~mouse->u.event.id;
- mouse_status.button &= ~mouse->u.event.id;
- }
- mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
- if (mouse_status.flags == 0)
- return 0;
-
- if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
- cur_console->status |= MOUSE_VISIBLE;
-
- if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
- u_char buf[8];
- int i;
-
- buf[0] = MOUSE_MSC_SYNC
- | butmap[mouse_status.button & MOUSE_STDBUTTONS];
- buf[7] = (~mouse_status.button >> 3) & 0x7f;
- buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
- for (i = 0;
- i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
- : MOUSE_MSC_PACKETSIZE); i++)
- (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY);
- }
-
- if (cur_console->mouse_signal) {
- if (cur_console->mouse_proc &&
- (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
- cur_console->mouse_signal = 0;
- cur_console->mouse_proc = NULL;
- cur_console->mouse_pid = 0;
- }
- else
- psignal(cur_console->mouse_proc, cur_console->mouse_signal);
- break;
- }
-
- if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
- break;
-
- switch (mouse->u.event.id) {
- case MOUSE_BUTTON1DOWN:
- switch (mouse->u.event.value % 4) {
- case 0: /* up */
- mouse_cut_end(cur_console);
- break;
- case 1:
- mouse_cut_start(cur_console);
- break;
- case 2:
- mouse_cut_word(cur_console);
- break;
- case 3:
- mouse_cut_line(cur_console);
- break;
- }
- break;
- case MOUSE_BUTTON2DOWN:
- switch (mouse->u.event.value) {
- case 0: /* up */
- break;
- default:
- mouse_paste(cur_console);
- break;
- }
- break;
- case MOUSE_BUTTON3DOWN:
- switch (mouse->u.event.value) {
- case 0: /* up */
- if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN))
- mouse_cut_end(cur_console);
- break;
- default:
- mouse_cut_extend(cur_console);
- break;
- }
- break;
- }
- break;
-
- default:
- return EINVAL;
- }
- /* make screensaver happy */
- sc_touch_scrn_saver();
- return 0;
- }
-
- /* MOUSE_XXX: /dev/sysmouse ioctls */
- case MOUSE_GETHWINFO: /* get device information */
- {
- mousehw_t *hw = (mousehw_t *)data;
-
- if (tp != MOUSE_TTY)
- return ENOTTY;
- hw->buttons = 10; /* XXX unknown */
- hw->iftype = MOUSE_IF_SYSMOUSE;
- hw->type = MOUSE_MOUSE;
- hw->model = MOUSE_MODEL_GENERIC;
- hw->hwid = 0;
+ sc->flags &= ~SC_QUIET_BELL;
return 0;
- }
-
- case MOUSE_GETMODE: /* get protocol/mode */
- {
- mousemode_t *mode = (mousemode_t *)data;
-
- if (tp != MOUSE_TTY)
- return ENOTTY;
- mode->level = mouse_level;
- switch (mode->level) {
- case 0:
- /* at this level, sysmouse emulates MouseSystems protocol */
- mode->protocol = MOUSE_PROTO_MSC;
- mode->rate = -1; /* unknown */
- mode->resolution = -1; /* unknown */
- mode->accelfactor = 0; /* disabled */
- mode->packetsize = MOUSE_MSC_PACKETSIZE;
- mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
- mode->syncmask[1] = MOUSE_MSC_SYNC;
- break;
-
- case 1:
- /* at this level, sysmouse uses its own protocol */
- mode->protocol = MOUSE_PROTO_SYSMOUSE;
- mode->rate = -1;
- mode->resolution = -1;
- mode->accelfactor = 0;
- mode->packetsize = MOUSE_SYS_PACKETSIZE;
- mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
- mode->syncmask[1] = MOUSE_SYS_SYNC;
- break;
- }
- return 0;
- }
-
- case MOUSE_SETMODE: /* set protocol/mode */
- {
- mousemode_t *mode = (mousemode_t *)data;
-
- if (tp != MOUSE_TTY)
- return ENOTTY;
- if ((mode->level < 0) || (mode->level > 1))
- return EINVAL;
- mouse_level = mode->level;
- return 0;
- }
-
- case MOUSE_GETLEVEL: /* get operation level */
- if (tp != MOUSE_TTY)
- return ENOTTY;
- *(int *)data = mouse_level;
- return 0;
-
- case MOUSE_SETLEVEL: /* set operation level */
- if (tp != MOUSE_TTY)
- return ENOTTY;
- if ((*(int *)data < 0) || (*(int *)data > 1))
- return EINVAL;
- mouse_level = *(int *)data;
- return 0;
-
- case MOUSE_GETSTATUS: /* get accumulated mouse events */
- if (tp != MOUSE_TTY)
- return ENOTTY;
- s = spltty();
- *(mousestatus_t *)data = mouse_status;
- mouse_status.flags = 0;
- mouse_status.obutton = mouse_status.button;
- mouse_status.dx = 0;
- mouse_status.dy = 0;
- mouse_status.dz = 0;
- splx(s);
- return 0;
-
-#if notyet
- case MOUSE_GETVARS: /* get internal mouse variables */
- case MOUSE_SETVARS: /* set internal mouse variables */
- if (tp != MOUSE_TTY)
- return ENOTTY;
- return ENODEV;
-#endif
-
- case MOUSE_READSTATE: /* read status from the device */
- case MOUSE_READDATA: /* read data from the device */
- if (tp != MOUSE_TTY)
- return ENOTTY;
- return ENODEV;
case CONS_GETINFO: /* get current (virtual) console info */
{
vid_info_t *ptr = (vid_info_t*)data;
if (ptr->size == sizeof(struct vid_info)) {
- ptr->m_num = get_scr_num();
+ ptr->m_num = sc->cur_scp->index;
ptr->mv_col = scp->xpos;
ptr->mv_row = scp->ypos;
ptr->mv_csz = scp->xsize;
@@ -1382,7 +818,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
ptr->mv_grfc.fore = 0; /* not supported */
ptr->mv_grfc.back = 0; /* not supported */
ptr->mv_ovscan = scp->border;
- if (scp == cur_console)
+ if (scp == sc->cur_scp)
save_kbd_state(scp);
ptr->mk_keylock = scp->status & LOCK_MASK;
return 0;
@@ -1404,9 +840,9 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
* graphics mode in the current screen, we should say that the
* screen has been idle.
*/
- *(int *)data = scrn_idle
- && (!ISGRAPHSC(cur_console)
- || (cur_console->status & SAVER_RUNNING));
+ *(int *)data = (sc->flags & SC_SCRN_IDLE)
+ && (!ISGRAPHSC(sc->cur_scp)
+ || (sc->cur_scp->status & SAVER_RUNNING));
return 0;
case CONS_SAVERMODE: /* set saver mode */
@@ -1416,10 +852,13 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
scsplash_stick(FALSE);
saver_mode = *(int *)data;
s = spltty();
- if ((error = wait_scrn_saver_stop())) {
+#if NSPLASH > 0
+ if ((error = wait_scrn_saver_stop(NULL))) {
splx(s);
return error;
}
+#endif /* NSPLASH */
+ run_scrn_saver = TRUE;
scp->status |= SAVER_RUNNING;
scsplash_stick(TRUE);
splx(s);
@@ -1444,7 +883,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
s = spltty();
run_scrn_saver = (*(int *)data != 0);
if (run_scrn_saver)
- scrn_time_stamp -= scrn_blank_time;
+ sc->scrn_time_stamp -= scrn_blank_time;
splx(s);
return 0;
@@ -1453,16 +892,51 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
struct vt_mode *mode;
mode = (struct vt_mode *)data;
- if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) &&
- ISSIGVALID(mode->frsig)) {
- bcopy(data, &scp->smode, sizeof(struct vt_mode));
- if (scp->smode.mode == VT_PROCESS) {
- scp->proc = p;
- scp->pid = scp->proc->p_pid;
+ DPRINTF(5, ("sc%d: VT_SETMODE ", sc->unit));
+ if (scp->smode.mode == VT_PROCESS) {
+ if (scp->proc == pfind(scp->pid) && scp->proc != p) {
+ DPRINTF(5, ("error EPERM\n"));
+ return EPERM;
}
- return 0;
- } else
- return EINVAL;
+ }
+ s = spltty();
+ if (mode->mode == VT_AUTO) {
+ scp->smode.mode = VT_AUTO;
+ scp->proc = NULL;
+ scp->pid = 0;
+ DPRINTF(5, ("VT_AUTO, "));
+ if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
+ cons_unavail = FALSE;
+ /* were we in the middle of the vty switching process? */
+ if (scp->status & SWITCH_WAIT_REL) {
+ /* assert(scp == scp->sc->cur_scp) */
+ DPRINTF(5, ("reset WAIT_REL, "));
+ scp->status &= ~SWITCH_WAIT_REL;
+ s = do_switch_scr(sc, s);
+ }
+ if (scp->status & SWITCH_WAIT_ACQ) {
+ /* assert(scp == scp->sc->cur_scp) */
+ DPRINTF(5, ("reset WAIT_ACQ, "));
+ scp->status &= ~SWITCH_WAIT_ACQ;
+ sc->switch_in_progress = 0;
+ }
+ } else {
+ if (!ISSIGVALID(mode->relsig) || !ISSIGVALID(mode->acqsig)
+ || !ISSIGVALID(mode->frsig)) {
+ splx(s);
+ DPRINTF(5, ("error EINVAL\n"));
+ return EINVAL;
+ }
+ DPRINTF(5, ("VT_PROCESS %d, ", p->p_pid));
+ bcopy(data, &scp->smode, sizeof(struct vt_mode));
+ scp->proc = p;
+ scp->pid = scp->proc->p_pid;
+ if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
+ cons_unavail = TRUE;
+ }
+ splx(s);
+ DPRINTF(5, ("\n"));
+ return 0;
}
case VT_GETMODE: /* get screen switcher mode */
@@ -1470,45 +944,58 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return 0;
case VT_RELDISP: /* screen switcher ioctl */
+ s = spltty();
+ /*
+ * This must be the current vty which is in the VT_PROCESS
+ * switching mode...
+ */
+ if ((scp != sc->cur_scp) || (scp->smode.mode != VT_PROCESS)) {
+ splx(s);
+ return EINVAL;
+ }
+ /* ...and this process is controlling it. */
+ if (scp->proc != p) {
+ splx(s);
+ return EPERM;
+ }
+ error = EINVAL;
switch(*(int *)data) {
case VT_FALSE: /* user refuses to release screen, abort */
- if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
- old_scp->status &= ~SWITCH_WAIT_REL;
- switch_in_progress = FALSE;
- return 0;
+ if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) {
+ sc->old_scp->status &= ~SWITCH_WAIT_REL;
+ sc->switch_in_progress = 0;
+ DPRINTF(5, ("sc%d: VT_FALSE\n", sc->unit));
+ error = 0;
}
- return EINVAL;
+ break;
case VT_TRUE: /* user has released screen, go on */
- if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
+ if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) {
scp->status &= ~SWITCH_WAIT_REL;
- exchange_scr();
- if (new_scp->smode.mode == VT_PROCESS) {
- new_scp->status |= SWITCH_WAIT_ACQ;
- psignal(new_scp->proc, new_scp->smode.acqsig);
- }
- else
- switch_in_progress = FALSE;
- return 0;
+ s = do_switch_scr(sc, s);
+ DPRINTF(5, ("sc%d: VT_TRUE\n", sc->unit));
+ error = 0;
}
- return EINVAL;
+ break;
case VT_ACKACQ: /* acquire acknowledged, switch completed */
- if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
+ if ((scp == sc->new_scp) && (scp->status & SWITCH_WAIT_ACQ)) {
scp->status &= ~SWITCH_WAIT_ACQ;
- switch_in_progress = FALSE;
- return 0;
+ sc->switch_in_progress = 0;
+ DPRINTF(5, ("sc%d: VT_ACKACQ\n", sc->unit));
+ error = 0;
}
- return EINVAL;
+ break;
default:
- return EINVAL;
+ break;
}
- /* NOT REACHED */
+ splx(s);
+ return error;
case VT_OPENQRY: /* return free virtual console */
- for (i = 0; i < MAXCONS; i++) {
- tp = VIRTUAL_TTY(i);
+ for (i = sc->first_vty; i < sc->first_vty + sc->vtys; i++) {
+ tp = VIRTUAL_TTY(sc, i);
if (!(tp->t_state & TS_ISOPEN)) {
*(int *)data = i + 1;
return 0;
@@ -1518,32 +1005,33 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case VT_ACTIVATE: /* switch to screen *data */
s = spltty();
- sc_clean_up(cur_console);
+ sc_clean_up(sc->cur_scp);
splx(s);
- return switch_scr(scp, *(int *)data - 1);
+ return switch_scr(sc, *(int *)data - 1);
case VT_WAITACTIVE: /* wait for switch to occur */
- if (*(int *)data > MAXCONS || *(int *)data < 0)
+ if ((*(int *)data >= sc->first_vty + sc->vtys)
+ || (*(int *)data < sc->first_vty))
return EINVAL;
s = spltty();
- error = sc_clean_up(cur_console);
+ error = sc_clean_up(sc->cur_scp);
splx(s);
if (error)
return error;
- if (minor(dev) == *(int *)data - 1)
+ if (*(int *)data != 0)
+ scp = sc->console[*(int *)data - 1 - sc->first_vty];
+ if (scp == scp->sc->cur_scp)
return 0;
- if (*(int *)data == 0) {
- if (scp == cur_console)
- return 0;
- }
- else
- scp = console[*(int *)data - 1];
while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
"waitvt", 0)) == ERESTART) ;
return error;
- case VT_GETACTIVE:
- *(int *)data = get_scr_num()+1;
+ case VT_GETACTIVE: /* get active vty # */
+ *(int *)data = sc->cur_scp->index + 1;
+ return 0;
+
+ case VT_GETINDEX: /* get this vty # */
+ *(int *)data = scp->index + 1;
return 0;
case KDENABIO: /* allow io operations */
@@ -1568,18 +1056,18 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
scp->status &= ~LOCK_MASK;
scp->status |= *(int *)data;
- if (scp == cur_console)
- update_kbd_state(scp->status, LOCK_MASK);
+ if (scp == sc->cur_scp)
+ update_kbd_state(scp, scp->status, LOCK_MASK);
return 0;
case KDGKBSTATE: /* get keyboard state (locks) */
- if (scp == cur_console)
+ if (scp == sc->cur_scp)
save_kbd_state(scp);
*(int *)data = scp->status & LOCK_MASK;
return 0;
case KDSETREPEAT: /* set keyboard repeat & delay rates (new) */
- error = kbd_ioctl(kbd, cmd, data);
+ error = kbd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL)
error = ENODEV;
return error;
@@ -1587,7 +1075,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case KDSETRAD: /* set keyboard repeat & delay rates (old) */
if (*(int *)data & ~0x7f)
return EINVAL;
- error = kbd_ioctl(kbd, cmd, data);
+ error = kbd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL)
error = ENODEV;
return error;
@@ -1598,8 +1086,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case K_RAW: /* switch to RAW scancode mode */
case K_CODE: /* switch to CODE mode */
scp->kbd_mode = *(int *)data;
- if (scp == cur_console)
- kbd_ioctl(kbd, cmd, data);
+ if (scp == sc->cur_scp)
+ kbd_ioctl(sc->kbd, cmd, data);
return 0;
default:
return EINVAL;
@@ -1611,7 +1099,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return 0;
case KDGKBINFO:
- error = kbd_ioctl(kbd, cmd, data);
+ error = kbd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL)
error = ENODEV;
return error;
@@ -1625,33 +1113,16 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return 0;
case KIOCSOUND: /* make tone (*data) hz */
-#ifdef __i386__
- if (scp == cur_console) {
- if (*(int*)data) {
- int pitch = timer_freq / *(int*)data;
-
- /* set command for counter 2, 2 byte write */
- if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE))
- return EBUSY;
-
- /* set pitch */
- outb(TIMER_CNTR2, pitch);
- outb(TIMER_CNTR2, (pitch>>8));
-
- /* enable counter 2 output to speaker */
- outb(IO_PPI, inb(IO_PPI) | 3);
- }
- else {
- /* disable counter 2 output to speaker */
- outb(IO_PPI, inb(IO_PPI) & 0xFC);
- release_timer2();
- }
+ if (scp == sc->cur_scp) {
+ if (*(int *)data)
+ return sc_tone(*(int *)data);
+ else
+ return sc_tone(0);
}
-#endif /* __i386__ */
return 0;
case KDGKBTYPE: /* get keyboard type */
- error = kbd_ioctl(kbd, cmd, data);
+ error = kbd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL) {
/* always return something? XXX */
*(int *)data = 0;
@@ -1663,12 +1134,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
scp->status &= ~LED_MASK;
scp->status |= *(int *)data;
- if (scp == cur_console)
- update_kbd_leds(scp->status);
+ if (scp == sc->cur_scp)
+ update_kbd_leds(scp, scp->status);
return 0;
case KDGETLED: /* get keyboard LED status */
- if (scp == cur_console)
+ if (scp == sc->cur_scp)
save_kbd_state(scp);
*(int *)data = scp->status & LED_MASK;
return 0;
@@ -1684,19 +1155,21 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
}
error = 0;
- if (kbd != newkbd) {
+ if (sc->kbd != newkbd) {
i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit,
- (void *)&keyboard, sckbdevent, NULL);
+ (void *)&sc->keyboard, sckbdevent, sc);
/* i == newkbd->kb_index */
if (i >= 0) {
- if (kbd != NULL) {
- save_kbd_state(cur_console);
- kbd_release(kbd, (void *)&keyboard);
+ if (sc->kbd != NULL) {
+ save_kbd_state(sc->cur_scp);
+ kbd_release(sc->kbd, (void *)&sc->keyboard);
}
- kbd = kbd_get_keyboard(i); /* kbd == newkbd */
- keyboard = i;
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode);
- update_kbd_state(cur_console->status, LOCK_MASK);
+ sc->kbd = kbd_get_keyboard(i); /* sc->kbd == newkbd */
+ sc->keyboard = i;
+ kbd_ioctl(sc->kbd, KDSKBMODE,
+ (caddr_t)&sc->cur_scp->kbd_mode);
+ update_kbd_state(sc->cur_scp, sc->cur_scp->status,
+ LOCK_MASK);
} else {
error = EPERM; /* XXX */
}
@@ -1708,25 +1181,26 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case CONS_RELKBD: /* release the current keyboard */
s = spltty();
error = 0;
- if (kbd != NULL) {
- save_kbd_state(cur_console);
- error = kbd_release(kbd, (void *)&keyboard);
+ if (sc->kbd != NULL) {
+ save_kbd_state(sc->cur_scp);
+ error = kbd_release(sc->kbd, (void *)&sc->keyboard);
if (error == 0) {
- kbd = NULL;
- keyboard = -1;
+ sc->kbd = NULL;
+ sc->keyboard = -1;
}
}
splx(s);
return error;
case GIO_SCRNMAP: /* get output translation table */
- bcopy(&scr_map, data, sizeof(scr_map));
+ bcopy(&sc->scr_map, data, sizeof(sc->scr_map));
return 0;
case PIO_SCRNMAP: /* set output translation table */
- bcopy(data, &scr_map, sizeof(scr_map));
- for (i=0; i<sizeof(scr_map); i++)
- scr_rmap[scr_map[i]] = i;
+ bcopy(data, &sc->scr_map, sizeof(sc->scr_map));
+ for (i=0; i<sizeof(sc->scr_map); i++) {
+ sc->scr_rmap[sc->scr_map[i]] = i;
+ }
return 0;
case GIO_KEYMAP: /* get keyboard translation table */
@@ -1735,83 +1209,89 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case PIO_DEADKEYMAP: /* set accent key translation table */
case GETFKEY: /* get function key string */
case SETFKEY: /* set function key string */
- error = kbd_ioctl(kbd, cmd, data);
+ error = kbd_ioctl(sc->kbd, cmd, data);
if (error == ENOIOCTL)
error = ENODEV;
return error;
+#ifndef SC_NO_FONT_LOADING
+
case PIO_FONT8x8: /* set 8x8 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- bcopy(data, font_8, 8*256);
- fonts_loaded |= FONT_8;
+ bcopy(data, sc->font_8, 8*256);
+ sc->fonts_loaded |= FONT_8;
/*
* FONT KLUDGE
* Always use the font page #0. XXX
* Don't load if the current font size is not 8x8.
*/
- if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
- copy_font(cur_console, LOAD, 8, font_8);
+ if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
+ copy_font(sc->cur_scp, LOAD, 8, sc->font_8);
return 0;
case GIO_FONT8x8: /* get 8x8 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- if (fonts_loaded & FONT_8) {
- bcopy(font_8, data, 8*256);
+ if (sc->fonts_loaded & FONT_8) {
+ bcopy(sc->font_8, data, 8*256);
return 0;
}
else
return ENXIO;
case PIO_FONT8x14: /* set 8x14 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- bcopy(data, font_14, 14*256);
- fonts_loaded |= FONT_14;
+ bcopy(data, sc->font_14, 14*256);
+ sc->fonts_loaded |= FONT_14;
/*
* FONT KLUDGE
* Always use the font page #0. XXX
* Don't load if the current font size is not 8x14.
*/
- if (ISTEXTSC(cur_console)
- && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
- copy_font(cur_console, LOAD, 14, font_14);
+ if (ISTEXTSC(sc->cur_scp)
+ && (sc->cur_scp->font_size >= 14)
+ && (sc->cur_scp->font_size < 16))
+ copy_font(sc->cur_scp, LOAD, 14, sc->font_14);
return 0;
case GIO_FONT8x14: /* get 8x14 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- if (fonts_loaded & FONT_14) {
- bcopy(font_14, data, 14*256);
+ if (sc->fonts_loaded & FONT_14) {
+ bcopy(sc->font_14, data, 14*256);
return 0;
}
else
return ENXIO;
case PIO_FONT8x16: /* set 8x16 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- bcopy(data, font_16, 16*256);
- fonts_loaded |= FONT_16;
+ bcopy(data, sc->font_16, 16*256);
+ sc->fonts_loaded |= FONT_16;
/*
* FONT KLUDGE
* Always use the font page #0. XXX
* Don't load if the current font size is not 8x16.
*/
- if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
- copy_font(cur_console, LOAD, 16, font_16);
+ if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
+ copy_font(sc->cur_scp, LOAD, 16, sc->font_16);
return 0;
case GIO_FONT8x16: /* get 8x16 dot font */
- if (!ISFONTAVAIL(scp->adp->va_flags))
+ if (!ISFONTAVAIL(sc->adp->va_flags))
return ENXIO;
- if (fonts_loaded & FONT_16) {
- bcopy(font_16, data, 16*256);
+ if (sc->fonts_loaded & FONT_16) {
+ bcopy(sc->font_16, data, 16*256);
return 0;
}
else
return ENXIO;
+
+#endif /* SC_NO_FONT_LOADING */
+
default:
break;
}
@@ -1833,8 +1313,8 @@ scstart(struct tty *tp)
u_char buf[PCBURST];
scr_stat *scp = sc_get_scr_stat(tp->t_dev);
- if (scp->status & SLKED || blink_in_progress)
- return; /* XXX who repeats the call when the above flags are cleared? */
+ if (scp->status & SLKED || scp->sc->blink_in_progress)
+ return;
s = spltty();
if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
tp->t_state |= TS_BUSY;
@@ -1871,105 +1351,141 @@ scmousestart(struct tty *tp)
splx(s);
}
-#if __i386__
-
-/* XXX kludge! */
-extern struct isa_driver scdriver;
-
static void
sccnprobe(struct consdev *cp)
{
-#if 0
- struct isa_device *dvp;
+#if __i386__
+ int unit;
+ int flags;
- /*
- * Take control if we are the highest priority enabled display device.
- */
- dvp = find_display();
- if (dvp == NULL || dvp->id_driver != &scdriver) {
- cp->cn_pri = CN_DEAD;
- return;
- }
+ cp->cn_pri = sc_get_cons_priority(&unit, &flags);
- if (!scvidprobe(dvp->id_unit, dvp->id_flags, TRUE)) {
- cp->cn_pri = CN_DEAD;
- return;
- }
- sckbdprobe(dvp->id_unit, dvp->id_flags, TRUE);
-#else
- if (!scvidprobe(0, 0, TRUE)) {
+ /* a video card is always required */
+ if (!scvidprobe(unit, flags, TRUE))
cp->cn_pri = CN_DEAD;
+
+ /* syscons will become console even when there is no keyboard */
+ sckbdprobe(unit, flags, TRUE);
+
+ if (cp->cn_pri == CN_DEAD)
return;
- }
- sckbdprobe(0, 0, TRUE);
-#endif
/* initialize required fields */
- cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE);
- cp->cn_pri = CN_INTERNAL;
+ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLECTL);
+#endif /* __i386__ */
+
+#if __alpha__
+ /*
+ * alpha use sccnattach() rather than cnprobe()/cninit()/cnterm()
+ * interface to install the console. Always return CN_DEAD from
+ * here.
+ */
+ cp->cn_pri = CN_DEAD;
+#endif /* __alpha__ */
}
static void
sccninit(struct consdev *cp)
{
- scinit();
+#if __i386__
+ int unit;
+ int flags;
+
+ sc_get_cons_priority(&unit, &flags);
+ scinit(unit, flags | SC_KERNEL_CONSOLE);
+ sc_console_unit = unit;
+ sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console[0];
+#endif /* __i386__ */
+
+#if __alpha__
+ /* SHOULDN'T REACH HERE */
+#endif /* __alpha__ */
+}
+
+static void
+sccnterm(struct consdev *cp)
+{
+ /* we are not the kernel console any more, release everything */
+
+ if (sc_console_unit < 0)
+ return; /* shouldn't happen */
+
+#if __i386__
+#if 0 /* XXX */
+ sc_clear_screen(sc_console);
+ sccnupdate(sc_console);
+#endif
+ scterm(sc_console_unit, SC_KERNEL_CONSOLE);
+ sc_console_unit = -1;
+ sc_console = NULL;
+#endif /* __i386__ */
+
+#if __alpha__
+ /* do nothing XXX */
+#endif /* __alpha__ */
}
-#else /* !__i386__ */
+#ifdef __alpha__
extern struct consdev *cn_tab;
void
sccnattach(void)
{
- if (!scvidprobe(0, 0, TRUE) || !sckbdprobe(0, 0, TRUE)) {
+ static struct consdev consdev;
+ int unit;
+ int flags;
+
+ bcopy(&sc_consdev, &consdev, sizeof(sc_consdev));
+ consdev.cn_pri = sc_get_cons_priority(&unit, &flags);
+
+ /* a video card is always required */
+ if (!scvidprobe(unit, flags, TRUE))
+ consdev.cn_pri = CN_DEAD;
+
+ /* alpha doesn't allow the console being without a keyboard... Why? */
+ if (!sckbdprobe(unit, flags, TRUE))
+ consdev.cn_pri = CN_DEAD;
+
+ if (consdev.cn_pri == CN_DEAD)
return;
- }
- scinit();
- sc_cons.cn_dev = makedev(CDEV_MAJOR, 0);
- cn_tab = &sc_cons;
+ scinit(unit, flags | SC_KERNEL_CONSOLE);
+ sc_console_unit = unit;
+ sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console[0];
+ consdev.cn_dev = makedev(CDEV_MAJOR, 0);
+ cn_tab = &consdev;
}
-#endif /* __i386__ */
+#endif /* __alpha__ */
static void
sccnputc(dev_t dev, int c)
{
u_char buf[1];
- scr_stat *scp = console[0];
+ scr_stat *scp = sc_console;
term_stat save = scp->term;
- u_short *p;
int s;
- int i;
- if (scp == cur_console && scp->status & SLKED) {
+ /* assert(sc_console != NULL) */
+
+#ifndef SC_NO_HISTORY
+ if (scp == scp->sc->cur_scp && scp->status & SLKED) {
scp->status &= ~SLKED;
- update_kbd_state(scp->status, SLKED);
- if (cur_console->status & BUFFER_SAVED) {
- p = cur_console->history_save;
- for (i = 0; i < cur_console->ysize; ++i) {
- bcopy(p, cur_console->scr_buf + (cur_console->xsize*i),
- cur_console->xsize*sizeof(u_short));
- p += cur_console->xsize;
- if (p + cur_console->xsize
- > cur_console->history + cur_console->history_size)
- p = cur_console->history;
- }
- cur_console->status &= ~BUFFER_SAVED;
- cur_console->history_head = cur_console->history_save;
- cur_console->status |= CURSOR_ENABLED;
- mark_all(cur_console);
+ update_kbd_state(scp, scp->status, SLKED);
+ if (scp->status & BUFFER_SAVED) {
+ if (!sc_hist_restore(scp))
+ sc_remove_cutmarking(scp);
+ scp->status &= ~BUFFER_SAVED;
+ scp->status |= CURSOR_ENABLED;
+ draw_cursor_image(scp);
}
-#if 1 /* XXX */
- scstart(VIRTUAL_TTY(get_scr_num()));
-#endif
+ scstart(VIRTUAL_TTY(scp->sc, scp->index));
}
+#endif /* !SC_NO_HISTORY */
scp->term = kernel_console;
current_default = &kernel_default;
- if (scp == cur_console && !ISGRAPHSC(scp))
- remove_cursor_image(scp);
buf[0] = c;
ansi_put(scp, buf, 1);
kernel_console = scp->term;
@@ -1996,18 +1512,30 @@ sccncheckc(dev_t dev)
static int
sccngetch(int flags)
{
+ static struct fkeytab fkey;
+ static int fkeycp;
+ scr_stat *scp;
+ u_char *p;
int cur_mode;
int s = spltty(); /* block sckbdevent and scrn_timer while we poll */
int c;
+ /* assert(sc_console != NULL) */
+
/*
* Stop the screen saver and update the screen if necessary.
* What if we have been running in the screen saver code... XXX
*/
sc_touch_scrn_saver();
- sccnupdate(cur_console);
+ scp = sc_console->sc->cur_scp; /* XXX */
+ sccnupdate(scp);
+
+ if (fkeycp < fkey.len) {
+ splx(s);
+ return fkey.str[fkeycp++];
+ }
- if (kbd == NULL) {
+ if (scp->sc->kbd == NULL) {
splx(s);
return -1;
}
@@ -2016,26 +1544,33 @@ sccngetch(int flags)
* Make sure the keyboard is accessible even when the kbd device
* driver is disabled.
*/
- kbd_enable(kbd);
+ kbd_enable(scp->sc->kbd);
/* we shall always use the keyboard in the XLATE mode here */
- cur_mode = cur_console->kbd_mode;
- cur_console->kbd_mode = K_XLATE;
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode);
+ cur_mode = scp->kbd_mode;
+ scp->kbd_mode = K_XLATE;
+ kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
- kbd_poll(kbd, TRUE);
- c = scgetc(kbd, SCGETC_CN | flags);
- kbd_poll(kbd, FALSE);
+ kbd_poll(scp->sc->kbd, TRUE);
+ c = scgetc(scp->sc, SCGETC_CN | flags);
+ kbd_poll(scp->sc->kbd, FALSE);
- cur_console->kbd_mode = cur_mode;
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode);
- kbd_disable(kbd);
+ scp->kbd_mode = cur_mode;
+ kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
+ kbd_disable(scp->sc->kbd);
splx(s);
switch (KEYFLAGS(c)) {
case 0: /* normal char */
return KEYCHAR(c);
case FKEY: /* function key */
+ p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp);
+ fkey.len = fkeycp;
+ if ((p != NULL) && (fkey.len > 0)) {
+ bcopy(p, fkey.str, fkey.len);
+ fkeycp = 1;
+ return fkey.str[0];
+ }
return c; /* XXX */
case NOKEY:
case ERRKEY:
@@ -2050,23 +1585,30 @@ sccnupdate(scr_stat *scp)
{
/* this is a cut-down version of scrn_timer()... */
- if (font_loading_in_progress)
+ if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress)
return;
- if (panicstr || shutdown_in_progress) {
+ if (debugger || panicstr || shutdown_in_progress) {
sc_touch_scrn_saver();
- } else if (scp != cur_console) {
+ } else if (scp != scp->sc->cur_scp) {
return;
}
if (!run_scrn_saver)
- scrn_idle = FALSE;
- if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
- if (scrn_blanked)
- stop_scrn_saver(current_saver);
+ scp->sc->flags &= ~SC_SCRN_IDLE;
+#if NSPLASH > 0
+ if ((saver_mode != CONS_LKM_SAVER) || !(scp->sc->flags & SC_SCRN_IDLE))
+ if (scp->sc->flags & SC_SCRN_BLANKED)
+ stop_scrn_saver(scp->sc, current_saver);
+#endif /* NSPLASH */
- if (scp != cur_console || blink_in_progress || switch_in_progress)
+ if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress
+ || scp->sc->switch_in_progress)
return;
+ /*
+ * FIXME: unlike scrn_timer(), we call scrn_update() from here even
+ * when write_in_progress is non-zero. XXX
+ */
if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
scrn_update(scp, TRUE);
@@ -2075,23 +1617,22 @@ sccnupdate(scr_stat *scp)
scr_stat
*sc_get_scr_stat(dev_t dev)
{
- int unit = minor(dev);
+ sc_softc_t *sc;
+ int vty = SC_VTY(dev);
+ int unit;
- if (unit == SC_CONSOLE)
- return console[0];
- if (unit >= MAXCONS || unit < 0)
- return(NULL);
- return console[unit];
-}
-
-static int
-get_scr_num()
-{
- int i = 0;
+ if (vty < 0)
+ return NULL;
+ if (vty == SC_CONSOLECTL)
+ return sc_console;
- while ((i < MAXCONS) && (cur_console != console[i]))
- i++;
- return i < MAXCONS ? i : 0;
+ unit = scdevtounit(dev);
+ sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
+ if (sc == NULL)
+ return NULL;
+ if ((sc->first_vty <= vty) && (vty < sc->first_vty + sc->vtys))
+ return sc->console[vty - sc->first_vty];
+ return NULL;
}
static void
@@ -2099,113 +1640,187 @@ scrn_timer(void *arg)
{
static int kbd_interval = 0;
struct timeval tv;
+ sc_softc_t *sc;
scr_stat *scp;
+ int again;
int s;
- /* don't do anything when we are touching font */
- if (font_loading_in_progress) {
- if (arg)
- timeout(scrn_timer, (void *)TRUE, hz / 10);
+ again = (arg != NULL);
+ if (arg != NULL)
+ sc = (sc_softc_t *)arg;
+ else if (sc_console != NULL)
+ sc = sc_console->sc;
+ else
+ return;
+
+ /* don't do anything when we are performing some I/O operations */
+ if (sc->font_loading_in_progress || sc->videoio_in_progress) {
+ if (again)
+ timeout(scrn_timer, sc, hz / 10);
return;
}
s = spltty();
- if ((kbd == NULL) && (sc_flags & AUTODETECT_KBD)) {
+ if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
/* try to allocate a keyboard automatically */
if (++kbd_interval >= 25) {
- keyboard = kbd_allocate("*", -1, (void *)&keyboard,
- sckbdevent, NULL);
- if (keyboard >= 0) {
- kbd = kbd_get_keyboard(keyboard);
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode);
- update_kbd_state(cur_console->status, LOCK_MASK);
+ sc->keyboard = kbd_allocate("*", -1, (void *)&sc->keyboard,
+ sckbdevent, sc);
+ if (sc->keyboard >= 0) {
+ sc->kbd = kbd_get_keyboard(sc->keyboard);
+ kbd_ioctl(sc->kbd, KDSKBMODE,
+ (caddr_t)&sc->cur_scp->kbd_mode);
+ update_kbd_state(sc->cur_scp, sc->cur_scp->status,
+ LOCK_MASK);
}
kbd_interval = 0;
}
}
+ /* find the vty to update */
+ scp = sc->cur_scp;
+
/* should we stop the screen saver? */
getmicrouptime(&tv);
- if (panicstr || shutdown_in_progress)
+ if (debugger || panicstr || shutdown_in_progress)
sc_touch_scrn_saver();
if (run_scrn_saver) {
- scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time);
+ if (tv.tv_sec > sc->scrn_time_stamp + scrn_blank_time)
+ sc->flags |= SC_SCRN_IDLE;
+ else
+ sc->flags &= ~SC_SCRN_IDLE;
} else {
- scrn_time_stamp = tv.tv_sec;
- scrn_idle = FALSE;
+ sc->scrn_time_stamp = tv.tv_sec;
+ sc->flags &= ~SC_SCRN_IDLE;
if (scrn_blank_time > 0)
run_scrn_saver = TRUE;
}
- if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
- if (scrn_blanked)
- stop_scrn_saver(current_saver);
+#if NSPLASH > 0
+ if ((saver_mode != CONS_LKM_SAVER) || !(sc->flags & SC_SCRN_IDLE))
+ if (sc->flags & SC_SCRN_BLANKED)
+ stop_scrn_saver(sc, current_saver);
+#endif /* NSPLASH */
/* should we just return ? */
- if (blink_in_progress || switch_in_progress) {
- if (arg)
- timeout(scrn_timer, (void *)TRUE, hz / 10);
+ if (sc->blink_in_progress || sc->switch_in_progress
+ || sc->write_in_progress) {
+ if (again)
+ timeout(scrn_timer, sc, hz / 10);
splx(s);
return;
}
/* Update the screen */
- scp = cur_console;
+ scp = sc->cur_scp; /* cur_scp may have changed... */
if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
scrn_update(scp, TRUE);
+#if NSPLASH > 0
/* should we activate the screen saver? */
- if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
- if (!ISGRAPHSC(scp) || scrn_blanked)
- (*current_saver)(TRUE);
+ if ((saver_mode == CONS_LKM_SAVER) && (sc->flags & SC_SCRN_IDLE))
+ if (!ISGRAPHSC(scp) || (sc->flags & SC_SCRN_BLANKED))
+ (*current_saver)(sc, TRUE);
+#endif /* NSPLASH */
- if (arg)
- timeout(scrn_timer, (void *)TRUE, hz / 25);
+ if (again)
+ timeout(scrn_timer, sc, hz / 25);
splx(s);
}
+static int
+and_region(int *s1, int *e1, int s2, int e2)
+{
+ if (*e1 < s2 || e2 < *s1)
+ return FALSE;
+ *s1 = imax(*s1, s2);
+ *e1 = imin(*e1, e2);
+ return TRUE;
+}
+
static void
scrn_update(scr_stat *scp, int show_cursor)
{
+ int start;
+ int end;
+ int s;
+ int e;
+
+ /* assert(scp == scp->sc->cur_scp) */
+
+ ++scp->sc->videoio_in_progress;
+
+#ifndef SC_NO_CUTPASTE
+ /* remove the previous mouse pointer image if necessary */
+ if ((scp->status & (MOUSE_VISIBLE | MOUSE_MOVED))
+ == (MOUSE_VISIBLE | MOUSE_MOVED)) {
+ /* FIXME: I don't like this... XXX */
+ sc_remove_mouse_image(scp);
+ if (scp->end >= scp->xsize*scp->ysize)
+ scp->end = scp->xsize*scp->ysize - 1;
+ }
+#endif /* !SC_NO_CUTPASTE */
+
+#if 1
+ /* debug: XXX */
+ if (scp->end >= scp->xsize*scp->ysize) {
+ printf("scrn_update(): scp->end %d > size_of_screen!!\n", scp->end);
+ scp->end = scp->xsize*scp->ysize - 1;
+ }
+ if (scp->start < 0) {
+ printf("scrn_update(): scp->start %d < 0\n", scp->start);
+ scp->start = 0;
+ }
+#endif
+
/* update screen image */
- if (scp->start <= scp->end)
- sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0);
+ if (scp->start <= scp->end) {
+ if (scp->mouse_cut_end >= 0) {
+ /* there is a marked region for cut & paste */
+ if (scp->mouse_cut_start <= scp->mouse_cut_end) {
+ start = scp->mouse_cut_start;
+ end = scp->mouse_cut_end;
+ } else {
+ start = scp->mouse_cut_end;
+ end = scp->mouse_cut_start - 1;
+ }
+ s = start;
+ e = end;
+ /* does the cut-mark region overlap with the update region? */
+ if (and_region(&s, &e, scp->start, scp->end)) {
+ (*scp->rndr->draw)(scp, s, e - s + 1, TRUE);
+ s = 0;
+ e = start - 1;
+ if (and_region(&s, &e, scp->start, scp->end))
+ (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
+ s = end + 1;
+ e = scp->xsize*scp->ysize - 1;
+ if (and_region(&s, &e, scp->start, scp->end))
+ (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
+ } else {
+ (*scp->rndr->draw)(scp, scp->start,
+ scp->end - scp->start + 1, FALSE);
+ }
+ } else {
+ (*scp->rndr->draw)(scp, scp->start,
+ scp->end - scp->start + 1, FALSE);
+ }
+ }
/* we are not to show the cursor and the mouse pointer... */
if (!show_cursor) {
scp->end = 0;
scp->start = scp->xsize*scp->ysize - 1;
+ --scp->sc->videoio_in_progress;
return;
}
- /* update "pseudo" mouse pointer image */
- if (scp->status & MOUSE_VISIBLE) {
- /* did mouse move since last time ? */
- if (scp->status & MOUSE_MOVED) {
- /* do we need to remove old mouse pointer image ? */
- if (scp->mouse_cut_start != NULL ||
- (scp->mouse_pos-scp->scr_buf) <= scp->start ||
- (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) {
- remove_mouse_image(scp);
- }
- scp->status &= ~MOUSE_MOVED;
- draw_mouse_image(scp);
- }
- else {
- /* mouse didn't move, has it been overwritten ? */
- if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start &&
- (scp->mouse_pos - scp->scr_buf) <= scp->end) {
- draw_mouse_image(scp);
- }
- }
- }
-
/* update cursor image */
if (scp->status & CURSOR_ENABLED) {
/* did cursor move since last time ? */
if (scp->cursor_pos != scp->cursor_oldpos) {
/* do we need to remove old cursor image ? */
- if ((scp->cursor_oldpos - scp->scr_buf) < scp->start ||
- ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) {
+ if (scp->cursor_oldpos < scp->start ||
+ scp->cursor_oldpos > scp->end) {
remove_cursor_image(scp);
}
scp->cursor_oldpos = scp->cursor_pos;
@@ -2213,40 +1828,64 @@ scrn_update(scr_stat *scp, int show_cursor)
}
else {
/* cursor didn't move, has it been overwritten ? */
- if (scp->cursor_pos - scp->scr_buf >= scp->start &&
- scp->cursor_pos - scp->scr_buf <= scp->end) {
+ if (scp->cursor_pos >= scp->start && scp->cursor_pos <= scp->end) {
draw_cursor_image(scp);
} else {
/* if its a blinking cursor, we may have to update it */
- if (sc_flags & BLINK_CURSOR)
- draw_cursor_image(scp);
+ if (scp->sc->flags & SC_BLINK_CURSOR)
+ (*scp->rndr->blink_cursor)(scp, scp->cursor_pos,
+ sc_inside_cutmark(scp,
+ scp->cursor_pos));
}
}
- blinkrate++;
}
- if (scp->mouse_cut_start != NULL)
- draw_cutmarking(scp);
+#ifndef SC_NO_CUTPASTE
+ /* update "pseudo" mouse pointer image */
+ if (scp->status & MOUSE_VISIBLE) {
+ /* did mouse move since last time ? */
+ if (scp->status & MOUSE_MOVED) {
+ /* the previous pointer image has been removed, see above */
+ scp->status &= ~MOUSE_MOVED;
+ sc_draw_mouse_image(scp);
+ } else {
+ /* mouse didn't move, has it been overwritten ? */
+ if (scp->mouse_pos + scp->xsize + 1 >= scp->start &&
+ scp->mouse_pos <= scp->end) {
+ sc_draw_mouse_image(scp);
+ } else if (scp->cursor_pos == scp->mouse_pos ||
+ scp->cursor_pos == scp->mouse_pos + 1 ||
+ scp->cursor_pos == scp->mouse_pos + scp->xsize ||
+ scp->cursor_pos == scp->mouse_pos + scp->xsize + 1) {
+ sc_draw_mouse_image(scp);
+ }
+ }
+ }
+#endif /* SC_NO_CUTPASTE */
scp->end = 0;
scp->start = scp->xsize*scp->ysize - 1;
+
+ --scp->sc->videoio_in_progress;
}
#if NSPLASH > 0
-
static int
-scsplash_callback(int event)
+scsplash_callback(int event, void *arg)
{
+ sc_softc_t *sc;
int error;
+ sc = (sc_softc_t *)arg;
+
switch (event) {
case SPLASH_INIT:
- scrn_saver_failed = FALSE;
if (add_scrn_saver(scsplash_saver) == 0) {
+ sc->flags &= ~SC_SAVER_FAILED;
run_scrn_saver = TRUE;
if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) {
scsplash_stick(TRUE);
- (*current_saver)(TRUE);
+ (*current_saver)(sc, TRUE);
}
}
return 0;
@@ -2266,7 +1905,7 @@ scsplash_callback(int event)
}
static void
-scsplash_saver(int show)
+scsplash_saver(sc_softc_t *sc, int show)
{
static int busy = FALSE;
scr_stat *scp;
@@ -2275,38 +1914,37 @@ scsplash_saver(int show)
return;
busy = TRUE;
- scp = cur_console;
+ scp = sc->cur_scp;
if (show) {
- if (!scrn_saver_failed) {
- if (!scrn_blanked)
+ if (!(sc->flags & SC_SAVER_FAILED)) {
+ if (!(sc->flags & SC_SCRN_BLANKED))
set_scrn_saver_mode(scp, -1, NULL, 0);
- switch (splash(scp->adp, TRUE)) {
+ switch (splash(sc->adp, TRUE)) {
case 0: /* succeeded */
- scrn_blanked = TRUE;
break;
case EAGAIN: /* try later */
restore_scrn_saver_mode(scp, FALSE);
+ sc_touch_scrn_saver(); /* XXX */
break;
default:
- scrn_saver_failed = TRUE;
+ sc->flags |= SC_SAVER_FAILED;
scsplash_stick(FALSE);
- printf("scsplash_saver(): failed to put up the image\n");
restore_scrn_saver_mode(scp, TRUE);
+ printf("scsplash_saver(): failed to put up the image\n");
break;
}
}
} else if (!sticky_splash) {
- if (scrn_blanked && (splash(scp->adp, FALSE) == 0)) {
+ if ((sc->flags & SC_SCRN_BLANKED) && (splash(sc->adp, FALSE) == 0))
restore_scrn_saver_mode(scp, TRUE);
- scrn_blanked = FALSE;
- }
}
busy = FALSE;
}
static int
-add_scrn_saver(void (*this_saver)(int))
+add_scrn_saver(void (*this_saver)(sc_softc_t *, int))
{
+#if 0
int error;
if (current_saver != none_saver) {
@@ -2314,6 +1952,9 @@ add_scrn_saver(void (*this_saver)(int))
if (error)
return error;
}
+#endif
+ if (current_saver != none_saver)
+ return EBUSY;
run_scrn_saver = FALSE;
saver_mode = CONS_LKM_SAVER;
@@ -2322,11 +1963,12 @@ add_scrn_saver(void (*this_saver)(int))
}
static int
-remove_scrn_saver(void (*this_saver)(int))
+remove_scrn_saver(void (*this_saver)(sc_softc_t *, int))
{
if (current_saver != this_saver)
return EINVAL;
+#if 0
/*
* In order to prevent `current_saver' from being called by
* the timeout routine `scrn_timer()' while we manipulate
@@ -2336,8 +1978,15 @@ remove_scrn_saver(void (*this_saver)(int))
current_saver = none_saver;
if (scrn_blanked)
stop_scrn_saver(this_saver);
+#endif
+
+ /* unblank all blanked screens */
+ wait_scrn_saver_stop(NULL);
+ if (scrn_blanked)
+ return EBUSY;
- return (scrn_blanked ? EBUSY : 0);
+ current_saver = none_saver;
+ return 0;
}
static int
@@ -2345,21 +1994,27 @@ set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
{
int s;
- /* assert(scp == cur_console) */
+ /* assert(scp == scp->sc->cur_scp) */
s = spltty();
+ if (!ISGRAPHSC(scp))
+ remove_cursor_image(scp);
scp->splash_save_mode = scp->mode;
scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE);
scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
scp->status |= (UNKNOWN_MODE | SAVER_RUNNING);
+ scp->sc->flags |= SC_SCRN_BLANKED;
+ ++scrn_blanked;
splx(s);
if (mode < 0)
return 0;
scp->mode = mode;
if (set_mode(scp) == 0) {
- if (scp->adp->va_info.vi_flags & V_INFO_GRAPHICS)
+ if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS)
scp->status |= GRAPHICS_MODE;
+#ifndef SC_NO_PALETTE_LOADING
if (pal != NULL)
- load_palette(scp->adp, pal);
+ load_palette(scp->sc->adp, pal);
+#endif
set_border(scp, border);
return 0;
} else {
@@ -2379,19 +2034,26 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
int status;
int s;
- /* assert(scp == cur_console) */
+ /* assert(scp == scp->sc->cur_scp) */
s = spltty();
mode = scp->mode;
status = scp->status;
scp->mode = scp->splash_save_mode;
scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
scp->status |= scp->splash_save_status;
+ scp->sc->flags &= ~SC_SCRN_BLANKED;
if (!changemode) {
+ if (!ISGRAPHSC(scp))
+ draw_cursor_image(scp);
+ --scrn_blanked;
splx(s);
return 0;
}
if (set_mode(scp) == 0) {
- load_palette(scp->adp, palette);
+#ifndef SC_NO_PALETTE_LOADING
+ load_palette(scp->sc->adp, scp->sc->palette);
+#endif
+ --scrn_blanked;
splx(s);
return 0;
} else {
@@ -2403,35 +2065,38 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
}
static void
-stop_scrn_saver(void (*saver)(int))
+stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int))
{
- (*saver)(FALSE);
+ (*saver)(sc, FALSE);
run_scrn_saver = FALSE;
/* the screen saver may have chosen not to stop after all... */
- if (scrn_blanked)
+ if (sc->flags & SC_SCRN_BLANKED)
return;
- mark_all(cur_console);
- if (delayed_next_scr)
- switch_scr(cur_console, delayed_next_scr - 1);
+ mark_all(sc->cur_scp);
+ if (sc->delayed_next_scr)
+ switch_scr(sc, sc->delayed_next_scr - 1);
wakeup((caddr_t)&scrn_blanked);
}
static int
-wait_scrn_saver_stop(void)
+wait_scrn_saver_stop(sc_softc_t *sc)
{
int error = 0;
- while (scrn_blanked) {
+ while (scrn_blanked > 0) {
run_scrn_saver = FALSE;
+ if (sc && !(sc->flags & SC_SCRN_BLANKED)) {
+ error = 0;
+ break;
+ }
error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
- run_scrn_saver = FALSE;
- if (error != ERESTART)
+ if ((error != 0) && (error != ERESTART))
break;
}
+ run_scrn_saver = FALSE;
return error;
}
-
#endif /* NSPLASH */
void
@@ -2446,99 +2111,297 @@ sc_clear_screen(scr_stat *scp)
{
move_crsr(scp, 0, 0);
scp->cursor_oldpos = scp->cursor_pos;
- fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
- scp->xsize * scp->ysize);
+ sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], scp->term.cur_color);
mark_all(scp);
- remove_cutmarking(scp);
+ sc_remove_cutmarking(scp);
}
static int
-switch_scr(scr_stat *scp, u_int next_scr)
+switch_scr(sc_softc_t *sc, u_int next_scr)
{
- /* delay switch if actively updating screen */
- if (scrn_blanked || write_in_progress || blink_in_progress) {
- delayed_next_scr = next_scr+1;
+ struct tty *tp;
+ int s;
+
+ DPRINTF(5, ("sc0: switch_scr() %d ", next_scr + 1));
+
+ /* delay switch if the screen is blanked or being updated */
+ if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress
+ || sc->blink_in_progress || sc->videoio_in_progress) {
+ sc->delayed_next_scr = next_scr + 1;
sc_touch_scrn_saver();
+ DPRINTF(5, ("switch delayed\n"));
return 0;
}
- if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid)))
- switch_in_progress = FALSE;
+ s = spltty();
- if (next_scr >= MAXCONS || switch_in_progress ||
- (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
- do_bell(scp, BELL_PITCH, BELL_DURATION);
+ /* we are in the middle of the vty switching process... */
+ if (sc->switch_in_progress
+ && (sc->cur_scp->smode.mode == VT_PROCESS)
+ && sc->cur_scp->proc) {
+ if (sc->cur_scp->proc != pfind(sc->cur_scp->pid)) {
+ /*
+ * The controlling process has died!!. Do some clean up.
+ * NOTE:`cur_scp->proc' and `cur_scp->smode.mode'
+ * are not reset here yet; they will be cleared later.
+ */
+ DPRINTF(5, ("cur_scp controlling process %d died, ",
+ sc->cur_scp->pid));
+ if (sc->cur_scp->status & SWITCH_WAIT_REL) {
+ /*
+ * Force the previous switch to finish, but return now
+ * with error.
+ */
+ DPRINTF(5, ("reset WAIT_REL, "));
+ sc->cur_scp->status &= ~SWITCH_WAIT_REL;
+ s = do_switch_scr(sc, s);
+ splx(s);
+ DPRINTF(5, ("finishing previous switch\n"));
+ return EINVAL;
+ } else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) {
+ /* let's assume screen switch has been completed. */
+ DPRINTF(5, ("reset WAIT_ACQ, "));
+ sc->cur_scp->status &= ~SWITCH_WAIT_ACQ;
+ sc->switch_in_progress = 0;
+ } else {
+ /*
+ * We are in between screen release and acquisition, and
+ * reached here via scgetc() or scrn_timer() which has
+ * interrupted exchange_scr(). Don't do anything stupid.
+ */
+ DPRINTF(5, ("waiting nothing, "));
+ }
+ } else {
+ /*
+ * The controlling process is alive, but not responding...
+ * It is either buggy or it may be just taking time.
+ * The following code is a gross kludge to cope with this
+ * problem for which there is no clean solution. XXX
+ */
+ if (sc->cur_scp->status & SWITCH_WAIT_REL) {
+ switch (sc->switch_in_progress++) {
+ case 1:
+ break;
+ case 2:
+ DPRINTF(5, ("sending relsig again, "));
+ signal_vt_rel(sc->cur_scp);
+ break;
+ case 3:
+ break;
+ case 4:
+ default:
+ /*
+ * Clear the flag and force the previous switch to finish,
+ * but return now with error.
+ */
+ DPRINTF(5, ("force reset WAIT_REL, "));
+ sc->cur_scp->status &= ~SWITCH_WAIT_REL;
+ s = do_switch_scr(sc, s);
+ splx(s);
+ DPRINTF(5, ("force finishing previous switch\n"));
+ return EINVAL;
+ }
+ } else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) {
+ switch (sc->switch_in_progress++) {
+ case 1:
+ break;
+ case 2:
+ DPRINTF(5, ("sending acqsig again, "));
+ signal_vt_acq(sc->cur_scp);
+ break;
+ case 3:
+ break;
+ case 4:
+ default:
+ /* clear the flag and finish the previous switch */
+ DPRINTF(5, ("force reset WAIT_ACQ, "));
+ sc->cur_scp->status &= ~SWITCH_WAIT_ACQ;
+ sc->switch_in_progress = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Return error if an invalid argument is given, or vty switch
+ * is still in progress.
+ */
+ if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys)
+ || sc->switch_in_progress) {
+ splx(s);
+ do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
+ DPRINTF(5, ("error 1\n"));
+ return EINVAL;
+ }
+
+ /*
+ * Don't allow switching away from the graphics mode vty
+ * if the switch mode is VT_AUTO, unless the next vty is the same
+ * as the current or the current vty has been closed (but showing).
+ */
+ tp = VIRTUAL_TTY(sc, sc->cur_scp->index);
+ if ((sc->cur_scp->index != next_scr)
+ && (tp->t_state & TS_ISOPEN)
+ && (sc->cur_scp->smode.mode == VT_AUTO)
+ && ISGRAPHSC(sc->cur_scp)) {
+ splx(s);
+ do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
+ DPRINTF(5, ("error, graphics mode\n"));
return EINVAL;
}
- /* is the wanted virtual console open ? */
- if (next_scr) {
- struct tty *tp = VIRTUAL_TTY(next_scr);
+ /*
+ * Is the wanted vty open? Don't allow switching to a closed vty.
+ * Note that we always allow the user to switch to the kernel
+ * console even if it is closed.
+ */
+ if ((sc_console == NULL) || (next_scr != sc_console->index)) {
+ tp = VIRTUAL_TTY(sc, next_scr);
if (!(tp->t_state & TS_ISOPEN)) {
- do_bell(scp, BELL_PITCH, BELL_DURATION);
+ splx(s);
+ do_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
+ DPRINTF(5, ("error 2, requested vty isn't open!\n"));
return EINVAL;
}
}
- switch_in_progress = TRUE;
- old_scp = cur_console;
- new_scp = console[next_scr];
- wakeup((caddr_t)&new_scp->smode);
- if (new_scp == old_scp) {
- switch_in_progress = FALSE;
- delayed_next_scr = FALSE;
+ /* this is the start of vty switching process... */
+ ++sc->switch_in_progress;
+ sc->delayed_next_scr = 0;
+ sc->old_scp = sc->cur_scp;
+ sc->new_scp = sc->console[next_scr - sc->first_vty];
+ if (sc->new_scp == sc->old_scp) {
+ sc->switch_in_progress = 0;
+ wakeup((caddr_t)&sc->new_scp->smode);
+ splx(s);
+ DPRINTF(5, ("switch done (new == old)\n"));
return 0;
}
/* has controlling process died? */
- if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
- old_scp->smode.mode = VT_AUTO;
- if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
- new_scp->smode.mode = VT_AUTO;
-
- /* check the modes and switch appropriately */
- if (old_scp->smode.mode == VT_PROCESS) {
- old_scp->status |= SWITCH_WAIT_REL;
- psignal(old_scp->proc, old_scp->smode.relsig);
+ vt_proc_alive(sc->old_scp);
+ vt_proc_alive(sc->new_scp);
+
+ /* wait for the controlling process to release the screen, if necessary */
+ if (signal_vt_rel(sc->old_scp)) {
+ splx(s);
+ return 0;
}
- else {
- exchange_scr();
- if (new_scp->smode.mode == VT_PROCESS) {
- new_scp->status |= SWITCH_WAIT_ACQ;
- psignal(new_scp->proc, new_scp->smode.acqsig);
- }
- else
- switch_in_progress = FALSE;
+
+ /* go set up the new vty screen */
+ splx(s);
+ exchange_scr(sc);
+ s = spltty();
+
+ /* wake up processes waiting for this vty */
+ wakeup((caddr_t)&sc->cur_scp->smode);
+
+ /* wait for the controlling process to acknowledge, if necessary */
+ if (signal_vt_acq(sc->cur_scp)) {
+ splx(s);
+ return 0;
}
+
+ sc->switch_in_progress = 0;
+ if (sc->unit == sc_console_unit)
+ cons_unavail = FALSE;
+ splx(s);
+ DPRINTF(5, ("switch done\n"));
+
return 0;
}
+static int
+do_switch_scr(sc_softc_t *sc, int s)
+{
+ vt_proc_alive(sc->new_scp);
+
+ splx(s);
+ exchange_scr(sc);
+ s = spltty();
+ /* sc->cur_scp == sc->new_scp */
+ wakeup((caddr_t)&sc->cur_scp->smode);
+
+ /* wait for the controlling process to acknowledge, if necessary */
+ if (!signal_vt_acq(sc->cur_scp)) {
+ sc->switch_in_progress = 0;
+ if (sc->unit == sc_console_unit)
+ cons_unavail = FALSE;
+ }
+
+ return s;
+}
+
+static int
+vt_proc_alive(scr_stat *scp)
+{
+ if (scp->proc) {
+ if (scp->proc == pfind(scp->pid))
+ return TRUE;
+ scp->proc = NULL;
+ scp->smode.mode = VT_AUTO;
+ DPRINTF(5, ("vt controlling process %d died\n", scp->pid));
+ }
+ return FALSE;
+}
+
+static int
+signal_vt_rel(scr_stat *scp)
+{
+ if (scp->smode.mode != VT_PROCESS)
+ return FALSE;
+ scp->status |= SWITCH_WAIT_REL;
+ psignal(scp->proc, scp->smode.relsig);
+ DPRINTF(5, ("sending relsig to %d\n", scp->pid));
+ return TRUE;
+}
+
+static int
+signal_vt_acq(scr_stat *scp)
+{
+ if (scp->smode.mode != VT_PROCESS)
+ return FALSE;
+ if (scp->sc->unit == sc_console_unit)
+ cons_unavail = TRUE;
+ scp->status |= SWITCH_WAIT_ACQ;
+ psignal(scp->proc, scp->smode.acqsig);
+ DPRINTF(5, ("sending acqsig to %d\n", scp->pid));
+ return TRUE;
+}
+
static void
-exchange_scr(void)
+exchange_scr(sc_softc_t *sc)
{
+ scr_stat *scp;
+
/* save the current state of video and keyboard */
- move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
- if (old_scp->kbd_mode == K_XLATE)
- save_kbd_state(old_scp);
+ move_crsr(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos);
+ if (sc->old_scp->kbd_mode == K_XLATE)
+ save_kbd_state(sc->old_scp);
/* set up the video for the new screen */
- cur_console = new_scp;
- if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp))
- set_mode(new_scp);
- move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
- if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR))
- set_destructive_cursor(new_scp);
- if (ISGRAPHSC(old_scp))
- load_palette(new_scp->adp, palette);
- set_border(new_scp, new_scp->border);
+ scp = sc->cur_scp = sc->new_scp;
+ if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp))
+ set_mode(scp);
+ else
+ sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
+ (void *)sc->adp->va_window, FALSE);
+ move_crsr(scp, scp->xpos, scp->ypos);
+ if (!ISGRAPHSC(scp))
+ sc_set_cursor_image(scp);
+#ifndef SC_NO_PALETTE_LOADING
+ if (ISGRAPHSC(sc->old_scp))
+ load_palette(sc->adp, sc->palette);
+#endif
+ set_border(scp, scp->border);
/* set up the keyboard for the new screen */
- if (old_scp->kbd_mode != new_scp->kbd_mode)
- kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&new_scp->kbd_mode);
- update_kbd_state(new_scp->status, LOCK_MASK);
+ if (sc->old_scp->kbd_mode != scp->kbd_mode)
+ kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
+ update_kbd_state(scp, scp->status, LOCK_MASK);
- delayed_next_scr = FALSE;
- mark_all(new_scp);
+ mark_all(scp);
}
static void
@@ -2546,9 +2409,11 @@ scan_esc(scr_stat *scp, u_char c)
{
static u_char ansi_col[16] =
{0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
+ sc_softc_t *sc;
int i, n;
- u_short *src, *dst, count;
+ int count;
+ sc = scp->sc;
if (scp->term.esc == 1) { /* seen ESC */
switch (c) {
@@ -2574,10 +2439,8 @@ scan_esc(scr_stat *scp, u_char c)
if (scp->ypos > 0)
move_crsr(scp, scp->xpos, scp->ypos - 1);
else {
- bcopy(scp->scr_buf, scp->scr_buf + scp->xsize,
- (scp->ysize - 1) * scp->xsize * sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->scr_buf, scp->xsize);
+ sc_vtb_ins(&scp->vtb, 0, scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_all(scp);
}
break;
@@ -2669,26 +2532,24 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0];
switch (n) {
case 0: /* clear form cursor to end of display */
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->cursor_pos,
- scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ sc_vtb_erase(&scp->vtb, scp->cursor_pos,
+ scp->xsize * scp->ysize - scp->cursor_pos,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, scp->cursor_pos);
mark_for_update(scp, scp->xsize * scp->ysize - 1);
- remove_cutmarking(scp);
+ sc_remove_cutmarking(scp);
break;
case 1: /* clear from beginning of display to cursor */
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->scr_buf,
- scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, 0);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- remove_cutmarking(scp);
+ sc_vtb_erase(&scp->vtb, 0, scp->cursor_pos,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, 0);
+ mark_for_update(scp, scp->cursor_pos);
+ sc_remove_cutmarking(scp);
break;
case 2: /* clear entire display */
- fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
- scp->xsize * scp->ysize);
+ sc_vtb_clear(&scp->vtb, sc->scr_map[0x20], scp->term.cur_color);
mark_all(scp);
- remove_cutmarking(scp);
+ sc_remove_cutmarking(scp);
break;
}
break;
@@ -2700,24 +2561,24 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0];
switch (n) {
case 0: /* clear form cursor to end of line */
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->cursor_pos,
- scp->xsize - scp->xpos);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf +
+ sc_vtb_erase(&scp->vtb, scp->cursor_pos,
+ scp->xsize - scp->xpos,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, scp->cursor_pos);
+ mark_for_update(scp, scp->cursor_pos +
scp->xsize - 1 - scp->xpos);
break;
case 1: /* clear from beginning of line to cursor */
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->cursor_pos - scp->xpos,
- scp->xpos + 1);
+ sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
+ scp->xpos + 1,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_for_update(scp, scp->ypos * scp->xsize);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
break;
case 2: /* clear entire line */
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->cursor_pos - scp->xpos,
- scp->xsize);
+ sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
+ scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_for_update(scp, scp->ypos * scp->xsize);
mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1);
break;
@@ -2728,12 +2589,8 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->ysize - scp->ypos)
n = scp->ysize - scp->ypos;
- src = scp->scr_buf + scp->ypos * scp->xsize;
- dst = src + n * scp->xsize;
- count = scp->ysize - (scp->ypos + n);
- bcopy(src, dst, count * scp->xsize * sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20], src,
- n * scp->xsize);
+ sc_vtb_ins(&scp->vtb, scp->ypos * scp->xsize, n * scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_for_update(scp, scp->ypos * scp->xsize);
mark_for_update(scp, scp->xsize * scp->ysize - 1);
break;
@@ -2742,13 +2599,8 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->ysize - scp->ypos)
n = scp->ysize - scp->ypos;
- dst = scp->scr_buf + scp->ypos * scp->xsize;
- src = dst + n * scp->xsize;
- count = scp->ysize - (scp->ypos + n);
- bcopy(src, dst, count * scp->xsize * sizeof(u_short));
- src = dst + count * scp->xsize;
- fillw(scp->term.cur_color | scr_map[0x20], src,
- n * scp->xsize);
+ sc_vtb_delete(&scp->vtb, scp->ypos * scp->xsize, n * scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_for_update(scp, scp->ypos * scp->xsize);
mark_for_update(scp, scp->xsize * scp->ysize - 1);
break;
@@ -2757,39 +2609,30 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->xsize - scp->xpos)
n = scp->xsize - scp->xpos;
- dst = scp->cursor_pos;
- src = dst + n;
count = scp->xsize - (scp->xpos + n);
- bcopy(src, dst, count * sizeof(u_short));
- src = dst + count;
- fillw(scp->term.cur_color | scr_map[0x20], src, n);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1);
+ sc_vtb_delete(&scp->vtb, scp->cursor_pos, n,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, scp->cursor_pos);
+ mark_for_update(scp, scp->cursor_pos + n + count - 1);
break;
case '@': /* Insert n chars */
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->xsize - scp->xpos)
n = scp->xsize - scp->xpos;
- src = scp->cursor_pos;
- dst = src + n;
count = scp->xsize - (scp->xpos + n);
- bcopy(src, dst, count * sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20], src, n);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1);
+ sc_vtb_ins(&scp->vtb, scp->cursor_pos, n,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, scp->cursor_pos);
+ mark_for_update(scp, scp->cursor_pos + n + count - 1);
break;
case 'S': /* scroll up n lines */
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->ysize)
n = scp->ysize;
- bcopy(scp->scr_buf + (scp->xsize * n),
- scp->scr_buf,
- scp->xsize * (scp->ysize - n) * sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->scr_buf + scp->xsize * (scp->ysize - n),
- scp->xsize * n);
+ sc_vtb_delete(&scp->vtb, 0, n * scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_all(scp);
break;
@@ -2797,12 +2640,8 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->ysize)
n = scp->ysize;
- bcopy(scp->scr_buf,
- scp->scr_buf + (scp->xsize * n),
- scp->xsize * (scp->ysize - n) *
- sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->scr_buf, scp->xsize * n);
+ sc_vtb_ins(&scp->vtb, 0, n * scp->xsize,
+ sc->scr_map[0x20], scp->term.cur_color);
mark_all(scp);
break;
@@ -2810,10 +2649,10 @@ scan_esc(scr_stat *scp, u_char c)
n = scp->term.param[0]; if (n < 1) n = 1;
if (n > scp->xsize - scp->xpos)
n = scp->xsize - scp->xpos;
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->cursor_pos, n);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1);
+ sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
+ sc->scr_map[0x20], scp->term.cur_color);
+ mark_for_update(scp, scp->cursor_pos);
+ mark_for_update(scp, scp->cursor_pos + n - 1);
break;
case 'Z': /* move n tabs backwards */
@@ -2962,7 +2801,7 @@ scan_esc(scr_stat *scp, u_char c)
case 'z': /* switch to (virtual) console n */
if (scp->term.num_param == 1)
- switch_scr(scp, scp->term.param[0]);
+ switch_scr(sc, scp->term.param[0]);
break;
}
}
@@ -2990,8 +2829,8 @@ scan_esc(scr_stat *scp, u_char c)
case 'A': /* set display border color */
if (scp->term.num_param == 1) {
scp->border=scp->term.param[0] & 0xff;
- if (scp == cur_console)
- set_border(cur_console, scp->border);
+ if (scp == sc->cur_scp)
+ set_border(scp, scp->border);
}
break;
@@ -3003,31 +2842,32 @@ scan_esc(scr_stat *scp, u_char c)
break;
case 'C': /* set cursor type & shape */
+ if (!ISGRAPHSC(sc->cur_scp))
+ remove_cursor_image(sc->cur_scp);
if (scp->term.num_param == 1) {
if (scp->term.param[0] & 0x01)
- sc_flags |= BLINK_CURSOR;
+ sc->flags |= SC_BLINK_CURSOR;
else
- sc_flags &= ~BLINK_CURSOR;
- if ((scp->term.param[0] & 0x02)
- && ISFONTAVAIL(scp->adp->va_flags))
- sc_flags |= CHAR_CURSOR;
+ sc->flags &= ~SC_BLINK_CURSOR;
+ if (scp->term.param[0] & 0x02)
+ sc->flags |= SC_CHAR_CURSOR;
else
- sc_flags &= ~CHAR_CURSOR;
+ sc->flags &= ~SC_CHAR_CURSOR;
}
else if (scp->term.num_param == 2) {
- scp->cursor_start = scp->term.param[0] & 0x1F;
- scp->cursor_end = scp->term.param[1] & 0x1F;
+ sc->cursor_base = scp->font_size
+ - (scp->term.param[1] & 0x1F) - 1;
+ sc->cursor_height = (scp->term.param[1] & 0x1F)
+ - (scp->term.param[0] & 0x1F) + 1;
}
/*
* The cursor shape is global property; all virtual consoles
* are affected. Update the cursor in the current console...
*/
- if (!ISGRAPHSC(cur_console)) {
+ if (!ISGRAPHSC(sc->cur_scp)) {
i = spltty();
- remove_cursor_image(cur_console);
- if (sc_flags & CHAR_CURSOR)
- set_destructive_cursor(cur_console);
- draw_cursor_image(cur_console);
+ sc_set_cursor_image(sc->cur_scp);
+ draw_cursor_image(sc->cur_scp);
splx(i);
}
break;
@@ -3094,19 +2934,28 @@ ansi_put(scr_stat *scp, u_char *buf, int len)
u_char *ptr = buf;
/* make screensaver happy */
- if (!sticky_splash && scp == cur_console)
+ if (!sticky_splash && scp == scp->sc->cur_scp)
run_scrn_saver = FALSE;
- write_in_progress++;
outloop:
+ scp->sc->write_in_progress++;
if (scp->term.esc) {
scan_esc(scp, *ptr++);
len--;
}
else if (PRINTABLE(*ptr)) { /* Print only printables */
- int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos);
- u_short cur_attr = scp->term.cur_attr;
- u_short *cursor_pos = scp->cursor_pos;
+ vm_offset_t p;
+ u_char *map;
+ int cnt;
+ int attr;
+ int i;
+
+ p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
+ map = scp->sc->scr_map;
+ attr = scp->term.cur_attr;
+
+ cnt = (len <= scp->xsize - scp->xpos) ? len : (scp->xsize - scp->xpos);
+ i = cnt;
do {
/*
* gcc-2.6.3 generates poor (un)sign extension code. Casting the
@@ -3115,15 +2964,17 @@ outloop:
* (+ cache misses) on i486's.
*/
#define UCVP(ucp) ((u_char volatile *)(ucp))
- *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr;
- ptr++;
- cnt--;
- } while (cnt && PRINTABLE(*ptr));
- len -= (cursor_pos - scp->cursor_pos);
- scp->xpos += (cursor_pos - scp->cursor_pos);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
- mark_for_update(scp, cursor_pos - scp->scr_buf);
- scp->cursor_pos = cursor_pos;
+ p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)], attr);
+ ++ptr;
+ --i;
+ } while (i > 0 && PRINTABLE(*ptr));
+
+ len -= cnt - i;
+ mark_for_update(scp, scp->cursor_pos);
+ scp->cursor_pos += cnt - i;
+ mark_for_update(scp, scp->cursor_pos - 1);
+ scp->xpos += cnt - i;
+
if (scp->xpos >= scp->xsize) {
scp->xpos = 0;
scp->ypos++;
@@ -3136,10 +2987,10 @@ outloop:
break;
case 0x08: /* non-destructive backspace */
- if (scp->cursor_pos > scp->scr_buf) {
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ if (scp->cursor_pos > 0) {
+ mark_for_update(scp, scp->cursor_pos);
scp->cursor_pos--;
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
if (scp->xpos > 0)
scp->xpos--;
else {
@@ -3150,9 +3001,9 @@ outloop:
break;
case 0x09: /* non-destructive tab */
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
scp->cursor_pos += (8 - scp->xpos % 8u);
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) {
scp->xpos = 0;
scp->ypos++;
@@ -3160,9 +3011,9 @@ outloop:
break;
case 0x0a: /* newline, same pos */
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
scp->cursor_pos += scp->xsize;
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
scp->ypos++;
break;
@@ -3171,9 +3022,9 @@ outloop:
break;
case 0x0d: /* return, return to pos 0 */
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
scp->cursor_pos -= scp->xpos;
- mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
+ mark_for_update(scp, scp->cursor_pos);
scp->xpos = 0;
break;
@@ -3185,117 +3036,379 @@ outloop:
ptr++; len--;
}
/* do we have to scroll ?? */
- if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) {
- remove_cutmarking(scp);
- if (scp->history != NULL) {
- bcopy(scp->scr_buf, scp->history_head,
- scp->xsize * sizeof(u_short));
- scp->history_head += scp->xsize;
- if (scp->history_head + scp->xsize >
- scp->history + scp->history_size)
- scp->history_head = scp->history;
- }
- bcopy(scp->scr_buf + scp->xsize, scp->scr_buf,
- scp->xsize * (scp->ysize - 1) * sizeof(u_short));
- fillw(scp->term.cur_color | scr_map[0x20],
- scp->scr_buf + scp->xsize * (scp->ysize - 1),
- scp->xsize);
+ if (scp->cursor_pos >= scp->ysize * scp->xsize) {
+ sc_remove_cutmarking(scp);
+#ifndef SC_NO_HISTORY
+ if (scp->history != NULL)
+ sc_hist_save_one_line(scp, 0);
+#endif
+ sc_vtb_delete(&scp->vtb, 0, scp->xsize,
+ scp->sc->scr_map[0x20], scp->term.cur_color);
scp->cursor_pos -= scp->xsize;
scp->ypos--;
mark_all(scp);
}
+ scp->sc->write_in_progress--;
if (len)
goto outloop;
- write_in_progress--;
- if (delayed_next_scr)
- switch_scr(scp, delayed_next_scr - 1);
+ if (scp->sc->delayed_next_scr)
+ switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
}
static void
-scinit(void)
+draw_cursor_image(scr_stat *scp)
+{
+ /* assert(scp == scp->sc->cur_scp); */
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
+ scp->sc->flags & SC_BLINK_CURSOR, TRUE,
+ sc_inside_cutmark(scp, scp->cursor_pos));
+ --scp->sc->videoio_in_progress;
+}
+
+static void
+remove_cursor_image(scr_stat *scp)
+{
+ /* assert(scp == scp->sc->cur_scp); */
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
+ scp->sc->flags & SC_BLINK_CURSOR, FALSE,
+ sc_inside_cutmark(scp, scp->cursor_oldpos));
+ --scp->sc->videoio_in_progress;
+}
+
+static void
+update_cursor_image(scr_stat *scp)
{
+ int blink;
+
+ if (scp->sc->flags & SC_CHAR_CURSOR) {
+ scp->cursor_base = scp->sc->cursor_base;
+ scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
+ } else {
+ scp->cursor_base = 0;
+ scp->cursor_height = scp->font_size;
+ }
+ blink = scp->sc->flags & SC_BLINK_CURSOR;
+
+ /* assert(scp == scp->sc->cur_scp); */
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, blink, FALSE,
+ sc_inside_cutmark(scp, scp->cursor_pos));
+ (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, blink);
+ (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE,
+ sc_inside_cutmark(scp, scp->cursor_pos));
+ --scp->sc->videoio_in_progress;
+}
+
+void
+sc_set_cursor_image(scr_stat *scp)
+{
+ if (scp->sc->flags & SC_CHAR_CURSOR) {
+ scp->cursor_base = scp->sc->cursor_base;
+ scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
+ } else {
+ scp->cursor_base = 0;
+ scp->cursor_height = scp->font_size;
+ }
+
+ /* assert(scp == scp->sc->cur_scp); */
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height,
+ scp->sc->flags & SC_BLINK_CURSOR);
+ --scp->sc->videoio_in_progress;
+}
+
+static void
+move_crsr(scr_stat *scp, int x, int y)
+{
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x >= scp->xsize)
+ x = scp->xsize-1;
+ if (y >= scp->ysize)
+ y = scp->ysize-1;
+ scp->xpos = x;
+ scp->ypos = y;
+ scp->cursor_pos = scp->ypos * scp->xsize + scp->xpos;
+}
+
+static void
+scinit(int unit, int flags)
+{
+ /*
+ * When syscons is being initialized as the kernel console, malloc()
+ * is not yet functional, because various kernel structures has not been
+ * fully initialized yet. Therefore, we need to declare the following
+ * static buffers for the console. This is less than ideal,
+ * but is necessry evil for the time being. XXX
+ */
+ static scr_stat main_console;
+ static scr_stat *main_vtys[MAXCONS];
+ static struct tty main_tty[MAXCONS];
+ static u_short sc_buffer[ROW*COL]; /* XXX */
+#ifdef DEVFS
+ static void *main_devfs_token[MAXCONS];
+#endif
+#ifndef SC_NO_FONT_LOADING
+ static u_char font_8[256*8];
+ static u_char font_14[256*14];
+ static u_char font_16[256*16];
+#endif
+
+ sc_softc_t *sc;
+ scr_stat *scp;
video_adapter_t *adp;
int col;
int row;
- u_int i;
+ int i;
- if (init_done != COLD)
- return;
+ /* one time initialization */
+ if (init_done == COLD) {
+ sc_get_bios_values(&bios_value);
+ current_default = &user_default;
+ /* kernel console attributes */
+ kernel_console.esc = 0;
+ kernel_console.attr_mask = NORMAL_ATTR;
+ kernel_console.cur_attr =
+ kernel_console.cur_color = kernel_console.std_color =
+ kernel_default.std_color;
+ kernel_console.rev_color = kernel_default.rev_color;
+ }
init_done = WARM;
- get_bios_values();
+ /*
+ * Allocate resources. Even if we are being called for the second
+ * time, we must allocate them again, because they might have
+ * disappeared...
+ */
+ sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
+ adp = NULL;
+ if (sc->adapter >= 0) {
+ vid_release(sc->adp, (void *)&sc->adapter);
+ adp = sc->adp;
+ sc->adp = NULL;
+ }
+ if (sc->keyboard >= 0) {
+ DPRINTF(5, ("sc%d: releasing kbd%d\n", unit, sc->keyboard));
+ i = kbd_release(sc->kbd, (void *)&sc->keyboard);
+ DPRINTF(5, ("sc%d: kbd_release returned %d\n", unit, i));
+ if (sc->kbd != NULL) {
+ DPRINTF(5, ("sc%d: kbd != NULL!, index:%d, minor:%d, flags:0x%x\n",
+ unit, sc->kbd->kb_index, sc->kbd->kb_minor, sc->kbd->kb_flags));
+ }
+ sc->kbd = NULL;
+ }
+ sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
+ sc->adp = vid_get_adapter(sc->adapter);
+ /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
+ sc->keyboard = kbd_allocate("*", unit, (void *)&sc->keyboard,
+ sckbdevent, sc);
+ DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
+ sc->kbd = kbd_get_keyboard(sc->keyboard);
+ if (sc->kbd != NULL) {
+ DPRINTF(1, ("sc%d: kbd index:%d, minor:%d, flags:0x%x\n",
+ unit, sc->kbd->kb_index, sc->kbd->kb_minor, sc->kbd->kb_flags));
+ }
+
+ if (!(sc->flags & SC_INIT_DONE) || (adp != sc->adp)) {
+
+ sc->initial_mode = sc->adp->va_initial_mode;
+
+#ifndef SC_NO_FONT_LOADING
+ if (flags & SC_KERNEL_CONSOLE) {
+ sc->font_8 = font_8;
+ sc->font_14 = font_14;
+ sc->font_16 = font_16;
+ } else if (sc->font_8 == NULL) {
+ /* assert(sc_malloc) */
+ sc->font_8 = malloc(sizeof(font_8), M_DEVBUF, M_WAITOK);
+ sc->font_14 = malloc(sizeof(font_14), M_DEVBUF, M_WAITOK);
+ sc->font_16 = malloc(sizeof(font_16), M_DEVBUF, M_WAITOK);
+ }
+#endif
- /* extract the hardware cursor location and hide the cursor for now */
- adp = vid_get_adapter(adapter);
- (*vidsw[adapter]->read_hw_cursor)(adp, &col, &row);
- (*vidsw[adapter]->set_hw_cursor)(adp, -1, -1);
+ /* extract the hardware cursor location and hide the cursor for now */
+ (*vidsw[sc->adapter]->read_hw_cursor)(sc->adp, &col, &row);
+ (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, -1, -1);
- /* set up the first console */
- current_default = &user_default;
- console[0] = &main_console;
- init_scp(console[0]);
- cur_console = console[0];
-
- /* copy screen to temporary buffer */
- if (ISTEXTSC(console[0]))
- bcopy_fromio(console[0]->adp->va_window, sc_buffer,
- console[0]->xsize * console[0]->ysize * sizeof(u_short));
-
- console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
- = sc_buffer;
- if (col >= console[0]->xsize)
- col = 0;
- if (row >= console[0]->ysize)
- row = console[0]->ysize - 1;
- console[0]->xpos = col;
- console[0]->ypos = row;
- console[0]->cursor_pos = console[0]->cursor_oldpos =
- sc_buffer + row*console[0]->xsize + col;
- console[0]->cursor_saveunder = *console[0]->cursor_pos;
- for (i=1; i<MAXCONS; i++)
- console[i] = NULL;
- kernel_console.esc = 0;
- kernel_console.attr_mask = NORMAL_ATTR;
- kernel_console.cur_attr =
- kernel_console.cur_color = kernel_console.std_color =
- kernel_default.std_color;
- kernel_console.rev_color = kernel_default.rev_color;
+ /* set up the first console */
+ sc->first_vty = unit*MAXCONS;
+ if (flags & SC_KERNEL_CONSOLE) {
+ sc->vtys = sizeof(main_vtys)/sizeof(main_vtys[0]);
+ sc->tty = main_tty;
+#ifdef DEVFS
+ sc->devfs_token = main_devfs_token;
+#endif
+ sc->console = main_vtys;
+ scp = main_vtys[0] = &main_console;
+ init_scp(sc, sc->first_vty, scp);
+ sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
+ (void *)sc_buffer, FALSE);
+ } else {
+ /* assert(sc_malloc) */
+ sc->vtys = MAXCONS;
+ sc->tty = malloc(sizeof(struct tty)*MAXCONS, M_DEVBUF, M_WAITOK);
+ bzero(sc->tty, sizeof(struct tty)*MAXCONS);
+#ifdef DEVFS
+ sc->devfs_token = malloc(sizeof(void *)*MAXCONS,
+ M_DEVBUF, M_WAITOK);
+#endif
+ sc->console = malloc(sizeof(struct scr_stat *)*MAXCONS,
+ M_DEVBUF, M_WAITOK);
+ scp = sc->console[0] = alloc_scp(sc, sc->first_vty);
+ }
+ sc->cur_scp = scp;
+
+ /* copy screen to temporary buffer */
+ sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
+ (void *)scp->sc->adp->va_window, FALSE);
+ if (ISTEXTSC(scp))
+ sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize);
+
+ /* move cursors to the initial positions */
+ scp->mouse_pos = scp->mouse_oldpos = 0;
+ if (col >= scp->xsize)
+ col = 0;
+ if (row >= scp->ysize)
+ row = scp->ysize - 1;
+ scp->xpos = col;
+ scp->ypos = row;
+ scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
+ if (bios_value.cursor_end < scp->font_size)
+ sc->cursor_base = scp->font_size - bios_value.cursor_end - 1;
+ else
+ sc->cursor_base = 0;
+ i = bios_value.cursor_end - bios_value.cursor_start + 1;
+ sc->cursor_height = imin(i, scp->font_size);
+ if (!ISGRAPHSC(scp)) {
+ sc_set_cursor_image(scp);
+ draw_cursor_image(scp);
+ }
- /* initialize mapscrn arrays to a one to one map */
- for (i=0; i<sizeof(scr_map); i++) {
- scr_map[i] = scr_rmap[i] = i;
- }
+ /* save font and palette */
+#ifndef SC_NO_FONT_LOADING
+ sc->fonts_loaded = 0;
+ if (ISFONTAVAIL(sc->adp->va_flags)) {
+#ifdef SC_DFLT_FONT
+ bcopy(dflt_font_8, sc->font_8, sizeof(dflt_font_8));
+ bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14));
+ bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16));
+ sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8;
+ if (scp->font_size < 14) {
+ copy_font(scp, LOAD, 8, sc->font_8);
+ sc->fonts_loaded = FONT_8;
+ } else if (scp->font_size >= 16) {
+ copy_font(scp, LOAD, 16, sc->font_16);
+ sc->fonts_loaded = FONT_16;
+ } else {
+ copy_font(scp, LOAD, 14, sc->font_14);
+ sc->fonts_loaded = FONT_14;
+ }
+#else /* !SC_DFLT_FONT */
+ if (scp->font_size < 14) {
+ copy_font(scp, SAVE, 8, sc->font_8);
+ sc->fonts_loaded = FONT_8;
+ } else if (scp->font_size >= 16) {
+ copy_font(scp, SAVE, 16, sc->font_16);
+ sc->fonts_loaded = FONT_16;
+ } else {
+ copy_font(scp, SAVE, 14, sc->font_14);
+ sc->fonts_loaded = FONT_14;
+ }
+#endif /* SC_DFLT_FONT */
+ /* FONT KLUDGE: always use the font page #0. XXX */
+ (*vidsw[sc->adapter]->show_font)(sc->adp, 0);
+ }
+#endif /* !SC_NO_FONT_LOADING */
- /* Save font and palette */
- if (ISFONTAVAIL(cur_console->adp->va_flags)) {
- if (fonts_loaded & FONT_16) {
- copy_font(cur_console, LOAD, 16, font_16);
- } else {
- copy_font(cur_console, SAVE, 16, font_16);
- fonts_loaded = FONT_16;
- set_destructive_cursor(cur_console);
+#ifndef SC_NO_PALETTE_LOADING
+ save_palette(sc->adp, sc->palette);
+#endif
+
+#if NSPLASH > 0
+ if (!(sc->flags & SC_SPLASH_SCRN) && (flags & SC_KERNEL_CONSOLE)) {
+ /* we are ready to put up the splash image! */
+ splash_init(sc->adp, scsplash_callback, sc);
+ sc->flags |= SC_SPLASH_SCRN;
}
- /*
- * FONT KLUDGE
- * Always use the font page #0. XXX
- */
- (*vidsw[cur_console->ad]->show_font)(cur_console->adp, 0);
+#endif /* NSPLASH */
}
- save_palette(cur_console->adp, palette);
+
+ /* the rest is not necessary, if we have done it once */
+ if (sc->flags & SC_INIT_DONE)
+ return;
+
+ /* clear structures */
+ for (i = 1; i < sc->vtys; i++)
+ sc->console[i] = NULL;
+
+ /* initialize mapscrn arrays to a one to one map */
+ for (i = 0; i < sizeof(sc->scr_map); i++)
+ sc->scr_map[i] = sc->scr_rmap[i] = i;
+
+ sc->flags |= SC_INIT_DONE;
+}
+
+static void
+scterm(int unit, int flags)
+{
+ sc_softc_t *sc;
+
+ sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
+ if (sc == NULL)
+ return; /* shouldn't happen */
#if NSPLASH > 0
- /* we are ready to put up the splash image! */
- splash_init(cur_console->adp, scsplash_callback);
+ /* this console is no longer available for the splash screen */
+ if (sc->flags & SC_SPLASH_SCRN) {
+ splash_term(sc->adp);
+ sc->flags &= ~SC_SPLASH_SCRN;
+ }
+#endif /* NSPLASH */
+
+#if 0 /* XXX */
+ /* move the hardware cursor to the upper-left corner */
+ (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, 0, 0);
+#endif
+
+ /* release the keyboard and the video card */
+ if (sc->keyboard >= 0)
+ kbd_release(sc->kbd, &sc->keyboard);
+ if (sc->adapter >= 0)
+ vid_release(sc->adp, &sc->adapter);
+
+ /* clear the structure */
+ if (!(flags & SC_KERNEL_CONSOLE)) {
+ free(sc->console, M_DEVBUF);
+ free(sc->tty, M_DEVBUF);
+#ifdef DEVFS
+ free(sc->devfs_token, M_DEVBUF);
#endif
+#ifndef SC_NO_FONT_LOADING
+ free(sc->font_8, M_DEVBUF);
+ free(sc->font_14, M_DEVBUF);
+ free(sc->font_16, M_DEVBUF);
+#endif
+ /* XXX vtb, history */
+ }
+ bzero(sc, sizeof(*sc));
+ sc->keyboard = -1;
+ sc->adapter = -1;
}
static void
scshutdown(int howto, void *arg)
{
+ /* assert(sc_console != NULL) */
+
sc_touch_scrn_saver();
- if (!cold && cur_console->smode.mode == VT_AUTO
- && console[0]->smode.mode == VT_AUTO)
- switch_scr(cur_console, 0);
+ if (!cold && sc_console
+ && sc_console->sc->cur_scp->smode.mode == VT_AUTO
+ && sc_console->smode.mode == VT_AUTO)
+ switch_scr(sc_console->sc, sc_console->index);
shutdown_in_progress = TRUE;
}
@@ -3305,108 +3418,83 @@ sc_clean_up(scr_stat *scp)
int error;
sc_touch_scrn_saver();
- if ((error = wait_scrn_saver_stop()))
+#if NSPLASH > 0
+ if ((error = wait_scrn_saver_stop(scp->sc)))
return error;
+#endif /* NSPLASH */
scp->status &= ~MOUSE_VISIBLE;
- remove_cutmarking(scp);
+ sc_remove_cutmarking(scp);
return 0;
}
void
-sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
+sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
{
- if (scp->scr_buf)
- free(scp->scr_buf, M_DEVBUF);
- scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
- M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+ sc_vtb_t new;
+ sc_vtb_t old;
+ int s;
- if (clear) {
+ old = scp->vtb;
+ sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
+ if (!discard && (old.vtb_flags & VTB_VALID)) {
+ /* retain the current cursor position and buffer contants */
+ scp->cursor_oldpos = scp->cursor_pos;
+ /*
+ * This works only if the old buffer has the same size as or larger
+ * than the new one. XXX
+ */
+ sc_vtb_copy(&old, 0, &new, 0, scp->xsize*scp->ysize);
+ scp->vtb = new;
+ } else {
/* clear the screen and move the text cursor to the top-left position */
+ s = splhigh();
+ scp->vtb = new;
sc_clear_screen(scp);
- } else {
- /* retain the current cursor position, but adjust pointers */
- move_crsr(scp, scp->xpos, scp->ypos);
- scp->cursor_oldpos = scp->cursor_pos;
+ splx(s);
+ sc_vtb_destroy(&old);
}
+#ifndef SC_NO_SYSMOUSE
/* move the mouse cursor at the center of the screen */
- sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
-}
-
-void
-sc_alloc_cut_buffer(scr_stat *scp, int wait)
-{
- if ((cut_buffer == NULL)
- || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
- if (cut_buffer != NULL)
- free(cut_buffer, M_DEVBUF);
- cut_buffer_size = scp->xsize * scp->ysize + 1;
- cut_buffer = (u_char *)malloc(cut_buffer_size,
- M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
- if (cut_buffer != NULL)
- cut_buffer[0] = '\0';
- }
-}
-
-void
-sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
-{
- u_short *usp;
-
- if (lines < scp->ysize)
- lines = scp->ysize;
-
- usp = scp->history;
- scp->history = NULL;
- if (usp != NULL) {
- free(usp, M_DEVBUF);
- if (extra > 0)
- extra_history_size += extra;
- }
-
- scp->history_size = lines * scp->xsize;
- if (lines > imax(sc_history_size, scp->ysize))
- extra_history_size -= lines - imax(sc_history_size, scp->ysize);
- usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
- M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
- if (usp != NULL)
- bzero(usp, scp->history_size * sizeof(u_short));
- scp->history_head = scp->history_pos = usp;
- scp->history = usp;
+ sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
+#endif
}
static scr_stat
-*alloc_scp()
+*alloc_scp(sc_softc_t *sc, int vty)
{
scr_stat *scp;
+ /* assert(sc_malloc) */
+
scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
- init_scp(scp);
+ init_scp(sc, vty, scp);
+
sc_alloc_scr_buffer(scp, TRUE, TRUE);
- if (ISMOUSEAVAIL(scp->adp->va_flags))
+
+#ifndef SC_NO_SYSMOUSE
+ if (ISMOUSEAVAIL(sc->adp->va_flags))
sc_alloc_cut_buffer(scp, TRUE);
- sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
-/* SOS
- if (scp->adp->va_flags & V_ADP_MODECHANGE)
- set_mode(scp);
-*/
+#endif
+
+#ifndef SC_NO_HISTORY
+ sc_alloc_history_buffer(scp, 0, TRUE);
+#endif
+
sc_clear_screen(scp);
- scp->cursor_saveunder = *scp->cursor_pos;
return scp;
}
static void
-init_scp(scr_stat *scp)
+init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
{
video_info_t info;
- scp->ad = adapter;
- scp->adp = vid_get_adapter(scp->ad);
- (*vidsw[scp->ad]->get_info)(scp->adp, initial_video_mode, &info);
-
+ scp->index = vty;
+ scp->sc = sc;
scp->status = 0;
- scp->mode = initial_video_mode;
- scp->scr_buf = NULL;
+ scp->mode = sc->initial_mode;
+ (*vidsw[sc->adapter]->get_info)(sc->adp, scp->mode, &info);
if (info.vi_flags & V_INFO_GRAPHICS) {
scp->status |= GRAPHICS_MODE;
scp->xpixel = info.vi_width;
@@ -3414,17 +3502,41 @@ init_scp(scr_stat *scp)
scp->xsize = info.vi_width/8;
scp->ysize = info.vi_height/info.vi_cheight;
scp->font_size = FONT_NONE;
+ scp->font = NULL;
} else {
scp->xsize = info.vi_width;
scp->ysize = info.vi_height;
scp->xpixel = scp->xsize*8;
scp->ypixel = scp->ysize*info.vi_cheight;
- scp->font_size = info.vi_cheight;
+ if (info.vi_cheight < 14) {
+ scp->font_size = 8;
+#ifndef SC_NO_FONT_LOADING
+ scp->font = sc->font_8;
+#else
+ scp->font = NULL;
+#endif
+ } else if (info.vi_cheight >= 16) {
+ scp->font_size = 16;
+#ifndef SC_NO_FONT_LOADING
+ scp->font = sc->font_16;
+#else
+ scp->font = NULL;
+#endif
+ } else {
+ scp->font_size = 14;
+#ifndef SC_NO_FONT_LOADING
+ scp->font = sc->font_14;
+#else
+ scp->font = NULL;
+#endif
+ }
}
+ sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
+ sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
scp->xoff = scp->yoff = 0;
scp->xpos = scp->ypos = 0;
scp->saved_xpos = scp->saved_ypos = -1;
- scp->start = scp->xsize * scp->ysize;
+ scp->start = scp->xsize * scp->ysize - 1;
scp->end = 0;
scp->term.esc = 0;
scp->term.attr_mask = NORMAL_ATTR;
@@ -3433,70 +3545,30 @@ init_scp(scr_stat *scp)
current_default->std_color;
scp->term.rev_color = current_default->rev_color;
scp->border = BG_BLACK;
- scp->cursor_start = bios_value.cursor_start;
- scp->cursor_end = bios_value.cursor_end;
- scp->mouse_xpos = scp->xsize*8/2;
- scp->mouse_ypos = scp->ysize*scp->font_size/2;
- scp->mouse_cut_start = scp->mouse_cut_end = NULL;
+ scp->cursor_base = sc->cursor_base;
+ scp->cursor_height = imin(sc->cursor_height, scp->font_size);
+ scp->mouse_xpos = scp->xoff*8 + scp->xsize*8/2;
+ scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size/2;
+ scp->mouse_cut_start = scp->xsize*scp->ysize;
+ scp->mouse_cut_end = -1;
scp->mouse_signal = 0;
scp->mouse_pid = 0;
scp->mouse_proc = NULL;
scp->kbd_mode = K_XLATE;
- scp->bell_pitch = BELL_PITCH;
+ scp->bell_pitch = bios_value.bell_pitch;
scp->bell_duration = BELL_DURATION;
- scp->status |= (bios_value.shift_state & 0x20) ? NLKED : 0;
+ scp->status |= (bios_value.shift_state & NLKED);
scp->status |= CURSOR_ENABLED;
scp->pid = 0;
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
- scp->history_head = scp->history_pos = scp->history = NULL;
- scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
-}
-
-static void
-get_bios_values(void)
-{
- bios_value.cursor_start = *(u_int8_t *)pa_to_va(0x461);
- bios_value.cursor_end = *(u_int8_t *)pa_to_va(0x460);
- bios_value.shift_state = *(u_int8_t *)pa_to_va(0x417);
-}
-
-static void
-history_to_screen(scr_stat *scp)
-{
- int i;
-
- for (i=0; i<scp->ysize; i++)
- bcopy(scp->history + (((scp->history_pos - scp->history) +
- scp->history_size-((i+1)*scp->xsize))%scp->history_size),
- scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)),
- scp->xsize * sizeof(u_short));
- mark_all(scp);
-}
-
-static int
-history_up_line(scr_stat *scp)
-{
- if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) !=
- scp->history_head) {
- scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize);
- history_to_screen(scp);
- return 0;
- }
- else
- return -1;
-}
+ scp->history = NULL;
+ scp->history_pos = 0;
+ scp->history_size = 0;
-static int
-history_down_line(scr_stat *scp)
-{
- if (scp->history_pos != scp->history_head) {
- scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize);
- history_to_screen(scp);
- return 0;
- }
- else
- return -1;
+ /* what if the following call fails... XXX */
+ scp->rndr = sc_render_match(scp, scp->sc->adp,
+ scp->status & (GRAPHICS_MODE | PIXEL_MODE));
}
/*
@@ -3506,26 +3578,30 @@ history_down_line(scr_stat *scp)
* return NOKEY if there is nothing there.
*/
static u_int
-scgetc(keyboard_t *kbd, u_int flags)
+scgetc(sc_softc_t *sc, u_int flags)
{
+ scr_stat *scp;
u_int c;
int this_scr;
int f;
int i;
- if (kbd == NULL)
+ if (sc->kbd == NULL)
return NOKEY;
next_code:
+#if 1
/* I don't like this, but... XXX */
if (flags & SCGETC_CN)
- sccnupdate(cur_console);
+ sccnupdate(sc->cur_scp);
+#endif
+ scp = sc->cur_scp;
/* first see if there is something in the keyboard port */
for (;;) {
- c = kbd_read_char(kbd, !(flags & SCGETC_NONBLOCK));
+ c = kbd_read_char(sc->kbd, !(flags & SCGETC_NONBLOCK));
if (c == ERRKEY) {
if (!(flags & SCGETC_CN))
- do_bell(cur_console, BELL_PITCH, BELL_DURATION);
+ do_bell(scp, bios_value.bell_pitch, BELL_DURATION);
} else if (c == NOKEY)
return c;
else
@@ -3542,81 +3618,67 @@ next_code:
add_keyboard_randomness(c);
#endif
- if (cur_console->kbd_mode != K_XLATE)
+ if (scp->kbd_mode != K_XLATE)
return KEYCHAR(c);
/* if scroll-lock pressed allow history browsing */
- if (!ISGRAPHSC(cur_console) && cur_console->history
- && cur_console->status & SLKED) {
-
- cur_console->status &= ~CURSOR_ENABLED;
- if (!(cur_console->status & BUFFER_SAVED)) {
- cur_console->status |= BUFFER_SAVED;
- cur_console->history_save = cur_console->history_head;
-
- /* copy screen into top of history buffer */
- for (i=0; i<cur_console->ysize; i++) {
- bcopy(cur_console->scr_buf + (cur_console->xsize * i),
- cur_console->history_head,
- cur_console->xsize * sizeof(u_short));
- cur_console->history_head += cur_console->xsize;
- if (cur_console->history_head + cur_console->xsize >
- cur_console->history + cur_console->history_size)
- cur_console->history_head=cur_console->history;
- }
- cur_console->history_pos = cur_console->history_head;
- history_to_screen(cur_console);
+ if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) {
+
+ scp->status &= ~CURSOR_ENABLED;
+ remove_cursor_image(scp);
+
+#ifndef SC_NO_HISTORY
+ if (!(scp->status & BUFFER_SAVED)) {
+ scp->status |= BUFFER_SAVED;
+ sc_hist_save(scp);
}
switch (c) {
/* FIXME: key codes */
case SPCLKEY | FKEY | F(49): /* home key */
- remove_cutmarking(cur_console);
- cur_console->history_pos = cur_console->history_head;
- history_to_screen(cur_console);
+ sc_remove_cutmarking(scp);
+ sc_hist_home(scp);
goto next_code;
case SPCLKEY | FKEY | F(57): /* end key */
- remove_cutmarking(cur_console);
- cur_console->history_pos =
- WRAPHIST(cur_console, cur_console->history_head,
- cur_console->xsize*cur_console->ysize);
- history_to_screen(cur_console);
+ sc_remove_cutmarking(scp);
+ sc_hist_end(scp);
goto next_code;
case SPCLKEY | FKEY | F(50): /* up arrow key */
- remove_cutmarking(cur_console);
- if (history_up_line(cur_console))
+ sc_remove_cutmarking(scp);
+ if (sc_hist_up_line(scp))
if (!(flags & SCGETC_CN))
- do_bell(cur_console, BELL_PITCH, BELL_DURATION);
+ do_bell(scp, bios_value.bell_pitch, BELL_DURATION);
goto next_code;
case SPCLKEY | FKEY | F(58): /* down arrow key */
- remove_cutmarking(cur_console);
- if (history_down_line(cur_console))
+ sc_remove_cutmarking(scp);
+ if (sc_hist_down_line(scp))
if (!(flags & SCGETC_CN))
- do_bell(cur_console, BELL_PITCH, BELL_DURATION);
+ do_bell(scp, bios_value.bell_pitch, BELL_DURATION);
goto next_code;
case SPCLKEY | FKEY | F(51): /* page up key */
- remove_cutmarking(cur_console);
- for (i=0; i<cur_console->ysize; i++)
- if (history_up_line(cur_console)) {
+ sc_remove_cutmarking(scp);
+ for (i=0; i<scp->ysize; i++)
+ if (sc_hist_up_line(scp)) {
if (!(flags & SCGETC_CN))
- do_bell(cur_console, BELL_PITCH, BELL_DURATION);
+ do_bell(scp, bios_value.bell_pitch, BELL_DURATION);
break;
}
goto next_code;
case SPCLKEY | FKEY | F(59): /* page down key */
- remove_cutmarking(cur_console);
- for (i=0; i<cur_console->ysize; i++)
- if (history_down_line(cur_console)) {
+ sc_remove_cutmarking(scp);
+ for (i=0; i<scp->ysize; i++)
+ if (sc_hist_down_line(scp)) {
if (!(flags & SCGETC_CN))
- do_bell(cur_console, BELL_PITCH, BELL_DURATION);
+ do_bell(scp, bios_value.bell_pitch, BELL_DURATION);
break;
}
goto next_code;
}
+#endif /* SC_NO_HISTORY */
}
/*
@@ -3635,33 +3697,22 @@ next_code:
case NLK: case CLK: case ALK:
break;
case SLK:
- kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&f);
+ kbd_ioctl(sc->kbd, KDGKBSTATE, (caddr_t)&f);
if (f & SLKED) {
- cur_console->status |= SLKED;
+ scp->status |= SLKED;
} else {
- if (cur_console->status & SLKED) {
- cur_console->status &= ~SLKED;
- if (cur_console->status & BUFFER_SAVED) {
- int i;
- u_short *ptr = cur_console->history_save;
-
- for (i=0; i<cur_console->ysize; i++) {
- bcopy(ptr,
- cur_console->scr_buf +
- (cur_console->xsize*i),
- cur_console->xsize * sizeof(u_short));
- ptr += cur_console->xsize;
- if (ptr + cur_console->xsize >
- cur_console->history +
- cur_console->history_size)
- ptr = cur_console->history;
- }
- cur_console->status &= ~BUFFER_SAVED;
- cur_console->history_head=cur_console->history_save;
- cur_console->status |= CURSOR_ENABLED;
- mark_all(cur_console);
+ if (scp->status & SLKED) {
+ scp->status &= ~SLKED;
+#ifndef SC_NO_HISTORY
+ if (scp->status & BUFFER_SAVED) {
+ if (!sc_hist_restore(scp))
+ sc_remove_cutmarking(scp);
+ scp->status &= ~BUFFER_SAVED;
+ scp->status |= CURSOR_ENABLED;
+ draw_cursor_image(scp);
}
- scstart(VIRTUAL_TTY(get_scr_num()));
+#endif
+ scstart(VIRTUAL_TTY(sc, scp->index));
}
}
break;
@@ -3673,27 +3724,29 @@ next_code:
break;
case BTAB:
- return c;
+ if (!(sc->flags & SC_SCRN_BLANKED))
+ return c;
+ break;
case SPSC:
+#if NSPLASH > 0
/* force activatation/deactivation of the screen saver */
- if (!scrn_blanked) {
+ if (!(sc->flags & SC_SCRN_BLANKED)) {
run_scrn_saver = TRUE;
- scrn_time_stamp -= scrn_blank_time;
+ sc->scrn_time_stamp -= scrn_blank_time;
}
-#if NSPLASH > 0
if (cold) {
/*
* While devices are being probed, the screen saver need
* to be invoked explictly. XXX
*/
- if (scrn_blanked) {
+ if (sc->flags & SC_SCRN_BLANKED) {
scsplash_stick(FALSE);
- stop_scrn_saver(current_saver);
+ stop_scrn_saver(sc, current_saver);
} else {
- if (!ISGRAPHSC(cur_console)) {
+ if (!ISGRAPHSC(scp)) {
scsplash_stick(TRUE);
- (*current_saver)(TRUE);
+ (*current_saver)(sc, TRUE);
}
}
}
@@ -3720,28 +3773,53 @@ next_code:
#endif
case DBG:
-#ifdef DDB /* try to switch to console 0 */
- /*
- * TRY to make sure the screen saver is stopped,
- * and the screen is updated before switching to
- * the vty0.
- */
- scrn_timer((void *)FALSE);
- if (cur_console->smode.mode == VT_AUTO &&
- console[0]->smode.mode == VT_AUTO)
- switch_scr(cur_console, 0);
+#ifndef SC_DISABLE_DDBKEY
+#ifdef DDB
+ if (debugger)
+ break;
+ /* try to switch to the kernel console screen */
+ if (sc_console) {
+ /*
+ * TRY to make sure the screen saver is stopped,
+ * and the screen is updated before switching to
+ * the vty0.
+ */
+ scrn_timer(NULL);
+ if (!cold
+ && sc_console->sc->cur_scp->smode.mode == VT_AUTO
+ && sc_console->smode.mode == VT_AUTO)
+ switch_scr(sc_console->sc, sc_console->index);
+ }
Debugger("manual escape to debugger");
#else
printf("No debugger in kernel\n");
#endif
+#else /* SC_DISABLE_DDBKEY */
+ /* do nothing */
+#endif /* SC_DISABLE_DDBKEY */
break;
case NEXT:
- this_scr = get_scr_num();
- for (i = this_scr + 1; i != this_scr; i = (i + 1)%MAXCONS) {
- struct tty *tp = VIRTUAL_TTY(i);
+ this_scr = scp->index;
+ for (i = (this_scr - sc->first_vty + 1)%sc->vtys;
+ sc->first_vty + i != this_scr;
+ i = (i + 1)%sc->vtys) {
+ struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
+ if (tp->t_state & TS_ISOPEN) {
+ switch_scr(scp->sc, sc->first_vty + i);
+ break;
+ }
+ }
+ break;
+
+ case PREV:
+ this_scr = scp->index;
+ for (i = (this_scr - sc->first_vty + sc->vtys - 1)%sc->vtys;
+ sc->first_vty + i != this_scr;
+ i = (i + sc->vtys - 1)%sc->vtys) {
+ struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
if (tp->t_state & TS_ISOPEN) {
- switch_scr(cur_console, i);
+ switch_scr(scp->sc, sc->first_vty + i);
break;
}
}
@@ -3749,16 +3827,19 @@ next_code:
default:
if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) {
- switch_scr(cur_console, KEYCHAR(c) - F_SCR);
+ switch_scr(scp->sc, sc->first_vty + KEYCHAR(c) - F_SCR);
break;
}
/* assert(c & FKEY) */
- return c;
+ if (!(sc->flags & SC_SCRN_BLANKED))
+ return c;
+ break;
}
/* goto next_code */
} else {
/* regular keys (maybe MKEY is set) */
- return c;
+ if (!(sc->flags & SC_SCRN_BLANKED))
+ return c;
}
}
@@ -3775,7 +3856,7 @@ scmmap(dev_t dev, vm_offset_t offset, int nprot)
if (!tp)
return ENXIO;
scp = sc_get_scr_stat(tp->t_dev);
- return (*vidsw[scp->ad]->mmap)(scp->adp, offset);
+ return (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, offset, nprot);
}
/*
@@ -3813,7 +3894,7 @@ save_kbd_state(scr_stat *scp)
int state;
int error;
- error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state);
+ error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
if (error == ENOIOCTL)
error = ENODEV;
if (error == 0) {
@@ -3824,13 +3905,13 @@ save_kbd_state(scr_stat *scp)
}
static int
-update_kbd_state(int new_bits, int mask)
+update_kbd_state(scr_stat *scp, int new_bits, int mask)
{
int state;
int error;
if (mask != LOCK_MASK) {
- error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state);
+ error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
if (error == ENOIOCTL)
error = ENODEV;
if (error)
@@ -3840,19 +3921,19 @@ update_kbd_state(int new_bits, int mask)
} else {
state = new_bits & LOCK_MASK;
}
- error = kbd_ioctl(kbd, KDSKBSTATE, (caddr_t)&state);
+ error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state);
if (error == ENOIOCTL)
error = ENODEV;
return error;
}
static int
-update_kbd_leds(int which)
+update_kbd_leds(scr_stat *scp, int which)
{
int error;
which &= LOCK_MASK;
- error = kbd_ioctl(kbd, KDSETLED, (caddr_t)&which);
+ error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which);
if (error == ENOIOCTL)
error = ENODEV;
return error;
@@ -3864,28 +3945,31 @@ set_mode(scr_stat *scp)
video_info_t info;
/* reject unsupported mode */
- if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info))
+ if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info))
return 1;
/* if this vty is not currently showing, do nothing */
- if (scp != cur_console)
+ if (scp != scp->sc->cur_scp)
return 0;
/* setup video hardware for the given mode */
- (*vidsw[scp->ad]->set_mode)(scp->adp, scp->mode);
+ (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
+ sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
+ (void *)scp->sc->adp->va_window, FALSE);
+#ifndef SC_NO_FONT_LOADING
+ /* load appropriate font */
if (!(scp->status & GRAPHICS_MODE)) {
- /* load appropriate font */
- if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->adp->va_flags)) {
+ if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) {
if (scp->font_size < 14) {
- if (fonts_loaded & FONT_8)
- copy_font(scp, LOAD, 8, font_8);
+ if (scp->sc->fonts_loaded & FONT_8)
+ copy_font(scp, LOAD, 8, scp->sc->font_8);
} else if (scp->font_size >= 16) {
- if (fonts_loaded & FONT_16)
- copy_font(scp, LOAD, 16, font_16);
+ if (scp->sc->fonts_loaded & FONT_16)
+ copy_font(scp, LOAD, 16, scp->sc->font_16);
} else {
- if (fonts_loaded & FONT_14)
- copy_font(scp, LOAD, 14, font_14);
+ if (scp->sc->fonts_loaded & FONT_14)
+ copy_font(scp, LOAD, 14, scp->sc->font_14);
}
/*
* FONT KLUDGE:
@@ -3894,18 +3978,14 @@ set_mode(scr_stat *scp)
* Somehow we cannot show the font in other font pages on
* some video cards... XXX
*/
- (*vidsw[scp->ad]->show_font)(scp->adp, 0);
+ (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, 0);
}
mark_all(scp);
}
-
- if (scp->status & PIXEL_MODE)
- bzero_io(scp->adp->va_window, scp->xpixel*scp->ypixel/8);
+#endif /* !SC_NO_FONT_LOADING */
set_border(scp, scp->border);
-
- /* move hardware cursor out of the way */
- (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1);
+ sc_set_cursor_image(scp);
return 0;
}
@@ -3913,43 +3993,12 @@ set_mode(scr_stat *scp)
void
set_border(scr_stat *scp, int color)
{
- vm_offset_t p;
- int xoff;
- int yoff;
- int xlen;
- int ylen;
- int i;
-
- (*vidsw[scp->ad]->set_border)(scp->adp, color);
-
- if (scp->status & PIXEL_MODE) {
- outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
- outw(GDCIDX, 0x0003); /* data rotate/function select */
- outw(GDCIDX, 0x0f01); /* set/reset enable */
- outw(GDCIDX, 0xff08); /* bit mask */
- outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
- p = scp->adp->va_window;
- xoff = scp->xoff;
- yoff = scp->yoff*scp->font_size;
- xlen = scp->xpixel/8;
- ylen = scp->ysize*scp->font_size;
- if (yoff > 0) {
- bzero_io(p, xlen*yoff);
- bzero_io(p + xlen*(yoff + ylen),
- xlen*scp->ypixel - xlen*(yoff + ylen));
- }
- if (xoff > 0) {
- for (i = 0; i < ylen; ++i) {
- bzero_io(p + xlen*(yoff + i), xoff);
- bzero_io(p + xlen*(yoff + i) + xoff + scp->xsize,
- xlen - xoff - scp->xsize);
- }
- }
- outw(GDCIDX, 0x0000); /* set/reset */
- outw(GDCIDX, 0x0001); /* set/reset enable */
- }
+ ++scp->sc->videoio_in_progress;
+ (*scp->rndr->draw_border)(scp, color);
+ --scp->sc->videoio_in_progress;
}
+#ifndef SC_NO_FONT_LOADING
void
copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
{
@@ -3960,450 +4009,41 @@ copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
* Somehow we cannot show the font in other font pages on
* some video cards... XXX
*/
- font_loading_in_progress = TRUE;
+ scp->sc->font_loading_in_progress = TRUE;
if (operation == LOAD) {
- (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, buf, 0, 256);
- if (sc_flags & CHAR_CURSOR)
- set_destructive_cursor(scp);
+ (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, font_size,
+ buf, 0, 256);
} else if (operation == SAVE) {
- (*vidsw[scp->ad]->save_font)(scp->adp, 0, font_size, buf, 0, 256);
+ (*vidsw[scp->sc->adapter]->save_font)(scp->sc->adp, 0, font_size,
+ buf, 0, 256);
}
- font_loading_in_progress = FALSE;
+ scp->sc->font_loading_in_progress = FALSE;
}
+#endif /* !SC_NO_FONT_LOADING */
-static void
-set_destructive_cursor(scr_stat *scp)
+#ifndef SC_NO_SYSMOUSE
+struct tty
+*sc_get_mouse_tty(void)
{
- u_char cursor[32];
- u_char *font_buffer;
- int font_size;
- int crtc_addr;
- int i;
-
- if (!ISFONTAVAIL(scp->adp->va_flags)
- || (scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
- return;
-
- if (scp->font_size < 14) {
- font_buffer = font_8;
- font_size = 8;
- } else if (scp->font_size >= 16) {
- font_buffer = font_16;
- font_size = 16;
- } else {
- font_buffer = font_14;
- font_size = 14;
- }
-
- if (scp->status & MOUSE_VISIBLE) {
- if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
- bcopy(&scp->mouse_cursor[0], cursor, scp->font_size);
- else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1)
- bcopy(&scp->mouse_cursor[32], cursor, scp->font_size);
- else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2)
- bcopy(&scp->mouse_cursor[64], cursor, scp->font_size);
- else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3)
- bcopy(&scp->mouse_cursor[96], cursor, scp->font_size);
- else
- bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size),
- cursor, scp->font_size);
- }
- else
- bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size),
- cursor, scp->font_size);
- for (i=0; i<32; i++)
- if ((i >= scp->cursor_start && i <= scp->cursor_end) ||
- (scp->cursor_start >= scp->font_size && i == scp->font_size - 1))
- cursor[i] |= 0xff;
-#if 1
- crtc_addr = scp->adp->va_crtc_addr;
- while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
-#endif
- font_loading_in_progress = TRUE;
- (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
- font_loading_in_progress = FALSE;
+ return MOUSE_TTY;
}
+#endif /* !SC_NO_SYSMOUSE */
+#ifndef SC_NO_CUTPASTE
void
-sc_move_mouse(scr_stat *scp, int x, int y)
+sc_paste(scr_stat *scp, u_char *p, int count)
{
- scp->mouse_xpos = x;
- scp->mouse_ypos = y;
- scp->mouse_pos = scp->mouse_oldpos =
- scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
-}
-
-static void
-set_mouse_pos(scr_stat *scp)
-{
- static int last_xpos = -1, last_ypos = -1;
-
- if (scp->mouse_xpos < 0)
- scp->mouse_xpos = 0;
- if (scp->mouse_ypos < 0)
- scp->mouse_ypos = 0;
- if (!ISTEXTSC(scp)) {
- if (scp->mouse_xpos > scp->xpixel-1)
- scp->mouse_xpos = scp->xpixel-1;
- if (scp->mouse_ypos > scp->ypixel-1)
- scp->mouse_ypos = scp->ypixel-1;
- return;
- }
- if (scp->mouse_xpos > (scp->xsize*8)-1)
- scp->mouse_xpos = (scp->xsize*8)-1;
- if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1)
- scp->mouse_ypos = (scp->ysize*scp->font_size)-1;
-
- if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
- scp->status |= MOUSE_MOVED;
-
- scp->mouse_pos = scp->scr_buf +
- ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8);
-
- if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
- mouse_cut(scp);
- }
-}
-
-#define isspace(c) (((c) & 0xff) == ' ')
-
-static int
-skip_spc_right(scr_stat *scp, u_short *p)
-{
- int i;
-
- for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
- if (!isspace(*p))
- break;
- ++p;
- }
- return i;
-}
-
-static int
-skip_spc_left(scr_stat *scp, u_short *p)
-{
- int i;
-
- for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) {
- if (!isspace(*p))
- break;
- --p;
- }
- return i;
-}
-
-static void
-mouse_cut(scr_stat *scp)
-{
- u_short *end;
- u_short *p;
- int i = 0;
- int j = 0;
-
- scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ?
- scp->mouse_pos + 1 : scp->mouse_pos;
- end = (scp->mouse_cut_start > scp->mouse_cut_end) ?
- scp->mouse_cut_start : scp->mouse_cut_end;
- for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ?
- scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) {
- cut_buffer[i] = *p & 0xff;
- /* remember the position of the last non-space char */
- if (!isspace(cut_buffer[i++]))
- j = i;
- /* trim trailing blank when crossing lines */
- if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) {
- cut_buffer[j++] = '\r';
- i = j;
- }
- }
- cut_buffer[i] = '\0';
-
- /* scan towards the end of the last line */
- --p;
- for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
- if (!isspace(*p))
- break;
- ++p;
- }
- /* if there is nothing but blank chars, trim them, but mark towards eol */
- if (i >= scp->xsize) {
- if (scp->mouse_cut_start > scp->mouse_cut_end)
- scp->mouse_cut_start = p;
- else
- scp->mouse_cut_end = p;
- cut_buffer[j++] = '\r';
- cut_buffer[j] = '\0';
- }
-
- mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf);
- mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf);
-}
-
-static void
-mouse_cut_start(scr_stat *scp)
-{
- int i;
-
- if (scp->status & MOUSE_VISIBLE) {
- if (scp->mouse_pos == scp->mouse_cut_start &&
- scp->mouse_cut_start == scp->mouse_cut_end - 1) {
- cut_buffer[0] = '\0';
- remove_cutmarking(scp);
- } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
- /* if the pointer is on trailing blank chars, mark towards eol */
- i = skip_spc_left(scp, scp->mouse_pos) + 1;
- scp->mouse_cut_start = scp->scr_buf +
- ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i;
- scp->mouse_cut_end = scp->scr_buf +
- ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize;
- cut_buffer[0] = '\r';
- cut_buffer[1] = '\0';
- scp->status |= MOUSE_CUTTING;
- } else {
- scp->mouse_cut_start = scp->mouse_pos;
- scp->mouse_cut_end = scp->mouse_cut_start + 1;
- cut_buffer[0] = *scp->mouse_cut_start & 0xff;
- cut_buffer[1] = '\0';
- scp->status |= MOUSE_CUTTING;
- }
- mark_all(scp);
- /* delete all other screens cut markings */
- for (i=0; i<MAXCONS; i++) {
- if (console[i] == NULL || console[i] == scp)
- continue;
- remove_cutmarking(console[i]);
- }
- }
-}
-
-static void
-mouse_cut_end(scr_stat *scp)
-{
- if (scp->status & MOUSE_VISIBLE) {
- scp->status &= ~MOUSE_CUTTING;
- }
-}
-
-static void
-mouse_cut_word(scr_stat *scp)
-{
- u_short *p;
- u_short *sol;
- u_short *eol;
- int i;
-
- /*
- * Because we don't have locale information in the kernel,
- * we only distinguish space char and non-space chars. Punctuation
- * chars, symbols and other regular chars are all treated alike.
- */
- if (scp->status & MOUSE_VISIBLE) {
- sol = scp->scr_buf
- + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
- eol = sol + scp->xsize;
- if (isspace(*scp->mouse_pos)) {
- for (p = scp->mouse_pos; p >= sol; --p)
- if (!isspace(*p))
- break;
- scp->mouse_cut_start = ++p;
- for (p = scp->mouse_pos; p < eol; ++p)
- if (!isspace(*p))
- break;
- scp->mouse_cut_end = p;
- } else {
- for (p = scp->mouse_pos; p >= sol; --p)
- if (isspace(*p))
- break;
- scp->mouse_cut_start = ++p;
- for (p = scp->mouse_pos; p < eol; ++p)
- if (isspace(*p))
- break;
- scp->mouse_cut_end = p;
- }
- for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
- cut_buffer[i++] = *p & 0xff;
- cut_buffer[i] = '\0';
- scp->status |= MOUSE_CUTTING;
- }
-}
-
-static void
-mouse_cut_line(scr_stat *scp)
-{
- u_short *p;
- int i;
-
- if (scp->status & MOUSE_VISIBLE) {
- scp->mouse_cut_start = scp->scr_buf
- + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
- scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize;
- for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
- cut_buffer[i++] = *p & 0xff;
- cut_buffer[i++] = '\r';
- cut_buffer[i] = '\0';
- scp->status |= MOUSE_CUTTING;
- }
-}
-
-static void
-mouse_cut_extend(scr_stat *scp)
-{
- if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
- && (scp->mouse_cut_start != NULL)) {
- mouse_cut(scp);
- scp->status |= MOUSE_CUTTING;
- }
-}
+ struct tty *tp;
+ u_char *rmap;
-static void
-mouse_paste(scr_stat *scp)
-{
if (scp->status & MOUSE_VISIBLE) {
- struct tty *tp;
- u_char *ptr = cut_buffer;
-
- tp = VIRTUAL_TTY(get_scr_num());
- while (*ptr)
- (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp);
- }
-}
-
-static void
-draw_mouse_image(scr_stat *scp)
-{
- u_short buffer[32];
- u_short xoffset, yoffset;
- vm_offset_t crt_pos = scp->adp->va_window + 2*(scp->mouse_pos - scp->scr_buf);
- u_char *font_buffer;
- int font_size;
- int crtc_addr;
- int i;
-
- if (scp->font_size < 14) {
- font_buffer = font_8;
- font_size = 8;
- } else if (scp->font_size >= 16) {
- font_buffer = font_16;
- font_size = 16;
- } else {
- font_buffer = font_14;
- font_size = 14;
- }
-
- xoffset = scp->mouse_xpos % 8;
- yoffset = scp->mouse_ypos % scp->font_size;
-
- /* prepare mousepointer char's bitmaps */
- bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
- &scp->mouse_cursor[0], font_size);
- bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size),
- &scp->mouse_cursor[32], font_size);
- bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size),
- &scp->mouse_cursor[64], font_size);
- bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size),
- &scp->mouse_cursor[96], font_size);
- for (i=0; i<font_size; i++) {
- buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32];
- buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96];
- }
-
- /* now and-or in the mousepointer image */
- for (i=0; i<16; i++) {
- buffer[i+yoffset] =
- ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset))
- | (mouse_or_mask[i] >> xoffset);
- }
- for (i=0; i<font_size; i++) {
- scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8;
- scp->mouse_cursor[i+32] = buffer[i] & 0xff;
- scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8;
- scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff;
- }
-
- scp->mouse_oldpos = scp->mouse_pos;
-
-#if 1
- /* wait for vertical retrace to avoid jitter on some videocards */
- crtc_addr = scp->adp->va_crtc_addr;
- while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
-#endif
- font_loading_in_progress = TRUE;
- (*vidsw[scp->ad]->load_font)(scp->adp, 0, 32, scp->mouse_cursor,
- SC_MOUSE_CHAR, 4);
- font_loading_in_progress = FALSE;
-
- writew(crt_pos, (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR);
- writew(crt_pos+2*scp->xsize,
- (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2));
- if (scp->mouse_xpos < (scp->xsize-1)*8) {
- writew(crt_pos + 2, (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1));
- writew(crt_pos+2*scp->xsize + 2,
- (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3));
- }
- mark_for_update(scp, scp->mouse_pos - scp->scr_buf);
- mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf);
-}
-
-static void
-remove_mouse_image(scr_stat *scp)
-{
- vm_offset_t crt_pos;
-
- if (!ISTEXTSC(scp))
- return;
-
- crt_pos = scp->adp->va_window + 2*(scp->mouse_oldpos - scp->scr_buf);
- writew(crt_pos, *(scp->mouse_oldpos));
- writew(crt_pos+2, *(scp->mouse_oldpos+1));
- writew(crt_pos+2*scp->xsize, *(scp->mouse_oldpos+scp->xsize));
- writew(crt_pos+2*scp->xsize+2, *(scp->mouse_oldpos+scp->xsize+1));
- mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf);
- mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf);
-}
-
-static void
-draw_cutmarking(scr_stat *scp)
-{
- vm_offset_t crt_pos;
- u_short *ptr;
- u_short och, nch;
-
- crt_pos = scp->adp->va_window;
- for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) {
- nch = och = readw(crt_pos + 2*(ptr - scp->scr_buf));
- /* are we outside the selected area ? */
- if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ?
- scp->mouse_cut_end : scp->mouse_cut_start) ||
- ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ?
- scp->mouse_cut_start : scp->mouse_cut_end)) {
- if (ptr != scp->cursor_pos)
- nch = (och & 0xff) | (*ptr & 0xff00);
- }
- else {
- /* are we clear of the cursor image ? */
- if (ptr != scp->cursor_pos)
- nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4;
- else {
- if (sc_flags & CHAR_CURSOR)
- nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4;
- else
- if (!(sc_flags & BLINK_CURSOR))
- nch = (och & 0xff) | (*ptr & 0xff00);
- }
- }
- if (nch != och)
- writew(crt_pos + 2*(ptr - scp->scr_buf), nch);
+ tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index);
+ rmap = scp->sc->scr_rmap;
+ for (; count > 0; --count)
+ (*linesw[tp->t_line].l_rint)(rmap[*p++], tp);
}
}
-
-static void
-remove_cutmarking(scr_stat *scp)
-{
- scp->mouse_cut_start = scp->mouse_cut_end = NULL;
- scp->status &= ~MOUSE_CUTTING;
- mark_all(scp);
-}
+#endif /* SC_NO_CUTPASTE */
static void
do_bell(scr_stat *scp, int pitch, int duration)
@@ -4411,18 +4051,18 @@ do_bell(scr_stat *scp, int pitch, int duration)
if (cold || shutdown_in_progress)
return;
- if (scp != cur_console && (sc_flags & QUIET_BELL))
+ if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL))
return;
- if (sc_flags & VISUAL_BELL) {
- if (blink_in_progress)
+ if (scp->sc->flags & SC_VISUAL_BELL) {
+ if (scp->sc->blink_in_progress)
return;
- blink_in_progress = 4;
- if (scp != cur_console)
- blink_in_progress += 2;
- blink_screen(cur_console);
+ scp->sc->blink_in_progress = 3;
+ if (scp != scp->sc->cur_scp)
+ scp->sc->blink_in_progress += 2;
+ blink_screen(scp->sc->cur_scp);
} else {
- if (scp != cur_console)
+ if (scp != scp->sc->cur_scp)
pitch *= 2;
sysbeep(pitch, duration);
}
@@ -4433,122 +4073,19 @@ blink_screen(void *arg)
{
scr_stat *scp = arg;
- if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
- blink_in_progress = FALSE;
+ if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
+ scp->sc->blink_in_progress = 0;
mark_all(scp);
- if (delayed_next_scr)
- switch_scr(scp, delayed_next_scr - 1);
+ scstart(VIRTUAL_TTY(scp->sc, scp->index));
+ if (scp->sc->delayed_next_scr)
+ switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
}
else {
- if (blink_in_progress & 1)
- fillw_io(kernel_default.std_color | scr_map[0x20],
- scp->adp->va_window,
- scp->xsize * scp->ysize);
- else
- fillw_io(kernel_default.rev_color | scr_map[0x20],
- scp->adp->va_window,
- scp->xsize * scp->ysize);
- blink_in_progress--;
+ (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize,
+ scp->sc->blink_in_progress & 1);
+ scp->sc->blink_in_progress--;
timeout(blink_screen, scp, hz / 10);
}
}
-void
-sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
-{
- u_char *font;
- vm_offset_t d;
- vm_offset_t e;
- u_char *f;
- int font_size;
- int line_length;
- int xsize;
- u_short bg;
- int i, j;
- u_char c;
-
- if (ISTEXTSC(scp)) {
- bcopy_toio(p + from, scp->adp->va_window + 2*from,
- (to - from + 1)*sizeof(u_short));
- } else /* if ISPIXELSC(scp) */ {
- if (mark)
- mark = 255;
- font_size = scp->font_size;
- if (font_size < 14)
- font = font_8;
- else if (font_size >= 16)
- font = font_16;
- else
- font = font_14;
- line_length = scp->xpixel/8;
- xsize = scp->xsize;
- d = scp->adp->va_window
- + scp->xoff + scp->yoff*font_size*line_length
- + (from%xsize) + font_size*line_length*(from/xsize);
-
- outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
- outw(GDCIDX, 0x0003); /* data rotate/function select */
- outw(GDCIDX, 0x0f01); /* set/reset enable */
- bg = -1;
- for (i = from ; i <= to ; i++) {
- /* set background color in EGA/VGA latch */
- if (bg != (p[i] & 0xf000)) {
- bg = (p[i] & 0xf000);
- outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */
- outw(GDCIDX, 0xff08); /* bit mask */
- writeb(d, 0);
- c = readb(d); /* set the background color in the latch */
- }
- /* foreground color */
- outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */
- e = d;
- f = &font[(p[i] & 0x00ff)*font_size];
- for (j = 0 ; j < font_size; j++, f++) {
- outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */
- writeb(e, 0);
- e += line_length;
- }
- d++;
- if ((i % xsize) == xsize - 1)
- d += scp->xoff*2 + (font_size - 1)*line_length;
- }
- outw(GDCIDX, 0x0000); /* set/reset */
- outw(GDCIDX, 0x0001); /* set/reset enable */
- outw(GDCIDX, 0xff08); /* bit mask */
-
-#if 0 /* VGA only */
- outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
- outw(GDCIDX, 0x0003); /* data rotate/function select */
- outw(GDCIDX, 0x0f01); /* set/reset enable */
- outw(GDCIDX, 0xff08); /* bit mask */
- bg = -1;
- for (i = from ; i <= to ; i++) {
- /* set background color in EGA/VGA latch */
- if (bg != (p[i] & 0xf000)) {
- bg = (p[i] & 0xf000);
- outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
- outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */
- *d = 0;
- c = *d; /* set the background color in the latch */
- outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
- }
- /* foreground color */
- outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */
- e = (u_char *)d;
- f = &font[(p[i] & 0x00ff)*font_size];
- for (j = 0 ; j < font_size; j++, f++) {
- *e = *f^mark;
- e += line_length;
- }
- d++;
- if ((i % xsize) == xsize - 1)
- d += scp->xoff*2 + (font_size - 1)*line_length;
- }
- outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
- outw(GDCIDX, 0x0000); /* set/reset */
- outw(GDCIDX, 0x0001); /* set/reset enable */
-#endif /* 0 */
- }
-}
-
#endif /* NSC */
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index c8ba6cd..da48c7c 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -25,21 +25,51 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.h,v 1.46 1999/01/19 11:31:19 yokota Exp $
+ * $Id: syscons.h,v 1.47 1999/04/12 13:34:56 des Exp $
*/
#ifndef _DEV_SYSCONS_SYSCONS_H_
#define _DEV_SYSCONS_SYSCONS_H_
-/* vm things */
-#define ISMAPPED(pa, width) \
- (((pa) <= (u_long)0x1000 - (width)) \
- || ((pa) >= 0xa0000 && (pa) <= 0x100000 - (width)))
-#define pa_to_va(pa) (KERNBASE + (pa)) /* works if ISMAPPED(pa...) */
+/* machine-dependent part of the header */
+
+#ifdef PC98
+#include <pc98/pc98/sc_machdep.h>
+#elif defined(__i386__)
+/* nothing for the moment */
+#elif defined(__alpha__)
+/* nothing for the moment */
+#endif
+
+/* default values for configuration options */
+
+#ifndef MAXCONS
+#define MAXCONS 16
+#endif
+
+#ifdef SC_NO_SYSMOUSE
+#undef SC_NO_CUTPASTE
+#define SC_NO_CUTPASTE 1
+#endif
+
+#ifdef SC_NO_MODE_CHANGE
+#undef SC_PIXEL_MODE
+#endif
+
+#ifndef SC_DEBUG_LEVEL
+#define SC_DEBUG_LEVEL 0
+#endif
+
+#define DPRINTF(l, p) if (SC_DEBUG_LEVEL >= (l)) printf p
+
+#define SC_DRIVER_NAME "sc"
+#define SC_VTY(dev) minor(dev)
/* printable chars */
+#ifndef PRINTABLE
#define PRINTABLE(ch) ((ch) > 0x1b || ((ch) > 0x0d && (ch) < 0x1b) \
|| (ch) < 0x07)
+#endif
/* macros for "intelligent" screen update */
#define mark_for_update(scp, x) {\
@@ -51,33 +81,20 @@
scp->end = scp->xsize * scp->ysize - 1;\
}
-/* status flags */
+/* vty status flags (scp->status) */
#define UNKNOWN_MODE 0x00010
#define SWITCH_WAIT_REL 0x00080
#define SWITCH_WAIT_ACQ 0x00100
#define BUFFER_SAVED 0x00200
#define CURSOR_ENABLED 0x00400
-#define MOUSE_ENABLED 0x00800
#define MOUSE_MOVED 0x01000
#define MOUSE_CUTTING 0x02000
#define MOUSE_VISIBLE 0x04000
#define GRAPHICS_MODE 0x08000
#define PIXEL_MODE 0x10000
#define SAVER_RUNNING 0x20000
-
-/* configuration flags */
-#define VISUAL_BELL 0x00001
-#define BLINK_CURSOR 0x00002
-#define CHAR_CURSOR 0x00004
-/* these options are now obsolete; use corresponding options for kbd driver */
-#if 0
-#define DETECT_KBD 0x00008
-#define XT_KEYBD 0x00010
-#define KBD_NORESET 0x00020
-#endif
-#define QUIET_BELL 0x00040
-#define VESA800X600 0x00080
-#define AUTODETECT_KBD 0x00100
+#define VR_CURSOR_BLINK 0x40000
+#define VR_CURSOR_ON 0x80000
/* attribute flags */
#define NORMAL_ATTR 0x00
@@ -96,8 +113,6 @@
#define SAVE 0
#define COL 80
#define ROW 25
-#define BELL_DURATION 5
-#define BELL_PITCH 800
#define CONSOLE_BUFSIZE 1024
#define PCBURST 128
#define FONT_NONE 1
@@ -105,6 +120,11 @@
#define FONT_14 4
#define FONT_16 8
+#ifndef BELL_DURATION
+#define BELL_DURATION 5
+#define BELL_PITCH 800
+#endif
+
/* special characters */
#define cntlc 0x03
#define cntld 0x04
@@ -115,6 +135,23 @@
#define DEAD_CHAR 0x07 /* char used for cursor */
+/* virtual terminal buffer */
+typedef struct sc_vtb {
+ int vtb_flags;
+#define VTB_VALID (1 << 0)
+ int vtb_type;
+#define VTB_INVALID 0
+#define VTB_MEMORY 1
+#define VTB_FRAMEBUFFER 2
+#define VTB_RINGBUFFER 3
+ int vtb_cols;
+ int vtb_rows;
+ int vtb_size;
+ vm_offset_t vtb_buffer;
+ int vtb_tail; /* valid for VTB_RINGBUFFER only */
+} sc_vtb_t;
+
+/* terminal status */
typedef struct term_stat {
int esc; /* processing escape sequence */
int num_param; /* # of parameters to ESC */
@@ -127,10 +164,89 @@ typedef struct term_stat {
int rev_color; /* reverse hardware color */
} term_stat;
+/* softc */
+
+struct keyboard;
+struct video_adapter;
+struct scr_stat;
+struct tty;
+
+typedef struct sc_softc {
+ int unit; /* unit # */
+ int config; /* configuration flags */
+#define SC_VESA800X600 (1 << 7)
+#define SC_AUTODETECT_KBD (1 << 8)
+#define SC_KERNEL_CONSOLE (1 << 9)
+
+ int flags; /* status flags */
+#define SC_VISUAL_BELL (1 << 0)
+#define SC_QUIET_BELL (1 << 1)
+#define SC_BLINK_CURSOR (1 << 2)
+#define SC_CHAR_CURSOR (1 << 3)
+#define SC_MOUSE_ENABLED (1 << 4)
+#define SC_SCRN_IDLE (1 << 5)
+#define SC_SCRN_BLANKED (1 << 6)
+#define SC_SAVER_FAILED (1 << 7)
+
+#define SC_INIT_DONE (1 << 16)
+#define SC_SPLASH_SCRN (1 << 17)
+
+ int keyboard; /* -1 if unavailable */
+ struct keyboard *kbd;
+
+ int adapter;
+ struct video_adapter *adp;
+ int initial_mode; /* initial video mode */
+
+ int first_vty;
+ int vtys;
+ struct tty *tty;
+ struct scr_stat **console;
+ struct scr_stat *cur_scp;
+ struct scr_stat *new_scp;
+ struct scr_stat *old_scp;
+ int delayed_next_scr;
+
+ void **devfs_token;
+
+ char font_loading_in_progress;
+ char switch_in_progress;
+ char videoio_in_progress;
+ char write_in_progress;
+ char blink_in_progress;
+
+ long scrn_time_stamp;
+
+ char cursor_base;
+ char cursor_height;
+
+ u_char scr_map[256];
+ u_char scr_rmap[256];
+
+#ifdef _SC_MD_SOFTC_DECLARED_
+ sc_md_softc_t md; /* machine dependent vars */
+#endif
+
+#ifndef SC_NO_PALETTE_LOADING
+ u_char palette[256*3];
+#endif
+
+#ifndef SC_NO_FONT_LOADING
+ int fonts_loaded;
+ u_char *font_8;
+ u_char *font_14;
+ u_char *font_16;
+#endif
+
+} sc_softc_t;
+
+/* virtual screen */
typedef struct scr_stat {
- int ad; /* video adapter index */
- video_adapter_t *adp; /* video adapter structure */
- u_short *scr_buf; /* buffer when off screen */
+ int index; /* index of this vty */
+ struct sc_softc *sc; /* pointer to softc */
+ struct sc_rndr_sw *rndr; /* renderer */
+ sc_vtb_t scr;
+ sc_vtb_t vtb;
int xpos; /* current X position */
int ypos; /* current Y position */
int saved_xpos; /* saved X position */
@@ -141,25 +257,26 @@ typedef struct scr_stat {
int ypixel; /* Y graphics size */
int xoff; /* X offset in pixel mode */
int yoff; /* Y offset in pixel mode */
+ u_char *font; /* current font */
int font_size; /* fontsize in Y direction */
int start; /* modified area start */
int end; /* modified area end */
term_stat term; /* terminal emulation stuff */
int status; /* status (bitfield) */
int kbd_mode; /* keyboard I/O mode */
- u_short *cursor_pos; /* cursor buffer position */
- u_short *cursor_oldpos; /* cursor old buffer position */
- u_short cursor_saveunder; /* saved chars under cursor */
- char cursor_start; /* cursor start line # */
- char cursor_end; /* cursor end line # */
- u_short *mouse_pos; /* mouse buffer position */
- u_short *mouse_oldpos; /* mouse old buffer position */
+ int cursor_pos; /* cursor buffer position */
+ int cursor_oldpos; /* cursor old buffer position */
+ u_short cursor_saveunder_char; /* saved char under cursor */
+ u_short cursor_saveunder_attr; /* saved attr under cursor */
+ char cursor_base; /* cursor base line # */
+ char cursor_height; /* cursor height */
+ int mouse_pos; /* mouse buffer position */
+ int mouse_oldpos; /* mouse old buffer position */
short mouse_xpos; /* mouse x coordinate */
short mouse_ypos; /* mouse y coordinate */
short mouse_buttons; /* mouse buttons */
- u_char mouse_cursor[128]; /* mouse cursor bitmap store */
- u_short *mouse_cut_start; /* mouse cut start pos */
- u_short *mouse_cut_end; /* mouse cut end pos */
+ int mouse_cut_start; /* mouse cut start pos */
+ int mouse_cut_end; /* mouse cut end pos */
struct proc *mouse_proc; /* proc* of controlling proc */
pid_t mouse_pid; /* pid of controlling proc */
int mouse_signal; /* signal # to report with */
@@ -170,16 +287,14 @@ typedef struct scr_stat {
pid_t pid; /* pid of controlling proc */
struct proc *proc; /* proc* of controlling proc */
struct vt_mode smode; /* switch mode */
- u_short *history; /* circular history buffer */
- u_short *history_head; /* current head position */
- u_short *history_pos; /* position shown on screen */
- u_short *history_save; /* save area index */
+ sc_vtb_t *history; /* circular history buffer */
+ int history_pos; /* position shown on screen */
int history_size; /* size of history buffer */
-#ifdef __i386__
- struct apmhook r_hook; /* reconfiguration support */
-#endif
int splash_save_mode; /* saved mode for splash screen */
int splash_save_status; /* saved status for splash screen */
+#ifdef _SCR_MD_STAT_DECLARED_
+ scr_md_stat_t md; /* machine dependent vars */
+#endif
} scr_stat;
typedef struct default_attr {
@@ -187,7 +302,63 @@ typedef struct default_attr {
int rev_color; /* reverse hardware color */
} default_attr;
+#ifndef SC_NORM_ATTR
+#define SC_NORM_ATTR (FG_LIGHTGREY | BG_BLACK)
+#endif
+#ifndef SC_NORM_REV_ATTR
+#define SC_NORM_REV_ATTR (FG_BLACK | BG_LIGHTGREY)
+#endif
+#ifndef SC_KERNEL_CONS_ATTR
+#define SC_KERNEL_CONS_ATTR (FG_WHITE | BG_BLACK)
+#endif
+#ifndef SC_KERNEL_CONS_REV_ATTR
+#define SC_KERNEL_CONS_REV_ATTR (FG_BLACK | BG_LIGHTGREY)
+#endif
+
+/* renderer function table */
+typedef void vr_clear_t(scr_stat *scp, int c, int attr);
+typedef void vr_draw_border_t(scr_stat *scp, int color);
+typedef void vr_draw_t(scr_stat *scp, int from, int count, int flip);
+typedef void vr_set_cursor_t(scr_stat *scp, int base, int height, int blink);
+typedef void vr_draw_cursor_t(scr_stat *scp, int at, int blink,
+ int on, int flip);
+typedef void vr_blink_cursor_t(scr_stat *scp, int at, int flip);
+typedef void vr_set_mouse_t(scr_stat *scp);
+typedef void vr_draw_mouse_t(scr_stat *scp, int x, int y, int on);
+
+typedef struct sc_rndr_sw {
+ vr_clear_t *clear;
+ vr_draw_border_t *draw_border;
+ vr_draw_t *draw;
+ vr_set_cursor_t *set_cursor;
+ vr_draw_cursor_t *draw_cursor;
+ vr_blink_cursor_t *blink_cursor;
+ vr_set_mouse_t *set_mouse;
+ vr_draw_mouse_t *draw_mouse;
+} sc_rndr_sw_t;
+
+typedef struct sc_renderer {
+ char *name;
+ int mode;
+ sc_rndr_sw_t *rndrsw;
+} sc_renderer_t;
+
+#define RENDERER(name, mode, sw) \
+ static struct sc_renderer name##_##mode##_renderer = { \
+ #name, mode, &sw \
+ }; \
+ DATA_SET(scrndr_set, name##_##mode##_renderer)
+extern struct linker_set scrndr_set;
+
+typedef struct {
+ int cursor_start;
+ int cursor_end;
+ int shift_state;
+ int bell_pitch;
+} bios_values_t;
+
+/* other macros */
#define ISTEXTSC(scp) (!((scp)->status \
& (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE)))
#define ISGRAPHSC(scp) (((scp)->status \
@@ -197,41 +368,143 @@ typedef struct default_attr {
== PIXEL_MODE)
#define ISUNKNOWNSC(scp) ((scp)->status & UNKNOWN_MODE)
-#define ISFONTAVAIL(af) ((af) & V_ADP_FONT)
+#ifndef ISMOUSEAVAIL
+#ifdef SC_ALT_MOUSE_IMAGE
+#define ISMOUSEAVAIL(af) (1)
+#else
#define ISMOUSEAVAIL(af) ((af) & V_ADP_FONT)
+#endif /* SC_ALT_MOUSE_IMAGE */
+#define ISFONTAVAIL(af) ((af) & V_ADP_FONT)
#define ISPALAVAIL(af) ((af) & V_ADP_PALETTE)
+#endif /* ISMOUSEAVAIL */
-/* misc prototypes used by different syscons related LKM's */
+#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
+
+#define kbd_read_char(kbd, wait) \
+ (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))
+#define kbd_check_char(kbd) \
+ (*kbdsw[(kbd)->kb_index]->check_char)((kbd))
+#define kbd_enable(kbd) \
+ (*kbdsw[(kbd)->kb_index]->enable)((kbd))
+#define kbd_disable(kbd) \
+ (*kbdsw[(kbd)->kb_index]->disable)((kbd))
+#define kbd_lock(kbd, lockf) \
+ (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf))
+#define kbd_ioctl(kbd, cmd, arg) \
+ (((kbd) == NULL) ? \
+ ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg)))
+#define kbd_clear_state(kbd) \
+ (*kbdsw[(kbd)->kb_index]->clear_state)((kbd))
+#define kbd_get_fkeystr(kbd, fkey, len) \
+ (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len))
+#define kbd_poll(kbd, on) \
+ (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
/* syscons.c */
-int sc_probe_unit(int unit, int flags);
-int sc_attach_unit(int unit, int flags);
+extern int (*sc_user_ioctl)(dev_t dev, u_long cmd, caddr_t data,
+ int flag, struct proc *p);
+
+int sc_probe_unit(int unit, int flags);
+int sc_attach_unit(int unit, int flags);
+int sc_resume_unit(int unit);
-extern int (*sc_user_ioctl)(dev_t dev, u_long cmd, caddr_t data, int flag,
- struct proc *p);
+int set_mode(scr_stat *scp);
+scr_stat *sc_get_scr_stat(dev_t dev);
-int set_mode(scr_stat *scp);
-scr_stat *sc_get_scr_stat(dev_t dev);
+void copy_font(scr_stat *scp, int operation, int font_size,
+ u_char *font_image);
+void set_border(scr_stat *scp, int color);
-void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image);
-void set_border(scr_stat *scp, int color);
+void sc_touch_scrn_saver(void);
+void sc_clear_screen(scr_stat *scp);
+void sc_set_cursor_image(scr_stat *scp);
+int sc_clean_up(scr_stat *scp);
+void sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard);
+struct tty *scdevtotty(dev_t dev);
+#ifndef SC_NO_SYSMOUSE
+struct tty *sc_get_mouse_tty(void);
+#endif /* SC_NO_SYSMOUSE */
+#ifndef SC_NO_CUTPASTE
+void sc_paste(scr_stat *scp, u_char *p, int count);
+#endif /* SC_NO_CUTPASTE */
-void sc_touch_scrn_saver(void);
-void sc_clear_screen(scr_stat *scp);
-void sc_move_mouse(scr_stat *scp, int x, int y);
-int sc_clean_up(scr_stat *scp);
-void sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear);
-void sc_alloc_cut_buffer(scr_stat *scp, int wait);
-void sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait);
-struct tty *scdevtotty(dev_t dev);
+/* schistory.c */
+#ifndef SC_NO_HISTORY
+int sc_alloc_history_buffer(scr_stat *scp, int lines, int wait);
+void sc_hist_save(scr_stat *scp);
+#define sc_hist_save_one_line(scp, from) \
+ sc_vtb_append(&(scp)->vtb, (from), (scp)->history, (scp)->xsize)
+int sc_hist_restore(scr_stat *scp);
+void sc_hist_home(scr_stat *scp);
+void sc_hist_end(scr_stat *scp);
+int sc_hist_up_line(scr_stat *scp);
+int sc_hist_down_line(scr_stat *scp);
+int sc_hist_ioctl(struct tty *tp, u_long cmd, caddr_t data,
+ int flag, struct proc *p);
+#endif /* SC_NO_HISTORY */
+
+/* scmouse.c */
+#ifndef SC_NO_CUTPASTE
+void sc_alloc_cut_buffer(scr_stat *scp, int wait);
+void sc_draw_mouse_image(scr_stat *scp);
+void sc_remove_mouse_image(scr_stat *scp);
+int sc_inside_cutmark(scr_stat *scp, int pos);
+void sc_remove_cutmarking(scr_stat *scp);
+void sc_remove_all_cutmarkings(sc_softc_t *scp);
+void sc_remove_all_mouse(sc_softc_t *scp);
+#else
+#define sc_inside_cutmark(scp, pos) FALSE
+#define sc_remove_cutmarking(scp)
+#endif /* SC_NO_CUTPASTE */
+#ifndef SC_NO_SYSMOUSE
+void sc_mouse_set_level(int level);
+void sc_mouse_move(scr_stat *scp, int x, int y);
+int sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data,
+ int flag, struct proc *p);
+#endif /* SC_NO_SYSMOUSE */
/* scvidctl.c */
-int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode,
- int xsize, int ysize, int fontsize);
-int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode);
-int sc_set_pixel_mode(scr_stat *scp, struct tty *tp,
- int xsize, int ysize, int fontsize);
-int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
- struct proc *p);
+int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode,
+ int xsize, int ysize, int fontsize);
+int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode);
+int sc_set_pixel_mode(scr_stat *scp, struct tty *tp,
+ int xsize, int ysize, int fontsize);
+sc_rndr_sw_t *sc_render_match(scr_stat *scp, video_adapter_t *adp, int mode);
+int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
+ struct proc *p);
+
+/* scvtb.c */
+void sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows,
+ void *buffer, int wait);
+void sc_vtb_destroy(sc_vtb_t *vtb);
+size_t sc_vtb_size(int cols, int rows);
+void sc_vtb_clear(sc_vtb_t *vtb, int c, int attr);
+
+int sc_vtb_getc(sc_vtb_t *vtb, int at);
+int sc_vtb_geta(sc_vtb_t *vtb, int at);
+void sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a);
+vm_offset_t sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a);
+vm_offset_t sc_vtb_pointer(sc_vtb_t *vtb, int at);
+int sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset);
+
+#define sc_vtb_tail(vtb) ((vtb)->vtb_tail)
+#define sc_vtb_rows(vtb) ((vtb)->vtb_rows)
+
+void sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to,
+ int count);
+void sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2,
+ int count);
+void sc_vtb_seek(sc_vtb_t *vtb, int pos);
+void sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr);
+void sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr);
+void sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr);
+
+/* machine dependent functions */
+int sc_max_unit(void);
+sc_softc_t *sc_get_softc(int unit, int flags);
+sc_softc_t *sc_find_softc(struct video_adapter *adp, struct keyboard *kbd);
+int sc_get_cons_priority(int *unit, int *flags);
+void sc_get_bios_values(bios_values_t *values);
+int sc_tone(int herz);
#endif /* !_DEV_SYSCONS_SYSCONS_H_ */
diff --git a/sys/dev/syscons/warp/warp_saver.c b/sys/dev/syscons/warp/warp_saver.c
index 3476c36..cd6f42b 100644
--- a/sys/dev/syscons/warp/warp_saver.c
+++ b/sys/dev/syscons/warp/warp_saver.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: warp_saver.c,v 1.4 1999/01/11 03:18:55 yokota Exp $
+ * $Id: warp_saver.c,v 1.5 1999/04/12 13:34:58 des Exp $
*/
#include <sys/param.h>
@@ -33,11 +33,14 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/syslog.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
-#include <machine/md_var.h>
#include <machine/random.h>
-#include <saver.h>
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
static u_char *vid;
static int blanked;
OpenPOWER on IntegriCloud