316 lines
7.5 KiB
C
316 lines
7.5 KiB
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
|
|
* 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 as
|
|
* the first lines of this file unmodified.
|
|
* 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 AUTHORS ``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 AUTHORS 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 Andrew Miklic
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
#include "opt_syscons.h"
|
|
#ifdef __powerpc__
|
|
#include "opt_ofwfb.h"
|
|
#endif
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/fbio.h>
|
|
#include <sys/consio.h>
|
|
|
|
#include <machine/bus.h>
|
|
|
|
#include <dev/fb/fbreg.h>
|
|
#include <dev/syscons/syscons.h>
|
|
|
|
#ifndef SC_RENDER_DEBUG
|
|
#define SC_RENDER_DEBUG 0
|
|
#endif
|
|
|
|
static vr_clear_t gfb_clear;
|
|
static vr_draw_border_t gfb_border;
|
|
static vr_draw_t gfb_draw;
|
|
static vr_set_cursor_t gfb_cursor_shape;
|
|
static vr_draw_cursor_t gfb_cursor;
|
|
static vr_blink_cursor_t gfb_blink;
|
|
#ifndef SC_NO_CUTPASTE
|
|
static vr_draw_mouse_t gfb_mouse;
|
|
#else
|
|
#define gfb_mouse (vr_draw_mouse_t *)gfb_nop
|
|
#endif
|
|
|
|
static void gfb_nop(scr_stat *scp);
|
|
|
|
sc_rndr_sw_t txtrndrsw = {
|
|
(vr_init_t *)gfb_nop,
|
|
gfb_clear,
|
|
gfb_border,
|
|
gfb_draw,
|
|
gfb_cursor_shape,
|
|
gfb_cursor,
|
|
gfb_blink,
|
|
(vr_set_mouse_t *)gfb_nop,
|
|
gfb_mouse,
|
|
};
|
|
|
|
#ifdef SC_PIXEL_MODE
|
|
sc_rndr_sw_t gfbrndrsw = {
|
|
(vr_init_t *)gfb_nop,
|
|
gfb_clear,
|
|
gfb_border,
|
|
gfb_draw,
|
|
gfb_cursor_shape,
|
|
gfb_cursor,
|
|
gfb_blink,
|
|
(vr_set_mouse_t *)gfb_nop,
|
|
gfb_mouse,
|
|
};
|
|
#endif /* SC_PIXEL_MODE */
|
|
|
|
#ifndef SC_NO_MODE_CHANGE
|
|
sc_rndr_sw_t grrndrsw = {
|
|
(vr_init_t *)gfb_nop,
|
|
(vr_clear_t *)gfb_nop,
|
|
gfb_border,
|
|
(vr_draw_t *)gfb_nop,
|
|
(vr_set_cursor_t *)gfb_nop,
|
|
(vr_draw_cursor_t *)gfb_nop,
|
|
(vr_blink_cursor_t *)gfb_nop,
|
|
(vr_set_mouse_t *)gfb_nop,
|
|
(vr_draw_mouse_t *)gfb_nop,
|
|
};
|
|
#endif /* SC_NO_MODE_CHANGE */
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
static u_char mouse_pointer[16] = {
|
|
0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
|
|
0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
#endif
|
|
|
|
static void
|
|
gfb_nop(scr_stat *scp)
|
|
{
|
|
}
|
|
|
|
/* text mode renderer */
|
|
|
|
static void
|
|
gfb_clear(scr_stat *scp, int c, int attr)
|
|
{
|
|
vidd_clear(scp->sc->adp);
|
|
}
|
|
|
|
static void
|
|
gfb_border(scr_stat *scp, int color)
|
|
{
|
|
vidd_set_border(scp->sc->adp, color);
|
|
}
|
|
|
|
static void
|
|
gfb_draw(scr_stat *scp, int from, int count, int flip)
|
|
{
|
|
int c;
|
|
int a;
|
|
int i, n;
|
|
video_adapter_t *adp;
|
|
|
|
adp = scp->sc->adp;
|
|
|
|
/*
|
|
Determine if we need to scroll based on the offset
|
|
and the number of characters to be displayed...
|
|
*/
|
|
if (from + count > scp->xsize*scp->ysize) {
|
|
/*
|
|
Calculate the number of characters past the end of the
|
|
visible screen...
|
|
*/
|
|
count = (from + count) -
|
|
(adp->va_info.vi_width * adp->va_info.vi_height);
|
|
|
|
/*
|
|
Calculate the number of rows past the end of the visible
|
|
screen...
|
|
*/
|
|
n = (count / adp->va_info.vi_width) + 1;
|
|
|
|
/* Scroll to make room for new text rows... */
|
|
vidd_copy(adp, n, 0, n);
|
|
#if 0
|
|
vidd_clear(adp, n);
|
|
#endif
|
|
|
|
/* Display new text rows... */
|
|
vidd_puts(adp, from,
|
|
(u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
|
|
}
|
|
|
|
/*
|
|
We don't need to scroll, so we can just put the characters
|
|
all-at-once...
|
|
*/
|
|
else {
|
|
/*
|
|
Determine the method by which we are to display characters
|
|
(are we going to print forwards or backwards?
|
|
do we need to do a character-by-character copy, then?)...
|
|
*/
|
|
if (flip)
|
|
for (i = count; i-- > 0; ++from) {
|
|
c = sc_vtb_getc(&scp->vtb, from);
|
|
a = sc_vtb_geta(&scp->vtb, from) >> 8;
|
|
vidd_putc(adp, from, c,
|
|
(a >> 4) | ((a & 0xf) << 4));
|
|
}
|
|
else {
|
|
vidd_puts(adp, from,
|
|
(u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
|
|
count);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
|
|
{
|
|
if (base < 0 || base >= scp->font_size)
|
|
return;
|
|
/* the caller may set height <= 0 in order to disable the cursor */
|
|
#if 0
|
|
scp->cursor_base = base;
|
|
scp->cursor_height = height;
|
|
#endif
|
|
vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
|
|
blink);
|
|
}
|
|
|
|
static int pxlblinkrate = 0;
|
|
|
|
#if defined(SC_OFWFB)
|
|
static void
|
|
gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
|
|
{
|
|
video_adapter_t *adp;
|
|
int a, c;
|
|
|
|
if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
|
|
return;
|
|
|
|
adp = scp->sc->adp;
|
|
if(blink) {
|
|
scp->status |= VR_CURSOR_BLINK;
|
|
if (on) {
|
|
scp->status |= VR_CURSOR_ON;
|
|
vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
|
|
} else {
|
|
if (scp->status & VR_CURSOR_ON)
|
|
vidd_set_hw_cursor(adp, -1, -1);
|
|
scp->status &= ~VR_CURSOR_ON;
|
|
}
|
|
} else {
|
|
scp->status &= ~VR_CURSOR_BLINK;
|
|
if(on) {
|
|
scp->status |= VR_CURSOR_ON;
|
|
vidd_putc(scp->sc->adp, scp->cursor_oldpos,
|
|
sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
|
|
sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
|
|
a = sc_vtb_geta(&scp->vtb, at) >> 8;
|
|
c = sc_vtb_getc(&scp->vtb, at);
|
|
vidd_putc(scp->sc->adp, at, c,
|
|
(a >> 4) | ((a & 0xf) << 4));
|
|
} else {
|
|
if (scp->status & VR_CURSOR_ON)
|
|
vidd_putc(scp->sc->adp, at,
|
|
sc_vtb_getc(&scp->vtb, at),
|
|
sc_vtb_geta(&scp->vtb, at) >> 8);
|
|
scp->status &= ~VR_CURSOR_ON;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
static void
|
|
gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
|
|
{
|
|
video_adapter_t *adp;
|
|
|
|
adp = scp->sc->adp;
|
|
if (scp->curs_attr.height <= 0)
|
|
/* the text cursor is disabled */
|
|
return;
|
|
|
|
if (on) {
|
|
if (!blink) {
|
|
scp->status |= VR_CURSOR_ON;
|
|
vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
|
|
} else if (++pxlblinkrate & 4) {
|
|
pxlblinkrate = 0;
|
|
scp->status ^= VR_CURSOR_ON;
|
|
if(scp->status & VR_CURSOR_ON)
|
|
vidd_set_hw_cursor(adp, at%scp->xsize,
|
|
at/scp->xsize);
|
|
else
|
|
vidd_set_hw_cursor(adp, -1, -1);
|
|
}
|
|
} else {
|
|
if (scp->status & VR_CURSOR_ON)
|
|
vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
|
|
scp->status &= ~VR_CURSOR_ON;
|
|
}
|
|
if (blink)
|
|
scp->status |= VR_CURSOR_BLINK;
|
|
else
|
|
scp->status &= ~VR_CURSOR_BLINK;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
gfb_blink(scr_stat *scp, int at, int flip)
|
|
{
|
|
if (!(scp->status & VR_CURSOR_BLINK))
|
|
return;
|
|
if (!(++pxlblinkrate & 4))
|
|
return;
|
|
pxlblinkrate = 0;
|
|
scp->status ^= VR_CURSOR_ON;
|
|
gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
|
|
scp->status & VR_CURSOR_ON, flip);
|
|
}
|
|
|
|
#ifndef SC_NO_CUTPASTE
|
|
|
|
static void
|
|
gfb_mouse(scr_stat *scp, int x, int y, int on)
|
|
{
|
|
if (on) {
|
|
vidd_putm(scp->sc->adp, x, y, mouse_pointer,
|
|
0xffffffff, 16, 8);
|
|
} else {
|
|
/* XXX: removal is incomplete for h/w cursors and borders. */
|
|
}
|
|
}
|
|
|
|
#endif /* SC_NO_CUTPASTE */
|