Home | History | Annotate | Line # | Download | only in vsa
smg.c revision 1.65
      1  1.65    andvar /*	$NetBSD: smg.c,v 1.65 2023/03/26 15:12:34 andvar Exp $ */
      2  1.64   tsutsui /*	$OpenBSD: smg.c,v 1.28 2014/12/23 21:39:12 miod Exp $	*/
      3  1.64   tsutsui /*
      4  1.64   tsutsui  * Copyright (c) 2006, Miodrag Vallat
      5  1.64   tsutsui  *
      6  1.64   tsutsui  * Redistribution and use in source and binary forms, with or without
      7  1.64   tsutsui  * modification, are permitted provided that the following conditions
      8  1.64   tsutsui  * are met:
      9  1.64   tsutsui  * 1. Redistributions of source code must retain the above copyright
     10  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer.
     11  1.64   tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer in the
     13  1.64   tsutsui  *    documentation and/or other materials provided with the distribution.
     14  1.64   tsutsui  *
     15  1.64   tsutsui  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  1.64   tsutsui  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.64   tsutsui  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.64   tsutsui  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  1.64   tsutsui  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  1.64   tsutsui  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.64   tsutsui  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.64   tsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  1.64   tsutsui  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  1.64   tsutsui  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  1.64   tsutsui  * POSSIBILITY OF SUCH DAMAGE.
     26  1.64   tsutsui  */
     27  1.64   tsutsui /*-
     28  1.64   tsutsui  * Copyright (c) 2000 The NetBSD Foundation, Inc.
     29  1.64   tsutsui  * All rights reserved.
     30  1.64   tsutsui  *
     31  1.64   tsutsui  * This code is derived from software contributed to The NetBSD Foundation
     32  1.64   tsutsui  * by Tohru Nishimura.
     33  1.64   tsutsui  *
     34  1.64   tsutsui  * Redistribution and use in source and binary forms, with or without
     35  1.64   tsutsui  * modification, are permitted provided that the following conditions
     36  1.64   tsutsui  * are met:
     37  1.64   tsutsui  * 1. Redistributions of source code must retain the above copyright
     38  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer.
     39  1.64   tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     40  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer in the
     41  1.64   tsutsui  *    documentation and/or other materials provided with the distribution.
     42  1.64   tsutsui  *
     43  1.64   tsutsui  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     44  1.64   tsutsui  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     45  1.64   tsutsui  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     46  1.64   tsutsui  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     47  1.64   tsutsui  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     48  1.64   tsutsui  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     49  1.64   tsutsui  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     50  1.64   tsutsui  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     51  1.64   tsutsui  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     52  1.64   tsutsui  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     53  1.64   tsutsui  * POSSIBILITY OF SUCH DAMAGE.
     54  1.64   tsutsui  */
     55   1.1     ragge /*
     56   1.1     ragge  * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
     57   1.1     ragge  * All rights reserved.
     58   1.1     ragge  *
     59   1.1     ragge  * Redistribution and use in source and binary forms, with or without
     60   1.1     ragge  * modification, are permitted provided that the following conditions
     61   1.1     ragge  * are met:
     62   1.1     ragge  * 1. Redistributions of source code must retain the above copyright
     63   1.1     ragge  *    notice, this list of conditions and the following disclaimer.
     64   1.1     ragge  * 2. Redistributions in binary form must reproduce the above copyright
     65   1.1     ragge  *    notice, this list of conditions and the following disclaimer in the
     66   1.1     ragge  *    documentation and/or other materials provided with the distribution.
     67   1.1     ragge  *
     68   1.1     ragge  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     69   1.1     ragge  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     70   1.1     ragge  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     71   1.1     ragge  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     72   1.1     ragge  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     73   1.1     ragge  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     74   1.1     ragge  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     75   1.1     ragge  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     76   1.1     ragge  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     77   1.1     ragge  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     78   1.1     ragge  */
     79  1.64   tsutsui /*
     80  1.64   tsutsui  * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
     81  1.64   tsutsui  * Copyright (c) 1991 University of Utah.
     82  1.64   tsutsui  * Copyright (c) 1990, 1993
     83  1.64   tsutsui  *	The Regents of the University of California.  All rights reserved.
     84  1.64   tsutsui  *
     85  1.64   tsutsui  * This code is derived from software contributed to Berkeley by
     86  1.64   tsutsui  * the Systems Programming Group of the University of Utah Computer
     87  1.64   tsutsui  * Science Department and Mark Davies of the Department of Computer
     88  1.64   tsutsui  * Science, Victoria University of Wellington, New Zealand.
     89  1.64   tsutsui  *
     90  1.64   tsutsui  * Redistribution and use in source and binary forms, with or without
     91  1.64   tsutsui  * modification, are permitted provided that the following conditions
     92  1.64   tsutsui  * are met:
     93  1.64   tsutsui  * 1. Redistributions of source code must retain the above copyright
     94  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer.
     95  1.64   tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     96  1.64   tsutsui  *    notice, this list of conditions and the following disclaimer in the
     97  1.64   tsutsui  *    documentation and/or other materials provided with the distribution.
     98  1.64   tsutsui  * 3. Neither the name of the University nor the names of its contributors
     99  1.64   tsutsui  *    may be used to endorse or promote products derived from this software
    100  1.64   tsutsui  *    without specific prior written permission.
    101  1.64   tsutsui  *
    102  1.64   tsutsui  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    103  1.64   tsutsui  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    104  1.64   tsutsui  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    105  1.64   tsutsui  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    106  1.64   tsutsui  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    107  1.64   tsutsui  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    108  1.64   tsutsui  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    109  1.64   tsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    110  1.64   tsutsui  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    111  1.64   tsutsui  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    112  1.64   tsutsui  * SUCH DAMAGE.
    113  1.64   tsutsui  *
    114  1.64   tsutsui  * from: Utah $Hdr: grf_hy.c 1.2 93/08/13$
    115  1.64   tsutsui  *
    116  1.64   tsutsui  *	@(#)grf_hy.c	8.4 (Berkeley) 1/12/94
    117  1.64   tsutsui  */
    118  1.37     lukem 
    119  1.37     lukem #include <sys/cdefs.h>
    120  1.65    andvar __KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.65 2023/03/26 15:12:34 andvar Exp $");
    121  1.63   tsutsui 
    122  1.63   tsutsui #include "dzkbd.h"
    123  1.63   tsutsui #include "wsdisplay.h"
    124   1.1     ragge 
    125   1.1     ragge #include <sys/param.h>
    126  1.64   tsutsui #include <sys/device.h>
    127   1.1     ragge #include <sys/systm.h>
    128  1.64   tsutsui #include <sys/kmem.h>
    129   1.1     ragge #include <sys/conf.h>
    130   1.1     ragge 
    131  1.26     ragge #include <machine/vsbus.h>
    132  1.26     ragge #include <machine/sid.h>
    133  1.64   tsutsui #include <machine/cpu.h>
    134  1.26     ragge #include <machine/ka420.h>
    135  1.63   tsutsui #include <machine/scb.h>
    136  1.26     ragge 
    137   1.1     ragge #include <dev/cons.h>
    138   1.1     ragge 
    139  1.64   tsutsui #include <dev/ic/dc503reg.h>
    140  1.64   tsutsui 
    141  1.28        ad #include <dev/dec/dzreg.h>
    142  1.28        ad #include <dev/dec/dzvar.h>
    143  1.26     ragge #include <dev/dec/dzkbdvar.h>
    144  1.26     ragge 
    145  1.64   tsutsui #include <dev/wscons/wsconsio.h>
    146   1.1     ragge #include <dev/wscons/wsdisplayvar.h>
    147  1.64   tsutsui #include <dev/rasops/rasops.h>
    148   1.1     ragge 
    149  1.26     ragge /* Screen hardware defs */
    150  1.26     ragge #define SM_XWIDTH	1024
    151  1.64   tsutsui #define SM_YWIDTH	864
    152  1.26     ragge 
    153  1.26     ragge #define CUR_XBIAS	216	/* Add to cursor position */
    154  1.64   tsutsui #define CUR_YBIAS	33
    155  1.26     ragge 
    156  1.64   tsutsui static int	smg_match(device_t, cfdata_t, void *);
    157  1.64   tsutsui static void	smg_attach(device_t, device_t, void *);
    158   1.1     ragge 
    159  1.64   tsutsui struct	smg_screen {
    160  1.64   tsutsui 	struct rasops_info ss_ri;
    161  1.64   tsutsui 	uint8_t		*ss_addr;		/* frame buffer address */
    162  1.64   tsutsui 	struct dc503reg	*ss_cursor;		/* cursor registers */
    163  1.64   tsutsui 	uint16_t	ss_curcmd;
    164  1.64   tsutsui 	struct wsdisplay_curpos ss_curpos, ss_curhot;
    165  1.64   tsutsui 	uint16_t	ss_curimg[PCC_CURSOR_SIZE];
    166  1.64   tsutsui 	uint16_t	ss_curmask[PCC_CURSOR_SIZE];
    167  1.64   tsutsui };
    168   1.1     ragge 
    169  1.64   tsutsui /* for console */
    170  1.64   tsutsui static struct smg_screen smg_consscr;
    171   1.1     ragge 
    172  1.64   tsutsui struct	smg_softc {
    173  1.64   tsutsui 	device_t sc_dev;
    174  1.64   tsutsui 	struct smg_screen *sc_scr;
    175  1.64   tsutsui 	int	sc_nscreens;
    176   1.1     ragge };
    177   1.1     ragge 
    178  1.64   tsutsui CFATTACH_DECL_NEW(smg, sizeof(struct smg_softc),
    179  1.64   tsutsui     smg_match, smg_attach, NULL, NULL);
    180  1.64   tsutsui 
    181  1.64   tsutsui static struct wsscreen_descr smg_stdscreen = {
    182  1.64   tsutsui 	.name = "std",
    183   1.1     ragge };
    184   1.1     ragge 
    185  1.64   tsutsui static const struct wsscreen_descr *_smg_scrlist[] = {
    186   1.1     ragge 	&smg_stdscreen,
    187   1.1     ragge };
    188   1.1     ragge 
    189  1.64   tsutsui static const struct wsscreen_list smg_screenlist = {
    190  1.64   tsutsui 	.nscreens = sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *),
    191  1.47      matt 	.screens = _smg_scrlist,
    192   1.1     ragge };
    193   1.1     ragge 
    194  1.64   tsutsui static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *);
    195  1.64   tsutsui static paddr_t smg_mmap(void *, void *, off_t, int);
    196  1.64   tsutsui static int smg_alloc_screen(void *, const struct wsscreen_descr *,
    197  1.64   tsutsui     void **, int *, int *, long *);
    198  1.64   tsutsui static void smg_free_screen(void *, void *);
    199  1.64   tsutsui static int smg_show_screen(void *, void *, int, void (*) (void *, int, int),
    200  1.64   tsutsui     void *);
    201  1.26     ragge 
    202  1.64   tsutsui static const struct wsdisplay_accessops smg_accessops = {
    203  1.47      matt 	.ioctl = smg_ioctl,
    204  1.47      matt 	.mmap = smg_mmap,
    205  1.47      matt 	.alloc_screen = smg_alloc_screen,
    206  1.47      matt 	.free_screen = smg_free_screen,
    207  1.47      matt 	.show_screen = smg_show_screen,
    208  1.64   tsutsui 	.load_font = NULL
    209   1.1     ragge };
    210   1.1     ragge 
    211  1.64   tsutsui static void smg_putchar(void *, int, int, u_int, long);
    212  1.64   tsutsui static void smg_cursor(void *, int, int, int);
    213  1.64   tsutsui static void smg_blockmove(struct rasops_info *, u_int, u_int, u_int, u_int,
    214  1.64   tsutsui     u_int, int);
    215  1.64   tsutsui static void smg_copycols(void *, int, int, int, int);
    216  1.64   tsutsui static void smg_erasecols(void *, int, int, int, long);
    217  1.64   tsutsui 
    218  1.64   tsutsui static int smg_getcursor(struct smg_screen *, struct wsdisplay_cursor *);
    219  1.64   tsutsui static int smg_setup_screen(struct smg_screen *);
    220  1.64   tsutsui static int smg_setcursor(struct smg_screen *, struct wsdisplay_cursor *);
    221  1.64   tsutsui static void smg_updatecursor(struct smg_screen *, u_int);
    222   1.1     ragge 
    223  1.64   tsutsui static int
    224  1.63   tsutsui smg_match(device_t parent, cfdata_t cf, void *aux)
    225   1.1     ragge {
    226  1.64   tsutsui 	struct vsbus_attach_args *va = aux;
    227  1.64   tsutsui 	volatile short *curcmd;
    228  1.64   tsutsui 	volatile short *cfgtst;
    229  1.64   tsutsui 	short tmp, tmp2;
    230  1.15     ragge 
    231  1.63   tsutsui 	switch (vax_boardtype) {
    232  1.63   tsutsui 	default:
    233  1.17     ragge 		return 0;
    234  1.17     ragge 
    235  1.63   tsutsui 	case VAX_BTYP_410:
    236  1.63   tsutsui 	case VAX_BTYP_420:
    237  1.63   tsutsui 	case VAX_BTYP_43:
    238  1.63   tsutsui 		if (va->va_paddr != KA420_CUR_BASE)
    239  1.63   tsutsui 			return 0;
    240  1.63   tsutsui 
    241  1.63   tsutsui 		/* not present on microvaxes */
    242  1.63   tsutsui 		if ((vax_confdata & KA420_CFG_MULTU) != 0)
    243  1.63   tsutsui 			return 0;
    244  1.64   tsutsui 
    245  1.63   tsutsui 		/*
    246  1.63   tsutsui 		 * If the color option board is present, do not attach
    247  1.63   tsutsui 		 * unless we are explicitely asked to via device flags.
    248  1.63   tsutsui 		 */
    249  1.63   tsutsui 		if ((vax_confdata & KA420_CFG_VIDOPT) != 0 &&
    250  1.63   tsutsui 		    (cf->cf_flags & 1) == 0)
    251  1.63   tsutsui 			return 0;
    252  1.63   tsutsui 		break;
    253  1.63   tsutsui 	}
    254  1.63   tsutsui 
    255  1.63   tsutsui 	/* when already running as console, always fake things */
    256  1.63   tsutsui 	if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0
    257  1.63   tsutsui #if NWSDISPLAY > 0
    258  1.63   tsutsui 	    && cn_tab->cn_putc == wsdisplay_cnputc
    259  1.63   tsutsui #endif
    260  1.63   tsutsui 	) {
    261  1.63   tsutsui 		struct vsbus_softc *sc = device_private(parent);
    262  1.63   tsutsui 
    263  1.63   tsutsui 		sc->sc_mask = 0x08;
    264  1.63   tsutsui 		scb_fake(0x44, 0x15);
    265  1.63   tsutsui 		return 20;
    266  1.63   tsutsui 	} else {
    267  1.63   tsutsui 		/*
    268  1.63   tsutsui 		 * Try to find the cursor chip by testing the flip-flop.
    269  1.63   tsutsui 		 * If nonexistent, no glass tty.
    270  1.63   tsutsui 		 */
    271  1.64   tsutsui 		curcmd = (short *)va->va_addr;
    272  1.64   tsutsui 		cfgtst = (short *)vax_map_physmem(VS_CFGTST, 1);
    273  1.64   tsutsui 		curcmd[0] = PCCCMD_HSHI | PCCCMD_FOPB;
    274  1.63   tsutsui 		DELAY(300000);
    275  1.63   tsutsui 		tmp = cfgtst[0];
    276  1.64   tsutsui 		curcmd[0] = PCCCMD_TEST | PCCCMD_HSHI;
    277  1.63   tsutsui 		DELAY(300000);
    278  1.63   tsutsui 		tmp2 = cfgtst[0];
    279  1.63   tsutsui 		vax_unmap_physmem((vaddr_t)cfgtst, 1);
    280  1.63   tsutsui 
    281  1.63   tsutsui 		if (tmp2 != tmp)
    282  1.63   tsutsui 			return 20; /* Using periodic interrupt */
    283  1.63   tsutsui 		else
    284  1.63   tsutsui 			return 0;
    285  1.63   tsutsui 	}
    286   1.1     ragge }
    287   1.1     ragge 
    288  1.64   tsutsui static void
    289  1.47      matt smg_attach(device_t parent, device_t self, void *aux)
    290   1.1     ragge {
    291  1.64   tsutsui 	struct smg_softc *sc = device_private(self);
    292  1.64   tsutsui 	struct smg_screen *scr;
    293   1.1     ragge 	struct wsemuldisplaydev_attach_args aa;
    294  1.64   tsutsui 	int console;
    295   1.1     ragge 
    296  1.64   tsutsui 	console =
    297  1.63   tsutsui #if NWSDISPLAY > 0
    298  1.63   tsutsui 	    (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0 &&
    299  1.63   tsutsui 	    cn_tab->cn_putc == wsdisplay_cnputc;
    300  1.63   tsutsui #else
    301  1.63   tsutsui 	    (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0;
    302  1.63   tsutsui #endif
    303  1.64   tsutsui 	if (console) {
    304  1.64   tsutsui 		scr = &smg_consscr;
    305  1.64   tsutsui 		sc->sc_nscreens = 1;
    306  1.64   tsutsui 	} else {
    307  1.64   tsutsui 		scr = kmem_zalloc(sizeof(*scr), KM_SLEEP);
    308  1.30     ragge 
    309  1.64   tsutsui 		scr->ss_addr =
    310  1.64   tsutsui 		    (void *)vax_map_physmem(SMADDR, SMSIZE / VAX_NBPG);
    311  1.64   tsutsui 		if (scr->ss_addr == NULL) {
    312  1.64   tsutsui 			aprint_error(": can not map frame buffer\n");
    313  1.64   tsutsui 			kmem_free(scr, sizeof(*scr));
    314  1.64   tsutsui 			return;
    315  1.64   tsutsui 		}
    316   1.1     ragge 
    317  1.64   tsutsui 		scr->ss_cursor =
    318  1.64   tsutsui 		    (struct dc503reg *)vax_map_physmem(KA420_CUR_BASE, 1);
    319  1.64   tsutsui 		if (scr->ss_cursor == NULL) {
    320  1.64   tsutsui 			aprint_error(": can not map cursor chip\n");
    321  1.64   tsutsui 			vax_unmap_physmem((vaddr_t)scr->ss_addr,
    322  1.64   tsutsui 			    SMSIZE / VAX_NBPG);
    323  1.64   tsutsui 			kmem_free(scr, sizeof(*scr));
    324  1.64   tsutsui 			return;
    325  1.64   tsutsui 		}
    326   1.1     ragge 
    327  1.64   tsutsui 		if (smg_setup_screen(scr) != 0) {
    328  1.64   tsutsui 			aprint_error(": initialization failed\n");
    329  1.64   tsutsui 			vax_unmap_physmem((vaddr_t)scr->ss_cursor, 1);
    330  1.64   tsutsui 			vax_unmap_physmem((vaddr_t)scr->ss_addr,
    331  1.64   tsutsui 			    SMSIZE / VAX_NBPG);
    332  1.64   tsutsui 			kmem_free(scr, sizeof(*scr));
    333  1.64   tsutsui 			return;
    334  1.64   tsutsui 		}
    335   1.6     ragge 	}
    336  1.64   tsutsui 	sc->sc_scr = scr;
    337   1.5  drochner 
    338  1.64   tsutsui 	aprint_normal("\n");
    339  1.64   tsutsui 	aprint_normal_dev(self, "%dx%d on-board monochrome framebuffer\n",
    340  1.64   tsutsui 	    SM_XWIDTH, SM_YWIDTH);
    341   1.1     ragge 
    342  1.64   tsutsui 	aa.console = console;
    343  1.64   tsutsui 	aa.scrdata = &smg_screenlist;
    344  1.64   tsutsui 	aa.accessops = &smg_accessops;
    345  1.64   tsutsui 	aa.accesscookie = sc;
    346   1.1     ragge 
    347  1.64   tsutsui 	config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
    348   1.1     ragge }
    349   1.1     ragge 
    350   1.1     ragge /*
    351  1.64   tsutsui  * Initialize anything necessary for an emulating wsdisplay to work (i.e.
    352  1.64   tsutsui  * pick a font, initialize a rasops structure, setup the accessops callbacks.)
    353   1.1     ragge  */
    354  1.64   tsutsui static int
    355  1.64   tsutsui smg_setup_screen(struct smg_screen *ss)
    356   1.1     ragge {
    357  1.64   tsutsui 	struct rasops_info *ri = &ss->ss_ri;
    358  1.64   tsutsui 	int cookie;
    359   1.1     ragge 
    360  1.64   tsutsui 	memset(ri, 0, sizeof(*ri));
    361  1.64   tsutsui 	ri->ri_depth = 1;
    362  1.64   tsutsui 	ri->ri_width = SM_XWIDTH;
    363  1.64   tsutsui 	ri->ri_height = SM_YWIDTH;
    364  1.64   tsutsui 	ri->ri_stride = SM_XWIDTH >> 3;
    365  1.64   tsutsui 	ri->ri_flg = RI_CLEAR | RI_CENTER;
    366  1.64   tsutsui 	ri->ri_bits = (void *)ss->ss_addr;
    367  1.64   tsutsui 	ri->ri_hw = ss;
    368  1.64   tsutsui 	if (ss == &smg_consscr)
    369  1.64   tsutsui 		ri->ri_flg |= RI_NO_AUTO;
    370   1.1     ragge 
    371  1.64   tsutsui 	wsfont_init();
    372  1.64   tsutsui 	cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
    373  1.64   tsutsui 	    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
    374  1.64   tsutsui 	if (cookie < 0)
    375  1.64   tsutsui 		cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L,
    376  1.64   tsutsui 		    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
    377  1.64   tsutsui 	if (cookie < 0)
    378  1.64   tsutsui 		cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
    379  1.64   tsutsui 		    WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
    380  1.64   tsutsui 	if (cookie < 0)
    381  1.64   tsutsui 		return -1;
    382  1.64   tsutsui 	if (wsfont_lock(cookie, &ri->ri_font) != 0)
    383  1.64   tsutsui 		return -1;
    384  1.64   tsutsui 	ri->ri_wsfcookie = cookie;
    385   1.1     ragge 
    386  1.64   tsutsui 	/*
    387  1.64   tsutsui 	 * Ask for an unholy big display, rasops will trim this to more
    388  1.64   tsutsui 	 * reasonable values.
    389  1.64   tsutsui 	 */
    390  1.64   tsutsui 	if (rasops_init(ri, 160, 160) != 0)
    391  1.64   tsutsui 		return -1;
    392   1.1     ragge 
    393  1.64   tsutsui 	ri->ri_ops.cursor = smg_cursor;
    394  1.64   tsutsui 	ri->ri_ops.putchar = smg_putchar;
    395  1.64   tsutsui 	ri->ri_ops.copycols = smg_copycols;
    396  1.64   tsutsui 	ri->ri_ops.erasecols = smg_erasecols;
    397  1.64   tsutsui 
    398  1.64   tsutsui 	smg_stdscreen.ncols = ri->ri_cols;
    399  1.64   tsutsui 	smg_stdscreen.nrows = ri->ri_rows;
    400  1.64   tsutsui 	smg_stdscreen.textops = &ri->ri_ops;
    401  1.64   tsutsui 	smg_stdscreen.fontwidth = ri->ri_font->fontwidth;
    402  1.64   tsutsui 	smg_stdscreen.fontheight = ri->ri_font->fontheight;
    403  1.64   tsutsui 	smg_stdscreen.capabilities = ri->ri_caps;
    404   1.1     ragge 
    405  1.64   tsutsui 	ss->ss_curcmd = PCCCMD_HSHI;
    406  1.64   tsutsui 	ss->ss_cursor->cmdr = ss->ss_curcmd;
    407   1.1     ragge 
    408  1.64   tsutsui 	return 0;
    409   1.1     ragge }
    410   1.1     ragge 
    411   1.1     ragge static int
    412  1.42  christos smg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    413   1.1     ragge {
    414  1.64   tsutsui 	struct smg_softc *sc = v;
    415  1.64   tsutsui 	struct smg_screen *ss = sc->sc_scr;
    416  1.64   tsutsui 	struct wsdisplay_fbinfo *wdf;
    417  1.64   tsutsui 	struct wsdisplay_curpos *pos;
    418   1.8     ragge 
    419   1.8     ragge 	switch (cmd) {
    420   1.8     ragge 	case WSDISPLAYIO_GTYPE:
    421  1.26     ragge 		*(u_int *)data = WSDISPLAY_TYPE_VAX_MONO;
    422   1.8     ragge 		break;
    423   1.8     ragge 
    424   1.8     ragge 	case WSDISPLAYIO_GINFO:
    425  1.64   tsutsui 		wdf = (struct wsdisplay_fbinfo *)data;
    426  1.64   tsutsui 		wdf->height = ss->ss_ri.ri_height;
    427  1.64   tsutsui 		wdf->width = ss->ss_ri.ri_width;
    428  1.64   tsutsui 		wdf->depth = ss->ss_ri.ri_depth;
    429  1.64   tsutsui 		wdf->cmsize = 0;
    430  1.26     ragge 		break;
    431  1.26     ragge 
    432  1.64   tsutsui 	case WSDISPLAYIO_LINEBYTES:
    433  1.64   tsutsui 		*(u_int *)data = ss->ss_ri.ri_stride;
    434  1.26     ragge 		break;
    435  1.26     ragge 
    436  1.64   tsutsui 	case WSDISPLAYIO_GETCMAP:
    437  1.64   tsutsui 	case WSDISPLAYIO_PUTCMAP:
    438  1.26     ragge 	case WSDISPLAYIO_GVIDEO:
    439  1.64   tsutsui 	case WSDISPLAYIO_SVIDEO:
    440  1.26     ragge 		break;
    441  1.26     ragge 
    442  1.64   tsutsui 	case WSDISPLAYIO_GCURPOS:
    443  1.64   tsutsui 		pos = (struct wsdisplay_curpos *)data;
    444  1.64   tsutsui 		pos->x = ss->ss_curpos.x;
    445  1.64   tsutsui 		pos->y = ss->ss_curpos.y;
    446  1.26     ragge 		break;
    447  1.26     ragge 
    448  1.26     ragge 	case WSDISPLAYIO_SCURPOS:
    449  1.64   tsutsui 		pos = (struct wsdisplay_curpos *)data;
    450  1.64   tsutsui 		ss->ss_curpos.x = pos->x;
    451  1.64   tsutsui 		ss->ss_curpos.y = pos->y;
    452  1.64   tsutsui 		smg_updatecursor(ss, WSDISPLAY_CURSOR_DOPOS);
    453  1.26     ragge 		break;
    454  1.26     ragge 
    455  1.64   tsutsui 	case WSDISPLAYIO_GCURMAX:
    456  1.64   tsutsui 		pos = (struct wsdisplay_curpos *)data;
    457  1.64   tsutsui 		pos->x = pos->y = PCC_CURSOR_SIZE;
    458  1.64   tsutsui 
    459  1.64   tsutsui 	case WSDISPLAYIO_GCURSOR:
    460  1.64   tsutsui 		return smg_getcursor(ss, (struct wsdisplay_cursor *)data);
    461  1.36        ad 
    462  1.64   tsutsui 	case WSDISPLAYIO_SCURSOR:
    463  1.64   tsutsui 		return smg_setcursor(ss, (struct wsdisplay_cursor *)data);
    464   1.8     ragge 
    465   1.8     ragge 	default:
    466  1.29    atatat 		return EPASSTHROUGH;
    467   1.8     ragge 	}
    468   1.8     ragge 	return 0;
    469   1.1     ragge }
    470   1.1     ragge 
    471  1.23    simonb static paddr_t
    472  1.41      jmmv smg_mmap(void *v, void *vs, off_t offset, int prot)
    473   1.1     ragge {
    474  1.64   tsutsui 
    475   1.9       mrg 	if (offset >= SMSIZE || offset < 0)
    476   1.8     ragge 		return -1;
    477  1.64   tsutsui 
    478  1.64   tsutsui 	return SMADDR + offset;
    479   1.1     ragge }
    480   1.1     ragge 
    481  1.64   tsutsui static int
    482  1.26     ragge smg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    483  1.26     ragge     int *curxp, int *curyp, long *defattrp)
    484   1.1     ragge {
    485  1.64   tsutsui 	struct smg_softc *sc = v;
    486  1.64   tsutsui 	struct smg_screen *ss = sc->sc_scr;
    487  1.64   tsutsui 	struct rasops_info *ri = &ss->ss_ri;
    488  1.64   tsutsui 
    489  1.64   tsutsui 	if (sc->sc_nscreens > 0)
    490  1.64   tsutsui 		return ENOMEM;
    491  1.64   tsutsui 
    492  1.64   tsutsui 	*cookiep = ri;
    493  1.64   tsutsui 	*curxp = *curyp = 0;
    494  1.64   tsutsui 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, defattrp);
    495  1.64   tsutsui 	sc->sc_nscreens++;
    496  1.64   tsutsui 
    497   1.1     ragge 	return 0;
    498   1.1     ragge }
    499   1.1     ragge 
    500  1.64   tsutsui static void
    501  1.26     ragge smg_free_screen(void *v, void *cookie)
    502   1.1     ragge {
    503  1.64   tsutsui 	struct smg_softc *sc = v;
    504  1.64   tsutsui 
    505  1.64   tsutsui 	sc->sc_nscreens--;
    506   1.1     ragge }
    507   1.1     ragge 
    508  1.64   tsutsui static int
    509  1.26     ragge smg_show_screen(void *v, void *cookie, int waitok,
    510  1.26     ragge     void (*cb)(void *, int, int), void *cbarg)
    511   1.1     ragge {
    512   1.2     ragge 
    513  1.64   tsutsui 	return 0;
    514  1.64   tsutsui }
    515  1.64   tsutsui 
    516  1.64   tsutsui static int
    517  1.64   tsutsui smg_getcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
    518  1.64   tsutsui {
    519  1.64   tsutsui 	int error;
    520  1.64   tsutsui 
    521  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0)
    522  1.64   tsutsui 		wdc->enable = ss->ss_curcmd & PCCCMD_ENPA ? 1 : 0;
    523  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
    524  1.64   tsutsui 		wdc->pos.x = ss->ss_curpos.x;
    525  1.64   tsutsui 		wdc->pos.y = ss->ss_curpos.y;
    526  1.64   tsutsui 	}
    527  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
    528  1.64   tsutsui 		wdc->hot.x = ss->ss_curhot.x;
    529  1.64   tsutsui 		wdc->hot.y = ss->ss_curhot.y;
    530  1.64   tsutsui 	}
    531  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    532  1.64   tsutsui 		wdc->cmap.index = 0;
    533  1.64   tsutsui 		wdc->cmap.count = 0;
    534  1.64   tsutsui 	}
    535  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    536  1.64   tsutsui 		wdc->size.x = wdc->size.y = PCC_CURSOR_SIZE;
    537  1.64   tsutsui 		error = copyout(ss->ss_curimg, wdc->image,
    538  1.64   tsutsui 		    sizeof(ss->ss_curimg));
    539  1.64   tsutsui 		if (error != 0)
    540  1.64   tsutsui 			return error;
    541  1.64   tsutsui 		error = copyout(ss->ss_curmask, wdc->mask,
    542  1.64   tsutsui 		    sizeof(ss->ss_curmask));
    543  1.64   tsutsui 		if (error != 0)
    544  1.64   tsutsui 			return error;
    545  1.64   tsutsui 	}
    546  1.64   tsutsui 
    547  1.64   tsutsui 	return 0;
    548  1.64   tsutsui }
    549  1.64   tsutsui 
    550  1.64   tsutsui static int
    551  1.64   tsutsui smg_setcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
    552  1.64   tsutsui {
    553  1.64   tsutsui 	uint16_t curfg[PCC_CURSOR_SIZE], curmask[PCC_CURSOR_SIZE];
    554  1.64   tsutsui 	int error;
    555  1.64   tsutsui 
    556  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    557  1.64   tsutsui 		/* No cursor colormap since we are a B&W device. */
    558  1.64   tsutsui 		if (wdc->cmap.count != 0)
    559  1.64   tsutsui 			return EINVAL;
    560  1.64   tsutsui 	}
    561  1.64   tsutsui 
    562  1.64   tsutsui 	/*
    563  1.64   tsutsui 	 * First, do the userland-kernel data transfers, so that we can fail
    564  1.64   tsutsui 	 * if necessary before altering anything.
    565  1.64   tsutsui 	 */
    566  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    567  1.64   tsutsui 		if (wdc->size.x != PCC_CURSOR_SIZE ||
    568  1.64   tsutsui 		    wdc->size.y != PCC_CURSOR_SIZE)
    569  1.64   tsutsui 			return EINVAL;
    570  1.64   tsutsui 		error = copyin(wdc->image, curfg, sizeof(curfg));
    571  1.64   tsutsui 		if (error != 0)
    572  1.64   tsutsui 			return error;
    573  1.64   tsutsui 		error = copyin(wdc->mask, curmask, sizeof(curmask));
    574  1.64   tsutsui 		if (error != 0)
    575  1.64   tsutsui 			return error;
    576  1.64   tsutsui 	}
    577  1.64   tsutsui 
    578  1.64   tsutsui 	/*
    579  1.64   tsutsui 	 * Now update our variables...
    580  1.64   tsutsui 	 */
    581  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0) {
    582  1.64   tsutsui 		if (wdc->enable)
    583  1.64   tsutsui 			ss->ss_curcmd |= PCCCMD_ENPB | PCCCMD_ENPA;
    584  1.64   tsutsui 		else
    585  1.64   tsutsui 			ss->ss_curcmd &= ~(PCCCMD_ENPB | PCCCMD_ENPA);
    586  1.64   tsutsui 	}
    587  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
    588  1.64   tsutsui 		ss->ss_curpos.x = wdc->pos.x;
    589  1.64   tsutsui 		ss->ss_curpos.y = wdc->pos.y;
    590  1.64   tsutsui 	}
    591  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
    592  1.64   tsutsui 		ss->ss_curhot.x = wdc->hot.x;
    593  1.64   tsutsui 		ss->ss_curhot.y = wdc->hot.y;
    594  1.64   tsutsui 	}
    595  1.64   tsutsui 	if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    596  1.64   tsutsui 		memcpy(ss->ss_curimg, curfg, sizeof(ss->ss_curimg));
    597  1.64   tsutsui 		memcpy(ss->ss_curmask, curmask, sizeof(ss->ss_curmask));
    598  1.64   tsutsui 	}
    599  1.64   tsutsui 
    600  1.64   tsutsui 	/*
    601  1.64   tsutsui 	 * ...and update the cursor
    602  1.64   tsutsui 	 */
    603  1.64   tsutsui 	smg_updatecursor(ss, wdc->which);
    604  1.64   tsutsui 
    605  1.64   tsutsui 	return 0;
    606  1.64   tsutsui }
    607  1.64   tsutsui 
    608  1.64   tsutsui static void
    609  1.64   tsutsui smg_updatecursor(struct smg_screen *ss, u_int which)
    610  1.64   tsutsui {
    611  1.64   tsutsui 	u_int i;
    612  1.64   tsutsui 
    613  1.64   tsutsui 	if ((which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
    614  1.64   tsutsui 		ss->ss_cursor->xpos =
    615  1.64   tsutsui 		    ss->ss_curpos.x - ss->ss_curhot.x + CUR_XBIAS;
    616  1.64   tsutsui 		ss->ss_cursor->ypos =
    617  1.64   tsutsui 		    ss->ss_curpos.y - ss->ss_curhot.y + CUR_YBIAS;
    618  1.64   tsutsui 	}
    619  1.64   tsutsui 	if ((which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    620  1.64   tsutsui 		ss->ss_cursor->cmdr = ss->ss_curcmd | PCCCMD_LODSA;
    621  1.64   tsutsui 		for (i = 0; i < PCC_CURSOR_SIZE; i++)
    622  1.64   tsutsui 			ss->ss_cursor->load = ss->ss_curimg[i];
    623  1.64   tsutsui 		for (i = 0; i < PCC_CURSOR_SIZE; i++)
    624  1.64   tsutsui 			ss->ss_cursor->load = ss->ss_curmask[i];
    625  1.64   tsutsui 		ss->ss_cursor->cmdr = ss->ss_curcmd;
    626  1.64   tsutsui 	} else
    627  1.64   tsutsui 	if ((which & WSDISPLAY_CURSOR_DOCUR) != 0)
    628  1.64   tsutsui 		ss->ss_cursor->cmdr = ss->ss_curcmd;
    629  1.64   tsutsui }
    630  1.64   tsutsui 
    631  1.64   tsutsui /*
    632  1.64   tsutsui  * Faster console operations
    633  1.64   tsutsui  */
    634  1.64   tsutsui 
    635  1.64   tsutsui #include <vax/vsa/maskbits.h>
    636  1.64   tsutsui 
    637  1.64   tsutsui /* putchar() and cursor() ops are taken from luna68k omrasops.c */
    638  1.64   tsutsui 
    639  1.64   tsutsui #define	ALL1BITS	(~0U)
    640  1.64   tsutsui #define	ALL0BITS	(0U)
    641  1.64   tsutsui #define	BLITWIDTH	(32)
    642  1.64   tsutsui #define	ALIGNMASK	(0x1f)
    643  1.64   tsutsui #define	BYTESDONE	(4)
    644  1.64   tsutsui 
    645  1.64   tsutsui static void
    646  1.64   tsutsui smg_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
    647  1.64   tsutsui {
    648  1.64   tsutsui 	struct rasops_info *ri = cookie;
    649  1.64   tsutsui 	uint8_t *p;
    650  1.64   tsutsui 	int scanspan, startx, height, width, align, y;
    651  1.64   tsutsui 	uint32_t lmask, rmask, glyph, inverse;
    652  1.64   tsutsui 	int i;
    653  1.64   tsutsui 	uint8_t *fb;
    654  1.64   tsutsui 
    655  1.64   tsutsui 	scanspan = ri->ri_stride;
    656  1.64   tsutsui 	y = ri->ri_font->fontheight * row;
    657  1.64   tsutsui 	startx = ri->ri_font->fontwidth * startcol;
    658  1.64   tsutsui 	height = ri->ri_font->fontheight;
    659  1.64   tsutsui 	fb = (uint8_t *)ri->ri_font->data +
    660  1.64   tsutsui 	    (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
    661  1.64   tsutsui 	inverse = ((attr & WSATTR_REVERSE) != 0) ? ALL1BITS : ALL0BITS;
    662  1.64   tsutsui 
    663  1.64   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    664  1.64   tsutsui 	align = startx & ALIGNMASK;
    665  1.64   tsutsui 	width = ri->ri_font->fontwidth + align;
    666  1.64   tsutsui 	/* lmask and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */
    667  1.64   tsutsui 	lmask = ALL1BITS << align;
    668  1.64   tsutsui 	rmask = ALL1BITS >> (-width & ALIGNMASK);
    669  1.64   tsutsui 	if (width <= BLITWIDTH) {
    670  1.64   tsutsui 		uint32_t mask = lmask & rmask;
    671  1.64   tsutsui 		while (height > 0) {
    672  1.64   tsutsui 			uint32_t image;
    673  1.64   tsutsui 			/*
    674  1.64   tsutsui 			 * The font glyph is stored in byteorder and bitorder
    675  1.64   tsutsui 			 * WSDISPLAY_FONTORDER_R2L to use proper shift ops.
    676  1.64   tsutsui 			 * On the other hand, VRAM data is stored in
    677  1.64   tsutsui 			 * WSDISPLAY_FONTORDER_R2L bitorder and
    678  1.65    andvar 			 * WSDISPLAY_FONTORDER_L2R byteorder.
    679  1.64   tsutsui 			 */
    680  1.64   tsutsui 			glyph = 0;
    681  1.64   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    682  1.64   tsutsui 				glyph = (glyph << 8) | *fb++;
    683  1.64   tsutsui 			glyph = (glyph << align) ^ inverse;
    684  1.64   tsutsui 			image = *(uint32_t *)p;
    685  1.64   tsutsui 			*(uint32_t *)p = (image & ~mask) | (glyph & mask);
    686  1.64   tsutsui 			p += scanspan;
    687  1.64   tsutsui 			height--;
    688  1.64   tsutsui 		}
    689  1.64   tsutsui 	} else {
    690  1.64   tsutsui 		uint8_t *q = p;
    691  1.64   tsutsui 		uint32_t lhalf, rhalf;
    692   1.2     ragge 
    693  1.64   tsutsui 		while (height > 0) {
    694  1.64   tsutsui 			uint32_t image;
    695  1.64   tsutsui 			glyph = 0;
    696  1.64   tsutsui 			for (i = ri->ri_font->stride; i != 0; i--)
    697  1.64   tsutsui 				glyph = (glyph << 8) | *fb++;
    698  1.64   tsutsui 			lhalf = (glyph << align) ^ inverse;
    699  1.64   tsutsui 			image = *(uint32_t *)p;
    700  1.64   tsutsui 			*(uint32_t *)p = (image & ~lmask) | (lhalf & lmask);
    701  1.64   tsutsui 			p += BYTESDONE;
    702  1.64   tsutsui 			rhalf = (glyph >> (BLITWIDTH - align)) ^ inverse;
    703  1.64   tsutsui 			image = *(uint32_t *)p;
    704  1.64   tsutsui 			*(uint32_t *)p = (rhalf & rmask) | (image & ~rmask);
    705  1.64   tsutsui 
    706  1.64   tsutsui 			p = (q += scanspan);
    707  1.64   tsutsui 			height--;
    708   1.8     ragge 		}
    709  1.64   tsutsui 	}
    710   1.1     ragge }
    711   1.1     ragge 
    712  1.64   tsutsui static void
    713  1.64   tsutsui smg_cursor(void *cookie, int on, int row, int col)
    714  1.64   tsutsui {
    715  1.64   tsutsui 	struct rasops_info *ri = cookie;
    716  1.64   tsutsui 	uint8_t *p;
    717  1.64   tsutsui 	int scanspan, startx, height, width, align, y;
    718  1.64   tsutsui 	uint32_t lmask, rmask, image;
    719  1.64   tsutsui 
    720  1.64   tsutsui 	if (!on) {
    721  1.64   tsutsui 		/* make sure it's on */
    722  1.64   tsutsui 		if ((ri->ri_flg & RI_CURSOR) == 0)
    723  1.64   tsutsui 			return;
    724  1.64   tsutsui 
    725  1.64   tsutsui 		row = ri->ri_crow;
    726  1.64   tsutsui 		col = ri->ri_ccol;
    727  1.64   tsutsui 	} else {
    728  1.64   tsutsui 		/* unpaint the old copy. */
    729  1.64   tsutsui 		ri->ri_crow = row;
    730  1.64   tsutsui 		ri->ri_ccol = col;
    731  1.64   tsutsui 	}
    732  1.64   tsutsui 
    733  1.64   tsutsui 	scanspan = ri->ri_stride;
    734  1.64   tsutsui 	y = ri->ri_font->fontheight * row;
    735  1.64   tsutsui 	startx = ri->ri_font->fontwidth * col;
    736  1.64   tsutsui 	height = ri->ri_font->fontheight;
    737  1.64   tsutsui 
    738  1.64   tsutsui 	p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
    739  1.64   tsutsui 	align = startx & ALIGNMASK;
    740  1.64   tsutsui 	width = ri->ri_font->fontwidth + align;
    741  1.64   tsutsui 	/* lmask and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */
    742  1.64   tsutsui 	lmask = ALL1BITS << align;
    743  1.64   tsutsui 	rmask = ALL1BITS >> (-width & ALIGNMASK);
    744  1.64   tsutsui 	if (width <= BLITWIDTH) {
    745  1.64   tsutsui 		uint32_t mask = lmask & rmask;
    746  1.64   tsutsui 		while (height > 0) {
    747  1.64   tsutsui 			image = *(uint32_t *)p;
    748  1.64   tsutsui 			*(uint32_t *)p =
    749  1.64   tsutsui 			    (image & ~mask) | ((image ^ ALL1BITS) & mask);
    750  1.64   tsutsui 			p += scanspan;
    751  1.64   tsutsui 			height--;
    752  1.64   tsutsui 		}
    753  1.64   tsutsui 	} else {
    754  1.64   tsutsui 		uint8_t *q = p;
    755  1.64   tsutsui 
    756  1.64   tsutsui 		while (height > 0) {
    757  1.64   tsutsui 			image = *(uint32_t *)p;
    758  1.64   tsutsui 			*(uint32_t *)p =
    759  1.64   tsutsui 			    (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
    760  1.64   tsutsui 			p += BYTESDONE;
    761  1.64   tsutsui 			image = *(uint32_t *)p;
    762  1.64   tsutsui 			*(uint32_t *)p =
    763  1.64   tsutsui 			    ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
    764  1.64   tsutsui 
    765  1.64   tsutsui 			p = (q += scanspan);
    766  1.64   tsutsui 			height--;
    767  1.64   tsutsui 		}
    768  1.64   tsutsui 	}
    769  1.64   tsutsui 	ri->ri_flg ^= RI_CURSOR;
    770  1.64   tsutsui }
    771   1.1     ragge 
    772  1.64   tsutsui static void
    773  1.64   tsutsui smg_blockmove(struct rasops_info *ri, u_int sx, u_int y, u_int dx, u_int cx,
    774  1.64   tsutsui     u_int cy, int rop)
    775   1.1     ragge {
    776  1.64   tsutsui 	int width;		/* add to get to same position in next line */
    777  1.64   tsutsui 
    778  1.64   tsutsui 	unsigned int *psrcLine, *pdstLine;
    779  1.64   tsutsui 				/* pointers to line with current src and dst */
    780  1.64   tsutsui 	unsigned int *psrc;	/* pointer to current src longword */
    781  1.64   tsutsui 	unsigned int *pdst;	/* pointer to current dst longword */
    782  1.64   tsutsui 
    783  1.64   tsutsui 				/* following used for looping through a line */
    784  1.64   tsutsui 	unsigned int startmask, endmask;  /* masks for writing ends of dst */
    785  1.64   tsutsui 	int nlMiddle;		/* whole longwords in dst */
    786  1.64   tsutsui 	int nl;			/* temp copy of nlMiddle */
    787  1.64   tsutsui 	int xoffSrc;		/* offset (>= 0, < 32) from which to
    788  1.64   tsutsui 				   fetch whole longwords fetched in src */
    789  1.64   tsutsui 	int nstart;		/* number of ragged bits at start of dst */
    790  1.64   tsutsui 	int nend;		/* number of ragged bits at end of dst */
    791  1.64   tsutsui 	int srcStartOver;	/* pulling nstart bits from src
    792  1.64   tsutsui 				   overflows into the next word? */
    793  1.64   tsutsui 
    794  1.64   tsutsui 	width = SM_XWIDTH >> 5;
    795  1.64   tsutsui 
    796  1.64   tsutsui 	/* start at first scanline */
    797  1.64   tsutsui 	psrcLine = pdstLine = ((u_int *)ri->ri_bits) + (y * width);
    798  1.64   tsutsui 
    799  1.64   tsutsui 	/* x direction doesn't matter for < 1 longword */
    800  1.64   tsutsui 	if (cx <= 32) {
    801  1.64   tsutsui 		int srcBit, dstBit;	/* bit offset of src and dst */
    802  1.64   tsutsui 
    803  1.64   tsutsui 		pdstLine += (dx >> 5);
    804  1.64   tsutsui 		psrcLine += (sx >> 5);
    805  1.64   tsutsui 		psrc = psrcLine;
    806  1.64   tsutsui 		pdst = pdstLine;
    807  1.64   tsutsui 
    808  1.64   tsutsui 		srcBit = sx & ALIGNMASK;
    809  1.64   tsutsui 		dstBit = dx & ALIGNMASK;
    810  1.64   tsutsui 
    811  1.64   tsutsui 		while (cy--) {
    812  1.64   tsutsui 			getandputrop(psrc, srcBit, dstBit, cx, pdst, rop);
    813  1.64   tsutsui 			pdst += width;
    814  1.64   tsutsui 			psrc += width;
    815  1.64   tsutsui 		}
    816  1.64   tsutsui 	} else {
    817  1.64   tsutsui 		startmask = ALL1BITS << (dx & ALIGNMASK);
    818  1.64   tsutsui 		endmask   = ALL1BITS >> (~cx & ALIGNMASK);
    819  1.64   tsutsui 		if (startmask)
    820  1.64   tsutsui 			nlMiddle = (cx - (32 - (dx & ALIGNMASK))) >> 5;
    821  1.64   tsutsui 		else
    822  1.64   tsutsui 			nlMiddle = cx >> 5;
    823  1.63   tsutsui 
    824  1.64   tsutsui 		if (startmask)
    825  1.64   tsutsui 			nstart = 32 - (dx & ALIGNMASK);
    826  1.64   tsutsui 		else
    827  1.64   tsutsui 			nstart = 0;
    828  1.64   tsutsui 		if (endmask)
    829  1.64   tsutsui 			nend = (dx + cx) & ALIGNMASK;
    830  1.64   tsutsui 		else
    831  1.64   tsutsui 			nend = 0;
    832  1.63   tsutsui 
    833  1.64   tsutsui 		xoffSrc = ((sx & ALIGNMASK) + nstart) & ALIGNMASK;
    834  1.64   tsutsui 		srcStartOver = ((sx & ALIGNMASK) + nstart) > 31;
    835  1.63   tsutsui 
    836  1.64   tsutsui 		if (sx >= dx) {	/* move left to right */
    837  1.64   tsutsui 			pdstLine += (dx >> 5);
    838  1.64   tsutsui 			psrcLine += (sx >> 5);
    839  1.64   tsutsui 
    840  1.64   tsutsui 			while (cy--) {
    841  1.64   tsutsui 				psrc = psrcLine;
    842  1.64   tsutsui 				pdst = pdstLine;
    843  1.64   tsutsui 
    844  1.64   tsutsui 				if (startmask) {
    845  1.64   tsutsui 					getandputrop(psrc, (sx & ALIGNMASK),
    846  1.64   tsutsui 					    (dx & ALIGNMASK), nstart, pdst, rop);
    847  1.64   tsutsui 					pdst++;
    848  1.64   tsutsui 					if (srcStartOver)
    849  1.64   tsutsui 						psrc++;
    850  1.64   tsutsui 				}
    851  1.64   tsutsui 
    852  1.64   tsutsui 				/* special case for aligned operations */
    853  1.64   tsutsui 				if (xoffSrc == 0) {
    854  1.64   tsutsui 					nl = nlMiddle;
    855  1.64   tsutsui 					while (nl--) {
    856  1.64   tsutsui 						switch (rop) {
    857  1.64   tsutsui 						case RR_CLEAR:
    858  1.64   tsutsui 							*pdst = 0;
    859  1.64   tsutsui 							break;
    860  1.64   tsutsui 						case RR_SET:
    861  1.64   tsutsui 							*pdst = ~0;
    862  1.64   tsutsui 							break;
    863  1.64   tsutsui 						default:
    864  1.64   tsutsui 							*pdst = *psrc;
    865  1.64   tsutsui 							break;
    866  1.64   tsutsui 						}
    867  1.64   tsutsui 						psrc++;
    868  1.64   tsutsui 						pdst++;
    869  1.64   tsutsui 					}
    870  1.64   tsutsui 				} else {
    871  1.64   tsutsui 					nl = nlMiddle + 1;
    872  1.64   tsutsui 					while (--nl) {
    873  1.64   tsutsui 						switch (rop) {
    874  1.64   tsutsui 						case RR_CLEAR:
    875  1.64   tsutsui 							*pdst = 0;
    876  1.64   tsutsui 							break;
    877  1.64   tsutsui 						case RR_SET:
    878  1.64   tsutsui 							*pdst = ~0;
    879  1.64   tsutsui 							break;
    880  1.64   tsutsui 						default:
    881  1.64   tsutsui 							getunalignedword(psrc,
    882  1.64   tsutsui 							    xoffSrc, *pdst);
    883  1.64   tsutsui 							break;
    884  1.64   tsutsui 						}
    885  1.64   tsutsui 						pdst++;
    886  1.64   tsutsui 						psrc++;
    887  1.64   tsutsui 					}
    888  1.64   tsutsui 				}
    889  1.64   tsutsui 
    890  1.64   tsutsui 				if (endmask) {
    891  1.64   tsutsui 					getandputrop(psrc, xoffSrc, 0, nend,
    892  1.64   tsutsui 					    pdst, rop);
    893  1.64   tsutsui 				}
    894   1.1     ragge 
    895  1.64   tsutsui 				pdstLine += width;
    896  1.64   tsutsui 				psrcLine += width;
    897  1.64   tsutsui 			}
    898  1.64   tsutsui 		} else {	/* move right to left */
    899  1.64   tsutsui 			pdstLine += ((dx + cx) >> 5);
    900  1.64   tsutsui 			psrcLine += ((sx + cx) >> 5);
    901  1.64   tsutsui 			/*
    902  1.64   tsutsui 			 * If fetch of last partial bits from source crosses
    903  1.64   tsutsui 			 * a longword boundary, start at the previous longword
    904  1.64   tsutsui 			 */
    905  1.64   tsutsui 			if (xoffSrc + nend >= 32)
    906  1.64   tsutsui 				--psrcLine;
    907  1.64   tsutsui 
    908  1.64   tsutsui 			while (cy--) {
    909  1.64   tsutsui 				psrc = psrcLine;
    910  1.64   tsutsui 				pdst = pdstLine;
    911  1.64   tsutsui 
    912  1.64   tsutsui 				if (endmask) {
    913  1.64   tsutsui 					getandputrop(psrc, xoffSrc, 0, nend,
    914  1.64   tsutsui 					    pdst, rop);
    915  1.64   tsutsui 				}
    916  1.64   tsutsui 
    917  1.64   tsutsui 				nl = nlMiddle + 1;
    918  1.64   tsutsui 				while (--nl) {
    919  1.64   tsutsui 					--psrc;
    920  1.64   tsutsui 					--pdst;
    921  1.64   tsutsui 					switch (rop) {
    922  1.64   tsutsui 					case RR_CLEAR:
    923  1.64   tsutsui 						*pdst = 0;
    924  1.64   tsutsui 						break;
    925  1.64   tsutsui 					case RR_SET:
    926  1.64   tsutsui 						*pdst = ~0;
    927  1.64   tsutsui 						break;
    928  1.64   tsutsui 					default:
    929  1.64   tsutsui 						getunalignedword(psrc, xoffSrc,
    930  1.64   tsutsui 						    *pdst);
    931  1.64   tsutsui 						break;
    932  1.64   tsutsui 					}
    933  1.64   tsutsui 				}
    934  1.64   tsutsui 
    935  1.64   tsutsui 				if (startmask) {
    936  1.64   tsutsui 					if (srcStartOver)
    937  1.64   tsutsui 						--psrc;
    938  1.64   tsutsui 					--pdst;
    939  1.64   tsutsui 					getandputrop(psrc, (sx & ALIGNMASK),
    940  1.64   tsutsui 					    (dx & ALIGNMASK), nstart, pdst,
    941  1.64   tsutsui 					    rop);
    942  1.64   tsutsui 				}
    943  1.45        ad 
    944  1.64   tsutsui 				pdstLine += width;
    945  1.64   tsutsui 				psrcLine += width;
    946  1.64   tsutsui 			}
    947  1.64   tsutsui 		}
    948  1.39        he 	}
    949  1.64   tsutsui }
    950  1.64   tsutsui 
    951  1.64   tsutsui static void
    952  1.64   tsutsui smg_copycols(void *cookie, int row, int src, int dst, int n)
    953  1.64   tsutsui {
    954  1.64   tsutsui 	struct rasops_info *ri = cookie;
    955  1.64   tsutsui 
    956  1.64   tsutsui 	n *= ri->ri_font->fontwidth;
    957  1.64   tsutsui 	src *= ri->ri_font->fontwidth;
    958  1.64   tsutsui 	dst *= ri->ri_font->fontwidth;
    959  1.64   tsutsui 	row *= ri->ri_font->fontheight;
    960  1.64   tsutsui 
    961  1.64   tsutsui 	smg_blockmove(ri, src, row, dst, n, ri->ri_font->fontheight,
    962  1.64   tsutsui 	    RR_COPY);
    963  1.64   tsutsui }
    964  1.64   tsutsui 
    965  1.64   tsutsui static void
    966  1.64   tsutsui smg_erasecols(void *cookie, int row, int col, int num, long attr)
    967  1.64   tsutsui {
    968  1.64   tsutsui 	struct rasops_info *ri = cookie;
    969  1.64   tsutsui 	int fg, bg;
    970  1.64   tsutsui 
    971  1.64   tsutsui 	rasops_unpack_attr(attr, &fg, &bg, NULL);
    972  1.64   tsutsui 
    973  1.64   tsutsui 	num *= ri->ri_font->fontwidth;
    974  1.64   tsutsui 	col *= ri->ri_font->fontwidth;
    975  1.64   tsutsui 	row *= ri->ri_font->fontheight;
    976  1.26     ragge 
    977  1.64   tsutsui 	smg_blockmove(ri, col, row, col, num, ri->ri_font->fontheight,
    978  1.64   tsutsui 	    bg == 0 ? RR_CLEAR : RR_SET);
    979   1.1     ragge }
    980   1.1     ragge 
    981  1.18     ragge /*
    982  1.64   tsutsui  * Console support code
    983  1.18     ragge  */
    984  1.64   tsutsui 
    985  1.64   tsutsui cons_decl(smg);
    986  1.64   tsutsui 
    987  1.18     ragge void
    988  1.47      matt smgcnprobe(struct consdev *cndev)
    989   1.1     ragge {
    990  1.32   gehenna 	extern const struct cdevsw wsdisplay_cdevsw;
    991  1.18     ragge 
    992   1.1     ragge 	switch (vax_boardtype) {
    993   1.1     ragge 	case VAX_BTYP_410:
    994   1.1     ragge 	case VAX_BTYP_420:
    995   1.1     ragge 	case VAX_BTYP_43:
    996  1.64   tsutsui 		if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0)
    997  1.64   tsutsui 			break;	/* doesn't use graphics console */
    998  1.64   tsutsui 
    999  1.64   tsutsui 		if ((vax_confdata & KA420_CFG_VIDOPT) != 0)
   1000  1.64   tsutsui 			break;	/* there is a color option */
   1001  1.64   tsutsui 
   1002  1.18     ragge 		cndev->cn_pri = CN_INTERNAL;
   1003  1.63   tsutsui 		cndev->cn_dev =
   1004  1.63   tsutsui 		    makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 0);
   1005  1.18     ragge 		break;
   1006   1.1     ragge 
   1007   1.1     ragge 	default:
   1008   1.1     ragge 		break;
   1009   1.1     ragge 	}
   1010   1.1     ragge }
   1011  1.64   tsutsui 
   1012  1.64   tsutsui /*
   1013  1.64   tsutsui  * Called very early to setup the glass tty as console.
   1014  1.64   tsutsui  * Because it's called before the VM system is initialized, virtual memory
   1015  1.64   tsutsui  * for the framebuffer can be stolen directly without disturbing anything.
   1016  1.64   tsutsui  */
   1017  1.64   tsutsui void
   1018  1.64   tsutsui smgcninit(struct consdev *cndev)
   1019  1.64   tsutsui {
   1020  1.64   tsutsui 	struct smg_screen *ss = &smg_consscr;
   1021  1.64   tsutsui 	vaddr_t ova;
   1022  1.64   tsutsui 	long defattr;
   1023  1.64   tsutsui 	struct rasops_info *ri;
   1024  1.64   tsutsui 	extern vaddr_t virtual_avail;
   1025  1.64   tsutsui 
   1026  1.64   tsutsui 	ova = virtual_avail;
   1027  1.64   tsutsui 
   1028  1.64   tsutsui 	ss->ss_addr = (uint8_t *)virtual_avail;
   1029  1.64   tsutsui 	ioaccess(virtual_avail, SMADDR, SMSIZE / VAX_NBPG);
   1030  1.64   tsutsui 	virtual_avail += SMSIZE;
   1031  1.64   tsutsui 
   1032  1.64   tsutsui 	ss->ss_cursor = (struct dc503reg *)virtual_avail;
   1033  1.64   tsutsui 	ioaccess(virtual_avail, KA420_CUR_BASE, 1);
   1034  1.64   tsutsui 	virtual_avail += VAX_NBPG;
   1035  1.64   tsutsui 
   1036  1.64   tsutsui 	virtual_avail = round_page(virtual_avail);
   1037  1.64   tsutsui 
   1038  1.64   tsutsui 	/* this had better not fail */
   1039  1.64   tsutsui 	if (smg_setup_screen(ss) != 0) {
   1040  1.64   tsutsui 		iounaccess((vaddr_t)ss->ss_addr, SMSIZE / VAX_NBPG);
   1041  1.64   tsutsui 		iounaccess((vaddr_t)ss->ss_cursor, 1);
   1042  1.64   tsutsui 		virtual_avail = ova;
   1043  1.64   tsutsui 		return;
   1044  1.64   tsutsui 	}
   1045  1.64   tsutsui 
   1046  1.64   tsutsui 	ri = &ss->ss_ri;
   1047  1.64   tsutsui 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
   1048  1.64   tsutsui 	wsdisplay_cnattach(&smg_stdscreen, ri, 0, 0, defattr);
   1049  1.64   tsutsui 	cn_tab->cn_pri = CN_INTERNAL;
   1050  1.64   tsutsui 
   1051  1.64   tsutsui #if NDZKBD > 0
   1052  1.64   tsutsui 	dzkbd_cnattach(0); /* Connect keyboard and screen together */
   1053  1.64   tsutsui #endif
   1054  1.64   tsutsui }
   1055