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