diff options
author | Steve Murphree <smurph@cvs.openbsd.org> | 2001-06-26 21:58:11 +0000 |
---|---|---|
committer | Steve Murphree <smurph@cvs.openbsd.org> | 2001-06-26 21:58:11 +0000 |
commit | 416f561c78b0eca90fdb484e72a96080b0825dca (patch) | |
tree | d310db0254b85229b90b9d90e79cabfbbcb6101a /sys/arch/mvmeppc/pci | |
parent | 77682e0d8d22531ed2952aaab30aae7c69483b3d (diff) |
Initial import of mvmeppc.
Diffstat (limited to 'sys/arch/mvmeppc/pci')
-rw-r--r-- | sys/arch/mvmeppc/pci/mpcpcibr.c | 666 | ||||
-rw-r--r-- | sys/arch/mvmeppc/pci/pchb.c | 106 | ||||
-rw-r--r-- | sys/arch/mvmeppc/pci/pci_machdep.h | 93 | ||||
-rw-r--r-- | sys/arch/mvmeppc/pci/pcib.c | 143 | ||||
-rw-r--r-- | sys/arch/mvmeppc/pci/pcibrvar.h | 56 | ||||
-rw-r--r-- | sys/arch/mvmeppc/pci/raven.c | 600 |
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_); +} |