Resent-Date: Mon, 1 Feb 1999 11:43:14 +0100 (MET)
Date: Mon, 1 Feb 1999 11:39:39 +0100
From: Kars de Jong <jongk@cs.utwente.nl>
To: Andreas Schmitz <OTTER@chessy.aworld.de>
Cc: linux-m68k@lists.linux-m68k.org
Subject: Re: Oktagon patch (NCR53C9x)
Mail-Followup-To: Andreas Schmitz <OTTER@chessy.aworld.de>,
	linux-m68k@lists.linux-m68k.org
References: <2rsyYMD46BaUz1@otter.chessy.aworld.de> <2s2HoMD46Basz2@otter.chessy.aworld.de>
In-Reply-To: <2s2HoMD46Basz2@otter.chessy.aworld.de>; from Andreas Schmitz on Sat, Jan 30, 1999 at 06:47:52PM +0000
Resent-From: linux-m68k@phil.uni-sb.de

On Sat, Jan 30, 1999 at 06:47:52PM +0000, Andreas Schmitz wrote:
> Not really. You forgot the -N option for diff, I think. The "new" files are
> not included...

Whoops. That's what you get for using a CVS tree. I didn't 'add' the new
files yet. This diff should be okay.

Kars.
-- 
------------------------------------------------------------------------------
Kars de Jong             Signaalkamp rules the waves!       Turrican@Discworld
--------======]**-----|      jongk@cs.utwente.nl      |-----**[======---------

Index: arch/m68k/config.in
===================================================================
RCS file: /usr/src/CVS/linux/arch/m68k/config.in,v
retrieving revision 1.2
diff -u -r1.2 config.in
--- config.in	1999/01/18 19:38:07	1.2
+++ config.in	1999/01/28 15:11:22
@@ -147,6 +147,7 @@
     bool 'A4091 SCSI support' CONFIG_A4091_SCSI
     bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
     bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
+    dep_tristate 'BSC Oktagon SCSI support' CONFIG_OKTAGON_SCSI $CONFIG_SCSI
 #    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
 #    bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
   fi
Index: drivers/scsi/Makefile
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/Makefile,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile
--- Makefile	1999/01/18 16:20:45	1.1.1.1
+++ Makefile	1999/01/28 14:09:56
@@ -18,7 +18,10 @@
 CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
 
 .SUFFIXES:
-.SUFFIXES: .c .o .h .a
+.SUFFIXES: .c .o .h .a .S
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ -c $< -o $*.o
 
 ifeq (${CFLAGS},)
 CFLAGS = -D__KERNEL__=1 \
@@ -254,6 +257,14 @@
 else
   ifeq ($(CONFIG_FASTLANE_SCSI),m)
   M_OBJS += NCR53C9x.o fastlane.o
+  endif
+endif
+
+ifeq ($(CONFIG_OKTAGON_SCSI),y)
+L_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o
+else
+  ifeq ($(CONFIG_OKTAGON_SCSI),m)
+  M_OBJS += NCR53C9x.o oktagon_esp.o oktagon_io.o
   endif
 endif
 
Index: drivers/scsi/NCR53C9x.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/NCR53C9x.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 NCR53C9x.c
--- NCR53C9x.c	1999/01/18 16:21:03	1.1.1.1
+++ NCR53C9x.c	1999/01/28 17:52:24
@@ -6,6 +6,9 @@
  *
  * Most DMA dependencies put in driver specific files by 
  * Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Set up to use esp_read/esp_write (preprocessor macros in NCR53c9x.h) by
+ * Tymm Twillman (tymm@coe.missouri.edu)
  */
 
 /* TODO:
@@ -508,7 +511,7 @@
 }
 
 /* This places the ESP into a known state at boot time. */
-static void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
+void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	volatile unchar trash;
 
@@ -547,6 +550,9 @@
 	esp->edev = esp_dev;
 	esp->esp_id = nesps++;
 
+	/* Set bitshift value (only used on Amiga with multiple ESPs) */
+	esp->shift = 2;
+
 	/* Put into the chain of esp chips detected */
 	if(espchain) {
 		elink = espchain;
@@ -560,6 +566,20 @@
 	return esp;
 }
 
+void esp_deallocate(struct NCR_ESP *esp)
+{
+	struct NCR_ESP *elink;
+
+	if(espchain == esp) {
+		espchain = 0;
+	} else {
+		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);
+		if(elink) 
+			elink->next = esp->next;
+	}
+	nesps--;
+}
+
 /* Complete initialization of ESP structure and device
  * Caller must have initialized appropriate parts of the ESP structure
  * between the call to esp_allocate and this function.
@@ -1794,7 +1814,7 @@
 		int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
 		int fifocnt = 0;
 
-		oldphase = eregs->esp_status & ESP_STAT_PMASK;
+		oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK;
 
 		/*
 		 * polled transfer; ugly, can we make this happen in a DRQ 
@@ -3395,7 +3415,7 @@
 	esp->sreg = esp_read(eregs->esp_status);
 	esp->sreg &= (~ESP_STAT_INTR);
 	esp->seqreg = (esp_read(eregs->esp_sstep) & ESP_STEP_VBITS);
-	esp->ireg = eregs->esp_intrpt;   /* Unlatch intr and stat regs */
+	esp->ireg = esp_read(eregs->esp_intrpt);   /* Unlatch intr and stat regs */
 	ESPIRQ(("handle_irq: [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
 		esp->sreg, esp->seqreg, esp->ireg));
 	if(esp->sreg & (ESP_STAT_SPAM)) {
@@ -3596,5 +3616,7 @@
 void esp_release(void)
 {
 	MOD_DEC_USE_COUNT;
+	esps_in_use--;
+	esps_running = esps_in_use;
 }
 #endif
Index: drivers/scsi/NCR53C9x.h
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/NCR53C9x.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 NCR53C9x.h
--- NCR53C9x.h	1999/01/18 16:21:03	1.1.1.1
+++ NCR53C9x.h	1999/01/28 17:54:31
@@ -6,6 +6,8 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *
  * Generalization by Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * More generalization (for i386 stuff) by Tymm Twillman (tymm@computer.org)
  */
 
 #ifndef NCR53C9X_H
@@ -20,6 +22,22 @@
 #define PAD_SIZE 3
 #endif
 
+/* Handle multiple hostadapters on Amiga
+ * generally PAD_SIZE = 3
+ * but there is one exception: Oktagon (PAD_SIZE = 1) */
+#if defined(CONFIG_OKTAGON_SCSI) || defined(CONFIG_OKTAGON_SCSI_MODULE)
+#undef PAD_SIZE
+#if defined(CONFIG_BLZ1230_SCSI) || defined(CONFIG_BLZ1230_SCSI_MODULE) || \
+    defined(CONFIG_BLZ2060_SCSI) || defined(CONFIG_BLZ2060_SCSI_MODULE) || \
+    defined(CONFIG_CYBERSTORM_SCSI) || defined(CONFIG_CYBERSTORM_SCSI_MODULE) || \
+    defined(CONFIG_CYBERSTORMII_SCSI) || defined(CONFIG_CYBERSTORMII_SCSI_MODULE) || \
+    defined(CONFIG_FASTLANE_SCSI) || defined(CONFIG_FASTLANE_SCSI_MODULE)
+#define MULTIPLE_PAD_SIZES
+#else
+#define PAD_SIZE 1
+#endif
+#endif
+
 /* Macros for debugging messages */
 
 #define DEBUG_ESP
@@ -107,8 +125,10 @@
 #ifdef CONFIG_JAZZ_ESP
 #define EREGS_PAD(n)
 #else
+#ifndef MULTIPLE_PAD_SIZES
 #define EREGS_PAD(n)    unchar n[PAD_SIZE];
 #endif
+#endif
 
 /* The ESP SCSI controllers have their register sets in three
  * "classes":
@@ -120,12 +140,10 @@
  * Yet, they all live within the same IO space.
  */
 
-/* All the ESP registers are one byte each and are accessed longwords
- * apart with a big-endian ordering to the bytes.
- */
-
 #ifndef __i386__
 
+#ifndef MULTIPLE_PAD_SIZES
+
 #define esp_write(__reg, __val) ((__reg) = (__val))
 #define esp_read(__reg) (__reg)
 
@@ -172,14 +190,51 @@
     volatile unchar esp_fgrnd;  /* rw  Data base for fifo             0x3c  */
 };
 
