#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
#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
#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)
{
}
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;
if (from + count > scp->xsize*scp->ysize) {
count = (from + count) -
(adp->va_info.vi_width * adp->va_info.vi_height);
n = (count / adp->va_info.vi_width) + 1;
vidd_copy(adp, n, 0, n);
#if 0
vidd_clear(adp, n);
#endif
vidd_puts(adp, from,
(u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
}
else {
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;
#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)
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)
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 {
}
}
#endif