Module Name:    src
Committed By:   martin
Date:           Mon Dec 28 20:10:04 UTC 2020

Modified Files:
        src/sys/arch/hp300/dev [netbsd-9]: sti_sgc.c
        src/sys/dev/ic [netbsd-9]: sti.c stivar.h

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

        sys/dev/ic/stivar.h: revision 1.11
        sys/dev/ic/sti.c: revision 1.23
        sys/dev/ic/sti.c: revision 1.24
        sys/dev/ic/sti.c: revision 1.25
        sys/arch/hp300/dev/sti_sgc.c: revision 1.4

Pull the latest OpenBSD sti(4) changes for bitmap framebuffer support.
- bitmap and colormap ops based on old HP ngle X11 driver:
  http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/dev/ic/sti.c#rev1.76
  > Work-in-progress support for non-accelerated X11 on *some* sti(4)
  > frame buffers; based upon the old HP ngle X11 driver.
  > Currently limited to CRX (720/735/750), Timber (710, old 715),
  > Artist (712, 715) and EG (B-series), however the
  > colormap isn't set up correctly on Timber and EG yet.
  >
  > Joint work with Artem Falcon, now in good enough shape to be worked further
  > in the tree.
- misc other cosmetic changes to reduce diffs
No particular comments on port-hp300@ and port-hppa@:
 https://mail-index.netbsd.org/port-hp300/2020/12/19/msg000184.html
 https://mail-index.netbsd.org/port-hp300/2020/12/20/msg000185.html

The MD hp300 attachment for SGC CRX (A1659-66001) will be committed
separately.

Add bitmap access ops support for SGC CRX (A1659-66001) framebuffer.
Also modify existing 425e EVRX attachment to use updated MI sti(4) ops
more efficiently.

The Xorg server and mlterm-wscons (that support wsdisplay bitmap) work
fine on SGC hp425t.

No particular comments on port-hp300@ and port-hppa@:
 https://mail-index.netbsd.org/port-hp300/2020/12/19/msg000184.html
 https://mail-index.netbsd.org/port-hp300/2020/12/20/msg000185.html

Special thanks to Miod Vallat again, for contributing the SGC CRX
framebuffer with the SGC connector and flexible cable for HP9000/425t.

He also contributed DIO-II "Hyperion" monochrome framebuffer and
1 plane grayscale SGC GRX (A1924-66001), and I've confirmed hyper(4)
just works even with Xorg server.  I will try GRX as the next project.

Handle WSSCREEN_REVERSE properly.  Based on OpenBSD's sti(4).

Also remove WSSCREEN_UNDERLINE from capabilities that is not handled
by sti(4) ROM routines.

Tested on HP9000/425t with CRX.

Ignore WSDISPLAYIO_PUTCMAP in WSDISPLAYIO_MODE_EMUL, i.e. text mode.

The hardware palette settings are handled by the STI ROM in STI_TEXTMODE
and changing cmap could cause mangled text colors at least on CRX on 425t.

Updating CMAP in EMUL mode isn't expected anyway.

Fixes "red or invisible text" after exiting mlterm-wscons on A1659 CRX.


To generate a diff of this commit:
cvs rdiff -u -r1.2.34.1 -r1.2.34.2 src/sys/arch/hp300/dev/sti_sgc.c
cvs rdiff -u -r1.19.12.1 -r1.19.12.2 src/sys/dev/ic/sti.c
cvs rdiff -u -r1.9.34.1 -r1.9.34.2 src/sys/dev/ic/stivar.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/hp300/dev/sti_sgc.c
diff -u src/sys/arch/hp300/dev/sti_sgc.c:1.2.34.1 src/sys/arch/hp300/dev/sti_sgc.c:1.2.34.2
--- src/sys/arch/hp300/dev/sti_sgc.c:1.2.34.1	Mon May 18 17:52:22 2020
+++ src/sys/arch/hp300/dev/sti_sgc.c	Mon Dec 28 20:10:04 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: sti_sgc.c,v 1.2.34.1 2020/05/18 17:52:22 martin Exp $	*/
+/*	$NetBSD: sti_sgc.c,v 1.2.34.2 2020/12/28 20:10:04 martin Exp $	*/
 /*	$OpenBSD: sti_sgc.c,v 1.14 2007/05/26 00:36:03 krw Exp $	*/
 
 /*
@@ -27,7 +27,7 @@
  *
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sti_sgc.c,v 1.2.34.1 2020/05/18 17:52:22 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sti_sgc.c,v 1.2.34.2 2020/12/28 20:10:04 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -49,33 +49,40 @@ struct sti_sgc_softc {
 	struct sti_softc sc_sti;
 
 	paddr_t sc_bitmap;
-	bus_space_tag_t sc_bst;
-	bus_space_handle_t sc_ramdach;
 };
 
 /*
  * 425e EVRX specific hardware
  */
-#define STI_EVRX_RAMDACOFFSET	0x060000
-#define STI_EVRX_RAMDACSIZE	0x000800
+/*
+ * EVRX RAMDAC (Bt458) is found at offset 0x060000 from SGC bus PA and 
+ * offset 0x040000 length 0x1c0000 is mapped in MI sti via ROM region 2
+ */
+#define STI_EVRX_REGNO2OFFSET	0x020000
 #define STI_EVRX_FBOFFSET	0x200000
 
-#define EVRX_BT458_ADDR		(0x200 + 2)
-#define EVRX_BT458_CMAP		(0x204 + 2)
-#define EVRX_BT458_CTRL		(0x208 + 2)
-#define EVRX_BT458_OMAP		(0x20C + 2)
+#define EVRX_BT458_ADDR		(STI_EVRX_REGNO2OFFSET + 0x200 + 2)
+#define EVRX_BT458_CMAP		(STI_EVRX_REGNO2OFFSET + 0x204 + 2)
+#define EVRX_BT458_CTRL		(STI_EVRX_REGNO2OFFSET + 0x208 + 2)
+#define EVRX_BT458_OMAP		(STI_EVRX_REGNO2OFFSET + 0x20C + 2)
 
 /* from HP-UX /usr/lib/libddevrx.a */
-#define EVRX_MAGIC00		0x600
-#define EVRX_MAGIC04		0x604
-#define EVRX_MAGIC08		0x608
-#define EVRX_MAGIC0C		0x60c
-#define EVRX_MAGIC10		0x610
+#define EVRX_MAGIC00		(STI_EVRX_REGNO2OFFSET + 0x600)
+#define EVRX_MAGIC04		(STI_EVRX_REGNO2OFFSET + 0x604)
+#define EVRX_MAGIC08		(STI_EVRX_REGNO2OFFSET + 0x608)
+#define EVRX_MAGIC0C		(STI_EVRX_REGNO2OFFSET + 0x60c)
+#define EVRX_MAGIC10		(STI_EVRX_REGNO2OFFSET + 0x610)
 #define EVRX_MAGIC10_BSY	0x00010000
