aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--sys/conf/options.mips8
-rw-r--r--sys/mips/conf/SWARM3
-rw-r--r--sys/mips/mips/nexus.c36
-rw-r--r--sys/mips/sibyte/sb_zbpci.c132
4 files changed, 132 insertions, 47 deletions
diff --git a/sys/conf/options.mips b/sys/conf/options.mips
index 409175983126..d3b8767ce18d 100644
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -61,14 +61,6 @@ TICK_USE_YAMON_FREQ opt_global.h
TICK_USE_MALTA_RTC opt_global.h
#
-# The MIPS architecture does not have separate memory and i/o address space
-# like x86. However some MIPS processors provide a memory-mapped window that
-# maps onto the PCI I/O space.
-#
-PCI_IOSPACE_SIZE opt_global.h
-PCI_IOSPACE_ADDR opt_global.h
-
-#
# The highest memory address that can be used by the kernel in units of KB.
#
MAXMEM opt_global.h
diff --git a/sys/mips/conf/SWARM b/sys/mips/conf/SWARM
index 6ce85a475cde..2c55533db14f 100644
--- a/sys/mips/conf/SWARM
+++ b/sys/mips/conf/SWARM
@@ -8,9 +8,6 @@ options CPU_SB1
files "../sibyte/files.sibyte"
hints "SWARM.hints"
-options PCI_IOSPACE_ADDR=0xFC000000
-options PCI_IOSPACE_SIZE=0x02000000
-
#
# 32-bit kernel cannot deal with physical memory beyond 4GB
# XXX pmap assumes that all the memory can be mapped using KSEG0
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index a325f3ebb9fd..7d3f1902fe3c 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -77,7 +77,6 @@ struct nexus_device {
static struct rman irq_rman;
static struct rman mem_rman;
-static struct rman port_rman;
static struct resource *
nexus_alloc_resource(device_t, device_t, int, int *, u_long,
@@ -161,21 +160,6 @@ nexus_probe(device_t dev)
panic("%s: mem_rman", __func__);
}
- /*
- * MIPS has no concept of the x86 I/O address space but some cpus
- * provide a memory mapped window to access the PCI I/O BARs.
- */
- port_rman.rm_start = 0;
-#ifdef PCI_IOSPACE_SIZE
- port_rman.rm_end = PCI_IOSPACE_SIZE - 1;
-#endif
- port_rman.rm_type = RMAN_ARRAY;
- port_rman.rm_descr = "I/O ports";
- if (rman_init(&port_rman) != 0 ||
- rman_manage_region(&port_rman, 0, port_rman.rm_end) != 0)
- panic("%s: port_rman", __func__);
-
-
return (0);
}
@@ -241,7 +225,6 @@ nexus_print_all_resources(device_t dev)
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
return (retval);
}
@@ -368,9 +351,6 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
case SYS_RES_MEMORY:
rm = &mem_rman;
break;
- case SYS_RES_IOPORT:
- rm = &port_rman;
- break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
@@ -400,21 +380,17 @@ static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
+ void *vaddr;
+ u_int32_t paddr, psize;
+
/*
* If this is a memory resource, track the direct mapping
* in the uncached MIPS KSEG1 segment.
*/
- /* XXX we shouldn't be supporting sys_res_ioport here */
- if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
- caddr_t vaddr = 0;
- u_int32_t paddr;
- u_int32_t psize;
- u_int32_t poffs;
-
+ if (type == SYS_RES_MEMORY) {
paddr = rman_get_start(r);
psize = rman_get_size(r);
- poffs = paddr - trunc_page(paddr);
- vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
+ vaddr = pmap_mapdev(paddr, psize);
rman_set_virtual(r, vaddr);
rman_set_bustag(r, mips_bus_space_generic);
@@ -501,7 +477,7 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
{
vm_offset_t va;
- if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ if (type == SYS_RES_MEMORY) {
va = (vm_offset_t)rman_get_virtual(r);
pmap_unmapdev(va, rman_get_size(r));
}
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),