aboutsummaryrefslogtreecommitdiff
path: root/sys/mips/sibyte
diff options
context:
space:
mode:
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),