Home | History | Annotate | Line # | Download | only in tc
stic.c revision 1.4
      1 /*	$NetBSD: stic.c,v 1.4 2000/12/17 13:52:04 ad Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Andrew Doran.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Copyright (c) 1998, 1999 Tohru Nishimura.  All rights reserved.
     41  *
     42  * Redistribution and use in source and binary forms, with or without
     43  * modification, are permitted provided that the following conditions
     44  * are met:
     45  * 1. Redistributions of source code must retain the above copyright
     46  *    notice, this list of conditions and the following disclaimer.
     47  * 2. Redistributions in binary form must reproduce the above copyright
     48  *    notice, this list of conditions and the following disclaimer in the
     49  *    documentation and/or other materials provided with the distribution.
     50  * 3. All advertising materials mentioning features or use of this software
     51  *    must display the following acknowledgement:
     52  *      This product includes software developed by Tohru Nishimura
     53  *	for the NetBSD Project.
     54  * 4. The name of the author may not be used to endorse or promote products
     55  *    derived from this software without specific prior written permission
     56  *
     57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     60  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     62  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     63  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     64  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     66  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     67  */
     68 
     69 /*
     70  * Driver for the DEC PixelStamp interface chip (STIC).
     71  *
     72  * XXX The bt459 interface shouldn't be replicated here.
     73  */
     74 
     75 #include <sys/param.h>
     76 #include <sys/systm.h>
     77 #include <sys/kernel.h>
     78 #include <sys/device.h>
     79 #include <sys/malloc.h>
     80 #include <sys/buf.h>
     81 #include <sys/ioctl.h>
     82 #include <sys/callout.h>
     83 
     84 #include <uvm/uvm_extern.h>
     85 
     86 #if defined(pmax)
     87 #include <mips/cpuregs.h>
     88 #elif defined(alpha)
     89 #include <alpha/alpha_cpu.h>
     90 #endif
     91 
     92 #include <machine/bus.h>
     93 #include <machine/intr.h>
     94 
     95 #include <dev/wscons/wsconsio.h>
     96 #include <dev/wscons/wsdisplayvar.h>
     97 
     98 #include <dev/wsfont/wsfont.h>
     99 
    100 #include <dev/ic/bt459reg.h>
    101 
    102 #include <dev/tc/tcvar.h>
    103 #include <dev/tc/sticreg.h>
    104 #include <dev/tc/sticvar.h>
    105 
    106 #define DUPBYTE0(x) ((((x)&0xff)<<16) | (((x)&0xff)<<8) | ((x)&0xff))
    107 #define DUPBYTE1(x) ((((x)<<8)&0xff0000) | ((x)&0xff00) | (((x)>>8)&0xff))
    108 #define DUPBYTE2(x) (((x)&0xff0000) | (((x)>>8)&0xff00) | (((x)>>16)&0xff))
    109 
    110 #define PACK(p, o) ((p)[(o)] | ((p)[(o)+1] << 16))
    111 
    112 #if defined(pmax)
    113 #define	machine_btop(x)		mips_btop(x)
    114 #elif defined(alpha)
    115 #define machine_btop(x)		alpha_btop(x)
    116 #endif
    117 
    118 /*
    119  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
    120  * obscure register layout such as 2nd and 3rd Bt459 registers are
    121  * adjacent each other in a word, i.e.,
    122  *	struct bt459triplet {
    123  * 		struct {
    124  *			u_int8_t u0;
    125  *			u_int8_t u1;
    126  *			u_int8_t u2;
    127  *			unsigned :8;
    128  *		} bt_lo;
    129  *		struct {
    130  *
    131  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
    132  *	struct bt459reg {
    133  *		   u_int32_t	   bt_lo;
    134  *		   u_int32_t	   bt_hi;
    135  *		   u_int32_t	   bt_reg;
    136  *		   u_int32_t	   bt_cmap;
    137  *	};
    138  *
    139  */
    140 
    141 /* Bt459 hardware registers */
    142 #define bt_lo	0
    143 #define bt_hi	1
    144 #define bt_reg	2
    145 #define bt_cmap 3
    146 
    147 #define REG(base, index)	*((u_int32_t *)(base) + (index))
    148 #define SELECT(vdac, regno) do {		\
    149 	REG(vdac, bt_lo) = DUPBYTE0(regno);	\
    150 	REG(vdac, bt_hi) = DUPBYTE1(regno);	\
    151 	tc_wmb();				\
    152    } while (0)
    153 
    154 static int sticioctl(void *, u_long, caddr_t, int, struct proc *);
    155 static paddr_t sticmmap(void *, off_t, int);
    156 static int stic_alloc_screen(void *, const struct wsscreen_descr *,
    157 			     void **, int *, int *, long *);
    158 static void stic_free_screen(void *, void *);
    159 static int stic_show_screen(void *, void *, int,
    160 			    void (*) (void *, int, int), void *);
    161 static void stic_do_switch(void *);
    162 static int stic_setup_backing(struct stic_info *, struct stic_screen *, int);
    163 static void stic_setup_cmap(struct stic_screen *);
    164 static void stic_setup_cursor(struct stic_info *, struct stic_screen *);
    165 
    166 static int stic_get_cmap(struct stic_screen *, struct wsdisplay_cmap *);
    167 static int stic_set_cmap(struct stic_screen *, struct wsdisplay_cmap *);
    168 static int stic_set_cursor(struct stic_screen *, struct wsdisplay_cursor *);
    169 static int stic_get_cursor(struct stic_screen *, struct wsdisplay_cursor *);
    170 static void stic_set_curpos(struct stic_screen *, struct wsdisplay_curpos *);
    171 static void stic_set_hwcurpos(struct stic_screen *);
    172 
    173 static void stic_cursor(void *, int, int, int);
    174 static void stic_copycols(void *, int, int, int, int);
    175 static void stic_copyrows(void *, int, int, int);
    176 static void stic_erasecols(void *, int, int, int, long);
    177 static void stic_eraserows(void *, int, int, long);
    178 static int stic_mapchar(void *, int, u_int *);
    179 static void stic_putchar(void *, int, int, u_int, long);
    180 static int stic_alloc_attr(void *, int, int, int, long *);
    181 
    182 /* Colormap for wscons, matching WSCOL_*. Upper 8 are high-intensity. */
    183 static const u_int8_t stic_cmap[16*3] = {
    184 	0x00, 0x00, 0x00, /* black */
    185 	0x7f, 0x00, 0x00, /* red */
    186 	0x00, 0x7f, 0x00, /* green */
    187 	0x7f, 0x7f, 0x00, /* brown */
    188 	0x00, 0x00, 0x7f, /* blue */
    189 	0x7f, 0x00, 0x7f, /* magenta */
    190 	0x00, 0x7f, 0x7f, /* cyan */
    191 	0xc7, 0xc7, 0xc7, /* white */
    192 
    193 	0x7f, 0x7f, 0x7f, /* black */
    194 	0xff, 0x00, 0x00, /* red */
    195 	0x00, 0xff, 0x00, /* green */
    196 	0xff, 0xff, 0x00, /* brown */
    197 	0x00, 0x00, 0xff, /* blue */
    198 	0xff, 0x00, 0xff, /* magenta */
    199 	0x00, 0xff, 0xff, /* cyan */
    200 	0xff, 0xff, 0xff, /* white */
    201 };
    202 
    203 /*
    204  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    205  *   M M M M I I I I		M I M I M I M I
    206  *	[ before ]		   [ after ]
    207  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    208  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    209  */
    210 static const u_int8_t shuffle[256] = {
    211 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    212 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    213 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    214 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    215 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    216 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    217 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    218 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    219 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    220 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    221 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    222 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    223 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    224 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    225 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    226 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    227 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    228 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    229 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    230 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    231 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    232 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    233 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    234 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    235 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    236 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    237 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    238 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    239 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    240 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    241 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    242 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    243 };
    244 
    245 static const struct wsdisplay_accessops stic_accessops = {
    246 	sticioctl,
    247 	sticmmap,
    248 	stic_alloc_screen,
    249 	stic_free_screen,
    250 	stic_show_screen,
    251 	0 /* load_font */
    252 };
    253 
    254 static const struct wsdisplay_emulops stic_emulops = {
    255 	stic_cursor,
    256 	stic_mapchar,
    257 	stic_putchar,
    258 	stic_copycols,
    259 	stic_erasecols,
    260 	stic_copyrows,
    261 	stic_eraserows,
    262 	stic_alloc_attr
    263 };
    264 
    265 static struct wsscreen_descr stic_stdscreen = {
    266 	"std",
    267 	0, 0,
    268 	&stic_emulops,
    269 	0, 0,
    270 	WSATTR_REVERSE | WSATTR_HILIT | WSATTR_WSCOLORS
    271 };
    272 
    273 static const struct wsscreen_descr *_stic_scrlist[] = {
    274 	&stic_stdscreen,
    275 };
    276 
    277 static const struct wsscreen_list stic_screenlist = {
    278 	sizeof(_stic_scrlist) / sizeof(struct wsscreen_descr *), _stic_scrlist
    279 };
    280 
    281 struct	stic_info stic_consinfo;
    282 static struct	stic_screen stic_consscr;
    283 
    284 void
    285 stic_init(struct stic_info *si)
    286 {
    287 	volatile u_int32_t *vdac;
    288 	int i, cookie;
    289 
    290 	/* Reset the STIC & stamp(s). */
    291 	stic_reset(si);
    292 	vdac = si->si_vdac;
    293 
    294 	/* Hit it... */
    295 	SELECT(vdac, BT459_IREG_COMMAND_0);
    296 	REG(vdac, bt_reg) = 0x00c0c0c0; tc_syncbus();
    297 
    298 	/* Now reset the VDAC. */
    299 	*si->si_vdac_reset = 0;
    300 	tc_syncbus();
    301 	DELAY(1000);
    302 
    303 	/* Finish the initalization. */
    304 	SELECT(vdac, BT459_IREG_COMMAND_1);
    305 	REG(vdac, bt_reg) = 0x00000000; tc_wmb();
    306 	REG(vdac, bt_reg) = 0x00c2c2c2; tc_wmb();
    307 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    308 
    309 	for (i = 0; i < 7; i++) {
    310 		REG(vdac, bt_reg) = 0x00000000;
    311 		tc_wmb();
    312 	}
    313 
    314 	/* Set cursor colormap. */
    315 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    316 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    317 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    318 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    319 	REG(vdac, bt_reg) = 0x00000000; tc_wmb();
    320 	REG(vdac, bt_reg) = 0x00000000; tc_wmb();
    321 	REG(vdac, bt_reg) = 0x00000000; tc_wmb();
    322 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    323 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    324 	REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
    325 
    326 	si->si_vdacctl = STIC_VDAC_BLINK;
    327 
    328 	/* Get a font and set up screen metrics. */
    329 	wsfont_init();
    330 	cookie = wsfont_find(NULL, 0, 0, 0);
    331 
    332 	if (wsfont_lock(cookie, &si->si_font,
    333 	    WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0)
    334 		panic("stic_init: couldn't lock font\n");
    335 
    336 	si->si_fonth = si->si_font->fontheight;
    337 	si->si_fontw = si->si_font->fontwidth;
    338 	si->si_consh = 1024 / si->si_fonth;
    339 	si->si_consw = (1280 / si->si_fontw) & ~1;
    340 	stic_stdscreen.nrows = si->si_consh;
    341 	stic_stdscreen.ncols = si->si_consw;
    342 
    343 #ifdef DIAGNOSTIC
    344 	if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16)
    345 		panic("stic_init: unusable font");
    346 #endif
    347 }
    348 
    349 void
    350 stic_reset(struct stic_info *si)
    351 {
    352 	int modtype, xconfig, yconfig, config;
    353 	volatile struct stic_regs *sr;
    354 
    355 	sr = si->si_stic;
    356 
    357 	/*
    358 	 * Initialize the interface chip registers.
    359 	 */
    360 	sr->sr_sticsr = 0x00000030;	/* Get the STIC's attention. */
    361 	tc_syncbus();
    362 	DELAY(4000);			/* wait 4ms for STIC to respond. */
    363 	sr->sr_sticsr = 0x00000000;	/* Hit the STIC's csr again... */
    364 	tc_syncbus();
    365 	sr->sr_buscsr = 0xffffffff;	/* and bash its bus-acess csr. */
    366 	tc_syncbus();			/* Blam! */
    367 	DELAY(20000);			/* wait until the stic recovers... */
    368 
    369 	modtype = sr->sr_modcl;
    370 	xconfig = (modtype & 0x800) >> 11;
    371 	yconfig = (modtype & 0x600) >> 9;
    372 	config = (yconfig << 1) | xconfig;
    373 	si->si_stampw = (xconfig ? 5 : 4);
    374 	si->si_stamph = (1 << yconfig);
    375 #ifdef notyet
    376 	si->si_option = (char)((modtype >> 12) & 3);
    377 #endif
    378 
    379 	/* First PixelStamp */
    380 	si->si_stamp[0x000b0] = config;
    381 	si->si_stamp[0x000b4] = 0x0;
    382 
    383 	/* Second PixelStamp */
    384 	if (yconfig > 0) {
    385 		si->si_stamp[0x100b0] = config | 8;
    386 		si->si_stamp[0x100b4] = 0;
    387 	}
    388 
    389 	/*
    390 	 * Initialize STIC video registers.
    391 	 */
    392 	sr->sr_vblank = (1024 << 16) | 1063;
    393 	sr->sr_vsync = (1027 << 16) | 1030;
    394 	sr->sr_hblank = (255 << 16) | 340;
    395 	sr->sr_hsync2 = 245;
    396 	sr->sr_hsync = (261 << 16) | 293;
    397 	sr->sr_ipdvint = STIC_INT_CLR | STIC_INT_WE;
    398 	sr->sr_sticsr = 8;
    399 	tc_wmb();
    400 }
    401 
    402 void
    403 stic_attach(struct device *self, struct stic_info *si, int console)
    404 {
    405 	struct wsemuldisplaydev_attach_args waa;
    406 
    407 	callout_init(&si->si_switch_callout);
    408 
    409 	/*
    410 	 * Allocate backing for the console.  We could trawl back through
    411 	 * msgbuf and and fill the backing, but it's not worth the hassle.
    412 	 * We could also grab backing using pmap_steal_memory() early on,
    413 	 * but that's a little ugly.
    414 	 */
    415 	if (console)
    416 		stic_setup_backing(si, &stic_consscr, M_NOWAIT);
    417 
    418 	waa.console = console;
    419 	waa.scrdata = &stic_screenlist;
    420 	waa.accessops = &stic_accessops;
    421 	waa.accesscookie = si;
    422 	config_found(self, &waa, wsemuldisplaydevprint);
    423 }
    424 
    425 void
    426 stic_cnattach(struct stic_info *si)
    427 {
    428 	struct stic_screen *ss;
    429 	long defattr;
    430 	int i;
    431 
    432 	ss = &stic_consscr;
    433 	si->si_curscreen = ss;
    434 	ss->ss_flags = SS_ALLOCED | SS_ACTIVE | SS_CURENB | SS_CURENB_CHANGED;
    435 	ss->ss_si = si;
    436 
    437 	stic_setup_cursor(si, ss);
    438 	stic_setup_cmap(ss);
    439 	stic_flush(si);
    440 	stic_eraserows(ss, 0, si->si_consh, 0);
    441 
    442 	stic_alloc_attr(ss, 0, 0, 0, &defattr);
    443 	wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr);
    444 }
    445 
    446 static void
    447 stic_setup_cursor(struct stic_info *si, struct stic_screen *ss)
    448 {
    449 	u_int8_t *ip, *mp;
    450 	int r, c, o, b;
    451 
    452 	ip = (u_int8_t *)ss->ss_cursor.cc_image;
    453 	mp = ip + (sizeof(ss->ss_cursor.cc_image) >> 1);
    454 	memset(ip, 0, sizeof(ss->ss_cursor.cc_image));
    455 
    456 	for (r = 0; r < si->si_fonth; r++) {
    457 		for (c = 0; c < si->si_fontw; c++) {
    458 			o = c >> 3;
    459 			b = 1 << (c & 7);
    460 			ip[o] |= b;
    461 			mp[o] |= b;
    462 		}
    463 
    464 		ip += 16;
    465 		mp += 16;
    466 	}
    467 
    468 	ss->ss_cursor.cc_size.x = 64;
    469 	ss->ss_cursor.cc_size.y = si->si_fonth;
    470 	ss->ss_cursor.cc_hot.x = 0;
    471 	ss->ss_cursor.cc_hot.y = 0;
    472 
    473 	ss->ss_cursor.cc_color[0] = 0xff;
    474 	ss->ss_cursor.cc_color[2] = 0xff;
    475 	ss->ss_cursor.cc_color[4] = 0xff;
    476 	ss->ss_cursor.cc_color[1] = 0x00;
    477 	ss->ss_cursor.cc_color[3] = 0x00;
    478 	ss->ss_cursor.cc_color[5] = 0x00;
    479 
    480 	ss->ss_flags |= SS_CURSHAPE_CHANGED | SS_CURCMAP_CHANGED;
    481 }
    482 
    483 static int
    484 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    485 {
    486 	struct stic_info *si;
    487 	struct stic_screen *ss;
    488 	struct stic_xinfo *sxi;
    489 
    490 	ss = (struct stic_screen *)v;
    491 	si = ss->ss_si;
    492 
    493 	switch (cmd) {
    494 	case WSDISPLAYIO_GTYPE:
    495 		*(u_int *)data = si->si_disptype;
    496 		return (0);
    497 
    498 	case WSDISPLAYIO_GINFO:
    499 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    500 		wsd_fbip->height = 1024;
    501 		wsd_fbip->width = 1280;
    502 		wsd_fbip->depth = si->si_depth;
    503 		wsd_fbip->cmsize = CMAP_SIZE;
    504 #undef fbt
    505 		return (0);
    506 
    507 	case WSDISPLAYIO_GETCMAP:
    508 		return (stic_get_cmap(ss, (struct wsdisplay_cmap *)data));
    509 
    510 	case WSDISPLAYIO_PUTCMAP:
    511 		return (stic_set_cmap(ss, (struct wsdisplay_cmap *)data));
    512 
    513 	case WSDISPLAYIO_SVIDEO:
    514 #if 0 /* XXX later */
    515 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    516 		if ((si->si_blanked == 0) ^ turnoff)
    517 			si->si_blanked = turnoff;
    518 #endif
    519 		return (0);
    520 
    521 	case WSDISPLAYIO_GVIDEO:
    522 #if 0 /* XXX later */
    523 		*(u_int *)data = si->si_blanked ?
    524 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    525 #endif
    526 		return (0);
    527 
    528 	case WSDISPLAYIO_GCURPOS:
    529 		*(struct wsdisplay_curpos *)data = ss->ss_cursor.cc_pos;
    530 		return (0);
    531 
    532 	case WSDISPLAYIO_SCURPOS:
    533 		stic_set_curpos(ss, (struct wsdisplay_curpos *)data);
    534 		stic_set_hwcurpos(ss);
    535 		return (0);
    536 
    537 	case WSDISPLAYIO_GCURMAX:
    538 		((struct wsdisplay_curpos *)data)->x =
    539 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    540 		return (0);
    541 
    542 	case WSDISPLAYIO_GCURSOR:
    543 		return (stic_get_cursor(ss, (struct wsdisplay_cursor *)data));
    544 
    545 	case WSDISPLAYIO_SCURSOR:
    546 		return (stic_set_cursor(ss, (struct wsdisplay_cursor *)data));
    547 
    548 	case STICIO_GXINFO:
    549 		sxi = (struct stic_xinfo *)data;
    550 		sxi->sxi_stampw = si->si_stampw;
    551 		sxi->sxi_stamph = si->si_stamph;
    552 		sxi->sxi_buf_size = si->si_buf_size;
    553 		sxi->sxi_buf_phys = (u_long)si->si_buf_phys;
    554 		break;
    555 
    556 	case STICIO_SBLINK:
    557 		if ((int *)data != 0)
    558 			si->si_vdacctl |= STIC_VDAC_BLINK;
    559 		else
    560 			si->si_vdacctl &= ~STIC_VDAC_BLINK;
    561 		break;
    562 
    563 	case STICIO_S24BIT:
    564 		if ((int *)data != 0)
    565 			si->si_vdacctl |= STIC_VDAC_24BIT;
    566 		else
    567 			si->si_vdacctl &= ~STIC_VDAC_24BIT;
    568 		break;
    569 	}
    570 
    571 	return (ENOTTY);
    572 }
    573 
    574 static paddr_t
    575 sticmmap(void *v, off_t offset, int prot)
    576 {
    577 	struct stic_softc *sc;
    578 	struct stic_xmap sxm;
    579 	paddr_t pa;
    580 
    581 	sc = v;
    582 
    583 	if (offset < 0)
    584 		return ((paddr_t)-1L);
    585 
    586 	if (offset < sizeof(sxm.sxm_stic)) {
    587 		pa = STIC_KSEG_TO_PHYS(si->si_stic);
    588 		return (machine_btop(pa + pffset));
    589 	}
    590 	offset -= sizeof(sxm.sxm_stic);
    591 
    592 	if (offset < sizeof(sxm.sxm_poll)) {
    593 		pa = STIC_KSEG_TO_PHYS(si->si_slotkva);
    594 		return (machine_btop(pa + pffset));
    595 	}
    596 	offset -= sizeof(sxm.sxm_slotkva);
    597 
    598 	if (offset < si->si_buf_size) {
    599 		pa = STIC_KSEG_TO_PHYS(si->si_buf_phys);
    600 		return (machine_btop(pa + pffset));
    601 	}
    602 
    603 	return ((paddr_t)-1L);
    604 }
    605 
    606 static int
    607 stic_setup_backing(struct stic_info *si, struct stic_screen *ss, int mflag)
    608 {
    609 	int size;
    610 
    611 	size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing);
    612 	if ((ss->ss_backing = malloc(size, M_DEVBUF, mflag)) == NULL) {
    613 		free(ss, M_DEVBUF);
    614 		return (ENOMEM);
    615 	}
    616 	memset(ss->ss_backing, 0, size);
    617 	return (0);
    618 }
    619 
    620 static void
    621 stic_setup_cmap(struct stic_screen *ss)
    622 {
    623 	int i;
    624 
    625 	memset(&ss->ss_cmap, 0, sizeof(ss->ss_cmap));
    626 	for (i = 0; i < 16; i++) {
    627 		ss->ss_cmap.r[i] = stic_cmap[i*3 + 0];
    628 		ss->ss_cmap.g[i] = stic_cmap[i*3 + 1];
    629 		ss->ss_cmap.b[i] = stic_cmap[i*3 + 2];
    630 	}
    631 
    632 	ss->ss_flags |= SS_CMAP_CHANGED;
    633 }
    634 
    635 static int
    636 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    637 		  int *curxp, int *curyp, long *attrp)
    638 {
    639 	struct stic_info *si;
    640 	struct stic_screen *ss;
    641 	int i;
    642 
    643 	si = (struct stic_info *)v;
    644 
    645 	if ((stic_consscr.ss_flags & SS_ALLOCED) == 0) {
    646 		ss = &stic_consscr;
    647 
    648 		if (stic_setup_backing(si, ss, M_WAITOK) != 0)
    649 			return (ENOMEM);
    650 	} else {
    651 		if ((ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK)) == NULL)
    652 			return (ENOMEM);
    653 		memset(ss, 0, sizeof(*ss));
    654 
    655 		if (stic_setup_backing(si, ss, M_WAITOK) != 0) {
    656 			free(ss, M_DEVBUF);
    657 			return (ENOMEM);
    658 		}
    659 	}
    660 
    661 	ss->ss_si = si;
    662 	ss->ss_flags |= SS_ALLOCED | SS_CURENB;
    663 
    664 	*cookiep = ss;
    665 	*curxp = 0;
    666 	*curyp = 0;
    667 
    668 	stic_alloc_attr(ss, 0, 0, 0, attrp);
    669 	stic_setup_cursor(si, ss);
    670 	stic_setup_cmap(ss);
    671 
    672 	return (0);
    673 }
    674 
    675 static void
    676 stic_free_screen(void *v, void *cookie)
    677 {
    678 	struct stic_screen *ss;
    679 
    680 	ss = cookie;
    681 
    682 #ifdef DIAGNOSTIC
    683 	if (ss == &stic_consscr)
    684 		panic("stic_free_screen: console");
    685 	if (ss == ((struct stic_info *)v)->si_curscreen)
    686 		panic("stic_free_screen: freeing current screen");
    687 #endif
    688 
    689 	free(ss->ss_backing, M_DEVBUF);
    690 	free(ss, M_DEVBUF);
    691 }
    692 
    693 static int
    694 stic_show_screen(void *v, void *cookie, int waitok,
    695 		 void (*cb)(void *, int, int), void *cbarg)
    696 {
    697 	struct stic_info *si;
    698 
    699 	si = (struct stic_info *)v;
    700 	if (si->si_switchcbarg != NULL)
    701 		return (EAGAIN);
    702 	si->si_switchcb = cb;
    703 	si->si_switchcbarg = cbarg;
    704 
    705 	if (cb != NULL) {
    706 		callout_reset(&si->si_switch_callout, 0, stic_do_switch,
    707 		    cookie);
    708 		return (EAGAIN);
    709 	}
    710 
    711 	stic_do_switch(cookie);
    712 	return (0);
    713 }
    714 
    715 static void
    716 stic_do_switch(void *cookie)
    717 {
    718 	struct stic_screen *ss;
    719 	struct stic_info *si;
    720 	u_int r, c, nr, nc;
    721 	u_int16_t *p, *sp;
    722 
    723 	ss = cookie;
    724 	si = ss->ss_si;
    725 
    726 	if (ss == si->si_curscreen) {
    727 		si->si_switchcbarg = NULL;
    728 		return;
    729 	}
    730 
    731 #ifdef DIAGNOSTIC
    732 	if (ss->ss_backing == NULL)
    733 		panic("stic_do_switch: screen not backed");
    734 #endif
    735 
    736 	/* Swap in the new screen, and temporarily disable its backing. */
    737 	si->si_curscreen->ss_flags ^= SS_ACTIVE;
    738 	si->si_curscreen = ss;
    739 	ss->ss_flags |= SS_ACTIVE;
    740 	sp = ss->ss_backing;
    741 	ss->ss_backing = NULL;
    742 
    743 	/*
    744 	 * We assume that most of the screen is blank and blast it with
    745 	 * eraserows(), because eraserows() is cheap.
    746 	 */
    747 	nr = si->si_consh;
    748 	stic_eraserows(ss, 0, nr, 0);
    749 
    750 	nc = si->si_consw;
    751 	p = sp;
    752 	for (r = 0; r < nr; r++)
    753 		for (c = 0; c < nc; c += 2, p += 2) {
    754 			if ((p[0] & 0xfff0) != 0)
    755 				stic_putchar(ss, r, c, p[0] >> 8,
    756 				    p[0] & 0x00ff);
    757 			if ((p[1] & 0xfff0) != 0)
    758 				stic_putchar(ss, r, c, p[1] >> 8,
    759 				    p[1] & 0x00ff);
    760 		}
    761 
    762 	/* Re-enable the screen's backing and flush out the new VDAC state. */
    763 	ss->ss_backing = sp;
    764 	ss->ss_flags |= SS_ALL_CHANGED;
    765 	stic_flush(si);
    766 
    767 	/* Move the cursor to the correct spot. */
    768 	stic_set_hwcurpos(ss);
    769 
    770 	/* Tell wscons that we're done. */
    771 	if (si->si_switchcbarg != NULL) {
    772 		cookie = si->si_switchcbarg;
    773 		si->si_switchcbarg = NULL;
    774 		(*si->si_switchcb)(cookie, 0, 0);
    775 	}
    776 }
    777 
    778 static int
    779 stic_alloc_attr(void *cookie, int fg, int bg, int flags, long *attr)
    780 {
    781 	long tmp;
    782 	int swap;
    783 
    784 	if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
    785 		return (EINVAL);
    786 
    787 	if ((flags & WSATTR_HILIT) != 0)
    788 		fg += 8;
    789 
    790 	if ((flags & WSATTR_REVERSE) != 0) {
    791 		swap = fg;
    792 		fg = bg;
    793 		bg = swap;
    794 	}
    795 
    796 	tmp = fg | (bg << 4);
    797 	*attr = tmp | (tmp << 16);
    798 	return (0);
    799 }
    800 
    801 static void
    802 stic_erasecols(void *cookie, int row, int col, int num, long attr)
    803 {
    804 	struct stic_info *si;
    805 	struct stic_screen *ss;
    806 	u_int32_t *pb;
    807 	u_int i, linewidth;
    808 	u_int16_t *p;
    809 
    810 	ss = cookie;
    811 	si = ss->ss_si;
    812 
    813 	if (ss->ss_backing != NULL) {
    814 		p = ss->ss_backing + row * si->si_consw + col;
    815 		for (i = num; i != 0; i--)
    816 			*p++ = (u_int16_t)attr;
    817 	}
    818 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    819 		return;
    820 
    821 	si = (struct stic_info *)cookie;
    822 	col = (col * si->si_fontw) << 19;
    823 	num = (num * si->si_fontw) << 19;
    824 	row = row * si->si_fonth;
    825 	attr = (attr & 0xf0) >> 4;
    826 
    827 	pb = (*si->si_pbuf_get)(si);
    828 
    829 	linewidth = (si->si_fonth << 2) - 1;
    830 	row = (row << 3) + linewidth;
    831 
    832 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
    833 	pb[1] = 0x01ffffff;
    834 	pb[2] = 0;
    835 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
    836 	pb[4] = linewidth;
    837 	pb[5] = DUPBYTE0(attr);
    838 	pb[6] = col | row;
    839 	pb[7] = (col + num) | row;
    840 
    841 	(*si->si_pbuf_post)(si, pb);
    842 }
    843 
    844 static void
    845 stic_eraserows(void *cookie, int row, int num, long attr)
    846 {
    847 	struct stic_info *si;
    848 	struct stic_screen *ss;
    849 	u_int linewidth, i;
    850 	u_int32_t *pb;
    851 
    852 	ss = cookie;
    853 	si = ss->ss_si;
    854 
    855 	if (ss->ss_backing != NULL) {
    856 		pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
    857 		for (i = si->si_consw * num; i != 0; i -= 2)
    858 			*pb++ = (u_int32_t)attr;
    859 	}
    860 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    861 		return;
    862 
    863 	row *= si->si_fonth;
    864 	num *= si->si_fonth;
    865 	attr = (attr & 0xf0) >> 4;
    866 
    867 	pb = (*si->si_pbuf_get)(si);
    868 
    869 	linewidth = (num << 2) - 1;
    870 	row = (row << 3) + linewidth;
    871 
    872 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
    873 	pb[1] = 0x01ffffff;
    874 	pb[2] = 0;
    875 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
    876 	pb[4] = linewidth;
    877 	pb[5] = DUPBYTE0(attr);
    878 	pb[6] = row;
    879 	pb[7] = (1280 << 19) | row;
    880 
    881 	(*si->si_pbuf_post)(si, pb);
    882 }
    883 
    884 static void
    885 stic_copyrows(void *cookie, int src, int dst, int height)
    886 {
    887 	struct stic_info *si;
    888 	struct stic_screen *ss;
    889 	u_int32_t *pb, *pbs;
    890 	u_int num, inc, adj;
    891 
    892 	ss = cookie;
    893 	si = ss->ss_si;
    894 
    895 	if (ss->ss_backing != NULL)
    896 		bcopy(ss->ss_backing + src * si->si_consw,
    897 		    ss->ss_backing + dst * si->si_consw,
    898 		    si->si_consw * sizeof(*ss->ss_backing) * height);
    899 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    900 		return;
    901 
    902 	/*
    903 	 * We need to do this in reverse if the destination row is below
    904 	 * the source.
    905 	 */
    906 	if (dst > src) {
    907 		src += height;
    908 		dst += height;
    909 		inc = -8;
    910 		adj = -1;
    911 	} else {
    912 		inc = 8;
    913 		adj = 0;
    914 	}
    915 
    916 	src = (src * si->si_fonth + adj) << 3;
    917 	dst = (dst * si->si_fonth + adj) << 3;
    918 	height *= si->si_fonth;
    919 
    920 	while (height > 0) {
    921 		num = (height < 255 ? height : 255);
    922 		height -= num;
    923 
    924 		pbs = (*si->si_pbuf_get)(si);
    925 		pb = pbs;
    926 
    927 		pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
    928 		pb[1] = (num << 24) | 0xffffff;
    929 		pb[2] = 0x0;
    930 		pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN |
    931 		    STAMP_COPYSPAN_ALIGNED;
    932 		pb[4] = 1; /* linewidth */
    933 
    934 		for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
    935 			pb[5] = 1280 << 3;
    936 			pb[6] = src;
    937 			pb[7] = dst;
    938 		}
    939 
    940 	    	(*si->si_pbuf_post)(si, pbs);
    941 	}
    942 }
    943 
    944 static void
    945 stic_copycols(void *cookie, int row, int src, int dst, int num)
    946 {
    947 	struct stic_info *si;
    948 	struct stic_screen *ss;
    949 	u_int height, updword;
    950 	u_int32_t *pb, *pbs;
    951 
    952 	ss = cookie;
    953 	si = ss->ss_si;
    954 
    955 	if (ss->ss_backing != NULL)
    956 		bcopy(ss->ss_backing + row * si->si_consw + src,
    957 		    ss->ss_backing + row * si->si_consw + dst,
    958 		    num * sizeof(*ss->ss_backing));
    959 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    960 		return;
    961 
    962 	/*
    963 	 * The stamp reads and writes left -> right only, so we need to
    964 	 * buffer the span if the source and destination regions overlap
    965 	 * and the source is left of the destination.
    966 	 */
    967 	updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
    968 
    969 	if (src < dst && src + num > dst)
    970 		updword |= STAMP_HALF_BUFF;
    971 
    972 	row = (row * si->si_fonth) << 3;
    973 	num = (num * si->si_fontw) << 3;
    974 	src = row | ((src * si->si_fontw) << 19);
    975 	dst = row | ((dst * si->si_fontw) << 19);
    976 	height = si->si_fonth;
    977 
    978 	pbs = (*si->si_pbuf_get)(si);
    979 	pb = pbs;
    980 
    981 	pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
    982 	pb[1] = (height << 24) | 0xffffff;
    983 	pb[2] = 0x0;
    984 	pb[3] = updword;
    985 	pb[4] = 1; /* linewidth */
    986 
    987 	for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
    988 		pb[5] = num;
    989 		pb[6] = src;
    990 		pb[7] = dst;
    991 	}
    992 
    993 	(*si->si_pbuf_post)(si, pbs);
    994 }
    995 
    996 static void
    997 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
    998 {
    999 	struct wsdisplay_font *font;
   1000 	struct stic_screen *ss;
   1001 	struct stic_info *si;
   1002 	u_int i, bgcolor, fgcolor;
   1003 	u_int *pb, v1, v2, xya;
   1004 	u_short *fr;
   1005 
   1006 	ss = cookie;
   1007 	si = ss->ss_si;
   1008 
   1009 	/* It's cheaper to use erasecols() to blit blanks. */
   1010 	if (uc == 0) {
   1011 		stic_erasecols(cookie, r, c, 1, attr);
   1012 		return;
   1013 	}
   1014 
   1015 	if (ss->ss_backing != NULL)
   1016 		ss->ss_backing[r * si->si_consw + c] =
   1017 		    (u_int16_t)((attr & 0xff) | (uc << 8));
   1018 	if ((ss->ss_flags & SS_ACTIVE) == 0)
   1019 		return;
   1020 
   1021 	font = si->si_font;
   1022 	pb = (*si->si_pbuf_get)(si);
   1023 
   1024 	/*
   1025 	 * Create a mask from the glyph.  Squeeze the foreground color
   1026 	 * through the mask, and then squeeze the background color through
   1027 	 * the inverted mask.  We may well read outside the glyph when
   1028 	 * creating the mask, but it's bounded by the hardware so it
   1029 	 * shouldn't matter a great deal...
   1030 	 */
   1031 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
   1032 	    STAMP_LW_PERPRIMATIVE;
   1033 	pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
   1034 	pb[2] = 0x0;
   1035 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
   1036 
   1037 	r *= font->fontheight;
   1038 	c *= font->fontwidth;
   1039 	uc = (uc - font->firstchar) * font->stride * font->fontheight;
   1040 	fr = (u_short *)((caddr_t)font->data + uc);
   1041 	bgcolor = DUPBYTE1((attr & 0x40) >> 4);
   1042 	fgcolor = DUPBYTE0(attr & 0x0f);
   1043 
   1044 	i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
   1045 	v1 = (c << 19) | ((r << 3) + i);
   1046 	v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
   1047 	xya = XYMASKADDR(si->si_stampw, si->si_stamph, c, r, 0, 0);
   1048 
   1049 	pb[4] = PACK(fr, 0);
   1050 	pb[5] = PACK(fr, 2);
   1051 	pb[6] = PACK(fr, 4);
   1052 	pb[7] = PACK(fr, 6);
   1053 	pb[8] = PACK(fr, 8);
   1054 	pb[9] = PACK(fr, 10);
   1055 	pb[10] = PACK(fr, 12);
   1056 	pb[11] = PACK(fr, 14);
   1057 	pb[12] = xya;
   1058 	pb[13] = v1;
   1059 	pb[14] = v2;
   1060 	pb[15] = i;
   1061 	pb[16] = fgcolor;
   1062 
   1063 	pb[17] = ~pb[4];
   1064 	pb[18] = ~pb[5];
   1065 	pb[19] = ~pb[6];
   1066 	pb[20] = ~pb[7];
   1067 	pb[21] = ~pb[8];
   1068 	pb[22] = ~pb[9];
   1069 	pb[23] = ~pb[10];
   1070 	pb[24] = ~pb[11];
   1071 	pb[25] = xya;
   1072 	pb[26] = v1;
   1073 	pb[27] = v2;
   1074 	pb[28] = i;
   1075 	pb[29] = bgcolor;
   1076 
   1077 	/* Two more squeezes for the lower part of the character. */
   1078 	if (font->fontheight > 16) {
   1079 		i = ((font->fontheight - 16) << 2) - 1;
   1080 		r += 16;
   1081 		v1 = (c << 19) | ((r << 3) + i);
   1082 		v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
   1083 
   1084 		pb[30] = PACK(fr, 16);
   1085 		pb[31] = PACK(fr, 18);
   1086 		pb[32] = PACK(fr, 20);
   1087 		pb[33] = PACK(fr, 22);
   1088 		pb[34] = PACK(fr, 24);
   1089 		pb[35] = PACK(fr, 26);
   1090 		pb[36] = PACK(fr, 28);
   1091 		pb[37] = PACK(fr, 30);
   1092 		pb[38] = xya;
   1093 		pb[39] = v1;
   1094 		pb[40] = v2;
   1095 		pb[41] = i;
   1096 		pb[42] = fgcolor;
   1097 
   1098 		pb[43] = ~pb[30];
   1099 		pb[44] = ~pb[31];
   1100 		pb[45] = ~pb[32];
   1101 		pb[46] = ~pb[33];
   1102 		pb[47] = ~pb[34];
   1103 		pb[48] = ~pb[35];
   1104 		pb[49] = ~pb[36];
   1105 		pb[50] = ~pb[37];
   1106 		pb[51] = xya;
   1107 		pb[52] = v1;
   1108 		pb[53] = v2;
   1109 		pb[54] = i;
   1110 		pb[55] = bgcolor;
   1111 	}
   1112 
   1113 	(*si->si_pbuf_post)(si, pb);
   1114 }
   1115 
   1116 static int
   1117 stic_mapchar(void *cookie, int c, u_int *cp)
   1118 {
   1119 	struct stic_info *si;
   1120 
   1121 	si = ((struct stic_screen *)cookie)->ss_si;
   1122 
   1123 	if (c < si->si_font->firstchar || c == ' ') {
   1124 		*cp = 0;
   1125 		return (0);
   1126 	}
   1127 
   1128 	if (c - si->si_font->firstchar >= si->si_font->numchars) {
   1129 		*cp = 0;
   1130 		return (0);
   1131 	}
   1132 
   1133 	*cp = c;
   1134 	return (5);
   1135 }
   1136 
   1137 static void
   1138 stic_cursor(void *cookie, int on, int row, int col)
   1139 {
   1140 	struct stic_screen *ss;
   1141 
   1142 	ss = cookie;
   1143 
   1144 	/* XXX We should do cursor on/off. */
   1145 	ss->ss_cursor.cc_pos.x = col * ss->ss_si->si_fontw;
   1146 	ss->ss_cursor.cc_pos.y = row * ss->ss_si->si_fonth;
   1147 	stic_set_hwcurpos(ss);
   1148 }
   1149 
   1150 void
   1151 stic_flush(struct stic_info *si)
   1152 {
   1153 	struct stic_screen *ss;
   1154 	volatile u_int32_t *vdac;
   1155 	int v;
   1156 
   1157 	ss = si->si_curscreen;
   1158 	if ((ss->ss_flags & SS_ALL_CHANGED) == 0)
   1159 		return;
   1160 
   1161 	vdac = si->si_vdac;
   1162 	v = ss->ss_flags;
   1163 	ss->ss_flags &= ~SS_ALL_CHANGED;
   1164 
   1165 	if ((v & SS_CURENB_CHANGED) != 0) {
   1166 		SELECT(vdac, BT459_IREG_CCR);
   1167 		if ((v & SS_CURENB) != 0) {
   1168 			if ((si->si_vdacctl & STIC_VDAC_BLINK) != 0)
   1169 				REG(vdac, bt_reg) = 0x00c1c1c1;
   1170 			else
   1171 				REG(vdac, bt_reg) = 0x00c0c0c0;
   1172 		} else
   1173 			REG(vdac, bt_reg) = 0x00000000;
   1174 		tc_wmb();
   1175 	}
   1176 
   1177 	if ((v & SS_CURCMAP_CHANGED) != 0) {
   1178 		u_int8_t *cp;
   1179 
   1180 		cp = ss->ss_cursor.cc_color;
   1181 
   1182 		SELECT(vdac, BT459_IREG_CCOLOR_2);
   1183 		if ((si->si_vdacctl & STIC_VDAC_24BIT) != 0) {
   1184 			REG(vdac, bt_reg) = cp[1];		tc_wmb();
   1185 			REG(vdac, bt_reg) = cp[3] << 8;		tc_wmb();
   1186 			REG(vdac, bt_reg) = cp[5] << 16;	tc_wmb();
   1187 			REG(vdac, bt_reg) = cp[0];		tc_wmb();
   1188 			REG(vdac, bt_reg) = cp[2] << 8;		tc_wmb();
   1189 			REG(vdac, bt_reg) = cp[4] << 16;	tc_wmb();
   1190 		} else {
   1191 			REG(vdac, bt_reg) = DUPBYTE0(cp[1]);	tc_wmb();
   1192 			REG(vdac, bt_reg) = DUPBYTE0(cp[3]);	tc_wmb();
   1193 			REG(vdac, bt_reg) = DUPBYTE0(cp[5]);	tc_wmb();
   1194 			REG(vdac, bt_reg) = DUPBYTE0(cp[0]);	tc_wmb();
   1195 			REG(vdac, bt_reg) = DUPBYTE0(cp[2]);	tc_wmb();
   1196 			REG(vdac, bt_reg) = DUPBYTE0(cp[4]);	tc_wmb();
   1197 		}
   1198 	}
   1199 
   1200 	if ((v & SS_CURSHAPE_CHANGED) != 0) {
   1201 		u_int8_t *ip, *mp, img, msk;
   1202 		u_int8_t u;
   1203 		int bcnt;
   1204 
   1205 		ip = (u_int8_t *)ss->ss_cursor.cc_image;
   1206 		mp = (u_int8_t *)(ss->ss_cursor.cc_image + CURSOR_MAX_SIZE);
   1207 
   1208 		bcnt = 0;
   1209 		SELECT(vdac, BT459_IREG_CRAM_BASE+0);
   1210 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
   1211 		while (bcnt < ss->ss_cursor.cc_size.y * 16) {
   1212 			/* pad right half 32 pixel when smaller than 33 */
   1213 			if ((bcnt & 0x8) && ss->ss_cursor.cc_size.x < 33) {
   1214 				REG(vdac, bt_reg) = 0; tc_wmb();
   1215 				REG(vdac, bt_reg) = 0; tc_wmb();
   1216 			} else {
   1217 				img = *ip++;
   1218 				msk = *mp++;
   1219 				img &= msk;	/* cookie off image */
   1220 				u = (msk & 0x0f) << 4 | (img & 0x0f);
   1221 				REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
   1222 				tc_wmb();
   1223 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
   1224 				REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
   1225 				tc_wmb();
   1226 			}
   1227 			bcnt += 2;
   1228 		}
   1229 		/* pad unoccupied scan lines */
   1230 		while (bcnt < CURSOR_MAX_SIZE * 16) {
   1231 			REG(vdac, bt_reg) = 0; tc_wmb();
   1232 			REG(vdac, bt_reg) = 0; tc_wmb();
   1233 			bcnt += 2;
   1234 		}
   1235 	}
   1236 
   1237 	if ((v & SS_CMAP_CHANGED) != 0) {
   1238 		struct stic_hwcmap256 *cm;
   1239 		int index;
   1240 
   1241 		cm = &ss->ss_cmap;
   1242 
   1243 		SELECT(vdac, 0);
   1244 		SELECT(vdac, 0);
   1245 		if ((si->si_vdacctl & STIC_VDAC_24BIT) != 0) {
   1246 			for (index = 0; index < CMAP_SIZE; index++) {
   1247 				REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
   1248 				tc_wmb();
   1249 				REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
   1250 				tc_wmb();
   1251 				REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
   1252 				tc_wmb();
   1253 			}
   1254 		} else {
   1255 			for (index = 0; index < CMAP_SIZE; index++) {
   1256 				REG(vdac, bt_cmap) = cm->r[index];
   1257 				tc_wmb();
   1258 				REG(vdac, bt_cmap) = cm->g[index] << 8;
   1259 				tc_wmb();
   1260 				REG(vdac, bt_cmap) = cm->b[index] << 16;
   1261 				tc_wmb();
   1262 			}
   1263 		}
   1264 	}
   1265 }
   1266 
   1267 static int
   1268 stic_get_cmap(struct stic_screen *ss, struct wsdisplay_cmap *p)
   1269 {
   1270 	u_int index, count;
   1271 
   1272 	index = p->index;
   1273 	count = p->count;
   1274 
   1275 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
   1276 		return (EINVAL);
   1277 
   1278 	if (!uvm_useracc(p->red, count, B_WRITE) ||
   1279 	    !uvm_useracc(p->green, count, B_WRITE) ||
   1280 	    !uvm_useracc(p->blue, count, B_WRITE))
   1281 		return (EFAULT);
   1282 
   1283 	copyout(&ss->ss_cmap.r[index], p->red, count);
   1284 	copyout(&ss->ss_cmap.g[index], p->green, count);
   1285 	copyout(&ss->ss_cmap.b[index], p->blue, count);
   1286 	return (0);
   1287 }
   1288 
   1289 static int
   1290 stic_set_cmap(struct stic_screen *ss, struct wsdisplay_cmap *p)
   1291 {
   1292 	u_int index, count;
   1293 
   1294 	index = p->index;
   1295 	count = p->count;
   1296 
   1297 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
   1298 		return (EINVAL);
   1299 
   1300 	if (!uvm_useracc(p->red, count, B_READ) ||
   1301 	    !uvm_useracc(p->green, count, B_READ) ||
   1302 	    !uvm_useracc(p->blue, count, B_READ))
   1303 		return (EFAULT);
   1304 
   1305 	copyin(p->red, &ss->ss_cmap.r[index], count);
   1306 	copyin(p->green, &ss->ss_cmap.g[index], count);
   1307 	copyin(p->blue, &ss->ss_cmap.b[index], count);
   1308 
   1309 	ss->ss_flags |= SS_CMAP_CHANGED;
   1310 
   1311 	/*
   1312 	 * XXX Since we don't yet receive vblank interrupts from the PXG, we
   1313 	 * must flush immediatley.
   1314 	 */
   1315 	if (ss->ss_si->si_disptype == WSDISPLAY_TYPE_PXG)
   1316 		stic_flush(ss->ss_si);
   1317 
   1318 	return (0);
   1319 }
   1320 
   1321 static int
   1322 stic_set_cursor(struct stic_screen *ss, struct wsdisplay_cursor *p)
   1323 {
   1324 #define	cc (&ss->ss_cursor)
   1325 	int v, index, count, icount;
   1326 
   1327 	v = p->which;
   1328 
   1329 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
   1330 		index = p->cmap.index;
   1331 		count = p->cmap.count;
   1332 		if (index >= 2 || (index + count) > 2)
   1333 			return (EINVAL);
   1334 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
   1335 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
   1336 		    !uvm_useracc(p->cmap.blue, count, B_READ))
   1337 			return (EFAULT);
   1338 	}
   1339 
   1340 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
   1341 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
   1342 			return (EINVAL);
   1343 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
   1344 		if (!uvm_useracc(p->image, icount, B_READ) ||
   1345 		    !uvm_useracc(p->mask, icount, B_READ))
   1346 			return (EFAULT);
   1347 	}
   1348 
   1349 	if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
   1350 		if (v & WSDISPLAY_CURSOR_DOCUR)
   1351 			cc->cc_hot = p->hot;
   1352 		if (v & WSDISPLAY_CURSOR_DOPOS)
   1353 			stic_set_curpos(ss, &p->pos);
   1354 		stic_set_hwcurpos(ss);
   1355 	}
   1356 
   1357 	ss->ss_flags &= ~SS_ALL_CHANGED;
   1358 
   1359 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
   1360 		if (p->enable)
   1361 			ss->ss_flags |= SS_CURENB;
   1362 		else
   1363 			ss->ss_flags &= ~SS_CURENB;
   1364 		ss->ss_flags |= SS_CURENB_CHANGED;
   1365 	}
   1366 
   1367 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
   1368 		copyin(p->cmap.red, &cc->cc_color[index], count);
   1369 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
   1370 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
   1371 		ss->ss_flags |= SS_CURCMAP_CHANGED;
   1372 	}
   1373 
   1374 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
   1375 		cc->cc_size = p->size;
   1376 		memset(cc->cc_image, 0, sizeof cc->cc_image);
   1377 		copyin(p->image, cc->cc_image, icount);
   1378 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
   1379 		ss->ss_flags |= SS_CURSHAPE_CHANGED;
   1380 	}
   1381 
   1382 	/*
   1383 	 * XXX Since we don't yet receive vblank interrupts from the PXG, we
   1384 	 * must flush immediatley.
   1385 	 */
   1386 	if (ss->ss_si->si_disptype == WSDISPLAY_TYPE_PXG)
   1387 		stic_flush(ss->ss_si);
   1388 
   1389 	return (0);
   1390 #undef cc
   1391 }
   1392 
   1393 static int
   1394 stic_get_cursor(struct stic_screen *ss, struct wsdisplay_cursor *p)
   1395 {
   1396 
   1397 	/* XXX No X support yet. */
   1398 	return (ENOTTY);
   1399 }
   1400 
   1401 static void
   1402 stic_set_curpos(struct stic_screen *ss, struct wsdisplay_curpos *curpos)
   1403 {
   1404 	int x, y;
   1405 
   1406 	x = curpos->x;
   1407 	y = curpos->y;
   1408 
   1409 	if (y < 0)
   1410 		y = 0;
   1411 	else if (y > 1023)
   1412 		y = 1023;
   1413 	if (x < 0)
   1414 		x = 0;
   1415 	else if (x > 1279)
   1416 		x = 1279;
   1417 
   1418 	ss->ss_cursor.cc_pos.x = x;
   1419 	ss->ss_cursor.cc_pos.y = y;
   1420 	stic_set_hwcurpos(ss);
   1421 }
   1422 
   1423 static void
   1424 stic_set_hwcurpos(struct stic_screen *ss)
   1425 {
   1426 	struct stic_info *si;
   1427 	volatile u_int32_t *vdac;
   1428 	int x, y, s;
   1429 
   1430 	si = ss->ss_si;
   1431 	vdac = si->si_vdac;
   1432 
   1433 	x = ss->ss_cursor.cc_pos.x - ss->ss_cursor.cc_hot.x;
   1434 	y = ss->ss_cursor.cc_pos.y - ss->ss_cursor.cc_hot.y;
   1435 	x += STIC_MAGIC_X;
   1436 	y += STIC_MAGIC_Y;
   1437 
   1438 	s = spltty();
   1439 	SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
   1440 	REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb();
   1441 	REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb();
   1442 	REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb();
   1443 	REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb();
   1444 	splx(s);
   1445 }
   1446