Resent-Date: Mon, 18 Jan 1999 10:10:13 +0100 (MET)
Date: Mon, 18 Jan 1999 10:11:52 +0100 (CET)
From: "Christian T. Steigies" <cts@ap031.experimentalphysik.uni-kiel.de>
Reply-To: "Christian T. Steigies" <steigies@physik.uni-kiel.de>
To: linux-m68k <linux-m68k@lists.linux-m68k.org>
Subject: buddha/catweasel for 2.0.36
Resent-From: linux-m68k@phil.uni-sb.de

Hi,
this is the catweasel patch for 2.0.36-pre2. Can someone with A4000/A1200
IDE please check that this doesnt break anything for him? It would be
perfect, if he could test with A4000/A1200 IDE _and_ with buddha also...
You can turn on full warning messages by uncommenting AMIGA_BUDDHA_DEBUG, I
think the messages are wasting too much kernel memory if they are included
in every kernel?

This is working for my on A2000 with Catweasel and one IDE disk connected.
It should support all three interfaces now, but I did not test with more
than one disk yet.

Ciao,
Christian.

--- drivers/block/ide.c.orig	Tue Dec  1 17:32:35 1998
+++ drivers/block/ide.c	Sun Jan 17 22:07:13 1999
@@ -854,11 +854,11 @@
  * individually reset without clobbering other devices on the same interface.
  *
  * Unfortunately, the IDE interface does not generate an interrupt to let
