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