/*-
* Copyright (c) 1995 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Ignatios Souvatzis.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* We give all these values in MI units, that is:
* horizontal timings in units of pixels
* vertical timings in units of lines
* point of reference is blanking end.
*
* The ul_load_mon transforms these values right before loading
* them into the chip.
*
* This leaves us with a single point where things are transformed,
* which should make life easier if we ever change things again.
*/
/*
* XXX load shadow overlay palette with what the TMS code will load
* into the real one some time after the TMS code is started below.
* This might be considered a rude hack.
*/
memcpy(gup->gus_ovcmap, ul_ovl_palette, 3*4);
/*
* Unflush cache, unhalt CPU -> nmi starts to run. This MUST NOT BE
* DONE before the image color map initialization above, to guarantee
* the index register in the BT458 is not used by more than one CPU
* at once.
*
* XXX For the same reason, we'll have to rething ul_putcmap(). For
* details, look at comment there.
*/
ba->ctrl &= ~(HLT|CF);
#else
/*
* XXX I wonder why this partially ever worked.
*
* This can't possibly work this way, as we are copyin()ing data in
* ul_putcmap.
*
* I guess this partially worked because SFC happened to point to
* to supervisor data space on 68030 machines coming from the old
* boot loader.
*
* While this looks more correct than the hack in the other part of the
* loop, we would have to do our own version of the loop through
* colormap entries, set up command buffer, and call gsp_write(), or
* factor out some code.
*/
/*
* XXX This version will work for the overlay, if our queue codes
* initial conditions are set at load time (not start time).
* It further assumes that ul_putcmap only uses the
* GRFIMDEV/GRFOVDEV bits of the dev parameter.
*/
/* unflush cache, unhalt CPU first -> nmi starts to run */
ba->ctrl &= ~(HLT|CF);
/* I guess this should be in the yet unimplemented mode select ioctl */
/* Hm.. maybe not. We always put the console on overlay plane no 0. */
/* Anyway, this _IS_ called in the mode select ioctl. */
/*
* 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
grfulmatch(device_t parent, cfdata_t cf, void *aux)
{
#ifdef ULOWELLCONSOLE
static int ulconunit = -1;
#endif
struct zbus_args *zap;
zap = aux;
/*
* allow only one ulowell console
*/
if (amiga_realconfig == 0)
#ifdef ULOWELLCONSOLE
if (ulconunit != -1)
#endif
return(0);
if (zap->manid != 1030 || zap->prodid != 0)
return(0);
#ifdef ULOWELLCONSOLE
if (amiga_realconfig == 0 || ulconunit != cf->cf_unit) {
#endif
if ((unsigned)ulowell_default_mon > ulowell_mon_max)
ulowell_default_mon = 1;
switch (cmd) {
case GM_GRFON:
gup->gus_ovslct |= 0x40;
break;
case GM_GRFOFF:
gup->gus_ovslct &= ~0x40;
break;
case GM_GRFOVON:
gup->gus_ovslct |= 3;
break;
case GM_GRFOVOFF:
gup->gus_ovslct &= ~3;
break;
}
ba->data = gup->gus_ovslct;
}
/*
* Change the mode of the display.
* Return a UNIX error number or 0 for success.
*/
int
ul_mode(struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
{
int i;
struct grfdyninfo *gd;
switch (cmd) {
case GM_GRFON:
case GM_GRFOFF:
case GM_GRFOVON:
case GM_GRFOVOFF:
ul_setfb (gp, cmd);
return 0;
case GM_GRFCONFIG:
gd = (struct grfdyninfo *)arg;
for (i=0; i<ulowell_mon_max; ++i) {
if (ul_monitor_defs[i].disp_width == gd->gdi_dwidth &&
ul_monitor_defs[i].disp_height == gd->gdi_dheight)
return ul_setvmode(gp, i+1);
}
return EINVAL;
case GM_GRFGETVMODE:
return ul_getvmode (gp, (struct grfvideo_mode *) arg);
case GM_GRFSETVMODE:
return ul_setvmode (gp, *(unsigned *) arg);
case GM_GRFGETNUMVM:
*(int *)arg = ulowell_mon_max;
return 0;
case GM_GRFIOCTL:
return ul_ioctl (gp, a2, arg, (dev_t)a3);
default:
break;
}
return EPASSTHROUGH;
}
int
ul_ioctl (register struct grf_softc *gp, u_long cmd, void *data, dev_t dev)
{
switch (cmd) {
#if 0
/*
* XXX we have no hardware sprites, but might implement them
* later in TMS code.
*/
case GRFIOCGSPRITEPOS:
return ul_getspritepos (gp, (struct grf_position *) data);
case GRFIOCSSPRITEPOS:
return ul_setspritepos (gp, (struct grf_position *) data);
case GRFIOCSSPRITEINF:
return ul_setspriteinfo (gp, (struct grf_spriteinfo *) data);
case GRFIOCGSPRITEINF:
return ul_getspriteinfo (gp, (struct grf_spriteinfo *) data);
case GRFIOCGSPRITEMAX:
return ul_getspritemax (gp, (struct grf_position *) data);
#endif
case GRFIOCGETCMAP:
return ul_getcmap (gp, (struct grf_colormap *) data, dev);
case GRFIOCPUTCMAP:
return ul_putcmap (gp, (struct grf_colormap *) data, dev);
case GRFIOCBITBLT:
return ul_bitblt (gp, (struct grf_bitblt *) data, dev);
case GRFIOCBLANK:
return ul_blank (gp, (int *) data, dev);
}
return EPASSTHROUGH;
}
int
ul_getcmap (struct grf_softc *gp, struct grf_colormap *cmap, dev_t dev)
{
struct grf_ul_softc *gup;
u_int8_t *mymap;
int mxidx, error;
/* then write from there to the hardware */
ba = (volatile struct gspregs *)gp->g_regkva;
/*
* XXX This is a bad thing to do.
* We should always use the gsp call, or have a means to arbitrate
* the usage of the BT458 index register. Else there might be a
* race condition (when writing both colormaps at nearly the same
* time), where one CPU changes the index register when the other
* one has not finished using it.
*/
if (mxidx > 4) {
/* image color map: we can write, with a hack, directly */
ba->ctrl = LBL;
ba->hstadrh = 0xfe80;
ba->hstadrl = 0x0000;
ba->ctrl |= INCW;
ba->data = cmap->index;
ba->ctrl &= ~INCW;
GSPSETHADRS(gsp, PUT_PTR_ADRS);
put = gsp->data;
new_put = put + (8<<4);
GSPSETHADRS(gsp, GET_PTR_ADRS);
next = gsp->data;
while (next == new_put) {
/*
* we should use an intr. here. unfortunately, we already
* are called from an interrupt and can't use tsleep.
* so we do busy waiting, at least for the moment.
*/
GSPSETHADRS(gsp,GET_PTR_ADRS);
next = gsp->data;
}