- * us know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to complete,
- * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
- * we set a timer to poll at 50ms intervals.
- */
+ * us know when the reset operation has finished, so we must poll for this. 
+ * Equally poor, though, is the fact that this may take a very long time to
+ * complete, (up to 30 seconds worstcase).  So, instead of busy-waiting here
+ * for it, we set a timer to poll at 50ms intervals.
+ */ 
 static void do_reset1 (ide_drive_t *drive, int  do_not_try_atapi)
 {
 	unsigned int unit;
@@ -3845,9 +3845,16 @@
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_AMIGA
+/* #define AMIGA_BUDDHA_DEBUG */
 static void ide_probe_amiga (void)
 {
 	ide_hwif_t *hwif = &ide_hwifs[0];
+	int i, key; 
+	const struct ConfigDev *cd;
+	static u_long buddha_board = 0;
+	static int buddha_num_hwifs = 0;
+	static int amiga_num_hwifs = 0;
+#include "buddha.h"
 
 	if (!MACH_IS_AMIGA)
 		return;
@@ -3858,30 +3865,113 @@
 	if (AMIGAHW_PRESENT(A4000_IDE)) {
 		hwif->io_base = (unsigned char *)ZTWO_VADDR(HD_BASE_A4000);
 		hwif->hd_regs.hd_irq = (unsigned char *)ZTWO_VADDR(HD_A4000_IRQ);
+		amiga_num_hwifs++;
 		printk("Gayle IDE interface (A4000 style)\n");
 	} else if (AMIGAHW_PRESENT(A1200_IDE)) {
 		hwif->io_base = (unsigned char *)ZTWO_VADDR(HD_BASE_A1200);
 		hwif->hd_regs.hd_irq = (unsigned char *)ZTWO_VADDR(HD_A1200_IRQ);
+		amiga_num_hwifs++;
 		printk("Gayle IDE interface (A1200 style)\n");
-	} else /* Not A4000 nor A1200, 
-		  doesn't have a supported IDE controller */
-		{
-			hwif->noprobe = 1;
+	}
+	if (amiga_num_hwifs > 0) { /* we can have max one gayle interface */
+		/* Now set the hd_regs struct */
+		hwif->hd_regs.hd_error   = hwif->io_base + AMI_HD_ERROR;
+		hwif->hd_regs.hd_nsector = hwif->io_base + AMI_HD_NSECTOR;
+		hwif->hd_regs.hd_sector  = hwif->io_base + AMI_HD_SECTOR;
+		hwif->hd_regs.hd_lcyl    = hwif->io_base + AMI_HD_LCYL;
+		hwif->hd_regs.hd_hcyl    = hwif->io_base + AMI_HD_HCYL;
+		hwif->hd_regs.hd_select  = hwif->io_base + AMI_HD_SELECT;
+		hwif->hd_regs.hd_status  = hwif->io_base + AMI_HD_STATUS;
+		hwif->ctl_port           = hwif->io_base + AMI_HD_CMD;
+
+		/* Disable interrupt for probing */
+		disable_irq(hwif->irq);
+
+		hwif++; /* next interface, please */		
+
+		if ( (amiga_num_hwifs + 1) > MAX_HWIFS) { 
+		/* MAX_HWIFS must be >1 for use with buddha/catweasel */
+#ifdef AMIGA_BUDDHA_DEBUG
+			printk("WARNING: this kernel can handle only %d IDE interfaces!\n", MAX_HWIFS);
+			printk(" Edit include/asm-m68k/ide.h if you want to use more.\n");
+#endif
 			return;
 		}
+	} /* Maybe we have a Buddha or Catweasel controller? */
+	if ((key = zorro_find(MANUF_INDIVIDUAL_COMP, PROD_BUDDHA, 0, 0))) {
+		buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+		printk("Buddha IDE interface\n");
+	} else if ((key = zorro_find(MANUF_INDIVIDUAL_COMP, PROD_CATWEASEL, 0, 0))) {
+		buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
+		printk("Catweasel IDE interface\n");
+	}
+	if ( (amiga_num_hwifs + buddha_num_hwifs) > MAX_HWIFS) { 
+	/* check if MAX_HWIFS is large enough for gayle and buddha/catweasel */
+#ifdef AMIGA_BUDDHA_DEBUG
+		printk("WARNING: this kernel can handle only %d IDE interfaces,\n", MAX_HWIFS);
+		printk(" this machine seems to have %d!\n", (amiga_num_hwifs + buddha_num_hwifs) );
+		printk(" Edit include/asm-m68k/ide.h if you want to use them all (now using only %d).\n", amiga_num_hwifs);
+#endif
+		return;
+	} /* this is very paranoid, too paranoid? */
+	if (key) {
+		cd = zorro_get_board(key);
+		buddha_board = (u_long)cd->cd_BoardAddr;
+		if (buddha_board) {
+			buddha_board = ZTWO_VADDR(buddha_board);
+			/* write to BUDDHA_IRQ_MR to enable the board IRQ */
+			*(char *)(buddha_board+BUDDHA_IRQ_MR) = 0;
+			zorro_config_board(key, 0);
+		} else { /* can this happen ? */
+			buddha_num_hwifs = 0;
+		}
+	} else { /* no buddha or catweasel present */
+		buddha_num_hwifs = 0;
+	} 
+	
+	if (buddha_num_hwifs > 0) { 
+	/* we have two or three more interfaces, now setup ide_hwifs  */
+		for (i = 1; i <= buddha_num_hwifs; i++) {	
+			switch (i) {
+			case 1:
+				hwif->io_base = (unsigned char *)(buddha_board + BUDDHA_BASE1); 
+				hwif->hd_regs.hd_irq = (unsigned char *)(buddha_board + BUDDHA_IRQ1);
+				break;
+			case 2:
+				hwif->io_base = (unsigned char *)(buddha_board + BUDDHA_BASE2); 
+				hwif->hd_regs.hd_irq = (unsigned char *)(buddha_board + BUDDHA_IRQ2);
+				break;
+			case 3:
+				hwif->io_base = (unsigned char *)(buddha_board + BUDDHA_BASE3); 
+				hwif->hd_regs.hd_irq = (unsigned char *)(buddha_board + BUDDHA_IRQ3);
+				break;
+			default:
+				return; /* this can not happen */
+			}
+			hwif->hd_regs.hd_error   = hwif->io_base + BUDDHA_ERROR;
+			hwif->hd_regs.hd_nsector = hwif->io_base + BUDDHA_NSECTOR;
+			hwif->hd_regs.hd_sector  = hwif->io_base + BUDDHA_SECTOR;
+			hwif->hd_regs.hd_lcyl    = hwif->io_base + BUDDHA_LCYL;
+			hwif->hd_regs.hd_hcyl    = hwif->io_base + BUDDHA_HCYL;
+			hwif->hd_regs.hd_select  = hwif->io_base + BUDDHA_SELECT;
+			hwif->hd_regs.hd_status  = hwif->io_base + BUDDHA_STATUS;
+			hwif->ctl_port           = hwif->io_base + BUDDHA_CONTROL;
 
-	/* Now set the hd_regs struct */
-	hwif->hd_regs.hd_error   = hwif->io_base + AMI_HD_ERROR;
-	hwif->hd_regs.hd_nsector = hwif->io_base + AMI_HD_NSECTOR;
-	hwif->hd_regs.hd_sector  = hwif->io_base + AMI_HD_SECTOR;
-	hwif->hd_regs.hd_lcyl    = hwif->io_base + AMI_HD_LCYL;
-	hwif->hd_regs.hd_hcyl    = hwif->io_base + AMI_HD_HCYL;
-	hwif->hd_regs.hd_select  = hwif->io_base + AMI_HD_SELECT;
-	hwif->hd_regs.hd_status  = hwif->io_base + AMI_HD_STATUS;
-	hwif->ctl_port           = hwif->io_base + AMI_HD_CMD;
+			/* Disable interrupt for probing */
+			disable_irq(hwif->irq);
 
-	/* Disable interrupt for probing */
-	disable_irq(hwif->irq);
+			hwif++; /* next interface, please */
+		}
+	}
+	if ( ( amiga_num_hwifs + buddha_num_hwifs ) < MAX_HWIFS ) {
+	/* the kernel could cope with more interfaces, now set the remaining to noprobe */ 
+		int i;
+		
+		for (i = (amiga_num_hwifs + buddha_num_hwifs); i < MAX_HWIFS; i++) {
+			hwif->noprobe = 1;
+			hwif++; /* next interface, please */			
+		}
+	}
 }
 #endif /* CONFIG_AMIGA */
 
--- drivers/block/buddha.h.orig	Sun Jan 10 19:35:31 1999
+++ drivers/block/buddha.h	Tue Jan 12 06:08:26 1999
@@ -0,0 +1,71 @@
+/*  This file as well as the changes in ide.c are based on 
+ *  linux/drivers/block/buddha.c from linux-2.1.131
+ *
+ *  - tested on A2000, currently only one controller is working
+ *    19-01-1999 CTS
+ *
+ *
+ *  linux/drivers/block/buddha.c -- Amiga Buddha and Catweasel IDE Driver
+ *
+ *      Copyright (C) 1997 by Geert Uytterhoeven
+ *
+ *  This driver was written by based on the specifications in README.buddha.
+ *
+ *  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.
+ *
+ *  TODO:
+ *    - test it :-)
+ *    - tune the timings using the speed-register
+ */
+              
+#ifndef _BUDDHA_H
+#define _BUDDHA_H
+
+
+    /*
+     *  The Buddha has 2 IDE interfaces, the Catweasel has 3
+     */
+
+#define BUDDHA_NUM_HWIFS	2
+#define CATWEASEL_NUM_HWIFS	3
+
+
+    /*
+     *  Bases of the IDE interfaces (relative to the board address)
+     */
+
+#define BUDDHA_BASE1	0x800
+#define BUDDHA_BASE2	0xa00
+#define BUDDHA_BASE3	0xc00
+
+
+    /*
+     *  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
+
+
+    /*
+     *  Other registers
+     */
+
+#define BUDDHA_IRQ1	0xf00		/* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2	0xf40		/* interrupt */
+#define BUDDHA_IRQ3	0xf80
+
+
+#define BUDDHA_IRQ_MR	0xfc0		/* master interrupt enable */
+
+
+#endif /* _BUDDHA_H */
--- include/asm-m68k/ide.h.orig	Sun Jan 10 14:23:58 1999
+++ include/asm-m68k/ide.h	Tue Jan 12 05:52:56 1999
@@ -26,7 +26,11 @@
 #define IDE_MEM_MAPPED_IO
 
 #ifndef MAX_HWIFS
+#ifdef CONFIG_AMIGA
+#define MAX_HWIFS	4
+#else
 #define MAX_HWIFS	1
+#endif
 #endif
 
 #undef SUPPORT_VLB_SYNC

