Date: Mon, 6 Oct 1997 16:18:59 +0200 (MET DST)
From: Juergen Orschiedt <juergen.orschiedt@zx.basf-ag.de>
Subject: L68K: detection of (atari) videohardware
To: linux-m68k@lists.linux-m68k.org
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: juergen.orschiedt@zx.basf-ag.de

This extension allows the autodetection of (well-known) videocards.
It sets a global pointer-array 'detected_videohw[8]' which can be used
by fb-drivers:

typedef struct {
       __u8    Card;           /* card descriptor */
       __u8    Chip;           /* chiptype */
       __u8    RamDac;         /* RAMDAC */
       __u8    Flags;          /* ATARI_VME || MEDUSA_ISA || HADES_ISA ... */
       int     ChipId;         /* detected chip revision */
       char *  CardName;
       __vga_region IOBase;
       __vga_region BaseMem;
       __vga_region ExtMem;
} __vga_fingerprint;

So the drivers theirself doesn't need parameters like 'iobase' or
'basemem' any more.

Commandline-options:

videhw=auto	tries to find the videocard, detect chipset and 	
		mem-regions

videohw=[card=CardName][;iobase=0xX][;basemem=0xX][;extmem=0xX]
	[;gdc=ChipName][;dac=DacName]

In auto-mode a lot of debug-messages are produced...

Juergen

diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/Documentation/Configure.help /usr/src/linux-2.1.57/Documentation/Configure.help
--- /usr/src/clean/linux-2.1.57/Documentation/Configure.help	Fri Oct  3 16:18:31 1997
+++ /usr/src/linux-2.1.57/Documentation/Configure.help	Wed Oct  1 21:18:37 1997
@@ -5956,6 +5956,11 @@
   want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
+Atari Video Hardware detection support
+CONFIG_FB_VIDEOHW_DETECT
+  If you say Y, this option tries to (auto)detect the most common used
+  external video-hardware during startup on Atari-computers.
+
 Amiga builtin serial support
 CONFIG_AMIGA_BUILTIN_SERIAL
   If you want to use your Amiga's built-in serial port in Linux, say
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/Documentation/m68k/kernel-options.txt /usr/src/linux-2.1.57/Documentation/m68k/kernel-options.txt
--- /usr/src/clean/linux-2.1.57/Documentation/m68k/kernel-options.txt	Fri Oct  3 16:11:33 1997
+++ /usr/src/linux-2.1.57/Documentation/m68k/kernel-options.txt	Tue Sep 30 00:13:51 1997
@@ -645,6 +645,54 @@
     can be performed in optimal order. Not all SCSI devices support
     tagged queuing (:-().
 
+4.5) videohw=
+-------------
+
+Syntax: videohw=[card=<videocard>] 
+		videohw=[basemem=<addr>[;iobase=<addr>[;extmem=<addr>]]]
+
+  This option tries to ease the use of external video-cards in Atari-machines.
+  You have to use either the "card="-syntax or the "basemem=..."-syntax.
+  The later one is available for new or undefined cards, but requires a driver
+  which knows about the used hardware (ET4000, Mach64, ProMST, MV300 etc).
+
+4.5.1) card=<videocard>
+
+  One of the following video-extenders:
+
+    Crazy Dots ST, Crazy Dots II, Crazy Dots VME,
+    Gengtec
+    Medusa ET4000, Medusa Mach64,
+    Mega4000,
+	MV300,
+    Nova Imagine, Nova VME-STE, Nova ET4000-STE, Nova ET4000-TT,
+    Nova VME-TT, Nova II+ TT, Nova II+ Falcon, Nova II+ STE,
+    Panther, Panther64,
+    ProMST,
+    Spectrum, Spectrum HC, Spectrum TC,
+    STGA,
+    VoFa
+
+4.5.2) basemem=...
+
+  These parameters are similiar to the corresponding 'external='-parameters.
+The <addr> argument is a hexadecimal number with a '0x' prefix. Use this
+Parameters only if your card isn't cointained by the "card=" option.
+You have to know exactly about your hardware...
+
+  basemem=<addr>
+  This is an important information about the video hardware. It is the
+base address of the video memory.
+
+  iobase=<addr>
+  This parameter is optional. If you have a PC-ISA-card, you have to
+specify this address so that the hardware dependend driver can access
+the GDC special registers.
+
+  extmem=<addr>
+  If you have a PC-ISA-card like Mach32, Mach64, Tseng-W32, you have to
+specify the start of the 'lineare apperture' (extended Memory on ISA-Bus)
+starts.
 
 
 5) Options for Amiga Only:
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/arch/m68k/atari/atari_ksyms.c /usr/src/linux-2.1.57/arch/m68k/atari/atari_ksyms.c
--- /usr/src/clean/linux-2.1.57/arch/m68k/atari/atari_ksyms.c	Wed Apr 16 16:56:51 1997
+++ /usr/src/linux-2.1.57/arch/m68k/atari/atari_ksyms.c	Wed Oct  1 08:36:48 1997
@@ -10,6 +10,7 @@
 
 extern void atari_microwire_cmd( int cmd );
 extern int atari_SCC_reset_done;
+extern void *detected_videohw[];
 
 EXPORT_SYMBOL(atari_mch_cookie);
 EXPORT_SYMBOL(atari_hw_present);
@@ -33,3 +34,5 @@
 EXPORT_SYMBOL(ikbd_mouse_disable);
 
 EXPORT_SYMBOL(atari_microwire_cmd);
+
+EXPORT_SYMBOL(detected_videohw);
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/arch/m68k/atari/config.c /usr/src/linux-2.1.57/arch/m68k/atari/config.c
--- /usr/src/clean/linux-2.1.57/arch/m68k/atari/config.c	Fri Oct  3 16:11:37 1997
+++ /usr/src/linux-2.1.57/arch/m68k/atari/config.c	Mon Sep 29 20:57:33 1997
@@ -87,6 +87,10 @@
 
 static struct console atari_console_driver;
 
+/* filled in by detect_videohw() */
+void *detected_videohw[8] = { NULL, NULL, NULL, NULL,
+					 NULL, NULL, NULL, NULL };
+
 /* Can be set somewhere, if a SCC master reset has already be done and should
  * not be repeated; used by kgdb */
 int atari_SCC_reset_done = 0;

diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/8514a.h /usr/src/linux-2.1.57/drivers/video/8514a.h
--- /usr/src/clean/linux-2.1.57/drivers/video/8514a.h	Thu Jan  1 01:00:00 1970
+++ /usr/src/linux-2.1.57/drivers/video/8514a.h	Fri Sep 19 20:28:35 1997
@@ -0,0 +1,95 @@
+/* tab-width: 4 */
+
+/*
+ * linux/drivers/video/8514a.h		$Revision: 2.6.1.3 $
+ *
+ *   purpose: defines and macros for 8514 and ATI Mach32 Hardware
+ *
+ *    Copyright (C) 1997 J. Orschiedt
+ *
+ *    based on 8514a from svgalib
+ */
+
+#if !defined(__8514a_h__)
+#define __8514a_h__
+
+/*
+ *	0xXXe8:	8514, Mach8 and Mach32
+ *	0xXXee:	Mach8/Mach32
+ */
+
+#define	ATI_IDX			0x01ce		/* ATI special registerset */
+#define ATI_DTA			0x01cf
+
+#define H_TOTAL			0x02e8
+#define H_DISP			0x06e8
+#define H_SYNC_STRT		0x0ae8
+#define H_SYNC_WID		0x0ee8
+#define V_TOTAL			0x12e8
+#define CONF_STAT1		0x12ee
+#define V_DISP			0x16e8
+#define CONF_STAT2		0x16ee
+#define V_SYNC_STRT		0x1ae8
+#define V_SYNC_WID		0x1ee8
+#define DISP_CNTL		0x22e8
+#define CRT_PITCH		0x26ee
+#define CRT_OFFSET_LO	0x2Aee
+#define CRT_OFFSET_HI	0x2eee
+#define LOCAL_CNTL		0x32ee
+#define MISC_OPTIONS	0x36ee
+#define SUBSYS_CNTL		0x42e8
+#define SUBSYS_STAT		0x42e8
+#define MEM_BNDRY		0x42ee
+#define SHADOW_CTL		0x46ee
+#define ADVFUNC_CNTL	0x4ae8
+#define CLOCK_SEL		0x4aee
+#define SCRATCH_PAD_0	0x52ee
+#define SHADOW_SET		0x5aee
+#define MEM_CFG			0x5eee
+#define GE_OFFSET_LO	0x6eee
+#define GE_OFFSET_HI	0x72ee
+#define GE_PITCH		0x76ee
+#define EXT_GE_CONF		0x7aee
+#define MISC_CTL		0x7eee
+#define CUR_Y			0x82e8
+#define CUR_X			0x86e8
+#define DESTY_AXSTP		0x8ae8
+#define SRC_Y			0x8ae8
+#define DESTX_DIASTP	0x8ee8
+#define SRC_X			0x8ee8
+#define R_EXT_GE_CONF	0x8eee
+#define R_MISC_CTL		0x92ee
+#define MAJ_AXIS_PCNT	0x96e8
+#define CMD				0x9ae8
+#define GE_STAT			0x9ae8
+#define EXT_FIFO_STATUS	0x9aee
+#define FRGD_COLOR		0xa6e8
+#define DEST_X_START	0xa6ee
+#define DEST_X_END		0xaaee
+#define DEST_Y_END		0xaeee
+#define R_H_TOTAL		0xb2ee
+#define SRC_X_START		0xb2ee
+#define ALU_BG_FN		0xb6ee
+#define R_H_SYNC_STRT	0xb6ee
+#define BKGD_MIX		0xbae8
+#define FRGD_MIX		0xbae8
+#define ALU_FG_FN		0xbaee
+#define R_H_SYNC_WID	0xbaee
+#define MULTI_FUNC_CNTL	0xbee8
+#define SRC_X_END		0xbeee
+#define R_V_TOTAL		0xc2ee
+#define SRC_Y_DIR		0xc2ee
+#define R_V_DISP		0xc6ee
+#define R_V_SYNC_STRT	0xcaee
+#define SCAN_TO_X		0xcaee
+#define DP_CONFIG		0xceee
+#define R_V_SYNC_WID	0xd2ee
+#define EXT_SCISSOR_L	0xdaee
+#define R_SRC_X			0xdaee
+#define EXT_SCISSOR_T	0xdeee
+#define EXT_SCISSOR_B	0xe6ee
+#define EXT_SCISSOR_R	0xe6ee
+#define DEST_CMP_FN		0xeeee
+#define CHIP_ID			0xfaee
+
+#endif
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/Config.in /usr/src/linux-2.1.57/drivers/video/Config.in
--- /usr/src/clean/linux-2.1.57/drivers/video/Config.in	Fri Oct  3 16:18:22 1997
+++ /usr/src/linux-2.1.57/drivers/video/Config.in	Thu Oct  2 23:49:55 1997
@@ -21,6 +21,9 @@
   fi
   if [ "$CONFIG_ATARI" = "y" ]; then
     bool 'Atari native chipset support' CONFIG_FB_ATARI
+	tristate 'Atari videohw autodetect' CONFIG_FB_VIDEOHW_DETECT
+#	tristate '- not yet - SVGA Frame Buffer support' CONFIG_FB_SVGA
+#   tristate '- not yet - Mach32 Frame Buffer support' CONFIG_FB_MACH32
     tristate 'Mach64 Frame Buffer support' CONFIG_FB_MACH64
   fi 
   tristate 'Virtual Frame Buffer support' CONFIG_FB_VIRTUAL
@@ -37,6 +40,9 @@
     tristate '16 bpp packed pixel support' CONFIG_FBCON_CFB16
     tristate 'Cybervision support (accelerated)' CONFIG_FBCON_CYBER
     tristate 'RetinaZ3 support (accelerated)' CONFIG_FBCON_RETINAZ3
