Home | History | Annotate | Line # | Download | only in ic
sti.c revision 1.34
      1 /*	$NetBSD: sti.c,v 1.34 2024/02/01 06:50:36 skrll Exp $	*/
      2 
      3 /*	$OpenBSD: sti.c,v 1.61 2009/09/05 14:09:35 miod Exp $	*/
      4 
      5 /*
      6  * Copyright (c) 2000-2003 Michael Shalayeff
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
     22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 /*
     31  * TODO:
     32  *	call sti procs asynchronously;
     33  *	implement console scroll-back;
     34  *	X11 support on more models.
     35  */
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.34 2024/02/01 06:50:36 skrll Exp $");
     39 
     40 #include "wsdisplay.h"
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/device.h>
     45 #include <sys/malloc.h>
     46 
     47 #include <uvm/uvm_extern.h>
     48 
     49 #include <sys/bus.h>
     50 
     51 #include <dev/wscons/wsdisplayvar.h>
     52 #include <dev/wscons/wsconsio.h>
     53 
     54 #include <dev/ic/stireg.h>
     55 #include <dev/ic/stivar.h>
     56 
     57 #ifdef STIDEBUG
     58 
     59 #define	DPRINTF(s)	do {	\
     60 	if (stidebug)		\
     61 		printf s;	\
     62 } while(0)
     63 
     64 int stidebug = 1;
     65 #else
     66 #define	DPRINTF(s)	/* */
     67 #endif
     68 
     69 void sti_cursor(void *, int, int, int);
     70 int  sti_mapchar(void *, int, u_int *);
     71 void sti_putchar(void *, int, int, u_int, long);
     72 void sti_copycols(void *, int, int, int, int);
     73 void sti_erasecols(void *, int, int, int, long);
     74 void sti_copyrows(void *, int, int, int);
     75 void sti_eraserows(void *, int, int, long);
     76 int  sti_alloc_attr(void *, int, int, int, long *);
     77 
     78 /* pseudo attribute ops for sti ROM putchar function */
     79 #define WSATTR_FG_SHIFT	24
     80 #define WSATTR_BG_SHIFT	16
     81 #define WSATTR_UNPACK_FG(attr)	(((attr) >> WSATTR_FG_SHIFT) & 0xff)
     82 #define WSATTR_UNPACK_BG(attr)	(((attr) >> WSATTR_BG_SHIFT) & 0xff)
     83 #define WSATTR_UNPACK_FLAG(attr) ((attr) & WSATTR_USERMASK)
     84 #define WSATTR_PACK_FG(fg)	((fg) << WSATTR_FG_SHIFT)
     85 #define WSATTR_PACK_BG(bg)	((bg) << WSATTR_BG_SHIFT)
     86 #define WSATTR_PACK_FLAG(flag)	((flag))
     87 #define WSATTR_PACK(fg, bg, flag)	\
     88     (WSATTR_PACK_FG(fg) | WSATTR_PACK_BG(bg) | WSATTR_PACK_FLAG(flag))
     89 
     90 struct wsdisplay_emulops sti_emulops = {
     91 	.cursor = sti_cursor,
     92 	.mapchar = sti_mapchar,
     93 	.putchar = sti_putchar,
     94 	.copycols = sti_copycols,
     95 	.erasecols = sti_erasecols,
     96 	.copyrows = sti_copyrows,
     97 	.eraserows = sti_eraserows,
     98 	.allocattr = sti_alloc_attr
     99 };
    100 
    101 const struct wsdisplay_accessops sti_accessops = {
    102 	.ioctl = sti_ioctl,
    103 	.mmap = sti_mmap,
    104 	.alloc_screen = sti_alloc_screen,
    105 	.free_screen = sti_free_screen,
    106 	.show_screen = sti_show_screen,
    107 	.load_font = sti_load_font
    108 };
    109 
    110 enum sti_bmove_funcs {
    111 	bmf_clear, bmf_copy, bmf_invert, bmf_underline
    112 };
    113 
    114 void	sti_bmove(struct sti_screen *, int, int, int, int, int, int,
    115 	    enum sti_bmove_funcs);
    116 int	sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
    117 int	sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char);
    118 
    119 struct sti_screen *sti_attach_screen(struct sti_softc *, int);
    120 void	sti_describe_screen(struct sti_softc *, struct sti_screen *);
    121 
    122 int	sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t,
    123 	    u_int);
    124 void	sti_region_setup(struct sti_screen *);
    125 int	sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
    126 	    bus_space_handle_t, bus_addr_t *, u_int);
    127 int	sti_screen_setup(struct sti_screen *, int);
    128 
    129 int	ngle_default_putcmap(struct sti_screen *, u_int, u_int);
    130 
    131 #ifndef SMALL_KERNEL
    132 void	ngle_artist_setupfb(struct sti_screen *);
    133 void	ngle_elk_setupfb(struct sti_screen *);
    134 void	ngle_timber_setupfb(struct sti_screen *);
    135 int	ngle_putcmap(struct sti_screen *, u_int, u_int);
    136 #endif
    137 
    138 #define	STI_ENABLE_ROM(sc) \
    139 do { \
    140 	if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
    141 		(*(sc)->sc_enable_rom)(sc); \
    142 } while (0)
    143 #define	STI_DISABLE_ROM(sc) \
    144 do { \
    145 	if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
    146 		(*(sc)->sc_disable_rom)(sc); \
    147 } while (0)
    148 
    149 /* Macros to read larger than 8 bit values from byte roms */
    150 #define	parseshort(o) \
    151 	((bus_space_read_1(memt, romh, (o) + 3) <<  8) | \
    152 	 (bus_space_read_1(memt, romh, (o) + 7)))
    153 #define	parseword(o) \
    154 	((bus_space_read_1(memt, romh, (o) +  3) << 24) | \
    155 	 (bus_space_read_1(memt, romh, (o) +  7) << 16) | \
    156 	 (bus_space_read_1(memt, romh, (o) + 11) <<  8) | \
    157 	 (bus_space_read_1(memt, romh, (o) + 15)))
    158 
    159 int
    160 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot,
    161     bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase)
    162 {
    163 	struct sti_rom *rom;
    164 	int rc;
    165 
    166 	rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF,
    167 	    M_WAITOK | M_ZERO);
    168 	rom->rom_softc = sc;
    169 	rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase);
    170 	if (rc != 0) {
    171 		free(rom, M_DEVBUF);
    172 		return rc;
    173 	}
    174 
    175 	sc->sc_rom = rom;
    176 
    177 	sti_describe(sc);
    178 
    179 	sc->sc_scr = sti_attach_screen(sc,
    180 	    sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR);
    181 	if (sc->sc_scr == NULL)
    182 		rc = ENOMEM;
    183 
    184 	return rc;
    185 }
    186 
    187 struct sti_screen *
    188 sti_attach_screen(struct sti_softc *sc, int flags)
    189 {
    190 	struct sti_screen *scr;
    191 	int rc;
    192 
    193 	scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF,
    194 	    M_WAITOK | M_ZERO);
    195 	scr->scr_rom = sc->sc_rom;
    196 	rc = sti_screen_setup(scr, flags);
    197 	if (rc != 0) {
    198 		free(scr, M_DEVBUF);
    199 		return NULL;
    200 	}
    201 
    202 	sti_describe_screen(sc, scr);
    203 
    204 	return scr;
    205 }
    206 
    207 int
    208 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
    209     bus_space_handle_t romh, bus_addr_t *bases, u_int codebase)
    210 {
    211 	struct sti_dd *dd;
    212 	int error, size, i;
    213 
    214 	KASSERT(rom != NULL);
    215 	STI_ENABLE_ROM(rom->rom_softc);
    216 
    217 	rom->iot = iot;
    218 	rom->memt = memt;
    219 	rom->romh = romh;
    220 	rom->bases = bases;
    221 
    222 	/*
    223 	 * Get ROM header and code function pointers.
    224 	 */
    225 
    226 	dd = &rom->rom_dd;
    227 	rom->rom_devtype = bus_space_read_1(memt, romh, 3);
    228 	if (rom->rom_devtype == STI_DEVTYPE1) {
    229 		dd->dd_type      = bus_space_read_1(memt, romh, 0x03);
    230 		dd->dd_nmon      = bus_space_read_1(memt, romh, 0x07);
    231 		dd->dd_grrev     = bus_space_read_1(memt, romh, 0x0b);
    232 		dd->dd_lrrev     = bus_space_read_1(memt, romh, 0x0f);
    233 		dd->dd_grid[0]   = parseword(0x10);
    234 		dd->dd_grid[1]   = parseword(0x20);
    235 		dd->dd_fntaddr   = parseword(0x30) & ~3;
    236 		dd->dd_maxst     = parseword(0x40);
    237 		dd->dd_romend    = parseword(0x50) & ~3;
    238 		dd->dd_reglst    = parseword(0x60) & ~3;
    239 		dd->dd_maxreent  = parseshort(0x70);
    240 		dd->dd_maxtimo   = parseshort(0x78);
    241 		dd->dd_montbl    = parseword(0x80) & ~3;
    242 		dd->dd_udaddr    = parseword(0x90) & ~3;
    243 		dd->dd_stimemreq = parseword(0xa0);
    244 		dd->dd_udsize    = parseword(0xb0);
    245 		dd->dd_pwruse    = parseshort(0xc0);
    246 		dd->dd_bussup    = bus_space_read_1(memt, romh, 0xcb);
    247 		dd->dd_ebussup   = bus_space_read_1(memt, romh, 0xcf);
    248 		dd->dd_altcodet  = bus_space_read_1(memt, romh, 0xd3);
    249 		dd->dd_eddst[0]  = bus_space_read_1(memt, romh, 0xd7);
    250 		dd->dd_eddst[1]  = bus_space_read_1(memt, romh, 0xdb);
    251 		dd->dd_eddst[2]  = bus_space_read_1(memt, romh, 0xdf);
    252 		dd->dd_cfbaddr   = parseword(0xe0) & ~3;
    253 
    254 		codebase <<= 2;
    255 		dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3;
    256 		dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3;
    257 		dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3;
    258 		dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3;
    259 		dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3;
    260 		dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3;
    261 		dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3;
    262 		dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3;
    263 		dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3;
    264 		dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3;
    265 		dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3;
    266 		dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3;
    267 		dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3;
    268 		dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3;
    269 		dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3;
    270 		dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3;
    271 	} else {	/* STI_DEVTYPE4 */
    272 		bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd,
    273 		    sizeof(*dd) / 4);
    274 		/* fix pacode... */
    275 		bus_space_read_region_stream_4(memt, romh, codebase,
    276 		    (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4);
    277 	}
    278 
    279 	STI_DISABLE_ROM(rom->rom_softc);
    280 
    281 	DPRINTF(("dd:\n"
    282 	    "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n"
    283 	    "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
    284 	    "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
    285 	    "code=",
    286 	    dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
    287 	    dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst,
    288 	    dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
    289 	    dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
    290 	    dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr));
    291 	DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
    292 	    dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
    293 	    dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
    294 	    dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
    295 	    dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
    296 	    dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
    297 	    dd->dd_pacode[0xf]));
    298 
    299 	/*
    300 	 * Figure out how many bytes we need for the STI code.
    301 	 * Note there could be fewer than STI_END pointer entries
    302 	 * populated, especially on older devices.
    303 	 */
    304 	for (i = STI_END; dd->dd_pacode[i] == 0; i--)
    305 		;
    306 
    307 	size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
    308 
    309 	if (rom->rom_devtype == STI_DEVTYPE1)
    310 		size = (size + 3) / 4;
    311 	if (size == 0) {
    312 		aprint_error(": no code for the requested platform\n");
    313 		return EINVAL;
    314 	}
    315 
    316 	if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0,
    317 	    UVM_KMF_WIRED))) {
    318 		aprint_error(": cannot allocate %u bytes for code\n", size);
    319 		return ENOMEM;
    320 	}
    321 	DPRINTF(("code=0x%lx[%x]\n", rom->rom_code, size));
    322 
    323 	/*
    324 	 * Copy code into memory and make it executable.
    325 	 */
    326 
    327 	STI_ENABLE_ROM(rom->rom_softc);
    328 
    329 	if (rom->rom_devtype == STI_DEVTYPE1) {
    330 		uint8_t *p;
    331 		uint32_t addr, eaddr;
    332 
    333 		p = (uint8_t *)rom->rom_code;
    334 
    335 		for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
    336 		    addr < eaddr; addr += 4 ) {
    337 			*p++ = bus_space_read_4(memt, romh, addr) & 0xff;
    338 		}
    339 	} else {	/* STI_DEVTYPE4 */
    340 		bus_space_read_region_stream_4(memt, romh,
    341 		    dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code,
    342 		    size / 4);
    343 	}
    344 
    345 	STI_DISABLE_ROM(rom->rom_softc);
    346 
    347 	if ((error = uvm_map_protect(kernel_map, rom->rom_code,
    348 	    rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) {
    349 		aprint_error(": uvm_map_protect failed (%d)\n", error);
    350 		uvm_km_free(kernel_map, rom->rom_code, round_page(size),
    351 		    UVM_KMF_WIRED);
    352 		return error;
    353 	}
    354 
    355 	/*
    356 	 * Setup code function pointers.
    357 	 */
    358 
    359 #define	O(i) \
    360 	(dd->dd_pacode[(i)] == 0 ? 0 : \
    361 	    (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) /	\
    362 	    (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1)))
    363 
    364 	rom->init	= (sti_init_t)O(STI_INIT_GRAPH);
    365 	rom->mgmt	= (sti_mgmt_t)O(STI_STATE_MGMT);
    366 	rom->unpmv	= (sti_unpmv_t)O(STI_FONT_UNPMV);
    367 	rom->blkmv	= (sti_blkmv_t)O(STI_BLOCK_MOVE);
    368 	rom->test	= (sti_test_t)O(STI_SELF_TEST);
    369 	rom->exhdl	= (sti_exhdl_t)O(STI_EXCEP_HDLR);
    370 	rom->inqconf	= (sti_inqconf_t)O(STI_INQ_CONF);
    371 	rom->scment	= (sti_scment_t)O(STI_SCM_ENT);
    372 	rom->dmac	= (sti_dmac_t)O(STI_DMA_CTRL);
    373 	rom->flowc	= (sti_flowc_t)O(STI_FLOW_CTRL);
    374 	rom->utiming	= (sti_utiming_t)O(STI_UTIMING);
    375 	rom->pmgr	= (sti_pmgr_t)O(STI_PROC_MGR);
    376 	rom->util	= (sti_util_t)O(STI_UTIL);
    377 
    378 #undef O
    379 
    380 	/*
    381 	 * Set colormap entry is not implemented until 8.04, so force
    382 	 * a NULL pointer here.
    383 	 */
    384 	if (dd->dd_grrev < STI_REVISION(8, 4)) {
    385 		rom->scment = NULL;
    386 	}
    387 
    388 	return 0;
    389 }
    390 
    391 /*
    392  * Map all regions.
    393  */
    394 void
    395 sti_region_setup(struct sti_screen *scr)
    396 {
    397 	struct sti_rom *rom = scr->scr_rom;
    398 	bus_space_tag_t memt = rom->memt;
    399 	bus_space_handle_t romh = rom->romh;
    400 	bus_addr_t *bases = rom->bases;
    401 	struct sti_dd *dd = &rom->rom_dd;
    402 	struct sti_cfg *cc = &scr->scr_cfg;
    403 	struct sti_region regions[STI_REGION_MAX], *r;
    404 	u_int regno, regcnt;
    405 	bus_addr_t addr;
    406 
    407 	DPRINTF(("stiregions @ %x:\n", dd->dd_reglst));
    408 
    409 	/*
    410 	 * Read the region information.
    411 	 */
    412 
    413 	STI_ENABLE_ROM(rom->rom_softc);
    414 
    415 	if (rom->rom_devtype == STI_DEVTYPE1) {
    416 		for (regno = 0; regno < STI_REGION_MAX; regno++)
    417 			*(u_int *)(regions + regno) =
    418 			    parseword(dd->dd_reglst + regno * 0x10);
    419 	} else {
    420 		bus_space_read_region_stream_4(memt, romh, dd->dd_reglst,
    421 		    (uint32_t *)regions, sizeof(regions) / 4);
    422 	}
    423 
    424 	STI_DISABLE_ROM(rom->rom_softc);
    425 
    426 	/*
    427 	 * Count them.
    428 	 */
    429 
    430 	for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++)
    431 		if (r->last)
    432 			break;
    433 	regcnt++;
    434 
    435 	/*
    436 	 * Map them.
    437 	 */
    438 
    439 	for (regno = 0, r = regions; regno < regcnt; regno++, r++) {
    440 		if (r->length == 0)
    441 			continue;
    442 
    443 		/*
    444 		 * Assume an existing mapping exists.
    445 		 */
    446 		addr = bases[regno] + (r->offset << PGSHIFT);
    447 		DPRINTF(("%08x @ 0x%08x%s%s%s%s",
    448 		    r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "",
    449 		    r->cache ? " cache" : "", r->btlb ? " btlb" : "",
    450 		    r->last ? " last" : ""));
    451 
    452 		/*
    453 		 * Region #0 is always the rom, and it should have been
    454 		 * mapped already.
    455 		 * XXX This expects a 1:1 mapping...
    456 		 */
    457 		if (regno == 0 && romh == bases[0]) {
    458 			cc->regions[0] = addr;
    459 			DPRINTF(("\n"));
    460 			continue;
    461 		}
    462 
    463 		if (bus_space_map(memt, addr, r->length << PGSHIFT,
    464 		    BUS_SPACE_MAP_LINEAR | (r->cache ?
    465 		    BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) {
    466 			rom->regh[regno] = romh;	/* XXX */
    467 			DPRINTF((" - already mapped region\n"));
    468 		} else {
    469 			addr = (bus_addr_t)
    470 			    bus_space_vaddr(memt, rom->regh[regno]);
    471 			if (regno == 1) {
    472 				DPRINTF((" - fb"));
    473 				scr->fbaddr = addr;
    474 				scr->fblen = r->length << PGSHIFT;
    475 			}
    476 			DPRINTF(("\n"));
    477 		}
    478 
    479 		cc->regions[regno] = addr;
    480 	}
    481 
    482 #ifdef STIDEBUG
    483 	/*
    484 	 * Make sure we'll trap accessing unmapped regions
    485 	 */
    486 	for (regno = 0; regno < STI_REGION_MAX; regno++)
    487 		if (cc->regions[regno] == 0)
    488 		    cc->regions[regno] = 0x81234567;
    489 #endif
    490 }
    491 
    492 int
    493 sti_screen_setup(struct sti_screen *scr, int flags)
    494 {
    495 	struct sti_rom *rom = scr->scr_rom;
    496 	bus_space_tag_t memt = rom->memt;
    497 	bus_space_handle_t romh = rom->romh;
    498 	struct sti_dd *dd = &rom->rom_dd;
    499 	struct sti_cfg *cc = &scr->scr_cfg;
    500 	struct sti_inqconfout cfg;
    501 	struct sti_einqconfout ecfg;
    502 #ifdef STIDEBUG
    503 	char buf[256];
    504 #endif
    505 	int error, i;
    506 	int geometry_kluge = 0;
    507 	u_int fontindex = 0;
    508 
    509 	KASSERT(scr != NULL);
    510 	memset(cc, 0, sizeof(*cc));
    511 	cc->ext_cfg = &scr->scr_ecfg;
    512 	memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));
    513 
    514 	if (dd->dd_stimemreq) {
    515 		scr->scr_ecfg.addr =
    516 		    malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK);
    517 	}
    518 
    519 	sti_region_setup(scr);
    520 
    521 	if ((error = sti_init(scr, 0))) {
    522 		aprint_error(": cannot initialize (%d)\n", error);
    523 		goto fail;
    524 	}
    525 
    526 	memset(&cfg, 0, sizeof(cfg));
    527 	memset(&ecfg, 0, sizeof(ecfg));
    528 	cfg.ext = &ecfg;
    529 	if ((error = sti_inqcfg(scr, &cfg))) {
    530 		aprint_error(": error %d inquiring config\n", error);
    531 		goto fail;
    532 	}
    533 
    534 	/*
    535 	 * Older (rev 8.02) boards report wrong offset values,
    536 	 * similar to the displayable area size, at least in m68k mode.
    537 	 * Attempt to detect this and adjust here.
    538 	 */
    539 	if (cfg.owidth == cfg.width &&
    540 	    cfg.oheight == cfg.height)
    541 		geometry_kluge = 1;
    542 
    543 	if (geometry_kluge) {
    544 		scr->scr_cfg.oscr_width = cfg.owidth =
    545 		    cfg.fbwidth - cfg.width;
    546 		scr->scr_cfg.oscr_height = cfg.oheight =
    547 		    cfg.fbheight - cfg.height;
    548 	}
    549 
    550 	/*
    551 	 * Save a few fields for sti_describe_screen() later
    552 	 */
    553 	scr->fbheight = cfg.fbheight;
    554 	scr->fbwidth = cfg.fbwidth;
    555 	scr->oheight = cfg.oheight;
    556 	scr->owidth = cfg.owidth;
    557 	memcpy(scr->name, cfg.name, sizeof(scr->name));
    558 
    559 	if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
    560 		aprint_error(": cannot initialize (%d)\n", error);
    561 		goto fail;
    562 	}
    563 #ifdef STIDEBUG
    564 	snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
    565 	DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
    566 	    "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
    567 	    cfg.planes, buf,
    568 	    ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
    569 	    ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
    570 #endif
    571 	scr->scr_bpp = cfg.bppu;
    572 
    573 	/*
    574 	 * Although scr->scr_ecfg.current_monitor is not filled by
    575 	 * sti_init() as expected, we can nevertheless walk the monitor
    576 	 * list, if there is any, and if we find a mode matching our
    577 	 * resolution, pick its font index.
    578 	 */
    579 	if (dd->dd_montbl != 0) {
    580 		STI_ENABLE_ROM(rom->rom_softc);
    581 
    582 		for (i = 0; i < dd->dd_nmon; i++) {
    583 			u_int offs = dd->dd_montbl + 8 * i;
    584 			uint32_t m[2];
    585 			sti_mon_t mon = (void *)m;
    586 			if (rom->rom_devtype == STI_DEVTYPE1) {
    587 				m[0] = parseword(4 * offs);
    588 				m[1] = parseword(4 * (offs + 4));
    589 			} else {
    590 				bus_space_read_region_stream_4(memt, romh, offs,
    591 				    (uint32_t *)mon, sizeof(*mon) / 4);
    592 			}
    593 
    594 			if (mon->width == scr->scr_cfg.scr_width &&
    595 			    mon->height == scr->scr_cfg.scr_height) {
    596 				fontindex = mon->font;
    597 				break;
    598 			}
    599 		}
    600 
    601 		STI_DISABLE_ROM(rom->rom_softc);
    602 
    603 		DPRINTF(("font index: %d\n", fontindex));
    604 	}
    605 
    606 	if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
    607 		aprint_error(": cannot fetch fonts (%d)\n", error);
    608 		goto fail;
    609 	}
    610 
    611 	/*
    612 	 * setup screen descriptions:
    613 	 *	figure number of fonts supported;
    614 	 *	allocate wscons structures;
    615 	 *	calculate dimensions.
    616 	 */
    617 
    618 	scr->scr_wsd.name = "std";
    619 	scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
    620 	scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
    621 	scr->scr_wsd.textops = &sti_emulops;
    622 	scr->scr_wsd.fontwidth = scr->scr_curfont.width;
    623 	scr->scr_wsd.fontheight = scr->scr_curfont.height;
    624 	scr->scr_wsd.capabilities = WSSCREEN_REVERSE;
    625 
    626 	scr->scr_scrlist[0] = &scr->scr_wsd;
    627 	scr->scr_screenlist.nscreens = 1;
    628 	scr->scr_screenlist.screens = scr->scr_scrlist;
    629 
    630 #ifndef SMALL_KERNEL
    631 	/*
    632 	 * Decide which board-specific routines to use.
    633 	 */
    634 
    635 	switch (dd->dd_grid[0]) {
    636 	case STI_DD_CRX:
    637 		scr->setupfb = ngle_elk_setupfb;
    638 		scr->putcmap = ngle_putcmap;
    639 
    640 		scr->reg10_value = 0x13601000;
    641 		if (scr->scr_bpp > 8)
    642 			scr->reg12_value = NGLE_BUFF1_CMAP3;
    643 		else
    644 			scr->reg12_value = NGLE_BUFF1_CMAP0;
    645 		scr->cmap_finish_register = NGLE_REG_1;
    646 		break;
    647 
    648 	case STI_DD_TIMBER:
    649 		scr->setupfb = ngle_timber_setupfb;
    650 		scr->putcmap = ngle_putcmap;
    651 
    652 		scr->reg10_value = 0x13602000;
    653 		scr->reg12_value = NGLE_BUFF1_CMAP0;
    654 		scr->cmap_finish_register = NGLE_REG_1;
    655 		break;
    656 
    657 	case STI_DD_ARTIST:
    658 		scr->setupfb = ngle_artist_setupfb;
    659 		scr->putcmap = ngle_putcmap;
    660 
    661 		scr->reg10_value = 0x13601000;
    662 		scr->reg12_value = NGLE_ARTIST_CMAP0;
    663 		scr->cmap_finish_register = NGLE_REG_26;
    664 		break;
    665 
    666 	case STI_DD_EG:
    667 		scr->setupfb = ngle_artist_setupfb;
    668 		scr->putcmap = ngle_putcmap;
    669 
    670 		scr->reg10_value = 0x13601000;
    671 		if (scr->scr_bpp > 8) {
    672 			scr->reg12_value = NGLE_BUFF1_CMAP3;
    673 			scr->cmap_finish_register = NGLE_REG_1;
    674 		} else {
    675 			scr->reg12_value = NGLE_ARTIST_CMAP0;
    676 			scr->cmap_finish_register = NGLE_REG_26;
    677 		}
    678 		break;
    679 
    680 	case STI_DD_GRX:
    681 	case STI_DD_CRX24:
    682 	case STI_DD_EVRX:
    683 	case STI_DD_3X2V:
    684 	case STI_DD_DUAL_CRX:
    685 	case STI_DD_HCRX:
    686 	case STI_DD_LEGO:
    687 	case STI_DD_SUMMIT:
    688 	case STI_DD_PINNACLE:
    689 	default:
    690 		scr->setupfb = NULL;
    691 		scr->putcmap =
    692 		    rom->scment == NULL ? NULL : ngle_default_putcmap;
    693 		break;
    694 	}
    695 #endif
    696 
    697 	return 0;
    698 
    699 fail:
    700 	/* XXX free resources */
    701 	if (scr->scr_ecfg.addr != NULL) {
    702 		free(scr->scr_ecfg.addr, M_DEVBUF);
    703 		scr->scr_ecfg.addr = NULL;
    704 	}
    705 
    706 	return ENXIO;
    707 }
    708 
    709 void
    710 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
    711 {
    712 	struct sti_font *fp = &scr->scr_curfont;
    713 
    714 	aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
    715 	    device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
    716 	    scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
    717 
    718 	aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    719 	    device_xname(sc->sc_dev), fp->width, fp->height,
    720 	    fp->type, fp->bpc, fp->first, fp->last);
    721 }
    722 
    723 void
    724 sti_describe(struct sti_softc *sc)
    725 {
    726 	struct sti_rom *rom = sc->sc_rom;
    727 	struct sti_dd *dd = &rom->rom_dd;
    728 
    729 	aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
    730 	    dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
    731 	    dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
    732 
    733 	if (sc->sc_scr != NULL)
    734 		sti_describe_screen(sc, sc->sc_scr);
    735 }
    736 
    737 /*
    738  * Final part of attachment. On hppa where we use the PDC console
    739  * during autoconf, this has to be postponed until autoconf has
    740  * completed.
    741  */
    742 void
    743 sti_end_attach(struct sti_softc *sc)
    744 {
    745 	struct sti_screen *scr = sc->sc_scr;
    746 
    747 	if (scr == NULL)
    748 		return;
    749 #if NWSDISPLAY > 0
    750 	else {
    751 		struct wsemuldisplaydev_attach_args waa;
    752 		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
    753 
    754 		waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
    755 		waa.scrdata = &scr->scr_screenlist;
    756 		waa.accessops = &sti_accessops;
    757 		waa.accesscookie = scr;
    758 
    759 		/* attach as console if required */
    760 		if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
    761 			long defattr;
    762 
    763 			sti_alloc_attr(scr, 0, 0, 0, &defattr);
    764 			wsdisplay_cnattach(&scr->scr_wsd, scr,
    765 			    0, scr->scr_wsd.nrows - 1, defattr);
    766 			sc->sc_flags |= STI_ATTACHED;
    767 		}
    768 
    769 		config_found(sc->sc_dev, &waa, wsemuldisplaydevprint,
    770 		    CFARGS_NONE);
    771 	}
    772 #endif
    773 }
    774 
    775 u_int
    776 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
    777 {
    778 	int devtype;
    779 	u_int romend;
    780 
    781 	devtype = bus_space_read_1(memt, romh, 3);
    782 	if (devtype == STI_DEVTYPE4) {
    783 		bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
    784 		    (uint32_t *)&romend, 1);
    785 	} else {
    786 		romend = parseword(STI_DEV1_DD_ROMEND);
    787 	}
    788 
    789 	DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
    790 
    791 	return round_page(romend);
    792 }
    793 
    794 int
    795 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
    796     uint32_t baseaddr, u_int fontindex)
    797 {
    798 	struct sti_rom *rom = scr->scr_rom;
    799 	bus_space_tag_t memt = rom->memt;
    800 	bus_space_handle_t romh = rom->romh;
    801 	struct sti_font *fp = &scr->scr_curfont;
    802 	uint32_t addr;
    803 	int size;
    804 #ifdef notyet
    805 	int uc;
    806 	struct {
    807 		struct sti_unpmvflags flags;
    808 		struct sti_unpmvin in;
    809 		struct sti_unpmvout out;
    810 	} a;
    811 #endif
    812 
    813 	/*
    814 	 * Get the first PROM font in memory
    815 	 */
    816 
    817 	STI_ENABLE_ROM(rom->rom_softc);
    818 
    819 rescan:
    820 	addr = baseaddr;
    821 	do {
    822 		if (rom->rom_devtype == STI_DEVTYPE1) {
    823 			fp->first  = parseshort(addr + 0x00);
    824 			fp->last   = parseshort(addr + 0x08);
    825 			fp->width  = bus_space_read_1(memt, romh, addr + 0x13);
    826 			fp->height = bus_space_read_1(memt, romh, addr + 0x17);
    827 			fp->type   = bus_space_read_1(memt, romh, addr + 0x1b);
    828 			fp->bpc    = bus_space_read_1(memt, romh, addr + 0x1f);
    829 			fp->next   = parseword(addr + 0x20);
    830 			fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
    831 			fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
    832 		} else {	/* STI_DEVTYPE4 */
    833 			bus_space_read_region_stream_4(memt, romh, addr,
    834 			    (uint32_t *)fp, sizeof(struct sti_font) / 4);
    835 		}
    836 
    837 #ifdef STIDEBUG
    838 		STI_DISABLE_ROM(rom->rom_softc);
    839 		DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    840 		    device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
    841 		    fp->height, fp->type, fp->bpc, fp->first, fp->last));
    842 		STI_ENABLE_ROM(rom->rom_softc);
    843 #endif
    844 
    845 		if (fontindex == 0) {
    846 			size = sizeof(struct sti_font) +
    847 			    (fp->last - fp->first + 1) * fp->bpc;
    848 			if (rom->rom_devtype == STI_DEVTYPE1)
    849 				size *= 4;
    850 			scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK);
    851 
    852 			bus_space_read_region_stream_4(memt, romh, addr,
    853 			    (uint32_t *)scr->scr_romfont, size / 4);
    854 			break;
    855 		}
    856 
    857 		addr = baseaddr + fp->next;
    858 		fontindex--;
    859 	} while (fp->next != 0);
    860 
    861 	/*
    862 	 * If our font index was bogus, we did not find the expected font.
    863 	 * In this case, pick the first one and be done with it.
    864 	 */
    865 	if (fp->next == 0 && scr->scr_romfont == NULL) {
    866 		fontindex = 0;
    867 		goto rescan;
    868 	}
    869 
    870 	STI_DISABLE_ROM(rom->rom_softc);
    871 
    872 #ifdef notyet
    873 	/*
    874 	 * If there is enough room in the off-screen framebuffer memory,
    875 	 * display all the characters there in order to display them
    876 	 * faster with blkmv operations rather than unpmv later on.
    877 	 */
    878 	if (size <= cfg->fbheight *
    879 	    (cfg->fbwidth - cfg->width - cfg->owidth)) {
    880 		memset(&a, 0, sizeof(a));
    881 		a.flags.flags = STI_UNPMVF_WAIT;
    882 		a.in.fg_colour = STI_COLOUR_WHITE;
    883 		a.in.bg_colour = STI_COLOUR_BLACK;
    884 		a.in.font_addr = scr->scr_romfont;
    885 
    886 		scr->scr_fontmaxcol = cfg->fbheight / fp->height;
    887 		scr->scr_fontbase = cfg->width + cfg->owidth;
    888 		for (uc = fp->first; uc <= fp->last; uc++) {
    889 			a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
    890 			    fp->width + scr->scr_fontbase;
    891 			a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
    892 			    fp->height;
    893 			a.in.index = uc;
    894 
    895 			(*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    896 			if (a.out.errno) {
    897 				aprint_error_dev(sc->sc_dev, "unpmv %d "
    898 				    "returned %d\n", uc, a.out.errno);
    899 				return 0;
    900 			}
    901 		}
    902 
    903 		free(scr->scr_romfont, M_DEVBUF);
    904 		scr->scr_romfont = NULL;
    905 	}
    906 #endif
    907 
    908 	return 0;
    909 }
    910 
    911 /*
    912  * Wrappers around STI code pointers
    913  */
    914 
    915 int
    916 sti_init(struct sti_screen *scr, int mode)
    917 {
    918 	struct sti_rom *rom = scr->scr_rom;
    919 	struct {
    920 		struct sti_initflags flags;
    921 		struct sti_initin in;
    922 		struct sti_einitin ein;
    923 		struct sti_initout out;
    924 	} a;
    925 
    926 	KASSERT(rom != NULL);
    927 	memset(&a, 0, sizeof(a));
    928 
    929 	a.flags.flags = STI_INITF_WAIT | STI_INITF_PBET | STI_INITF_PBETI;
    930 	if ((mode & STI_TEXTMODE) != 0) {
    931 		a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB |
    932 		    STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT;
    933 		a.in.text_planes = 1;
    934 	} else {
    935 		a.flags.flags |= STI_INITF_TEXT | STI_INITF_NTEXT;
    936 		/*
    937 		 * Request as many text planes as STI will allow.
    938 		 * The reason to do this - when switching to framebuffer mode
    939 		 * for X we need access to all planes. In theory STI should do
    940 		 * just that when we request access to both text and non-text
    941 		 * planes as above.
    942 		 * In reality though, at least on my PCI Visualize EG, some
    943 		 * planes and/or colour registers remain inaccessible if we
    944 		 * request only one text plane.
    945 		 * Clearly we're missing a register write or two here, but so
    946 		 * far I haven't found it.
    947 		 */
    948 		a.in.text_planes = 3;
    949 	}
    950 	if ((mode & STI_CLEARSCR) != 0)
    951 		a.flags.flags |= STI_INITF_CLEAR;
    952 
    953 	a.in.ext_in = &a.ein;
    954 
    955 	DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
    956 	    device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
    957 	    &a.in, &a.out, &scr->scr_cfg));
    958 
    959 	(*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    960 
    961 	if (a.out.text_planes != a.in.text_planes)
    962 		return -1;	/* not colliding with sti errno values */
    963 	return a.out.errno;
    964 }
    965 
    966 int
    967 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
    968 {
    969 	struct sti_rom *rom = scr->scr_rom;
    970 	struct {
    971 		struct sti_inqconfflags flags;
    972 		struct sti_inqconfin in;
    973 	} a;
    974 
    975 	memset(&a, 0, sizeof(a));
    976 
    977 	a.flags.flags = STI_INQCONFF_WAIT;
    978 	(*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
    979 
    980 	return out->errno;
    981 }
    982 
    983 void
    984 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
    985     enum sti_bmove_funcs f)
    986 {
    987 	struct sti_rom *rom = scr->scr_rom;
    988 	struct {
    989 		struct sti_blkmvflags flags;
    990 		struct sti_blkmvin in;
    991 		struct sti_blkmvout out;
    992 	} a;
    993 
    994 	memset(&a, 0, sizeof(a));
    995 
    996 	a.flags.flags = STI_BLKMVF_WAIT;
    997 	switch (f) {
    998 	case bmf_clear:
    999 		a.flags.flags |= STI_BLKMVF_CLR;
   1000 		a.in.bg_colour = STI_COLOUR_BLACK;
   1001 		break;
   1002 	case bmf_underline:
   1003 	case bmf_copy:
   1004 		a.in.fg_colour = STI_COLOUR_WHITE;
   1005 		a.in.bg_colour = STI_COLOUR_BLACK;
   1006 		break;
   1007 	case bmf_invert:
   1008 		a.flags.flags |= STI_BLKMVF_COLR;
   1009 		a.in.fg_colour = STI_COLOUR_BLACK;
   1010 		a.in.bg_colour = STI_COLOUR_WHITE;
   1011 		break;
   1012 	}
   1013 	a.in.srcx = x1;
   1014 	a.in.srcy = y1;
   1015 	a.in.dstx = x2;
   1016 	a.in.dsty = y2;
   1017 	a.in.height = h;
   1018 	a.in.width = w;
   1019 
   1020 	(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1021 #ifdef STIDEBUG
   1022 	if (a.out.errno)
   1023 		printf("%s: blkmv returned %d\n",
   1024 		    device_xname(rom->rom_softc->sc_dev), a.out.errno);
   1025 #endif
   1026 }
   1027 
   1028 int
   1029 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
   1030 {
   1031 	struct sti_rom *rom = scr->scr_rom;
   1032 	struct {
   1033 		struct sti_scmentflags flags;
   1034 		struct sti_scmentin in;
   1035 		struct sti_scmentout out;
   1036 	} a;
   1037 
   1038 	memset(&a, 0, sizeof(a));
   1039 
   1040 	a.flags.flags = STI_SCMENTF_WAIT;
   1041 	a.in.entry = i;
   1042 	a.in.value = (r << 16) | (g << 8) | b;
   1043 
   1044 	(*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1045 
   1046 	return a.out.errno;
   1047 }
   1048 
   1049 /*
   1050  * wsdisplay accessops
   1051  */
   1052 int
   1053 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
   1054 {
   1055 	struct sti_screen *scr = (struct sti_screen *)v;
   1056 	struct wsdisplay_fbinfo *wdf;
   1057 	struct wsdisplay_cmap *cmapp;
   1058 	u_int mode, idx, count;
   1059 	int ret;
   1060 
   1061 	ret = 0;
   1062 	switch (cmd) {
   1063 	case WSDISPLAYIO_GMODE:
   1064 		*(u_int *)data = scr->scr_wsmode;
   1065 		break;
   1066 
   1067 	case WSDISPLAYIO_SMODE:
   1068 		mode = *(u_int *)data;
   1069 		switch (mode) {
   1070 		case WSDISPLAYIO_MODE_EMUL:
   1071 			if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
   1072 				ret = sti_init(scr, STI_TEXTMODE);
   1073 			break;
   1074 		case WSDISPLAYIO_MODE_DUMBFB:
   1075 			if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
   1076 				ret = sti_init(scr, 0);
   1077 				if (scr->setupfb != NULL)
   1078 					scr->setupfb(scr);
   1079 				else
   1080 #if 0
   1081 					ret = sti_init(scr, STI_FBMODE);
   1082 #else
   1083 					ret = EINVAL;
   1084 #endif
   1085 			}
   1086 			break;
   1087 		case WSDISPLAYIO_MODE_MAPPED:
   1088 		default:
   1089 			ret = EINVAL;
   1090 			break;
   1091 		}
   1092 		if (ret == 0)
   1093 			scr->scr_wsmode = mode;
   1094 		break;
   1095 
   1096 	case WSDISPLAYIO_GTYPE:
   1097 		*(u_int *)data = WSDISPLAY_TYPE_STI;
   1098 		break;
   1099 
   1100 	case WSDISPLAYIO_GINFO:
   1101 		wdf = (struct wsdisplay_fbinfo *)data;
   1102 		wdf->height = scr->scr_cfg.scr_height;
   1103 		wdf->width  = scr->scr_cfg.scr_width;
   1104 		wdf->depth  = scr->scr_bpp;
   1105 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1106 			wdf->cmsize = 0;
   1107 		else
   1108 			wdf->cmsize = STI_NCMAP;
   1109 		break;
   1110 
   1111 	case WSDISPLAYIO_LINEBYTES:
   1112 		if (scr->scr_bpp > 8)
   1113 			*(u_int *)data = scr->scr_cfg.fb_width * 4;
   1114 		else
   1115 			*(u_int *)data = scr->scr_cfg.fb_width;
   1116 		break;
   1117 
   1118 	case WSDISPLAYIO_GETCMAP:
   1119 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1120 			return ENODEV;
   1121 		cmapp = (struct wsdisplay_cmap *)data;
   1122 		idx = cmapp->index;
   1123 		count = cmapp->count;
   1124 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1125 			return EINVAL;
   1126 		if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
   1127 			break;
   1128 		if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
   1129 			break;
   1130 		if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
   1131 			break;
   1132 		break;
   1133 
   1134 	case WSDISPLAYIO_PUTCMAP:
   1135 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1136 			return ENODEV;
   1137 		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) {
   1138 			/*
   1139 			 * The hardware palette settings are handled by
   1140 			 * the STI ROM in STI_TEXTMODE and changing cmap
   1141 			 * could cause mangled text colors at least on CRX.
   1142 			 * Updating CMAP in EMUL mode isn't expected anyway
   1143 			 * so just ignore it.
   1144 			 */
   1145 			return 0;
   1146 		}
   1147 		cmapp = (struct wsdisplay_cmap *)data;
   1148 		idx = cmapp->index;
   1149 		count = cmapp->count;
   1150 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1151 			return EINVAL;
   1152 		if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
   1153 			break;
   1154 		if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
   1155 			break;
   1156 		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
   1157 			break;
   1158 		ret = scr->putcmap(scr, idx, count);
   1159 		break;
   1160 
   1161 	case WSDISPLAYIO_SVIDEO:
   1162 	case WSDISPLAYIO_GVIDEO:
   1163 	case WSDISPLAYIO_GCURPOS:
   1164 	case WSDISPLAYIO_SCURPOS:
   1165 	case WSDISPLAYIO_GCURMAX:
   1166 	case WSDISPLAYIO_GCURSOR:
   1167 	case WSDISPLAYIO_SCURSOR:
   1168 	default:
   1169 		return ENOTTY;	/* not supported yet */
   1170 	}
   1171 
   1172 	return ret;
   1173 }
   1174 
   1175 paddr_t
   1176 sti_mmap(void *v, void *vs, off_t offset, int prot)
   1177 {
   1178 	struct sti_screen *scr = (struct sti_screen *)v;
   1179 	struct sti_rom *rom = scr->scr_rom;
   1180 	paddr_t pa;
   1181 
   1182 	if ((offset & PAGE_MASK) != 0)
   1183 		return -1;
   1184 
   1185 	if (offset < 0 || offset >= scr->fblen)
   1186 		return -1;
   1187 
   1188 	if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB)
   1189 		return -1;
   1190 
   1191 	pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
   1192 	    BUS_SPACE_MAP_LINEAR);
   1193 
   1194 	if (pa == -1)
   1195 		pa = scr->fbaddr + offset;
   1196 
   1197 	return pa;
   1198 }
   1199 
   1200 int
   1201 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
   1202     int *cxp, int *cyp, long *defattr)
   1203 {
   1204 	struct sti_screen *scr = (struct sti_screen *)v;
   1205 
   1206 	if (scr->scr_nscreens > 0)
   1207 		return ENOMEM;
   1208 
   1209 	*cookiep = scr;
   1210 	*cxp = 0;
   1211 	*cyp = 0;
   1212 	sti_alloc_attr(scr, 0, 0, 0, defattr);
   1213 	scr->scr_nscreens++;
   1214 	return 0;
   1215 }
   1216 
   1217 void
   1218 sti_free_screen(void *v, void *cookie)
   1219 {
   1220 	struct sti_screen *scr = (struct sti_screen *)v;
   1221 
   1222 	scr->scr_nscreens--;
   1223 }
   1224 
   1225 int
   1226 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
   1227     void *cbarg)
   1228 {
   1229 #if 0
   1230 	struct sti_screen *scr = (struct sti_screen *)v;
   1231 #endif
   1232 
   1233 	return 0;
   1234 }
   1235 
   1236 int
   1237 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
   1238 {
   1239 #if 0
   1240 	struct sti_screen *scr = (struct sti_screen *)v;
   1241 #endif
   1242 
   1243 	return -1;
   1244 }
   1245 
   1246 /*
   1247  * wsdisplay emulops
   1248  */
   1249 void
   1250 sti_cursor(void *v, int on, int row, int col)
   1251 {
   1252 	struct sti_screen *scr = (struct sti_screen *)v;
   1253 	struct sti_font *fp = &scr->scr_curfont;
   1254 
   1255 	sti_bmove(scr,
   1256 	    col * fp->width, row * fp->height,
   1257 	    col * fp->width, row * fp->height,
   1258 	    fp->height, fp->width, bmf_invert);
   1259 }
   1260 
   1261 /*
   1262  * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
   1263  */
   1264 static const uint8_t
   1265 sti_unitoroman[0x100 - 0xa0] = {
   1266 	0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc,    0, 0xbd,
   1267 	0xab,    0, 0xf9, 0xfb,    0, 0xf6,    0, 0xb0,
   1268 
   1269 	0xb3, 0xfe,    0,    0, 0xa8, 0xf3, 0xf4, 0xf2,
   1270 	   0,    0, 0xfa, 0xfd, 0xf7, 0xf8,    0, 0xb9,
   1271 
   1272 	0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
   1273 	0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
   1274 
   1275 	0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda,    0,
   1276 	0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
   1277 
   1278 	0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
   1279 	0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
   1280 
   1281 	0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce,    0,
   1282 	0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
   1283 };
   1284 
   1285 int
   1286 sti_mapchar(void *v, int uni, u_int *index)
   1287 {
   1288 	struct sti_screen *scr = (struct sti_screen *)v;
   1289 	struct sti_font *fp = &scr->scr_curfont;
   1290 	int c;
   1291 
   1292 	switch (fp->type) {
   1293 	case STI_FONT_HPROMAN8:
   1294 		if (uni >= 0x80 && uni < 0xa0)
   1295 			c = -1;
   1296 		else if (uni >= 0xa0 && uni < 0x100) {
   1297 			c = (int)sti_unitoroman[uni - 0xa0];
   1298 			if (c == 0)
   1299 				c = -1;
   1300 		} else
   1301 			c = uni;
   1302 		break;
   1303 	default:
   1304 		c = uni;
   1305 		break;
   1306 	}
   1307 
   1308 	if (c == -1 || c < fp->first || c > fp->last) {
   1309 		*index = ' ';
   1310 		return 0;
   1311 	}
   1312 
   1313 	*index = c;
   1314 	return 5;
   1315 }
   1316 
   1317 void
   1318 sti_putchar(void *v, int row, int col, u_int uc, long attr)
   1319 {
   1320 	struct sti_screen *scr = (struct sti_screen *)v;
   1321 	struct sti_rom *rom = scr->scr_rom;
   1322 	struct sti_font *fp = &scr->scr_curfont;
   1323 	int bg, fg;
   1324 
   1325 	fg = WSATTR_UNPACK_FG(attr);
   1326 	bg = WSATTR_UNPACK_BG(attr);
   1327 
   1328 	if (scr->scr_romfont != NULL) {
   1329 		/*
   1330 		 * Font is in memory, use unpmv
   1331 		 */
   1332 		struct {
   1333 			struct sti_unpmvflags flags;
   1334 			struct sti_unpmvin in;
   1335 			struct sti_unpmvout out;
   1336 		} a;
   1337 
   1338 		memset(&a, 0, sizeof(a));
   1339 
   1340 		a.flags.flags = STI_UNPMVF_WAIT;
   1341 		a.in.fg_colour = fg;
   1342 		a.in.bg_colour = bg;
   1343 		a.in.x = col * fp->width;
   1344 		a.in.y = row * fp->height;
   1345 		a.in.font_addr = scr->scr_romfont;
   1346 		a.in.index = uc;
   1347 
   1348 		(*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1349 	} else {
   1350 		/*
   1351 		 * Font is in frame buffer, use blkmv
   1352 		 */
   1353 		struct {
   1354 			struct sti_blkmvflags flags;
   1355 			struct sti_blkmvin in;
   1356 			struct sti_blkmvout out;
   1357 		} a;
   1358 
   1359 		memset(&a, 0, sizeof(a));
   1360 
   1361 		a.flags.flags = STI_BLKMVF_WAIT;
   1362 		a.in.fg_colour = fg;
   1363 		a.in.bg_colour = bg;
   1364 
   1365 		a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
   1366 		    fp->width + scr->scr_fontbase;
   1367 		a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
   1368 		    fp->height;
   1369 		a.in.dstx = col * fp->width;
   1370 		a.in.dsty = row * fp->height;
   1371 		a.in.height = fp->height;
   1372 		a.in.width = fp->width;
   1373 
   1374 		(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1375 	}
   1376 }
   1377 
   1378 void
   1379 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
   1380 {
   1381 	struct sti_screen *scr = (struct sti_screen *)v;
   1382 	struct sti_font *fp = &scr->scr_curfont;
   1383 
   1384 	sti_bmove(scr,
   1385 	    srccol * fp->width, row * fp->height,
   1386 	    dstcol * fp->width, row * fp->height,
   1387 	    fp->height, ncols * fp->width, bmf_copy);
   1388 }
   1389 
   1390 void
   1391 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
   1392 {
   1393 	struct sti_screen *scr = (struct sti_screen *)v;
   1394 	struct sti_font *fp = &scr->scr_curfont;
   1395 
   1396 	sti_bmove(scr,
   1397 	    startcol * fp->width, row * fp->height,
   1398 	    startcol * fp->width, row * fp->height,
   1399 	    fp->height, ncols * fp->width, bmf_clear);
   1400 }
   1401 
   1402 void
   1403 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
   1404 {
   1405 	struct sti_screen *scr = (struct sti_screen *)v;
   1406 	struct sti_font *fp = &scr->scr_curfont;
   1407 
   1408 	sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
   1409 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
   1410 }
   1411 
   1412 void
   1413 sti_eraserows(void *v, int srcrow, int nrows, long attr)
   1414 {
   1415 	struct sti_screen *scr = (struct sti_screen *)v;
   1416 	struct sti_font *fp = &scr->scr_curfont;
   1417 
   1418 	sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
   1419 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
   1420 }
   1421 
   1422 int
   1423 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
   1424 {
   1425 #if 0
   1426 	struct sti_screen *scr = (struct sti_screen *)v;
   1427 #endif
   1428 
   1429 	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
   1430 	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
   1431 		return EINVAL;
   1432 	if ((flags & WSATTR_REVERSE) != 0) {
   1433 		fg = STI_COLOUR_BLACK;
   1434 		bg = STI_COLOUR_WHITE;
   1435 	} else {
   1436 		fg = STI_COLOUR_WHITE;
   1437 		bg = STI_COLOUR_BLACK;
   1438 	}
   1439 
   1440 	*pattr = WSATTR_PACK(fg, bg, flags);
   1441 	return 0;
   1442 }
   1443 
   1444 /*
   1445  * Early console support.  Only used on hp300, currently
   1446  */
   1447 int
   1448 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt,
   1449     bus_addr_t *bases, u_int codebase)
   1450 {
   1451 	bus_space_handle_t romh;
   1452 	u_int romend;
   1453 	int error;
   1454 	long defattr;
   1455 
   1456 	if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0)
   1457 		return error;
   1458 
   1459 	/*
   1460 	 * Compute real PROM size
   1461 	 */
   1462 	romend = sti_rom_size(memt, romh);
   1463 
   1464 	bus_space_unmap(memt, romh, PAGE_SIZE);
   1465 
   1466 	if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0)
   1467 		return error;
   1468 
   1469 	bases[0] = romh;
   1470 	if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0)
   1471 		return -1;
   1472 	scr->scr_rom = rom;
   1473 	if (sti_screen_setup(scr, STI_CLEARSCR) != 0)
   1474 		return -1;
   1475 
   1476 	sti_alloc_attr(scr, 0, 0, 0, &defattr);
   1477 	wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
   1478 
   1479 	return 0;
   1480 }
   1481 
   1482 int
   1483 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
   1484 {
   1485 	int i, ret;
   1486 
   1487 	for (i = idx + count - 1; i >= (int)idx; i--)
   1488 		if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
   1489 		    scr->scr_gcmap[i], scr->scr_bcmap[i])))
   1490 			return EINVAL;
   1491 
   1492 	return 0;
   1493 }
   1494 
   1495 #ifndef SMALL_KERNEL
   1496 
   1497 void	ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
   1498 void	ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
   1499 void	ngle_setup_attr_planes(struct sti_screen *scr);
   1500 void	ngle_setup_bt458(struct sti_screen *scr);
   1501 
   1502 #define	ngle_bt458_write(memt, memh, r, v) \
   1503 	bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
   1504 
   1505 void
   1506 ngle_artist_setupfb(struct sti_screen *scr)
   1507 {
   1508 	struct sti_rom *rom = scr->scr_rom;
   1509 	bus_space_tag_t memt = rom->memt;
   1510 	bus_space_handle_t memh = rom->regh[2];
   1511 
   1512 	ngle_setup_bt458(scr);
   1513 
   1514 	ngle_setup_hw(memt, memh);
   1515 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1516 
   1517 	ngle_setup_attr_planes(scr);
   1518 
   1519 	ngle_setup_hw(memt, memh);
   1520 	bus_space_write_stream_4(memt, memh, NGLE_REG_21,
   1521 	    bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
   1522 	bus_space_write_stream_4(memt, memh, NGLE_REG_27,
   1523 	    bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
   1524 }
   1525 
   1526 void
   1527 ngle_elk_setupfb(struct sti_screen *scr)
   1528 {
   1529 	struct sti_rom *rom = scr->scr_rom;
   1530 	bus_space_tag_t memt = rom->memt;
   1531 	bus_space_handle_t memh = rom->regh[2];
   1532 
   1533 	ngle_setup_bt458(scr);
   1534 
   1535 	ngle_setup_hw(memt, memh);
   1536 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1537 
   1538 	ngle_setup_attr_planes(scr);
   1539 
   1540 	ngle_setup_hw(memt, memh);
   1541 	/* enable overlay planes in Bt458 command register */
   1542 	ngle_bt458_write(memt, memh, 0x0c, 0x06);
   1543 	ngle_bt458_write(memt, memh, 0x0e, 0x43);
   1544 }
   1545 
   1546 void
   1547 ngle_timber_setupfb(struct sti_screen *scr)
   1548 {
   1549 	struct sti_rom *rom = scr->scr_rom;
   1550 	bus_space_tag_t memt = rom->memt;
   1551 	bus_space_handle_t memh = rom->regh[2];
   1552 
   1553 	ngle_setup_bt458(scr);
   1554 
   1555 	ngle_setup_hw(memt, memh);
   1556 	/* enable overlay planes in Bt458 command register */
   1557 	ngle_bt458_write(memt, memh, 0x0c, 0x06);
   1558 	ngle_bt458_write(memt, memh, 0x0e, 0x43);
   1559 }
   1560 
   1561 void
   1562 ngle_setup_bt458(struct sti_screen *scr)
   1563 {
   1564 	struct sti_rom *rom = scr->scr_rom;
   1565 	bus_space_tag_t memt = rom->memt;
   1566 	bus_space_handle_t memh = rom->regh[2];
   1567 
   1568 	ngle_setup_hw(memt, memh);
   1569 	/* set Bt458 read mask register to all planes */
   1570 	ngle_bt458_write(memt, memh, 0x08, 0x04);
   1571 	ngle_bt458_write(memt, memh, 0x0a, 0xff);
   1572 }
   1573 
   1574 void
   1575 ngle_setup_attr_planes(struct sti_screen *scr)
   1576 {
   1577 	struct sti_rom *rom = scr->scr_rom;
   1578 	bus_space_tag_t memt = rom->memt;
   1579 	bus_space_handle_t memh = rom->regh[2];
   1580 
   1581 	ngle_setup_hw(memt, memh);
   1582 	bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
   1583 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x23000302);
   1584 	bus_space_write_stream_4(memt, memh, NGLE_REG_12, scr->reg12_value);
   1585 	bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff);
   1586 
   1587 	bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x00000000);
   1588 	bus_space_write_stream_4(memt, memh, NGLE_REG_9,
   1589 	    (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
   1590 	bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x05000000);
   1591 	bus_space_write_stream_4(memt, memh, NGLE_REG_9, 0x00040001);
   1592 
   1593 	ngle_setup_hw(memt, memh);
   1594 	bus_space_write_stream_4(memt, memh, NGLE_REG_12, 0x00000000);
   1595 
   1596 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1597 }
   1598 
   1599 int
   1600 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
   1601 {
   1602 	struct sti_rom *rom = scr->scr_rom;
   1603 	bus_space_tag_t memt = rom->memt;
   1604 	bus_space_handle_t memh = rom->regh[2];
   1605 	uint8_t *r, *g, *b;
   1606 	uint32_t cmap_finish;
   1607 
   1608 	if (scr->scr_bpp > 8)
   1609 		cmap_finish = 0x83000100;
   1610 	else
   1611 		cmap_finish = 0x80000100;
   1612 
   1613 	r = scr->scr_rcmap + idx;
   1614 	g = scr->scr_gcmap + idx;
   1615 	b = scr->scr_bcmap + idx;
   1616 
   1617 	ngle_setup_hw(memt, memh);
   1618 	bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
   1619 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
   1620 	bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
   1621 
   1622 	while (count-- != 0) {
   1623 		ngle_setup_hw(memt, memh);
   1624 		bus_space_write_stream_4(memt, memh, NGLE_REG_3,
   1625 		    0x400 | (idx << 2));
   1626 		bus_space_write_stream_4(memt, memh, NGLE_REG_4,
   1627 		    (*r << 16) | (*g << 8) | *b);
   1628 
   1629 		idx++;
   1630 		r++, g++, b++;
   1631 	}
   1632 
   1633 	bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
   1634 	bus_space_write_stream_4(memt, memh, scr->cmap_finish_register,
   1635 	    cmap_finish);
   1636 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1637 
   1638 
   1639 	return 0;
   1640 }
   1641 
   1642 void
   1643 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
   1644 {
   1645 	uint8_t stat;
   1646 
   1647 	do {
   1648 		stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
   1649 		if (stat == 0)
   1650 			stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
   1651 	} while (stat != 0);
   1652 }
   1653 
   1654 void
   1655 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
   1656 {
   1657 
   1658 	ngle_setup_hw(memt, memh);
   1659 	bus_space_write_stream_4(memt, memh, NGLE_REG_10, reg10);
   1660 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x83000300);
   1661 	ngle_setup_hw(memt, memh);
   1662 	bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
   1663 }
   1664 #endif	/* SMALL_KERNEL */
   1665