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