Home | History | Annotate | Line # | Download | only in ic
sti.c revision 1.20
      1 /*	$NetBSD: sti.c,v 1.20 2019/11/10 21:16:35 chs 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.
     35  */
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.20 2019/11/10 21:16:35 chs 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.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 struct wsdisplay_emulops sti_emulops = {
     83 	sti_cursor,
     84 	sti_mapchar,
     85 	sti_putchar,
     86 	sti_copycols,
     87 	sti_erasecols,
     88 	sti_copyrows,
     89 	sti_eraserows,
     90 	sti_alloc_attr
     91 };
     92 
     93 const struct wsdisplay_accessops sti_accessops = {
     94 	sti_ioctl,
     95 	sti_mmap,
     96 	sti_alloc_screen,
     97 	sti_free_screen,
     98 	sti_show_screen,
     99 	sti_load_font
    100 };
    101 
    102 enum sti_bmove_funcs {
    103 	bmf_clear, bmf_copy, bmf_invert, bmf_underline
    104 };
    105 
    106 int	sti_init(struct sti_screen *, int);
    107 #define	STI_TEXTMODE	0x01
    108 #define	STI_CLEARSCR	0x02
    109 int	sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
    110 void	sti_bmove(struct sti_screen *, int, int, int, int, int, int,
    111 	    enum sti_bmove_funcs);
    112 int	sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char);
    113 
    114 struct sti_screen *sti_attach_screen(struct sti_softc *, int);
    115 void	sti_describe_screen(struct sti_softc *, struct sti_screen *);
    116 
    117 int	sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t,
    118 	    u_int);
    119 void	sti_region_setup(struct sti_screen *);
    120 int	sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
    121 	    bus_space_handle_t, bus_addr_t *, u_int);
    122 int	sti_screen_setup(struct sti_screen *, int);
    123 
    124 #if NSTI_PCI > 0
    125 #define	STI_ENABLE_ROM(sc) \
    126 do { \
    127 	if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
    128 		(*(sc)->sc_enable_rom)(sc); \
    129 } while (0)
    130 #define	STI_DISABLE_ROM(sc) \
    131 do { \
    132 	if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
    133 		(*(sc)->sc_disable_rom)(sc); \
    134 } while (0)
    135 #else
    136 #define	STI_ENABLE_ROM(sc)		do { /* nothing */ } while (0)
    137 #define	STI_DISABLE_ROM(sc)		do { /* nothing */ } while (0)
    138 #endif
    139 
    140 /* Macros to read larger than 8 bit values from byte roms */
    141 #define	parseshort(o) \
    142 	((bus_space_read_1(memt, romh, (o) + 3) <<  8) | \
    143 	 (bus_space_read_1(memt, romh, (o) + 7)))
    144 #define	parseword(o) \
    145 	((bus_space_read_1(memt, romh, (o) +  3) << 24) | \
    146 	 (bus_space_read_1(memt, romh, (o) +  7) << 16) | \
    147 	 (bus_space_read_1(memt, romh, (o) + 11) <<  8) | \
    148 	 (bus_space_read_1(memt, romh, (o) + 15)))
    149 
    150 int
    151 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot,
    152     bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase)
    153 {
    154 	struct sti_rom *rom;
    155 	int rc;
    156 
    157 	rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF,
    158 	    M_WAITOK | M_ZERO);
    159 	rom->rom_softc = sc;
    160 	rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase);
    161 	if (rc != 0) {
    162 		free(rom, M_DEVBUF);
    163 		return rc;
    164 	}
    165 
    166 	sc->sc_rom = rom;
    167 
    168 	sti_describe(sc);
    169 
    170 	sc->sc_scr = sti_attach_screen(sc,
    171 	    sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR);
    172 	if (sc->sc_scr == NULL)
    173 		rc = ENOMEM;
    174 
    175 	return rc;
    176 }
    177 
    178 struct sti_screen *
    179 sti_attach_screen(struct sti_softc *sc, int flags)
    180 {
    181 	struct sti_screen *scr;
    182 	int rc;
    183 
    184 	scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF,
    185 	    M_WAITOK | M_ZERO);
    186 	scr->scr_rom = sc->sc_rom;
    187 	rc = sti_screen_setup(scr, flags);
    188 	if (rc != 0) {
    189 		free(scr, M_DEVBUF);
    190 		return NULL;
    191 	}
    192 
    193 	sti_describe_screen(sc, scr);
    194 
    195 	return scr;
    196 }
    197 
    198 int
    199 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
    200     bus_space_handle_t romh, bus_addr_t *bases, u_int codebase)
    201 {
    202 	struct sti_dd *dd;
    203 	int error, size, i;
    204 
    205 	KASSERT(rom != NULL);
    206 	STI_ENABLE_ROM(rom->rom_softc);
    207 
    208 	rom->iot = iot;
    209 	rom->memt = memt;
    210 	rom->romh = romh;
    211 	rom->bases = bases;
    212 
    213 	/*
    214 	 * Get ROM header and code function pointers.
    215 	 */
    216 	dd = &rom->rom_dd;
    217 	rom->rom_devtype = bus_space_read_1(memt, romh, 3);
    218 	if (rom->rom_devtype == STI_DEVTYPE1) {
    219 		dd->dd_type  = bus_space_read_1(memt, romh, 0x03);
    220 		dd->dd_nmon  = bus_space_read_1(memt, romh, 0x07);
    221 		dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b);
    222 		dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f);
    223 		dd->dd_grid[0] = parseword(0x10);
    224 		dd->dd_grid[1] = parseword(0x20);
    225 		dd->dd_fntaddr = parseword(0x30) & ~3;
    226 		dd->dd_maxst   = parseword(0x40);
    227 		dd->dd_romend  = parseword(0x50) & ~3;
    228 		dd->dd_reglst  = parseword(0x60) & ~3;
    229 		dd->dd_maxreent= parseshort(0x70);
    230 		dd->dd_maxtimo = parseshort(0x78);
    231 		dd->dd_montbl  = parseword(0x80) & ~3;
    232 		dd->dd_udaddr  = parseword(0x90) & ~3;
    233 		dd->dd_stimemreq=parseword(0xa0);
    234 		dd->dd_udsize  = parseword(0xb0);
    235 		dd->dd_pwruse  = parseshort(0xc0);
    236 		dd->dd_bussup  = bus_space_read_1(memt, romh, 0xcb);
    237 		dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf);
    238 		dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3);
    239 		dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7);
    240 		dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb);
    241 		dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf);
    242 		dd->dd_cfbaddr = parseword(0xe0) & ~3;
    243 
    244 		codebase <<= 2;
    245 		dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3;
    246 		dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3;
    247 		dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3;
    248 		dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3;
    249 		dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3;
    250 		dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3;
    251 		dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3;
    252 		dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3;
    253 		dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3;
    254 		dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3;
    255 		dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3;
    256 		dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3;
    257 		dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3;
    258 		dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3;
    259 		dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3;
    260 		dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3;
    261 	} else {	/* STI_DEVTYPE4 */
    262 		bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd,
    263 		    sizeof(*dd) / 4);
    264 		/* fix pacode... */
    265 		bus_space_read_region_stream_4(memt, romh, codebase,
    266 		    (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4);
    267 	}
    268 
    269 	STI_DISABLE_ROM(rom->rom_softc);
    270 
    271 	DPRINTF(("dd:\n"
    272 	    "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n"
    273 	    "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
    274 	    "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
    275 	    "code=",
    276 	    dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
    277 	    dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst,
    278 	    dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
    279 	    dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
    280 	    dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr));
    281 	DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
    282 	    dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
    283 	    dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
    284 	    dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
    285 	    dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
    286 	    dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
    287 	    dd->dd_pacode[0xf]));
    288 
    289 	/*
    290 	 * Figure out how many bytes we need for the STI code.
    291 	 * Note there could be fewer than STI_END pointer entries
    292 	 * populated, especially on older devices.
    293 	 */
    294 	for (i = STI_END; !dd->dd_pacode[i]; i--)
    295 		;
    296 
    297 	size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
    298 
    299 	if (rom->rom_devtype == STI_DEVTYPE1)
    300 		size = (size + 3) / 4;
    301 	if (size == 0) {
    302 		aprint_error(": no code for the requested platform\n");
    303 		return EINVAL;
    304 	}
    305 
    306 	DPRINTF(("code size %x/%x\n", size, round_page(size)));
    307 
    308 	if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0,
    309 	    UVM_KMF_WIRED))) {
    310 		aprint_error(": cannot allocate %u bytes for code\n", size);
    311 		return ENOMEM;
    312 	}
    313 
    314 	/*
    315 	 * Copy code into memory and make it executable.
    316 	 */
    317 
    318 	STI_ENABLE_ROM(rom->rom_softc);
    319 
    320 	if (rom->rom_devtype == STI_DEVTYPE1) {
    321 		uint8_t *p;
    322 		uint32_t addr, eaddr;
    323 
    324 		p = (uint8_t *)rom->rom_code;
    325 
    326 		for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
    327 		    addr < eaddr; addr += 4 ) {
    328 			*p++ = bus_space_read_4(memt, romh, addr)
    329 			    & 0xff;
    330 		}
    331 	} else {	/* STI_DEVTYPE4 */
    332 		bus_space_read_region_stream_4(memt, romh,
    333 		    dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code,
    334 		    size / 4);
    335 	}
    336 
    337 	STI_DISABLE_ROM(rom->rom_softc);
    338 
    339 	if ((error = uvm_map_protect(kernel_map, rom->rom_code,
    340 	    rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) {
    341 		aprint_error(": uvm_map_protect failed (%d)\n", error);
    342 		uvm_km_free(kernel_map, rom->rom_code, round_page(size),
    343 		    UVM_KMF_WIRED);
    344 		return error;
    345 	}
    346 
    347 	/*
    348 	 * Setup code function pointers.
    349 	 */
    350 
    351 #define	O(i) \
    352 	(dd->dd_pacode[(i)] == 0 ? 0 : \
    353 	    (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) /	\
    354 	    (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1)))
    355 	rom->init	= (sti_init_t)	O(STI_INIT_GRAPH);
    356 	rom->mgmt	= (sti_mgmt_t)	O(STI_STATE_MGMT);
    357 	rom->unpmv	= (sti_unpmv_t)	O(STI_FONT_UNPMV);
    358 	rom->blkmv	= (sti_blkmv_t)	O(STI_BLOCK_MOVE);
    359 	rom->test	= (sti_test_t)	O(STI_SELF_TEST);
    360 	rom->exhdl	= (sti_exhdl_t)	O(STI_EXCEP_HDLR);
    361 	rom->inqconf	= (sti_inqconf_t)O(STI_INQ_CONF);
    362 	rom->scment	= (sti_scment_t)O(STI_SCM_ENT);
    363 	rom->dmac	= (sti_dmac_t)	O(STI_DMA_CTRL);
    364 	rom->flowc	= (sti_flowc_t)	O(STI_FLOW_CTRL);
    365 	rom->utiming	= (sti_utiming_t)O(STI_UTIMING);
    366 	rom->pmgr	= (sti_pmgr_t)	O(STI_PROC_MGR);
    367 	rom->util	= (sti_util_t)	O(STI_UTIL);
    368 
    369 #undef O
    370 	/*
    371 	 * Set colormap entry is not implemented until 8.04, so force
    372 	 * a NULL pointer here.
    373 	 */
    374 
    375 	if (dd->dd_grrev < STI_REVISION(8, 4)) {
    376 		rom->scment = NULL;
    377 	}
    378 
    379 	return 0;
    380 }
    381 
    382 /*
    383  * Map all regions.
    384  */
    385 void
    386 sti_region_setup(struct sti_screen *scr)
    387 {
    388 	struct sti_rom *rom = scr->scr_rom;
    389 	bus_space_tag_t memt = rom->memt;
    390 	bus_space_handle_t romh = rom->romh;
    391 	bus_addr_t *bases = rom->bases;
    392 	struct sti_dd *dd = &rom->rom_dd;
    393 	struct sti_cfg *cc = &scr->scr_cfg;
    394 	bus_space_handle_t bh;
    395 	struct sti_region regions[STI_REGION_MAX], *r;
    396 	u_int regno, regcnt;
    397 	bus_addr_t addr;
    398 
    399 	DPRINTF(("stiregions @ %x:\n", dd->dd_reglst));
    400 
    401 	/*
    402 	 * Read the region information.
    403 	 */
    404 
    405 	STI_ENABLE_ROM(rom->rom_softc);
    406 
    407 	if (rom->rom_devtype == STI_DEVTYPE1) {
    408 		for (regno = 0; regno < STI_REGION_MAX; regno++)
    409 			*(u_int *)(regions + regno) =
    410 			    parseword(dd->dd_reglst + regno * 0x10);
    411 	} else {
    412 		bus_space_read_region_stream_4(memt, romh, dd->dd_reglst,
    413 		    (uint32_t *)regions, sizeof(regions) / 4);
    414 	}
    415 
    416 	STI_DISABLE_ROM(rom->rom_softc);
    417 
    418 	/*
    419 	 * Count them.
    420 	 */
    421 
    422 	for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++)
    423 		if (r->last)
    424 			break;
    425 	regcnt++;
    426 
    427 	/*
    428 	 * Map them.
    429 	 */
    430 
    431 	for (regno = 0, r = regions; regno < regcnt; regno++, r++) {
    432 		if (r->length == 0)
    433 			continue;
    434 
    435 		/*
    436 		 * Assume an existing mapping exists.
    437 		 */
    438 		addr = bases[regno] + (r->offset << PGSHIFT);
    439 		DPRINTF(("%08x @ 0x%08x%s%s%s%s",
    440 		    r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "",
    441 		    r->cache ? " cache" : "", r->btlb ? " btlb" : "",
    442 		    r->last ? " last" : ""));
    443 
    444 		/*
    445 		 * Region #0 is always the rom, and it should have been
    446 		 * mapped already.
    447 		 * XXX This expects a 1:1 mapping...
    448 		 */
    449 		if (regno == 0 && romh == bases[0]) {
    450 			cc->regions[0] = addr;
    451 			DPRINTF(("\n"));
    452 			continue;
    453 		}
    454 
    455 		/* XXXNH BUS_SPACE_MAP_CACHEABLE */
    456 		if (bus_space_map(memt, addr, r->length << PGSHIFT,
    457 		    r->cache ? BUS_SPACE_MAP_CACHEABLE : 0, &bh)) {
    458 			DPRINTF((" - already mapped region\n"));
    459 		} else {
    460 
    461 			/* XXX should use bus_space_vaddr */
    462 			addr = (bus_addr_t)bh;
    463 			if (regno == 1) {
    464 				DPRINTF((" - fb"));
    465 				scr->fbaddr = addr;
    466 				scr->fblen = r->length << PGSHIFT;
    467 			}
    468 			DPRINTF(("\n"));
    469 		}
    470 
    471 		cc->regions[regno] = addr;
    472 	}
    473 
    474 #ifdef STIDEBUG
    475 	/*
    476 	 * Make sure we'll trap accessing unmapped regions
    477 	 */
    478 	for (regno = 0; regno < STI_REGION_MAX; regno++)
    479 		if (cc->regions[regno] == 0)
    480 		    cc->regions[regno] = 0x81234567;
    481 #endif
    482 }
    483 
    484 int
    485 sti_screen_setup(struct sti_screen *scr, int flags)
    486 {
    487 	struct sti_rom *rom = scr->scr_rom;
    488 	bus_space_tag_t memt = rom->memt;
    489 	bus_space_handle_t romh = rom->romh;
    490 	struct sti_dd *dd = &rom->rom_dd;
    491 	struct sti_cfg *cc = &scr->scr_cfg;
    492 	struct sti_inqconfout cfg;
    493 	struct sti_einqconfout ecfg;
    494 #ifdef STIDEBUG
    495 	char buf[256];
    496 #endif
    497 	int error, i;
    498 	int geometry_kluge = 0;
    499 	u_int fontindex = 0;
    500 
    501 	KASSERT(scr != NULL);
    502 	memset(cc, 0, sizeof(*cc));
    503 	cc->ext_cfg = &scr->scr_ecfg;
    504 	memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));
    505 
    506 	if (dd->dd_stimemreq) {
    507 		scr->scr_ecfg.addr =
    508 		    malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK);
    509 	}
    510 
    511 	sti_region_setup(scr);
    512 
    513 	if ((error = sti_init(scr, 0))) {
    514 		aprint_error(": cannot initialize (%d)\n", error);
    515 		goto fail;
    516 	}
    517 
    518 	memset(&cfg, 0, sizeof(cfg));
    519 	memset(&ecfg, 0, sizeof(ecfg));
    520 	cfg.ext = &ecfg;
    521 	if ((error = sti_inqcfg(scr, &cfg))) {
    522 		aprint_error(": error %d inquiring config\n", error);
    523 		goto fail;
    524 	}
    525 
    526 	/*
    527 	 * Older (rev 8.02) boards report wrong offset values,
    528 	 * similar to the displayable area size, at least in m68k mode.
    529 	 * Attempt to detect this and adjust here.
    530 	 */
    531 	if (cfg.owidth == cfg.width &&
    532 	    cfg.oheight == cfg.height)
    533 		geometry_kluge = 1;
    534 
    535 	if (geometry_kluge) {
    536 		scr->scr_cfg.oscr_width = cfg.owidth =
    537 		    cfg.fbwidth - cfg.width;
    538 		scr->scr_cfg.oscr_height = cfg.oheight =
    539 		    cfg.fbheight - cfg.height;
    540 	}
    541 
    542 	/*
    543 	 * Save a few fields for sti_describe_screen() later
    544 	 */
    545 	scr->fbheight = cfg.fbheight;
    546 	scr->fbwidth = cfg.fbwidth;
    547 	scr->oheight = cfg.oheight;
    548 	scr->owidth = cfg.owidth;
    549 	memcpy(scr->name, cfg.name, sizeof(scr->name));
    550 
    551 	if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
    552 		aprint_error(": cannot initialize (%d)\n", error);
    553 		goto fail;
    554 	}
    555 #ifdef STIDEBUG
    556 	snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
    557 	DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
    558 	    "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
    559 	    cfg.planes, buf,
    560 	    ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
    561 	    ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
    562 #endif
    563 	scr->scr_bpp = cfg.bppu;
    564 
    565 	/*
    566 	 * Although scr->scr_ecfg.current_monitor is not filled by
    567 	 * sti_init() as expected, we can nevertheless walk the monitor
    568 	 * list, if there is any, and if we find a mode matching our
    569 	 * resolution, pick its font index.
    570 	 */
    571 	if (dd->dd_montbl != 0) {
    572 		STI_ENABLE_ROM(rom->rom_softc);
    573 
    574 		for (i = 0; i < dd->dd_nmon; i++) {
    575 			u_int offs = dd->dd_montbl + 8 * i;
    576 			uint32_t m[2];
    577 			sti_mon_t mon = (void *)m;
    578 			if (rom->rom_devtype == STI_DEVTYPE1) {
    579 				m[0] = parseword(4 * offs);
    580 				m[1] = parseword(4 * (offs + 4));
    581 			} else {
    582 				bus_space_read_region_stream_4(memt, romh, offs,
    583 				    (uint32_t *)mon, sizeof(*mon) / 4);
    584 			}
    585 
    586 			if (mon->width == scr->scr_cfg.scr_width &&
    587 			    mon->height == scr->scr_cfg.scr_height) {
    588 				fontindex = mon->font;
    589 				break;
    590 			}
    591 		}
    592 
    593 		STI_DISABLE_ROM(rom->rom_softc);
    594 
    595 		DPRINTF(("font index: %d\n", fontindex));
    596 	}
    597 
    598 	if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
    599 		aprint_error(": cannot fetch fonts (%d)\n", error);
    600 		goto fail;
    601 	}
    602 
    603 	/*
    604 	 * setup screen descriptions:
    605 	 *	figure number of fonts supported;
    606 	 *	allocate wscons structures;
    607 	 *	calculate dimensions.
    608 	 */
    609 
    610 	scr->scr_wsd.name = "std";
    611 	scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
    612 	scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
    613 	scr->scr_wsd.textops = &sti_emulops;
    614 	scr->scr_wsd.fontwidth = scr->scr_curfont.width;
    615 	scr->scr_wsd.fontheight = scr->scr_curfont.height;
    616 	scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE;
    617 
    618 	scr->scr_scrlist[0] = &scr->scr_wsd;
    619 	scr->scr_screenlist.nscreens = 1;
    620 	scr->scr_screenlist.screens = scr->scr_scrlist;
    621 
    622 	return 0;
    623 
    624 fail:
    625 	/* XXX free resources */
    626 	if (scr->scr_ecfg.addr != NULL) {
    627 		free(scr->scr_ecfg.addr, M_DEVBUF);
    628 		scr->scr_ecfg.addr = NULL;
    629 	}
    630 
    631 	return ENXIO;
    632 }
    633 
    634 void
    635 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
    636 {
    637 	struct sti_font *fp = &scr->scr_curfont;
    638 
    639 	aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
    640 	    device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
    641 	    scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
    642 
    643 	aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    644 	    device_xname(sc->sc_dev), fp->width, fp->height,
    645 	    fp->type, fp->bpc, fp->first, fp->last);
    646 }
    647 
    648 void
    649 sti_describe(struct sti_softc *sc)
    650 {
    651 	struct sti_rom *rom = sc->sc_rom;
    652 	struct sti_dd *dd = &rom->rom_dd;
    653 
    654 	aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
    655 	    dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
    656 	    dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
    657 
    658 	if (sc->sc_scr != NULL)
    659 		sti_describe_screen(sc, sc->sc_scr);
    660 }
    661 
    662 void
    663 sti_end_attach(struct sti_softc *sc)
    664 {
    665 	struct sti_screen *scr = sc->sc_scr;
    666 
    667 	if (scr == NULL)
    668 		return;
    669 #if NWSDISPLAY > 0
    670 	else {
    671 		struct wsemuldisplaydev_attach_args waa;
    672 		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
    673 
    674 		waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
    675 		waa.scrdata = &scr->scr_screenlist;
    676 		waa.accessops = &sti_accessops;
    677 		waa.accesscookie = scr;
    678 
    679 		/* attach as console if required */
    680 		if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
    681 			long defattr;
    682 
    683 			sti_alloc_attr(scr, 0, 0, 0, &defattr);
    684 			wsdisplay_cnattach(&scr->scr_wsd, scr,
    685 			    0, scr->scr_wsd.nrows - 1, defattr);
    686 			sc->sc_flags |= STI_ATTACHED;
    687 		}
    688 
    689 		config_found(sc->sc_dev, &waa, wsemuldisplaydevprint);
    690 	}
    691 #endif
    692 }
    693 
    694 u_int
    695 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
    696 {
    697 	int devtype;
    698 	u_int romend;
    699 
    700 	devtype = bus_space_read_1(memt, romh, 3);
    701 	if (devtype == STI_DEVTYPE4) {
    702 		bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
    703 		    (uint32_t *)&romend, 1);
    704 	} else {
    705 		romend = parseword(STI_DEV1_DD_ROMEND);
    706 	}
    707 
    708 	DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
    709 
    710 	return round_page(romend);
    711 }
    712 
    713 int
    714 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
    715     uint32_t baseaddr, u_int fontindex)
    716 {
    717 	struct sti_rom *rom = scr->scr_rom;
    718 	bus_space_tag_t memt = rom->memt;
    719 	bus_space_handle_t romh = rom->romh;
    720 	struct sti_font *fp = &scr->scr_curfont;
    721 	uint32_t addr;
    722 	int size;
    723 #ifdef notyet
    724 	int uc;
    725 	struct {
    726 		struct sti_unpmvflags flags;
    727 		struct sti_unpmvin in;
    728 		struct sti_unpmvout out;
    729 	} a;
    730 #endif
    731 
    732 	/*
    733 	 * Get the first PROM font in memory
    734 	 */
    735 
    736 	STI_ENABLE_ROM(rom->rom_softc);
    737 
    738 rescan:
    739 	addr = baseaddr;
    740 	do {
    741 		if (rom->rom_devtype == STI_DEVTYPE1) {
    742 			fp->first  = parseshort(addr + 0x00);
    743 			fp->last   = parseshort(addr + 0x08);
    744 			fp->width  = bus_space_read_1(memt, romh, addr + 0x13);
    745 			fp->height = bus_space_read_1(memt, romh, addr + 0x17);
    746 			fp->type   = bus_space_read_1(memt, romh, addr + 0x1b);
    747 			fp->bpc    = bus_space_read_1(memt, romh, addr + 0x1f);
    748 			fp->next   = parseword(addr + 0x20);
    749 			fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
    750 			fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
    751 		} else {	/* STI_DEVTYPE4 */
    752 			bus_space_read_region_stream_4(memt, romh, addr,
    753 			    (uint32_t *)fp, sizeof(struct sti_font) / 4);
    754 		}
    755 
    756 #ifdef STIDEBUG
    757 		STI_DISABLE_ROM(rom->rom_softc);
    758 		DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    759 		    device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
    760 		    fp->height, fp->type, fp->bpc, fp->first, fp->last));
    761 		STI_ENABLE_ROM(rom->rom_softc);
    762 #endif
    763 
    764 		if (fontindex == 0) {
    765 			size = sizeof(struct sti_font) +
    766 			    (fp->last - fp->first + 1) * fp->bpc;
    767 			if (rom->rom_devtype == STI_DEVTYPE1)
    768 				size *= 4;
    769 			scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK);
    770 
    771 			bus_space_read_region_stream_4(memt, romh, addr,
    772 			    (uint32_t *)scr->scr_romfont, size / 4);
    773 			break;
    774 		}
    775 
    776 		addr = baseaddr + fp->next;
    777 		fontindex--;
    778 	} while (fp->next != 0);
    779 
    780 	/*
    781 	 * If our font index was bogus, we did not find the expected font.
    782 	 * In this case, pick the first one and be done with it.
    783 	 */
    784 	if (fp->next == 0 && scr->scr_romfont == NULL) {
    785 		fontindex = 0;
    786 		goto rescan;
    787 	}
    788 
    789 	STI_DISABLE_ROM(rom->rom_softc);
    790 
    791 #ifdef notyet
    792 	/*
    793 	 * If there is enough room in the off-screen framebuffer memory,
    794 	 * display all the characters there in order to display them
    795 	 * faster with blkmv operations rather than unpmv later on.
    796 	 */
    797 	if (size <= cfg->fbheight *
    798 	    (cfg->fbwidth - cfg->width - cfg->owidth)) {
    799 		memset(&a, 0, sizeof(a));
    800 		a.flags.flags = STI_UNPMVF_WAIT;
    801 		a.in.fg_colour = STI_COLOUR_WHITE;
    802 		a.in.bg_colour = STI_COLOUR_BLACK;
    803 		a.in.font_addr = scr->scr_romfont;
    804 
    805 		scr->scr_fontmaxcol = cfg->fbheight / fp->height;
    806 		scr->scr_fontbase = cfg->width + cfg->owidth;
    807 		for (uc = fp->first; uc <= fp->last; uc++) {
    808 			a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
    809 			    fp->width + scr->scr_fontbase;
    810 			a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
    811 			    fp->height;
    812 			a.in.index = uc;
    813 
    814 			(*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    815 			if (a.out.errno) {
    816 				aprint_error_dev(sc->sc_dev, "unpmv %d "
    817 				    "returned %d\n", uc, a.out.errno);
    818 				return 0;
    819 			}
    820 		}
    821 
    822 		free(scr->scr_romfont, M_DEVBUF);
    823 		scr->scr_romfont = NULL;
    824 	}
    825 #endif
    826 
    827 	return 0;
    828 }
    829 
    830 /*
    831  * Wrappers around STI code pointers
    832  */
    833 int
    834 sti_init(struct sti_screen *scr, int mode)
    835 {
    836 	struct sti_rom *rom = scr->scr_rom;
    837 	struct {
    838 		struct sti_initflags flags;
    839 		struct sti_initin in;
    840 		struct sti_einitin ein;
    841 		struct sti_initout out;
    842 	} a;
    843 
    844 	KASSERT(rom != NULL);
    845 	memset(&a, 0, sizeof(a));
    846 
    847 	a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
    848 	    (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET |
    849 	     STI_INITF_PBETI | STI_INITF_ICMT : 0) |
    850 	    (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0);
    851 	a.in.text_planes = 1;
    852 	a.in.ext_in = &a.ein;
    853 
    854 	DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
    855 	    device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
    856 	    &a.in, &a.out, &scr->scr_cfg));
    857 
    858 	(*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    859 
    860 	if (a.out.text_planes != a.in.text_planes)
    861 		return -1;	/* not colliding with sti errno values */
    862 	return a.out.errno;
    863 }
    864 
    865 int
    866 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
    867 {
    868 	struct sti_rom *rom = scr->scr_rom;
    869 	struct {
    870 		struct sti_inqconfflags flags;
    871 		struct sti_inqconfin in;
    872 	} a;
    873 
    874 	memset(&a, 0, sizeof(a));
    875 
    876 	a.flags.flags = STI_INQCONFF_WAIT;
    877 	(*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
    878 
    879 	return out->errno;
    880 }
    881 
    882 void
    883 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
    884     enum sti_bmove_funcs f)
    885 {
    886 	struct sti_rom *rom = scr->scr_rom;
    887 	struct {
    888 		struct sti_blkmvflags flags;
    889 		struct sti_blkmvin in;
    890 		struct sti_blkmvout out;
    891 	} a;
    892 
    893 	memset(&a, 0, sizeof(a));
    894 
    895 	a.flags.flags = STI_BLKMVF_WAIT;
    896 	switch (f) {
    897 	case bmf_clear:
    898 		a.flags.flags |= STI_BLKMVF_CLR;
    899 		a.in.bg_colour = STI_COLOUR_BLACK;
    900 		break;
    901 	case bmf_underline:
    902 	case bmf_copy:
    903 		a.in.fg_colour = STI_COLOUR_WHITE;
    904 		a.in.bg_colour = STI_COLOUR_BLACK;
    905 		break;
    906 	case bmf_invert:
    907 		a.flags.flags |= STI_BLKMVF_COLR;
    908 		a.in.fg_colour = STI_COLOUR_BLACK;
    909 		a.in.bg_colour = STI_COLOUR_WHITE;
    910 		break;
    911 	}
    912 	a.in.srcx = x1;
    913 	a.in.srcy = y1;
    914 	a.in.dstx = x2;
    915 	a.in.dsty = y2;
    916 	a.in.height = h;
    917 	a.in.width = w;
    918 
    919 	(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    920 #ifdef STIDEBUG
    921 	if (a.out.errno)
    922 		printf("%s: blkmv returned %d\n",
    923 		    device_xname(rom->rom_softc->sc_dev), a.out.errno);
    924 #endif
    925 }
    926 
    927 int
    928 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
    929 {
    930 	struct sti_rom *rom = scr->scr_rom;
    931 	struct {
    932 		struct sti_scmentflags flags;
    933 		struct sti_scmentin in;
    934 		struct sti_scmentout out;
    935 	} a;
    936 
    937 	memset(&a, 0, sizeof(a));
    938 
    939 	a.flags.flags = STI_SCMENTF_WAIT;
    940 	a.in.entry = i;
    941 	a.in.value = (r << 16) | (g << 8) | b;
    942 
    943 	(*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    944 
    945 	return a.out.errno;
    946 }
    947 
    948 /*
    949  * wsdisplay accessops
    950  */
    951 int
    952 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    953 {
    954 	struct sti_screen *scr = (struct sti_screen *)v;
    955 	struct sti_rom *rom = scr->scr_rom;
    956 	struct wsdisplay_fbinfo *wdf;
    957 	struct wsdisplay_cmap *cmapp;
    958 	u_int mode, idx, count;
    959 	int i, ret;
    960 
    961 	ret = 0;
    962 	switch (cmd) {
    963 	case WSDISPLAYIO_GMODE:
    964 		*(u_int *)data = scr->scr_wsmode;
    965 		break;
    966 
    967 	case WSDISPLAYIO_SMODE:
    968 		mode = *(u_int *)data;
    969 		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
    970 		    mode == WSDISPLAYIO_MODE_DUMBFB)
    971 			ret = sti_init(scr, 0);
    972 		else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
    973 		    mode == WSDISPLAYIO_MODE_EMUL)
    974 			ret = sti_init(scr, STI_TEXTMODE);
    975 		scr->scr_wsmode = mode;
    976 		break;
    977 
    978 	case WSDISPLAYIO_GTYPE:
    979 		*(u_int *)data = WSDISPLAY_TYPE_STI;
    980 		break;
    981 
    982 	case WSDISPLAYIO_GINFO:
    983 		wdf = (struct wsdisplay_fbinfo *)data;
    984 		wdf->height = scr->scr_cfg.scr_height;
    985 		wdf->width  = scr->scr_cfg.scr_width;
    986 		wdf->depth  = scr->scr_bpp;
    987 		if (rom->scment == NULL)
    988 			wdf->cmsize = 0;
    989 		else
    990 			wdf->cmsize = STI_NCMAP;
    991 		break;
    992 
    993 	case WSDISPLAYIO_LINEBYTES:
    994 		*(u_int *)data = scr->scr_cfg.fb_width;
    995 		break;
    996 
    997 	case WSDISPLAYIO_GETCMAP:
    998 		if (rom->scment == NULL)
    999 			return ENOTTY;
   1000 		cmapp = (struct wsdisplay_cmap *)data;
   1001 		idx = cmapp->index;
   1002 		count = cmapp->count;
   1003 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1004 			return EINVAL;
   1005 		if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
   1006 			break;
   1007 		if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
   1008 			break;
   1009 		if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
   1010 			break;
   1011 		break;
   1012 
   1013 	case WSDISPLAYIO_PUTCMAP:
   1014 		if (rom->scment == NULL)
   1015 			return ENOTTY;
   1016 		cmapp = (struct wsdisplay_cmap *)data;
   1017 		idx = cmapp->index;
   1018 		count = cmapp->count;
   1019 		if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
   1020 			return EINVAL;
   1021 		if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
   1022 			break;
   1023 		if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
   1024 			break;
   1025 		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
   1026 			break;
   1027 		for (i = idx + count - 1; i >= idx; i--)
   1028 			if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
   1029 			    scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
   1030 
   1031 				DPRINTF(("sti_ioctl: "
   1032 				    "sti_setcment(%d, %u, %u, %u): %%d\n", i,
   1033 				    (u_int)scr->scr_rcmap[i],
   1034 				    (u_int)scr->scr_gcmap[i],
   1035 				    (u_int)scr->scr_bcmap[i]));
   1036 
   1037 				ret = EINVAL;
   1038 				break;
   1039 			}
   1040 		break;
   1041 
   1042 	case WSDISPLAYIO_SVIDEO:
   1043 	case WSDISPLAYIO_GVIDEO:
   1044 	case WSDISPLAYIO_GCURPOS:
   1045 	case WSDISPLAYIO_SCURPOS:
   1046 	case WSDISPLAYIO_GCURMAX:
   1047 	case WSDISPLAYIO_GCURSOR:
   1048 	case WSDISPLAYIO_SCURSOR:
   1049 	default:
   1050 		return ENOTTY;	/* not supported yet */
   1051 	}
   1052 
   1053 	return ret;
   1054 }
   1055 
   1056 paddr_t
   1057 sti_mmap(void *v, void *vs, off_t offset, int prot)
   1058 {
   1059 #if 0
   1060 	struct sti_screen *scr = (struct sti_screen *)v;
   1061 #endif
   1062 	/* XXX not finished */
   1063 	return -1;
   1064 }
   1065 
   1066 int
   1067 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
   1068     int *cxp, int *cyp, long *defattr)
   1069 {
   1070 	struct sti_screen *scr = (struct sti_screen *)v;
   1071 
   1072 	if (scr->scr_nscreens > 0)
   1073 		return ENOMEM;
   1074 
   1075 	*cookiep = scr;
   1076 	*cxp = 0;
   1077 	*cyp = 0;
   1078 	sti_alloc_attr(scr, 0, 0, 0, defattr);
   1079 	scr->scr_nscreens++;
   1080 
   1081 	return 0;
   1082 }
   1083 
   1084 void
   1085 sti_free_screen(void *v, void *cookie)
   1086 {
   1087 	struct sti_screen *scr = (struct sti_screen *)v;
   1088 
   1089 	scr->scr_nscreens--;
   1090 }
   1091 
   1092 int
   1093 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
   1094     void *cbarg)
   1095 {
   1096 #if 0
   1097 	struct sti_screen *scr = (struct sti_screen *)v;
   1098 #endif
   1099 
   1100 	return 0;
   1101 }
   1102 
   1103 int
   1104 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
   1105 {
   1106 #if 0
   1107 	struct sti_screen *scr = (struct sti_screen *)v;
   1108 #endif
   1109 
   1110 	return -1;
   1111 }
   1112 
   1113 /*
   1114  * wsdisplay emulops
   1115  */
   1116 void
   1117 sti_cursor(void *v, int on, int row, int col)
   1118 {
   1119 	struct sti_screen *scr = (struct sti_screen *)v;
   1120 	struct sti_font *fp = &scr->scr_curfont;
   1121 
   1122 	sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width,
   1123 	    row * fp->height, fp->height, fp->width, bmf_invert);
   1124 }
   1125 
   1126 /*
   1127  * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
   1128  */
   1129 static const uint8_t
   1130 sti_unitoroman[0x100 - 0xa0] = {
   1131 	0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc,    0, 0xbd,
   1132 	0xab,    0, 0xf9, 0xfb,    0, 0xf6,    0, 0xb0,
   1133 
   1134 	0xb3, 0xfe,    0,    0, 0xa8, 0xf3, 0xf4, 0xf2,
   1135 	   0,    0, 0xfa, 0xfd, 0xf7, 0xf8,    0, 0xb9,
   1136 
   1137 	0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
   1138 	0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
   1139 
   1140 	0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda,    0,
   1141 	0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
   1142 
   1143 	0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
   1144 	0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
   1145 
   1146 	0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce,    0,
   1147 	0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
   1148 };
   1149 
   1150 int
   1151 sti_mapchar(void *v, int uni, u_int *index)
   1152 {
   1153 	struct sti_screen *scr = (struct sti_screen *)v;
   1154 	struct sti_font *fp = &scr->scr_curfont;
   1155 	int c;
   1156 
   1157 	switch (fp->type) {
   1158 	case STI_FONT_HPROMAN8:
   1159 		if (uni >= 0x80 && uni < 0xa0)
   1160 			c = -1;
   1161 		else if (uni >= 0xa0 && uni < 0x100) {
   1162 			c = (int)sti_unitoroman[uni - 0xa0];
   1163 			if (c == 0)
   1164 				c = -1;
   1165 		} else
   1166 			c = uni;
   1167 		break;
   1168 	default:
   1169 		c = uni;
   1170 		break;
   1171 	}
   1172 
   1173 	if (c == -1 || c < fp->first || c > fp->last) {
   1174 		*index = ' ';
   1175 		return 0;
   1176 	}
   1177 
   1178 	*index = c;
   1179 	return 5;
   1180 }
   1181 
   1182 void
   1183 sti_putchar(void *v, int row, int col, u_int uc, long attr)
   1184 {
   1185 	struct sti_screen *scr = (struct sti_screen *)v;
   1186 	struct sti_rom *rom = scr->scr_rom;
   1187 	struct sti_font *fp = &scr->scr_curfont;
   1188 
   1189 	if (scr->scr_romfont != NULL) {
   1190 		/*
   1191 		 * Font is in memory, use unpmv
   1192 		 */
   1193 		struct {
   1194 			struct sti_unpmvflags flags;
   1195 			struct sti_unpmvin in;
   1196 			struct sti_unpmvout out;
   1197 		} a;
   1198 
   1199 		memset(&a, 0, sizeof(a));
   1200 
   1201 		a.flags.flags = STI_UNPMVF_WAIT;
   1202 		/* XXX does not handle text attributes */
   1203 		a.in.fg_colour = STI_COLOUR_WHITE;
   1204 		a.in.bg_colour = STI_COLOUR_BLACK;
   1205 		a.in.x = col * fp->width;
   1206 		a.in.y = row * fp->height;
   1207 		a.in.font_addr = scr->scr_romfont;
   1208 		a.in.index = uc;
   1209 
   1210 		(*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1211 	} else {
   1212 		/*
   1213 		 * Font is in frame buffer, use blkmv
   1214 		 */
   1215 		struct {
   1216 			struct sti_blkmvflags flags;
   1217 			struct sti_blkmvin in;
   1218 			struct sti_blkmvout out;
   1219 		} a;
   1220 
   1221 		memset(&a, 0, sizeof(a));
   1222 
   1223 		a.flags.flags = STI_BLKMVF_WAIT;
   1224 		/* XXX does not handle text attributes */
   1225 		a.in.fg_colour = STI_COLOUR_WHITE;
   1226 		a.in.bg_colour = STI_COLOUR_BLACK;
   1227 
   1228 		a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
   1229 		    fp->width + scr->scr_fontbase;
   1230 		a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
   1231 		    fp->height;
   1232 		a.in.dstx = col * fp->width;
   1233 		a.in.dsty = row * fp->height;
   1234 		a.in.height = fp->height;
   1235 		a.in.width = fp->width;
   1236 
   1237 		(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1238 	}
   1239 }
   1240 
   1241 void
   1242 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
   1243 {
   1244 	struct sti_screen *scr = (struct sti_screen *)v;
   1245 	struct sti_font *fp = &scr->scr_curfont;
   1246 
   1247 	sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width,
   1248 	    row * fp->height, fp->height, ncols * fp->width, bmf_copy);
   1249 }
   1250 
   1251 void
   1252 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
   1253 {
   1254 	struct sti_screen *scr = (struct sti_screen *)v;
   1255 	struct sti_font *fp = &scr->scr_curfont;
   1256 
   1257 	sti_bmove(scr, startcol * fp->width, row * fp->height,
   1258 	    startcol * fp->width, row * fp->height, fp->height,
   1259 	    ncols * fp->width, bmf_clear);
   1260 }
   1261 
   1262 void
   1263 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
   1264 {
   1265 	struct sti_screen *scr = (struct sti_screen *)v;
   1266 	struct sti_font *fp = &scr->scr_curfont;
   1267 
   1268 	sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
   1269 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
   1270 }
   1271 
   1272 void
   1273 sti_eraserows(void *v, int srcrow, int nrows, long attr)
   1274 {
   1275 	struct sti_screen *scr = (struct sti_screen *)v;
   1276 	struct sti_font *fp = &scr->scr_curfont;
   1277 
   1278 	sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
   1279 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
   1280 }
   1281 
   1282 int
   1283 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
   1284 {
   1285 #if 0
   1286 	struct sti_screen *scr = (struct sti_screen *)v;
   1287 #endif
   1288 
   1289 	*pattr = 0;
   1290 
   1291 	return 0;
   1292 }
   1293 
   1294 #ifdef hp300	/* XXX */
   1295 /*
   1296  * Early console support.  Only used on hp300.
   1297  */
   1298 int
   1299 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt,
   1300     bus_addr_t *bases, u_int codebase)
   1301 {
   1302 	bus_space_handle_t romh;
   1303 	u_int romend;
   1304 	int error;
   1305 	long defattr;
   1306 
   1307 	if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0)
   1308 		return error;
   1309 
   1310 	/*
   1311 	 * Compute real PROM size
   1312 	 */
   1313 	romend = sti_rom_size(memt, romh);
   1314 
   1315 	bus_space_unmap(memt, romh, PAGE_SIZE);
   1316 
   1317 	if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0)
   1318 		return error;
   1319 
   1320 	bases[0] = romh;
   1321 	if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0)
   1322 		return -1;
   1323 	scr->scr_rom = rom;
   1324 	if (sti_screen_setup(scr, STI_CLEARSCR) != 0)
   1325 		return -1;
   1326 
   1327 	sti_alloc_attr(scr, 0, 0, 0, &defattr);
   1328 	wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
   1329 
   1330 	return 0;
   1331 }
   1332 #endif
   1333