Subject: [CFT] DECstation SCSI driver clean-ups

From: "Maciej W. Rozycki" <[email-masked]>
Date: Mon, 20 Jan 2003 22:47:29 +0100 (MET)

Hello,

 Testing of the dec_esp.c driver in a 64-bit environment (thanks, Karsten
and Thiemo) uncovered a few incorrect assumptions present in the code
leading to kernel crashes or misoperation.  I decided it's the right
moment to clean the driver up a bit.  Thus I rewrote iomem handling
consistently, adopted the unified I/O ASIC interface, added appropriate
SSR locking and fixed iomem coherency handling.  There are minor fixes
scattered through the code as well. 

 I'm going to commit the changes in a few days, but having no SCSI devices
attached to my DECstations, I cannot test the code at all.  I'd prefer to
avoid a non-working driver in the CVS, so I would appreciate if someone
with a suitable setup could test the new code.  A patch follows.

 The single PMAZ-A limitation of the driver still applies, but it should
be fairly easy to relax in the next step.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

patch-mips-2.4.20-20030112-dec_esp-ioasic-5
diff -up --recursive --new-file linux-mips-2.4.20-20030112.macro/arch/mips/dec/setup.c linux-mips-2.4.20-20030112/arch/mips/dec/setup.c
--- linux-mips-2.4.20-20030112.macro/arch/mips/dec/setup.c	2002-12-17 03:56:40.000000000 +0000
+++ linux-mips-2.4.20-20030112/arch/mips/dec/setup.c	2003-01-17 01:04:16.000000000 +0000
@@ -16,6 +16,7 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 #include <linux/types.h>
 
 #include <asm/cpu.h>
@@ -46,6 +47,8 @@ extern void dec_intr_halt(int irq, void 
 
 extern asmlinkage void decstation_handle_int(void);
 
+spinlock_t ioasic_ssr_lock;
+
 volatile u32 *ioasic_base;
 unsigned long dec_kn_slot_size;
 
diff -up --recursive --new-file linux-mips-2.4.20-20030112.macro/drivers/net/declance.c linux-mips-2.4.20-20030112/drivers/net/declance.c
--- linux-mips-2.4.20-20030112.macro/drivers/net/declance.c	2002-07-25 02:58:09.000000000 +0000
+++ linux-mips-2.4.20-20030112/drivers/net/declance.c	2003-01-17 01:10:59.000000000 +0000
@@ -52,6 +52,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/spinlock.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 
@@ -787,15 +788,23 @@ static int lance_open(struct net_device 
 		return -EAGAIN;
 	}
 	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
 		if (request_irq(lp->dma_irq, &lance_dma_merr_int, 0,
 				"lance error", dev)) {
 			free_irq(dev->irq, dev);
 			printk("lance: Can't get DMA IRQ %d\n", lp->dma_irq);
 			return -EAGAIN;
 		}
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
 		/* Enable I/O ASIC LANCE DMA.  */
-		fast_wmb();
 		ioasic_write(SSR, ioasic_read(SSR) | LANCE_DMA_EN);
+
+		fast_mb();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
 	}
 
 	status = init_restart_lance(lp);
@@ -821,9 +830,17 @@ static int lance_close(struct net_device
 	writereg(&ll->rdp, LE_C0_STOP);
 
 	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
 		/* Disable I/O ASIC LANCE DMA.  */
 		ioasic_write(SSR, ioasic_read(SSR) & ~LANCE_DMA_EN);
+
 		fast_iob();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
+
 		free_irq(lp->dma_irq, dev);
 	}
 	free_irq(dev->irq, dev);
diff -up --recursive --new-file linux-mips-2.4.20-20030112.macro/drivers/scsi/dec_esp.c linux-mips-2.4.20-20030112/drivers/scsi/dec_esp.c
--- linux-mips-2.4.20-20030112.macro/drivers/scsi/dec_esp.c	2002-12-04 03:57:01.000000000 +0000
+++ linux-mips-2.4.20-20030112/drivers/scsi/dec_esp.c	2003-01-17 16:04:20.000000000 +0000
@@ -17,6 +17,8 @@
  *            data.
  * 20001005	- Initialization fixes for 2.4.0-test9
  * 			  Florian Lohoff <[email-masked]>
