summaryrefslogtreecommitdiff
path: root/sys/arch/arc/algor
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>1997-03-12 19:17:04 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>1997-03-12 19:17:04 +0000
commit63e70c1bce393b8e92002c93029eeb1a67f80fcc (patch)
tree1ffb854bd1045ee6f0999913b74a788a879368bc /sys/arch/arc/algor
parentfd5a4621c16957714dbc7335eb5afa6b0f28b29e (diff)
Addition of support for a PCI based Vr4300 board from Algorithmics, the P-4032.
Changes to io macros were done to handle sparse bus addressing dynamically. This is a first cut (rough).
Diffstat (limited to 'sys/arch/arc/algor')
-rw-r--r--sys/arch/arc/algor/algor.h111
-rw-r--r--sys/arch/arc/algor/algorbus.c438
2 files changed, 549 insertions, 0 deletions
diff --git a/sys/arch/arc/algor/algor.h b/sys/arch/arc/algor/algor.h
new file mode 100644
index 00000000000..bfe02f65104
--- /dev/null
+++ b/sys/arch/arc/algor/algor.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: algor.h,v 1.1 1997/03/12 19:16:33 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _ALGOR_H_
+#define _ALGOR_H_ 1
+
+/*
+ * P-4032's Physical address space
+ */
+
+#define P4032_PHYS_MIN 0x00000000 /* 256 Meg */
+#define P4032_PHYS_MAX 0x0fffffff
+
+/*
+ * Memory map
+ */
+
+#define P4032_PHYS_MEMORY_START 0x00000000
+#define P4032_PHYS_MEMORY_END 0x0fffffff /* 256 Meg in 2 slots */
+
+/*
+ * I/O map
+ */
+
+#define P4032_V96x 0xbef00000 /* PCI Bus bridge ctrlregs */
+
+#define P4032_CLOCK 0xbff00000 /* RTC clock ptr reg */
+#define P4032_KEYB 0xbff10000 /* PC Keyboard controller */
+#define P4032_LED 0xbff20010 /* 4 Char LED display */
+#define P4032_LCD 0xbff30000 /* LCD option display */
+#define P4032_GPIO 0xbff40000 /* General purpose I/O */
+#define P4032_GPIO_IACK 0xbff50000 /* General purpose I/O Iack */
+#define P4032_FPY 0xbff807c0 /* Floppy controller */
+#define P4032_COM1 0xbff80fe0
+#define P4032_COM2 0xbff80be0
+#define P4032_IMR 0xbff90000 /* Int mask reg (wr) */
+#define P4032_IRR 0xbff90000 /* Int request reg (rd) */
+#define P4032_EIRR 0xbff90004 /* Error int request reg (rd) */
+#define P4032_ICR 0xbff90004 /* Int clear register (wr) */
+#define P4032_PCIIMR 0xbff90008 /* PCI Int mask reg (wr) */
+#define P4032_PCIIRR 0xbff90008 /* PCI Int req reg (rd) */
+#define P4032_IXR0 0xbff9000c /* Int crossbar register 0 */
+#define P4032_IXR1 0xbff90010 /* Int crossbar register 0 */
+#define P4032_IXR2 0xbff90014 /* Int crossbar register 0 */
+
+/*
+ * Interrupt controller interrupt masks
+ */
+
+#define P4032_IM_RTC 0x80 /* RT Clock */
+#define P4032_IM_GPIO 0x40 /* General purpose I/O */
+#define P4032_IM_CENTR 0x20 /* Centronics paralell port */
+#define P4032_IM_COM2 0x10 /* Serial port 2 */
+#define P4032_IM_COM1 0x08 /* Serial port 1 */
+#define P4032_IM_KEYB 0x04 /* PC Keyboard IFC */
+#define P4032_IM_FPY 0x02 /* Floppy disk */
+#define P4032_IM_PCI 0x01 /* PCI controller */
+
+#define P4032_IRR_BER 0x04 /* Bus error */
+#define P4032_IRR_PFAIL 0x02 /* Power fail */
+#define P4032_IRR_DBG 0x01 /* Debug switch */
+
+#define P4032_PCI_IRQ3 0x80 /* PCI interrupt request 3 */
+#define P4032_PCI_IRQ2 0x40 /* PCI interrupt request 2 */
+#define P4032_PCI_IRQ1 0x20 /* PCI interrupt request 1 */
+#define P4032_PCI_IRQ0 0x10 /* PCI interrupt request 0 */
+#define P4032_FPY_DMA 0x08 /* FPY "DMA" interrupt request */
+/*
+ * Interrupt vector descriptor for device on pica bus.
+ */
+struct algor_int_desc {
+ int int_mask; /* Mask used in PICA_SYS_LB_IE */
+ intr_handler_t int_hand; /* Interrupt handler */
+ void *param; /* Parameter to send to handler */
+ int spl_mask; /* Spl mask for interrupt */
+};
+
+int algor_intrnull __P((void *));
+
+#endif /* _ALGOR_H_ */
diff --git a/sys/arch/arc/algor/algorbus.c b/sys/arch/arc/algor/algorbus.c
new file mode 100644
index 00000000000..b6fc840471a
--- /dev/null
+++ b/sys/arch/arc/algor/algorbus.c
@@ -0,0 +1,438 @@
+/* $OpenBSD: algorbus.c,v 1.1 1997/03/12 19:16:35 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Per Fogelstrom.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/intr.h>
+#include <machine/autoconf.h>
+
+#include <arc/arc/arctype.h>
+#include <arc/algor/algor.h>
+
+#include <dev/ic/mc146818reg.h>
+
+struct algor_softc {
+ struct device sc_dv;
+ struct abus sc_bus;
+ struct algor_dev *sc_devs;
+};
+
+/* Definition of the driver for autoconfig. */
+int algormatch(struct device *, void *, void *);
+void algorattach(struct device *, struct device *, void *);
+int algorprint(void *, const char *);
+
+struct cfattach algor_ca = {
+ sizeof(struct algor_softc), algormatch, algorattach
+};
+struct cfdriver algor_cd = {
+ NULL, "algor", DV_DULL, NULL, 0
+};
+
+void algor_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void algor_intr_disestablish __P((struct confargs *));
+caddr_t algor_cvtaddr __P((struct confargs *));
+int algor_matchname __P((struct confargs *, char *));
+int algor_iointr __P((unsigned, struct clockframe *));
+int algor_clkintr __P((unsigned, struct clockframe *));
+int algor_errintr __P((unsigned, struct clockframe *));
+
+extern int cputype;
+
+int p4032_imask = 0;
+int p4032_ixr = 0;
+
+/*
+ * Interrupt dispatch table.
+ */
+static struct algor_int_desc int_table[] = {
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 0 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 1 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 2 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 3 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 4 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 5 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 6 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 7 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 8 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 9 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 10 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 11 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 12 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 13 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 14 */
+ {0, algor_intrnull, (void *)NULL, 0 }, /* 15 */
+};
+#define NUM_INT_SLOTS (sizeof(int_table) / sizeof(struct algor_int_desc))
+
+struct algor_dev {
+ struct confargs ps_ca;
+ u_int8_t ps_mask;
+ u_int8_t ps_ipl;
+ u_int16_t ps_route;
+ intr_handler_t ps_handler;
+ void *ps_base;
+};
+struct algor_dev algor_4032_cpu[] = {
+ {{ "dallas_rtc", 0, 0, },
+ P4032_IM_RTC, IPL_CLOCK, 0xc000, algor_intrnull, (void *)P4032_CLOCK, },
+ {{ "com", 1, 0, },
+ P4032_IM_COM1, IPL_TTY, 0x00c0, algor_intrnull, (void *)P4032_COM1, },
+ {{ "com", 2, 0, },
+ P4032_IM_COM2, IPL_TTY, 0x0300, algor_intrnull, (void *)P4032_COM2, },
+ {{ NULL, -1, NULL, },
+ 0, 0x0000, NULL, (void *)NULL, },
+};
+#define NUM_ALGOR_DEVS (sizeof(algor_4032_cpu) / sizeof(struct algor_dev))
+
+/* IPL routing values */
+static int ipxrtab[] = {
+ 0x000000, /* IPL_BIO */
+ 0x555555, /* IPL_NET */
+ 0xaaaaaa, /* IPL_TTY */
+ 0xffffff, /* IPL_CLOCK */
+};
+
+
+
+struct algor_dev *algor_cpu_devs[] = {
+ NULL, /* Unused */
+ NULL, /* Unused */
+ NULL, /* Unused */
+ NULL, /* Unused */
+ NULL, /* Unused */
+ NULL, /* Unused */
+ algor_4032_cpu, /* 6 = ALGORITHMICS R4032 Board */
+ NULL,
+};
+int nalgor_cpu_devs = sizeof algor_cpu_devs / sizeof algor_cpu_devs[0];
+
+int
+algormatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+ struct confargs *ca = aux;
+
+ /* Make sure that we're looking for a ALGORITHMICS BUS */
+ if (strcmp(ca->ca_name, algor_cd.cd_name) != 0)
+ return (0);
+
+ /* Make sure that unit exists. */
+ if (cf->cf_unit != 0 ||
+ cputype > nalgor_cpu_devs || algor_cpu_devs[cputype] == NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+algorattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct algor_softc *sc = (struct algor_softc *)self;
+ struct confargs *nca;
+ int i;
+
+ printf("\n");
+
+ /* keep our CPU device description handy */
+ sc->sc_devs = algor_cpu_devs[cputype];
+
+ /* set up interrupt handlers */
+ set_intr(INT_MASK_1, algor_iointr, 2);
+ set_intr(INT_MASK_4, algor_errintr, 0);
+
+ sc->sc_bus.ab_dv = (struct device *)sc;
+ sc->sc_bus.ab_type = BUS_ALGOR;
+ sc->sc_bus.ab_intr_establish = algor_intr_establish;
+ sc->sc_bus.ab_intr_disestablish = algor_intr_disestablish;
+ sc->sc_bus.ab_cvtaddr = algor_cvtaddr;
+ sc->sc_bus.ab_matchname = algor_matchname;
+
+ /* Try to configure each ALGOR attached device */
+ for (i = 0; sc->sc_devs[i].ps_ca.ca_slot >= 0; i++) {
+
+ if(sc->sc_devs[i].ps_ca.ca_name == NULL)
+ continue; /* Empty slot */
+
+ nca = &sc->sc_devs[i].ps_ca;
+ nca->ca_bus = &sc->sc_bus;
+
+ /* Tell the autoconfig machinery we've found the hardware. */
+ config_found(self, nca, algorprint);
+ }
+}
+
+int
+algorprint(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct confargs *ca = aux;
+
+ if (pnp)
+ printf("%s at %s", ca->ca_name, pnp);
+ printf(" slot %ld offset 0x%lx", ca->ca_slot, ca->ca_offset);
+ return (UNCONF);
+}
+
+caddr_t
+algor_cvtaddr(ca)
+ struct confargs *ca;
+{
+ struct algor_softc *sc = algor_cd.cd_devs[0];
+
+ return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset);
+
+}
+
+void
+algor_intr_establish(ca, handler, arg)
+ struct confargs *ca;
+ intr_handler_t handler;
+ void *arg;
+{
+ struct algor_softc *sc = algor_cd.cd_devs[0];
+ int slot = ca->ca_slot;
+ struct algor_dev *dev = &sc->sc_devs[slot];
+ int ipl = dev->ps_ipl;
+
+ if(int_table[slot].int_mask != 0) {
+ panic("algor intr already set");
+ }
+ else {
+ int_table[slot].int_mask = dev->ps_mask;
+ int_table[slot].int_hand = handler;
+ int_table[slot].param = arg;
+ }
+ p4032_ixr |= ipxrtab[ipl] & dev->ps_route;
+ outb(P4032_IXR0, p4032_ixr);
+ outb(P4032_IXR1, p4032_ixr >> 8);
+ outb(P4032_IXR2, p4032_ixr >> 16);
+
+ if(slot == 0) { /* Slot 0 is special, clock */
+ set_intr(INT_MASK_0 << ipl, algor_clkintr, ipl + 1);
+ }
+ else {
+ set_intr(INT_MASK_0 << ipl, algor_iointr, ipl + 1);
+ }
+
+ p4032_imask |= dev->ps_mask;
+ outb(P4032_IMR, p4032_imask);
+ outb(P4032_PCIIMR, p4032_imask >> 8);
+}
+
+void *
+algor_pci_intr_establish(ih, level, handler, arg, name)
+ int level;
+ intr_handler_t handler;
+ void *arg;
+ void *name;
+{
+ int imask;
+ int route;
+ int slot;
+
+ if(level < IPL_BIO || level >= IPL_CLOCK) {
+ panic("pci intr: ipl level out of range");
+ }
+ if(ih < 0 || ih >= 4) {
+ panic("pci intr: irq out of range");
+ }
+
+ imask = (0x1000 << ih);
+ route = (0x30000 << ih+ih);
+
+ slot = NUM_INT_SLOTS;
+ while(slot > 0) {
+ if(int_table[slot].int_mask == 0)
+ break;
+ slot--;
+ }
+ if(slot < 0) {
+ panic("pci intr: out of int slots");
+ }
+
+ int_table[slot].int_mask = imask;
+ int_table[slot].int_hand = handler;
+ int_table[slot].param = arg;
+
+ p4032_ixr |= ipxrtab[level] & route;
+ outb(P4032_IXR0, p4032_ixr);
+ outb(P4032_IXR1, p4032_ixr >> 8);
+ outb(P4032_IXR2, p4032_ixr >> 16);
+
+ set_intr(INT_MASK_0 << level, algor_iointr, level + 1);
+
+ p4032_imask |= imask;
+ outb(P4032_IMR, p4032_imask);
+ outb(P4032_PCIIMR, p4032_imask >> 8);
+
+ return((void *)slot);
+}
+
+void
+algor_intr_disestablish(ca)
+ struct confargs *ca;
+{
+ struct algor_softc *sc = algor_cd.cd_devs[0];
+
+ int slot;
+
+ slot = ca->ca_slot;
+ p4032_imask &= ~int_table[slot].int_mask;
+ outb(P4032_IMR, p4032_imask);
+ outb(P4032_PCIIMR, p4032_imask >> 8);
+
+ if(slot = 0) { /* Slot 0 is special, clock */
+ }
+ else {
+ int_table[slot].int_mask = 0;
+ int_table[slot].int_hand = algor_intrnull;
+ int_table[slot].param = (void *)NULL;
+ }
+}
+
+void
+algor_pci_intr_disestablish(cookie)
+ void *cookie;
+{
+ int slot = (int)cookie;
+
+ p4032_imask &= ~int_table[slot].int_mask;
+ outb(P4032_IMR, p4032_imask);
+ outb(P4032_PCIIMR, p4032_imask >> 8);
+
+ int_table[slot].int_mask = 0;
+ int_table[slot].int_hand = algor_intrnull;
+ int_table[slot].param = (void *)NULL;
+}
+
+int
+algor_matchname(ca, name)
+ struct confargs *ca;
+ char *name;
+{
+ return (strcmp(name, ca->ca_name) == 0);
+}
+
+int
+algor_intrnull(val)
+ void *val;
+{
+ panic("uncaught ALGOR intr for slot %d\n", val);
+}
+
+/*
+ * Handle algor i/o interrupt.
+ */
+int
+algor_iointr(mask, cf)
+ unsigned mask;
+ struct clockframe *cf;
+{
+ int i;
+ int pend;
+
+ pend = inb(P4032_IRR);
+ pend |= inb(P4032_PCIIRR) << 8;
+ pend &= p4032_imask;
+
+ for(i = 0; i < NUM_INT_SLOTS; i++) {
+ if(pend & int_table[i].int_mask)
+ (*int_table[i].int_hand)(int_table[i].param);
+ }
+ return(~0); /* Dont reenable */
+}
+
+/*
+ * Handle algor interval clock interrupt.
+ */
+int
+algor_clkintr(mask, cf)
+ unsigned mask;
+ struct clockframe *cf;
+{
+ int temp;
+
+ /* Ack clock interrupt */
+ outb(P4032_CLOCK, MC_REGC);
+ (void) inb(P4032_CLOCK + 4);
+
+ hardclock(cf);
+
+ /* Re-enable clock interrupts */
+ splx(INT_MASK_0 << IPL_CLOCK | SR_INT_ENAB);
+
+ return(~(INT_MASK_0 << IPL_CLOCK)); /* Keep clock interrupts enabled */
+}
+
+/*
+ * Handle algor interval clock interrupt.
+ */
+int
+algor_errintr(mask, cf)
+ unsigned mask;
+ struct clockframe *cf;
+{
+ int why;
+
+ why = inb(P4032_EIRR);
+
+ if(why & P4032_IRR_BER) {
+ printf("Bus error interrupt\n");
+ outb(P4032_ICR, P4032_IRR_BER);
+ }
+ if(why & P4032_IRR_PFAIL) {
+ printf("Power failure!\n");
+ }
+ if(why & P4032_IRR_DBG) {
+ printf("Debug switch\n");
+ outb(P4032_ICR, P4032_IRR_DBG);
+#ifdef DEBUG
+ mdbpanic();
+#else
+ printf("Not DEBUG compiled, sorry!\n");
+#endif
+ }
+ return(~0);
+}