+#else /* MULTIPLE_PAD_SIZES */
+
+#define esp_write(__reg, __val) (*(__reg) = (__val))
+#define esp_read(__reg) (*(__reg))
+
+struct ESP_regs {
+    unsigned char io_addr[64]; /* dummy */
+                                                 /* Access    Description              Offset */
+#define esp_tclow   io_addr                      /* rw  Low bits of the transfer count 0x00   */
+#define esp_tcmed   io_addr + (1<<(esp->shift))  /* rw  Mid bits of the transfer count 0x04   */
+#define esp_fdata   io_addr + (2<<(esp->shift))  /* rw  FIFO data bits                 0x08   */
+#define esp_cmnd    io_addr + (3<<(esp->shift))  /* rw  SCSI command bits              0x0c   */
+#define esp_status  io_addr + (4<<(esp->shift))  /* ro  ESP status register            0x10   */
+#define esp_busid   esp_status                   /* wo  Bus ID for select/reselect     0x10   */
+#define esp_intrpt  io_addr + (5<<(esp->shift))  /* ro  Kind of interrupt              0x14   */
+#define esp_timeo   esp_intrpt                   /* wo  Timeout value for select/resel 0x14   */
+#define esp_sstep   io_addr + (6<<(esp->shift))  /* ro  Sequence step register         0x18   */
+#define esp_stp     esp_sstep                    /* wo  Transfer period per sync       0x18   */
+#define esp_fflags  io_addr + (7<<(esp->shift))  /* ro  Bits of current FIFO info      0x1c   */
+#define esp_soff    esp_fflags                   /* wo  Sync offset                    0x1c   */
+#define esp_cfg1    io_addr + (8<<(esp->shift))  /* rw  First configuration register   0x20   */
+#define esp_cfact   io_addr + (9<<(esp->shift))  /* wo  Clock conversion factor        0x24   */
+#define esp_ctest   io_addr + (10<<(esp->shift)) /* wo  Chip test register             0x28   */
+#define esp_cfg2    io_addr + (11<<(esp->shift)) /* rw  Second configuration register  0x2c   */
+
+    /* The following is only found on the 53C9X series SCSI chips */
+#define esp_cfg3    io_addr + (12<<(esp->shift)) /* rw  Third configuration register   0x30  */
+#define esp_cfg4    io_addr + (13<<(esp->shift)) /* rw  Fourth configuration register  0x34  */
+
+    /* The following is found on all chips except the NCR53C90 (ESP100) */
+#define esp_tchi    io_addr + (14<<(esp->shift)) /* rw  High bits of transfer count    0x38  */
+#define esp_uid     esp_tchi                     /* ro  Unique ID code                 0x38  */
+#define esp_fgrnd   io_addr + (15<<(esp->shift)) /* rw  Data base for fifo             0x3c  */
+};
+
+#endif
+
 #else /* !defined __i386__ */
 
