Subject: kern/17445: second wsscroll patch
To: None <gnats-bugs@gnats.netbsd.org>
From: None <krp@freeshell.org>
List: netbsd-bugs
Date: 06/30/2002 22:18:30
>Number:         17445
>Category:       kern
>Synopsis:       allow scrolling on wscons terminals
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 30 13:23:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     David Ferlier
>Release:        NetBSD 1.6A
>Organization:
None

Run NetBSD    - www.NetBSD.org
David Ferlier - krp@freeshell.org
>Environment:
netbsd/i386
System: NetBSD hell 1.6A NetBSD 1.6A (LARGE_CHUNKS) #70: Sun Jun 21:56:52 PDT 2002 root@hell:/usr/src/sys/arch/i386/compile/LARGE_CHUNKS i386
Architecture: i386
Machine: i386
>Description:
	
Feel the lack of scrolling functions on wscons terminals
Attached patch works on 1.6A

>How-To-Repeat:
none
>Fix:

Index: sys/dev/wscons/wsdisplay.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/wscons/wsdisplay.c,v
retrieving revision 1.63
diff -u -r1.63 wsdisplay.c
--- wsdisplay.c	2002/04/07 09:25:47	1.63
+++ wsdisplay.c	2002/06/30 20:05:27
@@ -114,6 +114,9 @@
 	void	*sc_accesscookie;
 
 	const struct wsscreen_list *sc_scrdata;
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	struct wsdisplay_scroll_data sc_scroll_values;
+#endif
 
 	struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN];
 	int sc_focusidx;	/* available only if sc_focus isn't null */
@@ -152,6 +155,13 @@
 	wsdisplay_noemul_match,
 	wsdisplay_noemul_attach,
 };
+
+struct wsdisplay_scroll_data wsdisplay_default_scroll_values = {
+	WSDISPLAY_SCROLL_DOALL,
+	25,
+	2,
+};
+	
  
 /* Exported tty- and cdevsw-related functions. */
 cdev_decl(wsdisplay);
@@ -397,6 +407,32 @@
 	vdevgone(maj, mn, mn, VCHR);
 }
 
