Module Name:    src
Committed By:   tsutsui
Date:           Sat Dec 28 09:17:23 UTC 2013

Modified Files:
        src/sys/arch/luna68k/dev: lunafb.c omrasops.c omrasopsvar.h

Log Message:
Add preleminary support of 4bpp LUNA framebuffer.

Changes details:
- prepare and switch 4bpp rasops functions that read/write all 4 planes
  and also handle both fg and bg colors
- make 1bpp ops use first plane on write rather than common bitmap plane
  (which is prepared for multiple plane write with raster ops)
- prepare 4bpp allocattr function to handle ANSI 16 color text
- split omrasops_init() function for each bpp
- move struct hwcmap from softc to hwdevconfig to sync palette values
  on initialization
- allow mmap(2) against all available planes

Now we can use ANSI 16 color text console and also can
demonstrate mlterm-fb with color sixel graphics and wallpaper.
XXX: Xserver needs much more work.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/luna68k/dev/lunafb.c
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/luna68k/dev/omrasops.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/luna68k/dev/omrasopsvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/luna68k/dev/lunafb.c
diff -u src/sys/arch/luna68k/dev/lunafb.c:1.28 src/sys/arch/luna68k/dev/lunafb.c:1.29
--- src/sys/arch/luna68k/dev/lunafb.c:1.28	Sat Dec 14 19:51:13 2013
+++ src/sys/arch/luna68k/dev/lunafb.c	Sat Dec 28 09:17:23 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: lunafb.c,v 1.28 2013/12/14 19:51:13 tsutsui Exp $ */
+/* $NetBSD: lunafb.c,v 1.29 2013/12/28 09:17:23 tsutsui Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: lunafb.c,v 1.28 2013/12/14 19:51:13 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lunafb.c,v 1.29 2013/12/28 09:17:23 tsutsui Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -82,27 +82,50 @@ struct bt458 {
 #define	OMFB_RAMDAC	0xC1100000	/* Bt454/Bt458 RAMDAC */
 #define	OMFB_SIZE	(0xB1300000 - 0xB1080000 + PAGE_SIZE)
 
+struct hwcmap {
+#define CMAP_SIZE 256
+	uint8_t r[CMAP_SIZE];
+	uint8_t g[CMAP_SIZE];
+	uint8_t b[CMAP_SIZE];
+};
+
+static const struct {
+	uint8_t r;
+	uint8_t g;
+	uint8_t b;
+} ansicmap[16] = {
+	{    0,    0,    0},
+	{ 0x80,    0,    0},
+	{    0, 0x80,    0},
+	{ 0x80, 0x80,    0},
+	{    0,    0, 0x80},
+	{ 0x80,    0, 0x80},
+	{    0, 0x80, 0x80},
+	{ 0xc0, 0xc0, 0xc0},
+	{ 0x80, 0x80, 0x80},
+	{ 0xff,    0,    0},
+	{    0, 0xff,    0},
+	{ 0xff, 0xff,    0},
+	{    0,    0, 0xff},
+	{ 0xff,    0, 0xff},
+	{    0, 0xff, 0xff},
+	{ 0xff, 0xff, 0xff},
+};
+
 struct om_hwdevconfig {
 	int	dc_wid;			/* width of frame buffer */
 	int	dc_ht;			/* height of frame buffer */
 	int	dc_depth;		/* depth, bits per pixel */
 	int	dc_rowbytes;		/* bytes in a FB scan line */
 	int	dc_cmsize;		/* colormap size */
+	struct hwcmap dc_cmap;		/* software copy of colormap */
 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
 	struct rasops_info dc_ri;	/* raster blitter variables */
 };
 
-struct hwcmap {
-#define CMAP_SIZE 256
-	uint8_t r[CMAP_SIZE];
-	uint8_t g[CMAP_SIZE];
-	uint8_t b[CMAP_SIZE];
-};
-
 struct omfb_softc {
 	device_t sc_dev;		/* base device */
 	struct om_hwdevconfig *sc_dc;	/* device configuration */
-	struct hwcmap sc_cmap;		/* software copy of colormap */
 	int nscreens;
 };
 
