/*
 * DANG_BEGIN_MODULE
 *
 * Description:
 *   GVGA6400 driver for DOSEMU.  Code taken from SVGALIB. 
 * 
 *   Original driver copyright 1994 Arno Schaefer
 *
 * DANG_END_MODULE
 *
 * $Date: $
 * $Source: $
 * $Revision: $
 * $State: $
 *
 * $Log: $
 */

#include "dosemu.h"
#include "base/port.h"
#include "env/libvga.h"

#include <sys/mman.h>

static void gvga6400_setpage (int page)
{
	page &= 7;
	outb (0x3c4, 6);
	outb (0x3c5, 0x40 | page | (page << 3));
}

static void gvga6400_saveregs(Bit16u *regs)
{
	outb (0x3c4, 6);
	regs[2] = inb (0x3c5);
	outb (0x3c4, 7);
	regs[3] = inb (0x3c5);
	outb (0x3c4, 8);
	regs[4] = inb (0x3c5);
	outb (0x3c4, 0x10);
	regs[5] = inb (0x3c5);
	outb (0x3ce, 9);
	regs[6] = inb (0x3cf);
	outb (0x3d4, 0x2f);
	regs[10] = inb (0x3d5);
}

static void gvga6400_setregs(const Bit16u *regs)
{
	outb (0x3c4, 6);
	outb (0x3c5, regs[2]);
	outb (0x3c4, 7);
	outb (0x3c5, regs[3]);
	outb (0x3c4, 8);
	outb (0x3c5, regs[4]);
	outb (0x3c4, 0x10);
	outb (0x3c5, regs[5]);
	outb (0x3ce, 9);
	outb (0x3cf, regs[6]);
	outb (0x3d4, 0x2f);
	outb (0x3d5, regs[10]);
}

static Boolean gvga6400_init(void)
{
        v_printf("VGA: Using Genoa GVGA 6400 driver.\n");
	return TRUE;
}

static Boolean gvga6400_test(void)
{
  Bit8u *vga_bios;
  int    address;

  vga_bios = (Bit8u *)mmap(0, 4096, PROT_READ, MAP_SHARED, mem_fd, 0xc0000);
  if ((off_t)vga_bios <= 0) {
    v_printf("VGA: ATI mmap failed!\n");
    return FALSE;
  }

	address = vga_bios[0x37];

	if (vga_bios[address] == 0x77 &&
	vga_bios[address + 1] == 0x11 &&
	vga_bios[address + 2] == 0x99 &&
	vga_bios[address + 3] == 0x66)
	{
	  munmap((caddr_t) vga_bios, 4096);
	  return gvga6400_init();
	}

  munmap((caddr_t) vga_bios, 4096);
  return FALSE;
}

static void nothing(void) { }

DriverSpecs gvga6400_driverspecs = {
	"GVGA6400",
	gvga6400_saveregs,
	gvga6400_setregs,
	gvga6400_test,
	gvga6400_init,
	gvga6400_setpage,
	nothing,		/* set_perm */
	nothing,		/* release_perm */
	NULL,
	NULL
}; 