+#ifdef WSDISPLAY_SCROLLSUPPORT
+
+void
+wsdisplay_scroll(arg, op)
+	void *arg;
+	int op;
+{
+	struct wsdisplay_softc *sc = arg;
+	int lines;
+
+	if (op == WSDISPLAY_SCROLL_RESET)
+		lines = 0;
+	else {
+		lines = (op & WSDISPLAY_SCROLL_LOW) ? sc->sc_scroll_values.slowlines : sc->sc_scroll_values.fastlines;
+		if (op & WSDISPLAY_SCROLL_BACKWARD)
+			lines = -(lines);
+	}
+	
+	if (sc->sc_accessops->scroll) {
+		(*sc->sc_accessops->scroll)(sc->sc_accesscookie,
+		    sc->sc_focus->scr_dconf->emulcookie, lines);
+	}
+}
+
+#endif
+
 int
 wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags)
 {
@@ -615,6 +651,7 @@
 	sc->sc_accessops = accessops;
 	sc->sc_accesscookie = accesscookie;
 	sc->sc_scrdata = scrdata;
+	sc->sc_scroll_values = wsdisplay_default_scroll_values;
 
 	/*
 	 * Set up a number of virtual screens if wanted. The
@@ -916,6 +953,9 @@
 	int error;
 	char namebuf[16];
 	struct wsdisplay_font fd;
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	struct wsdisplay_scroll_data *ksdp, *usdp;
+#endif
 
 #if NWSKBD > 0
 	struct wsevsrc *inp;
@@ -964,6 +1004,32 @@
 
 	    return (0);
 #undef d
+
+#ifdef WSDISPLAY_SCROLLSUPPORT
+
+#define	SETSCROLLLINES(dstp, srcp, dfltp)								\
+    do {															\
+	(dstp)->fastlines = ((srcp)->which & WSDISPLAY_SCROLL_DOFASTLINES) ?	\
+	    (srcp)->fastlines : (dfltp)->fastlines;								\
+	(dstp)->slowlines = ((srcp)->which & WSDISPLAY_SCROLL_DOSLOWLINES) ?			\
+	    (srcp)->slowlines : (dfltp)->slowlines;								\
+	(dstp)->which = WSDISPLAY_SCROLL_DOALL;								\
+    } while (0)
+
+
+	case WSDISPLAYIO_DSSCROLL:
+		usdp = (struct wsdisplay_scroll_data *)data;
+		ksdp = &sc->sc_scroll_values;
+		SETSCROLLLINES(ksdp, usdp, ksdp);
+		return (0);
+
+	case WSDISPLAYIO_DGSCROLL:
+		usdp = (struct wsdisplay_scroll_data *)data;
+		ksdp = &sc->sc_scroll_values;
+		SETSCROLLLINES(usdp, ksdp, ksdp);
+		return (0);
+
+#endif
 
 	case WSDISPLAYIO_SFONT:
 #define d ((struct wsdisplay_usefontdata *)data)
Index: sys/dev/wscons/wsdisplayvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/wscons/wsdisplayvar.h,v
retrieving revision 1.20
diff -u -r1.20 wsdisplayvar.h
--- wsdisplayvar.h	2001/10/13 15:56:15	1.20
+++ wsdisplayvar.h	2002/06/30 20:05:29
@@ -106,6 +106,7 @@
 	int	(*show_screen)(void *, void *, int,
 				    void (*) (void *, int, int), void *);
 	int	(*load_font)(void *, void *, struct wsdisplay_font *);
+	void	(*scroll) __P((void *, void *, int));
 	void	(*pollc)(void *, int);
 };
 
@@ -188,6 +189,15 @@
 
 int wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
 			int flag, struct proc *p);
+
+#ifdef WSDISPLAY_SCROLLSUPPORT
+void wsdisplay_scroll __P((void *v, int op));
+#endif
+
+#define WSDISPLAY_SCROLL_BACKWARD	1
+#define WSDISPLAY_SCROLL_FORWARD	(1 << 1)
+#define WSDISPLAY_SCROLL_RESET		(1 << 2)
+#define WSDISPLAY_SCROLL_LOW		(1 << 3)
 
 /*
  * for general use
Index: sys/dev/wscons/wskbd.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/wscons/wskbd.c,v
retrieving revision 1.61
diff -u -r1.61 wskbd.c
--- wskbd.c	2002/03/17 19:41:06	1.61
+++ wskbd.c	2002/06/30 20:05:44
@@ -113,6 +113,7 @@
 #include <dev/wscons/wskbdvar.h>
 #include <dev/wscons/wsksymdef.h>
 #include <dev/wscons/wsksymvar.h>
+#include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wseventvar.h>
 #include <dev/wscons/wscons_callbacks.h>
 
@@ -162,6 +163,9 @@
 
 	struct wskbd_bell_data sc_bell_data;
 	struct wskbd_keyrepeat_data sc_keyrepeat_data;
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	struct wskbd_scroll_data sc_scroll_data;
+#endif
 
 	int	sc_repeating;		/* we've called timeout() */
 	struct callout sc_repeat_ch;
@@ -199,6 +203,16 @@
 #define MOD_ONESET(id, mask)	(((id)->t_modifiers & (mask)) != 0)
 #define MOD_ALLSET(id, mask)	(((id)->t_modifiers & (mask)) == (mask))
 
+#define GETMODSTATE(src, dst)		\
+	do {							\
+		dst |= (src & MOD_SHIFT_L) ? MOD_SHIFT_L : 0; \
+		dst |= (src & MOD_SHIFT_R) ? MOD_SHIFT_R : 0; \
+		dst |= (src & MOD_CONTROL_L) ? MOD_CONTROL_L : 0; \
+		dst |= (src & MOD_CONTROL_R) ? MOD_CONTROL_R : 0; \
+		dst |= (src & MOD_META_L) ? MOD_META_L : 0; \
+		dst |= (src & MOD_META_R) ? MOD_META_R : 0; \
+	} while (0)
+
 static int  wskbd_match(struct device *, struct cfdata *, void *);
 static void wskbd_attach(struct device *, struct device *, void *);
 static int  wskbd_detach(struct device *, int);
@@ -273,6 +287,16 @@
 	WSKBD_DEFAULT_KEYREPEAT_DELN,
 };
 