+ *
+ *	Copyright (C) 2002, 2003  Maciej W. Rozycki
  */
 
 #include <linux/kernel.h>
@@ -26,54 +28,48 @@
 #include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
+#include <linux/spinlock.h>
 #include <linux/stat.h>
 
-#include "scsi.h"
-#include "hosts.h"
-#include "NCR53C9x.h"
-#include "dec_esp.h"
-
-#include <asm/irq.h>
 #include <asm/dma.h>
-
+#include <asm/irq.h>
 #include <asm/pgtable.h>
+#include <asm/system.h>
 
-#include <asm/dec/tc.h>
 #include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/ioasic_ints.h>
 #include <asm/dec/machtype.h>
+#include <asm/dec/tc.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "dec_esp.h"
 
-#include <asm/system.h>
 
-/*
- * Once upon a time the pmaz code used to be working but
- * it hasn't been maintained for quite some time.
- * It isn't working anymore but I'll leave here as a
- * starting point. #define this an be prepared for tons
- * of warnings and errors :)
- */
 static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
 static void dma_drain(struct NCR_ESP *esp);
 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_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 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_setup(struct NCR_ESP *esp, u32 addr, int count, int write);
 static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
 static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
 static void dma_advance_sg(Scsi_Cmnd * sp);
 
 static void pmaz_dma_drain(struct NCR_ESP *esp);
-static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length);
+static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length);
 static void pmaz_dma_ints_off(struct NCR_ESP *esp);
 static void pmaz_dma_ints_on(struct NCR_ESP *esp);
-static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+static void pmaz_dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write);
 static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
 
 #define TC_ESP_RAM_SIZE 0x20000
