Add the TGA video driver. This is a great accomplishtment and will help

us a lot on older Alphas.
Andrew Gallatin, Thomas V. Crimi, and Peter Jeremy contributed to this
work along with the submitter.

Submitted by:	 Andrew M. Miklic <miklic@home.com>
This commit is contained in:
David E. O'Brien 2001-11-01 08:26:30 +00:00
parent a91e945fbe
commit 2a200695e4
10 changed files with 9562 additions and 739 deletions

4678
sys/dev/fb/boot_font.c Normal file

File diff suppressed because it is too large Load Diff

948
sys/dev/fb/gfb.c Normal file
View File

@ -0,0 +1,948 @@
/*-
* 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_memio.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 <pci/pcireg.h>
#include <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.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, 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 != 8))
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, 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 = 8;
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, int prot)
{
int error;
if(offset > adp->va_window_size - PAGE_SIZE)
error = ENXIO;
#ifdef __i386__
error = i386_btop(adp->va_info.vi_window + offset);
#elsif defined(__alpha__)
error = alpha_btop(adp->va_info.vi_window + offset);
#else
error = ENXIO;
#endif
return(error);
}
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)
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)
{
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);
}

172
sys/dev/fb/gfb.h Normal file
View File

@ -0,0 +1,172 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic
*
* $FreeBSD$
*/
#ifndef _FB_GFB_H_
#define _FB_GFB_H_
#define MAX_NUM_GFB_CARDS 16
#define GFB_UNIT(dev) minor(dev)
#define GFB_MKMINOR(unit) (unit)
#define BIT_REVERSE(byte) \
((((byte) & 0x01) << 7) | \
(((byte) & 0x02) << 5) | \
(((byte) & 0x04) << 3) | \
(((byte) & 0x08) << 1) | \
(((byte) & 0x10) >> 1) | \
(((byte) & 0x20) >> 3) | \
(((byte) & 0x40) >> 5) | \
(((byte) & 0x80) >> 7))
#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
struct gfb_softc;
int gfb_error(void);
vi_probe_t gfb_probe;
vi_init_t gfb_init;
vi_get_info_t gfb_get_info;
/*vi_query_mode_t gfb_query_mode;*/
vi_set_mode_t gfb_set_mode;
vi_save_font_t gfb_save_font;
vi_load_font_t gfb_load_font;
vi_show_font_t gfb_show_font;
vi_save_palette_t gfb_save_palette;
vi_load_palette_t gfb_load_palette;
vi_save_state_t gfb_save_state;
vi_load_state_t gfb_load_state;
vi_read_hw_cursor_t gfb_read_hw_cursor;
vi_set_hw_cursor_t gfb_set_hw_cursor;
vi_set_hw_cursor_shape_t gfb_set_hw_cursor_shape;
vi_mmap_t gfb_mmap;
vi_ioctl_t gfb_ioctl;
vi_set_border_t gfb_set_border;
vi_set_win_org_t gfb_set_win_org;
vi_fill_rect_t gfb_fill_rect;
vi_bitblt_t gfb_bitblt;
vi_clear_t gfb_clear;
vi_diag_t gfb_diag;
vi_save_cursor_palette_t gfb_save_cursor_palette;
vi_load_cursor_palette_t gfb_load_cursor_palette;
vi_copy_t gfb_copy;
vi_putp_t gfb_putp;
vi_putc_t gfb_putc;
vi_puts_t gfb_puts;
vi_putm_t gfb_putm;
typedef void gfb_ramdac_init_t(struct gfb_softc *);
typedef u_int8_t gfb_ramdac_rd_t(struct gfb_softc *, u_int);
typedef void gfb_ramdac_wr_t(struct gfb_softc *, u_int, u_int8_t);
typedef void gfb_ramdac_intr_t(struct gfb_softc *);
typedef int gfb_ramdac_save_palette_t(video_adapter_t *, video_color_palette_t *);
typedef int gfb_ramdac_load_palette_t(video_adapter_t *, video_color_palette_t *);
typedef int gfb_ramdac_save_cursor_palette_t(video_adapter_t *, struct fbcmap *);
typedef int gfb_ramdac_load_cursor_palette_t(video_adapter_t *, struct fbcmap *);
typedef int gfb_ramdac_read_hw_cursor_t(video_adapter_t *, int *, int *);
typedef int gfb_ramdac_set_hw_cursor_t(video_adapter_t *, int, int);
typedef int gfb_ramdac_set_hw_cursor_shape_t(video_adapter_t *, int, int, int, int);
typedef int gfb_builtin_save_palette_t(video_adapter_t *, video_color_palette_t *);
typedef int gfb_builtin_load_palette_t(video_adapter_t *, video_color_palette_t *);
typedef int gfb_builtin_save_cursor_palette_t(video_adapter_t *, struct fbcmap *);
typedef int gfb_builtin_load_cursor_palette_t(video_adapter_t *, struct fbcmap *);
typedef int gfb_builtin_read_hw_cursor_t(video_adapter_t *, int *, int *);
typedef int gfb_builtin_set_hw_cursor_t(video_adapter_t *, int, int);
typedef int gfb_builtin_set_hw_cursor_shape_t(video_adapter_t *, int, int, int, int);
struct monitor {
u_int16_t cols; /* Columns */
u_int16_t hfp; /* Horizontal Front Porch */
u_int16_t hsync; /* Horizontal Sync */
u_int16_t hbp; /* Horizontal Back Porch */
u_int16_t rows; /* Rows */
u_int16_t vfp; /* Vertical Front Porch */
u_int16_t vsync; /* Vertical Sync */
u_int16_t vbp; /* Vertical Back Porch */
u_int32_t dotclock; /* Dot Clock */
};
struct gfb_font {
int width;
int height;
u_char data[256 * 32];
};
struct gfb_conf {
char *name; /* name for this board type */
char *ramdac_name; /* name for this RAMDAC */
u_char *font;
struct gfb_font fonts[4];
video_color_palette_t palette;
struct fbcmap cursor_palette;
gfb_ramdac_init_t *ramdac_init;
gfb_ramdac_rd_t *ramdac_rd;
gfb_ramdac_wr_t *ramdac_wr;
gfb_ramdac_intr_t *ramdac_intr;
gfb_ramdac_save_palette_t *ramdac_save_palette;
gfb_ramdac_load_palette_t *ramdac_load_palette;
gfb_ramdac_save_cursor_palette_t *ramdac_save_cursor_palette;
gfb_ramdac_load_cursor_palette_t *ramdac_load_cursor_palette;
gfb_ramdac_read_hw_cursor_t *ramdac_read_hw_cursor;
gfb_ramdac_set_hw_cursor_t *ramdac_set_hw_cursor;
gfb_ramdac_set_hw_cursor_shape_t *ramdac_set_hw_cursor_shape;
gfb_builtin_save_palette_t *builtin_save_palette;
gfb_builtin_load_palette_t *builtin_load_palette;
gfb_builtin_save_cursor_palette_t *builtin_save_cursor_palette;
gfb_builtin_load_cursor_palette_t *builtin_load_cursor_palette;
gfb_builtin_read_hw_cursor_t *builtin_read_hw_cursor;
gfb_builtin_set_hw_cursor_t *builtin_set_hw_cursor;
gfb_builtin_set_hw_cursor_shape_t *builtin_set_hw_cursor_shape;
};
struct video_adapter;
struct genfb_softc;
typedef struct gfb_softc {
char *driver_name; /* name for this driver */
struct video_adapter *adp;
struct genfb_softc *gensc;
struct gfb_conf *gfbc;
bus_space_handle_t bhandle;
bus_space_tag_t btag;
bus_space_handle_t regs;
void *intrhand;
struct resource *irq;
struct resource *res;
u_int8_t rev; /* GFB revision */
int type;
int model;
struct cdevsw *cdevsw;
dev_t devt;
} *gfb_softc_t;
#endif /* _FB_GFB_H_ */

