Home | History | Annotate | Line # | Download | only in tc
stic.c revision 1.26
      1 /*	$NetBSD: stic.c,v 1.26 2003/11/13 03:09:29 chs 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.26 2003/11/13 03:09:29 chs 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, nokqfilter,
    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");
    354 
    355 	if (wsfont_lock(cookie, &si->si_font))
    356 		panic("stic_init: couldn't lock font");
    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 = (u_int8_t *)si->si_cursor.cc_mask;
    494 	memset(ip, 0, sizeof(si->si_cursor.cc_image));
    495 	memset(mp, 0, sizeof(si->si_cursor.cc_mask));
    496 
    497 	for (r = 0; r < si->si_fonth; r++) {
    498 		for (c = r & 1; c < si->si_fontw; c += 2) {
    499 			o = c >> 3;
    500 			b = 1 << (c & 7);
    501 			ip[o] |= b;
    502 			mp[o] |= b;
    503 		}
    504 
    505 		ip += 8;
    506 		mp += 8;
    507 	}
    508 
    509 	si->si_cursor.cc_size.x = 64;
    510 	si->si_cursor.cc_size.y = si->si_fonth;
    511 	si->si_cursor.cc_hot.x = 0;
    512 	si->si_cursor.cc_hot.y = 0;
    513 
    514 	si->si_cursor.cc_color[0] = 0xff;
    515 	si->si_cursor.cc_color[2] = 0xff;
    516 	si->si_cursor.cc_color[4] = 0xff;
    517 	si->si_cursor.cc_color[1] = 0x00;
    518 	si->si_cursor.cc_color[3] = 0x00;
    519 	si->si_cursor.cc_color[5] = 0x00;
    520 
    521 	memset(&si->si_cmap, 0, sizeof(si->si_cmap));
    522 	for (i = 0; i < 16; i++) {
    523 		si->si_cmap.r[i] = stic_cmap[i*3 + 0];
    524 		si->si_cmap.g[i] = stic_cmap[i*3 + 1];
    525 		si->si_cmap.b[i] = stic_cmap[i*3 + 2];
    526 	}
    527 
    528 	si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED |
    529 	    SI_CURCMAP_CHANGED;
    530 
    531 	splx(s);
    532 }
    533 
    534 void
    535 stic_clear_screen(struct stic_info *si)
    536 {
    537 	u_int32_t *pb;
    538 	int i;
    539 
    540 	/*
    541 	 * Do this twice, since the first packet after a reset may be
    542 	 * silently ignored.
    543 	 */
    544 	for (i = 0; i < 2; i++) {
    545 		pb = (*si->si_pbuf_get)(si);
    546 
    547 		pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
    548 		pb[1] = 0x01ffffff;
    549 		pb[2] = 0;
    550 		pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
    551 		pb[4] = (1024 << 2) - 1;
    552 		pb[5] = 0;
    553 		pb[6] = 0;
    554 		pb[7] = (1280 << 19) | ((1024 << 3) + pb[4]);
    555 
    556 		(*si->si_pbuf_post)(si, pb);
    557 	}
    558 }
    559 
    560 int
    561 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    562 {
    563 	struct stic_info *si;
    564 
    565 	si = v;
    566 
    567 	switch (cmd) {
    568 	case WSDISPLAYIO_GTYPE:
    569 		*(u_int *)data = si->si_disptype;
    570 		return (0);
    571 
    572 	case WSDISPLAYIO_GINFO:
    573 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    574 		wsd_fbip->height = 1024;
    575 		wsd_fbip->width = 1280;
    576 		wsd_fbip->depth = si->si_depth == 8 ? 8 : 32;
    577 		wsd_fbip->cmsize = CMAP_SIZE;
    578 #undef fbt
    579 		return (0);
    580 
    581 	case WSDISPLAYIO_GETCMAP:
    582 		return (stic_get_cmap(si, (struct wsdisplay_cmap *)data));
    583 
    584 	case WSDISPLAYIO_PUTCMAP:
    585 		return (stic_set_cmap(si, (struct wsdisplay_cmap *)data));
    586 
    587 	case WSDISPLAYIO_SVIDEO:
    588 #if 0 /* XXX later */
    589 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    590 		if ((si->si_blanked == 0) ^ turnoff)
    591 			si->si_blanked = turnoff;
    592 #endif
    593 		return (0);
    594 
    595 	case WSDISPLAYIO_GVIDEO:
    596 #if 0 /* XXX later */
    597 		*(u_int *)data = si->si_blanked ?
    598 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    599 #endif
    600 		return (0);
    601 
    602 	case WSDISPLAYIO_GCURPOS:
    603 		*(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos;
    604 		return (0);
    605 
    606 	case WSDISPLAYIO_SCURPOS:
    607 		stic_set_curpos(si, (struct wsdisplay_curpos *)data);
    608 		return (0);
    609 
    610 	case WSDISPLAYIO_GCURMAX:
    611 		((struct wsdisplay_curpos *)data)->x =
    612 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    613 		return (0);
    614 
    615 	case WSDISPLAYIO_GCURSOR:
    616 		return (stic_get_cursor(si, (struct wsdisplay_cursor *)data));
    617 
    618 	case WSDISPLAYIO_SCURSOR:
    619 		return (stic_set_cursor(si, (struct wsdisplay_cursor *)data));
    620 
    621 	case WSDISPLAYIO_SMODE:
    622 		si->si_dispmode = *(int *)data;
    623 		if (si->si_dispmode == WSDISPLAYIO_MODE_EMUL) {
    624 			(*si->si_ioctl)(si, STICIO_STOPQ, NULL, flag, p);
    625 			stic_setup_vdac(si);
    626 			stic_flush(si);
    627 			stic_clear_screen(si);
    628 			stic_do_switch(si->si_curscreen);
    629 		}
    630 		return (0);
    631 
    632 	case STICIO_RESET:
    633 		stic_reset(si);
    634 		return (0);
    635 	}
    636 
    637 	if (si->si_ioctl != NULL)
    638 		return ((*si->si_ioctl)(si, cmd, data, flag, p));
    639 
    640 	return (EPASSTHROUGH);
    641 }
    642 
    643 void
    644 stic_setup_backing(struct stic_info *si, struct stic_screen *ss)
    645 {
    646 	int size;
    647 
    648 	size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing);
    649 	ss->ss_backing = malloc(size, M_DEVBUF, M_NOWAIT|M_ZERO);
    650 }
    651 
    652 int
    653 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    654 		  int *curxp, int *curyp, long *attrp)
    655 {
    656 	struct stic_info *si;
    657 	struct stic_screen *ss;
    658 
    659 	si = (struct stic_info *)v;
    660 
    661 	if ((stic_consscr.ss_flags & SS_ALLOCED) == 0)
    662 		ss = &stic_consscr;
    663 	else {
    664 		ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK|M_ZERO);
    665 	}
    666 	stic_setup_backing(si, ss);
    667 
    668 	ss->ss_si = si;
    669 	ss->ss_flags = SS_ALLOCED | SS_CURENB;
    670 
    671 	*cookiep = ss;
    672 	*curxp = 0;
    673 	*curyp = 0;
    674 
    675 	stic_allocattr(ss, 0, 0, 0, attrp);
    676 	return (0);
    677 }
    678 
    679 void
    680 stic_free_screen(void *v, void *cookie)
    681 {
    682 	struct stic_screen *ss;
    683 
    684 	ss = cookie;
    685 
    686 #ifdef DIAGNOSTIC
    687 	if (ss == &stic_consscr)
    688 		panic("stic_free_screen: console");
    689 	if (ss == ((struct stic_info *)v)->si_curscreen)
    690 		panic("stic_free_screen: freeing current screen");
    691 #endif
    692 
    693 	free(ss->ss_backing, M_DEVBUF);
    694 	free(ss, M_DEVBUF);
    695 }
    696 
    697 int
    698 stic_show_screen(void *v, void *cookie, int waitok,
    699 		 void (*cb)(void *, int, int), void *cbarg)
    700 {
    701 	struct stic_info *si;
    702 
    703 	si = (struct stic_info *)v;
    704 	if (si->si_switchcbarg != NULL)
    705 		return (EAGAIN);
    706 	si->si_switchcb = cb;
    707 	si->si_switchcbarg = cbarg;
    708 
    709 	if (cb != NULL) {
    710 		callout_reset(&si->si_switch_callout, 0, stic_do_switch,
    711 		    cookie);
    712 		return (EAGAIN);
    713 	}
    714 
    715 	stic_do_switch(cookie);
    716 	return (0);
    717 }
    718 
    719 void
    720 stic_do_switch(void *cookie)
    721 {
    722 	struct stic_screen *ss;
    723 	struct stic_info *si;
    724 	u_int r, c, nr, nc;
    725 	u_int16_t *p, *sp;
    726 
    727 	ss = cookie;
    728 	si = ss->ss_si;
    729 
    730 #ifdef DIAGNOSTIC
    731 	if (ss->ss_backing == NULL)
    732 		panic("stic_do_switch: screen not backed");
    733 #endif
    734 
    735 	/* Swap in the new screen, and temporarily disable its backing. */
    736 	if (si->si_curscreen != NULL)
    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 + 1, p[1] >> 8,
    759 				    p[1] & 0x00ff);
    760 		}
    761 
    762 	/*
    763 	 * Re-enable the screen's backing, and move the cursor to the
    764 	 * correct spot.
    765 	 */
    766 	ss->ss_backing = sp;
    767 	si->si_cursor.cc_pos.x = ss->ss_curx;
    768 	si->si_cursor.cc_pos.y = ss->ss_cury;
    769 	stic_set_hwcurpos(si);
    770 	si->si_flags |= SI_CURENB_CHANGED;
    771 
    772 	/*
    773 	 * XXX Since we don't yet receive vblank interrupts from the
    774 	 * PXG, we must flush immediatley.
    775 	 */
    776 	if (si->si_disptype == WSDISPLAY_TYPE_PXG)
    777 		stic_flush(si);
    778 
    779 	/* Tell wscons that we're done. */
    780 	if (si->si_switchcbarg != NULL) {
    781 		cookie = si->si_switchcbarg;
    782 		si->si_switchcbarg = NULL;
    783 		(*si->si_switchcb)(cookie, 0, 0);
    784 	}
    785 }
    786 
    787 int
    788 stic_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
    789 {
    790 	long tmp;
    791 
    792 	if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
    793 		return (EINVAL);
    794 
    795 	if ((flags & WSATTR_WSCOLORS) == 0) {
    796 		fg = 7;
    797 		bg = 0;
    798 	}
    799 
    800 	if ((flags & WSATTR_HILIT) != 0)
    801 		fg += 8;
    802 
    803 	tmp = fg | (bg << 4);
    804 	*attr = tmp | (tmp << 16);
    805 	return (0);
    806 }
    807 
    808 void
    809 stic_erasecols(void *cookie, int row, int col, int num, long attr)
    810 {
    811 	struct stic_info *si;
    812 	struct stic_screen *ss;
    813 	u_int32_t *pb;
    814 	u_int i, linewidth;
    815 	u_int16_t *p;
    816 
    817 	ss = cookie;
    818 	si = ss->ss_si;
    819 
    820 	if (ss->ss_backing != NULL) {
    821 		p = ss->ss_backing + row * si->si_consw + col;
    822 		for (i = num; i != 0; i--)
    823 			*p++ = (u_int16_t)attr;
    824 	}
    825 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    826 		return;
    827 
    828 	col = (col * si->si_fontw) << 19;
    829 	num = (num * si->si_fontw) << 19;
    830 	row = row * si->si_fonth;
    831 	attr = (attr & 0xf0) >> 4;
    832 	linewidth = (si->si_fonth << 2) - 1;
    833 	row = (row << 3) + linewidth;
    834 
    835 	pb = (*si->si_pbuf_get)(si);
    836 
    837 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
    838 	pb[1] = 0x01ffffff;
    839 	pb[2] = 0;
    840 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
    841 	pb[4] = linewidth;
    842 	pb[5] = DUPBYTE0(attr);
    843 	pb[6] = col | row;
    844 	pb[7] = (col + num) | row;
    845 
    846 	(*si->si_pbuf_post)(si, pb);
    847 }
    848 
    849 void
    850 stic_eraserows(void *cookie, int row, int num, long attr)
    851 {
    852 	struct stic_info *si;
    853 	struct stic_screen *ss;
    854 	u_int linewidth, i;
    855 	u_int32_t *pb;
    856 
    857 	ss = cookie;
    858 	si = ss->ss_si;
    859 
    860 	if (ss->ss_backing != NULL) {
    861 		pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
    862 		for (i = si->si_consw * num; i > 0; i -= 2)
    863 			*pb++ = (u_int32_t)attr;
    864 	}
    865 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    866 		return;
    867 
    868 	row *= si->si_fonth;
    869 	num *= si->si_fonth;
    870 	attr = (attr & 0xf0) >> 4;
    871 	linewidth = (num << 2) - 1;
    872 	row = (row << 3) + linewidth;
    873 
    874 	pb = (*si->si_pbuf_get)(si);
    875 
    876 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
    877 	pb[1] = 0x01ffffff;
    878 	pb[2] = 0;
    879 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
    880 	pb[4] = linewidth;
    881 	pb[5] = DUPBYTE0(attr);
    882 	pb[6] = row;
    883 	pb[7] = (1280 << 19) | row;
    884 
    885 	(*si->si_pbuf_post)(si, pb);
    886 }
    887 
    888 void
    889 stic_copyrows(void *cookie, int src, int dst, int height)
    890 {
    891 	struct stic_info *si;
    892 	struct stic_screen *ss;
    893 	u_int32_t *pb, *pbs;
    894 	u_int num, inc, adj;
    895 
    896 	ss = cookie;
    897 	si = ss->ss_si;
    898 
    899 	if (ss->ss_backing != NULL)
    900 		bcopy(ss->ss_backing + src * si->si_consw,
    901 		    ss->ss_backing + dst * si->si_consw,
    902 		    si->si_consw * sizeof(*ss->ss_backing) * height);
    903 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    904 		return;
    905 
    906 	/*
    907 	 * We need to do this in reverse if the destination row is below
    908 	 * the source.
    909 	 */
    910 	if (dst > src) {
    911 		src += height;
    912 		dst += height;
    913 		inc = -8;
    914 		adj = -1;
    915 	} else {
    916 		inc = 8;
    917 		adj = 0;
    918 	}
    919 
    920 	src = (src * si->si_fonth + adj) << 3;
    921 	dst = (dst * si->si_fonth + adj) << 3;
    922 	height *= si->si_fonth;
    923 
    924 	while (height > 0) {
    925 		num = (height < 255 ? height : 255);
    926 		height -= num;
    927 
    928 		pbs = (*si->si_pbuf_get)(si);
    929 		pb = pbs;
    930 
    931 		pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
    932 		pb[1] = (num << 24) | 0xffffff;
    933 		pb[2] = 0x0;
    934 		pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN |
    935 		    STAMP_COPYSPAN_ALIGNED;
    936 		pb[4] = 1; /* linewidth */
    937 
    938 		for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
    939 			pb[5] = 1280 << 3;
    940 			pb[6] = src;
    941 			pb[7] = dst;
    942 		}
    943 
    944 	    	(*si->si_pbuf_post)(si, pbs);
    945 	}
    946 }
    947 
    948 void
    949 stic_copycols(void *cookie, int row, int src, int dst, int num)
    950 {
    951 	struct stic_info *si;
    952 	struct stic_screen *ss;
    953 	u_int height, updword;
    954 	u_int32_t *pb, *pbs;
    955 
    956 	ss = cookie;
    957 	si = ss->ss_si;
    958 
    959 	if (ss->ss_backing != NULL)
    960 		bcopy(ss->ss_backing + row * si->si_consw + src,
    961 		    ss->ss_backing + row * si->si_consw + dst,
    962 		    num * sizeof(*ss->ss_backing));
    963 	if ((ss->ss_flags & SS_ACTIVE) == 0)
    964 		return;
    965 
    966 	/*
    967 	 * The stamp reads and writes left -> right only, so we need to
    968 	 * buffer the span if the source and destination regions overlap
    969 	 * and the source is left of the destination.
    970 	 */
    971 	updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
    972 
    973 	if (src < dst && src + num > dst)
    974 		updword |= STAMP_HALF_BUFF;
    975 
    976 	row = (row * si->si_fonth) << 3;
    977 	num = (num * si->si_fontw) << 3;
    978 	src = row | ((src * si->si_fontw) << 19);
    979 	dst = row | ((dst * si->si_fontw) << 19);
    980 	height = si->si_fonth;
    981 
    982 	pbs = (*si->si_pbuf_get)(si);
    983 	pb = pbs;
    984 
    985 	pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
    986 	pb[1] = (height << 24) | 0xffffff;
    987 	pb[2] = 0x0;
    988 	pb[3] = updword;
    989 	pb[4] = 1; /* linewidth */
    990 
    991 	for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
    992 		pb[5] = num;
    993 		pb[6] = src;
    994 		pb[7] = dst;
    995 	}
    996 
    997 	(*si->si_pbuf_post)(si, pbs);
    998 }
    999 
   1000 void
   1001 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
   1002 {
   1003 	struct wsdisplay_font *font;
   1004 	struct stic_screen *ss;
   1005 	struct stic_info *si;
   1006 	u_int i, bgcolor, fgcolor;
   1007 	u_int *pb, v1, v2, xya;
   1008 	u_short *fr;
   1009 
   1010 	ss = cookie;
   1011 	si = ss->ss_si;
   1012 
   1013 	/* It's cheaper to use erasecols() to blit blanks. */
   1014 	if (uc == 0) {
   1015 		stic_erasecols(cookie, r, c, 1, attr);
   1016 		return;
   1017 	}
   1018 
   1019 	if (ss->ss_backing != NULL)
   1020 		ss->ss_backing[r * si->si_consw + c] =
   1021 		    (u_short)((attr & 0xff) | (uc << 8));
   1022 	if ((ss->ss_flags & SS_ACTIVE) == 0)
   1023 		return;
   1024 
   1025 	font = si->si_font;
   1026 	pb = (*si->si_pbuf_get)(si);
   1027 
   1028 	/*
   1029 	 * Create a mask from the glyph.  Squeeze the foreground color
   1030 	 * through the mask, and then squeeze the background color through
   1031 	 * the inverted mask.  We may well read outside the glyph when
   1032 	 * creating the mask, but it's bounded by the hardware so it
   1033 	 * shouldn't matter a great deal...
   1034 	 */
   1035 	pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
   1036 	    STAMP_LW_PERPRIMATIVE;
   1037 	pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
   1038 	pb[2] = 0x0;
   1039 	pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
   1040 
   1041 	r *= font->fontheight;
   1042 	c *= font->fontwidth;
   1043 	uc = (uc - font->firstchar) * font->stride * font->fontheight;
   1044 	fr = (u_short *)((caddr_t)font->data + uc);
   1045 	bgcolor = DUPBYTE0((attr & 0xf0) >> 4);
   1046 	fgcolor = DUPBYTE0(attr & 0x0f);
   1047 
   1048 	i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
   1049 	v1 = (c << 19) | ((r << 3) + i);
   1050 	v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
   1051 	xya = XYMASKADDR(si->si_stampw, si->si_stamphm, c, r, 0, 0);
   1052 
   1053 	pb[4] = PACK(fr, 0);
   1054 	pb[5] = PACK(fr, 2);
   1055 	pb[6] = PACK(fr, 4);
   1056 	pb[7] = PACK(fr, 6);
   1057 	pb[8] = PACK(fr, 8);
   1058 	pb[9] = PACK(fr, 10);
   1059 	pb[10] = PACK(fr, 12);
   1060 	pb[11] = PACK(fr, 14);
   1061 	pb[12] = xya;
   1062 	pb[13] = v1;
   1063 	pb[14] = v2;
   1064 	pb[15] = i;
   1065 	pb[16] = fgcolor;
   1066 
   1067 	pb[17] = ~pb[4];
   1068 	pb[18] = ~pb[5];
   1069 	pb[19] = ~pb[6];
   1070 	pb[20] = ~pb[7];
   1071 	pb[21] = ~pb[8];
   1072 	pb[22] = ~pb[9];
   1073 	pb[23] = ~pb[10];
   1074 	pb[24] = ~pb[11];
   1075 	pb[25] = xya;
   1076 	pb[26] = v1;
   1077 	pb[27] = v2;
   1078 	pb[28] = i;
   1079 	pb[29] = bgcolor;
   1080 
   1081 	/* Two more squeezes for the lower part of the character. */
   1082 	if (font->fontheight > 16) {
   1083 		i = ((font->fontheight - 16) << 2) - 1;
   1084 		r += 16;
   1085 		v1 = (c << 19) | ((r << 3) + i);
   1086 		v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
   1087 
   1088 		pb[30] = PACK(fr, 16);
   1089 		pb[31] = PACK(fr, 18);
   1090 		pb[32] = PACK(fr, 20);
   1091 		pb[33] = PACK(fr, 22);
   1092 		pb[34] = PACK(fr, 24);
   1093 		pb[35] = PACK(fr, 26);
   1094 		pb[36] = PACK(fr, 28);
   1095 		pb[37] = PACK(fr, 30);
   1096 		pb[38] = xya;
   1097 		pb[39] = v1;
   1098 		pb[40] = v2;
   1099 		pb[41] = i;
   1100 		pb[42] = fgcolor;
   1101 
   1102 		pb[43] = ~pb[30];
   1103 		pb[44] = ~pb[31];
   1104 		pb[45] = ~pb[32];
   1105 		pb[46] = ~pb[33];
   1106 		pb[47] = ~pb[34];
   1107 		pb[48] = ~pb[35];
   1108 		pb[49] = ~pb[36];
   1109 		pb[50] = ~pb[37];
   1110 		pb[51] = xya;
   1111 		pb[52] = v1;
   1112 		pb[53] = v2;
   1113 		pb[54] = i;
   1114 		pb[55] = bgcolor;
   1115 	}
   1116 
   1117 	(*si->si_pbuf_post)(si, pb);
   1118 }
   1119 
   1120 int
   1121 stic_mapchar(void *cookie, int c, u_int *cp)
   1122 {
   1123 	struct stic_info *si;
   1124 
   1125 	si = ((struct stic_screen *)cookie)->ss_si;
   1126 
   1127 	if (c < si->si_font->firstchar || c == ' ') {
   1128 		*cp = 0;
   1129 		return (0);
   1130 	}
   1131 
   1132 	if (c - si->si_font->firstchar >= si->si_font->numchars) {
   1133 		*cp = 0;
   1134 		return (0);
   1135 	}
   1136 
   1137 	*cp = c;
   1138 	return (5);
   1139 }
   1140 
   1141 void
   1142 stic_cursor(void *cookie, int on, int row, int col)
   1143 {
   1144 	struct stic_screen *ss;
   1145 	struct stic_info *si;
   1146 	int s;
   1147 
   1148 	ss = cookie;
   1149 	si = ss->ss_si;
   1150 
   1151 	ss->ss_curx = col * si->si_fontw;
   1152 	ss->ss_cury = row * si->si_fonth;
   1153 
   1154 	s = spltty();
   1155 
   1156 	if (on)
   1157 		ss->ss_flags |= SS_CURENB;
   1158 	else
   1159 		ss->ss_flags &= ~SS_CURENB;
   1160 
   1161 	if ((ss->ss_flags & SS_ACTIVE) != 0) {
   1162 		si->si_cursor.cc_pos.x = ss->ss_curx;
   1163 		si->si_cursor.cc_pos.y = ss->ss_cury;
   1164 		si->si_flags |= SI_CURENB_CHANGED;
   1165 		stic_set_hwcurpos(si);
   1166 
   1167 		/*
   1168 		 * XXX Since we don't yet receive vblank interrupts from the
   1169 		 * PXG, we must flush immediatley.
   1170 		 */
   1171 		if (si->si_disptype == WSDISPLAY_TYPE_PXG)
   1172 			stic_flush(si);
   1173 	}
   1174 
   1175 	splx(s);
   1176 }
   1177 
   1178 void
   1179 stic_flush(struct stic_info *si)
   1180 {
   1181 	volatile u_int32_t *vdac;
   1182 	int v;
   1183 
   1184 	if ((si->si_flags & SI_ALL_CHANGED) == 0)
   1185 		return;
   1186 
   1187 	vdac = si->si_vdac;
   1188 	v = si->si_flags;
   1189 	si->si_flags &= ~SI_ALL_CHANGED;
   1190 
   1191 	if ((v & SI_CURENB_CHANGED) != 0) {
   1192 		SELECT(vdac, BT459_IREG_CCR);
   1193 		if ((si->si_curscreen->ss_flags & SS_CURENB) != 0)
   1194 			REG(vdac, bt_reg) = 0x00c0c0c0;
   1195 		else
   1196 			REG(vdac, bt_reg) = 0x00000000;
   1197 		tc_wmb();
   1198 	}
   1199 
   1200 	if ((v & SI_CURCMAP_CHANGED) != 0) {
   1201 		u_int8_t *cp;
   1202 
   1203 		cp = si->si_cursor.cc_color;
   1204 
   1205 		SELECT(vdac, BT459_IREG_CCOLOR_2);
   1206 		REG(vdac, bt_reg) = DUPBYTE0(cp[1]);	tc_wmb();
   1207 		REG(vdac, bt_reg) = DUPBYTE0(cp[3]);	tc_wmb();
   1208 		REG(vdac, bt_reg) = DUPBYTE0(cp[5]);	tc_wmb();
   1209 		REG(vdac, bt_reg) = DUPBYTE0(cp[0]);	tc_wmb();
   1210 		REG(vdac, bt_reg) = DUPBYTE0(cp[2]);	tc_wmb();
   1211 		REG(vdac, bt_reg) = DUPBYTE0(cp[4]);	tc_wmb();
   1212 	}
   1213 
   1214 	if ((v & SI_CURSHAPE_CHANGED) != 0) {
   1215 		u_int8_t *ip, *mp, img, msk;
   1216 		u_int8_t u;
   1217 		int bcnt;
   1218 
   1219 		ip = (u_int8_t *)si->si_cursor.cc_image;
   1220 		mp = (u_int8_t *)si->si_cursor.cc_mask;
   1221 
   1222 		bcnt = 0;
   1223 		SELECT(vdac, BT459_IREG_CRAM_BASE);
   1224 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
   1225 		while (bcnt < CURSOR_MAX_SIZE * 16) {
   1226 			img = *ip++;
   1227 			msk = *mp++;
   1228 			img &= msk;	/* cookie off image */
   1229 			u = (msk & 0x0f) << 4 | (img & 0x0f);
   1230 			REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
   1231 			tc_wmb();
   1232 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
   1233 			REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
   1234 			tc_wmb();
   1235 			bcnt += 2;
   1236 		}
   1237 	}
   1238 
   1239 	if ((v & SI_CMAP_CHANGED) != 0) {
   1240 		struct stic_hwcmap256 *cm;
   1241 		int index;
   1242 
   1243 		cm = &si->si_cmap;
   1244 
   1245 		SELECT(vdac, 0);
   1246 		SELECT(vdac, 0);
   1247 		for (index = 0; index < CMAP_SIZE; index++) {
   1248 			REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
   1249 			tc_wmb();
   1250 			REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
   1251 			tc_wmb();
   1252 			REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
   1253 			tc_wmb();
   1254 		}
   1255 	}
   1256 }
   1257 
   1258 int
   1259 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
   1260 {
   1261 	u_int index = p->index, count = p->count;
   1262 	int error;
   1263 
   1264 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
   1265 		return (EINVAL);
   1266 
   1267 	error = copyout(&si->si_cmap.r[index], p->red, count);
   1268 	if (error)
   1269 		return error;
   1270 	error = copyout(&si->si_cmap.g[index], p->green, count);
   1271 	if (error)
   1272 		return error;
   1273 	error = copyout(&si->si_cmap.b[index], p->blue, count);
   1274 	return error;
   1275 }
   1276 
   1277 int
   1278 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
   1279 {
   1280 	struct stic_hwcmap256 cmap;
   1281 	u_int index, count;
   1282 	int s, error;
   1283 
   1284 	index = p->index;
   1285 	count = p->count;
   1286 
   1287 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
   1288 		return (EINVAL);
   1289 
   1290 	error = copyin(p->red, &cmap.r[index], count);
   1291 	if (error)
   1292 		return error;
   1293 	error = copyin(p->green, &cmap.g[index], count);
   1294 	if (error)
   1295 		return error;
   1296 	error = copyin(p->blue, &cmap.b[index], count);
   1297 	if (error)
   1298 		return error;
   1299 
   1300 	s = spltty();
   1301 	memcpy(&si->si_cmap.r[index], &cmap.r[index], count);
   1302 	memcpy(&si->si_cmap.g[index], &cmap.g[index], count);
   1303 	memcpy(&si->si_cmap.b[index], &cmap.b[index], count);
   1304 	si->si_flags |= SI_CMAP_CHANGED;
   1305 	splx(s);
   1306 
   1307 	/*
   1308 	 * XXX Since we don't yet receive vblank interrupts from the PXG, we
   1309 	 * must flush immediatley.
   1310 	 */
   1311 	if (si->si_disptype == WSDISPLAY_TYPE_PXG)
   1312 		stic_flush(si);
   1313 
   1314 	return (0);
   1315 }
   1316 
   1317 int
   1318 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
   1319 {
   1320 #define	cc (&si->si_cursor)
   1321 	u_int v, index = 0, count = 0, icount = 0;
   1322 	struct stic_screen *ss;
   1323 	uint8_t r[2], g[2], b[2], image[512], mask[512];
   1324 	int s, error;
   1325 
   1326 	v = p->which;
   1327 	ss = si->si_curscreen;
   1328 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
   1329 		index = p->cmap.index;
   1330 		count = p->cmap.count;
   1331 		if (index >= 2 || (index + count) > 2)
   1332 			return (EINVAL);
   1333 		error = copyin(p->cmap.red, &r[index], count);
   1334 		if (error)
   1335 			return error;
   1336 		error = copyin(p->cmap.green, &g[index], count);
   1337 		if (error)
   1338 			return error;
   1339 		error = copyin(p->cmap.blue, &b[index], count);
   1340 		if (error)
   1341 			return error;
   1342 	}
   1343 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
   1344 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
   1345 			return (EINVAL);
   1346 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
   1347 		error = copyin(p->image, image, icount);
   1348 		if (error)
   1349 			return error;
   1350 		error = copyin(p->mask, mask, icount);
   1351 		if (error)
   1352 			return error;
   1353 	}
   1354 	if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
   1355 		if (v & WSDISPLAY_CURSOR_DOCUR)
   1356 			cc->cc_hot = p->hot;
   1357 		if (v & WSDISPLAY_CURSOR_DOPOS)
   1358 			stic_set_curpos(si, &p->pos);
   1359 	}
   1360 
   1361 	s = spltty();
   1362 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
   1363 		if (p->enable)
   1364 			ss->ss_flags |= SS_CURENB;
   1365 		else
   1366 			ss->ss_flags &= ~SS_CURENB;
   1367 		si->si_flags |= SI_CURENB_CHANGED;
   1368 	}
   1369 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
   1370 		memcpy(&cc->cc_color[index], &r[index], count);
   1371 		memcpy(&cc->cc_color[index + 2], &g[index], count);
   1372 		memcpy(&cc->cc_color[index + 4], &b[index], count);
   1373 		si->si_flags |= SI_CURCMAP_CHANGED;
   1374 	}
   1375 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
   1376 		memset(cc->cc_image, 0, sizeof cc->cc_image);
   1377 		memcpy(cc->cc_image, image, icount);
   1378 		memset(cc->cc_mask, 0, sizeof cc->cc_mask);
   1379 		memcpy(cc->cc_mask, mask, icount);
   1380 		si->si_flags |= SI_CURSHAPE_CHANGED;
   1381 	}
   1382 	splx(s);
   1383 
   1384 	/*
   1385 	 * XXX Since we don't yet receive vblank interrupts from the PXG, we
   1386 	 * must flush immediatley.
   1387 	 */
   1388 	if (si->si_disptype == WSDISPLAY_TYPE_PXG)
   1389 		stic_flush(si);
   1390 
   1391 	return (0);
   1392 #undef cc
   1393 }
   1394 
   1395 int
   1396 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
   1397 {
   1398 
   1399 	/* XXX */
   1400 	return (EPASSTHROUGH);
   1401 }
   1402 
   1403 void
   1404 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos)
   1405 {
   1406 	int x, y;
   1407 
   1408 	x = curpos->x;
   1409 	y = curpos->y;
   1410 
   1411 	if (y < 0)
   1412 		y = 0;
   1413 	else if (y > 1023)
   1414 		y = 1023;
   1415 	if (x < 0)
   1416 		x = 0;
   1417 	else if (x > 1279)
   1418 		x = 1279;
   1419 
   1420 	si->si_cursor.cc_pos.x = x;
   1421 	si->si_cursor.cc_pos.y = y;
   1422 	stic_set_hwcurpos(si);
   1423 }
   1424 
   1425 void
   1426 stic_set_hwcurpos(struct stic_info *si)
   1427 {
   1428 	volatile u_int32_t *vdac;
   1429 	int x, y, s;
   1430 
   1431 	vdac = si->si_vdac;
   1432 
   1433 	x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x;
   1434 	y = si->si_cursor.cc_pos.y - si->si_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 
   1447 /*
   1448  * STIC control inteface.  We have a separate device for mapping the board,
   1449  * because access to the DMA engine means that it's possible to circumvent
   1450  * the securelevel mechanism.  Given the way devices work in the BSD kernel,
   1451  * and given the unfortunate design of the mmap() call it's near impossible
   1452  * to protect against this using a shared device (i.e. wsdisplay).
   1453  *
   1454  * This is a gross hack... Hopefully not too many other devices will need
   1455  * it.
   1456  */
   1457 int
   1458 sticopen(dev_t dev, int flag, int mode, struct proc *p)
   1459 {
   1460 	struct stic_info *si;
   1461 	int s;
   1462 
   1463 	if (securelevel > 0)
   1464 		return (EPERM);
   1465 	if (minor(dev) >= STIC_MAXDV)
   1466 		return (ENXIO);
   1467 	if ((si = stic_info[minor(dev)]) == NULL)
   1468 		return (ENXIO);
   1469 
   1470 	s = spltty();
   1471 	if ((si->si_flags & SI_DVOPEN) != 0) {
   1472 		splx(s);
   1473 		return (EBUSY);
   1474 	}
   1475 	si->si_flags |= SI_DVOPEN;
   1476 	splx(s);
   1477 
   1478 	return (0);
   1479 }
   1480 
   1481 int
   1482 sticclose(dev_t dev, int flag, int mode, struct proc *p)
   1483 {
   1484 	struct stic_info *si;
   1485 	int s;
   1486 
   1487 	si = stic_info[minor(dev)];
   1488 	s = spltty();
   1489 	si->si_flags &= ~SI_DVOPEN;
   1490 	splx(s);
   1491 
   1492 	return (0);
   1493 }
   1494 
   1495 paddr_t
   1496 sticmmap(dev_t dev, off_t offset, int prot)
   1497 {
   1498 	struct stic_info *si;
   1499 	struct stic_xmap *sxm;
   1500 	paddr_t pa;
   1501 
   1502 	si = stic_info[minor(dev)];
   1503 	sxm = NULL;
   1504 
   1505 	if (securelevel > 0)
   1506 		return (-1L);
   1507 	if (si->si_dispmode != WSDISPLAYIO_MODE_MAPPED)
   1508 		return (-1L);
   1509 
   1510 	if (offset < 0)
   1511 		return ((paddr_t)-1L);
   1512 
   1513 	if (offset < sizeof(sxm->sxm_stic)) {
   1514 		pa = STIC_KSEG_TO_PHYS(si->si_stic);
   1515 		return (machine_btop(pa + offset));
   1516 	}
   1517 	offset -= sizeof(sxm->sxm_stic);
   1518 
   1519 	if (offset < sizeof(sxm->sxm_poll)) {
   1520 		pa = STIC_KSEG_TO_PHYS(si->si_slotbase);
   1521 		return (machine_btop(pa + offset));
   1522 	}
   1523 	offset -= sizeof(sxm->sxm_poll);
   1524 
   1525 	if (offset < si->si_buf_size)
   1526 		return (machine_btop(si->si_buf_phys + offset));
   1527 
   1528 	return ((paddr_t)-1L);
   1529 }
   1530