/*
* Copyright (c) 1996 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.
*/
/*
* Most of the lower-level et4000 stuff was derived from:
* .../amiga/dev/grf_et.c
*
* Which was copyrighted by:
* Copyright (c) 1996 Tobias Abt
* Copyright (c) 1995 Ezra Story
* Copyright (c) 1995 Kari Mettinen
* Copyright (c) 1994 Markus Wild
* Copyright (c) 1994 Lutz Vieweg
*
* Thanks guys!
*
*/
/*
* Allow a 16Kb io-region and a 4MB frame buffer to be mapped. This
* is more or less required by the XFree server.
*/
#define REG_MAPPABLE (16 * 1024)
#define FRAME_MAPPABLE (4 * 1024 * 1024)
#define VGA_MAPPABLE (128 * 1024)
#define VGA_BASE 0xa0000
/*
* Linear memory base, near the end of the pci area
*/
#define PCI_LINMEMBASE 0x0e000000
if (dm->current_view && (dm->current_view != v)) {
/*
* Mark current view for this mode as no longer displayed
*/
dm->current_view->flags &= ~VF_DISPLAY;
}
dm->current_view = v;
v->flags |= VF_DISPLAY;
if (RGfx(ba, GCT_ID_MISC) & 1) {
#if 0 /* XXX: Can't use printf here.... */
printf("et_save_view: Don't know how to save"
" a graphics mode\n");
#endif
return;
}
if (v->save_area == NULL)
v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_NOWAIT);
/*
* Calculate the size of the copy
*/
font_height = RCrt(ba, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
sv_size = uimin(SAVEBUF_SIZE, sv_size);
/*
* Save all we need to know....
*/
sa = (save_area_t *)v->save_area;
et_hwsave(&sa->sv_regs);
sa->fb_size = sv_size;
src = (u_short *)bm->plane;
dst = sa->sv_fb;
while (sv_size--)
*dst++ = *src++;
bm->plane = (u_char *)sa->sv_fb;
}
void
et_free_view(view_t *v)
{
if (v) {
et_remove_view(v);
if (v->colormap != &gra_con_cmap)
free(v->colormap, M_DEVBUF);
if (v->save_area != NULL)
free(v->save_area, M_DEVBUF);
if (v != &gra_con_view) {
free(v->bitmap, M_DEVBUF);
free(v, M_DEVBUF);
}
}
}
static int
et_use_colormap(view_t *v, colormap_t *cm)
{
return (0); /* XXX: Nothing here for now... */
}
/*
* Allocate a save_area.
* Note: If atari_realconfig is false, no save area is (can be)
* allocated. This means that the plane is the video memory,
* which is what's wanted in this case.
*/
if (atari_realconfig) {
v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
sa = (save_area_t*)v->save_area;
sa->fb_size = 0;
bm->plane = (u_char *)sa->sv_fb;
et_loadmode(mode->data, &sa->sv_regs);
} else
v->save_area = NULL;
v->colormap = alloc_colormap(mode);
if (v->colormap) {
INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
init_view(v, bm, mode, &box);
return (v);
}
if (v != &gra_con_view) {
free(v, M_DEVBUF);
free(bm, M_DEVBUF);
}
return (NULL);
}
/* XXX: No more than a stub... */
static colormap_t *
alloc_colormap(dmode_t *dm)
{
colormap_t *cm;
int i;
cm = &gra_con_cmap;
cm->entry = gra_con_colors;
cm->first = 0;
cm->size = 2;
for (i = 0; i < 2; i++)
cm->entry[i] = gra_def_color16[i % 16];
return (cm);
}
/*
* Go look for a VGA card on the PCI-bus. This search is a
* stripped down version of the PCI-probe. It only looks on
* bus0 for et4000/et6000 cards. The first card found is used.
*/
int
et_probe_card(void)
{
pci_chipset_tag_t pc = NULL; /* XXX */
pcitag_t tag;
int device, found, id, maxndevs;
found = 0;
tag = 0;
id = 0;
maxndevs = pci_bus_maxdevs(pc, 0);
tag = pci_make_tag(pc, 0, device, 0);
id = pci_conf_read(pc, tag, PCI_ID_REG);
if (id == 0 || id == 0xffffffff)
continue;
switch (PCI_PRODUCT(id)) {
case PCI_PRODUCT_TSENG_ET6000:
case PCI_PRODUCT_TSENG_ET4000_W32P_A:
case PCI_PRODUCT_TSENG_ET4000_W32P_B:
case PCI_PRODUCT_TSENG_ET4000_W32P_C:
case PCI_PRODUCT_TSENG_ET4000_W32P_D:
found = 1;
break;
default:
break;
}
}
if (!found)
return (0);
for (i = 0; i < 0x10; i++)
regs->attr[i] = i;
regs->attr[ACT_ID_ATTR_MODE_CNTL] = 0x01;
regs->attr[ACT_ID_OVERSCAN_COLOR] = 0x00;
regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f;
regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00;
regs->attr[ACT_ID_COLOR_SELECT] = 0x00;
regs->attr[ACT_ID_MISCELLANEOUS] = 0x00;
/*
* XXX: This works for depth == 4. I need some better docs
* to fix the other modes....
*/
/*
* What we need would be probe functions for RAMDAC/clock chip
*/
vgar(ba, VDAC_ADDRESS); /* clear old state */
vgar(ba, VDAC_MASK);
vgar(ba, VDAC_MASK);
vgar(ba, VDAC_MASK);
vgar(ba, VDAC_MASK);
vgaw(ba, VDAC_MASK, 0); /* set to palette */
vgar(ba, VDAC_ADDRESS); /* clear state */
vgaw(ba, VDAC_MASK, 0xff);
/*
* End of depth stuff
*/
/*
* Compute Hsync & Vsync polarity
* Note: This seems to be some kind of a black art :-(
*/
tmp = regs->misc_output & 0x3f;
#if 1 /* This is according to my BW monitor & Xfree... */
if (VDE < 400)
tmp |= 0x40; /* -hsync +vsync */
else if (VDE < 480)
tmp |= 0xc0; /* -hsync -vsync */
#else /* This is according to my color monitor.... */
if (VDE < 400)
tmp |= 0x00; /* +hsync +vsync */
else if (VDE < 480)
tmp |= 0x80; /* +hsync -vsync */
#endif
/* I'm unable to try the rest.... */
regs->misc_output = tmp;
if (regs == &loc_regs)
et_hwrest(regs);
}
void
et_hwsave(et_sv_reg_t *et_regs)
{
volatile u_char *ba;
int i, s;
ba = et_priv.regkva;
s = splhigh();
/*
* General VGA registers
*/
et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
for (i = 0; i < 25; i++)
et_regs->crt[i] = RCrt(ba, i);
for (i = 0; i < 21; i++)
et_regs->attr[i] = RAttr(ba, i | 0x20);
for (i = 0; i < 9; i++)
et_regs->grf[i] = RGfx(ba, i);
for (i = 0; i < 5; i++)
et_regs->seq[i] = RSeq(ba, i);
/*
* General VGA registers
*/
WSeq(ba, SEQ_ID_RESET, 0x01);
for (i = 1; i < 5; i++)
WSeq(ba, i, et_regs->seq[i]);
WSeq(ba, SEQ_ID_RESET, 0x03);
/*
* Make sure we're allowed to write all crt-registers
*/
WCrt(ba, CRT_ID_END_VER_RETR,
et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
for (i = 0; i < 25; i++)
WCrt(ba, i, et_regs->crt[i]);
for (i = 0; i < 9; i++)
WGfx(ba, i, et_regs->grf[i]);
for (i = 0; i < 21; i++)
WAttr(ba, i | 0x20, et_regs->attr[i]);