summaryrefslogtreecommitdiff
path: root/sys/arch/macppc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/macppc')
-rw-r--r--sys/arch/macppc/conf/GENERIC14
-rw-r--r--sys/arch/macppc/conf/files.macppc6
-rw-r--r--sys/arch/macppc/include/rbus_machdep.h61
-rw-r--r--sys/arch/macppc/macppc/machdep.c27
-rw-r--r--sys/arch/macppc/macppc/rbus_machdep.c146
-rw-r--r--sys/arch/macppc/pci/mpcpcibus.c31
-rw-r--r--sys/arch/macppc/pci/pci_addr_fixup.c498
-rw-r--r--sys/arch/macppc/pci/pcibrvar.h9
8 files changed, 750 insertions, 42 deletions
diff --git a/sys/arch/macppc/conf/GENERIC b/sys/arch/macppc/conf/GENERIC
index 4651f252fa5..a396620abcc 100644
--- a/sys/arch/macppc/conf/GENERIC
+++ b/sys/arch/macppc/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.28 2002/06/25 17:11:49 itojun Exp $g
+# $OpenBSD: GENERIC,v 1.29 2002/07/23 17:53:24 drahn Exp $g
#
# PPC GENERIC config file
#
@@ -168,6 +168,18 @@ aue* at uhub? port ? # USB EtherNet
uplcom* at uhub? port ? # I/O DATA USB-RSAQ2 serial adapter
ucom* at uplcom? portno ?
+# CardBus bus support
+cardbus* at cardslot?
+pcmcia* at cardslot?
+cbb* at pci? dev ? function ?
+cardslot* at cbb?
+wi* at pcmcia? function ? # WaveLAN IEEE 802.11DS
+#dc* at cardbus? dev ? function ? # 21143, "tulip" clone ethernet
+#fxp* at cardbus? dev ? function ? # Intel PRO/100 ethernet
+#xl* at cardbus? dev ? function ? # 3C575/3C656 ethernet
+#rl* at cardbus? dev ? function ? # RealTek 81[23]9 ethernet
+#wdc* at pcmcia? function ?
+
wsdisplay* at vgafb?
wskbd* at ukbd? console ? mux 1
diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc
index 3f7b71b8655..6149a487c3c 100644
--- a/sys/arch/macppc/conf/files.macppc
+++ b/sys/arch/macppc/conf/files.macppc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.macppc,v 1.12 2002/06/25 17:11:49 itojun Exp $
+# $OpenBSD: files.macppc,v 1.13 2002/07/23 17:53:24 drahn Exp $
#
# macppc-specific configuration info
@@ -71,7 +71,7 @@ file arch/macppc/pci/pciide_machdep.c pciide
device mpcpcibr {} : pcibus
attach mpcpcibr at mainbus
file arch/macppc/pci/mpcpcibus.c mpcpcibr
-#file arch/macppc/pci/pci_addr_fixup.c mpcpcibr
+file arch/macppc/pci/pci_addr_fixup.c mpcpcibr
#
# "workstation console" routines
@@ -204,7 +204,7 @@ file arch/macppc/pci/vgafb_pci.c vgafb_pci needs-flag
# CARDBUS
#
include "dev/cardbus/files.cardbus"
-#file arch/macppc/macppc/rbus_machdep.c cardbus
+file arch/macppc/macppc/rbus_machdep.c cardbus
#
# Machine-independent PCMCIA drivers
diff --git a/sys/arch/macppc/include/rbus_machdep.h b/sys/arch/macppc/include/rbus_machdep.h
new file mode 100644
index 00000000000..42bb0cc022b
--- /dev/null
+++ b/sys/arch/macppc/include/rbus_machdep.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: rbus_machdep.h,v 1.1 2002/07/23 17:53:24 drahn Exp $ */
+/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */
+
+/*
+ * Copyright (c) 1999
+ * HAYAKAWA Koichi. 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 by HAYAKAWA Koichi.
+ * 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.
+ */
+
+
+#if !defined _ARCH_MACPPC_MACPPC_RBUS_MACHDEP_H_
+#define _ARCH_MACPPC_MACPPC_RBUS_MACHDEP_H_
+
+struct pci_attach_args; /* XXX */
+
+void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t, bus_addr_t *);
+
+#define md_space_map(bt, physaddr, size, flags, bshp) \
+ bus_space_map((bt), (physaddr), (size), (flags), (bshp))
+
+/* XXX */
+bus_addr_t bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size);
+
+
+#define md_space_unmap(bt, bsh, size, adrp) \
+ do { \
+ *adrp = bus_space_unmap_p((bt), (bsh), (size)); \
+ } while (0)
+
+rbus_tag_t rbus_pccbb_parent_io(struct device *self,
+ struct pci_attach_args *pa);
+rbus_tag_t rbus_pccbb_parent_mem(struct device *self,
+ struct pci_attach_args *pa);
+
+#endif /* _ARCH_MACPPC_MACPPC_RBUS_MACHDEP_H_ */
diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c
index f50cb9699ae..e76cf0d1fa4 100644
--- a/sys/arch/macppc/macppc/machdep.c
+++ b/sys/arch/macppc/macppc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.36 2002/07/20 19:24:56 art Exp $ */
+/* $OpenBSD: machdep.c,v 1.37 2002/07/23 17:53:24 drahn Exp $ */
/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
/*
@@ -1168,30 +1168,31 @@ bus_space_unmap(t, bsh, size)
{
bus_addr_t sva;
bus_size_t off, len;
+ bus_addr_t bpa;
/* should this verify that the proper size is freed? */
sva = trunc_page(bsh);
off = bsh - sva;
len = size+off;
+ if (pmap_extract(pmap_kernel(), sva, &bpa) == TRUE) {
+ if (extent_free(devio_ex, bpa, size, EX_NOWAIT |
+ (ppc_malloc_ok ? EX_MALLOCOK : 0)))
+ {
+ printf("bus_space_map: pa 0x%x, size 0x%x\n",
+ bpa, size);
+ printf("bus_space_map: can't free region\n");
+ }
+ }
/* do not free memory which was stolen from the vm system */
if (ppc_malloc_ok &&
((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS)) )
{
uvm_km_free(phys_map, sva, len);
+ } else {
+ pmap_remove(vm_map_pmap(phys_map), sva, sva+len);
+ pmap_update(pmap_kernel());
}
-#if 0
- pmap_extract(pmap_kernel(), sva, &bpa);
- if (extent_free(devio_ex, bpa, size, EX_NOWAIT |
- (ppc_malloc_ok ? EX_MALLOCOK : 0)))
- {
- printf("bus_space_map: pa 0x%x, size 0x%x\n",
- bpa, size);
- printf("bus_space_map: can't free region\n");
- }
-#endif
- pmap_remove(vm_map_pmap(phys_map), sva, sva+len);
- pmap_update(pmap_kernel());
}
vm_offset_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE;
diff --git a/sys/arch/macppc/macppc/rbus_machdep.c b/sys/arch/macppc/macppc/rbus_machdep.c
new file mode 100644
index 00000000000..b801620c47f
--- /dev/null
+++ b/sys/arch/macppc/macppc/rbus_machdep.c
@@ -0,0 +1,146 @@
+/* $OpenBSD: rbus_machdep.c,v 1.1 2002/07/23 17:53:24 drahn Exp $ */
+/* $NetBSD: rbus_machdep.c,v 1.2 1999/10/15 06:43:06 haya Exp $ */
+
+/*
+ * Copyright (c) 1999
+ * HAYAKAWA Koichi. 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 by HAYAKAWA Koichi.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/extent.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <sys/sysctl.h>
+
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <dev/cardbus/rbus.h>
+
+#include <dev/pci/pcivar.h>
+#include <arch/macppc/pci/pcibrvar.h>
+
+void macppc_cardbus_init(pci_chipset_tag_t pc, pcitag_t tag);
+
+/**********************************************************************
+ * rbus_tag_t rbus_fakeparent_mem(struct pci_attach_args *pa)
+ *
+ * This function makes an rbus tag for memory space. This rbus tag
+ * shares the all memory region of ex_iomem.
+ **********************************************************************/
+#define RBUS_MEM_SIZE 0x10000000
+
+rbus_tag_t
+rbus_pccbb_parent_mem(self, pa)
+ struct device *self;
+ struct pci_attach_args *pa;
+{
+ bus_addr_t start;
+ bus_size_t size;
+ struct extent *ex;
+
+ macppc_cardbus_init(pa->pa_pc, pa->pa_tag);
+
+ size = RBUS_MEM_SIZE;
+ if ((ex = pciaddr_search(PCIADDR_SEARCH_MEM, self, &start, size)) == NULL)
+ {
+ /* XXX */
+ printf("failed\n");
+ }
+
+ return rbus_new_root_share(pa->pa_memt, ex, start, size, 0);
+}
+
+
+/**********************************************************************
+ * rbus_tag_t rbus_pccbb_parent_io(struct pci_attach_args *pa)
+ **********************************************************************/
+#define RBUS_IO_SIZE 0x1000
+
+rbus_tag_t
+rbus_pccbb_parent_io(self, pa)
+ struct device *self;
+ struct pci_attach_args *pa;
+{
+ struct extent *ex;
+ bus_addr_t start;
+ bus_size_t size;
+
+
+ size = RBUS_IO_SIZE;
+ if ((ex = pciaddr_search(PCIADDR_SEARCH_IO, self, &start, size)) == NULL)
+ {
+ /* XXX */
+ printf("failed\n");
+ }
+
+ return rbus_new_root_share(pa->pa_iot, ex, start, size, 0);
+}
+
+
+/*
+ * Big ugly hack to enable bridge/fix interrupts
+ */
+void
+macppc_cardbus_init(pc, tag)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+{
+ u_int x;
+ static int initted = 0;
+
+ if (initted)
+ return;
+ initted = 1;
+
+ /* XXX What about other bridges? */
+
+ x = pci_conf_read(pc, tag, PCI_ID_REG);
+ if (PCI_VENDOR(x) == PCI_VENDOR_TI &&
+ PCI_PRODUCT(x) == PCI_PRODUCT_TI_PCI1211) {
+ /* For CardBus card. */
+ pci_conf_write(pc, tag, 0x18, 0x10010100);
+
+ /* Route INTA to MFUNC0 */
+ x = pci_conf_read(pc, tag, 0x8c);
+ x |= 0x02;
+ pci_conf_write(pc, tag, 0x8c, x);
+
+ tag = pci_make_tag(pc, 0, 0, 0);
+ x = pci_conf_read(pc, tag, PCI_ID_REG);
+ if (PCI_VENDOR(x) == PCI_VENDOR_MOT &&
+ PCI_PRODUCT(x) == PCI_PRODUCT_MOT_MPC106) {
+ /* Set subordinate bus number to 1. */
+ x = pci_conf_read(pc, tag, 0x40);
+ x |= 1 << 8;
+ pci_conf_write(pc, tag, 0x40, x);
+ }
+ }
+}
diff --git a/sys/arch/macppc/pci/mpcpcibus.c b/sys/arch/macppc/pci/mpcpcibus.c
index 6d7d4d0483a..ac7a104ed31 100644
--- a/sys/arch/macppc/pci/mpcpcibus.c
+++ b/sys/arch/macppc/pci/mpcpcibus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpcpcibus.c,v 1.10 2002/04/22 21:39:58 miod Exp $ */
+/* $OpenBSD: mpcpcibus.c,v 1.11 2002/07/23 17:53:25 drahn Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -445,7 +445,7 @@ mpcpcibrattach(parent, self, aux)
" compatible %s\n", compat);
return;
}
-#ifdef PCI_DEBUG
+#ifdef DEBUG_FIXUP
printf(" mem base %x sz %x io base %x sz %x\n config addr %x"
" config data %x\n",
sc->sc_membus_space.bus_base,
@@ -492,9 +492,7 @@ mpcpcibrattach(parent, self, aux)
printf(": %s, Revision 0x%x\n", compat,
mpc_cfg_read_1(lcp, MPC106_PCI_REVID));
-#if 0
- pci_addr_fixup(sc, &lcp->lc_pc, 32, &null_reserve);
-#endif
+ pci_addr_fixup(sc, &lcp->lc_pc, 32);
}
break;
@@ -523,9 +521,6 @@ mpcpcibrattach(parent, self, aux)
len = OF_getprop(node, "name", name,
sizeof(name));
name[len] = 0;
-#ifdef DEBUG_FIXUP
- printf("checking node %s", name);
-#endif
fix_node_irq(node, &pba);
/* iterate section */
@@ -574,9 +569,6 @@ find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
-#ifdef DEBUG_FIXUP
- printf("parent %x len %x mlen %x\n", parent, len, mlen);
-#endif
if ((len == -1) || (mlen == -1))
goto nomap;
n_mlen = mlen/sizeof(u_int32_t);
@@ -601,11 +593,6 @@ find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
}
while (len > mlen) {
-#ifdef DEBUG_FIXUP
- printf ("[%x %x %x %x] [%x %x %x %x] %x\n",
- maskedaddr[0], maskedaddr[1], maskedaddr[2], maskedaddr[3],
- mp[0], mp[1], mp[2], mp[3], step);
-#endif
match = bcmp(maskedaddr, mp, mlen);
mp1 = mp + n_mlen;
@@ -672,11 +659,6 @@ fix_node_irq(node, pba)
pcifunc(addr[0].phys_hi));
intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-#ifdef DEBUG_FIXUP
- printf("changing interrupt from %x to %x\n",
- intr & PCI_INTERRUPT_LINE_MASK,
- irq & PCI_INTERRUPT_LINE_MASK);
-#endif
intr &= ~PCI_INTERRUPT_LINE_MASK;
intr |= irq & PCI_INTERRUPT_LINE_MASK;
pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
@@ -1126,3 +1108,10 @@ mpc_cfg_read_4(cp, reg)
splx(s);
return(_v_);
}
+
+int
+pci_intr_line(ih)
+ pci_intr_handle_t ih;
+{
+ return (ih);
+}
diff --git a/sys/arch/macppc/pci/pci_addr_fixup.c b/sys/arch/macppc/pci/pci_addr_fixup.c
new file mode 100644
index 00000000000..2055be6a380
--- /dev/null
+++ b/sys/arch/macppc/pci/pci_addr_fixup.c
@@ -0,0 +1,498 @@
+/* $OpenBSD: pci_addr_fixup.c,v 1.1 2002/07/23 17:53:25 drahn Exp $ */
+/* $NetBSD: pci_addr_fixup.c,v 1.7 2000/08/03 20:10:45 nathanw Exp $ */
+
+/*-
+ * Copyright (c) 2000 UCHIYAMA Yasushi. 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+
+#include <uvm/uvm_param.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <macppc/pci/pcibrvar.h>
+
+typedef int (*pciaddr_resource_manage_func_t)(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t, int, struct extent *, int, bus_addr_t *,
+ bus_size_t);
+void pciaddr_resource_manage(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t, pciaddr_resource_manage_func_t);
+void pciaddr_resource_reserve(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t);
+int pciaddr_do_resource_reserve(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t, int, struct extent *, int,
+ bus_addr_t *, bus_size_t);
+void pciaddr_resource_allocate(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t);
+int pciaddr_do_resource_allocate(struct pcibr_softc *,
+ pci_chipset_tag_t, pcitag_t, int, struct extent *, int, bus_addr_t *,
+ bus_size_t);
+bus_addr_t pciaddr_ioaddr(u_int32_t);
+void pciaddr_print_devid(pci_chipset_tag_t, pcitag_t);
+
+int pciaddr_device_is_agp(pci_chipset_tag_t, pcitag_t);
+
+void pci_device_foreach(struct pcibr_softc *sc, pci_chipset_tag_t pc,
+ int maxbus,
+ void (*func)(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t));
+
+#define PCIADDR_MEM_START 0x0
+#define PCIADDR_MEM_END 0xffffffff
+#define PCIADDR_PORT_START 0x0
+#define PCIADDR_PORT_END 0xffff
+
+int pcibr_flags = 0;
+#define PCIBR_VERBOSE 1
+#define PCIBR_ADDR_FIXUP 2
+
+#define PCIBIOS_PRINTV(x) if (pcibr_flags & PCIBR_VERBOSE) \
+ printf x
+
+void
+pci_addr_fixup(sc, pc, maxbus)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ int maxbus;
+{
+ const char *verbose_header =
+ "[%s]-----------------------\n"
+ " device vendor product\n"
+ " register space address size\n"
+ "--------------------------------------------\n";
+ const char *verbose_footer =
+ "--------------------------[%3d devices bogus]\n";
+
+ sc->extent_mem = extent_create("PCI I/O memory space",
+ sc->sc_membus_space.bus_base,
+ sc->sc_membus_space.bus_base + sc->sc_membus_space.bus_size,
+ M_DEVBUF, 0, 0, EX_NOWAIT);
+ KASSERT(sc->extent_mem);
+ sc->extent_port = extent_create("PCI I/O port space",
+#if 1
+ sc->sc_iobus_space.bus_base,
+ sc->sc_iobus_space.bus_base + sc->sc_iobus_space.bus_size,
+#else
+ PCIADDR_PORT_START, PCIADDR_PORT_END,
+#endif
+ M_DEVBUF, 0, 0, EX_NOWAIT);
+ KASSERT(sc->extent_port);
+
+ /*
+ * 1. check & reserve system BIOS setting.
+ */
+ PCIBIOS_PRINTV((verbose_header, "System BIOS Setting"));
+ pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve);
+ PCIBIOS_PRINTV((verbose_footer, sc->nbogus));
+
+ {
+ struct extent_region *rp;
+ struct extent *ex = sc->extent_mem;
+ for (rp = LIST_FIRST(&ex->ex_regions);
+ rp; rp = LIST_NEXT(rp, er_link)) {
+ }
+ }
+ {
+ struct extent_region *rp;
+ struct extent *ex = sc->extent_port;
+ for (rp = LIST_FIRST(&ex->ex_regions);
+ rp; rp = LIST_NEXT(rp, er_link)) {
+ }
+ }
+
+ if (sc->nbogus == 0)
+ return; /* no need to fixup */
+
+ /*
+ * 4. do fixup
+ */
+ PCIBIOS_PRINTV((verbose_header, "PCIBIOS fixup stage"));
+ sc->nbogus = 0;
+ pci_device_foreach(sc, pc, maxbus, pciaddr_resource_allocate);
+ PCIBIOS_PRINTV((verbose_footer, sc->nbogus));
+
+}
+
+void
+pciaddr_resource_reserve(sc, pc, tag)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+{
+ if (pcibr_flags & PCIBR_VERBOSE)
+ pciaddr_print_devid(pc, tag);
+ pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve);
+}
+
+void
+pciaddr_resource_allocate(sc, pc, tag)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+{
+ if (pcibr_flags & PCIBR_VERBOSE)
+ pciaddr_print_devid(pc, tag);
+ pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_allocate);
+}
+
+void
+pciaddr_resource_manage(sc, pc, tag, func)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ pciaddr_resource_manage_func_t func;
+{
+ struct extent *ex;
+ pcireg_t val, mask;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error, mapreg, type, reg_start, reg_end, width;
+
+ val = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ switch (PCI_HDRTYPE_TYPE(val)) {
+ default:
+ printf("WARNING: unknown PCI device header.\n");
+ sc->nbogus++;
+ return;
+ case 0:
+ reg_start = PCI_MAPREG_START;
+ reg_end = PCI_MAPREG_END;
+ break;
+ case 1: /* PCI-PCI bridge */
+ reg_start = PCI_MAPREG_START;
+ reg_end = PCI_MAPREG_PPB_END;
+ break;
+ case 2: /* PCI-CardBus bridge */
+ reg_start = PCI_MAPREG_START;
+ reg_end = PCI_MAPREG_PCB_END;
+ break;
+ }
+ error = 0;
+
+ for (mapreg = reg_start; mapreg < reg_end; mapreg += width) {
+ /* inquire PCI device bus space requirement */
+ val = pci_conf_read(pc, tag, mapreg);
+ pci_conf_write(pc, tag, mapreg, ~0);
+
+ mask = pci_conf_read(pc, tag, mapreg);
+ pci_conf_write(pc, tag, mapreg, val);
+
+ type = PCI_MAPREG_TYPE(val);
+ width = 4;
+ if (type == PCI_MAPREG_TYPE_MEM) {
+ if (PCI_MAPREG_MEM_TYPE(val) ==
+ PCI_MAPREG_MEM_TYPE_64BIT) {
+ /* XXX We could examine the upper 32 bits
+ * XXX of the BAR here, but we are totally
+ * XXX unprepared to handle a non-zero value,
+ * XXX either here or anywhere else in
+ * XXX i386-land.
+ * XXX So just arrange to not look at the
+ * XXX upper 32 bits, lest we misinterpret
+ * XXX it as a 32-bit BAR set to zero.
+ */
+ width = 8;
+ }
+ addr = PCI_MAPREG_MEM_ADDR(val);
+ size = PCI_MAPREG_MEM_SIZE(mask);
+ ex = sc->extent_mem;
+ } else {
+ /* XXX some devices give 32bit value */
+ addr = (PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END) |
+ sc->sc_iobus_space.bus_base,
+
+ size = PCI_MAPREG_IO_SIZE(mask);
+ ex = sc->extent_port;
+ }
+
+ if (!size) /* unused register */
+ continue;
+
+ /* reservation/allocation phase */
+ error += (*func) (sc, pc, tag, mapreg, ex, type, &addr, size);
+
+ PCIBIOS_PRINTV(("\t%02xh %s 0x%08x 0x%08x\n",
+ mapreg, type ? "port" : "mem ",
+ (unsigned int)addr, (unsigned int)size));
+ }
+
+ /* enable/disable PCI device */
+ val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
+ if (error == 0)
+ val |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
+ PCI_COMMAND_MASTER_ENABLE);
+ else
+ val &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
+ PCI_COMMAND_MASTER_ENABLE);
+ pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val);
+
+ if (error)
+ sc->nbogus++;
+
+ PCIBIOS_PRINTV(("\t\t[%s]\n", error ? "NG" : "OK"));
+}
+
+int
+pciaddr_do_resource_allocate(sc, pc, tag, mapreg, ex, type, addr, size)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ struct extent *ex;
+ int mapreg, type;
+ bus_addr_t *addr;
+ bus_size_t size;
+{
+ bus_addr_t start;
+ int error;
+
+ if (*addr) /* no need to allocate */
+ return (0);
+
+ /* XXX Don't allocate if device is AGP device to avoid conflict. */
+ if (pciaddr_device_is_agp(pc, tag))
+ return (0);
+
+ start = (type == PCI_MAPREG_TYPE_MEM ? sc->sc_membus_space.bus_base
+ : sc->sc_iobus_space.bus_base);
+ if (start < ex->ex_start || start + size - 1 >= ex->ex_end) {
+ PCIBIOS_PRINTV(("No available resources. fixup failed\n"));
+ return (1);
+ }
+ error = extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0, 0,
+ EX_FAST|EX_NOWAIT|EX_MALLOCOK, addr);
+ if (error) {
+ PCIBIOS_PRINTV(("No available resources. fixup failed\n"));
+ return (1);
+ }
+
+ /* write new address to PCI device configuration header */
+ pci_conf_write(pc, tag, mapreg, *addr);
+ /* check */
+ if (!pcibr_flags & PCIBR_VERBOSE)
+ {
+ printf("pci_addr_fixup: ");
+ pciaddr_print_devid(pc, tag);
+ }
+
+ if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
+ pci_conf_write(pc, tag, mapreg, 0); /* clear */
+ printf("fixup failed. (new address=%#x)\n", *addr);
+ return (1);
+ }
+ if (!pcibr_flags & PCIBR_VERBOSE)
+ printf("new address 0x%08x\n", *addr);
+
+ return (0);
+}
+
+int
+pciaddr_do_resource_reserve(sc, pc, tag, mapreg, ex, type, addr, size)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ struct extent *ex;
+ int type, mapreg;
+ bus_addr_t *addr;
+ bus_size_t size;
+{
+ int error;
+
+ if (*addr == 0)
+ return (1);
+
+ error = extent_alloc_region(ex, *addr, size, EX_NOWAIT | EX_MALLOCOK);
+ if (error) {
+ PCIBIOS_PRINTV(("Resource conflict.\n"));
+ pci_conf_write(pc, tag, mapreg, 0); /* clear */
+ return (1);
+ }
+
+ return (0);
+}
+
+bus_addr_t
+pciaddr_ioaddr(val)
+ u_int32_t val;
+{
+ return ((PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM)
+ ? PCI_MAPREG_MEM_ADDR(val)
+ : (PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END));
+}
+
+void
+pciaddr_print_devid(pc, tag)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+{
+ int bus, device, function;
+ pcireg_t id;
+
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+ pci_decompose_tag(pc, tag, &bus, &device, &function);
+ printf("%03d:%02d:%d %04x:%04x\n", bus, device, function,
+ PCI_VENDOR(id), PCI_PRODUCT(id));
+}
+
+int
+pciaddr_device_is_agp(pc, tag)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+{
+ pcireg_t class, status, rval;
+ int off;
+
+ /* Check AGP device. */
+ class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+ if (PCI_CLASS(class) == PCI_CLASS_DISPLAY) {
+ status = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
+ if (status & PCI_STATUS_CAPLIST_SUPPORT) {
+ rval = pci_conf_read(pc, tag, PCI_CAPLISTPTR_REG);
+ for (off = PCI_CAPLIST_PTR(rval);
+ off != 0;
+ off = PCI_CAPLIST_NEXT(rval) ) {
+ rval = pci_conf_read(pc, tag, off);
+ if (PCI_CAPLIST_CAP(rval) == PCI_CAP_AGP)
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
+
+struct extent *
+pciaddr_search(mem_port, parent, startp, size)
+ int mem_port;
+ struct device *parent;
+ bus_addr_t *startp;
+ bus_size_t size;
+{
+ struct pcibr_softc *sc;
+
+ /* find the bridge, 'mpcpcibr' */
+
+ sc = NULL;
+ while (parent != NULL) {
+ if (strncmp("mpcpcibr", parent->dv_xname, 8) == 0) {
+ sc = (void *)parent;
+ break;
+ }
+ parent = parent->dv_parent;
+ }
+
+ if (sc && !(pcibr_flags & PCIBR_ADDR_FIXUP)) {
+ struct extent_region *rp;
+ struct extent *ex = mem_port? sc->extent_mem : sc->extent_port;
+
+ /* Search the PCI I/O memory space extent for free
+ * space that will accomodate size. Remember that the
+ * extent stores allocated space and we're searching
+ * for the gaps.
+ *
+ * If we're at the end or the gap between this region
+ * and the next region big enough, then we're done
+ */
+ *startp = ex->ex_start;
+ rp = LIST_FIRST(&ex->ex_regions);
+
+ for (rp = LIST_FIRST(&ex->ex_regions);
+ rp && *startp + size > rp->er_start;
+ rp = LIST_NEXT(rp, er_link)) {
+ bus_addr_t new_start;
+
+ new_start = (rp->er_end - 1 + size) & ~(size - 1);
+ if (new_start > *startp)
+ *startp = new_start;
+ }
+
+ return (ex);
+ }
+
+ return (NULL);
+}
+
+
+void
+pci_device_foreach(sc, pc, maxbus, func)
+ struct pcibr_softc *sc;
+ pci_chipset_tag_t pc;
+ int maxbus;
+ void (*func)(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t);
+{
+ const struct pci_quirkdata *qd;
+ int bus, device, function, maxdevs, nfuncs;
+ pcireg_t id, bhlcr;
+ pcitag_t tag;
+
+ for (bus = 0; bus <= maxbus; bus++) {
+ maxdevs = pci_bus_maxdevs(pc, bus);
+ for (device = 0; device < maxdevs; device++) {
+ tag = pci_make_tag(pc, bus, device, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+
+ qd = pci_lookup_quirkdata(PCI_VENDOR(id),
+ PCI_PRODUCT(id));
+
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
+ (qd != NULL &&
+ (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+ nfuncs = 8;
+ else
+ nfuncs = 1;
+
+ for (function = 0; function < nfuncs; function++) {
+ tag = pci_make_tag(pc, bus, device, function);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /*
+ * XXX Not invalid, but we've done this
+ * ~forever.
+ */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+ (*func)(sc, pc, tag);
+ }
+ }
+ }
+}
diff --git a/sys/arch/macppc/pci/pcibrvar.h b/sys/arch/macppc/pci/pcibrvar.h
index 6efdbc8af38..39dba16855c 100644
--- a/sys/arch/macppc/pci/pcibrvar.h
+++ b/sys/arch/macppc/pci/pcibrvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcibrvar.h,v 1.2 2002/03/14 01:26:37 millert Exp $ */
+/* $OpenBSD: pcibrvar.h,v 1.3 2002/07/23 17:53:25 drahn Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -68,10 +68,11 @@ struct pci_reserve_mem {
char *name;
};
-void pci_addr_fixup(struct pcibr_softc *, pci_chipset_tag_t, int,
- struct pci_reserve_mem *);
+void pci_addr_fixup(struct pcibr_softc *, pci_chipset_tag_t, int);
#define PCIADDR_SEARCH_IO 0
#define PCIADDR_SEARCH_MEM 1
-struct extent *pciaddr_search(struct device *, int, bus_addr_t *, bus_size_t);
+
+struct extent * pciaddr_search(int mem_port, struct device *,
+ bus_addr_t *startp, bus_size_t size);