+#   tristate '- not yet - ET4000-W32 support (accelerated)' CONFIG_FBCON_ET4W32
+#   tristate '- not yet - ET6000 support (accelerated)' CONFIG_FBCON_ET6000
+#   tristate '- not yet - Mach32 support (accelerated)' CONFIG_FBCON_MACH32
     tristate 'Mach64 support (accelerated)' CONFIG_FBCON_MACH64
   else
     if [ "$CONFIG_FB_AMIGA" != "n" -o "$CONFIG_FB_ATARI" != "n" -o \
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/Makefile /usr/src/linux-2.1.57/drivers/video/Makefile
--- /usr/src/clean/linux-2.1.57/drivers/video/Makefile	Fri Sep 12 20:41:56 1997
+++ /usr/src/linux-2.1.57/drivers/video/Makefile	Thu Oct  2 23:52:35 1997
@@ -16,7 +16,7 @@
 L_OBJS   :=
 M_OBJS   :=
 LX_OBJS  :=
-MX_OBJS  :=
+MX_OBJS  := 
 MOD_LIST_NAME := VIDEO_MODULES
 
 # Frame buffer devices
@@ -39,6 +39,14 @@
 else
   ifeq ($(CONFIG_FB_ATARI),m)
   M_OBJS += atafb.o
+  endif
+endif
+
+ifeq ($(CONFIG_FB_VIDEOHW_DETECT),y)
+L_OBJS += svgadetect.o
+else
+  ifeq ($(CONFIG_FB_VIDEOHW_DETECT),m)
+  M_OBJS += svgadetect.o
   endif
 endif
 
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/svgadetect.c /usr/src/linux-2.1.57/drivers/video/svgadetect.c
--- /usr/src/clean/linux-2.1.57/drivers/video/svgadetect.c	Thu Jan  1 01:00:00 1970
+++ /usr/src/linux-2.1.57/drivers/video/svgadetect.c	Sun Oct  5 13:49:14 1997
@@ -0,0 +1,1931 @@
+/* tab-width: 4
+ * linux/drivers/video/svgadetect.c		$Revision: 2.6.1.10 $
+ *     purpose: detect a potential SVGA-card in ATARI Computers
+ *
+ * (C) 1997 Jürgen Orschiedt
+ *
+ * inspirated by XFree86 SuperProbe, svgalib and vgadoc4
+ *
+ * Purpose:
+ *    try to detect SVGA-card and set global available variables
+ *    for potential frame buffer drivers.
+ *
+ * SVGAdetect generates an array of __vga_fingerprint (see vgafb.h).
+ * These entry are for the framebuffer-drivers itself.
+ * The drivers itself doesn't need the IOBase etc. parameters anymore.
+ * Instead, they should have parameters to refine f.e. the RamDac-type
+ * and ClockGen if it's impossible to detect them by software.
+ *
+ * Card:
+ *
+ * The Card-Type is required to do the right thing (TM), f.e. to choose
+ * the clock-select method or to do additional memory mappings.
+ *
+ *					Type		IOBase		BaseMem		ExtMem		Chip
+ *	Medusa Mach64	PC_ISA		0x7f100000	0x7f000000	0x7f400000	Mach64
+ *	Medusa ET4000	PC_ISA		0x7f300000	0x7f000000	----		ET4000
+ *	Nova VME-TT		NOVAPLUS	0xfe900000	0xfe800000	0xfea00000	Mach32
+ *	Nova II+ TT		NOVAPLUS	0xfe900000	0xfe800000	0xfec00000	Mach64
+ *  ProMST			PROMST		0xfea40000  0xfea00000  ----		TI34061
+ *	Nova II+ STE	NOVAPLUS	0xfeb00000	0xfea00000  0xfec00000	Mach64 1)
+ *	Crazy Dots II	CRAZYDOTS	0xfebf0000	0xfec00000	----		ET4000 2)
+ *	Panther II		PC_ISA		0xfec00000	0xfec80000	0xfe800000	Mach64 3)
+ *	Nova Imagine	NOVA		0xfecc0000	0xfec00000  ----		ET4000
+ *	STGA			PC_ISA		0x00cf0000	0x00c00000	----		ET4000
+ *	VoFa			PC_ISA		0x00d00000	0x00c00000	----		ET4000 4)
+ *	Panther			PC_ISA		0xfed00000	0xfec00000	----		ET4000 5)
+ *	Spectrum		SPECTRUM	0xfed00000	0xfec00000	----		ET4000 6)
+ *	Nova VME-STE	NOVA		0xfed00000	0xfec00000	0xfea00000	Mach32
+ *	Spectrum TC		SPECTRUM	0xfed80000	0xfec00000	----		ET4000
+ *	Nova ET4000		NOVA		0xfedc0000	0xfec00000	----		ET4000 7)
+ *	Crazy Dots ST	CRAZYDOTS	0xfeff0000	0xfec00000	----		ET4000 8)
+ *  Mega4000		PC_ISA		0xfeff0000	0xfec00000	----		ET4000
+ *  Hades ISA		PC_ISA		0xfff00000	0xff000000	0xff100000	ET4000 9)
+ *
+ *
+ * 1) Nova II+ Falcon is identical
+ *
+ * 2) Crazy Dots VME is identical
+ *
+ * 3) ISA busextender, max. 4MB of video memory
+ *	  the BaseMem 0xfec80000 maps to ISA-Adressbus 0x080000-0x0fffff
+ *	  The ExtMem  0xfe800000 maps to ISA-Adressbus 0x400000-0x7fffff
+ *
+ * 4) Gentec is identical
+ *
+ * 5) For Panther (and also Panther II) are different decoders in work,
+ *    which allows byte-read. The information will be included if the
+ *	  decoder-GAL is official available.
+ *
+ * 6) Spectrum HC is identical
+ *
+ * 7) Nova ET4000-STE and Nova ET4000-TT
+ *
+ * 8) The Mega 4000 has an identical address-mapping
+ *    The difference between these cards is the clock-generation,
+ *    Crazy Dots uses an 8bit wo-register at IOBase,
+ *    the Mega 4000 is a PC-ISA card.
+ *
+ * 9) The IO-Area is 8x64k, 16bit 
+ *	  the area 0xfff30000 is special, 'cause it allows byte-access to
+ *    ISA-hardware (ISA low- and highbyte always to D0-D7)
+ *    The Memory-area occupies the first 8MB of ISA-Memory, so ExtMem
+ *    starts at 0xff100000 (the apperture for accelerated cards)
+ *
+ *	  Hades ISA: either Tseng ET4000 or ATI Mach64
+ *	  Hades PCI: currently not supported
+ *
+ * ProMST: very special, doesn't fit into SVGA-category
+ *	       (no RAMDAC, different IO-Layout (0x001 - 0x101)
+ *
+ * !! On ST(e), we can't distinguish between 0x00d00000 and 0xfed00000,
+ *	  therefore we always use 0xfexxxxxx (doesn't care).
+ *
+ * Cards which are based on ISA-Hardware are always of type PC_ISA.
+ * This information is only required for Clocksetting and special Features
+ * not available on PC Hardware (like Spectrum, Crazy Dots).
+ *
+ * Chip:	identifies the chipset
+ *		currently, the following chipsets will be detected:
+ *
+ *		MV300		based on INMOS G300, (no information available)
+ *		ET4000		the old Tseng ET4000
+ *		ET4000 W32x	the newer one's with buildin accelerator
+ *		Mach32		ATI Mach32
+ *		Mach64		ATI Mach64
+ *
+ * Each other chipset is identified as STDVGA.
+ *
+ * RamDac:	identifies the RAMDAC
+ *		following RAMDACs will be detected:
+ *
+ *		DAC_BLIND6	256 of 6^3 colors
+ *		BLINDW32	256 of 6^3 colors with PLL register bank
+ *		named		different RAMDACs (see vgafb.h)
+ *
+ * The BLINDxxx addresses a misfeature with some ET4000 Boards connected
+ * to ATARI: the odd registers (0x3c7 == PEL_ReadAddr and 0x3c9 == PEL_Data)
+ * always return 0xff insteat of the correct values. This problem also
+ * occures with the PLL-Registerset of GENDACs. It's a hardware-problem of 
+ * the ISA-Atari-Interface. 
+ *
+ * $Log: svgadetect.c,v $
+ * Revision 2.6.1.10  1997/10/03 20:00:03  orschied
+ * - uups - parser is working, but some refinements required...
+ *
+ * Revision 2.6.1.9  1997/10/02 07:30:36  orschied
+ * - changed some variables (detected_svga -> detected_videohw)
+ * - changed parser - iobase & co always work on last cardname
+ *   last card is preset to User Defined
+ *
+ * Revision 2.6.1.8  1997/09/30 21:40:46  orschied
+ * - major changes for parse_cmdline
+ *
+ * Revision 2.6.1.7  1997/09/23 22:25:38  orschied
+ * - started support for commandline-parameter
+ *
+ * 'til Revision 2.6.1.6
+ * - added MFP-based delay-function delay_N_msec
+ * - removed XXXXI2M
+ *   known hardware always requires le32_to_cpu, therefore we don't
+ *   have to distinguish between swapped/non_swapped
+ * - added Romans transparent translation code - no more kernel_map()
+ * - changed default for Mach32:
+ *   on Atari, the default is MACH32I2M which is treatened
+ *   as MACH32 (meaning we always have to do a le16_to..
+ *   or a cpu_to_le16 before/after word-sized output/input.
+ *   May be that NOVA has different behaviour - but currently
+ *   we dont't look at the bytesex (awaiting bug-reports...)
+ * - added timeout during mach32-detect
+ *   lot of test with mach32 hardware, not reported here
+ * - added ChipId to __vga_fingerprint
+ * - added Revision to fingerprint, 'cause we only will have init_func here
+ * - added __vga_fingerprint for MV300 to stay consistent
+ * - cleaned up detect_videohw
+ * # missing:
+ * #   most function should be of type init_func
+ * #   also most data should be of type init_data
+ * #   distinguish between Spectrum/Crazy Dots/PC-ISA
+ * - added (empty) probe_s3() to get rid of compiler warnings
+ * # still missing: distingtion of Spectrum/Crazy Dots/PC-ISA.
+ *   (very soon...)
+ * - additional clean-up
+ * - added skip for shadow-SVGAs
+ * - revise tseng-detection (video-memory looks like W32P)
+ *   a tseng chip also has a RAMDAC - use it to distinguish
+ *	 between RAM and IOBase
+ * - added detect-message in detect_tseng
+ * - removed duplicate fingerprints
+ * - added detect_xxx function
+ * - detect_machXX only if ExtMem available
+ * - changed detection of fingerprint
+ * - support for multiple SVGA-cards 
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include <asm/atarihw.h>
+#include <asm/byteorder.h>
+#include <asm/types.h>
+
+#include "videohw.h"
+#include "vgafb.h"
+#include "8514a.h"
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+#define DEBUG	1
+
+#ifdef DEBUG
+#define debug(text, args...)	printk("SVGAdetect: " text,## args)
+#else
+define debug(text, args...)
+#endif
+
+#define message(text, args...)	printk("SVGAdetect: " text,## args)
+
+/*
+ * modes for addr_accessible
+ */
+#define READ_BYTE	0
+#define READ_WORD	1
+#define WRITE_BYTE	2
+#define WRITE_WORD	3
+
+/* PEL-Addr and Data for testing
+ */
+#define PEL_TSTADDR 128
+#define PEL_TSTDATA 0x1a
+
+/*
+ * global and static variables
+ */
+
+static							/* only required for svgadetect */
+__u8 *ISA_IOBase,
+	 *ISA_BaseMem,
+	 *ISA_ExtMem;
+
+static
+int cards = 0;
+
+/* 
+ * Notes:
+ * the size-field descripes the decoded range of the given region.
+ * It is required to skip phantom-devices and to do the correctly
+ * sized kernel_map. It must be the maximum size of any card with
+ * same fingerprints.
+ *
+ */
+
+static
+__vga_fingerprint fingerprints[] = {
+	{PC_ISA, 0xff, 0, 0, ATARI_VME, "User defined", },		/* filled by driver */
+	{MV300, G300, 0, 0, ATARI_VME, "Atari MV300", },	/* filled by driver */
+
+	{PC_ISA, MACH64, 0, 0, MEDUSA_ISA, "Medusa Mach64",	
+		{(__u8 *)0x7f100000, NULL, 64*1024 },
+		{(__u8 *)0x7f000000, NULL, 1024*1024 },
+		{(__u8 *)0x7f400000, NULL, 4096*1024 }},
+
+	{PC_ISA, ET4000, 0, 0, MEDUSA_ISA, "Medusa ET4000",
+		{(__u8 *)0x7f300000, NULL, 64*1024 },
+		{(__u8 *)0x7f000000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+
+	{NOVAPLUS, MACH32, 0, 0, ATARI_VME, "Nova VME-TT",		
+		{(__u8 *)0xfe900000, NULL, 64*1024 },
+		{(__u8 *)0xfe800000, NULL, 1024*1024 },
+		{(__u8 *)0xfea00000, NULL, 2048*1024 }},
+		   
+	{NOVAPLUS, MACH64, 0, 0, ATARI_VME, "Nova II+ TT",		
+		{(__u8 *)0xfe900000, NULL, 64*1024 },
+		{(__u8 *)0xfe800000, NULL, 1024*1024 },
+		{(__u8 *)0xfec00000, NULL, 4096*1024 }},
+
+	{PROMST, TI34061, 0, 0, ATARI_VME, "ProMST",
+		{(__u8 *)0xfea40000, NULL, 64*1024 },
+		{(__u8 *)0xfea00000, NULL, 256*1024 },
+		{(__u8 *)0x00000000, NULL, 0*1024 }},
+		   
+	{NOVAPLUS, MACH64, 0, 0, ATARI_VME, "Nova II+ STE",	
+		{(__u8 *)0xfeb00000, NULL, 64*1024 },
+		{(__u8 *)0xfea00000, NULL, 1024*1024 },
+		{(__u8 *)0xfec00000, NULL, 4096*1024 }},
+		   
+	{CRAZYDOTS, ET4000, 0, 0, ATARI_VME, "Crazy Dots II",	
+		{(__u8 *)0xfebf0000, NULL, 64*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, MACH64, 0, 0, ATARI_VME, "Panther II",		
+		{(__u8 *)0xfec00000, NULL, 512*1024 },	/* 512kB decoded */
+		{(__u8 *)0xfec80000, NULL, 512*1024 },
+		{(__u8 *)0xfe800000, NULL, 4096*1024 }},
+
+	{NOVA, ET4000, 0, 0, ATARI_VME, "Nova Imagine",	
+		{(__u8 *)0xfecc0000, NULL, 256*1024 },	/* assume 256k decoded */
+		{(__u8 *)0xfec00000, NULL, 768*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, ET4000, 0, 0, ATARI_VME, "STGA",			
+		{(__u8 *)0xfecf0000, NULL, 64*1024 },
+		{(__u8 *)0xfec00000, NULL, 960*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+
+	{SPECTRUM, ET4000, 0, 0, ATARI_VME, "Spectrum",		
+		{(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, ET4000, 0, 0, ATARI_VME, "Panther",		
+		{(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, ET4000, 0, 0, ATARI_VME, "VoFa",		
+		{(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{NOVAPLUS, MACH32, 0, 0, ATARI_VME, "Nova VME-STE",	
+		{(__u8 *)0xfed00000, NULL, 64*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0xfea00000, NULL, 4096*1024 }},
+		   
+	{SPECTRUM, ET4000, 0, 0, ATARI_VME, "Spectrum TC",		
+		{(__u8 *)0xfed80000, NULL, 64*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{NOVA, ET4000, 0, 0, ATARI_VME, "Nova ET4000",	
+		{(__u8 *)0xfedc0000, NULL, 64*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{CRAZYDOTS, ET4000, 0, 0, ATARI_VME, "Crazy Dots ST",	
+		{(__u8 *)0xfeff0000, NULL, 16*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, ET4000, 0, 0, ATARI_VME, "Mega 4000",	
+		{(__u8 *)0xfeff0000, NULL, 16*1024 },
+		{(__u8 *)0xfec00000, NULL, 1024*1024 },
+		{(__u8 *)0x00000000, NULL,    0*1024 }},
+		   
+	{PC_ISA, ET4000, 0, 0, HADES_ISA, "Hades ISA",	
+		{(__u8 *)0xfff00000, NULL,   8*64*1024 },
+		{(__u8 *)0xff000000, NULL,   1024*1024 },
+		{(__u8 *)0xff100000, NULL, 7*1024*1024 }},
+		   
+	{0, }
+};
+
+/*
+ * here we'll hold the detected SVGA descriptions
+ */
+extern __vga_fingerprint *detected_videohw[MAX_SVGA];
+
+char * __initdata known_chips[__NUM_CHIPs] = {
+	"noGDC?",
+	"Standard-VGA",
+	"INMOS-G300",
+	"ET4000", "ET4000-W32", "ET6000",
+	"Mach32",
+	"Mach64",
+	"TI34061"
+};
+
+char * __initdata known_dacs[__NUM_DACs] = {
+	"noDAC?",
+	"Blind 6bit",
+	"Standard",
+	"SS-24", "Sierra-15", "Sierra-15/16", "Sierra-24",
+	"Music-4870", "Music-4910",
+	"ACUMOS",
+	"Cirrus-24",
+	"ATT-490", "ATT-491", "ATT-492", "ATT-493",
+	"EDSUN",
+	"Blind GENDAC",
+	"ET6000",
+	"ICS-5341", "ICS-5301",
+	"ATI-Internal",
+	"ATI-68830", "ATI-68860", "ATI-68875", "ATI-Misc24",
+	"ATT-498", "ATT-408",
+	"CH8398",
+	"IBMRGB525",
+	"IMSG174",
+	"MU9C1880",
+	"STG1700", "STG1702", "STG1703",
+	"TVP3025",
+	"S3",
+	"unknown"
+};
+
+/*
+ * function declarations
+ */
+
+/*
+ * public functions
+ */
+int detect_videohw(char *, int *) ;
+void et4000_key(int) ;
+__u32 measure_vga_vtime(void);
+__u32 wait_for_retrace(void);
+
+/*
+ * init functions
+ */
+static int find_videohw(void) ;
+static int parse_videohw(char *, int *);
+static __inline__ void dac_to_pel(void);
+static __inline__ __u8 trig_dac(void) ;
+static __inline__ __u8 dac_to_comm(void) ;
+static __inline__ __u8 get_dac_comm(void) ;
+
+static int probe_mach32(__vga_fingerprint *) ;
+static int probe_mach64(__vga_fingerprint *) ;
+static int probe_tseng(__vga_fingerprint *) ;
+static int probe_s3(__vga_fingerprint *) ;
+static int probe_mv300(__vga_fingerprint *) ;
+
+static int detect_mach32(__u32 *) ;
+static int detect_mach64(__u32 *) ;
+static int detect_s3(__u32 *) ;
+static int detect_tseng(__u32 *) ;
+
+
+static int detect_blinddac(int) ;
+static int detect_vgadac(int) ;
+static int detect_machdac(int) ;
+static int detect_s3dac(int) ;
+
+static void delay_N_msec(int);
+static char * strtoke(char *, const char *);
+
+static __u8 set_comm(__u8) ;
+static int test_DAC_bit(__u8, __u8, __u8) ;
+static int width8check(void) ;
+
+static int test_fingerprint(__vga_fingerprint *) ;
+static int addr_accessible(volatile void *iobase, int flag) ;
+static void read_pel_reg(__u8, __u8 *) ;
+static void write_pel_reg(__u8, __u8 *);
+
+/* thanks to Roman ... */
+static __inline__ void transp_map_16Marea(caddr_t);
+static __inline__ void transp_map_off(caddr_t);
+
+/*
+ *	Detect the available video hardware
+ *  Set the global variables and give out the informations
+ *  (sometimes a little bit cryptic) on the console.
+ */
+
+__initfunc(int detect_videohw(char *argv, int *ints))
+{
+	int cards;
+
+	message("$Revision: 2.6.1.10 $\n");
+	message("argv=%s\n", argv);
+
+	if (!MACH_IS_ATARI)
+		return -1;			/* we should really use a better returncode */
+	
+	if (argv && strcmp(argv,"auto")) {
+		/* parse the argument string */
+		cards = parse_videohw(argv, ints);
+	} else {
+		cards = find_videohw();
+	}
+
+	if (cards) {
+		int i;
+
+		for (i=0; i < cards; i++) {
+			__vga_fingerprint *fpp = detected_videohw[i];
+
+			message("Found [%d]: IOBase=%p, BaseMem=%p, ExtMem=%p\n"
+					"            Card: %s, Chip: %s Rev. %x, RamDac: %s\n",
+					 i,
+					 fpp->IOBase.phys, fpp->BaseMem.phys, fpp->ExtMem.phys,
+				 fpp->CardName, known_chips[fpp->Chip], fpp->ChipId,
+				 known_dacs[fpp->RamDac & ~(DAC_6_8_PROGRAM | DAC_8BIT)]);
+		}
+	} else 
+		message("no SVGA controller detected!\n");
+	return (cards);
+}
+
+__initfunc(int find_videohw(void))
+{
+	__vga_fingerprint *vfp = fingerprints + 1;
+	caddr_t next_possible = NULL;
+	/* try to detect the hardware addresses */
+	for (vfp=fingerprints +1; vfp->Chip; vfp++) {
+		if (vfp->IOBase.phys < next_possible) {
+			debug("skip possible shadow at %p\n",
+				  vfp->IOBase.phys);
+			continue;
+		}
+
+		if (vfp->Card == MV300) {
+			if (probe_mv300(vfp)) {
+				detected_videohw[cards++] = vfp;
+				next_possible = vfp->IOBase.phys + vfp->IOBase.size;
+			}
+			continue;
+		}
+
+		if (test_fingerprint(vfp) && (cards < MAX_SVGA)) {
+			/* we've found a region which may be a SVGA-adaptor.
+			 * Now, let's look if it's really a SVGA
+			 */
+
+		debug("%s: 0x%p:%d, 0x%p:%d, 0x%p:%d\n",
+				vfp->CardName,
+				vfp->IOBase.phys, vfp->IOBase.size/1024,
+				vfp->BaseMem.phys, vfp->BaseMem.size/1024,
+				vfp->ExtMem.phys, vfp->ExtMem.size/1024);
+
+		ISA_IOBase = vfp->IOBase.phys;
+		ISA_BaseMem= vfp->BaseMem.phys;
+		ISA_ExtMem = vfp->ExtMem.phys;
+
+		/* for medusa, we don't have kernel_maps at this point.
+		 * In this case, we have to map transparently.
+		 */
+
+		if ((vfp->Flags & MEDUSA_ISA) && is_medusa)
+			transp_map_16Marea(vfp->BaseMem.phys);
+
+		if (probe_mach32(vfp) || probe_mach64(vfp) ||
+			probe_s3(vfp)	  || probe_tseng(vfp))  {
+			detected_videohw[cards++] = vfp;
+			next_possible = vfp->IOBase.phys + vfp->IOBase.size;
+		}
+
+		if ((vfp->Flags & MEDUSA_ISA) && is_medusa) 
+			transp_map_off(vfp->BaseMem.phys);
+		}
+	}
+	return (cards);
+}
+
+__initfunc(int parse_videohw(char *argv, int *ints))
+{
+	char *arg;
+	__vga_fingerprint *vfp = fingerprints;
+
+	for (arg = strtoke(argv, ";"); arg ; arg = strtoke(NULL, ";")) {
+
+		message("parse_videohw: arg=%s\n", arg);
+
+		if (!strncmp(arg, "card=", 5)) {
+			__vga_fingerprint *lvfp;
+
+			arg += 5;
+
+			for (lvfp=fingerprints; lvfp->Card; lvfp++) {
+				if (!strcmp(arg, lvfp->CardName)) {
+					if (lvfp->Card == MV300)
+						if (!probe_mv300(lvfp))
+							continue;
+
+					detected_videohw[cards++] = vfp = lvfp;
+					break;
+				}
+			}
+			continue;
+		}
+
+		if (!strncmp(arg, "basemem=", 8)) {
+			arg += 8;
+			vfp->BaseMem.phys = (caddr_t) simple_strtoul(arg, NULL, 0);
+			vfp->BaseMem.size = 1024 * 1024;
+
+			/* allow 'card=basemem=<>' as shortcut for 'User defined' */
+			if (!cards)
+				detected_videohw[cards++] = vfp;
+
+			continue;
+		}
+
+		if (!strncmp(arg, "iobase=", 7)) {
+			arg += 7;
+			vfp->IOBase.phys = (caddr_t) simple_strtoul(arg, NULL, 0);
+			vfp->IOBase.size = 64 * 1024;
+			continue;
+		}
+
+		if (!strncmp(arg, "extmem=", 7)) {
+			arg += 7;
+			vfp->ExtMem.phys = (caddr_t) simple_strtoul(arg, NULL, 0);
+			vfp->ExtMem.size = 4 * 1024 * 1024;
+			continue;
+		}
+
+		if (!strncmp(arg, "gdc=", 4)) {
+			int gdc=0;
+			arg += 4;
+
+			for (gdc=1; gdc < __NUM_CHIPs; gdc++)
+				if (!strcmp(arg, known_chips[gdc])) {
+					vfp->Chip = gdc;
+					vfp->ChipId = 0;
+				}
+			continue;
+		}
+
+		if (!strncmp(arg, "dac=", 4)) {
+			int dac=0;
+			arg += 4;
+
+			for (dac=1; dac < __NUM_DACs; dac++)
+				if (!strcmp(arg, known_dacs[dac]))
+					vfp->RamDac = dac;
+			continue;
+		}
+	}
+	return (cards);
+}
+
+/* -------------------------------------------------------------------
+ * probe for different graphic chips and boards.
+ * ------------------------------------------------------------------- */
+
+__initfunc(static
+int probe_mach32(__vga_fingerprint *vfp))
+{
+	int result = 0;
+
+	if (!vfp->IOBase.phys)
+		return result;
+
+	if (1 || vfp->ExtMem.size) {
+		if ((result = detect_mach32(&vfp->ChipId))) {
+			int ramdac;
+
+			vfp->Chip = result;
+			if ((ramdac = detect_machdac(result)) ||
+				(ramdac = detect_vgadac(result)))
+				vfp->RamDac = ramdac;
+		}
+	}
+	return result;
+}
+
+__initfunc(static
+int probe_mach64(__vga_fingerprint *vfp))
+{
+	int result = 0;
+
+	if (!vfp->IOBase.phys)
+		return result;
+
+	if (vfp->ExtMem.size) {
+		if ((result = detect_mach64(&vfp->ChipId))) {
+			int ramdac;
+
+			vfp->Chip = result;
+			if ((ramdac = detect_machdac(result)) ||
+				(ramdac = detect_vgadac(result)))
+				vfp->RamDac = ramdac;
+		}
+	}
+	return result;
+}
+
+__initfunc(static
+int probe_s3(__vga_fingerprint *vfp))
+{
+	int result = 0;
+
+	if (!vfp->IOBase.phys)
+		return result;
+
+	if (vfp->ExtMem.size) {
+		if ((result = detect_s3(&vfp->ChipId))) {
+			int ramdac;
+
+			vfp->Chip = result;
+			if ((ramdac = detect_vgadac(result)) ||
+				(ramdac = detect_s3dac(result)))
+				vfp->RamDac = ramdac;
+		}
+	}
+	return result;
+}
+
+__initfunc(static
+int probe_tseng(__vga_fingerprint *vfp))
+{
+	int result = 0;
+
+	if (!vfp->IOBase.phys)
+		return result;
+
+	if ((result = detect_tseng(&vfp->ChipId))) {
+		int ramdac;
+
+		vfp->Chip = result;
+		if ((ramdac = detect_blinddac(result)) ||
+		    (ramdac = detect_vgadac(result)))
+		   vfp->RamDac = ramdac;
+
+		if ((vfp->Card == SPECTRUM) ||
+			(vfp->Card == CRAZYDOTS)) {
+			/* lots of cards, distinguish via Clock Selection */
+			debug("missing: distinguish class\n");
+		}
+
+		message("IOBase=%p, BaseMem= %p, ExtMem=%p\n"
+			   "            architecture=%s, chip=%s, ramdac=%s\n",
+				vfp->IOBase.phys, vfp->BaseMem.phys, vfp->ExtMem.phys,
+				vfp->CardName,
+				known_chips[vfp->Chip],
+				known_dacs[vfp->RamDac & ~(DAC_6_8_PROGRAM | DAC_8BIT)]);
+	}
+	return result;
+}
+
+/* ------------------------------------------------- */
+
+/* !! I have the following informations about MV300:
+ * STe:		ISA_IOBase = 0xdf?001	(?=0..f)
+ *			IRQ_Vector = 0xdf?801	(?=0..f)
+ *			ISA_BaseMem= 0x?00000	(?=a..c)
+ * TT:		ISA_IOBase = 0xfeff?001	(?=0..f)
+ *			IRQ_Vector = 0xfeff?801	(?=0..f)
+ *			ISA_BaseMem= 0xfe?00000 (?=0..f)
+ *
+ * The MV300 generates an AutoIRQ with Level 4 on each VSYNC pulse.
+ * Allows 1bpp, 2bpp, 4bpp, 8bpp, 16bpp, 32bpp, all packed formats.
+ * Sorry, but no additional info's about registers etc.
+ */
+__initfunc(static
+int probe_mv300(__vga_fingerprint *fpp))
+{
+	caddr_t iobase, basemem, extmem;
+	iobase = basemem = extmem = 0;
+
+	if ((atari_mch_cookie & (ATARI_MCH_STE << 16)) ||
+		(atari_mch_cookie & (ATARI_MCH_TT  << 16))) {
+		caddr_t irq_vector;
+
+		message("looking for MV300...\n");
+
+		irq_vector = (atari_mch_cookie & (ATARI_MCH_TT << 16)) ?
+					 (caddr_t)0xfeff0801 : (caddr_t)0xfedf0801;
+		for (; (__u32)irq_vector & 0x000f0000; irq_vector += 0x1000)
+			if (addr_accessible(irq_vector, READ_BYTE))
+				break;
+
+		if ((__u32)irq_vector & 0x000f0000) {
+			/* do some additional checking */
+			__u8 vector, newvector;
+			__u32 flags;
+
+			save_flags(flags);
+			cli();
+			vector	  = *irq_vector; *irq_vector = ~vector;
+			newvector = *irq_vector; *irq_vector = vector;
+			restore_flags(flags);
+
+			if (vector == ~newvector) {
+				/* scan for video memory */
+				caddr_t lowbase, highbase;
+				iobase = (caddr_t)((__u32)irq_vector & 0xfffff000);
+				if (atari_mch_cookie & (ATARI_MCH_TT << 16)) {
+					lowbase = (caddr_t)0xfe000000;
+					highbase= (caddr_t)0xff000000;
+				} else {
+					lowbase = (caddr_t)0xfea00000;
+					highbase= (caddr_t)0xfed00000;
+				}
+				for (irq_vector =lowbase; irq_vector < highbase;
+					 irq_vector+= 0x00100000)
+					if (addr_accessible(irq_vector, WRITE_WORD) &&
+						addr_accessible(irq_vector+0x80000, WRITE_WORD) &&
+						addr_accessible(irq_vector+0xffffe, WRITE_WORD)) {
+							basemem = irq_vector;
+							break;
+					}
+			}
+		}
+		if (basemem && iobase) {
+			message("probe_mv300: IOBase=0x%p, BaseMem=0x%p\n",
+					 iobase, basemem);
+			fpp->IOBase.phys = iobase;  fpp->IOBase.size = 64 * 1024;
+			fpp->BaseMem.phys= basemem; fpp->BaseMem.size= 1024 * 1024;
+			return MV300;
+		}
+	}
+	return 0;
+}
+
+/* Code based on ATI Documentation - not tested
+ * We'll only distinguish between Mach32 and Mach64 - i didn't hear
+ * about 8514 or Mach8 Cards for Atari.
+ */
+
+__initfunc(static
+__inline__ __u16 mach32_waitq(void))
+{
+	__u16 tmp;
+	int i;
+
+	if ((tmp = inpw(0x9aee)) == 0xffff)
+		for (i=0; i < 800000; i++)
+			if (!(tmp=inpw(0x9aee)))
+				break;
+	return tmp;
+}
+
+__initfunc(static
+void detect_ati_id(void))
+{
+	static __u8 id_u8[10];
+	__u16 *id_u16 = (__u16 *)id_u8;
+	__u32 *id_u32 = (__u32 *)id_u8;
+
+	static __u8* ati_id = "761295520";	/* well defined */
+	       __u8 *ati_id_addr = ISA_BaseMem + 0xc0000 + 0x30;
+
+	int i;
+
+	/* byte test */
+	for (i=0; i < 10; i++)
+		id_u8[i] = ati_id_addr[i];
+	debug("detect_ati_id: byte: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+		id_u8[0],id_u8[1],id_u8[2],id_u8[3],id_u8[4],
+		id_u8[5],id_u8[6],id_u8[7],id_u8[8],id_u8[9]);
+
+	/* word test */
+	for (i=0; i < 5; i++)
+		id_u16[i] = ((__u16 *)ati_id_addr)[i];
+	debug("detect_ati_id: word: %04x%04x%04x%04x%04x\n",
+		id_u16[0], id_u16[1], id_u16[2], id_u16[3], id_u16[4]);
+
+
+	/* long test */
+	for (i=0; i < 3; i++)
+		id_u32[i] = ((__u32 *)ati_id_addr)[i];
+	debug("detect_ati_id: long: %08x%08x%08x\n",
+		id_u32[0], id_u32[1], id_u32[2]);
+}
+
+__initfunc(static int detect_mach32(__u32 *rev))
+{
+	int chip = 0;
+	__u16 tmp, chipid = 0;
+
+#define W_STATE_ENA	( 1 <<  0)
+#define HOST_8_ENA	( 0 <<  1)
+#define MEM_SIZE_ALIAS ( 2 << 2)
+#define DISABLE_VGA	( 1 <<  4)
+#define IO_16_BIT	( 1 <<  5)
+
+	message("looking for ATImach32 chipset ...\n");
+
+	outb(0x102, 1);		/* enable card */
+	/* 16bit 8514, enable VGA, 2MB, 16bit Host, waitstate disable */
+	outw(0x36ee, le16_to_cpu(0x1000 | IO_16_BIT | DISABLE_VGA | MEM_SIZE_ALIAS
+									| HOST_8_ENA | W_STATE_ENA ));
+	outb(0x1ce, 0xa0); outb(0x1cf, 0x18);
+	outb(0x1ce, 0xa3); outb(0x1cf, 0x07);
+
+	detect_ati_id();
+
+	/* ATI Application Note APPL0003-01
+	 * Detecting the Mach32 video adapter
+	 *
+	 * Check for existence of EXT_FIFO_STATUS register.
+	 * This register is needed to wait for engine idle between SRC_X checks.
+	 * If the register does not exist, an FFFFh will be read.
+	 * This is also the value read back if the register exists and the engine
+	 * FIFO is full (all 16 bit entries are set to 1).
+	 * Therefore, if FFFFh is read the first time, wait for about
+	 * 200 milliseconds (for the FIFO is clear) and read the register again.
+	 */
+	
+	tmp = mach32_waitq();
+
+	if (tmp != 0xffff) {
+		__u16 pattern;
+		char *notfndmsg="mach32: response to outw(0x8ee8,0x%x)=0x%04x\n";
+
+		/* reset the engine */
+		outw(0x42e8, cpu_to_le16(0x9000));
+		outw(0x42e8, cpu_to_le16(0x500f));
+
+		/* write 555h to SRC_X register. This register is read from R_SRC_X. */
+		pattern=0x555;
+		outw(0x8ee8, cpu_to_le16(pattern));
+
+		/* wait for engine idle */
+		tmp = mach32_waitq();
+
+		/* attempt to read 555h from SRC_X register value (R_SRC_X) */
+		tmp = le16_to_cpu(inpw(0xdaee));
+
+		if (tmp == pattern) {
+			/* write 2AAh to SRC_X register */
+			pattern=0x2aa;
+			outw(0x8ee8, cpu_to_le16(pattern));
+
+			/* wait for engine idle */
+			tmp = mach32_waitq();
+
+			/* attempt to read 2AAh from SRC_X register value (R_SRC_X) */
+			tmp = le16_to_cpu(inpw(0xdaee));
+			if (tmp == pattern) {
+				chip = MACH32;
+			} else
+				printk(notfndmsg, pattern, tmp);
+		}
+		else
+			printk(notfndmsg, pattern, tmp);
+	}
+	if (chip) {
+		chipid = le16_to_cpu(inpw(0xfaee));
+		message("ATI %s, Type = %04x, Class = %02x, Rev.= %02x\n",
+				known_chips[chip],
+				chipid & 0x3ff, (chipid >> 10) & 0x03, chipid >> 12);
+		*rev = (__u32) chipid;
+	}
+	return chip;
+}
+
+__initfunc(static int detect_mach64(__u32 *rev))
+{
+	int chip = 0;
+	__u16 tmp;
+
+	__u32 scratch0, chipid=0,
+		  byteswap, longswap;
+
+	message("looking for ATImach64 chipset ...\n");
+
+	scratch0 = le32_to_cpu(inpl(0x42ec));
+	outl(0x42ec, cpu_to_le32(0x5555aaaa));
+	if (inpl(0x42ec) == cpu_to_le32(0x5555aaaa)) {
+		outl(0x42ec, cpu_to_le32(0xaaaa5555));
+		if (inpl(0x42ec) == cpu_to_le32(0xaaaa5555)) {
+
+			chipid = le32_to_cpu(inpl(0x6eec));
+			debug("scratch0: 0x55/0xaa passed\n");
+			debug("chipid = %08x\n", chipid);
+			/* try to get bytesex information 
+			 * We're using PEL_ReadAddr/PEL_Command and Dac_Regs:
+				<0x5eec> == <0x3c8> (PEL_WriteAddr)
+				<0x5eed> == <0x3c9> (PEL_Data)
+				<0x5eee> == <0x3c6> (PEL_Mask)
+				<0x5eef> == <0x3c7> (PEL_ReadAddr)
+			 */
+
+			tmp = inpb(0x3c6);		/* PEL_Mask */
+
+			/* most of the Mach64 registers are accessed via outl/inpl.
+			 * As an exception Dac_Regs may be accessed bytewise.
+			 * Therefore we use Dac_Regs to check if le32_to_cpu is necessary.
+			 */
+
+			outb(0x3c6, 0x1a); outb(0x3c8, 0xe5);
+			byteswap = inpb(0x5eec) << 24 | inpb(0x5eee) <<  8;
+
+			if (byteswap == 0xe5001a00) {
+				outb(0x3c6, 0x1a); outb(0x3c8, 0xe5);
+				longswap = inpl(0x5eec);
+
+				debug("bytesex: rdbyte: %08x, rdlong: %08x\n",
+					   byteswap, longswap);
+
+				if ((byteswap && longswap) == byteswap)
+					chip = MACH64;
+			}
+
+			outb(0x3c6, tmp);		/* restore Mask */
+		}
+	}
+	outl(0x42ec, cpu_to_le32(scratch0));
+
+	if (chip) {
+		message("ATI %s, Type: %04x, Class: %02x, Rev: %02x\n",
+				known_chips[chip],
+				chipid & 0xffff, (chipid >> 16) & 0xff, chipid >> 24);
+		*rev = (__u32) chipid;
+	}
+	return chip;
+}
+
+/*
+ * need at least a S3 ISA-Board to start the coding
+ */
+__initfunc(static int detect_s3(__u32 *rev))
+{
+	int chip = 0;
+
+	return chip;
+}
+
+__initfunc(static int detect_tseng(__u32* rev))
+{
+	__u8 hercules, modectrl,
+		 cur, new, tmp, tmp1,
+		 test[3] = {PEL_TSTDATA, PEL_TSTDATA, PEL_TSTDATA};
+	__u32 modectrl_reg;
+
+	int chip = 0;
+
+	*rev = 0;
+	modectrl_reg = (inpb(GREG_MISC_OUTPUT_R) & 0x01) ? 0x3d8 : 0x3b8;
+
+	hercules = inpb(0x3bf);
+	modectrl = inpb(modectrl_reg);
+
+	outb(0x3bf, 0x03); outb(modectrl_reg, 0xa0);
+
+	/* check if we have a RAMDAC at 0x3c6 - 0x3c9
+	 * we use the auto-increment-feature of the PELAddr 
+	 * due to the blinddac-problem we have to overwrite one PEL.
+	 */
+
+	tmp = inpb(0x3c6);
+	cur = inpb(0x3c8);		/* save PelRdAddr */
+	read_pel_reg(PEL_TSTADDR, test);
+	tmp1 = inpb(0x3c6);
+	new = inpb(0x3c8);
+
+	if ((new != (PEL_TSTADDR +1)) && (new != (PEL_TSTADDR +2))) {
+		debug("detect_tseng: pel[%02x]={%02x,%02x,%02x}, addr=%02xr/%02xw\n",
+			PEL_TSTADDR, test[0], test[1], test[2], tmp1, new);
+		outb(0x3c8, cur);		/* restore prev. value */
+		return chip;			/* nothing! */
+	}
+
+	/* check if SegmentSelect{0:5} is writable */
+	cur = inpb(0x3cd);
+	outb(0x3cd, cur & ~ 0x3f); new = inpb(0x3cd) & 0x3f;
+	outb(0x3cd, cur |   0x3f); tmp = inpb(0x3cd) & 0x3f;
+	outb(0x3cd, cur);
+
+	if (tmp == 0x3f && new == 0x00) {
+		/* it's at least an ET3000
+		 * - the ET4000 has an ext. start address register at CRTC IDX 0x33 */
+
+		cur = crt_r(0x33);
+		crt_wb(0x33, cur & ~0x0f); new = crt_r(0x33) & 0x0f;
+		crt_wb(0x33, cur |  0x0f); tmp = crt_r(0x33) & 0x0f;
+		crt_wb(0x33, cur);
+
+		if (tmp == 0x0f && new == 0x00) {
+			/* it's at least an ET4000
+			 * - the W32's have a second segment select register at 0x3cb */
+#if DEBUG
+			printk(" - ET4000");
+#endif
+			cur = inpb(0x3cb);
+			outb(0x3cb, cur &~0x33); new = inpb(0x3cb) & 0x33;
+			outb(0x3cb, cur | 0x33); tmp = inpb(0x3cb) & 0x33;
+			outb(0x3cb, cur);
+
+			if (tmp == 0x33 && new == 0x00) {
+				__u8 chipid = 0;
+
+				chip = ET4000W32;
+
+				outb(0x217a, 0xec);
+				chipid = inpb(0x217b) >> 4;
+				*rev = (__u32) chipid;
+
+#if DEBUG
+				switch (chipid) {
+					case 0x00:
+								printk(" - ET4000W32");
+								break;
+					case 0x01:
+								printk(" - ET4000W32I");
+								break;
+					case 0x02:
+								printk(" - ET4000W32P/a");
+								break;
+					case 0x03:
+								printk(" - ET4000W32I/b");
+								break;
+					case 0x05:
+								printk(" - ET4000W32P/b");
+								break;
+					case 0x06:
+								printk(" - ET4000W32P/d");
+								break;
+					case 0x07:
+								printk(" - ET4000W32P/c");
+								break;
+					case 0x0b:
+								printk(" - ET4000W32I/c");
+								break;
+					default:
+								printk(" - ET4000W32/%d", *rev);
+								break;
+				}
+#endif
+			} else
+				chip = ET4000;
+		}
+	}
+	outb(modectrl_reg, modectrl); outb(0x3bf, hercules);
+#if DEBUG
+	printk("\n");
+#endif
+	return chip;
+}
+
+/* -------------------------------------------------------------------
+ *    Try to detect the RAMDAC
+ *  Parts based on XFree86 SuperProbe:RamDac.c
+ *
+ *  I encountered some problems, at least with the ET4000 cards i own:
+ *  the odd RAMDAC registers always return 0xff. There seems no possi-
+ *  bility to read back the PEL and, with new GENDACs, the PLL register.
+ *
+ * ------------------------------------------------------------------- */
+__initfunc(static int detect_blinddac(int chip))
+{
+	__u8 dacmask, peladdr, pel[3],
+		 newmask, newaddr, new[3],
+		 test[3] = {PEL_TSTDATA, PEL_TSTDATA, PEL_TSTDATA};
+
+	debug("detect_blinddac: chip=%s\n", known_chips[chip]);
+
+	/* check RAMDAC mask and RAMDAC WrPelAddr - should be readable */
+	dacmask = inpb(0x3c6); outb(0x3c6, ~dacmask);
+	newmask = inpb(0x3c6); outb(0x3c6, dacmask);
+
+	peladdr = inpb(0x3c8); outb(0x3c8, ~peladdr);
+	newaddr = inpb(0x3c8); outb(0x3c8, peladdr);
+
+	if ((dacmask != (__u8)~newmask) || (peladdr != (__u8)~newaddr)) {
+		/* uuups - there's something wrong */
+		message("detect_blinddac: can't read PELMask/PELWrAddr\n");
+		message("   dacmask=%02x, newmask=%02x, peladdr=%02x, newaddr=%02x\n",
+				dacmask, newmask, peladdr, newaddr);
+		/* seems a very blind DAC - or another architectur? */
+		return 0;
+	}
+
+	/* ok, at least PELMask and PELWrAddr are r/w.
+	 */
+
+	newaddr = inpb(0x3c8);		/* clear DACstate */
+	peladdr = inpb(0x3c7);
+
+	read_pel_reg(PEL_TSTADDR, pel);	/* save current state */
+	write_pel_reg(PEL_TSTADDR, test);
+	read_pel_reg(PEL_TSTADDR, new);
+	write_pel_reg(PEL_TSTADDR, pel);
+
+	debug("detect_blinddac: pel.red=%02x, pel.green=%02x, pel.blue=%02x\n"
+		  "                 new.red=%02x, new.green=%02x, new.blue=%02x\n",
+		  pel[0], pel[1], pel[2], new[0], new[1], new[2]);
+
+	if ((new[0] != test[0]) ||
+	    (new[1] != test[1]) ||
+	    (new[2] != test[2])) {
+
+		/* looks like a blind one - may be also a GENDAC... */
+
+		debug("detect_blinddac: RAMDAC is blind, testing for GENDAC\n");
+		if (chip == ET4000W32) {
+			__u8 crti31, tmpmask, tmpaddr;
+
+			/* most ET4000W32 boards use CS3 for RS2 */
+			crti31 = crt_r(0x31);			/* get gpp register (CS3,CS4) */
+			dacmask = inpb(0x3c6); peladdr = inpb(0x3c8);
+
+			crt_wb(0x31, crti31 | 0x40);	/* set RAMDAC RS2 */
+			newmask = inpb(0x3c6); newaddr = inpb(0x3c8);
+			crt_wb(0x31, crti31);			/* reset RS2 */
+
+			outb(0x3c6, ~newmask); outb(0x3c8, ~newaddr);
+
+			crt_wb(0x31, crti31 | 0x40);	/* set RAMDAC RS2 */
+			tmpmask = inpb(0x3c6); tmpaddr = inpb(0x3c8);
+			crt_wb(0x31, crti31);
+
+			outb(0x3c6, dacmask); outb(0x3c8, peladdr);
+
+			debug("detect_blinddac: dacmask=%02x, newmask=%02x, tmpmask=%02x\n"
+				  "                 peladdr=%02x, newaddr=%02x, tmpaddr=%02x\n",
+					dacmask, newmask, tmpmask, peladdr, newaddr, tmpaddr);
+			if ((newmask == tmpmask) && (newaddr == tmpaddr)) {
+				debug("detect_blinddac: seems a blind GENDAC\n");
+				return BLINDW32;
+			}
+		}
+		return DAC_BLIND6;
+	}
+	return 0;
+}
+
+__initfunc(static int detect_vgadac(int chip))
+{
+	__u8 x, y, z, u, v, oldcomm, oldpel, notcomm, tmp;
+	int  dac8, dac8now, ramdac=0;
+
+	debug("detect_vgadac: chip=%s\n", known_chips[chip]);
+
+	if (chip == ET6000)
+		return DAC_ET6000;
+
+	if (chip == ET4000W32) {
+		__u32 clock01, clock23;
+		__u8 vsconf1, cr31, lut[6];
+		__u8 *clk01=(__u8 *)&clock01,
+			 *clk23=(__u8 *)&clock23;
+		int i;
+
+		et4000_key(1);
+
+		cr31=crt_r(0x31);
+		vsconf1 = crt_r(0x36);
+
+		debug("looking for ET4000W32 RAMDAC (vsconf=%02x)...\n", vsconf1);
+
+		crt_wb(0x31, cr31 & ~0x40);		/* clear CS3 */
+		crt_wb(0x36, vsconf1^0x80);		/* select 8bit I/O */
+
+		outb(0x3c7, 0);
+		for (i=0; i < 6; i++) {
+			lut[i] = inpb(0x3c9);		/* save lut{0,1} */
+		}
+		debug("ramdac: LUT regs (0,1): %02x%02x%02x, %02x%02x%02x\n",
+			lut[0],lut[1],lut[2],lut[3],lut[4],lut[5]);	
+		outb(0x3c8, 0);
+		for (i=0; i < 6; i++) {
+			outb(0x3c9, 0);				/* clear lut{0,1} */
+		}
+
+		/* try to read PLL registers */
+		crt_wb(0x31, cr31 | 0x40);		/* set CS3 */
+
+		outb(0x3c7, 0);
+		for (i=0; i < 4; i++) {
+			clk01[i]  = inpb(0x3c9);
+		}
+		for (i=0; i < 4; i++) {
+			clk23[i] =  inpb(0x3c9);
+		}
+
+		debug("ramdac: PLL regs (CS3): %4x, %4x, %4x, %4x\n",
+				clock01 >>16, clock01 &0xffff, clock23 >>16, clock23 &0xffff);
+		/* restore lut{0,1} */
+
+		crt_wb(0x31, cr31 & ~0x40);
+
+		outb(0x3c8, 0);				/* select PEL write */
+		for (i=0; i < 6; i++)
+			outb(0x3c9, lut[i]);
+
+		crt_wb(0x31, cr31);				/* restore cr31 */
+		if (clock01 != 0x00) {
+			/* seems we found something... */
+			dac_to_pel();
+			if ((trig_dac() & 0xf0) == 0xb0)
+				ramdac = DAC_ICS5341;
+			else
+				ramdac = DAC_ICS5301;
+			dac_to_pel();
+		}
+		crt_wb(0x36, vsconf1);			/* restore IO rw-size */
+		et4000_key(0);
+		return ramdac;
+	}
+
+	/*
+	 * Save current state.
+	 */
+	(void) dac_to_comm();
+	oldcomm = inpb(0x3c6);
+	dac_to_pel();
+	oldpel = inpb(0x3c6);
+
+	/*
+	 * Do 8-bit-wide check.
+	 */
+	(void) dac_to_comm();
+	outb(0x3c6, 0x00);
+	dac8 = width8check();
+	dac_to_pel();
+
+	/*
+	 * Check whether this DAC has a HiColor-style command register.
+	 */
+	notcomm = ~oldcomm;
+	outb(0x3c6, notcomm);
+	(void) dac_to_comm();
+	v = inpb(0x3c6);
+	if (v != notcomm) {
+	    /* Check for early-generation HiColor-style DAC.  */
+	    if ((set_comm(0xe0) & 0xe0) != 0xe0) {
+			dac_to_pel();
+			x = inpb(0x3c6);
+			do {
+				/* Wait for same value twice.  */
+				y = x;
+				x = inpb(0x3c6);
+			} while (x != y);
+			z = x;
+			u = dac_to_comm();
+			if (u != 0x8e) {
+				/* If command register is 0x8E, we've got an SS24; */
+				y = 8;
+				do {
+					x = inpb(0x3c6);
+					y--;
+				} while ((x != 0x8e) && (y != 0));
+			} else
+				x = u;
+			if (x == 0x8e)
+				ramdac = DAC_SS24;
+			else
+				ramdac = DAC_SIERRA15;
+			dac_to_pel();
+	    } else {
+			/* New generation of advanced DACs */
+			if ((set_comm(0x60) & 0xE0) == 0x00) {
+				/* AT&T 20C490/20C493 */
+				if ((set_comm(0x02) & 0x02) != 0x00)
+					ramdac = DAC_ATT490 | DAC_6_8_PROGRAM;
+				else
+					ramdac = DAC_ATT493;
+			} else {
+				x = set_comm(oldcomm);
+				if (inpb(0x3C6) == notcomm)
+					if (set_comm(0xff) != 0xff)
+						ramdac = DAC_ACUMOS;
+					else {
+						(void) width8check();
+						dac_to_comm();
+						tmp = inpb(0x3c6);
+						dac_to_comm();
+						outb(0x3c6, (tmp | 0x02) & 0xfe);
+						dac8now = width8check();
+						if (dac8now)
+							if (width8check())
+								ramdac = DAC_ATT491 | DAC_6_8_PROGRAM;
+							else
+								ramdac = DAC_CIRRUS24;
+						else
+							ramdac = DAC_ATT492;
+		    } else
+				if (trig_dac() == notcomm)
+					ramdac = DAC_CIRRUS24;
+				else {
+					dac_to_pel();
+					outb(0x3C6, 0xFF);
+					switch (trig_dac()) {
+						case 0x44:
+							ramdac = DAC_MUSIC4870;
+							break;
+						case 0x82:
+							ramdac = DAC_MUSIC4910;
+							break;
+						case 0x8E:
+							ramdac = DAC_SS24;
+							break;
+						default:
+							if (test_DAC_bit(0x10,oldcomm,oldpel))
+								ramdac = DAC_SIERRA24 | DAC_6_8_PROGRAM;
+							else if (test_DAC_bit(0x04,oldcomm,oldpel))
+								ramdac = DAC_UNKNOWN;
+							else
+								ramdac = DAC_SIERRA15_16;
+							break;
+						}
+					}
+		    }
+		}
+	    dac_to_comm();
+	    outb(0x3c6, oldcomm);
+	}
+	dac_to_pel();
+	outb(0x3c6, oldpel);
+
+	/* If no special DAC found, check for the EDSUN DAC. */
+	if (ramdac == DAC_STANDARD) {
+	    /* Write "CEGEDSUN" + mode to DAC index 0xde (222) */
+	    wait_for_retrace();
+	    outb(0x3c8, 0xde);
+	    outb(0x3c9, (__u8)'C');
+	    outb(0x3c9, (__u8)'E');
+	    outb(0x3c9, (__u8)'G');
+	    outb(0x3c8, 0xde);
+	    outb(0x3c9, (__u8)'E');
+	    outb(0x3c9, (__u8)'D');
+	    outb(0x3c9, (__u8)'S');
+	    outb(0x3c8, 0xde);
+	    outb(0x3c9, (__u8)'U');
+	    outb(0x3c9, (__u8)'N');
+	    outb(0x3c9, (__u8)'\n');
+	    /* Should be in CEG mode now. */
+	    outb(0x3c6, 0xff);
+	    x = (inpb(0x3c6) >> 4) & 0x07;
+	    if (x < 0x07) {
+			ramdac = DAC_EDSUN;
+			wait_for_retrace();
+			outb(0x3c8, 0xdf);
+			outb(0x3c9, 0x00);
+	    }
+	}
+
+	/* Remember if DAC was in 8-bit mode. */
+	if (dac8)
+		ramdac |= DAC_8BIT;
+	return ramdac;
+}
+
+__initfunc(static int detect_machdac(int chip))
+{
+	int ramdac = 0;
+
+	debug("detect_machdac: chip=%s\n", known_chips[chip]);
+	if (chip == MACH32) {
+		__u16 dactype;
+
+		int mach32dacs[8] = {
+			DAC_ATI68830,
+			DAC_SIERRA15_16,
+			DAC_ATI68875 | DAC_6_8_PROGRAM,
+			DAC_STANDARD,
+			DAC_ATIMISC24 | DAC_6_8_PROGRAM,
+			DAC_ATI68860 | DAC_6_8_PROGRAM,
+			DAC_STG1700 | DAC_6_8_PROGRAM,
+			DAC_ATT498 | DAC_6_8_PROGRAM};
+		
+		dactype = le16_to_cpu(inpw(0x12ee));
+		debug("config_status_1: %x\n", dactype);
+
+		ramdac = mach32dacs[(dactype >> 9) & 0x07];
+		if (ramdac == DAC_ATI68860 || ramdac == DAC_ATIMISC24)
+			if (width8check())
+				ramdac |= DAC_8BIT;
+	}
+
+	if (chip == MACH64) {
+		__u32 dac_cntl, scratch1;
+
+		/* do the chipset-depended checking... */
+
+		scratch1 = le32_to_cpu(inpl(0x6eec));
+		debug("config_chip_id=%x\n", scratch1);
+
+		switch (scratch1 & 0xffff) {
+			case 0x0053:
+			case 0x4354:
+			case 0x0093:
+			case 0x4554:
+			case 0x0166:
+			case 0x4c47:
+			case 0x02b3:
+			case 0x5654:
+			case 0x00d3:
+			case 0x4754:	/* ATI264xx uses the ATI_INTERNAL RAMDAC */
+							ramdac = DAC_ATI_INTERNAL | DAC_6_8_PROGRAM;
+							if (width8check())
+								ramdac |= DAC_8BIT;
+							 break;
+		}
+
+		if (!ramdac) {
+			__u32 dactype;
+			/* if the pre-detection is done from Mach64 Bios we'll loose... */
+			dac_cntl = le32_to_cpu(0x62ec);
+			scratch1 = le32_to_cpu(0x46ec);
+
+			dactype = (((dac_cntl & 0x00070000) |
+						(scratch1 & 0x0000f000)) >> 12);
+			debug("no ATI264: dac_cntl=%x, scratch1=%x, dactype=%x\n",
+				dac_cntl, scratch1, dactype);
+			switch (dactype) {
+				case 0x10:	ramdac = DAC_IBMRGB525 | DAC_6_8_PROGRAM;
+							break;
+				case 0x20:	ramdac = DAC_ATI68875 | DAC_6_8_PROGRAM;
+							break;
+				case 0x27:
+				case 0x57:	ramdac = DAC_TVP3025 | DAC_6_8_PROGRAM;
+							break;
+				case 0x30:	ramdac = DAC_STANDARD;
+							break;
+				case 0x40:	ramdac = DAC_ATIMISC24;
+							break;
+				case 0x41:	ramdac = DAC_ATT491;
+							break;
+				case 0x42:	ramdac = DAC_SIERRA24;
+							break;
+				case 0x43:	ramdac = DAC_MU9C1880;
+							break;
+				case 0x44:	ramdac = DAC_IMSG174;
+							break;
+				case 0x50:
+				case 0x51:	ramdac = DAC_ATI68860 | DAC_6_8_PROGRAM;
+							break;
+				case 0x60:	ramdac = DAC_STG1700 | DAC_6_8_PROGRAM;
+							break;
+				case 0x61:	ramdac = DAC_ATT498 | DAC_6_8_PROGRAM;
+							break;
+				case 0x70:	ramdac = DAC_STG1702 | DAC_6_8_PROGRAM;
+							break;
+				case 0x71:	ramdac = DAC_SIERRA24 | DAC_6_8_PROGRAM;
+							break;
+				case 0x72:	ramdac = DAC_ATT498 | DAC_6_8_PROGRAM;
+							break;
+				case 0x73:	ramdac = DAC_STG1703 | DAC_6_8_PROGRAM;
+							break;
+				case 0x74:	ramdac = DAC_CH8398 | DAC_6_8_PROGRAM;
+							break;
+				case 0x75:	ramdac = DAC_ATT408 | DAC_6_8_PROGRAM;
+							break;
+				default:	break;
+			}
+			if (width8check())
+				ramdac |= DAC_8BIT;
+		}
+	}
+
+	message("detect_machdac: ramdac=%s, [6/8bit=%d, 8bit=%d]\n",
+		known_dacs[ramdac & ~(DAC_6_8_PROGRAM | DAC_8BIT)],
+		(ramdac & DAC_6_8_PROGRAM) != 0,
+		(ramdac & DAC_8BIT) != 0);
+	return ramdac;
+}
+
+__initfunc(static
+int detect_s3dac(int chip))
+{
+	int ramdac = 0;
+
+	return ramdac;
+}
+
+/* -------------------------------------------------------------------
+ * various helper functions
+ * ------------------------------------------------------------------- */
+
+__initfunc(static
+int region_accessible(__vga_region *region, int mode, int chkend))
+{
+	__u8 *memregion;
+	int res = 1;
+
+	memregion = region->phys;
+	if (memregion) {
+		if (chkend)
+			memregion += region->size;
+		res = addr_accessible(memregion, mode);
+	}
+	return res;
+}
+
+/*
+ * look if the triple {IOBase, BaseMem, ExtMem} is accessible.
+ *
+ * Note:
+ *   Currently, the transparent mapping is only required for medusa.
+ *   Therefore we assume that IOBase, BaseMem and ExtMem are in the
+ *   same 16MB area.
+ */
+__initfunc(static
+int test_fingerprint(__vga_fingerprint *vfp))
+{
+	int res = 0;
+
+	if (is_medusa && (vfp->Flags & MEDUSA_ISA))
+		transp_map_16Marea(vfp->BaseMem.phys);
+		
+	if ((region_accessible(&vfp->BaseMem, READ_BYTE, 0)) &&
+	    (region_accessible(&vfp->IOBase, READ_BYTE, 0))) {
+			if ((!vfp->ExtMem.phys) ||
+				(region_accessible(&vfp->ExtMem, READ_BYTE, 0)))
+				res=1;
+		}
+
+	if (is_medusa && (vfp->Flags & MEDUSA_ISA))
+		transp_map_off(vfp->BaseMem.phys);
+	return res;
+}
+
+/* -------------------------------------------------------------------
+ * measure the vertical retrace frequency for vga compatible devices
+ *
+ * we use the MFP Timer A with a prescale factor of 4 
+ * which gives a resolution of 1.627us.
+ * ------------------------------------------------------------------- */
+__initfunc(__u32 measure_vga_vtime(void))
+{
+	__volatile__ __u8 *inpstat1;
+	__u32 count, i;		/* current and new values */
+	int  reload = 256, loops = 50;
+
+	inpstat1 = ISA_IOBase + (inpb(GREG_MISC_OUTPUT_R)&0x01 ? 0x3da : 0x3ba);
+
+	if (wait_for_retrace()) {
+		__u32 flags;
+		__u8 prev, cur;
+
+		save_flags(flags);
+		cli();
+
+
+		prev = cur = count = i = 0;
+		mfp.int_en_a = 0x00;		/* no interrupt */
+		mfp.tim_dt_a = reload;
+
+		while ((*inpstat1 & 0x08) != 0x00);			/* wait during vertical retrace */
+		mfp.tim_ct_a = 1;							/* delay mode, prescale = 4 */
+		do {
+			do {
+				prev = cur; cur = mfp.tim_dt_a;
+				if ((int)cur > (int)prev ) {
+					count += reload;
+				}
+			} while ((*inpstat1 & 0x08) == 0x00);	/* vertical display data */
+
+			do {
+				prev = cur; cur = mfp.tim_dt_a;
+				if ((int)cur > (int)prev) {
+					count +=reload;
+				}
+			} while ((*inpstat1 & 0x08) != 0x00);	/* vertical retrace */
+		} while (++i < loops);
+		mfp.tim_ct_a = 0;							/* stop delay counter */
+
+		restore_flags(flags);
+
+		count += (reload - cur);
+		count *= 1627;					/* ns */
+		return count/loops;
+	}
+	return -1;
+}
+
+/*
+ *	wait N msec using Timer A
+ *  - only used during initialisation if we can't rely on jiffies or loop_count
+ *
+ * we're using a prescale of 10 and a loop-count of 246 which leads to a delay of 1.0005ms
+ *
+ */
+__initfunc(static
+void delay_N_msec(int msec))
+{
+	int ticks = 0;
+
+	mfp.int_en_a = 0x00;		/* no interrupt */
+	mfp.tim_dt_a = 246;
+	mfp.tim_ct_a = 2;			/* delay mode, prescale = 10 */
+
+	for (ticks = 0; ticks < msec; ticks++)
+		while (mfp.tim_dt_a != 0);
+
+	mfp.tim_ct_a = 0;			/* stop counter/timer */
+}
+/* -------------------------------------------------------------------
+ * change transparent translation for given address
+ * Based on Roman Hodek's code
+ *
+ * purpose:
+ *   instead of doing kernel_map() we transparently translate
+ *   the given address. Depending on the memchunk-size we save
+ *   a lot of unnecessary pagedescriptors/tables.
+ *   NOTE that these mappings are only done temporary.
+ *   NOTE that it's absolute legal and doesn't harm if
+ *        we map a region twice via different ttr's.
+ *   NOTE also that i doesn't own a Medusa/Hades, therefore
+ *        i completely relies on bugreports!
+ *   NOTE also that we won't execute any code in the translated
+ *        areas - therefore the settings should be enough
+ */
+
+__initfunc(static
+__inline__ void transp_map_16Marea( caddr_t addr ))
+{
+	__u32 address = (__u32) addr;
+	if (address) {
+		address &= 0xff000000;
+		if (CPU_IS_020_OR_030) {
+			address |= 0x8543;
+			/* enable, cache inhibit, read and write, FDC mask = 3, FDC val = 4
+			 * -> Supervisor only */
+			__asm__ __volatile__ ( ".chip 68030; pmove %0@,%/tt0; .chip 68k"
+								   : : "a" (&address) );
+		}
+		else
+			/* enable, supervisor only, non-cacheable/serialized, writable */
+			__asm__ __volatile__ ( ".chip 68040; movec %0,%%dtt0; .chip 68k"
+								   : : "d" (address | 0xa040));
+	}
+}
+
+__initfunc(static
+__inline__ void transp_map_off( caddr_t addr ))
+{
+	if (addr) {
+		if (CPU_IS_020_OR_030) {
+			unsigned long tt_val = 0;
+			__asm__ __volatile__ ( ".chip 68030; pmove %0@,%/tt0; .chip 68k"
+								   : : "a" (&tt_val) );
+		}
+		else
+			__asm__ __volatile__ ( ".chip 68040; movec %0,%%dtt0; .chip 68k"
+								   : : "d" (0));
+	}
+}
+
+/* -------------------------------------------------------------------
+ * test the accessibility of a given memory location.
+ * Based on Roman Hodek's code
+ *
+ *  regp:	location to test
+ *  flag:		 0		1
+ *		& 0x01:	byte   word
+ *		& 0x02:	read   write
+ *
+ * ------------------------------------------------------------------- */
+__initfunc(static
+int addr_accessible(volatile void *regp, int flag))
+{
+    int ret;
+    __u32 flags, *vbr, save_berr;
+
+    save_flags(flags);
+    cli();
+
+    /* save address of buserror handler */
+    __asm__ __volatile__ ( "movec   %/vbr,%0" : "=r" (vbr) : );
+    save_berr = vbr[2];
+
+    __asm__ __volatile__ (
+		"movel  %/sp,%/d1	\n\t"	/* save sp */
+		"movel	#40f,%2@	\n\t"	/* new buserror handler */
+		"moveq	#0,%0		\n\t"	/* preset "no success" */
+
+		"btst	#0,%3		\n\t"	/* byte access? */
+		"bne	20f			\n\t"	/* no -> */
+
+	"10: moveb	%1@,%/d0	\n\t"	/* read byte */
+		"nop				\n\t" 
+		"btst	#1,%3		\n\t"	/* write access? */
+		"beq	30f			\n\t"
+		"clrb	%1@			\n\t"	/* write 0x00 */
+		"moveb	%/d0,%1@	\n\t"	/* previous value */
+		"bra	30f			\n\t"
+
+	"20: movew  %1@,%/d0	\n\t"	/* read word */
+		"nop    			\n\t"                   
+		"btst	#1,%3		\n\t"  	/* write access? */
+		"beq    30f			\n\t"
+		"clrw   %1@			\n\t"	/* write 0x0000 */
+		"movew  %/d0,%1@	\n\t"	/* previous value */
+
+	"30: moveq  #1,%0		\n\t"	/* return success */
+	"40:					\n\t"	/* entry for bus error */
+		"movel  %/d1,%/sp	"		/* restore sp */
+        : "=&d" (ret)
+        : "a" (regp), "a" (&vbr[2]), "rm" (flag)
+        : "d0", "d1", "memory"
+    );
+
+    /* restore bus error handler */
+    vbr[2] = save_berr;
+    restore_flags(flags);
+
+    return( ret );
+}
+
+/* -------------------------
+ * general purpose functions
+ *
+ */
+
+void et4000_key(int enable)
+{
+	__volatile__ __u8 *modectrl;
+	static __u8 hercules, modereg;
+	modectrl = ISA_IOBase 
+			 + (ISA_IOBase[GREG_MISC_OUTPUT_R] & 0x01 ? 0x3d8 : 0x3b8);
+
+	if (enable) {
+		hercules = ISA_IOBase[0x3bf];
+		modereg  = *modectrl;
+
+		ISA_IOBase[0x3bf] = 0x03;
+		*modectrl         = 0xa0;
+	} else {
+		*modectrl		  = modereg;
+		ISA_IOBase[0x3bf] = hercules;
+	}
+}
+
+/*
+ * wait for vertical retrace
+ */
+__u32 wait_for_retrace(void)
+{
+	__volatile__ __u8 *inpstat1;
+	int loopcount = 0;
+	extern unsigned long loops_per_sec;
+
+	inpstat1 = ISA_IOBase 
+			 + (ISA_IOBase[GREG_MISC_OUTPUT_R] & 0x01 ? 0x3da : 0x3ba);
+
+	while ((*inpstat1 & 0x08) != 0) {
+		if (loopcount++ > loops_per_sec)
+			return 0;						/* no retrace signal... */
+	}
+
+	while ((*inpstat1 & 0x08) == 0)
+		barrier();
+
+	return 1;
+}
+
+__initfunc(__inline__
+void dac_to_pel(void))
+{
+	(void) inpb(0x3c8);
+}
+
+__initfunc(__inline__
+__u8 trig_dac(void))
+{
+	(void) inpb(0x3c6);
+	(void) inpb(0x3c6);
+	(void) inpb(0x3c6);
+	return inpb(0x3c6);
+}
+
+__initfunc(__inline__
+__u8 dac_to_comm(void))
+{
+	dac_to_pel();
+	return trig_dac();
+}
+
+__initfunc(__inline__
+__u8 get_dac_comm(void))
+{
+	__u8 ret;
+
+	dac_to_comm();
+	ret = inpb(0x3c6);
+	dac_to_pel();
+	return ret;
+
+}
+
+static void read_pel_reg(__u8 idx, __u8 *pix)
+{
+	outb(0x3c7, idx);
+	*pix++ = inpb(0x3c9);
+	*pix++ = inpb(0x3c9);
+	*pix   = inpb(0x3c9);
+}
+
+static void write_pel_reg(__u8 idx, __u8 *pix)
+{
+	outb(0x3c8, idx);
+	outb(0x3c9, *pix++);
+	outb(0x3c9, *pix++);
+	outb(0x3c9, *pix);
+}
+
+static __u8 set_comm(__u8 comm)
+{
+	dac_to_comm();
+	outb(0x3c6, comm);
+	dac_to_comm();
+	return inpb(0x3c6);
+}
+
+static int width8check(void)
+{
+	__u8 oldidx, oldred, newred,
+		 pix[3];
+
+	oldidx = inpb(0x3c8);
+	read_pel_reg(0xff, pix);
+	oldred = pix[0];
+	pix[0] = 0xff;
+	write_pel_reg(0xff, pix);
+	read_pel_reg(0xff, pix);
+	newred = pix[0];
+	pix[0] = oldred;
+	write_pel_reg(0xff, pix);
+	outb(0x3c8, oldidx);
+	return (newred == 0xff);
+}
+
+static int test_DAC_bit(__u8 bit, __u8 oldcomm, __u8 oldpel)
+{
+	__u8 tmp;
+
+	dac_to_pel();
+	outb(0x3c6, oldpel & (bit ^ 0xff));
+	dac_to_comm();
+	outb(0x3c6, oldcomm | bit);
+	tmp = inpb(0x3c6);
+	outb(0x3c6, tmp & (bit ^ 0xff));
+	return ((tmp & bit) != 0);
+}
+
+/* a strtok which returns empty strings, too */
+
+__initfunc(static
+char * strtoke(char * s,const char * ct))
+{
+  char *sbegin, *send;
+  static char *ssave = NULL;
+  
+  sbegin  = s ? s : ssave;
+  if (!sbegin) {
+	  return NULL;
+  }
+  if (*sbegin == '\0') {
+    ssave = NULL;
+    return NULL;
+  }
+  send = strpbrk(sbegin, ct);
+  if (send && *send != '\0')
+    *send++ = '\0';
+  ssave = send;
+  return sbegin;
+}
+
+/* ---------------------------- */
+
+#ifdef MODULE
+char *mod_argv = NULL;
+MODULE_PARM(mod_argv,"s");
+
+int init_module(void)
+{
+	int dummy;
+	detect_videohw(mod_argv, &dummy);
+    return(1);
+}
+
+void cleanup_module(void)
+{
+	return;
+}
+
+#endif /* MODULE */
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/vgafb.h /usr/src/linux-2.1.57/drivers/video/vgafb.h
--- /usr/src/clean/linux-2.1.57/drivers/video/vgafb.h	Thu Jan  1 01:00:00 1970
+++ /usr/src/linux-2.1.57/drivers/video/vgafb.h	Sun Oct  5 12:48:33 1997
@@ -0,0 +1,240 @@
+/* tab-width: 4 */
+
+/*
+ * linux/drivers/video/vga.h		$Revision: 2.6.1.3 $
+ *
+ *   purpose: defines and macros for PC-compatible hardware
+ *
+ *    Copyright (C) 1997 J. Orschiedt
+ *
+ *    based on retz3fb.h
+ *	 Copyright (C) 1997 Jes Sorensen
+ *
+ * Changes against retz3fb.h:
+ *   vga.h contains the subset for VGA-controller. So the card-specific
+ *         header-file only needs the specific extensions.
+ *
+ * Parameter used in macros
+ *   ISA_IOBase	 base-address to reach IO-port 0x0000
+ *   ISA_BaseMem base-address to reach the first Meg of ISA-Memory (usually
+ *		 the standard VGA-memory, starting at 0xA0000 in ISA-memspace)
+ *
+ *   (maybe you'll have to redefine these parameters if you've more than one board,
+ *    f.e. #define ISA_IOBase locIOBase[x]
+ *    whereby x is the instance of the driver)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * make life a little bit easier
+ */
+ 
+#define inpb(port)									\
+    (*(__volatile__ __u8 *)(ISA_IOBase+port))
+
+#define outb(port, val)								\
+    do {											\
+	(*(__volatile__ __u8 *)(ISA_IOBase+port)) = (__u8) val;		\
+    } while (0)
+    
+#define inpw(port)									\
+    (*(__volatile__ __u16 *)(ISA_IOBase+port))
+
+#define outw(port, val)								\
+    do {											\
+	(*(__volatile__ __u16 *)(ISA_IOBase+port)) = (__u16) val;	\
+    } while (0)
+
+#define inpl(port)									\
+    (*(__volatile__ __u32 *)(ISA_IOBase+port))
+
+#define outl(port,val)								\
+    do {											\
+	(*(__volatile__ __u32 *)(ISA_IOBase+port)) = (__u32) val; 	\
+    } while (0)
+ 
+/*
+ * Macros to access the indexed VGA-registers.
+ *   The IDX-register is at offset port, the DATA at port+1
+ *
+ *   we have four different sets of macros:
+ *
+ *  xxx_r	read the given index register
+ *
+ *  xxx_wb	access the registers in bytemode, means we need always
+ *		two writes to put the data to the indexed register
+ *  xxx_wm	access the registers in wordmode, motorola-fashion
+ *		IDX-register in upper byte, register-data in lower byte
+ *  xxx_wi	access the registers in wordmode, intel-fashion
+ *		IDX-register in lower byte, register-data in upper byte
+ */
+ 
+ 
+/*
+ * Macro to access the timing-sequencer.
+ */
+#define seq_r(sreg)	\
+    ({outb(SEQ_IDX, sreg); inpb(SEQ_DATA);})
+
+#define seq_wb(sreg,sdat) \
+    do{outb(SEQ_IDX, sreg); outb(SEQ_DATA, sdat);} while(0)
+
+#define seq_wm(sreg,sdat) \
+    do{outw(SEQ_IDX, (sreg << 8) | sdat);} while (0)
+
+#define seq_wi(sreg,sdat) \
+    do{outw(SEQ_IDX, sreg | (sdat << 8));} while (0)
+
+/*
+ * Macro to access the CRT controller.
+ */
+#define crt_r(creg)	\
+    ({outb(CRT_IDX, creg); inpb(CRT_DATA);})
+
+#define crt_wb(creg,cdat) \
+    do{outb(CRT_IDX, creg); outb(CRT_DATA, cdat);} while(0)
+
+#define crt_wm(creg,cdat) \
+    do{outw(CRT_IDX, (creg << 8) | cdat);} while (0)
+
+#define crt_wi(creg,cdat) \
+    do{outw(CRT_IDX, creg | (cdat << 8));} while (0)
+
+/*
+ * Macro to access the graphics controller.
+ */
+#define gfx_r(greg)	\
+    ({ outb(GFX_IDX, greg); inpb(GFX_DATA); })
+
+#define gfx_wb(greg,gdat) \
+    do{outb(GFX_IDX, greg); outb(GFX_DATA, gdat);} while(0)
+
+#define gfx_wm(greg,gdat) \
+    do{outw(GFX_IDX, (greg << 8) | gdat);} while (0)
+
+#define gfx_wi(greg,gdat) \
+    do{outw(GFX_IDX, greg | (gdat << 8));} while (0)
+
+/*
+ * Macro to access the attribute controller.
+ */
+#define attr_r(areg)	\
+    ({outb(ACT_IDX, areg); inpb(ACT_DATA);})
+
+#define attr_wb(areg,adat) \
+    do{outb(ACT_IDX, areg); outb(ACT_DATA, adat);} while(0)
+	
+#define attr_wm(areg,adat) \
+    do{outw(ACT_IDX, (areg << 8) | adat);} while (0)
+
+#define attr_wi(areg,adat) \
+    do{outw(ACT_IDX, areg | (adat << 8));} while (0)
+
+/*
+ * General Registers
+ */
+#define GREG_STATUS0_R		0x03c2
+#define GREG_STATUS1_R		0x03da
+#define GREG_MISC_OUTPUT_R	0x03cc
+#define GREG_MISC_OUTPUT_W	0x03c2	
+#define GREG_FEATURE_CONTROL_R	0x03ca
+#define GREG_FEATURE_CONTROL_W	0x03da
+#define GREG_POS		0x0102
+
+/*
+ * Video DAC addresses
+ */
+#define VDAC_ADDRESS		0x03c8
+#define VDAC_ADDRESS_W		0x03c8
+#define VDAC_ADDRESS_R		0x03c7
+#define VDAC_STATE		0x03c7
+#define VDAC_DATA		0x03c9
+#define VDAC_MASK		0x03c6
+
+/*
+ * Timing Sequencer
+ */
+#define SEQ_IDX			0x03c4	/* Sequencer Index */
+#define SEQ_DATA		0x03c5
+#define SEQ_RESET		0x00
+#define SEQ_CLOCKING_MODE	0x01
+#define SEQ_MAP_MASK		0x02
+#define SEQ_CHAR_MAP_SELECT	0x03
+#define SEQ_MEMORY_MODE		0x04
+
+/*
+ * Graphics Controller
+ */
+#define GFX_IDX			0x03ce
+#define GFX_DATA		0x03cf
+#define GFX_SET_RESET		0x00
+#define GFX_ENABLE_SET_RESET	0x01
+#define GFX_COLOR_COMPARE	0x02
+#define GFX_DATA_ROTATE		0x03
+#define GFX_READ_MAP_SELECT	0x04
+#define GFX_GRAPHICS_MODE	0x05
+#define GFX_MISC		0x06
+#define GFX_COLOR_XCARE		0x07
+#define GFX_BITMASK		0x08
+
+/*
+ * CRT Controller
+ */
+#define CRT_IDX			0x03d4
+#define CRT_DATA		0x03d5
+#define CRT_HOR_TOTAL		0x00
+#define CRT_HOR_DISP_ENA_END	0x01
+#define CRT_START_HOR_BLANK	0x02
+#define CRT_END_HOR_BLANK	0x03
+#define CRT_START_HOR_RETR	0x04
+#define CRT_END_HOR_RETR	0x05
+#define CRT_VER_TOTAL		0x06
+#define CRT_OVERFLOW		0x07
+#define CRT_PRESET_ROW_SCAN	0x08
+#define CRT_MAX_SCAN_LINE	0x09
+#define CRT_CURSOR_START	0x0a
+#define CRT_CURSOR_END		0x0b
+#define CRT_START_ADDR_HIGH	0x0c
+#define CRT_START_ADDR_LOW	0x0d
+#define CRT_CURSOR_LOC_HIGH	0x0e
+#define CRT_CURSOR_LOC_LOW	0x0f
+#define CRT_START_VER_RETR	0x10
+#define CRT_END_VER_RETR	0x11
+#define CRT_VER_DISP_ENA_END	0x12
+#define CRT_OFFSET		0x13
+#define CRT_UNDERLINE_LOC	0x14
+#define CRT_START_VER_BLANK	0x15
+#define CRT_END_VER_BLANK	0x16
+#define CRT_MODE_CONTROL	0x17
+#define CRT_LINE_COMPARE	0x18
+
+/*
+ * Attribute Controller
+ */
+#define ACT_IDX			0x03C0
+#define ACT_ADDRESS_R		0x03C0
+#define ACT_DATA		0x03C0
+#define ACT_PALETTE0		0x00
+#define ACT_PALETTE1		0x01
+#define ACT_PALETTE2		0x02
+#define ACT_PALETTE3		0x03
+#define ACT_PALETTE4		0x04
+#define ACT_PALETTE5		0x05
+#define ACT_PALETTE6		0x06
+#define ACT_PALETTE7		0x07
+#define ACT_PALETTE8		0x08
+#define ACT_PALETTE9		0x09
+#define ACT_PALETTE10		0x0A
+#define ACT_PALETTE11		0x0B
+#define ACT_PALETTE12		0x0C
+#define ACT_PALETTE13		0x0D
+#define ACT_PALETTE14		0x0E
+#define ACT_PALETTE15		0x0F
+#define ACT_ATTR_MODE_CNTL	0x10
+#define ACT_OVERSCAN_COLOR	0x11
+#define ACT_COLOR_PLANE_ENA	0x12
+#define ACT_HOR_PEL_PANNING	0x13
+#define ACT_COLOR_SELECT	0x14
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/drivers/video/videohw.h /usr/src/linux-2.1.57/drivers/video/videohw.h
--- /usr/src/clean/linux-2.1.57/drivers/video/videohw.h	Thu Jan  1 01:00:00 1970
+++ /usr/src/linux-2.1.57/drivers/video/videohw.h	Sun Oct  5 12:47:30 1997
@@ -0,0 +1,105 @@
+/* tab-width: 4 */
+
+/*
+ * linux/drivers/video/videohw.h		$Revision: 2.6.1.3 $
+ *
+ *    Copyright (C) 1997 J. Orschiedt
+ *
+ * Definitions for Hardware detections
+ */
+
+/* architectures */
+enum {
+	CRAZYDOTS = 1,
+	MV300,
+	NOVA,
+	NOVAPLUS,
+	PANTHER64,
+	PC_ISA,
+	SPECTRUM,
+	PROMST,
+	__NUM_ARCHs};
+
+/* graphic chips */
+enum {
+	STDVGA = 1,
+	G300,
+	ET4000,
+	ET4000W32,
+	ET6000,
+	MACH32,
+	MACH64,
+	TI34061,
+	__NUM_CHIPs};
+
+/* RAMDACs */
+
+enum {
+	DAC_BLIND6 = 1,
+	DAC_STANDARD,
+	DAC_SS24, DAC_SIERRA15, DAC_SIERRA15_16, DAC_SIERRA24,
+	DAC_MUSIC4870, DAC_MUSIC4910,
+	DAC_ACUMOS,
+	DAC_CIRRUS24,
+	DAC_ATT490, DAC_ATT491, DAC_ATT492, DAC_ATT493,
+	DAC_EDSUN,
+	BLINDW32,
+	DAC_ET6000,
+	DAC_ICS5341, DAC_ICS5301,
+	DAC_ATI_INTERNAL,
+	DAC_ATI68830, DAC_ATI68860, DAC_ATI68875, DAC_ATIMISC24,
+	DAC_ATT498, DAC_ATT408,
+	DAC_CH8398,
+	DAC_IBMRGB525,
+	DAC_IMSG174,
+	DAC_MU9C1880,
+	DAC_STG1700, DAC_STG1702, DAC_STG1703,
+	DAC_TVP3025,
+	DAC_S3,
+	DAC_UNKNOWN,
+	__NUM_DACs};
+
+#define	DAC_6_8_PROGRAM	0x40
+#define	DAC_8BIT		0x80
+
+/* flags for machine-dependencies */
+#define	ATARI_VME	0x01
+#define MEDUSA_ISA	0x02
+#define HADES_ISA	0x04
+#define HADES_PCI	0x08
+#define VAPOUR_WARE	0x80
+
+/*
+ * structures for regions and fingerprints
+ */
+typedef struct {
+	caddr_t	phys,
+			virt;
+	__u32	size;
+} __vga_region;
+
+typedef struct {
+	__u8	Card;		/* card descriptor */
+	__u8	Chip;		/* chiptype */
+	__u8	RamDac;		/* RAMDAC */
+	__u8	Flags;		/* ATARI_VME || MEDUSA_ISA || HADES_ISA ... */
+	int		ChipId;		/* detected chip revision */
+	char *	CardName;
+	__vga_region IOBase;
+	__vga_region BaseMem;
+	__vga_region ExtMem;
+} __vga_fingerprint;
+
+/*
+ * i know this value is absolutely crazy, but it doesn't hurt
+ */
+#define MAX_SVGA	8
+extern __vga_fingerprint *detected_svga[MAX_SVGA];
+
+/*
+ * Local Variables:
+ * tab-width: 4
+ * End:
+ * vi: ts=4 sw=4
+ * vim: si
+ */
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/include/linux/fb.h /usr/src/linux-2.1.57/include/linux/fb.h
--- /usr/src/clean/linux-2.1.57/include/linux/fb.h	Fri Oct  3 16:18:18 1997
+++ /usr/src/linux-2.1.57/include/linux/fb.h	Fri Oct  3 22:51:19 1997
@@ -76,6 +76,11 @@
 #define FB_ACCEL_RETINAZ3	4	/* RetinaZ3 (NCR77C32BLT)       */
 #define FB_ACCEL_MACH64		6	/* ATI Mach 64			*/
 
+#define FB_ACCEL_MACH64		6	/* ATI Mach64 */
+#define FB_ACCEL_MACH32		7	/* ATI Mach32 */
+#define FB_ACCEL_ET4W32		8	/* ET4000 W32 */
+#define FB_ACCEL_ET6000		9	/* ET6000 */
+
 #define FB_SYNC_HOR_HIGH_ACT	1	/* horizontal sync high active	*/
 #define FB_SYNC_VERT_HIGH_ACT	2	/* vertical sync high active	*/
 #define FB_SYNC_EXT		4	/* external sync		*/
diff -u -N --recursive --exclude-from=/home/jor/diff-excludes /usr/src/clean/linux-2.1.57/init/main.c /usr/src/linux-2.1.57/init/main.c
--- /usr/src/clean/linux-2.1.57/init/main.c	Fri Oct  3 16:18:16 1997
+++ /usr/src/linux-2.1.57/init/main.c	Fri Oct  3 22:05:32 1997
@@ -138,6 +138,7 @@
 extern void scsi_luns_setup(char *str, int *ints);
 extern void sound_setup(char *str, int *ints);
 extern void reboot_setup(char *str, int *ints);
+extern void detect_videohw(char *str, int *ints);
 extern void video_setup(char *str, int *ints);
 #ifdef CONFIG_CDU31A
 extern void cdu31a_setup(char *str, int *ints);
@@ -335,6 +336,9 @@
 #endif
 #endif
 #ifdef CONFIG_FB
+#ifdef CONFIG_FB_VIDEOHW_DETECT
+	{"videohw=", detect_videohw },
+#endif
 	{ "video=", video_setup },
 #endif
 	{ "swap=", swap_setup },



