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 @@ -60,14 +60,6 @@ TARGET_XLR_XLS opt_global.h 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. # 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 #include #include +#include #include #include @@ -45,6 +46,7 @@ #include #include +#include #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),