1839 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1839 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Id: s3.c,v 1.3 1999/11/02 08:17:24 keithp Exp $
 | 
						|
 *
 | 
						|
 * Copyright 1999 SuSE, Inc.
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of SuSE not be used in advertising or
 | 
						|
 * publicity pertaining to distribution of the software without specific,
 | 
						|
 * written prior permission.  SuSE makes no representations about the
 | 
						|
 * suitability of this software for any purpose.  It is provided "as is"
 | 
						|
 * without express or implied warranty.
 | 
						|
 *
 | 
						|
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 | 
						|
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 | 
						|
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 | 
						|
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
 | 
						|
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 *
 | 
						|
 * Author:  Keith Packard, SuSE, Inc.
 | 
						|
 */
 | 
						|
/* $RCSId: xc/programs/Xserver/hw/kdrive/savage/s3.c,v 1.4 2000/05/06 22:17:44 keithp Exp $ */
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <config.h>
 | 
						|
#endif
 | 
						|
#include "s3.h"
 | 
						|
 | 
						|
#define REGISTERS_OFFSET    (0x1000000)
 | 
						|
#define PACKED_OFFSET	    (0x8100)
 | 
						|
#define IOMAP_OFFSET	    (0x8000)
 | 
						|
 | 
						|
#define S3_MIN_CLOCK	    250000
 | 
						|
 | 
						|
static void
 | 
						|
_s3SetBlank (S3Ptr s3, S3Vga *s3vga, Bool blank)
 | 
						|
{
 | 
						|
    CARD8   clock_mode;
 | 
						|
    
 | 
						|
    s3SetImm(s3vga, s3_screen_off, blank ? 1 : 0);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3CardInit (KdCardInfo *card)
 | 
						|
{
 | 
						|
    S3CardInfo	*s3c;
 | 
						|
    S3Ptr	s3;
 | 
						|
    S3Vga	*s3vga;
 | 
						|
    int		size;
 | 
						|
    CARD8	*registers;
 | 
						|
    CARD32	s3FrameBuffer;
 | 
						|
    CARD32	s3Registers;
 | 
						|
    CARD8	*temp_buffer;
 | 
						|
    CARD32	max_memory;
 | 
						|
    VGA32	save_linear_window_size;
 | 
						|
    VGA32	save_enable_linear;
 | 
						|
    VGA32	save_register_lock_2;
 | 
						|
    VGA32	save_misc_output;
 | 
						|
 | 
						|
    s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo));
 | 
						|
    if (!s3c)
 | 
						|
    {
 | 
						|
	goto bail0;
 | 
						|
    }
 | 
						|
    
 | 
						|
    memset (s3c, '\0', sizeof (S3CardInfo));
 | 
						|
    
 | 
						|
    card->driver = s3c;
 | 
						|
    
 | 
						|
#ifdef VXWORKS
 | 
						|
    s3c->bios_initialized = 0;
 | 
						|
#else
 | 
						|
    s3c->bios_initialized = 1;
 | 
						|
#endif
 | 
						|
    
 | 
						|
    if (card->attr.naddr > 1 && card->attr.address[1])
 | 
						|
    {
 | 
						|
	s3FrameBuffer = card->attr.address[1];
 | 
						|
	s3Registers = card->attr.address[0];
 | 
						|
	max_memory = 32 * 1024 * 1024;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	s3FrameBuffer = card->attr.address[0];
 | 
						|
	s3Registers = s3FrameBuffer + REGISTERS_OFFSET;
 | 
						|
	max_memory = 16 * 1024 * 1024;
 | 
						|
    }
 | 
						|
	
 | 
						|
#ifdef DEBUG
 | 
						|
    fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer);
 | 
						|
#endif
 | 
						|
    registers = KdMapDevice (s3Registers,
 | 
						|
			     sizeof (S3) + PACKED_OFFSET);
 | 
						|
    if (!registers)
 | 
						|
    {
 | 
						|
	ErrorF ("Can't map s3 device\n");
 | 
						|
	goto bail2;
 | 
						|
    }
 | 
						|
    s3 = (S3Ptr) (registers + PACKED_OFFSET);
 | 
						|
    s3c->registers = registers;
 | 
						|
    s3c->s3 = s3;
 | 
						|
    
 | 
						|
    s3vga = &s3c->s3vga;
 | 
						|
    s3RegInit (s3vga, (VGAVOL8 *) (registers + IOMAP_OFFSET));
 | 
						|
    
 | 
						|
    if (!s3c->bios_initialized)
 | 
						|
    {
 | 
						|
	volatile CARD32	*wakeup;
 | 
						|
 | 
						|
	wakeup = (volatile CARD32 *) (registers + 0x8510);
 | 
						|
	ErrorF ("Wakeup S3 chip at 0x%x\n", wakeup);
 | 
						|
	ErrorF ("Wakeup was 0x%x\n", *wakeup);
 | 
						|
	/* wakeup the chip */
 | 
						|
	*(volatile CARD32 *) (registers + 0x8510) = 1;
 | 
						|
	ErrorF ("Wakeup is 0x%x\n", *wakeup);
 | 
						|
    }
 | 
						|
    s3Set (s3vga, s3_io_addr_select, 1);
 | 
						|
    s3Set (s3vga, s3_enable_ram, 1);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
    
 | 
						|
    save_register_lock_2 = s3Get (s3vga, s3_register_lock_2);
 | 
						|
    s3SetImm (s3vga, s3_register_lock_2, 0xa0);
 | 
						|
    save_linear_window_size = s3Get (s3vga, s3_linear_window_size);
 | 
						|
    save_enable_linear = s3Get (s3vga, s3_enable_linear);
 | 
						|
    s3Set (s3vga, s3_linear_window_size, 3);
 | 
						|
    s3Set (s3vga, s3_enable_linear, 1);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
    VgaFinish (&s3vga->card);
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Can't trust S3 register value for frame buffer amount, must compute
 | 
						|
     */
 | 
						|
    temp_buffer = KdMapDevice (s3FrameBuffer, max_memory);
 | 
						|
    
 | 
						|
    s3c->memory = KdFrameBufferSize (temp_buffer, max_memory);
 | 
						|
 | 
						|
    s3Set (s3vga, s3_linear_window_size, save_linear_window_size);
 | 
						|
    s3Set (s3vga, s3_enable_linear, save_enable_linear);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
    s3SetImm (s3vga, s3_register_lock_2, save_register_lock_2);
 | 
						|
    VgaFinish (&s3vga->card);
 | 
						|
#ifdef DEBUG
 | 
						|
    fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory);
 | 
						|
#endif
 | 
						|
    KdUnmapDevice (temp_buffer, max_memory);
 | 
						|
    
 | 
						|
    if (!s3c->memory)
 | 
						|
    {
 | 
						|
	ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer);
 | 
						|
	goto bail3;
 | 
						|
    }
 | 
						|
    
 | 
						|
    s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory);
 | 
						|
    if (!s3c->frameBuffer)
 | 
						|
    {
 | 
						|
	ErrorF ("Can't map s3 frame buffer\n");
 | 
						|
	goto bail3;
 | 
						|
    }
 | 
						|
 | 
						|
    card->driver = s3c;
 | 
						|
    
 | 
						|
    return TRUE;
 | 
						|
bail3:
 | 
						|
    KdUnmapDevice ((void *) s3, sizeof (S3));
 | 
						|
bail2:
 | 
						|
bail1:
 | 
						|
    xfree (s3c);
 | 
						|
bail0:
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3ModeSupported (KdScreenInfo		*screen,
 | 
						|
		 const KdMonitorTiming	*t)
 | 
						|
{
 | 
						|
    if (screen->fb[1].depth)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * Must have at least one true color stream
 | 
						|
	 */
 | 
						|
	if (screen->fb[0].depth <= 8 &&
 | 
						|
	    screen->fb[1].depth <= 8)
 | 
						|
	    return FALSE;
 | 
						|
    }
 | 
						|
    /* make sure the clock isn't too fast */
 | 
						|
    if (t->clock > S3_MAX_CLOCK * 2)
 | 
						|
	return FALSE;
 | 
						|
    /* width must be a multiple of 16 */
 | 
						|
    if (t->horizontal & 0xf)
 | 
						|
	return FALSE;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3ModeUsable (KdScreenInfo	*screen)
 | 
						|
{
 | 
						|
    KdCardInfo	    *card = screen->card;
 | 
						|
    S3CardInfo	    *s3c = (S3CardInfo *) card->driver;
 | 
						|
    int		    screen_size;
 | 
						|
    int		    pixel_width;
 | 
						|
    int		    byte_width;
 | 
						|
    int		    fb;
 | 
						|
    
 | 
						|
    screen_size = 0;
 | 
						|
    for (fb = 0; fb < KD_MAX_FB && screen->fb[fb].depth; fb++)
 | 
						|
    {
 | 
						|
	if (screen->fb[fb].depth >= 24)
 | 
						|
	{
 | 
						|
	    screen->fb[fb].depth = 24;
 | 
						|
	    if (screen->fb[fb].bitsPerPixel != 24)
 | 
						|
		screen->fb[fb].bitsPerPixel = 32;
 | 
						|
	}
 | 
						|
	else if (screen->fb[fb].depth >= 16)
 | 
						|
	{
 | 
						|
	    screen->fb[fb].depth = 16;
 | 
						|
	    screen->fb[fb].bitsPerPixel = 16;
 | 
						|
	}
 | 
						|
	else if (screen->fb[fb].depth >= 15)
 | 
						|
	{
 | 
						|
	    screen->fb[fb].depth = 15;
 | 
						|
	    screen->fb[fb].bitsPerPixel = 16;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    screen->fb[fb].depth = 8;
 | 
						|
	    screen->fb[fb].bitsPerPixel = 8;
 | 
						|
	}
 | 
						|
    
 | 
						|
        /*
 | 
						|
         * SGRAM requires stride % 64 == 0
 | 
						|
         */
 | 
						|
        screen->fb[fb].pixelStride = (screen->width + 63) & ~63;
 | 
						|
        screen->fb[fb].byteStride = screen->fb[fb].pixelStride * (screen->fb[fb].bitsPerPixel >> 3);
 | 
						|
        screen_size += screen->fb[fb].byteStride * screen->height;
 | 
						|
    }
 | 
						|
 | 
						|
    return screen_size <= s3c->memory;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3ScreenInit (KdScreenInfo *screen)
 | 
						|
{
 | 
						|
    KdCardInfo	    *card = screen->card;
 | 
						|
    S3CardInfo	    *s3c = (S3CardInfo *) card->driver;
 | 
						|
    S3ScreenInfo    *s3s;
 | 
						|
    int		    memory;
 | 
						|
    int		    requested_memory;
 | 
						|
    int		    v_total, h_total;
 | 
						|
    int		    m, n, r;
 | 
						|
    int		    i;
 | 
						|
    const KdMonitorTiming *t;
 | 
						|
    int		    screen_size;
 | 
						|
    int		    fb;
 | 
						|
    int		    ma;
 | 
						|
 | 
						|
    s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo));
 | 
						|
    if (!s3s)
 | 
						|
	return FALSE;
 | 
						|
 | 
						|
    memset (s3s, '\0', sizeof (S3ScreenInfo));
 | 
						|
 | 
						|
#ifdef PHOENIX
 | 
						|
    screen->width = 1152;
 | 
						|
    screen->height = 900;
 | 
						|
    screen->rate = 85;
 | 
						|
    screen->depth = 32;
 | 
						|