-#define EVRX_MAGIC18		0x618
-#define EVRX_MAGIC1C		0x61c
+#define EVRX_MAGIC18		(STI_EVRX_REGNO2OFFSET + 0x618)
+#define EVRX_MAGIC1C		(STI_EVRX_REGNO2OFFSET + 0x61c)
+
+/*
+ * HP A1659A CRX specific hardware
+ */
+#define STI_CRX_FBOFFSET	0x01000000
 
 static int sticonslot = -1;
+static struct bus_space_tag sticn_tag;
 static struct sti_rom sticn_rom;
 static struct sti_screen sticn_scr;
 static bus_addr_t sticn_bases[STI_REGION_MAX];
@@ -88,16 +95,16 @@ static int sti_sgc_probe(bus_space_tag_t
 CFATTACH_DECL_NEW(sti_sgc, sizeof(struct sti_sgc_softc),
     sti_sgc_match, sti_sgc_attach, NULL, NULL);
 
-/* 425e EVRX specific access functions */
-static int sti_evrx_setcmap(struct sti_sgc_softc *, struct wsdisplay_cmap *);
-static void sti_evrx_resetramdac(struct sti_sgc_softc *);
-static void sti_evrx_resetcmap(struct sti_sgc_softc *);
-static int sti_evrx_ioctl(void *, void *, u_long, void *, int, struct lwp *);
-static paddr_t sti_evrx_mmap(void *, void *, off_t, int);
-
-static const struct wsdisplay_accessops sti_evrx_accessops = {
-	sti_evrx_ioctl,
-	sti_evrx_mmap,
+/* 425e EVRX/CRX specific access functions */
+static int sti_evrx_putcmap(struct sti_screen *, u_int, u_int);
+static void sti_evrx_resetramdac(struct sti_screen *);
+static void sti_evrx_resetcmap(struct sti_screen *);
+static void sti_evrx_setupfb(struct sti_screen *);
+static paddr_t sti_m68k_mmap(void *, void *, off_t, int);
+
+static const struct wsdisplay_accessops sti_m68k_accessops = {
+	sti_ioctl,
+	sti_m68k_mmap,
 	sti_alloc_screen,
 	sti_free_screen,
 	sti_show_screen,
@@ -126,6 +133,7 @@ sti_sgc_attach(device_t parent, device_t
 	struct sti_softc *ssc = &sc->sc_sti;
 	struct sgc_attach_args *saa = aux;
 	struct sti_screen *scr;
+	bus_space_tag_t bst;
 	bus_space_handle_t romh;
 	bus_addr_t base;
 	struct wsemuldisplaydev_attach_args waa;
@@ -135,6 +143,7 @@ sti_sgc_attach(device_t parent, device_t
 	int i;
 
 	ssc->sc_dev = self;
+	bst = saa->saa_iot;
 	base = (bus_addr_t)sgc_slottopa(saa->saa_slot);
 
 	if (saa->saa_slot == sticonslot) {
@@ -147,18 +156,18 @@ sti_sgc_attach(device_t parent, device_t
 
 		sti_describe(ssc);
 	} else {
-		if (bus_space_map(saa->saa_iot, base, PAGE_SIZE, 0, &romh)) {
+		if (bus_space_map(bst, base, PAGE_SIZE, 0, &romh)) {
 			aprint_error(": can't map ROM");
 			return;
 		}
 		/*
 		 * Compute real PROM size
 		 */
-		romend = sti_rom_size(saa->saa_iot, romh);
+		romend = sti_rom_size(bst, romh);
 
-		bus_space_unmap(saa->saa_iot, romh, PAGE_SIZE);
+		bus_space_unmap(bst, romh, PAGE_SIZE);
 
-		if (bus_space_map(saa->saa_iot, base, romend, 0, &romh)) {
+		if (bus_space_map(bst, base, romend, 0, &romh)) {
 			aprint_error(": can't map frame buffer");
 			return;
 		}
@@ -167,7 +176,7 @@ sti_sgc_attach(device_t parent, device_t
 		for (i = 0; i < STI_REGION_MAX; i++)
 			ssc->bases[i] = base;
 
-		if (sti_attach_common(ssc, saa->saa_iot, saa->saa_iot, romh,
+		if (sti_attach_common(ssc, bst, bst, romh,
 		    STI_CODEBASE_ALT) != 0)
 			return;
 	}
@@ -185,29 +194,21 @@ sti_sgc_attach(device_t parent, device_t
 		 */
 		sc->sc_bitmap = base + STI_EVRX_FBOFFSET;
 
-		/*
-		 * Bt458 RAMDAC can be accessed at offset +0x60200 and
-		 * unknown control registers are around +0x60600.
-		 */
-		sc->sc_bst = saa->saa_iot;
-		if (bus_space_map(sc->sc_bst, base + STI_EVRX_RAMDACOFFSET,
-		    STI_EVRX_RAMDACSIZE, 0, &sc->sc_ramdach)) {
-			aprint_error_dev(self, "can't map RAMDAC\n");
-			return;
-		}
-
 		aprint_normal_dev(self, "Enable mmap support\n");
 
 		/*
 		 * initialize Bt458 RAMDAC and preserve initial color map
 		 */
-		sti_evrx_resetramdac(sc);
-		sti_evrx_resetcmap(sc);
+		sti_evrx_resetramdac(scr);
+		sti_evrx_resetcmap(scr);
+
+		scr->setupfb = sti_evrx_setupfb;
+		scr->putcmap = sti_evrx_putcmap;
 
 		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
 		waa.console = ssc->sc_flags & STI_CONSOLE ? 1 : 0;
 		waa.scrdata = &scr->scr_screenlist;
-		waa.accessops = &sti_evrx_accessops;
+		waa.accessops = &sti_m68k_accessops;
 		waa.accesscookie = scr;
 
 		config_found(ssc->sc_dev, &waa, wsemuldisplaydevprint);
@@ -216,9 +217,20 @@ sti_sgc_attach(device_t parent, device_t
 	case STI_DD_CRX:
 		/*
 		 * HP A1659A CRX on some 425t variants.
-		 * Not investigated yet; needs to check HP-UX libddgcrx.a etc.
+		 * bitmap memory can be accessed at offset +0x1000000.
 		 */
-		/* FALLTHROUGH */
+		sc->sc_bitmap = base + STI_CRX_FBOFFSET;
+
+		aprint_normal_dev(self, "Enable mmap support\n");
+
+		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
+		waa.console = ssc->sc_flags & STI_CONSOLE ? 1 : 0;
+		waa.scrdata = &scr->scr_screenlist;
+		waa.accessops = &sti_m68k_accessops;
+		waa.accesscookie = scr;
+
+		config_found(ssc->sc_dev, &waa, wsemuldisplaydevprint);
+		break;
 	default:
 		/*
 		 * Unsupported variants.
@@ -256,34 +268,12 @@ sti_sgc_probe(bus_space_tag_t iot, int s
 }
 
 static int
-sti_evrx_setcmap(struct sti_sgc_softc *sc, struct wsdisplay_cmap *p)
+sti_evrx_putcmap(struct sti_screen *scr, u_int index, u_int count)
 {
-	struct sti_softc *ssc = &sc->sc_sti;
-	struct sti_screen *scr = ssc->sc_scr;
-	bus_space_tag_t bst = sc->sc_bst;
-	bus_space_handle_t bsh = sc->sc_ramdach;
-	uint8_t r[STI_NCMAP], g[STI_NCMAP], b[STI_NCMAP];
-	u_int index, count;
-	int i, error;
-
-	index = p->index;
-	count = p->count;
-	if (index >= STI_NCMAP || count > STI_NCMAP - index)
-		return EINVAL;
-
-	error = copyin(p->red, &r[index], count);
-	if (error)
-		return error;
-	error = copyin(p->green, &g[index], count);
-	if (error)
-		return error;
-	error = copyin(p->blue, &b[index], count);
-	if (error)
-		return error;
-
-	memcpy(&scr->scr_rcmap[index], &r[index], count);
-	memcpy(&scr->scr_gcmap[index], &g[index], count);
-	memcpy(&scr->scr_bcmap[index], &b[index], count);
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t bst = rom->memt;
+	bus_space_handle_t bsh = rom->regh[2];
+	int i;
 
 	/* magic setup from HP-UX */
 	bus_space_write_4(bst, bsh, EVRX_MAGIC08, 0x00000001);
@@ -302,10 +292,11 @@ sti_evrx_setcmap(struct sti_sgc_softc *s
 }
 
 static void
-sti_evrx_resetramdac(struct sti_sgc_softc *sc)
+sti_evrx_resetramdac(struct sti_screen *scr)
 {
-	bus_space_tag_t bst = sc->sc_bst;
-	bus_space_handle_t bsh = sc->sc_ramdach;
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t bst = rom->memt;
+	bus_space_handle_t bsh = rom->regh[2];
 #if 0
 	int i;
 #endif
@@ -351,12 +342,11 @@ sti_evrx_resetramdac(struct sti_sgc_soft
 }
 
 static void
-sti_evrx_resetcmap(struct sti_sgc_softc *sc)
+sti_evrx_resetcmap(struct sti_screen *scr)
 {
-	struct sti_softc *ssc = &sc->sc_sti;
-	struct sti_screen *scr = ssc->sc_scr;
-	bus_space_tag_t bst = sc->sc_bst;
-	bus_space_handle_t bsh = sc->sc_ramdach;
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t bst = rom->memt;
+	bus_space_handle_t bsh = rom->regh[2];
 	int i;
 
 	/* magic setup from HP-UX */
@@ -376,68 +366,16 @@ sti_evrx_resetcmap(struct sti_sgc_softc 
 	}
 }
 
-static int
-sti_evrx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
-    struct lwp *l)
+static void
+sti_evrx_setupfb(struct sti_screen *scr)
 {
-	struct sti_screen *scr = (struct sti_screen *)v;
-	struct sti_rom *rom = scr->scr_rom;
-	struct sti_softc *ssc = rom->rom_softc;
-	struct sti_sgc_softc *sc = device_private(ssc->sc_dev);
-	struct wsdisplay_fbinfo *wdf;
-	struct wsdisplay_cmap *cmapp;
-	u_int idx, count;
-	int error, new_mode;
-
-	switch (cmd) {
-	case WSDISPLAYIO_GINFO:
-		wdf = (struct wsdisplay_fbinfo *)data;
-		wdf->height = scr->scr_cfg.scr_height;
-		wdf->width  = scr->scr_cfg.scr_width;
-		wdf->depth  = scr->scr_bpp;
-		wdf->cmsize = STI_NCMAP;
-		return 0;
-
-	case WSDISPLAYIO_GETCMAP:
-		cmapp = (struct wsdisplay_cmap *)data;
-		idx = cmapp->index;
-		count = cmapp->count;
-		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
-			return EINVAL;
-		error = copyout(&scr->scr_rcmap[idx], cmapp->red, count);
-		if (error != 0)
-			return error;
-		error = copyout(&scr->scr_gcmap[idx], cmapp->green, count);
-		if (error != 0)
-			return error;
-		error = copyout(&scr->scr_bcmap[idx], cmapp->blue, count);
-		if (error != 0)
-			return error;
-		return 0;
-		
-	case WSDISPLAYIO_PUTCMAP:
-		cmapp = (struct wsdisplay_cmap *)data;
-		return sti_evrx_setcmap(sc, cmapp);
-
-	case WSDISPLAYIO_SMODE:
-		new_mode = *(int *)data;
-		if (new_mode != scr->scr_wsmode) {
-			scr->scr_wsmode = new_mode;
-			if (new_mode == WSDISPLAYIO_MODE_EMUL) {
-				sti_init(scr, STI_TEXTMODE);
-			} else if (new_mode == WSDISPLAYIO_MODE_DUMBFB) {
-				sti_init(scr, 0);
-				sti_evrx_resetramdac(sc);
-			}
-		}
-		return 0;
 
-	}
-	return sti_ioctl(v, vs, cmd, data, flag, l);
+	sti_init(scr, 0);
+	sti_evrx_resetramdac(scr);
 }
 
 static paddr_t
-sti_evrx_mmap(void *v, void *vs, off_t offset, int prot)
+sti_m68k_mmap(void *v, void *vs, off_t offset, int prot)
 {
 	struct sti_screen *scr = (struct sti_screen *)v;
 	struct sti_rom *rom = scr->scr_rom;
@@ -491,11 +429,13 @@ sti_sgc_cnattach(bus_space_tag_t bst, bu
 {
 	int i;
 
+	sticn_tag = *bst;
+
 	/* sticn_bases[0] will be fixed in sti_cnattach() */
 	for (i = 0; i < STI_REGION_MAX; i++)
 		sticn_bases[i] = addr;
 
-	sti_cnattach(&sticn_rom, &sticn_scr, bst, sticn_bases,
+	sti_cnattach(&sticn_rom, &sticn_scr, &sticn_tag, sticn_bases,
 	    STI_CODEBASE_ALT);
 
 	sticonslot = slot;

Index: src/sys/dev/ic/sti.c
diff -u src/sys/dev/ic/sti.c:1.19.12.1 src/sys/dev/ic/sti.c:1.19.12.2
--- src/sys/dev/ic/sti.c:1.19.12.1	Mon May 18 17:52:22 2020
+++ src/sys/dev/ic/sti.c	Mon Dec 28 20:10:04 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: sti.c,v 1.19.12.1 2020/05/18 17:52:22 martin Exp $	*/
+/*	$NetBSD: sti.c,v 1.19.12.2 2020/12/28 20:10:04 martin Exp $	*/
 
 /*	$OpenBSD: sti.c,v 1.61 2009/09/05 14:09:35 miod Exp $	*/
 
@@ -31,11 +31,11 @@
  * TODO:
  *	call sti procs asynchronously;
  *	implement console scroll-back;
- *	X11 support.
+ *	X11 support on more models.
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.19.12.1 2020/05/18 17:52:22 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.19.12.2 2020/12/28 20:10:04 martin Exp $");
 
 #include "wsdisplay.h"
 
@@ -79,33 +79,45 @@ void sti_copyrows(void *, int, int, int)
 void sti_eraserows(void *, int, int, long);
 int  sti_alloc_attr(void *, int, int, int, long *);
 
+/* pseudo attribute ops for sti ROM putchar function */
+#define WSATTR_FG_SHIFT	24
+#define WSATTR_BG_SHIFT	16
+#define WSATTR_UNPACK_FG(attr)	(((attr) >> WSATTR_FG_SHIFT) & 0xff)
+#define WSATTR_UNPACK_BG(attr)	(((attr) >> WSATTR_BG_SHIFT) & 0xff)
+#define WSATTR_UNPACK_FLAG(attr) ((attr) & WSATTR_USERMASK)
+#define WSATTR_PACK_FG(fg)	((fg) << WSATTR_FG_SHIFT)
+#define WSATTR_PACK_BG(bg)	((bg) << WSATTR_BG_SHIFT)
+#define WSATTR_PACK_FLAG(flag)	((flag))
+#define WSATTR_PACK(fg, bg, flag)	\
+    (WSATTR_PACK_FG(fg) | WSATTR_PACK_BG(bg) | WSATTR_PACK_FLAG(flag))
+
 struct wsdisplay_emulops sti_emulops = {
-	sti_cursor,
-	sti_mapchar,
-	sti_putchar,
-	sti_copycols,
-	sti_erasecols,
-	sti_copyrows,
-	sti_eraserows,
-	sti_alloc_attr
+	.cursor = sti_cursor,
+	.mapchar = sti_mapchar,
+	.putchar = sti_putchar,
+	.copycols = sti_copycols,
+	.erasecols = sti_erasecols,
+	.copyrows = sti_copyrows,
+	.eraserows = sti_eraserows,
+	.allocattr = sti_alloc_attr
 };
 
 const struct wsdisplay_accessops sti_accessops = {
-	sti_ioctl,
-	sti_mmap,
-	sti_alloc_screen,
-	sti_free_screen,
-	sti_show_screen,
-	sti_load_font
+	.ioctl = sti_ioctl,
+	.mmap = sti_mmap,
+	.alloc_screen = sti_alloc_screen,
+	.free_screen = sti_free_screen,
+	.show_screen = sti_show_screen,
+	.load_font = sti_load_font
 };
 
 enum sti_bmove_funcs {
 	bmf_clear, bmf_copy, bmf_invert, bmf_underline
 };
 
-int	sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
 void	sti_bmove(struct sti_screen *, int, int, int, int, int, int,
 	    enum sti_bmove_funcs);
+int	sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
 int	sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char);
 
 struct sti_screen *sti_attach_screen(struct sti_softc *, int);
@@ -118,6 +130,15 @@ int	sti_rom_setup(struct sti_rom *, bus_
 	    bus_space_handle_t, bus_addr_t *, u_int);
 int	sti_screen_setup(struct sti_screen *, int);
 
+int	ngle_default_putcmap(struct sti_screen *, u_int, u_int);
+
+#ifndef SMALL_KERNEL
+void	ngle_artist_setupfb(struct sti_screen *);
+void	ngle_elk_setupfb(struct sti_screen *);
+void	ngle_timber_setupfb(struct sti_screen *);
+int	ngle_putcmap(struct sti_screen *, u_int, u_int);
+#endif
+
 #if NSTI_PCI > 0
 #define	STI_ENABLE_ROM(sc) \
 do { \
@@ -220,51 +241,52 @@ sti_rom_setup(struct sti_rom *rom, bus_s
 	/*
 	 * Get ROM header and code function pointers.
 	 */
+
 	dd = &rom->rom_dd;
 	rom->rom_devtype = bus_space_read_1(memt, romh, 3);
 	if (rom->rom_devtype == STI_DEVTYPE1) {
-		dd->dd_type  = bus_space_read_1(memt, romh, 0x03);
-		dd->dd_nmon  = bus_space_read_1(memt, romh, 0x07);
-		dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b);
-		dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f);
-		dd->dd_grid[0] = parseword(0x10);
-		dd->dd_grid[1] = parseword(0x20);
-		dd->dd_fntaddr = parseword(0x30) & ~3;
-		dd->dd_maxst   = parseword(0x40);
-		dd->dd_romend  = parseword(0x50) & ~3;
-		dd->dd_reglst  = parseword(0x60) & ~3;
-		dd->dd_maxreent= parseshort(0x70);
-		dd->dd_maxtimo = parseshort(0x78);
-		dd->dd_montbl  = parseword(0x80) & ~3;
-		dd->dd_udaddr  = parseword(0x90) & ~3;
-		dd->dd_stimemreq=parseword(0xa0);
-		dd->dd_udsize  = parseword(0xb0);
-		dd->dd_pwruse  = parseshort(0xc0);
-		dd->dd_bussup  = bus_space_read_1(memt, romh, 0xcb);
-		dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf);
-		dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3);
-		dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7);
-		dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb);
-		dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf);
-		dd->dd_cfbaddr = parseword(0xe0) & ~3;
+		dd->dd_type      = bus_space_read_1(memt, romh, 0x03);
+		dd->dd_nmon      = bus_space_read_1(memt, romh, 0x07);
+		dd->dd_grrev     = bus_space_read_1(memt, romh, 0x0b);
+		dd->dd_lrrev     = bus_space_read_1(memt, romh, 0x0f);
+		dd->dd_grid[0]   = parseword(0x10);
+		dd->dd_grid[1]   = parseword(0x20);
+		dd->dd_fntaddr   = parseword(0x30) & ~3;
+		dd->dd_maxst     = parseword(0x40);
+		dd->dd_romend    = parseword(0x50) & ~3;
+		dd->dd_reglst    = parseword(0x60) & ~3;
+		dd->dd_maxreent  = parseshort(0x70);
+		dd->dd_maxtimo   = parseshort(0x78);
+		dd->dd_montbl    = parseword(0x80) & ~3;
+		dd->dd_udaddr    = parseword(0x90) & ~3;
+		dd->dd_stimemreq = parseword(0xa0);
+		dd->dd_udsize    = parseword(0xb0);
+		dd->dd_pwruse    = parseshort(0xc0);
+		dd->dd_bussup    = bus_space_read_1(memt, romh, 0xcb);
+		dd->dd_ebussup   = bus_space_read_1(memt, romh, 0xcf);
+		dd->dd_altcodet  = bus_space_read_1(memt, romh, 0xd3);
+		dd->dd_eddst[0]  = bus_space_read_1(memt, romh, 0xd7);
+		dd->dd_eddst[1]  = bus_space_read_1(memt, romh, 0xdb);
+		dd->dd_eddst[2]  = bus_space_read_1(memt, romh, 0xdf);
+		dd->dd_cfbaddr   = parseword(0xe0) & ~3;
 
 		codebase <<= 2;
-		dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3;
-		dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3;
-		dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3;
-		dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3;
-		dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3;
-		dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3;
-		dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3;
-		dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3;
-		dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3;
-		dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3;
-		dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3;
-		dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3;
-		dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3;
-		dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3;
-		dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3;
-		dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3;
+		dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3;
+		dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3;
+		dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3;
+		dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3;
+		dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3;
+		dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3;
+		dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3;
+		dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3;
+		dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3;
+		dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3;
+		dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3;
+		dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3;
+		dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3;
+		dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3;
+		dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3;
+		dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3;
 	} else {	/* STI_DEVTYPE4 */
 		bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd,
 		    sizeof(*dd) / 4);
@@ -298,7 +320,7 @@ sti_rom_setup(struct sti_rom *rom, bus_s
 	 * Note there could be fewer than STI_END pointer entries
 	 * populated, especially on older devices.
 	 */
-	for (i = STI_END; !dd->dd_pacode[i]; i--)
+	for (i = STI_END; dd->dd_pacode[i] == 0; i--)
 		;
 
 	size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
@@ -310,13 +332,12 @@ sti_rom_setup(struct sti_rom *rom, bus_s
 		return EINVAL;
 	}
 
-	DPRINTF(("code size %x/%x\n", size, round_page(size)));
-
 	if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0,
 	    UVM_KMF_WIRED))) {
 		aprint_error(": cannot allocate %u bytes for code\n", size);
 		return ENOMEM;
 	}
+	DPRINTF(("code=0x%lx[%x]\n", rom->rom_code, size));
 
 	/*
 	 * Copy code into memory and make it executable.
@@ -332,8 +353,7 @@ sti_rom_setup(struct sti_rom *rom, bus_s
 
 		for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
 		    addr < eaddr; addr += 4 ) {
-			*p++ = bus_space_read_4(memt, romh, addr)
-			    & 0xff;
+			*p++ = bus_space_read_4(memt, romh, addr) & 0xff;
 		}
 	} else {	/* STI_DEVTYPE4 */
 		bus_space_read_region_stream_4(memt, romh,
@@ -359,26 +379,27 @@ sti_rom_setup(struct sti_rom *rom, bus_s
 	(dd->dd_pacode[(i)] == 0 ? 0 : \
 	    (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) /	\
 	    (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1)))
-	rom->init	= (sti_init_t)	O(STI_INIT_GRAPH);
-	rom->mgmt	= (sti_mgmt_t)	O(STI_STATE_MGMT);
-	rom->unpmv	= (sti_unpmv_t)	O(STI_FONT_UNPMV);
-	rom->blkmv	= (sti_blkmv_t)	O(STI_BLOCK_MOVE);
-	rom->test	= (sti_test_t)	O(STI_SELF_TEST);
-	rom->exhdl	= (sti_exhdl_t)	O(STI_EXCEP_HDLR);
+
+	rom->init	= (sti_init_t)O(STI_INIT_GRAPH);
+	rom->mgmt	= (sti_mgmt_t)O(STI_STATE_MGMT);
+	rom->unpmv	= (sti_unpmv_t)O(STI_FONT_UNPMV);
+	rom->blkmv	= (sti_blkmv_t)O(STI_BLOCK_MOVE);
+	rom->test	= (sti_test_t)O(STI_SELF_TEST);
+	rom->exhdl	= (sti_exhdl_t)O(STI_EXCEP_HDLR);
 	rom->inqconf	= (sti_inqconf_t)O(STI_INQ_CONF);
 	rom->scment	= (sti_scment_t)O(STI_SCM_ENT);
-	rom->dmac	= (sti_dmac_t)	O(STI_DMA_CTRL);
-	rom->flowc	= (sti_flowc_t)	O(STI_FLOW_CTRL);
+	rom->dmac	= (sti_dmac_t)O(STI_DMA_CTRL);
+	rom->flowc	= (sti_flowc_t)O(STI_FLOW_CTRL);
 	rom->utiming	= (sti_utiming_t)O(STI_UTIMING);
-	rom->pmgr	= (sti_pmgr_t)	O(STI_PROC_MGR);
-	rom->util	= (sti_util_t)	O(STI_UTIL);
+	rom->pmgr	= (sti_pmgr_t)O(STI_PROC_MGR);
+	rom->util	= (sti_util_t)O(STI_UTIL);
 
 #undef O
+
 	/*
 	 * Set colormap entry is not implemented until 8.04, so force
 	 * a NULL pointer here.
 	 */
-
 	if (dd->dd_grrev < STI_REVISION(8, 4)) {
 		rom->scment = NULL;
 	}
@@ -398,7 +419,6 @@ sti_region_setup(struct sti_screen *scr)
 	bus_addr_t *bases = rom->bases;
 	struct sti_dd *dd = &rom->rom_dd;
 	struct sti_cfg *cc = &scr->scr_cfg;
-	bus_space_handle_t bh;
 	struct sti_region regions[STI_REGION_MAX], *r;
 	u_int regno, regcnt;
 	bus_addr_t addr;
@@ -459,14 +479,14 @@ sti_region_setup(struct sti_screen *scr)
 			continue;
 		}
 
-		/* XXXNH BUS_SPACE_MAP_CACHEABLE */
 		if (bus_space_map(memt, addr, r->length << PGSHIFT,
-		    r->cache ? BUS_SPACE_MAP_CACHEABLE : 0, &bh)) {
+		    BUS_SPACE_MAP_LINEAR | (r->cache ?
+		    BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) {
+			rom->regh[regno] = romh;	/* XXX */
 			DPRINTF((" - already mapped region\n"));
 		} else {
-
-			/* XXX should use bus_space_vaddr */
-			addr = (bus_addr_t)bh;
+			addr = (bus_addr_t)
+			    bus_space_vaddr(memt, rom->regh[regno]);
 			if (regno == 1) {
 				DPRINTF((" - fb"));
 				scr->fbaddr = addr;
@@ -625,12 +645,79 @@ sti_screen_setup(struct sti_screen *scr,
 	scr->scr_wsd.textops = &sti_emulops;
 	scr->scr_wsd.fontwidth = scr->scr_curfont.width;
 	scr->scr_wsd.fontheight = scr->scr_curfont.height;
-	scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE;
+	scr->scr_wsd.capabilities = WSSCREEN_REVERSE;
 
 	scr->scr_scrlist[0] = &scr->scr_wsd;
 	scr->scr_screenlist.nscreens = 1;
 	scr->scr_screenlist.screens = scr->scr_scrlist;
 
+#ifndef SMALL_KERNEL
+	/*
+	 * Decide which board-specific routines to use.
+	 */
+
+	switch (dd->dd_grid[0]) {
+	case STI_DD_CRX:
+		scr->setupfb = ngle_elk_setupfb;
+		scr->putcmap = ngle_putcmap;
+
+		scr->reg10_value = 0x13601000;
+		if (scr->scr_bpp > 8)
+			scr->reg12_value = NGLE_BUFF1_CMAP3;
+		else
+			scr->reg12_value = NGLE_BUFF1_CMAP0;
+		scr->cmap_finish_register = NGLE_REG_1;
+		break;
+
+	case STI_DD_TIMBER:
+		scr->setupfb = ngle_timber_setupfb;
+		scr->putcmap = ngle_putcmap;
+
+		scr->reg10_value = 0x13602000;
+		scr->reg12_value = NGLE_BUFF1_CMAP0;
+		scr->cmap_finish_register = NGLE_REG_1;
+		break;
+
+	case STI_DD_ARTIST:
+		scr->setupfb = ngle_artist_setupfb;
+		scr->putcmap = ngle_putcmap;
+
+		scr->reg10_value = 0x13601000;
+		scr->reg12_value = NGLE_ARTIST_CMAP0;
+		scr->cmap_finish_register = NGLE_REG_26;
+		break;
+
+	case STI_DD_EG:
+		scr->setupfb = ngle_artist_setupfb;
+		scr->putcmap = ngle_putcmap;
+
+		scr->reg10_value = 0x13601000;
+		if (scr->scr_bpp > 8) {
+			scr->reg12_value = NGLE_BUFF1_CMAP3;
+			scr->cmap_finish_register = NGLE_REG_1;
+		} else {
+			scr->reg12_value = NGLE_ARTIST_CMAP0;
+			scr->cmap_finish_register = NGLE_REG_26;
+		}
+		break;
+
+	case STI_DD_GRX:
+	case STI_DD_CRX24:
+	case STI_DD_EVRX:
+	case STI_DD_3X2V:
+	case STI_DD_DUAL_CRX:
+	case STI_DD_HCRX:
+	case STI_DD_LEGO:
+	case STI_DD_SUMMIT:
+	case STI_DD_PINNACLE:
+	default:
+		scr->setupfb = NULL;
+		scr->putcmap =
+		    rom->scment == NULL ? NULL : ngle_default_putcmap;
+		break;
+	}
+#endif
+
 	return 0;
 
 fail:
@@ -671,6 +758,11 @@ sti_describe(struct sti_softc *sc)
 		sti_describe_screen(sc, sc->sc_scr);
 }
 
+/*
+ * Final part of attachment. On hppa where we use the PDC console
+ * during autoconf, this has to be postponed until autoconf has
+ * completed.
+ */
 void
 sti_end_attach(struct sti_softc *sc)
 {
@@ -844,6 +936,7 @@ rescan:
 /*
  * Wrappers around STI code pointers
  */
+
 int
 sti_init(struct sti_screen *scr, int mode)
 {
@@ -972,11 +1065,10 @@ int
 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
 {
 	struct sti_screen *scr = (struct sti_screen *)v;
-	struct sti_rom *rom = scr->scr_rom;
 	struct wsdisplay_fbinfo *wdf;
 	struct wsdisplay_cmap *cmapp;
 	u_int mode, idx, count;
-	int i, ret;
+	int ret;
 
 	ret = 0;
 	switch (cmd) {
@@ -986,13 +1078,31 @@ sti_ioctl(void *v, void *vs, u_long cmd,
 
 	case WSDISPLAYIO_SMODE:
 		mode = *(u_int *)data;
-		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
-		    mode == WSDISPLAYIO_MODE_DUMBFB)
-			ret = sti_init(scr, 0);
-		else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
-		    mode == WSDISPLAYIO_MODE_EMUL)
-			ret = sti_init(scr, STI_TEXTMODE);
-		scr->scr_wsmode = mode;
+		switch (mode) {
+		case WSDISPLAYIO_MODE_EMUL:
+			if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
+				ret = sti_init(scr, STI_TEXTMODE);
+			break;
+		case WSDISPLAYIO_MODE_DUMBFB:
+			if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
+				sti_init(scr, 0);
+				if (scr->setupfb != NULL)
+					scr->setupfb(scr);
+				else
+#if 0
+					ret = sti_init(scr, STI_FBMODE);
+#else
+					ret = EINVAL;
+#endif
+			}
+			break;
+		case WSDISPLAYIO_MODE_MAPPED:
+		default:
+			ret = EINVAL;
+			break;
+		}
+		if (ret == 0)
+			scr->scr_wsmode = mode;
 		break;
 
 	case WSDISPLAYIO_GTYPE:
@@ -1004,19 +1114,22 @@ sti_ioctl(void *v, void *vs, u_long cmd,
 		wdf->height = scr->scr_cfg.scr_height;
 		wdf->width  = scr->scr_cfg.scr_width;
 		wdf->depth  = scr->scr_bpp;
-		if (rom->scment == NULL)
+		if (scr->putcmap == NULL || scr->scr_bpp > 8)
 			wdf->cmsize = 0;
 		else
 			wdf->cmsize = STI_NCMAP;
 		break;
 
 	case WSDISPLAYIO_LINEBYTES:
-		*(u_int *)data = scr->scr_cfg.fb_width;
+		if (scr->scr_bpp > 8)
+			*(u_int *)data = scr->scr_cfg.fb_width * 4;
+		else
+			*(u_int *)data = scr->scr_cfg.fb_width;
 		break;
 
 	case WSDISPLAYIO_GETCMAP:
-		if (rom->scment == NULL)
-			return ENOTTY;
+		if (scr->putcmap == NULL || scr->scr_bpp > 8)
+			return ENODEV;
 		cmapp = (struct wsdisplay_cmap *)data;
 		idx = cmapp->index;
 		count = cmapp->count;
@@ -1031,8 +1144,18 @@ sti_ioctl(void *v, void *vs, u_long cmd,
 		break;
 
 	case WSDISPLAYIO_PUTCMAP:
-		if (rom->scment == NULL)
-			return ENOTTY;
+		if (scr->putcmap == NULL || scr->scr_bpp > 8)
+			return ENODEV;
+		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) {
+			/*
+			 * The hardware palette settings are handled by
+			 * the STI ROM in STI_TEXTMODE and changing cmap
+			 * could cause mangled text colors at least on CRX.
+			 * Updating CMAP in EMUL mode isn't expected anyway
+			 * so just ignore it.
+			 */
+			return 0;
+		}
 		cmapp = (struct wsdisplay_cmap *)data;
 		idx = cmapp->index;
 		count = cmapp->count;
@@ -1044,19 +1167,7 @@ sti_ioctl(void *v, void *vs, u_long cmd,
 			break;
 		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
 			break;
-		for (i = idx + count - 1; i >= idx; i--)
-			if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
-			    scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
-
-				DPRINTF(("sti_ioctl: "
-				    "sti_setcment(%d, %u, %u, %u): %%d\n", i,
-				    (u_int)scr->scr_rcmap[i],
-				    (u_int)scr->scr_gcmap[i],
-				    (u_int)scr->scr_bcmap[i]));
-
-				ret = EINVAL;
-				break;
-			}
+		ret = scr->putcmap(scr, idx, count);
 		break;
 
 	case WSDISPLAYIO_SVIDEO:
@@ -1076,11 +1187,26 @@ sti_ioctl(void *v, void *vs, u_long cmd,
 paddr_t
 sti_mmap(void *v, void *vs, off_t offset, int prot)
 {
-#if 0
 	struct sti_screen *scr = (struct sti_screen *)v;
+#if 0
+	struct sti_rom *rom = scr->scr_rom;
 #endif
-	/* XXX not finished */
-	return -1;
+	paddr_t pa;
+
+	if ((offset & PAGE_MASK) != 0)
+		return -1;
+
+	if (offset < 0 || offset >= scr->fblen)
+		return -1;
+
+#if 0 /* XXX not all platforms provide bus_space_mmap() yet */
+	pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
+	    BUS_SPACE_MAP_LINEAR);
+#else
+	pa = scr->fbaddr + offset;
+#endif
+
+	return pa;
 }
 
 int
@@ -1097,7 +1223,6 @@ sti_alloc_screen(void *v, const struct w
 	*cyp = 0;
 	sti_alloc_attr(scr, 0, 0, 0, defattr);
 	scr->scr_nscreens++;
-
 	return 0;
 }
 
@@ -1139,8 +1264,10 @@ sti_cursor(void *v, int on, int row, int
 	struct sti_screen *scr = (struct sti_screen *)v;
 	struct sti_font *fp = &scr->scr_curfont;
 
-	sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width,
-	    row * fp->height, fp->height, fp->width, bmf_invert);
+	sti_bmove(scr,
+	    col * fp->width, row * fp->height,
+	    col * fp->width, row * fp->height,
+	    fp->height, fp->width, bmf_invert);
 }
 
 /*
@@ -1205,6 +1332,10 @@ sti_putchar(void *v, int row, int col, u
 	struct sti_screen *scr = (struct sti_screen *)v;
 	struct sti_rom *rom = scr->scr_rom;
 	struct sti_font *fp = &scr->scr_curfont;
+	int bg, fg;
+
+	fg = WSATTR_UNPACK_FG(attr);
+	bg = WSATTR_UNPACK_BG(attr);
 
 	if (scr->scr_romfont != NULL) {
 		/*
@@ -1219,9 +1350,8 @@ sti_putchar(void *v, int row, int col, u
 		memset(&a, 0, sizeof(a));
 
 		a.flags.flags = STI_UNPMVF_WAIT;
-		/* XXX does not handle text attributes */
-		a.in.fg_colour = STI_COLOUR_WHITE;
-		a.in.bg_colour = STI_COLOUR_BLACK;
+		a.in.fg_colour = fg;
+		a.in.bg_colour = bg;
 		a.in.x = col * fp->width;
 		a.in.y = row * fp->height;
 		a.in.font_addr = scr->scr_romfont;
@@ -1241,9 +1371,8 @@ sti_putchar(void *v, int row, int col, u
 		memset(&a, 0, sizeof(a));
 
 		a.flags.flags = STI_BLKMVF_WAIT;
-		/* XXX does not handle text attributes */
-		a.in.fg_colour = STI_COLOUR_WHITE;
-		a.in.bg_colour = STI_COLOUR_BLACK;
+		a.in.fg_colour = fg;
+		a.in.bg_colour = bg;
 
 		a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
 		    fp->width + scr->scr_fontbase;
@@ -1264,8 +1393,10 @@ sti_copycols(void *v, int row, int srcco
 	struct sti_screen *scr = (struct sti_screen *)v;
 	struct sti_font *fp = &scr->scr_curfont;
 
-	sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width,
-	    row * fp->height, fp->height, ncols * fp->width, bmf_copy);
+	sti_bmove(scr,
+	    srccol * fp->width, row * fp->height,
+	    dstcol * fp->width, row * fp->height,
+	    fp->height, ncols * fp->width, bmf_copy);
 }
 
 void
@@ -1274,9 +1405,10 @@ sti_erasecols(void *v, int row, int star
 	struct sti_screen *scr = (struct sti_screen *)v;
 	struct sti_font *fp = &scr->scr_curfont;
 
-	sti_bmove(scr, startcol * fp->width, row * fp->height,
-	    startcol * fp->width, row * fp->height, fp->height,
-	    ncols * fp->width, bmf_clear);
+	sti_bmove(scr,
+	    startcol * fp->width, row * fp->height,
+	    startcol * fp->width, row * fp->height,
+	    fp->height, ncols * fp->width, bmf_clear);
 }
 
 void
@@ -1306,8 +1438,18 @@ sti_alloc_attr(void *v, int fg, int bg, 
 	struct sti_screen *scr = (struct sti_screen *)v;
 #endif
 
-	*pattr = 0;
+	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
+	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
+		return EINVAL;
+	if ((flags & WSATTR_REVERSE) != 0) {
+		fg = STI_COLOUR_BLACK; 
+		bg = STI_COLOUR_WHITE;
+	} else {
+		fg = STI_COLOUR_WHITE;
+		bg = STI_COLOUR_BLACK; 
+	}
 
+	*pattr = WSATTR_PACK(fg, bg, flags);
 	return 0;
 }
 
@@ -1350,3 +1492,185 @@ sti_cnattach(struct sti_rom *rom, struct
 	return 0;
 }
 #endif
+
+int
+ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
+{
+	int i, ret;
+
+	for (i = idx + count - 1; i >= (int)idx; i--)
+		if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
+		    scr->scr_gcmap[i], scr->scr_bcmap[i])))
+			return EINVAL;
+
+	return 0;
+}
+
+#ifndef SMALL_KERNEL
+
+void	ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
+void	ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
+void	ngle_setup_attr_planes(struct sti_screen *scr);
+void	ngle_setup_bt458(struct sti_screen *scr);
+
+#define	ngle_bt458_write(memt, memh, r, v) \
+	bus_space_write_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
+
+void
+ngle_artist_setupfb(struct sti_screen *scr)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	ngle_setup_bt458(scr);
+
+	ngle_setup_hw(memt, memh);
+	ngle_setup_fb(memt, memh, scr->reg10_value);
+
+	ngle_setup_attr_planes(scr);
+
+	ngle_setup_hw(memt, memh);
+	bus_space_write_4(memt, memh, NGLE_REG_21,
+	    bus_space_read_4(memt, memh, NGLE_REG_21) | 0x0a000000);
+	bus_space_write_4(memt, memh, NGLE_REG_27,
+	    bus_space_read_4(memt, memh, NGLE_REG_27) | 0x00800000);
+}
+
+void
+ngle_elk_setupfb(struct sti_screen *scr)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	ngle_setup_bt458(scr);
+
+	ngle_setup_hw(memt, memh);
+	ngle_setup_fb(memt, memh, scr->reg10_value);
+
+	ngle_setup_attr_planes(scr);
+
+	ngle_setup_hw(memt, memh);
+	/* enable overlay planes in Bt458 command register */
+	ngle_bt458_write(memt, memh, 0x0c, 0x06);
+	ngle_bt458_write(memt, memh, 0x0e, 0x43);
+}
+
+void
+ngle_timber_setupfb(struct sti_screen *scr)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	ngle_setup_bt458(scr);
+
+	ngle_setup_hw(memt, memh);
+	/* enable overlay planes in Bt458 command register */
+	ngle_bt458_write(memt, memh, 0x0c, 0x06);
+	ngle_bt458_write(memt, memh, 0x0e, 0x43);
+}
+
+void
+ngle_setup_bt458(struct sti_screen *scr)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	ngle_setup_hw(memt, memh);
+	/* set Bt458 read mask register to all planes */
+	ngle_bt458_write(memt, memh, 0x08, 0x04);
+	ngle_bt458_write(memt, memh, 0x0a, 0xff);
+}
+
+void
+ngle_setup_attr_planes(struct sti_screen *scr)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	ngle_setup_hw(memt, memh);
+	bus_space_write_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
+	bus_space_write_4(memt, memh, NGLE_REG_14, 0x23000302);
+	bus_space_write_4(memt, memh, NGLE_REG_12, scr->reg12_value);
+	bus_space_write_4(memt, memh, NGLE_REG_8, 0xffffffff);
+
+	bus_space_write_4(memt, memh, NGLE_REG_6, 0x00000000);
+	bus_space_write_4(memt, memh, NGLE_REG_9,
+	    (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
+	bus_space_write_4(memt, memh, NGLE_REG_6, 0x05000000);
+	bus_space_write_4(memt, memh, NGLE_REG_9, 0x00040001);
+
+	ngle_setup_hw(memt, memh);
+	bus_space_write_4(memt, memh, NGLE_REG_12, 0x00000000);
+
+	ngle_setup_fb(memt, memh, scr->reg10_value);
+}
+
+int
+ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
+{
+	struct sti_rom *rom = scr->scr_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+	uint8_t *r, *g, *b;
+	uint32_t cmap_finish;
+
+	if (scr->scr_bpp > 8)
+		cmap_finish = 0x83000100;
+	else
+		cmap_finish = 0x80000100;
+
+	r = scr->scr_rcmap + idx;
+	g = scr->scr_gcmap + idx;
+	b = scr->scr_bcmap + idx;
+
+	ngle_setup_hw(memt, memh);
+	bus_space_write_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
+	bus_space_write_4(memt, memh, NGLE_REG_14, 0x03000300);
+	bus_space_write_4(memt, memh, NGLE_REG_13, 0xffffffff);
+
+	while (count-- != 0) {
+		ngle_setup_hw(memt, memh);
+		bus_space_write_4(memt, memh, NGLE_REG_3, 0x400 | (idx << 2));
+		bus_space_write_4(memt, memh, NGLE_REG_4,
+		    (*r << 16) | (*g << 8) | *b);
+
+		idx++;
+		r++, g++, b++;
+	}
+
+	bus_space_write_4(memt, memh, NGLE_REG_2, 0x400);
+	bus_space_write_4(memt, memh, scr->cmap_finish_register, cmap_finish);
+	ngle_setup_fb(memt, memh, scr->reg10_value);
+
+
+	return 0;
+}
+
+void
+ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
+{
+	uint8_t stat;
+
+	do {
+		stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
+		if (stat == 0)
+			stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
+	} while (stat != 0);
+}
+
+void
+ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
+{
+
+	ngle_setup_hw(memt, memh);
+	bus_space_write_4(memt, memh, NGLE_REG_10, reg10);
+	bus_space_write_4(memt, memh, NGLE_REG_14, 0x83000300);
+	ngle_setup_hw(memt, memh);
+	bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
+}
+#endif	/* SMALL_KERNEL */

Index: src/sys/dev/ic/stivar.h
diff -u src/sys/dev/ic/stivar.h:1.9.34.1 src/sys/dev/ic/stivar.h:1.9.34.2
--- src/sys/dev/ic/stivar.h:1.9.34.1	Mon May 18 17:52:22 2020
+++ src/sys/dev/ic/stivar.h	Mon Dec 28 20:10:04 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: stivar.h,v 1.9.34.1 2020/05/18 17:52:22 martin Exp $	*/
+/*	$NetBSD: stivar.h,v 1.9.34.2 2020/12/28 20:10:04 martin Exp $	*/
 
 /*	$OpenBSD: stivar.h,v 1.24 2009/02/06 22:51:04 miod Exp $	*/
 
@@ -42,11 +42,15 @@ struct sti_rom {
 
 	bus_space_tag_t		 iot, memt;	/* XXX iot unused */
 	bus_space_handle_t	 romh;
+	bus_space_handle_t	 regh[STI_REGION_MAX];
 	bus_addr_t		*bases;
 
 	struct sti_dd		 rom_dd;	/* in word format */
-
 	vaddr_t			 rom_code;
+
+	/*
+	 * ROM-provided function pointers
+	 */
 	sti_init_t		 init;
 	sti_mgmt_t		 mgmt;
 	sti_unpmv_t		 unpmv;
@@ -98,10 +102,20 @@ struct sti_screen {
 	struct	wsscreen_descr	 scr_wsd;
 	const struct wsscreen_descr	*scr_scrlist[1];
 	struct	wsscreen_list	 scr_screenlist;
+
+	/*
+	 * Board-specific function data and pointers
+	 */
+	void			(*setupfb)(struct sti_screen *);
+	int			(*putcmap)(struct sti_screen *, u_int, u_int);
+
+	uint32_t		reg10_value;
+	uint32_t		reg12_value;
+	bus_addr_t		cmap_finish_register;
 };
 
 /*
- * STI Device state
+ * STI device state
  */
 struct sti_softc {
 	device_t sc_dev;
@@ -134,6 +148,7 @@ u_int	sti_rom_size(bus_space_tag_t, bus_
 int	sti_init(struct sti_screen *, int);
 #define	STI_TEXTMODE	0x01
 #define	STI_CLEARSCR	0x02
+#define	STI_FBMODE	0x04
 int	sti_ioctl(void *, void *, u_long, void *, int, struct lwp *);
 paddr_t	sti_mmap(void *, void *, off_t, int);
 int	sti_alloc_screen(void *, const struct wsscreen_descr *,

Reply via email to