/*
* Copyright (c) 1993 Markus Wild
* Copyright (c) 1993 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 "opt_amigacons.h"
int rt_ioctl(struct grf_softc *gp, u_long, void *);
/*
* marked true early so that retina_cnprobe() can tell if we are alive.
*/
int retina_inited;
/*
* 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 77C22E+" Data Manual
*/
/*
* This code offers low-level routines to access the Retina graphics-board
* manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
*
* Thanks to MacroSystem for providing me with the necessary information
* to create these routines. The sparse documentation of this code
* results from the agreements between MS and me.
*/
unsigned char NCRStdPalette[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 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.
Then you'll need to adapt your 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.
*/
/* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-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)! */
/* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-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)! */
/* XXXX according to the NCR specs, this register should be set to 1
XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
XXXX setting. */
WSeq (ba, SEQ_ID_RESET, 0x03);
/* if this does what I think it does, it selects DAC
register 0, and writes the palette in subsequent
registers, thus it works similar to the WD33C93
select/data mechanism */
vgaw (ba, VDAC_REG_SELECT, 0x00);
{
short x = 15;
const unsigned char * col = md->PAL;
do {
/* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
if (md->DEP == 4) {
/* first set the whole font memory to a test-pattern, so we
can see if something that shouldn't be drawn IS drawn.. */
{
volatile char *c = fb;
long x;
Map(2);
for (x = 0; x < 65536; x++) {
*c++ = (x & 1)? 0xaa : 0x55;
}
}
{
volatile char *c = fb;
long x;
Map(3);
for (x = 0; x < 65536; x++) {
*c++ = (x & 1)? 0xaa : 0x55;
}
}
{
/* ok, now position at first defined character, and
copy over the images */
volatile char *c = fb + md->FLo * 32;
const unsigned char * f = md->FData;
unsigned short z;
Map(2);
for (z = md->FLo; z <= md->FHi; z++) {
short y = md->FY-1;
if (md->FX > 8){
do {
*c++ = *f;
f += 2;
} while (y--);
}
else {
do {
*c++ = *f++;
} while (y--);
}
c += 32-md->FY;
}
if (md->FX > 8) {
unsigned short zz;
Map(3);
c = fb + md->FLo*32;
f = md->FData+1;
for (zz = md->FLo; z <= md->FHi; zz++) {
short y = md->FY-1;
do {
*c++ = *f;
f += 2;
} while (y--);
c += 32-md->FY;
}
}
}
}
/* select map 0 */
WGfx (ba, GCT_ID_READ_MAP_SELECT, 0);
if (md->DEP == 4)
/* allow writes into maps 0 and 1 */
WSeq (ba, SEQ_ID_MAP_MASK, 3);
else
/* allow writes into all maps */
WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
/* select extended chain4 addressing:
!A0/!A1 map 0 character to be displayed
!A1/ A1 map 1 attribute of that character
A0/!A1 map 2 not used (masked out, ignored)
A0/ A1 map 3 not used (masked out, ignored) */
WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
if (md->DEP == 4) {
/* position in display memory */
volatile unsigned short * c = (volatile unsigned short *) fb;
/* fill with blank, white on black */
const unsigned short fill_val = 0x2010;
short x = md->XY;
do {
*c = fill_val;
c += 2; } while (x--);
/* I won't comment this :-)) */
c = (volatile unsigned short *) fb;
c += (md->TX-6)*2;
{
unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
unsigned short * f = init_msg;
x = 5;
do {
*c = *f++;
c += 2;
} while (x--);
}
}
else if (md->DEP == 8) {
/* could clear the gfx screen here, but that's what the X server does anyway */
;
}
/*
* only used in console init
*/
static struct cfdata *cfdata;
/*
* we make sure to only init things once. this is somewhat
* tricky regarding the console.
*/
int
grfrtmatch(device_t parent, cfdata_t cf, void *aux)
{
#ifdef RETINACONSOLE
static int rtconunit = -1;
#endif
struct zbus_args *zap;
zap = aux;
/*
* allow only one retina console
*/
if (amiga_realconfig == 0)
#ifdef RETINACONSOLE
if (rtconunit != -1)
#endif
return(0);
/*
* check that this is a retina board.
*/
if (zap->manid != 18260 || zap->prodid != 6)
return(0);
/*
* 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 weird.
* 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
*/
/*
* Change the mode of the display.
* Return a UNIX error number or 0 for success.
*/
int
rt_mode(struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
{
/* implement these later... */
ba = gfp->g_regkva;
/* first read colors out of the chip, then copyout to userspace */
vgaw (ba, VDAC_REG_SELECT, cmap->index);
x = cmap->count - 1;
rp = red + cmap->index;
gp = green + cmap->index;
bp = blue + cmap->index;
do {
*rp++ = vgar (ba, VDAC_REG_DATA);
*gp++ = vgar (ba, VDAC_REG_DATA);
*bp++ = vgar (ba, VDAC_REG_DATA);
}
while (x--);
/* assume an at least 2M retina (XXX), sprite is last in memory.
* According to the bogus docs, the cursor can be at most 128 lines
* in height, and the x-hostspot can be placed at most at pos 31,
* this gives width of a long
*/
#define SPRITE_ADDR (2*1024*1024 - 128*4)
/* set write mode 1, "[...] data in the read latches is written
to memory during CPU memory write cycles. [...]" */
WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
/* write to primary, read from secondary */
WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
if (src_offset < dst_offset)
{
/* start at end */
src_offset += tot;
dst_offset += tot;
}