Date: Tue, 15 Jul 1997 10:12:47 +0200 (CEST)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Linux/m68k <linux-m68k@phil.uni-sb.de>
Subject: L68K: More Amiga IDE drivers...
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: linux-m68k@phil.uni-sb.de


This patch is EXPERIMENTAL! It's a replacement for my IDE doubler patch.

It adds support for the following things:

  - IDE doublers on the Amiga builtin IDE interface. Using such a doubler you
    can connect up to 4 IDE devices on the builtin IDE interface. Note that the
    standard Linux/m68k IDE driver for Amiga may not work correctly if you have
    an IDE doubler...

    Activation: CONFIG_BLK_DEV_IDEDOUBLER at compile time, `ide=doubler' on
    the kernel command line. Without `ide=doubler' it behaves exactly like the
    original driver.

    Please test this part! Even if you don't have an IDE doubler, I'd like to
    see your kernel output, especially the probe for the capacitance on the
    IDE port (I still don't believe that part can be made reliable...). Booting
    the kernel without a root file system is sufficient if you don't have an
    IDE doubler.

  - IDE interfaces on the Buddha (2 IDE interfaces) and Catweasel (3 IDE
    interfaces) Amiga expansion boards. This part is even more experimental,
    I have no idea whether it will work at all. Anyone with a Buddha/Catweasel
    and a bit kernel experience to sort things out?

    Note that maximum _one_ Buddha _or_ Catweasel is supported; and only one of
    them, not both!

    The Catweasel also contains a floppy controller, but this won't be
    supported in the near future, unless the manufacturer decides to release
    the specs (the specs of the IDE part are free).

Now up to 4 hardware interfaces are supported, cfr. on PC. A4000s with IDE
doublers and Catweasels will miss some devices :-) But this can be changed by
increasing MAX_HWIFS in <asm/ide.h>.

To do the above things, I had to make the following changes to the IDE design:

  - If the IDE doubler is enabled, the CONTROL register on the IDE interface is
    no longer available. But this isn't a problem on m68k. Now all accesses to
    this register are guarded with an `if (IDE_CONTROL_REG)'.

  - On PCs, all IDE registers of one interface are at the same offset of one
    base register.  This is not true on Amiga and Atari: different IDE
    interfaces can have different port organizations (in memory). To support
    this, port registers are now initialized through ide_setup_ports() (ide.c).

    BTW, what to do with ide_init_hwif_ports()???

  - Split off of IDE hardware interface specific things. I created 4 new files
    in drivers/block:

      o pc_ide.c: support for 4 IDE interfaces at the `well known' I/O ports on
                  PC hardware. Untested, but it compiles.

      o gayle.c: support for the Amiga Gayle IDE interface, plus a second
      		 interface if IDE doubler support is enabled.

      o falcon-ide.c: support for the Atari Falcon IDE interface. Untested, but
		      it compiles.

      o buddha.c: support for the Buddha and Catweasel IDE interfaces (both
      		  boards are similar, hence one driver). Untested, but it
      		  compiles.

    Mark/Gadi: shouldn't the check_region() et al calls on I/O ports be put in
    pc_ide.c? They are not needed for gayle/falcon-ide/buddha.c.

  - IDE interfaces are probed through probe_hwif() (ide.c), which asks all
    drivers to look for a new hardware interface.

Good luck! And please test this on Atari Falcon, too! If it works on Atari, it
should be safe to include this patch in the next kernel release.

P.S. Mark Lord and Gadi Oxman will receive patches relative to the native
     2.1.42.

P.S.2. If you've lost sync, you can find the diffs for my current source tree
       (relative to m68k-2.1.42, more than 2MB after decompression!) at

     http://www.cs.kuleuven.ac.be/~geert/bin/linux-m68k-2.1.42-970714.diff.gz

--- clean/linux/m68k-2.1.42/Documentation/Configure.help	Sun Jun  1 22:04:26 1997
+++ linux-2.1.42/Documentation/Configure.help	Sun Jul 13 22:10:49 1997
@@ -367,6 +367,44 @@
   devices are not supported yet.  See the Documentation/ide.txt and
   promise.c files for more info.
 
