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