summaryrefslogtreecommitdiffstats
path: root/sys/mips/sibyte
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2010-02-12 02:59:49 +0000
committerneel <neel@FreeBSD.org>2010-02-12 02:59:49 +0000
commitf2eeadb198afb89ff67c9589eff8c717036632d2 (patch)
tree5a183fa578b3061ceb9f3dccb39c3b9fd5346bd2 /sys/mips/sibyte
parent2d898efa0f4c98f1caff58bc68f8d94b3428295c (diff)
downloadFreeBSD-src-f2eeadb198afb89ff67c9589eff8c717036632d2.zip
FreeBSD-src-f2eeadb198afb89ff67c9589eff8c717036632d2.tar.gz
Remove the PCI_IOSPACE_SIZE and PCI_IOSPACE_ADDR hack from nexus.c. Implement
this in the Sibyte PCI hostbridge driver instead. The nexus driver sees resource allocation requests for memory and irq resources only. These are legitimate resources on all MIPS platforms. Suggested by: imp
Diffstat (limited to 'sys/mips/sibyte')
-rw-r--r--sys/mips/sibyte/sb_zbpci.c132
1 files changed, 126 insertions, 6 deletions
diff --git a/sys/mips/sibyte/sb_zbpci.c b/sys/mips/sibyte/sb_zbpci.c
index 4e57407..6107b36 100644
--- a/sys/mips/sibyte/sb_zbpci.c
+++ b/sys/mips/sibyte/sb_zbpci.c
@@ -30,6 +30,7 @@
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/rman.h>
#include <sys/pcpu.h>
#include <sys/smp.h>
@@ -45,6 +46,7 @@
#include <machine/pmap.h>
#include <machine/resource.h>
+#include <machine/bus.h>
#include "pcib_if.h"
@@ -58,7 +60,11 @@ static struct {
} zbpci_config_space[MAXCPU];
static const vm_paddr_t CFG_PADDR_BASE = 0xFE000000;
-
+static const u_long PCI_IOSPACE_ADDR = 0xFC000000;
+static const u_long PCI_IOSPACE_SIZE = 0x02000000;
+
+static struct rman port_rman;
+
static int
zbpci_probe(device_t dev)
{
@@ -73,13 +79,32 @@ zbpci_attach(device_t dev)
int n, rid, size;
vm_offset_t va;
struct resource *res;
+
+ /*
+ * Reserve the physical memory window used to map PCI I/O space.
+ */
+ rid = 0;
+ res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ PCI_IOSPACE_ADDR,
+ PCI_IOSPACE_ADDR + PCI_IOSPACE_SIZE - 1,
+ PCI_IOSPACE_SIZE, 0);
+ if (res == NULL)
+ panic("Cannot allocate resource for PCI I/O space mapping.");
+
+ port_rman.rm_start = 0;
+ port_rman.rm_end = PCI_IOSPACE_SIZE - 1;
+ port_rman.rm_type = RMAN_ARRAY;
+ port_rman.rm_descr = "PCI I/O ports";
+ if (rman_init(&port_rman) != 0 ||
+ rman_manage_region(&port_rman, 0, PCI_IOSPACE_SIZE - 1) != 0)
+ panic("%s: port_rman", __func__);
/*
* Reserve the the physical memory that is used to read/write to the
* pci config space but don't activate it. We are using a page worth
* of KVA as a window over this region.
*/
- rid = 0;
+ rid = 1;
size = (PCI_BUSMAX + 1) * (PCI_SLOTMAX + 1) * (PCI_FUNCMAX + 1) * 256;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, CFG_PADDR_BASE,
CFG_PADDR_BASE + size - 1, size, 0);
@@ -115,6 +140,101 @@ zbpci_attach(device_t dev)
return (bus_generic_attach(dev));
}
+static struct resource *
+zbpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *res;
+
+ /*
+ * Handle PCI I/O port resources here and pass everything else to nexus.
+ */
+ if (type != SYS_RES_IOPORT) {
+ res = bus_generic_alloc_resource(bus, child, type, rid,
+ start, end, count, flags);
+ return (res);
+ }
+
+ res = rman_reserve_resource(&port_rman, start, end, count,
+ flags, child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_rid(res, *rid);
+
+ /* Activate the resource is requested */
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, res) != 0) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ }
+
+ return (res);
+}
+
+static int
+zbpci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ void *vaddr;
+ u_long paddr, psize;
+
+ if (type != SYS_RES_IOPORT) {
+ return (bus_generic_activate_resource(bus, child, type,
+ rid, res));
+ }
+
+ /*
+ * Map the I/O space resource through the memory window starting
+ * at PCI_IOSPACE_ADDR.
+ */
+ paddr = rman_get_start(res) + PCI_IOSPACE_ADDR;
+ psize = rman_get_size(res);
+ vaddr = pmap_mapdev(paddr, psize);
+
+ rman_set_virtual(res, vaddr);
+ rman_set_bustag(res, mips_bus_space_generic);
+ rman_set_bushandle(res, (bus_space_handle_t)vaddr);
+
+ return (rman_activate_resource(res));
+}
+
+static int
+zbpci_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ int error;
+
+ if (type != SYS_RES_IOPORT)
+ return (bus_generic_release_resource(bus, child, type, rid, r));
+
+ if (rman_get_flags(r) & RF_ACTIVE) {
+ error = bus_deactivate_resource(child, type, rid, r);
+ if (error)
+ return (error);
+ }
+
+ return (rman_release_resource(r));
+}
+
+static int
+zbpci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ vm_offset_t va;
+
+ if (type != SYS_RES_IOPORT) {
+ return (bus_generic_deactivate_resource(bus, child, type,
+ rid, r));
+ }
+
+ va = (vm_offset_t)rman_get_virtual(r);
+ pmap_unmapdev(va, rman_get_size(r));
+
+ return (rman_deactivate_resource(r));
+}
+
static int
zbpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
@@ -248,10 +368,10 @@ static device_method_t zbpci_methods[] ={
/* Bus interface */
DEVMETHOD(bus_read_ivar, zbpci_read_ivar),
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
- DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_alloc_resource, zbpci_alloc_resource),
+ DEVMETHOD(bus_activate_resource, zbpci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, zbpci_deactivate_resource),
+ DEVMETHOD(bus_release_resource, zbpci_release_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_add_child, bus_generic_add_child),
OpenPOWER on IntegriCloud