+struct wskbd_scroll_data wskbd_default_scroll_data = {
+	WSKBD_SCROLL_DOALL,
+	WSKBD_SCROLL_MODE_NORMAL,
+#ifdef WSDISPLAY_SCROLLCOMBO
+	WSDISPLAY_SCROLLCOMBO,
+#else
+	MOD_SHIFT_L,
+#endif
+};
+
 cdev_decl(wskbd);
 
 #if NWSDISPLAY > 0 || NWSMUX > 0
@@ -398,6 +422,7 @@
 	/* set default bell and key repeat data */
 	sc->sc_bell_data = wskbd_default_bell_data;
 	sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
+	sc->sc_scroll_data = wskbd_default_scroll_data;
 
 	if (ap->console) {
 		KASSERT(wskbd_console_initted); 
@@ -570,7 +595,7 @@
 		sc->sc_repeating = 0;
 		callout_stop(&sc->sc_repeat_ch);
 	}
-
+	
 	/*
 	 * If /dev/wskbdN is not connected in event mode translate and
 	 * send upstream.
@@ -579,6 +604,9 @@
 		num = wskbd_translate(sc->id, type, value);
 		if (num > 0) {
 			if (sc->sc_base.me_dispdv != NULL) {
+				if (sc->id->t_symbols [0] != KS_Print_Screen) {
+					wsdisplay_scroll (sc->sc_base.me_dispdv, WSDISPLAY_SCROLL_RESET);
+				}
 				for (i = 0; i < num; i++)
 					wsdisplay_kbdinput(
 						sc->sc_base.me_dispdv,
@@ -887,6 +915,9 @@
 wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag,
 	struct proc *p)
 {
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	struct wskbd_scroll_data *usdp, *ksdp;
+#endif
 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
 	struct wskbd_bell_data *ubdp, *kbdp;
 	struct wskbd_keyrepeat_data *ukdp, *kkdp;
@@ -987,6 +1018,30 @@
 		kkdp = &wskbd_default_keyrepeat_data;
 		goto getkeyrepeat;
 
+#ifdef WSDISPLAY_SCROLLSUPPORT
+
+#define	SETSCROLLMOD(dstp, srcp, dfltp)					\
+    do {								\
+	(dstp)->mode = ((srcp)->which & WSKBD_SCROLL_DOMODE) ?	\
+	    (srcp)->mode : (dfltp)->mode;				\
+	(dstp)->modifier = ((srcp)->which & WSKBD_SCROLL_DOMODIFIER) ?	\
+	    (srcp)->modifier : (dfltp)->modifier;				\
+	(dstp)->which = WSKBD_SCROLL_DOALL;				\
+    } while (0)
+
+	case WSKBDIO_SETSCROLL:
+		usdp = (struct wskbd_scroll_data *)data;
+		ksdp = &sc->sc_scroll_data;
+		SETSCROLLMOD(ksdp, usdp, ksdp);
+		return (0);
+
+	case WSKBDIO_GETSCROLL:
+		usdp = (struct wskbd_scroll_data *)data;
+		ksdp = &sc->sc_scroll_data;
+		SETSCROLLMOD(usdp, ksdp, ksdp);
+		return (0);
+#endif
+
 #undef SETKEYREPEAT
 
 	case WSKBDIO_SETMAP:
@@ -1306,7 +1361,48 @@
 internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym,
 	keysym_t ksym2)
 {
+	u_int state=0;
 	switch (ksym) {
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	case KS_Cmd_ScrollFastUp:
+	case KS_Cmd_ScrollFastDown:
+		if (*type == WSCONS_EVENT_KEY_DOWN) {
+			GETMODSTATE(sc->id->t_modifiers, state);
+			if ((sc->sc_scroll_data.mode == WSKBD_SCROLL_MODE_HOLD
+			   	&& MOD_ONESET(sc->id, MOD_HOLDSCREEN))
+			|| (sc->sc_scroll_data.mode == WSKBD_SCROLL_MODE_NORMAL
+				&& sc->sc_scroll_data.modifier == state)) {
+					update_modifier(sc->id, *type, 0, MOD_COMMAND);
+					wsdisplay_scroll(sc->sc_base.me_dispdv,
+						(ksym == KS_Cmd_ScrollFastUp) ?
+						WSDISPLAY_SCROLL_BACKWARD :
+						WSDISPLAY_SCROLL_FORWARD);
+					return (1);
+			} else {
+				return (0);
+			}
+		}
+
+	case KS_Cmd_ScrollSlowUp:
+	case KS_Cmd_ScrollSlowDown:
+		if (*type == WSCONS_EVENT_KEY_DOWN) {
+			GETMODSTATE(sc->id->t_modifiers, state);
+			if ((sc->sc_scroll_data.mode == WSKBD_SCROLL_MODE_HOLD
+			   	&& MOD_ONESET(sc->id, MOD_HOLDSCREEN))
+			|| (sc->sc_scroll_data.mode == WSKBD_SCROLL_MODE_NORMAL
+				&& sc->sc_scroll_data.modifier == state)) {
+					update_modifier(sc->id, *type, 0, MOD_COMMAND);
+					wsdisplay_scroll(sc->sc_base.me_dispdv,
+					   	(ksym == KS_Cmd_ScrollSlowUp) ?
+						WSDISPLAY_SCROLL_BACKWARD | WSDISPLAY_SCROLL_LOW:
+						WSDISPLAY_SCROLL_FORWARD | WSDISPLAY_SCROLL_LOW);
+					return (1);
+			} else {
+				return (0);
+			}
+		}
+#endif
+
 	case KS_Cmd:
 		update_modifier(sc->id, *type, 0, MOD_COMMAND);
 		ksym = ksym2;
@@ -1327,6 +1423,7 @@
 		return (0);
 
 	switch (ksym) {
+	
 #if defined(DDB) || defined(KGDB)
 	case KS_Cmd_Debugger:
 		if (sc->sc_isconsole) {
Index: sys/dev/wscons/wsconsio.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.50
diff -u -r1.50 wsconsio.h
--- wsconsio.h	2002/04/07 09:25:47	1.50
+++ wsconsio.h	2002/06/30 20:05:50
@@ -99,6 +99,21 @@
 	u_int	period;				/* period, in milliseconds */
 	u_int	volume;				/* percentage of max volume */
 };
