Resent-Date: Mon, 5 Oct 1998 20:39:26 +0200 (MET DST)
Date: Mon, 5 Oct 1998 20:31:55 +0200 (NST)
From: Wout Klaren <W.Klaren@inter.NL.net>
To: linux-m68k@lists.linux-m68k.org
Subject: PCI patches
Resent-From: linux-m68k@phil.uni-sb.de

Hello,

These patches to the Linux/m68k PCI BIOS improve the following:

- separated in a hardware independent and a hardware dependent
  part. This should make it easier to add support for other
  m68k machines with a PCI bus.

- no longer skip VGA cards when assigning base addresses to
  PCI cards. The framebuffers are now initialised after the
  PCI BIOS, so it is safe to change the base address register
  of VGA cards.

- use the 'sysdata' member of the 'pci_bus' structure to pass
  a structure with system dependent information like the
  base addresses of the PCI memory and I/O areas. This is useful
  for drivers for PCI cards which have I/O registers at a
  fixed address, like VGA cards.


Wout Klaren


diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver -x *.flags linux-2.1.120.orig/arch/m68k/kernel/Makefile linux-2.1.120/arch/m68k/kernel/Makefile
--- linux-2.1.120.orig/arch/m68k/kernel/Makefile	Sat Jan 31 14:04:52 1998
+++ linux-2.1.120/arch/m68k/kernel/Makefile	Sun Oct  4 13:07:21 1998
@@ -21,7 +21,7 @@
 endif
 
 ifdef CONFIG_PCI
-O_OBJS += bios32.o
+O_OBJS += bios32.o hades-pci.o
 endif
 
 head.o: head.S m68k_defs.h
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver -x *.flags linux-2.1.120.orig/arch/m68k/kernel/bios32.c linux-2.1.120/arch/m68k/kernel/bios32.c
--- linux-2.1.120.orig/arch/m68k/kernel/bios32.c	Sun Aug  9 11:34:19 1998
+++ linux-2.1.120/arch/m68k/kernel/bios32.c	Mon Oct  5 19:30:43 1998
@@ -1,6 +1,5 @@
 /*
- * bios32.c - PCI BIOS functions for Alpha systems not using BIOS
- *	      emulation code.
+ * bios32.c - PCI BIOS functions for m68k systems.
  *
  * Written by Wout Klaren.
  *
@@ -37,10 +36,8 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/byteorder.h>
 #include <asm/io.h>
+#include <asm/pci.h>
 #include <asm/uaccess.h>
 
 #define KB		1024
@@ -48,14 +45,7 @@
 #define GB		(1024*MB)
 
 #define MAJOR_REV	0
-#define MINOR_REV	1
-
-/*
- * Base addresses of the PCI memory and I/O areas on the Hades.
- */
-
-static unsigned long pci_mem_base = 0;
-static unsigned long pci_io_base = 0;
+#define MINOR_REV	2
 
 /*
  * Align VAL to ALIGN, which must be a power of two.
@@ -63,181 +53,87 @@
 
 #define ALIGN(val,align)	(((val) + ((align) - 1)) & ~((align) - 1))
 
+#define MAX(val1, val2) 	(((val1) > (val2)) ? val1 : val2)
+
+extern struct pci_bus_info *init_hades_pci(void);
+
 /*
- * Calculate the address of the PCI configuration area of the given
- * device.
- *
- * BUG: boards with multiple functions are probably not correctly
- * supported.
+ * Bus info structure of the PCI bus. A pointer to this structure is
+ * put in the sysdata member of the pci_bus structure.
  */
 
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
-			unsigned char where, unsigned long *pci_addr)
-{
-	static const unsigned long pci_conf_base[] = { 0xA0080000, 0xA0040000,
-						       0xA0020000, 0xA0010000 };
-	int device = device_fn >> 3;
-
-	DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
-		  bus, device_fn, where, pci_addr));
-
-	if (device > 3) {
-		DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning -1\n", device));
-		return -1;
-	}
+static struct pci_bus_info *bus_info;
 