2431
sys/dev/fb/tga.c Normal file

File diff suppressed because it is too large Load Diff

155
sys/dev/fb/tga.h Normal file
View File

@ -0,0 +1,155 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic
*
* $FreeBSD$
*/
#ifndef _FB_TGA_H_
#define _FB_TGA_H_
/* TGA-specific FB stuff */
struct gfb_softc;
struct video_adapter;
/*
* Register definitions for the Brooktree Bt463 135MHz Monolithic
* CMOS TrueVu RAMDAC.
*/
/*
* Directly-accessible registers. Note the address register is
* auto-incrementing.
*/
#define BT463_REG_ADDR_LOW 0x00 /* C1,C0 == 0,0 */
#define BT463_REG_ADDR_HIGH 0x01 /* C1,C0 == 0,1 */
#define BT463_REG_IREG_DATA 0x02 /* C1,C0 == 1,0 */
#define BT463_REG_CMAP_DATA 0x03 /* C1,C0 == 1,1 */
#define BT463_REG_MAX BT463_REG_CMAP_DATA
/*
* All internal register access to the Bt463 is done indirectly via the
* Address Register (mapped into the host bus in a device-specific
* fashion). The following register definitions are in terms of
* their address register address values.
*/
/* C1,C0 must be 1,0 */
#define BT463_IREG_CURSOR_COLOR_0 0x0100 /* 3 r/w cycles */
#define BT463_IREG_CURSOR_COLOR_1 0x0101 /* 3 r/w cycles */
#define BT463_IREG_ID 0x0200
#define BT463_IREG_COMMAND_0 0x0201
#define BT463_IREG_COMMAND_1 0x0202
#define BT463_IREG_COMMAND_2 0x0203
#define BT463_IREG_READ_MASK_P0_P7 0x0205
#define BT463_IREG_READ_MASK_P8_P15 0x0206
#define BT463_IREG_READ_MASK_P16_P23 0x0207
#define BT463_IREG_READ_MASK_P24_P27 0x0208
#define BT463_IREG_BLINK_MASK_P0_P7 0x0209
#define BT463_IREG_BLINK_MASK_P8_P15 0x020a
#define BT463_IREG_BLINK_MASK_P16_P23 0x020b
#define BT463_IREG_BLINK_MASK_P24_P27 0x020c
#define BT463_IREG_TEST 0x020d
#define BT463_IREG_INPUT_SIG 0x020e /* 2 of 3 r/w cycles */
#define BT463_IREG_OUTPUT_SIG 0x020f /* 3 r/w cycles */
#define BT463_IREG_REVISION 0x0220
#define BT463_IREG_WINDOW_TYPE_TABLE 0x0300 /* 3 r/w cycles */
#define BT463_NWTYPE_ENTRIES 0x10 /* 16 window type entries */
/* C1,C0 must be 1,1 */
#define BT463_IREG_CPALETTE_RAM 0x0000 /* 3 r/w cycles */
#define BT463_NCMAP_ENTRIES 0x210 /* 528 CMAP entries */
#define BT463_DATA_CURCMAP_CHANGED 0x01 /* cursor colormap changed */
#define BT463_DATA_CMAP_CHANGED 0x02 /* colormap changed */
#define BT463_DATA_WTYPE_CHANGED 0x04 /* window type table changed */
#define BT463_DATA_ALL_CHANGED 0x07
/*
* Register definitions for the Brooktree Bt485A 170MHz Monolithic
* CMOS True-Color RAMDAC.
*/
/*
* Directly-addressed registers.
*/
#define BT485_REG_PCRAM_WRADDR 0x00
#define BT485_REG_PALETTE 0x01
#define BT485_REG_PIXMASK 0x02
#define BT485_REG_PCRAM_RDADDR 0x03
#define BT485_REG_COC_WRADDR 0x04
#define BT485_REG_COCDATA 0x05
#define BT485_REG_COMMAND_0 0x06
#define BT485_REG_COC_RDADDR 0x07
#define BT485_REG_COMMAND_1 0x08
#define BT485_REG_COMMAND_2 0x09
#define BT485_REG_STATUS 0x0a
#define BT485_REG_EXTENDED BT485_REG_STATUS
#define BT485_REG_CURSOR_RAM 0x0b
#define BT485_REG_CURSOR_X_LOW 0x0c
#define BT485_REG_CURSOR_X_HIGH 0x0d
#define BT485_REG_CURSOR_Y_LOW 0x0e
#define BT485_REG_CURSOR_Y_HIGH 0x0f
#define BT485_REG_MAX 0x0f
#define BT485_IREG_STATUS 0x00
#define BT485_IREG_COMMAND_3 0x01
#define BT485_IREG_COMMAND_4 0x02
#define BT485_IREG_RSA 0x20
#define BT485_IREG_GSA 0x21
#define BT485_IREG_BSA 0x22
#define BT485_DATA_ENB_CHANGED 0x01 /* cursor enable changed */
#define BT485_DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
#define BT485_DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
#define BT485_DATA_CMAP_CHANGED 0x08 /* colormap changed */
#define BT485_DATA_ALL_CHANGED 0x0f
#define CURSOR_MAX_SIZE 64
#define TGA_DRIVER_NAME "tga"
#define TGA2_DRIVER_NAME "tga2"
#define BTWREG(sc, addr, val) \
sc->gfbc->ramdac_wr((sc), BT463_REG_ADDR_LOW, (addr) & 0xff); \
sc->gfbc->ramdac_wr((sc), BT463_REG_ADDR_HIGH, ((addr) >> 8) & 0xff);\
(sc)->gfbc->ramdac_wr((sc), BT463_REG_IREG_DATA, (val))
#define BTWNREG(sc, val) \
(sc)->gfbc->ramdac_wr((sc), BT463_REG_IREG_DATA, (val))
#define BTRREG(sc, addr) \
sc->gfbc->ramdac_wr((sc), BT463_REG_ADDR_LOW, (addr) & 0xff); \
sc->gfbc->ramdac_wr((sc), BT463_REG_ADDR_HIGH, ((addr) >> 8) & 0xff);\
(sc)->gfbc->ramdac_rd((sc), BT463_REG_IREG_DATA)
#define BTRNREG(sc) \
(sc)->gfbc->ramdac_rd((sc), BT463_REG_IREG_DATA)
#endif /* _FB_TGA_H_ */

