#include "opt_amigacons.h"
#include "opt_retina.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: grf_rh.c,v 1.62 2022/05/03 20:52:30 andvar Exp $");
#include "grfrh.h"
#include "ite.h"
#if NGRFRH > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/device.h>
#include <sys/device_impl.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(struct MonDef *);
u_short rh_CompFQ(u_int fq);
int rh_load_mon(struct grf_softc *gp, struct MonDef *md);
int rh_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm);
int rh_setvmode(struct grf_softc *gp, unsigned int mode, enum mode_type type);
#ifndef RH_MEMCLK
#define RH_MEMCLK 61000000
#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
#define MDF_DBL 1
#define MDF_LACE 2
#define MDF_CLKDIV2 4
#ifdef __m68k__
#define M2I(val) \
__asm volatile (" rorw #8,%0 ; \
swap %0 ; \
rorw #8,%0 ; " : "=d" (val) : "0" (val));
#else
#define M2I(val) \
val = ((val & 0xff000000) >> 24) | \
((val & 0x00ff0000) >> 8 ) | \
((val & 0x0000ff00) << 8 ) | \
((val & 0x000000ff) << 24)
#endif
#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(struct grf_softc *gp)
{
volatile void *ba = gp->g_regkva;
WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00);
}
void
RZ3SetupHWC(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 *)__UNVOLATILE(ba);
c += 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
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(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(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 = (volatile unsigned long *) (ba +
ACM_OFFSET);
unsigned short mod;
xs *= 4;
ys *= 4;
xd *= 4;
yd *= 4;
w *= 4;
{
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(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 = (volatile unsigned long *) (ba +
ACM_OFFSET);
const struct MonDef *md = (struct MonDef *) gp->g_data;
unsigned short mod;
{
volatile unsigned long * pt =
(volatile 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(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 = (volatile unsigned long *) (ba +
ACM_OFFSET);
const struct MonDef * md = (struct MonDef *) gp->g_data;
unsigned short mod;
{
volatile unsigned long * pt =
(volatile 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(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 = (volatile unsigned long *) (ba +
ACM_OFFSET);
const struct MonDef * md = (struct MonDef *) gp->g_data;
unsigned short mod;
{
volatile unsigned long * pt =
(volatile 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(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(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(struct grf_softc *gp, unsigned char colornum, unsigned char red,
unsigned char green, unsigned char 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));
}
void
RZ3SetPanning(struct grf_softc *gp, unsigned short xoff, unsigned short yoff)
{
volatile unsigned char *ba = gp->g_regkva;
struct grfinfo *gi = &gp->g_display;
const struct MonDef * md = (struct MonDef *) gp->g_data;
unsigned long off;
gi->gd_fbx = xoff;
gi->gd_fby = 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));
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(struct grf_softc *gp, unsigned short x, unsigned short y)
{
volatile unsigned char *ba = gp->g_regkva;
const struct MonDef *md = (struct MonDef *) gp->g_data;
struct grfinfo *gi = &gp->g_display;
if (x < gi->gd_fbx)
RZ3SetPanning(gp, x, gi->gd_fby);
if (x >= (gi->gd_fbx+md->MW))
RZ3SetPanning(gp, (1 + x - md->MW) , gi->gd_fby);
if (y < gi->gd_fby)
RZ3SetPanning(gp, gi->gd_fbx, y);
if (y >= (gi->gd_fby+md->MH))
RZ3SetPanning(gp, gi->gd_fbx, (1 + y - md->MH));
x -= gi->gd_fbx;
y -= gi->gd_fby;
#if 1
WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, x >> 8);
WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, x & 0xff);
WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, y >> 8);
WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, y & 0xff);
#else
*(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
*(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
*(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
*(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
#endif
}
u_short
rh_CompFQ(u_int fq)
{
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(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);
default:
return(0);
}
}
int
rh_load_mon(struct grf_softc *gp, struct MonDef *md)
{
struct grfinfo *gi = &gp->g_display;
volatile void *ba;
volatile void *fb;
short FW, clksel, HDE = 0, VDE;
volatile unsigned short *c;
unsigned short z;
const unsigned char *f;
ba = gp->g_regkva;
fb = gp->g_fbkva;
gp->g_data = (void *) md;
gi->gd_regaddr = (void *) kvtop (__UNVOLATILE(ba));
gi->gd_regsize = LM_OFFSET;
gi->gd_fbaddr = (void *) kvtop (__UNVOLATILE(fb));
gi->gd_fbsize = MEMSIZE *1024*1024;
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) {
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) {
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
}
else if (md->DEP == 8) {
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
}
else if (md->DEP == 16) {
WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
}
else if (md->DEP == 24) {
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, 0x03);
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));
}
#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 );
}
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 = rh_CompFQ(md->FQ);
WPLL(ba, 2 , tmp);
tmp = rh_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);
if (md->DEP < 16) {
vgaw(ba, 0x83c6, ((0 & 7) << 5) );
}
else if (md->DEP == 16) {
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 = (volatile unsigned short *)((volatile char*)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);
}
{
volatile unsigned long *pt = (volatile unsigned long *)
((volatile char *)ba +
LM_OFFSET + PAT_MEM_OFF);
unsigned long tmp = 0xffff0000;
*pt++ = tmp;
*pt = tmp;
}
WSeq(ba, SEQ_ID_MAP_MASK, 3);
c = (volatile unsigned short *)((volatile char*)ba + LM_OFFSET);
c += (md->TX-6)*2;
{
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);
gi->gd_fbx = 0;
gi->gd_fby = 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);
gi->gd_fbx = 0;
gi->gd_fby = 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 );
gi->gd_fbx = 0;
gi->gd_fby = 0;
return 1;
} else
return(0);
}
unsigned char RZ3StdPalette[16*3] = {
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,
255,255,255,
255, 0, 0,
0,255, 0,
0, 0,255,
255,255, 0,
0,255,255,
255, 0,255
};
#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[] = {
{ 50000000, 28, 640, 440, 81, 86, 93, 98, 95, 481, 490, 498, 522, 522,
4, RZ3StdPalette, 80, 55, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 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},
{ 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},
#ifdef RH_HARDWARECURSOR
{ 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},
{ 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},
{ 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},
{ 62000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 77000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 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},
{ 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},
{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},
{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},
{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},
{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},
{ 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},
{ 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},
{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},
{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},
{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},
{ 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},
{ 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},
{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},
{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},
{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},
{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},
#else
{ 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502,
8, RZ3StdPalette, 640, 480, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502,
8, RZ3StdPalette, 640, 480, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628,
8, RZ3StdPalette, 800, 600, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 62000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 77000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
{ 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938,
8, RZ3StdPalette, 1120, 896, 5120, FX, FY, KERNEL_FONT, 32, 255},
{110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953,
8, RZ3StdPalette, 1152, 910, 5120, FX, FY, KERNEL_FONT, 32, 255},
{110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888,
8, RZ3StdPalette, 1184, 848, 5120, FX, FY, KERNEL_FONT, 32, 255},
{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},
{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},
{ 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502,
16, 0, 640, 480, 7200, FX, FY, KERNEL_FONT, 32, 255},
{ 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628,
16, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
{110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804,
16, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
{109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678,
16, 0, 864, 648, 7200, FX, FY, KERNEL_FONT, 32, 255},
{124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804,
16, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
{ 46000000, 1, 320, 200, 241,268,287,324,323, 401, 405, 412, 418, 418,
24, 0, 320, 200, 7200, FX, FY, KERNEL_FONT, 32, 255},
{ 76000000, 0, 640, 400, 481,514,552,601,600, 401, 402, 409, 418, 418,
24, 0, 640, 400, 7200, FX, FY, KERNEL_FONT, 32, 255},
{101000000, 0, 724, 482, 544,576,619,682,678, 483, 487, 495, 495, 504,
24, 0, 724, 482, 7200, FX, FY, KERNEL_FONT, 32, 255},
{110000000, 0, 800, 600, 601,602,647,723,722, 601, 602, 612, 628, 628,
24, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
{132000000, 0, 800, 600, 601,641,688,749,748, 601, 611, 621, 628, 628,
24, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
{110000000, 2, 1024, 768, 769,770,824,854,853, 385, 386, 392, 401, 401,
24, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
#endif
};
#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) 44kHz",
"GFX-8 (1024x768) 50kHz",
"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]);
int rh_default_mon = 0;
int rh_default_gfx = 4;
static struct MonDef *current_mon;
int rh_mode(struct grf_softc *, u_long, void *, u_long, int);
void grfrhattach(device_t, device_t, void *);
int grfrhprint(void *, const char *);
int grfrhmatch(device_t, cfdata_t, void *);
CFATTACH_DECL_NEW(grfrh, sizeof(struct grf_softc),
grfrhmatch, grfrhattach, NULL, NULL);
static struct cfdata *cfdata;
int
grfrhmatch(device_t parent, cfdata_t cf, void *aux)
{
#ifdef RETINACONSOLE
static int rhconunit = -1;
#endif
struct zbus_args *zap;
zap = aux;
if (amiga_realconfig == 0)
#ifdef RETINACONSOLE
if (rhconunit != -1)
#endif
return(0);
if (zap->manid != 18260 ||
((zap->prodid != 16) && (zap->prodid != 19)))
return(0);
#ifdef RETINACONSOLE
if (amiga_realconfig == 0 || rhconunit != cf->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 = cf->cf_unit;
cfdata = cf;
}
}
#endif
return(1);
}
void
grfrhattach(device_t parent, device_t self, void *aux)
{
static struct grf_softc congrf;
struct device temp;
struct zbus_args *zap;
struct grf_softc *gp;
zap = aux;
if (self == NULL) {
gp = &congrf;
gp->g_device = &temp;
temp.dv_private = gp;
} else {
gp = device_private(self);
gp->g_device = self;
}
if (self != NULL && congrf.g_regkva != 0) {
memcpy(&gp->g_display, &congrf.g_display,
(char *)&gp[1] - (char *)&gp->g_display);
} else {
gp->g_regkva = (volatile void *)zap->va;
gp->g_fbkva = (volatile char *)zap->va + LM_OFFSET;
gp->g_unit = GRF_RETINAIII_UNIT;
gp->g_mode = rh_mode;
gp->g_flags = GF_ALIVE;
#if NITE > 0
gp->g_conpri = grfrh_cnprobe();
grfrh_iteinit(gp);
#endif
(void)rh_load_mon(gp, current_mon);
}
if (self != NULL)
printf("\n");
amiga_config_found(cfdata, gp->g_device, gp, grfrhprint, CFARGS_NONE);
}
int
grfrhprint(void *aux, const char *pnp)
{
if (pnp)
aprint_normal("ite at %s", pnp);
return(UNCONF);
}
int
rh_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
{
struct MonDef *md;
int vmul;
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;
if (md->DEP != 4) {
vm->hblank_start = md->HBS * 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->hsync_start = md->HSS * md->FX;
vm->hsync_stop = md->HSE * md->FX;
vm->htotal = md->HT * md->FX;
}
vm->disp_flags = 0;
vmul = 2;
if (md->FLG & MDF_DBL) {
vm->disp_flags |= GRF_FLAGS_DBLSCAN;
vmul = 4;
}
if (md->FLG & MDF_LACE) {
vm->disp_flags |= GRF_FLAGS_LACE;
vmul = 1;
}
vm->vblank_start = md->VBS * vmul / 2;
vm->vsync_start = md->VSS * vmul / 2;
vm->vsync_stop = md->VSE * vmul / 2;
vm->vtotal = md->VT * vmul / 2;
return(0);
}
int
rh_setvmode(struct grf_softc *gp, unsigned mode, enum mode_type type)
{
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);
}
int
rh_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
int 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);
case GM_GRFIOCTL:
return(rh_ioctl (gp, a2, arg));
default:
break;
}
return(EPASSTHROUGH);
}
int
rh_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
{
switch (cmd) {
#ifdef RH_HARDWARECURSOR
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));
#else
case GRFIOCGSPRITEPOS:
case GRFIOCSSPRITEPOS:
case GRFIOCSSPRITEINF:
case GRFIOCGSPRITEMAX:
break;
#endif
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));
case GRFIOCBLANK:
return (rh_blank(gp, (int *)data));
}
return(EPASSTHROUGH);
}
int
rh_getcmap(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->count > 256 - cmap->index)
cmap->count = 256 - cmap->index;
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 {
*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(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->count > 256 - cmap->index)
cmap->count = 256 - cmap->index;
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))) {
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(struct grf_softc *gp, struct grf_position *pos)
{
struct grfinfo *gi = &gp->g_display;
#if 1
volatile unsigned char *ba = gp->g_regkva;
pos->x = (RSeq(ba, SEQ_ID_CURSOR_X_LOC_HI) << 8) |
RSeq(ba, SEQ_ID_CURSOR_X_LOC_LO);
pos->y = (RSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8) |
RSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO);
#else
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);
#endif
pos->x += gi->gd_fbx;
pos->y += gi->gd_fby;
return(0);
}
int
rh_setspritepos (struct grf_softc *gp, struct grf_position *pos)
{
RZ3SetHWCloc (gp, pos->x, pos->y);
return(0);
}
int
rh_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
{
volatile unsigned char *ba;
ba = gp->g_regkva;
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;
#ifdef RH_64BIT_SPRITE
info->size.x = 64;
info->size.y = 64;
for (row = 0,
hwp = (volatile 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 = (volatile 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(struct grf_softc *gp, struct grf_spriteinfo *info)
{
volatile unsigned char *ba;
#if 0
u_char control;
#endif
ba = gp->g_regkva;
if (info->set & GRFSPRSET_SHAPE) {
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 = (volatile u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
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) {
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(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(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);
return(0);
}
int
rh_blank(struct grf_softc *gp, int *on)
{
struct MonDef *md = (struct MonDef *)gp->g_data;
int r;
r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
return(0);
}
#endif