Module Name:    src
Committed By:   martin
Date:           Wed Feb 15 19:14:50 UTC 2023

Modified Files:
        src/sys/arch/vax/vsa [netbsd-10]: smg.c
Added Files:
        src/sys/arch/vax/vsa [netbsd-10]: maskbits.h
        src/sys/dev/ic [netbsd-10]: dc503reg.h

Log Message:
Pull up following revision(s) (requested by tsutsui in ticket #86):

        sys/arch/vax/vsa/smg.c: revision 1.64
        sys/arch/vax/vsa/maskbits.h: revision 1.1
        sys/dev/ic/dc503reg.h: revision 1.1

Port rasops'fied smg(4) framebuffer driver for VS3100 from OpenBSD/vax.

This allows using more fonts other than 8x15 pixels on smg(4).
Tested on my VAXstation 3100/m30.

Note the bitorder of smg(4) VRAM is LSB first (i.e. LSBit is the
most left side pixel) and this requires more complicated changes
to bitmask ops in MI rasops(9) because several LE machines have
VRAMs whose MSBit is connected to the most left side pixel,
but for now I prepared smg(4) specific putchar and cursor ops
based on old luna68k omrasops.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/vax/vsa/maskbits.h
cvs rdiff -u -r1.61.6.2 -r1.61.6.3 src/sys/arch/vax/vsa/smg.c
cvs rdiff -u -r0 -r1.1.2.2 src/sys/dev/ic/dc503reg.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/vax/vsa/smg.c
diff -u src/sys/arch/vax/vsa/smg.c:1.61.6.2 src/sys/arch/vax/vsa/smg.c:1.61.6.3
--- src/sys/arch/vax/vsa/smg.c:1.61.6.2	Sun Feb 12 12:27:26 2023
+++ src/sys/arch/vax/vsa/smg.c	Wed Feb 15 19:14:50 2023
@@ -1,4 +1,57 @@
-/*	$NetBSD: smg.c,v 1.61.6.2 2023/02/12 12:27:26 martin Exp $ */
+/*	$NetBSD: smg.c,v 1.61.6.3 2023/02/15 19:14:50 martin Exp $ */
+/*	$OpenBSD: smg.c,v 1.28 2014/12/23 21:39:12 miod Exp $	*/
+/*
+ * Copyright (c) 2006, Miodrag Vallat
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Tohru Nishimura.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 /*
  * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
  * All rights reserved.
@@ -23,178 +76,157 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+/*
+ * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
+ * Copyright (c) 1991 University of Utah.
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Mark Davies of the Department of Computer
+ * Science, Victoria University of Wellington, New Zealand.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: grf_hy.c 1.2 93/08/13$
+ *
+ *	@(#)grf_hy.c	8.4 (Berkeley) 1/12/94
+ */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.61.6.2 2023/02/12 12:27:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.61.6.3 2023/02/15 19:14:50 martin Exp $");
 
-#include "opt_wsfont.h"
 #include "dzkbd.h"
 #include "wsdisplay.h"
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/callout.h>
-#include <sys/conf.h>
-#include <sys/cpu.h>
 #include <sys/device.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
 #include <sys/kmem.h>
-#include <sys/time.h>
+#include <sys/conf.h>
 
 #include <machine/vsbus.h>
 #include <machine/sid.h>
+#include <machine/cpu.h>
 #include <machine/ka420.h>
 #include <machine/scb.h>
 
 #include <dev/cons.h>
 
+#include <dev/ic/dc503reg.h>
+
 #include <dev/dec/dzreg.h>
 #include <dev/dec/dzvar.h>
 #include <dev/dec/dzkbdvar.h>
 
-#include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
-#include <dev/wscons/wscons_callbacks.h>
-#include <dev/wsfont/wsfont.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
 
 /* Screen hardware defs */
-#define SM_COLS		128	/* char width of screen */
-#define SM_ROWS		57	/* rows of char on screen */
-#define SM_CHEIGHT	15	/* lines a char consists of */
-#define SM_NEXTROW	(SM_COLS * SM_CHEIGHT)
-#define	SM_YWIDTH	864
 #define SM_XWIDTH	1024
-
-/* Cursor register definitions */
-#define	CUR_CMD		0
-#define	CUR_XPOS	4
-#define CUR_YPOS	8
-#define CUR_XMIN_1	12
-#define CUR_XMAX_1	16
-#define CUR_YMIN_1	20
-#define CUR_YMAX_1	24
-#define CUR_XMIN_2	28
-#define CUR_XMAX_2	32
-#define CUR_YMIN_2	36
-#define CUR_YMAX_2	40
-#define CUR_LOAD	44
-
-#define CUR_CMD_TEST	0x8000
-#define CUR_CMD_HSHI	0x4000
-#define CUR_CMD_VBHI	0x2000
-#define CUR_CMD_LODSA	0x1000
-#define CUR_CMD_FORG2	0x0800
-#define CUR_CMD_ENRG2	0x0400
-#define CUR_CMD_FORG1	0x0200
-#define CUR_CMD_ENRG1	0x0100
-#define CUR_CMD_XHWID	0x0080
-#define CUR_CMD_XHCL1	0x0040
-#define CUR_CMD_XHCLP	0x0020
-#define CUR_CMD_XHAIR	0x0010
-#define CUR_CMD_FOPB	0x0008
-#define CUR_CMD_ENPB	0x0004
-#define CUR_CMD_FOPA	0x0002
-#define CUR_CMD_ENPA	0x0001
+#define SM_YWIDTH	864
 
 #define CUR_XBIAS	216	/* Add to cursor position */
-#define	CUR_YBIAS	33
+#define CUR_YBIAS	33
 
-#define	WRITECUR(addr, val)	*(volatile uint16_t *)(curaddr + (addr)) = (val)
-static	char *curaddr;
-static	uint16_t curcmd, curx, cury, hotX, hotY;
-static	int bgmask, fgmask;
+static int	smg_match(device_t, cfdata_t, void *);
+static void	smg_attach(device_t, device_t, void *);
 
-static	int smg_match(device_t, cfdata_t, void *);
-static	void smg_attach(device_t, device_t, void *);
+struct	smg_screen {
+	struct rasops_info ss_ri;
+	uint8_t		*ss_addr;		/* frame buffer address */
+	struct dc503reg	*ss_cursor;		/* cursor registers */
+	uint16_t	ss_curcmd;
+	struct wsdisplay_curpos ss_curpos, ss_curhot;
+	uint16_t	ss_curimg[PCC_CURSOR_SIZE];
+	uint16_t	ss_curmask[PCC_CURSOR_SIZE];
+};
 
-CFATTACH_DECL_NEW(smg, 0,
-    smg_match, smg_attach, NULL, NULL);
+/* for console */
+static struct smg_screen smg_consscr;
 
-static void	smg_cursor(void *, int, int, int);
-static int	smg_mapchar(void *, int, unsigned int *);
-static void	smg_putchar(void *, int, int, u_int, long);
-static void	smg_copycols(void *, int, int, int,int);
-static void	smg_erasecols(void *, int, int, int, long);
-static void	smg_copyrows(void *, int, int, int);
-static void	smg_eraserows(void *, int, int, long);
-static int	smg_allocattr(void *, int, int, int, long *);
-
-const struct wsdisplay_emulops smg_emulops = {
-	.cursor = smg_cursor,
-	.mapchar = smg_mapchar,
-	.putchar = smg_putchar,
-	.copycols = smg_copycols,
-	.erasecols = smg_erasecols,
-	.copyrows = smg_copyrows,
-	.eraserows = smg_eraserows,
-	.allocattr = smg_allocattr
+struct	smg_softc {
+	device_t sc_dev;
+	struct smg_screen *sc_scr;
+	int	sc_nscreens;
 };
 
-const struct wsscreen_descr smg_stdscreen = {
-	.name = "128x57",
-	.ncols = SM_COLS,
-	.nrows = SM_ROWS,
-	.textops = &smg_emulops,
-	.fontwidth = 8,
-	.fontheight = SM_CHEIGHT,
-	.capabilities = WSSCREEN_UNDERLINE|WSSCREEN_REVERSE,
+CFATTACH_DECL_NEW(smg, sizeof(struct smg_softc),
+    smg_match, smg_attach, NULL, NULL);
+
+static struct wsscreen_descr smg_stdscreen = {
+	.name = "std",
 };
 
-const struct wsscreen_descr *_smg_scrlist[] = {
+static const struct wsscreen_descr *_smg_scrlist[] = {
 	&smg_stdscreen,
 };
 
-const struct wsscreen_list smg_screenlist = {
-	.nscreens = __arraycount(_smg_scrlist),
+static const struct wsscreen_list smg_screenlist = {
+	.nscreens = sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *),
 	.screens = _smg_scrlist,
 };
 
-static	char *sm_addr;
-
-static  u_char *qf;
+static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *);
+static paddr_t smg_mmap(void *, void *, off_t, int);
+static int smg_alloc_screen(void *, const struct wsscreen_descr *,
+    void **, int *, int *, long *);
+static void smg_free_screen(void *, void *);
+static int smg_show_screen(void *, void *, int, void (*) (void *, int, int),
+    void *);
 
-#define QCHAR(c) (c < 32 ? 32 : (c > 127 ? c - 66 : c - 32))
-#define QFONT(c,line)	qf[QCHAR(c) * 15 + line]
-#define	SM_ADDR(row, col, line) \
-	sm_addr[col + (row * SM_CHEIGHT * SM_COLS) + line * SM_COLS]
-
-
-static int	smg_ioctl(void *, void *, u_long, void *, int, struct lwp *);
-static paddr_t	smg_mmap(void *, void *, off_t, int);
-static int	smg_alloc_screen(void *, const struct wsscreen_descr *,
-				      void **, int *, int *, long *);
-static void	smg_free_screen(void *, void *);
-static int	smg_show_screen(void *, void *, int,
-				     void (*) (void *, int, int), void *);
-static void	smg_crsr_blink(void *);
-
-const struct wsdisplay_accessops smg_accessops = {
+static const struct wsdisplay_accessops smg_accessops = {
 	.ioctl = smg_ioctl,
 	.mmap = smg_mmap,
 	.alloc_screen = smg_alloc_screen,
 	.free_screen = smg_free_screen,
 	.show_screen = smg_show_screen,
+	.load_font = NULL
 };
 
-struct	smg_screen {
-	int	ss_curx;
-	int	ss_cury;
-	u_char	ss_image[SM_ROWS][SM_COLS];	/* Image of current screen */
-	u_char	ss_attr[SM_ROWS][SM_COLS];	/* Reversed etc... */
-};
-
-static	struct smg_screen smg_conscreen;
-static	struct smg_screen *curscr;
-
-static	callout_t smg_cursor_ch;
+static void smg_putchar(void *, int, int, u_int, long);
+static void smg_cursor(void *, int, int, int);
+static void smg_blockmove(struct rasops_info *, u_int, u_int, u_int, u_int,
+    u_int, int);
+static void smg_copycols(void *, int, int, int, int);
+static void smg_erasecols(void *, int, int, int, long);
+
+static int smg_getcursor(struct smg_screen *, struct wsdisplay_cursor *);
+static int smg_setup_screen(struct smg_screen *);
+static int smg_setcursor(struct smg_screen *, struct wsdisplay_cursor *);
+static void smg_updatecursor(struct smg_screen *, u_int);
 
-int
+static int
 smg_match(device_t parent, cfdata_t cf, void *aux)
 {
-	struct vsbus_attach_args * const va = aux;
-	volatile uint16_t *ccmd;
-	volatile uint16_t *cfgtst;
-	uint16_t tmp, tmp2;
+	struct vsbus_attach_args *va = aux;
+	volatile short *curcmd;
+	volatile short *cfgtst;
+	short tmp, tmp2;
 
 	switch (vax_boardtype) {
 	default:
@@ -209,6 +241,7 @@ smg_match(device_t parent, cfdata_t cf, 
 		/* not present on microvaxes */
 		if ((vax_confdata & KA420_CFG_MULTU) != 0)
 			return 0;
+
 		/*
 		 * If the color option board is present, do not attach
 		 * unless we are explicitely asked to via device flags.
@@ -235,12 +268,12 @@ smg_match(device_t parent, cfdata_t cf, 
 		 * Try to find the cursor chip by testing the flip-flop.
 		 * If nonexistent, no glass tty.
 		 */
-		ccmd = (uint16_t *)va->va_addr;
-		cfgtst = (uint16_t *)vax_map_physmem(VS_CFGTST, 1);
-		ccmd[0] = CUR_CMD_HSHI|CUR_CMD_FOPB;
+		curcmd = (short *)va->va_addr;
+		cfgtst = (short *)vax_map_physmem(VS_CFGTST, 1);
+		curcmd[0] = PCCCMD_HSHI | PCCCMD_FOPB;
 		DELAY(300000);
 		tmp = cfgtst[0];
-		ccmd[0] = CUR_CMD_TEST|CUR_CMD_HSHI;
+		curcmd[0] = PCCCMD_TEST | PCCCMD_HSHI;
 		DELAY(300000);
 		tmp2 = cfgtst[0];
 		vax_unmap_physmem((vaddr_t)cfgtst, 1);
@@ -252,260 +285,136 @@ smg_match(device_t parent, cfdata_t cf, 
 	}
 }
 
-void
+static void
 smg_attach(device_t parent, device_t self, void *aux)
 {
+	struct smg_softc *sc = device_private(self);
+	struct smg_screen *scr;
 	struct wsemuldisplaydev_attach_args aa;
-	struct wsdisplay_font *console_font;
-	int fcookie;
+	int console;
 
-	aprint_normal("\n");
-	sm_addr = (void *)vax_map_physmem(SMADDR, (SMSIZE/VAX_NBPG));
-	curaddr = (void *)vax_map_physmem(KA420_CUR_BASE, 1);
-	if (sm_addr == 0) {
-		aprint_error_dev(self, "Couldn't alloc graphics memory.\n");
-		return;
-	}
-	if (curscr == NULL)
-		callout_init(&smg_cursor_ch, 0);
-	curscr = &smg_conscreen;
-	aa.console =
+	console =
 #if NWSDISPLAY > 0
 	    (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0 &&
 	    cn_tab->cn_putc == wsdisplay_cnputc;
 #else
 	    (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0;
 #endif
+	if (console) {
+		scr = &smg_consscr;
+		sc->sc_nscreens = 1;
+	} else {
+		scr = kmem_zalloc(sizeof(*scr), KM_SLEEP);
 
-	aa.scrdata = &smg_screenlist;
-	aa.accessops = &smg_accessops;
-	callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL);
-	curcmd = CUR_CMD_HSHI;
-	WRITECUR(CUR_CMD, curcmd);
-	wsfont_init();
-	if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L,
-	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) {
-		aprint_error_dev(self, "could not find 8x15 font\n");
-		return;
-	}
-	if (wsfont_lock(fcookie, &console_font) != 0) {
-		aprint_error_dev(self, "could not lock 8x15 font\n");
-		return;
-	}
-	qf = console_font->data;
-
-	config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
-}
-
-static	u_char *cursor;
-static	int cur_on;
-
-static void
-smg_crsr_blink(void *arg)
-{
-	if (cur_on)
-		*cursor ^= 255;
-	callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL);
-}
-
-void
-smg_cursor(void *id, int on, int row, int col)
-{
-	struct smg_screen * const ss = id;
+		scr->ss_addr =
+		    (void *)vax_map_physmem(SMADDR, SMSIZE / VAX_NBPG);
+		if (scr->ss_addr == NULL) {
+			aprint_error(": can not map frame buffer\n");
+			kmem_free(scr, sizeof(*scr));
+			return;
+		}
 
-	if (ss == curscr) {
-		SM_ADDR(ss->ss_cury, ss->ss_curx, 14) =
-		    QFONT(ss->ss_image[ss->ss_cury][ss->ss_curx], 14);
-		cursor = &SM_ADDR(row, col, 14);
-		if ((cur_on = on))
-			*cursor ^= 255;
-	}
-	ss->ss_curx = col;
-	ss->ss_cury = row;
-}
+		scr->ss_cursor =
+		    (struct dc503reg *)vax_map_physmem(KA420_CUR_BASE, 1);
+		if (scr->ss_cursor == NULL) {
+			aprint_error(": can not map cursor chip\n");
+			vax_unmap_physmem((vaddr_t)scr->ss_addr,
+			    SMSIZE / VAX_NBPG);
+			kmem_free(scr, sizeof(*scr));
+			return;
+		}
 
-int
-smg_mapchar(void *id, int uni, unsigned int *index)
-{
-	if (uni < 256) {
-		*index = uni;
-		return (5);
+		if (smg_setup_screen(scr) != 0) {
+			aprint_error(": initialization failed\n");
+			vax_unmap_physmem((vaddr_t)scr->ss_cursor, 1);
+			vax_unmap_physmem((vaddr_t)scr->ss_addr,
+			    SMSIZE / VAX_NBPG);
+			kmem_free(scr, sizeof(*scr));
+			return;
+		}
 	}
-	*index = ' ';
-	return (0);
-}
-
-static void
-smg_putchar(void *id, int row, int col, u_int c, long attr)
-{
-	struct smg_screen * const ss = id;
-	int i;
-
-	c &= 0xff;
-
-	ss->ss_image[row][col] = c;
-	ss->ss_attr[row][col] = attr;
-	if (ss != curscr)
-		return;
-	for (i = 0; i < 15; i++) {
-		unsigned char ch = QFONT(c, i);
+	sc->sc_scr = scr;
 
-		SM_ADDR(row, col, i) = (attr & WSATTR_REVERSE ? ~ch : ch);
-		
-	}
-	if (attr & WSATTR_UNDERLINE)
-		SM_ADDR(row, col, 14) ^= SM_ADDR(row, col, 14);
-}
+	aprint_normal("\n");
+	aprint_normal_dev(self, "%dx%d on-board monochrome framebuffer\n",
+	    SM_XWIDTH, SM_YWIDTH);
 
-/*
- * copies columns inside a row.
- */
-static void
-smg_copycols(void *id, int row, int srccol, int dstcol, int ncols)
-{
-	struct smg_screen * const ss = id;
-	int i;
+	aa.console = console;
+	aa.scrdata = &smg_screenlist;
+	aa.accessops = &smg_accessops;
+	aa.accesscookie = sc;
 
-	memcpy(&ss->ss_image[row][dstcol], &ss->ss_image[row][srccol], ncols);
-	memcpy(&ss->ss_attr[row][dstcol], &ss->ss_attr[row][srccol], ncols);
-	if (ss != curscr)
-		return;
-	for (i = 0; i < SM_CHEIGHT; i++)
-		memcpy(&SM_ADDR(row, dstcol, i), &SM_ADDR(row, srccol, i), ncols);
+	config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
 }
 
 /*
- * Erases a bunch of chars inside one row.
+ * Initialize anything necessary for an emulating wsdisplay to work (i.e.
+ * pick a font, initialize a rasops structure, setup the accessops callbacks.)
  */
-static void
-smg_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
+static int
+smg_setup_screen(struct smg_screen *ss)
 {
-	struct smg_screen * const ss = id;
-	int i;
+	struct rasops_info *ri = &ss->ss_ri;
+	int cookie;
 
-	memset(&ss->ss_image[row][startcol], 0, ncols);
-	memset(&ss->ss_attr[row][startcol], 0, ncols);
-	if (ss != curscr)
-		return;
-	for (i = 0; i < SM_CHEIGHT; i++)
-		memset(&SM_ADDR(row, startcol, i), 0, ncols);
-}
+	memset(ri, 0, sizeof(*ri));
+	ri->ri_depth = 1;
+	ri->ri_width = SM_XWIDTH;
+	ri->ri_height = SM_YWIDTH;
+	ri->ri_stride = SM_XWIDTH >> 3;
+	ri->ri_flg = RI_CLEAR | RI_CENTER;
+	ri->ri_bits = (void *)ss->ss_addr;
+	ri->ri_hw = ss;
+	if (ss == &smg_consscr)
+		ri->ri_flg |= RI_NO_AUTO;
 
-static void
-smg_copyrows(void *id, int srcrow, int dstrow, int nrows)
-{
-	struct smg_screen * const ss = id;
-	int frows;
+	wsfont_init();
+	cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
+	    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
+	if (cookie < 0)
+		cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L,
+		    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
+	if (cookie < 0)
+		cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
+		    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
+	if (cookie < 0)
+		return -1;
+	if (wsfont_lock(cookie, &ri->ri_font) != 0)
+		return -1;
+	ri->ri_wsfcookie = cookie;
 
-	memcpy(&ss->ss_image[dstrow][0], &ss->ss_image[srcrow][0],
-	    nrows * SM_COLS);
-	memcpy(&ss->ss_attr[dstrow][0], &ss->ss_attr[srcrow][0],
-	    nrows * SM_COLS);
-	if (ss != curscr)
-		return;
-	if (nrows > 25) {
-		frows = nrows >> 1;
-		if (srcrow > dstrow) {
-			bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
-			    &sm_addr[(dstrow * SM_NEXTROW)],
-			    frows * SM_NEXTROW);
-			bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
-			    &sm_addr[((dstrow + frows) * SM_NEXTROW)],
-			    (nrows - frows) * SM_NEXTROW);
-		} else {
-			bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
-			    &sm_addr[((dstrow + frows) * SM_NEXTROW)],
-			    (nrows - frows) * SM_NEXTROW);
-			bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
-			    &sm_addr[(dstrow * SM_NEXTROW)],
-			    frows * SM_NEXTROW);
-		}
-	} else
-		bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
-		    &sm_addr[(dstrow * SM_NEXTROW)], nrows * SM_NEXTROW);
-}
+	/*
+	 * Ask for an unholy big display, rasops will trim this to more
+	 * reasonable values.
+	 */
+	if (rasops_init(ri, 160, 160) != 0)
+		return -1;
 
-static void
-smg_eraserows(void *id, int startrow, int nrows, long fillattr)
-{
-	struct smg_screen * const ss = id;
-	int frows;
+	ri->ri_ops.cursor = smg_cursor;
+	ri->ri_ops.putchar = smg_putchar;
+	ri->ri_ops.copycols = smg_copycols;
+	ri->ri_ops.erasecols = smg_erasecols;
+
+	smg_stdscreen.ncols = ri->ri_cols;
+	smg_stdscreen.nrows = ri->ri_rows;
+	smg_stdscreen.textops = &ri->ri_ops;
+	smg_stdscreen.fontwidth = ri->ri_font->fontwidth;
+	smg_stdscreen.fontheight = ri->ri_font->fontheight;
+	smg_stdscreen.capabilities = ri->ri_caps;
 
-	memset(&ss->ss_image[startrow][0], 0, nrows * SM_COLS);
-	memset(&ss->ss_attr[startrow][0], 0, nrows * SM_COLS);
-	if (ss != curscr)
-		return;
-	if (nrows > 25) {
-		frows = nrows >> 1;
-		memset(&sm_addr[(startrow * SM_NEXTROW)], 0, frows * SM_NEXTROW);
-		memset(&sm_addr[((startrow + frows) * SM_NEXTROW)], 0,
-		    (nrows - frows) * SM_NEXTROW);
-	} else
-		memset(&sm_addr[(startrow * SM_NEXTROW)], 0, nrows * SM_NEXTROW);
-}
+	ss->ss_curcmd = PCCCMD_HSHI;
+	ss->ss_cursor->cmdr = ss->ss_curcmd;
 
-static int
-smg_allocattr(void *id, int fg, int bg, int flags, long *attrp)
-{
-	*attrp = flags;
 	return 0;
 }
 
-static void
-setcursor(struct wsdisplay_cursor *v)
-{
-	uint16_t red, green, blue;
-	uint32_t curfg[16], curmask[16];
-	int i;
-
-	/* Enable cursor */
-	if (v->which & WSDISPLAY_CURSOR_DOCUR) {
-		if (v->enable)
-			curcmd |= CUR_CMD_ENPB|CUR_CMD_ENPA;
-		else
-			curcmd &= ~(CUR_CMD_ENPB|CUR_CMD_ENPA);
-		WRITECUR(CUR_CMD, curcmd);
-	}
-	if (v->which & WSDISPLAY_CURSOR_DOHOT) {
-		hotX = v->hot.x;
-		hotY = v->hot.y;
-	}
-	if (v->which & WSDISPLAY_CURSOR_DOCMAP) {
-		/* First background */
-		if (copyin(v->cmap.red, &red, sizeof(red)) == 0 &&
-		    copyin(v->cmap.green, &green, sizeof(green)) == 0 &&
-		    copyin(v->cmap.blue, &blue, sizeof(blue)) == 0) {
-			bgmask = (((30L * red + 59L * green + 11L * blue) >> 8)
-			    >= (((1<<8)-1)*50)) ? ~0 : 0;
-		}
-		if (copyin(v->cmap.red + 2, &red, sizeof(red)) == 0 &&
-		    copyin(v->cmap.green + 2, &green, sizeof(green)) == 0 &&
-		    copyin(v->cmap.blue + 2, &blue, sizeof(blue)) == 0) {
-			fgmask = (((30L * red + 59L * green + 11L * blue) >> 8)
-			    >= (((1<<8)-1)*50)) ? ~0 : 0;
-		}
-	}
-	if (v->which & WSDISPLAY_CURSOR_DOSHAPE) {
-		WRITECUR(CUR_CMD, curcmd | CUR_CMD_LODSA);
-		copyin(v->image, curfg, sizeof(curfg));
-		copyin(v->mask, curmask, sizeof(curmask));
-		for (i = 0; i < sizeof(curfg)/sizeof(curfg[0]); i++) {
-			WRITECUR(CUR_LOAD, ((uint16_t)curfg[i] & fgmask) |
-			    (((uint16_t)curmask[i] & (uint16_t)~curfg[i])
-			    & bgmask));
-		}
-		for (i = 0; i < sizeof(curmask)/sizeof(curmask[0]); i++) {
-			WRITECUR(CUR_LOAD, (uint16_t)curmask[i]);
-		}
-		WRITECUR(CUR_CMD, curcmd);
-	}
-}
-
-int
+static int
 smg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
 {
-	struct wsdisplay_fbinfo *fb = (void *)data;
-	static uint16_t curc;
+	struct smg_softc *sc = v;
+	struct smg_screen *ss = sc->sc_scr;
+	struct wsdisplay_fbinfo *wdf;
+	struct wsdisplay_curpos *pos;
 
 	switch (cmd) {
 	case WSDISPLAYIO_GTYPE:
@@ -513,48 +422,45 @@ smg_ioctl(void *v, void *vs, u_long cmd,
 		break;
 
 	case WSDISPLAYIO_GINFO:
-		fb->height = SM_YWIDTH;
-		fb->width = SM_XWIDTH;
-		fb->depth = 1;
-		fb->cmsize = 2;
+		wdf = (struct wsdisplay_fbinfo *)data;
+		wdf->height = ss->ss_ri.ri_height;
+		wdf->width = ss->ss_ri.ri_width;
+		wdf->depth = ss->ss_ri.ri_depth;
+		wdf->cmsize = 0;
 		break;
 
-	case WSDISPLAYIO_SVIDEO:
-		if (*(u_int *)data == WSDISPLAYIO_VIDEO_ON) {
-			curcmd = curc;
-		} else {
-			curc = curcmd;
-			curcmd &= ~(CUR_CMD_FOPA|CUR_CMD_ENPA);
-			curcmd |= CUR_CMD_FOPB;
-		}
-		WRITECUR(CUR_CMD, curcmd);
+	case WSDISPLAYIO_LINEBYTES:
+		*(u_int *)data = ss->ss_ri.ri_stride;
 		break;
 
+	case WSDISPLAYIO_GETCMAP:
+	case WSDISPLAYIO_PUTCMAP:
 	case WSDISPLAYIO_GVIDEO:
-		*(u_int *)data = (curcmd & CUR_CMD_FOPB ?
-		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON);
+	case WSDISPLAYIO_SVIDEO:
 		break;
 
-	case WSDISPLAYIO_SCURSOR:
-		setcursor((struct wsdisplay_cursor *)data);
+	case WSDISPLAYIO_GCURPOS:
+		pos = (struct wsdisplay_curpos *)data;
+		pos->x = ss->ss_curpos.x;
+		pos->y = ss->ss_curpos.y;
 		break;
 
 	case WSDISPLAYIO_SCURPOS:
-		curx = ((struct wsdisplay_curpos *)data)->x;
-		cury = ((struct wsdisplay_curpos *)data)->y;
-		WRITECUR(CUR_XPOS, curx + CUR_XBIAS);
-		WRITECUR(CUR_YPOS, cury + CUR_YBIAS);
-		break;
-
-	case WSDISPLAYIO_GCURPOS:
-		((struct wsdisplay_curpos *)data)->x = curx;
-		((struct wsdisplay_curpos *)data)->y = cury;
+		pos = (struct wsdisplay_curpos *)data;
+		ss->ss_curpos.x = pos->x;
+		ss->ss_curpos.y = pos->y;
+		smg_updatecursor(ss, WSDISPLAY_CURSOR_DOPOS);
 		break;
 
 	case WSDISPLAYIO_GCURMAX:
-		((struct wsdisplay_curpos *)data)->x = 16;
-		((struct wsdisplay_curpos *)data)->y = 16;
-		break;
+		pos = (struct wsdisplay_curpos *)data;
+		pos->x = pos->y = PCC_CURSOR_SIZE;
+
+	case WSDISPLAYIO_GCURSOR:
+		return smg_getcursor(ss, (struct wsdisplay_cursor *)data);
+
+	case WSDISPLAYIO_SCURSOR:
+		return smg_setcursor(ss, (struct wsdisplay_cursor *)data);
 
 	default:
 		return EPASSTHROUGH;
@@ -565,103 +471,519 @@ smg_ioctl(void *v, void *vs, u_long cmd,
 static paddr_t
 smg_mmap(void *v, void *vs, off_t offset, int prot)
 {
+
 	if (offset >= SMSIZE || offset < 0)
 		return -1;
-	return (SMADDR + offset) >> PGSHIFT;
+
+	return SMADDR + offset;
 }
 
-int
+static int
 smg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
     int *curxp, int *curyp, long *defattrp)
 {
-	*cookiep = kmem_zalloc(sizeof(struct smg_screen), KM_SLEEP);
-	*curxp = *curyp = *defattrp = 0;
+	struct smg_softc *sc = v;
+	struct smg_screen *ss = sc->sc_scr;
+	struct rasops_info *ri = &ss->ss_ri;
+
+	if (sc->sc_nscreens > 0)
+		return ENOMEM;
+
+	*cookiep = ri;
+	*curxp = *curyp = 0;
+	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, defattrp);
+	sc->sc_nscreens++;
+
 	return 0;
 }
 
-void
+static void
 smg_free_screen(void *v, void *cookie)
 {
+	struct smg_softc *sc = v;
+
+	sc->sc_nscreens--;
 }
 
-int
+static int
 smg_show_screen(void *v, void *cookie, int waitok,
     void (*cb)(void *, int, int), void *cbarg)
 {
-	struct smg_screen *ss = cookie;
-	int row, col, line;
 
-	if (ss == curscr)
-		return (0);
+	return 0;
+}
+
+static int
+smg_getcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
+{
+	int error;
+
+	if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0)
+		wdc->enable = ss->ss_curcmd & PCCCMD_ENPA ? 1 : 0;
+	if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
+		wdc->pos.x = ss->ss_curpos.x;
+		wdc->pos.y = ss->ss_curpos.y;
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
+		wdc->hot.x = ss->ss_curhot.x;
+		wdc->hot.y = ss->ss_curhot.y;
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
+		wdc->cmap.index = 0;
+		wdc->cmap.count = 0;
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
+		wdc->size.x = wdc->size.y = PCC_CURSOR_SIZE;
+		error = copyout(ss->ss_curimg, wdc->image,
+		    sizeof(ss->ss_curimg));
+		if (error != 0)
+			return error;
+		error = copyout(ss->ss_curmask, wdc->mask,
+		    sizeof(ss->ss_curmask));
+		if (error != 0)
+			return error;
+	}
 
-	for (row = 0; row < SM_ROWS; row++)
-		for (line = 0; line < SM_CHEIGHT; line++) {
-			for (col = 0; col < SM_COLS; col++) {
-				u_char s, c = ss->ss_image[row][col];
-
-				if (c < 32)
-					c = 32;
-				s = QFONT(c, line);
-				if (ss->ss_attr[row][col] & WSATTR_REVERSE)
-					s ^= 255;
-				SM_ADDR(row, col, line) = s;
-				if (ss->ss_attr[row][col] & WSATTR_UNDERLINE)
-					SM_ADDR(row, col, line) = 255;
-			}
-		}
-	cursor = &sm_addr[(ss->ss_cury * SM_CHEIGHT * SM_COLS) + ss->ss_curx +
-	    ((SM_CHEIGHT - 1) * SM_COLS)];
-	curscr = ss;
-	return (0);
+	return 0;
 }
 
-cons_decl(smg);
+static int
+smg_setcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
+{
+	uint16_t curfg[PCC_CURSOR_SIZE], curmask[PCC_CURSOR_SIZE];
+	int error;
 
-void
-smgcninit(struct consdev *cndev)
+	if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
+		/* No cursor colormap since we are a B&W device. */
+		if (wdc->cmap.count != 0)
+			return EINVAL;
+	}
+
+	/*
+	 * First, do the userland-kernel data transfers, so that we can fail
+	 * if necessary before altering anything.
+	 */
+	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
+		if (wdc->size.x != PCC_CURSOR_SIZE ||
+		    wdc->size.y != PCC_CURSOR_SIZE)
+			return EINVAL;
+		error = copyin(wdc->image, curfg, sizeof(curfg));
+		if (error != 0)
+			return error;
+		error = copyin(wdc->mask, curmask, sizeof(curmask));
+		if (error != 0)
+			return error;
+	}
+
+	/*
+	 * Now update our variables...
+	 */
+	if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0) {
+		if (wdc->enable)
+			ss->ss_curcmd |= PCCCMD_ENPB | PCCCMD_ENPA;
+		else
+			ss->ss_curcmd &= ~(PCCCMD_ENPB | PCCCMD_ENPA);
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
+		ss->ss_curpos.x = wdc->pos.x;
+		ss->ss_curpos.y = wdc->pos.y;
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
+		ss->ss_curhot.x = wdc->hot.x;
+		ss->ss_curhot.y = wdc->hot.y;
+	}
+	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
+		memcpy(ss->ss_curimg, curfg, sizeof(ss->ss_curimg));
+		memcpy(ss->ss_curmask, curmask, sizeof(ss->ss_curmask));
+	}
+
+	/*
+	 * ...and update the cursor
+	 */
+	smg_updatecursor(ss, wdc->which);
+
+	return 0;
+}
+
+static void
+smg_updatecursor(struct smg_screen *ss, u_int which)
 {
-	int fcookie;
-	struct wsdisplay_font *console_font;
-	extern vaddr_t virtual_avail;
-	extern int dz_vsbus_lk201_cnattach(int);
+	u_int i;
 
-	sm_addr = (void *)virtual_avail;
-	ioaccess((vaddr_t)sm_addr, SMADDR, (SMSIZE / VAX_NBPG));
-	virtual_avail += SMSIZE;
+	if ((which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
+		ss->ss_cursor->xpos =
+		    ss->ss_curpos.x - ss->ss_curhot.x + CUR_XBIAS;
+		ss->ss_cursor->ypos =
+		    ss->ss_curpos.y - ss->ss_curhot.y + CUR_YBIAS;
+	}
+	if ((which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
+		ss->ss_cursor->cmdr = ss->ss_curcmd | PCCCMD_LODSA;
+		for (i = 0; i < PCC_CURSOR_SIZE; i++)
+			ss->ss_cursor->load = ss->ss_curimg[i];
+		for (i = 0; i < PCC_CURSOR_SIZE; i++)
+			ss->ss_cursor->load = ss->ss_curmask[i];
+		ss->ss_cursor->cmdr = ss->ss_curcmd;
+	} else
+	if ((which & WSDISPLAY_CURSOR_DOCUR) != 0)
+		ss->ss_cursor->cmdr = ss->ss_curcmd;
+}
 
-	virtual_avail = round_page(virtual_avail);
+/*
+ * Faster console operations
+ */
 
-	/* Clear screen */
-	memset(sm_addr, 0, 128*864);
+#include <vax/vsa/maskbits.h>
 
-	callout_init(&smg_cursor_ch, 0);
+/* putchar() and cursor() ops are taken from luna68k omrasops.c */
 
-	curscr = &smg_conscreen;
-	wsdisplay_cnattach(&smg_stdscreen, &smg_conscreen, 0, 0, 0);
-	cn_tab->cn_pri = CN_INTERNAL;
-	wsfont_init();
-	if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L,
-	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0)
-	{
-		printf("smg: could not find 8x15 font\n");
-		return;
+#define	ALL1BITS	(~0U)
+#define	ALL0BITS	(0U)
+#define	BLITWIDTH	(32)
+#define	ALIGNMASK	(0x1f)
+#define	BYTESDONE	(4)
+
+static void
+smg_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, inverse;
+	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;
+	inverse = ((attr & WSATTR_REVERSE) != 0) ? ALL1BITS : ALL0BITS;
+
+	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
+	align = startx & ALIGNMASK;
+	width = ri->ri_font->fontwidth + align;
+	/* lmask and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */
+	lmask = ALL1BITS << align;
+	rmask = ALL1BITS >> (-width & ALIGNMASK);
+	if (width <= BLITWIDTH) {
+		uint32_t mask = lmask & rmask;
+		while (height > 0) {
+			uint32_t image;
+			/*
+			 * The font glyph is stored in byteorder and bitorder
+			 * WSDISPLAY_FONTORDER_R2L to use proper shift ops.
+			 * On the other hand, VRAM data is stored in
+			 * WSDISPLAY_FONTORDER_R2L bitorder and
+			 * WSDIPPLAY_FONTORDER_L2R byteorder.
+			 */
+			glyph = 0;
+			for (i = ri->ri_font->stride; i != 0; i--)
+				glyph = (glyph << 8) | *fb++;
+			glyph = (glyph << align) ^ inverse;
+			image = *(uint32_t *)p;
+			*(uint32_t *)p = (image & ~mask) | (glyph & mask);
+			p += scanspan;
+			height--;
+		}
+	} else {
+		uint8_t *q = p;
+		uint32_t lhalf, rhalf;
+
+		while (height > 0) {
+			uint32_t image;
+			glyph = 0;
+			for (i = ri->ri_font->stride; i != 0; i--)
+				glyph = (glyph << 8) | *fb++;
+			lhalf = (glyph << align) ^ inverse;
+			image = *(uint32_t *)p;
+			*(uint32_t *)p = (image & ~lmask) | (lhalf & lmask);
+			p += BYTESDONE;
+			rhalf = (glyph >> (BLITWIDTH - align)) ^ inverse;
+			image = *(uint32_t *)p;
+			*(uint32_t *)p = (rhalf & rmask) | (image & ~rmask);
+
+			p = (q += scanspan);
+			height--;
+		}
 	}
-	if (wsfont_lock(fcookie, &console_font) != 0) {
-		printf("smg: could not lock 8x15 font\n");
-		return;
+}
+
+static void
+smg_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;
 	}
-	qf = console_font->data;
 
-#if NDZKBD > 0
-	dzkbd_cnattach(0); /* Connect keyboard and screen together */
-#endif
+	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 and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */
+	lmask = ALL1BITS << align;
+	rmask = ALL1BITS >> (-width & ALIGNMASK);
+	if (width <= BLITWIDTH) {
+		uint32_t mask = lmask & rmask;
+		while (height > 0) {
+			image = *(uint32_t *)p;
+			*(uint32_t *)p =
+			    (image & ~mask) | ((image ^ ALL1BITS) & mask);
+			p += scanspan;
+			height--;
+		}
+	} else {
+		uint8_t *q = p;
+
+		while (height > 0) {
+			image = *(uint32_t *)p;
+			*(uint32_t *)p =
+			    (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
+			p += BYTESDONE;
+			image = *(uint32_t *)p;
+			*(uint32_t *)p =
+			    ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
+
+			p = (q += scanspan);
+			height--;
+		}
+	}
+	ri->ri_flg ^= RI_CURSOR;
+}
+
+static void
+smg_blockmove(struct rasops_info *ri, u_int sx, u_int y, u_int dx, u_int cx,
+    u_int cy, int rop)
+{
+	int width;		/* add to get to same position in next line */
+
+	unsigned int *psrcLine, *pdstLine;
+				/* pointers to line with current src and dst */
+	unsigned int *psrc;	/* pointer to current src longword */
+	unsigned int *pdst;	/* pointer to current dst longword */
+
+				/* following used for looping through a line */
+	unsigned int startmask, endmask;  /* masks for writing ends of dst */
+	int nlMiddle;		/* whole longwords in dst */
+	int nl;			/* temp copy of nlMiddle */
+	int xoffSrc;		/* offset (>= 0, < 32) from which to
+				   fetch whole longwords fetched in src */
+	int nstart;		/* number of ragged bits at start of dst */
+	int nend;		/* number of ragged bits at end of dst */
+	int srcStartOver;	/* pulling nstart bits from src
+				   overflows into the next word? */
+
+	width = SM_XWIDTH >> 5;
+
+	/* start at first scanline */
+	psrcLine = pdstLine = ((u_int *)ri->ri_bits) + (y * width);
+
+	/* x direction doesn't matter for < 1 longword */
+	if (cx <= 32) {
+		int srcBit, dstBit;	/* bit offset of src and dst */
+
+		pdstLine += (dx >> 5);
+		psrcLine += (sx >> 5);
+		psrc = psrcLine;
+		pdst = pdstLine;
+
+		srcBit = sx & ALIGNMASK;
+		dstBit = dx & ALIGNMASK;
+
+		while (cy--) {
+			getandputrop(psrc, srcBit, dstBit, cx, pdst, rop);
+			pdst += width;
+			psrc += width;
+		}
+	} else {
+		startmask = ALL1BITS << (dx & ALIGNMASK);
+		endmask   = ALL1BITS >> (~cx & ALIGNMASK);
+		if (startmask)
+			nlMiddle = (cx - (32 - (dx & ALIGNMASK))) >> 5;
+		else
+			nlMiddle = cx >> 5;
+
+		if (startmask)
+			nstart = 32 - (dx & ALIGNMASK);
+		else
+			nstart = 0;
+		if (endmask)
+			nend = (dx + cx) & ALIGNMASK;
+		else
+			nend = 0;
+
+		xoffSrc = ((sx & ALIGNMASK) + nstart) & ALIGNMASK;
+		srcStartOver = ((sx & ALIGNMASK) + nstart) > 31;
+
+		if (sx >= dx) {	/* move left to right */
+			pdstLine += (dx >> 5);
+			psrcLine += (sx >> 5);
+
+			while (cy--) {
+				psrc = psrcLine;
+				pdst = pdstLine;
+
+				if (startmask) {
+					getandputrop(psrc, (sx & ALIGNMASK),
+					    (dx & ALIGNMASK), nstart, pdst, rop);
+					pdst++;
+					if (srcStartOver)
+						psrc++;
+				}
+
+				/* special case for aligned operations */
+				if (xoffSrc == 0) {
+					nl = nlMiddle;
+					while (nl--) {
+						switch (rop) {
+						case RR_CLEAR:
+							*pdst = 0;
+							break;
+						case RR_SET:
+							*pdst = ~0;
+							break;
+						default:
+							*pdst = *psrc;
+							break;
+						}
+						psrc++;
+						pdst++;
+					}
+				} else {
+					nl = nlMiddle + 1;
+					while (--nl) {
+						switch (rop) {
+						case RR_CLEAR:
+							*pdst = 0;
+							break;
+						case RR_SET:
+							*pdst = ~0;
+							break;
+						default:
+							getunalignedword(psrc,
+							    xoffSrc, *pdst);
+							break;
+						}
+						pdst++;
+						psrc++;
+					}
+				}
+
+				if (endmask) {
+					getandputrop(psrc, xoffSrc, 0, nend,
+					    pdst, rop);
+				}
+
+				pdstLine += width;
+				psrcLine += width;
+			}
+		} else {	/* move right to left */
+			pdstLine += ((dx + cx) >> 5);
+			psrcLine += ((sx + cx) >> 5);
+			/*
+			 * If fetch of last partial bits from source crosses
+			 * a longword boundary, start at the previous longword
+			 */
+			if (xoffSrc + nend >= 32)
+				--psrcLine;
+
+			while (cy--) {
+				psrc = psrcLine;
+				pdst = pdstLine;
+
+				if (endmask) {
+					getandputrop(psrc, xoffSrc, 0, nend,
+					    pdst, rop);
+				}
+
+				nl = nlMiddle + 1;
+				while (--nl) {
+					--psrc;
+					--pdst;
+					switch (rop) {
+					case RR_CLEAR:
+						*pdst = 0;
+						break;
+					case RR_SET:
+						*pdst = ~0;
+						break;
+					default:
+						getunalignedword(psrc, xoffSrc,
+						    *pdst);
+						break;
+					}
+				}
+
+				if (startmask) {
+					if (srcStartOver)
+						--psrc;
+					--pdst;
+					getandputrop(psrc, (sx & ALIGNMASK),
+					    (dx & ALIGNMASK), nstart, pdst,
+					    rop);
+				}
+
+				pdstLine += width;
+				psrcLine += width;
+			}
+		}
+	}
+}
+
+static void
+smg_copycols(void *cookie, int row, int src, int dst, int n)
+{
+	struct rasops_info *ri = cookie;
+
+	n *= ri->ri_font->fontwidth;
+	src *= ri->ri_font->fontwidth;
+	dst *= ri->ri_font->fontwidth;
+	row *= ri->ri_font->fontheight;
+
+	smg_blockmove(ri, src, row, dst, n, ri->ri_font->fontheight,
+	    RR_COPY);
+}
+
+static void
+smg_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+	struct rasops_info *ri = cookie;
+	int fg, bg;
+
+	rasops_unpack_attr(attr, &fg, &bg, NULL);
+
+	num *= ri->ri_font->fontwidth;
+	col *= ri->ri_font->fontwidth;
+	row *= ri->ri_font->fontheight;
+
+	smg_blockmove(ri, col, row, col, num, ri->ri_font->fontheight,
+	    bg == 0 ? RR_CLEAR : RR_SET);
 }
 
 /*
- * Called very early to setup the glass tty as console.
- * Because it's called before the VM system is inited, virtual memory
- * for the framebuffer can be stolen directly without disturbing anything.
+ * Console support code
  */