322
sys/dev/gfb/gfb_pci.c Normal file
View File

@ -0,0 +1,322 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic, Andrew Gallatin, and Thomas V. Crimi
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#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_memio.h>
#include <machine/bus.h>
#include <machine/pc/vesa.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/gfb.h>
#include <dev/gfb/gfb_pci.h>
#ifdef __alpha__
#include <machine/rpb.h>
#include <machine/cpu.h>
#endif /* __alpha__ */
#include "opt_fb.h"
static devclass_t gfb_devclass;
#ifdef __alpha__
extern void sccnattach(void);
#endif /* __alpha__ */
extern struct gfb_font bold8x16;
extern struct gfb_softc *gfb_device_softcs[2][16];
int
pcigfb_attach(device_t dev)
{
int s;
gfb_softc_t sc;
video_adapter_t *adp;
int unit, flags, error, rid, va_index;
#ifdef __alpha__
struct ctb *ctb;
#endif /* __alpha__ */
s = splimp();
error = 0;
unit = device_get_unit(dev);
flags = device_get_flags(dev);
sc = device_get_softc(dev);
sc->rev = pci_get_revid(dev);
rid = GFB_MEM_BASE_RID;
sc->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1,
RF_ACTIVE|PCI_RF_DENSE);
if(sc->res == NULL) {
device_printf(dev, "couldn't map memory\n");
goto fail;
}
sc->btag = rman_get_bustag(sc->res);
sc->bhandle = rman_get_bushandle(sc->res);
/* Allocate interrupt (irq)... */
rid = 0x0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
RF_SHAREABLE|RF_ACTIVE);
if(sc->irq == NULL) {
device_printf(dev, "Couldn't map interrupt\n");
goto fail;
}
if((va_index = vid_find_adapter(sc->driver_name, unit)) < 0) {
sc->adp = (video_adapter_t *)malloc(sizeof(video_adapter_t),
M_DEVBUF, M_NOWAIT);
adp = sc->adp;
bzero(adp, sizeof(video_adapter_t));
vid_init_struct(adp, sc->driver_name, sc->type, unit);
if(vid_register(adp) < 0) {
free(sc->adp, M_DEVBUF);
goto fail;
}
adp->va_flags |= V_ADP_REGISTERED;
adp->va_model = sc->model;
adp->va_mem_base = (vm_offset_t)rman_get_virtual(sc->res);
adp->va_mem_size = rman_get_end(sc->res) -
rman_get_start(sc->res);
adp->va_io_base = NULL;
adp->va_io_size = 0;
adp->va_crtc_addr = NULL;
gfb_device_softcs[sc->model][unit] = sc;
sc->gfbc = (struct gfb_conf *)malloc(sizeof(struct gfb_conf),
M_DEVBUF, M_NOWAIT);
bzero(sc->gfbc, sizeof(struct gfb_conf));
if((*vidsw[adp->va_index]->init)(unit, adp, flags)) {
device_printf(dev, "Couldn't initialize adapter\n");
vid_unregister(adp);
gfb_device_softcs[sc->model][unit] = NULL;
free(sc->gfbc, M_DEVBUF);
free(sc->adp, M_DEVBUF);
goto fail;
}
sc->gfbc->palette.red =
(u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
M_NOWAIT);
sc->gfbc->palette.green =
(u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
M_NOWAIT);
sc->gfbc->palette.blue =
(u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
M_NOWAIT);
sc->gfbc->cursor_palette.red =
(u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
M_NOWAIT);
sc->gfbc->cursor_palette.green =
(u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
M_NOWAIT);
sc->gfbc->cursor_palette.blue =
(u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
M_NOWAIT);
if(gfb_init(unit, adp, flags)) {
device_printf(dev, "Couldn't initialize framebuffer\n");
vid_unregister(adp);
gfb_device_softcs[sc->model][unit] = NULL;
free(sc->gfbc->cursor_palette.blue, M_DEVBUF);
free(sc->gfbc->cursor_palette.green, M_DEVBUF);
free(sc->gfbc->cursor_palette.red, M_DEVBUF);
free(sc->gfbc->palette.blue, M_DEVBUF);
free(sc->gfbc->palette.green, M_DEVBUF);
free(sc->gfbc->palette.red, M_DEVBUF);
free(sc->gfbc, M_DEVBUF);
free(sc->adp, M_DEVBUF);
goto fail;
}
} else {
(*vidsw[va_index]->probe)(unit, &adp, (void *)sc->driver_name,
flags);
sc->adp = adp;
sc->gfbc = gfb_device_softcs[sc->model][unit]->gfbc;
gfb_device_softcs[sc->model][unit] = sc;
}
/*
This is a back-door for PCI devices--since FreeBSD no longer supports
PCI configuration-space accesses during the *configure() phase for
video adapters, we cannot identify a PCI device as the console during
the first call to sccnattach(). There must be a second chance for PCI
adapters to be recognized as the console, and this is it...
*/
#ifdef __alpha__
ctb = (struct ctb *)(((caddr_t)hwrpb) + hwrpb->rpb_ctb_off);
if (ctb->ctb_term_type == 3) /* Display adapter */
sccnattach();
#endif /* __alpha__ */
device_printf(dev, "Board type %s\n", sc->gfbc->name);
device_printf(dev, "%d x %d, %dbpp, %s RAMDAC\n",
sc->adp->va_info.vi_width, sc->adp->va_info.vi_height,
sc->adp->va_info.vi_depth, sc->gfbc->ramdac_name);
#ifdef FB_INSTALL_CDEV
/* attach a virtual frame buffer device */
error = fb_attach(makedev(0, unit), sc->adp, sc->cdevsw);
if(error)
goto fail;
if(bootverbose)
(*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
#if experimental
device_add_child(dev, "fb", -1);
bus_generic_attach(dev);
#endif /*experimental*/
#endif /*FB_INSTALL_CDEV*/
goto done;
fail:
if(sc->intrhand != NULL) {
bus_teardown_intr(dev, sc->irq, sc->intrhand);
sc->intrhand = NULL;
}
if(sc->irq != NULL) {
rid = 0x0;
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
sc->irq = NULL;
}
if(sc->res != NULL) {
rid = GFB_MEM_BASE_RID;
bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
sc->res = NULL;
}
error = ENXIO;
done:
splx(s);
return(error);
}
int
pcigfb_detach(device_t dev)
{
struct gfb_softc *sc;
int rid;
sc = device_get_softc(dev);
#ifdef FB_INSTALL_CDEV
destroy_dev(sc->devt);
#endif /*FB_INSTALL_CDEV*/
bus_teardown_intr(dev, sc->irq, sc->intrhand);
rid = 0x0;
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
rid = GFB_MEM_BASE_RID;
bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
return(0);
}
#ifdef FB_INSTALL_CDEV
int
pcigfb_open(dev_t dev, int flag, int mode, struct proc *p)
{
struct gfb_softc *sc;
int error;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
if(sc == NULL)
error = ENXIO;
else if(mode & (O_CREAT | O_APPEND | O_TRUNC))
error = ENODEV;
else
error = genfbopen(&sc->gensc, sc->adp, flag, mode, p);
return(error);
}
int
pcigfb_close(dev_t dev, int flag, int mode, struct proc *p)
{
struct gfb_softc *sc;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
return genfbclose(&sc->gensc, sc->adp, flag, mode, p);
}
int
pcigfb_read(dev_t dev, struct uio *uio, int flag)
{
struct gfb_softc *sc;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
return genfbread(&sc->gensc, sc->adp, uio, flag);
}
int
pcigfb_write(dev_t dev, struct uio *uio, int flag)
{
struct gfb_softc *sc;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
return genfbwrite(&sc->gensc, sc->adp, uio, flag);
}
int
pcigfb_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
struct gfb_softc *sc;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, p);
}
int
pcigfb_mmap(dev_t dev, vm_offset_t offset, int prot)
{
struct gfb_softc *sc;
sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
return genfbmmap(&sc->gensc, sc->adp, offset, prot);
}
#endif /*FB_INSTALL_CDEV*/