+/* Manipulate the scrolling modifiers and mode */
+struct wskbd_scroll_data {
+	u_int		which;
+	u_int		mode;
+	u_int		modifier;
+};
+
+/* Manipulate the scrolling values (how many lines to scroll) */
+
+struct wsdisplay_scroll_data {
+	u_int		which;
+	u_int		fastlines;
+	u_int		slowlines;
+};
+
 #define		WSKBD_BELL_DOPITCH	0x1		/* get/set pitch */
 #define		WSKBD_BELL_DOPERIOD	0x2		/* get/set period */
 #define		WSKBD_BELL_DOVOLUME	0x4		/* get/set volume */
@@ -157,6 +172,15 @@
 #define	WSKBDIO_SETKEYCLICK	_IOW('W', 21, int)
 #define	WSKBDIO_GETKEYCLICK	_IOR('W', 22, int)
 
+#define WSKBDIO_GETSCROLL		_IOR('W', 23, struct wskbd_scroll_data)
+#define WSKBDIO_SETSCROLL		_IOW('W', 24, struct wskbd_scroll_data)
+
+#define		WSKBD_SCROLL_MODE_NORMAL	0x00
+#define		WSKBD_SCROLL_MODE_HOLD		0x01
+#define		WSKBD_SCROLL_DOMODIFIER		0x01
+#define		WSKBD_SCROLL_DOMODE			0x02
+#define		WSKBD_SCROLL_DOALL			0x03
+
 /*
  * Mouse ioctls (32 - 63)
  */
@@ -294,6 +318,11 @@
 #define		WSDISPLAY_CURSOR_DOSHAPE	0x10	/* get/set img/mask */
 #define		WSDISPLAY_CURSOR_DOALL		0x1f	/* all of the above */
 
