b7c96c0d0b
and do some preparations for handling 12x22 fonts (currently lots of code implies and/or hardcodes a font width of 8 pixels). This will be required on sparc64 which uses a default font size of 12x22 in order to add font loading and saving support as well as to use a syscons(4)-supplied mouse pointer image. This API breakage is committed now so it can be MFC'ed in time for 6.0 and later on upcoming framebuffer drivers destined for use on sparc64 and which are expected to rely on using font loading internally and on a syscons(4)-supplied mouse pointer image can be easily MFC'ed to RELENG_6 rather than requiring a backport. Tested on: i386, sparc64, make universe MFC after: 1 week
941 lines
24 KiB
C
941 lines
24 KiB
C
/*-
|
|
* Copyright (c) 2001 Andrew Miklic
|
|
* 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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) 1995, 1996 Carnegie-Mellon University.
|
|
* All rights reserved.
|
|
*
|
|
* Author: Chris G. Demetriou
|
|
*
|
|
* Permission to use, copy, modify and distribute this software and
|
|
* its documentation is hereby granted, provided that both the copyright
|
|
* notice and this permission notice appear in all copies of the
|
|
* software, derivative works or modified versions, and any portions
|
|
* thereof, and that both notices appear in supporting documentation.
|
|
*
|
|
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
|
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
|
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
*
|
|
* Carnegie Mellon requests users of this software to return to
|
|
*
|
|
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
|
* School of Computer Science
|
|
* Carnegie Mellon University
|
|
* Pittsburgh PA 15213-3890
|
|
*
|
|
* any improvements or extensions that they make and grant Carnegie the
|
|
* rights to redistribute these changes.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <machine/stdarg.h>
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/fcntl.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/fbio.h>
|
|
|
|
#include <vm/vm.h>
|
|
#include <vm/vm_param.h>
|
|
#include <vm/pmap.h>
|
|
|
|
#include <machine/md_var.h>
|
|
#include <machine/pc/bios.h>
|
|
#include <machine/clock.h>
|
|
#include <machine/bus.h>
|
|
#include <machine/pc/vesa.h>
|
|
#include <machine/resource.h>
|
|
#include <machine/rpb.h>
|
|
|
|
#include <sys/bus.h>
|
|
#include <sys/rman.h>
|
|
|
|
#include <dev/pci/pcireg.h>
|
|
#include <dev/pci/pcivar.h>
|
|
|
|
#include <dev/fb/fbreg.h>
|
|
#include <dev/fb/gfb.h>
|
|
#include <dev/gfb/gfb_pci.h>
|
|
|
|
#include "opt_gfb.h"
|
|
|
|
struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS] = {
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
|
},
|
|
};
|
|
|
|
/*
|
|
The following 9 variables exist only because we need statically
|
|
allocated structures very early in boot to support gfb_configure()...
|
|
*/
|
|
struct gfb_softc console;
|
|
video_adapter_t console_adp;
|
|
struct gfb_conf console_gfbc;
|
|
u_char console_palette_red[256];
|
|
u_char console_palette_green[256];
|
|
u_char console_palette_blue[256];
|
|
u_char console_cursor_palette_red[3];
|
|
u_char console_cursor_palette_green[3];
|
|
u_char console_cursor_palette_blue[3];
|
|
|
|
extern struct gfb_font bold8x16;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FB-generic functions
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
gfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
|
|
{
|
|
int error;
|
|
|
|
/* Assume the best... */
|
|
error = 0;
|
|
|
|
if((*adpp = vid_get_adapter(vid_find_adapter((char *)arg, unit))) == NULL)
|
|
error = ENODEV;
|
|
else
|
|
(*adpp)->va_flags |= V_ADP_PROBED;
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_init(int unit, video_adapter_t *adp, int flags)
|
|
{
|
|
struct gfb_softc *sc;
|
|
struct gfb_conf *gfbc;
|
|
int error;
|
|
|
|
/* Assume the best... */
|
|
error = 0;
|
|
|
|
if(!init_done(adp)) {
|
|
sc = gfb_device_softcs[adp->va_model][unit];
|
|
gfbc = sc->gfbc;
|
|
|
|
/* Initialize the RAMDAC... */
|
|
(*gfbc->ramdac_init)(sc);
|
|
|
|
/* Initialize the palettes... */
|
|
(*gfbc->ramdac_load_palette)(sc->adp, &sc->gfbc->palette);
|
|
(*gfbc->ramdac_load_cursor_palette)(sc->adp,
|
|
&sc->gfbc->cursor_palette);
|
|
|
|
/* Prepare the default font... */
|
|
(*vidsw[adp->va_index]->load_font)(adp, 0, bold8x16.height,
|
|
bold8x16.width, bold8x16.data, 0, 256);
|
|
adp->va_info.vi_cwidth = gfbc->fonts[0].width;
|
|
adp->va_info.vi_cheight = gfbc->fonts[0].height;
|
|
|
|
/*
|
|
Normalize vi_width and vi_height to be in terms of
|
|
on-screen characters, rather than pixels (*_init()
|
|
leaves them in terms of pixels...
|
|
*/
|
|
adp->va_info.vi_width /= adp->va_info.vi_cwidth;
|
|
adp->va_info.vi_height /= adp->va_info.vi_cheight;
|
|
|
|
/* Enable the default font... */
|
|
(*vidsw[adp->va_index]->show_font)(adp, 0);
|
|
|
|
/* Enable future font-loading... */
|
|
adp->va_flags |= V_ADP_FONT;
|
|
|
|
/* Flag this initialization for this adapter... */
|
|
adp->va_flags |= V_ADP_INITIALIZED;
|
|
}
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
|
|
{
|
|
int error;
|
|
|
|
/* Assume the best... */
|
|
error = 0;
|
|
|
|
/*
|
|
The info for GFB adapters does not depend on its mode,
|
|
so just copy it indiscriminantly (actually, we originally
|
|
checked the mode, but the current fb framework is somewhat
|
|
sloppily done in places, and assumes VGA in several places,
|
|
which makes such checks always fail for such GFBs as TGA)...
|
|
*/
|
|
bcopy(&adp->va_info, info, sizeof(video_info_t));
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_set_mode(video_adapter_t *adp, int mode)
|
|
{
|
|
|
|
adp->va_mode = mode;
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_save_font(video_adapter_t *adp, int page, int fontsize, int fontwidth,
|
|
u_char *data, int ch, int count)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
int i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* Check the font information... */
|
|
if((sc->gfbc->fonts[page].height != fontsize) ||
|
|
(sc->gfbc->fonts[page].width != fontwidth))
|
|
error = EINVAL;
|
|
else
|
|
|
|
/*
|
|
Copy the character pixel array from our
|
|
very own private cache...
|
|
*/
|
|
for(i = ch; i < count * fontsize; i++)
|
|
data[i] = adp->va_little_bitian ?
|
|
BIT_REVERSE(sc->gfbc->fonts[page].data[i]) :
|
|
sc->gfbc->fonts[page].data[i];
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_load_font(video_adapter_t *adp, int page, int fontsize, int fontwidth,
|
|
u_char *data, int ch, int count)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
int i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* Copy the character pixel array into our very own private cache... */
|
|
for(i = ch; i < count * fontsize; i++)
|
|
sc->gfbc->fonts[page].data[i] = adp->va_little_bitian ?
|
|
BIT_REVERSE(data[i]) : data[i];
|
|
|
|
/* Save the font information... */
|
|
sc->gfbc->fonts[page].height = fontsize;
|
|
sc->gfbc->fonts[page].width = fontwidth;
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_show_font(video_adapter_t *adp, int page)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* Normalize adapter values... */
|
|
adp->va_info.vi_height *= adp->va_info.vi_cheight;
|
|
adp->va_info.vi_width *= adp->va_info.vi_cwidth;
|
|
|
|
/* Set the current font pixels... */
|
|
sc->gfbc->font = sc->gfbc->fonts[page].data;
|
|
|
|
/* Set the current font width... */
|
|
adp->va_info.vi_cwidth = sc->gfbc->fonts[page].width;
|
|
|
|
/* Set the current font height... */
|
|
adp->va_info.vi_cheight = sc->gfbc->fonts[page].height;
|
|
|
|
/* Recompute adapter values... */
|
|
adp->va_info.vi_height /= adp->va_info.vi_cheight;
|
|
adp->va_info.vi_width /= adp->va_info.vi_cwidth;
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_save_palette(video_adapter_t *adp, u_char *palette)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
int i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
#if 0
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_save_palette)
|
|
error = sc->gfbc->ramdac_save_palette(adp, &sc->gfbc->palette);
|
|
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_save_palette(adp, &sc->gfbc->palette);
|
|
#endif
|
|
|
|
for(i = 0; i < sc->gfbc->palette.count; i++) {
|
|
palette[(3 * i)] = sc->gfbc->palette.red[i];
|
|
palette[(3 * i) + 1] = sc->gfbc->palette.green[i];
|
|
palette[(3 * i) + 2] = sc->gfbc->palette.blue[i];
|
|
}
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_load_palette(video_adapter_t *adp, u_char *palette)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
int i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
for(i = 0; i < sc->gfbc->palette.count; i++) {
|
|
sc->gfbc->palette.red[i] = palette[(3 * i)];
|
|
sc->gfbc->palette.green[i] = palette[(3 * i) + 1];
|
|
sc->gfbc->palette.blue[i] = palette[(3 * i) + 2];
|
|
}
|
|
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_load_palette)
|
|
error = sc->gfbc->ramdac_load_palette(adp, &sc->gfbc->palette);
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_load_palette(adp, &sc->gfbc->palette);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_set_border(video_adapter_t *adp, int color)
|
|
{
|
|
|
|
return(ENODEV);
|
|
}
|
|
|
|
int
|
|
gfb_save_state(video_adapter_t *adp, void *p, size_t size)
|
|
{
|
|
int i;
|
|
u_int32_t *regs;
|
|
|
|
regs = (u_int32_t *)p;
|
|
regs[0] = size;
|
|
for(i = 1; i <= size; i++)
|
|
regs[i] = READ_GFB_REGISTER(adp, i);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_load_state(video_adapter_t *adp, void *p)
|
|
{
|
|
size_t size;
|
|
int i;
|
|
u_int32_t *regs;
|
|
|
|
regs = (u_int32_t *)p;
|
|
size = regs[0];
|
|
for(i = 1; i <= size; i++)
|
|
WRITE_GFB_REGISTER(adp, i, regs[i]);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_set_win_org(video_adapter_t *adp, off_t offset)
|
|
{
|
|
|
|
adp->va_window_orig = offset;
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_read_hw_cursor)
|
|
error = sc->gfbc->ramdac_read_hw_cursor(adp, col, row);
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_read_hw_cursor(adp, col, row);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_set_hw_cursor(adp, col, row)
|
|
video_adapter_t *adp;
|
|
int col;
|
|
int row;
|
|
{
|
|
int error;
|
|
struct gfb_softc *sc;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_set_hw_cursor)
|
|
error = sc->gfbc->ramdac_set_hw_cursor(adp, col, row);
|
|
|
|
/* Otherwise, use the built-in functionality... */
|
|
else
|
|
error = sc->gfbc->builtin_set_hw_cursor(adp, col, row);
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
|
|
int cellsize, int blink)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_set_hw_cursor_shape)
|
|
error = sc->gfbc->ramdac_set_hw_cursor_shape(adp, base, height,
|
|
cellsize, blink);
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_set_hw_cursor_shape(adp, base,
|
|
height, cellsize, blink);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_offset_t *paddr, int prot)
|
|
{
|
|
|
|
/* XXX */
|
|
if(offset > adp->va_window_size - PAGE_SIZE)
|
|
return(ENXIO);
|
|
*paddr = adp->va_info.vi_window + offset;
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
switch (cmd) {
|
|
case FBIOPUTCMAP:
|
|
/* FALLTHROUGH */
|
|
case FBIO_GETWINORG:
|
|
/* FALLTHROUGH */
|
|
case FBIO_SETWINORG:
|
|
/* FALLTHROUGH */
|
|
case FBIO_SETDISPSTART:
|
|
/* FALLTHROUGH */
|
|
case FBIO_SETLINEWIDTH:
|
|
/* FALLTHROUGH */
|
|
case FBIO_GETPALETTE:
|
|
/* FALLTHROUGH */
|
|
case FBIOGTYPE:
|
|
/* FALLTHROUGH */
|
|
case FBIOGETCMAP:
|
|
/* FALLTHROUGH */
|
|
default:
|
|
error = fb_commonioctl(adp, cmd, arg);
|
|
}
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
|
|
{
|
|
int off;
|
|
|
|
/*
|
|
Just traverse the buffer, one pixel span at a time, setting
|
|
each pixel to the block-color...
|
|
*/
|
|
for(off = (x * y); off < ((x + cx) * (y + cy)); off++)
|
|
(*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
|
|
sizeof(u_int32_t), 1, 0, 0);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_bitblt(video_adapter_t *adp, ...)
|
|
{
|
|
va_list args;
|
|
vm_offset_t src, dst;
|
|
int count, i;
|
|
u_int32_t val;
|
|
|
|
va_start(args, adp);
|
|
|
|
src = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
|
|
0x0000000000fffff8;
|
|
dst = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
|
|
0x0000000000fffff8;
|
|
count = va_arg(args, int);
|
|
for(i = 0; i < count; i++, src++, dst++) {
|
|
val = READ_GFB_BUFFER(adp, src);
|
|
WRITE_GFB_BUFFER(adp, dst, val);
|
|
}
|
|
va_end(args);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
/*gfb_clear(video_adapter_t *adp, int n)*/
|
|
gfb_clear(video_adapter_t *adp)
|
|
{
|
|
int off;
|
|
|
|
#if 0
|
|
if(n == 0)
|
|
return(0);
|
|
#endif
|
|
|
|
/*
|
|
Just traverse the buffer, one 2K-pixel span at a time, clearing
|
|
each pixel...
|
|
*/
|
|
/* for(off = 0; off < (n * adp->va_line_width); off += (2 KB)) */
|
|
for(off = 0; off < adp->va_window_size; off++)
|
|
(*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
|
|
sizeof(u_int32_t), 1, 0, 0);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_diag(video_adapter_t *adp, int level)
|
|
{
|
|
video_info_t info;
|
|
struct gfb_softc *sc;
|
|
int error;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* Just dump everything we know about the adapter to the screen... */
|
|
fb_dump_adp_info(sc->driver_name, adp, level);
|
|
|
|
/* Try to get the info on this adapter... */
|
|
if(!(error = (*vidsw[adp->va_index]->get_info)(adp,
|
|
adp->va_initial_mode, &info)))
|
|
/*
|
|
Just dump everything we know about the adapter's mode
|
|
to the screen...
|
|
*/
|
|
fb_dump_mode_info(sc->driver_name, adp, &info, level);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error, i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
#if 0
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_save_cursor_palette)
|
|
error = sc->gfbc->ramdac_save_cursor_palette(adp,
|
|
&sc->gfbc->cursor_palette);
|
|
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_save_cursor_palette(adp,
|
|
&sc->gfbc->cursor_palette);
|
|
#endif
|
|
|
|
for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
|
|
palette[(3 * i)] = sc->gfbc->cursor_palette.red[i];
|
|
palette[(3 * i) + 1] = sc->gfbc->cursor_palette.green[i];
|
|
palette[(3 * i) + 2] = sc->gfbc->cursor_palette.blue[i];
|
|
}
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int error, i;
|
|
|
|
error = 0;
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
|
|
sc->gfbc->cursor_palette.red[i] = palette[(3 * i)];
|
|
sc->gfbc->cursor_palette.green[i] = palette[(3 * i) + 1];
|
|
sc->gfbc->cursor_palette.blue[i] = palette[(3 * i) + 2];
|
|
}
|
|
|
|
/* If we have a RAMDAC-specific counterpart, use it... */
|
|
if(sc->gfbc->ramdac_load_cursor_palette)
|
|
error = sc->gfbc->ramdac_load_cursor_palette(adp,
|
|
&sc->gfbc->cursor_palette);
|
|
else
|
|
/* Otherwise, use the built-in functionality... */
|
|
error = sc->gfbc->builtin_load_cursor_palette(adp,
|
|
&sc->gfbc->cursor_palette);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
|
|
{
|
|
int error, num_pixels;
|
|
|
|
if(n == 0)
|
|
return(0);
|
|
num_pixels = adp->va_info.vi_cheight * adp->va_line_width;
|
|
error = (*vidsw[adp->va_index]->bitblt)(adp, src * num_pixels,
|
|
dst * num_pixels, n * num_pixels);
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
gfb_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a,
|
|
int size, int bpp, int bit_ltor, int byte_ltor)
|
|
{
|
|
int i, j, k, num_shifts;
|
|
u_int32_t _p, val[32];
|
|
|
|
if(bpp < 1)
|
|
return(-1);
|
|
|
|
/*
|
|
If we don't display bits right-to-left (little-bitian?),
|
|
then perform a bit-swap on p...
|
|
*/
|
|
if(bit_ltor) {
|
|
num_shifts = 8 * size;
|
|
for(i = 0, _p = 0; i < num_shifts; i++, p >>= 1) {
|
|
_p <<= 1;
|
|
_p |= (p & 0x00000001);
|
|
}
|
|
} else
|
|
_p = p;
|
|
|
|
switch(bpp) {
|
|
/* Accelerate the simplest cases... */
|
|
case 1:
|
|
if((a & 0x00000001) == 0)
|
|
val[0] = 0;
|
|
else if(size <= 0)
|
|
val[0] = 0;
|
|
else if(size == 1)
|
|
val[0] = _p & 0x000000ff;
|
|
else if(size == 2)
|
|
val[0] = _p & 0x0000ffff;
|
|
else if(size == 3)
|
|
val[0] = _p & 0x00ffffff;
|
|
else if(size == 4)
|
|
val[0] = _p & 0xffffffff;
|
|
break;
|
|
|
|
/* Only do the following if we are not a simple case... */
|
|
case 8:
|
|
if(size > 0) {
|
|
a &= 0x000000ff;
|
|
val[0] = 0;
|
|
if(_p & 0x00000001) val[0] |= (a);
|
|
if(_p & 0x00000002) val[0] |= (a << 8);
|
|
if(_p & 0x00000004) val[0] |= (a << 16);
|
|
if(_p & 0x00000008) val[0] |= (a << 24);
|
|
val[1] = 0;
|
|
if(_p & 0x00000010) val[1] |= (a);
|
|
if(_p & 0x00000020) val[1] |= (a << 8);
|
|
if(_p & 0x00000040) val[1] |= (a << 16);
|
|
if(_p & 0x00000080) val[1] |= (a << 24);
|
|
}
|
|
if(size > 1) {
|
|
val[2] = 0;
|
|
if(_p & 0x00000100) val[2] |= (a);
|
|
if(_p & 0x00000200) val[2] |= (a << 8);
|
|
if(_p & 0x00000400) val[2] |= (a << 16);
|
|
if(_p & 0x00000800) val[2] |= (a << 24);
|
|
val[3] = 0;
|
|
if(_p & 0x00001000) val[3] |= (a);
|
|
if(_p & 0x00002000) val[3] |= (a << 8);
|
|
if(_p & 0x00004000) val[3] |= (a << 16);
|
|
if(_p & 0x00008000) val[3] |= (a << 24);
|
|
}
|
|
if(size > 2) {
|
|
val[4] = 0;
|
|
if(_p & 0x00010000) val[4] |= (a);
|
|
if(_p & 0x00020000) val[4] |= (a << 8);
|
|
if(_p & 0x00040000) val[4] |= (a << 16);
|
|
if(_p & 0x00080000) val[4] |= (a << 24);
|
|
val[5] = 0;
|
|
if(_p & 0x00100000) val[5] |= (a);
|
|
if(_p & 0x00200000) val[5] |= (a << 8);
|
|
if(_p & 0x00400000) val[5] |= (a << 16);
|
|
if(_p & 0x00800080) val[5] |= (a << 24);
|
|
}
|
|
if(size > 3) {
|
|
val[6] = 0;
|
|
if(_p & 0x01000000) val[6] |= (a);
|
|
if(_p & 0x02000000) val[6] |= (a << 8);
|
|
if(_p & 0x04000000) val[6] |= (a << 16);
|
|
if(_p & 0x08000000) val[6] |= (a << 24);
|
|
val[7] = 0;
|
|
if(_p & 0x10000000) val[7] |= (a);
|
|
if(_p & 0x20000000) val[7] |= (a << 8);
|
|
if(_p & 0x40000000) val[7] |= (a << 16);
|
|
if(_p & 0x80000000) val[7] |= (a << 24);
|
|
}
|
|
break;
|
|
case 16:
|
|
if(size > 0) {
|
|
a &= 0x0000ffff;
|
|
if(_p & 0x00000001) val[0] |= (a);
|
|
if(_p & 0x00000002) val[0] |= (a << 16);
|
|
if(_p & 0x00000004) val[1] |= (a);
|
|
if(_p & 0x00000008) val[1] |= (a << 16);
|
|
if(_p & 0x00000010) val[2] |= (a);
|
|
if(_p & 0x00000020) val[2] |= (a << 16);
|
|
if(_p & 0x00000040) val[3] |= (a);
|
|
if(_p & 0x00000080) val[3] |= (a << 16);
|
|
}
|
|
if(size > 1) {
|
|
if(_p & 0x00000100) val[4] |= (a);
|
|
if(_p & 0x00000200) val[4] |= (a << 16);
|
|
if(_p & 0x00000400) val[5] |= (a);
|
|
if(_p & 0x00000800) val[5] |= (a << 16);
|
|
if(_p & 0x00001000) val[6] |= (a);
|
|
if(_p & 0x00002000) val[6] |= (a << 16);
|
|
if(_p & 0x00004000) val[7] |= (a);
|
|
if(_p & 0x00008000) val[7] |= (a << 16);
|
|
}
|
|
if(size > 2) {
|
|
if(_p & 0x00010000) val[8] |= (a);
|
|
if(_p & 0x00020000) val[8] |= (a << 16);
|
|
if(_p & 0x00040000) val[9] |= (a);
|
|
if(_p & 0x00080000) val[9] |= (a << 16);
|
|
if(_p & 0x00100000) val[10] |= (a);
|
|
if(_p & 0x00200000) val[10] |= (a << 16);
|
|
if(_p & 0x00400000) val[11] |= (a);
|
|
if(_p & 0x00800000) val[11] |= (a << 16);
|
|
}
|
|
if(size > 3) {
|
|
if(_p & 0x01000000) val[12] |= (a);
|
|
if(_p & 0x02000000) val[12] |= (a << 16);
|
|
if(_p & 0x04000000) val[13] |= (a);
|
|
if(_p & 0x08000000) val[13] |= (a << 16);
|
|
if(_p & 0x10000000) val[14] |= (a);
|
|
if(_p & 0x20000000) val[14] |= (a << 16);
|
|
if(_p & 0x40000000) val[15] |= (a);
|
|
if(_p & 0x80000000) val[15] |= (a << 16);
|
|
}
|
|
break;
|
|
case 32:
|
|
if(size > 0) {
|
|
a &= 0xffffffff;
|
|
if(_p & 0x00000001) val[0] = (a);
|
|
if(_p & 0x00000002) val[1] = (a);
|
|
if(_p & 0x00000004) val[2] = (a);
|
|
if(_p & 0x00000008) val[3] = (a);
|
|
if(_p & 0x00000010) val[4] = (a);
|
|
if(_p & 0x00000020) val[5] = (a);
|
|
if(_p & 0x00000040) val[6] = (a);
|
|
if(_p & 0x00000080) val[7] = (a);
|
|
}
|
|
if(size > 1) {
|
|
if(_p & 0x00000100) val[8] = (a);
|
|
if(_p & 0x00000200) val[9] = (a);
|
|
if(_p & 0x00000400) val[10] = (a);
|
|
if(_p & 0x00000800) val[11] = (a);
|
|
if(_p & 0x00001000) val[12] = (a);
|
|
if(_p & 0x00002000) val[13] = (a);
|
|
if(_p & 0x00004000) val[14] = (a);
|
|
if(_p & 0x00008000) val[15] = (a);
|
|
}
|
|
if(size > 2) {
|
|
if(_p & 0x00010000) val[16] = (a);
|
|
if(_p & 0x00020000) val[17] = (a);
|
|
if(_p & 0x00040000) val[18] = (a);
|
|
if(_p & 0x00080000) val[19] = (a);
|
|
if(_p & 0x00100000) val[20] = (a);
|
|
if(_p & 0x00200000) val[21] = (a);
|
|
if(_p & 0x00400000) val[22] = (a);
|
|
if(_p & 0x00800000) val[23] = (a);
|
|
}
|
|
if(size > 3) {
|
|
if(_p & 0x01000000) val[24] = (a);
|
|
if(_p & 0x02000000) val[25] = (a);
|
|
if(_p & 0x04000000) val[26] = (a);
|
|
if(_p & 0x08000000) val[27] = (a);
|
|
if(_p & 0x10000000) val[28] = (a);
|
|
if(_p & 0x20000000) val[29] = (a);
|
|
if(_p & 0x40000000) val[30] = (a);
|
|
if(_p & 0x80000000) val[31] = (a);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
j = (bpp == 1) ? 1 : bpp * size / sizeof(u_int32_t);
|
|
|
|
/*
|
|
If we don't display bytes right-to-left (little-endian),
|
|
then perform a byte-swap on p (we don't have to swap if
|
|
bpp == 1 and val[0] == 0)...
|
|
*/
|
|
if((byte_ltor) && (j > 1) && (val[j] != 0)) {
|
|
for(i = 0; i < (j - i); i++) {
|
|
_p = val[j - i];
|
|
val[j - i] = val[i];
|
|
val[i] = _p;
|
|
}
|
|
for(i = 0; i < j; i++) {
|
|
_p = val[i];
|
|
for(k = 0, val[i] = 0; k < sizeof(u_int32_t);
|
|
k++, _p >>= 8) {
|
|
val[i] <<= 8;
|
|
val[i] |= (_p & 0xff);
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < j; i++) {
|
|
/* Write the pixel-row... */
|
|
WRITE_GFB_BUFFER(adp, (off + i), val[i]);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
|
|
{
|
|
vm_offset_t poff;
|
|
struct gfb_softc *sc;
|
|
int i, pixel_size;
|
|
u_int row, col;
|
|
u_int8_t *pixel;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
pixel_size = adp->va_info.vi_depth / 8;
|
|
|
|
/* Get the start of the array of pixels rows for this character... */
|
|
pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
|
|
|
|
/* Calculate the new cursor position... */
|
|
row = off / adp->va_info.vi_width;
|
|
col = off % adp->va_info.vi_width;
|
|
|
|
/* Iterate over all the pixel rows for this character... */
|
|
for(i = 0; i < adp->va_info.vi_cheight; i++) {
|
|
/* Get the address of the character's pixel-row... */
|
|
poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
|
|
(((row * adp->va_info.vi_cheight) + i) *
|
|
adp->va_line_width)) / sizeof(u_int32_t);
|
|
|
|
/* Now display the current pixel row... */
|
|
(*vidsw[adp->va_index]->putp)(adp, poff, pixel[i], a,
|
|
sizeof(u_int8_t), 1, 1, 0);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
|
|
{
|
|
struct gfb_softc *sc;
|
|
int i;
|
|
|
|
sc = gfb_device_softcs[adp->va_model][adp->va_unit];
|
|
|
|
/* If the string in empty, just return now... */
|
|
if(len == 0)
|
|
return(0);
|
|
|
|
for(i = 0; i < len; i++)
|
|
(*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0x00ff,
|
|
(s[i] & 0xff00) >> 8);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
|
|
u_int32_t pixel_mask, int size, int width)
|
|
{
|
|
vm_offset_t poff;
|
|
int i, pixel_size;
|
|
|
|
pixel_size = adp->va_info.vi_depth / 8;
|
|
|
|
/* Iterate over all the pixel rows for the mouse pointer... */
|
|
for(i = 0; i < size; i++) {
|
|
/* Get the address of the mouse pointer's pixel-row... */
|
|
poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
|
|
sizeof(u_int32_t);
|
|
/* Now display the current pixel-row... */
|
|
(*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
|
|
pixel_mask, sizeof(u_int8_t), 1, 1, 0);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
gfb_error(void)
|
|
{
|
|
|
|
return(0);
|
|
}
|