114
sys/dev/gfb/gfb_pci.h Normal file
View File

@ -0,0 +1,114 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic
*
* $FreeBSD$
*/
#ifndef _PCI_GFB_H_
#define _PCI_GFB_H_
#define GFB_MEM_BASE_RID 0x10
typedef u_int32_t gfb_reg_t;
/* GFB register access macros */
#define BUFADDR(adp, off) \
/* (adp)->va_buffer = (adp)->va_mem_base + \
(((adp)->va_buffer - \
(adp)->va_mem_base + \
(adp)->va_buffer_size) % \
(adp)->va_mem_size), \
(adp)->va_buffer_alias = ((adp)->va_buffer - \
(adp)->va_mem_base) / \
(adp)->va_buffer_size, \
(adp)->va_window = (adp)->va_buffer + \
(((adp)->va_window - \
(adp)->va_mem_base) / \
(adp)->va_buffer_alias), \
*/ ((adp)->va_window + (adp)->va_window_orig + \
((vm_offset_t)(off) << 2L))
#define REGADDR(adp, reg) \
/* (adp)->va_buffer = (adp)->va_mem_base + \
(((adp)->va_buffer - \
(adp)->va_mem_base + \
(adp)->va_buffer_size) % \
(adp)->va_mem_size), \
(adp)->va_buffer_alias = ((adp)->va_buffer - \
(adp)->va_mem_base) / \
(adp)->va_buffer_size, \
(adp)->va_registers = (adp)->va_buffer + \
(((adp)->va_registers - \
(adp)->va_mem_base) / \
(adp)->va_buffer_alias), \
*/ ((adp)->va_registers + ((vm_offset_t)(reg) << 2L))
#define READ_GFB_REGISTER(adp, reg) \
(*(u_int32_t *)(REGADDR(adp, reg)))
#define WRITE_GFB_REGISTER(adp, reg, val) \
(*(u_int32_t*)(REGADDR(adp, reg)) = (val))
#define GFB_REGISTER_WRITE_BARRIER(sc, reg, nregs) \
bus_space_barrier((sc)->btag, (sc)->regs, ((reg) << 2), \
4 * (nregs), BUS_SPACE_BARRIER_WRITE)
#define GFB_REGISTER_READ_BARRIER(sc, reg, nregs) \
bus_space_barrier((sc)->btag, (sc)->regs, ((reg) << 2), \
4 * (nregs), BUS_SPACE_BARRIER_READ)
#define GFB_REGISTER_READWRITE_BARRIER(sc, reg, nregs) \
bus_space_barrier((sc)->btag, (sc)->regs, ((reg) << 2), \
4 * (nregs), \
BUS_SPACE_BARRIER_READ | \
BUS_SPACE_BARRIER_WRITE)
#define READ_GFB_BUFFER(adp, reg) \
(*(u_int32_t *)(BUFADDR(adp, reg)))
#define WRITE_GFB_BUFFER(adp, reg, val) \
(*(u_int32_t*)(BUFADDR(adp, reg)) = (val))
/*int pcigfb_probe(device_t);*/
int pcigfb_attach(device_t);
int pcigfb_detach(device_t);
#ifdef FB_INSTALL_CDEV
d_open_t pcigfb_open;
d_close_t pcigfb_close;
d_read_t pcigfb_read;
d_write_t pcigfb_write;
d_ioctl_t pcigfb_ioctl;
d_mmap_t pcigfb_mmap;
#endif /*FB_INSTALL_CDEV*/
typedef struct gfb_type {
int vendor_id;
int device_id;
char* name;
} *gfb_type_t;
#endif /* _PCI_GFB_H_ */