+
+cons_decl(smg);
+
 void
 smgcnprobe(struct consdev *cndev)
 {
@@ -671,9 +993,12 @@ smgcnprobe(struct consdev *cndev)
 	case VAX_BTYP_410:
 	case VAX_BTYP_420:
 	case VAX_BTYP_43:
-		if ((vax_confdata & KA420_CFG_L3CON) ||
-		    (vax_confdata & KA420_CFG_MULTU))
-			break; /* doesn't use graphics console */
+		if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0)
+			break;	/* doesn't use graphics console */
+
+		if ((vax_confdata & KA420_CFG_VIDOPT) != 0)
+			break;	/* there is a color option */
+
 		cndev->cn_pri = CN_INTERNAL;
 		cndev->cn_dev =
 		    makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 0);
@@ -683,3 +1008,47 @@ smgcnprobe(struct consdev *cndev)
 		break;
 	}
 }
+
+/*
+ * Called very early to setup the glass tty as console.
+ * Because it's called before the VM system is initialized, virtual memory
+ * for the framebuffer can be stolen directly without disturbing anything.
+ */
+void
+smgcninit(struct consdev *cndev)
+{
+	struct smg_screen *ss = &smg_consscr;
+	vaddr_t ova;
+	long defattr;
+	struct rasops_info *ri;
+	extern vaddr_t virtual_avail;
+
+	ova = virtual_avail;
+
+	ss->ss_addr = (uint8_t *)virtual_avail;
+	ioaccess(virtual_avail, SMADDR, SMSIZE / VAX_NBPG);
+	virtual_avail += SMSIZE;
+
+	ss->ss_cursor = (struct dc503reg *)virtual_avail;
+	ioaccess(virtual_avail, KA420_CUR_BASE, 1);
+	virtual_avail += VAX_NBPG;
+
+	virtual_avail = round_page(virtual_avail);
+
+	/* this had better not fail */
+	if (smg_setup_screen(ss) != 0) {
+		iounaccess((vaddr_t)ss->ss_addr, SMSIZE / VAX_NBPG);
+		iounaccess((vaddr_t)ss->ss_cursor, 1);
+		virtual_avail = ova;
+		return;
+	}
+
+	ri = &ss->ss_ri;
+	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
+	wsdisplay_cnattach(&smg_stdscreen, ri, 0, 0, defattr);
+	cn_tab->cn_pri = CN_INTERNAL;
+
+#if NDZKBD > 0
+	dzkbd_cnattach(0); /* Connect keyboard and screen together */
+#endif
+}

