NetBSD/sys/arch/atari/dev/grfabs_et.c

864 lines
22 KiB
C

/* $NetBSD: grfabs_et.c,v 1.11 1998/12/20 14:32:53 thomas Exp $ */
/*
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Leo Weppelman.
* 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.
*/
/*
* 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!
*
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
/*
* For PCI probing...
*/
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <machine/iomap.h>
#include <machine/video.h>
#include <machine/mfp.h>
#include <machine/cpu.h>
#include <atari/atari/device.h>
#include <atari/dev/grfioctl.h>
#include <atari/dev/grfabs_reg.h>
#include <atari/dev/grfabs_et.h>
#include <atari/dev/grf_etreg.h>
#define SAVEBUF_SIZE (32*1024 + sizeof(save_area_t))
/*
* 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
/*
* Where we map the PCI registers in the io-space (et6000)
* XXX: 0x400 would probably work too...
*/
#define PCI_IOBASE 0x800
/*
* Linear memory base, near the end of the pci area
*/
#define PCI_LINMEMBASE 0x0e000000
/*
* Function decls
*/
static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
static colormap_t *alloc_colormap __P((dmode_t *));
static void et6000_init __P((void));
static void et_display_view __P((view_t *));
static view_t *et_alloc_view __P((dmode_t *, dimen_t *, u_char));
static void et_boardinit __P((void));
static void et_free_view __P((view_t *));
static void et_loadmode __P((struct grfvideo_mode *, et_sv_reg_t *));
static void et_remove_view __P((view_t *));
static void et_save_view __P((view_t *));
static int et_use_colormap __P((view_t *, colormap_t *));
/*
* Our function switch table
*/
struct grfabs_sw et_vid_sw = {
et_display_view,
et_alloc_view,
et_free_view,
et_remove_view,
et_save_view,
et_use_colormap
};
static struct grfvideo_mode hw_modes[] = {
{
0, "", 25175000, /* num, descr, pix-clock */
640, 400, 4, /* width, height, depth */
632/8, 672/8, 688/8, 808/8, 768/8,/* HBS, HBE, HSS, HSE, HT */
399, 450, 408, 413, 449 /* VBS, VBE, VSS, VSE, VT */
},
{
0, "", 25175000, /* num, descr, pix-clock */
640, 480, 4, /* width, height, depth */
632/8, 672/8, 688/8, 752/8, 752/8,/* HBS, HBE, HSS, HSE, HT */
481, 522, 490, 498, 522 /* VBS, VBE, VSS, VSE, VT */
}
};
static dmode_t vid_modes[] = {
{ { NULL, NULL },
"640x400", { 640, 400 }, 1, (void*)&hw_modes[0], &et_vid_sw },
{ { NULL, NULL },
"640x480", { 640, 480 }, 1, (void*)&hw_modes[1], &et_vid_sw },
{ { NULL, NULL }, NULL, }
};
#define ET_NUMCLOCKS 32
static u_int et_clockfreqs[ET_NUMCLOCKS] = {
6293750, 7080500, 7875000, 8125000,
9000000, 9375000, 10000000, 11225000,
12587500, 14161000, 15750000, 16250000,
18000000, 18750000, 20000000, 22450000,
25175000, 28322000, 31500000, 32500000,
36000000, 37500000, 40000000, 44900000,
50350000, 56644000, 63000000, 65000000,
72000000, 75000000, 80000000, 89800000
};
static bmap_t con_bm; /* XXX */
struct grfabs_et_priv {
pcitag_t pci_tag;
volatile caddr_t regkva;
volatile caddr_t memkva;
u_int linbase;
int regsz;
int memsz;
int board_type;
} et_priv;
/*
* Board types:
*/
#define BT_ET4000 1
#define BT_ET6000 2
/*
* XXX: called from ite console init routine.
* Initialize list of posible video modes.
*/
void
et_probe_video(modelp)
MODES *modelp;
{
dmode_t *dm;
int i;
for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
LIST_INSERT_HEAD(modelp, dm, link);
}
}
static void
et_display_view(v)
view_t *v;
{
dmode_t *dm = v->mode;
bmap_t *bm = v->bitmap;
int sv_size;
u_short *src, *dst;
save_area_t *sa;
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 ((sa = (save_area_t*)v->save_area) == NULL)
return; /* XXX: Can't happen.... */
/*
* Restore register settings and turn the plane pointer
* to the card-memory
*/
et_hwrest(&sa->sv_regs);
bm->plane = et_priv.memkva;
et_use_colormap(v, v->colormap);
/*
* Copy the backing store to card-memory
*/
sv_size = sa->fb_size;
src = sa->sv_fb;
dst = (u_short *)bm->plane;
while (sv_size--)
*dst++ = *src++;
}
void
et_remove_view(v)
view_t *v;
{
dmode_t *mode = v->mode;
if (mode->current_view == v) {
#if 0
if (v->flags & VF_DISPLAY)
panic("Cannot shutdown display\n"); /* XXX */
#endif
mode->current_view = NULL;
}
v->flags &= ~VF_DISPLAY;
}
void
et_save_view(v)
view_t *v;
{
bmap_t *bm = v->bitmap;
u_char font_height;
int sv_size;
u_short *src, *dst;
save_area_t *sa;
if (!atari_realconfig)
return;
if (RGfx(et_priv.regkva, 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(et_priv.regkva, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
sv_size = min(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(v)
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(v, cm)
view_t *v;
colormap_t *cm;
{
return (0); /* XXX: Nothing here for now... */
}
static view_t *
et_alloc_view(mode, dim, depth)
dmode_t *mode;
dimen_t *dim;
u_char depth;
{
view_t *v;
bmap_t *bm;
box_t box;
save_area_t *sa;
if (!atari_realconfig) {
v = &gra_con_view;
bm = &con_bm;
}
else {
v = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK);
}
v->bitmap = bm;
/*
* Initialize the bitmap
*/
bm->plane = et_priv.memkva;
bm->vga_address = (caddr_t)kvtop(et_priv.memkva);
bm->vga_base = VGA_BASE;
bm->hw_address = (caddr_t)(PCI_MEM_PHYS | et_priv.linbase);
bm->lin_base = et_priv.linbase;
bm->regs = et_priv.regkva;
bm->hw_regs = (caddr_t)kvtop(et_priv.regkva);
bm->reg_size = REG_MAPPABLE;
bm->phys_mappable = FRAME_MAPPABLE;
bm->vga_mappable = VGA_MAPPABLE;
bm->bytes_per_row = (mode->size.width * depth) / NBBY;
bm->rows = mode->size.height;
bm->depth = depth;
/*
* 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);
}
static void
init_view(v, bm, mode, dbox)
view_t *v;
bmap_t *bm;
dmode_t *mode;
box_t *dbox;
{
v->bitmap = bm;
v->mode = mode;
v->flags = 0;
bcopy(dbox, &v->display, sizeof(box_t));
}
/* XXX: No more than a stub... */
static colormap_t *
alloc_colormap(dm)
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()
{
pci_chipset_tag_t pc = NULL; /* XXX */
pcitag_t tag, csr;
int device, found, id, maxndevs;
found = 0;
tag = 0;
id = 0;
maxndevs = pci_bus_maxdevs(pc, 0);
for (device = 0; !found && (device < maxndevs); device++) {
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);
if (PCI_PRODUCT(id) == PCI_PRODUCT_TSENG_ET6000)
et_priv.board_type = BT_ET6000;
else et_priv.board_type = BT_ET4000;
/* Turn on the card */
pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
if (et_priv.board_type == BT_ET6000)
pci_conf_write(pc, tag, PCI_MAPREG_START+4,
PCI_IOBASE | PCI_MAPREG_TYPE_IO);
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
csr |= PCI_COMMAND_MASTER_ENABLE;
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
et_priv.pci_tag = tag;
/*
* The things below are setup in atari_init.c
*/
et_priv.regkva = (volatile caddr_t)pci_io_addr;
et_priv.memkva = (volatile caddr_t)pci_mem_addr;
et_priv.linbase = PCI_LINMEMBASE;
et_priv.memsz = PCI_VGA_SIZE;
et_priv.regsz = PCI_IO_SIZE;
if (found && !atari_realconfig) {
et_boardinit();
et_loadmode(&hw_modes[0], NULL);
return (1);
}
return (1);
}
static void
et_loadmode(mode, regs)
struct grfvideo_mode *mode;
et_sv_reg_t *regs;
{
unsigned short HDE, VDE;
int lace, dblscan;
int uplim, lowlim;
int i;
unsigned char clock, tmp;
volatile u_char *ba;
et_sv_reg_t loc_regs;
if (regs == NULL)
regs = &loc_regs;
ba = et_priv.regkva;
HDE = mode->disp_width / 8 - 1;
VDE = mode->disp_height - 1;
/* figure out whether lace or dblscan is needed */
uplim = mode->disp_height + (mode->disp_height / 4);
lowlim = mode->disp_height - (mode->disp_height / 4);
lace = (((mode->vtotal * 2) > lowlim)
&& ((mode->vtotal * 2) < uplim)) ? 1 : 0;
dblscan = (((mode->vtotal / 2) > lowlim)
&& ((mode->vtotal / 2) < uplim)) ? 1 : 0;
/* adjustments */
if (lace)
VDE /= 2;
regs->misc_output = 0x23; /* Page 0, Color mode */
regs->seg_sel = 0x00;
regs->state_ctl = 0x00;
regs->seq[SEQ_ID_RESET] = 0x03; /* reset off */
regs->seq[SEQ_ID_CLOCKING_MODE] = 0x21; /* Turn off screen */
regs->seq[SEQ_ID_MAP_MASK] = 0xff; /* Cpu writes all planes*/
regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0 */
regs->seq[SEQ_ID_MEMORY_MODE] = 0x0e; /* Seq. Memory mode */
/*
* Set the clock...
*/
for(clock = ET_NUMCLOCKS-1; clock > 0; clock--) {
if (et_clockfreqs[clock] <= mode->pixel_clock)
break;
}
regs->misc_output |= (clock & 3) << 2;
regs->aux_mode = 0xb4 | ((clock & 8) << 3);
regs->compat_6845 = (clock & 4) ? 0x0a : 0x08;
/*
* The display parameters...
*/
regs->crt[CRT_ID_HOR_TOTAL] = mode->htotal;
regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start)
? mode->hblank_stop - 1
: HDE);
regs->crt[CRT_ID_START_HOR_BLANK] = mode->hblank_start;
regs->crt[CRT_ID_END_HOR_BLANK] = (mode->hblank_stop & 0x1f) | 0x80;
regs->crt[CRT_ID_START_HOR_RETR] = mode->hsync_start;
regs->crt[CRT_ID_END_HOR_RETR] = (mode->hsync_stop & 0x1f)
| ((mode->hblank_stop & 0x20)
? 0x80 : 0x00);
regs->crt[CRT_ID_VER_TOTAL] = mode->vtotal;
regs->crt[CRT_ID_START_VER_RETR] = mode->vsync_start;
regs->crt[CRT_ID_END_VER_RETR] = (mode->vsync_stop & 0x0f) | 0x30;
regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE;
regs->crt[CRT_ID_START_VER_BLANK] = mode->vblank_start;
regs->crt[CRT_ID_END_VER_BLANK] = mode->vblank_stop;
regs->crt[CRT_ID_MODE_CONTROL] = 0xab;
regs->crt[CRT_ID_START_ADDR_HIGH] = 0x00;
regs->crt[CRT_ID_START_ADDR_LOW] = 0x00;
regs->crt[CRT_ID_LINE_COMPARE] = 0xff;
regs->crt[CRT_ID_UNDERLINE_LOC] = 0x00;
regs->crt[CRT_ID_OFFSET] = mode->disp_width/16;
regs->crt[CRT_ID_MAX_ROW_ADDRESS] =
0x40 |
(dblscan ? 0x80 : 0x00) |
((mode->vblank_start & 0x200) ? 0x20 : 0x00);
regs->crt[CRT_ID_OVERFLOW] =
0x10 |
((mode->vtotal & 0x100) ? 0x01 : 0x00) |
((VDE & 0x100) ? 0x02 : 0x00) |
((mode->vsync_start & 0x100) ? 0x04 : 0x00) |
((mode->vblank_start & 0x100) ? 0x08 : 0x00) |
((mode->vtotal & 0x200) ? 0x20 : 0x00) |
((VDE & 0x200) ? 0x40 : 0x00) |
((mode->vsync_start & 0x200) ? 0x80 : 0x00);
regs->overfl_high =
0x10 |
((mode->vblank_start & 0x400) ? 0x01 : 0x00) |
((mode->vtotal & 0x400) ? 0x02 : 0x00) |
((VDE & 0x400) ? 0x04 : 0x00) |
((mode->vsync_start & 0x400) ? 0x08 : 0x00) |
(lace ? 0x80 : 0x00);
regs->hor_overfl =
((mode->htotal & 0x100) ? 0x01 : 0x00) |
((mode->hblank_start & 0x100) ? 0x04 : 0x00) |
((mode->hsync_start & 0x100) ? 0x10 : 0x00);
regs->grf[GCT_ID_SET_RESET] = 0x00;
regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00;
regs->grf[GCT_ID_COLOR_COMPARE] = 0x00;
regs->grf[GCT_ID_DATA_ROTATE] = 0x00;
regs->grf[GCT_ID_READ_MAP_SELECT] = 0x00;
regs->grf[GCT_ID_GRAPHICS_MODE] = mode->depth == 1 ? 0x00: 0x40;
regs->grf[GCT_ID_MISC] = 0x01;
regs->grf[GCT_ID_COLOR_XCARE] = 0x0f;
regs->grf[GCT_ID_BITMASK] = 0xff;
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);
}
static void
et_boardinit()
{
volatile u_char *ba;
int i, j;
ba = et_priv.regkva;
vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
WSeq(ba, SEQ_ID_RESET, 0x03);
WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
WCrt(ba, CRT_ID_CURSOR_START, 0x00);
WCrt(ba, CRT_ID_CURSOR_END, 0x08);
WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3);
WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
/*
* ET4000 special
*/
WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
WCrt(ba, CTR_ID_EXT_START, 0x00);
WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
if (et_priv.board_type == BT_ET6000)
et6000_init();
else {
WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x43);
WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x09);
}
WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
WGfx(ba, GCT_ID_SET_RESET, 0x00);
WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
WGfx(ba, GCT_ID_MISC, 0x05);
WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
WGfx(ba, GCT_ID_BITMASK, 0xff);
vgaw(ba, GREG_SEGMENTSELECT, 0x00);
for (i = 0; i < 0x10; i++)
WAttr(ba, i, i);
WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
vgaw(ba, VDAC_MASK, 0xff);
#if 0 /* XXX: We like to do this: */
delay(200000);
#else /* But because we run before the delay is initialized: */
for(i = 0; i < 4000; i++)
for(j = 0; j < 400; j++);
#endif
/*
* colors initially set to greyscale
*/
vgaw(ba, VDAC_ADDRESS_W, 0);
for (i = 255; i >= 0; i--) {
vgaw(ba, VDAC_DATA, i);
vgaw(ba, VDAC_DATA, i);
vgaw(ba, VDAC_DATA, i);
}
}
/*
* Initialize the et6000 specific (PCI) registers. Try to do it like the
* video-bios would have done it, so things like Xservers get what they
* expect. Most info was kindly provided by Koen Gadeyne.
*
* XXX: not fit for programming beauty contest...
*/
static void
et6000_init()
{
volatile u_char *ba;
int i;
u_char dac_tab[] = { 0x7d,0x67, 0x5d,0x64, 0x56,0x63,
0x28,0x22, 0x79,0x49, 0x6f,0x47,
0x28,0x41, 0x6b,0x44, 0xfe,0xff,
0x00,0x00, 0x3d,0x23, 0x79,0x2e,
0xa8,0x00, 0x00,0x84 };
ba = et_priv.regkva + PCI_IOBASE;
ba[0x40] = 0x00; /* Use standard vga addressing */
ba[0x41] = 0x2a; /* Performance control */
ba[0x43] = 0x02; /* XCLK/SCLK config */
ba[0x44] = 0x11; /* RAS/CAS config */
ba[0x46] = 0x00; /* CRT display feature */
ba[0x58] = 0x00; /* Video Control 1 */
ba[0x59] = 0x04; /* Video Control 2 */
/*
* Setup a 'standard' CLKDAC
*/
ba[0x42] = 0x00; /* MCLK == CLK0 */
ba[0x67] = 0x00; /* Start filling from dac-reg 0 and up... */
for (i = 0; i < 0x0b; i++)
ba[0x69] = dac_tab[i];
}
void
et_hwsave(et_regs)
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);
/*
* ET4000 extensions
*/
et_regs->ext_start = RCrt(ba, CTR_ID_EXT_START);
et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
et_regs->hor_overfl = RCrt(ba, CRT_ID_HOR_OVERFLOW);
et_regs->state_ctl = RSeq(ba, SEQ_ID_STATE_CONTROL);
et_regs->aux_mode = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
et_regs->seg_sel = vgar(ba, GREG_SEGMENTSELECT);
s = splx(s);
}
void
et_hwrest(et_regs)
et_sv_reg_t *et_regs;
{
volatile u_char *ba;
int i, s;
ba = et_priv.regkva;
s = splhigh();
vgaw(ba, GREG_SEGMENTSELECT, 0);
vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
/*
* General VGA registers
*/
for(i = 0; i < 5; i++)
WSeq(ba, i, et_regs->seq[i]);
/*
* 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]);
/*
* ET4000 extensions
*/
WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
s = splx(s);
}