File diff suppressed because it is too large Load Diff

252
sys/dev/tga/tga_pci.c Normal file
View File

@ -0,0 +1,252 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic, Andrew Gallatin, and Thomas V. Crimi
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#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_memio.h>
#include <machine/bus.h>
#include <machine/pc/vesa.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/tga.h>
#include <dev/tga/tga_pci.h>
#include <dev/fb/gfb.h>
#include <dev/gfb/gfb_pci.h>
#include "opt_fb.h"
static int tga_probe(device_t);
static int tga_attach(device_t);
static void tga_intr(void *);
static device_method_t tga_methods[] = {
DEVMETHOD(device_probe, tga_probe),
DEVMETHOD(device_attach, tga_attach),
DEVMETHOD(device_detach, pcigfb_detach),
{ 0, 0 }
};
static driver_t tga_driver = {
"tga",
tga_methods,
sizeof(struct gfb_softc)
};
static devclass_t tga_devclass;
DRIVER_MODULE(tga, pci, tga_driver, tga_devclass, 0, 0);
static struct gfb_type tga_devs[] = {
{ DEC_VENDORID, DEC_DEVICEID_TGA,
"DEC TGA (21030) 2D Graphics Accelerator" },
{ DEC_VENDORID, DEC_DEVICEID_TGA2,
"DEC TGA2 (21130) 3D Graphics Accelerator" },
{ 0, 0, NULL }
};
#ifdef FB_INSTALL_CDEV
static struct cdevsw tga_cdevsw = {
/* open */ pcigfb_open,
/* close */ pcigfb_close,
/* read */ pcigfb_read,
/* write */ pcigfb_write,
/* ioctl */ pcigfb_ioctl,
/* poll */ nopoll,
/* mmap */ pcigfb_mmap,
/* strategy */ nostrategy,
/* name */ "tga",
/* maj */ -1,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ 0,
/* bmaj */ -1
};
#endif /*FB_INSTALL_CDEV*/
static int
tga_probe(device_t dev)
{
int error;
gfb_type_t t;
t = tga_devs;
error = ENXIO;
while(t->name != NULL) {
if((pci_get_vendor(dev) == t->vendor_id) &&
(pci_get_device(dev) == t->device_id)) {
device_set_desc(dev, t->name);
error = 0;
break;
}
t++;
}
return(error);
}
static int
tga_attach(device_t dev)
{
gfb_softc_t sc;
int unit, error, rid;
error = 0;
unit = device_get_unit(dev);
sc = device_get_softc(dev);
bzero(sc, sizeof(struct gfb_softc));
sc->driver_name = TGA_DRIVER_NAME;
switch(pci_get_device(dev)) {
case DEC_DEVICEID_TGA2:
sc->model = 1;
sc->type = KD_TGA2;
break;
case DEC_DEVICEID_TGA:
sc->model = 0;
sc->type = KD_TGA;
break;
default:
device_printf(dev, "Unrecognized TGA type\n");
goto fail;
}
if((error = pcigfb_attach(dev))) {
goto fail;
}
sc->regs = sc->bhandle + TGA_MEM_CREGS;
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, tga_intr, sc,
&sc->intrhand);
if(error) {
device_printf(dev, "couldn't set up irq\n");
goto fail;
}
switch(sc->rev) {
case 0x1:
case 0x2:
case 0x3:
device_printf(dev, "TGA (21030) step %c\n", 'A' + sc->rev - 1);
break;
case 0x20:
device_printf(dev, "TGA2 (21130) abstract software model\n");
break;
case 0x21:
case 0x22:
device_printf(dev, "TGA2 (21130) pass %d\n", sc->rev - 0x20);
break;
default:
device_printf(dev, "Unknown stepping (0x%x)\n", sc->rev);
break;
}
#ifdef FB_INSTALL_CDEV
sc->cdevsw = &tga_cdevsw;
sc->devt = make_dev(sc->cdevsw, unit, 0, 0, 02660, "tga%x", unit);
#endif /*FB_INSTALL_CDEV*/
goto done;
fail:
if(sc->intrhand != NULL) {
bus_teardown_intr(dev, sc->irq, sc->intrhand);
sc->intrhand = NULL;
}
if(sc->irq != NULL) {
rid = 0x0;
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
sc->irq = NULL;
}
if(sc->res != NULL) {
rid = GFB_MEM_BASE_RID;
bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
sc->res = NULL;
}
error = ENXIO;
done:
return(error);
}
static void
tga_intr(void *v)
{
struct gfb_softc *sc = (struct gfb_softc *)v;
u_int32_t reg;
reg = READ_GFB_REGISTER(sc->adp, TGA_REG_SISR);
if((reg & 0x00010001) != 0x00010001) {
/* Odd. We never set any of the other interrupt enables. */
if((reg & 0x1f) != 0) {
/* Clear the mysterious pending interrupts. */
WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, (reg & 0x1f));
GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
/* This was our interrupt, even if we're puzzled as to
* why we got it. Don't make the interrupt handler
* think it was a stray.
*/
}
}
/* Call the scheduled handler... */
sc->gfbc->ramdac_intr(sc);
/*
Clear interrupt field (this way, we will force a
memory error if we get an unexpected interrupt)...
*/
sc->gfbc->ramdac_intr = NULL;
/* Disable the interrupt... */
WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00000001);
GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
}

