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