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