-#define esp_write(__reg, __val) outb((__reg), (__val))
+#define esp_write(__reg, __val) outb((__val), (__reg))
 #define esp_read(__reg) inb((__reg))
 
 struct ESP_regs {
     unsigned int io_addr;
-                                  /* Access    Description              Offset */
+                                 /* Access    Description              Offset */
 #define esp_tclow   io_addr      /* rw  Low bits of the transfer count 0x00   */
 #define esp_tcmed   io_addr + 1  /* rw  Mid bits of the transfer count 0x04   */
 #define esp_fdata   io_addr + 2  /* rw  FIFO data bits                 0x08   */
@@ -339,6 +394,9 @@
 
   unchar do_pio_cmds;		/* Do command transfer with pio */
 
+  /* How much bits do we have to shift the registers */
+  unsigned char shift;
+
   /* Functions handling DMA
    */ 
   /* Required functions */
@@ -581,6 +639,7 @@
 extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
 			   unchar cmd);
 extern struct NCR_ESP *esp_allocate(Scsi_Host_Template *, void *);
+extern void esp_deallocate(struct NCR_ESP *);
 extern void esp_release(void);
 extern void esp_initialize(struct NCR_ESP *);
 extern void esp_intr(int, void *, struct pt_regs *);
Index: drivers/scsi/blz1230.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/blz1230.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 blz1230.c
--- blz1230.c	1999/01/18 16:21:03	1.1.1.1
+++ blz1230.c	1999/01/28 17:50:50
@@ -82,12 +82,15 @@
 		eregs = (struct ESP_regs *)(address + BLZ1230II_ESP_ADDR);
 #endif
 
-		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
-		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)){
+			esp_deallocate(esp);
+			scsi_unregister(esp->ehost);
 			return 0; /* Bail out if address did not hold data */
-
-		esp = esp_allocate(tpnt, (void *) esp_dev);
+		}
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
@@ -251,7 +254,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
@@ -289,6 +292,7 @@
 	unsigned int key;
 
 	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
 	esp_release();
 	zorro_unconfig_board(key, 0);
 	free_irq(IRQ_AMIGA_PORTS, esp_intr);
Index: drivers/scsi/blz2060.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/blz2060.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 blz2060.c
--- blz2060.c	1999/01/18 16:21:04	1.1.1.1
+++ blz2060.c	1999/01/28 17:51:10
@@ -203,7 +203,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -252,6 +252,7 @@
 	unsigned int key;
 
 	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
 	esp_release();
 	zorro_unconfig_board(key, 0);
 	free_irq(IRQ_AMIGA_PORTS, esp_intr);
Index: drivers/scsi/cyberstorm.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/cyberstorm.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 cyberstorm.c
--- cyberstorm.c	1999/01/18 16:21:04	1.1.1.1
+++ cyberstorm.c	1999/01/28 16:12:41
@@ -265,7 +265,7 @@
 static int dma_irq_p(struct NCR_ESP *esp)
 {
 	/* It's important to check the DMA IRQ bit in the correct way! */
-	return ((esp->eregs->esp_status & ESP_STAT_INTR) &&
+	return ((esp_read(esp->eregs->esp_status) & ESP_STAT_INTR) &&
 		((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) &
 		 CYBER_DMA_HNDL_INTR));
 }
@@ -317,6 +317,7 @@
 	unsigned int key;
 
 	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
 	esp_release();
 	zorro_unconfig_board(key, 0);
 	free_irq(IRQ_AMIGA_PORTS, esp_intr);
Index: drivers/scsi/cyberstormII.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/cyberstormII.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 cyberstormII.c
--- cyberstormII.c	1999/01/18 16:21:04	1.1.1.1
+++ cyberstormII.c	1999/01/28 16:16:13
@@ -73,12 +73,15 @@
 		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
 		eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
 
-		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
-		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)) {
+			esp_deallocate(esp);
+			scsi_unregister(esp->ehost);
 			return 0; /* Bail out if address did not hold data */
-
-		esp = esp_allocate(tpnt, (void *) esp_dev);
+		}
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
@@ -216,7 +219,7 @@
 static int dma_irq_p(struct NCR_ESP *esp)
 {
 	/* It's important to check the DMA IRQ bit in the correct way! */
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -264,6 +267,7 @@
 	unsigned int key;
 
 	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata); 
 	esp_release();
 	zorro_unconfig_board(key, 0);
 	free_irq(IRQ_AMIGA_PORTS, esp_intr);
