Module Name:    src
Committed By:   tsutsui
Date:           Wed Dec 23 08:34:35 UTC 2020

Modified Files:
        src/sys/dev/ic: sti.c stivar.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/ic/sti.c
cvs rdiff -u -r1.10 -r1.11 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/dev/ic/sti.c
diff -u src/sys/dev/ic/sti.c:1.22 src/sys/dev/ic/sti.c:1.23
--- src/sys/dev/ic/sti.c:1.22	Sat Sep  5 16:30:11 2020
+++ src/sys/dev/ic/sti.c	Wed Dec 23 08:34:35 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: sti.c,v 1.22 2020/09/05 16:30:11 riastradh Exp $	*/
+/*	$NetBSD: sti.c,v 1.23 2020/12/23 08:34:35 tsutsui 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.22 2020/09/05 16:30:11 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.23 2020/12/23 08:34:35 tsutsui Exp $");
 
 #include "wsdisplay.h"
 
@@ -80,32 +80,32 @@ void sti_eraserows(void *, int, int, lon
 int  sti_alloc_attr(void *, int, int, int, long *);
 
 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 +118,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 { \
@@ -210,51 +219,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);
@@ -288,7 +298,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];
@@ -300,13 +310,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.
@@ -322,8 +331,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,
@@ -349,26 +357,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;
 	}
@@ -388,7 +397,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;
@@ -449,14 +457,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;
@@ -616,6 +624,73 @@ sti_screen_setup(struct sti_screen *scr,
 	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:
@@ -656,6 +731,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)
 {
@@ -827,6 +907,7 @@ rescan:
 /*
  * Wrappers around STI code pointers
  */
+
 int
 sti_init(struct sti_screen *scr, int mode)
 {
@@ -955,11 +1036,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) {
@@ -969,13 +1049,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:
@@ -987,19 +1085,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;
@@ -1014,8 +1115,8 @@ 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;
 		cmapp = (struct wsdisplay_cmap *)data;
 		idx = cmapp->index;
 		count = cmapp->count;
@@ -1027,19 +1128,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:
@@ -1059,11 +1148,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
@@ -1080,7 +1184,6 @@ sti_alloc_screen(void *v, const struct w
 	*cyp = 0;
 	sti_alloc_attr(scr, 0, 0, 0, defattr);
 	scr->scr_nscreens++;
-
 	return 0;
 }
 
@@ -1122,8 +1225,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);
 }
 
 /*
@@ -1247,8 +1352,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
@@ -1257,9 +1364,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
@@ -1333,3 +1441,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.10 src/sys/dev/ic/stivar.h:1.11
--- src/sys/dev/ic/stivar.h:1.10	Mon May  4 06:52:53 2020
+++ src/sys/dev/ic/stivar.h	Wed Dec 23 08:34:35 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: stivar.h,v 1.10 2020/05/04 06:52:53 tsutsui Exp $	*/
+/*	$NetBSD: stivar.h,v 1.11 2020/12/23 08:34:35 tsutsui 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