@@ -84,7 +80,7 @@ static void pmaz_dma_mmu_get_scsi_one(st
 #define TC_ESP_DMAR_WRITE 0x80000000
 #define TC_ESP_DMA_ADDR(x) ((unsigned)(x) & TC_ESP_DMAR_MASK)
 
-__u32 esp_virt_buffer;
+u32 esp_virt_buffer;
 int scsi_current_length;
 
 volatile unsigned char cmd_buffer[16];
@@ -94,13 +90,6 @@ volatile unsigned char pmaz_cmd_buffer[1
 				 * via PIO.
 				 */
 
-volatile unsigned long *scsi_dma_ptr;
-volatile unsigned long *scsi_next_ptr;
-volatile unsigned long *scsi_scr;
-volatile unsigned long *ioasic_ssr;
-volatile unsigned long *scsi_sdr0;
-volatile unsigned long *scsi_sdr1;
-
 static void scsi_dma_merr_int(int, void *, struct pt_regs *);
 static void scsi_dma_err_int(int, void *, struct pt_regs *);
 static void scsi_dma_int(int, void *, struct pt_regs *);
@@ -121,13 +110,6 @@ int dec_esp_detect(Scsi_Host_Template * 
 		esp_dev = 0;
 		esp = esp_allocate(tpnt, (void *) esp_dev);
 
-		scsi_dma_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_P);
-		scsi_next_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_BP);
-		scsi_scr = (unsigned long *) (system_base + IOCTL + SCSI_SCR);
-		ioasic_ssr = (unsigned long *) (system_base + IOCTL + SSR);
-		scsi_sdr0 = (unsigned long *) (system_base + IOCTL + SCSI_SDR0);
-		scsi_sdr1 = (unsigned long *) (system_base + IOCTL + SCSI_SDR1);
-
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
 
@@ -174,7 +156,7 @@ int dec_esp_detect(Scsi_Host_Template * 
 		esp->esp_command = (volatile unsigned char *) cmd_buffer;
 
 		/* get virtual dma address for command buffer */
-		esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer);
+		esp->esp_command_dvma = virt_to_phys(cmd_buffer);
 
 		esp->irq = dec_interrupt[DEC_IRQ_ASC];
 
@@ -213,7 +195,7 @@ int dec_esp_detect(Scsi_Host_Template * 
 			mem_start = get_tc_base_addr(slot);
 
 			/* Store base addr into esp struct */
-			esp->slot = mem_start;
+			esp->slot = PHYSADDR(mem_start);
 
 			esp->dregs = 0;
 			esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG);
@@ -223,7 +205,7 @@ int dec_esp_detect(Scsi_Host_Template * 
 			esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer;
 
 			/* get virtual dma address for command buffer */
-			esp->esp_command_dvma = (__u32) KSEG0ADDR((volatile unsigned char *) pmaz_cmd_buffer);
+			esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer);
 
 			esp->cfreq = get_tc_speed();
 
@@ -303,40 +285,53 @@ static void scsi_dma_err_int(int irq, vo
 
 static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs)
 {
+	u32 scsi_next_ptr;
+
+	scsi_next_ptr = ioasic_read(SCSI_DMA_P);
+
 	/* next page */
-	*scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3;
+	scsi_next_ptr = (((scsi_next_ptr >> 3) + PAGE_SIZE) & PAGE_MASK) << 3;
+	ioasic_write(SCSI_DMA_BP, scsi_next_ptr);
 	fast_iob();
 }
 
 static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
 {
-    return fifo_count;
+	return fifo_count;
 }
 
 static void dma_drain(struct NCR_ESP *esp)
 {
-	unsigned long nw = *scsi_scr;
-	unsigned short *p = (unsigned short *)KSEG1ADDR((*scsi_dma_ptr) >> 3);
+	u32 nw, data0, data1, scsi_data_ptr;
+	u16 *p;
+
+	nw = ioasic_read(SCSI_SCR);
 
-    /*
+	/*
 	 * Is there something in the dma buffers left?
-     */
+	 */
 	if (nw) {
+		scsi_data_ptr = ioasic_read(SCSI_DMA_P) >> 3;
+		p = phys_to_virt(scsi_data_ptr);
 		switch (nw) {
 		case 1:
-			*p = (unsigned short) *scsi_sdr0;
+			data0 = ioasic_read(SCSI_SDR0);
+			p[0] = data0 & 0xffff;
 			break;
 		case 2:
-			*p++ = (unsigned short) (*scsi_sdr0);
-			*p = (unsigned short) ((*scsi_sdr0) >> 16);
+			data0 = ioasic_read(SCSI_SDR0);
+			p[0] = data0 & 0xffff;
+			p[1] = (data0 >> 16) & 0xffff;
 			break;
 		case 3:
-			*p++ = (unsigned short) (*scsi_sdr0);
-			*p++ = (unsigned short) ((*scsi_sdr0) >> 16);
-			*p = (unsigned short) (*scsi_sdr1);
+			data0 = ioasic_read(SCSI_SDR0);
+			data1 = ioasic_read(SCSI_SDR1);
+			p[0] = data0 & 0xffff;
+			p[1] = (data0 >> 16) & 0xffff;
+			p[2] = data1 & 0xffff;
 			break;
 		default:
-			printk("Strange: %d words in dma buffer left\n", (int) nw);
+			printk("Strange: %d words in dma buffer left\n", nw);
 			break;
 		}
 	}
@@ -351,38 +346,72 @@ static void dma_dump_state(struct NCR_ES
 {
 }
 
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
 {
+	u32 scsi_next_ptr, ioasic_ssr;
+	unsigned long flags;
+
 	if (vaddress & 3)
 		panic("dec_esp.c: unable to handle partial word transfers, yet...");
 
 	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
 
-	*ioasic_ssr &= ~SCSI_DMA_EN;
-	*scsi_scr = 0;
-	*scsi_dma_ptr = vaddress << 3;
+	spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+	fast_mb();
+	ioasic_ssr = ioasic_read(SSR);
+
+	ioasic_ssr &= ~SCSI_DMA_EN;
+	ioasic_write(SSR, ioasic_ssr);
+
+	fast_wmb();
+	ioasic_write(SCSI_SCR, 0);
+	ioasic_write(SCSI_DMA_P, vaddress << 3);
 
 	/* prepare for next page */
-	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
-	*ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN);
+	scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
+	ioasic_write(SCSI_DMA_BP, scsi_next_ptr);
+
+	ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN);
+	fast_wmb();
+	ioasic_write(SSR, ioasic_ssr);
+
 	fast_iob();
+	spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
 }
 
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length)
 {
+	u32 scsi_next_ptr, ioasic_ssr;
+	unsigned long flags;
+
 	if (vaddress & 3)
 		panic("dec_esp.c: unable to handle partial word transfers, yet...");
 
 	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
 
-	*ioasic_ssr &= ~(SCSI_DMA_DIR | SCSI_DMA_EN);
-	*scsi_scr = 0;
-	*scsi_dma_ptr = vaddress << 3;
+	spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+	fast_mb();
+	ioasic_ssr = ioasic_read(SSR);
+
+	ioasic_ssr &= ~(SCSI_DMA_DIR | SCSI_DMA_EN);
+	ioasic_write(SSR, ioasic_ssr);
+
+	fast_wmb();
+	ioasic_write(SCSI_SCR, 0);
+	ioasic_write(SCSI_DMA_P, vaddress << 3);
 
 	/* prepare for next page */
-	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
-	*ioasic_ssr |= SCSI_DMA_EN;
+	scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
+	ioasic_write(SCSI_DMA_BP, scsi_next_ptr);
+
+	ioasic_ssr |= SCSI_DMA_EN;
+	fast_wmb();
+	ioasic_write(SSR, ioasic_ssr);
+
 	fast_iob();
+	spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
 }
 
 static void dma_ints_off(struct NCR_ESP *esp)