Index: drivers/scsi/fastlane.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/fastlane.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 fastlane.c
--- fastlane.c	1999/01/18 16:21:04	1.1.1.1
+++ fastlane.c	1999/01/28 16:17:00
@@ -313,7 +313,7 @@
 	   (dma_status & FASTLANE_DMA_CREQ) &&
 #endif
 	   (!(dma_status & FASTLANE_DMA_MINT)) &&
-	   ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
+	   (esp_read(((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
@@ -363,6 +363,7 @@
 	unsigned int key;
 
 	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_deallocate((struct NCR_ESP *)instance->hostdata);
 	esp_release();
 	zorro_unconfig_board(key, 0);
 	free_irq(IRQ_AMIGA_PORTS, esp_intr);
Index: drivers/scsi/hosts.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/hosts.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 hosts.c
--- hosts.c	1999/01/18 20:27:43	1.1.1.2
+++ hosts.c	1999/01/28 14:09:57
@@ -95,6 +95,10 @@
 #include "fastlane.h"
 #endif
 
+#ifdef CONFIG_OKTAGON_SCSI
+#include "oktagon_esp.h"
+#endif
+
 #ifdef CONFIG_ATARI_SCSI
 #include "atari_scsi.h"
 #endif
@@ -389,6 +393,9 @@
 #endif
 #ifdef CONFIG_FASTLANE_SCSI
 	SCSI_FASTLANE,
+#endif
+#ifdef CONFIG_OKTAGON_SCSI
+	SCSI_OKTAGON_ESP,
 #endif
 #endif
 
Index: drivers/scsi/jazz_esp.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/jazz_esp.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 jazz_esp.c
--- jazz_esp.c	1999/01/18 16:21:05	1.1.1.1
+++ jazz_esp.c	1999/01/28 14:58:27
@@ -196,7 +196,7 @@
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-    return (esp->eregs->esp_status & ESP_STAT_INTR);
+    return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
Index: drivers/scsi/mac_esp.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/mac_esp.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 mac_esp.c
--- mac_esp.c	1999/01/18 20:27:51	1.1.1.2
+++ mac_esp.c	1999/01/28 14:58:03
@@ -480,7 +480,7 @@
 static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
 {
 	unsigned int ret;
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 
@@ -521,7 +521,7 @@
 static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
 {
 	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
@@ -625,7 +625,7 @@
 
 static int dma_irq_p(struct NCR_ESP * esp)
 {
-	int i = esp->eregs->esp_status;
+	int i = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p status %d\n", i);
@@ -640,7 +640,7 @@
 	 * Copied from iosb_dma_irq_p()
 	 */
 	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp->eregs->esp_status;
+	int sreg = esp_read(esp->eregs->esp_status);
 
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
Index: drivers/scsi/mca_53c9x.c
===================================================================
RCS file: /usr/src/CVS/linux/drivers/scsi/mca_53c9x.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mca_53c9x.c
--- mca_53c9x.c	1999/01/18 16:21:06	1.1.1.1
+++ mca_53c9x.c	1999/01/28 16:22:30
@@ -156,6 +156,8 @@
 			 "NCR 53c9x SCSI", esp_intr))
 			{
 				printk("Unable to request IRQ %d.\n", esp->irq);
+				esp_deallocate(esp);
+				unregister_scsi(esp->ehost);
 				return 0;
 			}
 
@@ -163,6 +165,8 @@
 				printk("Unable to request DMA channel %d.\n",
 				 esp->dma);
 				free_irq(esp->irq, esp_intr);
+				esp_deallocate(esp);
+				unregister_scsi(esp->ehost);
 				return 0;
 			}
 
@@ -259,7 +263,7 @@
 	struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
 	unsigned char tmp_byte;
 
-
+	esp_deallocate(esp);
 	/*
 	 * Tell the 86C01 to stop sending interrupts
 	 */
Index: drivers/scsi/oktagon_esp.c
===================================================================
RCS file: oktagon_esp.c
diff -N oktagon_esp.c
--- /dev/null	Sun Dec 27 23:06:15 1998
+++ oktagon_esp.c	Thu Jan 28 15:51:59 1999
@@ -0,0 +1,598 @@
+/*
+ * Oktagon_esp.c -- Driver for bsc Oktagon
+ *
+ * Written by Carsten Pluntke 1998
+ *
+ * Based on cyber_esp.c
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_AMIGA) || defined(CONFIG_APUS)
+#define USE_BOTTOM_HALF
+#endif
+
+#define __KERNEL_SYSCALLS__
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/reboot.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "oktagon_esp.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+#ifdef USE_BOTTOM_HALF
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#endif
+
+#include <linux/unistd.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void dma_ints_off(struct NCR_ESP *esp);
+static void dma_ints_on(struct NCR_ESP *esp);
+static int  dma_irq_p(struct NCR_ESP *esp);
+static void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+static void dma_irq_exit(struct NCR_ESP *esp);
+static void dma_invalidate(struct NCR_ESP *esp);
+
+static void dma_mmu_get_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_release_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_mmu_release_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
+static void dma_advance_sg(Scsi_Cmnd *);
+static int  oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x);
+
+void esp_bootup_reset(struct NCR_ESP *esp,struct ESP_regs *eregs);
+
+#ifdef USE_BOTTOM_HALF
+static void dma_commit(void *opaque);
+
+long oktag_to_io(long *paddr, long *addr, long len);
+long oktag_from_io(long *addr, long *paddr, long len);
+
+static struct tq_struct tq_fake_dma = { NULL, 0, dma_commit, NULL };
+
+#define DMA_MAXTRANSFER 0x8000
+
+#else
+
+/*
+ * No bottom half. Use transfer directly from IRQ. Find a narrow path
+ * between too much IRQ overhead and clogging the IRQ for too long.
+ */
+
+#define DMA_MAXTRANSFER 0x1000
+
+#endif
+
+static struct notifier_block oktagon_notifier = { 
+	oktagon_notify_reboot,
+	NULL,
+	0
+};
+
+static long *paddress;
+static long *address;
+static long len;
+static long dma_on;
+static int direction;
+static struct NCR_ESP *current_esp;
+
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int oktagon_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	int key;
+	unsigned long address;
+	struct ESP_regs *eregs;
+
+	if((key = zorro_find(ZORRO_PROD_BSC_OKTAGON_2008, 0, 0))){
+		esp_dev = zorro_get_board(key);
+
+		/*
+		 * It is a SCSI controller.
+		 * Hardwire Host adapter to SCSI ID 7
+		 */
+		
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+		eregs = (struct ESP_regs *)(address + OKTAGON_ESP_ADDR);
+
+		/* This line was 5 lines lower */
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* we have to shift the registers only one bit for oktagon */
+		esp->shift = 1;
+
+		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
+		udelay(5);
+		if (esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7))
+			return 0; /* Bail out if address did not hold data */
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = &dma_invalidate;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = &dma_irq_exit;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
+		esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
+		esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
+		esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
+		esp->dma_advance_sg = &dma_advance_sg;
+
+		/* SCSI chip speed */
+		/* Looking at the quartz of the SCSI board... */
+		esp->cfreq = 25000000;
+
+		/* The DMA registers on the CyberStorm are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		esp->dregs = (void *)(address + OKTAGON_DMA_ADDR);
+
+		paddress = (long *) esp->dregs;
+
+		/* ESP register base */
+		esp->eregs = eregs;
+		
+		/* Set the command buffer */
+		esp->esp_command = (volatile unsigned char*) cmd_buffer;
+
+		/* Yes, the virtual address. See below. */
+		esp->esp_command_dvma = (__u32) cmd_buffer;
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		esp->slot = key;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, "BSC Oktagon SCSI", esp_intr);
+
+		/* Figure out our scsi ID on the bus */
+		esp->scsi_id = 7;
+		
+		/* We don't have a differential SCSI-bus. */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+		printk("ESP_Oktagon Driver 1.1"
+#ifdef USE_BOTTOM_HALF
+		       " [BOTTOM_HALF]"
+#else
+		       " [IRQ]"
+#endif
+		       " registered.\n");
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
+		esps_running = esps_in_use;
+		current_esp = esp;
+		register_reboot_notifier(&oktagon_notifier);
+		return esps_in_use;
+	}
+	return 0;
+}
+
+
+/*
+ * On certain configurations the SCSI equipment gets confused on reboot,
+ * so we have to reset it then.
+ */
+
+static int
+oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
+{
+  struct NCR_ESP *esp;
+  
+  if((code == SYS_DOWN || code == SYS_HALT) && (esp = current_esp))
+   {
+    esp_bootup_reset(esp,esp->eregs);
+    udelay(500); /* Settle time. Maybe unneccessary. */
+   }
+  return NOTIFY_DONE;
+}
+    
+
+	
+#ifdef USE_BOTTOM_HALF
+
+
+/*
+ * The bsc Oktagon controller has no real DMA, so we have to do the 'DMA
+ * transfer' in the interrupt (Yikes!) or use a bottom half to not to clutter
+ * IRQ's for longer-than-good.
+ *
+ * FIXME
+ * BIG PROBLEM: 'len' is usually the buffer length, not the expected length
+ * of the data. So DMA may finish prematurely, further reads lead to
+ * 'machine check' on APUS systems (don't know about m68k systems, AmigaOS
+ * deliberately ignores the bus faults) and a normal copy-loop can't
+ * be exited prematurely just at the right moment by the dma_invalidate IRQ.
+ * So do it the hard way, write an own copier in assembler and
+ * catch the exception.
+ *                                     -- Carsten
+ */
+ 
+ 
+static void dma_commit(void *opaque)
+{
+    long wait,len2,pos;
+    struct NCR_ESP *esp;
+
+    ESPDATA(("Transfer: %ld bytes, Address 0x%08lX, Direction: %d\n",
+         len,(long) address,direction));
+    dma_ints_off(current_esp);
+
+    pos = 0;
+    wait = 1;
+    if(direction) /* write? (memory to device) */
+     {
+      while(len > 0)
+       {
+        len2 = oktag_to_io(paddress, address+pos, len);
+	if(!len2)
+	 {
+	  if(wait > 1000)
+	   {
+	    printk("Expedited DMA exit (writing) %ld\n",len);
+	    break;
+	   }
+	  mdelay(wait);
+	  wait *= 2;
+	 }
+	pos += len2;
+	len -= len2*sizeof(long);
+       }
+     } else {
+      while(len > 0)
+       {
+        len2 = oktag_from_io(address+pos, paddress, len);
+	if(!len2)
+	 {
+	  if(wait > 1000)
+	   {
+	    printk("Expedited DMA exit (reading) %ld\n",len);
+	    break;
+	   }
+	  mdelay(wait);
+	  wait *= 2;
+	 }
+	pos += len2;
+	len -= len2*sizeof(long);
+       }
+     }
+
+    /* to make esp->shift work */
+    esp=current_esp;
+
+#if 0
+    len2 = (esp_read(current_esp->eregs->esp_tclow) & 0xff) |
+           ((esp_read(current_esp->eregs->esp_tcmed) & 0xff) << 8);
+
+    /*
+     * Uh uh. If you see this, len and transfer count registers were out of
+     * sync. That means really serious trouble.
+     */
+
+    if(len2)
+      printk("Eeeek!! Transfer count still %ld!\n",len2);
+#endif
+
+    /*
+     * Normally we just need to exit and wait for the interrupt to come.
+     * But at least one device (my Microtek ScanMaker 630) regularly mis-
+     * calculates the bytes it should send which is really ugly because
+     * it locks up the SCSI bus if not accounted for.
+     */
+
+    if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+     {
+      long len = 100;
+      long trash[10];
+
+      /*
+       * Interrupt bit was not set. Either the device is just plain lazy
+       * so we give it a 10 ms chance or...
+       */
+      while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
+        udelay(100);
+
+
+      if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+       {
+        /*
+	 * So we think that the transfer count is out of sync. Since we
+	 * have all we want we are happy and can ditch the trash.
+	 */
+	 
+        len = DMA_MAXTRANSFER;
+
+        while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
+          oktag_from_io(trash,paddress,2);
+
+        if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
+         {
+          /*
+           * Things really have gone wrong. If we leave the system in that
+           * state, the SCSI bus is locked forever. I hope that this will
+           * turn the system in a more or less running state.
+           */
+          printk("Device is bolixed, trying bus reset...\n");
+	  esp_bootup_reset(current_esp,current_esp->eregs);
+         }
+       }
+     }
+
+    ESPDATA(("Transfer_finale: do_data_finale should come\n"));
+
+    len = 0;
+    dma_on = 0;
+    dma_ints_on(current_esp);
+}
+
+#endif
+
+/************************************************************* DMA Functions */
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > DMA_MAXTRANSFER)
+		sz = DMA_MAXTRANSFER;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+}
+
+/*
+ * What the f$@& is this?
+ *
+ * Some SCSI devices (like my Microtek ScanMaker 630 scanner) want to transfer
+ * more data than requested. How much? Dunno. So ditch the bogus data into
+ * the sink, hoping the device will advance to the next phase sooner or later.
+ *
+ *                         -- Carsten
+ */
+
+static long oktag_eva_buffer[16]; /* The data sink */
+
+static void oktag_check_dma(void)
+{
+  struct NCR_ESP *esp;
+
+  esp=current_esp;
+  if(!len)
+   {
+    address = oktag_eva_buffer;
+    len = 2;
+    /* esp_do_data sets them to zero like len */
+    esp_write(current_esp->eregs->esp_tclow,2);
+    esp_write(current_esp->eregs->esp_tcmed,0);
+   }
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	/* Zorro is noncached, everything else done using processor. */
+	/* cache_clear(addr, length); */
+	
+	if(dma_on)
+	  panic("dma_init_read while dma process is initialized/running!\n");
+	direction = 0;
+	address = (long *) vaddress;
+	current_esp = esp;
+	len = length;
+	oktag_check_dma();
+        dma_on = 1;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	/* cache_push(addr, length); */
+
+	if(dma_on)
+	  panic("dma_init_write while dma process is initialized/running!\n");
+	direction = 1;
+	address = (long *) vaddress;
+	current_esp = esp;
+	len = length;
+	oktag_check_dma();
+	dma_on = 1;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	/* It's important to check the DMA IRQ bit in the correct way! */
+	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
+	 * so when (write) is true, it actually means READ!
+	 */
+	if(write){
+		dma_init_read(esp, addr, count);
+	} else {
+		dma_init_write(esp, addr, count);
+	}
+}
+
+/*
+ * IRQ entry when DMA transfer is ready to be started
+ */
+
+static void dma_irq_exit(struct NCR_ESP *esp)
+{
+#ifdef USE_BOTTOM_HALF
+	if(dma_on)
+	 {
+	  tq_fake_dma.sync = 0;
+	  queue_task(&tq_fake_dma,&tq_immediate);
+	  mark_bh(IMMEDIATE_BH);
+	 }
+#else
+	while(len && !dma_irq_p(esp))
+	 {
+	  if(direction)
+	    *paddress = *address++;
+	   else
+	    *address++ = *paddress;
+	  len -= (sizeof(long));
+	 }
+	len = 0;
+        dma_on = 0;
+#endif
+}
+
+/*
+ * IRQ entry when DMA has just finished
+ */
+
+static void dma_invalidate(struct NCR_ESP *esp)
+{
+}
+
+/*
+ * Since the processor does the data transfer we have to use the custom
+ * mmu interface to pass the virtual address, not the physical.
+ */
+
+void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+        sp->SCp.have_data_in = (int) sp->SCp.ptr =
+                sp->request_buffer;
+}
+
+void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+        sp->SCp.ptr = 
+                sp->SCp.buffer->address;
+}
+
+void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+}
+
+void dma_mmu_release_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+}
+
+void dma_advance_sg(Scsi_Cmnd *sp)
+{
+  sp->SCp.ptr = sp->SCp.buffer->address;
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "oktagon_esp.h"
+
+Scsi_Host_Template driver_template = SCSI_OKTAGON_ESP;
+
+#include "scsi_module.c"
+
+#endif
+
+int oktagon_esp_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	unsigned int key;
+
+	key = ((struct NCR_ESP *)instance->hostdata)->slot;
+	esp_release();
+	zorro_unconfig_board(key, 0);
+	free_irq(IRQ_AMIGA_PORTS, esp_intr);
+	unregister_reboot_notifier(&oktagon_notifier);
+#endif
+	return 1;
+}
Index: drivers/scsi/oktagon_esp.h
===================================================================
RCS file: oktagon_esp.h
diff -N oktagon_esp.h
--- /dev/null	Sun Dec 27 23:06:15 1998
+++ oktagon_esp.h	Thu Jan 28 18:54:32 1999
@@ -0,0 +1,57 @@
+/* oktagon_esp.h: Defines and structures for the CyberStorm SCSI Mk II driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cs.auc.dk)
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef OKTAGON_ESP_H
+#define OKTAGON_ESP_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define OKTAGON_ESP_ADDR 0x03000
+#define OKTAGON_DMA_ADDR 0x01000
+
+
+/* The CyberStorm II DMA interface */
+struct oktagon_dma_registers {
+	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x000] */
+#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x000] */
+	unsigned char dmapad4[0x3f];
+	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x040] */
+	unsigned char dmapad1[3];
+	volatile unsigned char dma_addr1;	/* DMA address       [0x044] */
+	unsigned char dmapad2[3];
+	volatile unsigned char dma_addr2;	/* DMA address       [0x048] */
+	unsigned char dmapad3[3];
+	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x04c] */
+};
+
+extern int oktagon_esp_detect(struct SHT *);
+extern int oktagon_esp_release(struct Scsi_Host *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+			int hostno, int inout);
+
+#define SCSI_OKTAGON_ESP {                       \
+   proc_dir:            &proc_scsi_esp,          \
+   proc_info:           &esp_proc_info,          \
+   name:                "BSC Oktagon SCSI",      \
+   detect:              oktagon_esp_detect,      \
+   release:             oktagon_esp_release,     \
+   queuecommand:        esp_queue,               \
+   abort:               esp_abort,               \
+   reset:               esp_reset,               \
+   can_queue:           7,                       \
+   this_id:             7,                       \
+   sg_tablesize:        SG_ALL,                  \
+   cmd_per_lun:         1,                       \
+   use_clustering:      ENABLE_CLUSTERING }
+
+#endif /* OKTAGON_ESP_H */
Index: drivers/scsi/oktagon_io.S
===================================================================
RCS file: oktagon_io.S
diff -N oktagon_io.S
--- /dev/null	Sun Dec 27 23:06:15 1998
+++ oktagon_io.S	Thu Jan 28 15:09:57 1999
@@ -0,0 +1,194 @@
+/* -*- mode: asm -*-
+ * Due to problems while transferring data I've put these routines as assembly
+ * code.
+ * Since I'm no PPC assembler guru, the code is just the assembler version of
+
+int oktag_to_io(long *paddr,long *addr,long len)
+{
+  long *addr2 = addr;
+  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
+    *paddr = *addr2++;
+  return addr2 - addr;
+}
+
+int oktag_from_io(long *addr,long *paddr,long len)
+{
+  long *addr2 = addr;
+  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
+    *addr2++ = *paddr;
+  return addr2 - addr;
+}
+
+ * assembled using gcc -O2 -S, with two exception catch points where data
+ * is moved to/from the IO register.
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_APUS
+
+	.file	"oktagon_io.c"
+
+gcc2_compiled.:
+/*
+	.section ".text"
+*/
+	.align 2
+	.globl oktag_to_io
+	.type	 oktag_to_io,@function
+oktag_to_io:
+	addi 5,5,3
+	srwi 5,5,2
+	cmpwi 1,5,0
+	mr 9,3
+	mr 3,4
+	addi 5,5,-1
+	bc 12,6,.L3
+.L5:
+	cmpwi 1,5,0
+	lwz 0,0(3)
+	addi 3,3,4
+	addi 5,5,-1
+exp1:	stw 0,0(9)
+	bc 4,6,.L5
+.L3:
+ret1:	subf 3,4,3
+	srawi 3,3,2
+	blr
+.Lfe1:
+	.size	 oktag_to_io,.Lfe1-oktag_to_io
+	.align 2
+	.globl oktag_from_io
+	.type	 oktag_from_io,@function
+oktag_from_io:
+	addi 5,5,3
+	srwi 5,5,2
+	cmpwi 1,5,0
+	mr 9,3
+	addi 5,5,-1
+	bc 12,6,.L9
+.L11:
+	cmpwi 1,5,0
+exp2:	lwz 0,0(4)
+	addi 5,5,-1
+	stw 0,0(3)
+	addi 3,3,4
+	bc 4,6,.L11
+.L9:
+ret2:	subf 3,9,3
+	srawi 3,3,2
+	blr
+.Lfe2:
+	.size	 oktag_from_io,.Lfe2-oktag_from_io
+	.ident	"GCC: (GNU) egcs-2.90.29 980515 (egcs-1.0.3 release)"
+
+/*
+ * Exception table.
+ * Second longword shows where to jump when an exception at the addr the first
+ * longword is pointing to is caught.
+ */
+
+.section __ex_table,"a"
+	.align	2
+oktagon_except:
+	.long	exp1,ret1
+	.long	exp2,ret2
+
+#endif
+
+/*
+The code which follows is for 680x0 based assembler and is meant for
+Linux/m68k. It was created by cross compiling the code using the
+instructions given above. I then added the four labels used in the
+exception handler table at the bottom of this file.
+- Kevin <kcozens@interlog.com>
+*/
+
+#ifdef CONFIG_AMIGA
+
+	.file	"oktagon_io.c"
+	.version	"01.01"
+gcc2_compiled.:
+.text
+	.align 	2
+.globl oktag_to_io
+	.type	 oktag_to_io,@function
+oktag_to_io:
+	link.w %a6,#0
+	move.l %d2,-(%sp)
+	move.l 8(%a6),%a1
+	move.l 12(%a6),%d1
+	move.l %d1,%a0
+	move.l 16(%a6),%d0
+	addq.l #3,%d0
+	lsr.l #2,%d0
+	subq.l #1,%d0
+	moveq.l #-1,%d2
+	cmp.l %d0,%d2
+	jbeq .L3
+.L5:
+exp1:
+	move.l (%a0)+,(%a1)
+	dbra %d0,.L5
+	clr.w %d0
+	subq.l #1,%d0
+	jbcc .L5
+.L3:
+ret1:
+	move.l %a0,%d0
+	sub.l %d1,%d0
+	asr.l #2,%d0
+	move.l -4(%a6),%d2
+	unlk %a6
+	rts
+
+.Lfe1:
+	.size	 oktag_to_io,.Lfe1-oktag_to_io
+	.align 	2
+.globl oktag_from_io
+	.type	 oktag_from_io,@function
+oktag_from_io:
+	link.w %a6,#0
+	move.l %d2,-(%sp)
+	move.l 8(%a6),%d1
+	move.l 12(%a6),%a1
+	move.l %d1,%a0
+	move.l 16(%a6),%d0
+	addq.l #3,%d0
+	lsr.l #2,%d0
+	subq.l #1,%d0
+	moveq.l #-1,%d2
+	cmp.l %d0,%d2
+	jbeq .L9
+.L11:
+exp2:
+	move.l (%a1),(%a0)+
+	dbra %d0,.L11
+	clr.w %d0
+	subq.l #1,%d0
+	jbcc .L11
+.L9:
+ret2:
+	move.l %a0,%d0
+	sub.l %d1,%d0
+	asr.l #2,%d0
+	move.l -4(%a6),%d2
+	unlk %a6
+	rts
+.Lfe2:
+	.size	 oktag_from_io,.Lfe2-oktag_from_io
+	.ident	"GCC: (GNU) 2.7.2.1"
+
+/*
+ * Exception table.
+ * Second longword shows where to jump when an exception at the addr the first
+ * longword is pointing to is caught.
+ */
+
+.section __ex_table,"a"
+	.align	2
+oktagon_except:
+	.long	exp1,ret1
+	.long	exp2,ret2
+
+#endif

