Resent-Date: Sat, 14 Nov 1998 17:41:27 +0100 (MET)
Date: Sat, 14 Nov 1998 16:42:25 GMT
From: Jesper Skov <jskov@cygnus.co.uk>
To: linux-m68k@lists.linux-m68k.org, Jes.Sorensen@cern.ch
Subject: iobarrier changes
Resent-From: linux-m68k@phil.uni-sb.de


Here's the new iobarrier changes for the m68k tree. I even got to use
the _r/_w macros in the fastlane driver, so I guess there might
actually be a reason for having them :)  Good catch, Alan; hope you
like it better now.

Jesper



diff -u --recursive -B --exclude-from=/home/jskov/lib/diff-excludes -P /home/jskov/kernel/dist/linux-2.1.127/drivers/char/amiga_ser.c ./drivers/char/amiga_ser.c
--- /home/jskov/kernel/dist/linux-2.1.127/drivers/char/amiga_ser.c	Wed Aug  5 16:01:49 1998
+++ ./drivers/char/amiga_ser.c	Sat Nov 14 16:55:54 1998
@@ -43,6 +43,8 @@
 #include <asm/irq.h>
 #include <asm/atomic.h>
 
+#include <asm/io.h>
+
 /* some serial hardware definitions */
 #define SDR_OVRUN   (1<<15)
 #define SDR_RBF     (1<<14)
@@ -200,9 +202,14 @@
      * set the appropriate directions for the modem control flags,
      * and clear RTS and DTR
      */
-    ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
-    ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
-    
+    {
+	    unsigned short v = ciab.ddra;
+	    v |= (SER_DTR | SER_RTS);   /* outputs */
+	    v &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
+	    iobarrier_rw ();
+	    ciab.ddra = v;
+    }
+
     info->sw   = &amiga_ser_switch;
 
     return 0;
@@ -210,20 +217,24 @@
 
 static void ser_rx_int(int irq, void *data, struct pt_regs *fp)
 {
-      struct m68k_async_struct *info = data;
-      int ch, err;
+      int ch;
 
       ch = custom.serdatr;
+      iobarrier_rw ();
 
-      custom.intreq = IF_RBF;
-
-      if ((ch & 0x1ff) == 0)
-	  err = TTY_BREAK;
-      else if (ch & SDR_OVRUN)
-	  err = TTY_OVERRUN;
-      else
-	  err = 0;
-      rs_receive_char(info, ch & 0xff, err);
+      {
+	      struct m68k_async_struct *info = data;
+	      int err;
+
+	      custom.intreq = IF_RBF;
+	      if ((ch & 0x1ff) == 0)
+		      err = TTY_BREAK;
+	      else if (ch & SDR_OVRUN)
+		      err = TTY_OVERRUN;
+	      else
+		      err = 0;
+	      rs_receive_char(info, ch & 0xff, err);
+      }
 }
 
 static void ser_tx_int( int irq, void *data, struct pt_regs *fp)
@@ -456,9 +467,9 @@
 
 #ifdef CONFIG_KGDB
 int amiga_ser_out( unsigned char c )
-
 {
 	custom.serdat = c | 0x100;
+	iobarrier_rw ();
 	while (!(custom.serdatr & 0x2000))
 		barrier();
 	return( 1 );
@@ -468,30 +479,34 @@
 
 {
 	unsigned char c;
-	
+
 	/* XXX: is that ok?? derived from amiga_ser.c... */
 	while( !(custom.intreqr & IF_RBF) )
 		barrier();
-	c = custom.serdatr;
+
+	iobarrier_r ();
+	c = (unsigned char) (custom.serdatr & 0x00ff);
+	iobarrier_rw ();
+
 	/* clear the interrupt, so that another character can be read */
 	custom.intreq = IF_RBF;
-	return( 0 );
+	return c;
 }
 #endif
 
 #ifdef MODULE
 int init_module(void)
 {
-return amiga_serinit();
+	return amiga_serinit();
 }
 
 void cleanup_module(void)
 {
-unregister_serial(line);
-custom.intena = IF_RBF | IF_TBE; /* forbid interrupts */
-custom.intreq = IF_RBF | IF_TBE; /* clear pending interrupts */
-free_irq(IRQ_AMIGA_TBE, amiga_info);
-free_irq(IRQ_AMIGA_RBF, amiga_info);
+	unregister_serial(line);
+	custom.intena = IF_RBF | IF_TBE; /* forbid interrupts */
+	custom.intreq = IF_RBF | IF_TBE; /* clear pending interrupts */
+	free_irq(IRQ_AMIGA_TBE, amiga_info);
+	free_irq(IRQ_AMIGA_RBF, amiga_info);
 }
 #endif
 
diff -u --recursive -B --exclude-from=/home/jskov/lib/diff-excludes -P /home/jskov/kernel/dist/linux-2.1.127/drivers/scsi/fastlane.c ./drivers/scsi/fastlane.c
--- /home/jskov/kernel/dist/linux-2.1.127/drivers/scsi/fastlane.c	Thu Nov 12 17:34:08 1998
+++ ./drivers/scsi/fastlane.c	Sat Nov 14 17:06:16 1998
@@ -38,6 +38,7 @@
 
 #include <linux/zorro.h>
 #include <asm/irq.h>
+#include <asm/io.h>		/* iobarrier, virt_to_bus */
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 
@@ -163,7 +164,7 @@
 		
 		/* Set the command buffer */
 		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((unsigned long) cmd_buffer);
+		esp->esp_command_dvma = virt_to_bus((void*) cmd_buffer);
 
 		esp->irq = IRQ_AMIGA_PORTS;
 		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
@@ -230,10 +231,13 @@
 	t = (unsigned long *)((addr & 0x00ffffff) + esp->edev);
 
 	dregs->clear_strobe = 0;
+	iobarrier_w ();
 	*t = addr;
+	iobarrier_w ();
 
 	ctrl_data = (ctrl_data & FASTLANE_DMA_MASK) | FASTLANE_DMA_ENABLE;
 	dregs->ctrl_reg = ctrl_data;
+	iobarrier_rw ();
 }
 
 static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
