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