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