@@ -188,10 +211,6 @@ omfbattach(device_t parent, device_t sel
 	aprint_normal(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
 	    sc->sc_dc->dc_depth);
 
-	/* WHITE on BLACK */
-	memset(&sc->sc_cmap, 255, sizeof(struct hwcmap));
-	sc->sc_cmap.r[0] = sc->sc_cmap.g[0] = sc->sc_cmap.b[0] = 0;
-
 	waa.console = omfb_console;
 	waa.scrdata = &omfb_screenlist;
 	waa.accessops = &omfb_accessops;
@@ -271,7 +290,7 @@ omfbmmap(void *v, void *vs, off_t offset
 	if (offset >= 0 && offset < OMFB_SIZE)
 		cookie = m68k_btop(m68k_trunc_page(dc->dc_videobase) + offset);
 #else
-	if (offset >= 0 && offset < dc->dc_rowbytes * dc->dc_ht)
+	if (offset >= 0 && offset < dc->dc_rowbytes * dc->dc_ht * dc->dc_depth)
 		cookie = m68k_btop(m68k_trunc_page(OMFB_FB_RADDR) + offset);
 #endif
 
@@ -288,13 +307,13 @@ omgetcmap(struct omfb_softc *sc, struct 
 	if (index >= cmsize || count > cmsize - index)
 		return EINVAL;
 
-	error = copyout(&sc->sc_cmap.r[index], p->red, count);
+	error = copyout(&sc->sc_dc->dc_cmap.r[index], p->red, count);
 	if (error)
 		return error;
-	error = copyout(&sc->sc_cmap.g[index], p->green, count);
+	error = copyout(&sc->sc_dc->dc_cmap.g[index], p->green, count);
 	if (error)
 		return error;
-	error = copyout(&sc->sc_cmap.b[index], p->blue, count);
+	error = copyout(&sc->sc_dc->dc_cmap.b[index], p->blue, count);
 	return error;
 }
 
@@ -319,24 +338,24 @@ omsetcmap(struct omfb_softc *sc, struct 
 	if (error)
 		return error;
 
-	memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
-	memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
-	memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
+	memcpy(&sc->sc_dc->dc_cmap.r[index], &cmap.r[index], count);
+	memcpy(&sc->sc_dc->dc_cmap.g[index], &cmap.g[index], count);
+	memcpy(&sc->sc_dc->dc_cmap.b[index], &cmap.b[index], count);
 	if (hwplanemask == 0x0f) {
 		struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
 		odac->bt_addr = index;
 		for (i = index; i < index + count; i++) {
-			odac->bt_cmap = sc->sc_cmap.r[i];
-			odac->bt_cmap = sc->sc_cmap.g[i];
-			odac->bt_cmap = sc->sc_cmap.b[i];
+			odac->bt_cmap = sc->sc_dc->dc_cmap.r[i];
+			odac->bt_cmap = sc->sc_dc->dc_cmap.g[i];
+			odac->bt_cmap = sc->sc_dc->dc_cmap.b[i];
 		}
 	} else if (hwplanemask == 0xff) {
 		struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
 		ndac->bt_addr = index;
 		for (i = index; i < index + count; i++) {
-			ndac->bt_cmap = sc->sc_cmap.r[i];
-			ndac->bt_cmap = sc->sc_cmap.g[i];
-			ndac->bt_cmap = sc->sc_cmap.b[i];
+			ndac->bt_cmap = sc->sc_dc->dc_cmap.r[i];
+			ndac->bt_cmap = sc->sc_dc->dc_cmap.g[i];
+			ndac->bt_cmap = sc->sc_dc->dc_cmap.b[i];
 		}
 	}
 	return 0;
@@ -358,7 +377,7 @@ omfb_getdevconfig(paddr_t paddr, struct 
 		break;
 	default:
 	case 0x0f:
-#if 0
+#if 1
 		/*
 		 * XXX
 		 * experiment resulted in WHITE on SKYBLUE after Xorg server
@@ -389,28 +408,25 @@ omfb_getdevconfig(paddr_t paddr, struct 
 		 */
 		odac->bt_addr = 0;
 		for (i = 0; i < 15; i++) {
-			odac->bt_cmap = 0;
-			odac->bt_cmap = 0;
-			odac->bt_cmap = 0;
+			odac->bt_cmap = dc->dc_cmap.r[i] = 0;
+			odac->bt_cmap = dc->dc_cmap.g[i] = 0;
+			odac->bt_cmap = dc->dc_cmap.b[i] = 0;
 		}
 		/*
 		 * The B/W video connector is connected to IOG of Bt454,
 		 * and IOR and IOB are unused.
 		 */
-		odac->bt_cmap = 0;
-		odac->bt_cmap = 255;
-		odac->bt_cmap = 0;
+		odac->bt_cmap = dc->dc_cmap.r[15] = 0;
+		odac->bt_cmap = dc->dc_cmap.g[15] = 255;
+		odac->bt_cmap = dc->dc_cmap.b[15] = 0;
 	} else if (hwplanemask == 0x0f) {
 		struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
 
 		odac->bt_addr = 0;
-		odac->bt_cmap = 0;
-		odac->bt_cmap = 0;
-		odac->bt_cmap = 0;
-		for (i = 1; i < 16; i++) {
-			odac->bt_cmap = 255;
-			odac->bt_cmap = 255;
-			odac->bt_cmap = 255;
+		for (i = 0; i < 16; i++) {
+			odac->bt_cmap = dc->dc_cmap.r[i] = ansicmap[i].r;
+			odac->bt_cmap = dc->dc_cmap.g[i] = ansicmap[i].g;
+			odac->bt_cmap = dc->dc_cmap.b[i] = ansicmap[i].b;
 		}
 	} else if (hwplanemask == 0xff) {
 		struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
@@ -421,13 +437,13 @@ omfb_getdevconfig(paddr_t paddr, struct 
 		ndac->bt_ctrl = 0x43; /* pallete enabled, ovly plane */
 		ndac->bt_ctrl = 0x00; /* no test mode */
 		ndac->bt_addr = 0;
-		ndac->bt_cmap = 0;
-		ndac->bt_cmap = 0;
-		ndac->bt_cmap = 0;
+		ndac->bt_cmap = dc->dc_cmap.r[0] = 0;
+		ndac->bt_cmap = dc->dc_cmap.g[0] = 0;
+		ndac->bt_cmap = dc->dc_cmap.b[0] = 0;
 		for (i = 1; i < 256; i++) {
-			ndac->bt_cmap = 255;
-			ndac->bt_cmap = 255;
-			ndac->bt_cmap = 255;
+			ndac->bt_cmap = dc->dc_cmap.r[i] = 255;
+			ndac->bt_cmap = dc->dc_cmap.g[i] = 255;
+			ndac->bt_cmap = dc->dc_cmap.b[i] = 255;
 		}
 	}
 
@@ -456,7 +472,10 @@ omfb_getdevconfig(paddr_t paddr, struct 
 		ri->ri_flg |= RI_NO_AUTO;
 	ri->ri_hw = dc;
 
-	omrasops_init(ri, 34, 80);
+	if (bpp == 4)
+		omrasops4_init(ri, 34, 80);
+	else
+		omrasops1_init(ri, 34, 80);
 
 	omfb_stdscreen.nrows = ri->ri_rows;
 	omfb_stdscreen.ncols = ri->ri_cols;

Index: src/sys/arch/luna68k/dev/omrasops.c
diff -u src/sys/arch/luna68k/dev/omrasops.c:1.15 src/sys/arch/luna68k/dev/omrasops.c:1.16
--- src/sys/arch/luna68k/dev/omrasops.c:1.15	Sat Dec 14 19:27:41 2013
+++ src/sys/arch/luna68k/dev/omrasops.c	Sat Dec 28 09:17:23 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: omrasops.c,v 1.15 2013/12/14 19:27:41 tsutsui Exp $ */
+/* $NetBSD: omrasops.c,v 1.16 2013/12/28 09:17:23 tsutsui Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.15 2013/12/14 19:27:41 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.16 2013/12/28 09:17:23 tsutsui Exp $");
 
 /*
  * Designed speficically for 'm68k bitorder';
@@ -53,14 +53,23 @@ __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v
 #include <arch/luna68k/dev/omrasopsvar.h>
 
 /* wscons emulator operations */
-static void	om_cursor(void *, int, int, int);
+static void	om1_cursor(void *, int, int, int);
+static void	om4_cursor(void *, int, int, int);
 static int	om_mapchar(void *, int, unsigned int *);
-static void	om_putchar(void *, int, int, u_int, long);
-static void	om_copycols(void *, int, int, int, int);
-static void	om_copyrows(void *, int, int, int num);
-static void	om_erasecols(void *, int, int, int, long);
-static void	om_eraserows(void *, int, int, long);
-static int	om_allocattr(void *, int, int, int, long *);
+static void	om1_putchar(void *, int, int, u_int, long);
+static void	om4_putchar(void *, int, int, u_int, long);
+static void	om1_copycols(void *, int, int, int, int);
+static void	om4_copycols(void *, int, int, int, int);
+static void	om1_copyrows(void *, int, int, int num);
+static void	om4_copyrows(void *, int, int, int num);
+static void	om1_erasecols(void *, int, int, int, long);
+static void	om4_erasecols(void *, int, int, int, long);
+static void	om1_eraserows(void *, int, int, long);
+static void	om4_eraserows(void *, int, int, long);
+static int	om1_allocattr(void *, int, int, int, long *);
+static int	om4_allocattr(void *, int, int, int, long *);
+
+static int	omrasops_init(struct rasops_info *, int, int);
 
 #define	ALL1BITS	(~0U)
 #define	ALL0BITS	(0U)
@@ -70,6 +79,10 @@ static int	om_allocattr(void *, int, int
 
 #define	W(p) (*(uint32_t *)(p))
 #define	R(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
+#define	P0(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
+#define	P1(p) (*(uint32_t *)((uint8_t *)(p) + 0x80000))
+#define	P2(p) (*(uint32_t *)((uint8_t *)(p) + 0xc0000))
+#define	P3(p) (*(uint32_t *)((uint8_t *)(p) + 0x100000))
 
 /*
  * macros to handle unaligned bit copy ops.
@@ -82,19 +95,15 @@ static int	om_allocattr(void *, int, int
 #define	FASTGETBITS(psrc, x, w, dst)					\
 	asm("bfextu %3{%1:%2},%0"					\
 	    : "=d" (dst) 						\
-	    : "di" (x), "di" (w), "o" R(psrc))
+	    : "di" (x), "di" (w), "o" ((uint32_t *)(psrc)))
 
 /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
 /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
 #define	FASTPUTBITS(src, x, w, pdst)					\
-do {									\
-	uint32_t __tmp;							\
-	__tmp = R(pdst);						\
 	asm("bfins %3,%0{%1:%2}"					\
-	    : "+d" (__tmp)						\
-	    : "di" (x), "di" (w), "d" (src));				\
-	W(pdst) = __tmp;						\
-} while (/* CONSTCOND */0)
+	    : "+o" ((uint32_t *)(pdst))					\
+	    : "di" (x), "di" (w), "d" (src)				\
+	    : "memory" );
 
 #define	GETBITS(psrc, x, w, dst)	FASTGETBITS(psrc, x, w, dst)
 #define	PUTBITS(src, x, w, pdst)	FASTPUTBITS(src, x, w, pdst)
@@ -103,7 +112,7 @@ do {									\
  * Blit a character at the specified co-ordinates.
  */
 static void
-om_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
+om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *p;
@@ -118,7 +127,7 @@ om_putchar(void *cookie, int row, int st
 	height = ri->ri_font->fontheight;
 	fb = (uint8_t *)ri->ri_font->data +
 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
-	inverse = (attr != 0) ? ALL1BITS : ALL0BITS;
+	inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
 
 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
 	align = startx & ALIGNMASK;
@@ -133,7 +142,7 @@ om_putchar(void *cookie, int row, int st
 				glyph = (glyph << 8) | *fb++;
 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
 			glyph = (glyph >> align) ^ inverse;
-			W(p) = (R(p) & ~lmask) | (glyph & lmask);
+			P0(p) = (P0(p) & ~lmask) | (glyph & lmask);
 			p += scanspan;
 			height--;
 		}
@@ -147,10 +156,103 @@ om_putchar(void *cookie, int row, int st
 				glyph = (glyph << 8) | *fb++;
 			glyph <<= (4 - ri->ri_font->stride) * NBBY;
 			lhalf = (glyph >> align) ^ inverse;
-			W(p) = (R(p) & ~lmask) | (lhalf & lmask);
+			P0(p) = (P0(p) & ~lmask) | (lhalf & lmask);
 			p += BYTESDONE;
 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
-			W(p) = (rhalf & rmask) | (R(p) & ~rmask);
+			P0(p) = (rhalf & rmask) | (P0(p) & ~rmask);
+
+			p = (q += scanspan);
+			height--;
+		}
+	}
+}
+
+static void
+om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *p;
+	int scanspan, startx, height, width, align, y;
+	uint32_t lmask, rmask, glyph;
+	uint32_t glyphbg, fg, bg;
+	int i;
+	uint8_t *fb;
+
+	scanspan = ri->ri_stride;
+	y = ri->ri_font->fontheight * row;
+	startx = ri->ri_font->fontwidth * startcol;
+	height = ri->ri_font->fontheight;
+	fb = (uint8_t *)ri->ri_font->data +
+	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
+
+	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
+	align = startx & ALIGNMASK;
+	width = ri->ri_font->fontwidth + align;
+	lmask = ALL1BITS >> align;
+	rmask = ALL1BITS << (-width & ALIGNMASK);
+	if (width <= BLITWIDTH) {
+		lmask &= rmask;
+		while (height > 0) {
+			glyph = 0;
+			for (i = ri->ri_font->stride; i != 0; i--)
+				glyph = (glyph << 8) | *fb++;
+			glyph <<= (4 - ri->ri_font->stride) * NBBY;
+			glyph = (glyph >> align);
+			glyphbg = glyph ^ ALL1BITS;
+			fg = (attr & 0x01000000) ? glyph : 0;
+			bg = (attr & 0x00010000) ? glyphbg : 0;
+			P0(p) = (P0(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x02000000) ? glyph : 0;
+			bg = (attr & 0x00020000) ? glyphbg : 0;
+			P1(p) = (P1(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x04000000) ? glyph : 0;
+			bg = (attr & 0x00040000) ? glyphbg : 0;
+			P2(p) = (P2(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x08000000) ? glyph : 0;
+			bg = (attr & 0x00080000) ? glyphbg : 0;
+			P3(p) = (P3(p) & ~lmask) | ((fg | bg) & lmask);
+			p += scanspan;
+			height--;
+		}
+	} else {
+		uint8_t *q = p;
+		uint32_t lhalf, rhalf;
+		uint32_t lhalfbg, rhalfbg;
+
+		while (height > 0) {
+			glyph = 0;
+			for (i = ri->ri_font->stride; i != 0; i--)
+				glyph = (glyph << 8) | *fb++;
+			glyph <<= (4 - ri->ri_font->stride) * NBBY;
+			lhalf = (glyph >> align);
+			lhalfbg = lhalf ^ ALL1BITS;
+			fg = (attr & 0x01000000) ? lhalf : 0;
+			bg = (attr & 0x00010000) ? lhalfbg : 0;
+			P0(p) = (P0(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x02000000) ? lhalf : 0;
+			bg = (attr & 0x00020000) ? lhalfbg : 0;
+			P1(p) = (P1(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x04000000) ? lhalf : 0;
+			bg = (attr & 0x00040000) ? lhalfbg : 0;
+			P2(p) = (P2(p) & ~lmask) | ((fg | bg) & lmask);
+			fg = (attr & 0x08000000) ? lhalf : 0;
+			bg = (attr & 0x00080000) ? lhalfbg : 0;
+			P3(p) = (P3(p) & ~lmask) | ((fg | bg) & lmask);
+			p += BYTESDONE;
+			rhalf = (glyph << (BLITWIDTH - align));
+			rhalfbg = rhalf ^ ALL1BITS;
+			fg = (attr & 0x01000000) ? rhalf : 0;
+			bg = (attr & 0x00010000) ? rhalfbg : 0;
+			P0(p) = ((fg | bg) & rmask) | (P0(p) & ~rmask);
+			fg = (attr & 0x02000000) ? rhalf : 0;
+			bg = (attr & 0x00020000) ? rhalfbg : 0;
+			P1(p) = ((fg | bg) & rmask) | (P1(p) & ~rmask);
+			fg = (attr & 0x04000000) ? rhalf : 0;
+			bg = (attr & 0x00040000) ? rhalfbg : 0;
+			P2(p) = ((fg | bg) & rmask) | (P2(p) & ~rmask);
+			fg = (attr & 0x08000000) ? rhalf : 0;
+			bg = (attr & 0x00080000) ? rhalfbg : 0;
+			P3(p) = ((fg | bg) & rmask) | (P3(p) & ~rmask);
 
 			p = (q += scanspan);
 			height--;
@@ -159,7 +261,7 @@ om_putchar(void *cookie, int row, int st
 }
 
 static void
-om_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
+om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *p;
@@ -167,12 +269,11 @@ om_erasecols(void *cookie, int row, int 
 	uint32_t lmask, rmask, fill;
 
 	scanspan = ri->ri_stride;;
-	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
 	y = ri->ri_font->fontheight * row;
 	startx = ri->ri_font->fontwidth * startcol;
 	height = ri->ri_font->fontheight;
 	w = ri->ri_font->fontwidth * ncols;
-	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
+	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
 
 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
 	align = startx & ALIGNMASK;
@@ -181,24 +282,24 @@ om_erasecols(void *cookie, int row, int 
 	rmask = ALL1BITS << (-width & ALIGNMASK);
 	if (width <= BLITWIDTH) {
 		lmask &= rmask;
-		fill &= lmask;
+		fill  &= lmask;
 		while (height > 0) {
-			W(p) = (R(p) & ~lmask) | fill;
+			P0(p) = (P0(p) & ~lmask) | fill;
 			p += scanspan;
 			height--;
 		}
 	} else {
 		uint8_t *q = p;
 		while (height > 0) {
-			W(p) = (R(p) & ~lmask) | (fill & lmask);
+			P0(p) = (P0(p) & ~lmask) | (fill & lmask);
 			width -= 2 * BLITWIDTH;
 			while (width > 0) {
 				p += BYTESDONE;
-				W(p) = fill;
+				P0(p) = fill;
 				width -= BLITWIDTH;
 			}
 			p += BYTESDONE;
-			W(p) = (fill & rmask) | (R(p) & ~rmask);
+			P0(p) = (fill & rmask) | (P0(p) & ~rmask);
 
 			p = (q += scanspan);
 			width = w + align;
@@ -208,7 +309,73 @@ om_erasecols(void *cookie, int row, int 
 }
 
 static void
-om_eraserows(void *cookie, int startrow, int nrows, long attr)
+om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *p;
+	int scanspan, startx, height, width, align, w, y;
+	uint32_t lmask, rmask, fill0, fill1, fill2, fill3;
+
+	scanspan = ri->ri_stride;;
+	y = ri->ri_font->fontheight * row;
+	startx = ri->ri_font->fontwidth * startcol;
+	height = ri->ri_font->fontheight;
+	w = ri->ri_font->fontwidth * ncols;
+	fill0 = ((attr & 0x00010000) != 0) ? ALL1BITS : ALL0BITS;
+	fill1 = ((attr & 0x00020000) != 0) ? ALL1BITS : ALL0BITS;
+	fill2 = ((attr & 0x00040000) != 0) ? ALL1BITS : ALL0BITS;
+	fill3 = ((attr & 0x00080000) != 0) ? ALL1BITS : ALL0BITS;
+
+	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
+	align = startx & ALIGNMASK;
+	width = w + align;
+	lmask = ALL1BITS >> align;
+	rmask = ALL1BITS << (-width & ALIGNMASK);
+	if (width <= BLITWIDTH) {
+		lmask &= rmask;
+		fill0 &= lmask;
+		fill1 &= lmask;
+		fill2 &= lmask;
+		fill3 &= lmask;
+		while (height > 0) {
+			P0(p) = (P0(p) & ~lmask) | fill0;
+			P1(p) = (P1(p) & ~lmask) | fill1;
+			P2(p) = (P2(p) & ~lmask) | fill2;
+			P3(p) = (P3(p) & ~lmask) | fill3;
+			p += scanspan;
+			height--;
+		}
+	} else {
+		uint8_t *q = p;
+		while (height > 0) {
+			P0(p) = (P0(p) & ~lmask) | (fill0 & lmask);
+			P1(p) = (P1(p) & ~lmask) | (fill1 & lmask);
+			P2(p) = (P2(p) & ~lmask) | (fill2 & lmask);
+			P3(p) = (P3(p) & ~lmask) | (fill3 & lmask);
+			width -= 2 * BLITWIDTH;
+			while (width > 0) {
+				p += BYTESDONE;
+				P0(p) = fill0;
+				P1(p) = fill1;
+				P2(p) = fill2;
+				P3(p) = fill3;
+				width -= BLITWIDTH;
+			}
+			p += BYTESDONE;
+			P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
+			P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
+			P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
+			P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
+
+			p = (q += scanspan);
+			width = w + align;
+			height--;
+		}
+	}
+}
+
+static void
+om1_eraserows(void *cookie, int startrow, int nrows, long attr)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *p, *q;
@@ -219,22 +386,22 @@ om_eraserows(void *cookie, int startrow,
 	starty = ri->ri_font->fontheight * startrow;
 	height = ri->ri_font->fontheight * nrows;
 	w = ri->ri_emuwidth;
-	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
+	fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
 
 	p = (uint8_t *)ri->ri_bits + starty * scanspan;
 	width = w;
 	rmask = ALL1BITS << (-width & ALIGNMASK);
 	q = p;
 	while (height > 0) {
-		W(p) = fill;				/* always aligned */
+		P0(p) = fill;				/* always aligned */
 		width -= 2 * BLITWIDTH;
 		while (width > 0) {
 			p += BYTESDONE;
-			W(p) = fill;
+			P0(p) = fill;
 			width -= BLITWIDTH;
 		}
 		p += BYTESDONE;
-		W(p) = (fill & rmask) | (R(p) & ~rmask);
+		P0(p) = (fill & rmask) | (P0(p) & ~rmask);
 		p = (q += scanspan);
 		width = w;
 		height--;
@@ -242,7 +409,53 @@ om_eraserows(void *cookie, int startrow,
 }
 
 static void
-om_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
+om4_eraserows(void *cookie, int startrow, int nrows, long attr)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *p, *q;
+	int scanspan, starty, height, width, w;
+	uint32_t rmask, fill0, fill1, fill2, fill3;
+
+	scanspan = ri->ri_stride;
+	starty = ri->ri_font->fontheight * startrow;
+	height = ri->ri_font->fontheight * nrows;
+	w = ri->ri_emuwidth;
+	fill0 = ((attr & 0x00010000) != 0) ? ALL1BITS : ALL0BITS;
+	fill1 = ((attr & 0x00020000) != 0) ? ALL1BITS : ALL0BITS;
+	fill2 = ((attr & 0x00040000) != 0) ? ALL1BITS : ALL0BITS;
+	fill3 = ((attr & 0x00080000) != 0) ? ALL1BITS : ALL0BITS;
+
+	p = (uint8_t *)ri->ri_bits + starty * scanspan;
+	width = w;
+	rmask = ALL1BITS << (-width & ALIGNMASK);
+	q = p;
+	while (height > 0) {
+		P0(p) = fill0;				/* always aligned */
+		P1(p) = fill1;
+		P2(p) = fill2;
+		P3(p) = fill3;
+		width -= 2 * BLITWIDTH;
+		while (width > 0) {
+			p += BYTESDONE;
+			P0(p) = fill0;
+			P1(p) = fill1;
+			P2(p) = fill2;
+			P3(p) = fill3;
+			width -= BLITWIDTH;
+		}
+		p += BYTESDONE;
+		P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
+		P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
+		P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
+		P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
+		p = (q += scanspan);
+		width = w;
+		height--;
+	}
+}
+
+static void
+om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *p, *q;
@@ -264,15 +477,15 @@ om_copyrows(void *cookie, int srcrow, in
 	rmask = ALL1BITS << (-width & ALIGNMASK);
 	q = p;
 	while (height > 0) {
-		W(p + offset) = R(p);			/* always aligned */
+		P0(p + offset) = P0(p);			/* always aligned */
 		width -= 2 * BLITWIDTH;
 		while (width > 0) {
 			p += BYTESDONE;
-			W(p + offset) = R(p);
+			P0(p + offset) = P0(p);
 			width -= BLITWIDTH;
 		}
 		p += BYTESDONE;
-		W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
+		P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
 
 		p = (q += scanspan);
 		width = w;
@@ -281,7 +494,185 @@ om_copyrows(void *cookie, int srcrow, in
 }
 
 static void
-om_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
+om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *p, *q;
+	int scanspan, offset, srcy, height, width, w;
+	uint32_t rmask;
+
+	scanspan = ri->ri_stride;
+	height = ri->ri_font->fontheight * nrows;
+	offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
+	srcy = ri->ri_font->fontheight * srcrow;
+	if (srcrow < dstrow && srcrow + nrows > dstrow) {
+		scanspan = -scanspan;
+		srcy = srcy + height - 1;
+	}
+
+	p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
+	w = ri->ri_emuwidth;
+	width = w;
+	rmask = ALL1BITS << (-width & ALIGNMASK);
+	q = p;
+	while (height > 0) {
+		P0(p + offset) = P0(p);			/* always aligned */
+		P1(p + offset) = P1(p);
+		P2(p + offset) = P2(p);
+		P3(p + offset) = P3(p);
+		width -= 2 * BLITWIDTH;
+		while (width > 0) {
+			p += BYTESDONE;
+			P0(p + offset) = P0(p);
+			P1(p + offset) = P1(p);
+			P2(p + offset) = P2(p);
+			P3(p + offset) = P3(p);
+			width -= BLITWIDTH;
+		}
+		p += BYTESDONE;
+		P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
+		P1(p + offset) = (P1(p) & rmask) | (P1(p + offset) & ~rmask);
+		P2(p + offset) = (P2(p) & rmask) | (P2(p + offset) & ~rmask);
+		P3(p + offset) = (P3(p) & rmask) | (P3(p + offset) & ~rmask);
+
+		p = (q += scanspan);
+		width = w;
+		height--;
+	}
+}
+
+static void
+om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *sp, *dp, *sq, *dq, *basep;
+	int scanspan, height, w, y, srcx, dstx;
+	int sb, eb, db, sboff, full, cnt, lnum, rnum;
+	uint32_t lmask, rmask, tmp;
+	bool sbover;
+
+	scanspan = ri->ri_stride;
+	y = ri->ri_font->fontheight * startrow;
+	srcx = ri->ri_font->fontwidth * srccol;
+	dstx = ri->ri_font->fontwidth * dstcol;
+	height = ri->ri_font->fontheight;
+	w = ri->ri_font->fontwidth * ncols;
+	basep = (uint8_t *)ri->ri_bits + y * scanspan;
+
+	sb = srcx & ALIGNMASK;
+	db = dstx & ALIGNMASK;
+
+	if (db + w <= BLITWIDTH) {
+		/* Destination is contained within a single word */
+		sp = basep + (srcx / 32) * 4;
+		dp = basep + (dstx / 32) * 4;
+
+		while (height > 0) {
+			GETBITS(P0(sp), sb, w, tmp);
+			PUTBITS(tmp, db, w, P0(dp));
+			dp += scanspan;
+			sp += scanspan;
+			height--;
+		}
+		return;
+	}
+
+	lmask = (db == 0) ? 0 : ALL1BITS >> db;
+	eb = (db + w) & ALIGNMASK;
+	rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb); 
+	lnum = (32 - db) & ALIGNMASK;
+	rnum = (dstx + w) & ALIGNMASK;
+
+	if (lmask != 0)
+		full = (w - (32 - db)) / 32;
+	else
+		full = w / 32;
+
+	sbover = (sb + lnum) >= 32;
+
+	if (dstcol < srccol || srccol + ncols < dstcol) {
+		/* copy forward (left-to-right) */
+		sp = basep + (srcx / 32) * 4;
+		dp = basep + (dstx / 32) * 4;
+
+		if (lmask != 0) {
+			sboff = sb + lnum;
+			if (sboff >= 32)
+				sboff -= 32;
+		} else
+			sboff = sb;
+
+		sq = sp;
+		dq = dp;
+		while (height > 0) {
+			if (lmask != 0) {
+				GETBITS(P0(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P0(dp));
+				dp += BYTESDONE;
+				if (sbover)
+					sp += BYTESDONE;
+			}
+
+			for (cnt = full; cnt; cnt--) {
+				GETBITS(P0(sp), sboff, 32, tmp);
+				P0(dp) = tmp;
+				sp += BYTESDONE;
+				dp += BYTESDONE;
+			}
+
+			if (rmask != 0) {
+				GETBITS(P0(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P0(dp));
+			}
+
+			sp = (sq += scanspan);
+			dp = (dq += scanspan);
+			height--;
+		}
+	} else {
+		/* copy backward (right-to-left) */
+		sp = basep + ((srcx + w) / 32) * 4;
+		dp = basep + ((dstx + w) / 32) * 4;
+
+		sboff = (srcx + w) & ALIGNMASK;
+		sboff -= rnum;
+		if (sboff < 0) {
+			sp -= BYTESDONE;
+			sboff += 32;
+		}
+
+		sq = sp;
+		dq = dp;
+		while (height > 0) {
+			if (rnum != 0) {
+				GETBITS(P0(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P0(dp));
+			}
+
+			for (cnt = full; cnt; cnt--) {
+				sp -= BYTESDONE;
+				dp -= BYTESDONE;
+				GETBITS(P0(sp), sboff, 32, tmp);
+				P0(dp) = tmp;
+			}
+
+			if (lmask != 0) {
+				if (sbover)
+					sp -= BYTESDONE;
+				dp -= BYTESDONE;
+				GETBITS(P0(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P0(dp));
+			}
+
+			sp = (sq += scanspan);
+			dp = (dq += scanspan);
+			height--;
+		}
+	}
+}
+
+static void
+om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *sp, *dp, *sq, *dq, *basep;
@@ -307,8 +698,14 @@ om_copycols(void *cookie, int startrow, 
 		dp = basep + (dstx / 32) * 4;
 
 		while (height > 0) {
-			GETBITS(sp, sb, w, tmp);
-			PUTBITS(tmp, db, w, dp);
+			GETBITS(P0(sp), sb, w, tmp);
+			PUTBITS(tmp, db, w, P0(dp));
+			GETBITS(P1(sp), sb, w, tmp);
+			PUTBITS(tmp, db, w, P1(dp));
+			GETBITS(P2(sp), sb, w, tmp);
+			PUTBITS(tmp, db, w, P2(dp));
+			GETBITS(P3(sp), sb, w, tmp);
+			PUTBITS(tmp, db, w, P3(dp));
 			dp += scanspan;
 			sp += scanspan;
 			height--;
@@ -345,23 +742,41 @@ om_copycols(void *cookie, int startrow, 
 		dq = dp;
 		while (height > 0) {
 			if (lmask != 0) {
-				GETBITS(sp, sb, lnum, tmp);
-				PUTBITS(tmp, db, lnum, dp);
+				GETBITS(P0(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P0(dp));
+				GETBITS(P1(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P1(dp));
+				GETBITS(P2(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P2(dp));
+				GETBITS(P3(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P3(dp));
 				dp += BYTESDONE;
 				if (sbover)
 					sp += BYTESDONE;
 			}
 
 			for (cnt = full; cnt; cnt--) {
-				GETBITS(sp, sboff, 32, tmp);
-				W(dp) = tmp;
+				GETBITS(P0(sp), sboff, 32, tmp);
+				P0(dp) = tmp;
+				GETBITS(P1(sp), sboff, 32, tmp);
+				P1(dp) = tmp;
+				GETBITS(P2(sp), sboff, 32, tmp);
+				P2(dp) = tmp;
+				GETBITS(P3(sp), sboff, 32, tmp);
+				P3(dp) = tmp;
 				sp += BYTESDONE;
 				dp += BYTESDONE;
 			}
 
 			if (rmask != 0) {
-				GETBITS(sp, sboff, rnum, tmp);
-				PUTBITS(tmp, 0, rnum, dp);
+				GETBITS(P0(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P0(dp));
+				GETBITS(P1(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P1(dp));
+				GETBITS(P2(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P2(dp));
+				GETBITS(P3(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P3(dp));
 			}
 
 			sp = (sq += scanspan);
@@ -384,23 +799,41 @@ om_copycols(void *cookie, int startrow, 
 		dq = dp;
 		while (height > 0) {
 			if (rnum != 0) {
-				GETBITS(sp, sboff, rnum, tmp);
-				PUTBITS(tmp, 0, rnum, dp);
+				GETBITS(P0(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P0(dp));
+				GETBITS(P1(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P1(dp));
+				GETBITS(P2(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P2(dp));
+				GETBITS(P3(sp), sboff, rnum, tmp);
+				PUTBITS(tmp, 0, rnum, P3(dp));
 			}
 
 			for (cnt = full; cnt; cnt--) {
 				sp -= BYTESDONE;
 				dp -= BYTESDONE;
-				GETBITS(sp, sboff, 32, tmp);
-				W(dp) = tmp;
+				GETBITS(P0(sp), sboff, 32, tmp);
+				P0(dp) = tmp;
+				GETBITS(P1(sp), sboff, 32, tmp);
+				P1(dp) = tmp;
+				GETBITS(P2(sp), sboff, 32, tmp);
+				P2(dp) = tmp;
+				GETBITS(P3(sp), sboff, 32, tmp);
+				P3(dp) = tmp;
 			}
 
 			if (lmask != 0) {
 				if (sbover)
 					sp -= BYTESDONE;
 				dp -= BYTESDONE;
-				GETBITS(sp, sb, lnum, tmp);
-				PUTBITS(tmp, db, lnum, dp);
+				GETBITS(P0(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P0(dp));
+				GETBITS(P1(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P1(dp));
+				GETBITS(P2(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P2(dp));
+				GETBITS(P3(sp), sb, lnum, tmp);
+				PUTBITS(tmp, db, lnum, P3(dp));
 			}
 
 			sp = (sq += scanspan);
@@ -440,7 +873,7 @@ om_mapchar(void *cookie, int c, u_int *c
  * Position|{enable|disable} the cursor at the specified location.
  */
 static void
-om_cursor(void *cookie, int on, int row, int col)
+om1_cursor(void *cookie, int on, int row, int col)
 {
 	struct rasops_info *ri = cookie;
 	uint8_t *p;
@@ -473,8 +906,8 @@ om_cursor(void *cookie, int on, int row,
 	if (width <= BLITWIDTH) {
 		lmask &= rmask;
 		while (height > 0) {
-			image = R(p);
-			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P0(p);
+			P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
 			p += scanspan;
 			height--;
 		}
@@ -482,11 +915,85 @@ om_cursor(void *cookie, int on, int row,
 		uint8_t *q = p;
 
 		while (height > 0) {
-			image = R(p);
-			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P0(p);
+			P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
 			p += BYTESDONE;
-			image = R(p);
-			W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+			image = P0(p);
+			P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+
+			p = (q += scanspan);
+			height--;
+		}
+	}
+	ri->ri_flg ^= RI_CURSOR;
+}
+
+static void
+om4_cursor(void *cookie, int on, int row, int col)
+{
+	struct rasops_info *ri = cookie;
+	uint8_t *p;
+	int scanspan, startx, height, width, align, y;
+	uint32_t lmask, rmask, image;
+
+	if (!on) {
+		/* make sure it's on */
+		if ((ri->ri_flg & RI_CURSOR) == 0)
+			return;
+
+		row = ri->ri_crow;
+		col = ri->ri_ccol;
+	} else {
+		/* unpaint the old copy. */
+		ri->ri_crow = row;
+		ri->ri_ccol = col;
+	}
+
+	scanspan = ri->ri_stride;
+	y = ri->ri_font->fontheight * row;
+	startx = ri->ri_font->fontwidth * col;
+	height = ri->ri_font->fontheight;
+
+	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
+	align = startx & ALIGNMASK;
+	width = ri->ri_font->fontwidth + align;
+	lmask = ALL1BITS >> align;
+	rmask = ALL1BITS << (-width & ALIGNMASK);
+	if (width <= BLITWIDTH) {
+		lmask &= rmask;
+		while (height > 0) {
+			image = P0(p);
+			P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P1(p);
+			P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P2(p);
+			P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P3(p);
+			P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			p += scanspan;
+			height--;
+		}
+	} else {
+		uint8_t *q = p;
+
+		while (height > 0) {
+			image = P0(p);
+			P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P1(p);
+			P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P2(p);
+			P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			image = P3(p);
+			P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			p += BYTESDONE;
+			image = P0(p);
+			P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+			image = P1(p);
+			P1(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+			image = P2(p);
+			P2(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+			image = P3(p);
+			P3(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
 
 			p = (q += scanspan);
 			height--;
@@ -499,23 +1006,92 @@ om_cursor(void *cookie, int on, int row,
  * Allocate attribute. We just pack these into an integer.
  */
 static int
-om_allocattr(void *id, int fg, int bg, int flags, long *attrp)
+om1_allocattr(void *id, int fg, int bg, int flags, long *attrp)
 {
 
-	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
-	    WSATTR_UNDERLINE | WSATTR_WSCOLORS))
+	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
+	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
 		return EINVAL;
-	if (flags & WSATTR_REVERSE)
+	if ((flags & WSATTR_REVERSE) != 0)
 		*attrp = 1;
 	else
 		*attrp = 0;
 	return 0;
 }
 
+static int
+om4_allocattr(void *id, int fg, int bg, int flags, long *attrp)
+{
+
+	if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
+		return EINVAL;
+	if ((flags & WSATTR_WSCOLORS) == 0) {
+		fg = WSCOL_WHITE;
+		bg = WSCOL_BLACK;
+	}
+
+	if ((flags & WSATTR_REVERSE) != 0) {
+		int swap;
+		swap = fg;
+		fg = bg;
+		bg = swap;
+	}
+
+	if ((flags & WSATTR_HILIT) != 0)
+		fg += 8;
+
+	*attrp = (fg << 24) | (bg << 16);
+	return 0;
+}
+
 /*
  * Init subset of rasops(9) for omrasops.
  */
 int
+omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
+{
+
+	omrasops_init(ri, wantrows, wantcols);
+
+	/* fill our own emulops */
+	ri->ri_ops.cursor    = om1_cursor;
+	ri->ri_ops.mapchar   = om_mapchar;
+	ri->ri_ops.putchar   = om1_putchar;
+	ri->ri_ops.copycols  = om1_copycols;
+	ri->ri_ops.erasecols = om1_erasecols;
+	ri->ri_ops.copyrows  = om1_copyrows;
+	ri->ri_ops.eraserows = om1_eraserows;
+	ri->ri_ops.allocattr = om1_allocattr;
+	ri->ri_caps = WSSCREEN_REVERSE;
+
+	ri->ri_flg |= RI_CFGDONE;
+
+	return 0;
+}
+
+int
+omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
+{
+
+	omrasops_init(ri, wantrows, wantcols);
+
+	/* fill our own emulops */
+	ri->ri_ops.cursor    = om4_cursor;
+	ri->ri_ops.mapchar   = om_mapchar;
+	ri->ri_ops.putchar   = om4_putchar;
+	ri->ri_ops.copycols  = om4_copycols;
+	ri->ri_ops.erasecols = om4_erasecols;
+	ri->ri_ops.copyrows  = om4_copyrows;
+	ri->ri_ops.eraserows = om4_eraserows;
+	ri->ri_ops.allocattr = om4_allocattr;
+	ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
+
+	ri->ri_flg |= RI_CFGDONE;
+
+	return 0;
+}
+
+static int
 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
 {
 	int wsfcookie, bpp;
@@ -541,7 +1117,8 @@ omrasops_init(struct rasops_info *ri, in
 
 	KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
 
-	bpp = ri->ri_depth;
+	/* all planes are independently addressed */
+	bpp = 1;
 
 	/* Now constrain what they get */
 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
@@ -586,18 +1163,5 @@ omrasops_init(struct rasops_info *ri, in
 	} else
 		ri->ri_xorigin = ri->ri_yorigin = 0;
 
-	/* fill our own emulops */
-	ri->ri_ops.cursor    = om_cursor;
-	ri->ri_ops.mapchar   = om_mapchar;
-	ri->ri_ops.putchar   = om_putchar;
-	ri->ri_ops.copycols  = om_copycols;
-	ri->ri_ops.erasecols = om_erasecols;
-	ri->ri_ops.copyrows  = om_copyrows;
-	ri->ri_ops.eraserows = om_eraserows;
-	ri->ri_ops.allocattr = om_allocattr;
-	ri->ri_caps = WSSCREEN_REVERSE;
-
-	ri->ri_flg |= RI_CFGDONE;
-
 	return 0;
 }

Index: src/sys/arch/luna68k/dev/omrasopsvar.h
diff -u src/sys/arch/luna68k/dev/omrasopsvar.h:1.1 src/sys/arch/luna68k/dev/omrasopsvar.h:1.2
--- src/sys/arch/luna68k/dev/omrasopsvar.h:1.1	Fri Jul 20 19:31:53 2012
+++ src/sys/arch/luna68k/dev/omrasopsvar.h	Sat Dec 28 09:17:23 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: omrasopsvar.h,v 1.1 2012/07/20 19:31:53 tsutsui Exp $ */
+/* $NetBSD: omrasopsvar.h,v 1.2 2013/12/28 09:17:23 tsutsui Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -26,4 +26,5 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-int omrasops_init(struct rasops_info *, int, int);
+int omrasops1_init(struct rasops_info *, int, int);
+int omrasops4_init(struct rasops_info *, int, int);

Reply via email to