+#define		WSDISPLAY_SCROLL_DOFASTLINES	0x01
+#define		WSDISPLAY_SCROLL_DOSLOWLINES	0x02
+#define		WSDISPLAY_SCROLL_DOALL			0x03
+
+
 /* Cursor control: get and set position */
 #define	WSDISPLAYIO_GCURPOS	_IOR('W', 70, struct wsdisplay_curpos)
 #define	WSDISPLAYIO_SCURPOS	_IOW('W', 71, struct wsdisplay_curpos)
@@ -374,6 +403,9 @@
 };
 #define	WSDISPLAYIO_GETPARAM	_IOWR('W', 82, struct wsdisplay_param)
 #define	WSDISPLAYIO_SETPARAM	_IOWR('W', 83, struct wsdisplay_param)
+
+#define WSDISPLAYIO_DGSCROLL		_IOR('W', 84, struct wsdisplay_scroll_data)
+#define WSDISPLAYIO_DSSCROLL		_IOW('W', 85, struct wsdisplay_scroll_data)
 
 /* XXX NOT YET DEFINED */
 /* Mapping information retrieval. */
Index: sys/dev/wscons/wsksymdef.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/wscons/wsksymdef.h,v
retrieving revision 1.45
diff -u -r1.45 wsksymdef.h
--- wsksymdef.h	2002/04/23 13:42:46	1.45
+++ wsksymdef.h	2002/06/30 20:05:55
@@ -434,7 +434,10 @@
 #define KS_Cmd_ContrastUp	0xf429
 #define KS_Cmd_ContrastDown	0xf42a
 #define KS_Cmd_ContrastRotate	0xf42b
-
+#define KS_Cmd_ScrollFastUp		0xf42c
+#define KS_Cmd_ScrollFastDown	0xf42d
+#define KS_Cmd_ScrollSlowUp		0xf42e
+#define KS_Cmd_ScrollSlowDown	0xf42f
 
 /*
  * Group 5 (internal)
Index: sbin/wsconsctl/display.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/wsconsctl/display.c,v
retrieving revision 1.2
diff -u -r1.2 display.c
--- display.c	2002/04/07 10:40:04	1.2
+++ display.c	2002/06/30 20:05:57
@@ -37,6 +37,7 @@
  */
 
 #include <sys/ioctl.h>
+#include <stdio.h>
 #include <sys/time.h>
 #include <dev/wscons/wsconsio.h>
 #include <err.h>
@@ -44,10 +45,13 @@
 
 static int dpytype;
 static struct wsdisplay_usefontdata font;
+static struct wsdisplay_scroll_data scroll_l;
 
 struct field display_field_tab[] = {
-    { "type",			&dpytype,	FMT_DPYTYPE,	FLG_RDONLY },
-    { "font",			&font.name,	FMT_STRING,	FLG_WRONLY },
+    { "type",				&dpytype,	FMT_DPYTYPE,	FLG_RDONLY },
+    { "font",				&font.name,	FMT_STRING,	FLG_WRONLY },
+    { "scroll.fastlines",	&scroll_l.fastlines, FMT_UINT, FLG_MODIFY },
+    { "scroll.slowlines",	&scroll_l.slowlines, FMT_UINT, FLG_MODIFY },
 };
 
 int display_field_tab_len = sizeof(display_field_tab)/
@@ -60,6 +64,15 @@
 	if (field_by_value(&dpytype)->flags & FLG_GET)
 		if (ioctl(fd, WSDISPLAYIO_GTYPE, &dpytype) < 0)
 			err(1, "WSDISPLAYIO_GTYPE");
+	
+	scroll_l.which = 0;
+	if (field_by_value(&scroll_l.fastlines)->flags & FLG_GET)
+		scroll_l.which |= WSDISPLAY_SCROLL_DOFASTLINES;
+	if (field_by_value(&scroll_l.slowlines)->flags & FLG_GET)
+		scroll_l.which |= WSDISPLAY_SCROLL_DOSLOWLINES;
+	if (scroll_l.which != 0 && 
+		ioctl(fd, WSDISPLAYIO_DGSCROLL, &scroll_l) < 0)
+			err(1, "WSDISPLAYIO_GSCROLL");
 }
 
 void
