summaryrefslogtreecommitdiff
path: root/sys/arch/arc/pica/picabus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/arc/pica/picabus.c')
-rw-r--r--sys/arch/arc/pica/picabus.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/sys/arch/arc/pica/picabus.c b/sys/arch/arc/pica/picabus.c
new file mode 100644
index 00000000000..f6058cf8b4d
--- /dev/null
+++ b/sys/arch/arc/pica/picabus.c
@@ -0,0 +1,323 @@
+/* $OpenBSD: picabus.c,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: tc.c,v 1.2 1995/03/08 00:39:05 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * Author: Per Fogelstrom. (Mips R4x00)
+ *
+ * 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/device.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+
+#include <arc/pica/pica.h>
+#include <arc/arc/arctype.h>
+
+struct pica_softc {
+ struct device sc_dv;
+ struct abus sc_bus;
+ struct pica_dev *sc_devs;
+};
+
+/* Definition of the driver for autoconfig. */
+int picamatch(struct device *, void *, void *);
+void picaattach(struct device *, struct device *, void *);
+int picaprint(void *, char *);
+
+struct cfattach pica_ca = {
+ sizeof(struct pica_softc), picamatch, picaattach
+};
+struct cfdriver pica_cd = {
+ NULL, "pica", DV_DULL, NULL, 0
+};
+
+void pica_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void pica_intr_disestablish __P((struct confargs *));
+caddr_t pica_cvtaddr __P((struct confargs *));
+int pica_matchname __P((struct confargs *, char *));
+int pica_iointr __P((void *));
+int pica_clkintr __P((unsigned, unsigned, unsigned, unsigned));
+
+extern int cputype;
+
+/*
+ * Interrupt dispatch table.
+ */
+struct pica_int_desc int_table[] = {
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 0 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 1 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 2 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 3 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 4 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 5 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 6 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 7 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 8 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 9 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 10 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 11 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 12 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 13 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 14 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 15 */
+};
+
+struct pica_dev {
+ struct confargs ps_ca;
+ u_int ps_mask;
+ intr_handler_t ps_handler;
+ void *ps_base;
+};
+#ifdef ACER_PICA_61
+struct pica_dev acer_pica_61_cpu[] = {
+ {{ "dallas_rtc",0, 0, },
+ 0, pica_intrnull, (void *)PICA_SYS_CLOCK, },
+ {{ "lpt", 1, 0, },
+ PICA_SYS_LB_IE_PAR1, pica_intrnull, (void *)PICA_SYS_PAR1, },
+ {{ "fdc", 2, 0, },
+ PICA_SYS_LB_IE_FLOPPY,pica_intrnull, (void *)PICA_SYS_FLOPPY, },
+ {{ NULL, 3, NULL, },
+ 0, pica_intrnull, (void *)NULL, },
+ {{ NULL, 4, NULL, },
+ 0, pica_intrnull, (void *)NULL, },
+ {{ "sonic", 5, 0, },
+ PICA_SYS_LB_IE_SONIC, pica_intrnull, (void *)PICA_SYS_SONIC, },
+ {{ "asc", 6, 0, },
+ PICA_SYS_LB_IE_SCSI, pica_intrnull, (void *)PICA_SYS_SCSI, },
+ {{ "pc", 7, 0, },
+ PICA_SYS_LB_IE_KBD, pica_intrnull, (void *)PICA_SYS_KBD, },
+ {{ "pms", 8, NULL, },
+ PICA_SYS_LB_IE_MOUSE, pica_intrnull, (void *)PICA_SYS_KBD, },
+ {{ "com", 9, 0, },
+ PICA_SYS_LB_IE_COM1, pica_intrnull, (void *)PICA_SYS_COM1, },
+ {{ "com", 10, 0, },
+ PICA_SYS_LB_IE_COM2, pica_intrnull, (void *)PICA_SYS_COM2, },
+ {{ NULL, -1, NULL, },
+ 0, NULL, (void *)NULL, },
+};
+#endif
+
+struct pica_dev *pica_cpu_devs[] = {
+ NULL, /* Unused */
+#ifdef ACER_PICA_61
+ acer_pica_61_cpu, /* Acer PICA */
+#else
+ NULL,
+#endif
+};
+int npica_cpu_devs = sizeof pica_cpu_devs / sizeof pica_cpu_devs[0];
+
+int local_int_mask = 0; /* Local interrupt enable mask */
+
+int
+picamatch(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 PICA. */
+ if (strcmp(ca->ca_name, pica_cd.cd_name) != 0)
+ return (0);
+
+ /* Make sure that unit exists. */
+ if (cf->cf_unit != 0 ||
+ cputype > npica_cpu_devs || pica_cpu_devs[cputype] == NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+picaattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct pica_softc *sc = (struct pica_softc *)self;
+ struct confargs *nca;
+ int i;
+
+ printf("\n");
+
+ /* keep our CPU device description handy */
+ sc->sc_devs = pica_cpu_devs[cputype];
+
+ /* set up interrupt handlers */
+ set_intr(INT_MASK_1, pica_iointr, 2);
+
+ sc->sc_bus.ab_dv = (struct device *)sc;
+ sc->sc_bus.ab_type = BUS_PICA;
+ sc->sc_bus.ab_intr_establish = pica_intr_establish;
+ sc->sc_bus.ab_intr_disestablish = pica_intr_disestablish;
+ sc->sc_bus.ab_cvtaddr = pica_cvtaddr;
+ sc->sc_bus.ab_matchname = pica_matchname;
+
+ /* Initialize PICA Dma */
+ picaDmaInit();
+
+ /* Try to configure each PICA 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, picaprint);
+ }
+}
+
+int
+picaprint(aux, pnp)
+ void *aux;
+ 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
+pica_cvtaddr(ca)
+ struct confargs *ca;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset);
+
+}
+
+void
+pica_intr_establish(ca, handler, val)
+ struct confargs *ca;
+ intr_handler_t handler;
+ void *val;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ int slot;
+
+ slot = ca->ca_slot;
+ if(slot == 0) { /* Slot 0 is special, clock */
+ set_intr(INT_MASK_4, pica_clkintr, 1);
+ }
+
+ if(int_table[slot].int_mask != 0) {
+ panic("pica intr already set");
+ }
+ else {
+ int_table[slot].int_mask = sc->sc_devs[slot].ps_mask;;
+ local_int_mask |= int_table[slot].int_mask;
+ int_table[slot].int_hand = handler;
+ int_table[slot].param = val;
+ }
+ out16(PICA_SYS_LB_IE, local_int_mask);
+}
+
+void
+pica_intr_disestablish(ca)
+ struct confargs *ca;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ int slot;
+
+ slot = ca->ca_slot;
+ if(slot = 0) { /* Slot 0 is special, clock */
+ }
+ else {
+ local_int_mask &= ~int_table[slot].int_mask;
+ int_table[slot].int_mask = 0;
+ int_table[slot].int_hand = pica_intrnull;
+ int_table[slot].param = (void *)NULL;
+ }
+}
+
+int
+pica_matchname(ca, name)
+ struct confargs *ca;
+ char *name;
+{
+ return (strcmp(name, ca->ca_name) == 0);
+}
+
+int
+pica_intrnull(val)
+ void *val;
+{
+ panic("uncaught PICA intr for slot %d\n", val);
+}
+
+/*
+ * Handle pica i/o interrupt.
+ */
+int
+pica_iointr(val)
+ void *val;
+{
+ int vector;
+
+ while((vector = inb(PVIS) >> 2) != 0) {
+ (*int_table[vector].int_hand)(int_table[vector].param);
+ }
+ return(~0); /* Dont reenable */
+}
+
+/*
+ * Handle pica interval clock interrupt.
+ */
+int
+pica_clkintr(mask, pc, statusReg, causeReg)
+ unsigned mask;
+ unsigned pc;
+ unsigned statusReg;
+ unsigned causeReg;
+{
+ struct clockframe cf;
+ int temp;
+
+ temp = inw(PICA_SYS_IT_STAT);
+ cf.pc = pc;
+ cf.sr = statusReg;
+ hardclock(&cf);
+
+ /* Re-enable clock interrupts */
+ splx(INT_MASK_4 | SR_INT_ENAB);
+
+ return(~INT_MASK_4); /* Keep clock interrupts enabled */
+}
+