+Amiga Gayle IDE interface support
+CONFIG_BLK_DEV_GAYLE
+  This is the IDE driver for the builtin IDE interface on some Amigas
+  models.  It supports both the `A1200 style' (used in A600 and A1200)
+  and `A4000 style' (used in A4000 and A4000T) of the Gayle IDE
+  interface.
+  Say Y if you have such an Amiga model and want to use IDE devices
+  (hard disks, CD-ROM drives, etc.) that are connected to the builtin
+  IDE interface.
+
+Falcon IDE interface support
+CONFIG_BLK_DEV_FALCON_IDE
+  This is the IDE driver for the builtin IDE interface on the Atari
+  Falcon.
+  Say Y if you have a Falcon and want to use IDE devices (hard disks,
+  CD-ROM drives, etc.) that are connected to the builtin IDE interface.
+
+Buddha/Catweasel IDE interface support (EXPERIMENTAL)
+CONFIG_BLK_DEV_BUDDHA
+  This is the IDE driver for the IDE interfaces on the Buddha and
+  Catweasel expansion boards.  It supports up to two interfaces on the
+  Buddha and three on the Catweasel.
+  Say Y if you have a Buddha or Catweasel expansion board and want to
+  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
+  to one of its IDE interfaces.
+
+Amiga IDE Doubler support (EXPERIMENTAL)
+CONFIG_BLK_DEV_IDEDOUBLER
+  This driver provides support for the so called `IDE doublers' (made by
+  various manufacturers, e.g. Eyetech) that can be connected to the
+  builtin IDE interface of some Amiga models. Using such an IDE doubler,
+  you can connect up to four instead of two IDE devices on the Amiga's
+  builtin IDE interface.
+  Note that the normal Amiga Gayle IDE driver may not work correctly if
+  you have an IDE doubler and don't enable this driver!
+  Say Y if you have an IDE doubler.  The driver is enabled at kernel
+  runtime using the "ide=doubler" kernel boot parameter.
+
 XT harddisk support
 CONFIG_BLK_DEV_XD
   Very old 8 bit hard disk controllers used in the IBM XT computer. To
--- clean/linux/m68k-2.1.42/arch/m68k/config.in	Sun May 18 23:05:12 1997
+++ linux-2.1.42/arch/m68k/config.in	Sun Jul 13 22:10:47 1997
@@ -76,6 +76,16 @@
   dep_tristate '   Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
   dep_tristate '   Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
   dep_tristate '   SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
+  if [ "$CONFIG_AMIGA" = "y" ]; then
+    bool '   Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
+    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool '   Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA
+      bool '   Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE
+    fi
+  fi
+  if [ "$CONFIG_ATARI" = "y" ]; then
+    bool '   Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE
+  fi
 fi
 if [ "$CONFIG_AMIGA" = "y" ]; then
   tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
--- clean/linux/m68k-2.1.42/drivers/block/ide.c	Sun May 18 23:09:11 1997
+++ linux-2.1.42/drivers/block/ide.c	Mon Jul 14 22:13:43 1997
@@ -344,6 +344,10 @@
  */
 ide_hwif_t	ide_hwifs[MAX_HWIFS];	/* master data repository */
 
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+extern int ide_doubler;
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
 #if (DISK_RECOVERY_TIME > 0)
 /*
  * For really screwy hardware (hey, at least it *can* be used with Linux)
@@ -373,6 +377,42 @@
 }
 
 /*
+ * Setup the machine dependent stuff of an IDE interface
+ */
+void ide_setup_ports(ide_hwif_t *hwif, ide_ioreg_t base, const int *offsets,
+		     ide_ioreg_t irqport, ide_ack_intr_t *ack_intr)
+{
+    int i;
+
+    for (i = 0; i < IDE_IRQ_OFFSET; i++)
+	/* offset -1 means not present */
+	hwif->io_ports[i] = offsets[i] != -1 ? base+offsets[i] : 0;
+    hwif->io_ports[IDE_IRQ_OFFSET] = irqport;
+    hwif->ack_intr = ack_intr;
+}
+
+/*
+ * Probe for available interfaces
+ */
+static int probe_hwif(int index, ide_hwif_t *hwif)
+{
+    return 0
+#ifndef __mc68000__
+	|| pcide_probe_hwif(index, hwif)
+#endif
+#ifdef CONFIG_BLK_DEV_GAYLE
+	|| gayle_probe_hwif(index, hwif)
+#endif
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+	|| falconide_probe_hwif(index, hwif)
+#endif
+#ifdef CONFIG_BLK_DEV_BUDDHA
+	|| buddha_probe_hwif(index, hwif)
+#endif
+    ;
+}
+
+/*
  * Do not even *think* about calling this!
  */
 static void init_hwif_data (unsigned int index)
@@ -389,8 +429,7 @@
 
 	/* fill in any non-zero initial values */
 	hwif->index     = index;
-	ide_init_hwif_ports(hwif->io_ports, ide_default_io_base(index), &hwif->irq);
-	hwif->noprobe	= !hwif->io_ports[IDE_DATA_OFFSET];
+	hwif->noprobe = !probe_hwif(index, hwif);
 #ifdef CONFIG_BLK_DEV_HD
 	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
 		hwif->noprobe = 1; /* may be overridden by ide_setup() */
@@ -778,6 +817,10 @@
 		pre_reset(&hwif->drives[unit]);
 
 #if OK_TO_RESET_CONTROLLER
+	if (!IDE_CONTROL_REG) {
+		restore_flags (flags);
+		return;
+	}
 	/*
 	 * Note that we also set nIEN while resetting the device,
 	 * to mask unwanted interrupts from the interface during the reset.
@@ -976,7 +1019,8 @@
 void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
 	ide_set_handler (drive, handler, WAIT_CMD);
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
 	OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
@@ -1275,7 +1319,9 @@
 		ide_drive_t *drive = choose_drive(hwgroup);
 		if (drive != NULL) {
 			ide_hwif_t *hwif = HWIF(drive);
-			if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif)
+			if (hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET] &&
+			    hwgroup->hwif->sharing_irq &&
+			    hwif != hwgroup->hwif)
 				OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
 			drive->sleep = 0;
 			blk_dev[hwif->major].current_request = hwgroup->rq = drive->queue;
@@ -1451,8 +1501,7 @@
 	ide_hwgroup_t *hwgroup = dev_id;
 	ide_handler_t *handler;
 
-	if (!ide_ack_intr (hwgroup->hwif->io_ports[IDE_STATUS_OFFSET],
-			   hwgroup->hwif->io_ports[IDE_IRQ_OFFSET]))
+	if (hwgroup->hwif->ack_intr && !hwgroup->hwif->ack_intr(hwgroup->hwif))
 		return;
 
 	if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
@@ -1771,7 +1820,8 @@
 	 * allocated for weird IDE interface chipsets.
 	 */
 	ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-	ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+	if (hwif->io_ports[IDE_CONTROL_OFFSET])
+		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 
 	/*
 	 * Remove us from the hwgroup, and free
@@ -2261,6 +2311,7 @@
  * "ide0=qd6580"	: probe/support qd6580 interface
  * "ide0=ali14xx"	: probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
  * "ide0=umc8672"	: probe/support umc8672 chipsets
+ * "ide=doubler"	: probe/support IDE doublers on Amiga
  */
 __initfunc(void ide_setup (char *s))
 {
@@ -2270,6 +2321,14 @@
 	unsigned int hw, unit;
 	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
 	const char max_hwif  = '0' + (MAX_HWIFS - 1);
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+	if (!strcmp(s, "ide=doubler")) {
+		printk("+++ Enabled support for IDE doubler\n");
+		ide_doubler = 1;
+		return;
+	}
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
 
 	printk("ide_setup: %s", s);
 	init_ide_data ();
--- clean/linux/m68k-2.1.42/drivers/block/ide-cd.c	Thu Apr 17 17:06:48 1997
+++ linux-2.1.42/drivers/block/ide-cd.c	Sun Jul 13 22:10:44 1997
@@ -569,7 +569,8 @@
 
 	OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
 	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
-	OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
  
 	if (info->dma)
 		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
--- clean/linux/m68k-2.1.42/drivers/block/ide-disk.c	Sun May 18 23:09:09 1997
+++ linux-2.1.42/drivers/block/ide-disk.c	Sun Jul 13 22:10:44 1997
@@ -313,7 +313,8 @@
 	int use_promise_io = 0;
 #endif /* CONFIG_BLK_DEV_PROMISE */
 
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
 #ifdef CONFIG_BLK_DEV_PROMISE
 	if (IS_PROMISE_DRIVE) {
--- clean/linux/m68k-2.1.42/drivers/block/ide-floppy.c	Sun May 18 23:09:09 1997
+++ linux-2.1.42/drivers/block/ide-floppy.c	Sun Jul 13 22:10:45 1997
@@ -850,7 +850,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_TRITON */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
--- clean/linux/m68k-2.1.42/drivers/block/ide-probe.c	Sun May 18 23:09:09 1997
+++ linux-2.1.42/drivers/block/ide-probe.c	Mon Jul 14 22:50:48 1997
@@ -66,6 +66,8 @@
 
 #include "ide.h"
 
+#define DEBUG
+
 static inline void do_identify (ide_drive_t *drive, byte cmd)
 {
 	int bswap = 1;
@@ -176,14 +178,16 @@
 	unsigned long timeout;
 	int irqs = 0;
 
-	if (!HWIF(drive)->irq) {		/* already got an IRQ? */
+	if (IDE_CONTROL_REG && !HWIF(drive)->irq) { /* already got an IRQ? */
 		probe_irq_off(probe_irq_on());	/* clear dangling irqs */
 		irqs = probe_irq_on();		/* start monitoring irqs */
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
 	}
 
 	delay_50ms();				/* take a deep breath */
-	if ((IN_BYTE(IDE_ALTSTATUS_REG) ^ IN_BYTE(IDE_STATUS_REG)) & ~INDEX_STAT) {
+	if (!IDE_CONTROL_REG)
+		hd_status = IDE_STATUS_REG;
+	else if ((IN_BYTE(IDE_ALTSTATUS_REG) ^ IN_BYTE(IDE_STATUS_REG)) & ~INDEX_STAT) {
 		printk("%s: probing with STATUS instead of ALTSTATUS\n", drive->name);
 		hd_status = IDE_STATUS_REG;	/* ancient Seagate drives */
 	} else
@@ -221,7 +225,7 @@
 		restore_flags(flags);
 	} else
 		rc = 2;			/* drive refused ID */
-	if (!HWIF(drive)->irq) {
+	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
 		irqs = probe_irq_off(irqs);	/* get our irq number */
 		if (irqs > 0) {
 			HWIF(drive)->irq = irqs; /* save it for later */
@@ -389,6 +393,7 @@
 {
 	unsigned int unit;
 	unsigned long flags;
+	ide_ioreg_t ide_control_reg = hwif->io_ports[IDE_CONTROL_OFFSET];
 
 	if (hwif->noprobe)
 		return;
@@ -396,9 +401,9 @@
 		probe_cmos_for_drives (hwif);
 #if CONFIG_BLK_DEV_PROMISE
 	if (!hwif->is_promise2 &&
-	   (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1))) {
+	   (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || (ide_control_reg && ide_check_region(ide_control_reg,1)))) {
 #else
-	if (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1)) {
+	if (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || (ide_control_reg && ide_check_region(ide_control_reg,1))) {
 #endif /* CONFIG_BLK_DEV_PROMISE */
 		int msgout = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -426,17 +431,18 @@
 		if (drive->present && !hwif->present) {
 			hwif->present = 1;
 			ide_request_region(hwif->io_ports[IDE_DATA_OFFSET],  8, hwif->name);
-			ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
+			if (ide_control_reg)
+				ide_request_region(ide_control_reg, 1, hwif->name);
 		}
 	}
-	if (hwif->reset) {
+	if (ide_control_reg && hwif->reset) {
 		unsigned long timeout = jiffies + WAIT_WORSTCASE;
 		byte stat;
 
 		printk("%s: reset\n", hwif->name);
-		OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(12, ide_control_reg);
 		udelay(10);
-		OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(8, ide_control_reg);
 		do {
 			delay_50ms();
 			stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
--- clean/linux/m68k-2.1.42/drivers/block/ide-tape.c	Sun May 18 23:09:10 1997
+++ linux-2.1.42/drivers/block/ide-tape.c	Sun Jul 13 22:10:46 1997
@@ -1924,7 +1924,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_TRITON */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
--- clean/linux/m68k-2.1.42/drivers/block/ide.h	Thu Apr 17 17:06:52 1997
+++ linux-2.1.42/drivers/block/ide.h	Mon Jul 14 22:13:23 1997
@@ -292,6 +292,12 @@
 typedef void (ide_selectproc_t) (ide_drive_t *);
 
 /*
+ * Check for an interrupt and acknowledge the interrupt status
+ */
+struct hwif_s;
+typedef int (ide_ack_intr_t)(struct hwif_s *);
+
+/*
  * hwif_chipset_t is used to keep track of the specific hardware
  * chipset used by each IDE interface, if known.
  */
@@ -330,6 +336,7 @@
 #if (DISK_RECOVERY_TIME > 0)
 	unsigned long	last_time;	/* time when previous rq was done */
 #endif
+	ide_ack_intr_t	*ack_intr;	/* acknowledge interrupt */
 	} ide_hwif_t;
 
 /*
@@ -607,6 +614,21 @@
 ide_drive_t *ide_scan_devices (byte media, ide_driver_t *driver, int n);
 int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
 int ide_unregister_subdriver (ide_drive_t *drive);
+void ide_setup_ports(ide_hwif_t *hwif, ide_ioreg_t base, const int *offsets,
+		     ide_ioreg_t irqport, ide_ack_intr_t *ack_intr);
+
+#ifndef __mc68000__
+int pcide_probe_hwif(int index, ide_hwif_t *hwif);
+#endif
+#ifdef CONFIG_BLK_DEV_GAYLE
+int gayle_probe_hwif(int index, ide_hwif_t *hwif);
+#endif
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+int falconide_probe_hwif(int index, ide_hwif_t *hwif);
+#endif
+#ifdef CONFIG_BLK_DEV_BUDDHA
+int buddha_probe_hwif(int index, ide_hwif_t *hwif);
+#endif
 
 #ifdef CONFIG_BLK_DEV_TRITON
 void ide_init_triton (byte, byte);
--- clean/linux/m68k-2.1.42/drivers/block/Makefile	Sun May 18 23:36:28 1997
+++ linux-2.1.42/drivers/block/Makefile	Sun Jul 13 22:10:46 1997
@@ -105,6 +105,21 @@
   endif
 endif
 
+ifneq ($(CONFIG_BLK_DEV_IDE),n)
+  ifneq ($(ARCH),m68k)
+  L_OBJS += pc_ide.o
+  endif
+  ifeq ($(CONFIG_BLK_DEV_GAYLE),y)
+  L_OBJS += gayle.o
+  endif
+  ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y)
+  L_OBJS += falcon_ide.o
+  endif
+  ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
+  L_OBJS += buddha.o
+  endif
+endif
+
 ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
 L_OBJS += rz1000.o
 endif
--- clean/linux/m68k-2.1.42/drivers/scsi/ide-scsi.c	Sun May 18 23:10:05 1997
+++ linux-2.1.42/drivers/scsi/ide-scsi.c	Sun Jul 13 22:10:47 1997
@@ -338,7 +338,8 @@
 	if (drive->using_dma && rq->bh)
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok,IDE_FEATURE_REG);
 	OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG);
--- clean/linux/m68k-2.1.42/include/asm-i386/ide.h	Thu Apr 17 17:07:30 1997
+++ linux-2.1.42/include/asm-i386/ide.h	Sun Jul 13 22:10:42 1997
@@ -33,18 +33,6 @@
 	}
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0:	return 0x1f0;
-		case 1:	return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		default:
-			return 0;
-	}
-}
-
 static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
 	ide_ioreg_t port = base;
@@ -97,11 +85,6 @@
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
 static __inline__ void ide_fix_driveid(struct hd_driveid *id)
 {
 }
--- clean/linux/m68k-2.1.42/include/asm-alpha/ide.h	Thu Apr 17 17:07:29 1997
+++ linux-2.1.42/include/asm-alpha/ide.h	Sun Jul 13 22:10:42 1997
@@ -33,18 +33,6 @@
 	}
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0:	return 0x1f0;
-		case 1:	return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		default:
-			return 0;
-	}
-}
-
 static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
 	ide_ioreg_t port = base;
@@ -97,11 +85,6 @@
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
 static __inline__ void ide_fix_driveid(struct hd_driveid *id)
 {
 }
--- clean/linux/m68k-2.1.42/include/asm-m68k/amihdreg.h	Sun Mar 31 23:50:11 1996
+++ linux-2.1.42/include/asm-m68k/amihdreg.h	Sun Jul 13 22:10:42 1997
@@ -1,31 +0,0 @@
-#ifndef _LINUX_AMIHDREG_H
-#define _LINUX_AMIHDREG_H
-
-/*
- * This file contains some defines for the Amiga IDE hd controller.
- * Various sources. Check out some definitions (see comments with
- * a ques).
- */
-
-#define IDE_DISABLE_IRQ  0x02
-#define IDE_ENABLE_IRQ   0x00
- 
-/* Bases of the hard drive controller */
-#define HD_BASE_A4000   0xdd2020
-#define HD_BASE_A1200   0xda0000
-
-/* Offsets from one of the above bases */
-#define AMI_HD_ERROR	(0x06)		/* see err-bits */
-#define AMI_HD_NSECTOR	(0x0a)		/* nr of sectors to read/write */
-#define AMI_HD_SECTOR	(0x0e)		/* starting sector */
-#define AMI_HD_LCYL	(0x12)		/* starting cylinder */
-#define AMI_HD_HCYL	(0x16)		/* high byte of starting cyl */
-#define AMI_HD_SELECT	(0x1a)		/* 101dhhhh , d=drive, hhhh=head */
-#define AMI_HD_STATUS	(0x1e)		/* see status-bits */
-#define AMI_HD_CMD	(0x101a)
-
-/* These are at different offsets from the base */
-#define HD_A4000_IRQ	(0xdd3020)	/* MSB = 1, Harddisk is source of interrupt */
-#define HD_A1200_IRQ	(0xda9000)	/* MSB = 1, Harddisk is source of interrupt */
-
-#endif
--- clean/linux/m68k-2.1.42/include/asm-m68k/ide.h	Sun May 18 23:06:53 1997
+++ linux-2.1.42/include/asm-m68k/ide.h	Mon Jul 14 20:59:32 1997
@@ -33,20 +33,6 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amihdreg.h>
-#include <asm/amigaints.h>
-#endif /* CONFIG_AMIGA */
-
-#ifdef CONFIG_ATARI
-#include <linux/interrupt.h>	/* intr_count */
-#include <asm/atarihw.h>
-#include <asm/atarihdreg.h>
-#include <asm/atariints.h>
-#include <asm/atari_stdma.h>
-#endif /* CONFIG_ATARI */
-
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -54,7 +40,7 @@
 typedef unsigned char * ide_ioreg_t;
 
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	1
+#define MAX_HWIFS	4	/* same as the other archs */
 #endif
 
 static __inline int ide_default_irq (ide_ioreg_t base)
@@ -62,68 +48,12 @@
 	return 0;
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base (int index)
-{
-	if (index)
-		return NULL;
-#ifdef CONFIG_AMIGA
-	if (MACH_IS_AMIGA) {
-		if (AMIGAHW_PRESENT(A4000_IDE)) {
-			printk("Gayle IDE interface (A%d style)\n", 4000);
-			return ((ide_ioreg_t)ZTWO_VADDR(HD_BASE_A4000));
-		}
-		if (AMIGAHW_PRESENT(A1200_IDE)) {
-			printk("Gayle IDE interface (A%d style)\n", 1200);
-			return ((ide_ioreg_t)ZTWO_VADDR(HD_BASE_A1200));
-		}
-	}
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI) {
-		if (ATARIHW_PRESENT(IDE)) {
-			printk("Falcon IDE interface\n");
-			return ((ide_ioreg_t) ATA_HD_BASE);
-		}
-	}
-#endif /* CONFIG_ATARI */
-	return NULL;
-}
-
+/*
+ *  Can we do this in a generic manner??
+ */
 static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
-	*p++ = base;
-#ifdef CONFIG_AMIGA
-	if (MACH_IS_AMIGA) {
-		*p++ = base + AMI_HD_ERROR;
-		*p++ = base + AMI_HD_NSECTOR;
-		*p++ = base + AMI_HD_SECTOR;
-		*p++ = base + AMI_HD_LCYL;
-		*p++ = base + AMI_HD_HCYL;
-		*p++ = base + AMI_HD_SELECT;
-		*p++ = base + AMI_HD_STATUS;
-		*p++ = base + AMI_HD_CMD;
-		if (AMIGAHW_PRESENT(A4000_IDE))
-			*p++ = (ide_ioreg_t) ZTWO_VADDR(HD_A4000_IRQ);
-		else if (AMIGAHW_PRESENT(A1200_IDE))
-			*p++ = (ide_ioreg_t) ZTWO_VADDR(HD_A1200_IRQ);
-		if (irq != NULL)
-			*irq = IRQ_AMIGA_PORTS;
-	}
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI) {
-		*p++ = base + ATA_HD_ERROR;
-		*p++ = base + ATA_HD_NSECTOR;
-		*p++ = base + ATA_HD_SECTOR;
-		*p++ = base + ATA_HD_LCYL;
-		*p++ = base + ATA_HD_HCYL;
-		*p++ = base + ATA_HD_CURRENT;
-		*p++ = base + ATA_HD_STATUS;
-		*p++ = base + ATA_HD_CMD;
-		if (irq != NULL)
-			*irq = IRQ_MFP_IDE;
-	}
-#endif /* CONFIG_ATARI */
+    printk("ide_init_hwif_ports: must not be called\n");
 }
 
 typedef union {
@@ -362,23 +292,6 @@
 		: "d0", "a0", "a1", "d6")
 
 #endif /* CONFIG_ATARI */
-
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-#ifdef CONFIG_AMIGA
-	if (MACH_IS_AMIGA) {
-		unsigned char ch;
-		ch = inb(irq_port);
-		if (!(ch & 0x80))
-			return(0);
-		if (AMIGAHW_PRESENT(A1200_IDE)) {
-			(void) inb(status_port);
-			outb(0x7c | (ch & 0x03), irq_port);
-		}
-	}
-#endif /* CONFIG_AMIGA */
-	return(1);
-}
 
 #define T_CHAR          (0x0000)        /* char:  don't touch  */
 #define T_SHORT         (0x4000)        /* short: 12 -> 21     */
--- clean/linux/m68k-2.1.42/include/asm-m68k/atarihdreg.h	Fri Apr 19 01:35:24 1996
+++ linux-2.1.42/include/asm-m68k/atarihdreg.h	Sun Jul 13 22:10:43 1997
@@ -1,24 +0,0 @@
-#ifndef _LINUX_ATAHDREG_H
-#define _LINUX_ATAHDREG_H
-
-/*
- * This file contains some defines for the Falcon IDE hd controller.
- * Various sources. Check out some definitions (see comments with
- * a ques).
- */
-
-#define ATA_HD_BASE	0xfff00000
-
-#define ATA_HD_DATA	0x00	/* _CTL when writing */
-#define ATA_HD_ERROR	0x05	/* see err-bits */
-#define ATA_HD_NSECTOR	0x09	/* nr of sectors to read/write */
-#define ATA_HD_SECTOR	0x0d	/* starting sector */
-#define ATA_HD_LCYL	0x11	/* starting cylinder */
-#define ATA_HD_HCYL	0x15	/* high byte of starting cyl */
-#define ATA_HD_CURRENT	0x19	/* 101dhhhh , d=drive, hhhh=head */
-#define ATA_HD_STATUS	0x1d	/* see status-bits */
-
-#define ATA_HD_CMD	0x39
-#define ATA_HD_ALTSTATUS 0x39	/* same as HD_STATUS but doesn't clear irq */
-
-#endif	/* _LINUX_ATAHDREG_H */
--- clean/linux/m68k-2.1.42/include/asm-ppc/ide.h	Thu Jan  9 21:02:10 1997
+++ linux-2.1.42/include/asm-ppc/ide.h	Sun Jul 13 22:10:43 1997
@@ -33,18 +33,6 @@
 	}
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0:	return 0x1f0;
-		case 1:	return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		default:
-			return 0;
-	}
-}
-
 static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
 	ide_ioreg_t port = base;
@@ -97,11 +85,6 @@
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t base_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
 static __inline__ void ide_fix_driveid(struct hd_driveid *id)
 {
 }
--- /dev/null	Tue Aug  1 19:54:39 1995
+++ linux-2.1.42/drivers/block/gayle.c	Mon Jul 14 22:04:05 1997
@@ -0,0 +1,168 @@
+/*
+ *  linux/drivers/block/gayle.c -- Amiga Gayle IDE Driver
+ *
+ *	Created 9 Jul 1997 by Geert Uytterhoeven
+ *
+ *  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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include "ide.h"
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define GAYLE_BASE_4000	0xdd2020	/* A4000/A4000T */
+#define GAYLE_BASE_1200	0xda0000	/* A1200/A600 */
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define GAYLE_DATA	0x00
+#define GAYLE_ERROR	0x06		/* see err-bits */
+#define GAYLE_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define GAYLE_SECTOR	0x0e		/* starting sector */
+#define GAYLE_LCYL	0x12		/* starting cylinder */
+#define GAYLE_HCYL	0x16		/* high byte of starting cyl */
+#define GAYLE_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define GAYLE_STATUS	0x1e		/* see status-bits */
+#define GAYLE_CONTROL	0x101a
+
+u_int gayle_offsets[IDE_NR_PORTS] = {
+    GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+    GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, GAYLE_CONTROL
+};
+
+
+    /*
+     *  These are at different offsets from the base
+     */
+
+#define GAYLE_IRQ_4000	0xdd3020	/* MSB = 1, Harddisk is source of */
+#define GAYLE_IRQ_1200	0xda9000	/* interrupt */
+
+
+    /*
+     *  Offset of the secondary port for IDE doublers
+     *  Note that GAYLE_CONTROL is NOT available then!
+     */
+
+#define NEXT_PORT	0x1000
+
+#ifndef CONFIG_BLK_DEV_IDEDOUBLER
+#define NUM_GAYLE_HWIFS	1
+#define NUM_PROBE_HWIFS	NUM_GAYLE_HWIFS
+#define HAS_CONTROL_REG	1
+#else /* CONFIG_BLK_DEV_IDEDOUBLER */
+#define NUM_GAYLE_HWIFS	2
+#define NUM_PROBE_HWIFS	(ide_doubler ? NUM_GAYLE_HWIFS : NUM_GAYLE_HWIFS-1)
+#define HAS_CONTROL_REG	(!ide_doubler)
+int ide_doubler = 0;	/* support IDE doublers? */
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+    outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]);
+    return 1;
+}
+
+
+    /*
+     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+     */
+
+int gayle_probe_hwif(int index, ide_hwif_t *hwif)
+{
+    static int gayle_index[NUM_GAYLE_HWIFS] = { 0, };
+    int a4000, i;
+
+    if (!MACH_IS_AMIGA)
+	return 0;
+
+    if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE))
+	return 0;
+
+    if (!HAS_CONTROL_REG)
+	gayle_offsets[IDE_CONTROL_OFFSET] = -1;
+
+    for (i = 0; i < NUM_PROBE_HWIFS; i++) {
+	if (!gayle_index[i]) {
+	    switch (i) {
+		case 0:
+		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
+			   a4000 ? 4000 : 1200);
+		    break;
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+		case 1:
+		    printk("ide%d: IDE doubler\n", index);
+		    break;
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+	    }
+	    gayle_index[i] = index+1;
+	}
+	if (gayle_index[i] == index+1) {
+	    ide_ioreg_t base, irqport;
+	    ide_ack_intr_t *ack_intr;
+	    if (a4000) {
+		base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_4000);
+		irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000);
+		ack_intr = gayle_ack_intr_a4000;
+	    } else {
+		base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_1200);
+		irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200);
+		ack_intr = gayle_ack_intr_a1200;
+	    }
+	    base += i*NEXT_PORT;
+	    ide_setup_ports(hwif, base, gayle_offsets, irqport, ack_intr);
+#if 1 /* TESTING */
+	    if (i == 1) {
+		volatile u_short *addr = (u_short *)base;
+		u_short data;
+		printk("+++ Probing for IDE doubler... ");
+		*addr = 0xffff;
+		data = *addr;
+		printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data);
+	    }
+#endif /* TESTING */
+	    hwif->irq = IRQ_AMIGA_PORTS;
+	    return 1;
+	}
+    }
+    return 0;
+}
--- /dev/null	Tue Aug  1 19:54:39 1995
+++ linux-2.1.42/drivers/block/falcon_ide.c	Mon Jul 14 21:48:29 1997
@@ -0,0 +1,74 @@
+/*
+ *  linux/drivers/block/falcon-ide.c -- Atari Falcon IDE Driver
+ *
+ *	Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  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.
+ */
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include "ide.h"
+
+#include <asm/atarihw.h>
+#include <asm/atarihdreg.h>
+#include <asm/atariints.h>
+#include <asm/atari_stdma.h>
+
+
+    /*
+     *  Base of the IDE interface
+     */
+
+#define ATA_HD_BASE	0xfff00000
+
+    /*
+     *  Offsets from the above base
+     */
+
+#define ATA_HD_DATA	0x00
+#define ATA_HD_ERROR	0x05		/* see err-bits */
+#define ATA_HD_NSECTOR	0x09		/* nr of sectors to read/write */
+#define ATA_HD_SECTOR	0x0d		/* starting sector */
+#define ATA_HD_LCYL	0x11		/* starting cylinder */
+#define ATA_HD_HCYL	0x15		/* high byte of starting cyl */
+#define ATA_HD_SELECT	0x19		/* 101dhhhh , d=drive, hhhh=head */
+#define ATA_HD_STATUS	0x1d		/* see status-bits */
+#define ATA_HD_CONTROL	0x39
+
+const int falconide_offsets[IDE_NR_PORTS] = {
+    ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
+    ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL
+};
+
+
+    /*
+     *  Probe for a Falcon IDE interface
+     */
+
+int falconide_probe_hwif(int index, ide_hwif_t *hwif)
+{
+    static int falcon_index = 0;
+
+    if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
+	return 0;
+
+    if (!falcon_index) {
+	printk("ide%d: Falcon IDE interface\n", index);
+	falcon_index = index+1;
+    }
+    if (falcon_index == index+1) {
+	ide_setup_ports(hwif, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets, 0,
+			NULL);
+	hwif->irq = IRQ_MFP_IDE;
+	return 1;
+    }
+    return 0;
+}
--- /dev/null	Tue Aug  1 19:54:39 1995
+++ linux-2.1.42/drivers/block/buddha.c	Mon Jul 14 22:01:09 1997
@@ -0,0 +1,373 @@
+/*
+ *  linux/drivers/block/buddha.c -- Amiga Buddha and Catweasel IDE Driver
+ *
+ *	Copyright (C) 1997 by Geert Uytterhoeven
+ *
+ *  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.
+ *
+ *  The driver was written based on the following specifications:
+ *
+ *  ---------------------------------------------------------------------------
+ *  Register map of the Buddha IDE controller and the
+ *  Buddha-part of the Catweasel Zorro-II version
+ *  
+ *  The Autoconfiguration has been implemented just as Commodore
+ *  described  in  their  manuals, no tricks have been used (for
+ *  example leaving some address lines out of the equations...).
+ *  If you want to configure the board yourself (for example let
+ *  a  Linux  kernel  configure the card), look at the Commodore
+ *  Docs.  Reading the nibbles should give this information:
+ *  
+ *  Vendor number: 4626 ($1212)
+ *  product number: 0 (42 for Catweasel Z-II)
+ *  Serial number: 0
+ *  Rom-vector: $1000
+ *  
+ *  The  card  should be a Z-II board, size 64K, not for freemem
+ *  list, Rom-Vektor is valid, no second Autoconfig-board on the
+ *  same card, no space preferrence, supports "Shutup_forever".
+ *  
+ *  Setting  the  base address should be done in two steps, just
+ *  as  the Amiga Kickstart does:  The lower nibble of the 8-Bit
+ *  address is written to $4a, then the whole Byte is written to
+ *  $48, while it doesn't matter how often you're writing to $4a
+ *  as  long as $48 is not touched.  After $48 has been written,
+ *  the  whole card disappears from $e8 and is mapped to the new
+ *  addrress just written.  Make shure $4a is written befor $48,
+ *  otherwise your chance is only 1:16 to find the board :-).
+ *  
+ *  The local memory-map is even active when mapped to $e8:
+ *  
+ *  $0-$7e	Autokonfig-space, see Z-II docs.
+ *  
+ *  $80-$7fd	reserved
+ *  
+ *  $7fe	Speed-select Register: Read & Write
+ *  		(description see further down)
+ *  
+ *  $800-$8ff	IDE-Select 0 (Port 0, Register set 0)
+ *  
+ *  $900-$9ff	IDE-Select 1 (Port 0, Register set 1)
+ *  
+ *  $a00-$aff	IDE-Select 2 (Port 1, Register set 0)
+ *  
+ *  $b00-$bff	IDE-Select 3 (Port 1, Register set 1)
+ *  
+ *  $c00-$cff	IDE-Select 4 (Port 2, Register set 0,
+ *                            Catweasel only!)
+ *  
+ *  $d00-$dff	IDE-Select 5 (Port 3, Register set 1,
+ *  			      Catweasel only!)
+ *  
+ *  $e00-$eff	local expansion port, on Catweasel Z-II the 
+ *  		Catweasel registers are also mapped here.
+ *  		Never touch, use multidisk.device!
+ *  		
+ *  $f00	read only, Byte-access: Bit 7 shows the 
+ *  		level of the IRQ-line of IDE port 0. 
+ *  
+ *  $f01-$f3f	mirror of $f00
+ *  
+ *  $f40	read only, Byte-access: Bit 7 shows the 
+ *  		level of the IRQ-line of IDE port 1. 
+ *  
+ *  $f41-$f7f	mirror of $f40
+ *  
+ *  $f80	read only, Byte-access: Bit 7 shows the 
+ *  		level of the IRQ-line of IDE port 2. 
+ *  		(Catweasel only!)
+ *  
+ *  $f81-$fbf	mirror of $f80
+ *  
+ *  $fc0	write-only: Writing any value to this
+ *  		register enables IRQs to be passed from the 
+ *  		IDE ports to the Zorro bus. This mechanism 
+ *  		has been implemented to be compatible with 
+ *  		harddisks that are either defective or have
+ *  		a buggy firmware and pull the IRQ line up 
+ *  		while starting up. If interrupts would 
+ *  		always be passed to the bus, the computer 
+ *  		might not start up. Once enabled, this flag 
+ *  		can not be disabled again. The level of the 
+ *  		flag can not be determined by software 
+ *  		(what for? Write to me if it's necessary!).
+ *  
+ *  $fc1-$fff	mirror of $fc0
+ *  
+ *  $1000-$ffff	Buddha-Rom with offset $1000 in the rom
+ *  		chip. The addresses $0 to $fff of the rom 
+ *  		chip cannot be read. Rom is Byte-wide and
+ *  		mapped to even addresses.
+ *  
+ *  The  IDE ports issue an INT2.  You can read the level of the
+ *  IRQ-lines  of  the  IDE-ports by reading from the three (two
+ *  for  Buddha-only)  registers  $f00, $f40 and $f80.  This way
+ *  more  than one I/O request can be handled and you can easily
+ *  determine  what  driver  has  to serve the INT2.  Buddha and
+ *  Catweasel  expansion  boards  can issue an INT6.  A seperate
+ *  memory  map  is available for the I/O module and the sysop's
+ *  I/O module.
+ *  
+ *  The IDE ports are fed by the address lines A2 to A4, just as
+ *  the  Amiga  1200  and  Amiga  4000  IDE ports are.  This way
+ *  existing  drivers  can be easily ported to Buddha.  A move.l
+ *  polls  two  words  out of the same address of IDE port since
+ *  every  word  is  mirrored  once.  movem is not possible, but
+ *  it's  not  necessary  either,  because  you can only speedup
+ *  68000  systems  with  this  technique.   A 68020 system with
+ *  fastmem is faster with move.l.
+ *  
+ *  If you're using the mirrored registers of the IDE-ports with
+ *  A6=1,  the Buddha doesn't care about the speed that you have
+ *  selected  in  the  speed  register (see further down).  With
+ *  A6=1  (for example $840 for port 0, register set 0), a 780ns
+ *  access  is being made.  These registers should be used for a
+ *  command   access   to  the  harddisk/CD-Rom,  since  command
+ *  accesses  are Byte-wide and have to be made slower according
+ *  to the ATA-X3T9 manual.
+ *  
+ *  Now  for the speed-register:  The register is byte-wide, and
+ *  only  the  upper  three  bits are used (Bits 7 to 5).  Bit 4
+ *  must  always  be set to 1 to be compatible with later Buddha
+ *  versions  (if  I'll  ever  update this one).  I presume that
+ *  I'll  never use the lower four bits, but they have to be set
+ *  to 1 by definition.
+ *    The  values in this table have to be shifted 5 bits to the
+ *  left and or'd with $1f (this sets the lower 5 bits).
+ *  
+ *  All  the timings have in common:  Select and IOR/IOW rise at
+ *  the  same  time.   IOR  and  IOW have a propagation delay of
+ *  about  30ns  to  the clocks on the Zorro bus, that's why the
+ *  values  are no multiple of 71.  One clock-cycle is 71ns long
+ *  (exactly 70,5 at 14,18 Mhz on PAL systems).
+ *  
+ *  value 0 (Default after reset)
+ *  
+ *  497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles)
+ *  (same timing as the Amiga 1200 does on it's IDE port without
+ *  accelerator card)
+ *  
+ *  value 1
+ *  
+ *  639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+ *  
+ *  value 2
+ *  
+ *  781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+ *  
+ *  value 3
+ *  
+ *  355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+ *  
+ *  value 4
+ *  
+ *  355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles)
+ *  
+ *  value 5
+ *  
+ *  355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+ *  
+ *  value 6
+ *  
+ *  1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+ *  
+ *  value 7
+ *  
+ *  355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+ *  
+ *  When accessing IDE registers with A6=1 (for example $84x),
+ *  the timing will always be mode 0 8-bit compatible, no matter
+ *  what you have selected in the speed register:
+ *  
+ *  781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive. 
+ *  
+ *  All  the  timings with a very short select-signal (the 355ns
+ *  fast  accesses)  depend  on the accelerator card used in the
+ *  system:  Sometimes two more clock cycles are inserted by the
+ *  bus  interface,  making  the  whole access 497ns long.  This
+ *  doesn't  affect  the  reliability  of the controller nor the
+ *  performance  of  the  card,  since  this doesn't happen very
+ *  often.
+ *  
+ *  All  the  timings  are  calculated  and  only  confirmed  by
+ *  measurements  that allowed me to count the clock cycles.  If
+ *  the  system  is clocked by an oscillator other than 28,37516
+ *  Mhz  (for  example  the  NTSC-frequency  28,63636 Mhz), each
+ *  clock  cycle is shortened to a bit less than 70ns (not worth
+ *  mentioning).   You  could think of a small performance boost
+ *  by  overclocking  the  system,  but  you would either need a
+ *  multisync  monitor,  or  a  graphics card, and your internal
+ *  diskdrive would go crazy, that's why you shouldn't tune your
+ *  Amiga this way.
+ *  
+ *  Giving  you  the  possibility  to  write  software  that  is
+ *  compatible  with both the Buddha and the Catweasel Z-II, The
+ *  Buddha  acts  just  like  a  Catweasel  Z-II  with no device
+ *  connected  to  the  third  IDE-port.   The IRQ-register $f80
+ *  always  shows a "no IRQ here" on the Buddha, and accesses to
+ *  the  third  IDE  port  are  going into data's Nirwana on the
+ *  Buddha.
+ *  
+ *  			    Jens Schönfeld february 19th, 1997
+ *  					updated may 27th, 1997
+ *                           eMail: sysop@nostlgic.tng.oche.de
+ *  ---------------------------------------------------------------------------
+ *
+ *  TODO:
+ *    - test it :-)
+ *    - tune the timings using the speed-register
+ */
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+
+#include "ide.h"
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  The Buddha has 2 IDE interfaces, the Catweasel has 3
+     */
+
+#define NUM_BUDDHA_HWIFS	2
+#define NUM_CATWEASEL_HWIFS	3
+
+
+    /*
+     *  Bases of the IDE interfaces (relative to the board address)
+     */
+
+#define BUDDHA_BASE1	0x800
+#define BUDDHA_BASE2	0xa00
+#define BUDDHA_BASE3	0xc00
+
+const u_int buddha_bases[NUM_CATWEASEL_HWIFS] = {
+    BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
+};
+
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define BUDDHA_DATA	0x00
+#define BUDDHA_ERROR	0x06		/* see err-bits */
+#define BUDDHA_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define BUDDHA_SECTOR	0x0e		/* starting sector */
+#define BUDDHA_LCYL	0x12		/* starting cylinder */
+#define BUDDHA_HCYL	0x16		/* high byte of starting cyl */
+#define BUDDHA_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define BUDDHA_STATUS	0x1e		/* see status-bits */
+#define BUDDHA_CONTROL	0x11a
+
+const u_int buddha_offsets[IDE_NR_PORTS] = {
+    BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+    BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL
+};
+
+
+    /*
+     *  Other registers
+     */
+
+#define BUDDHA_IRQ1	0xf00		/* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2	0xf40		/* interrupt */
+#define BUDDHA_IRQ3	0xf80
+
+const int buddha_irqports[NUM_CATWEASEL_HWIFS] = {
+    BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
+};
+
+#define BUDDHA_IRQ_MR	0xfc0		/* master interrupt enable */
+
+
+    /*
+     *  Board information
+     */
+
+static u_long board = 0;
+static int numhwifs = -1;
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int buddha_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+
+    /*
+     *  Any Buddha or Catweasel boards present?
+     */
+
+int find_buddha(void)
+{
+    u_int key;
+    const struct ConfigDev *cd;
+
+    numhwifs = 0;
+    if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, 0, 0)))
+	numhwifs = NUM_BUDDHA_HWIFS;
+    else if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, 0,
+			       0)))
+	numhwifs = NUM_CATWEASEL_HWIFS;
+    if (key) {
+	cd = zorro_get_board(key);
+	board = (u_long)cd->cd_BoardAddr;
+	if (board) {
+	    board = ZTWO_VADDR(board);
+	    /* write to BUDDHA_IRQ_MR to enable the board IRQ */
+	    *(char *)(board+BUDDHA_IRQ_MR) = 0;
+	}
+    }
+    return numhwifs;
+}
+
+
+    /*
+     *  Probe for a Buddha or Catweasel IDE interface
+     *  We support only _one_ of them, no multiple boards
+     */
+
+int buddha_probe_hwif(int index, ide_hwif_t *hwif)
+{
+    static int buddha_index[NUM_CATWEASEL_HWIFS] = { 0, };
+    int i;
+
+    if (numhwifs < 0 && !find_buddha())
+	return 0;
+
+    for (i = 0; i < numhwifs; i++) {
+	if (!buddha_index[i]) {
+	    printk("ide%d: %s IDE interface\n", index,
+		   numhwifs == NUM_BUDDHA_HWIFS ? "Buddha" : "Catweasel");
+	    buddha_index[i] = index+1;
+	}
+	if (buddha_index[i] == index+1) {
+	    ide_setup_ports(hwif, (ide_ioreg_t)(board+buddha_bases[i]),
+	    		    buddha_offsets,
+			    (ide_ioreg_t)(board+buddha_irqports[i]),
+			    buddha_ack_intr);
+	    hwif->irq = IRQ_AMIGA_PORTS;
+	    return 1;
+	}
+    }
+    return 0;
+}
--- /dev/null	Tue Aug  1 19:54:39 1995
+++ linux-2.1.42/drivers/block/pc_ide.c	Mon Jul 14 22:07:36 1997
@@ -0,0 +1,71 @@
+/*
+ *  linux/drivers/block/pc-ide.c -- PC I/O port IDE Driver
+ *
+ *	Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  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.
+ */
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include "ide.h"
+
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define NUM_PCIDE_HWIFS	4
+
+#define PCIDE_BASE1	0x1f0
+#define PCIDE_BASE2	0x170
+#define PCIDE_BASE3	0x1e8
+#define PCIDE_BASE4	0x168
+
+const ide_ioreg_t pcide_bases[NUM_PCIDE_HWIFS] = {
+    PCIDE_BASE1, PCIDE_BASE2, PCIDE_BASE3, PCIDE_BASE4
+};
+
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define PCIDE_REG(x)	(HD_##x-PCIDE_BASE1)
+
+const int pcide_offsets[IDE_NR_PORTS] = {
+    PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR),
+    PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS),
+    PCIDE_REG(CMD)
+};
+
+
+    /*
+     *  Probe for PC IDE interfaces
+     */
+
+int pcide_probe_hwif(int index, ide_hwif_t *hwif)
+{
+    static int pcide_index[NUM_PCIDE_HWIFS] = { 0, };
+    int i;
+
+    for (i = 0; i < NUM_PCIDE_HWIFS; i++) {
+	if (!pcide_index[i]) {
+	    printk("ide%d: PC IDE interface\n", index);
+	    pcide_index[i] = index+1;
+	}
+	if (pcide_index[i] == index+1) {
+	    ide_setup_ports(hwif, pcide_bases[i], pcide_offsets, 0, NULL);
+	    hwif->irq = 0;
+	    return 1;
+	}
+    }
+    return 0;
+}

Greetings,

						Geert

--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/m68k on Amiga          http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

