2042 lines
53 KiB
C
2042 lines
53 KiB
C
/* $NetBSD: grf_rh.c,v 1.10 1996/01/28 19:19:05 chopps Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1994 Markus Wild
|
|
* Copyright (c) 1994 Lutz Vieweg
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Lutz Vieweg.
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include "grfrh.h"
|
|
#if NGRFRH > 0
|
|
|
|
/*
|
|
* Graphics routines for the Retina BLT Z3 board,
|
|
* using the NCR 77C32BLT VGA controller.
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/device.h>
|
|
#include <sys/malloc.h>
|
|
#include <machine/cpu.h>
|
|
#include <amiga/amiga/device.h>
|
|
#include <amiga/dev/grfioctl.h>
|
|
#include <amiga/dev/grfvar.h>
|
|
#include <amiga/dev/grf_rhreg.h>
|
|
#include <amiga/dev/zbusvar.h>
|
|
|
|
enum mode_type { MT_TXTONLY, MT_GFXONLY, MT_BOTH };
|
|
|
|
int rh_mondefok __P((struct MonDef *));
|
|
|
|
u_short CompFQ __P((u_int fq));
|
|
int rh_load_mon __P((struct grf_softc *gp, struct MonDef *md));
|
|
int rh_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
|
|
int rh_setvmode __P((struct grf_softc *gp, unsigned int mode,
|
|
enum mode_type type));
|
|
|
|
/* make it patchable, and settable by kernel config option */
|
|
#ifndef RH_MEMCLK
|
|
#define RH_MEMCLK 61000000 /* this is the memory clock value, you shouldn't
|
|
set it to less than 61000000, higher values may
|
|
speed up blits a little bit, if you raise this
|
|
value too much, some trash will appear on your
|
|
screen. */
|
|
#endif
|
|
int rh_memclk = RH_MEMCLK;
|
|
|
|
|
|
extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height;
|
|
extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi;
|
|
extern unsigned char kernel_font_8x8[];
|
|
#ifdef KFONT_8X11
|
|
extern unsigned char kernel_font_8x11_width, kernel_font_8x11_height;
|
|
extern unsigned char kernel_font_8x11_lo, kernel_font_8x11_hi;
|
|
extern unsigned char kernel_font_8x11[];
|
|
#endif
|
|
|
|
/*
|
|
* This driver for the MacroSystem Retina board was only possible,
|
|
* because MacroSystem provided information about the pecularities
|
|
* of the board. THANKS! Competition in Europe among gfx board
|
|
* manufacturers is rather tough, so Lutz Vieweg, who wrote the
|
|
* initial driver, has made an agreement with MS not to document
|
|
* the driver source (see also his comment below).
|
|
* -> ALL comments after
|
|
* -> "/* -------------- START OF CODE -------------- * /"
|
|
* -> have been added by myself (mw) from studying the publically
|
|
* -> available "NCR 77C32BLT" Data Manual
|
|
*/
|
|
/*
|
|
* This code offers low-level routines to access the Retina BLT Z3
|
|
* graphics-board manufactured by MS MacroSystem GmbH from within NetBSD
|
|
* for the Amiga.
|
|
*
|
|
* Thanks to MacroSystem for providing me with the neccessary information
|
|
* to create theese routines. The sparse documentation of this code
|
|
* results from the agreements between MS and me.
|
|
*/
|
|
|
|
|
|
|
|
#define MDF_DBL 1
|
|
#define MDF_LACE 2
|
|
#define MDF_CLKDIV2 4
|
|
|
|
/* set this as an option in your kernel config file! */
|
|
/* #define RH_64BIT_SPRITE */
|
|
|
|
/* -------------- START OF CODE -------------- */
|
|
|
|
/* Convert big-endian long into little-endian long. */
|
|
|
|
#define M2I(val) \
|
|
asm volatile (" rorw #8,%0 ; \
|
|
swap %0 ; \
|
|
rorw #8,%0 ; " : "=d" (val) : "0" (val));
|
|
|
|
#define M2INS(val) \
|
|
asm volatile (" rorw #8,%0 ; \
|
|
swap %0 ; \
|
|
rorw #8,%0 ; \
|
|
swap %0 ; " : "=d" (val) : "0" (val));
|
|
|
|
#define ACM_OFFSET (0x00b00000)
|
|
#define LM_OFFSET (0x00c00000)
|
|
|
|
static unsigned char optab[] = {
|
|
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
|
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
|
|
};
|
|
static char optabs[] = {
|
|
0, -1, -1, -1, -1, 0, -1, -1,
|
|
-1, -1, 0, -1, -1, -1, -1, 0
|
|
};
|
|
|
|
void
|
|
RZ3DisableHWC(gp)
|
|
struct grf_softc *gp;
|
|
{
|
|
volatile void *ba = gp->g_regkva;
|
|
|
|
WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00);
|
|
}
|
|
|
|
void
|
|
RZ3SetupHWC(gp, col1, col2, hsx, hsy, data)
|
|
struct grf_softc *gp;
|
|
unsigned char col1;
|
|
unsigned col2;
|
|
unsigned char hsx;
|
|
unsigned char hsy;
|
|
const unsigned long *data;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
unsigned long *c = (unsigned long *)(ba + LM_OFFSET + HWC_MEM_OFF);
|
|
const unsigned long *s = data;
|
|
struct MonDef *MonitorDef = (struct MonDef *) gp->g_data;
|
|
#ifdef RH_64BIT_SPRITE
|
|
short x = (HWC_MEM_SIZE / (4*4)) - 1;
|
|
#else
|
|
short x = (HWC_MEM_SIZE / (4*4*2)) - 1;
|
|
#endif
|
|
/* copy only, if there is a data pointer. */
|
|
if (data) do {
|
|
*c++ = *s++;
|
|
*c++ = *s++;
|
|
*c++ = *s++;
|
|
*c++ = *s++;
|
|
} while (x-- > 0);
|
|
|
|
WSeq(ba, SEQ_ID_CURSOR_COLOR1, col1);
|
|
WSeq(ba, SEQ_ID_CURSOR_COLOR0, col2);
|
|
if (MonitorDef->DEP <= 8) {
|
|
#ifdef RH_64BIT_SPRITE
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x85);
|
|
#else
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x03);
|
|
#endif
|
|
}
|
|
else if (MonitorDef->DEP <= 16) {
|
|
#ifdef RH_64BIT_SPRITE
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xa5);
|
|
#else
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x23);
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef RH_64BIT_SPRITE
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xc5);
|
|
#else
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x43);
|
|
#endif
|
|
}
|
|
WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, 0x00);
|
|
WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, 0x00);
|
|
WSeq(ba, SEQ_ID_CURSOR_X_INDEX, hsx);
|
|
WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, hsy);
|
|
WSeq(ba, SEQ_ID_CURSOR_STORE_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_CURSOR_STORE_LO, ((HWC_MEM_OFF / 4) & 0x0000f));
|
|
WSeq(ba, SEQ_ID_CURSOR_ST_OFF_HI, (((HWC_MEM_OFF / 4) & 0xff000) >> 12));
|
|
WSeq(ba, SEQ_ID_CURSOR_ST_OFF_LO, (((HWC_MEM_OFF / 4) & 0x00ff0) >> 4));
|
|
WSeq(ba, SEQ_ID_CURSOR_PIXELMASK, 0xff);
|
|
}
|
|
|
|
void
|
|
RZ3AlphaErase (gp, xd, yd, w, h)
|
|
struct grf_softc *gp;
|
|
unsigned short xd;
|
|
unsigned short yd;
|
|
unsigned short w;
|
|
unsigned short h;
|
|
{
|
|
const struct MonDef * md = (struct MonDef *) gp->g_data;
|
|
RZ3AlphaCopy(gp, xd, yd+md->TY, xd, yd, w, h);
|
|
}
|
|
|
|
void
|
|
RZ3AlphaCopy (gp, xs, ys, xd, yd, w, h)
|
|
struct grf_softc *gp;
|
|
unsigned short xs;
|
|
unsigned short ys;
|
|
unsigned short xd;
|
|
unsigned short yd;
|
|
unsigned short w;
|
|
unsigned short h;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
const struct MonDef *md = (struct MonDef *) gp->g_data;
|
|
volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
|
|
unsigned short mod;
|
|
|
|
xs *= 4;
|
|
ys *= 4;
|
|
xd *= 4;
|
|
yd *= 4;
|
|
w *= 4;
|
|
|
|
{
|
|
/* anyone got Windoze GDI opcodes handy?... */
|
|
unsigned long tmp = 0x0000ca00;
|
|
*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
|
|
}
|
|
|
|
mod = 0xc0c2;
|
|
|
|
{
|
|
unsigned long pat = 8 * PAT_MEM_OFF;
|
|
unsigned long dst = 8 * (xd + yd * md->TX);
|
|
|
|
unsigned long src = 8 * (xs + ys * md->TX);
|
|
|
|
if (xd > xs) {
|
|
mod &= ~0x8000;
|
|
src += 8 * (w - 1);
|
|
dst += 8 * (w - 1);
|
|
pat += 8 * 2;
|
|
}
|
|
if (yd > ys) {
|
|
mod &= ~0x4000;
|
|
src += 8 * (h - 1) * md->TX * 4;
|
|
dst += 8 * (h - 1) * md->TX * 4;
|
|
pat += 8 * 4;
|
|
}
|
|
|
|
M2I(src);
|
|
*(acm + ACM_SOURCE/4) = src;
|
|
|
|
M2I(pat);
|
|
*(acm + ACM_PATTERN/4) = pat;
|
|
|
|
M2I(dst);
|
|
*(acm + ACM_DESTINATION/4) = dst;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = mod << 16;
|
|
*(acm + ACM_CONTROL/4) = tmp;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = w | (h << 16);
|
|
M2I(tmp);
|
|
*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
|
|
}
|
|
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
|
|
|
|
while ((*(((volatile unsigned char *)acm) +
|
|
(ACM_START_STATUS + 2)) & 1) == 0);
|
|
}
|
|
|
|
void
|
|
RZ3BitBlit (gp, gbb)
|
|
struct grf_softc *gp;
|
|
struct grf_bitblt * gbb;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
volatile unsigned char *lm = ba + LM_OFFSET;
|
|
volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
|
|
const struct MonDef *md = (struct MonDef *) gp->g_data;
|
|
unsigned short mod;
|
|
|
|
{
|
|
unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
|
|
unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
|
|
*pt++ = tmp;
|
|
*pt = tmp;
|
|
}
|
|
|
|
{
|
|
|
|
unsigned long tmp = optab[ gbb->op ] << 8;
|
|
*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
|
|
}
|
|
|
|
mod = 0xc0c2;
|
|
|
|
{
|
|
unsigned long pat = 8 * PAT_MEM_OFF;
|
|
unsigned long dst = 8 * (gbb->dst_x + gbb->dst_y * md->TX);
|
|
|
|
if (optabs[gbb->op]) {
|
|
unsigned long src = 8 * (gbb->src_x + gbb->src_y * md->TX);
|
|
|
|
if (gbb->dst_x > gbb->src_x) {
|
|
mod &= ~0x8000;
|
|
src += 8 * (gbb->w - 1);
|
|
dst += 8 * (gbb->w - 1);
|
|
pat += 8 * 2;
|
|
}
|
|
if (gbb->dst_y > gbb->src_y) {
|
|
mod &= ~0x4000;
|
|
src += 8 * (gbb->h - 1) * md->TX;
|
|
dst += 8 * (gbb->h - 1) * md->TX;
|
|
pat += 8 * 4;
|
|
}
|
|
|
|
M2I(src);
|
|
*(acm + ACM_SOURCE/4) = src;
|
|
}
|
|
|
|
M2I(pat);
|
|
*(acm + ACM_PATTERN/4) = pat;
|
|
|
|
M2I(dst);
|
|
*(acm + ACM_DESTINATION/4) = dst;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = mod << 16;
|
|
*(acm + ACM_CONTROL/4) = tmp;
|
|
}
|
|
{
|
|
unsigned long tmp = gbb->w | (gbb->h << 16);
|
|
M2I(tmp);
|
|
*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
|
|
}
|
|
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
|
|
|
|
while ((*(((volatile unsigned char *)acm) +
|
|
(ACM_START_STATUS + 2)) & 1) == 0);
|
|
}
|
|
|
|
void
|
|
RZ3BitBlit16 (gp, gbb)
|
|
struct grf_softc *gp;
|
|
struct grf_bitblt * gbb;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
volatile unsigned char *lm = ba + LM_OFFSET;
|
|
volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET);
|
|
const struct MonDef * md = (struct MonDef *) gp->g_data;
|
|
unsigned short mod;
|
|
|
|
{
|
|
unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
|
|
unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt = tmp;
|
|
}
|
|
|
|
{
|
|
|
|
unsigned long tmp = optab[ gbb->op ] << 8;
|
|
*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
|
|
}
|
|
|
|
mod = 0xc0c2;
|
|
|
|
{
|
|
unsigned long pat = 8 * PAT_MEM_OFF;
|
|
unsigned long dst = 8 * 2 * (gbb->dst_x + gbb->dst_y * md->TX);
|
|
|
|
if (optabs[gbb->op]) {
|
|
unsigned long src = 8 * 2 * (gbb->src_x + gbb->src_y * md->TX);
|
|
|
|
if (gbb->dst_x > gbb->src_x) {
|
|
mod &= ~0x8000;
|
|
src += 8 * 2 * (gbb->w);
|
|
dst += 8 * 2 * (gbb->w);
|
|
pat += 8 * 2 * 2;
|
|
}
|
|
if (gbb->dst_y > gbb->src_y) {
|
|
mod &= ~0x4000;
|
|
src += 8 * 2 * (gbb->h - 1) * md->TX;
|
|
dst += 8 * 2 * (gbb->h - 1) * md->TX;
|
|
pat += 8 * 4 * 2;
|
|
}
|
|
|
|
M2I(src);
|
|
*(acm + ACM_SOURCE/4) = src;
|
|
}
|
|
|
|
M2I(pat);
|
|
*(acm + ACM_PATTERN/4) = pat;
|
|
|
|
M2I(dst);
|
|
*(acm + ACM_DESTINATION/4) = dst;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = mod << 16;
|
|
*(acm + ACM_CONTROL/4) = tmp;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = gbb->w | (gbb->h << 16);
|
|
M2I(tmp);
|
|
*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
|
|
}
|
|
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
|
|
|
|
while ((*(((volatile unsigned char *)acm) +
|
|
(ACM_START_STATUS+ 2)) & 1) == 0);
|
|
}
|
|
|
|
void
|
|
RZ3BitBlit24 (gp, gbb)
|
|
struct grf_softc *gp;
|
|
struct grf_bitblt * gbb;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
volatile unsigned char *lm = ba + LM_OFFSET;
|
|
volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET);
|
|
const struct MonDef * md = (struct MonDef *) gp->g_data;
|
|
unsigned short mod;
|
|
|
|
|
|
{
|
|
unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
|
|
unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt++ = tmp;
|
|
*pt = tmp;
|
|
}
|
|
|
|
{
|
|
|
|
unsigned long tmp = optab[ gbb->op ] << 8;
|
|
*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
|
|
}
|
|
|
|
mod = 0xc0c2;
|
|
|
|
{
|
|
unsigned long pat = 8 * PAT_MEM_OFF;
|
|
unsigned long dst = 8 * 3 * (gbb->dst_x + gbb->dst_y * md->TX);
|
|
|
|
if (optabs[gbb->op]) {
|
|
unsigned long src = 8 * 3 * (gbb->src_x + gbb->src_y * md->TX);
|
|
|
|
if (gbb->dst_x > gbb->src_x ) {
|
|
mod &= ~0x8000;
|
|
src += 8 * 3 * (gbb->w);
|
|
dst += 8 * 3 * (gbb->w);
|
|
pat += 8 * 3 * 2;
|
|
}
|
|
if (gbb->dst_y > gbb->src_y) {
|
|
mod &= ~0x4000;
|
|
src += 8 * 3 * (gbb->h - 1) * md->TX;
|
|
dst += 8 * 3 * (gbb->h - 1) * md->TX;
|
|
pat += 8 * 4 * 3;
|
|
}
|
|
|
|
M2I(src);
|
|
*(acm + ACM_SOURCE/4) = src;
|
|
}
|
|
|
|
|
|
M2I(pat);
|
|
*(acm + ACM_PATTERN/4) = pat;
|
|
|
|
|
|
M2I(dst);
|
|
*(acm + ACM_DESTINATION/4) = dst;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = mod << 16;
|
|
*(acm + ACM_CONTROL/4) = tmp;
|
|
}
|
|
{
|
|
|
|
unsigned long tmp = gbb->w | (gbb->h << 16);
|
|
M2I(tmp);
|
|
*(acm + ACM_BITMAP_DIMENSION/4) = tmp;
|
|
}
|
|
|
|
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
|
|
*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
|
|
|
|
while ( (*(((volatile unsigned char *)acm)
|
|
+ (ACM_START_STATUS+ 2)) & 1) == 0 ) {};
|
|
|
|
}
|
|
|
|
|
|
void
|
|
RZ3SetCursorPos (gp, pos)
|
|
struct grf_softc *gp;
|
|
unsigned short pos;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
|
|
WCrt(ba, CRT_ID_CURSOR_LOC_LOW, (unsigned char)pos);
|
|
WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (unsigned char)(pos >> 8));
|
|
|
|
}
|
|
|
|
void
|
|
RZ3LoadPalette (gp, pal, firstcol, colors)
|
|
struct grf_softc *gp;
|
|
unsigned char * pal;
|
|
unsigned char firstcol;
|
|
unsigned char colors;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
|
|
if (colors == 0)
|
|
return;
|
|
|
|
vgaw(ba, VDAC_ADDRESS_W, firstcol);
|
|
|
|
{
|
|
|
|
short x = colors-1;
|
|
const unsigned char * col = pal;
|
|
do {
|
|
|
|
vgaw(ba, VDAC_DATA, (*col++ >> 2));
|
|
vgaw(ba, VDAC_DATA, (*col++ >> 2));
|
|
vgaw(ba, VDAC_DATA, (*col++ >> 2));
|
|
|
|
} while (x-- > 0);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
RZ3SetPalette (gp, colornum, red, green, blue)
|
|
struct grf_softc *gp;
|
|
unsigned char colornum;
|
|
unsigned char red, green, blue;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
|
|
vgaw(ba, VDAC_ADDRESS_W, colornum);
|
|
|
|
vgaw(ba, VDAC_DATA, (red >> 2));
|
|
vgaw(ba, VDAC_DATA, (green >> 2));
|
|
vgaw(ba, VDAC_DATA, (blue >> 2));
|
|
|
|
}
|
|
|
|
/* XXXXXXXXX !! */
|
|
static unsigned short xpan;
|
|
static unsigned short ypan;
|
|
|
|
void
|
|
RZ3SetPanning (gp, xoff, yoff)
|
|
struct grf_softc *gp;
|
|
unsigned short xoff, yoff;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
const struct MonDef * md = (struct MonDef *) gp->g_data;
|
|
unsigned long off;
|
|
|
|
xpan = xoff;
|
|
ypan = yoff;
|
|
|
|
|
|
if (md->DEP > 8 && md->DEP <= 16) xoff *= 2;
|
|
else if (md->DEP > 16) xoff *= 3;
|
|
|
|
vgar(ba, ACT_ADDRESS_RESET);
|
|
WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07));
|
|
/* have the color lookup function normally again */
|
|
vgaw(ba, ACT_ADDRESS_W, 0x20);
|
|
|
|
if (md->DEP == 8)
|
|
off = ((yoff * md->TX)/ 4) + (xoff >> 2);
|
|
else if (md->DEP == 16)
|
|
off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2);
|
|
else
|
|
off = ((yoff * md->TX * 3)/ 4) + (xoff >> 2);
|
|
WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off));
|
|
off >>= 8;
|
|
WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off));
|
|
off >>= 8;
|
|
WCrt(ba, CRT_ID_EXT_START_ADDR,
|
|
((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f)));
|
|
|
|
|
|
}
|
|
|
|
void
|
|
RZ3SetHWCloc (gp, x, y)
|
|
struct grf_softc *gp;
|
|
unsigned short x, y;
|
|
{
|
|
volatile unsigned char *ba = gp->g_regkva;
|
|
const struct MonDef *md = (struct MonDef *) gp->g_data;
|
|
volatile unsigned char *acm = ba + ACM_OFFSET;
|
|
|
|
if (x < xpan)
|
|
RZ3SetPanning(gp, x, ypan);
|
|
|
|
if (x >= (xpan+md->MW))
|
|
RZ3SetPanning(gp, (1 + x - md->MW) , ypan);
|
|
|
|
if (y < ypan)
|
|
RZ3SetPanning(gp, xpan, y);
|
|
|
|
if (y >= (ypan+md->MH))
|
|
RZ3SetPanning(gp, xpan, (1 + y - md->MH));
|
|
|
|
x -= xpan;
|
|
y -= ypan;
|
|
|
|
*(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
|
|
*(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
|
|
*(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
|
|
*(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
|
|
}
|
|
|
|
u_short
|
|
CompFQ(fq)
|
|
u_int fq;
|
|
{
|
|
/* yuck... this sure could need some explanation.. */
|
|
|
|
unsigned long f = fq;
|
|
long n2 = 3;
|
|
long abw = 0x7fffffff;
|
|
long n1 = 3;
|
|
unsigned long m;
|
|
unsigned short erg = 0;
|
|
|
|
f *= 8;
|
|
|
|
do {
|
|
|
|
if (f <= 250000000)
|
|
break;
|
|
f /= 2;
|
|
|
|
} while (n2-- > 0);
|
|
|
|
if (n2 < 0)
|
|
return(0);
|
|
|
|
|
|
do {
|
|
long tmp;
|
|
|
|
f = fq;
|
|
f >>= 3;
|
|
f <<= n2;
|
|
f >>= 7;
|
|
|
|
m = (f * n1) / (14318180/1024);
|
|
|
|
if (m > 129)
|
|
break;
|
|
|
|
tmp = (((m * 14318180) >> n2) / n1) - fq;
|
|
if (tmp < 0)
|
|
tmp = -tmp;
|
|
|
|
if (tmp < abw) {
|
|
abw = tmp;
|
|
erg = (((n2 << 5) | (n1-2)) << 8) | (m-2);
|
|
}
|
|
|
|
} while ( (++n1) <= 21);
|
|
|
|
return(erg);
|
|
}
|
|
|
|
int
|
|
rh_mondefok(mdp)
|
|
struct MonDef *mdp;
|
|
{
|
|
switch(mdp->DEP) {
|
|
case 8:
|
|
case 16:
|
|
case 24:
|
|
return(1);
|
|
case 4:
|
|
if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
|
|
return(1);
|
|
/*FALLTHROUGH*/
|
|
default:
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
rh_load_mon(gp, md)
|
|
struct grf_softc *gp;
|
|
struct MonDef *md;
|
|
{
|
|
struct grfinfo *gi = &gp->g_display;
|
|
volatile unsigned char *ba;
|
|
volatile unsigned char *fb;
|
|
short FW, clksel, HDE, VDE;
|
|
unsigned short *c, z;
|
|
const unsigned char *f;
|
|
|
|
ba = gp->g_regkva;;
|
|
fb = gp->g_fbkva;
|
|
|
|
/* provide all needed information in grf device-independant
|
|
* locations */
|
|
gp->g_data = (caddr_t) md;
|
|
gi->gd_regaddr = (caddr_t) kvtop (ba);
|
|
gi->gd_regsize = LM_OFFSET;
|
|
gi->gd_fbaddr = (caddr_t) kvtop (fb);
|
|
gi->gd_fbsize = MEMSIZE *1024*1024;
|
|
#ifdef BANKEDDEVPAGER
|
|
/* we're not using banks NO MORE! */
|
|
gi->gd_bank_size = 0;
|
|
#endif
|
|
gi->gd_colors = 1 << md->DEP;
|
|
gi->gd_planes = md->DEP;
|
|
|
|
if (md->DEP == 4) {
|
|
gi->gd_fbwidth = md->MW;
|
|
gi->gd_fbheight = md->MH;
|
|
gi->gd_fbx = 0;
|
|
gi->gd_fby = 0;
|
|
gi->gd_dwidth = md->TX * md->FX;
|
|
gi->gd_dheight = md->TY * md->FY;
|
|
gi->gd_dx = 0;
|
|
gi->gd_dy = 0;
|
|
} else {
|
|
gi->gd_fbwidth = md->TX;
|
|
gi->gd_fbheight = md->TY;
|
|
gi->gd_fbx = 0;
|
|
gi->gd_fby = 0;
|
|
gi->gd_dwidth = md->MW;
|
|
gi->gd_dheight = md->MH;
|
|
gi->gd_dx = 0;
|
|
gi->gd_dy = 0;
|
|
}
|
|
|
|
FW =0;
|
|
if (md->DEP == 4) { /* XXX some text-mode! */
|
|
switch (md->FX) {
|
|
case 4:
|
|
FW = 0;
|
|
break;
|
|
case 7:
|
|
FW = 1;
|
|
break;
|
|
case 8:
|
|
FW = 2;
|
|
break;
|
|
case 9:
|
|
FW = 3;
|
|
break;
|
|
case 10:
|
|
FW = 4;
|
|
break;
|
|
case 11:
|
|
FW = 5;
|
|
break;
|
|
case 12:
|
|
FW = 6;
|
|
break;
|
|
case 13:
|
|
FW = 7;
|
|
break;
|
|
case 14:
|
|
FW = 8;
|
|
break;
|
|
case 15:
|
|
FW = 9;
|
|
break;
|
|
case 16:
|
|
FW = 11;
|
|
break;
|
|
default:
|
|
return(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
|
|
else if (md->DEP == 8) HDE = (md->MW+3)/4;
|
|
else if (md->DEP == 16) HDE = (md->MW*2+3)/4;
|
|
else if (md->DEP == 24) HDE = (md->MW*3+3)/4;
|
|
|
|
VDE = md->MH-1;
|
|
|
|
clksel = 0;
|
|
|
|
vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
|
|
vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
|
|
|
|
WSeq(ba, SEQ_ID_RESET, 0x00);
|
|
WSeq(ba, SEQ_ID_RESET, 0x03);
|
|
WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
|
|
WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
|
|
WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
|
|
WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
|
|
WSeq(ba, SEQ_ID_RESET, 0x01);
|
|
WSeq(ba, SEQ_ID_RESET, 0x03);
|
|
|
|
WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
|
|
WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
|
|
WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
|
|
|
|
WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
|
|
WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
|
|
WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
|
|
WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
|
|
WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
|
|
if (md->DEP == 4) {
|
|
/* 8bit pixel, no gfx byte path */
|
|
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
|
|
}
|
|
else if (md->DEP == 8) {
|
|
/* 8bit pixel, gfx byte path */
|
|
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
|
|
}
|
|
else if (md->DEP == 16) {
|
|
/* 16bit pixel, gfx byte path */
|
|
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
|
|
}
|
|
else if (md->DEP == 24) {
|
|
/* 24bit pixel, gfx byte path */
|
|
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x21);
|
|
}
|
|
WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
|
|
WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
|
|
WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
|
|
WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
|
|
WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
|
|
WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
|
|
WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
|
|
WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
|
|
WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
|
|
WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
|
|
WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
|
|
WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
|
|
WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
|
|
WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
|
|
WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x07);
|
|
|
|
WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
|
|
WCrt(ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
|
|
WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
|
|
WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
|
|
WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
|
|
|
|
WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
|
|
WCrt(ba, CRT_ID_END_HOR_RETR,
|
|
(md->HSE & 0x1f) |
|
|
((md->HBE & 0x20)/ 0x20 * 0x80));
|
|
WCrt(ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
|
|
WCrt(ba, CRT_ID_OVERFLOW,
|
|
((md->VSS & 0x200) / 0x200 * 0x80) |
|
|
((VDE & 0x200) / 0x200 * 0x40) |
|
|
((md->VT & 0x200) / 0x200 * 0x20) |
|
|
0x10 |
|
|
((md->VBS & 0x100) / 0x100 * 8) |
|
|
((md->VSS & 0x100) / 0x100 * 4) |
|
|
((VDE & 0x100) / 0x100 * 2) |
|
|
((md->VT & 0x100) / 0x100));
|
|
WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
|
|
|
|
if (md->DEP == 4) {
|
|
WCrt(ba, CRT_ID_MAX_SCAN_LINE,
|
|
((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
|
|
0x40 |
|
|
((md->VBS & 0x200)/0x200*0x20) |
|
|
((md->FY-1) & 0x1f));
|
|
} else {
|
|
WCrt(ba, CRT_ID_MAX_SCAN_LINE,
|
|
((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
|
|
0x40 |
|
|
((md->VBS & 0x200)/0x200*0x20) |
|
|
(0 & 0x1f));
|
|
}
|
|
|
|
/* I prefer "_" cursor to "block" cursor.. */
|
|
#if 1
|
|
WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
|
|
WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
|
|
#else
|
|
WCrt(ba, CRT_ID_CURSOR_START, 0x00);
|
|
WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
|
|
#endif
|
|
|
|
WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
|
|
WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
|
|
|
|
WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
|
|
WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
|
|
|
|
WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
|
|
WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
|
|
WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
|
|
|
|
if (md->DEP == 4) {
|
|
WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff );
|
|
}
|
|
/* all gfx-modes are in byte-mode, means values are multiplied by 8 */
|
|
else if (md->DEP == 8) {
|
|
WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff );
|
|
} else if (md->DEP == 16) {
|
|
WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff );
|
|
} else {
|
|
WCrt(ba, CRT_ID_OFFSET, (md->TX * 3 / 8) & 0xff );
|
|
}
|
|
|
|
WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
|
|
WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
|
|
WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
|
|
WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
|
|
WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
|
|
|
|
WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
|
|
0 | 0x20 |
|
|
((md->FLG & MDF_LACE) / MDF_LACE * 0x10) |
|
|
((md->HT & 0x100) / 0x100) |
|
|
(((HDE-1) & 0x100) / 0x100 * 2) |
|
|
((md->HBS & 0x100) / 0x100 * 4) |
|
|
((md->HSS & 0x100) / 0x100 * 8));
|
|
|
|
if (md->DEP == 4) {
|
|
WCrt(ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
|
|
}
|
|
else if (md->DEP == 8) {
|
|
WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16));
|
|
} else if (md->DEP == 16) {
|
|
WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 4) & 0x100)/0x100 * 16));
|
|
} else {
|
|
WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX * 3 / 8) & 0x100)/0x100 * 16));
|
|
}
|
|
|
|
WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
|
|
((md->HT & 0x200)/ 0x200) |
|
|
(((HDE-1) & 0x200)/ 0x200 * 2 ) |
|
|
((md->HBS & 0x200)/ 0x200 * 4 ) |
|
|
((md->HSS & 0x200)/ 0x200 * 8 ) |
|
|
((md->HBE & 0xc0) / 0x40 * 16 ) |
|
|
((md->HSE & 0x60) / 0x20 * 64));
|
|
|
|
WCrt(ba, CRT_ID_EXT_VER_TIMING,
|
|
((md->VSE & 0x10) / 0x10 * 0x80 ) |
|
|
((md->VBE & 0x300)/ 0x100 * 0x20 ) |
|
|
0x10 |
|
|
((md->VSS & 0x400)/ 0x400 * 8 ) |
|
|
((md->VBS & 0x400)/ 0x400 * 4 ) |
|
|
((VDE & 0x400)/ 0x400 * 2 ) |
|
|
((md->VT & 0x400)/ 0x400));
|
|
WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
|
|
|
|
{
|
|
unsigned short tmp = CompFQ(md->FQ);
|
|
WPLL(ba, 2 , tmp);
|
|
tmp = CompFQ(rh_memclk);
|
|
WPLL(ba,10 , tmp);
|
|
WPLL(ba,14 , 0x22);
|
|
}
|
|
|
|
WGfx(ba, GCT_ID_SET_RESET, 0x00);
|
|
WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
|
|
WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
|
|
WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
|
|
WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
|
|
WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
|
|
if (md->DEP == 4)
|
|
WGfx(ba, GCT_ID_MISC, 0x04);
|
|
else
|
|
WGfx(ba, GCT_ID_MISC, 0x05);
|
|
WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
|
|
WGfx(ba, GCT_ID_BITMASK, 0xff);
|
|
|
|
vgar(ba, ACT_ADDRESS_RESET);
|
|
WAttr(ba, ACT_ID_PALETTE0 , 0x00);
|
|
WAttr(ba, ACT_ID_PALETTE1 , 0x01);
|
|
WAttr(ba, ACT_ID_PALETTE2 , 0x02);
|
|
WAttr(ba, ACT_ID_PALETTE3 , 0x03);
|
|
WAttr(ba, ACT_ID_PALETTE4 , 0x04);
|
|
WAttr(ba, ACT_ID_PALETTE5 , 0x05);
|
|
WAttr(ba, ACT_ID_PALETTE6 , 0x06);
|
|
WAttr(ba, ACT_ID_PALETTE7 , 0x07);
|
|
WAttr(ba, ACT_ID_PALETTE8 , 0x08);
|
|
WAttr(ba, ACT_ID_PALETTE9 , 0x09);
|
|
WAttr(ba, ACT_ID_PALETTE10, 0x0a);
|
|
WAttr(ba, ACT_ID_PALETTE11, 0x0b);
|
|
WAttr(ba, ACT_ID_PALETTE12, 0x0c);
|
|
WAttr(ba, ACT_ID_PALETTE13, 0x0d);
|
|
WAttr(ba, ACT_ID_PALETTE14, 0x0e);
|
|
WAttr(ba, ACT_ID_PALETTE15, 0x0f);
|
|
|
|
vgar(ba, ACT_ADDRESS_RESET);
|
|
if (md->DEP == 4)
|
|
WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
|
|
else
|
|
WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
|
|
|
|
WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
|
|
WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
|
|
WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
|
|
WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
|
|
|
|
vgar(ba, ACT_ADDRESS_RESET);
|
|
vgaw(ba, ACT_ADDRESS_W, 0x20);
|
|
|
|
vgaw(ba, VDAC_MASK, 0xff);
|
|
/* probably some PLL timing stuff here. The value
|
|
for 24bit was found by trial&error :-) */
|
|
if (md->DEP < 16) {
|
|
vgaw(ba, 0x83c6, ((0 & 7) << 5) );
|
|
}
|
|
else if (md->DEP == 16) {
|
|
/* well... */
|
|
vgaw(ba, 0x83c6, ((3 & 7) << 5) );
|
|
}
|
|
else if (md->DEP == 24) {
|
|
vgaw(ba, 0x83c6, 0xe0);
|
|
}
|
|
vgaw(ba, VDAC_ADDRESS_W, 0x00);
|
|
|
|
if (md->DEP < 16) {
|
|
short x = 256-17;
|
|
unsigned char cl = 16;
|
|
RZ3LoadPalette(gp, md->PAL, 0, 16);
|
|
do {
|
|
vgaw(ba, VDAC_DATA, (cl >> 2));
|
|
vgaw(ba, VDAC_DATA, (cl >> 2));
|
|
vgaw(ba, VDAC_DATA, (cl >> 2));
|
|
cl++;
|
|
} while (x-- > 0);
|
|
}
|
|
|
|
if (md->DEP == 4) {
|
|
{
|
|
struct grf_bitblt bb = {
|
|
GRFBBOPset,
|
|
0, 0,
|
|
0, 0,
|
|
md->TX*4, 2*md->TY,
|
|
EMPTY_ALPHA
|
|
};
|
|
RZ3BitBlit(gp, &bb);
|
|
}
|
|
|
|
c = (unsigned short *)(ba + LM_OFFSET);
|
|
c += 2 * md->FLo*32;
|
|
c += 1;
|
|
f = md->FData;
|
|
for (z = md->FLo; z <= md->FHi; z++) {
|
|
short y = md->FY-1;
|
|
if (md->FX > 8){
|
|
do {
|
|
*c = *((const unsigned short *)f);
|
|
c += 2;
|
|
f += 2;
|
|
} while (y-- > 0);
|
|
} else {
|
|
do {
|
|
*c = (*f++) << 8;
|
|
c += 2;
|
|
} while (y-- > 0);
|
|
}
|
|
|
|
c += 2 * (32-md->FY);
|
|
}
|
|
{
|
|
unsigned long * pt = (unsigned long *) (ba + LM_OFFSET + PAT_MEM_OFF);
|
|
unsigned long tmp = 0xffff0000;
|
|
*pt++ = tmp;
|
|
*pt = tmp;
|
|
}
|
|
|
|
WSeq(ba, SEQ_ID_MAP_MASK, 3);
|
|
|
|
c = (unsigned short *)(ba + LM_OFFSET);
|
|
c += (md->TX-6)*2;
|
|
{
|
|
/* it's show-time :-) */
|
|
static unsigned short init_msg[6] = {
|
|
0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
|
|
};
|
|
unsigned short * m = init_msg;
|
|
short x = 5;
|
|
do {
|
|
*c = *m++;
|
|
c += 2;
|
|
} while (x-- > 0);
|
|
}
|
|
|
|
return(1);
|
|
} else if (md->DEP == 8) {
|
|
struct grf_bitblt bb = {
|
|
GRFBBOPset,
|
|
0, 0,
|
|
0, 0,
|
|
md->TX, md->TY,
|
|
0x0000
|
|
};
|
|
WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
|
|
|
|
RZ3BitBlit(gp, &bb);
|
|
|
|
xpan = 0;
|
|
ypan = 0;
|
|
|
|
return(1);
|
|
} else if (md->DEP == 16) {
|
|
struct grf_bitblt bb = {
|
|
GRFBBOPset,
|
|
0, 0,
|
|
0, 0,
|
|
md->TX, md->TY,
|
|
0x0000
|
|
};
|
|
WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
|
|
|
|
RZ3BitBlit16(gp, &bb);
|
|
|
|
xpan = 0;
|
|
ypan = 0;
|
|
|
|
return(1);
|
|
} else if (md->DEP == 24) {
|
|
struct grf_bitblt bb = {
|
|
GRFBBOPset,
|
|
0, 0,
|
|
0, 0,
|
|
md->TX, md->TY,
|
|
0x0000
|
|
};
|
|
WSeq(ba, SEQ_ID_MAP_MASK, 0x0f );
|
|
|
|
RZ3BitBlit24(gp, &bb );
|
|
|
|
xpan = 0;
|
|
ypan = 0;
|
|
|
|
return 1;
|
|
} else
|
|
return(0);
|
|
}
|
|
|
|
/* standard-palette definition */
|
|
|
|
unsigned char RZ3StdPalette[16*3] = {
|
|
/* R G B */
|
|
0, 0, 0,
|
|
192,192,192,
|
|
128, 0, 0,
|
|
0,128, 0,
|
|
0, 0,128,
|
|
128,128, 0,
|
|
0,128,128,
|
|
128, 0,128,
|
|
64, 64, 64, /* the higher 8 colors have more intensity for */
|
|
255,255,255, /* compatibility with standard attributes */
|
|
255, 0, 0,
|
|
0,255, 0,
|
|
0, 0,255,
|
|
255,255, 0,
|
|
0,255,255,
|
|
255, 0,255
|
|
};
|
|
|
|
/*
|
|
* The following structures are examples for monitor-definitions. To make one
|
|
* of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
|
|
* monitor-mode of your dreams. Then save it, and make a structure from the
|
|
* values provided in the file DefineMonitor stored - the labels in the comment
|
|
* above the structure definition show where to put what value.
|
|
*
|
|
* If you want to use your definition for the text-mode, you'll need to adapt
|
|
* your 8-bit monitor-definition to the font you want to use. Be FX the width of
|
|
* the font, then the following modifications have to be applied to your values:
|
|
*
|
|
* HBS = (HBS * 4) / FX
|
|
* HSS = (HSS * 4) / FX
|
|
* HSE = (HSE * 4) / FX
|
|
* HBE = (HBE * 4) / FX
|
|
* HT = (HT * 4) / FX
|
|
*
|
|
* Make sure your maximum width (MW) and height (MH) are even multiples of
|
|
* the fonts' width and height.
|
|
*
|
|
* You may use definitons created by the old DefineMonitor, but you'll get
|
|
* better results with the new DefineMonitor supplied along with the Retin Z3.
|
|
*/
|
|
|
|
/*
|
|
* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT
|
|
* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi
|
|
*/
|
|
#ifdef KFONT_8X11
|
|
#define KERNEL_FONT kernel_font_8x11
|
|
#define FY 11
|
|
#define FX 8
|
|
#else
|
|
#define KERNEL_FONT kernel_font_8x8
|
|
#define FY 8
|
|
#define FX 8
|
|
#endif
|
|
|
|
|
|
static struct MonDef monitor_defs[] = {
|
|
/* Text-mode definitions */
|
|
|
|
/* horizontal 31.5 kHz */
|
|
{ 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
|
|
4, RZ3StdPalette, 80, 64, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* horizontal 38kHz */
|
|
{ 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
|
|
4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* horizontal 64kHz */
|
|
{ 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
|
|
4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 8-bit gfx-mode definitions */
|
|
|
|
/* IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
|
|
independent from the "physical" screen size. If your code does NOT
|
|
support panning, please adjust the "logical" screen sizes below to
|
|
match the physical ones
|
|
*/
|
|
|
|
/* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
|
|
{ 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
/* This is the logical ^ ^ screen size */
|
|
|
|
/* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
|
|
{ 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
|
|
{ 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
|
|
{ 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
|
|
{ 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
|
|
{110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
|
|
{110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
|
|
{104000000, 0, 1280,1024, 321,323,348,399,398,1025,1026,1043,1073,1073,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
|
|
HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
|
|
MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
|
|
/* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
|
|
{121000000, 0, 1280,1024, 321,322,347,397,396,1025,1026,1043,1073,1073,
|
|
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
|
|
/* 16-bit gfx-mode definitions */
|
|
|
|
/* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
|
|
{ 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502,
|
|
16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
|
|
{ 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628,
|
|
16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
|
|
{110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804,
|
|
16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
|
|
{109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678,
|
|
16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
|
|
HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
|
|
MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
|
|
/* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
|
|
{124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804,
|
|
16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
|
|
/* 24-bit gfx-mode definitions */
|
|
|
|
/* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
|
|
{ 46000000, 1, 320, 200, 241,268,287,324,323, 401, 405, 412, 418, 418,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
|
|
{ 76000000, 0, 640, 400, 481,514,552,601,600, 401, 402, 409, 418, 418,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
|
|
{101000000, 0, 724, 482, 544,576,619,682,678, 483, 487, 495, 495, 504,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
|
|
{110000000, 0, 800, 600, 601,602,647,723,722, 601, 602, 612, 628, 628,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
|
|
{132000000, 0, 800, 600, 601,641,688,749,748, 601, 611, 621, 628, 628,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
|
|
/*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
|
|
{110000000, 2, 1024, 768, 769,770,824,854,853, 385, 386, 392, 401, 401,
|
|
24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
|
|
};
|
|
#undef KERNEL_FONT
|
|
#undef FX
|
|
#undef FY
|
|
|
|
static const char *monitor_descr[] = {
|
|
#ifdef KFONT_8X11
|
|
"80x46 (640x506) 31.5kHz",
|
|
"96x54 (768x594) 38kHz",
|
|
"96x54 (768x594) 64kHz",
|
|
#else
|
|
"80x64 (640x512) 31.5kHz",
|
|
"96x75 (768x600) 38kHz",
|
|
"96x75 (768x600) 64kHz",
|
|
#endif
|
|
|
|
"GFX-8 (640x480) 31.5kHz",
|
|
"GFX-8 (640x480) 38kHz",
|
|
"GFX-8 (800x600) 38.5kHz",
|
|
"GFX-8 (1024x768) 64kHz",
|
|
"GFX-8 (1120x896) 64kHz",
|
|
"GFX-8 (1152x910) 76kHz",
|
|
"GFX-8 (1182x848) 73kHz",
|
|
"GFX-8 (1280x1024) 64.5kHz",
|
|
"GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
|
|
|
|
"GFX-16 (640x480) 31.8kHz",
|
|
"GFX-16 (800x600) 38.5kHz",
|
|
"GFX-16 (1024x768) 42.8kHz",
|
|
"GFX-16 (864x648) 50kHz",
|
|
"GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
|
|
|
|
"GFX-24 (320x200 d) 35kHz",
|
|
"GFX-24 (640x400) 31.4kHz",
|
|
"GFX-24 (724x482) 37kHz",
|
|
"GFX-24 (800x600) 38kHz",
|
|
"GFX-24 (800x600) 44kHz ***EXCEEDS CHIP LIMIT!!!***",
|
|
"GFX-24 (1024x768) 32kHz-i",
|
|
};
|
|
|
|
int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
|
|
|
|
/* patchable */
|
|
int rh_default_mon = 0;
|
|
int rh_default_gfx = 4;
|
|
|
|
static struct MonDef *current_mon;
|
|
|
|
int rh_mode __P((struct grf_softc *, int, void *, int, int));
|
|
void grfrhattach __P((struct device *, struct device *, void *));
|
|
int grfrhprint __P((void *, char *));
|
|
int grfrhmatch __P((struct device *, struct cfdata *, void *));
|
|
|
|
struct cfdriver grfrhcd = {
|
|
NULL, "grfrh", (cfmatch_t)grfrhmatch, grfrhattach,
|
|
DV_DULL, sizeof(struct grf_softc), NULL, 0
|
|
};
|
|
|
|
static struct cfdata *cfdata;
|
|
|
|
int
|
|
grfrhmatch(pdp, cfp, auxp)
|
|
struct device *pdp;
|
|
struct cfdata *cfp;
|
|
void *auxp;
|
|
{
|
|
#ifdef RETINACONSOLE
|
|
static int rhconunit = -1;
|
|
#endif
|
|
struct zbus_args *zap;
|
|
|
|
zap = auxp;
|
|
|
|
if (amiga_realconfig == 0)
|
|
#ifdef RETINACONSOLE
|
|
if (rhconunit != -1)
|
|
#endif
|
|
return(0);
|
|
if (zap->manid != 18260 || zap->prodid != 16)
|
|
return(0);
|
|
#ifdef RETINACONSOLE
|
|
if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
|
|
#endif
|
|
if ((unsigned)rh_default_mon >= rh_mon_max ||
|
|
monitor_defs[rh_default_mon].DEP == 8)
|
|
rh_default_mon = 0;
|
|
current_mon = monitor_defs + rh_default_mon;
|
|
if (rh_mondefok(current_mon) == 0)
|
|
return(0);
|
|
#ifdef RETINACONSOLE
|
|
if (amiga_realconfig == 0) {
|
|
rhconunit = cfp->cf_unit;
|
|
cfdata = cfp;
|
|
}
|
|
}
|
|
#endif
|
|
return(1);
|
|
}
|
|
|
|
void
|
|
grfrhattach(pdp, dp, auxp)
|
|
struct device *pdp, *dp;
|
|
void *auxp;
|
|
{
|
|
static struct grf_softc congrf;
|
|
static int coninited;
|
|
struct zbus_args *zap;
|
|
struct grf_softc *gp;
|
|
|
|
zap = auxp;
|
|
|
|
if (dp == NULL)
|
|
gp = &congrf;
|
|
else
|
|
gp = (struct grf_softc *)dp;
|
|
if (dp != NULL && congrf.g_regkva != 0) {
|
|
/*
|
|
* inited earlier, just copy (not device struct)
|
|
*/
|
|
bcopy(&congrf.g_display, &gp->g_display,
|
|
(char *)&gp[1] - (char *)&gp->g_display);
|
|
} else {
|
|
gp->g_regkva = (volatile caddr_t)zap->va;
|
|
gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
|
|
gp->g_unit = GRF_RETINAIII_UNIT;
|
|
gp->g_mode = rh_mode;
|
|
gp->g_conpri = grfrh_cnprobe();
|
|
gp->g_flags = GF_ALIVE;
|
|
grfrh_iteinit(gp);
|
|
(void)rh_load_mon(gp, current_mon);
|
|
}
|
|
if (dp != NULL)
|
|
printf("\n");
|
|
/*
|
|
* attach grf
|
|
*/
|
|
amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
|
|
}
|
|
|
|
int
|
|
grfrhprint(auxp, pnp)
|
|
void *auxp;
|
|
char *pnp;
|
|
{
|
|
if (pnp)
|
|
printf("ite at %s", pnp);
|
|
return(UNCONF);
|
|
}
|
|
|
|
int
|
|
rh_getvmode(gp, vm)
|
|
struct grf_softc *gp;
|
|
struct grfvideo_mode *vm;
|
|
{
|
|
struct MonDef *md;
|
|
|
|
if (vm->mode_num && vm->mode_num > rh_mon_max)
|
|
return(EINVAL);
|
|
|
|
if (! vm->mode_num)
|
|
vm->mode_num = (current_mon - monitor_defs) + 1;
|
|
|
|
md = monitor_defs + (vm->mode_num - 1);
|
|
strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
|
|
sizeof (vm->mode_descr));
|
|
vm->pixel_clock = md->FQ;
|
|
vm->disp_width = (md->DEP == 4) ? md->MW : md->TX;
|
|
vm->disp_height = (md->DEP == 4) ? md->MH : md->TY;
|
|
vm->depth = md->DEP;
|
|
|
|
/*
|
|
* From observation of the monitor definition table above, I guess
|
|
* that the horizontal timings are in units of longwords. Hence, I
|
|
* get the pixels by multiplication with 32 and division by the depth.
|
|
* The text modes, apparently marked by depth == 4, are even more
|
|
* wierd. According to a comment above, they are computed from a
|
|
* depth==8 mode thats for us: * 32 / 8) by applying another factor
|
|
* of 4 / font width.
|
|
* Reverse applying the latter formula most of the constants cancel
|
|
* themselves and we are left with a nice (* font width).
|
|
* That is, internal timings are in units of longwords for graphics
|
|
* modes, or in units of characters widths for text modes.
|
|
* We better don't WRITE modes until this has been real live checked.
|
|
* - Ignatios Souvatzis
|
|
*/
|
|
|
|
if (md->DEP == 4) {
|
|
vm->hblank_start = md->HBS * 32 / md->DEP;
|
|
vm->hblank_stop = md->HBE * 32 / md->DEP;
|
|
vm->hsync_start = md->HSS * 32 / md->DEP;
|
|
vm->hsync_stop = md->HSE * 32 / md->DEP;
|
|
vm->htotal = md->HT * 32 / md->DEP;
|
|
} else {
|
|
vm->hblank_start = md->HBS * md->FX;
|
|
vm->hblank_stop = md->HBE * md->FX;
|
|
vm->hsync_start = md->HSS * md->FX;
|
|
vm->hsync_stop = md->HSE * md->FX;
|
|
vm->htotal = md->HT * md->FX;
|
|
}
|
|
|
|
vm->vblank_start = md->VBS;
|
|
vm->vblank_stop = md->VBE;
|
|
vm->vsync_start = md->VSS;
|
|
vm->vsync_stop = md->VSE;
|
|
vm->vtotal = md->VT;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
int
|
|
rh_setvmode(gp, mode, type)
|
|
struct grf_softc *gp;
|
|
unsigned mode;
|
|
enum mode_type type;
|
|
{
|
|
struct MonDef *md;
|
|
int error;
|
|
|
|
if (!mode || mode > rh_mon_max)
|
|
return(EINVAL);
|
|
|
|
if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
|
|
|| (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
|
|
return(EINVAL);
|
|
|
|
current_mon = monitor_defs + (mode - 1);
|
|
|
|
error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
|
|
|
|
return(error);
|
|
}
|
|
|
|
|
|
/*
|
|
* Change the mode of the display.
|
|
* Return a UNIX error number or 0 for success.
|
|
*/
|
|
rh_mode(gp, cmd, arg, a2, a3)
|
|
register struct grf_softc *gp;
|
|
int cmd;
|
|
void *arg;
|
|
int a2, a3;
|
|
{
|
|
switch (cmd) {
|
|
case GM_GRFON:
|
|
rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
|
|
return(0);
|
|
|
|
case GM_GRFOFF:
|
|
rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
|
|
return(0);
|
|
|
|
case GM_GRFCONFIG:
|
|
return(0);
|
|
|
|
case GM_GRFGETVMODE:
|
|
return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
|
|
|
|
case GM_GRFSETVMODE:
|
|
return(rh_setvmode (gp, *(unsigned *) arg,
|
|
(gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
|
|
|
|
case GM_GRFGETNUMVM:
|
|
*(int *)arg = rh_mon_max;
|
|
return(0);
|
|
|
|
#ifdef BANKEDDEVPAGER
|
|
case GM_GRFGETBANK:
|
|
case GM_GRFGETCURBANK:
|
|
case GM_GRFSETBANK:
|
|
return(EINVAL);
|
|
#endif
|
|
case GM_GRFIOCTL:
|
|
return(rh_ioctl (gp, (u_long) arg, (caddr_t) a2));
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return(EINVAL);
|
|
}
|
|
|
|
int
|
|
rh_ioctl (gp, cmd, data)
|
|
register struct grf_softc *gp;
|
|
u_long cmd;
|
|
void *data;
|
|
{
|
|
switch (cmd) {
|
|
case GRFIOCGSPRITEPOS:
|
|
return(rh_getspritepos (gp, (struct grf_position *) data));
|
|
|
|
case GRFIOCSSPRITEPOS:
|
|
return(rh_setspritepos (gp, (struct grf_position *) data));
|
|
|
|
case GRFIOCSSPRITEINF:
|
|
return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
|
|
|
|
case GRFIOCGSPRITEINF:
|
|
return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
|
|
|
|
case GRFIOCGSPRITEMAX:
|
|
return(rh_getspritemax (gp, (struct grf_position *) data));
|
|
|
|
case GRFIOCGETCMAP:
|
|
return(rh_getcmap (gp, (struct grf_colormap *) data));
|
|
|
|
case GRFIOCPUTCMAP:
|
|
return(rh_putcmap (gp, (struct grf_colormap *) data));
|
|
|
|
case GRFIOCBITBLT:
|
|
return(rh_bitblt (gp, (struct grf_bitblt *) data));
|
|
}
|
|
|
|
return(EINVAL);
|
|
}
|
|
|
|
|
|
int
|
|
rh_getcmap (gfp, cmap)
|
|
struct grf_softc *gfp;
|
|
struct grf_colormap *cmap;
|
|
{
|
|
volatile unsigned char *ba;
|
|
u_char red[256], green[256], blue[256], *rp, *gp, *bp;
|
|
short x;
|
|
int error;
|
|
|
|
if (cmap->count == 0 || cmap->index >= 256)
|
|
return 0;
|
|
|
|
if (cmap->index + cmap->count > 256)
|
|
cmap->count = 256 - cmap->index;
|
|
|
|
ba = gfp->g_regkva;
|
|
/* first read colors out of the chip, then copyout to userspace */
|
|
vgaw (ba, VDAC_ADDRESS_W, cmap->index);
|
|
x = cmap->count - 1;
|
|
rp = red + cmap->index;
|
|
gp = green + cmap->index;
|
|
bp = blue + cmap->index;
|
|
do {
|
|
*rp++ = vgar (ba, VDAC_DATA) << 2;
|
|
*gp++ = vgar (ba, VDAC_DATA) << 2;
|
|
*bp++ = vgar (ba, VDAC_DATA) << 2;
|
|
} while (x-- > 0);
|
|
|
|
if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
|
|
&& !(error = copyout (green + cmap->index, cmap->green, cmap->count))
|
|
&& !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
|
|
return(0);
|
|
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
rh_putcmap (gfp, cmap)
|
|
struct grf_softc *gfp;
|
|
struct grf_colormap *cmap;
|
|
{
|
|
volatile unsigned char *ba;
|
|
u_char red[256], green[256], blue[256], *rp, *gp, *bp;
|
|
short x;
|
|
int error;
|
|
|
|
if (cmap->count == 0 || cmap->index >= 256)
|
|
return(0);
|
|
|
|
if (cmap->index + cmap->count > 256)
|
|
cmap->count = 256 - cmap->index;
|
|
|
|
/* first copy the colors into kernelspace */
|
|
if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
|
|
&& !(error = copyin (cmap->green, green + cmap->index, cmap->count))
|
|
&& !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
|
|
/* argl.. LoadPalette wants a different format, so do it like with
|
|
* Retina2.. */
|
|
ba = gfp->g_regkva;
|
|
vgaw (ba, VDAC_ADDRESS_W, cmap->index);
|
|
x = cmap->count - 1;
|
|
rp = red + cmap->index;
|
|
gp = green + cmap->index;
|
|
bp = blue + cmap->index;
|
|
do {
|
|
vgaw (ba, VDAC_DATA, *rp++ >> 2);
|
|
vgaw (ba, VDAC_DATA, *gp++ >> 2);
|
|
vgaw (ba, VDAC_DATA, *bp++ >> 2);
|
|
} while (x-- > 0);
|
|
return(0);
|
|
}
|
|
else
|
|
return(error);
|
|
}
|
|
|
|
int
|
|
rh_getspritepos (gp, pos)
|
|
struct grf_softc *gp;
|
|
struct grf_position *pos;
|
|
{
|
|
volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
|
|
|
|
pos->x = acm[ACM_CURSOR_POSITION + 0] +
|
|
(acm[ACM_CURSOR_POSITION + 1] << 8);
|
|
pos->y = acm[ACM_CURSOR_POSITION + 2] +
|
|
(acm[ACM_CURSOR_POSITION + 3] << 8);
|
|
|
|
pos->x += xpan;
|
|
pos->y += ypan;
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
rh_setspritepos (gp, pos)
|
|
struct grf_softc *gp;
|
|
struct grf_position *pos;
|
|
{
|
|
RZ3SetHWCloc (gp, pos->x, pos->y);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
rh_getspriteinfo (gp, info)
|
|
struct grf_softc *gp;
|
|
struct grf_spriteinfo *info;
|
|
{
|
|
volatile unsigned char *ba, *fb;
|
|
|
|
ba = gp->g_regkva;
|
|
fb = gp->g_fbkva;
|
|
if (info->set & GRFSPRSET_ENABLE)
|
|
info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
|
|
if (info->set & GRFSPRSET_POS)
|
|
rh_getspritepos (gp, &info->pos);
|
|
if (info->set & GRFSPRSET_HOT) {
|
|
info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
|
|
info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
|
|
}
|
|
if (info->set & GRFSPRSET_CMAP) {
|
|
struct grf_colormap cmap;
|
|
int index;
|
|
cmap.index = 0;
|
|
cmap.count = 256;
|
|
rh_getcmap (gp, &cmap);
|
|
index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
|
|
info->cmap.red[0] = cmap.red[index];
|
|
info->cmap.green[0] = cmap.green[index];
|
|
info->cmap.blue[0] = cmap.blue[index];
|
|
index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
|
|
info->cmap.red[1] = cmap.red[index];
|
|
info->cmap.green[1] = cmap.green[index];
|
|
info->cmap.blue[1] = cmap.blue[index];
|
|
}
|
|
if (info->set & GRFSPRSET_SHAPE) {
|
|
u_char image[128], mask[128];
|
|
volatile u_long *hwp;
|
|
u_char *imp, *mp;
|
|
short row;
|
|
|
|
/* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
|
|
* for an explanation. To convert to "our" format, the
|
|
* following holds:
|
|
* col2 = !image & mask
|
|
* col1 = image & mask
|
|
* transp = !mask
|
|
* and thus:
|
|
* image = col1
|
|
* mask = col1 | col2
|
|
* hope I got these bool-eqs right below..
|
|
*/
|
|
|
|
#ifdef RH_64BIT_SPRITE
|
|
info->size.x = 64;
|
|
info->size.y = 64;
|
|
for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
|
|
mp = mask, imp = image;
|
|
row < 64;
|
|
row++) {
|
|
u_long bp10, bp20, bp11, bp21;
|
|
bp10 = *hwp++;
|
|
bp20 = *hwp++;
|
|
bp11 = *hwp++;
|
|
bp21 = *hwp++;
|
|
M2I (bp10);
|
|
M2I (bp20);
|
|
M2I (bp11);
|
|
M2I (bp21);
|
|
*imp++ = (~bp10) & bp11;
|
|
*imp++ = (~bp20) & bp21;
|
|
*mp++ = (~bp10) | (bp10 & ~bp11);
|
|
*mp++ = (~bp20) & (bp20 & ~bp21);
|
|
}
|
|
#else
|
|
info->size.x = 32;
|
|
info->size.y = 32;
|
|
for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
|
|
mp = mask, imp = image;
|
|
row < 32;
|
|
row++) {
|
|
u_long bp10, bp11;
|
|
bp10 = *hwp++;
|
|
bp11 = *hwp++;
|
|
M2I (bp10);
|
|
M2I (bp11);
|
|
*imp++ = (~bp10) & bp11;
|
|
*mp++ = (~bp10) | (bp10 & ~bp11);
|
|
}
|
|
#endif
|
|
copyout (image, info->image, sizeof (image));
|
|
copyout (mask, info->mask, sizeof (mask));
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
rh_setspriteinfo (gp, info)
|
|
struct grf_softc *gp;
|
|
struct grf_spriteinfo *info;
|
|
{
|
|
volatile unsigned char *ba, *fb;
|
|
u_char control;
|
|
|
|
ba = gp->g_regkva;
|
|
fb = gp->g_fbkva;
|
|
|
|
if (info->set & GRFSPRSET_SHAPE) {
|
|
/*
|
|
* For an explanation of these weird actions here, see above
|
|
* when reading the shape. We set the shape directly into
|
|
* the video memory, there's no reason to keep 1k on the
|
|
* kernel stack just as template
|
|
*/
|
|
u_char *image, *mask;
|
|
volatile u_long *hwp;
|
|
u_char *imp, *mp;
|
|
short row;
|
|
|
|
#ifdef RH_64BIT_SPRITE
|
|
if (info->size.y > 64)
|
|
info->size.y = 64;
|
|
if (info->size.x > 64)
|
|
info->size.x = 64;
|
|
#else
|
|
if (info->size.y > 32)
|
|
info->size.y = 32;
|
|
if (info->size.x > 32)
|
|
info->size.x = 32;
|
|
#endif
|
|
|
|
if (info->size.x < 32)
|
|
info->size.x = 32;
|
|
|
|
image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
|
|
mask = image + HWC_MEM_SIZE/2;
|
|
|
|
copyin(info->image, image, info->size.y * info->size.x / 8);
|
|
copyin(info->mask, mask, info->size.y * info->size.x / 8);
|
|
|
|
hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
|
|
|
|
/*
|
|
* setting it is slightly more difficult, because we can't
|
|
* force the application to not pass a *smaller* than
|
|
* supported bitmap
|
|
*/
|
|
|
|
for (row = 0, mp = mask, imp = image;
|
|
row < info->size.y;
|
|
row++) {
|
|
u_long im1, im2, m1, m2;
|
|
|
|
im1 = *(unsigned long *)imp;
|
|
imp += 4;
|
|
m1 = *(unsigned long *)mp;
|
|
mp += 4;
|
|
#ifdef RH_64BIT_SPRITE
|
|
if (info->size.x > 32) {
|
|
im2 = *(unsigned long *)imp;
|
|
imp += 4;
|
|
m2 = *(unsigned long *)mp;
|
|
mp += 4;
|
|
}
|
|
else
|
|
#endif
|
|
im2 = m2 = 0;
|
|
|
|
M2I(im1);
|
|
M2I(im2);
|
|
M2I(m1);
|
|
M2I(m2);
|
|
|
|
*hwp++ = ~m1;
|
|
#ifdef RH_64BIT_SPRITE
|
|
*hwp++ = ~m2;
|
|
#endif
|
|
*hwp++ = m1 & im1;
|
|
#ifdef RH_64BIT_SPRITE
|
|
*hwp++ = m2 & im2;
|
|
#endif
|
|
}
|
|
#ifdef RH_64BIT_SPRITE
|
|
for (; row < 64; row++) {
|
|
*hwp++ = 0xffffffff;
|
|
*hwp++ = 0xffffffff;
|
|
*hwp++ = 0x00000000;
|
|
*hwp++ = 0x00000000;
|
|
}
|
|
#else
|
|
for (; row < 32; row++) {
|
|
*hwp++ = 0xffffffff;
|
|
*hwp++ = 0x00000000;
|
|
}
|
|
#endif
|
|
|
|
free(image, M_TEMP);
|
|
RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
|
|
}
|
|
if (info->set & GRFSPRSET_CMAP) {
|
|
/* hey cheat a bit here.. XXX */
|
|
WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
|
|
WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
|
|
}
|
|
if (info->set & GRFSPRSET_ENABLE) {
|
|
#if 0
|
|
if (info->enable)
|
|
control = 0x85;
|
|
else
|
|
control = 0;
|
|
WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
|
|
#endif
|
|
}
|
|
if (info->set & GRFSPRSET_POS)
|
|
rh_setspritepos(gp, &info->pos);
|
|
if (info->set & GRFSPRSET_HOT) {
|
|
WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
|
|
WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
rh_getspritemax (gp, pos)
|
|
struct grf_softc *gp;
|
|
struct grf_position *pos;
|
|
{
|
|
#ifdef RH_64BIT_SPRITE
|
|
pos->x = 64;
|
|
pos->y = 64;
|
|
#else
|
|
pos->x = 32;
|
|
pos->y = 32;
|
|
#endif
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
int
|
|
rh_bitblt (gp, bb)
|
|
struct grf_softc *gp;
|
|
struct grf_bitblt *bb;
|
|
{
|
|
struct MonDef *md = (struct MonDef *)gp->g_data;
|
|
if (md->DEP <= 8)
|
|
RZ3BitBlit(gp, bb);
|
|
else if (md->DEP <= 16)
|
|
RZ3BitBlit16(gp, bb);
|
|
else
|
|
RZ3BitBlit24(gp, bb);
|
|
}
|
|
#endif /* NGRF */
|