LCOV - code coverage report
Current view: top level - dev/rasops - rasops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 853 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 48 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: rasops.c,v 1.56 2018/08/27 09:30:07 kettenis Exp $    */
       2             : /*      $NetBSD: rasops.c,v 1.35 2001/02/02 06:01:01 marcus Exp $       */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1999 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Andrew Doran.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      21             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      23             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      24             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #include <sys/param.h>
      34             : #include <sys/malloc.h>
      35             : #include <sys/systm.h>
      36             : #include <sys/time.h>
      37             : #include <sys/task.h>
      38             : 
      39             : #include <dev/wscons/wsdisplayvar.h>
      40             : #include <dev/wscons/wsconsio.h>
      41             : #include <dev/wsfont/wsfont.h>
      42             : #include <dev/rasops/rasops.h>
      43             : 
      44             : #ifndef _KERNEL
      45             : #include <errno.h>
      46             : #endif
      47             : 
      48             : /* ANSI colormap (R,G,B) */
      49             : 
      50             : #define NORMAL_BLACK    0x000000
      51             : #define NORMAL_RED      0x7f0000
      52             : #define NORMAL_GREEN    0x007f00
      53             : #define NORMAL_BROWN    0x7f7f00
      54             : #define NORMAL_BLUE     0x00007f
      55             : #define NORMAL_MAGENTA  0x7f007f
      56             : #define NORMAL_CYAN     0x007f7f
      57             : #define NORMAL_WHITE    0xc7c7c7        /* XXX too dim? */
      58             : 
      59             : #define HILITE_BLACK    0x7f7f7f
      60             : #define HILITE_RED      0xff0000
      61             : #define HILITE_GREEN    0x00ff00
      62             : #define HILITE_BROWN    0xffff00
      63             : #define HILITE_BLUE     0x0000ff
      64             : #define HILITE_MAGENTA  0xff00ff
      65             : #define HILITE_CYAN     0x00ffff
      66             : #define HILITE_WHITE    0xffffff
      67             : 
      68             : const u_char rasops_cmap[256 * 3] = {
      69             : #define _C(x)   ((x) & 0xff0000) >> 16, ((x) & 0x00ff00) >> 8, ((x) & 0x0000ff)
      70             : 
      71             :         _C(NORMAL_BLACK),
      72             :         _C(NORMAL_RED),
      73             :         _C(NORMAL_GREEN),
      74             :         _C(NORMAL_BROWN),
      75             :         _C(NORMAL_BLUE),
      76             :         _C(NORMAL_MAGENTA),
      77             :         _C(NORMAL_CYAN),
      78             :         _C(NORMAL_WHITE),
      79             : 
      80             :         _C(HILITE_BLACK),
      81             :         _C(HILITE_RED),
      82             :         _C(HILITE_GREEN),
      83             :         _C(HILITE_BROWN),
      84             :         _C(HILITE_BLUE),
      85             :         _C(HILITE_MAGENTA),
      86             :         _C(HILITE_CYAN),
      87             :         _C(HILITE_WHITE),
      88             : 
      89             :         /*
      90             :          * For the cursor, we need the last 16 colors to be the
      91             :          * opposite of the first 16. Fill the intermediate space with
      92             :          * white completely for simplicity.
      93             :          */
      94             : #define _CMWHITE16 \
      95             :         _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
      96             :         _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
      97             :         _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), \
      98             :         _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE), _C(HILITE_WHITE),
      99             :         _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
     100             :         _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
     101             :         _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
     102             : #undef _CMWHITE16
     103             : 
     104             :         _C(~HILITE_WHITE),
     105             :         _C(~HILITE_CYAN),
     106             :         _C(~HILITE_MAGENTA),
     107             :         _C(~HILITE_BLUE),
     108             :         _C(~HILITE_BROWN),
     109             :         _C(~HILITE_GREEN),
     110             :         _C(~HILITE_RED),
     111             :         _C(~HILITE_BLACK),
     112             : 
     113             :         _C(~NORMAL_WHITE),
     114             :         _C(~NORMAL_CYAN),
     115             :         _C(~NORMAL_MAGENTA),
     116             :         _C(~NORMAL_BLUE),
     117             :         _C(~NORMAL_BROWN),
     118             :         _C(~NORMAL_GREEN),
     119             :         _C(~NORMAL_RED),
     120             :         _C(~NORMAL_BLACK),
     121             : 
     122             : #undef  _C
     123             : };
     124             : 
     125             : /* True if color is gray */
     126             : const u_char rasops_isgray[16] = {
     127             :         1, 0, 0, 0,
     128             :         0, 0, 0, 1,
     129             :         1, 0, 0, 0,
     130             :         0, 0, 0, 1
     131             : };
     132             : 
     133             : struct rasops_screen {
     134             :         LIST_ENTRY(rasops_screen) rs_next;
     135             :         struct rasops_info *rs_ri;
     136             : 
     137             :         struct wsdisplay_charcell *rs_bs;
     138             :         int rs_visible;
     139             :         int rs_crow;
     140             :         int rs_ccol;
     141             :         long rs_defattr;
     142             : 
     143             :         int rs_sbscreens;
     144             : #define RS_SCROLLBACK_SCREENS 5
     145             :         int rs_dispoffset;      /* rs_bs index, start of our actual screen */
     146             :         int rs_visibleoffset;   /* rs_bs index, current scrollback screen */
     147             : };
     148             : 
     149             : /* Generic functions */
     150             : int     rasops_copycols(void *, int, int, int, int);
     151             : int     rasops_copyrows(void *, int, int, int);
     152             : int     rasops_mapchar(void *, int, u_int *);
     153             : int     rasops_cursor(void *, int, int, int);
     154             : int     rasops_alloc_cattr(void *, int, int, int, long *);
     155             : int     rasops_alloc_mattr(void *, int, int, int, long *);
     156             : int     rasops_do_cursor(struct rasops_info *);
     157             : void    rasops_init_devcmap(struct rasops_info *);
     158             : void    rasops_unpack_attr(void *, long, int *, int *, int *);
     159             : #if NRASOPS_BSWAP > 0
     160             : static void slow_bcopy(void *, void *, size_t);
     161             : #endif
     162             : #if NRASOPS_ROTATION > 0
     163             : void    rasops_copychar(void *, int, int, int, int);
     164             : int     rasops_copycols_rotated(void *, int, int, int, int);
     165             : int     rasops_copyrows_rotated(void *, int, int, int);
     166             : int     rasops_erasecols_rotated(void *, int, int, int, long);
     167             : int     rasops_eraserows_rotated(void *, int, int, long);
     168             : int     rasops_putchar_rotated(void *, int, int, u_int, long);
     169             : void    rasops_rotate_font(int *, int);
     170             : 
     171             : /*
     172             :  * List of all rotated fonts
     173             :  */
     174             : SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
     175             : struct  rotatedfont {
     176             :         SLIST_ENTRY(rotatedfont) rf_next;
     177             :         int rf_cookie;
     178             :         int rf_rotated;
     179             : };
     180             : #endif
     181             : 
     182             : void    rasops_doswitch(void *);
     183             : int     rasops_vcons_cursor(void *, int, int, int);
     184             : int     rasops_vcons_mapchar(void *, int, u_int *);
     185             : int     rasops_vcons_putchar(void *, int, int, u_int, long);
     186             : int     rasops_vcons_copycols(void *, int, int, int, int);
     187             : int     rasops_vcons_erasecols(void *, int, int, int, long);
     188             : int     rasops_vcons_copyrows(void *, int, int, int);
     189             : int     rasops_vcons_eraserows(void *, int, int, long);
     190             : int     rasops_vcons_alloc_attr(void *, int, int, int, long *);
     191             : void    rasops_vcons_unpack_attr(void *, long, int *, int *, int *);
     192             : 
     193             : int     rasops_wronly_putchar(void *, int, int, u_int, long);
     194             : int     rasops_wronly_copycols(void *, int, int, int, int);
     195             : int     rasops_wronly_erasecols(void *, int, int, int, long);
     196             : int     rasops_wronly_copyrows(void *, int, int, int);
     197             : int     rasops_wronly_eraserows(void *, int, int, long);
     198             : int     rasops_wronly_do_cursor(struct rasops_info *);
     199             : 
     200             : int     rasops_add_font(struct rasops_info *, struct wsdisplay_font *);
     201             : int     rasops_use_font(struct rasops_info *, struct wsdisplay_font *);
     202             : int     rasops_list_font_cb(void *, struct wsdisplay_font *);
     203             : 
     204             : /*
     205             :  * Initialize a 'rasops_info' descriptor.
     206             :  */
     207             : int
     208           0 : rasops_init(struct rasops_info *ri, int wantrows, int wantcols)
     209             : {
     210             : 
     211             : #ifdef _KERNEL
     212             :         /* Select a font if the caller doesn't care */
     213           0 :         if (ri->ri_font == NULL) {
     214           0 :                 int cookie;
     215             : 
     216           0 :                 wsfont_init();
     217             : 
     218           0 :                 if (ri->ri_width > 80*12)
     219             :                         /* High res screen, choose a big font */
     220           0 :                         cookie = wsfont_find(NULL, 12, 0, 0);
     221             :                 else
     222             :                         /*  lower res, choose a 8 pixel wide font */
     223           0 :                         cookie = wsfont_find(NULL, 8, 0, 0);
     224             : 
     225           0 :                 if (cookie <= 0)
     226           0 :                         cookie = wsfont_find(NULL, 0, 0, 0);
     227             : 
     228           0 :                 if (cookie <= 0) {
     229           0 :                         printf("rasops_init: font table is empty\n");
     230           0 :                         return (-1);
     231             :                 }
     232             : 
     233             : #if NRASOPS_ROTATION > 0
     234             :                 /*
     235             :                  * Pick the rotated version of this font. This will create it
     236             :                  * if necessary.
     237             :                  */
     238           0 :                 if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW))
     239           0 :                         rasops_rotate_font(&cookie,
     240           0 :                             ISSET(ri->ri_flg, RI_ROTATE_CCW));
     241             : #endif
     242             : 
     243           0 :                 if (wsfont_lock(cookie, &ri->ri_font,
     244           0 :                     WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) {
     245           0 :                         printf("rasops_init: couldn't lock font\n");
     246           0 :                         return (-1);
     247             :                 }
     248             : 
     249           0 :                 ri->ri_wsfcookie = cookie;
     250           0 :         }
     251             : #endif
     252             : 
     253             :         /* This should never happen in reality... */
     254             : #ifdef DEBUG
     255             :         if ((long)ri->ri_bits & 3) {
     256             :                 printf("rasops_init: bits not aligned on 32-bit boundary\n");
     257             :                 return (-1);
     258             :         }
     259             : 
     260             :         if ((int)ri->ri_stride & 3) {
     261             :                 printf("rasops_init: stride not aligned on 32-bit boundary\n");
     262             :                 return (-1);
     263             :         }
     264             : #endif
     265             : 
     266           0 :         if (rasops_reconfig(ri, wantrows, wantcols))
     267           0 :                 return (-1);
     268             : 
     269           0 :         LIST_INIT(&ri->ri_screens);
     270           0 :         ri->ri_nscreens = 0;
     271             : 
     272           0 :         ri->ri_putchar = ri->ri_ops.putchar;
     273           0 :         ri->ri_copycols = ri->ri_ops.copycols;
     274           0 :         ri->ri_erasecols = ri->ri_ops.erasecols;
     275           0 :         ri->ri_copyrows = ri->ri_ops.copyrows;
     276           0 :         ri->ri_eraserows = ri->ri_ops.eraserows;
     277           0 :         ri->ri_alloc_attr = ri->ri_ops.alloc_attr;
     278             : 
     279           0 :         if (ri->ri_flg & RI_VCONS) {
     280           0 :                 void *cookie;
     281           0 :                 int curx, cury;
     282           0 :                 long attr;
     283             : 
     284           0 :                 if (rasops_alloc_screen(ri, &cookie, &curx, &cury, &attr))
     285           0 :                         return (-1);
     286             : 
     287           0 :                 ri->ri_active = cookie;
     288           0 :                 ri->ri_bs =
     289           0 :                     &ri->ri_active->rs_bs[ri->ri_active->rs_dispoffset];
     290             : 
     291           0 :                 ri->ri_ops.cursor = rasops_vcons_cursor;
     292           0 :                 ri->ri_ops.mapchar = rasops_vcons_mapchar;
     293           0 :                 ri->ri_ops.putchar = rasops_vcons_putchar;
     294           0 :                 ri->ri_ops.copycols = rasops_vcons_copycols;
     295           0 :                 ri->ri_ops.erasecols = rasops_vcons_erasecols;
     296           0 :                 ri->ri_ops.copyrows = rasops_vcons_copyrows;
     297           0 :                 ri->ri_ops.eraserows = rasops_vcons_eraserows;
     298           0 :                 ri->ri_ops.alloc_attr = rasops_vcons_alloc_attr;
     299           0 :                 ri->ri_ops.unpack_attr = rasops_vcons_unpack_attr;
     300           0 :                 ri->ri_do_cursor = rasops_wronly_do_cursor;
     301           0 :         } else if ((ri->ri_flg & RI_WRONLY) && ri->ri_bs != NULL) {
     302           0 :                 long attr;
     303             :                 int i;
     304             : 
     305           0 :                 ri->ri_ops.putchar = rasops_wronly_putchar;
     306           0 :                 ri->ri_ops.copycols = rasops_wronly_copycols;
     307           0 :                 ri->ri_ops.erasecols = rasops_wronly_erasecols;
     308           0 :                 ri->ri_ops.copyrows = rasops_wronly_copyrows;
     309           0 :                 ri->ri_ops.eraserows = rasops_wronly_eraserows;
     310           0 :                 ri->ri_do_cursor = rasops_wronly_do_cursor;
     311             : 
     312           0 :                 ri->ri_alloc_attr(ri, 0, 0, 0, &attr);
     313           0 :                 for (i = 0; i < ri->ri_rows * ri->ri_cols; i++) {
     314           0 :                         ri->ri_bs[i].uc = ' ';
     315           0 :                         ri->ri_bs[i].attr = attr;
     316             :                 }
     317           0 :         }
     318             : 
     319           0 :         task_set(&ri->ri_switchtask, rasops_doswitch, ri);
     320             : 
     321           0 :         rasops_init_devcmap(ri);
     322           0 :         return (0);
     323           0 : }
     324             : 
     325             : /*
     326             :  * Reconfigure (because parameters have changed in some way).
     327             :  */
     328             : int
     329           0 : rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
     330             : {
     331             :         int l, bpp, s;
     332             : 
     333           0 :         s = splhigh();
     334             : 
     335           0 :         if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4)
     336           0 :                 panic("rasops_init: fontwidth assumptions botched!");
     337             : 
     338             :         /* Need this to frob the setup below */
     339           0 :         bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
     340             : 
     341           0 :         if ((ri->ri_flg & RI_CFGDONE) != 0)
     342           0 :                 ri->ri_bits = ri->ri_origbits;
     343             : 
     344             :         /* Don't care if the caller wants a hideously small console */
     345           0 :         if (wantrows < 10)
     346           0 :                 wantrows = 10;
     347             : 
     348           0 :         if (wantcols < 20)
     349           0 :                 wantcols = 20;
     350             : 
     351             :         /* Now constrain what they get */
     352           0 :         ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
     353           0 :         ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
     354             : 
     355           0 :         if (ri->ri_emuwidth > ri->ri_width)
     356           0 :                 ri->ri_emuwidth = ri->ri_width;
     357             : 
     358           0 :         if (ri->ri_emuheight > ri->ri_height)
     359           0 :                 ri->ri_emuheight = ri->ri_height;
     360             : 
     361             :         /* Reduce width until aligned on a 32-bit boundary */
     362           0 :         while ((ri->ri_emuwidth * bpp & 31) != 0)
     363           0 :                 ri->ri_emuwidth--;
     364             : 
     365             : #if NRASOPS_ROTATION > 0
     366           0 :         if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW)) {
     367           0 :                 ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
     368           0 :                 ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
     369           0 :         } else
     370             : #endif
     371             :         {
     372           0 :                 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
     373           0 :                 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
     374             :         }
     375           0 :         ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
     376           0 :         ri->ri_delta = ri->ri_stride - ri->ri_emustride;
     377           0 :         ri->ri_ccol = 0;
     378           0 :         ri->ri_crow = 0;
     379           0 :         ri->ri_pelbytes = bpp >> 3;
     380             : 
     381           0 :         ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
     382           0 :         ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
     383           0 :         ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
     384             : 
     385             : #ifdef DEBUG
     386             :         if ((ri->ri_delta & 3) != 0)
     387             :                 panic("rasops_init: ri_delta not aligned on 32-bit boundary");
     388             : #endif
     389             :         /* Clear the entire display */
     390           0 :         if ((ri->ri_flg & RI_CLEAR) != 0) {
     391           0 :                 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
     392           0 :                 ri->ri_flg &= ~RI_CLEARMARGINS;
     393           0 :         }
     394             : 
     395             :         /* Now centre our window if needs be */
     396           0 :         ri->ri_origbits = ri->ri_bits;
     397             : 
     398           0 :         if ((ri->ri_flg & RI_CENTER) != 0) {
     399           0 :                 ri->ri_bits += (((ri->ri_width * bpp >> 3) -
     400           0 :                     ri->ri_emustride) >> 1) & ~3;
     401           0 :                 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
     402           0 :                     ri->ri_stride;
     403             : 
     404           0 :                 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
     405           0 :                    / ri->ri_stride;
     406           0 :                 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
     407           0 :                    % ri->ri_stride) * 8 / bpp);
     408           0 :         } else
     409           0 :                 ri->ri_xorigin = ri->ri_yorigin = 0;
     410             : 
     411             :         /* Clear the margins */
     412           0 :         if ((ri->ri_flg & RI_CLEARMARGINS) != 0) {
     413           0 :                 memset(ri->ri_origbits, 0, ri->ri_bits - ri->ri_origbits);
     414           0 :                 for (l = 0; l < ri->ri_emuheight; l++)
     415           0 :                         memset(ri->ri_bits + ri->ri_emustride +
     416             :                             l * ri->ri_stride, 0,
     417             :                             ri->ri_stride - ri->ri_emustride);
     418           0 :                 memset(ri->ri_bits + ri->ri_emuheight * ri->ri_stride, 0,
     419             :                     (ri->ri_origbits + ri->ri_height * ri->ri_stride) -
     420             :                     (ri->ri_bits + ri->ri_emuheight * ri->ri_stride));
     421           0 :         }
     422             : 
     423             :         /*
     424             :          * Fill in defaults for operations set.  XXX this nukes private
     425             :          * routines used by accelerated fb drivers.
     426             :          */
     427           0 :         ri->ri_ops.mapchar = rasops_mapchar;
     428           0 :         ri->ri_ops.copyrows = rasops_copyrows;
     429           0 :         ri->ri_ops.copycols = rasops_copycols;
     430           0 :         ri->ri_ops.erasecols = rasops_erasecols;
     431           0 :         ri->ri_ops.eraserows = rasops_eraserows;
     432           0 :         ri->ri_ops.cursor = rasops_cursor;
     433           0 :         ri->ri_ops.unpack_attr = rasops_unpack_attr;
     434           0 :         ri->ri_do_cursor = rasops_do_cursor;
     435           0 :         ri->ri_updatecursor = NULL;
     436             : 
     437           0 :         if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
     438           0 :                 ri->ri_ops.alloc_attr = rasops_alloc_mattr;
     439           0 :                 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
     440           0 :         } else {
     441           0 :                 ri->ri_ops.alloc_attr = rasops_alloc_cattr;
     442           0 :                 ri->ri_caps = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
     443             :                     WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
     444             :         }
     445             : 
     446           0 :         switch (ri->ri_depth) {
     447             : #if NRASOPS1 > 0
     448             :         case 1:
     449             :                 rasops1_init(ri);
     450             :                 break;
     451             : #endif
     452             : #if NRASOPS4 > 0
     453             :         case 4:
     454             :                 rasops4_init(ri);
     455             :                 break;
     456             : #endif
     457             : #if NRASOPS8 > 0
     458             :         case 8:
     459           0 :                 rasops8_init(ri);
     460           0 :                 break;
     461             : #endif
     462             : #if NRASOPS15 > 0 || NRASOPS16 > 0
     463             :         case 15:
     464             :         case 16:
     465           0 :                 rasops15_init(ri);
     466           0 :                 break;
     467             : #endif
     468             : #if NRASOPS24 > 0
     469             :         case 24:
     470           0 :                 rasops24_init(ri);
     471           0 :                 break;
     472             : #endif
     473             : #if NRASOPS32 > 0
     474             :         case 32:
     475           0 :                 rasops32_init(ri);
     476           0 :                 break;
     477             : #endif
     478             :         default:
     479           0 :                 ri->ri_flg &= ~RI_CFGDONE;
     480           0 :                 splx(s);
     481           0 :                 return (-1);
     482             :         }
     483             : 
     484             : #if NRASOPS_ROTATION > 0
     485           0 :         if (ri->ri_flg & (RI_ROTATE_CW | RI_ROTATE_CCW)) {
     486           0 :                 ri->ri_real_ops = ri->ri_ops;
     487           0 :                 ri->ri_ops.copycols = rasops_copycols_rotated;
     488           0 :                 ri->ri_ops.copyrows = rasops_copyrows_rotated;
     489           0 :                 ri->ri_ops.erasecols = rasops_erasecols_rotated;
     490           0 :                 ri->ri_ops.eraserows = rasops_eraserows_rotated;
     491           0 :                 ri->ri_ops.putchar = rasops_putchar_rotated;
     492           0 :         }
     493             : #endif
     494             : 
     495           0 :         ri->ri_flg |= RI_CFGDONE;
     496           0 :         splx(s);
     497           0 :         return (0);
     498           0 : }
     499             : 
     500             : /*
     501             :  * Map a character.
     502             :  */
     503             : int
     504           0 : rasops_mapchar(void *cookie, int c, u_int *cp)
     505             : {
     506             :         struct rasops_info *ri;
     507             : 
     508           0 :         ri = (struct rasops_info *)cookie;
     509             : 
     510             : #ifdef DIAGNOSTIC
     511           0 :         if (ri->ri_font == NULL)
     512           0 :                 panic("rasops_mapchar: no font selected");
     513             : #endif
     514           0 :         if (ri->ri_font->encoding != WSDISPLAY_FONTENC_ISO) {
     515             : 
     516           0 :                 if ( (c = wsfont_map_unichar(ri->ri_font, c)) < 0) {
     517             : 
     518           0 :                         *cp = '?';
     519           0 :                         return (0);
     520             : 
     521             :                 }
     522             :         }
     523             : 
     524             : 
     525           0 :         if (c < ri->ri_font->firstchar) {
     526           0 :                 *cp = '?';
     527           0 :                 return (0);
     528             :         }
     529             : 
     530           0 :         if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
     531           0 :                 *cp = '?';
     532           0 :                 return (0);
     533             :         }
     534             : 
     535           0 :         *cp = c;
     536           0 :         return (5);
     537           0 : }
     538             : 
     539             : /*
     540             :  * Allocate a color attribute.
     541             :  */
     542             : int
     543           0 : rasops_alloc_cattr(void *cookie, int fg, int bg, int flg, long *attr)
     544             : {
     545             :         int swap;
     546             : 
     547             : #ifdef RASOPS_CLIPPING
     548             :         fg &= 7;
     549             :         bg &= 7;
     550             : #endif
     551           0 :         if ((flg & WSATTR_BLINK) != 0)
     552           0 :                 return (EINVAL);
     553             : 
     554           0 :         if ((flg & WSATTR_WSCOLORS) == 0) {
     555             :                 fg = WS_DEFAULT_FG;
     556             :                 bg = WS_DEFAULT_BG;
     557           0 :         }
     558             : 
     559           0 :         if ((flg & WSATTR_REVERSE) != 0) {
     560             :                 swap = fg;
     561             :                 fg = bg;
     562             :                 bg = swap;
     563           0 :         }
     564             : 
     565           0 :         if ((flg & WSATTR_HILIT) != 0)
     566           0 :                 fg += 8;
     567             : 
     568           0 :         flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
     569             : 
     570           0 :         if (rasops_isgray[fg])
     571           0 :                 flg |= 2;
     572             : 
     573           0 :         if (rasops_isgray[bg])
     574           0 :                 flg |= 4;
     575             : 
     576           0 :         *attr = (bg << 16) | (fg << 24) | flg;
     577           0 :         return (0);
     578           0 : }
     579             : 
     580             : /*
     581             :  * Allocate a mono attribute.
     582             :  */
     583             : int
     584           0 : rasops_alloc_mattr(void *cookie, int fg, int bg, int flg, long *attr)
     585             : {
     586             :         int swap;
     587             : 
     588           0 :         if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
     589           0 :                 return (EINVAL);
     590             : 
     591             :         fg = 1;
     592             :         bg = 0;
     593             : 
     594           0 :         if ((flg & WSATTR_REVERSE) != 0) {
     595             :                 swap = fg;
     596             :                 fg = bg;
     597             :                 bg = swap;
     598           0 :         }
     599             : 
     600           0 :         *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
     601           0 :         return (0);
     602           0 : }
     603             : 
     604             : /*
     605             :  * Copy rows.
     606             :  */
     607             : int
     608           0 : rasops_copyrows(void *cookie, int src, int dst, int num)
     609             : {
     610             :         int32_t *sp, *dp, *srp, *drp;
     611             :         struct rasops_info *ri;
     612             :         int n8, n1, cnt, delta;
     613             : 
     614           0 :         ri = (struct rasops_info *)cookie;
     615             : 
     616             : #ifdef RASOPS_CLIPPING
     617             :         if (dst == src)
     618             :                 return 0;
     619             : 
     620             :         if (src < 0) {
     621             :                 num += src;
     622             :                 src = 0;
     623             :         }
     624             : 
     625             :         if ((src + num) > ri->ri_rows)
     626             :                 num = ri->ri_rows - src;
     627             : 
     628             :         if (dst < 0) {
     629             :                 num += dst;
     630             :                 dst = 0;
     631             :         }
     632             : 
     633             :         if ((dst + num) > ri->ri_rows)
     634             :                 num = ri->ri_rows - dst;
     635             : 
     636             :         if (num <= 0)
     637             :                 return 0;
     638             : #endif
     639             : 
     640           0 :         num *= ri->ri_font->fontheight;
     641           0 :         n8 = ri->ri_emustride >> 5;
     642           0 :         n1 = (ri->ri_emustride >> 2) & 7;
     643             : 
     644           0 :         if (dst < src) {
     645           0 :                 srp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
     646           0 :                 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
     647           0 :                 delta = ri->ri_stride;
     648           0 :         } else {
     649           0 :                 src = ri->ri_font->fontheight * src + num - 1;
     650           0 :                 dst = ri->ri_font->fontheight * dst + num - 1;
     651           0 :                 srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
     652           0 :                 drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
     653           0 :                 delta = -ri->ri_stride;
     654             :         }
     655             : 
     656           0 :         while (num--) {
     657             :                 dp = drp;
     658             :                 sp = srp;
     659           0 :                 DELTA(drp, delta, int32_t *);
     660           0 :                 DELTA(srp, delta, int32_t *);
     661             : 
     662           0 :                 for (cnt = n8; cnt; cnt--) {
     663           0 :                         dp[0] = sp[0];
     664           0 :                         dp[1] = sp[1];
     665           0 :                         dp[2] = sp[2];
     666           0 :                         dp[3] = sp[3];
     667           0 :                         dp[4] = sp[4];
     668           0 :                         dp[5] = sp[5];
     669           0 :                         dp[6] = sp[6];
     670           0 :                         dp[7] = sp[7];
     671           0 :                         dp += 8;
     672           0 :                         sp += 8;
     673             :                 }
     674             : 
     675           0 :                 for (cnt = n1; cnt; cnt--)
     676           0 :                         *dp++ = *sp++;
     677             :         }
     678             : 
     679           0 :         return 0;
     680             : }
     681             : 
     682             : /*
     683             :  * Copy columns. This is slow, and hard to optimize due to alignment,
     684             :  * and the fact that we have to copy both left->right and right->left.
     685             :  * We simply cop-out here and use either memmove() or slow_bcopy(),
     686             :  * since they handle all of these cases anyway.
     687             :  */
     688             : int
     689           0 : rasops_copycols(void *cookie, int row, int src, int dst, int num)
     690             : {
     691             :         struct rasops_info *ri;
     692             :         u_char *sp, *dp;
     693             :         int height;
     694             : 
     695           0 :         ri = (struct rasops_info *)cookie;
     696             : 
     697             : #ifdef RASOPS_CLIPPING
     698             :         if (dst == src)
     699             :                 return 0;
     700             : 
     701             :         /* Catches < 0 case too */
     702             :         if ((unsigned)row >= (unsigned)ri->ri_rows)
     703             :                 return 0;
     704             : 
     705             :         if (src < 0) {
     706             :                 num += src;
     707             :                 src = 0;
     708             :         }
     709             : 
     710             :         if ((src + num) > ri->ri_cols)
     711             :                 num = ri->ri_cols - src;
     712             : 
     713             :         if (dst < 0) {
     714             :                 num += dst;
     715             :                 dst = 0;
     716             :         }
     717             : 
     718             :         if ((dst + num) > ri->ri_cols)
     719             :                 num = ri->ri_cols - dst;
     720             : 
     721             :         if (num <= 0)
     722             :                 return 0;
     723             : #endif
     724             : 
     725           0 :         num *= ri->ri_xscale;
     726           0 :         row *= ri->ri_yscale;
     727           0 :         height = ri->ri_font->fontheight;
     728             : 
     729           0 :         sp = ri->ri_bits + row + src * ri->ri_xscale;
     730           0 :         dp = ri->ri_bits + row + dst * ri->ri_xscale;
     731             : 
     732             : #if NRASOPS_BSWAP > 0
     733             :         if (ri->ri_flg & RI_BSWAP) {
     734             :                 while (height--) {
     735             :                         slow_bcopy(sp, dp, num);
     736             :                         dp += ri->ri_stride;
     737             :                         sp += ri->ri_stride;
     738             :                 }
     739             :         } else
     740             : #endif
     741             :         {
     742           0 :                 while (height--) {
     743           0 :                         memmove(dp, sp, num);
     744           0 :                         dp += ri->ri_stride;
     745           0 :                         sp += ri->ri_stride;
     746             :                 }
     747             :         }
     748             : 
     749           0 :         return 0;
     750             : }
     751             : 
     752             : /*
     753             :  * Turn cursor off/on.
     754             :  */
     755             : int
     756           0 : rasops_cursor(void *cookie, int on, int row, int col)
     757             : {
     758             :         struct rasops_info *ri;
     759             :         int rc;
     760             : 
     761           0 :         ri = (struct rasops_info *)cookie;
     762             : 
     763             :         /* Turn old cursor off */
     764           0 :         if ((ri->ri_flg & RI_CURSOR) != 0) {
     765             : #ifdef RASOPS_CLIPPING
     766             :                 if ((ri->ri_flg & RI_CURSORCLIP) == 0)
     767             : #endif
     768           0 :                         if ((rc = ri->ri_do_cursor(ri)) != 0)
     769           0 :                                 return rc;
     770           0 :                 ri->ri_flg &= ~RI_CURSOR;
     771           0 :         }
     772             : 
     773             :         /* Select new cursor */
     774             : #ifdef RASOPS_CLIPPING
     775             :         ri->ri_flg &= ~RI_CURSORCLIP;
     776             : 
     777             :         if (row < 0 || row >= ri->ri_rows)
     778             :                 ri->ri_flg |= RI_CURSORCLIP;
     779             :         else if (col < 0 || col >= ri->ri_cols)
     780             :                 ri->ri_flg |= RI_CURSORCLIP;
     781             : #endif
     782           0 :         ri->ri_crow = row;
     783           0 :         ri->ri_ccol = col;
     784             : 
     785           0 :         if (ri->ri_updatecursor != NULL)
     786           0 :                 ri->ri_updatecursor(ri);
     787             : 
     788           0 :         if (on) {
     789             : #ifdef RASOPS_CLIPPING
     790             :                 if ((ri->ri_flg & RI_CURSORCLIP) == 0)
     791             : #endif
     792           0 :                         if ((rc = ri->ri_do_cursor(ri)) != 0)
     793           0 :                                 return rc;
     794           0 :                 ri->ri_flg |= RI_CURSOR;
     795           0 :         }
     796             : 
     797           0 :         return 0;
     798           0 : }
     799             : 
     800             : /*
     801             :  * Make the device colormap
     802             :  */
     803             : void
     804           0 : rasops_init_devcmap(struct rasops_info *ri)
     805             : {
     806             :         int i;
     807             : #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
     808             :         const u_char *p;
     809             : #endif
     810             : #if NRASOPS4 > 0 || NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
     811             :         int c;
     812             : #endif
     813             : 
     814           0 :         if (ri->ri_depth == 1 || (ri->ri_flg & RI_FORCEMONO) != 0) {
     815           0 :                 ri->ri_devcmap[0] = 0;
     816           0 :                 for (i = 1; i < 16; i++)
     817           0 :                         ri->ri_devcmap[i] = 0xffffffff;
     818           0 :                 return;
     819             :         }
     820             : 
     821           0 :         switch (ri->ri_depth) {
     822             : #if NRASOPS4 > 0
     823             :         case 4:
     824             :                 for (i = 0; i < 16; i++) {
     825             :                         c = i | (i << 4);
     826             :                         ri->ri_devcmap[i] = c | (c<<8) | (c<<16) | (c<<24);
     827             :                 }
     828             :                 return;
     829             : #endif
     830             : #if NRASOPS8 > 0
     831             :         case 8:
     832           0 :                 for (i = 0; i < 16; i++)
     833           0 :                         ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24);
     834           0 :                 return;
     835             : #endif
     836             :         default:
     837             :                 break;
     838             :         }
     839             : 
     840             : #if NRASOPS15 > 0 || NRASOPS16 > 0 || NRASOPS24 > 0 || NRASOPS32 > 0
     841             :         p = rasops_cmap;
     842             : 
     843           0 :         for (i = 0; i < 16; i++) {
     844           0 :                 if (ri->ri_rnum <= 8)
     845           0 :                         c = (*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
     846             :                 else
     847           0 :                         c = (*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
     848           0 :                 p++;
     849             : 
     850           0 :                 if (ri->ri_gnum <= 8)
     851           0 :                         c |= (*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
     852             :                 else
     853           0 :                         c |= (*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
     854           0 :                 p++;
     855             : 
     856           0 :                 if (ri->ri_bnum <= 8)
     857           0 :                         c |= (*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
     858             :                 else
     859           0 :                         c |= (*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
     860           0 :                 p++;
     861             : 
     862             :                 /* Fill the word for generic routines, which want this */
     863           0 :                 if (ri->ri_depth == 24)
     864           0 :                         c = c | ((c & 0xff) << 24);
     865           0 :                 else if (ri->ri_depth <= 16)
     866           0 :                         c = c | (c << 16);
     867             : 
     868             :                 /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
     869             : #if NRASOPS_BSWAP > 0
     870             :                 if ((ri->ri_flg & RI_BSWAP) == 0)
     871             :                         ri->ri_devcmap[i] = c;
     872             :                 else if (ri->ri_depth == 32)
     873             :                         ri->ri_devcmap[i] = swap32(c);
     874             :                 else if (ri->ri_depth == 16 || ri->ri_depth == 15)
     875             :                         ri->ri_devcmap[i] = swap16(c);
     876             :                 else
     877             :                         ri->ri_devcmap[i] = c;
     878             : #else
     879           0 :                 ri->ri_devcmap[i] = c;
     880             : #endif
     881             :         }
     882             : #endif
     883           0 : }
     884             : 
     885             : /*
     886             :  * Unpack a rasops attribute
     887             :  */
     888             : void
     889           0 : rasops_unpack_attr(void *cookie, long attr, int *fg, int *bg, int *underline)
     890             : {
     891           0 :         *fg = ((u_int)attr >> 24) & 0xf;
     892           0 :         *bg = ((u_int)attr >> 16) & 0xf;
     893           0 :         if (underline != NULL)
     894           0 :                 *underline = (u_int)attr & 1;
     895           0 : }
     896             : 
     897             : /*
     898             :  * Erase rows
     899             :  */
     900             : int
     901           0 : rasops_eraserows(void *cookie, int row, int num, long attr)
     902             : {
     903             :         struct rasops_info *ri;
     904             :         int np, nw, cnt, delta;
     905             :         int32_t *dp, clr;
     906             : 
     907           0 :         ri = (struct rasops_info *)cookie;
     908             : 
     909             : #ifdef RASOPS_CLIPPING
     910             :         if (row < 0) {
     911             :                 num += row;
     912             :                 row = 0;
     913             :         }
     914             : 
     915             :         if ((row + num) > ri->ri_rows)
     916             :                 num = ri->ri_rows - row;
     917             : 
     918             :         if (num <= 0)
     919             :                 return 0;
     920             : #endif
     921             : 
     922           0 :         clr = ri->ri_devcmap[(attr >> 16) & 0xf];
     923             : 
     924             :         /*
     925             :          * XXX The wsdisplay_emulops interface seems a little deficient in
     926             :          * that there is no way to clear the *entire* screen. We provide a
     927             :          * workaround here: if the entire console area is being cleared, and
     928             :          * the RI_FULLCLEAR flag is set, clear the entire display.
     929             :          */
     930           0 :         if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
     931           0 :                 np = ri->ri_stride >> 5;
     932           0 :                 nw = (ri->ri_stride >> 2) & 7;
     933           0 :                 num = ri->ri_height;
     934           0 :                 dp = (int32_t *)ri->ri_origbits;
     935             :                 delta = 0;
     936           0 :         } else {
     937           0 :                 np = ri->ri_emustride >> 5;
     938           0 :                 nw = (ri->ri_emustride >> 2) & 7;
     939           0 :                 num *= ri->ri_font->fontheight;
     940           0 :                 dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
     941           0 :                 delta = ri->ri_delta;
     942             :         }
     943             : 
     944           0 :         while (num--) {
     945           0 :                 for (cnt = np; cnt; cnt--) {
     946           0 :                         dp[0] = clr;
     947           0 :                         dp[1] = clr;
     948           0 :                         dp[2] = clr;
     949           0 :                         dp[3] = clr;
     950           0 :                         dp[4] = clr;
     951           0 :                         dp[5] = clr;
     952           0 :                         dp[6] = clr;
     953           0 :                         dp[7] = clr;
     954           0 :                         dp += 8;
     955             :                 }
     956             : 
     957           0 :                 for (cnt = nw; cnt; cnt--) {
     958           0 :                         *(int32_t *)dp = clr;
     959           0 :                         DELTA(dp, 4, int32_t *);
     960             :                 }
     961             : 
     962           0 :                 DELTA(dp, delta, int32_t *);
     963             :         }
     964             : 
     965           0 :         return 0;
     966             : }
     967             : 
     968             : /*
     969             :  * Actually turn the cursor on or off. This does the dirty work for
     970             :  * rasops_cursor().
     971             :  */
     972             : int
     973           0 : rasops_do_cursor(struct rasops_info *ri)
     974             : {
     975             :         int full1, height, cnt, slop1, slop2, row, col;
     976             :         u_char *dp, *rp;
     977             : 
     978             : #if NRASOPS_ROTATION > 0
     979           0 :         if (ri->ri_flg & RI_ROTATE_CW) {
     980             :                 /* Rotate rows/columns */
     981           0 :                 row = ri->ri_ccol;
     982           0 :                 col = ri->ri_rows - ri->ri_crow - 1;
     983           0 :         } else if (ri->ri_flg & RI_ROTATE_CCW) {
     984             :                 /* Rotate rows/columns */
     985           0 :                 row = ri->ri_cols - ri->ri_ccol - 1;
     986           0 :                 col = ri->ri_crow;
     987           0 :         } else          
     988             : #endif
     989             :         {
     990           0 :                 row = ri->ri_crow;
     991           0 :                 col = ri->ri_ccol;
     992             :         }
     993             : 
     994           0 :         rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
     995           0 :         height = ri->ri_font->fontheight;
     996           0 :         slop1 = (4 - ((long)rp & 3)) & 3;
     997             : 
     998           0 :         if (slop1 > ri->ri_xscale)
     999           0 :                 slop1 = ri->ri_xscale;
    1000             : 
    1001           0 :         slop2 = (ri->ri_xscale - slop1) & 3;
    1002           0 :         full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
    1003             : 
    1004           0 :         if ((slop1 | slop2) == 0) {
    1005             :                 /* A common case */
    1006           0 :                 while (height--) {
    1007             :                         dp = rp;
    1008           0 :                         rp += ri->ri_stride;
    1009             : 
    1010           0 :                         for (cnt = full1; cnt; cnt--) {
    1011           0 :                                 *(int32_t *)dp ^= ~0;
    1012           0 :                                 dp += 4;
    1013             :                         }
    1014             :                 }
    1015             :         } else {
    1016             :                 /* XXX this is stupid.. use masks instead */
    1017           0 :                 while (height--) {
    1018             :                         dp = rp;
    1019           0 :                         rp += ri->ri_stride;
    1020             : 
    1021           0 :                         if (slop1 & 1)
    1022           0 :                                 *dp++ ^= ~0;
    1023             : 
    1024           0 :                         if (slop1 & 2) {
    1025           0 :                                 *(int16_t *)dp ^= ~0;
    1026           0 :                                 dp += 2;
    1027           0 :                         }
    1028             : 
    1029           0 :                         for (cnt = full1; cnt; cnt--) {
    1030           0 :                                 *(int32_t *)dp ^= ~0;
    1031           0 :                                 dp += 4;
    1032             :                         }
    1033             : 
    1034           0 :                         if (slop2 & 1)
    1035           0 :                                 *dp++ ^= ~0;
    1036             : 
    1037           0 :                         if (slop2 & 2)
    1038           0 :                                 *(int16_t *)dp ^= ~0;
    1039             :                 }
    1040             :         }
    1041             : 
    1042           0 :         return 0;
    1043             : }
    1044             : 
    1045             : /*
    1046             :  * Erase columns.
    1047             :  */
    1048             : int
    1049           0 : rasops_erasecols(void *cookie, int row, int col, int num, long attr)
    1050             : {
    1051             :         int n8, height, cnt, slop1, slop2, clr;
    1052             :         struct rasops_info *ri;
    1053             :         int32_t *rp, *dp;
    1054             : 
    1055           0 :         ri = (struct rasops_info *)cookie;
    1056             : 
    1057             : #ifdef RASOPS_CLIPPING
    1058             :         if ((unsigned)row >= (unsigned)ri->ri_rows)
    1059             :                 return 0;
    1060             : 
    1061             :         if (col < 0) {
    1062             :                 num += col;
    1063             :                 col = 0;
    1064             :         }
    1065             : 
    1066             :         if ((col + num) > ri->ri_cols)
    1067             :                 num = ri->ri_cols - col;
    1068             : 
    1069             :         if (num <= 0)
    1070             :                 return 0;
    1071             : #endif
    1072             : 
    1073           0 :         num = num * ri->ri_xscale;
    1074           0 :         rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    1075           0 :         height = ri->ri_font->fontheight;
    1076           0 :         clr = ri->ri_devcmap[(attr >> 16) & 0xf];
    1077             : 
    1078             :         /* Don't bother using the full loop for <= 32 pels */
    1079           0 :         if (num <= 32) {
    1080           0 :                 if (((num | ri->ri_xscale) & 3) == 0) {
    1081             :                         /* Word aligned blt */
    1082           0 :                         num >>= 2;
    1083             : 
    1084           0 :                         while (height--) {
    1085             :                                 dp = rp;
    1086           0 :                                 DELTA(rp, ri->ri_stride, int32_t *);
    1087             : 
    1088           0 :                                 for (cnt = num; cnt; cnt--)
    1089           0 :                                         *dp++ = clr;
    1090             :                         }
    1091           0 :                 } else if (((num | ri->ri_xscale) & 1) == 0) {
    1092             :                         /*
    1093             :                          * Halfword aligned blt. This is needed so the
    1094             :                          * 15/16 bit ops can use this function.
    1095             :                          */
    1096           0 :                         num >>= 1;
    1097             : 
    1098           0 :                         while (height--) {
    1099             :                                 dp = rp;
    1100           0 :                                 DELTA(rp, ri->ri_stride, int32_t *);
    1101             : 
    1102           0 :                                 for (cnt = num; cnt; cnt--) {
    1103           0 :                                         *(int16_t *)dp = clr;
    1104           0 :                                         DELTA(dp, 2, int32_t *);
    1105             :                                 }
    1106             :                         }
    1107             :                 } else {
    1108           0 :                         while (height--) {
    1109             :                                 dp = rp;
    1110           0 :                                 DELTA(rp, ri->ri_stride, int32_t *);
    1111             : 
    1112           0 :                                 for (cnt = num; cnt; cnt--) {
    1113           0 :                                         *(u_char *)dp = clr;
    1114           0 :                                         DELTA(dp, 1, int32_t *);
    1115             :                                 }
    1116             :                         }
    1117             :                 }
    1118             : 
    1119           0 :                 return 0;
    1120             :         }
    1121             : 
    1122           0 :         slop1 = (4 - ((long)rp & 3)) & 3;
    1123           0 :         slop2 = (num - slop1) & 3;
    1124           0 :         num -= slop1 + slop2;
    1125           0 :         n8 = num >> 5;
    1126           0 :         num = (num >> 2) & 7;
    1127             : 
    1128           0 :         while (height--) {
    1129             :                 dp = rp;
    1130           0 :                 DELTA(rp, ri->ri_stride, int32_t *);
    1131             : 
    1132             :                 /* Align span to 4 bytes */
    1133           0 :                 if (slop1 & 1) {
    1134           0 :                         *(u_char *)dp = clr;
    1135           0 :                         DELTA(dp, 1, int32_t *);
    1136           0 :                 }
    1137             : 
    1138           0 :                 if (slop1 & 2) {
    1139           0 :                         *(int16_t *)dp = clr;
    1140           0 :                         DELTA(dp, 2, int32_t *);
    1141           0 :                 }
    1142             : 
    1143             :                 /* Write 32 bytes per loop */
    1144           0 :                 for (cnt = n8; cnt; cnt--) {
    1145           0 :                         dp[0] = clr;
    1146           0 :                         dp[1] = clr;
    1147           0 :                         dp[2] = clr;
    1148           0 :                         dp[3] = clr;
    1149           0 :                         dp[4] = clr;
    1150           0 :                         dp[5] = clr;
    1151           0 :                         dp[6] = clr;
    1152           0 :                         dp[7] = clr;
    1153           0 :                         dp += 8;
    1154             :                 }
    1155             : 
    1156             :                 /* Write 4 bytes per loop */
    1157           0 :                 for (cnt = num; cnt; cnt--)
    1158           0 :                         *dp++ = clr;
    1159             : 
    1160             :                 /* Write unaligned trailing slop */
    1161           0 :                 if (slop2 & 1) {
    1162           0 :                         *(u_char *)dp = clr;
    1163           0 :                         DELTA(dp, 1, int32_t *);
    1164           0 :                 }
    1165             : 
    1166           0 :                 if (slop2 & 2)
    1167           0 :                         *(int16_t *)dp = clr;
    1168             :         }
    1169             : 
    1170           0 :         return 0;
    1171           0 : }
    1172             : 
    1173             : #if NRASOPS_ROTATION > 0
    1174             : /*
    1175             :  * Quarter clockwise rotation routines (originally intended for the
    1176             :  * built-in Zaurus C3x00 display in 16bpp).
    1177             :  */
    1178             : 
    1179             : #include <sys/malloc.h>
    1180             : 
    1181             : void
    1182           0 : rasops_rotate_font(int *cookie, int ccw)
    1183             : {
    1184             :         struct rotatedfont *f;
    1185             :         int ncookie;
    1186             : 
    1187           0 :         SLIST_FOREACH(f, &rotatedfonts, rf_next) {
    1188           0 :                 if (f->rf_cookie == *cookie) {
    1189           0 :                         *cookie = f->rf_rotated;
    1190           0 :                         return;
    1191             :                 }
    1192             :         }
    1193             : 
    1194             :         /*
    1195             :          * We did not find a rotated version of this font. Ask the wsfont
    1196             :          * code to compute one for us.
    1197             :          */
    1198           0 :         if ((ncookie = wsfont_rotate(*cookie, ccw)) == -1)
    1199           0 :                 return;
    1200             : 
    1201           0 :         f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK);
    1202           0 :         f->rf_cookie = *cookie;
    1203           0 :         f->rf_rotated = ncookie;
    1204           0 :         SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
    1205             : 
    1206           0 :         *cookie = ncookie;
    1207           0 : }
    1208             : 
    1209             : void
    1210           0 : rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
    1211             : {
    1212             :         struct rasops_info *ri;
    1213             :         u_char *sp, *dp;
    1214             :         int height;
    1215             :         int r_srcrow, r_dstrow, r_srccol, r_dstcol;
    1216             : 
    1217           0 :         ri = (struct rasops_info *)cookie;
    1218             : 
    1219             :         r_srcrow = srccol;
    1220             :         r_dstrow = dstcol;
    1221           0 :         r_srccol = ri->ri_rows - srcrow - 1;
    1222           0 :         r_dstcol = ri->ri_rows - dstrow - 1;
    1223             : 
    1224           0 :         r_srcrow *= ri->ri_yscale;
    1225           0 :         r_dstrow *= ri->ri_yscale;
    1226           0 :         height = ri->ri_font->fontheight;
    1227             : 
    1228           0 :         sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
    1229           0 :         dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
    1230             : 
    1231             : #if NRASOPS_BSWAP > 0
    1232             :         if (ri->ri_flg & RI_BSWAP) {
    1233             :                 while (height--) {
    1234             :                         slow_bcopy(sp, dp, ri->ri_xscale);
    1235             :                         dp += ri->ri_stride;
    1236             :                         sp += ri->ri_stride;
    1237             :                 }
    1238             :         } else
    1239             : #endif
    1240             :         {
    1241           0 :                 while (height--) {
    1242           0 :                         memmove(dp, sp, ri->ri_xscale);
    1243           0 :                         dp += ri->ri_stride;
    1244           0 :                         sp += ri->ri_stride;
    1245             :                 }
    1246             :         }
    1247           0 : }
    1248             : 
    1249             : int
    1250           0 : rasops_putchar_rotated(void *cookie, int row, int col, u_int uc, long attr)
    1251             : {
    1252             :         struct rasops_info *ri;
    1253             :         u_char *rp;
    1254             :         int height;
    1255             :         int rc;
    1256             : 
    1257           0 :         ri = (struct rasops_info *)cookie;
    1258             : 
    1259           0 :         if (ri->ri_flg & RI_ROTATE_CW)
    1260           0 :                 row = ri->ri_rows - row - 1;
    1261             :         else
    1262           0 :                 col = ri->ri_cols - col - 1;
    1263             : 
    1264             :         /* Do rotated char sans (side)underline */
    1265           0 :         rc = ri->ri_real_ops.putchar(cookie, col, row, uc, attr & ~1);
    1266           0 :         if (rc != 0)
    1267           0 :                 return rc;
    1268             : 
    1269             :         /* Do rotated underline */
    1270           0 :         rp = ri->ri_bits + col * ri->ri_yscale + row * ri->ri_xscale;
    1271           0 :         if (ri->ri_flg & RI_ROTATE_CCW)
    1272           0 :                 rp += (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
    1273           0 :         height = ri->ri_font->fontheight;
    1274             : 
    1275             :         /* XXX this assumes 16-bit color depth */
    1276           0 :         if ((attr & 1) != 0) {
    1277           0 :                 int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
    1278             : 
    1279           0 :                 while (height--) {
    1280           0 :                         *(int16_t *)rp = c;
    1281           0 :                         rp += ri->ri_stride;
    1282             :                 }
    1283           0 :         }
    1284             : 
    1285           0 :         return 0;
    1286           0 : }
    1287             : 
    1288             : int
    1289           0 : rasops_erasecols_rotated(void *cookie, int row, int col, int num, long attr)
    1290             : {
    1291             :         int i;
    1292             :         int rc;
    1293             : 
    1294           0 :         for (i = col; i < col + num; i++) {
    1295           0 :                 rc = rasops_putchar_rotated(cookie, row, i, ' ', attr);
    1296           0 :                 if (rc != 0)
    1297           0 :                         return rc;
    1298             :         }
    1299             : 
    1300           0 :         return 0;
    1301           0 : }
    1302             : 
    1303             : /* XXX: these could likely be optimised somewhat. */
    1304             : int
    1305           0 : rasops_copyrows_rotated(void *cookie, int src, int dst, int num)
    1306             : {
    1307           0 :         struct rasops_info *ri = (struct rasops_info *)cookie;
    1308             :         int col, roff;
    1309             : 
    1310           0 :         if (src > dst) {
    1311           0 :                 for (roff = 0; roff < num; roff++)
    1312           0 :                         for (col = 0; col < ri->ri_cols; col++)
    1313           0 :                                 rasops_copychar(cookie, src + roff, dst + roff,
    1314             :                                     col, col);
    1315             :         } else {
    1316           0 :                 for (roff = num - 1; roff >= 0; roff--)
    1317           0 :                         for (col = 0; col < ri->ri_cols; col++)
    1318           0 :                                 rasops_copychar(cookie, src + roff, dst + roff,
    1319             :                                     col, col);
    1320             :         }
    1321             : 
    1322           0 :         return 0;
    1323             : }
    1324             : 
    1325             : int
    1326           0 : rasops_copycols_rotated(void *cookie, int row, int src, int dst, int num)
    1327             : {
    1328             :         int coff;
    1329             : 
    1330           0 :         if (src > dst) {
    1331           0 :                 for (coff = 0; coff < num; coff++)
    1332           0 :                         rasops_copychar(cookie, row, row, src + coff,
    1333           0 :                             dst + coff);
    1334             :         } else {
    1335           0 :                 for (coff = num - 1; coff >= 0; coff--)
    1336           0 :                         rasops_copychar(cookie, row, row, src + coff,
    1337           0 :                             dst + coff);
    1338             :         }
    1339             : 
    1340           0 :         return 0;
    1341             : }
    1342             : 
    1343             : int
    1344           0 : rasops_eraserows_rotated(void *cookie, int row, int num, long attr)
    1345             : {
    1346             :         struct rasops_info *ri;
    1347             :         int col, rn;
    1348             :         int rc;
    1349             : 
    1350           0 :         ri = (struct rasops_info *)cookie;
    1351             : 
    1352           0 :         for (rn = row; rn < row + num; rn++)
    1353           0 :                 for (col = 0; col < ri->ri_cols; col++) {
    1354           0 :                         rc = rasops_putchar_rotated(cookie, rn, col, ' ', attr);
    1355           0 :                         if (rc != 0)
    1356           0 :                                 return rc;
    1357             :                 }
    1358             : 
    1359           0 :         return 0;
    1360           0 : }
    1361             : #endif  /* NRASOPS_ROTATION */
    1362             : 
    1363             : #if NRASOPS_BSWAP > 0
    1364             : /*
    1365             :  * Strictly byte-only bcopy() version, to be used with RI_BSWAP, as the
    1366             :  * regular bcopy() may want to optimize things by doing larger-than-byte
    1367             :  * reads or write. This may confuse things if src and dst have different
    1368             :  * alignments.
    1369             :  */
    1370             : void
    1371             : slow_bcopy(void *s, void *d, size_t len)
    1372             : {
    1373             :         u_int8_t *src = s;
    1374             :         u_int8_t *dst = d;
    1375             : 
    1376             :         if ((vaddr_t)dst <= (vaddr_t)src) {
    1377             :                 while (len-- != 0)
    1378             :                         *dst++ = *src++;
    1379             :         } else {
    1380             :                 src += len;
    1381             :                 dst += len;
    1382             :                 if (len != 0)
    1383             :                         while (--len != 0)
    1384             :                                 *--dst = *--src;
    1385             :         }
    1386             : }
    1387             : #endif  /* NRASOPS_BSWAP */
    1388             : 
    1389             : int
    1390           0 : rasops_alloc_screen(void *v, void **cookiep,
    1391             :     int *curxp, int *curyp, long *attrp)
    1392             : {
    1393           0 :         struct rasops_info *ri = v;
    1394             :         struct rasops_screen *scr;
    1395             :         int i;
    1396             : 
    1397           0 :         scr = malloc(sizeof(*scr), M_DEVBUF, M_NOWAIT);
    1398           0 :         if (scr == NULL)
    1399           0 :                 return (ENOMEM);
    1400             : 
    1401           0 :         scr->rs_sbscreens = RS_SCROLLBACK_SCREENS;
    1402           0 :         scr->rs_bs = mallocarray(ri->ri_rows * (scr->rs_sbscreens + 1),
    1403           0 :             ri->ri_cols * sizeof(struct wsdisplay_charcell), M_DEVBUF,
    1404             :             M_NOWAIT);
    1405           0 :         if (scr->rs_bs == NULL) {
    1406           0 :                 free(scr, M_DEVBUF, sizeof(*scr));
    1407           0 :                 return (ENOMEM);
    1408             :         }
    1409           0 :         scr->rs_visibleoffset = scr->rs_dispoffset = ri->ri_rows *
    1410           0 :             scr->rs_sbscreens * ri->ri_cols;
    1411             : 
    1412           0 :         *cookiep = scr;
    1413           0 :         *curxp = 0;
    1414           0 :         *curyp = 0;
    1415           0 :         ri->ri_alloc_attr(ri, 0, 0, 0, attrp);
    1416             : 
    1417           0 :         scr->rs_ri = ri;
    1418           0 :         scr->rs_visible = (ri->ri_nscreens == 0);
    1419           0 :         scr->rs_crow = -1;
    1420           0 :         scr->rs_ccol = -1;
    1421           0 :         scr->rs_defattr = *attrp;
    1422             : 
    1423           0 :         for (i = 0; i < scr->rs_dispoffset; i++) {
    1424           0 :                 scr->rs_bs[i].uc = ' ';
    1425           0 :                 scr->rs_bs[i].attr = scr->rs_defattr;
    1426             :         }
    1427             : 
    1428           0 :         if (ri->ri_bs && scr->rs_visible) {
    1429           0 :                 memcpy(scr->rs_bs + scr->rs_dispoffset, ri->ri_bs,
    1430             :                     ri->ri_rows * ri->ri_cols *
    1431             :                     sizeof(struct wsdisplay_charcell));
    1432           0 :         } else {
    1433           0 :                 for (i = 0; i < ri->ri_rows * ri->ri_cols; i++) {
    1434           0 :                         scr->rs_bs[scr->rs_dispoffset + i].uc = ' ';
    1435           0 :                         scr->rs_bs[scr->rs_dispoffset + i].attr =
    1436           0 :                             scr->rs_defattr;
    1437             :                 }
    1438             :         }
    1439             : 
    1440           0 :         LIST_INSERT_HEAD(&ri->ri_screens, scr, rs_next);
    1441           0 :         ri->ri_nscreens++;
    1442             : 
    1443           0 :         return (0);
    1444           0 : }
    1445             : 
    1446             : void
    1447           0 : rasops_free_screen(void *v, void *cookie)
    1448             : {
    1449           0 :         struct rasops_info *ri = v;
    1450           0 :         struct rasops_screen *scr = cookie;
    1451             : 
    1452           0 :         LIST_REMOVE(scr, rs_next);
    1453           0 :         ri->ri_nscreens--;
    1454             : 
    1455           0 :         free(scr->rs_bs, M_DEVBUF,
    1456           0 :             ri->ri_rows * (scr->rs_sbscreens + 1) * ri->ri_cols *
    1457             :             sizeof(struct wsdisplay_charcell));
    1458           0 :         free(scr, M_DEVBUF, sizeof(*scr));
    1459           0 : }
    1460             : 
    1461             : int
    1462           0 : rasops_show_screen(void *v, void *cookie, int waitok,
    1463             :     void (*cb)(void *, int, int), void *cbarg)
    1464             : {
    1465           0 :         struct rasops_info *ri = v;
    1466             : 
    1467           0 :         ri->ri_switchcookie = cookie;
    1468           0 :         if (cb) {
    1469           0 :                 ri->ri_switchcb = cb;
    1470           0 :                 ri->ri_switchcbarg = cbarg;
    1471           0 :                 task_add(systq, &ri->ri_switchtask);
    1472           0 :                 return (EAGAIN);
    1473             :         }
    1474             : 
    1475           0 :         rasops_doswitch(ri);
    1476           0 :         return (0);
    1477           0 : }
    1478             : 
    1479             : void
    1480           0 : rasops_doswitch(void *v)
    1481             : {
    1482           0 :         struct rasops_info *ri = v;
    1483           0 :         struct rasops_screen *scr = ri->ri_switchcookie;
    1484             :         int row, col;
    1485             : 
    1486           0 :         rasops_cursor(ri, 0, 0, 0);
    1487           0 :         ri->ri_active->rs_visible = 0;
    1488           0 :         ri->ri_eraserows(ri, 0, ri->ri_rows, scr->rs_defattr);
    1489           0 :         ri->ri_active = scr;
    1490           0 :         ri->ri_bs = &ri->ri_active->rs_bs[ri->ri_active->rs_dispoffset];
    1491           0 :         ri->ri_active->rs_visible = 1;
    1492           0 :         ri->ri_active->rs_visibleoffset = ri->ri_active->rs_dispoffset;
    1493           0 :         for (row = 0; row < ri->ri_rows; row++) {
    1494           0 :                 for (col = 0; col < ri->ri_cols; col++) {
    1495           0 :                         int off = row * scr->rs_ri->ri_cols + col +
    1496           0 :                             scr->rs_visibleoffset;
    1497             : 
    1498           0 :                         ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
    1499           0 :                             scr->rs_bs[off].attr);
    1500             :                 }
    1501             :         }
    1502           0 :         if (scr->rs_crow != -1)
    1503           0 :                 rasops_cursor(ri, 1, scr->rs_crow, scr->rs_ccol);
    1504             : 
    1505           0 :         if (ri->ri_switchcb)
    1506           0 :                 (*ri->ri_switchcb)(ri->ri_switchcbarg, 0, 0);
    1507           0 : }
    1508             : 
    1509             : int
    1510           0 : rasops_getchar(void *v, int row, int col, struct wsdisplay_charcell *cell)
    1511             : {
    1512           0 :         struct rasops_info *ri = v;
    1513           0 :         struct rasops_screen *scr = ri->ri_active;
    1514             : 
    1515           0 :         if (scr == NULL || scr->rs_bs == NULL)
    1516           0 :                 return (1);
    1517             : 
    1518           0 :         *cell = scr->rs_bs[row * ri->ri_cols + col + scr->rs_dispoffset];
    1519           0 :         return (0);
    1520           0 : }
    1521             : 
    1522             : int
    1523           0 : rasops_vcons_cursor(void *cookie, int on, int row, int col)
    1524             : {
    1525           0 :         struct rasops_screen *scr = cookie;
    1526             : 
    1527           0 :         scr->rs_crow = on ? row : -1;
    1528           0 :         scr->rs_ccol = on ? col : -1;
    1529             : 
    1530           0 :         if (!scr->rs_visible)
    1531           0 :                 return 0;
    1532             : 
    1533           0 :         return rasops_cursor(scr->rs_ri, on, row, col);
    1534           0 : }
    1535             : 
    1536             : int
    1537           0 : rasops_vcons_mapchar(void *cookie, int c, u_int *cp)
    1538             : {
    1539           0 :         struct rasops_screen *scr = cookie;
    1540             : 
    1541           0 :         return rasops_mapchar(scr->rs_ri, c, cp);
    1542             : }
    1543             : 
    1544             : int
    1545           0 : rasops_vcons_putchar(void *cookie, int row, int col, u_int uc, long attr)
    1546             : {
    1547           0 :         struct rasops_screen *scr = cookie;
    1548           0 :         int off = row * scr->rs_ri->ri_cols + col + scr->rs_dispoffset;
    1549             : 
    1550           0 :         if (scr->rs_visible && scr->rs_visibleoffset != scr->rs_dispoffset)
    1551           0 :                 rasops_scrollback(scr->rs_ri, scr, 0);
    1552             : 
    1553           0 :         scr->rs_bs[off].uc = uc;
    1554           0 :         scr->rs_bs[off].attr = attr;
    1555             : 
    1556           0 :         if (!scr->rs_visible)
    1557           0 :                 return 0;
    1558             : 
    1559           0 :         return scr->rs_ri->ri_putchar(scr->rs_ri, row, col, uc, attr);
    1560           0 : }
    1561             : 
    1562             : int
    1563           0 : rasops_vcons_copycols(void *cookie, int row, int src, int dst, int num)
    1564             : {
    1565           0 :         struct rasops_screen *scr = cookie;
    1566           0 :         struct rasops_info *ri = scr->rs_ri;
    1567           0 :         int cols = scr->rs_ri->ri_cols;
    1568             :         int col, rc;
    1569             : 
    1570           0 :         memmove(&scr->rs_bs[row * cols + dst + scr->rs_dispoffset],
    1571             :             &scr->rs_bs[row * cols + src + scr->rs_dispoffset],
    1572             :             num * sizeof(struct wsdisplay_charcell));
    1573             : 
    1574           0 :         if (!scr->rs_visible)
    1575           0 :                 return 0;
    1576             : 
    1577           0 :         if ((ri->ri_flg & RI_WRONLY) == 0)
    1578           0 :                 return ri->ri_copycols(ri, row, src, dst, num);
    1579             : 
    1580           0 :         for (col = dst; col < dst + num; col++) {
    1581           0 :                 int off = row * cols + col + scr->rs_dispoffset;
    1582             : 
    1583           0 :                 rc = ri->ri_putchar(ri, row, col,
    1584           0 :                     scr->rs_bs[off].uc, scr->rs_bs[off].attr);
    1585           0 :                 if (rc != 0)
    1586           0 :                         return rc;
    1587           0 :         }
    1588             : 
    1589           0 :         return 0;
    1590           0 : }
    1591             : 
    1592             : int
    1593           0 : rasops_vcons_erasecols(void *cookie, int row, int col, int num, long attr)
    1594             : {
    1595           0 :         struct rasops_screen *scr = cookie;
    1596           0 :         int cols = scr->rs_ri->ri_cols;
    1597             :         int i;
    1598             : 
    1599           0 :         for (i = 0; i < num; i++) {
    1600           0 :                 int off = row * cols + col + i + scr->rs_dispoffset;
    1601             : 
    1602           0 :                 scr->rs_bs[off].uc = ' ';
    1603           0 :                 scr->rs_bs[off].attr = attr;
    1604             :         }
    1605             : 
    1606           0 :         if (!scr->rs_visible)
    1607           0 :                 return 0;
    1608             : 
    1609           0 :         return scr->rs_ri->ri_erasecols(scr->rs_ri, row, col, num, attr);
    1610           0 : }
    1611             : 
    1612             : int
    1613           0 : rasops_vcons_copyrows(void *cookie, int src, int dst, int num)
    1614             : {
    1615           0 :         struct rasops_screen *scr = cookie;
    1616           0 :         struct rasops_info *ri = scr->rs_ri;
    1617           0 :         int cols = ri->ri_cols;
    1618             :         int row, col, rc;
    1619             : 
    1620           0 :         if (dst == 0 && (src + num == ri->ri_rows) && scr->rs_sbscreens > 0)
    1621           0 :                 memmove(&scr->rs_bs[dst], &scr->rs_bs[src * cols],
    1622             :                     ((ri->ri_rows * (scr->rs_sbscreens + 1) * cols) -
    1623             :                     (src * cols)) * sizeof(struct wsdisplay_charcell));
    1624             :         else
    1625           0 :                 memmove(&scr->rs_bs[dst * cols + scr->rs_dispoffset],
    1626             :                     &scr->rs_bs[src * cols + scr->rs_dispoffset],
    1627             :                     num * cols * sizeof(struct wsdisplay_charcell));
    1628             : 
    1629           0 :         if (!scr->rs_visible)
    1630           0 :                 return 0;
    1631             : 
    1632           0 :         if ((ri->ri_flg & RI_WRONLY) == 0)
    1633           0 :                 return ri->ri_copyrows(ri, src, dst, num);
    1634             : 
    1635           0 :         for (row = dst; row < dst + num; row++) {
    1636           0 :                 for (col = 0; col < cols; col++) {
    1637           0 :                         int off = row * cols + col + scr->rs_dispoffset;
    1638             : 
    1639           0 :                         rc = ri->ri_putchar(ri, row, col,
    1640           0 :                             scr->rs_bs[off].uc, scr->rs_bs[off].attr);
    1641           0 :                         if (rc != 0)
    1642           0 :                                 return rc;
    1643           0 :                 }
    1644             :         }
    1645             : 
    1646           0 :         return 0;
    1647           0 : }
    1648             : 
    1649             : int
    1650           0 : rasops_vcons_eraserows(void *cookie, int row, int num, long attr)
    1651             : {
    1652           0 :         struct rasops_screen *scr = cookie;
    1653           0 :         int cols = scr->rs_ri->ri_cols;
    1654             :         int i;
    1655             : 
    1656           0 :         for (i = 0; i < num * cols; i++) {
    1657           0 :                 int off = row * cols + i + scr->rs_dispoffset;
    1658             : 
    1659           0 :                 scr->rs_bs[off].uc = ' ';
    1660           0 :                 scr->rs_bs[off].attr = attr;
    1661             :         }
    1662             : 
    1663           0 :         if (!scr->rs_visible)
    1664           0 :                 return 0;
    1665             : 
    1666           0 :         return scr->rs_ri->ri_eraserows(scr->rs_ri, row, num, attr);
    1667           0 : }
    1668             : 
    1669             : int
    1670           0 : rasops_vcons_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
    1671             : {
    1672           0 :         struct rasops_screen *scr = cookie;
    1673             : 
    1674           0 :         return scr->rs_ri->ri_alloc_attr(scr->rs_ri, fg, bg, flg, attr);
    1675             : }
    1676             : 
    1677             : void
    1678           0 : rasops_vcons_unpack_attr(void *cookie, long attr, int *fg, int *bg,
    1679             :     int *underline)
    1680             : {
    1681           0 :         struct rasops_screen *scr = cookie;
    1682             : 
    1683           0 :         rasops_unpack_attr(scr->rs_ri, attr, fg, bg, underline);
    1684           0 : }
    1685             : 
    1686             : int
    1687           0 : rasops_wronly_putchar(void *cookie, int row, int col, u_int uc, long attr)
    1688             : {
    1689           0 :         struct rasops_info *ri = cookie;
    1690           0 :         int off = row * ri->ri_cols + col;
    1691             : 
    1692           0 :         ri->ri_bs[off].uc = uc;
    1693           0 :         ri->ri_bs[off].attr = attr;
    1694             : 
    1695           0 :         return ri->ri_putchar(ri, row, col, uc, attr);
    1696             : }
    1697             : 
    1698             : int
    1699           0 : rasops_wronly_copycols(void *cookie, int row, int src, int dst, int num)
    1700             : {
    1701           0 :         struct rasops_info *ri = cookie;
    1702           0 :         int cols = ri->ri_cols;
    1703             :         int col, rc;
    1704             : 
    1705           0 :         memmove(&ri->ri_bs[row * cols + dst], &ri->ri_bs[row * cols + src],
    1706             :             num * sizeof(struct wsdisplay_charcell));
    1707             : 
    1708           0 :         for (col = dst; col < dst + num; col++) {
    1709           0 :                 int off = row * cols + col;
    1710             : 
    1711           0 :                 rc = ri->ri_putchar(ri, row, col,
    1712           0 :                     ri->ri_bs[off].uc, ri->ri_bs[off].attr);
    1713           0 :                 if (rc != 0)
    1714           0 :                         return rc;
    1715           0 :         }
    1716             : 
    1717           0 :         return 0;
    1718           0 : }
    1719             : 
    1720             : int
    1721           0 : rasops_wronly_erasecols(void *cookie, int row, int col, int num, long attr)
    1722             : {
    1723           0 :         struct rasops_info *ri = cookie;
    1724           0 :         int cols = ri->ri_cols;
    1725             :         int i;
    1726             : 
    1727           0 :         for (i = 0; i < num; i++) {
    1728           0 :                 int off = row * cols + col + i;
    1729             : 
    1730           0 :                 ri->ri_bs[off].uc = ' ';
    1731           0 :                 ri->ri_bs[off].attr = attr;
    1732             :         }
    1733             : 
    1734           0 :         return ri->ri_erasecols(ri, row, col, num, attr);
    1735             : }
    1736             : 
    1737             : int
    1738           0 : rasops_wronly_copyrows(void *cookie, int src, int dst, int num)
    1739             : {
    1740           0 :         struct rasops_info *ri = cookie;
    1741           0 :         int cols = ri->ri_cols;
    1742             :         int row, col, rc;
    1743             : 
    1744           0 :         memmove(&ri->ri_bs[dst * cols], &ri->ri_bs[src * cols],
    1745             :             num * cols * sizeof(struct wsdisplay_charcell));
    1746             : 
    1747           0 :         for (row = dst; row < dst + num; row++) {
    1748           0 :                 for (col = 0; col < cols; col++) {
    1749           0 :                         int off = row * cols + col;
    1750             : 
    1751           0 :                         rc = ri->ri_putchar(ri, row, col,
    1752           0 :                             ri->ri_bs[off].uc, ri->ri_bs[off].attr);
    1753           0 :                         if (rc != 0)
    1754           0 :                                 return rc;
    1755           0 :                 }
    1756             :         }
    1757             : 
    1758           0 :         return 0;
    1759           0 : }
    1760             : 
    1761             : int
    1762           0 : rasops_wronly_eraserows(void *cookie, int row, int num, long attr)
    1763             : {
    1764           0 :         struct rasops_info *ri = cookie;
    1765           0 :         int cols = ri->ri_cols;
    1766             :         int i;
    1767             : 
    1768           0 :         for (i = 0; i < num * cols; i++) {
    1769           0 :                 int off = row * cols + i;
    1770             : 
    1771           0 :                 ri->ri_bs[off].uc = ' ';
    1772           0 :                 ri->ri_bs[off].attr = attr;
    1773             :         }
    1774             : 
    1775           0 :         return ri->ri_eraserows(ri, row, num, attr);
    1776             : }
    1777             : 
    1778             : int
    1779           0 : rasops_wronly_do_cursor(struct rasops_info *ri)
    1780             : {
    1781           0 :         int off = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
    1782             :         u_int uc;
    1783             :         long attr;
    1784             :         int fg, bg;
    1785             : 
    1786           0 :         uc = ri->ri_bs[off].uc;
    1787           0 :         attr = ri->ri_bs[off].attr;
    1788             : 
    1789           0 :         if ((ri->ri_flg & RI_CURSOR) == 0) {
    1790           0 :                 fg = ((u_int)attr >> 24) & 0xf;
    1791           0 :                 bg = ((u_int)attr >> 16) & 0xf;
    1792           0 :                 attr &= ~0x0ffff0000;
    1793           0 :                 attr |= (fg << 16) | (bg << 24);
    1794           0 :         }
    1795             : 
    1796           0 :         return ri->ri_putchar(ri, ri->ri_crow, ri->ri_ccol, uc, attr);
    1797             : }
    1798             : 
    1799             : /*
    1800             :  * Font management.
    1801             :  *
    1802             :  * Fonts usable on raster frame buffers are managed by wsfont, and are not
    1803             :  * tied to any particular display.
    1804             :  */
    1805             : 
    1806             : int
    1807           0 : rasops_add_font(struct rasops_info *ri, struct wsdisplay_font *font)
    1808             : {
    1809             :         /* only accept matching metrics */
    1810           0 :         if (font->fontwidth != ri->ri_font->fontwidth ||
    1811           0 :             font->fontheight != ri->ri_font->fontheight)
    1812           0 :                 return EINVAL;
    1813             : 
    1814             :         /* for raster consoles, only accept ISO Latin-1 or Unicode encoding */
    1815           0 :         if (font->encoding != WSDISPLAY_FONTENC_ISO)
    1816           0 :                 return EINVAL;
    1817             : 
    1818           0 :         if (wsfont_add(font, 1) != 0)
    1819           0 :                 return EEXIST;  /* name collision */
    1820             : 
    1821           0 :         font->index = -1;    /* do not store in wsdisplay_softc */
    1822             : 
    1823           0 :         return 0;
    1824           0 : }
    1825             : 
    1826             : int
    1827           0 : rasops_use_font(struct rasops_info *ri, struct wsdisplay_font *font)
    1828             : {
    1829             :         int wsfcookie;
    1830           0 :         struct wsdisplay_font *wsf;
    1831             :         const char *name;
    1832             : 
    1833             :         /* allow an empty font name to revert to the initial font choice */
    1834           0 :         name = font->name;
    1835           0 :         if (*name == '\0')
    1836             :                 name = NULL;
    1837             : 
    1838           0 :         wsfcookie = wsfont_find(name, ri->ri_font->fontwidth,
    1839           0 :             ri->ri_font->fontheight, 0);
    1840           0 :         if (wsfcookie < 0) {
    1841           0 :                 wsfcookie = wsfont_find(name, 0, 0, 0);
    1842           0 :                 if (wsfcookie < 0)
    1843           0 :                         return ENOENT;  /* font exist, but different metrics */
    1844             :                 else
    1845           0 :                         return EINVAL;
    1846             :         }
    1847           0 :         if (wsfont_lock(wsfcookie, &wsf, WSDISPLAY_FONTORDER_KNOWN,
    1848           0 :             WSDISPLAY_FONTORDER_KNOWN) < 0)
    1849           0 :                 return EINVAL;
    1850             : 
    1851             :         /* if (ri->ri_wsfcookie >= 0) */
    1852           0 :                 wsfont_unlock(ri->ri_wsfcookie);
    1853           0 :         ri->ri_wsfcookie = wsfcookie;
    1854           0 :         ri->ri_font = wsf;
    1855           0 :         ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
    1856             : 
    1857           0 :         return 0;
    1858           0 : }
    1859             : 
    1860             : int
    1861           0 : rasops_load_font(void *v, void *cookie, struct wsdisplay_font *font)
    1862             : {
    1863           0 :         struct rasops_info *ri = v;
    1864             : 
    1865             :         /*
    1866             :          * For now, we want to only allow loading fonts of the same
    1867             :          * metrics as the currently in-use font. This requires the
    1868             :          * rasops struct to have been correctly configured, and a
    1869             :          * font to have been selected.
    1870             :          */
    1871           0 :         if ((ri->ri_flg & RI_CFGDONE) == 0 || ri->ri_font == NULL)
    1872           0 :                 return EINVAL;
    1873             : 
    1874           0 :         if (font->data != NULL)
    1875           0 :                 return rasops_add_font(ri, font);
    1876             :         else
    1877           0 :                 return rasops_use_font(ri, font);
    1878           0 : }
    1879             : 
    1880             : struct rasops_list_font_ctx {
    1881             :         struct rasops_info *ri;
    1882             :         int cnt;
    1883             :         struct wsdisplay_font *font;
    1884             : };
    1885             : 
    1886             : int
    1887           0 : rasops_list_font_cb(void *cbarg, struct wsdisplay_font *font)
    1888             : {
    1889           0 :         struct rasops_list_font_ctx *ctx = cbarg;
    1890             : 
    1891           0 :         if (font->fontheight != ctx->ri->ri_font->fontheight ||
    1892           0 :             font->fontwidth != ctx->ri->ri_font->fontwidth)
    1893           0 :                 return 0;
    1894             : 
    1895           0 :         if (ctx->cnt-- == 0) {
    1896           0 :                 ctx->font = font;
    1897           0 :                 return 1;
    1898             :         }
    1899             : 
    1900           0 :         return 0;
    1901           0 : }
    1902             : 
    1903             : int
    1904           0 : rasops_list_font(void *v, struct wsdisplay_font *font)
    1905             : {
    1906           0 :         struct rasops_info *ri = v;
    1907           0 :         struct rasops_list_font_ctx ctx;
    1908             :         int idx;
    1909             : 
    1910           0 :         if ((ri->ri_flg & RI_CFGDONE) == 0 || ri->ri_font == NULL)
    1911           0 :                 return EINVAL;
    1912             : 
    1913           0 :         if (font->index < 0)
    1914           0 :                 return EINVAL;
    1915             : 
    1916           0 :         ctx.ri = ri;
    1917           0 :         ctx.cnt = font->index;
    1918           0 :         ctx.font = NULL;
    1919           0 :         wsfont_enum(rasops_list_font_cb, &ctx);
    1920             : 
    1921           0 :         if (ctx.font == NULL)
    1922           0 :                 return EINVAL;
    1923             : 
    1924           0 :         idx = font->index;
    1925           0 :         *font = *ctx.font;      /* struct copy */
    1926           0 :         font->index = idx;
    1927           0 :         font->cookie = font->data = NULL; /* don't leak kernel pointers */
    1928           0 :         return 0;
    1929           0 : }
    1930             : 
    1931             : void
    1932           0 : rasops_scrollback(void *v, void *cookie, int lines)
    1933             : {
    1934           0 :         struct rasops_info *ri = v;
    1935           0 :         struct rasops_screen *scr = cookie;
    1936             :         int row, col, oldvoff;
    1937             : 
    1938           0 :         oldvoff = scr->rs_visibleoffset;
    1939             : 
    1940           0 :         if (lines == 0)
    1941           0 :                 scr->rs_visibleoffset = scr->rs_dispoffset;
    1942             :         else {
    1943           0 :                 int off = scr->rs_visibleoffset + (lines * ri->ri_cols);
    1944             : 
    1945           0 :                 if (off < 0)
    1946           0 :                         off = 0;
    1947           0 :                 else if (off > scr->rs_dispoffset)
    1948           0 :                         off = scr->rs_dispoffset;
    1949             : 
    1950           0 :                 scr->rs_visibleoffset = off;
    1951             :         }
    1952             : 
    1953           0 :         if (scr->rs_visibleoffset == oldvoff)
    1954           0 :                 return;
    1955             : 
    1956           0 :         rasops_cursor(ri, 0, 0, 0);
    1957           0 :         ri->ri_eraserows(ri, 0, ri->ri_rows, scr->rs_defattr);
    1958           0 :         for (row = 0; row < ri->ri_rows; row++) {
    1959           0 :                 for (col = 0; col < ri->ri_cols; col++) {
    1960           0 :                         int off = row * scr->rs_ri->ri_cols + col +
    1961           0 :                             scr->rs_visibleoffset;
    1962             : 
    1963           0 :                         ri->ri_putchar(ri, row, col, scr->rs_bs[off].uc,
    1964           0 :                             scr->rs_bs[off].attr);
    1965             :                 }
    1966             :         }
    1967             : 
    1968           0 :         if (scr->rs_crow != -1 && scr->rs_visibleoffset == scr->rs_dispoffset)
    1969           0 :                 rasops_cursor(ri, 1, scr->rs_crow, scr->rs_ccol);
    1970           0 : }
    1971             : 
    1972             : struct rasops_framebuffer {
    1973             :         SLIST_ENTRY(rasops_framebuffer) rf_list;
    1974             :         paddr_t         rf_base;
    1975             :         psize_t         rf_size;
    1976             :         struct device   *rf_dev;
    1977             : };
    1978             : 
    1979             : SLIST_HEAD(, rasops_framebuffer) rasops_framebuffers =
    1980             :     SLIST_HEAD_INITIALIZER(&rasops_framebuffers);
    1981             : 
    1982             : void
    1983           0 : rasops_claim_framebuffer(paddr_t base, psize_t size, struct device *dev)
    1984             : {
    1985             :         struct rasops_framebuffer *rf;
    1986             : 
    1987           0 :         rf = malloc(sizeof(*rf), M_DEVBUF, M_WAITOK);
    1988           0 :         rf->rf_base = base;
    1989           0 :         rf->rf_size = size;
    1990           0 :         rf->rf_dev = dev;
    1991             : 
    1992           0 :         SLIST_INSERT_HEAD(&rasops_framebuffers, rf, rf_list);
    1993           0 : }
    1994             : 
    1995             : int
    1996           0 : rasops_check_framebuffer(paddr_t base)
    1997             : {
    1998             :         struct rasops_framebuffer *rf;
    1999             : 
    2000           0 :         SLIST_FOREACH(rf, &rasops_framebuffers, rf_list) {
    2001           0 :                 if (base >= rf->rf_base && base < rf->rf_base + rf->rf_size)
    2002           0 :                         return 1;
    2003             :         }
    2004             : 
    2005           0 :         return 0;
    2006           0 : }

Generated by: LCOV version 1.13