/* $NetBSD: qv.c,v 1.38 2021/08/07 16:19:07 thorpej Exp $ */
/*
* Copyright (c) 2015 Charles H. Dickman. All rights reserved.
* Derived from smg.c
* Copyright (c) 1998 Ludd, University of Lule}, Sweden.
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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.
*/
/* 1 2 3 4 5 6 7 */
/*3456789012345678901234567890123456789012345678901234567890123456789012345678*/
struct _wsscreen_descr {
const struct wsscreen_descr qv_stdscreen; /* MUST BE FIRST */
const uint16_t qv_crtc_param[16];
};
/*
* Notes from the original Ultrix drivers
*
* Screen controller initialization parameters. The definations [sic] and use
* of these parameters can be found in the Motorola 68045 [sic] crtc specs. In
* essence they set the display parameters for the chip. The first set is
* for the 15" screen and the second is for the 19" separate sync. There
* is also a third set for a 19" composite sync monitor which we have not
* tested and which is not supported.
*/
uint8_t sc_curon; /* cursor on */
uint16_t sc_curx; /* cursor x position */
uint16_t sc_cury; /* cursor y position */
uint16_t sc_curhotX; /* cursor x hot spot */
uint16_t sc_curhotY; /* cursor y hot spot */
struct qv_screen *sc_curscr; /* current screen */
};
/* uint_32 is stored little endian in frame buffer */
/* bits are stored little endian in frame buffer */
/* uint_32 *fb; */
/* fb = (int *)phystova(0x303c0000); */
/* *fb = 0x00000001; */ /* sets bit in first column */
/* Frame Buffer Usage */
/* characters are 8 bits wide and QVHEIGHT high */
/* the scan map is allocated in terms of character height, */
/* so a pointer to the top line of a character can step to the */
/* next row without looking up the memory location in the scan map */
static char *cursor;
static int cur_on;
/*
* return pointer to line in character glyph
*/
static inline char *
qv_font(struct qv_softc *sc, int c, int line)
{
/* map char to font table offset */
if (c < 32)
c = 32;
else if (c > 127)
c -= 66;
else
c -= 32;
/* return pointer line in font glyph */
return &sc->sc_font[c*QV_CHEIGHT + line];
}
/*
* return pointer to character line in frame buffer
*/
static inline char *
qv_fbp(struct qv_softc *sc, int row, int col, int line)
{
return &sc->sc_fb[col + sc->sc_scanmap[row*QV_CHEIGHT + line]*QV_COLS];
}
/*
* emulop copy columns - copies columns inside a row
*/
static void
qv_copycols(void *id, int row, int srccol, int dstcol, int ncols)
{
struct qv_screen * const ss = id;
int i;
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 != ss->ss_sc->sc_curscr)
return;
for (i = 0; i < QV_CHEIGHT; i++)
memcpy(qv_fbp(ss->ss_sc, row, dstcol, i),
qv_fbp(ss->ss_sc, row, srccol, i), ncols);
}
/*
* emulop erase columns - erases a bunch of chars inside one row
*/
static void
qv_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
{
struct qv_screen * const ss = id;
int i;
memset(&ss->ss_image[row][startcol], 0, ncols);
memset(&ss->ss_attr[row][startcol], 0, ncols);
if (ss != ss->ss_sc->sc_curscr)
return;
for (i = 0; i < QV_CHEIGHT; i++)
memset(qv_fbp(ss->ss_sc, row, startcol, i), 0, ncols);
}
/*
* overlap check
* return 0 if no overlap
* -1 if overlap and dst is less than src (move up)
* +1 if overlap and src is less than dst (move down)
*/
static inline int
qv_rows_overlap(int srcrow, int dstrow, int nrows)
{
if (dstrow < srcrow) {
if (dstrow + nrows <= srcrow)
return 0;
else
return -1;
}
else {
if (srcrow + nrows <= dstrow)
return 0;
else
return 1;
}
}
/*
* emulop copyrows - copy entire rows
*/
static void
qv_copyrows(void *id, int srcrow, int dstrow, int nrows)
{
struct qv_screen * const ss = id;
int ol;
int n;
int line;
int tmp;
uint16_t *sp;
uint16_t *dp;
ol = qv_rows_overlap(srcrow, dstrow, nrows);
if (ol == 0)
for (n = 0; n < nrows; n++)
bcopy(qv_fbp(ss->ss_sc, srcrow + n, 0, 0),
qv_fbp(ss->ss_sc, dstrow + n, 0, 0), QV_NEXTROW);
else if (ol < 0) {
for (n = 0; n < nrows; n++) {
dp = &ss->ss_sc->sc_scanmap[(dstrow + n)*QV_CHEIGHT];
sp = &ss->ss_sc->sc_scanmap[(srcrow + n)*QV_CHEIGHT];
for (line = 0; line < QV_CHEIGHT; line++) {
tmp = *dp;
*dp = *sp;
*sp = tmp;
dp++;
sp++;
}
}
qv_copyrows(id, dstrow + nrows - srcrow + dstrow,
dstrow + nrows, srcrow - dstrow);
}
else {
for (n = nrows - 1; n >= 0; n--) {
dp = &ss->ss_sc->sc_scanmap[(dstrow + n)*QV_CHEIGHT];
sp = &ss->ss_sc->sc_scanmap[(srcrow + n)*QV_CHEIGHT];
for (line = 0; line < QV_CHEIGHT; line++) {
tmp = *dp;
*dp = *sp;
*sp = tmp;
dp++;
sp++;
}
}
qv_copyrows(id, srcrow, dstrow, dstrow - srcrow);
}
}
/*
* emulop eraserows - erase a number of entire rows
*/
static void
qv_eraserows(void *id, int startrow, int nrows, long fillattr)
{
struct qv_screen * const ss = id;
int row;
callout_init(&qv_cursor_ch, 0);
//curscr = &qv_conscreen;
wsdisplay_cnattach(&qv_stdscreen[0].qv_stdscreen,
&qv_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("qv: could not find 8x15 font\n");
return;
}
if (wsfont_lock(fcookie, &console_font) != 0) {
printf("qv: could not lock 8x15 font\n");
return;
}
//qf = console_font->data;
#if NQVKBD > 0 && 0
qvkbd_cnattach(0); /* Connect keyboard and screen together */
#endif
}
/*
* 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.
*/
void
qvcnprobe(struct consdev *cndev)
{
printf("qvcnprobe: \n");
#if 0
extern vaddr_t virtual_avail;
extern const struct cdevsw wsdisplay_cdevsw;
switch (vax_boardtype) {
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 */
qv_addr = (void *)virtual_avail;
virtual_avail += QVSIZE;
ioaccess((vaddr_t)qv_addr, QVADDR, (QVSIZE/VAX_NBPG));
cndev->cn_pri = CN_INTERNAL;
cndev->cn_dev = makedev(cdevsw_lookup_major(&wsdisplay_cdevsw),
0);
break;
default:
break;
}
#endif
}