@@ -249,12 +253,15 @@
 	t = (unsigned long *)((addr & 0x00ffffff) + (esp->edev));
 
 	dregs->clear_strobe = 0;
+	iobarrier_w ();
 	*t = addr;
+	iobarrier_w ();
 
 	ctrl_data = ((ctrl_data & FASTLANE_DMA_MASK) | 
 		     FASTLANE_DMA_ENABLE |
 		     FASTLANE_DMA_WRITE);
 	dregs->ctrl_reg = ctrl_data;
+	iobarrier_rw ();
 }
 
 static inline void dma_clear(struct NCR_ESP *esp)
@@ -269,7 +276,9 @@
 	t = (unsigned long *)(esp->edev);
 
 	dregs->clear_strobe = 0;
+	iobarrier_w ();
 	*t = 0 ;
+	iobarrier_rw ();
 }
 
 
@@ -292,12 +301,14 @@
 #ifdef __mc68000__
 	nop();
 #endif
+	iobarrier_w ();
 	dregs->ctrl_reg = ctrl_data;
+	iobarrier_rw ();
 }
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-	struct fastlane_dma_registers *dregs = 
+	volatile struct fastlane_dma_registers *dregs = 
 		(struct fastlane_dma_registers *) (esp->dregs);
 	unsigned char dma_status;
 
@@ -306,25 +317,30 @@
 	if(dma_status & FASTLANE_DMA_IACT)
 		return 0;	/* not our IRQ */
 
+	iobarrier_r ();		/* Make sure PPC doesn't touch eregs */
+				/* prematurely. */
+
 	/* Return non-zero if ESP requested IRQ */
 	return (
 #ifndef NODMAIRQ
 	   (dma_status & FASTLANE_DMA_CREQ) &&
 #endif
 	   (!(dma_status & FASTLANE_DMA_MINT)) &&
-	   ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
+	   ((((volatile struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
 }
 
 static void dma_led_off(struct NCR_ESP *esp)
 {
 	ctrl_data &= ~FASTLANE_DMA_LED;
 	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+	iobarrier_rw ();
 }
 
 static void dma_led_on(struct NCR_ESP *esp)
 {
 	ctrl_data |= FASTLANE_DMA_LED;
 	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+	iobarrier_rw ();
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
diff -u --recursive -B --exclude-from=/home/jskov/lib/diff-excludes -P /home/jskov/kernel/dist/linux-2.1.127/include/asm-m68k/io.h ./include/asm-m68k/io.h
--- /home/jskov/kernel/dist/linux-2.1.127/include/asm-m68k/io.h	Mon Sep  7 21:04:12 1998
+++ ./include/asm-m68k/io.h	Sat Nov 14 16:53:46 1998
@@ -13,6 +13,13 @@
 
 #include <asm/virtconvert.h>
 
+/* Enforce in-order execution of data I/O. 
+ * All NOPs on m68k.
+ */
+#define iobarrier_rw() do {} while (0)
+#define iobarrier_r()  do {} while (0)
+#define iobarrier_w()  do {} while (0)
+
 /*
  * readX/writeX() are used to access memory mapped devices. On some
  * architectures the memory mapped IO stuff needs to be accessed