-	*pci_addr = pci_conf_base[device] | (where);
-	DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", *pci_addr));
-	return 0;
-}
+static int pci_modify = 1;		/* If set, layout the PCI bus ourself. */
+static int skip_vga = 0;		/* If set do not modify base addresses
+					   of vga cards.*/
+
+static unsigned int io_base;
+static unsigned int mem_base;
 
 int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
 			     unsigned char where, unsigned char *value)
 {
-	unsigned long pci_addr;
-
-	*value = 0xff;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = *((unsigned char *)pci_addr);
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->read_config_byte(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 int pcibios_read_config_word(unsigned char bus, unsigned char device_fn,
 			     unsigned char where, unsigned short *value)
 {
-	unsigned long pci_addr;
-
-	*value = 0xffff;
-
-	if (where & 0x1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = le16_to_cpu(*((unsigned short *)pci_addr));
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->read_config_word(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 int pcibios_read_config_dword(unsigned char bus, unsigned char device_fn,
 			      unsigned char where, unsigned int *value)
 {
-	unsigned long pci_addr;
-
-	*value = 0xffffffff;
-
-	if (where & 0x3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = le32_to_cpu(*((unsigned int *)pci_addr));
-
-	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
-	{
-		if ((*value & PCI_BASE_ADDRESS_SPACE) ==
-		    PCI_BASE_ADDRESS_SPACE_IO)
-			*value += pci_io_base;
-		else
-		{
-			if (*value == 0)
-			{
-				/*
-				 * Base address is 0. Test if this base
-				 * address register is used.
-				 */
-
-				*((unsigned long *)pci_addr) = 0xffffffff;
-				if (*((unsigned long *)pci_addr) != 0)
-					*value += pci_mem_base;
-			}
-			else
-				*value += pci_mem_base;
-		}
-	}
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->read_config_dword(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 int pcibios_write_config_byte(unsigned char bus, unsigned char device_fn,
 			      unsigned char where, unsigned char value)
 {
-	unsigned long pci_addr;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*((unsigned char *)pci_addr) = value;
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->write_config_byte(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 int pcibios_write_config_word(unsigned char bus, unsigned char device_fn,
 			      unsigned char where, unsigned short value)
 {
-	unsigned long pci_addr;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*((unsigned short *)pci_addr) = cpu_to_le16(value);
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->write_config_word(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 int pcibios_write_config_dword(unsigned char bus, unsigned char device_fn,
 			       unsigned char where, unsigned int value)
 {
-	unsigned long pci_addr;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
-	{
-		if ((value & PCI_BASE_ADDRESS_SPACE) ==
-		    PCI_BASE_ADDRESS_SPACE_IO)
-			value -= pci_io_base;
-		else
-			value -= pci_mem_base;
-	}
-
-	*((unsigned int *)pci_addr) = cpu_to_le32(value);
-
-	return PCIBIOS_SUCCESSFUL;
+	if (bus_info != NULL)
+		return bus_info->write_config_dword(bus, device_fn, where, value);
+	else
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
 /*
- * Macro to enable programming of the PCI devices. On the Hades this
- * define should be true, because the Hades has no PCI BIOS.
- */
-
-#define PCI_MODIFY		1
-
-#if PCI_MODIFY
-
-/*
- * Leave some room for a VGA card. We assume that the VGA card is
- * always in the first 32M of PCI memory. For the time being we do
- * not program the VGA card, because to make this work we also
- * need to change the frame buffer device.
- */
-
-#define FIRST_IO_ADDR	0x10000
-#define FIRST_MEM_ADDR	0x02000000
-
-static unsigned int io_base = FIRST_IO_ADDR;	/* Skip first 64K. */
-static unsigned int mem_base = FIRST_MEM_ADDR;	/* Skip first 32M. */
-
-/*
+ * static void disable_dev(struct pci_dev *dev)
+ *
  * Disable PCI device DEV so that it does not respond to I/O or memory
  * accesses.
+ *
+ * Parameters:
+ *
+ * dev	- device to disable.
  */
 
 __initfunc(static void disable_dev(struct pci_dev *dev))
@@ -245,9 +141,9 @@
 	struct pci_bus *bus;
 	unsigned short cmd;
 
-	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
-	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
-	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+	if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
 		return;
 
 	bus = dev->bus;
@@ -261,10 +157,7 @@
  * Layout memory and I/O for a device:
  */
 
-#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
-
-__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
-								  unsigned long pci_io_base))
+__initfunc(static void layout_dev(struct pci_dev *dev))
 {
 	struct pci_bus *bus;
 	unsigned short cmd;
@@ -273,12 +166,12 @@
 	int i;
 
 	/*
-	 * Skip video cards for the time being.
+	 * Skip video cards if requested.
 	 */
 
-	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
-	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
-	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+	if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
 		return;
 
 	bus = dev->bus;
@@ -324,7 +217,7 @@
 			io_base = base + size;
 			pcibios_write_config_dword(bus->number, dev->devfn,
 						   reg, base | 0x1);
-			dev->base_address[i] = (pci_io_base + base) | 1;
+			dev->base_address[i] = base | 0x1;
 			DBG_DEVS(("layout_dev: IO address: %lX\n", base));
 		}
 		else
@@ -372,7 +265,7 @@
 			mem_base = base + size;
 			pcibios_write_config_dword(bus->number, dev->devfn,
 						   reg, base);
-			dev->base_address[i] = pci_mem_base + base;
+			dev->base_address[i] = base;
 		}
 	}
 
@@ -400,8 +293,7 @@
 		  bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
 }
 
-__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
-								  unsigned long pci_io_base))
+__initfunc(static void layout_bus(struct pci_bus *bus))
 {
 	struct pci_dev *dev;
 
@@ -443,65 +335,8 @@
 	for (dev = bus->devices; dev; dev = dev->sibling)
 	{
 		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
-			layout_dev(dev, pci_mem_base, pci_io_base);
-	}
-}
-
-#endif /* !PCI_MODIFY */
-
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.
- */
-
-int pcibios_find_device(unsigned short vendor, unsigned short device_id,
-			unsigned short index, unsigned char *bus,
-			unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next)
-	{
-		if (dev->vendor == vendor && dev->device == device_id)
-		{
-			if (curr == index)
-			{
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
+			layout_dev(dev);
 	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-
-int pcibios_find_class(unsigned int class_code, unsigned short index,
-		       unsigned char *bus, unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next)
-	{
-		if (dev->class == class_code)
-		{
-			if (curr == index)
-			{
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
 int pcibios_present(void)
@@ -516,75 +351,66 @@
 {
 	printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
 
-#if !PCI_MODIFY
-	printk("...NOT modifying existing PCI configuration\n");
-#endif
-
-	pci_mem_base = 0x80000000;
-	pci_io_base = 0xB0000000;
+	if (MACH_IS_HADES)
+		bus_info = init_hades_pci();
+	else
+		bus_info = NULL;
 }
 
-/*
- * static inline void hades_fixup(void)
- *
- * Assign IRQ numbers as used by Linux to the interrupt pins
- * of the PCI cards.
- */
-
-__initfunc(static inline void hades_fixup(void))
+__initfunc(static void pcibios_set_sysdata(struct pci_bus *bus))
 {
-	char irq_tab[4] = {
-			    IRQ_TT_MFP_IO0,	/* Slot 0. */
-			    IRQ_TT_MFP_IO1,	/* Slot 1. */
-			    IRQ_TT_MFP_SCC,	/* Slot 2. */
-			    IRQ_TT_MFP_SCSIDMA	/* Slot 3. */
-			  };
-	struct pci_dev *dev;
-	unsigned char slot;
+	struct pci_bus *p;
 
-	/*
-	 * Go through all devices, fixing up irqs as we see fit:
-	 */
+	bus->sysdata = (void *) bus_info;
 
-	for (dev = pci_devices; dev; dev = dev->next)
-	{
-		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
-		{
-			slot = PCI_SLOT(dev->devfn);	/* Determine slot number. */
-			dev->irq = irq_tab[slot];
-#if PCI_MODIFY
-			pcibios_write_config_byte(dev->bus->number, dev->devfn,
-						  PCI_INTERRUPT_LINE, dev->irq);
-#endif
-		}
-	}
+	for (p = bus->children; p != NULL; p = p->next)
+		pcibios_set_sysdata(p);
 }
 
 __initfunc(void pcibios_fixup(void))
 {
-#if PCI_MODIFY
-	unsigned long orig_mem_base, orig_io_base;
+	if (bus_info == NULL)
+		return;			/* No bus. Return. */
+
+	if (pci_modify)
+	{
+		/*
+		 * Layout the bus. First determine the start addresses to use. The
+		 * first 64K I/O addresses is always skipped. VGA cards might have
+		 * I/O registers in this area.
+		 */
+
+		io_base = bus_info->io_base + 0x10000;
+
+		/*
+		 * If 'skip_vga' is true, skip the first 64 MB when allocating
+		 * devices. The memory area of most video cards on the PCI bus
+		 * of the Hades are in the first 64 MB. Otherwise start
+		 * allocating devices from address 0.
+		 */
 
-	orig_mem_base = pci_mem_base;
-	orig_io_base = pci_io_base;
-	pci_mem_base = 0;
-	pci_io_base = 0;
+		mem_base = bus_info->mem_base;
+		if (skip_vga)
+			mem_base += 0x04000000;	/* Skip the first 64 MB. */
+
+		/*
+		 * Scan the tree, allocating PCI memory and I/O space.
+		 */
+
+		layout_bus(&pci_root);
+	}
 
 	/*
-	 * Scan the tree, allocating PCI memory and I/O space.
+	 * Fix interrupt assignments, etc.
 	 */
 
-	layout_bus(&pci_root, orig_mem_base, orig_io_base);
-
-	pci_mem_base = orig_mem_base;
-	pci_io_base = orig_io_base;
-#endif
+	bus_info->fixup(pci_modify);
 
 	/*
-	 * Now is the time to do all those dirty little deeds...
+	 * Set the 'sysdata' member of the PCI buses.
 	 */
 
-	hades_fixup();
+	pcibios_set_sysdata(&pci_root);
 }
 
 __initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
@@ -593,6 +419,17 @@
 
 __initfunc(char *pcibios_setup(char *str))
 {
+	if (!strcmp(str, "nomodify"))
+	{
+		pci_modify = 0;
+		return NULL;
+	}
+	else if (!strcmp(str, "skipvga"))
+	{
+		skip_vga = 1;
+		return NULL;
+	}
+
 	return str;
 }
 #endif /* CONFIG_PCI */
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver -x *.flags linux-2.1.120.orig/arch/m68k/kernel/hades-pci.c linux-2.1.120/arch/m68k/kernel/hades-pci.c
--- linux-2.1.120.orig/arch/m68k/kernel/hades-pci.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.120/arch/m68k/kernel/hades-pci.c	Sun Oct  4 13:16:44 1998
@@ -0,0 +1,306 @@
+/*
+ * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone.
+ *
+ * Written by Wout Klaren.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#if 0
+# define DBG_DEVS(args)		printk args
+#else
+# define DBG_DEVS(args)
+#endif
+
+#ifdef CONFIG_PCI
+
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/byteorder.h>
+#include <asm/pci.h>
+
+#define HADES_MEM_BASE	0x80000000
+#define HADES_MEM_SIZE	0x20000000
+#define HADES_IO_BASE	0xB0000000
+#define HADES_IO_SIZE	0x10000000
+
+/*
+ * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
+ *			     unsigned char where)
+ *
+ * Calculate the address of the PCI configuration area of the given
+ * device.
+ *
+ * BUG: boards with multiple functions are probably not correctly
+ * supported.
+ */
+
+static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
+			  unsigned char where)
+{
+	static const unsigned long pci_conf_base[] = { 0xA0080000, 0xA0040000,
+						       0xA0020000, 0xA0010000 };
+	int device = device_fn >> 3;
+	void *result;
+
+	DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
+		  bus, device_fn, where, pci_addr));
+
+	if (device > 3)
+	{
+		DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULL\n", device));
+		return NULL;
+	}
+
+	if (bus != 0)
+	{
+		DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULL\n", device));
+		return NULL;
+	}
+
+	result = (void *) (pci_conf_base[device] | (where));
+	DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", (unsigned long) result));
+	return result;
+}
+
+static int hades_read_config_byte(unsigned char bus, unsigned char device_fn,
+				  unsigned char where, unsigned char *value)
+{
+	volatile unsigned char *pci_addr;
+
+	*value = 0xff;
+
+	if ((pci_addr = (unsigned char *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = *pci_addr;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int hades_read_config_word(unsigned char bus, unsigned char device_fn,
+				  unsigned char where, unsigned short *value)
+{
+	volatile unsigned short *pci_addr;
+
+	*value = 0xffff;
+
+	if (where & 0x1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if ((pci_addr = (unsigned short *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = le16_to_cpu(*pci_addr);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int hades_read_config_dword(unsigned char bus, unsigned char device_fn,
+				   unsigned char where, unsigned int *value)
+{
+	volatile unsigned int *pci_addr;
+
+	*value = 0xffffffff;
+
+	if (where & 0x3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if ((pci_addr = (unsigned int *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = le32_to_cpu(*pci_addr);
+
+	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
+	{
+		if ((*value & PCI_BASE_ADDRESS_SPACE) ==
+		    PCI_BASE_ADDRESS_SPACE_IO)
+		{
+			/*
+			 * Base address register that contains an I/O address. If the
+			 * address is valid on the Hades (0 <= *value < HADES_IO_SIZE),
+			 * add HADES_IO_BASE to the value.
+			 */
+
+			if (*value < HADES_IO_SIZE)
+				*value += HADES_IO_BASE;
+		}
+		else
+		{
+			/*
+			 * Base address register that contains an memory address. If the
+			 * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE),
+			 * add HADES_MEM_BASE to the value.
+			 */
+
+			if (*value == 0)
+			{
+				/*
+				 * Base address is 0. Test if this base
+				 * address register is used.
+				 */
+
+				*pci_addr = 0xffffffff;
+				if (*pci_addr != 0)
+				{
+					*pci_addr = *value;
+					if (*value < HADES_MEM_SIZE)
+						*value += HADES_MEM_BASE;
+				}
+			}
+			else
+			{
+				if (*value < HADES_MEM_SIZE)
+					*value += HADES_MEM_BASE;
+			}
+		}
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int hades_write_config_byte(unsigned char bus, unsigned char device_fn,
+				   unsigned char where, unsigned char value)
+{
+	volatile unsigned char *pci_addr;
+
+	if ((pci_addr = (unsigned char *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*pci_addr = value;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int hades_write_config_word(unsigned char bus, unsigned char device_fn,
+				   unsigned char where, unsigned short value)
+{
+	volatile unsigned short *pci_addr;
+
+	if ((pci_addr = (unsigned short *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*pci_addr = cpu_to_le16(value);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int hades_write_config_dword(unsigned char bus, unsigned char device_fn,
+				    unsigned char where, unsigned int value)
+{
+	volatile unsigned int *pci_addr;
+
+	if ((pci_addr = (unsigned int *) mk_conf_addr(bus, device_fn, where)) == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
+	{
+		if ((value & PCI_BASE_ADDRESS_SPACE) ==
+		    PCI_BASE_ADDRESS_SPACE_IO)
+		{
+			/*
+			 * I/O address. Check if the address is valid address on
+			 * the Hades (HADES_IO_BASE <= value < HADES_IO_BASE + HADES_IO_SIZE) or
+			 * if the value is 0xffffffff. If not true do not write
+			 * the base address register. If it is a valid base address
+			 * subtract HADES_IO_BASE from the value.
+			 */
+
+			if ((value >= HADES_IO_BASE) && (value < (HADES_IO_BASE + HADES_IO_SIZE)))
+				value -= HADES_IO_BASE;
+			else
+			{
+				if (value != 0xffffffff)
+					return PCIBIOS_SET_FAILED;
+			}
+		}
+		else
+		{
+			/*
+			 * Memory address. Check if the address is valid address on
+			 * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or
+			 * if the value is 0xffffffff. If not true do not write
+			 * the base address register. If it is a valid base address
+			 * subtract HADES_MEM_BASE from the value.
+			 */
+
+			if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE)))
+				value -= HADES_MEM_BASE;
+			else
+			{
+				if (value != 0xffffffff)
+					return PCIBIOS_SET_FAILED;
+			}
+		}
+	}
+
+	*pci_addr = cpu_to_le32(value);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * static inline void hades_fixup(void)
+ *
+ * Assign IRQ numbers as used by Linux to the interrupt pins
+ * of the PCI cards.
+ */
+
+__initfunc(static void hades_fixup(int pci_modify))
+{
+	char irq_tab[4] = {
+			    IRQ_TT_MFP_IO0,	/* Slot 0. */
+			    IRQ_TT_MFP_IO1,	/* Slot 1. */
+			    IRQ_TT_MFP_SCC,	/* Slot 2. */
+			    IRQ_TT_MFP_SCSIDMA	/* Slot 3. */
+			  };
+	struct pci_dev *dev;
+	unsigned char slot;
+
+	/*
+	 * Go through all devices, fixing up irqs as we see fit:
+	 */
+
+	for (dev = pci_devices; dev; dev = dev->next)
+	{
+		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
+		{
+			slot = PCI_SLOT(dev->devfn);	/* Determine slot number. */
+			dev->irq = irq_tab[slot];
+			if (pci_modify)
+				pcibios_write_config_byte(dev->bus->number, dev->devfn,
+							  PCI_INTERRUPT_LINE, dev->irq);
+		}
+	}
+}
+
+__initfunc(struct pci_bus_info *init_hades_pci(void))
+{
+	struct pci_bus_info *bus;
+
+	bus = kmalloc(sizeof(struct pci_bus_info), GFP_ATOMIC);
+
+	bus->mem_base = HADES_MEM_BASE;
+	bus->mem_size = HADES_MEM_SIZE;
+	bus->io_base = HADES_IO_BASE;
+	bus->io_size = HADES_IO_SIZE;
+
+	bus->read_config_byte = hades_read_config_byte;
+	bus->read_config_word = hades_read_config_word;
+	bus->read_config_dword = hades_read_config_dword;
+
+	bus->write_config_byte = hades_write_config_byte;
+	bus->write_config_word = hades_write_config_word;
+	bus->write_config_dword = hades_write_config_dword;
+
+	bus->fixup = hades_fixup;
+
+	return bus;
+}
+#endif
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver -x *.flags linux-2.1.120.orig/include/asm-m68k/pci.h linux-2.1.120/include/asm-m68k/pci.h
--- linux-2.1.120.orig/include/asm-m68k/pci.h	Thu Jan  1 01:00:00 1970
+++ linux-2.1.120/include/asm-m68k/pci.h	Mon Oct  5 19:13:05 1998
@@ -0,0 +1,42 @@
+/*
+ * asm-m68k/pci.h - m68k specific PCI declarations.
+ *
+ * Written by Wout Klaren.
+ */
+
+/*
+ * Structure with hardware dependent information and functions of the
+ * PCI bus.
+ */
+
+struct pci_bus_info
+{
+	/*
+	 * Information about memory areas.
+	 */
+	
+	unsigned long mem_base;		/* Base address of memory area of the PCI bus. */
+	unsigned long mem_size;		/* Size of memory area. */
+	unsigned long io_base;		/* Base address of I/O area. */
+	unsigned long io_size;		/* Size of I/O area. */
+
+	/*
+	 * System dependent functions.
+	 */
+	
+	int (*read_config_byte)(unsigned char bus, unsigned char device_fn,
+				unsigned char where, unsigned char *value);
+	int (*read_config_word)(unsigned char bus, unsigned char device_fn,
+				unsigned char where, unsigned short *value);
+	int (*read_config_dword)(unsigned char bus, unsigned char device_fn,
+				 unsigned char where, unsigned int *value);
+
+	int (*write_config_byte)(unsigned char bus, unsigned char device_fn,
+				 unsigned char where, unsigned char value);
+	int (*write_config_word)(unsigned char bus, unsigned char device_fn,
+				 unsigned char where, unsigned short value);
+	int (*write_config_dword)(unsigned char bus, unsigned char device_fn,
+				  unsigned char where, unsigned int value);
+
+	void (*fixup)(int pci_modify);
+};

