Subject: psycho patch
To: None <port-sparc64@netbsd.org>
From: Jason Wright <jason@thought.net>
List: port-sparc64
Date: 09/01/2001 19:34:23
This patch allows psycho to match on the SUNW,Ultra-1-Engine and to
get through autoconf apprently ok (it's based on similiar logic to
ultralinux, using the "compatible" as well as "name" prom properties).

It also corrects some incorrect register offsets in the psychoreg
structure (verified against ultralinux, too and by experimentation).
And also prints the relevant registers in psycho_bus_{a|b} (the
ue registers are not as interesting as the pcierror registers).

Finally, it cleans up one debugging statement (output looks a touch
better, imo).

In reading psycho.c, I noticed what I think is an error, too.
psycho_set_intr() is called with ipl = 15, which is then passed
to intr_establish().  The intrhand array has 15 elements in it,
so, trying to access intrhand[15] seems like bad form.  I'm not
sure what's intended here, but I don't think the current code
is correct (or my reading of it is totally wrong... which is
certainly possible).

Lastly, this patch seems to mostly work (the onboard hme interrupts
and such, autoconf works, etc).  I haven't tested thoroughly under
NetBSD except to make sure the patch is syntactically correct.

--Jason L. Wright

[btw, this is like the third time I've tried to submit this...
someone filtering mail sent from cvs.openbsd.org -> mail.netbsd.org ?]

Index: psycho.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/psycho.c,v
retrieving revision 1.34
diff -u -r1.34 psycho.c
--- psycho.c	2001/07/20 00:07:13	1.34
+++ psycho.c	2001/09/01 20:58:55
@@ -132,6 +132,18 @@
         sizeof(struct psycho_softc), psycho_match, psycho_attach
 };
 
+struct psycho_type {
+	char *p_name;
+	int p_type;
+} psycho_types[] = {
+	{ "SUNW,sabre",		PSYCHO_MODE_SABRE	},
+	{ "pci180e,a000",	PSYCHO_MODE_SABRE	},
+	{ "pci108e,a001",	PSYCHO_MODE_SABRE	},
+	{ "SUNW,psycho",	PSYCHO_MODE_PSYCHO	},
+	{ "pci108e,8000",	PSYCHO_MODE_PSYCHO	},
+	{ NULL, 0 }
+};
+
 /*
  * "sabre" is the UltraSPARC IIi onboard UPA to PCI bridge.  It manages a
  * single PCI bus and does not have a streaming buffer.  It often has an APB
@@ -181,13 +193,21 @@
 	void		*aux;
 {
 	struct mainbus_attach_args *ma = aux;
-	char *model = getpropstring(ma->ma_node, "model");
+	struct psycho_type *ptype;
+	char *str;
 
 	/* match on a name of "pci" and a sabre or a psycho */
-	if (strcmp(ma->ma_name, ROM_PCI_NAME) == 0 &&
-	    (strcmp(model, ROM_SABRE_MODEL) == 0 ||
-	     strcmp(model, ROM_PSYCHO_MODEL) == 0))
-		return (1);
+	if (strcmp(ma->ma_name, ROM_PCI_NAME) != 0)
+		return (0);
+
+	for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
+		str = getpropstring(ma->ma_node, "model");
+		if (strcmp(str, ptype->p_name) == 0)
+			return (1);
+		str = getpropstring(ma->ma_node, "compatible");
+		if (strcmp(str, ptype->p_name) == 0)
+			return (1);
+	}
 
 	return (0);
 }
@@ -218,7 +238,7 @@
 	u_int64_t csr;
 	int psycho_br[2], n;
 	struct pci_ctl *pci_ctl;
-	char *model = getpropstring(ma->ma_node, "model");
+	struct psycho_type *ptype;
 
 	printf("\n");
 
@@ -230,13 +250,20 @@
 	 * call the model-specific initialisation routine.
 	 */
 
-	if (strcmp(model, ROM_SABRE_MODEL) == 0)
-		sc->sc_mode = PSYCHO_MODE_SABRE;
-	else if (strcmp(model, ROM_PSYCHO_MODEL) == 0)
-		sc->sc_mode = PSYCHO_MODE_PSYCHO;
-	else
-		panic("psycho_attach: unknown model %s?", model);
+	for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
+		char *str;
 
