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