Home | History | Annotate | Line # | Download | only in ic
sti.c revision 1.35
      1 /*	$NetBSD: sti.c,v 1.35 2024/02/13 13:17:51 macallan 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.35 2024/02/13 13:17:51 macallan 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 (flags & STI_FBMODE) {
    560 		/* we're done here */
    561 		sti_init(scr, STI_FBMODE);
    562 		return 0;
    563 	}
    564 
    565 	if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
    566 		aprint_error(": cannot initialize (%d)\n", error);
    567 		goto fail;
    568 	}
    569 #ifdef STIDEBUG
    570 	snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
    571 	DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
    572 	    "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
    573 	    cfg.planes, buf,
    574 	    ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
    575 	    ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
    576 #endif
    577 	scr->scr_bpp = cfg.bppu;
    578 
    579 	/*
    580 	 * Although scr->scr_ecfg.current_monitor is not filled by
    581 	 * sti_init() as expected, we can nevertheless walk the monitor
    582 	 * list, if there is any, and if we find a mode matching our
    583 	 * resolution, pick its font index.
    584 	 */
    585 	if (dd->dd_montbl != 0) {
    586 		STI_ENABLE_ROM(rom->rom_softc);
    587 
    588 		for (i = 0; i < dd->dd_nmon; i++) {
    589 			u_int offs = dd->dd_montbl + 8 * i;
    590 			uint32_t m[2];
    591 			sti_mon_t mon = (void *)m;
    592 			if (rom->rom_devtype == STI_DEVTYPE1) {
    593 				m[0] = parseword(4 * offs);
    594 				m[1] = parseword(4 * (offs + 4));
    595 			} else {
    596 				bus_space_read_region_stream_4(memt, romh, offs,
    597 				    (uint32_t *)mon, sizeof(*mon) / 4);
    598 			}
    599 
    600 			if (mon->width == scr->scr_cfg.scr_width &&
    601 			    mon->height == scr->scr_cfg.scr_height) {
    602 				fontindex = mon->font;
    603 				break;
    604 			}
    605 		}
    606 
    607 		STI_DISABLE_ROM(rom->rom_softc);
    608 
    609 		DPRINTF(("font index: %d\n", fontindex));
    610 	}
    611 
    612 	if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
    613 		aprint_error(": cannot fetch fonts (%d)\n", error);
    614 		goto fail;
    615 	}
    616 
    617 	/*
    618 	 * setup screen descriptions:
    619 	 *	figure number of fonts supported;
    620 	 *	allocate wscons structures;
    621 	 *	calculate dimensions.
    622 	 */
    623 
    624 	scr->scr_wsd.name = "std";
    625 	scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
    626 	scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
    627 	scr->scr_wsd.textops = &sti_emulops;
    628 	scr->scr_wsd.fontwidth = scr->scr_curfont.width;
    629 	scr->scr_wsd.fontheight = scr->scr_curfont.height;
    630 	scr->scr_wsd.capabilities = WSSCREEN_REVERSE;
    631 
    632 	scr->scr_scrlist[0] = &scr->scr_wsd;
    633 	scr->scr_screenlist.nscreens = 1;
    634 	scr->scr_screenlist.screens = scr->scr_scrlist;
    635 
    636 #ifndef SMALL_KERNEL
    637 	/*
    638 	 * Decide which board-specific routines to use.
    639 	 */
    640 
    641 	switch (dd->dd_grid[0]) {
    642 	case STI_DD_CRX:
    643 		scr->setupfb = ngle_elk_setupfb;
    644 		scr->putcmap = ngle_putcmap;
    645 
    646 		scr->reg10_value = 0x13601000;
    647 		if (scr->scr_bpp > 8)
    648 			scr->reg12_value = NGLE_BUFF1_CMAP3;
    649 		else
    650 			scr->reg12_value = NGLE_BUFF1_CMAP0;
    651 		scr->cmap_finish_register = NGLE_REG_1;
    652 		break;
    653 
    654 	case STI_DD_TIMBER:
    655 		scr->setupfb = ngle_timber_setupfb;
    656 		scr->putcmap = ngle_putcmap;
    657 
    658 		scr->reg10_value = 0x13602000;
    659 		scr->reg12_value = NGLE_BUFF1_CMAP0;
    660 		scr->cmap_finish_register = NGLE_REG_1;
    661 		break;
    662 
    663 	case STI_DD_ARTIST:
    664 		scr->setupfb = ngle_artist_setupfb;
    665 		scr->putcmap = ngle_putcmap;
    666 
    667 		scr->reg10_value = 0x13601000;
    668 		scr->reg12_value = NGLE_ARTIST_CMAP0;
    669 		scr->cmap_finish_register = NGLE_REG_26;
    670 		break;
    671 
    672 	case STI_DD_EG:
    673 		scr->setupfb = ngle_artist_setupfb;
    674 		scr->putcmap = ngle_putcmap;
    675 
    676 		scr->reg10_value = 0x13601000;
    677 		if (scr->scr_bpp > 8) {
    678 			scr->reg12_value = NGLE_BUFF1_CMAP3;
    679 			scr->cmap_finish_register = NGLE_REG_1;
    680 		} else {
    681 			scr->reg12_value = NGLE_ARTIST_CMAP0;
    682 			scr->cmap_finish_register = NGLE_REG_26;
    683 		}
    684 		break;
    685 
    686 	case STI_DD_GRX:
    687 	case STI_DD_CRX24:
    688 	case STI_DD_EVRX:
    689 	case STI_DD_3X2V:
    690 	case STI_DD_DUAL_CRX:
    691 	case STI_DD_HCRX:
    692 	case STI_DD_LEGO:
    693 	case STI_DD_SUMMIT:
    694 	case STI_DD_PINNACLE:
    695 	default:
    696 		scr->setupfb = NULL;
    697 		scr->putcmap =
    698 		    rom->scment == NULL ? NULL : ngle_default_putcmap;
    699 		break;
    700 	}
    701 #endif
    702 
    703 	return 0;
    704 
    705 fail:
    706 	/* XXX free resources */
    707 	if (scr->scr_ecfg.addr != NULL) {
    708 		free(scr->scr_ecfg.addr, M_DEVBUF);
    709 		scr->scr_ecfg.addr = NULL;
    710 	}
    711 
    712 	return ENXIO;
    713 }
    714 
    715 void
    716 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
    717 {
    718 	struct sti_font *fp = &scr->scr_curfont;
    719 
    720 	aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
    721 	    device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
    722 	    scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
    723 
    724 	aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    725 	    device_xname(sc->sc_dev), fp->width, fp->height,
    726 	    fp->type, fp->bpc, fp->first, fp->last);
    727 }
    728 
    729 void
    730 sti_describe(struct sti_softc *sc)
    731 {
    732 	struct sti_rom *rom = sc->sc_rom;
    733 	struct sti_dd *dd = &rom->rom_dd;
    734 
    735 	aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
    736 	    dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
    737 	    dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
    738 
    739 	if (sc->sc_scr != NULL)
    740 		sti_describe_screen(sc, sc->sc_scr);
    741 }
    742 
    743 /*
    744  * Final part of attachment. On hppa where we use the PDC console
    745  * during autoconf, this has to be postponed until autoconf has
    746  * completed.
    747  */
    748 void
    749 sti_end_attach(struct sti_softc *sc)
    750 {
    751 	struct sti_screen *scr = sc->sc_scr;
    752 
    753 	if (scr == NULL)
    754 		return;
    755 #if NWSDISPLAY > 0
    756 	else {
    757 		struct wsemuldisplaydev_attach_args waa;
    758 		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
    759 
    760 		waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
    761 		waa.scrdata = &scr->scr_screenlist;
    762 		waa.accessops = &sti_accessops;
    763 		waa.accesscookie = scr;
    764 
    765 		/* attach as console if required */
    766 		if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
    767 			long defattr;
    768 
    769 			sti_alloc_attr(scr, 0, 0, 0, &defattr);
    770 			wsdisplay_cnattach(&scr->scr_wsd, scr,
    771 			    0, scr->scr_wsd.nrows - 1, defattr);
    772 			sc->sc_flags |= STI_ATTACHED;
    773 		}
    774 
    775 		config_found(sc->sc_dev, &waa, wsemuldisplaydevprint,
    776 		    CFARGS_NONE);
    777 	}
    778 #endif
    779 }
    780 
    781 u_int
    782 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
    783 {
    784 	int devtype;
    785 	u_int romend;
    786 
    787 	devtype = bus_space_read_1(memt, romh, 3);
    788 	if (devtype == STI_DEVTYPE4) {
    789 		bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
    790 		    (uint32_t *)&romend, 1);
    791 	} else {
    792 		romend = parseword(STI_DEV1_DD_ROMEND);
    793 	}
    794 
    795 	DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
    796 
    797 	return round_page(romend);
    798 }
    799 
    800 int
    801 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
    802     uint32_t baseaddr, u_int fontindex)
    803 {
    804 	struct sti_rom *rom = scr->scr_rom;
    805 	bus_space_tag_t memt = rom->memt;
    806 	bus_space_handle_t romh = rom->romh;
    807 	struct sti_font *fp = &scr->scr_curfont;
    808 	uint32_t addr;
    809 	int size;
    810 #ifdef notyet
    811 	int uc;
    812 	struct {
    813 		struct sti_unpmvflags flags;
    814 		struct sti_unpmvin in;
    815 		struct sti_unpmvout out;
    816 	} a;
    817 #endif
    818 
    819 	/*
    820 	 * Get the first PROM font in memory
    821 	 */
    822 
    823 	STI_ENABLE_ROM(rom->rom_softc);
    824 
    825 rescan:
    826 	addr = baseaddr;
    827 	do {
    828 		if (rom->rom_devtype == STI_DEVTYPE1) {
    829 			fp->first  = parseshort(addr + 0x00);
    830 			fp->last   = parseshort(addr + 0x08);
    831 			fp->width  = bus_space_read_1(memt, romh, addr + 0x13);
    832 			fp->height = bus_space_read_1(memt, romh, addr + 0x17);
    833 			fp->type   = bus_space_read_1(memt, romh, addr + 0x1b);
    834 			fp->bpc    = bus_space_read_1(memt, romh, addr + 0x1f);
    835 			fp->next   = parseword(addr + 0x20);
    836 			fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
    837 			fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
    838 		} else {	/* STI_DEVTYPE4 */
    839 			bus_space_read_region_stream_4(memt, romh, addr,
    840 			    (uint32_t *)fp, sizeof(struct sti_font) / 4);
    841 		}
    842 
    843 #ifdef STIDEBUG
    844 		STI_DISABLE_ROM(rom->rom_softc);
    845 		DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    846 		    device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
    847 		    fp->height, fp->type, fp->bpc, fp->first, fp->last));
    848 		STI_ENABLE_ROM(rom->rom_softc);
    849 #endif
    850 
    851 		if (fontindex == 0) {
    852 			size = sizeof(struct sti_font) +
    853 			    (fp->last - fp->first + 1) * fp->bpc;
    854 			if (rom->rom_devtype == STI_DEVTYPE1)
    855 				size *= 4;
    856 			scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK);
    857 
    858 			bus_space_read_region_stream_4(memt, romh, addr,
    859 			    (uint32_t *)scr->scr_romfont, size / 4);
    860 			break;
    861 		}
    862 
    863 		addr = baseaddr + fp->next;
    864 		fontindex--;
    865 	} while (fp->next != 0);
    866 
    867 	/*
    868 	 * If our font index was bogus, we did not find the expected font.
    869 	 * In this case, pick the first one and be done with it.
    870 	 */
    871 	if (fp->next == 0 && scr->scr_romfont == NULL) {
    872 		fontindex = 0;
    873 		goto rescan;
    874 	}
    875 
    876 	STI_DISABLE_ROM(rom->rom_softc);
    877 
    878 #ifdef notyet
    879 	/*
    880 	 * If there is enough room in the off-screen framebuffer memory,
    881 	 * display all the characters there in order to display them
    882 	 * faster with blkmv operations rather than unpmv later on.
    883 	 */
    884 	if (size <= cfg->fbheight *
    885 	    (cfg->fbwidth - cfg->width - cfg->owidth)) {
    886 		memset(&a, 0, sizeof(a));
    887 		a.flags.flags = STI_UNPMVF_WAIT;
    888 		a.in.fg_colour = STI_COLOUR_WHITE;
    889 		a.in.bg_colour = STI_COLOUR_BLACK;
    890 		a.in.font_addr = scr->scr_romfont;
    891 
    892 		scr->scr_fontmaxcol = cfg->fbheight / fp->height;
    893 		scr->scr_fontbase = cfg->width + cfg->owidth;
    894 		for (uc = fp->first; uc <= fp->last; uc++) {
    895 			a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
    896 			    fp->width + scr->scr_fontbase;
    897 			a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
    898 			    fp->height;
    899 			a.in.index = uc;
    900 
    901 			(*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    902 			if (a.out.errno) {
    903 				aprint_error_dev(sc->sc_dev, "unpmv %d "
    904 				    "returned %d\n", uc, a.out.errno);
    905 				return 0;
    906 			}
    907 		}
    908 
    909 		free(scr->scr_romfont, M_DEVBUF);
    910 		scr->scr_romfont = NULL;
    911 	}
    912 #endif
    913 
    914 	return 0;
    915 }
    916 
    917 /*
    918  * Wrappers around STI code pointers
    919  */
    920 
    921 int
    922 sti_init(struct sti_screen *scr, int mode)
    923 {
    924 	struct sti_rom *rom = scr->scr_rom;
    925 	struct {
    926 		struct sti_initflags flags;
    927 		struct sti_initin in;
    928 		struct sti_einitin ein;
    929 		struct sti_initout out;
    930 	} a;
    931 
    932 	KASSERT(rom != NULL);
    933 	memset(&a, 0, sizeof(a));
    934 
    935 	a.flags.flags = STI_INITF_WAIT | STI_INITF_PBET | STI_INITF_PBETI;
    936 	if ((mode & STI_TEXTMODE) != 0) {
    937 		a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB |
    938 		    STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT;
    939 		a.in.text_planes = 1;
    940 	} else {
    941 		a.flags.flags |= STI_INITF_TEXT | STI_INITF_NTEXT;
    942 		/*
    943 		 * Request as many text planes as STI will allow.
    944 		 * The reason to do this - when switching to framebuffer mode
    945 		 * for X we need access to all planes. In theory STI should do
    946 		 * just that when we request access to both text and non-text
    947 		 * planes as above.
    948 		 * In reality though, at least on my PCI Visualize EG, some
    949 		 * planes and/or colour registers remain inaccessible if we
    950 		 * request only one text plane.
    951 		 * Clearly we're missing a register write or two here, but so
    952 		 * far I haven't found it.
    953 		 */
    954 		a.in.text_planes = 3;
    955 	}
    956 	if ((mode & STI_CLEARSCR) != 0)
    957 		a.flags.flags |= STI_INITF_CLEAR;
    958 
    959 	a.in.ext_in = &a.ein;
    960 
    961 	DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
    962 	    device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
    963 	    &a.in, &a.out, &scr->scr_cfg));
    964 
    965 	(*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    966 
    967 	if (a.out.text_planes != a.in.text_planes)
    968 		return -1;	/* not colliding with sti errno values */
    969 	return a.out.errno;
    970 }
    971 
    972 int
    973 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
    974 {
    975 	struct sti_rom *rom = scr->scr_rom;
    976 	struct {
    977 		struct sti_inqconfflags flags;
    978 		struct sti_inqconfin in;
    979 	} a;
    980 
    981 	memset(&a, 0, sizeof(a));
    982 
    983 	a.flags.flags = STI_INQCONFF_WAIT;
    984 	(*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
    985 
    986 	return out->errno;
    987 }
    988 
    989 void
    990 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
    991     enum sti_bmove_funcs f)
    992 {
    993 	struct sti_rom *rom = scr->scr_rom;
    994 	struct {
    995 		struct sti_blkmvflags flags;
    996 		struct sti_blkmvin in;
    997 		struct sti_blkmvout out;
    998 	} a;
    999 
   1000 	memset(&a, 0, sizeof(a));
   1001 
   1002 	a.flags.flags = STI_BLKMVF_WAIT;
   1003 	switch (f) {
   1004 	case bmf_clear:
   1005 		a.flags.flags |= STI_BLKMVF_CLR;
   1006 		a.in.bg_colour = STI_COLOUR_BLACK;
   1007 		break;
   1008 	case bmf_underline:
   1009 	case bmf_copy:
   1010 		a.in.fg_colour = STI_COLOUR_WHITE;
   1011 		a.in.bg_colour = STI_COLOUR_BLACK;
   1012 		break;
   1013 	case bmf_invert:
   1014 		a.flags.flags |= STI_BLKMVF_COLR;
   1015 		a.in.fg_colour = STI_COLOUR_BLACK;
   1016 		a.in.bg_colour = STI_COLOUR_WHITE;
   1017 		break;
   1018 	}
   1019 	a.in.srcx = x1;
   1020 	a.in.srcy = y1;
   1021 	a.in.dstx = x2;
   1022 	a.in.dsty = y2;
   1023 	a.in.height = h;
   1024 	a.in.width = w;
   1025 
   1026 	(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1027 #ifdef STIDEBUG
   1028 	if (a.out.errno)
   1029 		printf("%s: blkmv returned %d\n",
   1030 		    device_xname(rom->rom_softc->sc_dev), a.out.errno);
   1031 #endif
   1032 }
   1033 
   1034 int
   1035 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
   1036 {
   1037 	struct sti_rom *rom = scr->scr_rom;
   1038 	struct {
   1039 		struct sti_scmentflags flags;
   1040 		struct sti_scmentin in;
   1041 		struct sti_scmentout out;
   1042 	} a;
   1043 
   1044 	memset(&a, 0, sizeof(a));
   1045 
   1046 	a.flags.flags = STI_SCMENTF_WAIT;
   1047 	a.in.entry = i;
   1048 	a.in.value = (r << 16) | (g << 8) | b;
   1049 
   1050 	(*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1051 
   1052 	return a.out.errno;
   1053 }
   1054 
   1055 /*
   1056  * wsdisplay accessops
   1057  */
   1058 int
   1059 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
   1060 {
   1061 	struct sti_screen *scr = (struct sti_screen *)v;
   1062 	struct wsdisplay_fbinfo *wdf;
   1063 	struct wsdisplay_cmap *cmapp;
   1064 	u_int mode, idx, count;
   1065 	int ret;
   1066 
   1067 	ret = 0;
   1068 	switch (cmd) {
   1069 	case WSDISPLAYIO_GMODE:
   1070 		*(u_int *)data = scr->scr_wsmode;
   1071 		break;
   1072 
   1073 	case WSDISPLAYIO_SMODE:
   1074 		mode = *(u_int *)data;
   1075 		switch (mode) {
   1076 		case WSDISPLAYIO_MODE_EMUL:
   1077 			if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
   1078 				ret = sti_init(scr, STI_TEXTMODE);
   1079 			break;
   1080 		case WSDISPLAYIO_MODE_DUMBFB:
   1081 			if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
   1082 				ret = sti_init(scr, 0);
   1083 				if (scr->setupfb != NULL)
   1084 					scr->setupfb(scr);
   1085 				else
   1086 #if 0
   1087 					ret = sti_init(scr, STI_FBMODE);
   1088 #else
   1089 					ret = EINVAL;
   1090 #endif
   1091 			}
   1092 			break;
   1093 		case WSDISPLAYIO_MODE_MAPPED:
   1094 		default:
   1095 			ret = EINVAL;
   1096 			break;
   1097 		}
   1098 		if (ret == 0)
   1099 			scr->scr_wsmode = mode;
   1100 		break;
   1101 
   1102 	case WSDISPLAYIO_GTYPE:
   1103 		*(u_int *)data = WSDISPLAY_TYPE_STI;
   1104 		break;
   1105 
   1106 	case WSDISPLAYIO_GINFO:
   1107 		wdf = (struct wsdisplay_fbinfo *)data;
   1108 		wdf->height = scr->scr_cfg.scr_height;
   1109 		wdf->width  = scr->scr_cfg.scr_width;
   1110 		wdf->depth  = scr->scr_bpp;
   1111 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1112 			wdf->cmsize = 0;
   1113 		else
   1114 			wdf->cmsize = STI_NCMAP;
   1115 		break;
   1116 
   1117 	case WSDISPLAYIO_LINEBYTES:
   1118 		if (scr->scr_bpp > 8)
   1119 			*(u_int *)data = scr->scr_cfg.fb_width * 4;
   1120 		else
   1121 			*(u_int *)data = scr->scr_cfg.fb_width;
   1122 		break;
   1123 
   1124 	case WSDISPLAYIO_GETCMAP:
   1125 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1126 			return ENODEV;
   1127 		cmapp = (struct wsdisplay_cmap *)data;
   1128 		idx = cmapp->index;
   1129 		count = cmapp->count;
   1130 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1131 			return EINVAL;
   1132 		if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
   1133 			break;
   1134 		if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
   1135 			break;
   1136 		if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
   1137 			break;
   1138 		break;
   1139 
   1140 	case WSDISPLAYIO_PUTCMAP:
   1141 		if (scr->putcmap == NULL || scr->scr_bpp > 8)
   1142 			return ENODEV;
   1143 		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) {
   1144 			/*
   1145 			 * The hardware palette settings are handled by
   1146 			 * the STI ROM in STI_TEXTMODE and changing cmap
   1147 			 * could cause mangled text colors at least on CRX.
   1148 			 * Updating CMAP in EMUL mode isn't expected anyway
   1149 			 * so just ignore it.
   1150 			 */
   1151 			return 0;
   1152 		}
   1153 		cmapp = (struct wsdisplay_cmap *)data;
   1154 		idx = cmapp->index;
   1155 		count = cmapp->count;
   1156 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1157 			return EINVAL;
   1158 		if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
   1159 			break;
   1160 		if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
   1161 			break;
   1162 		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
   1163 			break;
   1164 		ret = scr->putcmap(scr, idx, count);
   1165 		break;
   1166 
   1167 	case WSDISPLAYIO_SVIDEO:
   1168 	case WSDISPLAYIO_GVIDEO:
   1169 	case WSDISPLAYIO_GCURPOS:
   1170 	case WSDISPLAYIO_SCURPOS:
   1171 	case WSDISPLAYIO_GCURMAX:
   1172 	case WSDISPLAYIO_GCURSOR:
   1173 	case WSDISPLAYIO_SCURSOR:
   1174 	default:
   1175 		return ENOTTY;	/* not supported yet */
   1176 	}
   1177 
   1178 	return ret;
   1179 }
   1180 
   1181 paddr_t
   1182 sti_mmap(void *v, void *vs, off_t offset, int prot)
   1183 {
   1184 	struct sti_screen *scr = (struct sti_screen *)v;
   1185 	struct sti_rom *rom = scr->scr_rom;
   1186 	paddr_t pa;
   1187 
   1188 	if ((offset & PAGE_MASK) != 0)
   1189 		return -1;
   1190 
   1191 	if (offset < 0 || offset >= scr->fblen)
   1192 		return -1;
   1193 
   1194 	if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB)
   1195 		return -1;
   1196 
   1197 	pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
   1198 	    BUS_SPACE_MAP_LINEAR);
   1199 
   1200 	if (pa == -1)
   1201 		pa = scr->fbaddr + offset;
   1202 
   1203 	return pa;
   1204 }
   1205 
   1206 int
   1207 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
   1208     int *cxp, int *cyp, long *defattr)
   1209 {
   1210 	struct sti_screen *scr = (struct sti_screen *)v;
   1211 
   1212 	if (scr->scr_nscreens > 0)
   1213 		return ENOMEM;
   1214 
   1215 	*cookiep = scr;
   1216 	*cxp = 0;
   1217 	*cyp = 0;
   1218 	sti_alloc_attr(scr, 0, 0, 0, defattr);
   1219 	scr->scr_nscreens++;
   1220 	return 0;
   1221 }
   1222 
   1223 void
   1224 sti_free_screen(void *v, void *cookie)
   1225 {
   1226 	struct sti_screen *scr = (struct sti_screen *)v;
   1227 
   1228 	scr->scr_nscreens--;
   1229 }
   1230 
   1231 int
   1232 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
   1233     void *cbarg)
   1234 {
   1235 #if 0
   1236 	struct sti_screen *scr = (struct sti_screen *)v;
   1237 #endif
   1238 
   1239 	return 0;
   1240 }
   1241 
   1242 int
   1243 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
   1244 {
   1245 #if 0
   1246 	struct sti_screen *scr = (struct sti_screen *)v;
   1247 #endif
   1248 
   1249 	return -1;
   1250 }
   1251 
   1252 /*
   1253  * wsdisplay emulops
   1254  */
   1255 void
   1256 sti_cursor(void *v, int on, int row, int col)
   1257 {
   1258 	struct sti_screen *scr = (struct sti_screen *)v;
   1259 	struct sti_font *fp = &scr->scr_curfont;
   1260 
   1261 	sti_bmove(scr,
   1262 	    col * fp->width, row * fp->height,
   1263 	    col * fp->width, row * fp->height,
   1264 	    fp->height, fp->width, bmf_invert);
   1265 }
   1266 
   1267 /*
   1268  * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
   1269  */
   1270 static const uint8_t
   1271 sti_unitoroman[0x100 - 0xa0] = {
   1272 	0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc,    0, 0xbd,
   1273 	0xab,    0, 0xf9, 0xfb,    0, 0xf6,    0, 0xb0,
   1274 
   1275 	0xb3, 0xfe,    0,    0, 0xa8, 0xf3, 0xf4, 0xf2,
   1276 	   0,    0, 0xfa, 0xfd, 0xf7, 0xf8,    0, 0xb9,
   1277 
   1278 	0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
   1279 	0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
   1280 
   1281 	0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda,    0,
   1282 	0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
   1283 
   1284 	0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
   1285 	0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
   1286 
   1287 	0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce,    0,
   1288 	0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
   1289 };
   1290 
   1291 int
   1292 sti_mapchar(void *v, int uni, u_int *index)
   1293 {
   1294 	struct sti_screen *scr = (struct sti_screen *)v;
   1295 	struct sti_font *fp = &scr->scr_curfont;
   1296 	int c;
   1297 
   1298 	switch (fp->type) {
   1299 	case STI_FONT_HPROMAN8:
   1300 		if (uni >= 0x80 && uni < 0xa0)
   1301 			c = -1;
   1302 		else if (uni >= 0xa0 && uni < 0x100) {
   1303 			c = (int)sti_unitoroman[uni - 0xa0];
   1304 			if (c == 0)
   1305 				c = -1;
   1306 		} else
   1307 			c = uni;
   1308 		break;
   1309 	default:
   1310 		c = uni;
   1311 		break;
   1312 	}
   1313 
   1314 	if (c == -1 || c < fp->first || c > fp->last) {
   1315 		*index = ' ';
   1316 		return 0;
   1317 	}
   1318 
   1319 	*index = c;
   1320 	return 5;
   1321 }
   1322 
   1323 void
   1324 sti_putchar(void *v, int row, int col, u_int uc, long attr)
   1325 {
   1326 	struct sti_screen *scr = (struct sti_screen *)v;
   1327 	struct sti_rom *rom = scr->scr_rom;
   1328 	struct sti_font *fp = &scr->scr_curfont;
   1329 	int bg, fg;
   1330 
   1331 	fg = WSATTR_UNPACK_FG(attr);
   1332 	bg = WSATTR_UNPACK_BG(attr);
   1333 
   1334 	if (scr->scr_romfont != NULL) {
   1335 		/*
   1336 		 * Font is in memory, use unpmv
   1337 		 */
   1338 		struct {
   1339 			struct sti_unpmvflags flags;
   1340 			struct sti_unpmvin in;
   1341 			struct sti_unpmvout out;
   1342 		} a;
   1343 
   1344 		memset(&a, 0, sizeof(a));
   1345 
   1346 		a.flags.flags = STI_UNPMVF_WAIT;
   1347 		a.in.fg_colour = fg;
   1348 		a.in.bg_colour = bg;
   1349 		a.in.x = col * fp->width;
   1350 		a.in.y = row * fp->height;
   1351 		a.in.font_addr = scr->scr_romfont;
   1352 		a.in.index = uc;
   1353 
   1354 		(*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1355 	} else {
   1356 		/*
   1357 		 * Font is in frame buffer, use blkmv
   1358 		 */
   1359 		struct {
   1360 			struct sti_blkmvflags flags;
   1361 			struct sti_blkmvin in;
   1362 			struct sti_blkmvout out;
   1363 		} a;
   1364 
   1365 		memset(&a, 0, sizeof(a));
   1366 
   1367 		a.flags.flags = STI_BLKMVF_WAIT;
   1368 		a.in.fg_colour = fg;
   1369 		a.in.bg_colour = bg;
   1370 
   1371 		a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
   1372 		    fp->width + scr->scr_fontbase;
   1373 		a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
   1374 		    fp->height;
   1375 		a.in.dstx = col * fp->width;
   1376 		a.in.dsty = row * fp->height;
   1377 		a.in.height = fp->height;
   1378 		a.in.width = fp->width;
   1379 
   1380 		(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1381 	}
   1382 }
   1383 
   1384 void
   1385 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
   1386 {
   1387 	struct sti_screen *scr = (struct sti_screen *)v;
   1388 	struct sti_font *fp = &scr->scr_curfont;
   1389 
   1390 	sti_bmove(scr,
   1391 	    srccol * fp->width, row * fp->height,
   1392 	    dstcol * fp->width, row * fp->height,
   1393 	    fp->height, ncols * fp->width, bmf_copy);
   1394 }
   1395 
   1396 void
   1397 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
   1398 {
   1399 	struct sti_screen *scr = (struct sti_screen *)v;
   1400 	struct sti_font *fp = &scr->scr_curfont;
   1401 
   1402 	sti_bmove(scr,
   1403 	    startcol * fp->width, row * fp->height,
   1404 	    startcol * fp->width, row * fp->height,
   1405 	    fp->height, ncols * fp->width, bmf_clear);
   1406 }
   1407 
   1408 void
   1409 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
   1410 {
   1411 	struct sti_screen *scr = (struct sti_screen *)v;
   1412 	struct sti_font *fp = &scr->scr_curfont;
   1413 
   1414 	sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
   1415 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
   1416 }
   1417 
   1418 void
   1419 sti_eraserows(void *v, int srcrow, int nrows, long attr)
   1420 {
   1421 	struct sti_screen *scr = (struct sti_screen *)v;
   1422 	struct sti_font *fp = &scr->scr_curfont;
   1423 
   1424 	sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
   1425 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
   1426 }
   1427 
   1428 int
   1429 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
   1430 {
   1431 #if 0
   1432 	struct sti_screen *scr = (struct sti_screen *)v;
   1433 #endif
   1434 
   1435 	if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
   1436 	    WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
   1437 		return EINVAL;
   1438 	if ((flags & WSATTR_REVERSE) != 0) {
   1439 		fg = STI_COLOUR_BLACK;
   1440 		bg = STI_COLOUR_WHITE;
   1441 	} else {
   1442 		fg = STI_COLOUR_WHITE;
   1443 		bg = STI_COLOUR_BLACK;
   1444 	}
   1445 
   1446 	*pattr = WSATTR_PACK(fg, bg, flags);
   1447 	return 0;
   1448 }
   1449 
   1450 /*
   1451  * Early console support.  Only used on hp300, currently
   1452  */
   1453 int
   1454 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt,
   1455     bus_addr_t *bases, u_int codebase)
   1456 {
   1457 	bus_space_handle_t romh;
   1458 	u_int romend;
   1459 	int error;
   1460 	long defattr;
   1461 
   1462 	if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0)
   1463 		return error;
   1464 
   1465 	/*
   1466 	 * Compute real PROM size
   1467 	 */
   1468 	romend = sti_rom_size(memt, romh);
   1469 
   1470 	bus_space_unmap(memt, romh, PAGE_SIZE);
   1471 
   1472 	if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0)
   1473 		return error;
   1474 
   1475 	bases[0] = romh;
   1476 	if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0)
   1477 		return -1;
   1478 	scr->scr_rom = rom;
   1479 	if (sti_screen_setup(scr, STI_CLEARSCR) != 0)
   1480 		return -1;
   1481 
   1482 	sti_alloc_attr(scr, 0, 0, 0, &defattr);
   1483 	wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
   1484 
   1485 	return 0;
   1486 }
   1487 
   1488 int
   1489 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
   1490 {
   1491 	int i, ret;
   1492 
   1493 	for (i = idx + count - 1; i >= (int)idx; i--)
   1494 		if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
   1495 		    scr->scr_gcmap[i], scr->scr_bcmap[i])))
   1496 			return EINVAL;
   1497 
   1498 	return 0;
   1499 }
   1500 
   1501 #ifndef SMALL_KERNEL
   1502 
   1503 void	ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
   1504 void	ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
   1505 void	ngle_setup_attr_planes(struct sti_screen *scr);
   1506 void	ngle_setup_bt458(struct sti_screen *scr);
   1507 
   1508 #define	ngle_bt458_write(memt, memh, r, v) \
   1509 	bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
   1510 
   1511 void
   1512 ngle_artist_setupfb(struct sti_screen *scr)
   1513 {
   1514 	struct sti_rom *rom = scr->scr_rom;
   1515 	bus_space_tag_t memt = rom->memt;
   1516 	bus_space_handle_t memh = rom->regh[2];
   1517 
   1518 	ngle_setup_bt458(scr);
   1519 
   1520 	ngle_setup_hw(memt, memh);
   1521 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1522 
   1523 	ngle_setup_attr_planes(scr);
   1524 
   1525 	ngle_setup_hw(memt, memh);
   1526 	bus_space_write_stream_4(memt, memh, NGLE_REG_21,
   1527 	    bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
   1528 	bus_space_write_stream_4(memt, memh, NGLE_REG_27,
   1529 	    bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
   1530 }
   1531 
   1532 void
   1533 ngle_elk_setupfb(struct sti_screen *scr)
   1534 {
   1535 	struct sti_rom *rom = scr->scr_rom;
   1536 	bus_space_tag_t memt = rom->memt;
   1537 	bus_space_handle_t memh = rom->regh[2];
   1538 
   1539 	ngle_setup_bt458(scr);
   1540 
   1541 	ngle_setup_hw(memt, memh);
   1542 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1543 
   1544 	ngle_setup_attr_planes(scr);
   1545 
   1546 	ngle_setup_hw(memt, memh);
   1547 	/* enable overlay planes in Bt458 command register */
   1548 	ngle_bt458_write(memt, memh, 0x0c, 0x06);
   1549 	ngle_bt458_write(memt, memh, 0x0e, 0x43);
   1550 }
   1551 
   1552 void
   1553 ngle_timber_setupfb(struct sti_screen *scr)
   1554 {
   1555 	struct sti_rom *rom = scr->scr_rom;
   1556 	bus_space_tag_t memt = rom->memt;
   1557 	bus_space_handle_t memh = rom->regh[2];
   1558 
   1559 	ngle_setup_bt458(scr);
   1560 
   1561 	ngle_setup_hw(memt, memh);
   1562 	/* enable overlay planes in Bt458 command register */
   1563 	ngle_bt458_write(memt, memh, 0x0c, 0x06);
   1564 	ngle_bt458_write(memt, memh, 0x0e, 0x43);
   1565 }
   1566 
   1567 void
   1568 ngle_setup_bt458(struct sti_screen *scr)
   1569 {
   1570 	struct sti_rom *rom = scr->scr_rom;
   1571 	bus_space_tag_t memt = rom->memt;
   1572 	bus_space_handle_t memh = rom->regh[2];
   1573 
   1574 	ngle_setup_hw(memt, memh);
   1575 	/* set Bt458 read mask register to all planes */
   1576 	ngle_bt458_write(memt, memh, 0x08, 0x04);
   1577 	ngle_bt458_write(memt, memh, 0x0a, 0xff);
   1578 }
   1579 
   1580 void
   1581 ngle_setup_attr_planes(struct sti_screen *scr)
   1582 {
   1583 	struct sti_rom *rom = scr->scr_rom;
   1584 	bus_space_tag_t memt = rom->memt;
   1585 	bus_space_handle_t memh = rom->regh[2];
   1586 
   1587 	ngle_setup_hw(memt, memh);
   1588 	bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
   1589 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x23000302);
   1590 	bus_space_write_stream_4(memt, memh, NGLE_REG_12, scr->reg12_value);
   1591 	bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff);
   1592 
   1593 	bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x00000000);
   1594 	bus_space_write_stream_4(memt, memh, NGLE_REG_9,
   1595 	    (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
   1596 	bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x05000000);
   1597 	bus_space_write_stream_4(memt, memh, NGLE_REG_9, 0x00040001);
   1598 
   1599 	ngle_setup_hw(memt, memh);
   1600 	bus_space_write_stream_4(memt, memh, NGLE_REG_12, 0x00000000);
   1601 
   1602 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1603 }
   1604 
   1605 int
   1606 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
   1607 {
   1608 	struct sti_rom *rom = scr->scr_rom;
   1609 	bus_space_tag_t memt = rom->memt;
   1610 	bus_space_handle_t memh = rom->regh[2];
   1611 	uint8_t *r, *g, *b;
   1612 	uint32_t cmap_finish;
   1613 
   1614 	if (scr->scr_bpp > 8)
   1615 		cmap_finish = 0x83000100;
   1616 	else
   1617 		cmap_finish = 0x80000100;
   1618 
   1619 	r = scr->scr_rcmap + idx;
   1620 	g = scr->scr_gcmap + idx;
   1621 	b = scr->scr_bcmap + idx;
   1622 
   1623 	ngle_setup_hw(memt, memh);
   1624 	bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
   1625 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
   1626 	bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
   1627 
   1628 	while (count-- != 0) {
   1629 		ngle_setup_hw(memt, memh);
   1630 		bus_space_write_stream_4(memt, memh, NGLE_REG_3,
   1631 		    0x400 | (idx << 2));
   1632 		bus_space_write_stream_4(memt, memh, NGLE_REG_4,
   1633 		    (*r << 16) | (*g << 8) | *b);
   1634 
   1635 		idx++;
   1636 		r++, g++, b++;
   1637 	}
   1638 
   1639 	bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
   1640 	bus_space_write_stream_4(memt, memh, scr->cmap_finish_register,
   1641 	    cmap_finish);
   1642 	ngle_setup_fb(memt, memh, scr->reg10_value);
   1643 
   1644 
   1645 	return 0;
   1646 }
   1647 
   1648 void
   1649 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
   1650 {
   1651 	uint8_t stat;
   1652 
   1653 	do {
   1654 		stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
   1655 		if (stat == 0)
   1656 			stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
   1657 	} while (stat != 0);
   1658 }
   1659 
   1660 void
   1661 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
   1662 {
   1663 
   1664 	ngle_setup_hw(memt, memh);
   1665 	bus_space_write_stream_4(memt, memh, NGLE_REG_10, reg10);
   1666 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x83000300);
   1667 	ngle_setup_hw(memt, memh);
   1668 	bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
   1669 }
   1670 #endif	/* SMALL_KERNEL */
   1671