Home | History | Annotate | Line # | Download | only in dev
omrasops.c revision 1.20.2.1
      1  1.20.2.1    martin /* $NetBSD: omrasops.c,v 1.20.2.1 2020/04/13 08:03:56 martin Exp $ */
      2       1.1  nisimura 
      3       1.1  nisimura /*-
      4       1.1  nisimura  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5       1.1  nisimura  * All rights reserved.
      6       1.1  nisimura  *
      7       1.1  nisimura  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1  nisimura  * by Tohru Nishimura.
      9       1.1  nisimura  *
     10       1.1  nisimura  * Redistribution and use in source and binary forms, with or without
     11       1.1  nisimura  * modification, are permitted provided that the following conditions
     12       1.1  nisimura  * are met:
     13       1.1  nisimura  * 1. Redistributions of source code must retain the above copyright
     14       1.1  nisimura  *    notice, this list of conditions and the following disclaimer.
     15       1.1  nisimura  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  nisimura  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  nisimura  *    documentation and/or other materials provided with the distribution.
     18       1.1  nisimura  *
     19       1.1  nisimura  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1  nisimura  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1  nisimura  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1  nisimura  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1  nisimura  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1  nisimura  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1  nisimura  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1  nisimura  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1  nisimura  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1  nisimura  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1  nisimura  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1  nisimura  */
     31       1.1  nisimura 
     32       1.1  nisimura #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     33       1.1  nisimura 
     34  1.20.2.1    martin __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.20.2.1 2020/04/13 08:03:56 martin Exp $");
     35       1.1  nisimura 
     36       1.1  nisimura /*
     37       1.1  nisimura  * Designed speficically for 'm68k bitorder';
     38       1.1  nisimura  *	- most significant byte is stored at lower address,
     39       1.1  nisimura  *	- most significant bit is displayed at left most on screen.
     40      1.12   tsutsui  * Implementation relies on;
     41      1.15   tsutsui  *	- first column is at 32bit aligned address,
     42       1.1  nisimura  *	- font glyphs are stored in 32bit padded.
     43       1.1  nisimura  */
     44       1.1  nisimura 
     45       1.1  nisimura #include <sys/param.h>
     46       1.1  nisimura #include <sys/systm.h>
     47       1.1  nisimura #include <sys/device.h>
     48       1.1  nisimura 
     49      1.13   tsutsui #include <dev/wscons/wsconsio.h>
     50       1.1  nisimura #include <dev/wscons/wsdisplayvar.h>
     51      1.13   tsutsui #include <dev/rasops/rasops.h>
     52       1.1  nisimura 
     53      1.13   tsutsui #include <arch/luna68k/dev/omrasopsvar.h>
     54       1.1  nisimura 
     55       1.1  nisimura /* wscons emulator operations */
     56      1.16   tsutsui static void	om1_cursor(void *, int, int, int);
     57      1.16   tsutsui static void	om4_cursor(void *, int, int, int);
     58       1.7       dsl static int	om_mapchar(void *, int, unsigned int *);
     59      1.16   tsutsui static void	om1_putchar(void *, int, int, u_int, long);
     60      1.16   tsutsui static void	om4_putchar(void *, int, int, u_int, long);
     61      1.16   tsutsui static void	om1_copycols(void *, int, int, int, int);
     62      1.16   tsutsui static void	om4_copycols(void *, int, int, int, int);
     63      1.16   tsutsui static void	om1_copyrows(void *, int, int, int num);
     64      1.16   tsutsui static void	om4_copyrows(void *, int, int, int num);
     65      1.16   tsutsui static void	om1_erasecols(void *, int, int, int, long);
     66      1.16   tsutsui static void	om4_erasecols(void *, int, int, int, long);
     67      1.16   tsutsui static void	om1_eraserows(void *, int, int, long);
     68      1.16   tsutsui static void	om4_eraserows(void *, int, int, long);
     69      1.16   tsutsui static int	om1_allocattr(void *, int, int, int, long *);
     70      1.16   tsutsui static int	om4_allocattr(void *, int, int, int, long *);
     71      1.17   tsutsui static void	om4_unpack_attr(long, int *, int *, int *);
     72      1.16   tsutsui 
     73      1.16   tsutsui static int	omrasops_init(struct rasops_info *, int, int);
     74       1.1  nisimura 
     75       1.1  nisimura #define	ALL1BITS	(~0U)
     76       1.1  nisimura #define	ALL0BITS	(0U)
     77       1.1  nisimura #define	BLITWIDTH	(32)
     78       1.1  nisimura #define	ALIGNMASK	(0x1f)
     79       1.1  nisimura #define	BYTESDONE	(4)
     80       1.1  nisimura 
     81       1.1  nisimura /*
     82      1.15   tsutsui  * macros to handle unaligned bit copy ops.
     83      1.15   tsutsui  * See src/sys/dev/rasops/rasops_mask.h for MI version.
     84      1.15   tsutsui  * Also refer src/sys/arch/hp300/dev/maskbits.h.
     85      1.15   tsutsui  * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c)
     86      1.15   tsutsui  */
     87      1.15   tsutsui 
     88      1.15   tsutsui /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */
     89      1.15   tsutsui #define	FASTGETBITS(psrc, x, w, dst)					\
     90      1.15   tsutsui 	asm("bfextu %3{%1:%2},%0"					\
     91      1.15   tsutsui 	    : "=d" (dst) 						\
     92      1.19   tsutsui 	    : "di" (x), "di" (w), "o" (*(uint32_t *)(psrc)))
     93      1.15   tsutsui 
     94      1.15   tsutsui /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
     95      1.15   tsutsui /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
     96      1.15   tsutsui #define	FASTPUTBITS(src, x, w, pdst)					\
     97      1.15   tsutsui 	asm("bfins %3,%0{%1:%2}"					\
     98      1.19   tsutsui 	    : "+o" (*(uint32_t *)(pdst))				\
     99      1.16   tsutsui 	    : "di" (x), "di" (w), "d" (src)				\
    100      1.16   tsutsui 	    : "memory" );
    101      1.15   tsutsui 
    102      1.15   tsutsui #define	GETBITS(psrc, x, w, dst)	FASTGETBITS(psrc, x, w, dst)
    103      1.15   tsutsui #define	PUTBITS(src, x, w, pdst)	FASTPUTBITS(src, x, w, pdst)
    104      1.15   tsutsui 
    105      1.15   tsutsui /*
    106       1.1  nisimura  * Blit a character at the specified co-ordinates.
    107       1.1  nisimura  */
    108       1.1  nisimura static void
    109      1.16   tsutsui om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
    110       1.1  nisimura {
    111      1.13   tsutsui 	struct rasops_info *ri = cookie;
    112       1.5   tsutsui 	uint8_t *p;
    113       1.1  nisimura 	int scanspan, startx, height, width, align, y;
    114      1.11   tsutsui 	uint32_t lmask, rmask, glyph, inverse;
    115      1.13   tsutsui 	int i;
    116      1.13   tsutsui 	uint8_t *fb;
    117       1.1  nisimura 
    118      1.13   tsutsui 	scanspan = ri->ri_stride;
    119      1.13   tsutsui 	y = ri->ri_font->fontheight * row;
    120      1.13   tsutsui 	startx = ri->ri_font->fontwidth * startcol;
    121      1.13   tsutsui 	height = ri->ri_font->fontheight;
    122      1.13   tsutsui 	fb = (uint8_t *)ri->ri_font->data +
    123      1.13   tsutsui 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
    124      1.16   tsutsui 	inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
    125       1.1  nisimura 
    126      1.13   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    127       1.1  nisimura 	align = startx & ALIGNMASK;
    128      1.13   tsutsui 	width = ri->ri_font->fontwidth + align;
    129       1.1  nisimura 	lmask = ALL1BITS >> align;
    130       1.1  nisimura 	rmask = ALL1BITS << (-width & ALIGNMASK);
    131       1.1  nisimura 	if (width <= BLITWIDTH) {
    132       1.1  nisimura 		lmask &= rmask;
    133      1.19   tsutsui 		/* set lmask as ROP mask value, with THROUGH mode */
    134      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
    135      1.19   tsutsui 
    136       1.1  nisimura 		while (height > 0) {
    137      1.13   tsutsui 			glyph = 0;
    138      1.13   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    139      1.13   tsutsui 				glyph = (glyph << 8) | *fb++;
    140      1.13   tsutsui 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
    141       1.1  nisimura 			glyph = (glyph >> align) ^ inverse;
    142      1.19   tsutsui 
    143      1.19   tsutsui 			*W(p) = glyph;
    144      1.19   tsutsui 
    145       1.1  nisimura 			p += scanspan;
    146       1.1  nisimura 			height--;
    147       1.1  nisimura 		}
    148      1.19   tsutsui 		/* reset mask value */
    149      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    150      1.11   tsutsui 	} else {
    151       1.5   tsutsui 		uint8_t *q = p;
    152      1.11   tsutsui 		uint32_t lhalf, rhalf;
    153       1.1  nisimura 
    154       1.1  nisimura 		while (height > 0) {
    155      1.13   tsutsui 			glyph = 0;
    156      1.13   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    157      1.13   tsutsui 				glyph = (glyph << 8) | *fb++;
    158      1.13   tsutsui 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
    159       1.1  nisimura 			lhalf = (glyph >> align) ^ inverse;
    160      1.19   tsutsui 			/* set lmask as ROP mask value, with THROUGH mode */
    161      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
    162      1.19   tsutsui 			    lmask;
    163      1.19   tsutsui 
    164      1.19   tsutsui 			*W(p) = lhalf;
    165      1.19   tsutsui 
    166       1.1  nisimura 			p += BYTESDONE;
    167      1.19   tsutsui 
    168       1.1  nisimura 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
    169      1.19   tsutsui 			/* set rmask as ROP mask value, with THROUGH mode */
    170      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
    171      1.19   tsutsui 			    rmask;
    172      1.19   tsutsui 
    173      1.19   tsutsui 			*W(p) = rhalf;
    174      1.16   tsutsui 
    175      1.16   tsutsui 			p = (q += scanspan);
    176      1.16   tsutsui 			height--;
    177      1.16   tsutsui 		}
    178      1.19   tsutsui 		/* reset mask value */
    179      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    180      1.16   tsutsui 	}
    181      1.16   tsutsui }
    182      1.16   tsutsui 
    183      1.16   tsutsui static void
    184      1.16   tsutsui om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
    185      1.16   tsutsui {
    186      1.16   tsutsui 	struct rasops_info *ri = cookie;
    187      1.16   tsutsui 	uint8_t *p;
    188      1.16   tsutsui 	int scanspan, startx, height, width, align, y;
    189      1.17   tsutsui 	uint32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
    190      1.18   tsutsui 	uint32_t fgmask0, fgmask1, fgmask2, fgmask3;
    191      1.18   tsutsui 	uint32_t bgmask0, bgmask1, bgmask2, bgmask3;
    192      1.17   tsutsui 	int i, fg, bg;
    193      1.16   tsutsui 	uint8_t *fb;
    194      1.16   tsutsui 
    195      1.16   tsutsui 	scanspan = ri->ri_stride;
    196      1.16   tsutsui 	y = ri->ri_font->fontheight * row;
    197      1.16   tsutsui 	startx = ri->ri_font->fontwidth * startcol;
    198      1.16   tsutsui 	height = ri->ri_font->fontheight;
    199      1.16   tsutsui 	fb = (uint8_t *)ri->ri_font->data +
    200      1.16   tsutsui 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
    201      1.17   tsutsui 	om4_unpack_attr(attr, &fg, &bg, NULL);
    202      1.18   tsutsui 	fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS;
    203      1.18   tsutsui 	fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS;
    204      1.18   tsutsui 	fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS;
    205      1.18   tsutsui 	fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS;
    206      1.18   tsutsui 	bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS;
    207      1.18   tsutsui 	bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS;
    208      1.18   tsutsui 	bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS;
    209      1.18   tsutsui 	bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS;
    210      1.16   tsutsui 
    211      1.16   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    212      1.16   tsutsui 	align = startx & ALIGNMASK;
    213      1.16   tsutsui 	width = ri->ri_font->fontwidth + align;
    214      1.16   tsutsui 	lmask = ALL1BITS >> align;
    215      1.16   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
    216      1.19   tsutsui 
    217      1.19   tsutsui 	/* select all planes for later ROP function target */
    218      1.19   tsutsui 	*(volatile uint32_t *)OMFB_PLANEMASK = 0xff;
    219      1.19   tsutsui 
    220      1.16   tsutsui 	if (width <= BLITWIDTH) {
    221      1.16   tsutsui 		lmask &= rmask;
    222      1.19   tsutsui 		/* set lmask as ROP mask value, with THROUGH mode */
    223      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
    224      1.19   tsutsui 
    225      1.16   tsutsui 		while (height > 0) {
    226      1.16   tsutsui 			glyph = 0;
    227      1.16   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    228      1.16   tsutsui 				glyph = (glyph << 8) | *fb++;
    229      1.16   tsutsui 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
    230      1.16   tsutsui 			glyph = (glyph >> align);
    231      1.16   tsutsui 			glyphbg = glyph ^ ALL1BITS;
    232      1.19   tsutsui 
    233      1.18   tsutsui 			fgpat = glyph   & fgmask0;
    234      1.18   tsutsui 			bgpat = glyphbg & bgmask0;
    235      1.19   tsutsui 			*P0(p) = (fgpat | bgpat);
    236      1.18   tsutsui 			fgpat = glyph   & fgmask1;
    237      1.18   tsutsui 			bgpat = glyphbg & bgmask1;
    238      1.19   tsutsui 			*P1(p) = (fgpat | bgpat);
    239      1.18   tsutsui 			fgpat = glyph   & fgmask2;
    240      1.18   tsutsui 			bgpat = glyphbg & bgmask2;
    241      1.19   tsutsui 			*P2(p) = (fgpat | bgpat);
    242      1.18   tsutsui 			fgpat = glyph   & fgmask3;
    243      1.18   tsutsui 			bgpat = glyphbg & bgmask3;
    244      1.19   tsutsui 			*P3(p) = (fgpat | bgpat);
    245      1.19   tsutsui 
    246      1.16   tsutsui 			p += scanspan;
    247      1.16   tsutsui 			height--;
    248      1.16   tsutsui 		}
    249      1.19   tsutsui 		/* reset mask value */
    250      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    251      1.16   tsutsui 	} else {
    252      1.16   tsutsui 		uint8_t *q = p;
    253      1.16   tsutsui 		uint32_t lhalf, rhalf;
    254      1.16   tsutsui 		uint32_t lhalfbg, rhalfbg;
    255      1.16   tsutsui 
    256      1.16   tsutsui 		while (height > 0) {
    257      1.16   tsutsui 			glyph = 0;
    258      1.16   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    259      1.16   tsutsui 				glyph = (glyph << 8) | *fb++;
    260      1.16   tsutsui 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
    261      1.16   tsutsui 			lhalf = (glyph >> align);
    262      1.16   tsutsui 			lhalfbg = lhalf ^ ALL1BITS;
    263      1.19   tsutsui 			/* set lmask as ROP mask value, with THROUGH mode */
    264      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
    265      1.19   tsutsui 			    lmask;
    266      1.19   tsutsui 
    267      1.18   tsutsui 			fgpat = lhalf   & fgmask0;
    268      1.18   tsutsui 			bgpat = lhalfbg & bgmask0;
    269      1.19   tsutsui 			*P0(p) = (fgpat | bgpat);
    270      1.18   tsutsui 			fgpat = lhalf   & fgmask1;
    271      1.18   tsutsui 			bgpat = lhalfbg & bgmask1;
    272      1.19   tsutsui 			*P1(p) = (fgpat | bgpat);
    273      1.18   tsutsui 			fgpat = lhalf   & fgmask2;
    274      1.18   tsutsui 			bgpat = lhalfbg & bgmask2;
    275      1.19   tsutsui 			*P2(p) = (fgpat | bgpat);
    276      1.18   tsutsui 			fgpat = lhalf   & fgmask3;
    277      1.18   tsutsui 			bgpat = lhalfbg & bgmask3;
    278      1.19   tsutsui 			*P3(p) = (fgpat | bgpat);
    279      1.19   tsutsui 
    280      1.16   tsutsui 			p += BYTESDONE;
    281      1.19   tsutsui 
    282      1.16   tsutsui 			rhalf = (glyph << (BLITWIDTH - align));
    283      1.16   tsutsui 			rhalfbg = rhalf ^ ALL1BITS;
    284      1.19   tsutsui 			/* set rmask as ROP mask value, with THROUGH mode */
    285      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] =
    286      1.19   tsutsui 			    rmask;
    287      1.19   tsutsui 
    288      1.18   tsutsui 			fgpat = rhalf   & fgmask0;
    289      1.18   tsutsui 			bgpat = rhalfbg & bgmask0;
    290      1.19   tsutsui 			*P0(p) = (fgpat | bgpat);
    291      1.18   tsutsui 			fgpat = rhalf   & fgmask1;
    292      1.18   tsutsui 			bgpat = rhalfbg & bgmask1;
    293      1.19   tsutsui 			*P1(p) = (fgpat | bgpat);
    294      1.18   tsutsui 			fgpat = rhalf   & fgmask2;
    295      1.18   tsutsui 			bgpat = rhalfbg & bgmask2;
    296      1.19   tsutsui 			*P2(p) = (fgpat | bgpat);
    297      1.18   tsutsui 			fgpat = rhalf   & fgmask3;
    298      1.18   tsutsui 			bgpat = rhalfbg & bgmask3;
    299      1.19   tsutsui 			*P3(p) = (fgpat | bgpat);
    300       1.1  nisimura 
    301       1.1  nisimura 			p = (q += scanspan);
    302       1.1  nisimura 			height--;
    303       1.1  nisimura 		}
    304      1.19   tsutsui 		/* reset mask value */
    305      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    306       1.1  nisimura 	}
    307      1.19   tsutsui 	/* select plane #0 only; XXX need this ? */
    308      1.19   tsutsui 	*(volatile uint32_t *)OMFB_PLANEMASK = 0x01;
    309       1.1  nisimura }
    310       1.1  nisimura 
    311       1.1  nisimura static void
    312      1.16   tsutsui om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
    313       1.1  nisimura {
    314      1.13   tsutsui 	struct rasops_info *ri = cookie;
    315      1.13   tsutsui 	uint8_t *p;
    316      1.13   tsutsui 	int scanspan, startx, height, width, align, w, y;
    317      1.13   tsutsui 	uint32_t lmask, rmask, fill;
    318      1.13   tsutsui 
    319      1.20      maya 	scanspan = ri->ri_stride;
    320      1.13   tsutsui 	y = ri->ri_font->fontheight * row;
    321      1.13   tsutsui 	startx = ri->ri_font->fontwidth * startcol;
    322      1.13   tsutsui 	height = ri->ri_font->fontheight;
    323      1.13   tsutsui 	w = ri->ri_font->fontwidth * ncols;
    324      1.16   tsutsui 	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
    325       1.1  nisimura 
    326      1.13   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    327       1.1  nisimura 	align = startx & ALIGNMASK;
    328       1.1  nisimura 	width = w + align;
    329       1.1  nisimura 	lmask = ALL1BITS >> align;
    330       1.1  nisimura 	rmask = ALL1BITS << (-width & ALIGNMASK);
    331       1.1  nisimura 	if (width <= BLITWIDTH) {
    332       1.1  nisimura 		lmask &= rmask;
    333      1.16   tsutsui 		fill  &= lmask;
    334       1.1  nisimura 		while (height > 0) {
    335      1.19   tsutsui 			*P0(p) = (*P0(p) & ~lmask) | fill;
    336       1.1  nisimura 			p += scanspan;
    337       1.1  nisimura 			height--;
    338       1.1  nisimura 		}
    339      1.11   tsutsui 	} else {
    340       1.5   tsutsui 		uint8_t *q = p;
    341       1.1  nisimura 		while (height > 0) {
    342      1.19   tsutsui 			*P0(p) = (*P0(p) & ~lmask) | (fill & lmask);
    343       1.1  nisimura 			width -= 2 * BLITWIDTH;
    344       1.1  nisimura 			while (width > 0) {
    345       1.1  nisimura 				p += BYTESDONE;
    346      1.19   tsutsui 				*P0(p) = fill;
    347       1.1  nisimura 				width -= BLITWIDTH;
    348       1.1  nisimura 			}
    349       1.1  nisimura 			p += BYTESDONE;
    350      1.19   tsutsui 			*P0(p) = (fill & rmask) | (*P0(p) & ~rmask);
    351       1.1  nisimura 
    352       1.1  nisimura 			p = (q += scanspan);
    353       1.1  nisimura 			width = w + align;
    354       1.1  nisimura 			height--;
    355       1.1  nisimura 		}
    356       1.1  nisimura 	}
    357       1.1  nisimura }
    358       1.1  nisimura 
    359       1.1  nisimura static void
    360      1.16   tsutsui om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
    361      1.16   tsutsui {
    362      1.16   tsutsui 	struct rasops_info *ri = cookie;
    363      1.16   tsutsui 	uint8_t *p;
    364      1.17   tsutsui 	int scanspan, startx, height, width, align, w, y, fg, bg;
    365      1.16   tsutsui 	uint32_t lmask, rmask, fill0, fill1, fill2, fill3;
    366      1.16   tsutsui 
    367      1.20      maya 	scanspan = ri->ri_stride;
    368      1.16   tsutsui 	y = ri->ri_font->fontheight * row;
    369      1.16   tsutsui 	startx = ri->ri_font->fontwidth * startcol;
    370      1.16   tsutsui 	height = ri->ri_font->fontheight;
    371      1.16   tsutsui 	w = ri->ri_font->fontwidth * ncols;
    372      1.17   tsutsui 	om4_unpack_attr(attr, &fg, &bg, NULL);
    373      1.17   tsutsui 	fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
    374      1.17   tsutsui 	fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
    375      1.17   tsutsui 	fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
    376      1.17   tsutsui 	fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
    377      1.16   tsutsui 
    378      1.16   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    379      1.16   tsutsui 	align = startx & ALIGNMASK;
    380      1.16   tsutsui 	width = w + align;
    381      1.16   tsutsui 	lmask = ALL1BITS >> align;
    382      1.16   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
    383      1.16   tsutsui 	if (width <= BLITWIDTH) {
    384      1.16   tsutsui 		lmask &= rmask;
    385      1.16   tsutsui 		fill0 &= lmask;
    386      1.16   tsutsui 		fill1 &= lmask;
    387      1.16   tsutsui 		fill2 &= lmask;
    388      1.16   tsutsui 		fill3 &= lmask;
    389      1.16   tsutsui 		while (height > 0) {
    390      1.19   tsutsui 			*P0(p) = (*P0(p) & ~lmask) | fill0;
    391      1.19   tsutsui 			*P1(p) = (*P1(p) & ~lmask) | fill1;
    392      1.19   tsutsui 			*P2(p) = (*P2(p) & ~lmask) | fill2;
    393      1.19   tsutsui 			*P3(p) = (*P3(p) & ~lmask) | fill3;
    394      1.16   tsutsui 			p += scanspan;
    395      1.16   tsutsui 			height--;
    396      1.16   tsutsui 		}
    397      1.16   tsutsui 	} else {
    398      1.16   tsutsui 		uint8_t *q = p;
    399      1.16   tsutsui 		while (height > 0) {
    400      1.19   tsutsui 			*P0(p) = (*P0(p) & ~lmask) | (fill0 & lmask);
    401      1.19   tsutsui 			*P1(p) = (*P1(p) & ~lmask) | (fill1 & lmask);
    402      1.19   tsutsui 			*P2(p) = (*P2(p) & ~lmask) | (fill2 & lmask);
    403      1.19   tsutsui 			*P3(p) = (*P3(p) & ~lmask) | (fill3 & lmask);
    404      1.16   tsutsui 			width -= 2 * BLITWIDTH;
    405      1.16   tsutsui 			while (width > 0) {
    406      1.16   tsutsui 				p += BYTESDONE;
    407      1.19   tsutsui 				*P0(p) = fill0;
    408      1.19   tsutsui 				*P1(p) = fill1;
    409      1.19   tsutsui 				*P2(p) = fill2;
    410      1.19   tsutsui 				*P3(p) = fill3;
    411      1.16   tsutsui 				width -= BLITWIDTH;
    412      1.16   tsutsui 			}
    413      1.16   tsutsui 			p += BYTESDONE;
    414      1.19   tsutsui 			*P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask);
    415      1.19   tsutsui 			*P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask);
    416      1.19   tsutsui 			*P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask);
    417      1.19   tsutsui 			*P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask);
    418      1.16   tsutsui 
    419      1.16   tsutsui 			p = (q += scanspan);
    420      1.16   tsutsui 			width = w + align;
    421      1.16   tsutsui 			height--;
    422      1.16   tsutsui 		}
    423      1.16   tsutsui 	}
    424      1.16   tsutsui }
    425      1.16   tsutsui 
    426      1.16   tsutsui static void
    427      1.16   tsutsui om1_eraserows(void *cookie, int startrow, int nrows, long attr)
    428       1.1  nisimura {
    429      1.13   tsutsui 	struct rasops_info *ri = cookie;
    430       1.5   tsutsui 	uint8_t *p, *q;
    431       1.1  nisimura 	int scanspan, starty, height, width, w;
    432      1.11   tsutsui 	uint32_t rmask, fill;
    433       1.1  nisimura 
    434      1.13   tsutsui 	scanspan = ri->ri_stride;
    435      1.13   tsutsui 	starty = ri->ri_font->fontheight * startrow;
    436      1.13   tsutsui 	height = ri->ri_font->fontheight * nrows;
    437      1.13   tsutsui 	w = ri->ri_emuwidth;
    438      1.16   tsutsui 	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
    439       1.1  nisimura 
    440      1.13   tsutsui 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
    441       1.1  nisimura 	width = w;
    442      1.13   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
    443       1.1  nisimura 	q = p;
    444       1.1  nisimura 	while (height > 0) {
    445      1.19   tsutsui 		*P0(p) = fill;				/* always aligned */
    446       1.1  nisimura 		width -= 2 * BLITWIDTH;
    447       1.1  nisimura 		while (width > 0) {
    448       1.1  nisimura 			p += BYTESDONE;
    449      1.19   tsutsui 			*P0(p) = fill;
    450       1.1  nisimura 			width -= BLITWIDTH;
    451       1.1  nisimura 		}
    452       1.1  nisimura 		p += BYTESDONE;
    453      1.19   tsutsui 		*P0(p) = (fill & rmask) | (*P0(p) & ~rmask);
    454       1.1  nisimura 		p = (q += scanspan);
    455       1.1  nisimura 		width = w;
    456       1.1  nisimura 		height--;
    457       1.1  nisimura 	}
    458       1.1  nisimura }
    459       1.1  nisimura 
    460       1.1  nisimura static void
    461      1.16   tsutsui om4_eraserows(void *cookie, int startrow, int nrows, long attr)
    462      1.16   tsutsui {
    463      1.16   tsutsui 	struct rasops_info *ri = cookie;
    464      1.16   tsutsui 	uint8_t *p, *q;
    465      1.17   tsutsui 	int scanspan, starty, height, width, w, fg, bg;
    466      1.16   tsutsui 	uint32_t rmask, fill0, fill1, fill2, fill3;
    467      1.16   tsutsui 
    468      1.16   tsutsui 	scanspan = ri->ri_stride;
    469      1.16   tsutsui 	starty = ri->ri_font->fontheight * startrow;
    470      1.16   tsutsui 	height = ri->ri_font->fontheight * nrows;
    471      1.16   tsutsui 	w = ri->ri_emuwidth;
    472      1.17   tsutsui 	om4_unpack_attr(attr, &fg, &bg, NULL);
    473      1.17   tsutsui 	fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
    474      1.17   tsutsui 	fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
    475      1.17   tsutsui 	fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
    476      1.17   tsutsui 	fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
    477      1.16   tsutsui 
    478      1.16   tsutsui 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
    479      1.16   tsutsui 	width = w;
    480      1.16   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
    481      1.16   tsutsui 	q = p;
    482      1.16   tsutsui 	while (height > 0) {
    483      1.19   tsutsui 		*P0(p) = fill0;				/* always aligned */
    484      1.19   tsutsui 		*P1(p) = fill1;
    485      1.19   tsutsui 		*P2(p) = fill2;
    486      1.19   tsutsui 		*P3(p) = fill3;
    487      1.16   tsutsui 		width -= 2 * BLITWIDTH;
    488      1.16   tsutsui 		while (width > 0) {
    489      1.16   tsutsui 			p += BYTESDONE;
    490      1.19   tsutsui 			*P0(p) = fill0;
    491      1.19   tsutsui 			*P1(p) = fill1;
    492      1.19   tsutsui 			*P2(p) = fill2;
    493      1.19   tsutsui 			*P3(p) = fill3;
    494      1.16   tsutsui 			width -= BLITWIDTH;
    495      1.16   tsutsui 		}
    496      1.16   tsutsui 		p += BYTESDONE;
    497      1.19   tsutsui 		*P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask);
    498      1.19   tsutsui 		*P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask);
    499      1.19   tsutsui 		*P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask);
    500      1.19   tsutsui 		*P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask);
    501      1.16   tsutsui 		p = (q += scanspan);
    502      1.16   tsutsui 		width = w;
    503      1.16   tsutsui 		height--;
    504      1.16   tsutsui 	}
    505      1.16   tsutsui }
    506      1.16   tsutsui 
    507      1.16   tsutsui static void
    508      1.16   tsutsui om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
    509       1.1  nisimura {
    510      1.13   tsutsui 	struct rasops_info *ri = cookie;
    511      1.13   tsutsui 	uint8_t *p, *q;
    512       1.1  nisimura 	int scanspan, offset, srcy, height, width, w;
    513      1.13   tsutsui 	uint32_t rmask;
    514      1.13   tsutsui 
    515      1.13   tsutsui 	scanspan = ri->ri_stride;
    516      1.13   tsutsui 	height = ri->ri_font->fontheight * nrows;
    517      1.13   tsutsui 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
    518      1.13   tsutsui 	srcy = ri->ri_font->fontheight * srcrow;
    519       1.1  nisimura 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
    520       1.1  nisimura 		scanspan = -scanspan;
    521      1.14   tsutsui 		srcy = srcy + height - 1;
    522       1.1  nisimura 	}
    523       1.1  nisimura 
    524      1.13   tsutsui 	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
    525      1.13   tsutsui 	w = ri->ri_emuwidth;
    526       1.1  nisimura 	width = w;
    527       1.1  nisimura 	rmask = ALL1BITS << (-width & ALIGNMASK);
    528       1.1  nisimura 	q = p;
    529       1.1  nisimura 	while (height > 0) {
    530      1.19   tsutsui 		*P0(p + offset) = *P0(p);		/* always aligned */
    531       1.1  nisimura 		width -= 2 * BLITWIDTH;
    532       1.1  nisimura 		while (width > 0) {
    533       1.1  nisimura 			p += BYTESDONE;
    534      1.19   tsutsui 			*P0(p + offset) = *P0(p);
    535       1.1  nisimura 			width -= BLITWIDTH;
    536       1.1  nisimura 		}
    537       1.1  nisimura 		p += BYTESDONE;
    538      1.19   tsutsui 		*P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask);
    539       1.1  nisimura 
    540       1.1  nisimura 		p = (q += scanspan);
    541       1.1  nisimura 		width = w;
    542       1.1  nisimura 		height--;
    543       1.1  nisimura 	}
    544       1.1  nisimura }
    545       1.1  nisimura 
    546       1.1  nisimura static void
    547      1.16   tsutsui om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
    548      1.16   tsutsui {
    549      1.16   tsutsui 	struct rasops_info *ri = cookie;
    550      1.16   tsutsui 	uint8_t *p, *q;
    551      1.16   tsutsui 	int scanspan, offset, srcy, height, width, w;
    552      1.16   tsutsui 	uint32_t rmask;
    553      1.16   tsutsui 
    554      1.16   tsutsui 	scanspan = ri->ri_stride;
    555      1.16   tsutsui 	height = ri->ri_font->fontheight * nrows;
    556      1.16   tsutsui 	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
    557      1.16   tsutsui 	srcy = ri->ri_font->fontheight * srcrow;
    558      1.16   tsutsui 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
    559      1.16   tsutsui 		scanspan = -scanspan;
    560      1.16   tsutsui 		srcy = srcy + height - 1;
    561      1.16   tsutsui 	}
    562      1.16   tsutsui 
    563      1.16   tsutsui 	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
    564      1.16   tsutsui 	w = ri->ri_emuwidth;
    565      1.16   tsutsui 	width = w;
    566      1.16   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
    567      1.16   tsutsui 	q = p;
    568      1.16   tsutsui 	while (height > 0) {
    569      1.19   tsutsui 		*P0(p + offset) = *P0(p);		/* always aligned */
    570      1.19   tsutsui 		*P1(p + offset) = *P1(p);
    571      1.19   tsutsui 		*P2(p + offset) = *P2(p);
    572      1.19   tsutsui 		*P3(p + offset) = *P3(p);
    573      1.16   tsutsui 		width -= 2 * BLITWIDTH;
    574      1.16   tsutsui 		while (width > 0) {
    575      1.16   tsutsui 			p += BYTESDONE;
    576      1.19   tsutsui 			*P0(p + offset) = *P0(p);
    577      1.19   tsutsui 			*P1(p + offset) = *P1(p);
    578      1.19   tsutsui 			*P2(p + offset) = *P2(p);
    579      1.19   tsutsui 			*P3(p + offset) = *P3(p);
    580      1.16   tsutsui 			width -= BLITWIDTH;
    581      1.16   tsutsui 		}
    582      1.16   tsutsui 		p += BYTESDONE;
    583      1.19   tsutsui 		*P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask);
    584      1.19   tsutsui 		*P1(p + offset) = (*P1(p) & rmask) | (*P1(p + offset) & ~rmask);
    585      1.19   tsutsui 		*P2(p + offset) = (*P2(p) & rmask) | (*P2(p + offset) & ~rmask);
    586      1.19   tsutsui 		*P3(p + offset) = (*P3(p) & rmask) | (*P3(p + offset) & ~rmask);
    587      1.16   tsutsui 
    588      1.16   tsutsui 		p = (q += scanspan);
    589      1.16   tsutsui 		width = w;
    590      1.16   tsutsui 		height--;
    591      1.16   tsutsui 	}
    592      1.16   tsutsui }
    593      1.16   tsutsui 
    594      1.16   tsutsui static void
    595      1.16   tsutsui om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
    596      1.16   tsutsui {
    597      1.16   tsutsui 	struct rasops_info *ri = cookie;
    598      1.16   tsutsui 	uint8_t *sp, *dp, *sq, *dq, *basep;
    599      1.16   tsutsui 	int scanspan, height, w, y, srcx, dstx;
    600      1.16   tsutsui 	int sb, eb, db, sboff, full, cnt, lnum, rnum;
    601      1.16   tsutsui 	uint32_t lmask, rmask, tmp;
    602      1.16   tsutsui 	bool sbover;
    603      1.16   tsutsui 
    604      1.16   tsutsui 	scanspan = ri->ri_stride;
    605      1.16   tsutsui 	y = ri->ri_font->fontheight * startrow;
    606      1.16   tsutsui 	srcx = ri->ri_font->fontwidth * srccol;
    607      1.16   tsutsui 	dstx = ri->ri_font->fontwidth * dstcol;
    608      1.16   tsutsui 	height = ri->ri_font->fontheight;
    609      1.16   tsutsui 	w = ri->ri_font->fontwidth * ncols;
    610      1.16   tsutsui 	basep = (uint8_t *)ri->ri_bits + y * scanspan;
    611      1.16   tsutsui 
    612      1.16   tsutsui 	sb = srcx & ALIGNMASK;
    613      1.16   tsutsui 	db = dstx & ALIGNMASK;
    614      1.16   tsutsui 
    615      1.16   tsutsui 	if (db + w <= BLITWIDTH) {
    616      1.16   tsutsui 		/* Destination is contained within a single word */
    617      1.16   tsutsui 		sp = basep + (srcx / 32) * 4;
    618      1.16   tsutsui 		dp = basep + (dstx / 32) * 4;
    619      1.16   tsutsui 
    620      1.16   tsutsui 		while (height > 0) {
    621      1.16   tsutsui 			GETBITS(P0(sp), sb, w, tmp);
    622      1.16   tsutsui 			PUTBITS(tmp, db, w, P0(dp));
    623      1.16   tsutsui 			dp += scanspan;
    624      1.16   tsutsui 			sp += scanspan;
    625      1.16   tsutsui 			height--;
    626      1.16   tsutsui 		}
    627      1.16   tsutsui 		return;
    628      1.16   tsutsui 	}
    629      1.16   tsutsui 
    630      1.16   tsutsui 	lmask = (db == 0) ? 0 : ALL1BITS >> db;
    631      1.16   tsutsui 	eb = (db + w) & ALIGNMASK;
    632      1.16   tsutsui 	rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
    633      1.16   tsutsui 	lnum = (32 - db) & ALIGNMASK;
    634      1.16   tsutsui 	rnum = (dstx + w) & ALIGNMASK;
    635      1.16   tsutsui 
    636      1.16   tsutsui 	if (lmask != 0)
    637      1.16   tsutsui 		full = (w - (32 - db)) / 32;
    638      1.16   tsutsui 	else
    639      1.16   tsutsui 		full = w / 32;
    640      1.16   tsutsui 
    641      1.16   tsutsui 	sbover = (sb + lnum) >= 32;
    642      1.16   tsutsui 
    643      1.16   tsutsui 	if (dstcol < srccol || srccol + ncols < dstcol) {
    644      1.16   tsutsui 		/* copy forward (left-to-right) */
    645      1.16   tsutsui 		sp = basep + (srcx / 32) * 4;
    646      1.16   tsutsui 		dp = basep + (dstx / 32) * 4;
    647      1.16   tsutsui 
    648      1.16   tsutsui 		if (lmask != 0) {
    649      1.16   tsutsui 			sboff = sb + lnum;
    650      1.16   tsutsui 			if (sboff >= 32)
    651      1.16   tsutsui 				sboff -= 32;
    652      1.16   tsutsui 		} else
    653      1.16   tsutsui 			sboff = sb;
    654      1.16   tsutsui 
    655      1.16   tsutsui 		sq = sp;
    656      1.16   tsutsui 		dq = dp;
    657      1.16   tsutsui 		while (height > 0) {
    658      1.16   tsutsui 			if (lmask != 0) {
    659      1.16   tsutsui 				GETBITS(P0(sp), sb, lnum, tmp);
    660      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P0(dp));
    661      1.16   tsutsui 				dp += BYTESDONE;
    662      1.16   tsutsui 				if (sbover)
    663      1.16   tsutsui 					sp += BYTESDONE;
    664      1.16   tsutsui 			}
    665      1.16   tsutsui 
    666      1.16   tsutsui 			for (cnt = full; cnt; cnt--) {
    667      1.16   tsutsui 				GETBITS(P0(sp), sboff, 32, tmp);
    668      1.19   tsutsui 				*P0(dp) = tmp;
    669      1.16   tsutsui 				sp += BYTESDONE;
    670      1.16   tsutsui 				dp += BYTESDONE;
    671      1.16   tsutsui 			}
    672      1.16   tsutsui 
    673      1.16   tsutsui 			if (rmask != 0) {
    674      1.16   tsutsui 				GETBITS(P0(sp), sboff, rnum, tmp);
    675      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P0(dp));
    676      1.16   tsutsui 			}
    677      1.16   tsutsui 
    678      1.16   tsutsui 			sp = (sq += scanspan);
    679      1.16   tsutsui 			dp = (dq += scanspan);
    680      1.16   tsutsui 			height--;
    681      1.16   tsutsui 		}
    682      1.16   tsutsui 	} else {
    683      1.16   tsutsui 		/* copy backward (right-to-left) */
    684      1.16   tsutsui 		sp = basep + ((srcx + w) / 32) * 4;
    685      1.16   tsutsui 		dp = basep + ((dstx + w) / 32) * 4;
    686      1.16   tsutsui 
    687      1.16   tsutsui 		sboff = (srcx + w) & ALIGNMASK;
    688      1.16   tsutsui 		sboff -= rnum;
    689      1.16   tsutsui 		if (sboff < 0) {
    690      1.16   tsutsui 			sp -= BYTESDONE;
    691      1.16   tsutsui 			sboff += 32;
    692      1.16   tsutsui 		}
    693      1.16   tsutsui 
    694      1.16   tsutsui 		sq = sp;
    695      1.16   tsutsui 		dq = dp;
    696      1.16   tsutsui 		while (height > 0) {
    697      1.16   tsutsui 			if (rnum != 0) {
    698      1.16   tsutsui 				GETBITS(P0(sp), sboff, rnum, tmp);
    699      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P0(dp));
    700      1.16   tsutsui 			}
    701      1.16   tsutsui 
    702      1.16   tsutsui 			for (cnt = full; cnt; cnt--) {
    703      1.16   tsutsui 				sp -= BYTESDONE;
    704      1.16   tsutsui 				dp -= BYTESDONE;
    705      1.16   tsutsui 				GETBITS(P0(sp), sboff, 32, tmp);
    706      1.19   tsutsui 				*P0(dp) = tmp;
    707      1.16   tsutsui 			}
    708      1.16   tsutsui 
    709      1.16   tsutsui 			if (lmask != 0) {
    710      1.16   tsutsui 				if (sbover)
    711      1.16   tsutsui 					sp -= BYTESDONE;
    712      1.16   tsutsui 				dp -= BYTESDONE;
    713      1.16   tsutsui 				GETBITS(P0(sp), sb, lnum, tmp);
    714      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P0(dp));
    715      1.16   tsutsui 			}
    716      1.16   tsutsui 
    717      1.16   tsutsui 			sp = (sq += scanspan);
    718      1.16   tsutsui 			dp = (dq += scanspan);
    719      1.16   tsutsui 			height--;
    720      1.16   tsutsui 		}
    721      1.16   tsutsui 	}
    722      1.16   tsutsui }
    723      1.16   tsutsui 
    724      1.16   tsutsui static void
    725      1.16   tsutsui om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
    726       1.1  nisimura {
    727      1.13   tsutsui 	struct rasops_info *ri = cookie;
    728      1.15   tsutsui 	uint8_t *sp, *dp, *sq, *dq, *basep;
    729      1.15   tsutsui 	int scanspan, height, w, y, srcx, dstx;
    730      1.15   tsutsui 	int sb, eb, db, sboff, full, cnt, lnum, rnum;
    731      1.15   tsutsui 	uint32_t lmask, rmask, tmp;
    732      1.15   tsutsui 	bool sbover;
    733       1.1  nisimura 
    734      1.13   tsutsui 	scanspan = ri->ri_stride;
    735      1.13   tsutsui 	y = ri->ri_font->fontheight * startrow;
    736      1.13   tsutsui 	srcx = ri->ri_font->fontwidth * srccol;
    737      1.13   tsutsui 	dstx = ri->ri_font->fontwidth * dstcol;
    738      1.13   tsutsui 	height = ri->ri_font->fontheight;
    739      1.13   tsutsui 	w = ri->ri_font->fontwidth * ncols;
    740      1.13   tsutsui 	basep = (uint8_t *)ri->ri_bits + y * scanspan;
    741       1.1  nisimura 
    742      1.15   tsutsui 	sb = srcx & ALIGNMASK;
    743      1.15   tsutsui 	db = dstx & ALIGNMASK;
    744       1.1  nisimura 
    745      1.15   tsutsui 	if (db + w <= BLITWIDTH) {
    746      1.15   tsutsui 		/* Destination is contained within a single word */
    747      1.15   tsutsui 		sp = basep + (srcx / 32) * 4;
    748      1.15   tsutsui 		dp = basep + (dstx / 32) * 4;
    749       1.1  nisimura 
    750       1.1  nisimura 		while (height > 0) {
    751      1.16   tsutsui 			GETBITS(P0(sp), sb, w, tmp);
    752      1.16   tsutsui 			PUTBITS(tmp, db, w, P0(dp));
    753      1.16   tsutsui 			GETBITS(P1(sp), sb, w, tmp);
    754      1.16   tsutsui 			PUTBITS(tmp, db, w, P1(dp));
    755      1.16   tsutsui 			GETBITS(P2(sp), sb, w, tmp);
    756      1.16   tsutsui 			PUTBITS(tmp, db, w, P2(dp));
    757      1.16   tsutsui 			GETBITS(P3(sp), sb, w, tmp);
    758      1.16   tsutsui 			PUTBITS(tmp, db, w, P3(dp));
    759       1.1  nisimura 			dp += scanspan;
    760       1.1  nisimura 			sp += scanspan;
    761       1.1  nisimura 			height--;
    762       1.1  nisimura 		}
    763      1.15   tsutsui 		return;
    764       1.1  nisimura 	}
    765       1.1  nisimura 
    766      1.15   tsutsui 	lmask = (db == 0) ? 0 : ALL1BITS >> db;
    767      1.15   tsutsui 	eb = (db + w) & ALIGNMASK;
    768      1.15   tsutsui 	rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
    769      1.15   tsutsui 	lnum = (32 - db) & ALIGNMASK;
    770      1.15   tsutsui 	rnum = (dstx + w) & ALIGNMASK;
    771      1.15   tsutsui 
    772      1.15   tsutsui 	if (lmask != 0)
    773      1.15   tsutsui 		full = (w - (32 - db)) / 32;
    774      1.15   tsutsui 	else
    775      1.15   tsutsui 		full = w / 32;
    776      1.15   tsutsui 
    777      1.15   tsutsui 	sbover = (sb + lnum) >= 32;
    778      1.15   tsutsui 
    779      1.15   tsutsui 	if (dstcol < srccol || srccol + ncols < dstcol) {
    780      1.15   tsutsui 		/* copy forward (left-to-right) */
    781      1.15   tsutsui 		sp = basep + (srcx / 32) * 4;
    782      1.15   tsutsui 		dp = basep + (dstx / 32) * 4;
    783      1.15   tsutsui 
    784      1.15   tsutsui 		if (lmask != 0) {
    785      1.15   tsutsui 			sboff = sb + lnum;
    786      1.15   tsutsui 			if (sboff >= 32)
    787      1.15   tsutsui 				sboff -= 32;
    788      1.15   tsutsui 		} else
    789      1.15   tsutsui 			sboff = sb;
    790      1.15   tsutsui 
    791      1.15   tsutsui 		sq = sp;
    792      1.15   tsutsui 		dq = dp;
    793       1.1  nisimura 		while (height > 0) {
    794      1.15   tsutsui 			if (lmask != 0) {
    795      1.16   tsutsui 				GETBITS(P0(sp), sb, lnum, tmp);
    796      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P0(dp));
    797      1.16   tsutsui 				GETBITS(P1(sp), sb, lnum, tmp);
    798      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P1(dp));
    799      1.16   tsutsui 				GETBITS(P2(sp), sb, lnum, tmp);
    800      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P2(dp));
    801      1.16   tsutsui 				GETBITS(P3(sp), sb, lnum, tmp);
    802      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P3(dp));
    803      1.15   tsutsui 				dp += BYTESDONE;
    804      1.15   tsutsui 				if (sbover)
    805      1.15   tsutsui 					sp += BYTESDONE;
    806      1.15   tsutsui 			}
    807      1.15   tsutsui 
    808      1.15   tsutsui 			for (cnt = full; cnt; cnt--) {
    809      1.16   tsutsui 				GETBITS(P0(sp), sboff, 32, tmp);
    810      1.19   tsutsui 				*P0(dp) = tmp;
    811      1.16   tsutsui 				GETBITS(P1(sp), sboff, 32, tmp);
    812      1.19   tsutsui 				*P1(dp) = tmp;
    813      1.16   tsutsui 				GETBITS(P2(sp), sboff, 32, tmp);
    814      1.19   tsutsui 				*P2(dp) = tmp;
    815      1.16   tsutsui 				GETBITS(P3(sp), sboff, 32, tmp);
    816      1.19   tsutsui 				*P3(dp) = tmp;
    817       1.1  nisimura 				sp += BYTESDONE;
    818       1.1  nisimura 				dp += BYTESDONE;
    819       1.1  nisimura 			}
    820      1.15   tsutsui 
    821      1.15   tsutsui 			if (rmask != 0) {
    822      1.16   tsutsui 				GETBITS(P0(sp), sboff, rnum, tmp);
    823      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P0(dp));
    824      1.16   tsutsui 				GETBITS(P1(sp), sboff, rnum, tmp);
    825      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P1(dp));
    826      1.16   tsutsui 				GETBITS(P2(sp), sboff, rnum, tmp);
    827      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P2(dp));
    828      1.16   tsutsui 				GETBITS(P3(sp), sboff, rnum, tmp);
    829      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P3(dp));
    830      1.15   tsutsui 			}
    831      1.15   tsutsui 
    832       1.1  nisimura 			sp = (sq += scanspan);
    833       1.1  nisimura 			dp = (dq += scanspan);
    834       1.1  nisimura 			height--;
    835       1.1  nisimura 		}
    836      1.15   tsutsui 	} else {
    837      1.15   tsutsui 		/* copy backward (right-to-left) */
    838      1.15   tsutsui 		sp = basep + ((srcx + w) / 32) * 4;
    839      1.15   tsutsui 		dp = basep + ((dstx + w) / 32) * 4;
    840      1.15   tsutsui 
    841      1.15   tsutsui 		sboff = (srcx + w) & ALIGNMASK;
    842      1.15   tsutsui 		sboff -= rnum;
    843      1.15   tsutsui 		if (sboff < 0) {
    844      1.15   tsutsui 			sp -= BYTESDONE;
    845      1.15   tsutsui 			sboff += 32;
    846      1.15   tsutsui 		}
    847      1.15   tsutsui 
    848      1.15   tsutsui 		sq = sp;
    849      1.15   tsutsui 		dq = dp;
    850       1.1  nisimura 		while (height > 0) {
    851      1.15   tsutsui 			if (rnum != 0) {
    852      1.16   tsutsui 				GETBITS(P0(sp), sboff, rnum, tmp);
    853      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P0(dp));
    854      1.16   tsutsui 				GETBITS(P1(sp), sboff, rnum, tmp);
    855      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P1(dp));
    856      1.16   tsutsui 				GETBITS(P2(sp), sboff, rnum, tmp);
    857      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P2(dp));
    858      1.16   tsutsui 				GETBITS(P3(sp), sboff, rnum, tmp);
    859      1.16   tsutsui 				PUTBITS(tmp, 0, rnum, P3(dp));
    860      1.15   tsutsui 			}
    861      1.15   tsutsui 
    862      1.15   tsutsui 			for (cnt = full; cnt; cnt--) {
    863       1.1  nisimura 				sp -= BYTESDONE;
    864       1.1  nisimura 				dp -= BYTESDONE;
    865      1.16   tsutsui 				GETBITS(P0(sp), sboff, 32, tmp);
    866      1.19   tsutsui 				*P0(dp) = tmp;
    867      1.16   tsutsui 				GETBITS(P1(sp), sboff, 32, tmp);
    868      1.19   tsutsui 				*P1(dp) = tmp;
    869      1.16   tsutsui 				GETBITS(P2(sp), sboff, 32, tmp);
    870      1.19   tsutsui 				*P2(dp) = tmp;
    871      1.16   tsutsui 				GETBITS(P3(sp), sboff, 32, tmp);
    872      1.19   tsutsui 				*P3(dp) = tmp;
    873      1.15   tsutsui 			}
    874      1.15   tsutsui 
    875      1.15   tsutsui 			if (lmask != 0) {
    876      1.15   tsutsui 				if (sbover)
    877      1.15   tsutsui 					sp -= BYTESDONE;
    878      1.15   tsutsui 				dp -= BYTESDONE;
    879      1.16   tsutsui 				GETBITS(P0(sp), sb, lnum, tmp);
    880      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P0(dp));
    881      1.16   tsutsui 				GETBITS(P1(sp), sb, lnum, tmp);
    882      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P1(dp));
    883      1.16   tsutsui 				GETBITS(P2(sp), sb, lnum, tmp);
    884      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P2(dp));
    885      1.16   tsutsui 				GETBITS(P3(sp), sb, lnum, tmp);
    886      1.16   tsutsui 				PUTBITS(tmp, db, lnum, P3(dp));
    887       1.1  nisimura 			}
    888       1.1  nisimura 
    889       1.1  nisimura 			sp = (sq += scanspan);
    890       1.1  nisimura 			dp = (dq += scanspan);
    891       1.1  nisimura 			height--;
    892       1.1  nisimura 		}
    893       1.1  nisimura 	}
    894       1.1  nisimura }
    895       1.1  nisimura 
    896       1.1  nisimura /*
    897       1.1  nisimura  * Map a character.
    898       1.1  nisimura  */
    899       1.1  nisimura static int
    900       1.8       dsl om_mapchar(void *cookie, int c, u_int *cp)
    901       1.1  nisimura {
    902      1.13   tsutsui 	struct rasops_info *ri = cookie;
    903      1.13   tsutsui 	struct wsdisplay_font *wf = ri->ri_font;
    904      1.11   tsutsui 
    905      1.13   tsutsui 	if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
    906      1.13   tsutsui 		c = wsfont_map_unichar(wf, c);
    907      1.13   tsutsui 
    908      1.13   tsutsui 		if (c < 0)
    909      1.13   tsutsui 			goto fail;
    910       1.1  nisimura 	}
    911      1.13   tsutsui 	if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
    912      1.13   tsutsui 		goto fail;
    913      1.13   tsutsui 
    914      1.13   tsutsui 	*cp = c;
    915      1.13   tsutsui 	return 5;
    916      1.13   tsutsui 
    917      1.13   tsutsui  fail:
    918       1.1  nisimura 	*cp = ' ';
    919      1.11   tsutsui 	return 0;
    920       1.1  nisimura }
    921       1.1  nisimura 
    922       1.1  nisimura /*
    923       1.1  nisimura  * Position|{enable|disable} the cursor at the specified location.
    924       1.1  nisimura  */
    925       1.1  nisimura static void
    926      1.16   tsutsui om1_cursor(void *cookie, int on, int row, int col)
    927       1.1  nisimura {
    928      1.13   tsutsui 	struct rasops_info *ri = cookie;
    929       1.5   tsutsui 	uint8_t *p;
    930       1.1  nisimura 	int scanspan, startx, height, width, align, y;
    931      1.19   tsutsui 	uint32_t lmask, rmask;
    932       1.1  nisimura 
    933       1.1  nisimura 	if (!on) {
    934       1.1  nisimura 		/* make sure it's on */
    935      1.13   tsutsui 		if ((ri->ri_flg & RI_CURSOR) == 0)
    936       1.1  nisimura 			return;
    937       1.1  nisimura 
    938      1.13   tsutsui 		row = ri->ri_crow;
    939      1.13   tsutsui 		col = ri->ri_ccol;
    940       1.1  nisimura 	} else {
    941       1.1  nisimura 		/* unpaint the old copy. */
    942      1.13   tsutsui 		ri->ri_crow = row;
    943      1.13   tsutsui 		ri->ri_ccol = col;
    944       1.1  nisimura 	}
    945       1.1  nisimura 
    946      1.13   tsutsui 	scanspan = ri->ri_stride;
    947      1.13   tsutsui 	y = ri->ri_font->fontheight * row;
    948      1.13   tsutsui 	startx = ri->ri_font->fontwidth * col;
    949      1.13   tsutsui 	height = ri->ri_font->fontheight;
    950       1.1  nisimura 
    951      1.13   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    952       1.1  nisimura 	align = startx & ALIGNMASK;
    953      1.13   tsutsui 	width = ri->ri_font->fontwidth + align;
    954       1.1  nisimura 	lmask = ALL1BITS >> align;
    955       1.1  nisimura 	rmask = ALL1BITS << (-width & ALIGNMASK);
    956       1.1  nisimura 	if (width <= BLITWIDTH) {
    957       1.1  nisimura 		lmask &= rmask;
    958      1.19   tsutsui 		/* set lmask as ROP mask value, with INV2 mode */
    959      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
    960      1.19   tsutsui 
    961       1.1  nisimura 		while (height > 0) {
    962      1.19   tsutsui 			*P0(p) = ALL1BITS;
    963       1.1  nisimura 			p += scanspan;
    964       1.1  nisimura 			height--;
    965       1.1  nisimura 		}
    966      1.19   tsutsui 		/* reset mask value */
    967      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    968      1.11   tsutsui 	} else {
    969       1.5   tsutsui 		uint8_t *q = p;
    970       1.1  nisimura 
    971       1.1  nisimura 		while (height > 0) {
    972      1.19   tsutsui 			/* set lmask as ROP mask value, with INV2 mode */
    973      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
    974      1.19   tsutsui 			*W(p) = ALL1BITS;
    975      1.19   tsutsui 
    976       1.1  nisimura 			p += BYTESDONE;
    977      1.19   tsutsui 
    978      1.19   tsutsui 			/* set lmask as ROP mask value, with INV2 mode */
    979      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
    980      1.19   tsutsui 			*W(p) = ALL1BITS;
    981      1.16   tsutsui 
    982      1.16   tsutsui 			p = (q += scanspan);
    983      1.16   tsutsui 			height--;
    984      1.16   tsutsui 		}
    985      1.19   tsutsui 		/* reset mask value */
    986      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
    987      1.16   tsutsui 	}
    988      1.16   tsutsui 	ri->ri_flg ^= RI_CURSOR;
    989      1.16   tsutsui }
    990      1.16   tsutsui 
    991      1.16   tsutsui static void
    992      1.16   tsutsui om4_cursor(void *cookie, int on, int row, int col)
    993      1.16   tsutsui {
    994      1.16   tsutsui 	struct rasops_info *ri = cookie;
    995      1.16   tsutsui 	uint8_t *p;
    996      1.16   tsutsui 	int scanspan, startx, height, width, align, y;
    997      1.19   tsutsui 	uint32_t lmask, rmask;
    998      1.16   tsutsui 
    999      1.16   tsutsui 	if (!on) {
   1000      1.16   tsutsui 		/* make sure it's on */
   1001      1.16   tsutsui 		if ((ri->ri_flg & RI_CURSOR) == 0)
   1002      1.16   tsutsui 			return;
   1003      1.16   tsutsui 
   1004      1.16   tsutsui 		row = ri->ri_crow;
   1005      1.16   tsutsui 		col = ri->ri_ccol;
   1006      1.16   tsutsui 	} else {
   1007      1.16   tsutsui 		/* unpaint the old copy. */
   1008      1.16   tsutsui 		ri->ri_crow = row;
   1009      1.16   tsutsui 		ri->ri_ccol = col;
   1010      1.16   tsutsui 	}
   1011      1.16   tsutsui 
   1012      1.16   tsutsui 	scanspan = ri->ri_stride;
   1013      1.16   tsutsui 	y = ri->ri_font->fontheight * row;
   1014      1.16   tsutsui 	startx = ri->ri_font->fontwidth * col;
   1015      1.16   tsutsui 	height = ri->ri_font->fontheight;
   1016      1.16   tsutsui 
   1017      1.16   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
   1018      1.16   tsutsui 	align = startx & ALIGNMASK;
   1019      1.16   tsutsui 	width = ri->ri_font->fontwidth + align;
   1020      1.16   tsutsui 	lmask = ALL1BITS >> align;
   1021      1.16   tsutsui 	rmask = ALL1BITS << (-width & ALIGNMASK);
   1022      1.19   tsutsui 
   1023      1.19   tsutsui 	/* select all planes for later ROP function target */
   1024      1.19   tsutsui 	*(volatile uint32_t *)OMFB_PLANEMASK = 0xff;
   1025      1.19   tsutsui 
   1026      1.16   tsutsui 	if (width <= BLITWIDTH) {
   1027      1.16   tsutsui 		lmask &= rmask;
   1028      1.19   tsutsui 		/* set lmask as ROP mask value, with INV2 mode */
   1029      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
   1030      1.19   tsutsui 
   1031      1.16   tsutsui 		while (height > 0) {
   1032      1.19   tsutsui 			*W(p) = ALL1BITS;
   1033      1.16   tsutsui 			p += scanspan;
   1034      1.16   tsutsui 			height--;
   1035      1.16   tsutsui 		}
   1036      1.19   tsutsui 		/* reset mask value */
   1037      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
   1038      1.16   tsutsui 	} else {
   1039      1.16   tsutsui 		uint8_t *q = p;
   1040      1.16   tsutsui 
   1041      1.16   tsutsui 		while (height > 0) {
   1042      1.19   tsutsui 			/* set lmask as ROP mask value, with INV2 mode */
   1043      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
   1044      1.19   tsutsui 			*W(p) = ALL1BITS;
   1045      1.19   tsutsui 
   1046      1.16   tsutsui 			p += BYTESDONE;
   1047      1.19   tsutsui 
   1048      1.19   tsutsui 			/* set rmask as ROP mask value, with INV2 mode */
   1049      1.19   tsutsui 			((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
   1050      1.19   tsutsui 			*W(p) = ALL1BITS;
   1051       1.1  nisimura 
   1052       1.1  nisimura 			p = (q += scanspan);
   1053       1.1  nisimura 			height--;
   1054       1.1  nisimura 		}
   1055      1.19   tsutsui 		/* reset mask value */
   1056      1.19   tsutsui 		((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
   1057       1.1  nisimura 	}
   1058      1.19   tsutsui 	/* select plane #0 only; XXX need this ? */
   1059      1.19   tsutsui 	*(volatile uint32_t *)OMFB_PLANEMASK = 0x01;
   1060      1.19   tsutsui 
   1061      1.13   tsutsui 	ri->ri_flg ^= RI_CURSOR;
   1062       1.1  nisimura }
   1063       1.1  nisimura 
   1064       1.1  nisimura /*
   1065       1.1  nisimura  * Allocate attribute. We just pack these into an integer.
   1066       1.1  nisimura  */
   1067       1.1  nisimura static int
   1068      1.16   tsutsui om1_allocattr(void *id, int fg, int bg, int flags, long *attrp)
   1069       1.1  nisimura {
   1070      1.11   tsutsui 
   1071      1.16   tsutsui 	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
   1072      1.16   tsutsui 	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
   1073      1.11   tsutsui 		return EINVAL;
   1074      1.16   tsutsui 	if ((flags & WSATTR_REVERSE) != 0)
   1075       1.1  nisimura 		*attrp = 1;
   1076       1.1  nisimura 	else
   1077       1.1  nisimura 		*attrp = 0;
   1078      1.11   tsutsui 	return 0;
   1079       1.1  nisimura }
   1080       1.1  nisimura 
   1081      1.16   tsutsui static int
   1082      1.16   tsutsui om4_allocattr(void *id, int fg, int bg, int flags, long *attrp)
   1083      1.16   tsutsui {
   1084      1.16   tsutsui 
   1085      1.16   tsutsui 	if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
   1086      1.16   tsutsui 		return EINVAL;
   1087      1.16   tsutsui 	if ((flags & WSATTR_WSCOLORS) == 0) {
   1088      1.16   tsutsui 		fg = WSCOL_WHITE;
   1089      1.16   tsutsui 		bg = WSCOL_BLACK;
   1090      1.16   tsutsui 	}
   1091      1.16   tsutsui 
   1092      1.16   tsutsui 	if ((flags & WSATTR_REVERSE) != 0) {
   1093      1.16   tsutsui 		int swap;
   1094      1.16   tsutsui 		swap = fg;
   1095      1.16   tsutsui 		fg = bg;
   1096      1.16   tsutsui 		bg = swap;
   1097      1.16   tsutsui 	}
   1098      1.16   tsutsui 
   1099      1.16   tsutsui 	if ((flags & WSATTR_HILIT) != 0)
   1100      1.16   tsutsui 		fg += 8;
   1101      1.16   tsutsui 
   1102      1.16   tsutsui 	*attrp = (fg << 24) | (bg << 16);
   1103      1.16   tsutsui 	return 0;
   1104      1.16   tsutsui }
   1105      1.16   tsutsui 
   1106      1.17   tsutsui static void
   1107      1.17   tsutsui om4_unpack_attr(long attr, int *fg, int *bg, int *underline)
   1108      1.17   tsutsui {
   1109      1.17   tsutsui 
   1110      1.17   tsutsui 	*fg = ((u_int)attr >> 24) & 0xf;
   1111      1.17   tsutsui 	*bg = ((u_int)attr >> 16) & 0xf;
   1112      1.17   tsutsui }
   1113      1.17   tsutsui 
   1114      1.13   tsutsui /*
   1115      1.13   tsutsui  * Init subset of rasops(9) for omrasops.
   1116      1.13   tsutsui  */
   1117      1.13   tsutsui int
   1118      1.16   tsutsui omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
   1119      1.16   tsutsui {
   1120      1.16   tsutsui 
   1121      1.16   tsutsui 	omrasops_init(ri, wantrows, wantcols);
   1122      1.16   tsutsui 
   1123      1.16   tsutsui 	/* fill our own emulops */
   1124      1.16   tsutsui 	ri->ri_ops.cursor    = om1_cursor;
   1125      1.16   tsutsui 	ri->ri_ops.mapchar   = om_mapchar;
   1126      1.16   tsutsui 	ri->ri_ops.putchar   = om1_putchar;
   1127      1.16   tsutsui 	ri->ri_ops.copycols  = om1_copycols;
   1128      1.16   tsutsui 	ri->ri_ops.erasecols = om1_erasecols;
   1129      1.16   tsutsui 	ri->ri_ops.copyrows  = om1_copyrows;
   1130      1.16   tsutsui 	ri->ri_ops.eraserows = om1_eraserows;
   1131      1.16   tsutsui 	ri->ri_ops.allocattr = om1_allocattr;
   1132      1.16   tsutsui 	ri->ri_caps = WSSCREEN_REVERSE;
   1133      1.16   tsutsui 
   1134      1.16   tsutsui 	ri->ri_flg |= RI_CFGDONE;
   1135      1.16   tsutsui 
   1136      1.16   tsutsui 	return 0;
   1137      1.16   tsutsui }
   1138      1.16   tsutsui 
   1139      1.16   tsutsui int
   1140      1.16   tsutsui omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
   1141      1.16   tsutsui {
   1142      1.16   tsutsui 
   1143      1.16   tsutsui 	omrasops_init(ri, wantrows, wantcols);
   1144      1.16   tsutsui 
   1145      1.16   tsutsui 	/* fill our own emulops */
   1146      1.16   tsutsui 	ri->ri_ops.cursor    = om4_cursor;
   1147      1.16   tsutsui 	ri->ri_ops.mapchar   = om_mapchar;
   1148      1.16   tsutsui 	ri->ri_ops.putchar   = om4_putchar;
   1149      1.16   tsutsui 	ri->ri_ops.copycols  = om4_copycols;
   1150      1.16   tsutsui 	ri->ri_ops.erasecols = om4_erasecols;
   1151      1.16   tsutsui 	ri->ri_ops.copyrows  = om4_copyrows;
   1152      1.16   tsutsui 	ri->ri_ops.eraserows = om4_eraserows;
   1153      1.16   tsutsui 	ri->ri_ops.allocattr = om4_allocattr;
   1154      1.16   tsutsui 	ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
   1155      1.16   tsutsui 
   1156      1.16   tsutsui 	ri->ri_flg |= RI_CFGDONE;
   1157      1.16   tsutsui 
   1158      1.16   tsutsui 	return 0;
   1159      1.16   tsutsui }
   1160      1.16   tsutsui 
   1161      1.16   tsutsui static int
   1162      1.13   tsutsui omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
   1163       1.1  nisimura {
   1164      1.13   tsutsui 	int wsfcookie, bpp;
   1165      1.13   tsutsui 
   1166      1.13   tsutsui 	if (wantrows == 0)
   1167      1.13   tsutsui 		wantrows = 34;
   1168      1.13   tsutsui 	if (wantrows < 10)
   1169      1.13   tsutsui 		wantrows = 10;
   1170      1.13   tsutsui 	if (wantcols == 0)
   1171      1.13   tsutsui 		wantcols = 80;
   1172      1.13   tsutsui 	if (wantcols < 20)
   1173      1.13   tsutsui 		wantcols = 20;
   1174      1.13   tsutsui 
   1175      1.13   tsutsui 	/* Use default font */
   1176      1.13   tsutsui 	wsfont_init();
   1177      1.13   tsutsui 	wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
   1178      1.13   tsutsui 	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
   1179      1.13   tsutsui 	if (wsfcookie < 0)
   1180      1.13   tsutsui 		panic("%s: no font available", __func__);
   1181      1.13   tsutsui 	if (wsfont_lock(wsfcookie, &ri->ri_font))
   1182      1.13   tsutsui 		panic("%s: unable to lock font", __func__);
   1183      1.13   tsutsui 	ri->ri_wsfcookie = wsfcookie;
   1184      1.13   tsutsui 
   1185      1.13   tsutsui 	KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
   1186      1.13   tsutsui 
   1187      1.16   tsutsui 	/* all planes are independently addressed */
   1188      1.16   tsutsui 	bpp = 1;
   1189      1.13   tsutsui 
   1190      1.13   tsutsui 	/* Now constrain what they get */
   1191      1.13   tsutsui 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
   1192      1.13   tsutsui 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
   1193      1.13   tsutsui 	if (ri->ri_emuwidth > ri->ri_width)
   1194      1.13   tsutsui 		ri->ri_emuwidth = ri->ri_width;
   1195      1.13   tsutsui 	if (ri->ri_emuheight > ri->ri_height)
   1196      1.13   tsutsui 		ri->ri_emuheight = ri->ri_height;
   1197      1.13   tsutsui 
   1198      1.13   tsutsui 	/* Reduce width until aligned on a 32-bit boundary */
   1199      1.13   tsutsui 	while ((ri->ri_emuwidth * bpp & 31) != 0)
   1200      1.13   tsutsui 		ri->ri_emuwidth--;
   1201      1.13   tsutsui 
   1202      1.13   tsutsui 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
   1203      1.13   tsutsui 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
   1204      1.13   tsutsui 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
   1205      1.13   tsutsui 	ri->ri_ccol = 0;
   1206      1.13   tsutsui 	ri->ri_crow = 0;
   1207      1.13   tsutsui 	ri->ri_pelbytes = bpp >> 3;
   1208      1.13   tsutsui 
   1209      1.13   tsutsui 	ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
   1210      1.13   tsutsui 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
   1211      1.13   tsutsui 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
   1212      1.13   tsutsui 
   1213      1.13   tsutsui 	/* Clear the entire display */
   1214      1.13   tsutsui 	if ((ri->ri_flg & RI_CLEAR) != 0)
   1215      1.13   tsutsui 		memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
   1216      1.13   tsutsui 
   1217      1.13   tsutsui 	/* Now centre our window if needs be */
   1218      1.13   tsutsui 	ri->ri_origbits = ri->ri_bits;
   1219      1.13   tsutsui 
   1220      1.13   tsutsui 	if ((ri->ri_flg & RI_CENTER) != 0) {
   1221      1.13   tsutsui 		ri->ri_bits += (((ri->ri_width * bpp >> 3) -
   1222      1.13   tsutsui 		    ri->ri_emustride) >> 1) & ~3;
   1223      1.13   tsutsui 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
   1224      1.13   tsutsui 		    ri->ri_stride;
   1225      1.13   tsutsui 		ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
   1226      1.13   tsutsui 		   / ri->ri_stride;
   1227      1.13   tsutsui 		ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
   1228      1.13   tsutsui 		   % ri->ri_stride) * 8 / bpp);
   1229      1.13   tsutsui 	} else
   1230      1.13   tsutsui 		ri->ri_xorigin = ri->ri_yorigin = 0;
   1231      1.13   tsutsui 
   1232      1.13   tsutsui 	return 0;
   1233       1.1  nisimura }
   1234