diff options
author | Don Dugger <n0ano@n0ano.com> | 2016-06-03 03:33:22 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.206> | 2016-06-03 03:33:23 +0000 |
commit | da27230f80795d0028333713f036d44c53cb0e68 (patch) | |
tree | b3d379eaf000adf72b36cb01cdf4d79c3e3f064c /qemu/roms/openbios/drivers/pci.c | |
parent | 0e68cb048bb8aadb14675f5d4286d8ab2fc35449 (diff) | |
parent | 437fd90c0250dee670290f9b714253671a990160 (diff) |
Merge "These changes are the raw update to qemu-2.6."
Diffstat (limited to 'qemu/roms/openbios/drivers/pci.c')
-rw-r--r-- | qemu/roms/openbios/drivers/pci.c | 147 |
1 files changed, 89 insertions, 58 deletions
diff --git a/qemu/roms/openbios/drivers/pci.c b/qemu/roms/openbios/drivers/pci.c index 366f4a17f..5062f302f 100644 --- a/qemu/roms/openbios/drivers/pci.c +++ b/qemu/roms/openbios/drivers/pci.c @@ -144,9 +144,16 @@ static void dump_reg_property(const char* description, int nreg, u32 *reg) } #endif -static unsigned long pci_bus_addr_to_host_addr(uint32_t ba) +static unsigned long pci_bus_addr_to_host_addr(int space, uint32_t ba) { - return arch->host_pci_base + (unsigned long)ba; + if (space == IO_SPACE) { + return arch->io_base + (unsigned long)ba; + } else if (space == MEMORY_SPACE_32) { + return arch->host_pci_base + (unsigned long)ba; + } else { + /* Return unaltered to aid debugging property values */ + return (unsigned long)ba; + } } static void @@ -340,22 +347,27 @@ ob_pci_encode_unit(int *idx) ss, dev, fn, buf); } -/* ( pci-addr.lo pci-addr.hi size -- virt ) */ +/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ static void ob_pci_map_in(int *idx) { phys_addr_t phys; uint32_t ba; - ucell size, virt; + ucell size, virt, tmp; + int space; PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); size = POP(); + tmp = POP(); POP(); ba = POP(); - phys = pci_bus_addr_to_host_addr(ba); + /* Get the space from the pci-addr.hi */ + space = ((tmp & PCI_RANGE_TYPE_MASK) >> 24); + + phys = pci_bus_addr_to_host_addr(space, ba); #if defined(CONFIG_OFMEM) ofmem_claim_phys(phys, size, 0); @@ -448,13 +460,18 @@ static void pci_host_set_ranges(const pci_config_t *config) int ncells; ncells = 0; - /* first encode PCI configuration space */ - { - ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + +#ifdef CONFIG_SPARC64 + /* While configuration space isn't mentioned in the IEEE-1275 PCI + bindings, it appears in the PCI host bridge ranges property in + real device trees. Hence we disable this range for all host + bridges except for SPARC, particularly as it causes Darwin/OS X + to incorrectly calculated PCI memory space ranges on PPC. */ + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, config->dev, 0, 0); ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); ncells += pci_encode_size(props + ncells, arch->cfg_len); - } +#endif if (arch->io_base) { ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, @@ -585,13 +602,18 @@ static void pci_set_AAPL_address(const pci_config_t *config) { phandle_t dev = get_cur_dev(); cell props[7]; - int ncells, i; + uint32_t mask; + int ncells, i, flags, space_code; ncells = 0; for (i = 0; i < 6; i++) { if (!config->assigned[i] || !config->sizes[i]) continue; - props[ncells++] = config->assigned[i] & ~0x0000000F; + pci_decode_pci_addr(config->assigned[i], + &flags, &space_code, &mask); + + props[ncells++] = pci_bus_addr_to_host_addr(space_code, + config->assigned[i] & ~mask); } if (ncells) set_property(dev, "AAPL,address", (char *)props, @@ -752,13 +774,19 @@ int macio_keylargo_config_cb (const pci_config_t *config) int vga_config_cb (const pci_config_t *config) { unsigned long rom; - uint32_t rom_size, size; + uint32_t rom_size, size, mask; + int flags, space_code; phandle_t ph; if (config->assigned[0] != 0x00000000) { setup_video(); - rom = pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F); + pci_decode_pci_addr(config->assigned[1], + &flags, &space_code, &mask); + + rom = pci_bus_addr_to_host_addr(space_code, + config->assigned[1] & ~0x0000000F); + rom_size = config->sizes[1]; ph = get_cur_dev(); @@ -824,7 +852,7 @@ int ebus_config_cb(const pci_config_t *config) ncells += pci_encode_phys_addr(props + ncells, flags, space_code, config->dev, PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), - 0); + config->assigned[i] & ~mask); props[ncells++] = config->sizes[i]; } @@ -997,7 +1025,10 @@ static void ob_pci_add_properties(phandle_t phandle, } pci_set_assigned_addresses(phandle, config, num_bars); - OLDWORLD(pci_set_AAPL_address(config)); + + if (is_apple()) { + pci_set_AAPL_address(config); + } PCI_DPRINTF("\n"); } @@ -1397,9 +1428,11 @@ static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigne static void ob_pci_host_set_interrupt_map(phandle_t host) { - phandle_t dnode = 0; - u32 props[128]; - int i; + phandle_t dnode = 0, pci_childnode = 0; + u32 props[128], intno; + int i, ncells, len; + u32 *val, addr; + char *reg; #if defined(CONFIG_PPC) phandle_t target_node; @@ -1420,16 +1453,22 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) target_node = find_dev("/pci/mac-io/escc/ch-b"); set_int_property(target_node, "interrupt-parent", dnode); + target_node = find_dev("/pci/mac-io/escc-legacy/ch-a"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/escc-legacy/ch-b"); + set_int_property(target_node, "interrupt-parent", dnode); + /* QEMU only emulates 2 of the 3 ata buses currently */ /* On a new world Mac these are not numbered but named by the * ATA version they support. Thus we have: ata-3, ata-3, ata-4 * On g3beige they all called just ide. - * We take ata-3 and ata-4 which seems to work for both - * at least for clients we care about */ - target_node = find_dev("/pci/mac-io/ata-3"); + * We take 2 x ata-3 buses which seems to work for + * at least the clients we care about */ + target_node = find_dev("/pci/mac-io/ata-3@20000"); set_int_property(target_node, "interrupt-parent", dnode); - target_node = find_dev("/pci/mac-io/ata-4"); + target_node = find_dev("/pci/mac-io/ata-3@21000"); set_int_property(target_node, "interrupt-parent", dnode); target_node = find_dev("/pci/mac-io/via-cuda"); @@ -1437,69 +1476,61 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) target_node = find_dev("/pci"); set_int_property(target_node, "interrupt-parent", dnode); - - /* openpic interrupt mapping */ - for (i = 0; i < (7*8); i += 7) { - props[i + PCI_INT_MAP_PCI0] = 0; - props[i + PCI_INT_MAP_PCI1] = 0; - props[i + PCI_INT_MAP_PCI2] = 0; - props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1 - props[i + PCI_INT_MAP_PIC_HANDLE] = dnode; - props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7]; - props[i + PCI_INT_MAP_PIC_POL] = 3; - } - set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0])); - - props[PCI_INT_MAP_PCI0] = 0; - props[PCI_INT_MAP_PCI1] = 0; - props[PCI_INT_MAP_PCI2] = 0; - props[PCI_INT_MAP_PCI_INT] = 0x7; - - set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); } -#elif defined(CONFIG_SPARC64) - int ncells, len; - u32 *val, addr; - char *reg; +#else + /* PCI host bridge is the default interrupt controller */ + dnode = host; +#endif /* Set interrupt-map for PCI devices with an interrupt pin present */ ncells = 0; PUSH(host); fword("child"); - dnode = POP(); - while (dnode) { - if (get_int_property(dnode, "interrupts", &len)) { - reg = get_property(dnode, "reg", &len); - if (reg) { + pci_childnode = POP(); + while (pci_childnode) { + intno = get_int_property(pci_childnode, "interrupts", &len); + if (len && intno) { + reg = get_property(pci_childnode, "reg", &len); + if (len && reg) { val = (u32 *)reg; for (i = 0; i < (len / sizeof(u32)); i += 5) { addr = val[i]; /* Device address is in 1st 32-bit word of encoded PCI address for config space */ - if (!(addr & 0x03000000)) { + if ((addr & PCI_RANGE_TYPE_MASK) == PCI_RANGE_CONFIG) { +#if defined(CONFIG_SPARC64) ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = 1; /* always interrupt pin 1 for QEMU */ - props[ncells++] = host; - props[ncells++] = SUN4U_INTERRUPT(addr, 1); + props[ncells++] = intno; + props[ncells++] = dnode; + props[ncells++] = SUN4U_INTERRUPT(addr, intno); +#elif defined(CONFIG_PPC) + ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); + props[ncells++] = intno; + props[ncells++] = dnode; + props[ncells++] = arch->irqs[intno - 1]; + props[ncells++] = 3; +#else + /* Keep compiler quiet */ + dnode = dnode; +#endif } } } } - PUSH(dnode); + PUSH(pci_childnode); fword("peer"); - dnode = POP(); + pci_childnode = POP(); } set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0])); props[0] = 0x0000f800; props[1] = 0x0; props[2] = 0x0; - props[3] = 7; + props[3] = 0x7; set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); -#endif } int ob_pci_init(void) |