299
sys/dev/tga/tga_pci.h Normal file
View File

@ -0,0 +1,299 @@
/*
* 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.
*
* Copyright (c) 2000 Andrew Miklic
*
* $FreeBSD$
*/
#ifndef _PCI_TGA_H_
#define _PCI_TGA_H_
/*
* Device-specific PCI register offsets and contents.
*/
#define TGA_PCIREG_PVRR 0x40 /* PCI Address Extension Register */
#define TGA_PCIREG_PAER 0x44 /* PCI VGA Redirect Register */
/*
* TGA Memory Space offsets
*/
#define TGA_MEM_ALTROM 0x0000000 /* 0MB -- Alternate ROM space */
#define TGA2_MEM_EXTDEV 0x0000000 /* 0MB -- External Device Access */
#define TGA_MEM_CREGS 0x0100000 /* 1MB -- Core Registers */
#define TGA_CREGS_SIZE 0x0100000 /* Core registers occupy 1MB */
#define TGA_CREGS_ALIAS 0x0000400 /* Register copies every 1kB */
#define TGA2_MEM_CLOCK 0x0060000 /* TGA2 Clock access */
#define TGA2_MEM_RAMDAC 0x0080000 /* TGA2 RAMDAC access */
/*
* TGA Core Space register numbers and contents.
*/
#define TGA_REG_GCBR0 0x000 /* Copy buffer 0 */
#define TGA_REG_GCBR1 0x001 /* Copy buffer 1 */
#define TGA_REG_GCBR2 0x002 /* Copy buffer 2 */
#define TGA_REG_GCBR3 0x003 /* Copy buffer 3 */
#define TGA_REG_GCBR4 0x004 /* Copy buffer 4 */
#define TGA_REG_GCBR5 0x005 /* Copy buffer 5 */
#define TGA_REG_GCBR6 0x006 /* Copy buffer 6 */
#define TGA_REG_GCBR7 0x007 /* Copy buffer 7 */
#define TGA_REG_GFGR 0x008 /* Foreground */
#define TGA_REG_GBGR 0x009 /* Background */
#define TGA_REG_GPMR 0x00a /* Plane Mask */
#define TGA_REG_GPXR_S 0x00b /* Pixel Mask (one-shot) */
#define TGA_REG_GMOR 0x00c /* Mode */
#define TGA_REG_GOPR 0x00d /* Raster Operation */
#define TGA_REG_GPSR 0x00e /* Pixel Shift */
#define TGA_REG_GADR 0x00f /* Address */
#define TGA_REG_GB1R 0x010 /* Bresenham 1 */
#define TGA_REG_GB2R 0x011 /* Bresenham 2 */
#define TGA_REG_GB3R 0x012 /* Bresenham 3 */
#define TGA_REG_GCTR 0x013 /* Continue */
#define TGA_REG_GDER 0x014 /* Deep */
#define TGA_REG_GREV 0x015 /* Start/Version on TGA,
* Revision on TGA2 */
#define TGA_REG_GSMR 0x016 /* Stencil Mode */
#define TGA_REG_GPXR_P 0x017 /* Pixel Mask (persistent) */
#define TGA_REG_CCBR 0x018 /* Cursor Base Address */
#define TGA_REG_VHCR 0x019 /* Horizontal Control */
#define TGA_REG_VVCR 0x01a /* Vertical Control */
#define TGA_REG_VVBR 0x01b /* Video Base Address */
#define TGA_REG_VVVR 0x01c /* Video Valid */
#define TGA_REG_CXYR 0x01d /* Cursor XY */
#define TGA_REG_VSAR 0x01e /* Video Shift Address */
#define TGA_REG_SISR 0x01f /* Interrupt Status */
#define TGA_REG_GDAR 0x020 /* Data */
#define TGA_REG_GRIR 0x021 /* Red Increment */
#define TGA_REG_GGIR 0x022 /* Green Increment */
#define TGA_REG_GBIR 0x023 /* Blue Increment */
#define TGA_REG_GZIR_L 0x024 /* Z-increment Low */
#define TGA_REG_GZIR_H 0x025 /* Z-Increment High */
#define TGA_REG_GDBR 0x026 /* DMA Base Address */
#define TGA_REG_GBWR 0x027 /* Bresenham Width */
#define TGA_REG_GZVR_L 0x028 /* Z-value Low */
#define TGA_REG_GZVR_H 0x029 /* Z-value High */
#define TGA_REG_GZBR 0x02a /* Z-base address */
/* GADR alias 0x02b */
#define TGA_REG_GRVR 0x02c /* Red Value */
#define TGA_REG_GGVR 0x02d /* Green Value */
#define TGA_REG_GBVR 0x02e /* Blue Value */
#define TGA_REG_GSWR 0x02f /* Span Width */
#define TGA_REG_EPSR 0x030 /* Pallete and DAC Setup */
/* reserved 0x031 - 0x3f */
#define TGA_REG_GSNR0 0x040 /* Slope-no-go 0 */
#define TGA_REG_GSNR1 0x041 /* Slope-no-go 1 */
#define TGA_REG_GSNR2 0x042 /* Slope-no-go 2 */
#define TGA_REG_GSNR3 0x043 /* Slope-no-go 3 */
#define TGA_REG_GSNR4 0x044 /* Slope-no-go 4 */
#define TGA_REG_GSNR5 0x045 /* Slope-no-go 5 */
#define TGA_REG_GSNR6 0x046 /* Slope-no-go 6 */
#define TGA_REG_GSNR7 0x047 /* Slope-no-go 7 */
#define TGA_REG_GSLR0 0x048 /* Slope 0 */
#define TGA_REG_GSLR1 0x049 /* Slope 1 */
#define TGA_REG_GSLR2 0x04a /* Slope 2 */
#define TGA_REG_GSLR3 0x04b /* Slope 3 */
#define TGA_REG_GSLR4 0x04c /* Slope 4 */
#define TGA_REG_GSLR5 0x04d /* Slope 5 */
#define TGA_REG_GSLR6 0x04e /* Slope 6 */
#define TGA_REG_GSLR7 0x04f /* Slope 7 */
#define TGA_REG_GBCR0 0x050 /* Block Color 0 */
#define TGA_REG_GBCR1 0x051 /* Block Color 1 */
#define TGA_REG_GBCR2 0x052 /* Block Color 2 */
#define TGA_REG_GBCR3 0x053 /* Block Color 3 */
#define TGA_REG_GBCR4 0x054 /* Block Color 4 */
#define TGA_REG_GBCR5 0x055 /* Block Color 5 */
#define TGA_REG_GBCR6 0x056 /* Block Color 6 */
#define TGA_REG_GBCR7 0x057 /* Block Color 7 */
#define TGA_REG_GCSR 0x058 /* Copy 64 Source */
#define TGA_REG_GCDR 0x059 /* Copy 64 Destination */
/* GC[SD]R aliases 0x05a - 0x05f */
/* reserved 0x060 - 0x077 */
#define TGA_REG_ERWR 0x078 /* EEPROM write */
/* reserved 0x079 */
#define TGA_REG_ECGR 0x07a /* Clock */
/* reserved 0x07b */
#define TGA_REG_EPDR 0x07c /* Pallete and DAC Data */
/* reserved 0x07d */
#define TGA_REG_SCSR 0x07e /* Command Status */
/* reserved 0x07f */
/*
* Deep register
*/
#define GDER_HSS 0x00010000 /* Horizontal sync select */
#define GDER_SDAC 0x00004000 /* Slow DAC */
#define GDER_RWE 0x00001000 /* ROM write enable */
#define GDER_SAMS 0x00000400 /* Serial-access memory size */
#define GDER_CS 0x00000200 /* Column size */
#define GDER_BLOCK_MASK 0x000001e0 /* eight/four column segments */
#define GDER_BLOCK_SHIFT 5
#define GDER_ADDR_MASK 0x0000001c /* PCI address mask */
#define GDER_ADDR_SHIFT 2
#define GDER_ADDR_4MB 0x00000000 /* PCI mask <24:22> = 4MB */
#define GDER_ADDR_8MB 0x00000001 /* PCI mask <24:23> = 8MB */
#define GDER_ADDR_16MB 0x00000003 /* PCI mask bit 24 = 16MB */
#define GDER_ADDR_32MB 0x00000007 /* No PCI masking = 32MB */
#define GDER_DEEP 0x00000001 /* 32-bpp or 8 bpp frame buffer */
/*
* Graphics mode register
*/
#define GMOR_CE 0x00008000 /* Cap ends */
#define GMOR_Z16 0x00004000 /* 16 or 24 bit Z valuesx */
#define GMOR_GE 0x00002000 /* Win32 or X environment */
#define GMOR_SBY_MASK 0x00001800 /* Source byte mask for 32-bpp FB */
#define GMOR_SBY_0 0x00000000 /* Source byte 0 */
#define GMOR_SBY_1 0x00000800 /* Source byte 1 */
#define GMOR_SBY_2 0x00001000 /* Source byte 2 */
#define GMOR_SBY_3 0x00001800 /* Source byte 3 */
#define GMOR_SBM_MASK 0x00000700 /* Source bitmap format (32-bpp FB) */
#define GMOR_SBM_8P 0x00000000 /* 8-bpp packed */
#define GMOR_SBM_8U 0x00000100 /* 8-bpp unpacked */
#define GMOR_SBM_12L 0x00000200 /* 12-bpp low */
#define GMOR_SBM_12H 0x00000600 /* 12-bpp high */
#define GMOR_SBM_24 0x00000300 /* 24-bpp */
#define GMOR_MODE_MASK 0x0000007f /* Graphics mode mask */
#define GMOR_MODE_SIMPLE 0x0000 /* Simple */
#define GMOR_MODE_SIMPLEZ 0x0010 /* Simple Z */
#define GMOR_MODE_OPQ_STPL 0x0001 /* Opaque Stipple */
#define GMOR_MODE_OPQ_FILL 0x0021 /* Opaque Fill */
#define GMOR_MODE_TRN_STPL 0x0005 /* Transparent Stipple */
#define GMOR_MODE_TRN_FILL 0x0025 /* Transparent Fill */
#define GMOR_MODE_BLK_STPL 0x000d /* Block Stipple */
#define GMOR_MODE_BLK_FILL 0x002d /* Block Fill */
#define GMOR_MODE_OPQ_LINE 0x0002 /* Opaque Line */
#define GMOR_MODE_TRN_LINE 0x0006 /* Transparent Line */
#define GMOR_MODE_CITNDL 0x000e /* Color-interpolated transparent */
/* non-dithered line */
#define GMOR_MODE_CITDL 0x002e /* Color-intrp. trans. dithered line */
#define GMOR_MODE_SITL 0x004e /* Sequential-intrp. transp line */
#define GMOR_MODE_ZOPQ_LINE 0x0012 /* Z buffered Opaque Line */
#define GMOR_MODE_ZTRN_LINE 0x0016 /* Z buffered Trans Line */
#define GMOR_MODE_ZOCITNDL 0x001a /* Z buffered Opaque CITND line */
#define GMOR_MODE_ZOCITDL 0x003a /* Z buffered Opaque CITD line */
#define GMOR_MODE_ZOSITL 0x005a /* Z buffered Opaque SIT line */
#define GMOR_MODE_ZTCITNDL 0x001e /* Z buffered transparent CITND line */
#define GMOR_MODE_ZTCITDL 0x003e /* Z buffered transparent CITD line */
#define GMOR_MODE_ZTSITL 0x005e /* Z buffered transparent SIT line */
#define GMOR_MODE_COPY 0x0007 /* Copy */
#define GMOR_MODE_DRDND 0x0017 /* DMA-read copy, non-dithered */
#define GMOR_MODE_DRDD 0x0037 /* DMA-read copy, dithered */
#define GMOR_MODE_DWCOPY 0x001f /* DMA-write copy */
/*
* Video Horizontal Control Register
*/
#define VHCR_ODD 0x80000000 /* Enable 4-pixel line skew */
#define VHCR_HSP 0x40000000 /* Horizontal sync polarity */
#define VHCR_BPORCH_MASK 0xfe00000 /* Back porch pixels / 4 */
#define VHCR_BPORCH_SHIFT 21
#define VHCR_HSYNC_MASK 0x001fc000 /* Hsync width / 4 */
#define VHCR_HSYNC_SHIFT 14
#define VHCR_FPORCH_MASK 0x3e00 /* Front porch pixels / 4 */
#define VHCR_FPORCH_SHIFT 9
#define VHCR_ACTIVE_MASK 0x01ff /* Active lines */
#define VHCR_REG2ACTIVE(reg) ((((reg) >> 19) & 0x0600) | ((reg) & 0x01ff))
#define VHCR_ACTIVE2REG(val) ((((val) & 0x0600) << 19) | ((val) & 0x01ff))
/*
* Video Vertical Control Register
*/
#define VVCR_SE 0x80000000 /* Stereo Enable */
#define VVCR_VSP 0x40000000 /* Vertical sync polarity */
#define VVCR_BPORCH_MASK 0xfc00000 /* Back porch in lines */
#define VVCR_BPORCH_SHIFT 22
#define VVCR_VSYNC_MASK 0x003f0000 /* Vsync width in lines */
#define VVCR_VSYNC_SHIFT 16
#define VVCR_FPORCH_MASK 0xf800 /* Front porch in lines */
#define VVCR_FPORCH_SHIFT 11
#define VVCR_ACTIVE_MASK 0x07ff /* Active lines */
/*
* Video Valid Register
*/
#define VVR_VIDEOVALID 0x00000001 /* 0 VGA, 1 TGA2 (TGA2 only) */
#define VVR_BLANK 0x00000002 /* 0 active, 1 blank */
#define VVR_CURSOR 0x00000004 /* 0 disable, 1 enable (TGA2 R/O) */
#define VVR_INTERLACE 0x00000008 /* 0 N/Int, 1 Int. (TGA2 R/O) */
#define VVR_DPMS_MASK 0x00000030 /* See "DMPS mask" below */
#define VVR_DPMS_SHIFT 4
#define VVR_DDC 0x00000040 /* DDC-in pin value (R/O) */
#define VVR_TILED 0x00000400 /* 0 linear, 1 tiled (not on TGA2) */
#define VVR_LDDLY_MASK 0x01ff0000 /* load delay in quad pixel clock ticks
(not on TGA2) */
#define VVR_LDDLY_SHIFT 16
/* TGA PCI register values */
#define DEC_VENDORID 0x1011
#define DEC_DEVICEID_TGA 0x0004
#define DEC_DEVICEID_TGA2 0x000D /* This is 0x000C in the documentation,
but probing yields 0x000D... */
#define TGA_TYPE_T8_01 0 /* 8bpp, 1MB */
#define TGA_TYPE_T8_02 1 /* 8bpp, 2MB */
#define TGA_TYPE_T8_22 2 /* 8bpp, 4MB */
#define TGA_TYPE_T8_44 3 /* 8bpp, 8MB */
#define TGA_TYPE_T32_04 4 /* 32bpp, 4MB */
#define TGA_TYPE_T32_08 5 /* 32bpp, 8MB */
#define TGA_TYPE_T32_88 6 /* 32bpp, 16MB */
#define TGA2_TYPE_3D30 7 /* 8bpp, 8MB */
#define TGA2_TYPE_4D20 8 /* 32bpp, 16MB */
#define TGA_TYPE_UNKNOWN 9 /* unknown */
/* Possible video modes for TGA2... */
#define TGA2_VGA_MODE 0
#define TGA2_2DA_MODE 1
/* TGA register access macros */
#define TGA_REG_SPACE_OFFSET 0x100000
#define BASIC_READ_TGA_REGISTER(adp, reg) \
*(u_int32_t *)((adp)->va_mem_base + \
(vm_offset_t)TGA_REG_SPACE_OFFSET + \
(((vm_offset_t)(reg) << 2L)))
#endif /* _PCI_TGA_H_ */