aboutsummaryrefslogtreecommitdiff
path: root/sys/mips/sibyte
diff options
context:
space:
mode:
authorNeel Natu <neel@FreeBSD.org>2010-02-12 02:59:49 +0000
committerNeel Natu <neel@FreeBSD.org>2010-02-12 02:59:49 +0000
commit9dcae110dc19a28c5cc7fc4bb31234d08585d784 (patch)
tree5a183fa578b3061ceb9f3dccb39c3b9fd5346bd2 /sys/mips/sibyte
parent0b86b1bb019bf449a62d1247b678069ee1cbe430 (diff)
downloadsrc-9dcae110dc19a28c5cc7fc4bb31234d08585d784.tar.gz
src-9dcae110dc19a28c5cc7fc4bb31234d08585d784.zip
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
Notes
Notes: svn path=/head/; revision=203796
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 4e57407533f3..6107b36cc414 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),