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