#endif
 | 
						|
    if (!screen->width || !screen->height)
 | 
						|
    {
 | 
						|
	screen->width = 800;
 | 
						|
	screen->height = 600;
 | 
						|
	screen->rate = 72;
 | 
						|
    }
 | 
						|
    if (!screen->fb[0].depth)
 | 
						|
	screen->fb[0].depth = 8;
 | 
						|
    
 | 
						|
    t = KdFindMode (screen, s3ModeSupported);
 | 
						|
    screen->rate = t->rate;
 | 
						|
    screen->width = t->horizontal;
 | 
						|
    screen->height = t->vertical;
 | 
						|
    s3GetClock (t->clock, &m, &n, &r, 511, 127, 4, 250000);
 | 
						|
#ifdef DEBUG
 | 
						|
    fprintf (stderr, "computed %d,%d,%d (%d)\n",
 | 
						|
	     m, n, r, S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
#if 0
 | 
						|
    /*
 | 
						|
     * Can only operate in pixel-doubled mode at 8 or 16 bits per pixel
 | 
						|
     */
 | 
						|
    if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
 | 
						|
	screen->depth = 16;
 | 
						|
#endif
 | 
						|
    
 | 
						|
    if (!KdTuneMode (screen, s3ModeUsable, s3ModeSupported))
 | 
						|
    {
 | 
						|
	xfree (s3s);
 | 
						|
	return FALSE;
 | 
						|
    }
 | 
						|
    
 | 
						|
    s3s->fbmap[2] = -1;
 | 
						|
    if (screen->fb[1].depth)
 | 
						|
    {
 | 
						|
	if (screen->fb[0].bitsPerPixel >= 16)
 | 
						|
	{
 | 
						|
	    s3s->fbmap[0] = 1;
 | 
						|
	    s3s->fbmap[1] = 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    s3s->fbmap[0] = 0;
 | 
						|
	    s3s->fbmap[1] = 1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	s3s->fbmap[0] = 0;
 | 
						|
	s3s->fbmap[1] = -1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    screen_size = 0;
 | 
						|
    for (fb = 0; fb < KD_MAX_FB && screen->fb[fb].depth; fb++)
 | 
						|
	screen_size += screen->fb[fb].byteStride * screen->height;
 | 
						|
    
 | 
						|
    memory = s3c->memory - screen_size;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Stick cursor at end of memory
 | 
						|
     */
 | 
						|
    if (memory >= 2048)
 | 
						|
    {
 | 
						|
	s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048);
 | 
						|
	memory -= 2048;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	s3s->cursor_base = 0;
 | 
						|
 | 
						|
    screen_size = 0;
 | 
						|
    for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | 
						|
    {
 | 
						|
	fb = s3s->fbmap[ma];
 | 
						|
	screen->fb[fb].frameBuffer = s3c->frameBuffer + screen_size;
 | 
						|
	screen_size += screen->fb[fb].byteStride * screen->height;
 | 
						|
	
 | 
						|
	REGION_INIT(pScreen, (&s3s->region[fb]), NullBox, 0);
 | 
						|
	if (screen->fb[fb].bitsPerPixel == 8)
 | 
						|
	    s3s->fb[ma].chroma_key = 0xff;
 | 
						|
	else
 | 
						|
	    s3s->fb[ma].chroma_key = 0;
 | 
						|
	
 | 
						|
	/*
 | 
						|
	 * Use remaining memory for off-screen storage, but only use
 | 
						|
	 * one piece (either right or bottom).
 | 
						|
	 */
 | 
						|
	if (memory >= screen->fb[fb].byteStride * S3_TILE_SIZE)
 | 
						|
	{
 | 
						|
	    s3s->fb[ma].offscreen = screen->fb[fb].frameBuffer;
 | 
						|
	    s3s->fb[ma].offscreen_x = 0;
 | 
						|
	    s3s->fb[ma].offscreen_y = screen->height;
 | 
						|
	    s3s->fb[ma].offscreen_width = screen->fb[fb].pixelStride;
 | 
						|
	    s3s->fb[ma].offscreen_height = S3_TILE_SIZE;
 | 
						|
	    memory -= s3s->fb[ma].offscreen_height * screen->fb[fb].byteStride;
 | 
						|
	    screen_size += s3s->fb[ma].offscreen_height * screen->fb[fb].byteStride;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    s3s->fb[ma].offscreen = 0;
 | 
						|
    
 | 
						|
	switch (screen->fb[fb].depth) {
 | 
						|
	case 8:
 | 
						|
	    screen->fb[fb].visuals = ((1 << StaticGray) |
 | 
						|
				      (1 << GrayScale) |
 | 
						|
				      (1 << StaticColor) |
 | 
						|
				      (1 << PseudoColor) |
 | 
						|
				      (1 << TrueColor) |
 | 
						|
				      (1 << DirectColor));
 | 
						|
	    screen->fb[fb].blueMask  = 0x00;
 | 
						|
	    screen->fb[fb].greenMask = 0x00;
 | 
						|
	    screen->fb[fb].redMask   = 0x00;
 | 
						|
	    break;
 | 
						|
	case 15:
 | 
						|
	    screen->fb[fb].visuals = (1 << TrueColor);
 | 
						|
	    screen->fb[fb].blueMask  = 0x001f;
 | 
						|
	    screen->fb[fb].greenMask = 0x03e0;
 | 
						|
	    screen->fb[fb].redMask   = 0x7c00;
 | 
						|
	    break;
 | 
						|
	case 16:
 | 
						|
	    screen->fb[fb].visuals = (1 << TrueColor);
 | 
						|
	    screen->fb[fb].blueMask  = 0x001f;
 | 
						|
	    screen->fb[fb].greenMask = 0x07e0;
 | 
						|
	    screen->fb[fb].redMask   = 0xf800;
 | 
						|
	    break;
 | 
						|
	case 24:
 | 
						|
	    screen->fb[fb].visuals = (1 << TrueColor);
 | 
						|
	    screen->fb[fb].blueMask  = 0x0000ff;
 | 
						|
	    screen->fb[fb].greenMask = 0x00ff00;
 | 
						|
	    screen->fb[fb].redMask   = 0xff0000;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    
 | 
						|
    screen->driver = s3s;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
typedef struct _biosInit {
 | 
						|
    VGA16   reg;
 | 
						|
    VGA8    value;
 | 
						|
} s3BiosInit;
 | 
						|
 | 
						|
s3BiosInit s3BiosReg[] = {
 | 
						|
    S3_SR +0x15, 0x23,
 | 
						|
    S3_MISC_OUT, 0x2f,
 | 
						|
    0xffff, 1,
 | 
						|
    S3_SR +0x15, 0x03,
 | 
						|
 | 
						|
    S3_SR + 0x0, 0x03,
 | 
						|
    S3_SR + 0x1, 0x00,
 | 
						|
    S3_SR + 0x2, 0x03,
 | 
						|
    S3_SR + 0x3, 0x00,
 | 
						|
    S3_SR + 0x4, 0x02,
 | 
						|
    S3_SR + 0x5, 0x05,
 | 
						|
    S3_SR + 0x6, 0x06,
 | 
						|
    S3_SR + 0x7, 0x07,
 | 
						|
/*    S3_SR + 0x8, 0x06, */
 | 
						|
    S3_SR + 0x9, 0x00,
 | 
						|
    S3_SR + 0xa, 0x0a,
 | 
						|
    S3_SR + 0xb, 0x00,
 | 
						|
    S3_SR + 0xc, 0x0c,
 | 
						|
    S3_SR + 0xd, 0x00,
 | 
						|
    S3_SR + 0xe, 0x0e,
 | 
						|
    S3_SR + 0xf, 0x0f,
 | 
						|
 | 
						|
/*    S3_SR +0x10, 0x00, */
 | 
						|
/*     S3_SR +0x11, 0x0c, */
 | 
						|
    S3_SR +0x12, 0x01,
 | 
						|
    S3_SR +0x13, 0x52,
 | 
						|
    S3_SR +0x14, 0x00,
 | 
						|
    
 | 
						|
/*    S3_SR +0x15, 0x03, */
 | 
						|
    
 | 
						|
    S3_SR +0x16, 0xc5,
 | 
						|
    S3_SR +0x17, 0xfc,
 | 
						|
    S3_SR +0x18, 0x40,
 | 
						|
    S3_SR +0x19, 0x00,
 | 
						|
    S3_SR +0x1a, 0x01,
 | 
						|
    S3_SR +0x1b, 0x02,
 | 
						|
    S3_SR +0x1c, 0x5d,
 | 
						|
    S3_SR +0x1d, 0x00,
 | 
						|
    S3_SR +0x1e, 0x00,
 | 
						|
    S3_SR +0x1f, 0x00,
 | 
						|
    S3_SR +0x20, 0x20,
 | 
						|
    S3_SR +0x21, 0x21,
 | 
						|
    S3_SR +0x22, 0x22,
 | 
						|
    S3_SR +0x23, 0x23,
 | 
						|
    S3_SR +0x24, 0x24,
 | 
						|
    S3_SR +0x25, 0x25,
 | 
						|
    S3_SR +0x26, 0x26,
 | 
						|
    S3_SR +0x27, 0x04,
 | 
						|
    S3_SR +0x28, 0xff,
 | 
						|
    S3_SR +0x29, 0x00,
 | 
						|
    S3_SR +0x2a, 0x2a,
 | 
						|
    S3_SR +0x2b, 0x2b,
 | 
						|
    S3_SR +0x2c, 0x2c,
 | 
						|
    S3_SR +0x2d, 0x2d,
 | 
						|
    S3_SR +0x2e, 0x2e,
 | 
						|
    S3_SR +0x2f, 0x2f,
 | 
						|
    S3_SR +0x30, 0x00,
 | 
						|
    S3_SR +0x31, 0x06,
 | 
						|
    S3_SR +0x32, 0x41,
 | 
						|
    S3_SR +0x33, 0x67,
 | 
						|
    S3_SR +0x34, 0x00,
 | 
						|
    S3_SR +0x35, 0x00,
 | 
						|
    S3_SR +0x36, 0x01,
 | 
						|
    S3_SR +0x37, 0x52,
 | 
						|
    S3_SR +0x38, 0x5d,
 | 
						|
    S3_SR +0x39, 0x05,
 | 
						|
    S3_SR +0x3a, 0x3a,
 | 
						|
    S3_SR +0x3b, 0x3b,
 | 
						|
    S3_SR +0x3c, 0x3c,
 | 
						|
    S3_SR +0x3d, 0x00,
 | 
						|
    S3_SR +0x3e, 0x3e,
 | 
						|
    S3_SR +0x3f, 0x00,
 | 
						|
    S3_SR +0x40, 0x40,
 | 
						|
    S3_SR +0x41, 0x41,
 | 
						|
    S3_SR +0x42, 0x42,
 | 
						|
    S3_SR +0x43, 0x43,
 | 
						|
    S3_SR +0x44, 0x44,
 | 
						|
    S3_SR +0x45, 0x45,
 | 
						|
    S3_SR +0x46, 0x46,
 | 
						|
    S3_SR +0x47, 0x47,
 | 
						|
    S3_SR +0x48, 0x48,
 | 
						|
    S3_SR +0x49, 0x49,
 | 
						|
    S3_SR +0x4a, 0x4a,
 | 
						|
    S3_SR +0x4b, 0x4b,
 | 
						|
    S3_SR +0x4c, 0x4c,
 | 
						|
    S3_SR +0x4d, 0x4d,
 | 
						|
    S3_SR +0x4e, 0x4e,
 | 
						|
    S3_SR +0x4f, 0x4f,
 | 
						|
    S3_SR +0x50, 0x00,
 | 
						|
    S3_SR +0x51, 0x00,
 | 
						|
    S3_SR +0x52, 0x00,
 | 
						|
    S3_SR +0x53, 0x00,
 | 
						|
    S3_SR +0x54, 0x00,
 | 
						|
    S3_SR +0x55, 0x00,
 | 
						|
    S3_SR +0x56, 0x00,
 | 
						|
    S3_SR +0x57, 0x00,
 | 
						|
    S3_SR +0x58, 0x00,
 | 
						|
    S3_SR +0x59, 0x70,
 | 
						|
    S3_SR +0x5a, 0x38,
 | 
						|
    S3_SR +0x5b, 0x08,
 | 
						|
    S3_SR +0x5c, 0x77,
 | 
						|
    S3_SR +0x5d, 0x77,
 | 
						|
    S3_SR +0x5e, 0x00,
 | 
						|
    S3_SR +0x5f, 0x00,
 | 
						|
    S3_SR +0x60, 0xff,
 | 
						|
    S3_SR +0x61, 0xbf,
 | 
						|
    S3_SR +0x62, 0xff,
 | 
						|
    S3_SR +0x63, 0xff,
 | 
						|
    S3_SR +0x64, 0xf7,
 | 
						|
    S3_SR +0x65, 0xff,
 | 
						|
    S3_SR +0x66, 0xff,
 | 
						|
    S3_SR +0x67, 0xff,
 | 
						|
    S3_SR +0x68, 0xff,
 | 
						|
    S3_SR +0x69, 0xff,
 | 
						|
    S3_SR +0x6a, 0xff,
 | 
						|
    S3_SR +0x6b, 0xff,
 | 
						|
    S3_SR +0x6c, 0xff,
 | 
						|
    S3_SR +0x6d, 0xff,
 | 
						|
    S3_SR +0x6e, 0x9b,
 | 
						|
    S3_SR +0x6f, 0xbf,
 | 
						|
 | 
						|
    S3_AR + 0x00, 0x00,
 | 
						|
    S3_AR + 0x01, 0x01,
 | 
						|
    S3_AR + 0x02, 0x02,
 | 
						|
    S3_AR + 0x03, 0x03,
 | 
						|
    S3_AR + 0x04, 0x04,
 | 
						|
    S3_AR + 0x05, 0x05,
 | 
						|
    S3_AR + 0x06, 0x06,
 | 
						|
    S3_AR + 0x07, 0x07,
 | 
						|
    S3_AR + 0x08, 0x08,
 | 
						|
    S3_AR + 0x09, 0x09,
 | 
						|
    S3_AR + 0x0a, 0x0a,
 | 
						|
    S3_AR + 0x0b, 0x0b,
 | 
						|
    S3_AR + 0x0c, 0x0c,
 | 
						|
    S3_AR + 0x0d, 0x0d,
 | 
						|
    S3_AR + 0x0e, 0x0e,
 | 
						|
    S3_AR + 0x0f, 0x0f,
 | 
						|
    S3_AR + 0x10, 0x05,
 | 
						|
    S3_AR + 0x11, 0x00,
 | 
						|
    S3_AR + 0x12, 0x0f,
 | 
						|
    S3_AR + 0x13, 0x08,
 | 
						|
    S3_AR + 0x14, 0x00,
 | 
						|
    
 | 
						|
    S3_GR + 0x00, 0x00,
 | 
						|
    S3_GR + 0x01, 0x00,
 | 
						|
    S3_GR + 0x02, 0x00,
 | 
						|
    S3_GR + 0x03, 0x00,
 | 
						|
    S3_GR + 0x04, 0x00,
 | 
						|
    S3_GR + 0x05, 0x10,
 | 
						|
    S3_GR + 0x06, 0x0e,
 | 
						|
    S3_GR + 0x07, 0x00,
 | 
						|
 | 
						|
    S3_CR + 0x00, 0x5f,
 | 
						|
    S3_CR + 0x01, 0x4f,
 | 
						|
    S3_CR + 0x02, 0x50,
 | 
						|
    S3_CR + 0x03, 0x82,
 | 
						|
    S3_CR + 0x04, 0x55,
 | 
						|
    S3_CR + 0x05, 0x81,
 | 
						|
    S3_CR + 0x06, 0xbf,
 | 
						|
    S3_CR + 0x07, 0x1f,
 | 
						|
    S3_CR + 0x08, 0x00,
 | 
						|
    S3_CR + 0x09, 0x4f,
 | 
						|
    S3_CR + 0x0a, 0x0d,
 | 
						|
    S3_CR + 0x0b, 0x0e,
 | 
						|
    S3_CR + 0x0c, 0x00,
 | 
						|
    S3_CR + 0x0d, 0x00,
 | 
						|
    S3_CR + 0x0e, 0x3f,
 | 
						|
    S3_CR + 0x0f, 0xff,
 | 
						|
    S3_CR + 0x10, 0x9c,
 | 
						|
    S3_CR + 0x11, 0x0e,
 | 
						|
    S3_CR + 0x12, 0x8f,
 | 
						|
    S3_CR + 0x13, 0x28,
 | 
						|
    S3_CR + 0x14, 0x1f,
 | 
						|
    S3_CR + 0x15, 0x96,
 | 
						|
    S3_CR + 0x16, 0xb9,
 | 
						|
    S3_CR + 0x17, 0xa3,
 | 
						|
    S3_CR + 0x18, 0xff,
 | 
						|
    S3_CR + 0x19, 0xdf,
 | 
						|
    S3_CR + 0x1a, 0xdf,
 | 
						|
    S3_CR + 0x1b, 0xdf,
 | 
						|
    S3_CR + 0x1c, 0xdf,
 | 
						|
    S3_CR + 0x1d, 0xdf,
 | 
						|
    S3_CR + 0x1e, 0xdf,
 | 
						|
    S3_CR + 0x1f, 0xdf,
 | 
						|
    S3_CR + 0x20, 0xdf,
 | 
						|
    S3_CR + 0x21, 0x00,
 | 
						|
/*    S3_CR + 0x22, 0x07, */
 | 
						|
    S3_CR + 0x23, 0x00,
 | 
						|
    S3_CR + 0x24, 0xdf,
 | 
						|
    S3_CR + 0x25, 0xdf,
 | 
						|
    S3_CR + 0x26, 0x00,
 | 
						|
    S3_CR + 0x27, 0xdf,
 | 
						|
    S3_CR + 0x28, 0xdf,
 | 
						|
    S3_CR + 0x29, 0xdf,
 | 
						|
    S3_CR + 0x2a, 0xdf,
 | 
						|
    S3_CR + 0x2b, 0xdf,
 | 
						|
    S3_CR + 0x2c, 0xdf,
 | 
						|
    S3_CR + 0x2d, 0x8a,
 | 
						|
    S3_CR + 0x2e, 0x22,
 | 
						|
    S3_CR + 0x2f, 0x02,
 | 
						|
    S3_CR + 0x30, 0xe1,
 | 
						|
    S3_CR + 0x31, 0x05,
 | 
						|
    S3_CR + 0x32, 0x40,
 | 
						|
    S3_CR + 0x33, 0x08,
 | 
						|
    S3_CR + 0x34, 0x00,
 | 
						|
    S3_CR + 0x35, 0x00,
 | 
						|
    S3_CR + 0x36, 0xbf,
 | 
						|
    S3_CR + 0x37, 0x9b,
 | 
						|
/*    S3_CR + 0x38, 0x7b, */
 | 
						|
/*    S3_CR + 0x39, 0xb8, */
 | 
						|
    S3_CR + 0x3a, 0x45,
 | 
						|
    S3_CR + 0x3b, 0x5a,
 | 
						|
    S3_CR + 0x3c, 0x10,
 | 
						|
    S3_CR + 0x3d, 0x00,
 | 
						|
    S3_CR + 0x3e, 0xfd,
 | 
						|
    S3_CR + 0x3f, 0x00,
 | 
						|
    S3_CR + 0x40, 0x00,
 | 
						|
    S3_CR + 0x41, 0x92,
 | 
						|
    S3_CR + 0x42, 0xc0,
 | 
						|
    S3_CR + 0x43, 0x68,
 | 
						|
    S3_CR + 0x44, 0xff,
 | 
						|
    S3_CR + 0x45, 0xe8,
 | 
						|
    S3_CR + 0x46, 0xff,
 | 
						|
    S3_CR + 0x47, 0xff,
 | 
						|
    S3_CR + 0x48, 0xf8,
 | 
						|
    S3_CR + 0x49, 0xff,
 | 
						|
    S3_CR + 0x4a, 0xfe,
 | 
						|
    S3_CR + 0x4b, 0xff,
 | 
						|
    S3_CR + 0x4c, 0xff,
 | 
						|
    S3_CR + 0x4d, 0xff,
 | 
						|
    S3_CR + 0x4e, 0xff,
 | 
						|
    S3_CR + 0x4f, 0xff,
 | 
						|
    S3_CR + 0x50, 0x00,
 | 
						|
    S3_CR + 0x51, 0x00,
 | 
						|
    S3_CR + 0x52, 0x00,
 | 
						|
    S3_CR + 0x53, 0x00,
 | 
						|
    S3_CR + 0x54, 0x00,
 | 
						|
    S3_CR + 0x55, 0x00,
 | 
						|
    S3_CR + 0x56, 0x00,
 | 
						|
    S3_CR + 0x57, 0x00,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0x58, 0x00,
 | 
						|
    S3_CR + 0x59, 0xf0,
 | 
						|
#endif
 | 
						|
    S3_CR + 0x5a, 0x00,
 | 
						|
    S3_CR + 0x5b, 0x00,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0x5c, 0x00,
 | 
						|
#endif
 | 
						|
    S3_CR + 0x5d, 0x00,
 | 
						|
    S3_CR + 0x5e, 0x00,
 | 
						|
    S3_CR + 0x5f, 0x00,
 | 
						|
    S3_CR + 0x60, 0x09,
 | 
						|
    S3_CR + 0x61, 0x9d,
 | 
						|
    S3_CR + 0x62, 0xff,
 | 
						|
    S3_CR + 0x63, 0x00,
 | 
						|
    S3_CR + 0x64, 0xfd,
 | 
						|
    S3_CR + 0x65, 0x04,
 | 
						|
    S3_CR + 0x66, 0x88,
 | 
						|
    S3_CR + 0x67, 0x00,
 | 
						|
    S3_CR + 0x68, 0x7f,
 | 
						|
    S3_CR + 0x69, 0x00,
 | 
						|
    S3_CR + 0x6a, 0x00,
 | 
						|
    S3_CR + 0x6b, 0x00,
 | 
						|
    S3_CR + 0x6c, 0x00,
 | 
						|
    S3_CR + 0x6d, 0x11,
 | 
						|
    S3_CR + 0x6e, 0xff,
 | 
						|
    S3_CR + 0x6f, 0xfe,
 | 
						|
 | 
						|
    S3_CR + 0x70, 0x30,
 | 
						|
    S3_CR + 0x71, 0xc0,
 | 
						|
    S3_CR + 0x72, 0x07,
 | 
						|
    S3_CR + 0x73, 0x1f,
 | 
						|
    S3_CR + 0x74, 0x1f,
 | 
						|
    S3_CR + 0x75, 0x1f,
 | 
						|
    S3_CR + 0x76, 0x0f,
 | 
						|
    S3_CR + 0x77, 0x1f,
 | 
						|
    S3_CR + 0x78, 0x01,
 | 
						|
    S3_CR + 0x79, 0x01,
 | 
						|
    S3_CR + 0x7a, 0x1f,
 | 
						|
    S3_CR + 0x7b, 0x1f,
 | 
						|
    S3_CR + 0x7c, 0x17,
 | 
						|
    S3_CR + 0x7d, 0x17,
 | 
						|
    S3_CR + 0x7e, 0x17,
 | 
						|
    S3_CR + 0x7f, 0xfd,
 | 
						|
    S3_CR + 0x80, 0x00,
 | 
						|
    S3_CR + 0x81, 0x92,
 | 
						|
    S3_CR + 0x82, 0x10,
 | 
						|
    S3_CR + 0x83, 0x07,
 | 
						|
    S3_CR + 0x84, 0x42,
 | 
						|
    S3_CR + 0x85, 0x00,
 | 
						|
    S3_CR + 0x86, 0x00,
 | 
						|
    S3_CR + 0x87, 0x00,
 | 
						|
    S3_CR + 0x88, 0x10,
 | 
						|
    S3_CR + 0x89, 0xfd,
 | 
						|
    S3_CR + 0x8a, 0xfd,
 | 
						|
    S3_CR + 0x8b, 0xfd,
 | 
						|
    S3_CR + 0x8c, 0xfd,
 | 
						|
    S3_CR + 0x8d, 0xfd,
 | 
						|
    S3_CR + 0x8e, 0xfd,
 | 
						|
    S3_CR + 0x8f, 0xfd,
 | 
						|
    S3_CR + 0x90, 0x00,
 | 
						|
    S3_CR + 0x91, 0x4f,
 | 
						|
    S3_CR + 0x92, 0x10,
 | 
						|
    S3_CR + 0x93, 0x00,
 | 
						|
    S3_CR + 0x94, 0xfd,
 | 
						|
    S3_CR + 0x95, 0xfd,
 | 
						|
    S3_CR + 0x96, 0xfd,
 | 
						|
    S3_CR + 0x97, 0xfd,
 | 
						|
    S3_CR + 0x98, 0xfd,
 | 
						|
    S3_CR + 0x99, 0xff,
 | 
						|
    S3_CR + 0x9a, 0xfd,
 | 
						|
    S3_CR + 0x9b, 0xff,
 | 
						|
    S3_CR + 0x9c, 0xfd,
 | 
						|
    S3_CR + 0x9d, 0xfd,
 | 
						|
    S3_CR + 0x9e, 0xfd,
 | 
						|
    S3_CR + 0x9f, 0xff,
 | 
						|
    S3_CR + 0xa0, 0x0f,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0xa1, 0x00,
 | 
						|
    S3_CR + 0xa2, 0x00,
 | 
						|
    S3_CR + 0xa3, 0x00,
 | 
						|
    S3_CR + 0xa4, 0x55,
 | 
						|
#endif
 | 
						|
    S3_CR + 0xa5, 0x09,
 | 
						|
    S3_CR + 0xa6, 0x20,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0xa7, 0x00,
 | 
						|
    S3_CR + 0xa8, 0x00,
 | 
						|
    S3_CR + 0xa9, 0x00,
 | 
						|
    S3_CR + 0xaa, 0x00,
 | 
						|
    S3_CR + 0xab, 0x00,
 | 
						|
    S3_CR + 0xac, 0x00,
 | 
						|
    S3_CR + 0xad, 0x00,
 | 
						|
    S3_CR + 0xae, 0x00,
 | 
						|
    S3_CR + 0xaf, 0x00,
 | 
						|
    S3_CR + 0xb0, 0xff,
 | 
						|
#endif
 | 
						|
    S3_CR + 0xb1, 0x0e,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0xb2, 0x55,
 | 
						|
    S3_CR + 0xb3, 0x00,
 | 
						|
    S3_CR + 0xb4, 0x55,
 | 
						|
    S3_CR + 0xb5, 0x00,
 | 
						|
    S3_CR + 0xb6, 0x00,
 | 
						|
#endif
 | 
						|
    S3_CR + 0xb7, 0x84,
 | 
						|
#if 0
 | 
						|
    S3_CR + 0xb8, 0xff,
 | 
						|
    S3_CR + 0xb9, 0xff,
 | 
						|
    S3_CR + 0xba, 0xff,
 | 
						|
    S3_CR + 0xbb, 0xff,
 | 
						|
    S3_CR + 0xbc, 0xff,
 | 
						|
    S3_CR + 0xbd, 0xff,
 | 
						|
    S3_CR + 0xbe, 0xff,
 | 
						|
    S3_CR + 0xbf, 0xff,
 | 
						|
#endif
 | 
						|
 | 
						|
    S3_SR +0x15, 0x23,
 | 
						|
    0xffff, 1,
 | 
						|
    S3_SR +0x15, 0x03,
 | 
						|
    0xffff, 1,
 | 
						|
};
 | 
						|
 | 
						|
#define	S3_NUM_BIOS_REG	(sizeof (s3BiosReg) / sizeof (s3BiosReg[0]))
 | 
						|
 | 
						|
typedef struct _bios32Init {
 | 
						|
    VGA16   offset;
 | 
						|
    VGA32   value;
 | 
						|
} s3Bios32Init;
 | 
						|
 | 
						|
s3Bios32Init s3Bios32Reg[] = {
 | 
						|
    0x8168, 0x00000000,
 | 
						|
    0x816c, 0x00000001,
 | 
						|
    0x8170, 0x00000000,
 | 
						|
    0x8174, 0x00000000,
 | 
						|
    0x8178, 0x00000000,
 | 
						|
    0x817c, 0x00000000,
 | 
						|
#if 0
 | 
						|
    0x8180, 0x00140000,
 | 
						|
    0x8184, 0x00000000,
 | 
						|
    0x8188, 0x00000000,
 | 
						|
    0x8190, 0x00000000,
 | 
						|
    0x8194, 0x00000000,
 | 
						|
    0x8198, 0x00000000,
 | 
						|
    0x819c, 0x00000000,
 | 
						|
    0x81a0, 0x00000000,
 | 
						|
#endif
 | 
						|
    0x81c0, 0x00000000,
 | 
						|
    0x81c4, 0x01fbffff,
 | 
						|
    0x81c8, 0x00f7ffbf,
 | 
						|
    0x81cc, 0x00f7ff00,
 | 
						|
    0x81d0, 0x11ffff7f,
 | 
						|
    0x81d4, 0x7fffffdf,
 | 
						|
    0x81d8, 0xfdfff9ff,
 | 
						|
    0x81e0, 0xfd000000,
 | 
						|
    0x81e4, 0x00000000,
 | 
						|
    0x81e8, 0x00000000,
 | 
						|
    0x81ec, 0x00010000,
 | 
						|
    0x81f0, 0x07ff057f,
 | 
						|
    0x81f4, 0x07ff07ff,
 | 
						|
    0x81f8, 0x00000000,
 | 
						|
    0x81fc, 0x00000000,
 | 
						|
    0x8200, 0x00000000,
 | 
						|
    0x8204, 0x00000000,
 | 
						|
    0x8208, 0x33000000,
 | 
						|
    0x820c, 0x7f000000,
 | 
						|
    0x8210, 0x80000000,
 | 
						|
    0x8214, 0x00000000,
 | 
						|
    0x8218, 0xffffffff,
 | 
						|
    0x8300, 0xff007fef,
 | 
						|
    0x8304, 0xfffdf7bf,
 | 
						|
    0x8308, 0xfdfffbff,
 | 
						|
};
 | 
						|
 | 
						|
#define S3_NUM_BIOS32_REG   (sizeof (s3Bios32Reg) / sizeof (s3Bios32Reg[0]))
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize the card precisely as the bios does
 | 
						|
 */
 | 
						|
s3DoBiosInit (KdCardInfo *card)
 | 
						|
{
 | 
						|
    S3CardInfo	*s3c = card->driver;
 | 
						|
    CARD32	*regs = (CARD32 *) s3c->registers;
 | 
						|
    S3Vga	*s3vga = &s3c->s3vga;
 | 
						|
    int		r;
 | 
						|
 | 
						|
    for (r = 0; r < S3_NUM_BIOS_REG; r++)
 | 
						|
    {
 | 
						|
	if (s3BiosReg[r].reg == 0xffff)
 | 
						|
	    sleep (s3BiosReg[r].value);
 | 
						|
	else
 | 
						|
	    VgaStore (&s3vga->card, s3BiosReg[r].reg, s3BiosReg[r].value);
 | 
						|
    }
 | 
						|
    VgaStore (&s3vga->card, S3_SR+0x10, 0x22);
 | 
						|
    VgaStore (&s3vga->card, S3_SR+0x11, 0x44);
 | 
						|
    VgaStore (&s3vga->card, S3_SR+0x15, 0x01);
 | 
						|
    sleep (1);
 | 
						|
    VgaStore (&s3vga->card, S3_SR+0x15, 0x03);
 | 
						|
    VgaStore (&s3vga->card, S3_CR+0x6f, 0xff);
 | 
						|
    VgaStore (&s3vga->card, S3_CR+0x3f, 0x3f);
 | 
						|
    sleep (1);
 | 
						|
    VgaStore (&s3vga->card, S3_CR+0x3f, 0x00);
 | 
						|
    VgaStore (&s3vga->card, S3_CR+0x6f, 0xfe);
 | 
						|
    VgaInvalidate (&s3vga->card);
 | 
						|
    for (r = 0; r < S3_NUM_BIOS32_REG; r++)
 | 
						|
	regs[s3Bios32Reg[r].offset/4] = s3Bios32Reg[r].value;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
s3Preserve (KdCardInfo *card)
 | 
						|
{
 | 
						|
    S3CardInfo	*s3c = card->driver;
 | 
						|
    S3Ptr   s3 = s3c->s3;
 | 
						|
    S3Vga   *s3vga = &s3c->s3vga;
 | 
						|
    S3Save  *save = &s3c->save;
 | 
						|
    CARD8   t1, t2;
 | 
						|
    CARD8   *cursor_base;
 | 
						|
    CARD8   streams_mode;
 | 
						|
 | 
						|
    s3Save (s3vga);
 | 
						|
    if (!s3c->bios_initialized)
 | 
						|
	s3DoBiosInit (card);
 | 
						|
 | 
						|
    _s3SetBlank (s3, s3vga, TRUE);
 | 
						|
    /*
 | 
						|
     * Preserve the first part of the frame buffer which holds
 | 
						|
     * the text mode fonts and data
 | 
						|
     */
 | 
						|
    s3Set (s3vga, s3_linear_window_size, 3);
 | 
						|
    s3Set (s3vga, s3_enable_linear, 1);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
    memcpy (save->text_save, s3c->frameBuffer, S3_TEXT_SAVE);
 | 
						|
    /*
 | 
						|
     * Preserve graphics engine state
 | 
						|
     */
 | 
						|
    save->alt_mix = s3->alt_mix;
 | 
						|
    save->write_mask = s3->write_mask;
 | 
						|
    save->fg = s3->fg;
 | 
						|
    save->bg = s3->bg;
 | 
						|
    /*
 | 
						|
     * Preserve streams processor state
 | 
						|
     */
 | 
						|
    streams_mode = s3Get (s3vga, s3_streams_mode);
 | 
						|
    s3SetImm (s3vga, s3_streams_mode, 3);
 | 
						|
    save->global_bitmap_1 = s3->global_bitmap_1;
 | 
						|
    save->global_bitmap_2 = s3->global_bitmap_2;
 | 
						|
    save->adv_func_cntl = s3->adv_func_cntl;
 | 
						|
    save->primary_bitmap_1 = s3->primary_bitmap_1;
 | 
						|
    save->primary_bitmap_2 = s3->primary_bitmap_2;
 | 
						|
    save->secondary_bitmap_1 = s3->secondary_bitmap_1;
 | 
						|
    save->secondary_bitmap_2 = s3->secondary_bitmap_2;
 | 
						|
    save->primary_stream_control = s3->primary_stream_control;
 | 
						|
    save->blend_control = s3->blend_control;
 | 
						|
    save->primary_stream_addr_0 = s3->primary_stream_addr_0;
 | 
						|
    save->primary_stream_addr_1 = s3->primary_stream_addr_1;
 | 
						|
    save->primary_stream_stride = s3->primary_stream_stride;
 | 
						|
    save->primary_stream_xy = s3->primary_stream_xy;
 | 
						|
    save->primary_stream_size = s3->primary_stream_size;
 | 
						|
    save->primary_stream_mem = s3->primary_stream_mem;
 | 
						|
    save->secondary_stream_xy = s3->secondary_stream_xy;
 | 
						|
    save->secondary_stream_size = s3->secondary_stream_size;
 | 
						|
    save->streams_fifo = s3->streams_fifo;
 | 
						|
    s3SetImm (s3vga, s3_streams_mode, streams_mode);
 | 
						|
    _s3SetBlank (s3, s3vga, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Enable the card for rendering.  Manipulate the initial settings
 | 
						|
 * of the card here.
 | 
						|
 */
 | 
						|
int  s3CpuTimeout, s3AccelTimeout;
 | 
						|
 | 
						|
void
 | 
						|
s3SetGlobalBitmap (ScreenPtr pScreen, int ma)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    s3ScreenInfo (pScreenPriv);
 | 
						|
    
 | 
						|
    if (s3s->current_ma != ma)
 | 
						|
    {
 | 
						|
	s3CardInfo (pScreenPriv);
 | 
						|
	S3Vga   *s3vga = &s3c->s3vga;
 | 
						|
	S3Ptr   s3 = s3c->s3;
 | 
						|
	CARD32  gb1, gb2;
 | 
						|
	int	    depth;
 | 
						|
	int	    length;
 | 
						|
	KdCheckSync (pScreen);
 | 
						|
	switch (s3s->fb[ma].accel_bpp) {
 | 
						|
	case 8:
 | 
						|
	case 24:
 | 
						|
	    length = 0;
 | 
						|
	    break;
 | 
						|
	case 16:
 | 
						|
	    length = 1;
 | 
						|
	    break;
 | 
						|
	case 32:
 | 
						|
	    length = 3;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	s3SetImm (s3vga, s3_pixel_length, length);
 | 
						|
	gb1 = s3s->fb[ma].bitmap_offset;
 | 
						|
	gb2 = ((1 << 0) |
 | 
						|
	       (0 << 2) |
 | 
						|
	       (1 << 3) |
 | 
						|
	       ((s3s->fb[ma].accel_stride >> 4) << 4) |
 | 
						|
	       (s3s->fb[ma].accel_bpp << 16) |
 | 
						|
	       (0 << 24) |
 | 
						|
	       (1 << 28));
 | 
						|
	s3->global_bitmap_1 = gb1;
 | 
						|
	s3->global_bitmap_2 = gb2;
 | 
						|
	s3->global_bitmap_2 = gb2;
 | 
						|
	s3s->current_ma = ma;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3Enable (ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdCardInfo	    *card = pScreenPriv->card;
 | 
						|
    KdScreenInfo    *screen = pScreenPriv->screen;
 | 
						|
    s3CardInfo (pScreenPriv);
 | 
						|
    s3ScreenInfo (pScreenPriv);
 | 
						|
    
 | 
						|
    S3Vga   *s3vga = &s3c->s3vga;
 | 
						|
    S3Ptr   s3 = s3c->s3;
 | 
						|
    int	    hactive, hblank, hfp, hbp;
 | 
						|
    int	    vactive, vblank, vfp, vbp;
 | 
						|
    int	    hsize;
 | 
						|
 | 
						|
    int	    h_total;
 | 
						|
    int	    h_display_end;
 | 
						|
    int	    h_blank_start;
 | 
						|
    int	    h_blank_end;
 | 
						|
    int	    h_sync_start;
 | 
						|
    int	    h_sync_end;
 | 
						|
    int	    h_screen_off;
 | 
						|
    int	    h_start_fifo_fetch;
 | 
						|
 | 
						|
    int	    primary_stream_l1[KD_MAX_FB];
 | 
						|
 | 
						|
    int	    v_total;
 | 
						|
    int	    v_retrace_start;
 | 
						|
    int	    v_retrace_end;
 | 
						|
    int	    v_display_end;
 | 
						|
    int	    v_blank_start;
 | 
						|
    int	    v_blank_end;
 | 
						|
    int	    v_blank_start_adjust = 0;
 | 
						|
    int	    v_blank_end_adjust = 0;
 | 
						|
 | 
						|
    int	    h_blank_start_adjust = 0;
 | 
						|
    int	    h_blank_end_adjust = 0;
 | 
						|
    int	    h_sync_start_adjust = 0;
 | 
						|
    int	    h_sync_end_adjust = 0;
 | 
						|
    int	    h_start_fifo_fetch_adjust = 0;
 | 
						|
    int	    h_sync_extend;
 | 
						|
    int	    h_blank_extend;
 | 
						|
    int	    i;
 | 
						|
    CARD16  cursor_address;
 | 
						|
    const KdMonitorTiming *t;
 | 
						|
    int	    m, n, r;
 | 
						|
    Bool    clock_double;
 | 
						|
    int	    cpu_timeout;
 | 
						|
    int	    accel_timeout;
 | 
						|
    int	    bytes_per_ms;
 | 
						|
    CARD32  control[2];
 | 
						|
    int	    fb;
 | 
						|
    int	    ma;
 | 
						|
    
 | 
						|
    s3s->primary_depth = screen->fb[s3s->fbmap[0]].depth;
 | 
						|
    
 | 
						|
    s3s->use_streams = TRUE;
 | 
						|
    
 | 
						|
    t = KdFindMode (screen, s3ModeSupported);
 | 
						|
    
 | 
						|
    hfp = t->hfp;
 | 
						|
    hbp = t->hbp;
 | 
						|
    hblank = t->hblank;
 | 
						|
    hactive = t->horizontal;
 | 
						|
 | 
						|
    vfp = t->vfp;
 | 
						|
    vbp = t->vbp;
 | 
						|
    vblank = t->vblank;
 | 
						|
    vactive = t->vertical;
 | 
						|
 | 
						|
    
 | 
						|
    m = s3Get (s3vga, s3_dclk_m);
 | 
						|
    n = s3Get (s3vga, s3_dclk_n);
 | 
						|
    r = s3Get (s3vga, s3_dclk_r);
 | 
						|
#define DEBUG_CLOCK
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    fprintf (stderr, "old clock %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
    clock_double = FALSE;
 | 
						|
    s3GetClock (t->clock, &m, &n, &r, 511, 127, 4, 250000);
 | 
						|
    if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK && !s3s->use_streams)
 | 
						|
	clock_double = TRUE;
 | 
						|
    s3Set (s3vga, s3_clock_select, 3);
 | 
						|
    s3Set (s3vga, s3_dclk_m, m);
 | 
						|
    s3Set (s3vga, s3_dclk_n, n);
 | 
						|
    s3Set (s3vga, s3_dclk_r, r);
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    fprintf (stderr, "new clock %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
 | 
						|
    if (s3s->use_streams)
 | 
						|
    {
 | 
						|
	s3Set (s3vga, s3_streams_mode, 3);
 | 
						|
	s3Set (s3vga, s3_enable_l1_parameter, 1);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	s3Set (s3vga, s3_streams_mode, 0);
 | 
						|
	s3Set (s3vga, s3_enable_l1_parameter, 0);
 | 
						|
    }
 | 
						|
    s3Set (s3vga, s3_flat_panel_output_control_1, 0);
 | 
						|
    s3Set (s3vga, s3_flat_panel_output_control_2, 0);
 | 
						|
    s3Set (s3vga, s3_select_graphics_mode, 1);
 | 
						|
    s3Set (s3vga, s3_enable_blinking, 0);
 | 
						|
    s3Set (s3vga, s3_enable_vga_16bit, 0);
 | 
						|
    s3Set (s3vga, s3_enhanced_memory_mapping, 1);
 | 
						|
    s3Set (s3vga, s3_enable_sff, 1);
 | 
						|
    s3Set (s3vga, s3_enable_2d_access, 1);
 | 
						|
    s3Set (s3vga, s3_2bk_cga, 1);
 | 
						|
    s3Set (s3vga, s3_4bk_hga, 1);
 | 
						|
    s3Set (s3vga, s3_v_total_double, 0);
 | 
						|
    s3Set (s3vga, s3_address_16k_wrap, 1);
 | 
						|
    s3Set (s3vga, s3_word_mode, 0);
 | 
						|
    s3Set (s3vga, s3_byte_mode, 1);
 | 
						|
    s3Set (s3vga, s3_hardware_reset, 1);
 | 
						|
    s3Set (s3vga, s3_max_scan_line, 0);
 | 
						|
    s3Set (s3vga, s3_linear_window_size, 3);
 | 
						|
    s3Set (s3vga, s3_enable_linear, 1);
 | 
						|
    s3Set (s3vga, s3_enable_2d_3d, 1);
 | 
						|
    s3Set (s3vga, s3_refresh_control, 1);
 | 
						|
    s3Set (s3vga, s3_disable_pci_read_bursts, 0);
 | 
						|
    s3Set (s3vga, s3_pci_disconnect_enable, 1);
 | 
						|
    s3Set (s3vga, s3_primary_load_control, 0);
 | 
						|
    s3Set (s3vga, s3_secondary_load_control, 0);
 | 
						|
    s3Set (s3vga, s3_pci_retry_enable, 1);
 | 
						|
    s3Set (s3vga, s3_enable_256, 1);
 | 
						|
    s3Set (s3vga, s3_border_select, 1);	/* eliminate white border */
 | 
						|
    s3SetImm (s3vga, s3_lock_palette, 0);	/* unlock palette/border regs */
 | 
						|
    s3Set (s3vga, s3_disable_v_retrace_int, 1);
 | 
						|
    if (t->hpol == KdSyncPositive)
 | 
						|
	s3Set (s3vga, s3_horz_sync_neg, 0);
 | 
						|
    else
 | 
						|
	s3Set (s3vga, s3_horz_sync_neg, 1);
 | 
						|
    if (t->vpol == KdSyncPositive)
 | 
						|
	s3Set (s3vga, s3_vert_sync_neg, 0);
 | 
						|
    else
 | 
						|
	s3Set (s3vga, s3_vert_sync_neg, 1);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_dot_clock_8, 1);
 | 
						|
    s3Set (s3vga, s3_enable_write_plane, 0xf);
 | 
						|
    s3Set (s3vga, s3_extended_memory_access, 1);
 | 
						|
    s3Set (s3vga, s3_sequential_addressing_mode, 1);
 | 
						|
    s3Set (s3vga, s3_select_chain_4_mode, 1);
 | 
						|
    s3Set (s3vga, s3_linear_addressing_control, 1);
 | 
						|
 | 
						|
    s3Set (s3vga, s3_enable_gamma_correction, 0);
 | 
						|
 | 
						|
    s3Set (s3vga, s3_enable_8_bit_luts, 1);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_dclk_invert, 0);
 | 
						|
    s3Set (s3vga, s3_enable_clock_double, 0);
 | 
						|
    s3Set (s3vga, s3_dclk_over_2, 0);
 | 
						|
 | 
						|
    s3Set (s3vga, s3_delay_h_enable, 0);
 | 
						|
    s3Set (s3vga, s3_sdclk_skew, 0);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_dac_mask, 0xff);
 | 
						|
    
 | 
						|
#if 0
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    m = s3Get (s3vga, s3_mclk_m);
 | 
						|
    n = s3Get (s3vga, s3_mclk_n);
 | 
						|
    r = s3Get (s3vga, s3_mclk_r);
 | 
						|
    fprintf (stderr, "old mclk %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
    
 | 
						|
    s3GetClock (125282, &m, &n, &r, 127, 31, 3, 250000);
 | 
						|
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    fprintf (stderr, "new mclk %d, %d, %d (%d)\n", m, n, r,S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_mclk_m, m);
 | 
						|
    s3Set (s3vga, s3_mclk_n, n);
 | 
						|
    s3Set (s3vga, s3_mclk_r, r);
 | 
						|
    
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    m = s3Get (s3vga, s3_eclk_m);
 | 
						|
    n = s3Get (s3vga, s3_eclk_n);
 | 
						|
    r = s3Get (s3vga, s3_eclk_r);
 | 
						|
    fprintf (stderr, "old eclk %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
    
 | 
						|
#define S3_ECLK	125282
 | 
						|
    
 | 
						|
    s3GetClock (S3_ECLK, &m, &n, &r, 127, 31, 3, 250000);
 | 
						|
 | 
						|
#ifdef DEBUG_CLOCK
 | 
						|
    fprintf (stderr, "new eclk %d, %d, %d (%d)\n", m, n, r,S3_CLOCK(m,n,r));
 | 
						|
#endif
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_eclk_m, m);
 | 
						|
    s3Set (s3vga, s3_eclk_n, n);
 | 
						|
    s3Set (s3vga, s3_eclk_r, r);
 | 
						|
#endif
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Compute character lengths for horizontal timing values
 | 
						|
     */
 | 
						|
    hactive = screen->width / 8;
 | 
						|
    hblank /= 8;
 | 
						|
    hfp /= 8;
 | 
						|
    hbp /= 8;
 | 
						|
    /*
 | 
						|
     * Set pixel size, choose clock doubling mode
 | 
						|
     */
 | 
						|
 | 
						|
    bytes_per_ms = 0;
 | 
						|
    
 | 
						|
    for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | 
						|
    {
 | 
						|
	fb = s3s->fbmap[ma];
 | 
						|
	s3s->fb[ma].accel_bpp = screen->fb[fb].bitsPerPixel;
 | 
						|
	s3s->fb[ma].accel_stride = screen->fb[fb].pixelStride;
 | 
						|
	s3s->fb[ma].bitmap_offset = screen->fb[fb].frameBuffer - s3c->frameBuffer;
 | 
						|
	switch (s3s->fb[ma].accel_bpp) {
 | 
						|
	case 8:
 | 
						|
	    h_screen_off = hactive;
 | 
						|
	    s3Set (s3vga, s3_pixel_length, 0);
 | 
						|
	    s3Set (s3vga, s3_color_mode, 0);
 | 
						|
	    control[ma] = 0;	
 | 
						|
	    /*
 | 
						|
	     * Set up for double-pixel mode, switch color modes,
 | 
						|
	     * divide the dclk and delay h blank by 2 dclks
 | 
						|
	     */
 | 
						|
	    if (clock_double)
 | 
						|
	    {
 | 
						|
		s3Set (s3vga, s3_color_mode, 1);
 | 
						|
		s3Set (s3vga, s3_dclk_over_2, 1);
 | 
						|
		s3Set (s3vga, s3_enable_clock_double, 1);
 | 
						|
		s3Set (s3vga, s3_h_skew, 1);
 | 
						|
		h_blank_start_adjust = -3;
 | 
						|
		h_blank_end_adjust = -4;
 | 
						|
		s3Set (s3vga, s3_border_select, 0);
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case 16:
 | 
						|
	    h_screen_off = hactive * 2;
 | 
						|
	    s3Set (s3vga, s3_pixel_length, 1);
 | 
						|
	    if (screen->fb[fb].depth == 15)
 | 
						|
		control[ma] = 3 << 24;
 | 
						|
	    else
 | 
						|
		control[ma] = 5 << 24;
 | 
						|
	    if (clock_double)
 | 
						|
	    {
 | 
						|
		if (screen->fb[fb].depth == 15)
 | 
						|
		    s3Set (s3vga, s3_color_mode, 3);
 | 
						|
		else
 | 
						|
		    s3Set (s3vga, s3_color_mode, 5);
 | 
						|
		s3Set (s3vga, s3_dclk_over_2, 1);
 | 
						|
		s3Set (s3vga, s3_enable_clock_double, 1);
 | 
						|
		s3Set (s3vga, s3_border_select, 0);
 | 
						|
		h_blank_start_adjust = 4;
 | 
						|
		h_blank_end_adjust = -4;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		if (screen->fb[fb].depth == 15)
 | 
						|
		    s3Set (s3vga, s3_color_mode, 2);
 | 
						|
		else
 | 
						|
		    s3Set (s3vga, s3_color_mode, 4);
 | 
						|
		s3Set (s3vga, s3_dclk_over_2, 0);
 | 
						|
		s3Set (s3vga, s3_enable_clock_double, 0);
 | 
						|
		s3Set (s3vga, s3_delay_blank, 0);
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case 24:
 | 
						|
	    control[ma] = 6 << 24;
 | 
						|
	    h_screen_off = hactive * 3;
 | 
						|
	    s3s->fb[ma].accel_bpp = 8;
 | 
						|
	    s3s->fb[ma].accel_stride = screen->fb[fb].pixelStride * 3;
 | 
						|
	    break;
 | 
						|
	case 32:
 | 
						|
	    control[ma] = 7 << 24;
 | 
						|
	    h_screen_off = hactive * 4;
 | 
						|
	    s3Set (s3vga, s3_pixel_length, 3);
 | 
						|
	    s3Set (s3vga, s3_color_mode, 0xd);
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	bytes_per_ms += t->clock * (screen->fb[fb].bitsPerPixel / 8);
 | 
						|
	primary_stream_l1[ma] = (screen->width * screen->fb[fb].bitsPerPixel / (8 * 8)) - 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
     * X server starts frame buffer at top of memory
 | 
						|
     */
 | 
						|
    s3Set (s3vga, s3_start_address, 0);
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Set various registers to avoid snow on the screen
 | 
						|
     */
 | 
						|
    
 | 
						|
    fprintf (stderr, "bytes_per_ms %d\n", bytes_per_ms);
 | 
						|
    fprintf (stderr, "primary 0x%x master 0x%x command 0x%x lpb 0x%x cpu 0x%x 2d 0x%x\n",
 | 
						|
	     s3Get (s3vga, s3_primary_stream_timeout),
 | 
						|
	     s3Get (s3vga, s3_master_control_unit_timeout),
 | 
						|
	     s3Get (s3vga, s3_command_buffer_timeout),
 | 
						|
	     s3Get (s3vga, s3_lpb_timeout),
 | 
						|
	     s3Get (s3vga, s3_cpu_timeout),
 | 
						|
	     s3Get (s3vga, s3_2d_graphics_engine_timeout));
 | 
						|
 | 
						|
    /*
 | 
						|
     *	Test:
 | 
						|
     *	    accel	x11perf -line500
 | 
						|
     *	    cpu		x11perf -circle500
 | 
						|
     *
 | 
						|
     *				    cpu	    accel
 | 
						|
     *	1600x1200x32x85 (918000)    1	    1	    not enough
 | 
						|
     *  1600x1200x32x75 (810000)    3	    2
 | 
						|
     *	1600x1200x32x70 (756000)    4	    3
 | 
						|
     *	1600x1200x32x60 (648000)    6	    5
 | 
						|
     *
 | 
						|
     *	1280x1024x32x85 (630000)    6	    4
 | 
						|
     *	1280x1024x32x75 (540000)    a	    6
 | 
						|
     *	1280x1024x32x60 (432000)    1f	    a
 | 
						|
     *
 | 
						|
     *	1152x900x32x85	(490000)    a	    6
 | 
						|
     *	1152x900x32x75	(433000)    1f	    8
 | 
						|
     *	1152x900x32x70	(401000)    1f	    a
 | 
						|
     *	1152x900x32x66	(380000)    1f	    a
 | 
						|
     *
 | 
						|
     *	1024x768x32x85	(378000)    1f	    a
 | 
						|
     *	1024x768x32x75	(315000)    1f	    b
 | 
						|
     *	1024x768x32x70	(300000)    1f	    b
 | 
						|
     *	1024x768x32x60	(260000)    1f	    12
 | 
						|
     *
 | 
						|
     *	800x600x32x85	(225000)    1f	    1a
 | 
						|
     *	800x600x32x72	(200000)    1f	    1d
 | 
						|
     *	800x600x32x75	(198000)    1f	    1d
 | 
						|
     *
 | 
						|
     *	1600x1200x16x85 (459000)    1f	    8
 | 
						|
     *	1600x1200x16x75	(405000)    1f	    a
 | 
						|
     *	1600x1200x16x70	(378000)    1f	    b
 | 
						|
     *	1600x1200x16x60	(324000)    1f	    f
 | 
						|
     *
 | 
						|
     *  1280x1024x16x85 (315000)    1f	    12
 | 
						|
     *	1280x1024x16x75 (270000)    1f	    16
 | 
						|
     *	1280x1024x16x60 (216000)    1f	    1d
 | 
						|
     *
 | 
						|
     *	1600x1200x8x85	(229000)    1f	    1f
 | 
						|
     *
 | 
						|
     */
 | 
						|
    
 | 
						|
    if (s3CpuTimeout)
 | 
						|
    {
 | 
						|
	if (s3CpuTimeout < 0)
 | 
						|
	    cpu_timeout = 0;
 | 
						|
	else
 | 
						|
	    cpu_timeout = s3CpuTimeout;
 | 
						|
	if (s3AccelTimeout < 0)
 | 
						|
	    accel_timeout = 0;
 | 
						|
	else if (s3AccelTimeout)
 | 
						|
	    accel_timeout = s3AccelTimeout;
 | 
						|
	else
 | 
						|
	    accel_timeout = s3CpuTimeout;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 900000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x01;
 | 
						|
	accel_timeout = 0x01;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 800000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x03;
 | 
						|
	accel_timeout = 0x02;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 700000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x04;
 | 
						|
	accel_timeout = 0x03;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 600000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x06;
 | 
						|
	accel_timeout = 0x04;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 475000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x0a;
 | 
						|
	accel_timeout = 0x06;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 425000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x1f;
 | 
						|
	accel_timeout = 0x8;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 300000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x1f;
 | 
						|
	accel_timeout = 0x0a;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 250000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x1f;
 | 
						|
	accel_timeout = 0x12;
 | 
						|
    }
 | 
						|
    else if (bytes_per_ms >= 200000)
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x1f;
 | 
						|
	accel_timeout = 0x1a;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	cpu_timeout = 0x1f;
 | 
						|
	accel_timeout = 0x1f;
 | 
						|
    }
 | 
						|
	
 | 
						|
    fprintf (stderr, "cpu 0x%x accel 0x%x\n", cpu_timeout, accel_timeout);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_primary_stream_timeout, 0xc0);
 | 
						|
    s3Set (s3vga, s3_master_control_unit_timeout, 0xf);
 | 
						|
    s3Set (s3vga, s3_command_buffer_timeout, 0x1f);
 | 
						|
    s3Set (s3vga, s3_lpb_timeout, 0xf);
 | 
						|
    s3Set (s3vga, s3_2d_graphics_engine_timeout, accel_timeout);
 | 
						|
    s3Set (s3vga, s3_cpu_timeout, cpu_timeout);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_fifo_fetch_timing, 1);
 | 
						|
    s3Set (s3vga, s3_fifo_drain_delay, 2);
 | 
						|
 | 
						|
    /*
 | 
						|
     * Compute horizontal register values from timings
 | 
						|
     */
 | 
						|
    h_total = hactive + hblank - 5;
 | 
						|
    h_display_end = hactive - 1;
 | 
						|
    
 | 
						|
    h_sync_start = hactive + hfp + h_sync_start_adjust;
 | 
						|
    h_sync_end = hactive + hblank - hbp + h_sync_end_adjust;
 | 
						|
    /* 
 | 
						|
     * pad the blank values narrow a bit and use the border_select to
 | 
						|
     * eliminate the remaining border; don't know why, but it doesn't
 | 
						|
     * work in the documented fashion
 | 
						|
     */
 | 
						|
    h_blank_start = hactive + 1 + h_blank_start_adjust;
 | 
						|
    h_blank_end = hactive + hblank - 2 + h_blank_end_adjust;
 | 
						|
    /*
 | 
						|
     * The manual says h_total - 5, but the
 | 
						|
     * bios does differently...
 | 
						|
     */
 | 
						|
    if (screen->width >= 1600)
 | 
						|
	h_start_fifo_fetch = h_total - 24;
 | 
						|
    else if (screen->width >= 1280)
 | 
						|
	h_start_fifo_fetch = h_total - 19;
 | 
						|
    else if (screen->width >= 1024)
 | 
						|
	h_start_fifo_fetch = h_total - 14;
 | 
						|
    else if (screen->width >= 800)
 | 
						|
	h_start_fifo_fetch = h_total - 10;
 | 
						|
    else
 | 
						|
	h_start_fifo_fetch = h_total - 5;
 | 
						|
 | 
						|
    h_start_fifo_fetch += h_start_fifo_fetch_adjust;
 | 
						|
    if (h_blank_end - h_blank_start >= 0x40)
 | 
						|
	h_blank_extend = 1;
 | 
						|
    else
 | 
						|
	h_blank_extend = 0;
 | 
						|
    
 | 
						|
    if (h_sync_end - h_sync_start >= 0x20)
 | 
						|
	h_sync_extend = 1;
 | 
						|
    else
 | 
						|
	h_sync_extend = 0;
 | 
						|
    
 | 
						|
#ifdef DEBUG
 | 
						|
    fprintf (stderr, "h_total %d h_display_end %d\n",
 | 
						|
	     h_total, h_display_end);
 | 
						|
    fprintf (stderr, "h_sync_start %d h_sync_end %d h_sync_extend %d\n",
 | 
						|
	     h_sync_start, h_sync_end, h_sync_extend);
 | 
						|
    fprintf (stderr, "h_blank_start %d h_blank_end %d h_blank_extend %d\n",
 | 
						|
	     h_blank_start, h_blank_end, h_blank_extend);
 | 
						|
#endif
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_h_total, h_total);
 | 
						|
    s3Set (s3vga, s3_h_display_end, h_display_end);
 | 
						|
    s3Set (s3vga, s3_h_blank_start, h_blank_start);
 | 
						|
    s3Set (s3vga, s3_h_blank_end, h_blank_end);
 | 
						|
    s3Set (s3vga, s3_h_sync_start, h_sync_start);
 | 
						|
    s3Set (s3vga, s3_h_sync_end, h_sync_end);
 | 
						|
    s3Set (s3vga, s3_screen_offset, h_screen_off);
 | 
						|
    s3Set (s3vga, s3_h_start_fifo_fetch, h_start_fifo_fetch);
 | 
						|
    s3Set (s3vga, s3_h_sync_extend, h_sync_extend);
 | 
						|
    s3Set (s3vga, s3_h_blank_extend, h_blank_extend);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_dac_power_saving_disable, 0);
 | 
						|
    s3Set (s3vga, s3_dac_power_up_time, hactive + hblank);
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_primary_stream_l1, primary_stream_l1[0]);
 | 
						|
 | 
						|
    s3Set (s3vga, s3_streams_fifo_delay, 0);
 | 
						|
    
 | 
						|
    v_total = vactive + vblank - 2;
 | 
						|
    v_display_end = vactive - 1;
 | 
						|
    
 | 
						|
    v_blank_start = vactive - 1 + v_blank_start_adjust;
 | 
						|
    v_blank_end = v_blank_start + vblank - 1 + v_blank_end_adjust;
 | 
						|
    
 | 
						|
    v_retrace_start = vactive + vfp;
 | 
						|
    v_retrace_end = vactive + vblank - vbp;
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_v_total, v_total);
 | 
						|
    s3Set (s3vga, s3_v_retrace_start, v_retrace_start);
 | 
						|
    s3Set (s3vga, s3_v_retrace_end, v_retrace_end);
 | 
						|
    s3Set (s3vga, s3_v_display_end, v_display_end);
 | 
						|
    s3Set (s3vga, s3_v_blank_start, v_blank_start);
 | 
						|
    s3Set (s3vga, s3_v_blank_end, v_blank_end);
 | 
						|
    
 | 
						|
    if (vactive >= 1024)
 | 
						|
	s3Set (s3vga, s3_line_compare, 0x7ff);
 | 
						|
    else
 | 
						|
	s3Set (s3vga, s3_line_compare, 0x3ff);
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Set cursor
 | 
						|
     */
 | 
						|
    if (!screen->softCursor)
 | 
						|
    {
 | 
						|
	cursor_address = (s3s->cursor_base - s3c->frameBuffer) / 1024;
 | 
						|
 | 
						|
	s3Set (s3vga, s3_cursor_address, cursor_address);
 | 
						|
	s3Set (s3vga, s3_cursor_ms_x11, 0);
 | 
						|
	s3Set (s3vga, s3_cursor_enable, 1);
 | 
						|
    }
 | 
						|
    else
 | 
						|
	s3Set (s3vga, s3_cursor_enable, 0);
 | 
						|
    
 | 
						|
#define MAKE_GBF(bds,be,stride,bpp,tile) (\
 | 
						|
						  ((bds) << 0) | \
 | 
						|
						  ((be) << 3) | \
 | 
						|
						  ((stride) << 4) | \
 | 
						|
						  ((bpp) << 16) | \
 | 
						|
						  ((tile) << 24))
 | 
						|
    /*
 | 
						|
     * Set accelerator
 | 
						|
     */
 | 
						|
    switch (screen->width) {
 | 
						|
#if 0
 | 
						|
    case 640: s3Set (s3vga, s3_ge_screen_width, 1); break;
 | 
						|
    case 800: s3Set (s3vga, s3_ge_screen_width, 2); break;
 | 
						|
    case 1024:        s3Set (s3vga, s3_ge_screen_width, 0); break;
 | 
						|
    case 1152:        s3Set (s3vga, s3_ge_screen_width, 4); break;
 | 
						|
    case 1280:        s3Set (s3vga, s3_ge_screen_width, 3); break;
 | 
						|
    case 1600:        s3Set (s3vga, s3_ge_screen_width, 6); break;
 | 
						|
#endif
 | 
						|
    default:
 | 
						|
	s3Set (s3vga, s3_ge_screen_width, 7);   /* use global bitmap descriptor */
 | 
						|
    }
 | 
						|
    
 | 
						|
#if 0
 | 
						|
    crtc->l_parm_0_7 = screen->width / 4;	/* Undocumented. */
 | 
						|
#endif
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set DPMS to normal
 | 
						|
     */
 | 
						|
    s3Set (s3vga, s3_hsync_control, 0);
 | 
						|
    s3Set (s3vga, s3_vsync_control, 0);
 | 
						|
    
 | 
						|
    _s3SetBlank (s3, s3vga, TRUE);
 | 
						|
    if (s3s->use_streams)
 | 
						|
	s3Set (s3vga, s3_primary_stream_definition, 1);
 | 
						|
    else
 | 
						|
	s3Set (s3vga, s3_primary_stream_definition, 0);
 | 
						|
 | 
						|
    VgaFlush(&s3vga->card);
 | 
						|
    VgaSetImm (&s3vga->card, s3_clock_load_imm, 1);
 | 
						|
    VgaSetImm(&s3vga->card, s3_clock_load_imm, 0);
 | 
						|
 | 
						|
 | 
						|
    if (s3s->use_streams)
 | 
						|
    {
 | 
						|
	fb = s3s->fbmap[0];
 | 
						|
	s3->primary_stream_control = control[0];
 | 
						|
	s3->primary_stream_addr_0 =
 | 
						|
	s3->primary_stream_addr_1 = s3s->fb[0].bitmap_offset;
 | 
						|
	s3->primary_stream_stride = screen->fb[fb].byteStride;
 | 
						|
	s3->primary_stream_xy = (1 << 16) | 1;
 | 
						|
	s3->primary_stream_size = ((screen->fb[fb].pixelStride - 1) << 16) | screen->height;
 | 
						|
	s3->primary_stream_mem = (screen->fb[fb].byteStride * screen->height) / 8 - 1;
 | 
						|
	if (s3s->fbmap[1] >= 0)
 | 
						|
	{
 | 
						|
	    fb = s3s->fbmap[1];
 | 
						|
	    s3->blend_control = 5 << 24;
 | 
						|
	    if (s3s->fb[0].accel_bpp == 8)
 | 
						|
		s3->chroma_key_control = 0x33000000 | s3s->fb[0].chroma_key;
 | 
						|
	    else
 | 
						|
		s3->chroma_key_control = 0x13010101;
 | 
						|
	    s3->secondary_stream_control = control[1] | screen->width;
 | 
						|
	    s3->secondary_stream_h_scale = (1 << 15);
 | 
						|
	    s3->color_adjustment = 0;
 | 
						|
	    s3->secondary_stream_vscale = (1 << 15);
 | 
						|
	    s3->secondary_stream_vinit = 0;
 | 
						|
	    s3->secondary_stream_mbuf = 0;
 | 
						|
	    s3->secondary_stream_addr_0 =
 | 
						|
	    s3->secondary_stream_addr_1 = s3s->fb[1].bitmap_offset;
 | 
						|
	    s3->secondary_stream_stride = screen->fb[fb].byteStride;
 | 
						|
	    s3->secondary_stream_scount = screen->height;
 | 
						|
	    s3->secondary_stream_xy = (1 << 16) | 1;
 | 
						|
	    s3->secondary_stream_size = ((screen->fb[fb].pixelStride - 1) << 16) | screen->height;
 | 
						|
	    s3->secondary_stream_mem = (1 << 22) | ((screen->fb[fb].byteStride * screen->height) / 8 - 1);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    s3->blend_control = 1 << 24;
 | 
						|
	    s3->secondary_stream_xy = 0x07ff07ff;
 | 
						|
	    s3->secondary_stream_size = 0x00010001;
 | 
						|
	}
 | 
						|
	s3->streams_fifo = (0x20 << 11) | (0x20 << 5) | 0x2;
 | 
						|
    }
 | 
						|
    s3->mult_misc_read_sel = (((1 << 9) |
 | 
						|
			       (1 << 11) |
 | 
						|
			       (0xe << 12)) |
 | 
						|
			      (((0xe << 0) |
 | 
						|
				(0xf << 12)) << 16));
 | 
						|
    
 | 
						|
    s3->cmd_overflow_buf_ptr = (1 << 3);
 | 
						|
    s3->bci_power_management = (1 << 9);
 | 
						|
    s3->adv_func_cntl = (3 << 8) | (1 << 4) | (1 << 2) | 1;
 | 
						|
    s3->primary_bitmap_1 = 0;
 | 
						|
    s3->primary_bitmap_2 = 0;
 | 
						|
    s3->secondary_bitmap_1 = 0;
 | 
						|
    s3->secondary_bitmap_2 = 0;
 | 
						|
    s3s->current_ma = -1;
 | 
						|
    _s3SetBlank (s3, s3vga, FALSE);
 | 
						|
#if 0
 | 
						|
    {
 | 
						|
	VGA16	r;
 | 
						|
	static CARD32	streams[][2] = {
 | 
						|
	    /* PCI registers */
 | 
						|
	    0x8000, 0x8024,
 | 
						|
	    0x802c, 0x8034,
 | 
						|
	    0x803c, 0x8040,
 | 
						|
#if 0
 | 
						|
	    0x8080, 0x808c,	/* AGP */
 | 
						|
#endif
 | 
						|
	    0x80dc, 0x80e0,
 | 
						|
	    
 | 
						|
	    /* 2D registers */
 | 
						|
	    0x8168, 0x8188,
 | 
						|
	    0x8190, 0x81a0,
 | 
						|
	    0x81c0, 0x81d8,
 | 
						|
	    0x81e0, 0x8218,
 | 
						|
	    0x8300, 0x8308,
 | 
						|
	    0x8504, 0x8510,
 | 
						|
 | 
						|
	    /* LPB/VIP registers */
 | 
						|
	    0xff00, 0xff18,
 | 
						|
	    0xff20, 0xff38,
 | 
						|
	    0xff40, 0xff40,
 | 
						|
	    0xff70, 0xff78,
 | 
						|
	    0xff8c, 0xffa0,
 | 
						|
 | 
						|
#if 0
 | 
						|
	    /* 3D registers */
 | 
						|
	    0x48508, 0x48508,
 | 
						|
	    0x48528, 0x48528,
 | 
						|
	    0x48548, 0x48548,
 | 
						|
	    0x48584, 0x485f0,
 | 
						|
#endif
 | 
						|
 | 
						|
	    /* motion compensation registers */
 | 
						|
	    0x48900, 0x48924,
 | 
						|
#if 0
 | 
						|
	    0x48928, 0x48928,
 | 
						|
#endif
 | 
						|
 | 
						|
	    /* Mastered data transfer registers */
 | 
						|
	    0x48a00, 0x48a1c,
 | 
						|
 | 
						|
	    /* configuation/status registers */
 | 
						|
	    0x48c00, 0x48c18,
 | 
						|
	    0x48c20, 0x48c24,
 | 
						|
	    0x48c40, 0x48c50,
 | 
						|
	    0x48c60, 0x48c64,
 | 
						|
 | 
						|
	    0, 0,
 | 
						|
	};
 | 
						|
#ifdef PHOENIX
 | 
						|
#undef stderr
 | 
						|
#define stderr stdout
 | 
						|
#endif
 | 
						|
	CARD32	    *regs = (CARD32 *) s3c->registers;
 | 
						|
	int	    i;
 | 
						|
	CARD32	    reg;
 | 
						|
 | 
						|
 | 
						|
	for (r = S3_SR + 0; r < S3_SR + S3_NSR; r++)
 | 
						|
	    fprintf (stderr, "SR%02x = %02x\n", r-S3_SR, VgaFetch (&s3vga->card, r));
 | 
						|
	for (r = S3_GR + 0; r < S3_GR + S3_NGR; r++)
 | 
						|
	    fprintf (stderr, "GR%02x = %02x\n", r-S3_GR, VgaFetch (&s3vga->card, r));
 | 
						|
	for (r = S3_AR + 0; r < S3_AR + S3_NAR; r++)
 | 
						|
	    fprintf (stderr, "AR%02x = %02x\n", r-S3_AR, VgaFetch (&s3vga->card, r));
 | 
						|
	for (r = S3_CR + 0; r < S3_CR + S3_NCR; r++)
 | 
						|
	    fprintf (stderr, "CR%02x = %02x\n", r-S3_CR, VgaFetch (&s3vga->card, r));
 | 
						|
	for (r = S3_DAC + 0; r < S3_DAC + S3_NDAC; r++)
 | 
						|
	    fprintf (stderr, "DAC%02x = %02x\n", r-S3_DAC, VgaFetch (&s3vga->card, r));
 | 
						|
	fprintf (stderr, "MISC_OUT = %02x\n", VgaFetch (&s3vga->card, S3_MISC_OUT));
 | 
						|
	fprintf (stderr, "INPUT_STATUS = %02x\n", VgaFetch (&s3vga->card, S3_INPUT_STATUS_1));
 | 
						|
 | 
						|
 | 
						|
	for (i = 0; streams[i][0]; i++)
 | 
						|
	{
 | 
						|
	    for (reg = streams[i][0]; reg <= streams[i][1]; reg += 4)
 | 
						|
		fprintf (stderr, "0x%4x: 0x%08x\n", reg, regs[reg/4]);
 | 
						|
	}
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
s3Disable (ScreenPtr pScreen)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
s3Restore (KdCardInfo *card)
 | 
						|
{
 | 
						|
    S3CardInfo	*s3c = card->driver;
 | 
						|
    S3Ptr	s3 = s3c->s3;
 | 
						|
    S3Vga	*s3vga = &s3c->s3vga;
 | 
						|
    S3Save	*save = &s3c->save;
 | 
						|
    CARD8	*cursor_base;
 | 
						|
    CARD8	streams_mode;
 | 
						|
 | 
						|
    _s3SetBlank (s3, s3vga, TRUE);
 | 
						|
    /* streams processor state */
 | 
						|
    streams_mode = s3Get (s3vga, s3_streams_mode);
 | 
						|
    s3SetImm (s3vga, s3_streams_mode, 3);
 | 
						|
    s3->global_bitmap_1 = save->global_bitmap_1;
 | 
						|
    s3->global_bitmap_2 = save->global_bitmap_2;
 | 
						|
    s3->adv_func_cntl = save->adv_func_cntl;
 | 
						|
    s3->primary_bitmap_1 = save->primary_bitmap_1;
 | 
						|
    s3->primary_bitmap_2 = save->primary_bitmap_2;
 | 
						|
    s3->secondary_bitmap_1 = save->secondary_bitmap_1;
 | 
						|
    s3->secondary_bitmap_2 = save->secondary_bitmap_2;
 | 
						|
    s3->primary_stream_control = save->primary_stream_control;
 | 
						|
    s3->blend_control = save->blend_control;
 | 
						|
    s3->primary_stream_addr_0 = save->primary_stream_addr_0;
 | 
						|
    s3->primary_stream_addr_0 = save->primary_stream_addr_0;
 | 
						|
    s3->primary_stream_stride = save->primary_stream_stride;
 | 
						|
    s3->primary_stream_xy = save->primary_stream_xy;
 | 
						|
    s3->primary_stream_size = save->primary_stream_size;
 | 
						|
    s3->primary_stream_mem = save->primary_stream_mem;
 | 
						|
    s3->secondary_stream_xy = save->secondary_stream_xy;
 | 
						|
    s3->secondary_stream_size = save->secondary_stream_size;
 | 
						|
    s3->streams_fifo = save->streams_fifo;
 | 
						|
    s3SetImm (s3vga, s3_streams_mode, streams_mode);
 | 
						|
    /* graphics engine state */
 | 
						|
    s3->alt_mix = save->alt_mix;
 | 
						|
    s3->write_mask = save->write_mask;
 | 
						|
    s3->fg = save->fg;
 | 
						|
    s3->bg = save->bg;
 | 
						|
    /* XXX should save and restore real values? */
 | 
						|
    s3->scissors_tl = 0x00000000;
 | 
						|
    s3->scissors_br = 0x0fff0fff;
 | 
						|
    
 | 
						|
    VgaRestore (&s3vga->card);
 | 
						|
    s3Set (s3vga, s3_linear_window_size, 3);
 | 
						|
    s3Set (s3vga, s3_enable_linear, 1);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
    memcpy (s3c->frameBuffer, save->text_save, S3_TEXT_SAVE);
 | 
						|
    s3Reset (s3vga);
 | 
						|
    _s3SetBlank (s3, s3vga, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
_s3SetSync (S3CardInfo *s3c, int hsync, int vsync)
 | 
						|
{
 | 
						|
    /* this abuses the macros defined to access the crtc structure */
 | 
						|
    S3Ptr   s3 = s3c->s3;
 | 
						|
    S3Vga   *s3vga = &s3c->s3vga;
 | 
						|
    
 | 
						|
    s3Set (s3vga, s3_hsync_control, hsync);
 | 
						|
    s3Set (s3vga, s3_vsync_control, vsync);
 | 
						|
    VgaFlush (&s3vga->card);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3DPMS (ScreenPtr pScreen, int mode)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    s3CardInfo(pScreenPriv);
 | 
						|
    S3Vga   *s3vga = &s3c->s3vga;
 | 
						|
    
 | 
						|
    switch (mode) {
 | 
						|
    case KD_DPMS_NORMAL:
 | 
						|
	_s3SetSync (s3c, 0, 0);
 | 
						|
	_s3SetBlank (s3c->s3, s3vga, FALSE);
 | 
						|
	break;
 | 
						|
    case KD_DPMS_STANDBY:
 | 
						|
	_s3SetBlank (s3c->s3, s3vga, TRUE);
 | 
						|
	_s3SetSync (s3c, 1, 0);
 | 
						|
	break;
 | 
						|
    case KD_DPMS_SUSPEND:
 | 
						|
	_s3SetBlank (s3c->s3, s3vga, TRUE);
 | 
						|
	_s3SetSync (s3c, 0, 1);
 | 
						|
	break;
 | 
						|
    case KD_DPMS_POWERDOWN:
 | 
						|
	_s3SetBlank (s3c->s3, s3vga, TRUE);
 | 
						|
	_s3SetSync (s3c, 1, 1);
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
s3InitScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdCardInfo	    *card = pScreenPriv->card;
 | 
						|
    KdScreenInfo    *screen = pScreenPriv->screen;
 | 
						|
    s3CardInfo (pScreenPriv);
 | 
						|
    s3ScreenInfo (pScreenPriv);
 | 
						|
    int		ma, fb;
 | 
						|
 | 
						|
    if (screen->fb[1].depth)
 | 
						|
    {
 | 
						|
	FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 | 
						|
 | 
						|
	for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | 
						|
	{
 | 
						|
	    fb = s3s->fbmap[ma];
 | 
						|
	    pScrPriv->layer[fb].key = s3s->fb[ma].chroma_key;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
s3ScreenFini (KdScreenInfo *screen)
 | 
						|
{
 | 
						|
    S3ScreenInfo    *s3s = (S3ScreenInfo *) screen->driver;
 | 
						|
    
 | 
						|
    xfree (s3s);
 | 
						|
    screen->driver = 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
s3CardFini (KdCardInfo *card)
 | 
						|
{
 | 
						|
    S3CardInfo	*s3c = (S3CardInfo *) card->driver;
 | 
						|
    
 | 
						|
    KdUnmapDevice (s3c->frameBuffer, s3c->memory);
 | 
						|
    KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET);
 | 
						|
    xfree (s3c);
 | 
						|
    card->driver = 0;
 | 
						|
}
 | 
						|
 | 
						|
KdCardFuncs	s3Funcs = {
 | 
						|
    s3CardInit,
 | 
						|
    s3ScreenInit,
 | 
						|
    s3InitScreen,
 | 
						|
    s3Preserve,
 | 
						|
    s3Enable,
 | 
						|
    s3DPMS,
 | 
						|
    s3Disable,
 | 
						|
    s3Restore,
 | 
						|
    s3ScreenFini,
 | 
						|
    s3CardFini,
 | 
						|
    s3CursorInit,
 | 
						|
    s3CursorEnable,
 | 
						|
    s3CursorDisable,
 | 
						|
    s3CursorFini,
 | 
						|
    s3RecolorCursor,
 | 
						|
    s3DrawInit,
 | 
						|
    s3DrawEnable,
 | 
						|
    s3DrawSync,
 | 
						|
    s3DrawDisable,
 | 
						|
    s3DrawFini,
 | 
						|
    s3GetColors,
 | 
						|
    s3PutColors,
 | 
						|
};
 |