Added files:

Index: src/sys/arch/vax/vsa/maskbits.h
diff -u /dev/null src/sys/arch/vax/vsa/maskbits.h:1.1.2.2
--- /dev/null	Wed Feb 15 19:14:50 2023
+++ src/sys/arch/vax/vsa/maskbits.h	Wed Feb 15 19:14:50 2023
@@ -0,0 +1,75 @@
+/*	$NetBSD: maskbits.h,v 1.1.2.2 2023/02/15 19:14:50 martin Exp $	*/
+/*	$OpenBSD: maskbits.h,v 1.1 2006/08/05 10:00:30 miod Exp $	*/
+
+/*-
+ * Copyright (c) 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)maskbits.h	8.2 (Berkeley) 3/21/94
+ */
+
+/*
+ * Derived from X11R4
+ */
+
+#define	FASTGETBITS(psrc,x,w,dst)					\
+	__asm__ ("extzv %1,%2,%3,%0"					\
+		: "=g" (dst)						\
+		: "g" (x), "g" (w), "m" (*(char *)(psrc)))
+
+#define	FASTPUTBITS(src, x, w, pdst)					\
+	__asm__ ("insv %3,%1,%2,%0"					\
+		: "=m" (*(char *)(pdst))				\
+		: "g" (x), "g" (w), "g" (src))
+
+#define	RR_CLEAR	0x00
+#define	RR_SET		0x01
+#define	RR_COPY		0x02
+
+#define getandputrop(psrc, srcbit, dstbit, width, pdst, rop)		\
+do {									\
+	unsigned int _tmpdst;						\
+	switch (rop) {							\
+	case RR_CLEAR:							\
+		_tmpdst = 0;						\
+		break;							\
+	case RR_SET:							\
+		_tmpdst = ~0;						\
+		break;							\
+	default:							\
+		FASTGETBITS(psrc, srcbit, width, _tmpdst);		\
+		break;							\
+	}								\
+	FASTPUTBITS(_tmpdst, dstbit, width, pdst);			\
+} while (0)
+
+#define getunalignedword(psrc, x, dst)					\
+do {									\
+        int _tmp;							\
+        FASTGETBITS(psrc, x, 32, _tmp);					\
+        dst = _tmp;							\
+} while (0)