@@ -397,36 +426,32 @@ static void dma_ints_on(struct NCR_ESP *
 
 static int dma_irq_p(struct NCR_ESP *esp)
 {
-    return (esp->eregs->esp_status & ESP_STAT_INTR);
+	return (esp->eregs->esp_status & ESP_STAT_INTR);
 }
 
 static int dma_ports_p(struct NCR_ESP *esp)
 {
-/*
- * FIXME: what's this good for?
- */
+	/*
+	 * FIXME: what's this good for?
+	 */
 	return 1;
 }
 
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+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);
-    }
+	/*
+	 * 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);
 }
 
-/*
- * These aren't used yet
- */
 static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
 {
-	sp->SCp.ptr = (char *)PHYSADDR(sp->SCp.buffer);
+	sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
 }
 
 static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
@@ -435,32 +460,33 @@ static void dma_mmu_get_scsi_sgl(struct 
 	struct scatterlist *sg = sp->SCp.buffer;
 
 	while (sz >= 0) {
-		sg[sz].dma_address = PHYSADDR(sg[sz].address);
+		sg[sz].dma_address = virt_to_phys(sg[sz].address);
 		sz--;
 	}
-	sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dma_address);
+	sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
 }
 
 static void dma_advance_sg(Scsi_Cmnd * sp)
 {
-	sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dma_address);
+	sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
 }
 
 static void pmaz_dma_drain(struct NCR_ESP *esp)
 {
-	memcpy((void *) (KSEG0ADDR(esp_virt_buffer)),
-		(void *) ( esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
+	memcpy(phys_to_virt(esp_virt_buffer),
+		(void *)KSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
 		scsi_current_length);
 }
 
-static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
 {
-	volatile int *dmareg = (volatile int *) (esp->slot + DEC_SCSI_DMAREG);
+	volatile u32 *dmareg =
+		(volatile u32 *)KSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
 
 	if (length > ESP_TGT_DMA_SIZE)
 		length = ESP_TGT_DMA_SIZE;
 
-	*dmareg = TC_ESP_DMA_ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE);
+	*dmareg = TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE);
 
 	iob();
 
@@ -468,15 +494,16 @@ static void pmaz_dma_init_read(struct NC
 	scsi_current_length = length;
 }
 
-static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length)
 {
-	volatile int *dmareg = (volatile int *) ( esp->slot + DEC_SCSI_DMAREG );
+	volatile u32 *dmareg =
+		(volatile u32 *)KSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
 
-	memcpy((void *)(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
-	       (void *)KSEG0ADDR(vaddress), length);
+	memcpy((void *)KSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
+	       phys_to_virt(vaddress), length);
 
-	*dmareg = TC_ESP_DMAR_WRITE |
-		TC_ESP_DMA_ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE);
+	wmb();
+	*dmareg = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE);
 
 	iob();
 }
