summaryrefslogtreecommitdiff
path: root/sys/arch/alpha/pci/apecs.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/alpha/pci/apecs.c
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/alpha/pci/apecs.c')
-rw-r--r--sys/arch/alpha/pci/apecs.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/sys/arch/alpha/pci/apecs.c b/sys/arch/alpha/pci/apecs.c
new file mode 100644
index 00000000000..7648f2cdd7e
--- /dev/null
+++ b/sys/arch/alpha/pci/apecs.c
@@ -0,0 +1,271 @@
+/* $NetBSD: apecs.c,v 1.3 1995/08/03 01:16:47 cgd Exp $ */
+
+/*
+ * Copyright (c) 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <vm/vm.h>
+
+#include <machine/autoconf.h>
+#include <machine/pio.h>
+#include <machine/rpb.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <alpha/isa/isa_dma.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <alpha/pci/pci_chipset.h>
+#include <alpha/pci/apecsreg.h>
+
+int apecsmatch __P((struct device *, void *, void *));
+void apecsattach __P((struct device *, struct device *, void *));
+
+struct cfdriver apecscd = {
+ NULL, "apecs", apecsmatch, apecsattach, DV_DULL, sizeof(struct device)
+};
+
+static int apecsprint __P((void *, char *pnp));
+
+#ifdef DEC_2100_A50
+extern void pci_2100_a50_pickintr __P((void));
+#endif
+
+#define REGVAL(r) (*(int32_t *)phystok0seg(r))
+
+static int nsgmapent = 1024;
+static vm_offset_t sgmap_pci_base = 0x800000;
+/*static */struct sgmapent *sgmap;
+static char /* * */ sgbitmap[1024 / NBBY];
+
+int
+apecsmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct cfdata *cf = match;
+ struct confargs *pa = aux;
+
+ /* XXX */
+
+ return (1);
+}
+
+/*
+ * Set up the chipset's function pointers.
+ */
+void
+apecs_init()
+{
+ int pass2_epic;
+
+ pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
+
+ isadma_fcns = &apecs_isadma_fcns;
+ isa_pio_fcns = &apecs_pio_fcns;
+ if (!pass2_epic)
+ pci_cs_fcns = &apecs_p1e_cs_fcns;
+ else
+ pci_cs_fcns = &apecs_p2e_cs_fcns;
+}
+
+void
+apecsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct confargs *ca = aux;
+ struct confargs nca;
+ int pass2_comanche, widemem, pass2_epic;
+
+ pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
+ widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
+ pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
+
+ sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
+ M_DEVBUF, M_WAITOK);
+
+ printf(": DECchip %s Core Logic chipset\n",
+ widemem ? "21072" : "21071");
+ printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
+ self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
+ printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
+ /* XXX print bcache size */
+
+ if (!pass2_epic)
+ printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
+
+ /* set up the chipset's functions */
+ apecs_init();
+
+ switch (hwrpb->rpb_type) {
+#if defined(DEC_2100_A50)
+ case ST_DEC_2100_A50:
+ pci_2100_a50_pickintr();
+ break;
+#endif
+ default:
+ panic("apecsattach: shouldn't be here, really...");
+ }
+
+ /* attach the PCI bus that hangs off of it... */
+ nca.ca_name = "pci";
+ nca.ca_slot = 0;
+ nca.ca_offset = 0;
+ nca.ca_bus = NULL;
+ if (!config_found(self, &nca, apecsprint))
+ panic("apecsattach: couldn't attach PCI bus");
+}
+
+static int
+apecsprint(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+ register struct confargs *ca = aux;
+
+ if (pnp)
+ printf("%s at %s", ca->ca_name, pnp);
+ return (UNCONF);
+}
+
+vm_offset_t /* XXX? */
+apecs_sgmap_alloc(va, npg, nocross, waitok)
+ caddr_t va;
+ int npg;
+ vm_size_t nocross;
+ int waitok;
+{
+ int s;
+ int base, i, stride;
+
+#ifdef DIAGNOSTIC
+ /* Quick sanity checks. */
+ if ((vm_offset_t)va & PGOFSET)
+ panic("apecs_sgmap_alloc: va not page aligned");
+ if ((nocross & (nocross - 1)) != 0 || nocross == 0)
+ panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
+ if (npg <= 0)
+ panic("apecs_sgmap_alloc: not allocating anything");
+ if (npg > nsgmapent)
+ panic("apecs_sgmap_alloc: insane allocation");
+ if (ptoa(npg) > nocross)
+ panic("apecs_sgmap_alloc: must cross boundary");
+#endif
+
+ stride = atop(nocross);
+#ifdef DIAGNOSTIC
+ if (stride > nsgmapent)
+ panic("apecs_sgmap_alloc: cheesy implementation loses");
+#endif
+
+top:
+ s = splhigh();
+ for (base = 0; base < nsgmapent; base += stride) {
+ for (i = base; i < base + npg; i++)
+ if (isset(sgbitmap, i))
+ goto nextstride;
+ break;
+nextstride:
+ }
+ if (base < nsgmapent) /* found a free chunk, claim it */
+ for (i = base; i < base + npg; i++)
+ setbit(sgbitmap, i);
+ splx(s);
+
+ if (base >= nsgmapent) { /* didn't find a free chunk */
+ if (!waitok)
+ return 0;
+ tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
+ goto top;
+ }
+
+ for (i = base; i < base + npg; i++) {
+#ifdef DIAGNOSTIC
+ if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
+ panic("apecs_sgmap_alloc: unallocated entry valid");
+#endif
+ sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
+ va += PAGE_SIZE;
+ }
+
+ /* Invalidate old cached entries. */
+ REGVAL(EPIC_TBIA) = 1;
+
+ /* Return the PCI address. */
+ return (ptoa(base) + sgmap_pci_base);
+}
+
+void
+apecs_sgmap_dealloc(pa, npg)
+ vm_offset_t pa;
+ int npg;
+{
+ int i, pfn;
+
+#ifdef DIAGNOSTIC
+ /* Quick sanity checks. */
+ if (pa & PGOFSET)
+ panic("apecs_sgmap_dealloc: pa not page aligned");
+ if (npg <= 0)
+ panic("apecs_sgmap_dealloc: not deallocating anything");
+ if (npg > nsgmapent)
+ panic("apecs_sgmap_dealloc: insane deallocation");
+#endif
+
+ pfn = atop(pa - sgmap_pci_base);
+#ifdef DIAGNOSTIC
+ /* Bounds check the deallocation range. Paranoid about wraparound. */
+ if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
+ panic("apecs_sgmap_dealloc: pa out of range (%s)",
+ pfn < 0 ? "too low" : "too high");
+#endif
+
+ for (i = 0; i < npg; i++) {
+#ifdef DIAGNOSTIC
+ /* Make sure it's actually allocated. */
+ if (isclr(sgbitmap, i + pfn))
+ panic("apecs_sgmap_dealloc: multiple frees: entry %d",
+ i + pfn);
+#endif
+
+ /* Clear the entries and the allocation map bits. */
+ clrbit(sgbitmap, i + pfn);
+ sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
+ }
+
+ /* Invalidate old cached entries. */
+ REGVAL(EPIC_TBIA) = 1;
+
+ /* Wake up anybody waiting for map entries. */
+ wakeup(&sgmap);
+}