/*
* Copyright (c) 1995 Thomas Gerner.
* Copyright (c) 1995 Leo Weppelman.
* 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.
*
* 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.
*/
/*
* The following table contains timing values for the various video modes.
* I have only a multisync display, therefore I can not say if this values
* are useful at other displays.
* Use other video modes at YOUR OWN RISK.
* THERE IS NO WARRENTY ABOUT THIS VALUES TO WORK WITH A PARTICULAR
* DISPLAY. -- Thomas
*/
static struct videl videlinit[] = {
{ RES_FALAUTO, /* autodedect */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
static u_short mon_type;
/*
* XXX: called from ite console init routine.
* Initialize list of possible video modes.
*/
void
falcon_probe_video(MODES *modelp)
{
dmode_t *dm;
struct videl *vregs;
int i;
if (dm->current_view) {
/*
* Mark current view for this mode as no longer displayed
*/
dm->current_view->flags &= ~VF_DISPLAY;
}
dm->current_view = v;
v->flags |= VF_DISPLAY;
vregs = vm_regs(v->mode);
if (last_mode != vregs->video_mode) {
last_mode = vregs->video_mode;
if (dm->depth == 1) {
/*
* Set the resolution registers to a mode, which guarantee
* no shifting when the register are written during vbl.
*/
VIDEO->vd_fal_res = 0;
VIDEO->vd_st_res = 0;
}
/*
* Arrange for them to be activated
* at the second vbl interrupt.
*/
falcon_needs_vbl = (u_long)v;
}
}
void
falcon_display_switch(void)
{
view_t *v;
struct videl *vregs;
static int vbl_count = 1;
if (vbl_count--)
return;
v = (view_t*)falcon_needs_vbl;
vbl_count = 1;
falcon_needs_vbl = 0;
/*
* Write to videl registers only on VGA displays
* This is only a hack. Must be fixed soon. XXX -- Thomas
*/
if (mon_type != FAL_VGA)
return;
static void
falcon_free_view(view_t *v)
{
if (v) {
falcon_remove_view(v);
if (v->colormap != &gra_con_cmap)
free(v->colormap, M_DEVBUF);
free_bitmap(v->bitmap);
if (v != &gra_con_view)
free(v, M_DEVBUF);
}
}
static int
falcon_use_colormap(view_t *v, colormap_t *cm)
{
dmode_t *dm;
volatile u_short *creg;
volatile u_long *fcreg;
u_long *src;
colormap_t *vcm;
u_long *vcreg;
u_short ncreg;
int last_streg;
int i;
dm = v->mode;
vcm = v->colormap;
/*
* I guess it seems reasonable to require the maps to be
* of the same type...
*/
if (cm->type != vcm->type)
return (EINVAL);
/*
* First get the colormap addresses and calculate
* how many colors are in it.
*/
if (dm->depth == 16) /* direct color, no colormap;
but also not (yet) supported */
return(0);
fcreg = &VIDEO->vd_fal_rgb[0];
creg = &VIDEO->vd_st_rgb[0];
ncreg = 1 << dm->depth;
/* If first entry specified beyond capabilities -> error */
if (cm->first >= ncreg)
return (EINVAL);
/*
* A little tricky, the actual colormap pointer will be NULL
* when view is not displaying, valid otherwise.
*/
if (v->flags & VF_DISPLAY) {
creg = &creg[cm->first];
fcreg = &fcreg[cm->first];
} else {
creg = NULL;
fcreg = NULL;
}
for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) {
*vcreg = *src++;
/*
* If displaying, also update actual color register.
*/
if (fcreg != NULL) {
*fcreg++ = CM_L2FAL(*vcreg);
if (i < last_streg)
*creg++ = CM_L2ST(*vcreg);
}
}
return (0);
}
/*
* Sigh, it seems for mapping to work we need the bitplane data to
* 1: be aligned on a page boundary.
* 2: be n pages large.
*
* why? because the user gets a page aligned address, if this is before
* your allocation, too bad. Also it seems that the mapping routines
* do not watch to closely to the allowable length. so if you go over
* n pages by less than another page, the user gets to write all over
* the entire page. Since you did not allocate up to a page boundary
* (or more) the user writes into someone elses memory. -ch
*/
bm_size = m68k_round_page((width * height * depth) / NBBY);
total_size = bm_size + sizeof(bmap_t) + PAGE_SIZE;
if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL)
return(NULL);