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