@@ -71,4 +84,19 @@
 			err(1, "WSDISPLAYIO_SFONT");
 		pr_field(field_by_value(&font.name), " -> ");
 	}
+	
+	scroll_l.which = 0;
+	if (field_by_value(&scroll_l.fastlines)->flags & FLG_SET)
+		scroll_l.which |= WSDISPLAY_SCROLL_DOFASTLINES;
+	if (field_by_value(&scroll_l.slowlines)->flags & FLG_SET)
+		scroll_l.which |= WSDISPLAY_SCROLL_DOSLOWLINES;
+
+	if (scroll_l.which & WSDISPLAY_SCROLL_DOFASTLINES)
+		pr_field(field_by_value(&scroll_l.fastlines), " -> ");
+	if (scroll_l.which & WSDISPLAY_SCROLL_DOSLOWLINES)
+		pr_field(field_by_value(&scroll_l.slowlines), " -> ");
+	if (scroll_l.which != 0 &&
+		ioctl(fd, WSDISPLAYIO_DSSCROLL, &scroll_l) < 0)
+		err (1, "WSDISPLAYIO_SSCROLL");
+
 }
Index: sbin/wsconsctl/keyboard.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/wsconsctl/keyboard.c,v
retrieving revision 1.3
diff -u -r1.3 keyboard.c
--- keyboard.c	2001/09/19 12:45:24	1.3
+++ keyboard.c	2002/06/30 20:06:00
@@ -52,6 +52,7 @@
 							   and in util.c */
 static struct wskbd_keyrepeat_data repeat;
 static struct wskbd_keyrepeat_data dfrepeat;
+static struct wskbd_scroll_data scroll;
 static int ledstate;
 static kbd_t kbdencoding;
 
@@ -71,6 +72,8 @@
     { "ledstate",		&ledstate,	FMT_UINT,	0 },
     { "encoding",		&kbdencoding,	FMT_KBDENC,	FLG_MODIFY },
     { "keyclick",		&keyclick,	FMT_UINT,	FLG_MODIFY },
+	{ "scroll.mode",	&scroll.mode,	FMT_UINT,	FLG_MODIFY },
+	{ "scroll.modifier",	&scroll.modifier,	FMT_UINT,	FLG_MODIFY },
 };
 
 int keyboard_field_tab_len = sizeof(keyboard_field_tab)/
@@ -141,6 +144,15 @@
 		ioctl(fd, WSKBDIO_GETKEYCLICK, &keyclick);
 		/* Optional; don't complain. */
 	}
+	
+	scroll.which = 0;
+	if (field_by_value(&scroll.mode)->flags & FLG_GET)
+		scroll.which |= WSKBD_SCROLL_DOMODE;
+	if (field_by_value(&scroll.modifier)->flags & FLG_GET)
+		scroll.which |= WSKBD_SCROLL_DOMODIFIER;
+	if (scroll.which != 0 && 
+		ioctl(fd, WSKBDIO_GETSCROLL, &scroll) < 0)
+			err(1, "WSKBDIO_GETSCROLL");
 }
 
 void
@@ -229,4 +241,20 @@
 			err(1, "WSKBDIO_SETKEYCLICK");
 		pr_field(field_by_value(&keyclick), " -> ");
 	}
+
+
+	scroll.which = 0;
+	if (field_by_value(&scroll.mode)->flags & FLG_SET)
+		scroll.which |= WSKBD_SCROLL_DOMODE;
+	if (field_by_value(&scroll.modifier)->flags & FLG_SET)
+		scroll.which |= WSKBD_SCROLL_DOMODIFIER;
+
+	if (scroll.which & WSKBD_SCROLL_DOMODE)
+		pr_field(field_by_value(&scroll.mode), " -> ");
+	if (scroll.which & WSKBD_SCROLL_DOMODIFIER)
+		pr_field(field_by_value(&scroll.modifier), " -> ");
+	if (scroll.which != 0 &&
+		ioctl(fd, WSKBDIO_SETSCROLL, &scroll) < 0)
+		err (1, "WSKBDIO_SETSCROLL");
 }
