/* $NetBSD: gpx.c,v 1.4 2024/09/30 00:34:04 rin Exp $ */
/* $OpenBSD: gpx.c,v 1.25 2014/12/23 21:39:12 miod Exp $ */
/*
* Copyright (c) 2006 Miodrag Vallat.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice, this permission notice, and the disclaimer below
* appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Copyright (c) 1988 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.
*
* @(#)qd.c 7.1 (Berkeley) 6/28/91
*/
/************************************************************************
* *
* Copyright (c) 1985-1988 by *
* Digital Equipment Corporation, Maynard, MA *
* All rights reserved. *
* *
* This software is furnished under a license and may be used and *
* copied only in accordance with the terms of such license and *
* with the inclusion of the above copyright notice. This *
* software or any other copies thereof may not be provided or *
* otherwise made available to any other person. No title to and *
* ownership of the software is hereby transferred. *
* *
* The information in this software is subject to change without *
* notice and should not be construed as a commitment by Digital *
* Equipment Corporation. *
* *
* Digital assumes no responsibility for the use or reliability *
* of its software on equipment which is not supplied by Digital. *
* *
*************************************************************************/
/*
* Driver for the GPX color option on VAXstation 3100, based on the
* MicroVAX II qdss driver.
*
* The frame buffer memory itself is not directly accessible (unlike
* the on-board monochrome smg frame buffer), and writes through the
* Dragon chip can only happen in multiples of 16 pixels, horizontally.
*
* Because of this limitation, the font image is copied to offscreen
* memory (which there is plenty of), and screen to screen blt operations
* are done for everything.
*/
static int
gpx_show_screen(void *v, void *cookie, int waitok,
void (*cb)(void *, int, int), void *cbarg)
{
return 0;
}
/*
* wsdisplay emulops
*/
static void
gpx_putchar(void *v, int row, int col, u_int uc, long attr)
{
struct rasops_info *ri = v;
struct gpx_screen *ss = ri->ri_hw;
struct wsdisplay_font *font = ri->ri_font;
int dx, dy, sx, sy, fg, bg, ul;
rasops_unpack_attr(attr, &fg, &bg, &ul);
/* find where to output the glyph... */
dx = col * font->fontwidth + ri->ri_xorigin;
dy = row * font->fontheight + ri->ri_yorigin;
/* ... and where to pick it from */
uc -= font->firstchar;
sx = (uc % ss->ss_gpr) * font->stride * NBBY;
sy = GPX_HEIGHT - (1 + uc / ss->ss_gpr) * font->fontheight;
if (ul != 0) {
gpx_fillrect(ss, dx, dy + font->fontheight - 2, font->fontwidth,
1, attr, LF_R3); /* fg fill */
}
}
static void
gpx_copycols(void *v, int row, int src, int dst, int cnt)
{
struct rasops_info *ri = v;
struct gpx_screen *ss = ri->ri_hw;
struct wsdisplay_font *font = ri->ri_font;
int sx, y, dx, w, h;
sx = ri->ri_xorigin + src * font->fontwidth;
dx = ri->ri_xorigin + dst * font->fontwidth;
w = cnt * font->fontwidth;
y = ri->ri_yorigin + row * font->fontheight;
h = font->fontheight;
gpx_copyrect(ss, sx, y, dx, y, w, h);
}
static void
gpx_erasecols(void *v, int row, int col, int cnt, long attr)
{
struct rasops_info *ri = v;
struct gpx_screen *ss = ri->ri_hw;
struct wsdisplay_font *font = ri->ri_font;
int x, y, dx, dy;
x = ri->ri_xorigin + col * font->fontwidth;
dx = cnt * font->fontwidth;
y = ri->ri_yorigin + row * font->fontheight;
dy = font->fontheight;
gpx_fillrect(ss, x, y, dx, dy, attr, LF_R2); /* bg fill */
}
static void
gpx_copyrows(void *v, int src, int dst, int cnt)
{
struct rasops_info *ri = v;
struct gpx_screen *ss = ri->ri_hw;
struct wsdisplay_font *font = ri->ri_font;
int x, sy, dy, w, h;
x = ri->ri_xorigin;
w = ri->ri_emustride;
sy = ri->ri_yorigin + src * font->fontheight;
dy = ri->ri_yorigin + dst * font->fontheight;
h = cnt * font->fontheight;
gpx_copyrect(ss, x, sy, x, dy, w, h);
}
static void
gpx_eraserows(void *v, int row, int cnt, long attr)
{
struct rasops_info *ri = v;
struct gpx_screen *ss = ri->ri_hw;
struct wsdisplay_font *font = ri->ri_font;
int x, y, dx, dy;
x = ri->ri_xorigin;
dx = ri->ri_emustride;
y = ri->ri_yorigin + row * font->fontheight;
dy = cnt * font->fontheight;
gpx_fillrect(ss, x, y, dx, dy, attr, LF_R2); /* bg fill */
}
static void
gpx_do_cursor(struct rasops_info *ri)
{
struct gpx_screen *ss = ri->ri_hw;
int x, y, w, h;
x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
w = ri->ri_font->fontwidth;
h = ri->ri_font->fontheight;
static int
gpx_setup_screen(struct gpx_screen *ss)
{
struct rasops_info *ri = &ss->ss_ri;
int cookie;
memset(ri, 0, sizeof(*ri));
ri->ri_depth = 8; /* masquerade as a 8 bit device for rasops */
ri->ri_width = GPX_WIDTH;
ri->ri_height = GPX_VISHEIGHT;
ri->ri_stride = GPX_WIDTH;
ri->ri_flg = RI_CENTER; /* no RI_CLEAR as ri_bits is NULL! */
ri->ri_hw = ss;
if (ss == &gpx_consscr)
ri->ri_flg |= RI_NO_AUTO;
/*
* We can not let rasops select our font, because we need to use
* a font with right-to-left bit order on this frame buffer.
*/
wsfont_init();
cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
if (cookie < 0)
cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
if (cookie < 0)
cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
if (cookie < 0)
return -1;
if (wsfont_lock(cookie, &ri->ri_font) != 0)
return -1;
ri->ri_wsfcookie = cookie;
/*
* Ask for an unholy big display, rasops will trim this to more
* reasonable values.
*/
if (rasops_init(ri, 160, 160) != 0)
return -1;
/*
* Copy the selected wsfont to non-visible frame buffer area.
* This is necessary since the only way to send data to the frame buffer
* is through the ID interface, which is slow and needs 16 bit wide data.
* Adapted from qdss.
*/
static void
gpx_upload_font(struct gpx_screen *ss)
{
struct rasops_info *ri = &ss->ss_ri;
struct wsdisplay_font *font = ri->ri_font;
uint8_t *fontbits, *fb;
u_int remaining, nchars, row;
u_int i, j;
uint16_t data;
/*
* Load font data. The font is uploaded in 8 or 16 bit wide cells, on
* as many ``lines'' as necessary at the end of the display.
*/
ss->ss_gpr = MIN(GPX_WIDTH / (NBBY * font->stride), font->numchars);
if ((ss->ss_gpr & 1) != 0)
ss->ss_gpr--;
fontbits = font->data;
for (row = 1, remaining = font->numchars; remaining != 0;
row++, remaining -= nchars) {
nchars = MIN(ss->ss_gpr, remaining);
/* iteratively do the processor to bitmap xfer */
for (i = font->fontheight; i != 0; i--) {
fb = fontbits;
fontbits += font->stride;
/* PTOB a scan line */
for (j = nchars; j != 0; j--) {
/* PTOB one scan of a char cell */
if (font->stride == 1) {
data = *fb;
fb += font->fontheight;
/*
* Do not access past font memory if
* it has an odd number of characters
* and this is the last pair.
*/
if (j != 1 || (nchars & 1) == 0 ||
remaining != nchars) {
data |= ((uint16_t)*fb) << 8;
fb += font->fontheight;
}
} else {
data =
fb[0] | (((uint16_t)fb[1]) << 8);
fb += font->fontheight * font->stride;
}
/*
* Fill a rectangle with the given attribute and function (i.e. rop).
*/
static void
gpx_fillrect(struct gpx_screen *ss, int x, int y, int dx, int dy, long attr,
u_int function)
{
int fg, bg;
/* extract reds */
c = ss->ss_cmap + 0 + index * 3;
for (i = count, r = ramp; i != 0; i--)
*r++ = *c << (8 - ss->ss_depth), c += 3;
if ((error = copyout(ramp, cm->red, count)) != 0)
return error;
/* extract greens */
c = ss->ss_cmap + 1 + index * 3;
for (i = count, r = ramp; i != 0; i--)
*r++ = *c << (8 - ss->ss_depth), c += 3;
if ((error = copyout(ramp, cm->green, count)) != 0)
return error;
/* extract blues */
c = ss->ss_cmap + 2 + index * 3;
for (i = count, r = ramp; i != 0; i--)
*r++ = *c << (8 - ss->ss_depth), c += 3;
if ((error = copyout(ramp, cm->blue, count)) != 0)
return error;
return 0;
}
static int
gpx_putcmap(struct gpx_screen *ss, struct wsdisplay_cmap *cm)
{
u_int index = cm->index, count = cm->count;
u_int colcount = 1 << ss->ss_depth;
int i, error;
uint8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
/*
* 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
gpxcnprobe(struct consdev *cndev)
{
extern vaddr_t virtual_avail;
extern const struct cdevsw wsdisplay_cdevsw;
volatile struct adder *adder;
vaddr_t tmp;
int depth;
u_short status;
switch (vax_boardtype) {
case VAX_BTYP_410:
case VAX_BTYP_420:
case VAX_BTYP_43:
if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0)
break; /* doesn't use graphics console */
if ((vax_confdata & KA420_CFG_VIDOPT) == 0)
break; /* no color option */
/*
* 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
gpxcninit(struct consdev *cndev)
{
struct gpx_screen *ss = &gpx_consscr;
extern vaddr_t virtual_avail;
vaddr_t ova;
long defattr;
struct rasops_info *ri;