Index: src/sys/dev/ic/dc503reg.h
diff -u /dev/null src/sys/dev/ic/dc503reg.h:1.1.2.2
--- /dev/null	Wed Feb 15 19:14:50 2023
+++ src/sys/dev/ic/dc503reg.h	Wed Feb 15 19:14:50 2023
@@ -0,0 +1,100 @@
+/*	$NetBSD: dc503reg.h,v 1.1.2.2 2023/02/15 19:14:50 martin Exp $	*/
+/*	$OpenBSD: dc503reg.h,v 1.1 2006/07/23 19:17:23 miod Exp $	*/
+/*	NetBSD: pmreg.h,v 1.7 2005/12/11 12:18:36 christos Exp 	*/
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pmreg.h	8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Layout of the programmable cursor chip (DC503) registers.
+ * All registers are 16 bit wide.
+ */
+
+#define	PCC_CMD		0x00	/* cursor command register */
+#define	PCCCMD_TEST	0x8000
+#define	PCCCMD_HSHI	0x4000
+#define	PCCCMD_VBHI	0x2000
+#define	PCCCMD_LODSA	0x1000
+#define	PCCCMD_FORG2	0x0800
+#define	PCCCMD_ENRG2	0x0400
+#define	PCCCMD_FORG1	0x0200
+#define	PCCCMD_ENRG1	0x0100
+#define	PCCCMD_XHWID	0x0080
+#define	PCCCMD_XHCL1	0x0040
+#define	PCCCMD_XHCLP	0x0020
+#define	PCCCMD_XHAIR	0x0010
+#define	PCCCMD_FOPB	0x0008
+#define	PCCCMD_ENPB	0x0004
+#define	PCCCMD_FOPA	0x0002
+#define	PCCCMD_ENPA	0x0001
+
+#define	PCC_XPOS	0x04	/* cursor X position */
+#define	PCC_YPOS	0x08	/* cursor Y position */
+#define	PCC_XMIN_1	0x0c	/* region 1 left edge */
+#define	PCC_XMAX_1	0x10	/* region 1 right edge */
+#define	PCC_YMIN_1	0x14	/* region 1 top edge */
+#define	PCC_YMAX_1	0x18	/* region 1 bottom edge */
+#define	PCC_XMIN_2	0x1c	/* region 2 left edge */
+#define	PCC_XMAX_2	0x20	/* region 2 right edge */
+#define	PCC_YMIN_2	0x24	/* region 2 top edge */
+#define	PCC_YMAX_2	0x28	/* region 2 bottom edge */
+#define	PCC_LOAD	0x2c	/* cursor pattern load */
+
+struct dc503reg {
+	volatile uint16_t	cmdr;
+	int16_t	pad1;
+	volatile uint16_t	xpos;
+	int16_t	pad2;
+	volatile uint16_t	ypos;
+	int16_t	pad3;
+	volatile uint16_t	xmin1;
+	int16_t	pad4;
+	volatile uint16_t	xmax1;
+	int16_t	pad5;
+	volatile uint16_t	ymin1;
+	int16_t	pad6;
+	volatile uint16_t	ymax1;
+	int16_t	pad7[9];
+	volatile uint16_t	xmin2;
+	int16_t	pad8;
+	volatile uint16_t	xmax2;
+	int16_t	pad9;
+	volatile uint16_t	ymin2;
+	int16_t	pad10;
+	volatile uint16_t	ymax2;
+	int16_t	pad11;
+	volatile uint16_t	load;
+};
+
+#define	PCC_CURSOR_SIZE	16

Reply via email to