The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/misc/syscons/schistory.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    3  * Copyright (c) 1992-1998 Søren Schmidt
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer,
   11  *    without modification, immediately at the beginning of the file.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $FreeBSD: src/sys/dev/syscons/schistory.c,v 1.8.2.1 2001/07/19 06:38:53 dd Exp $
   30  * $DragonFly: src/sys/dev/misc/syscons/schistory.c,v 1.8 2006/09/05 00:55:38 dillon Exp $
   31  */
   32 
   33 #include "use_sc.h"
   34 #include "opt_syscons.h"
   35 
   36 #ifndef SC_NO_HISTORY
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/conf.h>
   41 #include <sys/tty.h>
   42 #include <sys/kernel.h>
   43 
   44 #include <machine/console.h>
   45 #include <machine/pc/display.h>
   46 
   47 #include "syscons.h"
   48 
   49 #if !defined(SC_MAX_HISTORY_SIZE)
   50 #define SC_MAX_HISTORY_SIZE     (1000 * MAXCONS * NSC)
   51 #endif
   52 
   53 #if !defined(SC_HISTORY_SIZE)
   54 #define SC_HISTORY_SIZE         (ROW * 4)
   55 #endif
   56 
   57 #if (SC_HISTORY_SIZE * MAXCONS * NSC) > SC_MAX_HISTORY_SIZE
   58 #undef SC_MAX_HISTORY_SIZE
   59 #define SC_MAX_HISTORY_SIZE     (SC_HISTORY_SIZE * MAXCONS * NSC)
   60 #endif
   61 
   62 /* local variables */
   63 static int              extra_history_size
   64                                 = SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE*MAXCONS;
   65 
   66 /* local functions */
   67 static void copy_history(sc_vtb_t *from, sc_vtb_t *to);
   68 static void history_to_screen(scr_stat *scp);
   69 
   70 /* allocate a history buffer */
   71 int
   72 sc_alloc_history_buffer(scr_stat *scp, int lines, int prev_ysize, int wait)
   73 {
   74         /*
   75          * syscons unconditionally allocates buffers upto 
   76          * SC_HISTORY_SIZE lines or scp->ysize lines, whichever 
   77          * is larger. A value greater than that is allowed, 
   78          * subject to extra_history_size.
   79          */
   80         sc_vtb_t *history;
   81         sc_vtb_t *prev_history;
   82         int cur_lines;                          /* current buffer size */
   83         int min_lines;                          /* guaranteed buffer size */
   84         int delta;                              /* lines to put back */
   85 
   86         if (lines <= 0)
   87                 lines = SC_HISTORY_SIZE;        /* use the default value */
   88 
   89         /* make it at least as large as the screen size */
   90         lines = imax(lines, scp->ysize);
   91 
   92         /* remove the history buffer while we update it */
   93         history = prev_history = scp->history;
   94         scp->history = NULL;
   95 
   96         /* calculate the amount of lines to put back to extra_history_size */
   97         delta = 0;
   98         if (prev_history) {
   99                 cur_lines = sc_vtb_rows(history);
  100                 min_lines = imax(SC_HISTORY_SIZE, prev_ysize);
  101                 if (cur_lines > min_lines)
  102                         delta = cur_lines - min_lines;
  103         }
  104 
  105         /* lines upto min_lines are always allowed. */
  106         min_lines = imax(SC_HISTORY_SIZE, scp->ysize);
  107         if (lines > min_lines) {
  108                 if (lines - min_lines > extra_history_size + delta) {
  109                         /* too many lines are requested */
  110                         scp->history = prev_history;
  111                         return EINVAL;
  112                 }
  113         }
  114 
  115         /* allocate a new buffer */
  116         history = kmalloc(sizeof(*history), M_SYSCONS,
  117                          (wait) ? M_WAITOK : M_NOWAIT);
  118         if (history != NULL) {
  119                 if (lines > min_lines)
  120                         extra_history_size -= lines - min_lines;
  121                 /* XXX error check? */
  122                 sc_vtb_init(history, VTB_RINGBUFFER, scp->xsize, lines,
  123                             NULL, wait);
  124                 /* FIXME: XXX no good? */
  125                 sc_vtb_clear(history, scp->sc->scr_map[0x20],
  126                              SC_NORM_ATTR << 8);
  127                 if (prev_history != NULL)
  128                         copy_history(prev_history, history);
  129                 scp->history_pos = sc_vtb_tail(history);
  130         } else {
  131                 scp->history_pos = 0;
  132         }
  133 
  134         /* destroy the previous buffer */
  135         if (prev_history != NULL) {
  136                 extra_history_size += delta;
  137                 sc_vtb_destroy(prev_history);
  138                 kfree(prev_history, M_SYSCONS);
  139         }
  140 
  141         scp->history = history;
  142 
  143         return 0;
  144 }
  145 
  146 static void
  147 copy_history(sc_vtb_t *from, sc_vtb_t *to)
  148 {
  149         int lines;
  150         int cols;
  151         int cols1;
  152         int cols2;
  153         int pos;
  154         int i;
  155 
  156         lines = sc_vtb_rows(from);
  157         cols1 = sc_vtb_cols(from);
  158         cols2 = sc_vtb_cols(to);
  159         cols = imin(cols1, cols2);
  160         pos = sc_vtb_tail(from);
  161         for (i = 0; i < lines; ++i) {
  162                 sc_vtb_append(from, pos, to, cols);
  163                 if (cols < cols2)
  164                         sc_vtb_seek(to, sc_vtb_pos(to, 
  165                                                    sc_vtb_tail(to), 
  166                                                    cols2 - cols));
  167                 pos = sc_vtb_pos(from, pos, cols1);
  168         }
  169 }
  170 
  171 void
  172 sc_free_history_buffer(scr_stat *scp, int prev_ysize)
  173 {
  174         sc_vtb_t *history;
  175         int cur_lines;                          /* current buffer size */
  176         int min_lines;                          /* guaranteed buffer size */
  177 
  178         history = scp->history;
  179         scp->history = NULL;
  180         if (history == NULL)
  181                 return;
  182 
  183         cur_lines = sc_vtb_rows(history);
  184         min_lines = imax(SC_HISTORY_SIZE, prev_ysize);
  185         extra_history_size += (cur_lines > min_lines) ? 
  186                                   cur_lines - min_lines : 0;
  187 
  188         sc_vtb_destroy(history);
  189         kfree(history, M_SYSCONS);
  190 }
  191 
  192 /* copy entire screen into the top of the history buffer */
  193 void
  194 sc_hist_save(scr_stat *scp)
  195 {
  196         sc_vtb_append(&scp->vtb, 0, scp->history, scp->xsize*scp->ysize);
  197         scp->history_pos = sc_vtb_tail(scp->history);
  198 }
  199 
  200 /* restore the screen by copying from the history buffer */
  201 int
  202 sc_hist_restore(scr_stat *scp)
  203 {
  204         int ret;
  205 
  206         if (scp->history_pos != sc_vtb_tail(scp->history)) {
  207                 scp->history_pos = sc_vtb_tail(scp->history);
  208                 history_to_screen(scp);
  209                 ret =  0;
  210         } else {
  211                 ret = 1;
  212         }
  213         sc_vtb_seek(scp->history, sc_vtb_pos(scp->history, 
  214                                              sc_vtb_tail(scp->history),
  215                                              -scp->xsize*scp->ysize));
  216         return ret;
  217 }
  218 
  219 /* copy screen-full of saved lines */
  220 static void
  221 history_to_screen(scr_stat *scp)
  222 {
  223         int pos;
  224         int i;
  225 
  226         pos = scp->history_pos;
  227         for (i = 1; i <= scp->ysize; ++i) {
  228                 pos = sc_vtb_pos(scp->history, pos, -scp->xsize);
  229                 sc_vtb_copy(scp->history, pos,
  230                             &scp->vtb, scp->xsize*(scp->ysize - i),
  231                             scp->xsize);
  232         }
  233         mark_all(scp);
  234 }
  235 
  236 /* go to the tail of the history buffer */
  237 void
  238 sc_hist_home(scr_stat *scp)
  239 {
  240         scp->history_pos = sc_vtb_tail(scp->history);
  241         history_to_screen(scp);
  242 }
  243 
  244 /* go to the top of the history buffer */
  245 void
  246 sc_hist_end(scr_stat *scp)
  247 {
  248         scp->history_pos = sc_vtb_pos(scp->history, sc_vtb_tail(scp->history),
  249                                       scp->xsize*scp->ysize);
  250         history_to_screen(scp);
  251 }
  252 
  253 /* move one line up */
  254 int
  255 sc_hist_up_line(scr_stat *scp)
  256 {
  257         if (sc_vtb_pos(scp->history, scp->history_pos, -(scp->xsize*scp->ysize))
  258             == sc_vtb_tail(scp->history))
  259                 return -1;
  260         scp->history_pos = sc_vtb_pos(scp->history, scp->history_pos,
  261                                       -scp->xsize);
  262         history_to_screen(scp);
  263         return 0;
  264 }
  265 
  266 /* move one line down */
  267 int
  268 sc_hist_down_line(scr_stat *scp)
  269 {
  270         if (scp->history_pos == sc_vtb_tail(scp->history))
  271                 return -1;
  272         scp->history_pos = sc_vtb_pos(scp->history, scp->history_pos,
  273                                       scp->xsize);
  274         history_to_screen(scp);
  275         return 0;
  276 }
  277 
  278 int
  279 sc_hist_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
  280 {
  281         scr_stat *scp;
  282         int error;
  283 
  284         switch (cmd) {
  285 
  286         case CONS_HISTORY:      /* set history size */
  287                 scp = SC_STAT(tp->t_dev);
  288                 if (*(int *)data <= 0)
  289                         return EINVAL;
  290                 if (scp->status & BUFFER_SAVED)
  291                         return EBUSY;
  292                 DPRINTF(5, ("lines:%d, ysize:%d, pool:%d\n",
  293                             *(int *)data, scp->ysize, extra_history_size));
  294                 error = sc_alloc_history_buffer(scp, 
  295                                                imax(*(int *)data, scp->ysize),
  296                                                scp->ysize, TRUE);
  297                 DPRINTF(5, ("error:%d, rows:%d, pool:%d\n", error,
  298                             sc_vtb_rows(scp->history), extra_history_size));
  299                 return error;
  300 
  301         case CONS_CLRHIST:
  302                 scp = SC_STAT(tp->t_dev);
  303                 sc_vtb_clear(scp->history, scp->sc->scr_map[0x20],
  304                     SC_NORM_ATTR << 8);
  305                 return 0;
  306         }
  307 
  308         return ENOIOCTL;
  309 }
  310 
  311 #endif /* SC_NO_HISTORY */

Cache object: 49f0b61cd748351cd59c79bc4bd54c0f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.