/*
* 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.
*/
/*
* this function is called from grf_rt to init the grf_softc->g_conpri
* field each time a retina is attached.
*/
int
grfrt_cnprobe(void)
{
static int done;
int rv;
/*
* init the required fields in the grf_softc struct for a
* grf to function as an ite.
*/
void
grfrt_iteinit(struct grf_softc *gp)
{
gp->g_iteinit = retina_init;
gp->g_itedeinit = retina_deinit;
gp->g_iteclear = retina_clear;
gp->g_iteputc = retina_putc;
gp->g_itescroll = retina_scroll;
gp->g_itecursor = retina_cursor;
}
/* the trick here is to use a feature of the NCR chip. It can
optimize data access in various read/write modes. One of
the modes is able to read/write from/to different zones.
Thus, by setting the read-offset to lineN, and the write-offset
to line0, we just cause read/write cycles for all characters
up to the last line, and have the chip transfer the data. The
`addqb' are the cheapest way to cause read/write cycles (DONT
use `tas' on the Amiga!), their results are completely ignored
by the NCR chip, it just replicates what it just read. */
/* 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);
/* clear extended chain4 mode */
WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
/* 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);
{
unsigned long * p = (unsigned long *) fb;
short x = (lines * (md->TX/16)) - 1;
const unsigned long dummyval = 0;
p += (1 + bottom - lines) * (md->TX/4);
do {
*p++ = dummyval;
*p++ = dummyval;
*p++ = dummyval;
*p++ = dummyval;
} while (x--);
}
/* 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 line TOP + LINES */
long toloc = (top + lines) * (md->TX / 16);
WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, ((unsigned char)toloc));
WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, ((unsigned char)(toloc >> 8)));
}
{
/* read from line TOP */
long fromloc = top * (md->TX / 16);
WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, ((unsigned char)fromloc));
WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, ((unsigned char)(fromloc >> 8))) ;
}
{ /* feed latches with value */
unsigned short * f = (unsigned short *) fb;
f += top * md->TX * 2;
*f = 0x2010;
}
/* clear extended chain4 mode */
WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02);
/* 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);
{
unsigned long * p = (unsigned long *) fb;
short x = (lines * (md->TX/16)) - 1;
const unsigned long dummyval = 0;
p += top * (md->TX/4);
do {
*p++ = dummyval;
*p++ = dummyval;
*p++ = dummyval;
*p++ = dummyval;
} while (x--);
}
void
retina_clear(struct ite_softc *ip, int sy, int sx, int h, int w)
{
volatile u_short * fb = (volatile u_short *) ip->grf->g_fbkva;
short x;
const u_short fillval = 0x2010;
/* could probably be optimized just like the scrolling functions !! */
fb += 2 * (sy * ip->cols + sx);
while (h--)
{
for (x = 2 * (w - 1); x >= 0; x -= 2)
fb[x] = fillval;
fb += 2 * ip->cols;
}
}
/*
* RETINA_SPEED_HACK code seems to work on some boards and on others
* it causes text to smear horizontally
*/
void
retina_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir)
{
u_long *fb;