Module Name:    src
Committed By:   thorpej
Date:           Tue Jan 16 07:07:00 UTC 2024

Modified Files:
        src/sys/arch/hp300/dev: dio.c dma.c dmavar.h
        src/sys/arch/hp300/hp300: autoconf.c
        src/sys/arch/hp300/include: intr.h

Log Message:
Fix computation of the appropriate auto-vector interrupt level to use
for the DMA controller by tracking all of the DIO devices that have
"ISRPRI_BIO" interrupt handlers, and finding the highest auto-vector
level among them and informing the DMA controller.

Previously, in a post-flattening world, the DMA controller was always
told to interrupt at lev5, which is fine I guess although definitely not
ideal, but would not work on aaaancient HP320 Rev A DMA boards.  To that
effect, print a warning if a Rev B DMA board ends up at ipl != 3 (we can't
differentiate between a Rev A and a Rev B board).


To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/sys/arch/hp300/dev/dio.c
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/hp300/dev/dma.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/hp300/dev/dmavar.h
cvs rdiff -u -r1.111 -r1.112 src/sys/arch/hp300/hp300/autoconf.c
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/hp300/include/intr.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/hp300/dev/dio.c
diff -u src/sys/arch/hp300/dev/dio.c:1.42 src/sys/arch/hp300/dev/dio.c:1.43
--- src/sys/arch/hp300/dev/dio.c:1.42	Tue Jan 16 03:44:43 2024
+++ src/sys/arch/hp300/dev/dio.c	Tue Jan 16 07:06:59 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: dio.c,v 1.42 2024/01/16 03:44:43 thorpej Exp $	*/
+/*	$NetBSD: dio.c,v 1.43 2024/01/16 07:06:59 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dio.c,v 1.42 2024/01/16 03:44:43 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dio.c,v 1.43 2024/01/16 07:06:59 thorpej Exp $");
 
 #define	_M68K_INTR_PRIVATE
 
@@ -78,6 +78,9 @@ static int	diosubmatch(device_t, cfdata_
 CFATTACH_DECL_NEW(dio, sizeof(struct dio_softc),
     diomatch, dioattach, NULL, NULL);
 
+static LIST_HEAD(, hp300_intrhand) dio_dma_users =
+    LIST_HEAD_INITIALIZER(dio_dma_users);
+
 static int
 diomatch(device_t parent, cfdata_t cf, void *aux)
 {
@@ -280,18 +283,40 @@ dio_devinfo(struct dio_attach_args *da, 
 }
 
 /*
+ * Enumerate the list of DMA controller users (the HPIB and SCSI
+ * controllers, essentially), and calculate what the highest
+ * auto-vector level used by those devices is.  Then tell the DMA
+ * controller to interrupt at that level.
+ */
+static void
+dio_dma_users_changed(void)
+{
+	struct hp300_intrhand *ih;
+	int ipl = 0;
+
+	LIST_FOREACH(ih, &dio_dma_users, ih_dio_link) {
+		KASSERT(ih->ih_super.ih_isrpri == ISRPRI_BIO);
+		if (ih->ih_super.ih_ipl > ipl) {
+			ipl = ih->ih_super.ih_ipl;
+		}
+	}
+	dmaupdateipl(ipl);
+}
+
+/*
  * Establish an interrupt handler for a DIO device.
  */
 void *
 dio_intr_establish(int (*func)(void *), void *arg, int ipl, int isrpri)
 {
-	void *ih;
+	struct hp300_intrhand *ih;
 
 	ih = intr_establish(func, arg, ipl, isrpri);
 
-	/* XXX XXX XXX */
-	if (isrpri == IPL_BIO)
-		dmacomputeipl();
+	if (ih != NULL && isrpri == ISRPRI_BIO) {
+		LIST_INSERT_HEAD(&dio_dma_users, ih, ih_dio_link);
+		dio_dma_users_changed();
+	}
 
 	return ih;
 }
