On Tue, 17 Apr 2018 at 07:52:28 +0200, Mark Kettenis wrote:
> > Date: Mon, 16 Apr 2018 10:45:52 -0500
> > From: joshua stein <[email protected]>
> 
> Does this do the right thing for early consoles?  The initial
> efifb_bs[] doesn't have space for the scrollback.  At the point where
> the scrollback code gets code, we've replaced that with a malloc'ed
> buffer?

Here is a new version that puts the scrollback count into each 
rasops_screen in case it changes later, which allows it to cope with 
the count being 0 if no scrollback has been allocated.

Though the scrollback callback won't be called until wsdisplay 
formally attaches later after each rasops_screen is allocated 
anyway.


Index: arch/amd64/amd64/efifb.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/efifb.c,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 efifb.c
--- arch/amd64/amd64/efifb.c    25 Apr 2018 00:46:28 -0000      1.15
+++ arch/amd64/amd64/efifb.c    27 Apr 2018 14:27:22 -0000
@@ -101,6 +101,7 @@ int  efifb_show_screen(void *, void *, i
            void *);
 int     efifb_list_font(void *, struct wsdisplay_font *);
 int     efifb_load_font(void *, void *, struct wsdisplay_font *);
+void    efifb_scrollback(void *, void *, int lines);
 void    efifb_efiinfo_init(struct efifb *);
 void    efifb_cnattach_common(void);
 
@@ -133,7 +134,8 @@ struct wsdisplay_accessops efifb_accesso
        .free_screen = efifb_free_screen,
        .show_screen = efifb_show_screen,
        .load_font = efifb_load_font,
