Resent-Date: Fri, 18 Sep 1998 00:45:33 +0200 (MET DST)
Date: Fri, 18 Sep 1998 00:46:56 +0200
From: Juergen Orschiedt <orschied@rumms.uni-mannheim.de>
To: linux-m68k@lists.linux-m68k.org
Subject: Atari: autodetect for ISA-bridges
Mail-Followup-To: linux-m68k@lists.linux-m68k.org
Resent-From: linux-m68k@phil.uni-sb.de

Ok,
here's the driver to detect bridges like Panther, Nova etc.
To stop the discussion about atari_request_irq, this drivers
changes only the edge-sensitivity if it detects an Panther/2.

Replace the previous atari_request_irq-patch by the present one,
it only contains the temp. workaround for SA_INTERRUPT.

Jürgen

--- jes-2.1.120/arch/m68k/atari/ataints.c	Fri May  1 19:05:53 1998
+++ linux/arch/m68k/atari/ataints.c	Wed Sep 16 23:11:15 1998
@@ -419,6 +419,7 @@
                       unsigned long flags, const char *devname, void *dev_id)
 {
 	int vector;
+	unsigned long oflags = flags;
 
 	/*
 	 * The following is a hack to make some PCI card drivers work,
@@ -427,9 +428,14 @@
 
 	flags &= ~SA_SHIRQ;
 
+	if (flags == SA_INTERRUPT) {
+		printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
+			__FUNCTION__, devname);
+		flags = IRQ_TYPE_SLOW;
+	}
 	if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
-		printk ("%s: Bad irq type %ld requested from %s\n",
-		        __FUNCTION__, flags, devname);
+		printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
+		        __FUNCTION__, flags, oflags, devname);
 		return -EINVAL;
 	}
 	if (!IS_VALID_INTNO(irq)) {

--- /dev/null	Sun Jun 16 21:20:44 1996
+++ linux/include/asm/atari_isaio.h	Thu Sep 17 23:32:28 1998
@@ -0,0 +1,195 @@
+/*
+ * include/asm/atari_isaio.h			$Revision: 1.2 $
+ *
+ * this file contains definitions for the various
+ * ISA-based boards for Atari machines
+ *
+ * __addr_region:	descripes an ISA-region
+ *	phys:		phys address in CPU-space
+ *	virt:		virt address
+ *	size:		size of decoded region
+ *
+ * __isa_descriptor:	description of ISA-bridge hardware
+ *	IOBase:		ISA IO address range
+ *	BaseMem:	ISA Membase, the first MB of ISA space
+ *	ExtMem:		extendend Mem, if adapter support this
+ *
+ * __vga_descriptor:	abstraction for (mostly used) VGA-boards
+ *      isa:		ISA-bridge descriptor
+ *      Card:		vendor type
+ *      Chip:		GDC chipset (mostly used)
+ *      Flags:		machine type,
+ *      ChipId:		not used
+ *      CardName:	vendor string
+ *
+ * isa_bridge:		points to a __isa_descriptor and descripes the
+ *			ISA adapters characteristics
+ *			at the moment only one adaptor possible!
+ *
+ * Parameter used in macros
+ *   BridgeIOBase	 base-address to reach IO-port 0x0000
+ *
+ *   (maybe you'll have to redefine these parameters if you have more than one board,
+ *    f.e. #define BridgeIOBase locIOBase[x] whereby x is the instance of the driver)
+ *
+ */
+
+#ifndef ATARI_ISAIO_INCLUDE
+#define ATARI_ISAIO_INCLUDE
+
+/*
+ * structures for regions and fingerprints
+ */
+typedef struct {
+	caddr_t	phys, virt;
+	__u32	size;
+} __addr_region;		/* previous __vga_region */
+
+typedef struct {
+	__addr_region IOBase;
+	__addr_region BaseMem;
+	__addr_region ExtMem;
+	__addr_region IOBaseOdd;
+} __isa_descriptor;		/* previous __vga_fingerprint */
+
+typedef struct {
+	__isa_descriptor isa;	/* address ranges */
+	__u8	Card;		/* card descriptor */
+	__u8	Chip;		/* chiptype */
+	__u8	Flags;		/* machine where this card can be found */
+	int	ChipId;		/* detected chip revision */
+	char *	CardName;
+} __vga_descriptor;
+
+extern __isa_descriptor *isa_bridge;	/* at the moment both variables are */
+extern u8 * const ISAio;		/* defined in tsengfb - 'til panther.c is ready */
+
+/*
+ * definitions to reuse iNtel code
+ */
+ 
+#undef inb
+#undef inb_p
+#define inb(port) ({ u8 __v = (*(volatile u8 *) ((BridgeIOBase)+port)); __v; })
+#define inb_p(port)  ({ u8 __v = (*(volatile u8 *) ((BridgeIOBase)+port)); __v; })
+
+#undef inw
+#undef inw_p
+#define inw(port) ({ u16 __v = (*(volatile u16 *) ((BridgeIOBase)+port)); __v; })
+#define inw_p(port)  ({ u16 __v = (*(volatile u16 *) ((BridgeIOBase)+port)); __v; })
+
+#undef inl
+#undef inl_p
+#define inl(port)  ({ u32 __v = (*(volatile u32 *) ((BridgeIOBase)+port)); __v; })
+#define inl_p(port)  ({ u32 __v = (*(volatile u32 *) ((BridgeIOBase)+port)); __v; })
+
+#undef outb
+#undef outb_p
+#define outb(val, port)	((*(volatile u8 *)((BridgeIOBase)+port)) = (val))
+#define outb_p(val, port) ((*(volatile u8 *)((BridgeIOBase)+port)) = (val))
+
+#undef outw
+#undef outw_p
+#define outw(val, port) ((*(volatile u16 *)((BridgeIOBase)+port)) = (val))
+#define outw_p(val, port) ((*(volatile u16 *)((BridgeIOBase)+port)) = (val))
+
+#undef outl
+#undef outl_p
+#define outl(val, port) ((*(volatile u32 *)((BridgeIOBase)+port)) = (val))
+#define outl_p(val, port) ((*(volatile u32 *)((BridgeIOBase)+port)) = (val))
+ 
+#define insb(port, dst, cnt)			\
+	do {u8 *__dst=(u8 *)dst;		\
+	    volatile u8 *__port = (BridgeIOBase) + port;	\
+		int __cnt=cnt;			\
+		while (__cnt--)			\
+		    *__dst++=*__port; \
+	} while (0)
+
+#define insw(port, dst, cnt)			\
+	do {u16 *__dst=(u16 *)dst;		\
+	    volatile u16 *__port = (BridgeIOBase) + port;	\
+		int __cnt=cnt;			\
+		while (__cnt--)			\
+		    *__dst++= *__port;		\
+	} while (0)
+
+#define outsb(port, src, cnt)			\
+	do { u8 *__src=(u8 *)src;		\
+	     volatile u8 *__port = (BridgeIOBase) + port;	\
+		int __cnt=cnt;			\
+		while (__cnt--)			\
+		    *__port = *__src++;	\
+	} while (0)
+
+#define outsw(port, src, cnt)			\
+	do { u16 *__src=(u16 *)src;		\
+	     volatile u16 *__port = (BridgeIOBase) + port;	\
+		int __cnt=cnt;			\
+		while (__cnt--)			\
+		    *__port = *__src++;	\
+	} while (0)
+
+#define IGNORE_CONST_1(var)			\
+	( { typedef __base_t = (var);		\
+	   __base_t *__p = (__base_t *)&(var);	\
+	   __p; } )
+
+#define IGNORE_CONST(var) (*IGNORE_CONST_1(var))
+
+
+/* a (hopefully) save definition for BridgeIOBase */
+#define BridgeIOBase ISAio
+
+/* various bridge-architectures */
+enum {
+	CRAZYDOTS = 1,
+	HADES, MV300, MEDUSA, MEGA4000, NOVA,
+	NOVAPLUS, PANTHER, PC_ISA, PROMST,
+	SPECTRUM, STGA, VOFA,
+	__NUM_ARCHs };
+
+/* graphic chips */
+enum {
+	STDVGA = 1,
+	G300, ET4000, ET4000W32, ET4000W32I, ET4000W32P,
+	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
+
+#endif
--- jes-2.1.120/arch/m68k/config.in	Mon Sep  7 20:37:49 1998
+++ linux/arch/m68k/config.in	Sun Sep 13 13:41:57 1998
@@ -28,6 +28,7 @@
   if [ "$CONFIG_HADES" = "y" ]; then
     define_bool CONFIG_PCI y
   fi  
+  bool '  Panther ISA-bridge support' CONFIG_PANTHER
 fi
 bool 'Macintosh support' CONFIG_MAC
 if [ "$CONFIG_MAC" = "y" ]; then
--- jes-2.1.120/arch/m68k/atari/Makefile	Tue Jan  6 15:50:56 1998
+++ linux/arch/m68k/atari/Makefile	Thu Sep 17 00:19:49 1998
@@ -12,4 +12,8 @@
             joystick.o stram.o
 OX_OBJS  := atari_ksyms.o
 
+ifdef CONFIG_PANTHER
+  OX_OBJS += panther.o
+endif
+
 include $(TOPDIR)/Rules.make
--- /dev/null	Sun Jun 16 21:20:44 1996
+++ linux/arch/m68k/atari/panther.c	Fri Sep 18 00:35:09 1998
@@ -0,0 +1,618 @@
+/* tab-width: 8
+ * arch/m68k/atari/panther.c			$Revision: 1.6 $
+ * purpose: try to detect an ISA-bridge in ATARI Computers
+ * 	    (and ATARI means ATARI, not MEDUSA or HADES...)
+ * 
+ * (c) 1998 Jürgen Orschiedt
+ *
+ * we may also detect different kinds of VGA-adapters which are using an
+ * internal ISA-bridge, but there is for my knowledge no combination which
+ * has a VGA adaptor and an separate ISA bridge. 
+ * 
+ * Table is sorted in ascending order: IOBase, BaseMem ExtMem
+ *
+ * sup.	Vendortype	Cardtype	IOBase		BaseMem		ExtMem		GDC-Chip
+ * - no Medusa Mach64	PC_ISA		0x7f100000	0x7f000000	0x7f400000	Mach64
+ * - no Medusa ET4000	PC_ISA		0x7f300000	0x7f000000	----		ET4000
+ *	Nova VME-TT	NOVAPLUS	0xfe900000	0xfe800000	0xfea00000	Mach32 
+ *	Panther		PC_ISA		0xfe900000	0xfe800000	0xfea00000	Mach32 3)
+ *	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		PC_ISA		0xfec00000	0xfec80000	0xfe800000	Mach64 3)
+ *	Nova Imagine	NOVA		0xfecc0000	0xfec00000	----		ET4000
+ *	STGA		PC_ISA		0xfecf0000	0xfec00000	----		ET4000
+ *	VoFa		PC_ISA		0xfed00000	0xfec00000	----		ET4000 4)
+ *	Panther		PC_ISA		0xfed00000	0xfec00000	----		ET4000 3)
+ *	Spectrum	SPECTRUM	0xfed00000	0xfec00000	----		ET4000 5)
+ *	Nova VME-STE	NOVA		0xfed00000	0xfec00000	0xfea00000	Mach32
+ *	Spectrum TC	SPECTRUM	0xfed80000	0xfec00000	----		ET4000
+ *	Nova ET4000	NOVA		0xfedc0000	0xfec00000	----		ET4000 6)
+ *	Crazy Dots ST	CRAZYDOTS	0xfeff0000	0xfec00000	----		ET4000 7)
+ *	Mega4000	PC_ISA		0xfeff0000	0xfec00000	----		ET4000
+ * - no Hades ISA	PC_ISA		0xfff00000	0xff000000	0xff100000	ET4000 8)
+ *
+ *
+ * 1) Nova II+ Falcon is identical
+ *
+ * 2) Crazy Dots VME is identical
+ *
+ * 3) Panther and Panther/2 are ISA busextender. There are different
+ *    decoder-GALs available, depending on the used GDC (more precisely:
+ *    depending on the available Drivers for TOS/MiNT/Magic).
+ *
+ *    ET4000:	Basemem 0xfec0.0000, 1MB
+ *    		IOBase  0xfed0.0000, 1MB
+ *    Mach32:	BaseMem 0xfe80.0000, 128k (== ISAMem 0x0a.0000-0x0b.ffff)
+ *    		IOBase  0xfe90.0000, 1MB
+ *    		ExtMem  0xfea0.0000, 2MB
+ *    Mach64:	Basemem	0xfec8.0000, 512k (== ISAMEM 0x08.0000-0x0f.ffff)
+ *    		IOBase	0xfec0.0000, 512k
+ *    		ExtMem  0xfe80.0000, 4M   (== ISAMEM 0x40.0000-0x7f.0000)
+ *
+ *    Main difference between Panther and Panther/2:
+ *    o Panther/2 is able to read from odd byteaddresses in IO-space
+ *    o maskable lowactive INT-output P2IntOut: ~(ISA-IRQ10 | ISA-IRQ11)
+ *    o three additional read-only registers
+ *      
+ *    The P2IntOut may be connected in several ways:
+ *    o using a special "Pupla/2", an Bus-Buffer which generates an IRQ5
+ *      (suggested by developer)
+ *    o connecting to the Blitter-IRQ (MFP Pin25)
+ *      
+ * 4) Gentec is identical
+ *
+ * 5) Spectrum HC is identical
+ *
+ * 6) Nova ET4000-STE and Nova ET4000-TT
+ *
+ * 7) 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[0],
+ *    the Mega 4000 is a PC-ISA card with card-specific clock generator.
+ *
+ * 8) 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. 
+ *
+ * ProMST: very special, doesn't fit into SVGA-category
+ *	       (no RAMDAC, different IO-Layout (0x001 - 0x101)
+ *
+ */
+ 
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/byteorder.h>
+#include <asm/entry.h>
+#include <asm/io.h>
+#include <asm/atari_isaio.h>		/* should go after io.h - redefines some macros */
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+/* #define DEBUG	1 */
+
+#ifdef DEBUG
+#define DPRINTK(text, args...)	printk("%s: " text, __FUNCTION__, ## args)
+#else
+#define DPRINTK(text, args...)
+#endif
+
+#define PRINTK(text, args...)	printk(text,## args)
+
+/*
+ * modes for addr_accessible
+ */
+#define READ_BYTE	0
+#define READ_WORD	1
+#define WRITE_BYTE	2
+#define WRITE_WORD	3
+
+static int test_fingerprint(__vga_descriptor *) ;
+static int addr_accessible(volatile void *iobase, int flag) ;
+static __inline void transp_map_16Marea(caddr_t);
+static __inline void transp_map_off(caddr_t);
+
+void panther_init(void);
+
+/* 
+ * 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_descriptor fingerprints[] __initdata = {
+	{{  {(__u8 *)0x7f100000, NULL, 64*1024 },
+	    {(__u8 *)0x7f000000, NULL, 1024*1024 },
+	    {(__u8 *)0x7f400000, NULL, 4096*1024 }},
+	    MEDUSA, MACH64, ATARI_MACH_MEDUSA, 0, "Medusa Mach64"},	
+
+	{{  {(__u8 *)0x7f300000, NULL, 64*1024 },
+	    {(__u8 *)0x7f000000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    MEDUSA, ET4000, ATARI_MACH_MEDUSA, 0, "Medusa ET4000"},
+
+	{{  {(__u8 *)0xfe900000, NULL, 128*1024 },
+	    {(__u8 *)0xfe800000, NULL, 1024*1024 },
+	    {(__u8 *)0xfea00000, NULL, 2048*1024 }},
+	    NOVAPLUS, MACH32, ATARI_MACH_NORMAL, 0, "Nova VME-TT"},		
+		   
+	{{  {(__u8 *)0xfe900000, NULL, 128*1024 },
+	    {(__u8 *)0xfe800000, NULL, 1024*1024 },
+	    {(__u8 *)0xfea00000, NULL, 2048*1024 }},
+	    PANTHER, MACH32, ATARI_MACH_NORMAL, 0, "Panther Mach32"},		
+		   
+	{{  {(__u8 *)0xfe900000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 4096*1024 },
+	    {(__u8 *)0xfe800000, NULL, 1024*1024 }},
+	    NOVAPLUS, MACH64, ATARI_MACH_NORMAL, 0, "Nova II+ TT"},		
+
+	{{  {(__u8 *)0xfea40000, NULL, 64*1024 },
+	    {(__u8 *)0xfea00000, NULL, 256*1024 },
+	    {(__u8 *)0x00000000, NULL, 0*1024 }},
+	    PROMST, TI34061, ATARI_MACH_NORMAL, 0, "ProMST"},
+		   
+	{{  {(__u8 *)0xfeb00000, NULL, 64*1024 },
+	    {(__u8 *)0xfea00000, NULL, 1024*1024 },
+	    {(__u8 *)0xfec00000, NULL, 4096*1024 }},
+	    NOVAPLUS, MACH64, ATARI_MACH_NORMAL, 0, "Nova II+ STE"},	
+		   
+	{{  {(__u8 *)0xfebf0000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    CRAZYDOTS, ET4000, ATARI_MACH_NORMAL, 0, "Crazy Dots II"},	
+		   
+	{{  {(__u8 *)0xfec00000, NULL, 512*1024 },	/* 512kB decoded */
+	    {(__u8 *)0xfec80000, NULL, 512*1024 },
+	    {(__u8 *)0xfe800000, NULL, 4096*1024 }},
+	    PANTHER, MACH64, ATARI_MACH_NORMAL, 0, "Panther Mach64"},		
+
+	{{  {(__u8 *)0xfecc0000, NULL, 256*1024 },	/* assume 256k decoded */
+	    {(__u8 *)0xfec00000, NULL, 768*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    NOVA, ET4000, ATARI_MACH_NORMAL, 0, "Nova Imagine"},	
+		   
+	{{  {(__u8 *)0xfecf0000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 960*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    STGA, ET4000, ATARI_MACH_NORMAL, 0, "STGA"},			
+
+	{{  {(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    PANTHER, ET4000, ATARI_MACH_NORMAL, 0, "Panther ET4000"},		
+		   
+	{{  {(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    SPECTRUM, ET4000, ATARI_MACH_NORMAL, 0, "Spectrum"},		
+		   
+	{{  {(__u8 *)0xfed00000, NULL, 1024*1024 },	/* 1MB decoded */
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    VOFA, ET4000, ATARI_MACH_NORMAL, 0, "VoFa"},		
+		   
+	{{  {(__u8 *)0xfed00000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0xfea00000, NULL, 4096*1024 }},
+	    NOVAPLUS, MACH32, ATARI_MACH_NORMAL, 0, "Nova VME-STE"},	
+		   
+	{{  {(__u8 *)0xfed80000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    SPECTRUM, ET4000, ATARI_MACH_NORMAL, 0, "Spectrum TC"},		
+		   
+	{{  {(__u8 *)0xfedc0000, NULL, 64*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    NOVA, ET4000, ATARI_MACH_NORMAL, 0, "Nova ET4000"},	
+		   
+	{{  {(__u8 *)0xfeff0000, NULL, 16*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    CRAZYDOTS, ET4000, ATARI_MACH_NORMAL, 0, "Crazy Dots ST"},	
+		   
+	{{  {(__u8 *)0xfeff0000, NULL, 16*1024 },
+	    {(__u8 *)0xfec00000, NULL, 1024*1024 },
+	    {(__u8 *)0x00000000, NULL,    0*1024 }},
+	    MEGA4000, ET4000, ATARI_MACH_NORMAL, 0, "Mega 4000"},	
+		   
+	{{  {(__u8 *)0xfff00000, NULL,   8*64*1024 },
+	    {(__u8 *)0xff000000, NULL,   1024*1024 },
+	    {(__u8 *)0xff100000, NULL, 7*1024*1024 }},
+	    HADES, ET4000, ATARI_MACH_HADES, 0, "Hades ISA"},	
+		   
+	{{  {0, },
+	    {0, },
+	    {0, }},
+	    0,     }
+};
+
+u8 * const ISAio;		/* point to ISA IO map */
+__isa_descriptor *isa_bridge;	/* the bridge parameters - if found */
+__vga_descriptor detected_vga;	/* the complete card parametes */
+
+int scratch __initdata = 0;
+int panther_irq __initdata = 0;
+__vga_descriptor last_bridge[arraysize(fingerprints)] __initdata = {};
+
+/*
+ * xxx_swirq - used to detect the INT
+ */
+
+__initfunc(void detect_swirq(int irqno, void *dev_id, struct pt_regs * regs))
+{
+    panther_irq = irqno;
+    scratch = ISAio[1];
+}
+
+__initfunc(void swapit(__addr_region *reg1, __addr_region *reg2))
+{
+    __addr_region temp;
+
+    temp = *reg1;
+    *reg1= *reg2;
+    *reg2= temp;
+}
+
+__initfunc(void sortit(__isa_descriptor *isa, __addr_region *reg1, __addr_region *reg2, __addr_region *reg3))
+{
+    *reg1 = isa->IOBase;
+    *reg2 = isa->BaseMem;
+    *reg3 = isa->ExtMem;
+
+    if (reg1->phys > reg2->phys) swapit(reg1, reg2);
+    if (reg1->phys > reg3->phys) swapit(reg1, reg3);
+    if (reg2->phys > reg3->phys) swapit(reg2, reg3);
+}
+
+/*
+ * first, we have to get rid of IOBase, BaseMem and ExtMem - they can be
+ * mixed up completely. Therefore we create an ascending list of baseaddresses
+ */
+__initfunc(int isbetter(__vga_descriptor *best, __vga_descriptor *curr))
+{
+    int result = 0;
+
+    __addr_region best1, best2, best3, curr1, curr2, curr3;
+
+    sortit(&best->isa, &best1, &best2, &best3);
+    sortit(&curr->isa, &curr1, &curr2, &curr3);
+
+    if ((curr1.phys <= best1.phys && (curr1.phys + curr1.size > best1.phys + best1.size)) ||
+   	(curr2.phys <= best2.phys && (curr2.phys + curr2.size > best2.phys + best2.size)) ||
+	(curr3.phys <= best3.phys && (curr3.phys + curr3.size > best3.phys + best3.size)))
+	result = 1;
+    return result;
+}
+
+__initfunc(int ispanther(u8 *io, u8* mem, u8* ext))
+{
+    int cnt;
+    __vga_descriptor *vp = fingerprints;
+
+    for (cnt = 0; cnt < arraysize(fingerprints); cnt++, vp++) {
+        if (vp-> Flags == ATARI_MACH_NORMAL &&
+	    vp->Card == PANTHER &&
+	    io == (u8 *) vp->isa.IOBase.phys &&
+	    mem== (u8 *) vp->isa.BaseMem.phys &&
+	    ext== (u8 *) vp->isa.ExtMem.phys)
+	    return 1;
+    }
+    return 0;
+}
+
+__initfunc(void panther_init(void))
+{
+    int found, cnt;
+
+    if (MACH_IS_ATARI && !MACH_IS_MEDUSA && !MACH_IS_HADES) {
+	__vga_descriptor *np = last_bridge;
+        __vga_descriptor *vfp = fingerprints;
+
+	/*
+	 * check for possible bridges
+	 */
+
+	for (found = 0; vfp->Chip; vfp++) {
+	    if (test_fingerprint(vfp)) {
+		/* we found a ISA-bridge - show it... */
+		DPRINTK("%s: 0x%p:%d, 0x%p:%d, 0x%p:%d\n",
+			vfp->CardName,
+			vfp->isa.IOBase.phys, vfp->isa.IOBase.size/1024,
+			vfp->isa.BaseMem.phys, vfp->isa.BaseMem.size/1024,
+			vfp->isa.ExtMem.phys, vfp->isa.ExtMem.size/1024);
+		*np++ = *vfp;
+		found += 1;
+	    }
+	}
+
+	/*
+	 * try to narrow the detected card type
+	 * Is it possible to have more than one bridge in an
+	 * AtariST/STE/TT/Falcon?
+	 * If yes, then there should be done additional effort...
+	 */
+
+	np = last_bridge + 1;				/* first bridge found */
+	if (found > 1) {
+	    int i;
+	    __vga_descriptor *best = last_bridge;	/* points to best fit bridge-description */
+
+	    for (i = 1; i < found; i++, np++)
+	        if (isbetter(best, np))
+	            best = np;
+
+ 	    last_bridge[0] = *best;	
+	}
+
+	if (last_bridge[0].isa.IOBase.phys) {
+	    /*
+	     * we found an ISA-bridge (or simple graphic card).
+	     * Preset the global available parameters for ISA-emulation
+	     */
+	    detected_vga = last_bridge[0];
+	    isa_bridge = &detected_vga.isa;
+
+	    if (isa_bridge->IOBase.phys)
+		isa_bridge->IOBase.virt = (u8 *)kernel_map((unsigned long) isa_bridge->IOBase.phys, isa_bridge->IOBase.size, 
+						     KERNELMAP_NO_COPYBACK, NULL);
+	    if (isa_bridge->BaseMem.phys)
+		isa_bridge->BaseMem.virt =(u8 *)kernel_map((unsigned long) isa_bridge->BaseMem.phys, isa_bridge->BaseMem.size, 
+						     KERNELMAP_NO_COPYBACK, NULL);
+	    if (isa_bridge->ExtMem.phys)
+		isa_bridge->ExtMem.virt = (u8 *)kernel_map((unsigned long) isa_bridge->ExtMem.phys, isa_bridge->ExtMem.size, 
+						     KERNELMAP_NO_COPYBACK, NULL);
+	    ISAio = isa_bridge->IOBase.virt;
+
+	    DPRINTK("isa-bridge = %s, io=%p, mem=%p, ext=%p\n",
+		    detected_vga.CardName, isa_bridge->IOBase.phys, isa_bridge->BaseMem.phys, isa_bridge->ExtMem.phys);
+
+	    if (ispanther(isa_bridge->IOBase.phys, isa_bridge->BaseMem.phys, isa_bridge->ExtMem.phys)) {
+
+		u8 par_dt_reg, active_edge, old_edge;
+	        int rqgpu, rqmmd, rqav5;
+
+		scratch = ISAio[0x01];
+	        panther_irq = 0;
+
+		/*
+		 * set edge-detection of MFP
+		 * we set the transition sensitivity to the opposite of the
+		 * ports current level.
+		 */
+
+		par_dt_reg = mfp.par_dt_reg;
+		active_edge= mfp.active_edge;
+
+		if (par_dt_reg & (1 << 3))	
+		    active_edge &=~(1 << 3);	/* set to H->L */
+		else
+		    active_edge |= (1 << 3);	/* set to L-H */
+
+		if (par_dt_reg & (1 << 7))
+		    active_edge &=~(1 << 7);
+		else
+		    active_edge |= (1 << 7);
+
+		old_edge =
+		mfp.active_edge = active_edge;
+
+	        /* assign the irq handlers */
+	        rqgpu = request_irq(IRQ_MFP_GPU, detect_swirq, IRQ_TYPE_FAST, "panther", NULL);
+	        rqmmd = request_irq(IRQ_MFP_MMD, detect_swirq, IRQ_TYPE_FAST, "panther", NULL);
+	        rqav5 = request_irq(IRQ_AUTO_5, detect_swirq, IRQ_TYPE_FAST, "panther", NULL);
+		
+		scratch =  ISAio[0x40];
+		for (cnt = 0; cnt < 100000; cnt++)
+			barrier();
+		scratch = ISAio[0x01];
+
+		if (!panther_irq) {
+		    active_edge ^= ((1 << 3) | (1 << 7));
+		    mfp.active_edge = active_edge;
+
+		    scratch = ISAio[0x40];
+		    for (cnt = 0; cnt < 100000; cnt++)
+			barrier();
+		    scratch = ISAio[0x01];
+		}
+
+		if (!rqgpu) free_irq(IRQ_MFP_GPU, 0);
+		if (!rqmmd) free_irq(IRQ_MFP_MMD, 0);
+		if (!rqav5) free_irq(IRQ_AUTO_5, 0);
+
+		if (panther_irq) scratch = ISAio[0];
+		else mfp.active_edge = old_edge;
+
+		PRINTK("%s, IRQ=%d, edge=%02x\n", 
+			panther_irq ? "Panther/2" : "Panther??", panther_irq, active_edge);
+	    }
+	}
+    }
+}
+
+
+/* -------------------------------------------------------------------
+ * 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 );
+}
+
+/*
+ * we have to test (region + 0x100), 'cause there is some hardware around which
+ * may react allergic against writes/reads to/from 0xXXXXXXX0.
+ * Crazy Dots has clockgenerator at wr(IOBase + 0)
+ * Panther/2  has special functions at rd(IOBase + [0..63])
+ */
+__initfunc(static
+int region_accessible(__addr_region *region, int mode, int chkend))
+{
+	__u8 *memregion;
+	int res = 0;
+
+	if ((memregion = region->phys)) {
+	    if (addr_accessible(memregion + 0x100, mode)) {	/* keep away from border */
+		    memregion += region->size - 2;
+		    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_descriptor *vfp))
+{
+	int res = 0;
+
+	if (vfp->ChipId == atari_mch_type) {
+	    if (MACH_IS_MEDUSA)
+		transp_map_16Marea(vfp->isa.BaseMem.phys);
+		
+	    if ((region_accessible(&vfp->isa.BaseMem, READ_BYTE, 0)) &&
+	        (region_accessible(&vfp->isa.IOBase, READ_BYTE, 0))) {
+		if ((!vfp->isa.ExtMem.phys) ||
+		    (region_accessible(&vfp->isa.ExtMem, READ_BYTE, 0)))
+		    res=1;
+	    }
+
+	    if (MACH_IS_MEDUSA)
+		transp_map_off(vfp->isa.BaseMem.phys);
+	}
+	return res;
+}
+
+EXPORT_SYMBOL(ISAio);
+EXPORT_SYMBOL(isa_bridge);
+EXPORT_SYMBOL(detected_vga);
+
--- jes-2.1.120/init/main.c	Mon Sep  7 20:40:41 1998
+++ linux/init/main.c	Thu Sep 10 00:23:12 1998
@@ -85,12 +85,16 @@
 extern void sock_init(void);
 extern void uidcache_init(void);
 extern void mca_init(void);
-extern long sbus_init(long, long);
-extern long powermac_init(unsigned long, unsigned long);
+extern void sbus_init(void);
+extern void powermac_init(void);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
 
+#ifdef CONFIG_PANTHER
+extern void panther_init(void);
+#endif
+
 #ifdef CONFIG_ARCH_ACORN
 extern void ecard_init(void);
 #endif
@@ -1164,6 +1176,9 @@
 #ifdef CONFIG_DIO
 	dio_init();
 #endif
+#ifdef CONFIG_PANTHER
+	panther_init();
+#endif
 
 	/* 
 	 *	We count on the initial thread going ok 
--- linux/Documentation/Configure.help.orig	Fri Sep 18 00:08:25 1998
+++ linux/Documentation/Configure.help	Fri Sep 18 00:13:52 1998
@@ -8873,6 +8873,13 @@
   This option enables support for the Hades Atari clone. If you plan to
   use this kernel on a Hades, say Y here; otherwise say N.
 
+Panther support
+CONFIG_PANTHER
+  This option enables support for the various ISA-bridges for Atari
+  machines. It detects ISA-bridges and exports the variables ISAio,
+  isa_bridge and detected_vga. If you plan to use this kernel on an
+  Atari, say Y here; otherwise say N.
+
 Macintosh support
 CONFIG_MAC
   This option enables support for the Apple Macintosh series of