@@ -302,14 +327,18 @@ dio_intr_establish(int (*func)(void *), 
 void
 dio_intr_disestablish(void *arg)
 {
-	struct m68k_intrhand *ih = arg;
-	int isrpri = ih->ih_isrpri;
+	struct hp300_intrhand *ih = arg;
+	int isrpri = ih->ih_super.ih_isrpri;
+
+	if (isrpri == ISRPRI_BIO) {
+		LIST_REMOVE(ih, ih_dio_link);
+	}
 
 	intr_disestablish(arg);
 
-	/* XXX XXX XXX */
-	if (isrpri == IPL_BIO)
-		dmacomputeipl();
+	if (isrpri == ISRPRI_BIO) {
+		dio_dma_users_changed();
+	}
 }
 
 /*

Index: src/sys/arch/hp300/dev/dma.c
diff -u src/sys/arch/hp300/dev/dma.c:1.46 src/sys/arch/hp300/dev/dma.c:1.47
--- src/sys/arch/hp300/dev/dma.c:1.46	Tue Jan 16 05:48:28 2024
+++ src/sys/arch/hp300/dev/dma.c	Tue Jan 16 07:06:59 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: dma.c,v 1.46 2024/01/16 05:48:28 thorpej Exp $	*/
+/*	$NetBSD: dma.c,v 1.47 2024/01/16 07:06:59 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 #include "opt_m68k_arch.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dma.c,v 1.46 2024/01/16 05:48:28 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dma.c,v 1.47 2024/01/16 07:06:59 thorpej Exp $");
 
 #include <machine/hp300spu.h>	/* XXX param.h includes cpu.h */
 
@@ -263,19 +263,30 @@ dmaattach(device_t parent, device_t self
  * for the DMA controller.
  */
 void
-dmacomputeipl(void)
+dmaupdateipl(int ipl)
 {
 	struct dma_softc *sc = dma_softc;
 
-	if (sc->sc_ih != NULL)
+	if (sc->sc_ih != NULL && sc->sc_ipl == ipl) {
+		/* No change. */
+		return;
+	}
+
+	if (sc->sc_ih != NULL) {
 		intr_disestablish(sc->sc_ih);
+	}
+
+	if ((sc->sc_ipl == ipl) == 0) {
+		/* Don't hook up a new handler. */
+		return;
+	}
 
-	/*
-	 * Our interrupt level must be as high as the highest
-	 * device using DMA (i.e. splbio).
-	 */
-	sc->sc_ipl = PSLTOIPL(ipl2psl_table[IPL_VM]);
 	sc->sc_ih = intr_establish(dmaintr, sc, sc->sc_ipl, ISRPRI_BIO);
+	if (sc->sc_type == DMA_B && sc->sc_ipl != 3) {
+		aprint_error_dev(sc->sc_dev,
+		    "WARNING: IPL set to %d on maybe-rev. A card!\n",
+		    sc->sc_ipl);
+	}
 }
 
 int

Index: src/sys/arch/hp300/dev/dmavar.h
diff -u src/sys/arch/hp300/dev/dmavar.h:1.14 src/sys/arch/hp300/dev/dmavar.h:1.15
--- src/sys/arch/hp300/dev/dmavar.h:1.14	Mon Apr 28 20:23:19 2008
+++ src/sys/arch/hp300/dev/dmavar.h	Tue Jan 16 07:06:59 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: dmavar.h,v 1.14 2008/04/28 20:23:19 martin Exp $	*/
+/*	$NetBSD: dmavar.h,v 1.15 2024/01/16 07:06:59 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -98,5 +98,5 @@ void	dmago(int, char *, int, int);
 void	dmastop(int);
 void	dmafree(struct dmaqueue *);
 int	dmareq(struct dmaqueue *);
-void	dmacomputeipl(void);
+void	dmaupdateipl(int);
 #endif /* _KERNEL */

Index: src/sys/arch/hp300/hp300/autoconf.c
diff -u src/sys/arch/hp300/hp300/autoconf.c:1.111 src/sys/arch/hp300/hp300/autoconf.c:1.112
--- src/sys/arch/hp300/hp300/autoconf.c:1.111	Sun Jan 15 06:19:46 2023
+++ src/sys/arch/hp300/hp300/autoconf.c	Tue Jan 16 07:07:00 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: autoconf.c,v 1.111 2023/01/15 06:19:46 tsutsui Exp $	*/
+/*	$NetBSD: autoconf.c,v 1.112 2024/01/16 07:07:00 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 2002 The NetBSD Foundation, Inc.
@@ -88,7 +88,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.111 2023/01/15 06:19:46 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.112 2024/01/16 07:07:00 thorpej Exp $");
 
 #include "dvbox.h"
 #include "gbox.h"
@@ -102,6 +102,8 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v
 #include "com_frodo.h"
 #include "dcm.h"
 
+#define	_M68K_INTR_PRIVATE
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/buf.h>
@@ -274,6 +276,30 @@ mainbussearch(device_t parent, cfdata_t 
 }
 
 /*
+ * hp300 systems need to track all DIO interrupt handlers on a single
+ * list in order to compute the auto-vector interrupt level the DMA
+ * controller should interrupt at.  So, we provide a custom allocator
+ * for the common interrupt dispatch code that allocates us handles
+ * with linkage for this list.
+ */
+static struct m68k_intrhand *
+hp300_ih_alloc(int km_flag)
+{
+	return kmem_zalloc(sizeof(struct hp300_intrhand), km_flag);
+}
+
+static void
+hp300_ih_free(struct m68k_intrhand *ih)
+{
+	kmem_free(ih, sizeof(struct hp300_intrhand));
+}
+ 
+static const struct m68k_ih_allocfuncs hp300_ih_allocfuncs = { 
+	.alloc = hp300_ih_alloc,
+	.free  = hp300_ih_free,
+}; 
+
+/*
  * Determine the device configuration for the running system.
  */
 void
@@ -291,7 +317,7 @@ cpu_configure(void)
 	(void)splhigh();
 
 	/* Initialize the interrupt handlers. */
-	intr_init();
+	m68k_intr_init(&hp300_ih_allocfuncs);
 
 	if (config_rootfound("mainbus", NULL) == NULL)
 		panic("no mainbus found");

Index: src/sys/arch/hp300/include/intr.h
diff -u src/sys/arch/hp300/include/intr.h:1.37 src/sys/arch/hp300/include/intr.h:1.38
--- src/sys/arch/hp300/include/intr.h:1.37	Tue Jan 16 03:44:44 2024
+++ src/sys/arch/hp300/include/intr.h	Tue Jan 16 07:07:00 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.h,v 1.37 2024/01/16 03:44:44 thorpej Exp $	*/
+/*	$NetBSD: intr.h,v 1.38 2024/01/16 07:07:00 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 2024 The NetBSD Foundation, Inc.
@@ -60,6 +60,13 @@
 
 #include <m68k/intr.h>
 
+#ifdef _M68K_INTR_PRIVATE
+struct hp300_intrhand {
+	struct m68k_intrhand       ih_super;
+	LIST_ENTRY(hp300_intrhand) ih_dio_link;
+};
+#endif
+
 /* These spl calls are _not_ to be used by machine-independent code. */
 #define	splhil()	splraise1()
 #define	splkbd()	splhil()
@@ -68,12 +75,6 @@
  * Interface wrappers.
  */
 
-static inline void
-intr_init(void)
-{
-	m68k_intr_init(NULL);
-}
-
 static inline void *
 intr_establish(int (*func)(void *), void *arg, int ipl, int isrpri)
 {

Reply via email to