Module Name: src Committed By: martin Date: Wed Feb 15 19:14:50 UTC 2023
Modified Files: src/sys/arch/vax/vsa [netbsd-10]: smg.c Added Files: src/sys/arch/vax/vsa [netbsd-10]: maskbits.h src/sys/dev/ic [netbsd-10]: dc503reg.h Log Message: Pull up following revision(s) (requested by tsutsui in ticket #86): sys/arch/vax/vsa/smg.c: revision 1.64 sys/arch/vax/vsa/maskbits.h: revision 1.1 sys/dev/ic/dc503reg.h: revision 1.1 Port rasops'fied smg(4) framebuffer driver for VS3100 from OpenBSD/vax. This allows using more fonts other than 8x15 pixels on smg(4). Tested on my VAXstation 3100/m30. Note the bitorder of smg(4) VRAM is LSB first (i.e. LSBit is the most left side pixel) and this requires more complicated changes to bitmask ops in MI rasops(9) because several LE machines have VRAMs whose MSBit is connected to the most left side pixel, but for now I prepared smg(4) specific putchar and cursor ops based on old luna68k omrasops. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/vax/vsa/maskbits.h cvs rdiff -u -r1.61.6.2 -r1.61.6.3 src/sys/arch/vax/vsa/smg.c cvs rdiff -u -r0 -r1.1.2.2 src/sys/dev/ic/dc503reg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/vax/vsa/smg.c diff -u src/sys/arch/vax/vsa/smg.c:1.61.6.2 src/sys/arch/vax/vsa/smg.c:1.61.6.3 --- src/sys/arch/vax/vsa/smg.c:1.61.6.2 Sun Feb 12 12:27:26 2023 +++ src/sys/arch/vax/vsa/smg.c Wed Feb 15 19:14:50 2023 @@ -1,4 +1,57 @@ -/* $NetBSD: smg.c,v 1.61.6.2 2023/02/12 12:27:26 martin Exp $ */ +/* $NetBSD: smg.c,v 1.61.6.3 2023/02/15 19:14:50 martin Exp $ */ +/* $OpenBSD: smg.c,v 1.28 2014/12/23 21:39:12 miod Exp $ */ +/* + * Copyright (c) 2006, Miodrag Vallat + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /* * Copyright (c) 1998 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -23,178 +76,157 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1991 University of Utah. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Mark Davies of the Department of Computer + * Science, Victoria University of Wellington, New Zealand. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: grf_hy.c 1.2 93/08/13$ + * + * @(#)grf_hy.c 8.4 (Berkeley) 1/12/94 + */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.61.6.2 2023/02/12 12:27:26 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.61.6.3 2023/02/15 19:14:50 martin Exp $"); -#include "opt_wsfont.h" #include "dzkbd.h" #include "wsdisplay.h" #include <sys/param.h> -#include <sys/systm.h> -#include <sys/callout.h> -#include <sys/conf.h> -#include <sys/cpu.h> #include <sys/device.h> -#include <sys/kernel.h> +#include <sys/systm.h> #include <sys/kmem.h> -#include <sys/time.h> +#include <sys/conf.h> #include <machine/vsbus.h> #include <machine/sid.h> +#include <machine/cpu.h> #include <machine/ka420.h> #include <machine/scb.h> #include <dev/cons.h> +#include <dev/ic/dc503reg.h> + #include <dev/dec/dzreg.h> #include <dev/dec/dzvar.h> #include <dev/dec/dzkbdvar.h> -#include <dev/wscons/wsdisplayvar.h> #include <dev/wscons/wsconsio.h> -#include <dev/wscons/wscons_callbacks.h> -#include <dev/wsfont/wsfont.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/rasops/rasops.h> /* Screen hardware defs */ -#define SM_COLS 128 /* char width of screen */ -#define SM_ROWS 57 /* rows of char on screen */ -#define SM_CHEIGHT 15 /* lines a char consists of */ -#define SM_NEXTROW (SM_COLS * SM_CHEIGHT) -#define SM_YWIDTH 864 #define SM_XWIDTH 1024 - -/* Cursor register definitions */ -#define CUR_CMD 0 -#define CUR_XPOS 4 -#define CUR_YPOS 8 -#define CUR_XMIN_1 12 -#define CUR_XMAX_1 16 -#define CUR_YMIN_1 20 -#define CUR_YMAX_1 24 -#define CUR_XMIN_2 28 -#define CUR_XMAX_2 32 -#define CUR_YMIN_2 36 -#define CUR_YMAX_2 40 -#define CUR_LOAD 44 - -#define CUR_CMD_TEST 0x8000 -#define CUR_CMD_HSHI 0x4000 -#define CUR_CMD_VBHI 0x2000 -#define CUR_CMD_LODSA 0x1000 -#define CUR_CMD_FORG2 0x0800 -#define CUR_CMD_ENRG2 0x0400 -#define CUR_CMD_FORG1 0x0200 -#define CUR_CMD_ENRG1 0x0100 -#define CUR_CMD_XHWID 0x0080 -#define CUR_CMD_XHCL1 0x0040 -#define CUR_CMD_XHCLP 0x0020 -#define CUR_CMD_XHAIR 0x0010 -#define CUR_CMD_FOPB 0x0008 -#define CUR_CMD_ENPB 0x0004 -#define CUR_CMD_FOPA 0x0002 -#define CUR_CMD_ENPA 0x0001 +#define SM_YWIDTH 864 #define CUR_XBIAS 216 /* Add to cursor position */ -#define CUR_YBIAS 33 +#define CUR_YBIAS 33 -#define WRITECUR(addr, val) *(volatile uint16_t *)(curaddr + (addr)) = (val) -static char *curaddr; -static uint16_t curcmd, curx, cury, hotX, hotY; -static int bgmask, fgmask; +static int smg_match(device_t, cfdata_t, void *); +static void smg_attach(device_t, device_t, void *); -static int smg_match(device_t, cfdata_t, void *); -static void smg_attach(device_t, device_t, void *); +struct smg_screen { + struct rasops_info ss_ri; + uint8_t *ss_addr; /* frame buffer address */ + struct dc503reg *ss_cursor; /* cursor registers */ + uint16_t ss_curcmd; + struct wsdisplay_curpos ss_curpos, ss_curhot; + uint16_t ss_curimg[PCC_CURSOR_SIZE]; + uint16_t ss_curmask[PCC_CURSOR_SIZE]; +}; -CFATTACH_DECL_NEW(smg, 0, - smg_match, smg_attach, NULL, NULL); +/* for console */ +static struct smg_screen smg_consscr; -static void smg_cursor(void *, int, int, int); -static int smg_mapchar(void *, int, unsigned int *); -static void smg_putchar(void *, int, int, u_int, long); -static void smg_copycols(void *, int, int, int,int); -static void smg_erasecols(void *, int, int, int, long); -static void smg_copyrows(void *, int, int, int); -static void smg_eraserows(void *, int, int, long); -static int smg_allocattr(void *, int, int, int, long *); - -const struct wsdisplay_emulops smg_emulops = { - .cursor = smg_cursor, - .mapchar = smg_mapchar, - .putchar = smg_putchar, - .copycols = smg_copycols, - .erasecols = smg_erasecols, - .copyrows = smg_copyrows, - .eraserows = smg_eraserows, - .allocattr = smg_allocattr +struct smg_softc { + device_t sc_dev; + struct smg_screen *sc_scr; + int sc_nscreens; }; -const struct wsscreen_descr smg_stdscreen = { - .name = "128x57", - .ncols = SM_COLS, - .nrows = SM_ROWS, - .textops = &smg_emulops, - .fontwidth = 8, - .fontheight = SM_CHEIGHT, - .capabilities = WSSCREEN_UNDERLINE|WSSCREEN_REVERSE, +CFATTACH_DECL_NEW(smg, sizeof(struct smg_softc), + smg_match, smg_attach, NULL, NULL); + +static struct wsscreen_descr smg_stdscreen = { + .name = "std", }; -const struct wsscreen_descr *_smg_scrlist[] = { +static const struct wsscreen_descr *_smg_scrlist[] = { &smg_stdscreen, }; -const struct wsscreen_list smg_screenlist = { - .nscreens = __arraycount(_smg_scrlist), +static const struct wsscreen_list smg_screenlist = { + .nscreens = sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *), .screens = _smg_scrlist, }; -static char *sm_addr; - -static u_char *qf; +static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *); +static paddr_t smg_mmap(void *, void *, off_t, int); +static int smg_alloc_screen(void *, const struct wsscreen_descr *, + void **, int *, int *, long *); +static void smg_free_screen(void *, void *); +static int smg_show_screen(void *, void *, int, void (*) (void *, int, int), + void *); -#define QCHAR(c) (c < 32 ? 32 : (c > 127 ? c - 66 : c - 32)) -#define QFONT(c,line) qf[QCHAR(c) * 15 + line] -#define SM_ADDR(row, col, line) \ - sm_addr[col + (row * SM_CHEIGHT * SM_COLS) + line * SM_COLS] - - -static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *); -static paddr_t smg_mmap(void *, void *, off_t, int); -static int smg_alloc_screen(void *, const struct wsscreen_descr *, - void **, int *, int *, long *); -static void smg_free_screen(void *, void *); -static int smg_show_screen(void *, void *, int, - void (*) (void *, int, int), void *); -static void smg_crsr_blink(void *); - -const struct wsdisplay_accessops smg_accessops = { +static const struct wsdisplay_accessops smg_accessops = { .ioctl = smg_ioctl, .mmap = smg_mmap, .alloc_screen = smg_alloc_screen, .free_screen = smg_free_screen, .show_screen = smg_show_screen, + .load_font = NULL }; -struct smg_screen { - int ss_curx; - int ss_cury; - u_char ss_image[SM_ROWS][SM_COLS]; /* Image of current screen */ - u_char ss_attr[SM_ROWS][SM_COLS]; /* Reversed etc... */ -}; - -static struct smg_screen smg_conscreen; -static struct smg_screen *curscr; - -static callout_t smg_cursor_ch; +static void smg_putchar(void *, int, int, u_int, long); +static void smg_cursor(void *, int, int, int); +static void smg_blockmove(struct rasops_info *, u_int, u_int, u_int, u_int, + u_int, int); +static void smg_copycols(void *, int, int, int, int); +static void smg_erasecols(void *, int, int, int, long); + +static int smg_getcursor(struct smg_screen *, struct wsdisplay_cursor *); +static int smg_setup_screen(struct smg_screen *); +static int smg_setcursor(struct smg_screen *, struct wsdisplay_cursor *); +static void smg_updatecursor(struct smg_screen *, u_int); -int +static int smg_match(device_t parent, cfdata_t cf, void *aux) { - struct vsbus_attach_args * const va = aux; - volatile uint16_t *ccmd; - volatile uint16_t *cfgtst; - uint16_t tmp, tmp2; + struct vsbus_attach_args *va = aux; + volatile short *curcmd; + volatile short *cfgtst; + short tmp, tmp2; switch (vax_boardtype) { default: @@ -209,6 +241,7 @@ smg_match(device_t parent, cfdata_t cf, /* not present on microvaxes */ if ((vax_confdata & KA420_CFG_MULTU) != 0) return 0; + /* * If the color option board is present, do not attach * unless we are explicitely asked to via device flags. @@ -235,12 +268,12 @@ smg_match(device_t parent, cfdata_t cf, * Try to find the cursor chip by testing the flip-flop. * If nonexistent, no glass tty. */ - ccmd = (uint16_t *)va->va_addr; - cfgtst = (uint16_t *)vax_map_physmem(VS_CFGTST, 1); - ccmd[0] = CUR_CMD_HSHI|CUR_CMD_FOPB; + curcmd = (short *)va->va_addr; + cfgtst = (short *)vax_map_physmem(VS_CFGTST, 1); + curcmd[0] = PCCCMD_HSHI | PCCCMD_FOPB; DELAY(300000); tmp = cfgtst[0]; - ccmd[0] = CUR_CMD_TEST|CUR_CMD_HSHI; + curcmd[0] = PCCCMD_TEST | PCCCMD_HSHI; DELAY(300000); tmp2 = cfgtst[0]; vax_unmap_physmem((vaddr_t)cfgtst, 1); @@ -252,260 +285,136 @@ smg_match(device_t parent, cfdata_t cf, } } -void +static void smg_attach(device_t parent, device_t self, void *aux) { + struct smg_softc *sc = device_private(self); + struct smg_screen *scr; struct wsemuldisplaydev_attach_args aa; - struct wsdisplay_font *console_font; - int fcookie; + int console; - aprint_normal("\n"); - sm_addr = (void *)vax_map_physmem(SMADDR, (SMSIZE/VAX_NBPG)); - curaddr = (void *)vax_map_physmem(KA420_CUR_BASE, 1); - if (sm_addr == 0) { - aprint_error_dev(self, "Couldn't alloc graphics memory.\n"); - return; - } - if (curscr == NULL) - callout_init(&smg_cursor_ch, 0); - curscr = &smg_conscreen; - aa.console = + console = #if NWSDISPLAY > 0 (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0 && cn_tab->cn_putc == wsdisplay_cnputc; #else (vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0; #endif + if (console) { + scr = &smg_consscr; + sc->sc_nscreens = 1; + } else { + scr = kmem_zalloc(sizeof(*scr), KM_SLEEP); - aa.scrdata = &smg_screenlist; - aa.accessops = &smg_accessops; - callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL); - curcmd = CUR_CMD_HSHI; - WRITECUR(CUR_CMD, curcmd); - wsfont_init(); - if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, - WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) { - aprint_error_dev(self, "could not find 8x15 font\n"); - return; - } - if (wsfont_lock(fcookie, &console_font) != 0) { - aprint_error_dev(self, "could not lock 8x15 font\n"); - return; - } - qf = console_font->data; - - config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); -} - -static u_char *cursor; -static int cur_on; - -static void -smg_crsr_blink(void *arg) -{ - if (cur_on) - *cursor ^= 255; - callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL); -} - -void -smg_cursor(void *id, int on, int row, int col) -{ - struct smg_screen * const ss = id; + scr->ss_addr = + (void *)vax_map_physmem(SMADDR, SMSIZE / VAX_NBPG); + if (scr->ss_addr == NULL) { + aprint_error(": can not map frame buffer\n"); + kmem_free(scr, sizeof(*scr)); + return; + } - if (ss == curscr) { - SM_ADDR(ss->ss_cury, ss->ss_curx, 14) = - QFONT(ss->ss_image[ss->ss_cury][ss->ss_curx], 14); - cursor = &SM_ADDR(row, col, 14); - if ((cur_on = on)) - *cursor ^= 255; - } - ss->ss_curx = col; - ss->ss_cury = row; -} + scr->ss_cursor = + (struct dc503reg *)vax_map_physmem(KA420_CUR_BASE, 1); + if (scr->ss_cursor == NULL) { + aprint_error(": can not map cursor chip\n"); + vax_unmap_physmem((vaddr_t)scr->ss_addr, + SMSIZE / VAX_NBPG); + kmem_free(scr, sizeof(*scr)); + return; + } -int -smg_mapchar(void *id, int uni, unsigned int *index) -{ - if (uni < 256) { - *index = uni; - return (5); + if (smg_setup_screen(scr) != 0) { + aprint_error(": initialization failed\n"); + vax_unmap_physmem((vaddr_t)scr->ss_cursor, 1); + vax_unmap_physmem((vaddr_t)scr->ss_addr, + SMSIZE / VAX_NBPG); + kmem_free(scr, sizeof(*scr)); + return; + } } - *index = ' '; - return (0); -} - -static void -smg_putchar(void *id, int row, int col, u_int c, long attr) -{ - struct smg_screen * const ss = id; - int i; - - c &= 0xff; - - ss->ss_image[row][col] = c; - ss->ss_attr[row][col] = attr; - if (ss != curscr) - return; - for (i = 0; i < 15; i++) { - unsigned char ch = QFONT(c, i); + sc->sc_scr = scr; - SM_ADDR(row, col, i) = (attr & WSATTR_REVERSE ? ~ch : ch); - - } - if (attr & WSATTR_UNDERLINE) - SM_ADDR(row, col, 14) ^= SM_ADDR(row, col, 14); -} + aprint_normal("\n"); + aprint_normal_dev(self, "%dx%d on-board monochrome framebuffer\n", + SM_XWIDTH, SM_YWIDTH); -/* - * copies columns inside a row. - */ -static void -smg_copycols(void *id, int row, int srccol, int dstcol, int ncols) -{ - struct smg_screen * const ss = id; - int i; + aa.console = console; + aa.scrdata = &smg_screenlist; + aa.accessops = &smg_accessops; + aa.accesscookie = sc; - memcpy(&ss->ss_image[row][dstcol], &ss->ss_image[row][srccol], ncols); - memcpy(&ss->ss_attr[row][dstcol], &ss->ss_attr[row][srccol], ncols); - if (ss != curscr) - return; - for (i = 0; i < SM_CHEIGHT; i++) - memcpy(&SM_ADDR(row, dstcol, i), &SM_ADDR(row, srccol, i), ncols); + config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); } /* - * Erases a bunch of chars inside one row. + * Initialize anything necessary for an emulating wsdisplay to work (i.e. + * pick a font, initialize a rasops structure, setup the accessops callbacks.) */ -static void -smg_erasecols(void *id, int row, int startcol, int ncols, long fillattr) +static int +smg_setup_screen(struct smg_screen *ss) { - struct smg_screen * const ss = id; - int i; + struct rasops_info *ri = &ss->ss_ri; + int cookie; - memset(&ss->ss_image[row][startcol], 0, ncols); - memset(&ss->ss_attr[row][startcol], 0, ncols); - if (ss != curscr) - return; - for (i = 0; i < SM_CHEIGHT; i++) - memset(&SM_ADDR(row, startcol, i), 0, ncols); -} + memset(ri, 0, sizeof(*ri)); + ri->ri_depth = 1; + ri->ri_width = SM_XWIDTH; + ri->ri_height = SM_YWIDTH; + ri->ri_stride = SM_XWIDTH >> 3; + ri->ri_flg = RI_CLEAR | RI_CENTER; + ri->ri_bits = (void *)ss->ss_addr; + ri->ri_hw = ss; + if (ss == &smg_consscr) + ri->ri_flg |= RI_NO_AUTO; -static void -smg_copyrows(void *id, int srcrow, int dstrow, int nrows) -{ - struct smg_screen * const ss = id; - int frows; + wsfont_init(); + cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, + WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP); + if (cookie < 0) + cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L, + WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP); + if (cookie < 0) + cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, + WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP); + if (cookie < 0) + return -1; + if (wsfont_lock(cookie, &ri->ri_font) != 0) + return -1; + ri->ri_wsfcookie = cookie; - memcpy(&ss->ss_image[dstrow][0], &ss->ss_image[srcrow][0], - nrows * SM_COLS); - memcpy(&ss->ss_attr[dstrow][0], &ss->ss_attr[srcrow][0], - nrows * SM_COLS); - if (ss != curscr) - return; - if (nrows > 25) { - frows = nrows >> 1; - if (srcrow > dstrow) { - bcopy(&sm_addr[(srcrow * SM_NEXTROW)], - &sm_addr[(dstrow * SM_NEXTROW)], - frows * SM_NEXTROW); - bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)], - &sm_addr[((dstrow + frows) * SM_NEXTROW)], - (nrows - frows) * SM_NEXTROW); - } else { - bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)], - &sm_addr[((dstrow + frows) * SM_NEXTROW)], - (nrows - frows) * SM_NEXTROW); - bcopy(&sm_addr[(srcrow * SM_NEXTROW)], - &sm_addr[(dstrow * SM_NEXTROW)], - frows * SM_NEXTROW); - } - } else - bcopy(&sm_addr[(srcrow * SM_NEXTROW)], - &sm_addr[(dstrow * SM_NEXTROW)], nrows * SM_NEXTROW); -} + /* + * Ask for an unholy big display, rasops will trim this to more + * reasonable values. + */ + if (rasops_init(ri, 160, 160) != 0) + return -1; -static void -smg_eraserows(void *id, int startrow, int nrows, long fillattr) -{ - struct smg_screen * const ss = id; - int frows; + ri->ri_ops.cursor = smg_cursor; + ri->ri_ops.putchar = smg_putchar; + ri->ri_ops.copycols = smg_copycols; + ri->ri_ops.erasecols = smg_erasecols; + + smg_stdscreen.ncols = ri->ri_cols; + smg_stdscreen.nrows = ri->ri_rows; + smg_stdscreen.textops = &ri->ri_ops; + smg_stdscreen.fontwidth = ri->ri_font->fontwidth; + smg_stdscreen.fontheight = ri->ri_font->fontheight; + smg_stdscreen.capabilities = ri->ri_caps; - memset(&ss->ss_image[startrow][0], 0, nrows * SM_COLS); - memset(&ss->ss_attr[startrow][0], 0, nrows * SM_COLS); - if (ss != curscr) - return; - if (nrows > 25) { - frows = nrows >> 1; - memset(&sm_addr[(startrow * SM_NEXTROW)], 0, frows * SM_NEXTROW); - memset(&sm_addr[((startrow + frows) * SM_NEXTROW)], 0, - (nrows - frows) * SM_NEXTROW); - } else - memset(&sm_addr[(startrow * SM_NEXTROW)], 0, nrows * SM_NEXTROW); -} + ss->ss_curcmd = PCCCMD_HSHI; + ss->ss_cursor->cmdr = ss->ss_curcmd; -static int -smg_allocattr(void *id, int fg, int bg, int flags, long *attrp) -{ - *attrp = flags; return 0; } -static void -setcursor(struct wsdisplay_cursor *v) -{ - uint16_t red, green, blue; - uint32_t curfg[16], curmask[16]; - int i; - - /* Enable cursor */ - if (v->which & WSDISPLAY_CURSOR_DOCUR) { - if (v->enable) - curcmd |= CUR_CMD_ENPB|CUR_CMD_ENPA; - else - curcmd &= ~(CUR_CMD_ENPB|CUR_CMD_ENPA); - WRITECUR(CUR_CMD, curcmd); - } - if (v->which & WSDISPLAY_CURSOR_DOHOT) { - hotX = v->hot.x; - hotY = v->hot.y; - } - if (v->which & WSDISPLAY_CURSOR_DOCMAP) { - /* First background */ - if (copyin(v->cmap.red, &red, sizeof(red)) == 0 && - copyin(v->cmap.green, &green, sizeof(green)) == 0 && - copyin(v->cmap.blue, &blue, sizeof(blue)) == 0) { - bgmask = (((30L * red + 59L * green + 11L * blue) >> 8) - >= (((1<<8)-1)*50)) ? ~0 : 0; - } - if (copyin(v->cmap.red + 2, &red, sizeof(red)) == 0 && - copyin(v->cmap.green + 2, &green, sizeof(green)) == 0 && - copyin(v->cmap.blue + 2, &blue, sizeof(blue)) == 0) { - fgmask = (((30L * red + 59L * green + 11L * blue) >> 8) - >= (((1<<8)-1)*50)) ? ~0 : 0; - } - } - if (v->which & WSDISPLAY_CURSOR_DOSHAPE) { - WRITECUR(CUR_CMD, curcmd | CUR_CMD_LODSA); - copyin(v->image, curfg, sizeof(curfg)); - copyin(v->mask, curmask, sizeof(curmask)); - for (i = 0; i < sizeof(curfg)/sizeof(curfg[0]); i++) { - WRITECUR(CUR_LOAD, ((uint16_t)curfg[i] & fgmask) | - (((uint16_t)curmask[i] & (uint16_t)~curfg[i]) - & bgmask)); - } - for (i = 0; i < sizeof(curmask)/sizeof(curmask[0]); i++) { - WRITECUR(CUR_LOAD, (uint16_t)curmask[i]); - } - WRITECUR(CUR_CMD, curcmd); - } -} - -int +static int smg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) { - struct wsdisplay_fbinfo *fb = (void *)data; - static uint16_t curc; + struct smg_softc *sc = v; + struct smg_screen *ss = sc->sc_scr; + struct wsdisplay_fbinfo *wdf; + struct wsdisplay_curpos *pos; switch (cmd) { case WSDISPLAYIO_GTYPE: @@ -513,48 +422,45 @@ smg_ioctl(void *v, void *vs, u_long cmd, break; case WSDISPLAYIO_GINFO: - fb->height = SM_YWIDTH; - fb->width = SM_XWIDTH; - fb->depth = 1; - fb->cmsize = 2; + wdf = (struct wsdisplay_fbinfo *)data; + wdf->height = ss->ss_ri.ri_height; + wdf->width = ss->ss_ri.ri_width; + wdf->depth = ss->ss_ri.ri_depth; + wdf->cmsize = 0; break; - case WSDISPLAYIO_SVIDEO: - if (*(u_int *)data == WSDISPLAYIO_VIDEO_ON) { - curcmd = curc; - } else { - curc = curcmd; - curcmd &= ~(CUR_CMD_FOPA|CUR_CMD_ENPA); - curcmd |= CUR_CMD_FOPB; - } - WRITECUR(CUR_CMD, curcmd); + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = ss->ss_ri.ri_stride; break; + case WSDISPLAYIO_GETCMAP: + case WSDISPLAYIO_PUTCMAP: case WSDISPLAYIO_GVIDEO: - *(u_int *)data = (curcmd & CUR_CMD_FOPB ? - WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON); + case WSDISPLAYIO_SVIDEO: break; - case WSDISPLAYIO_SCURSOR: - setcursor((struct wsdisplay_cursor *)data); + case WSDISPLAYIO_GCURPOS: + pos = (struct wsdisplay_curpos *)data; + pos->x = ss->ss_curpos.x; + pos->y = ss->ss_curpos.y; break; case WSDISPLAYIO_SCURPOS: - curx = ((struct wsdisplay_curpos *)data)->x; - cury = ((struct wsdisplay_curpos *)data)->y; - WRITECUR(CUR_XPOS, curx + CUR_XBIAS); - WRITECUR(CUR_YPOS, cury + CUR_YBIAS); - break; - - case WSDISPLAYIO_GCURPOS: - ((struct wsdisplay_curpos *)data)->x = curx; - ((struct wsdisplay_curpos *)data)->y = cury; + pos = (struct wsdisplay_curpos *)data; + ss->ss_curpos.x = pos->x; + ss->ss_curpos.y = pos->y; + smg_updatecursor(ss, WSDISPLAY_CURSOR_DOPOS); break; case WSDISPLAYIO_GCURMAX: - ((struct wsdisplay_curpos *)data)->x = 16; - ((struct wsdisplay_curpos *)data)->y = 16; - break; + pos = (struct wsdisplay_curpos *)data; + pos->x = pos->y = PCC_CURSOR_SIZE; + + case WSDISPLAYIO_GCURSOR: + return smg_getcursor(ss, (struct wsdisplay_cursor *)data); + + case WSDISPLAYIO_SCURSOR: + return smg_setcursor(ss, (struct wsdisplay_cursor *)data); default: return EPASSTHROUGH; @@ -565,103 +471,519 @@ smg_ioctl(void *v, void *vs, u_long cmd, static paddr_t smg_mmap(void *v, void *vs, off_t offset, int prot) { + if (offset >= SMSIZE || offset < 0) return -1; - return (SMADDR + offset) >> PGSHIFT; + + return SMADDR + offset; } -int +static int smg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, int *curxp, int *curyp, long *defattrp) { - *cookiep = kmem_zalloc(sizeof(struct smg_screen), KM_SLEEP); - *curxp = *curyp = *defattrp = 0; + struct smg_softc *sc = v; + struct smg_screen *ss = sc->sc_scr; + struct rasops_info *ri = &ss->ss_ri; + + if (sc->sc_nscreens > 0) + return ENOMEM; + + *cookiep = ri; + *curxp = *curyp = 0; + (*ri->ri_ops.allocattr)(ri, 0, 0, 0, defattrp); + sc->sc_nscreens++; + return 0; } -void +static void smg_free_screen(void *v, void *cookie) { + struct smg_softc *sc = v; + + sc->sc_nscreens--; } -int +static int smg_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), void *cbarg) { - struct smg_screen *ss = cookie; - int row, col, line; - if (ss == curscr) - return (0); + return 0; +} + +static int +smg_getcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc) +{ + int error; + + if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0) + wdc->enable = ss->ss_curcmd & PCCCMD_ENPA ? 1 : 0; + if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) { + wdc->pos.x = ss->ss_curpos.x; + wdc->pos.y = ss->ss_curpos.y; + } + if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) { + wdc->hot.x = ss->ss_curhot.x; + wdc->hot.y = ss->ss_curhot.y; + } + if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) { + wdc->cmap.index = 0; + wdc->cmap.count = 0; + } + if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) { + wdc->size.x = wdc->size.y = PCC_CURSOR_SIZE; + error = copyout(ss->ss_curimg, wdc->image, + sizeof(ss->ss_curimg)); + if (error != 0) + return error; + error = copyout(ss->ss_curmask, wdc->mask, + sizeof(ss->ss_curmask)); + if (error != 0) + return error; + } - for (row = 0; row < SM_ROWS; row++) - for (line = 0; line < SM_CHEIGHT; line++) { - for (col = 0; col < SM_COLS; col++) { - u_char s, c = ss->ss_image[row][col]; - - if (c < 32) - c = 32; - s = QFONT(c, line); - if (ss->ss_attr[row][col] & WSATTR_REVERSE) - s ^= 255; - SM_ADDR(row, col, line) = s; - if (ss->ss_attr[row][col] & WSATTR_UNDERLINE) - SM_ADDR(row, col, line) = 255; - } - } - cursor = &sm_addr[(ss->ss_cury * SM_CHEIGHT * SM_COLS) + ss->ss_curx + - ((SM_CHEIGHT - 1) * SM_COLS)]; - curscr = ss; - return (0); + return 0; } -cons_decl(smg); +static int +smg_setcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc) +{ + uint16_t curfg[PCC_CURSOR_SIZE], curmask[PCC_CURSOR_SIZE]; + int error; -void -smgcninit(struct consdev *cndev) + if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) { + /* No cursor colormap since we are a B&W device. */ + if (wdc->cmap.count != 0) + return EINVAL; + } + + /* + * First, do the userland-kernel data transfers, so that we can fail + * if necessary before altering anything. + */ + if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) { + if (wdc->size.x != PCC_CURSOR_SIZE || + wdc->size.y != PCC_CURSOR_SIZE) + return EINVAL; + error = copyin(wdc->image, curfg, sizeof(curfg)); + if (error != 0) + return error; + error = copyin(wdc->mask, curmask, sizeof(curmask)); + if (error != 0) + return error; + } + + /* + * Now update our variables... + */ + if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0) { + if (wdc->enable) + ss->ss_curcmd |= PCCCMD_ENPB | PCCCMD_ENPA; + else + ss->ss_curcmd &= ~(PCCCMD_ENPB | PCCCMD_ENPA); + } + if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) { + ss->ss_curpos.x = wdc->pos.x; + ss->ss_curpos.y = wdc->pos.y; + } + if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) { + ss->ss_curhot.x = wdc->hot.x; + ss->ss_curhot.y = wdc->hot.y; + } + if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) { + memcpy(ss->ss_curimg, curfg, sizeof(ss->ss_curimg)); + memcpy(ss->ss_curmask, curmask, sizeof(ss->ss_curmask)); + } + + /* + * ...and update the cursor + */ + smg_updatecursor(ss, wdc->which); + + return 0; +} + +static void +smg_updatecursor(struct smg_screen *ss, u_int which) { - int fcookie; - struct wsdisplay_font *console_font; - extern vaddr_t virtual_avail; - extern int dz_vsbus_lk201_cnattach(int); + u_int i; - sm_addr = (void *)virtual_avail; - ioaccess((vaddr_t)sm_addr, SMADDR, (SMSIZE / VAX_NBPG)); - virtual_avail += SMSIZE; + if ((which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) { + ss->ss_cursor->xpos = + ss->ss_curpos.x - ss->ss_curhot.x + CUR_XBIAS; + ss->ss_cursor->ypos = + ss->ss_curpos.y - ss->ss_curhot.y + CUR_YBIAS; + } + if ((which & WSDISPLAY_CURSOR_DOSHAPE) != 0) { + ss->ss_cursor->cmdr = ss->ss_curcmd | PCCCMD_LODSA; + for (i = 0; i < PCC_CURSOR_SIZE; i++) + ss->ss_cursor->load = ss->ss_curimg[i]; + for (i = 0; i < PCC_CURSOR_SIZE; i++) + ss->ss_cursor->load = ss->ss_curmask[i]; + ss->ss_cursor->cmdr = ss->ss_curcmd; + } else + if ((which & WSDISPLAY_CURSOR_DOCUR) != 0) + ss->ss_cursor->cmdr = ss->ss_curcmd; +} - virtual_avail = round_page(virtual_avail); +/* + * Faster console operations + */ - /* Clear screen */ - memset(sm_addr, 0, 128*864); +#include <vax/vsa/maskbits.h> - callout_init(&smg_cursor_ch, 0); +/* putchar() and cursor() ops are taken from luna68k omrasops.c */ - curscr = &smg_conscreen; - wsdisplay_cnattach(&smg_stdscreen, &smg_conscreen, 0, 0, 0); - cn_tab->cn_pri = CN_INTERNAL; - wsfont_init(); - if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, - WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) - { - printf("smg: could not find 8x15 font\n"); - return; +#define ALL1BITS (~0U) +#define ALL0BITS (0U) +#define BLITWIDTH (32) +#define ALIGNMASK (0x1f) +#define BYTESDONE (4) + +static void +smg_putchar(void *cookie, int row, int startcol, u_int uc, long attr) +{ + struct rasops_info *ri = cookie; + uint8_t *p; + int scanspan, startx, height, width, align, y; + uint32_t lmask, rmask, glyph, inverse; + int i; + uint8_t *fb; + + scanspan = ri->ri_stride; + y = ri->ri_font->fontheight * row; + startx = ri->ri_font->fontwidth * startcol; + height = ri->ri_font->fontheight; + fb = (uint8_t *)ri->ri_font->data + + (uc - ri->ri_font->firstchar) * ri->ri_fontscale; + inverse = ((attr & WSATTR_REVERSE) != 0) ? ALL1BITS : ALL0BITS; + + p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); + align = startx & ALIGNMASK; + width = ri->ri_font->fontwidth + align; + /* lmask and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */ + lmask = ALL1BITS << align; + rmask = ALL1BITS >> (-width & ALIGNMASK); + if (width <= BLITWIDTH) { + uint32_t mask = lmask & rmask; + while (height > 0) { + uint32_t image; + /* + * The font glyph is stored in byteorder and bitorder + * WSDISPLAY_FONTORDER_R2L to use proper shift ops. + * On the other hand, VRAM data is stored in + * WSDISPLAY_FONTORDER_R2L bitorder and + * WSDIPPLAY_FONTORDER_L2R byteorder. + */ + glyph = 0; + for (i = ri->ri_font->stride; i != 0; i--) + glyph = (glyph << 8) | *fb++; + glyph = (glyph << align) ^ inverse; + image = *(uint32_t *)p; + *(uint32_t *)p = (image & ~mask) | (glyph & mask); + p += scanspan; + height--; + } + } else { + uint8_t *q = p; + uint32_t lhalf, rhalf; + + while (height > 0) { + uint32_t image; + glyph = 0; + for (i = ri->ri_font->stride; i != 0; i--) + glyph = (glyph << 8) | *fb++; + lhalf = (glyph << align) ^ inverse; + image = *(uint32_t *)p; + *(uint32_t *)p = (image & ~lmask) | (lhalf & lmask); + p += BYTESDONE; + rhalf = (glyph >> (BLITWIDTH - align)) ^ inverse; + image = *(uint32_t *)p; + *(uint32_t *)p = (rhalf & rmask) | (image & ~rmask); + + p = (q += scanspan); + height--; + } } - if (wsfont_lock(fcookie, &console_font) != 0) { - printf("smg: could not lock 8x15 font\n"); - return; +} + +static void +smg_cursor(void *cookie, int on, int row, int col) +{ + struct rasops_info *ri = cookie; + uint8_t *p; + int scanspan, startx, height, width, align, y; + uint32_t lmask, rmask, image; + + if (!on) { + /* make sure it's on */ + if ((ri->ri_flg & RI_CURSOR) == 0) + return; + + row = ri->ri_crow; + col = ri->ri_ccol; + } else { + /* unpaint the old copy. */ + ri->ri_crow = row; + ri->ri_ccol = col; } - qf = console_font->data; -#if NDZKBD > 0 - dzkbd_cnattach(0); /* Connect keyboard and screen together */ -#endif + scanspan = ri->ri_stride; + y = ri->ri_font->fontheight * row; + startx = ri->ri_font->fontwidth * col; + height = ri->ri_font->fontheight; + + p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); + align = startx & ALIGNMASK; + width = ri->ri_font->fontwidth + align; + /* lmask and rmask are in WSDISPLAY_FONTORDER_R2L bitorder */ + lmask = ALL1BITS << align; + rmask = ALL1BITS >> (-width & ALIGNMASK); + if (width <= BLITWIDTH) { + uint32_t mask = lmask & rmask; + while (height > 0) { + image = *(uint32_t *)p; + *(uint32_t *)p = + (image & ~mask) | ((image ^ ALL1BITS) & mask); + p += scanspan; + height--; + } + } else { + uint8_t *q = p; + + while (height > 0) { + image = *(uint32_t *)p; + *(uint32_t *)p = + (image & ~lmask) | ((image ^ ALL1BITS) & lmask); + p += BYTESDONE; + image = *(uint32_t *)p; + *(uint32_t *)p = + ((image ^ ALL1BITS) & rmask) | (image & ~rmask); + + p = (q += scanspan); + height--; + } + } + ri->ri_flg ^= RI_CURSOR; +} + +static void +smg_blockmove(struct rasops_info *ri, u_int sx, u_int y, u_int dx, u_int cx, + u_int cy, int rop) +{ + int width; /* add to get to same position in next line */ + + unsigned int *psrcLine, *pdstLine; + /* pointers to line with current src and dst */ + unsigned int *psrc; /* pointer to current src longword */ + unsigned int *pdst; /* pointer to current dst longword */ + + /* following used for looping through a line */ + unsigned int startmask, endmask; /* masks for writing ends of dst */ + int nlMiddle; /* whole longwords in dst */ + int nl; /* temp copy of nlMiddle */ + int xoffSrc; /* offset (>= 0, < 32) from which to + fetch whole longwords fetched in src */ + int nstart; /* number of ragged bits at start of dst */ + int nend; /* number of ragged bits at end of dst */ + int srcStartOver; /* pulling nstart bits from src + overflows into the next word? */ + + width = SM_XWIDTH >> 5; + + /* start at first scanline */ + psrcLine = pdstLine = ((u_int *)ri->ri_bits) + (y * width); + + /* x direction doesn't matter for < 1 longword */ + if (cx <= 32) { + int srcBit, dstBit; /* bit offset of src and dst */ + + pdstLine += (dx >> 5); + psrcLine += (sx >> 5); + psrc = psrcLine; + pdst = pdstLine; + + srcBit = sx & ALIGNMASK; + dstBit = dx & ALIGNMASK; + + while (cy--) { + getandputrop(psrc, srcBit, dstBit, cx, pdst, rop); + pdst += width; + psrc += width; + } + } else { + startmask = ALL1BITS << (dx & ALIGNMASK); + endmask = ALL1BITS >> (~cx & ALIGNMASK); + if (startmask) + nlMiddle = (cx - (32 - (dx & ALIGNMASK))) >> 5; + else + nlMiddle = cx >> 5; + + if (startmask) + nstart = 32 - (dx & ALIGNMASK); + else + nstart = 0; + if (endmask) + nend = (dx + cx) & ALIGNMASK; + else + nend = 0; + + xoffSrc = ((sx & ALIGNMASK) + nstart) & ALIGNMASK; + srcStartOver = ((sx & ALIGNMASK) + nstart) > 31; + + if (sx >= dx) { /* move left to right */ + pdstLine += (dx >> 5); + psrcLine += (sx >> 5); + + while (cy--) { + psrc = psrcLine; + pdst = pdstLine; + + if (startmask) { + getandputrop(psrc, (sx & ALIGNMASK), + (dx & ALIGNMASK), nstart, pdst, rop); + pdst++; + if (srcStartOver) + psrc++; + } + + /* special case for aligned operations */ + if (xoffSrc == 0) { + nl = nlMiddle; + while (nl--) { + switch (rop) { + case RR_CLEAR: + *pdst = 0; + break; + case RR_SET: + *pdst = ~0; + break; + default: + *pdst = *psrc; + break; + } + psrc++; + pdst++; + } + } else { + nl = nlMiddle + 1; + while (--nl) { + switch (rop) { + case RR_CLEAR: + *pdst = 0; + break; + case RR_SET: + *pdst = ~0; + break; + default: + getunalignedword(psrc, + xoffSrc, *pdst); + break; + } + pdst++; + psrc++; + } + } + + if (endmask) { + getandputrop(psrc, xoffSrc, 0, nend, + pdst, rop); + } + + pdstLine += width; + psrcLine += width; + } + } else { /* move right to left */ + pdstLine += ((dx + cx) >> 5); + psrcLine += ((sx + cx) >> 5); + /* + * If fetch of last partial bits from source crosses + * a longword boundary, start at the previous longword + */ + if (xoffSrc + nend >= 32) + --psrcLine; + + while (cy--) { + psrc = psrcLine; + pdst = pdstLine; + + if (endmask) { + getandputrop(psrc, xoffSrc, 0, nend, + pdst, rop); + } + + nl = nlMiddle + 1; + while (--nl) { + --psrc; + --pdst; + switch (rop) { + case RR_CLEAR: + *pdst = 0; + break; + case RR_SET: + *pdst = ~0; + break; + default: + getunalignedword(psrc, xoffSrc, + *pdst); + break; + } + } + + if (startmask) { + if (srcStartOver) + --psrc; + --pdst; + getandputrop(psrc, (sx & ALIGNMASK), + (dx & ALIGNMASK), nstart, pdst, + rop); + } + + pdstLine += width; + psrcLine += width; + } + } + } +} + +static void +smg_copycols(void *cookie, int row, int src, int dst, int n) +{ + struct rasops_info *ri = cookie; + + n *= ri->ri_font->fontwidth; + src *= ri->ri_font->fontwidth; + dst *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; + + smg_blockmove(ri, src, row, dst, n, ri->ri_font->fontheight, + RR_COPY); +} + +static void +smg_erasecols(void *cookie, int row, int col, int num, long attr) +{ + struct rasops_info *ri = cookie; + int fg, bg; + + rasops_unpack_attr(attr, &fg, &bg, NULL); + + num *= ri->ri_font->fontwidth; + col *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; + + smg_blockmove(ri, col, row, col, num, ri->ri_font->fontheight, + bg == 0 ? RR_CLEAR : RR_SET); } /* - * Called very early to setup the glass tty as console. - * Because it's called before the VM system is inited, virtual memory - * for the framebuffer can be stolen directly without disturbing anything. + * Console support code */ + +cons_decl(smg); + void smgcnprobe(struct consdev *cndev) { @@ -671,9 +993,12 @@ smgcnprobe(struct consdev *cndev) case VAX_BTYP_410: case VAX_BTYP_420: case VAX_BTYP_43: - if ((vax_confdata & KA420_CFG_L3CON) || - (vax_confdata & KA420_CFG_MULTU)) - break; /* doesn't use graphics console */ + if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0) + break; /* doesn't use graphics console */ + + if ((vax_confdata & KA420_CFG_VIDOPT) != 0) + break; /* there is a color option */ + cndev->cn_pri = CN_INTERNAL; cndev->cn_dev = makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 0); @@ -683,3 +1008,47 @@ smgcnprobe(struct consdev *cndev) break; } } + +/* + * Called very early to setup the glass tty as console. + * Because it's called before the VM system is initialized, virtual memory + * for the framebuffer can be stolen directly without disturbing anything. + */ +void +smgcninit(struct consdev *cndev) +{ + struct smg_screen *ss = &smg_consscr; + vaddr_t ova; + long defattr; + struct rasops_info *ri; + extern vaddr_t virtual_avail; + + ova = virtual_avail; + + ss->ss_addr = (uint8_t *)virtual_avail; + ioaccess(virtual_avail, SMADDR, SMSIZE / VAX_NBPG); + virtual_avail += SMSIZE; + + ss->ss_cursor = (struct dc503reg *)virtual_avail; + ioaccess(virtual_avail, KA420_CUR_BASE, 1); + virtual_avail += VAX_NBPG; + + virtual_avail = round_page(virtual_avail); + + /* this had better not fail */ + if (smg_setup_screen(ss) != 0) { + iounaccess((vaddr_t)ss->ss_addr, SMSIZE / VAX_NBPG); + iounaccess((vaddr_t)ss->ss_cursor, 1); + virtual_avail = ova; + return; + } + + ri = &ss->ss_ri; + (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); + wsdisplay_cnattach(&smg_stdscreen, ri, 0, 0, defattr); + cn_tab->cn_pri = CN_INTERNAL; + +#if NDZKBD > 0 + dzkbd_cnattach(0); /* Connect keyboard and screen together */ +#endif +} Added files: Index: src/sys/arch/vax/vsa/maskbits.h diff -u /dev/null src/sys/arch/vax/vsa/maskbits.h:1.1.2.2 --- /dev/null Wed Feb 15 19:14:50 2023 +++ src/sys/arch/vax/vsa/maskbits.h Wed Feb 15 19:14:50 2023 @@ -0,0 +1,75 @@ +/* $NetBSD: maskbits.h,v 1.1.2.2 2023/02/15 19:14:50 martin Exp $ */ +/* $OpenBSD: maskbits.h,v 1.1 2006/08/05 10:00:30 miod Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)maskbits.h 8.2 (Berkeley) 3/21/94 + */ + +/* + * Derived from X11R4 + */ + +#define FASTGETBITS(psrc,x,w,dst) \ + __asm__ ("extzv %1,%2,%3,%0" \ + : "=g" (dst) \ + : "g" (x), "g" (w), "m" (*(char *)(psrc))) + +#define FASTPUTBITS(src, x, w, pdst) \ + __asm__ ("insv %3,%1,%2,%0" \ + : "=m" (*(char *)(pdst)) \ + : "g" (x), "g" (w), "g" (src)) + +#define RR_CLEAR 0x00 +#define RR_SET 0x01 +#define RR_COPY 0x02 + +#define getandputrop(psrc, srcbit, dstbit, width, pdst, rop) \ +do { \ + unsigned int _tmpdst; \ + switch (rop) { \ + case RR_CLEAR: \ + _tmpdst = 0; \ + break; \ + case RR_SET: \ + _tmpdst = ~0; \ + break; \ + default: \ + FASTGETBITS(psrc, srcbit, width, _tmpdst); \ + break; \ + } \ + FASTPUTBITS(_tmpdst, dstbit, width, pdst); \ +} while (0) + +#define getunalignedword(psrc, x, dst) \ +do { \ + int _tmp; \ + FASTGETBITS(psrc, x, 32, _tmp); \ + dst = _tmp; \ +} while (0) Index: src/sys/dev/ic/dc503reg.h diff -u /dev/null src/sys/dev/ic/dc503reg.h:1.1.2.2 --- /dev/null Wed Feb 15 19:14:50 2023 +++ src/sys/dev/ic/dc503reg.h Wed Feb 15 19:14:50 2023 @@ -0,0 +1,100 @@ +/* $NetBSD: dc503reg.h,v 1.1.2.2 2023/02/15 19:14:50 martin Exp $ */ +/* $OpenBSD: dc503reg.h,v 1.1 2006/07/23 19:17:23 miod Exp $ */ +/* NetBSD: pmreg.h,v 1.7 2005/12/11 12:18:36 christos Exp */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmreg.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Layout of the programmable cursor chip (DC503) registers. + * All registers are 16 bit wide. + */ + +#define PCC_CMD 0x00 /* cursor command register */ +#define PCCCMD_TEST 0x8000 +#define PCCCMD_HSHI 0x4000 +#define PCCCMD_VBHI 0x2000 +#define PCCCMD_LODSA 0x1000 +#define PCCCMD_FORG2 0x0800 +#define PCCCMD_ENRG2 0x0400 +#define PCCCMD_FORG1 0x0200 +#define PCCCMD_ENRG1 0x0100 +#define PCCCMD_XHWID 0x0080 +#define PCCCMD_XHCL1 0x0040 +#define PCCCMD_XHCLP 0x0020 +#define PCCCMD_XHAIR 0x0010 +#define PCCCMD_FOPB 0x0008 +#define PCCCMD_ENPB 0x0004 +#define PCCCMD_FOPA 0x0002 +#define PCCCMD_ENPA 0x0001 + +#define PCC_XPOS 0x04 /* cursor X position */ +#define PCC_YPOS 0x08 /* cursor Y position */ +#define PCC_XMIN_1 0x0c /* region 1 left edge */ +#define PCC_XMAX_1 0x10 /* region 1 right edge */ +#define PCC_YMIN_1 0x14 /* region 1 top edge */ +#define PCC_YMAX_1 0x18 /* region 1 bottom edge */ +#define PCC_XMIN_2 0x1c /* region 2 left edge */ +#define PCC_XMAX_2 0x20 /* region 2 right edge */ +#define PCC_YMIN_2 0x24 /* region 2 top edge */ +#define PCC_YMAX_2 0x28 /* region 2 bottom edge */ +#define PCC_LOAD 0x2c /* cursor pattern load */ + +struct dc503reg { + volatile uint16_t cmdr; + int16_t pad1; + volatile uint16_t xpos; + int16_t pad2; + volatile uint16_t ypos; + int16_t pad3; + volatile uint16_t xmin1; + int16_t pad4; + volatile uint16_t xmax1; + int16_t pad5; + volatile uint16_t ymin1; + int16_t pad6; + volatile uint16_t ymax1; + int16_t pad7[9]; + volatile uint16_t xmin2; + int16_t pad8; + volatile uint16_t xmax2; + int16_t pad9; + volatile uint16_t ymin2; + int16_t pad10; + volatile uint16_t ymax2; + int16_t pad11; + volatile uint16_t load; +}; + +#define PCC_CURSOR_SIZE 16