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