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