+		str = getpropstring(ma->ma_node, "model");
+		if (strcmp(str, ptype->p_name) == 0)
+			break;
+		str = getpropstring(ma->ma_node, "compatible");
+		if (strcmp(str, ptype->p_name) == 0)
+			break;
+	}
+	if (ptype->p_name == NULL)
+		panic("psycho_attach: unknown model?");
+	sc->sc_mode = ptype->p_type;
+
 	/*
 	 * The psycho gets three register banks:
 	 * (0) per-PBM configuration and status registers
@@ -302,10 +329,10 @@
 	sc->sc_ign = 0x7c0; /* APB IGN is always 0x7c */
 	if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
 		sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
+
+	printf("%s: impl %d, version %d: ign %x ", ptype->p_name,
+	    PSYCHO_GCSR_IMPL(csr), PSYCHO_GCSR_VERS(csr), sc->sc_ign);
 
-	printf("%s: impl %d, version %d: ign %x ",
-		model, PSYCHO_GCSR_IMPL(csr), PSYCHO_GCSR_VERS(csr),
-		sc->sc_ign);
 	/*
 	 * Match other psycho's that are already configured against
 	 * the base physical address. This will be the same for a
@@ -600,7 +627,8 @@
 
 	panic("%s: PCI bus A error AFAR %llx AFSR %llx\n",
 		sc->sc_dev.dv_xname, 
-		(long long)regs->psy_ue_afar, (long long)regs->psy_ue_afsr);
+		(long long)regs->psy_pcictl[0].pci_afar,
+		(long long)regs->psy_pcictl[0].pci_afsr);
 	return (1);
 }
 static int 
@@ -616,7 +644,8 @@
 
 	panic("%s: PCI bus B error AFAR %llx AFSR %llx\n",
 		sc->sc_dev.dv_xname, 
-		(long long)regs->psy_ue_afar, (long long)regs->psy_ue_afsr);
+		(long long)regs->psy_pcictl[1].pci_afar,
+		(long long)regs->psy_pcictl[1].pci_afsr);
 	return (1);
 }
 static int 
@@ -992,10 +1021,10 @@
 		/* Enable the interrupt */
 		intrmap |= INTMAP_V;
 		DPRINTF(PDB_INTR, ("; addr of intrmapptr = %p", intrmapptr));
-		DPRINTF(PDB_INTR, ("; writing intrmap = %016qx\n",
+		DPRINTF(PDB_INTR, ("; writing intrmap = %016qx",
 			(unsigned long long)intrmap));
 		*intrmapptr = intrmap;
-		DPRINTF(PDB_INTR, ("; reread intrmap = %016qx",
+		DPRINTF(PDB_INTR, ("; reread intrmap = %016qx\n",
 			(unsigned long long)(intrmap = *intrmapptr)));
 	}
 	return (ih);
Index: psychoreg.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/psychoreg.h,v
retrieving revision 1.7
diff -u -r1.7 psychoreg.h
--- psychoreg.h	2001/07/20 00:07:13	1.7
+++ psychoreg.h	2001/09/01 20:58:57
@@ -170,12 +170,13 @@
 
 	struct pci_ctl {
 		u_int64_t	pci_csr;	/* PCI a/b control/status register */	/* 1fe.0000.2000,4000 */
+		u_int64_t	pad;
 		u_int64_t	pci_afsr;	/* PCI a/b AFSR register */		/* 1fe.0000.2010,4010 */
 		u_int64_t	pci_afar;	/* PCI a/b AFAR register */		/* 1fe.0000.2018,4018 */
 		u_int64_t	pci_diag;	/* PCI a/b diagnostic register */	/* 1fe.0000.2020,4020 */
 		u_int64_t	pci_tasr;	/* PCI target address space reg (IIi)*/	/* 1fe.0000.2028,4028 */
 
-		u_int64_t	pad12[251];
+		u_int64_t	pad12[250];
 
 		/* This is really the IOMMU's, not the PCI bus's */
 		struct iommu_strbuf pci_strbuf;						/* 1fe.0000.2800-210 */