summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/dev/pcctwo.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k/dev/pcctwo.c')
-rw-r--r--sys/arch/mvme88k/dev/pcctwo.c306
1 files changed, 152 insertions, 154 deletions
diff --git a/sys/arch/mvme88k/dev/pcctwo.c b/sys/arch/mvme88k/dev/pcctwo.c
index 7ad4c3abee1..4156a8f440e 100644
--- a/sys/arch/mvme88k/dev/pcctwo.c
+++ b/sys/arch/mvme88k/dev/pcctwo.c
@@ -1,210 +1,208 @@
+
+/* $OpenBSD: pcctwo.c,v 1.5 1998/12/15 05:52:30 smurph Exp $ */
+
+/*
+ * Copyright (c) 1995 Theo de Raadt
+ * All rights reserved.
+ *
+ * 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
+ * Theo de Raadt for Willowglen Singapore.
+ * 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.
+ */
+
+/*
+ * VME18x PCC2 chip
+ */
#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/tty.h>
#include <sys/uio.h>
+#include <sys/callout.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/fcntl.h>
#include <sys/device.h>
#include <machine/cpu.h>
#include <machine/autoconf.h>
+#include <dev/cons.h>
#include <mvme88k/dev/pcctworeg.h>
struct pcctwosoftc {
- struct device sc_dev;
- volatile struct pcc2reg *sc_pcc2reg;
+ struct device sc_dev;
+ void *sc_vaddr; /* PCC2 space */
+ void *sc_paddr;
+ struct pcctworeg *sc_pcc2; /* the actual registers */
};
-int pcctwomatch __P((struct device *, void *, void *));
-int pcctwoscan __P((struct device *, void *, void *));
-void pcctwoattach __P((struct device *, struct device *, void *));
-
+void pcctwoattach __P((struct device *, struct device *, void *));
+int pcctwomatch __P((struct device *, void *, void *));
#ifdef MVME187
void setupiackvectors __P((void));
#endif /* MVME187 */
-struct cfattach pcctwo_ca = {
- sizeof(struct pcctwosoftc), pcctwomatch, pcctwoattach
+struct cfattach pcctwo_ca = {
+ sizeof(struct pcctwosoftc), pcctwomatch, pcctwoattach
};
struct cfdriver pcctwo_cd = {
- NULL, "pcctwo", DV_DULL, 0
-};
+ NULL, "pcctwo", DV_DULL, 0
+};
+
+struct pcctworeg *sys_pcc2 = NULL;
-/*ARGSUSED*/
int
-pcctwomatch(struct device *parent, void *self, void *aux)
+pcctwomatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
{
- int ret;
- u_char id, rev;
- caddr_t base;
- struct confargs *ca = aux;
- struct cfdata *cf = self;
-
-#if 0
- if (cputyp != CPU_167 && cputyp != CPU_166
-#ifdef MVME187
- && cputyp != CPU_187
-#endif
- )
- {
- return 0;
- }
-#endif /* 0 */
- if (cputyp != CPU_187) {
- return 0;
- }
-
- /*
- * If bus or name do not match, fail.
- */
- if (ca->ca_bustype != BUS_MAIN ||
- strcmp(cf->cf_driver->cd_name, "pcctwo")) {
- return 0;
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
+ struct pcctworeg *pcc2;
+
+ /* Bomb if wrong cpu */
+ if (cputyp != CPU_187){
+ printf("==> pcctwo: wrong CPU type %x.\n", cputyp);
+ return (0);
}
- if ((base = (caddr_t)cf->cf_loc[0]) == (caddr_t)-1) {
- return 0;
+ pcc2 = (struct pcctworeg *)(IIOV(ca->ca_paddr) + PCC2_PCC2CHIP_OFF);
+ if (badvaddr(pcc2, 4) <= 0){
+ printf("==> pcctwo: failed address check.\n");
+ return (0);
}
-
- id = badpaddr(base, 1);
- rev = badpaddr(base + 1, 1);
-
- if (id != PCC2_CHIP_ID || rev != PCC2_CHIP_REV) {
- return 0;
+ if (pcc2->pcc2_chipid != PCC2_CHIPID){
+ printf("==> pcctwo: wrong chip id %x.\n", pcc2->pcc2_chipid);
+ return (0);
}
-
- ca->ca_size = PCC2_SIZE;
- ca->ca_paddr = base;
-
- return 1;
+ return (1);
}
int
-pcctwoprint(void *aux, char *parent)
+pcctwo_print(args, bus)
+ void *args;
+ const char *bus;
{
- struct confargs *ca = aux;
-
- /*
- * We call pcctwoprint() via config_attach(). Parent
- * will always be null and config_attach() would have already
- * printed "nvram0 at pcctwo0".
- */
- printf(" addr %x size %x", ca->ca_paddr, ca->ca_size);
- if (ca->ca_ipl != -1) {
- printf(" ipl %x", ca->ca_ipl);
- }
+ struct confargs *ca = args;
+ if (ca->ca_offset != -1)
+ printf(" offset 0x%x", ca->ca_offset);
+ if (ca->ca_ipl > 0)
+ printf(" ipl %d", ca->ca_ipl);
return (UNCONF);
}
-/*ARGSUSED*/
int
-pcctwoscan(struct device *parent, void *self, void *aux)
+pcctwo_scan(parent, child, args)
+ struct device *parent;
+ void *child, *args;
{
- struct confargs ca;
- struct cfdata *cf = self;
+ struct cfdata *cf = child;
struct pcctwosoftc *sc = (struct pcctwosoftc *)parent;
-
- /*
- * Pcctwoscan gets called by config_search() for each
- * child of parent (pcctwo) specified in ioconf.c.
- * Fill in the bus type to be PCCTWO and call the child's
- * match routine. If the child's match returns 1, then
- * we need to allocate device memory, set it in confargs
- * and call config_attach(). This, in turn, will call the
- * child's attach.
- */
-
- ca.ca_bustype = BUS_PCCTWO;
-
- if ((*cf->cf_attach->ca_match)(parent, cf, &ca) == 0)
- return 0;
-
- /*
- * The child would have fixed up ca to reflect what its
- * requirements are.
- */
-
- if (cf->cf_loc[2] != ca.ca_ipl) {
- printf("Changing ipl %x specified in ioconf.c to %x for %s\n",
- cf->cf_loc[2], ca.ca_ipl, cf->cf_driver->cd_name);
+ struct confargs *ca = args;
+ struct confargs oca;
+
+ if (parent->dv_cfdata->cf_driver->cd_indirect) {
+ printf(" indirect devices not supported\n");
+ return 0;
+ }
+
+ bzero(&oca, sizeof oca);
+ oca.ca_offset = cf->cf_loc[0];
+ oca.ca_ipl = cf->cf_loc[1];
+ if ((oca.ca_offset != (void*)-1) && ISIIOVA(sc->sc_vaddr + oca.ca_offset)) {
+ oca.ca_vaddr = sc->sc_vaddr + oca.ca_offset;
+ oca.ca_paddr = sc->sc_paddr + oca.ca_offset;
+ } else {
+ oca.ca_vaddr = (void *)-1;
+ oca.ca_paddr = (void *)-1;
}
-
- /*
- * If the size specified by the child is 0, don't map
- * any IO space, but pass in the address of pcc2reg as vaddr.
- * This is for clock and parallel port which don't have a
- * separate address space by themselves but use pcc2's register
- * block.
- */
- if (ca.ca_size == 0) {
- /*
- * pcc2regs addr
- */
-#if 0
- ca.ca_vaddr = ((struct confargs *)aux)->ca_vaddr;
-#endif /* 0 */
- ca.ca_vaddr = (caddr_t)sc->sc_pcc2reg;
-
- } else {
- ca.ca_vaddr = ca.ca_paddr;
- }
-
-#if 0
- ca.ca_parent = ((struct confargs *)aux)->ca_vaddr;
-#endif /* 0 */
- ca.ca_parent = (caddr_t)sc->sc_pcc2reg;
-
- /*
- * Call child's attach using config_attach().
- */
- config_attach(parent, cf, &ca, pcctwoprint);
- return 1;
+ oca.ca_bustype = BUS_PCCTWO;
+ oca.ca_master = (void *)sc->sc_pcc2;
+ oca.ca_name = cf->cf_driver->cd_name;
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+ config_attach(parent, cf, &oca, pcctwo_print);
+ return (1);
}
-/*
- * This function calls the match routine of the configured children
- * in turn. For each configured child, map the device address into
- * iomap space and then call config_attach() to attach the child.
- */
-
-/* ARGSUSED */
void
-pcctwoattach(struct device *parent, struct device *self, void *aux)
+pcctwoattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
{
- struct pcctwosoftc *sc = (struct pcctwosoftc *)self;
- struct confargs *ca = aux;
- caddr_t base;
-
- if (self->dv_unit > 0) {
- printf(" unsupported\n");
- return;
- }
-
- base = ca->ca_vaddr;
+ struct confargs *ca = args;
+ struct pcctwosoftc *sc = (struct pcctwosoftc *)self;
+ int i;
- printf(": PCCTWO id 0x%2x rev 0x%2x\n",
- *(u_char *)base, *((u_char *)base + 1));
+ if (sys_pcc2)
+ panic("pcc2 already attached!");
/*
- * mainbus driver would have mapped Pcc2 at base. Save
- * the address in pcctwosoftc.
+ * since we know ourself to land in intiobase land,
+ * we must adjust our address
*/
- sc->sc_pcc2reg = (struct pcc2reg *)base;
+ sc->sc_paddr = ca->ca_paddr;
+ sc->sc_vaddr = (void *)IIOV(sc->sc_paddr);
+ sc->sc_pcc2 = (struct pcctworeg *)(sc->sc_vaddr + PCC2_PCC2CHIP_OFF);
+ sys_pcc2 = sc->sc_pcc2;
+
+ printf(": rev %d\n", sc->sc_pcc2->pcc2_chiprev);
+
+ sc->sc_pcc2->pcc2_vecbase = PCC2_VECBASE;
+ sc->sc_pcc2->pcc2_genctl |= PCC2_GENCTL_IEN; /* global irq enable */
/*
* Set pcc2intr_mask and pcc2intr_ipl.
*/
- pcc2intr_ipl = (u_char *)&(sc->sc_pcc2reg->pcc2_ipl);
- pcc2intr_mask = (u_char *)&(sc->sc_pcc2reg->pcc2_imask);
+ pcc2intr_ipl = (u_char *)&(sc->sc_pcc2->pcc2_ipl);
+ pcc2intr_mask = (u_char *)&(sc->sc_pcc2->pcc2_mask);
#ifdef MVME187
- /*
- * Get mappings for iack vectors. This doesn't belong here
- * but is more closely related to pcc than anything I can
- * think of. (could probably do it in locore.s).
- */
-
+ printf("setting interrupt ack vectors.\n");
setupiackvectors();
#endif /* MVME187 */
- (void)config_search(pcctwoscan, self, aux);
+ config_search(pcctwo_scan, self, args);
+}
+
+/*
+ * PCC2 interrupts land in a PCC2_NVEC sized hole starting at PCC2_VECBASE
+ */
+int
+pcctwointr_establish(vec, ih)
+ int vec;
+ struct intrhand *ih;
+{
+ if (vec >= PCC2_NVEC) {
+ printf("pcctwo: illegal vector: 0x%x\n", vec);
+ panic("pcctwointr_establish");
+ }
+ return (intr_establish(PCC2_VECBASE+vec, ih));
}