@@ -489,20 +516,19 @@ static void pmaz_dma_ints_on(struct NCR_
 {
 }
 
-static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+static void pmaz_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"
+	 * DMA_ST_WRITE means "move data from device to memory"
 	 * so when (write) is true, it actually means READ!
 	 */
-	if (write) {
+	if (write)
 		pmaz_dma_init_read(esp, addr, count);
-	} else {
+	else
 		pmaz_dma_init_write(esp, addr, count);
-	}
 }
 
 static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
 {
-	sp->SCp.ptr = (char *)KSEG0ADDR((sp->request_buffer));
+	sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
 }
diff -up --recursive --new-file linux-mips-2.4.20-20030112.macro/include/asm-mips/dec/ioasic.h linux-mips-2.4.20-20030112/include/asm-mips/dec/ioasic.h
--- linux-mips-2.4.20-20030112.macro/include/asm-mips/dec/ioasic.h	2003-01-16 01:13:18.000000000 +0000
+++ linux-mips-2.4.20-20030112/include/asm-mips/dec/ioasic.h	2003-01-17 00:59:53.000000000 +0000
@@ -3,7 +3,7 @@
  *
  *	DEC I/O ASIC access operations.
  *
- *	Copyright (C) 2000, 2002  Maciej W. Rozycki
+ *	Copyright (C) 2000, 2002, 2003  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -14,8 +14,11 @@
 #ifndef __ASM_DEC_IOASIC_H
 #define __ASM_DEC_IOASIC_H
 
+#include <linux/spinlock.h>
 #include <linux/types.h>
 
+extern spinlock_t ioasic_ssr_lock;
+
 extern volatile u32 *ioasic_base;
 
 static inline void ioasic_write(unsigned int reg, u32 v)
diff -up --recursive --new-file linux-mips-2.4.20-20030112.macro/include/asm-mips64/dec/ioasic.h linux-mips-2.4.20-20030112/include/asm-mips64/dec/ioasic.h
--- linux-mips-2.4.20-20030112.macro/include/asm-mips64/dec/ioasic.h	2002-05-14 02:57:37.000000000 +0000
+++ linux-mips-2.4.20-20030112/include/asm-mips64/dec/ioasic.h	2003-01-17 00:59:53.000000000 +0000
@@ -3,7 +3,7 @@
  *
  *	DEC I/O ASIC access operations.
  *
- *	Copyright (C) 2000, 2002  Maciej W. Rozycki
+ *	Copyright (C) 2000, 2002, 2003  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -14,8 +14,11 @@
 #ifndef __ASM_DEC_IOASIC_H
 #define __ASM_DEC_IOASIC_H
 
+#include <linux/spinlock.h>
 #include <linux/types.h>
 
+extern spinlock_t ioasic_ssr_lock;
+
 extern volatile u32 *ioasic_base;
 
 static inline void ioasic_write(unsigned int reg, u32 v)

---

From: Dave Airlie <[email-masked]>
Date: Mon, 20 Jan 2003 23:13:40 +0000 (GMT)

> be fairly easy to relax in the next step.

can someone try it on a 5000/200 if they have one also .. it's been a long
while since that code was written ... if it works on a PMAZ it'll probably
work on a 5000/200 anyways..

Dave.

-- 
David Airlie, Software Engineer
http://www.skynet.ie/~airlied / [email-masked]
pam_smb / Linux DecStation / Linux VAX / ILUG person

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 21 Jan 2003 16:59:56 +0100 (MET)

> work on a 5000/200 anyways..

 The "discrete" PMAZ-A is identical to the "integrated" one, so if one
works, the other does too.  Changes that affect the PMAZ-A are as follows: 

1. Use bus (physical) addresses everywhere, except when doing PIO copying
between host memory and the board's SRAM. 

2. An additional write barrier is added before triggering board's DMA
transfer from the board's SRAM (a nop for R3k). 

So they are minimal enough for a single run-time check to suffice. 

 Anyway, testing a current kernel on the /200 would be a good thing. 

  Maciej