Subject: Patch to add console scrollback support.
To: None <tech-kern@netbsd.org>
From: justin <lifter@crosswinds.net>
List: tech-kern
Date: 05/31/2001 23:36:04
Hi guys,
I've ported over the work that OpenBSD did with WSCONS to support console
scrollback. The key sequence on i386 is left ctrl+alt+shift+pg_up or pg_down.
The patch is for NetBSD 1.5.1_BETA_2, but I'm going to assume that it should be
pretty easy to apply it to -current. Since I'm not subscribed to the list,
please CC any comments to lifter@crosswinds.net.
If anybody gets this working, or doesn't get it working, please drop me a line
ASAP.
Thanks a lot!
Regards,
Justin Reigle
--- sys/dev/ic/pcdisplay_subr.c.orig Thu May 31 22:59:33 2001
+++ sys/dev/ic/pcdisplay_subr.c Thu May 31 21:49:17 2001
@@ -160,6 +160,25 @@
scr->mem[off] = c | (attr << 8);
}
+u_int16_t
+pcdisplay_getchar(id, row, col)
+ void *id;
+ int row, col;
+{
+ struct pcdisplayscreen *scr = id;
+ bus_space_tag_t memt = scr->hdl->ph_memt;
+ bus_space_handle_t memh = scr->hdl->ph_memh;
+ int off;
+
+ off = row * scr->type->ncols + col;
+
+ if (scr->active)
+ return (bus_space_read_2(memt, memh,
+ scr->dispoffset + off * 2));
+ else
+ return (scr->mem[off]);
+}
+
void
pcdisplay_copycols(id, row, srccol, dstcol, ncols)
void *id;
--- sys/dev/ic/pcdisplayvar.h.orig Thu May 31 22:59:57 2001
+++ sys/dev/ic/pcdisplayvar.h Thu May 31 21:24:37 2001
@@ -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 {
@@ -90,6 +91,7 @@
#endif
int pcdisplay_mapchar __P((void *, int, unsigned int *));
void pcdisplay_putchar __P((void *, int, int, u_int, long));
+u_int16_t pcdisplay_getchar __P((void *, int, int));
void pcdisplay_copycols __P((void *, int, int, int,int));
void pcdisplay_erasecols __P((void *, int, int, int, long));
void pcdisplay_copyrows __P((void *, int, int, int));
--- sys/dev/usb/ukbdmap.c.orig Thu May 31 23:19:23 2001
+++ sys/dev/usb/ukbdmap.c Thu May 31 23:20:29 2001
@@ -118,10 +118,10 @@
KC(72), KS_Pause,
KC(73), KS_Insert,
KC(74), KS_Home,
- KC(75), KS_Prior,
+ KC(75), KS_Cmd_ScrollBack, KS_Prior,
KC(76), KS_Delete,
KC(77), KS_End,
- KC(78), KS_Next,
+ KC(78), KS_Cmd_ScrollFwd, KS_Next,
KC(79), KS_Right,
KC(80), KS_Left,
KC(81), KS_Down,
--- sys/dev/ic/vga.c.orig Thu May 31 23:05:22 2001
+++ sys/dev/ic/vga.c Thu May 31 21:57:16 2001
@@ -80,6 +80,7 @@
/* palette */
int mindispoffset, maxdispoffset;
+ int vga_rollover;
};
struct vga_config {
@@ -122,13 +123,16 @@
static void vga_setfont __P((struct vga_config *, struct vgascreen *));
static int vga_mapchar __P((void *, int, unsigned int *));
+void vga_putchar __P((void *, int, int, u_int, long));
static int vga_alloc_attr __P((void *, int, int, int, long *));
void vga_copyrows __P((void *, int, int, int));
+void vga_scrollback __P((void *, void *, int));
+u_int16_t vga_getchar __P((void *, int, int));
const struct wsdisplay_emulops vga_emulops = {
pcdisplay_cursor,
vga_mapchar,
- pcdisplay_putchar,
+ vga_putchar,
pcdisplay_copycols,
pcdisplay_erasecols,
vga_copyrows,
@@ -269,7 +273,9 @@
vga_alloc_screen,
vga_free_screen,
vga_show_screen,
- vga_load_font
+ vga_load_font,
+ vga_scrollback,
+ vga_getchar
};
/*
@@ -905,6 +911,52 @@
return (0);
}
+
+void
+vga_scrollback(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; /* reset */
+ }
+ 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;
+ }
+
+ /* update visible position */
+ vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
+ vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
+}
+
static int
vga_alloc_attr(id, fg, bg, flags, attrp)
void *id;
@@ -1193,3 +1245,29 @@
*index = idx1;
return (res1);
}
+
+void
+vga_putchar(c, row, col, uc, attr)
+ void *c;
+ int row;
+ int col;
+ u_int uc;
+ long attr;
+{
+ struct vgascreen *scr = c;
+
+ if (scr->pcs.visibleoffset != scr->pcs.dispoffset)
+ vga_scrollback(scr->cfg, scr, 0);
+
+ pcdisplay_putchar(c, row, col, uc, attr);
+}
+
+u_int16_t
+vga_getchar(c, row, col)
+ void *c;
+ int row, col;
+{
+ struct vga_config *vc = c;
+
+ return (pcdisplay_getchar(vc->active, row, col));
+}
--- sys/dev/wscons/wsdisplay.c.orig Thu May 31 23:11:46 2001
+++ sys/dev/wscons/wsdisplay.c Thu May 31 20:46:32 2001
@@ -1799,6 +1799,29 @@
}
}
+
+void
+wsscrollback(arg, op)
+ void *arg;
+ int op;
+{
+ struct wsdisplay_softc *sc = arg;
+ int lines;
+
+ if (op == WSDISPLAY_SCROLL_RESET)
+ lines = 0;
+ else {
+ lines = sc->sc_focus->scr_dconf->scrdata->nrows - 1;
+ if (op == WSDISPLAY_SCROLL_BACKWARD)
+ lines = -lines;
+ }
+
+ if (sc->sc_accessops->scrollback) {
+ (*sc->sc_accessops->scrollback)(sc->sc_accesscookie,
+ sc->sc_focus->scr_dconf->emulcookie, lines);
+ }
+}
+
/*
* Switch the console at shutdown.
*/
--- sys/dev/wscons/wsdisplayvar.h.orig Thu May 31 23:11:56 2001
+++ sys/dev/wscons/wsdisplayvar.h Thu May 31 20:49:40 2001
@@ -110,6 +110,9 @@
int (*show_screen) __P((void *, void *, int,
void (*) (void *, int, int), void *));
int (*load_font) __P((void *, void *, struct wsdisplay_font *));
+ void (*scrollback) __P((void *, void *, int));
+ u_int16_t (*getchar) __P((void *, int, int));
+ void (*pollc) __P((void *, int));
};
/*
@@ -198,3 +201,9 @@
* for general use
*/
void wsdisplay_switchtoconsole __P((void));
+
+void wsscrollback __P((void *, int));
+
+#define WSDISPLAY_SCROLL_BACKWARD 0
+#define WSDISPLAY_SCROLL_FORWARD 1
+#define WSDISPLAY_SCROLL_RESET 2
--- sys/dev/wscons/wskbd.c.orig Thu May 31 23:12:18 2001
+++ sys/dev/wscons/wskbd.c Thu May 31 22:29:18 2001
@@ -109,6 +109,7 @@
#include <dev/wscons/wsksymvar.h>
#include <dev/wscons/wseventvar.h>
#include <dev/wscons/wscons_callbacks.h>
+#include <dev/wscons/wsdisplayvar.h>
#include "opt_wsdisplay_compat.h"
@@ -580,6 +581,11 @@
num = wskbd_translate(sc->id, type, value);
if (num > 0) {
if (sc->sc_displaydv != NULL) {
+ /* XXX - Shift_R+PGUP(release) emits PrtSc */
+ if (sc->id->t_symbols[0] != KS_Print_Screen) {
+ wsscrollback(sc->sc_displaydv,
+ WSDISPLAY_SCROLL_RESET);
+ }
for (i = 0; i < num; i++)
wsdisplay_kbdinput(sc->sc_displaydv,
sc->id->t_symbols[i]);
@@ -1299,6 +1305,25 @@
(! MOD_ONESET(sc->id, MOD_COMMAND) &&
! MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)))
return (0);
+
+
+#if NWSDISPLAY > 0
+ switch (ksym) {
+ case KS_Cmd_ScrollBack:
+ if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
+ wsscrollback(sc->sc_displaydv,
+ WSDISPLAY_SCROLL_BACKWARD);
+ return (1);
+ }
+
+ case KS_Cmd_ScrollFwd:
+ if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
+ wsscrollback(sc->sc_displaydv,
+ WSDISPLAY_SCROLL_FORWARD);
+ return (1);
+ }
+ }
+#endif
switch (ksym) {
#ifdef DDB
--- sys/dev/pckbc/wskbdmap_mfii.c.orig Thu May 31 23:10:18 2001
+++ sys/dev/pckbc/wskbdmap_mfii.c Thu May 31 22:36:02 2001
@@ -142,12 +142,12 @@
#endif
KC(199), KS_Home,
KC(200), KS_Up,
- KC(201), KS_Prior,
+ KC(201), KS_Cmd_ScrollBack, KS_Prior,
KC(203), KS_Left,
KC(205), KS_Right,
KC(207), KS_End,
KC(208), KS_Down,
- KC(209), KS_Next,
+ KC(209), KS_Cmd_ScrollFwd, KS_Next,
KC(210), KS_Insert,
KC(211), KS_Delete,
KC(219), KS_Meta_L,