summaryrefslogtreecommitdiff
path: root/sys/arch/mvmeppc/pci
diff options
context:
space:
mode:
authorSteve Murphree <smurph@cvs.openbsd.org>2001-06-26 21:58:11 +0000
committerSteve Murphree <smurph@cvs.openbsd.org>2001-06-26 21:58:11 +0000
commit416f561c78b0eca90fdb484e72a96080b0825dca (patch)
treed310db0254b85229b90b9d90e79cabfbbcb6101a /sys/arch/mvmeppc/pci
parent77682e0d8d22531ed2952aaab30aae7c69483b3d (diff)
Initial import of mvmeppc.
Diffstat (limited to 'sys/arch/mvmeppc/pci')
-rw-r--r--sys/arch/mvmeppc/pci/mpcpcibr.c666
-rw-r--r--sys/arch/mvmeppc/pci/pchb.c106
-rw-r--r--sys/arch/mvmeppc/pci/pci_machdep.h93
-rw-r--r--sys/arch/mvmeppc/pci/pcib.c143
-rw-r--r--sys/arch/mvmeppc/pci/pcibrvar.h56
-rw-r--r--sys/arch/mvmeppc/pci/raven.c600
6 files changed, 1664 insertions, 0 deletions
diff --git a/sys/arch/mvmeppc/pci/mpcpcibr.c b/sys/arch/mvmeppc/pci/mpcpcibr.c
new file mode 100644
index 00000000000..65166225d51
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/mpcpcibr.c
@@ -0,0 +1,666 @@
+/* $OpenBSD: mpcpcibr.c,v 1.1 2001/06/26 21:57:56 smurph Exp $ */
+
+/*
+ * Copyright (c) 2001 Steve Murphree, Jr.
+ *
+ * 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 for RTMX Inc
+ * by Per Fogelstrom, Opsycon AB.
+ * 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.
+ *
+ */
+
+/*
+ * Motorola 'Raven' PCI BUS Bridge driver.
+ * specialized hooks for different config methods.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+
+#include <machine/autoconf.h>
+#include <machine/bat.h>
+#include <machine/bus.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <mvmeppc/pci/pcibrvar.h>
+#include <mvmeppc/dev/ravenreg.h>
+
+extern vm_map_t phys_map;
+
+int mpcpcibrmatch __P((struct device *, void *, void *));
+void mpcpcibrattach __P((struct device *, struct device *, void *));
+
+void mpc_attach_hook __P((struct device *, struct device *,
+ struct pcibus_attach_args *));
+int mpc_bus_maxdevs __P((void *, int));
+pcitag_t mpc_make_tag __P((void *, int, int, int));
+void mpc_decompose_tag __P((void *, pcitag_t, int *, int *, int *));
+pcireg_t mpc_conf_read __P((void *, pcitag_t, int));
+void mpc_conf_write __P((void *, pcitag_t, int, pcireg_t));
+
+int mpc_intr_map __P((void *, pcitag_t, int, int, pci_intr_handle_t *));
+const char *mpc_intr_string __P((void *, pci_intr_handle_t));
+void *mpc_intr_establish __P((void *, pci_intr_handle_t,
+ int, int (*func)(void *), void *, char *));
+void mpc_intr_disestablish __P((void *, void *));
+int mpc_ether_hw_addr __P((struct ppc_pci_chipset *, u_int8_t *));
+
+void
+mpc_cfg_write_1( struct pcibr_config *cp, u_int32_t reg, u_int8_t val);
+void
+mpc_cfg_write_2( struct pcibr_config *cp, u_int32_t reg, u_int16_t val);
+void
+mpc_cfg_write_4( struct pcibr_config *cp, u_int32_t reg, u_int32_t val);
+
+u_int8_t
+mpc_cfg_read_1( struct pcibr_config *cp, u_int32_t reg);
+
+u_int16_t
+mpc_cfg_read_2( struct pcibr_config *cp, u_int32_t reg);
+
+u_int32_t
+mpc_cfg_read_4( struct pcibr_config *cp, u_int32_t reg);
+
+struct cfattach mpcpcibr_ca = {
+ sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
+};
+
+struct cfdriver mpcpcibr_cd = {
+ NULL, "mpcpcibr", DV_DULL,
+};
+
+static int mpcpcibrprint __P((void *, const char *pnp));
+
+struct pcibr_config mpc_config;
+
+/*
+ * config types
+ * bit meanings
+ * 0 - standard cf8/cfc type configurations,
+ * sometimes the base addresses for these are different
+ * 1 - Config Method #2 configuration - uni-north
+ *
+ * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
+ */
+
+struct powerpc_bus_dma_tag pci_bus_dma_tag = {
+ NULL,
+ _bus_dmamap_create,
+ _bus_dmamap_destroy,
+ _bus_dmamap_load,
+ _bus_dmamap_load_mbuf,
+ _bus_dmamap_load_uio,
+ _bus_dmamap_load_raw,
+ _bus_dmamap_unload,
+ _bus_dmamap_sync,
+ _bus_dmamem_alloc,
+ _bus_dmamem_free,
+ _bus_dmamem_map,
+ _bus_dmamem_unmap,
+ _bus_dmamem_mmap
+};
+
+int
+mpcpcibrmatch(parent, match, aux)
+struct device *parent;
+void *match, *aux;
+{
+ struct confargs *ca = aux;
+ int found = 0;
+
+ /* We must be a child of the raven device */
+ if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "raven") != 0)
+ return (0);
+#if 0
+ if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
+ return (0);
+#endif
+ return 1;
+}
+
+int pci_map_a = 0;
+void
+mpcpcibrattach(parent, self, aux)
+struct device *parent, *self;
+void *aux;
+{
+ struct pcibr_softc *sc = (struct pcibr_softc *)self;
+ struct confargs *ca = aux;
+ struct pcibr_config *lcp;
+ struct pcibus_attach_args pba;
+ int map, node;
+ char *bridge;
+ int of_node = 0;
+
+ lcp = sc->sc_pcibr = &mpc_config;
+
+ /*
+ addbatmap(RAVEN_V_PCI_MEM_SPACE, RAVEN_P_PCI_MEM_SPACE, BAT_I);
+ */
+ sc->sc_membus_space = prep_mem_space_tag;
+ sc->sc_iobus_space = prep_io_space_tag;
+
+ lcp->lc_pc.pc_conf_v = lcp;
+ lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
+ lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
+ lcp->lc_pc.pc_make_tag = mpc_make_tag;
+ lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
+ lcp->lc_pc.pc_conf_read = mpc_conf_read;
+ lcp->lc_pc.pc_conf_write = mpc_conf_write;
+ lcp->lc_pc.pc_ether_hw_addr = mpc_ether_hw_addr;
+ lcp->lc_iot = &sc->sc_iobus_space;
+ lcp->lc_memt = &sc->sc_membus_space;
+
+ lcp->ioh_cf8 = PREP_CONFIG_ADD;
+ lcp->ioh_cfc = PREP_CONFIG_DAT;
+
+ lcp->config_type = 0;
+
+ lcp->lc_pc.pc_intr_v = lcp;
+ lcp->lc_pc.pc_intr_map = mpc_intr_map;
+ lcp->lc_pc.pc_intr_string = mpc_intr_string;
+ lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
+ lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;
+
+ printf(": Raven, Revision 0x%x.\n",
+ mpc_cfg_read_1(lcp, RAVEN_PCI_REVID));
+ bridge = "RAVEN";
+ pba.pba_dmat = &pci_bus_dma_tag;
+
+ pba.pba_busname = "pci";
+ pba.pba_iot = &sc->sc_iobus_space;
+ pba.pba_memt = &sc->sc_membus_space;
+ pba.pba_pc = &lcp->lc_pc;
+ pba.pba_bus = 0;
+/*
+ pba.pba_flags = PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED;
+*/
+#if 1
+ /* set up prep environment */
+ *(unsigned int *)RAVEN_MSADD0 = RAVEN_MSADD0_PREP;
+ *(unsigned int *)RAVEN_MSOFF0 = RAVEN_MSOFF0_PREP;
+ *(unsigned int *)RAVEN_MSADD1 = RAVEN_MSADD1_PREP;
+ *(unsigned int *)RAVEN_MSOFF1 = RAVEN_MSOFF1_PREP;
+ *(unsigned int *)RAVEN_MSADD2 = RAVEN_MSADD2_PREP;
+ *(unsigned int *)RAVEN_MSOFF2 = RAVEN_MSOFF2_PREP;
+ *(unsigned int *)RAVEN_MSADD3 = RAVEN_MSADD3_PREP;
+ *(unsigned int *)RAVEN_MSOFF3 = RAVEN_MSOFF3_PREP;
+
+ /* set up PCI local bus */
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSADD0, RAVEN_PCI_PSADD0_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSOFF0, RAVEN_PCI_PSOFF0_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSADD1, RAVEN_PCI_PSADD1_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSOFF1, RAVEN_PCI_PSOFF1_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSADD2, RAVEN_PCI_PSADD2_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSOFF2, RAVEN_PCI_PSOFF2_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSADD3, RAVEN_PCI_PSADD3_VAL);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_PSOFF3, RAVEN_PCI_PSOFF3_VAL);
+
+ /* set up VME -> PCI local bus */
+
+ mpc_cfg_write_4(lcp, 0x100, 0x0);
+ mpc_cfg_write_4(lcp, 0x114, 0x0);
+ mpc_cfg_write_4(lcp, 0x128, 0x0);
+ mpc_cfg_write_4(lcp, 0x13C, 0x0);
+
+ mpc_cfg_write_4(lcp, 0xF00, 0x0);
+ mpc_cfg_write_4(lcp, 0xF14, 0x0);
+ mpc_cfg_write_4(lcp, 0xF28, 0x0);
+ mpc_cfg_write_4(lcp, 0xF3C, 0x0);
+#endif
+ /* enable mem and io mapping, and bus master */
+ mpc_cfg_write_2(lcp, RAVEN_PCI_CMD,
+ RAVEN_CMD_IOSP|RAVEN_CMD_MEMSP|RAVEN_CMD_MASTR);
+
+ config_found(self, &pba, mpcpcibrprint);
+}
+
+static int
+mpcpcibrprint(aux, pnp)
+void *aux;
+const char *pnp;
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if (pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+ return (UNCONF);
+}
+
+/*
+ * Get PCI physical address from given viritual address.
+ * XXX Note that cross page boundarys are *not* garantueed to work!
+ */
+#if 0
+vm_offset_t
+vtophys(p)
+void *p;
+{
+ vm_offset_t pa;
+ vm_offset_t va;
+
+ va = (vm_offset_t)p;
+ if ((vm_offset_t)va < VM_MIN_KERNEL_ADDRESS) {
+ pa = va;
+ } else {
+ pmap_extract(vm_map_pmap(phys_map), va, (paddr_t *)&pa);
+ }
+ return (pa | ((pci_map_a == 1) ? RAVEN_PCI_CPUMEM : 0 ));
+}
+
+#else
+vm_offset_t
+vtophys(p)
+ void *p;
+{
+ vm_offset_t pa;
+ vm_offset_t va;
+ extern int segment8_mapped;
+ extern int segmentC_mapped;
+
+ va = (vm_offset_t)p;
+ /* This crap gets maped by bats 1:1 */
+ if ((vm_offset_t)va < VM_MIN_KERNEL_ADDRESS) {
+ pa = va;
+ } else if (segment8_mapped && (va >= 0x80000000 && va < 0x90000000)) {
+ pa = va;
+ } else if (segmentC_mapped && (va >= 0xC0000000 && va < 0xD0000000)) {
+ pa = va;
+ } else if (pmap_extract(pmap_kernel(), va, &pa))
+ return pa;
+ return va;
+}
+#endif
+
+void
+mpc_attach_hook(parent, self, pba)
+struct device *parent, *self;
+struct pcibus_attach_args *pba;
+{
+}
+
+int
+mpc_ether_hw_addr(p, ethaddr)
+struct ppc_pci_chipset *p;
+u_int8_t *ethaddr;
+{
+ printf("mpc_ether_hw_addr not supported\n");
+ return (0);
+}
+
+int
+mpc_bus_maxdevs(cpv, busno)
+void *cpv;
+int busno;
+{
+ return (32);
+}
+
+#define BUS_SHIFT 16
+#define DEVICE_SHIFT 11
+#define FNC_SHIFT 8
+
+pcitag_t
+mpc_make_tag(cpv, bus, dev, fnc)
+void *cpv;
+int bus, dev, fnc;
+{
+ return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
+}
+
+void
+mpc_decompose_tag(cpv, tag, busp, devp, fncp)
+void *cpv;
+pcitag_t tag;
+int *busp, *devp, *fncp;
+{
+ if (busp != NULL)
+ *busp = (tag >> BUS_SHIFT) & 0xff;
+ if (devp != NULL)
+ *devp = (tag >> DEVICE_SHIFT) & 0x1f;
+ if (fncp != NULL)
+ *fncp = (tag >> FNC_SHIFT) & 0x7;
+}
+
+static u_int32_t
+mpc_gen_config_reg(cpv, tag, offset)
+void *cpv;
+pcitag_t tag;
+int offset;
+{
+ struct pcibr_config *cp = cpv;
+ unsigned int bus, dev, fcn;
+ u_int32_t reg;
+ /*
+ static int spin = 0;
+ while (spin > 85);
+ spin++;
+ */
+
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+
+ if (cp->config_type & 1) {
+ /* Config Mechanism #2 */
+ if (bus == 0) {
+ if (dev < 11) {
+ return 0xffffffff;
+ }
+ /*
+ * Need to do config type 0 operation
+ * 1 << (11?+dev) | fcn << 8 | reg
+ * 11? is because pci spec states
+ * that 11-15 is reserved.
+ */
+ reg = 1 << (dev) | fcn << 8 | offset;
+
+ } else {
+ if (dev > 15) {
+ return 0xffffffff;
+ }
+ /*
+ * config type 1
+ */
+ reg = tag | offset | 1;
+
+ }
+ } else {
+ /* config mechanism #2, type 0
+ /* standard cf8/cfc config */
+ reg = 0x80000000 | tag | offset;
+
+ }
+ return reg;
+}
+
+/*#define DEBUG_CONFIG */
+pcireg_t
+mpc_conf_read(cpv, tag, offset)
+void *cpv;
+pcitag_t tag;
+int offset;
+{
+ struct pcibr_config *cp = cpv;
+
+ pcireg_t data;
+ u_int32_t reg;
+ int device;
+ int s;
+ int handle;
+ int daddr = 0;
+
+ if (offset & 3 || offset < 0 || offset >= 0x100) {
+ printf ("pci_conf_read: bad reg %x\n", offset);
+ return (~0);
+ }
+
+ reg = mpc_gen_config_reg(cpv, tag, offset);
+ /* if invalid tag, return -1 */
+ if (reg == 0xffffffff) {
+ return 0xffffffff;
+ }
+
+ if ((cp->config_type & 2) && (offset & 0x04)) {
+ daddr += 4;
+ }
+
+ s = splhigh();
+
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+ data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+
+ splx(s);
+#ifdef DEBUG_CONFIG
+ if (!((offset == 0) && (data == 0xffffffff))) {
+ unsigned int bus, dev, fcn;
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+ printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
+ offset);
+ printf(" daddr %x reg %x",daddr, reg);
+ printf(" data %x\n", data);
+ }
+#endif
+
+ return (data);
+}
+
+void
+mpc_conf_write(cpv, tag, offset, data)
+void *cpv;
+pcitag_t tag;
+int offset;
+pcireg_t data;
+{
+ struct pcibr_config *cp = cpv;
+ u_int32_t reg;
+ int s;
+ int handle;
+ int daddr = 0;
+
+ reg = mpc_gen_config_reg(cpv, tag, offset);
+
+ /* if invalid tag, return ??? */
+ if (reg == 0xffffffff) {
+ return;
+ }
+ if ((cp->config_type & 2) && (offset & 0x04)) {
+ daddr += 4;
+ }
+#ifdef DEBUG_CONFIG
+ {
+ unsigned int bus, dev, fcn;
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+ printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
+ dev, fcn, offset);
+ printf(" daddr %x reg %x",daddr, reg);
+ printf(" data %x\n", data);
+ }
+#endif
+
+ s = splhigh();
+
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+ bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+
+ splx(s);
+}
+
+
+int
+mpc_intr_map(lcv, bustag, buspin, line, ihp)
+void *lcv;
+pcitag_t bustag;
+int buspin, line;
+pci_intr_handle_t *ihp;
+{
+ struct pcibr_config *lcp = lcv;
+ pci_chipset_tag_t pc = &lcp->lc_pc;
+ int error = 0;
+ int route;
+ int lvl;
+ int device;
+
+ *ihp = -1;
+ if (buspin == 0) {
+ /* No IRQ used. */
+ error = 1;
+ } else if (buspin > 4) {
+ printf("mpc_intr_map: bad interrupt pin %d\n", buspin);
+ error = 1;
+ }
+
+ if (!error)
+ *ihp = line;
+ return error;
+}
+
+const char *
+mpc_intr_string(lcv, ih)
+void *lcv;
+pci_intr_handle_t ih;
+{
+ static char str[16];
+
+ sprintf(str, "irq %d", ih);
+ return (str);
+}
+
+typedef void *(intr_establish_t) __P((void *, pci_intr_handle_t,
+ int, int, int (*func)(void *), void *, char *));
+typedef void (intr_disestablish_t) __P((void *, void *));
+extern intr_establish_t *intr_establish_func;
+extern intr_disestablish_t *intr_disestablish_func;
+
+void *
+mpc_intr_establish(lcv, ih, level, func, arg, name)
+void *lcv;
+pci_intr_handle_t ih;
+int level;
+int (*func) __P((void *));
+void *arg;
+char *name;
+{
+ return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
+ name);
+}
+
+void
+mpc_intr_disestablish(lcv, cookie)
+void *lcv, *cookie;
+{
+ /* XXX We should probably do something clever here.... later */
+}
+
+u_int32_t
+pci_iack()
+{
+ /* do pci IACK cycle */
+ /* this should be bus allocated. */
+ volatile u_int8_t *iack = (u_int8_t *)RAVEN_PIACK;
+ u_int8_t val;
+
+ val = *iack;
+ return val;
+}
+
+void
+mpc_cfg_write_1(cp, reg, val)
+struct pcibr_config *cp;
+u_int32_t reg;
+u_int8_t val;
+{
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0,
+ RAVEN_REGOFFS(reg));
+ bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+void
+mpc_cfg_write_2(cp, reg, val)
+struct pcibr_config *cp;
+u_int32_t reg;
+u_int16_t val;
+{
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+void
+mpc_cfg_write_4(cp, reg, val)
+struct pcibr_config *cp;
+u_int32_t reg;
+u_int32_t val;
+{
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+u_int8_t
+mpc_cfg_read_1(cp, reg)
+struct pcibr_config *cp;
+u_int32_t reg;
+{
+ u_int8_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return (_v_);
+}
+
+u_int16_t
+mpc_cfg_read_2(cp, reg)
+struct pcibr_config *cp;
+u_int32_t reg;
+{
+ u_int16_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return (_v_);
+}
+
+u_int32_t
+mpc_cfg_read_4(cp, reg)
+struct pcibr_config *cp;
+u_int32_t reg;
+{
+ u_int32_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return (_v_);
+}
diff --git a/sys/arch/mvmeppc/pci/pchb.c b/sys/arch/mvmeppc/pci/pchb.c
new file mode 100644
index 00000000000..9c72921a720
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/pchb.c
@@ -0,0 +1,106 @@
+/* $NetBSD: pchb.c,v 1.4 2000/01/25 07:19:11 tsubai Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 REGENTS OR CONTRIBUTORS 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/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+int pchbmatch __P((struct device *, void *, void *));
+void pchbattach __P((struct device *, struct device *, void *));
+
+struct cfattach pchb_ca = {
+ sizeof(struct device), pchbmatch, pchbattach
+};
+
+struct cfdriver pchb_cd = {
+ NULL, "pchb", DV_DULL
+};
+
+int
+pchbmatch(parent, cf, aux)
+ struct device *parent;
+ void *cf;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ /*
+ * Match all known PCI host chipsets.
+ */
+ switch (PCI_VENDOR(pa->pa_id)) {
+
+ case PCI_VENDOR_MOT:
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_MOT_RAVEN:
+ return (1);
+ }
+ break;
+ }
+
+ return (0);
+}
+
+void
+pchbattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+ char devinfo[256];
+
+ printf("\n");
+
+ /*
+ * All we do is print out a description. Eventually, we
+ * might want to add code that does something that's
+ * possibly chipset-specific.
+ */
+
+ /*
+ pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
+ printf("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
+ PCI_REVISION(pa->pa_class));
+ */
+}
diff --git a/sys/arch/mvmeppc/pci/pci_machdep.h b/sys/arch/mvmeppc/pci/pci_machdep.h
new file mode 100644
index 00000000000..08181e158af
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/pci_machdep.h
@@ -0,0 +1,93 @@
+/* $OpenBSD: pci_machdep.h,v 1.1 2001/06/26 21:57:57 smurph Exp $ */
+
+/*
+ * Copyright (c) 1996 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.
+ */
+
+/*
+ * Machine-specific definitions for PCI autoconfiguration.
+ */
+
+/*
+ * Types provided to machine-independent PCI code
+ */
+typedef struct ppc_pci_chipset *pci_chipset_tag_t;
+typedef u_long pcitag_t;
+typedef u_long pci_intr_handle_t;
+
+/*
+ * ppc-specific PCI structure and type definitions.
+ * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
+ */
+struct ppc_pci_chipset {
+ void *pc_conf_v;
+ void (*pc_attach_hook) __P((struct device *,
+ struct device *, struct pcibus_attach_args *));
+ int (*pc_bus_maxdevs) __P((void *, int));
+ pcitag_t (*pc_make_tag) __P((void *, int, int, int));
+ void (*pc_decompose_tag) __P((void *, pcitag_t, int *,
+ int *, int *));
+ pcireg_t (*pc_conf_read) __P((void *, pcitag_t, int));
+ void (*pc_conf_write) __P((void *, pcitag_t, int, pcireg_t));
+
+ void *pc_intr_v;
+ int (*pc_intr_map) __P((void *, pcitag_t, int, int,
+ pci_intr_handle_t *));
+ const char *(*pc_intr_string) __P((void *, pci_intr_handle_t));
+ void *(*pc_intr_establish) __P((void *, pci_intr_handle_t,
+ int, int (*)(void *), void *, char *));
+ void (*pc_intr_disestablish) __P((void *, void *));
+ int (*pc_ether_hw_addr) __P((struct ppc_pci_chipset *, u_int8_t *));
+};
+
+/*
+ * Functions provided to machine-independent PCI code.
+ */
+#define pci_attach_hook(p, s, pba) \
+ (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba))
+#define pci_bus_maxdevs(c, b) \
+ (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b))
+#define pci_make_tag(c, b, d, f) \
+ (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f))
+#define pci_decompose_tag(c, t, bp, dp, fp) \
+ (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp))
+#define pci_conf_read(c, t, r) \
+ (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r))
+#define pci_conf_write(c, t, r, v) \
+ (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v))
+#define pci_intr_map(c, it, ip, il, ihp) \
+ (*(c)->pc_intr_map)((c)->pc_intr_v, (it), (ip), (il), (ihp))
+#define pci_intr_string(c, ih) \
+ (*(c)->pc_intr_string)((c)->pc_intr_v, (ih))
+#define pci_intr_establish(c, ih, l, h, a, nm) \
+ (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm))
+#define pci_intr_disestablish(c, iv) \
+ (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv))
+#define pci_ether_hw_addr(c, s) \
+ (*(c)->pc_ether_hw_addr)((c), (s))
+
+vm_offset_t vtophys __P((void *));
+
diff --git a/sys/arch/mvmeppc/pci/pcib.c b/sys/arch/mvmeppc/pci/pcib.c
new file mode 100644
index 00000000000..2f7a56b5193
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/pcib.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: pcib.c,v 1.1 2001/06/26 21:57:57 smurph Exp $ */
+/* $NetBSD: pcib.c,v 1.6 1997/06/06 23:29:16 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <dev/isa/isavar.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/pci/pcidevs.h>
+#include <mvmeppc/dev/ravenreg.h>
+
+#include "isa.h"
+
+int pcibmatch __P((struct device *, void *, void *));
+void pcibattach __P((struct device *, struct device *, void *));
+void pcib_callback __P((struct device *));
+int pcib_print __P((void *, const char *));
+
+struct ppc_bus_space ppc_isa_io, ppc_isa_mem;
+
+struct cfattach pcib_ca = {
+ sizeof(struct device), pcibmatch, pcibattach
+};
+
+struct cfdriver pcib_cd = {
+ NULL, "pcib", DV_DULL
+};
+
+int
+pcibmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
+ return (1);
+
+ switch (PCI_VENDOR(pa->pa_id)) {
+ case PCI_VENDOR_SYMPHONY:
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_SYMPHONY_82C565:
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+void
+pcibattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+
+ ppc_isa_io = prep_isa_io_space_tag;
+ ppc_isa_mem = prep_isa_mem_space_tag;
+
+ /*
+ * Cannot attach isa bus now; must postpone for various reasons
+ */
+
+ printf("\n");
+
+ config_defer(self, pcib_callback);
+}
+
+void
+pcib_callback(self)
+ struct device *self;
+{
+ struct isabus_attach_args iba;
+
+#if NPCIBIOS > 0
+ pci_intr_post_fixup();
+#endif
+
+ /*
+ * Attach the ISA bus behind this bridge.
+ */
+ memset(&iba, 0, sizeof(iba));
+ iba.iba_busname = "isa";
+ iba.iba_iot = &ppc_isa_io;
+ iba.iba_memt = &ppc_isa_mem;
+#if NISADMA > 0
+ iba.iba_dmat = &isa_bus_dma_tag;
+#endif
+ config_found(self, &iba, pcib_print);
+}
+
+int
+pcib_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ /* Only ISAs can attach to pcib's; easy. */
+ if (pnp)
+ printf("isa at %s", pnp);
+ return (UNCONF);
+}
diff --git a/sys/arch/mvmeppc/pci/pcibrvar.h b/sys/arch/mvmeppc/pci/pcibrvar.h
new file mode 100644
index 00000000000..e3222f70272
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/pcibrvar.h
@@ -0,0 +1,56 @@
+/* $OpenBSD: pcibrvar.h,v 1.1 2001/06/26 21:57:57 smurph Exp $ */
+
+/*
+ * Copyright (c) 1997 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.
+ *
+ */
+
+struct pcibr_config {
+ bus_space_tag_t lc_memt;
+ bus_space_tag_t lc_iot;
+ bus_space_handle_t ioh_cf8;
+ bus_space_handle_t ioh_cfc;
+ struct ppc_pci_chipset lc_pc;
+ int config_type;
+ int bus;
+ int pci_init_done;
+ int node;
+};
+
+struct pcibr_softc {
+ struct device sc_dev;
+ struct pcibr_config *sc_pcibr;
+ struct ppc_bus_space sc_membus_space;
+ struct ppc_bus_space sc_iobus_space;
+ struct powerpc_bus_dma_tag sc_dmatag;
+ struct pcibr_config pcibr_config;
+};
+
+
diff --git a/sys/arch/mvmeppc/pci/raven.c b/sys/arch/mvmeppc/pci/raven.c
new file mode 100644
index 00000000000..1747ee0e9a4
--- /dev/null
+++ b/sys/arch/mvmeppc/pci/raven.c
@@ -0,0 +1,600 @@
+/* $OpenBSD: raven.c,v 1.1 2001/06/26 21:57:57 smurph Exp $ */
+
+/*
+ * Copyright (c) 2001 Steve Murphree, Jr.
+ *
+ * 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 for RTMX Inc
+ * by Per Fogelstrom, Opsycon AB.
+ * 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.
+ *
+ */
+
+/*
+ * Motorola 'Raven' PCI BUS Bridge driver.
+ * specialized hooks for different config methods.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+
+#include <machine/autoconf.h>
+#include <machine/bat.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <mvmeppc/pci/pcibrvar.h>
+#include <mvmeppc/pci/ravenreg.h>
+
+extern vm_map_t phys_map;
+
+int mpcpcibrmatch __P((struct device *, void *, void *));
+void mpcpcibrattach __P((struct device *, struct device *, void *));
+
+void mpc_attach_hook __P((struct device *, struct device *,
+ struct pcibus_attach_args *));
+int mpc_bus_maxdevs __P((void *, int));
+pcitag_t mpc_make_tag __P((void *, int, int, int));
+void mpc_decompose_tag __P((void *, pcitag_t, int *, int *, int *));
+pcireg_t mpc_conf_read __P((void *, pcitag_t, int));
+void mpc_conf_write __P((void *, pcitag_t, int, pcireg_t));
+
+int mpc_intr_map __P((void *, pcitag_t, int, int, pci_intr_handle_t *));
+const char *mpc_intr_string __P((void *, pci_intr_handle_t));
+void *mpc_intr_establish __P((void *, pci_intr_handle_t,
+ int, int (*func)(void *), void *, char *));
+void mpc_intr_disestablish __P((void *, void *));
+int mpc_ether_hw_addr __P((struct ppc_pci_chipset *, u_int8_t *));
+
+struct cfattach mpcpcibr_ca = {
+ sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
+};
+
+struct cfdriver mpcpcibr_cd = {
+ NULL, "mpcpcibr", DV_DULL,
+};
+
+static int mpcpcibrprint __P((void *, const char *pnp));
+
+struct pcibr_config mpc_config;
+
+/*
+ * config types
+ * bit meanings
+ * 0 - standard cf8/cfc type configurations,
+ * sometimes the base addresses for these are different
+ * 1 - Config Method #2 configuration - uni-north
+ *
+ * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
+ */
+
+struct powerpc_bus_dma_tag pci_bus_dma_tag = {
+ NULL,
+ _dmamap_create,
+ _dmamap_destroy,
+ _dmamap_load,
+ _dmamap_load_mbuf,
+ _dmamap_load_uio,
+ _dmamap_load_raw,
+ _dmamap_unload,
+ _dmamap_sync,
+ _dmamem_alloc,
+ _dmamem_free,
+ _dmamem_map,
+ _dmamem_unmap,
+ _dmamem_mmap
+};
+
+int
+mpcpcibrmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct confargs *ca = aux;
+ int handle;
+ int found = 0;
+ int err;
+ unsigned int val;
+ int qhandle;
+ char type[32];
+
+ if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
+ return (found);
+
+ found = 1;
+
+ return found;
+}
+
+int pci_map_a = 0;
+void
+mpcpcibrattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcibr_softc *sc = (struct pcibr_softc *)self;
+ struct confargs *ca = aux;
+ struct pcibr_config *lcp;
+ struct pcibus_attach_args pba;
+ int map, node;
+ char *bridge;
+ int of_node = 0;
+
+ lcp = sc->sc_pcibr = &mpc_config;
+
+ addbatmap(RAVEN_V_PCI_MEM_SPACE, RAVEN_P_PCI_MEM_SPACE, BAT_I);
+
+ sc->sc_membus_space.bus_base = RAVEN_V_PCI_MEM_SPACE;
+ sc->sc_membus_space.bus_reverse = 1;
+ sc->sc_iobus_space.bus_base = RAVEN_V_PCI_IO_SPACE;
+ sc->sc_iobus_space.bus_reverse = 1;
+
+ lcp->lc_pc.pc_conf_v = lcp;
+ lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
+ lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
+ lcp->lc_pc.pc_make_tag = mpc_make_tag;
+ lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
+ lcp->lc_pc.pc_conf_read = mpc_conf_read;
+ lcp->lc_pc.pc_conf_write = mpc_conf_write;
+ lcp->lc_pc.pc_ether_hw_addr = mpc_ether_hw_addr;
+ lcp->lc_iot = &sc->sc_iobus_space;
+ lcp->lc_memt = &sc->sc_membus_space;
+
+ lcp->ioh_cf8 = PREP_CONFIG_ADD;
+ lcp->ioh_cfc = PREP_CONFIG_DAT;
+
+ lcp->config_type = 0;
+
+ lcp->lc_pc.pc_intr_v = lcp;
+ lcp->lc_pc.pc_intr_map = mpc_intr_map;
+ lcp->lc_pc.pc_intr_string = mpc_intr_string;
+ lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
+ lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;
+
+ printf(": RAVEN, Revision 0x%x.\n",
+ mpc_cfg_read_1(lcp, RAVEN_PCI_REVID));
+ bridge = "RAVEN";
+ pba.pba_dmat = &pci_bus_dma_tag;
+
+ pba.pba_busname = "pci";
+ pba.pba_iot = &sc->sc_iobus_space;
+ pba.pba_memt = &sc->sc_membus_space;
+ pba.pba_pc = &lcp->lc_pc;
+ pba.pba_bus = 0;
+ pba.pba_flags = PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED;
+ /* set mem and io base addresses */
+ mpc_cfg_write_4(lcp, RAVEN_PCI_MEM, RAVEN_P_PCI_MEM_SPACE);
+ mpc_cfg_write_4(lcp, RAVEN_PCI_IO, RAVEN_P_PCI_IO_SPACE);
+ /* enable mem and io mapping, and bus master */
+ mpc_cfg_write_2(lcp, RAVEN_PCI_CMD,
+ RAVEN_CMD_IOSP|RAVEN_CMD_MEMSP|RAVEN_CMD_MASTR);
+
+ config_found(self, &pba, mpcpcibrprint);
+}
+
+static int
+mpcpcibrprint(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if(pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+ return(UNCONF);
+}
+
+/*
+ * Get PCI physical address from given viritual address.
+ * XXX Note that cross page boundarys are *not* garantueed to work!
+ */
+
+vm_offset_t
+vtophys(p)
+ void *p;
+{
+ vm_offset_t pa;
+ vm_offset_t va;
+
+ va = (vm_offset_t)p;
+ if((vm_offset_t)va < VM_MIN_KERNEL_ADDRESS) {
+ pa = va;
+ }
+ else {
+ pa = pmap_extract(vm_map_pmap(phys_map), va);
+ }
+ return(pa | ((pci_map_a == 1) ? RAVEN_PCI_CPUMEM : 0 ));
+}
+
+void
+mpc_attach_hook(parent, self, pba)
+ struct device *parent, *self;
+ struct pcibus_attach_args *pba;
+{
+}
+
+int
+mpc_ether_hw_addr(p, ethaddr)
+ struct ppc_pci_chipset *p;
+ u_int8_t *ethaddr;
+{
+ printf("mpc_ether_hw_addr not supported\n");
+ return(0);
+}
+
+int
+mpc_bus_maxdevs(cpv, busno)
+ void *cpv;
+ int busno;
+{
+ return(32);
+}
+
+#define BUS_SHIFT 16
+#define DEVICE_SHIFT 11
+#define FNC_SHIFT 8
+
+pcitag_t
+mpc_make_tag(cpv, bus, dev, fnc)
+ void *cpv;
+ int bus, dev, fnc;
+{
+ return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
+}
+
+void
+mpc_decompose_tag(cpv, tag, busp, devp, fncp)
+ void *cpv;
+ pcitag_t tag;
+ int *busp, *devp, *fncp;
+{
+ if (busp != NULL)
+ *busp = (tag >> BUS_SHIFT) & 0xff;
+ if (devp != NULL)
+ *devp = (tag >> DEVICE_SHIFT) & 0x1f;
+ if (fncp != NULL)
+ *fncp = (tag >> FNC_SHIFT) & 0x7;
+}
+
+static u_int32_t
+mpc_gen_config_reg(cpv, tag, offset)
+ void *cpv;
+ pcitag_t tag;
+ int offset;
+{
+ struct pcibr_config *cp = cpv;
+ unsigned int bus, dev, fcn;
+ u_int32_t reg;
+ /*
+ static int spin = 0;
+ while (spin > 85);
+ spin++;
+ */
+
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+
+ if (cp->config_type & 1) {
+ /* Config Mechanism #2 */
+ if (bus == 0) {
+ if (dev < 11) {
+ return 0xffffffff;
+ }
+ /*
+ * Need to do config type 0 operation
+ * 1 << (11?+dev) | fcn << 8 | reg
+ * 11? is because pci spec states
+ * that 11-15 is reserved.
+ */
+ reg = 1 << (dev) | fcn << 8 | offset;
+
+ } else {
+ if (dev > 15) {
+ return 0xffffffff;
+ }
+ /*
+ * config type 1
+ */
+ reg = tag | offset | 1;
+
+ }
+ } else {
+ /* config mechanism #2, type 0
+ /* standard cf8/cfc config */
+ reg = 0x80000000 | tag | offset;
+
+ }
+ return reg;
+}
+
+/*#define DEBUG_CONFIG */
+pcireg_t
+mpc_conf_read(cpv, tag, offset)
+ void *cpv;
+ pcitag_t tag;
+ int offset;
+{
+ struct pcibr_config *cp = cpv;
+
+ pcireg_t data;
+ u_int32_t reg;
+ int device;
+ int s;
+ int handle;
+ int daddr = 0;
+
+ if(offset & 3 || offset < 0 || offset >= 0x100) {
+ printf ("pci_conf_read: bad reg %x\n", offset);
+ return(~0);
+ }
+
+ reg = mpc_gen_config_reg(cpv, tag, offset);
+ /* if invalid tag, return -1 */
+ if (reg == 0xffffffff) {
+ return 0xffffffff;
+ }
+
+ if ((cp->config_type & 2) && (offset & 0x04)) {
+ daddr += 4;
+ }
+
+ s = splhigh();
+
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+ data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+
+ splx(s);
+#ifdef DEBUG_CONFIG
+ if (!((offset == 0) && (data == 0xffffffff))) {
+ unsigned int bus, dev, fcn;
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+ printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
+ offset);
+ printf(" daddr %x reg %x",daddr, reg);
+ printf(" data %x\n", data);
+ }
+#endif
+
+ return(data);
+}
+
+void
+mpc_conf_write(cpv, tag, offset, data)
+ void *cpv;
+ pcitag_t tag;
+ int offset;
+ pcireg_t data;
+{
+ struct pcibr_config *cp = cpv;
+ u_int32_t reg;
+ int s;
+ int handle;
+ int daddr = 0;
+
+ reg = mpc_gen_config_reg(cpv, tag, offset);
+
+ /* if invalid tag, return ??? */
+ if (reg == 0xffffffff) {
+ return;
+ }
+ if ((cp->config_type & 2) && (offset & 0x04)) {
+ daddr += 4;
+ }
+#ifdef DEBUG_CONFIG
+ {
+ unsigned int bus, dev, fcn;
+ mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
+ printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
+ dev, fcn, offset);
+ printf(" daddr %x reg %x",daddr, reg);
+ printf(" data %x\n", data);
+ }
+#endif
+
+ s = splhigh();
+
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+ bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
+ bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
+
+ splx(s);
+}
+
+
+int
+mpc_intr_map(lcv, bustag, buspin, line, ihp)
+ void *lcv;
+ pcitag_t bustag;
+ int buspin, line;
+ pci_intr_handle_t *ihp;
+{
+ struct pcibr_config *lcp = lcv;
+ pci_chipset_tag_t pc = &lcp->lc_pc;
+ int error = 0;
+ int route;
+ int lvl;
+ int device;
+
+ *ihp = -1;
+ if (buspin == 0) {
+ /* No IRQ used. */
+ error = 1;
+ }
+ else if (buspin > 4) {
+ printf("mpc_intr_map: bad interrupt pin %d\n", buspin);
+ error = 1;
+ }
+
+ if(!error)
+ *ihp = line;
+ return error;
+}
+
+const char *
+mpc_intr_string(lcv, ih)
+ void *lcv;
+ pci_intr_handle_t ih;
+{
+ static char str[16];
+
+ sprintf(str, "irq %d", ih);
+ return(str);
+}
+
+typedef void *(intr_establish_t) __P((void *, pci_intr_handle_t,
+ int, int, int (*func)(void *), void *, char *));
+typedef void (intr_disestablish_t) __P((void *, void *));
+extern intr_establish_t *intr_establish_func;
+extern intr_disestablish_t *intr_disestablish_func;
+
+void *
+mpc_intr_establish(lcv, ih, level, func, arg, name)
+ void *lcv;
+ pci_intr_handle_t ih;
+ int level;
+ int (*func) __P((void *));
+ void *arg;
+ char *name;
+{
+ return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
+ name);
+}
+
+void
+mpc_intr_disestablish(lcv, cookie)
+ void *lcv, *cookie;
+{
+ /* XXX We should probably do something clever here.... later */
+}
+
+u_int32_t
+pci_iack()
+{
+ /* do pci IACK cycle */
+ /* this should be bus allocated. */
+ volatile u_int8_t *iack = (u_int8_t *)RAVEN_PIACK;
+ u_int8_t val;
+
+ val = *iack;
+ return val;
+}
+
+void
+mpc_cfg_write_1(cp, reg, val)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+ u_int8_t val;
+{
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0,
+ RAVEN_REGOFFS(reg));
+ bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+void
+mpc_cfg_write_2(cp, reg, val)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+ u_int16_t val;
+{
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+void
+mpc_cfg_write_4(cp, reg, val)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+ u_int32_t val;
+{
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val);
+ splx(s);
+}
+
+u_int8_t
+mpc_cfg_read_1(cp, reg)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+{
+ u_int8_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return(_v_);
+}
+
+u_int16_t
+mpc_cfg_read_2(cp, reg)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+{
+ u_int16_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return(_v_);
+}
+
+u_int32_t
+mpc_cfg_read_4(cp, reg)
+ struct pcibr_config *cp;
+ u_int32_t reg;
+{
+ u_int32_t _v_;
+
+ int s;
+ s = splhigh();
+ bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, RAVEN_REGOFFS(reg));
+ _v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0);
+ splx(s);
+ return(_v_);
+}