-       .list_font = efifb_list_font
+       .list_font = efifb_list_font,
+       .scrollback = efifb_scrollback,
 };
 
 struct cfdriver efifb_cd = {
@@ -397,6 +399,15 @@ efifb_list_font(void *v, struct wsdispla
        struct rasops_info      *ri = &sc->sc_fb->rinfo;
 
        return (rasops_list_font(ri, font));
+}
+
+void
+efifb_scrollback(void *v, void *cookie, int lines)
+{
+       struct efifb_softc      *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       rasops_scrollback(ri, cookie, lines);
 }
 
 int
Index: dev/rasops/rasops.c
===================================================================
RCS file: /cvs/src/sys/dev/rasops/rasops.c,v
retrieving revision 1.52
diff -u -p -u -p -r1.52 rasops.c
--- dev/rasops/rasops.c 20 Apr 2018 16:09:37 -0000      1.52
+++ dev/rasops/rasops.c 27 Apr 2018 14:27:23 -0000
@@ -1373,6 +1373,11 @@ struct rasops_screen {
        int rs_visible;
        int rs_crow;
        int rs_ccol;
+
+       int rs_sbscreens;
+#define RS_SCROLLBACK_SCREENS 5
+       int rs_dispoffset;      /* rs_bs index, start of our actual screen */
+       int rs_visibleoffset;   /* rs_bs index, current scrollback screen */
 };
 
 int
@@ -1387,13 +1392,16 @@ rasops_alloc_screen(void *v, void **cook
        if (scr == NULL)
                return (ENOMEM);
 
-       scr->rs_bs = mallocarray(ri->ri_rows,
+       scr->rs_sbscreens = RS_SCROLLBACK_SCREENS;
+       scr->rs_bs = mallocarray(ri->ri_rows * (scr->rs_sbscreens + 1),
            ri->ri_cols * sizeof(struct wsdisplay_charcell), M_DEVBUF,
            M_NOWAIT);
        if (scr->rs_bs == NULL) {
                free(scr, M_DEVBUF, sizeof(*scr));
                return (ENOMEM);
        }
+       scr->rs_visibleoffset = scr->rs_dispoffset = ri->ri_rows *
+           scr->rs_sbscreens * ri->ri_cols;
 
        *cookiep = scr;
        *curxp = 0;
@@ -1405,13 +1413,19 @@ rasops_alloc_screen(void *v, void **cook
        scr->rs_crow = -1;
        scr->rs_ccol = -1;
 
+       for (i = 0; i < scr->rs_dispoffset; i++) {
+               scr->rs_bs[i].uc = ' ';
+               scr->rs_bs[i].attr = *attrp;
+       }
+
        if (ri->ri_bs && scr->rs_visible) {
-               memcpy(scr->rs_bs, ri->ri_bs, ri->ri_rows * ri->ri_cols *
+               memcpy(scr->rs_bs + scr->rs_dispoffset, ri->ri_bs,
+                   ri->ri_rows * ri->ri_cols *
                    sizeof(struct wsdisplay_charcell));
        } else {
                for (i = 0; i < ri->ri_rows * ri->ri_cols; i++) {
-                       scr->rs_bs[i].uc = ' ';
-                       scr->rs_bs[i].attr = *attrp;
+                       scr->rs_bs[scr->rs_dispoffset + i].uc = ' ';
+                       scr->rs_bs[scr->rs_dispoffset + i].attr = *attrp;
                }
        }
 
@@ -1431,7 +1445,8 @@ rasops_free_screen(void *v, void *cookie
        ri->ri_nscreens--;
 
        free(scr->rs_bs, M_DEVBUF,
-           ri->ri_rows * ri->ri_cols * sizeof(struct wsdisplay_charcell));
+           ri->ri_rows * (scr->rs_sbscreens + 1) * ri->ri_cols *
+           sizeof(struct wsdisplay_charcell));
        free(scr, M_DEVBUF, sizeof(*scr));
 }
 
@@ -1467,9 +1482,11 @@ rasops_doswitch(void *v)
        ri->ri_eraserows(ri, 0, ri->ri_rows, attr);
        ri->ri_active = scr;
        ri->ri_active->rs_visible = 1;
+       ri->ri_active->rs_visibleoffset = ri->ri_active->rs_dispoffset;
        for (row = 0; row < ri->ri_rows; row++) {
                for (col = 0; col < ri->ri_cols; col++) {
-                       int off = row * scr->rs_ri->ri_cols + col;
+                       int off = row * scr->rs_ri->ri_cols + col +
+                           scr->rs_visibleoffset;
 
                        ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
                            scr->rs_bs[off].attr);
@@ -1491,7 +1508,7 @@ rasops_getchar(void *v, int row, int col
        if (scr == NULL || scr->rs_bs == NULL)
                return (1);
 
-       *cell = scr->rs_bs[row * ri->ri_cols + col];
+       *cell = scr->rs_bs[row * ri->ri_cols + col + scr->rs_dispoffset];
        return (0);
 }
 
@@ -1521,7 +1538,10 @@ int
 rasops_vcons_putchar(void *cookie, int row, int col, u_int uc, long attr)
 {
        struct rasops_screen *scr = cookie;
-       int off = row * scr->rs_ri->ri_cols + col;
+       int off = row * scr->rs_ri->ri_cols + col + scr->rs_dispoffset;
+
+       if (scr->rs_visible && scr->rs_visibleoffset != scr->rs_dispoffset)
+               rasops_scrollback(scr->rs_ri, scr, 0);
 
        scr->rs_bs[off].uc = uc;
        scr->rs_bs[off].attr = attr;
@@ -1540,7 +1560,8 @@ rasops_vcons_copycols(void *cookie, int 
        int cols = scr->rs_ri->ri_cols;
        int col, rc;
 
-       memmove(&scr->rs_bs[row * cols + dst], &scr->rs_bs[row * cols + src],
+       memmove(&scr->rs_bs[row * cols + dst + scr->rs_dispoffset],
+           &scr->rs_bs[row * cols + src + scr->rs_dispoffset],
            num * sizeof(struct wsdisplay_charcell));
 
        if (!scr->rs_visible)
@@ -1550,7 +1571,7 @@ rasops_vcons_copycols(void *cookie, int 
                return ri->ri_copycols(ri, row, src, dst, num);
 
        for (col = dst; col < dst + num; col++) {
-               int off = row * cols + col;
+               int off = row * cols + col + scr->rs_dispoffset;
 
                rc = ri->ri_putchar(ri, row, col,
                    scr->rs_bs[off].uc, scr->rs_bs[off].attr);
@@ -1569,7 +1590,7 @@ rasops_vcons_erasecols(void *cookie, int
        int i;
 
        for (i = 0; i < num; i++) {
-               int off = row * cols + col + i;
+               int off = row * cols + col + i + scr->rs_dispoffset;
 
                scr->rs_bs[off].uc = ' ';
                scr->rs_bs[off].attr = attr;
@@ -1589,8 +1610,15 @@ rasops_vcons_copyrows(void *cookie, int 
        int cols = ri->ri_cols;
        int row, col, rc;
 
-       memmove(&scr->rs_bs[dst * cols], &scr->rs_bs[src * cols],
-           num * cols * sizeof(struct wsdisplay_charcell));
+       if (dst == 0 && (src + num == ri->ri_rows) && scr->rs_sbscreens)
+               memmove(&scr->rs_bs[dst], &scr->rs_bs[src * cols],
+                   ((ri->ri_rows * (scr->rs_sbscreens + 1) * cols) -
+                   (src * cols)) *
+                   sizeof(struct wsdisplay_charcell));
+       else
+               memmove(&scr->rs_bs[dst * cols + scr->rs_dispoffset],
+                   &scr->rs_bs[src * cols + scr->rs_dispoffset],
+                   num * cols * sizeof(struct wsdisplay_charcell));
 
        if (!scr->rs_visible)
                return 0;
@@ -1600,7 +1628,7 @@ rasops_vcons_copyrows(void *cookie, int 
 
        for (row = dst; row < dst + num; row++) {
                for (col = 0; col < cols; col++) {
-                       int off = row * cols + col;
+                       int off = row * cols + col + scr->rs_dispoffset;
 
                        rc = ri->ri_putchar(ri, row, col,
                            scr->rs_bs[off].uc, scr->rs_bs[off].attr);
@@ -1620,7 +1648,7 @@ rasops_vcons_eraserows(void *cookie, int
        int i;
 
        for (i = 0; i < num * cols; i++) {
-               int off = row * cols + i;
+               int off = row * cols + i + scr->rs_dispoffset;
 
                scr->rs_bs[off].uc = ' ';
                scr->rs_bs[off].attr = attr;
@@ -1871,4 +1899,46 @@ rasops_list_font(void *v, struct wsdispl
        font->index = idx;
        font->cookie = font->data = NULL;       /* don't leak kernel pointers */
        return 0;
+}
+
+void
+rasops_scrollback(void *v, void *cookie, int lines)
+{
+       struct rasops_info *ri = v;
+       struct rasops_screen *scr = cookie;
+       int row, col, oldvoff;
+       long attr;
+
+       oldvoff = scr->rs_visibleoffset;
+
+       if (lines == 0)
+               scr->rs_visibleoffset = scr->rs_dispoffset;
+       else {
+               int off = scr->rs_visibleoffset + (lines * ri->ri_cols);
+
+               if (off < 0)
+                       off = 0;
+               else if (off > scr->rs_dispoffset)
+                       off = scr->rs_dispoffset;
+
+               scr->rs_visibleoffset = off;
+       }
+
+       if (scr->rs_visibleoffset == oldvoff)
+               return;
+
+       rasops_cursor(ri, 0, 0, 0);
+       ri->ri_eraserows(ri, 0, ri->ri_rows, attr);
+       for (row = 0; row < ri->ri_rows; row++) {
+               for (col = 0; col < ri->ri_cols; col++) {
+                       int off = row * scr->rs_ri->ri_cols + col +
+                           scr->rs_visibleoffset;
+
+                       ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
+                           scr->rs_bs[off].attr);
+               }
+       }
+
+       if (scr->rs_crow != -1 && scr->rs_visibleoffset == scr->rs_dispoffset)
+               rasops_cursor(ri, 1, scr->rs_crow, scr->rs_ccol);
 }
Index: dev/rasops/rasops.h
===================================================================
RCS file: /cvs/src/sys/dev/rasops/rasops.h,v
retrieving revision 1.21
diff -u -p -u -p -r1.21 rasops.h
--- dev/rasops/rasops.h 20 Apr 2018 16:09:37 -0000      1.21
+++ dev/rasops/rasops.h 27 Apr 2018 14:27:23 -0000
@@ -178,6 +178,7 @@ int rasops_show_screen(void *, void *, i
 int    rasops_load_font(void *, void *, struct wsdisplay_font *);
 int    rasops_list_font(void *, struct wsdisplay_font *);
 int    rasops_getchar(void *, int, int, struct wsdisplay_charcell *);
+void   rasops_scrollback(void *, void *, int);
 
 extern const u_char    rasops_isgray[16];
 extern const u_char    rasops_cmap[256*3];
Index: dev/pci/drm/i915/i915_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v
retrieving revision 1.111
diff -u -p -u -p -r1.111 i915_drv.c
--- dev/pci/drm/i915/i915_drv.c 20 Apr 2018 16:09:36 -0000      1.111
+++ dev/pci/drm/i915/i915_drv.c 27 Apr 2018 14:27:23 -0000
@@ -1925,6 +1925,7 @@ int       inteldrm_list_font(void *, struct ws
 int    inteldrm_getchar(void *, int, int, struct wsdisplay_charcell *);
 void   inteldrm_burner(void *, u_int, u_int);
 void   inteldrm_burner_cb(void *);
+void   inteldrm_scrollback(void *, void *, int lines);
 
 struct wsscreen_descr inteldrm_stdscreen = {
        "std",
@@ -1953,6 +1954,7 @@ struct wsdisplay_accessops inteldrm_acce
        .getchar = inteldrm_getchar,
        .load_font = inteldrm_load_font,
        .list_font = inteldrm_list_font,
+       .scrollback = inteldrm_scrollback,
        .burn_screen = inteldrm_burner
 };
 
@@ -2173,6 +2175,15 @@ const struct backlight_ops inteldrm_back
        .update_status = inteldrm_backlight_update_status,
        .get_brightness = inteldrm_backlight_get_brightness
 };
+
+void
+inteldrm_scrollback(void *v, void *cookie, int lines)
+{
+       struct inteldrm_softc *dev_priv = v;
+       struct rasops_info *ri = &dev_priv->ro;
+
+       rasops_scrollback(ri, cookie, lines);
+}
 
 int    inteldrm_match(struct device *, void *, void *);
 void   inteldrm_attach(struct device *, struct device *, void *);

Reply via email to