diff --git a/obio/esp.c b/obio/esp.c
index 6580436..0cb1106 100644
--- a/obio/esp.c
+++ b/obio/esp.c
@@ -103,6 +103,21 @@ __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.60 2021/02/22 05:23:36 rin Exp $");
 #include <mac68k/obio/espvar.h>
 #include <mac68k/obio/obiovar.h>
 
+#undef ESP_DREQ_DEBUG
+#define	ESP_DREQ_DEBUG
+
+#ifdef ESP_DREQ_DEBUG
+#include <sys/evcnt.h>
+#define	ESP_EVCNT_ATTACH(name)						\
+    static struct evcnt esp_ev_##name =					\
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "esp", #name);		\
+    EVCNT_ATTACH_STATIC(esp_ev_##name)
+#define	ESP_EVCNT_INCR(name)	esp_ev_##name.ev_count++
+ESP_EVCNT_ATTACH(dreq0);
+ESP_EVCNT_ATTACH(dreq1);
+ESP_EVCNT_ATTACH(spurious);
+#endif
+
 static int	espmatch(device_t, cfdata_t, void *);
 static void	espattach(device_t, device_t, void *);
 
@@ -144,6 +159,7 @@ static int	esp_iosb_have_dreq(struct esp_softc *);
 int (*esp_have_dreq)(struct esp_softc *);
 
 static struct esp_softc *esp0, *esp1;
+static int esp_ack_intr;
 
 static struct ncr53c9x_glue esp_glue = {
 	.gl_read_reg = esp_read_reg,
@@ -182,7 +198,6 @@ espattach(device_t parent, device_t self, void *aux)
 	bus_addr_t		addr;
 	unsigned long		reg_offset;
 	int			quick = 0, avdma = 0;
-	uint8_t			irq_mask;	/* mask for clearing IRQ */
 	extern vaddr_t		SCSIBase;
 
 	sc->sc_dev = self;
@@ -257,7 +272,7 @@ dafb_dreq:	bst = oa->oa_tag;
 
 		esc->sc_reg = (volatile uint8_t *)SCSIBase;
 		via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc);
-		irq_mask = V2IF_SCSIIRQ;
+		esp_ack_intr = 1;
 		switch (reg_offset) {
 		case 0x10000:
 			/* From the Q650 developer's note */
@@ -276,7 +291,7 @@ dafb_dreq:	bst = oa->oa_tag;
 
 		esc->sc_reg = (volatile uint8_t *)SCSIBase + 0x402;
 		via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL);
-		irq_mask = 0;
+		esp_ack_intr = 0;
 		sc->sc_freq = 25000000;
 	}
 
@@ -342,10 +357,10 @@ dafb_dreq:	bst = oa->oa_tag;
 	/*
 	 * Configure interrupts.
 	 */
-	if (irq_mask) {
+	if (esp_ack_intr) {
 		via2_reg(vPCR) = 0x22;
-		via2_reg(vIFR) = irq_mask;
-		via2_reg(vIER) = 0x80 | irq_mask;
+		via2_reg(vIFR) = V2IF_SCSIIRQ;
+		via2_reg(vIER) = 0x80 | V2IF_SCSIIRQ;
 	}
 
 	/*
@@ -693,8 +708,18 @@ esp_dafb_have_dreq(struct esp_softc *esc)
 static int
 esp_iosb_have_dreq(struct esp_softc *esc)
 {
+#ifdef ESP_DREQ_DEBUG
+	int val = via2_reg(vIFR) & V2IF_SCSIDRQ;
+
+	if (val)
+		ESP_EVCNT_INCR(dreq1);
+	else
+		ESP_EVCNT_INCR(dreq0);
+	return val;
+#else
 
 	return via2_reg(vIFR) & V2IF_SCSIDRQ;
+#endif
 }
 
 static volatile int espspl = -1;
@@ -957,6 +982,14 @@ gotintr:
 		printf("g!\n");
 	}
 #endif
+	/*
+	 * Ack DREQ if we can exclusively use it.
+	 *
+	 * Otherwise, a spurious interrupt may occur, but it cannot
+	 * cause serious problems.
+	 */
+	if (esp_ack_intr)
+		via2_reg(vIFR) = V2IF_SCSIDRQ;
 	/*
 	 * We have been called from the MI ncr53c9x_intr() handler,
 	 * which protects itself against multiple invocation with a
@@ -978,6 +1011,11 @@ esp_intr(void *sc)
 	if (esc->sc_reg[NCR_STAT * 16] & 0x80) {
 		ncr53c9x_intr((struct ncr53c9x_softc *)esp0);
 	}
+#ifdef ESP_DREQ_DEBUG
+	else {
+		ESP_EVCNT_INCR(spurious);
+	}
+#endif
 }
 
 static void

By admin

Leave a Reply

Your email address will not be published.