Date: Wed, 15 Sep 1999 18:45:37 +0100 (BST) From: Mark Ovens <mark@ukug.uk.freebsd.org> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/13764: [PATCH] Stop syscons from flushing history buffer when changing video mode Message-ID: <199909151745.SAA06547@marder-1.>
index | next in thread | raw e-mail
>Number: 13764
>Category: kern
>Synopsis: [PATCH] Stop syscons from flushing history buffer when changing video mode
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Sep 15 11:00:01 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator: Mark Ovens
>Release: FreeBSD 3.1-RELEASE i386
>Organization:
>Environment:
FreeBSD marder-1 3.1-RELEASE FreeBSD 3.1-RELEASE #33:
Wed Sep 15 18:12:58 BST 1999
mark@marder-1:/usr/src/sys/compile/MARDER-1 i386
>Description:
When the console video mode is changed, with vidcontrol,
syscons free()s the current history buffer and malloc()s
a new one which means that the scroll-back buffer is lost.
This can be a problem if the video mode is set in /etc/rc.conf
(e.g. ``allscreens_flags="80x43"'') and a process which is started
from an rc* file fails to start as you cannot scroll back to look
at the error messages.
>How-To-Repeat:
Add ``allscreens_flags="80x43"'' to /etc/rc.conf, reboot, hit
the Scroll Lock key, then PgUp.
>Fix:
*** /usr/src/sys/dev/syscons/syscons.c.orig Wed Sep 8 18:42:25 1999
--- /usr/src/sys/dev/syscons/syscons.c Wed Sep 15 18:13:19 1999
***************
*** 3320,3347 ****
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;
}
static scr_stat
--- 3320,3380 ----
void
sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
{
! u_short *new, *old;
! u_short head_offset = 0, pos_offset = 0;
! int i, j;
! int old_size = 0;
! old = NULL;
!
! if (scp->history != NULL) {
!
! /* Save pointer offsets and size of the old buffer */
! head_offset = scp->history_head - scp->history;
! pos_offset = scp->history_pos - scp->history;
! old_size = scp->history_size;
! if (extra > 0)
extra_history_size += extra;
}
+ if (lines < scp->ysize)
+ lines = scp->ysize;
+
scp->history_size = lines * scp->xsize;
if (lines > imax(sc_history_size, scp->ysize))
extra_history_size -= lines - imax(sc_history_size, scp->ysize);
! new = (u_short *)malloc(scp->history_size * sizeof(u_short),
M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
! if (new != NULL)
! bzero(new, scp->history_size * sizeof(u_short));
!
! /* Copy contents of old buffer to the new one, but start at
! * the end and work back. This ensures that if the new buffer
! * is smaller than the old one then the oldest data is
! * truncated rather than the latest.
! */
!
! if (scp->history != NULL) {
! i = scp->history_size - 1;
! j = old_size - 1;
!
! while (i >= 0 && j >= 0)
! *(new + i--) = *(scp->history + j--);
!
! old = scp->history;
! scp->history = new;
!
! scp->history_head = scp->history_pos = scp->history + head_offset;
! scp->history_pos = scp->history_pos = scp->history + pos_offset;
!
! } else
! scp->history = scp->history_head = scp->history_pos = new;
!
! if (old != NULL) {
! free(old, M_DEVBUF);
!
! }
}
static scr_stat
*** /usr/src/sys/dev/syscons/scvidctl.c.orig Tue Sep 7 20:53:19 1999
--- /usr/src/sys/dev/syscons/scvidctl.c Wed Sep 15 00:44:55 1999
***************
*** 86,91 ****
--- 86,107 ----
int s;
int i;
+ /* Copy screen into the top of the history buffer. This must
+ * be done here so that scp->{x,y}size are still set to the
+ * old mode values. Any later and we will copy too few or too
+ * many (the extra will be garbage) lines.
+ */
+
+ for (i = 0; i < scp->ysize; i++) {
+ bcopy(scp->scr_buf + (scp->xsize * i), 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;
+ }
+
if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info))
return ENODEV;
***************
*** 138,153 ****
scp->xpixel = scp->xsize*8;
scp->ypixel = scp->ysize*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);
splx(s);
-
- if (scp == cur_console)
- set_mode(scp);
- scp->status &= ~UNKNOWN_MODE;
if (tp == NULL)
return 0;
--- 154,173 ----
scp->xpixel = scp->xsize*8;
scp->ypixel = scp->ysize*fontsize;
+ /* We need to call set_mode() before sc_alloc_history_buffer()
+ * or the history buffer will get screwed up.
+ */
+
+ if (scp == cur_console)
+ set_mode(scp);
+ scp->status &= ~UNKNOWN_MODE;
+
/* 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);
splx(s);
if (tp == NULL)
return 0;
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199909151745.SAA06547>
