From owner-freebsd-bugs Wed Sep 15 11: 0:29 1999 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id B17631535B for ; Wed, 15 Sep 1999 11:00:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id LAA07484; Wed, 15 Sep 1999 11:00:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from sand5.global.net.uk (sand5.mail.gxn.net [194.126.80.249]) by hub.freebsd.org (Postfix) with ESMTP id 5998915245 for ; Wed, 15 Sep 1999 10:54:05 -0700 (PDT) (envelope-from mark@globalnet.co.uk) Received: from p25s13a07.client.global.net.uk ([195.147.237.38] helo=marder-1.) by sand5.global.net.uk with esmtp (Exim 2.05 #1) id 11RJFq-0005uT-00 for FreeBSD-gnats-submit@freebsd.org; Wed, 15 Sep 1999 18:54:03 +0100 Received: (from root@localhost) by marder-1. (8.9.2/8.8.8) id SAA06547; Wed, 15 Sep 1999 18:45:37 +0100 (BST) (envelope-from mark) Message-Id: <199909151745.SAA06547@marder-1.> Date: Wed, 15 Sep 1999 18:45:37 +0100 (BST) From: Mark Ovens Reply-To: Mark Ovens To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/13764: [PATCH] Stop syscons from flushing history buffer when changing video mode Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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