+
Index: sys/dev/ic/vga.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/vga.c,v
retrieving revision 1.50
diff -u -r1.50 vga.c
--- vga.c	2002/04/04 13:08:35	1.50
+++ vga.c	2002/06/30 20:06:15
@@ -92,6 +92,8 @@
 	/* palette */
 
 	int mindispoffset, maxdispoffset;
+	int vga_rollover;
+	int visibleoffset;
 };
 
 static int vgaconsole, vga_console_type, vga_console_attached;
@@ -111,6 +113,7 @@
 static int vga_mapchar(void *, int, unsigned int *);
 static int vga_alloc_attr(void *, int, int, int, long *);
 static void vga_copyrows(void *, int, int, int);
+void vga_scroll __P((void *, void *, int));
 
 const struct wsdisplay_emulops vga_emulops = {
 	pcdisplay_cursor,
@@ -256,7 +259,12 @@
 	vga_alloc_screen,
 	vga_free_screen,
 	vga_show_screen,
-	vga_load_font
+	vga_load_font,
+#ifdef WSDISPLAY_SCROLLSUPPORT
+	vga_scroll
+#else
+	NULL
+#endif
 };
 
 /*
@@ -501,6 +509,9 @@
 		scr->pcs.dispoffset = scr->mindispoffset;
 	}
 
+	scr->pcs.visibleoffset = scr->pcs.dispoffset;
+	scr->vga_rollover = 0;
+
 	scr->pcs.vc_crow = cpos / type->ncols;
 	scr->pcs.vc_ccol = cpos % type->ncols;
 	pcdisplay_cursor_init(&scr->pcs, existing);
@@ -1290,3 +1301,48 @@
 	*index = idx1;
 	return (res1);
 }
+
+void
+vga_scroll(v, cookie, lines)
+	void *v;
+	void *cookie;
+	int lines;
+{
+	struct vga_config *vc = v;
+	struct vgascreen *scr = cookie;
+	struct vga_handle *vh = &vc->hdl;
+
+	if (lines == 0) {
+		if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
+			return;
+
+		scr->pcs.visibleoffset = scr->pcs.dispoffset;
+	}
+	else {
+		int vga_scr_end;
+		int margin = scr->pcs.type->ncols * 2;
+		int ul, we, p, st;
+
+		vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
+		    scr->pcs.type->nrows * 2);
+		if (scr->vga_rollover > vga_scr_end + margin) {
+			ul = vga_scr_end;
+			we = scr->vga_rollover + scr->pcs.type->ncols * 2;
+		} else {
+			ul = 0;
+			we = 0x8000;
+		}
+		p = (scr->pcs.visibleoffset - ul + we) % we + lines *
+		    (scr->pcs.type->ncols * 2);
+		st = (scr->pcs.dispoffset - ul + we) % we;
+		if (p < margin)
+			p = 0;
+		if (p > st - margin)
+			p = st;
+		scr->pcs.visibleoffset = (p + ul) % we;
+	}
+	
+	vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
+	vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
+}
+
Index: sys/dev/ic/pcdisplay_subr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/pcdisplay_subr.c,v
retrieving revision 1.20
diff -u -r1.20 pcdisplay_subr.c
--- pcdisplay_subr.c	2001/11/13 13:14:43	1.20
+++ pcdisplay_subr.c	2002/06/30 20:06:18
@@ -173,6 +173,8 @@
 				  c | (attr << 8));
 	else
 		scr->mem[off] = c | (attr << 8);
+
+	scr->visibleoffset = scr->dispoffset;
 }
 
 void
Index: sys/dev/ic/pcdisplayvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/pcdisplayvar.h,v
retrieving revision 1.8
diff -u -r1.8 pcdisplayvar.h
--- pcdisplayvar.h	2000/01/25 02:44:03	1.8
+++ pcdisplayvar.h	2002/06/30 20:06:19
@@ -49,6 +49,7 @@
 	int vc_ccol, vc_crow;	/* current cursor position */
 
 	int dispoffset; /* offset of displayed area in video mem */
+	int visibleoffset;
 };
 
 struct pcdisplay_handle {

>Release-Note:
>Audit-Trail:
>Unformatted: