Home | History | Annotate | Line # | Download | only in ic
sti.c revision 1.16
      1 /*	$NetBSD: sti.c,v 1.16 2011/07/11 02:30:49 matt 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.16 2011/07/11 02:30:49 matt 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 = scr->scr_scrlist;
    644 
    645 	return 0;
    646 
    647 fail:
    648 	/* XXX free resources */
    649 	if (scr->scr_ecfg.addr != NULL) {
    650 		free(scr->scr_ecfg.addr, M_DEVBUF);
    651 		scr->scr_ecfg.addr = NULL;
    652 	}
    653 
    654 	return ENXIO;
    655 }
    656 
    657 void
    658 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
    659 {
    660 	struct sti_font *fp = &scr->scr_curfont;
    661 
    662 	aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
    663 	    device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
    664 	    scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
    665 
    666 	aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    667 	    device_xname(sc->sc_dev), fp->width, fp->height,
    668 	    fp->type, fp->bpc, fp->first, fp->last);
    669 }
    670 
    671 void
    672 sti_describe(struct sti_softc *sc)
    673 {
    674 	struct sti_rom *rom = sc->sc_rom;
    675 	struct sti_dd *dd = &rom->rom_dd;
    676 
    677 	aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
    678 	    dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
    679 	    dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
    680 
    681 	if (sc->sc_scr != NULL)
    682 		sti_describe_screen(sc, sc->sc_scr);
    683 }
    684 
    685 void
    686 sti_end_attach(struct sti_softc *sc)
    687 {
    688 	struct sti_screen *scr = sc->sc_scr;
    689 
    690 	if (scr == NULL)
    691 		return;
    692 #if NWSDISPLAY > 0
    693 	else {
    694 		struct wsemuldisplaydev_attach_args waa;
    695 		scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
    696 
    697 		waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
    698 		waa.scrdata = &scr->scr_screenlist;
    699 		waa.accessops = &sti_accessops;
    700 		waa.accesscookie = scr;
    701 
    702 		/* attach as console if required */
    703 		if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
    704 			long defattr;
    705 
    706 			sti_alloc_attr(scr, 0, 0, 0, &defattr);
    707 			wsdisplay_cnattach(&scr->scr_wsd, scr,
    708 			    0, scr->scr_wsd.nrows - 1, defattr);
    709 			sc->sc_flags |= STI_ATTACHED;
    710 		}
    711 
    712 		config_found(sc->sc_dev, &waa, wsemuldisplaydevprint);
    713 	}
    714 #endif
    715 }
    716 
    717 u_int
    718 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
    719 {
    720 	int devtype;
    721 	u_int romend;
    722 
    723 	devtype = bus_space_read_1(memt, romh, 3);
    724 	if (devtype == STI_DEVTYPE4) {
    725 		bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
    726 		    (uint32_t *)&romend, 1);
    727 	} else {
    728 		romend = parseword(STI_DEV1_DD_ROMEND);
    729 	}
    730 
    731 	DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
    732 
    733 	return round_page(romend);
    734 }
    735 
    736 int
    737 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
    738     uint32_t baseaddr, u_int fontindex)
    739 {
    740 	struct sti_rom *rom = scr->scr_rom;
    741 	bus_space_tag_t memt = rom->memt;
    742 	bus_space_handle_t romh = rom->romh;
    743 	struct sti_font *fp = &scr->scr_curfont;
    744 	uint32_t addr;
    745 	int size;
    746 #ifdef notyet
    747 	int uc;
    748 	struct {
    749 		struct sti_unpmvflags flags;
    750 		struct sti_unpmvin in;
    751 		struct sti_unpmvout out;
    752 	} a;
    753 #endif
    754 
    755 	/*
    756 	 * Get the first PROM font in memory
    757 	 */
    758 
    759 	STI_ENABLE_ROM(rom->rom_softc);
    760 
    761 rescan:
    762 	addr = baseaddr;
    763 	do {
    764 		if (rom->rom_devtype == STI_DEVTYPE1) {
    765 			fp->first  = parseshort(addr + 0x00);
    766 			fp->last   = parseshort(addr + 0x08);
    767 			fp->width  = bus_space_read_1(memt, romh, addr + 0x13);
    768 			fp->height = bus_space_read_1(memt, romh, addr + 0x17);
    769 			fp->type   = bus_space_read_1(memt, romh, addr + 0x1b);
    770 			fp->bpc    = bus_space_read_1(memt, romh, addr + 0x1f);
    771 			fp->next   = parseword(addr + 0x20);
    772 			fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
    773 			fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
    774 		} else {	/* STI_DEVTYPE4 */
    775 			bus_space_read_region_stream_4(memt, romh, addr,
    776 			    (uint32_t *)fp, sizeof(struct sti_font) / 4);
    777 		}
    778 
    779 #ifdef STIDEBUG
    780 		STI_DISABLE_ROM(rom->rom_softc);
    781 		DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
    782 		    device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
    783 		    fp->height, fp->type, fp->bpc, fp->first, fp->last));
    784 		STI_ENABLE_ROM(rom->rom_softc);
    785 #endif
    786 
    787 		if (fontindex == 0) {
    788 			size = sizeof(struct sti_font) +
    789 			    (fp->last - fp->first + 1) * fp->bpc;
    790 			if (rom->rom_devtype == STI_DEVTYPE1)
    791 				size *= 4;
    792 			scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
    793 			if (scr->scr_romfont == NULL)
    794 				return ENOMEM;
    795 
    796 			bus_space_read_region_stream_4(memt, romh, addr,
    797 			    (uint32_t *)scr->scr_romfont, size / 4);
    798 			break;
    799 		}
    800 
    801 		addr = baseaddr + fp->next;
    802 		fontindex--;
    803 	} while (fp->next != 0);
    804 
    805 	/*
    806 	 * If our font index was bogus, we did not find the expected font.
    807 	 * In this case, pick the first one and be done with it.
    808 	 */
    809 	if (fp->next == 0 && scr->scr_romfont == NULL) {
    810 		fontindex = 0;
    811 		goto rescan;
    812 	}
    813 
    814 	STI_DISABLE_ROM(rom->rom_softc);
    815 
    816 #ifdef notyet
    817 	/*
    818 	 * If there is enough room in the off-screen framebuffer memory,
    819 	 * display all the characters there in order to display them
    820 	 * faster with blkmv operations rather than unpmv later on.
    821 	 */
    822 	if (size <= cfg->fbheight *
    823 	    (cfg->fbwidth - cfg->width - cfg->owidth)) {
    824 		memset(&a, 0, sizeof(a));
    825 		a.flags.flags = STI_UNPMVF_WAIT;
    826 		a.in.fg_colour = STI_COLOUR_WHITE;
    827 		a.in.bg_colour = STI_COLOUR_BLACK;
    828 		a.in.font_addr = scr->scr_romfont;
    829 
    830 		scr->scr_fontmaxcol = cfg->fbheight / fp->height;
    831 		scr->scr_fontbase = cfg->width + cfg->owidth;
    832 		for (uc = fp->first; uc <= fp->last; uc++) {
    833 			a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
    834 			    fp->width + scr->scr_fontbase;
    835 			a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
    836 			    fp->height;
    837 			a.in.index = uc;
    838 
    839 			(*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    840 			if (a.out.errno) {
    841 				aprint_error_dev(sc->sc_dev, "unpmv %d "
    842 				    "returned %d\n", uc, a.out.errno);
    843 				return 0;
    844 			}
    845 		}
    846 
    847 		free(scr->scr_romfont, M_DEVBUF);
    848 		scr->scr_romfont = NULL;
    849 	}
    850 #endif
    851 
    852 	return 0;
    853 }
    854 
    855 /*
    856  * Wrappers around STI code pointers
    857  */
    858 int
    859 sti_init(struct sti_screen *scr, int mode)
    860 {
    861 	struct sti_rom *rom = scr->scr_rom;
    862 	struct {
    863 		struct sti_initflags flags;
    864 		struct sti_initin in;
    865 		struct sti_einitin ein;
    866 		struct sti_initout out;
    867 	} a;
    868 
    869 	KASSERT(rom != NULL);
    870 	memset(&a, 0, sizeof(a));
    871 
    872 	a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
    873 	    (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET |
    874 	     STI_INITF_PBETI | STI_INITF_ICMT : 0) |
    875 	    (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0);
    876 	a.in.text_planes = 1;
    877 	a.in.ext_in = &a.ein;
    878 
    879 	DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
    880 	    device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
    881 	    &a.in, &a.out, &scr->scr_cfg));
    882 
    883 	(*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    884 
    885 	if (a.out.text_planes != a.in.text_planes)
    886 		return -1;	/* not colliding with sti errno values */
    887 	return a.out.errno;
    888 }
    889 
    890 int
    891 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
    892 {
    893 	struct sti_rom *rom = scr->scr_rom;
    894 	struct {
    895 		struct sti_inqconfflags flags;
    896 		struct sti_inqconfin in;
    897 	} a;
    898 
    899 	memset(&a, 0, sizeof(a));
    900 
    901 	a.flags.flags = STI_INQCONFF_WAIT;
    902 	(*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
    903 
    904 	return out->errno;
    905 }
    906 
    907 void
    908 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
    909     enum sti_bmove_funcs f)
    910 {
    911 	struct sti_rom *rom = scr->scr_rom;
    912 	struct {
    913 		struct sti_blkmvflags flags;
    914 		struct sti_blkmvin in;
    915 		struct sti_blkmvout out;
    916 	} a;
    917 
    918 	memset(&a, 0, sizeof(a));
    919 
    920 	a.flags.flags = STI_BLKMVF_WAIT;
    921 	switch (f) {
    922 	case bmf_clear:
    923 		a.flags.flags |= STI_BLKMVF_CLR;
    924 		a.in.bg_colour = STI_COLOUR_BLACK;
    925 		break;
    926 	case bmf_underline:
    927 	case bmf_copy:
    928 		a.in.fg_colour = STI_COLOUR_WHITE;
    929 		a.in.bg_colour = STI_COLOUR_BLACK;
    930 		break;
    931 	case bmf_invert:
    932 		a.flags.flags |= STI_BLKMVF_COLR;
    933 		a.in.fg_colour = STI_COLOUR_BLACK;
    934 		a.in.bg_colour = STI_COLOUR_WHITE;
    935 		break;
    936 	}
    937 	a.in.srcx = x1;
    938 	a.in.srcy = y1;
    939 	a.in.dstx = x2;
    940 	a.in.dsty = y2;
    941 	a.in.height = h;
    942 	a.in.width = w;
    943 
    944 	(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    945 #ifdef STIDEBUG
    946 	if (a.out.errno)
    947 		printf("%s: blkmv returned %d\n",
    948 		    device_xname(rom->rom_softc->sc_dev), a.out.errno);
    949 #endif
    950 }
    951 
    952 int
    953 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
    954 {
    955 	struct sti_rom *rom = scr->scr_rom;
    956 	struct {
    957 		struct sti_scmentflags flags;
    958 		struct sti_scmentin in;
    959 		struct sti_scmentout out;
    960 	} a;
    961 
    962 	memset(&a, 0, sizeof(a));
    963 
    964 	a.flags.flags = STI_SCMENTF_WAIT;
    965 	a.in.entry = i;
    966 	a.in.value = (r << 16) | (g << 8) | b;
    967 
    968 	(*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
    969 
    970 	return a.out.errno;
    971 }
    972 
    973 /*
    974  * wsdisplay accessops
    975  */
    976 int
    977 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    978 {
    979 	struct sti_screen *scr = (struct sti_screen *)v;
    980 	struct sti_rom *rom = scr->scr_rom;
    981 	struct wsdisplay_fbinfo *wdf;
    982 	struct wsdisplay_cmap *cmapp;
    983 	u_int mode, idx, count;
    984 	int i, ret;
    985 
    986 	ret = 0;
    987 	switch (cmd) {
    988 	case WSDISPLAYIO_GMODE:
    989 		*(u_int *)data = scr->scr_wsmode;
    990 		break;
    991 
    992 	case WSDISPLAYIO_SMODE:
    993 		mode = *(u_int *)data;
    994 		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
    995 		    mode == WSDISPLAYIO_MODE_DUMBFB)
    996 			ret = sti_init(scr, 0);
    997 		else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
    998 		    mode == WSDISPLAYIO_MODE_EMUL)
    999 			ret = sti_init(scr, STI_TEXTMODE);
   1000 		scr->scr_wsmode = mode;
   1001 		break;
   1002 
   1003 	case WSDISPLAYIO_GTYPE:
   1004 		*(u_int *)data = WSDISPLAY_TYPE_STI;
   1005 		break;
   1006 
   1007 	case WSDISPLAYIO_GINFO:
   1008 		wdf = (struct wsdisplay_fbinfo *)data;
   1009 		wdf->height = scr->scr_cfg.scr_height;
   1010 		wdf->width  = scr->scr_cfg.scr_width;
   1011 		wdf->depth  = scr->scr_bpp;
   1012 		if (rom->scment == NULL)
   1013 			wdf->cmsize = 0;
   1014 		else
   1015 			wdf->cmsize = STI_NCMAP;
   1016 		break;
   1017 
   1018 	case WSDISPLAYIO_LINEBYTES:
   1019 		*(u_int *)data = scr->scr_cfg.fb_width;
   1020 		break;
   1021 
   1022 	case WSDISPLAYIO_GETCMAP:
   1023 		if (rom->scment == NULL)
   1024 			return ENOTTY;
   1025 		cmapp = (struct wsdisplay_cmap *)data;
   1026 		idx = cmapp->index;
   1027 		count = cmapp->count;
   1028 		if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
   1029 			return EINVAL;
   1030 		if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
   1031 			break;
   1032 		if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
   1033 			break;
   1034 		if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
   1035 			break;
   1036 		break;
   1037 
   1038 	case WSDISPLAYIO_PUTCMAP:
   1039 		if (rom->scment == NULL)
   1040 			return ENOTTY;
   1041 		cmapp = (struct wsdisplay_cmap *)data;
   1042 		idx = cmapp->index;
   1043 		count = cmapp->count;
   1044 		if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
   1045 			return EINVAL;
   1046 		if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
   1047 			break;
   1048 		if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
   1049 			break;
   1050 		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
   1051 			break;
   1052 		for (i = idx + count - 1; i >= idx; i--)
   1053 			if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
   1054 			    scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
   1055 
   1056 				DPRINTF(("sti_ioctl: "
   1057 				    "sti_setcment(%d, %u, %u, %u): %%d\n", i,
   1058 				    (u_int)scr->scr_rcmap[i],
   1059 				    (u_int)scr->scr_gcmap[i],
   1060 				    (u_int)scr->scr_bcmap[i]));
   1061 
   1062 				ret = EINVAL;
   1063 				break;
   1064 			}
   1065 		break;
   1066 
   1067 	case WSDISPLAYIO_SVIDEO:
   1068 	case WSDISPLAYIO_GVIDEO:
   1069 	case WSDISPLAYIO_GCURPOS:
   1070 	case WSDISPLAYIO_SCURPOS:
   1071 	case WSDISPLAYIO_GCURMAX:
   1072 	case WSDISPLAYIO_GCURSOR:
   1073 	case WSDISPLAYIO_SCURSOR:
   1074 	default:
   1075 		return ENOTTY;	/* not supported yet */
   1076 	}
   1077 
   1078 	return ret;
   1079 }
   1080 
   1081 paddr_t
   1082 sti_mmap(void *v, void *vs, off_t offset, int prot)
   1083 {
   1084 #if 0
   1085 	struct sti_screen *scr = (struct sti_screen *)v;
   1086 #endif
   1087 	/* XXX not finished */
   1088 	return -1;
   1089 }
   1090 
   1091 int
   1092 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
   1093     int *cxp, int *cyp, long *defattr)
   1094 {
   1095 	struct sti_screen *scr = (struct sti_screen *)v;
   1096 
   1097 	if (scr->scr_nscreens > 0)
   1098 		return ENOMEM;
   1099 
   1100 	*cookiep = scr;
   1101 	*cxp = 0;
   1102 	*cyp = 0;
   1103 	sti_alloc_attr(scr, 0, 0, 0, defattr);
   1104 	scr->scr_nscreens++;
   1105 
   1106 	return 0;
   1107 }
   1108 
   1109 void
   1110 sti_free_screen(void *v, void *cookie)
   1111 {
   1112 	struct sti_screen *scr = (struct sti_screen *)v;
   1113 
   1114 	scr->scr_nscreens--;
   1115 }
   1116 
   1117 int
   1118 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
   1119     void *cbarg)
   1120 {
   1121 #if 0
   1122 	struct sti_screen *scr = (struct sti_screen *)v;
   1123 #endif
   1124 
   1125 	return 0;
   1126 }
   1127 
   1128 int
   1129 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
   1130 {
   1131 #if 0
   1132 	struct sti_screen *scr = (struct sti_screen *)v;
   1133 #endif
   1134 
   1135 	return -1;
   1136 }
   1137 
   1138 /*
   1139  * wsdisplay emulops
   1140  */
   1141 void
   1142 sti_cursor(void *v, int on, int row, int col)
   1143 {
   1144 	struct sti_screen *scr = (struct sti_screen *)v;
   1145 	struct sti_font *fp = &scr->scr_curfont;
   1146 
   1147 	sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width,
   1148 	    row * fp->height, fp->height, fp->width, bmf_invert);
   1149 }
   1150 
   1151 /*
   1152  * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
   1153  */
   1154 static const uint8_t
   1155 sti_unitoroman[0x100 - 0xa0] = {
   1156 	0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc,    0, 0xbd,
   1157 	0xab,    0, 0xf9, 0xfb,    0, 0xf6,    0, 0xb0,
   1158 
   1159 	0xb3, 0xfe,    0,    0, 0xa8, 0xf3, 0xf4, 0xf2,
   1160 	   0,    0, 0xfa, 0xfd, 0xf7, 0xf8,    0, 0xb9,
   1161 
   1162 	0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
   1163 	0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
   1164 
   1165 	0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda,    0,
   1166 	0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
   1167 
   1168 	0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
   1169 	0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
   1170 
   1171 	0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce,    0,
   1172 	0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
   1173 };
   1174 
   1175 int
   1176 sti_mapchar(void *v, int uni, u_int *index)
   1177 {
   1178 	struct sti_screen *scr = (struct sti_screen *)v;
   1179 	struct sti_font *fp = &scr->scr_curfont;
   1180 	int c;
   1181 
   1182 	switch (fp->type) {
   1183 	case STI_FONT_HPROMAN8:
   1184 		if (uni >= 0x80 && uni < 0xa0)
   1185 			c = -1;
   1186 		else if (uni >= 0xa0 && uni < 0x100) {
   1187 			c = (int)sti_unitoroman[uni - 0xa0];
   1188 			if (c == 0)
   1189 				c = -1;
   1190 		} else
   1191 			c = uni;
   1192 		break;
   1193 	default:
   1194 		c = uni;
   1195 		break;
   1196 	}
   1197 
   1198 	if (c == -1 || c < fp->first || c > fp->last) {
   1199 		*index = ' ';
   1200 		return 0;
   1201 	}
   1202 
   1203 	*index = c;
   1204 	return 5;
   1205 }
   1206 
   1207 void
   1208 sti_putchar(void *v, int row, int col, u_int uc, long attr)
   1209 {
   1210 	struct sti_screen *scr = (struct sti_screen *)v;
   1211 	struct sti_rom *rom = scr->scr_rom;
   1212 	struct sti_font *fp = &scr->scr_curfont;
   1213 
   1214 	if (scr->scr_romfont != NULL) {
   1215 		/*
   1216 		 * Font is in memory, use unpmv
   1217 		 */
   1218 		struct {
   1219 			struct sti_unpmvflags flags;
   1220 			struct sti_unpmvin in;
   1221 			struct sti_unpmvout out;
   1222 		} a;
   1223 
   1224 		memset(&a, 0, sizeof(a));
   1225 
   1226 		a.flags.flags = STI_UNPMVF_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 		a.in.x = col * fp->width;
   1231 		a.in.y = row * fp->height;
   1232 		a.in.font_addr = scr->scr_romfont;
   1233 		a.in.index = uc;
   1234 
   1235 		(*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1236 	} else {
   1237 		/*
   1238 		 * Font is in frame buffer, use blkmv
   1239 		 */
   1240 		struct {
   1241 			struct sti_blkmvflags flags;
   1242 			struct sti_blkmvin in;
   1243 			struct sti_blkmvout out;
   1244 		} a;
   1245 
   1246 		memset(&a, 0, sizeof(a));
   1247 
   1248 		a.flags.flags = STI_BLKMVF_WAIT;
   1249 		/* XXX does not handle text attributes */
   1250 		a.in.fg_colour = STI_COLOUR_WHITE;
   1251 		a.in.bg_colour = STI_COLOUR_BLACK;
   1252 
   1253 		a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
   1254 		    fp->width + scr->scr_fontbase;
   1255 		a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
   1256 		    fp->height;
   1257 		a.in.dstx = col * fp->width;
   1258 		a.in.dsty = row * fp->height;
   1259 		a.in.height = fp->height;
   1260 		a.in.width = fp->width;
   1261 
   1262 		(*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
   1263 	}
   1264 }
   1265 
   1266 void
   1267 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
   1268 {
   1269 	struct sti_screen *scr = (struct sti_screen *)v;
   1270 	struct sti_font *fp = &scr->scr_curfont;
   1271 
   1272 	sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width,
   1273 	    row * fp->height, fp->height, ncols * fp->width, bmf_copy);
   1274 }
   1275 
   1276 void
   1277 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
   1278 {
   1279 	struct sti_screen *scr = (struct sti_screen *)v;
   1280 	struct sti_font *fp = &scr->scr_curfont;
   1281 
   1282 	sti_bmove(scr, startcol * fp->width, row * fp->height,
   1283 	    startcol * fp->width, row * fp->height, fp->height,
   1284 	    ncols * fp->width, bmf_clear);
   1285 }
   1286 
   1287 void
   1288 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
   1289 {
   1290 	struct sti_screen *scr = (struct sti_screen *)v;
   1291 	struct sti_font *fp = &scr->scr_curfont;
   1292 
   1293 	sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
   1294 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
   1295 }
   1296 
   1297 void
   1298 sti_eraserows(void *v, int srcrow, int nrows, long attr)
   1299 {
   1300 	struct sti_screen *scr = (struct sti_screen *)v;
   1301 	struct sti_font *fp = &scr->scr_curfont;
   1302 
   1303 	sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
   1304 	    nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
   1305 }
   1306 
   1307 int
   1308 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
   1309 {
   1310 #if 0
   1311 	struct sti_screen *scr = (struct sti_screen *)v;
   1312 #endif
   1313 
   1314 	*pattr = 0;
   1315 
   1316 	return 0;
   1317 }
   1318