summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/pci-host/apb.c62
-rw-r--r--hw/sparc64/sun4u.c27
2 files changed, 61 insertions, 28 deletions
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 96e5d0b60d..b709456b97 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -155,6 +155,18 @@ typedef struct APBState {
     unsigned int nr_resets;
 } APBState;
 
+#define TYPE_PBM_PCI_BRIDGE "pbm-bridge"
+#define PBM_PCI_BRIDGE(obj) \
+    OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE)
+
+typedef struct PBMPCIBridge {
+    /*< private >*/
+    PCIBridge parent_obj;
+
+    /* Is this busA with in-built devices (ebus)? */
+    bool busA;
+} PBMPCIBridge;
+
 static inline void pbm_set_request(APBState *s, unsigned int irq_num)
 {
     APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
@@ -559,7 +571,7 @@ static uint64_t apb_config_readl (void *opaque,
 static const MemoryRegionOps apb_config_ops = {
     .read = apb_config_readl,
     .write = apb_config_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
 static void apb_pci_config_write(void *opaque, hwaddr addr,
@@ -568,7 +580,6 @@ static void apb_pci_config_write(void *opaque, hwaddr addr,
     APBState *s = opaque;
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
-    val = qemu_bswap_len(val, size);
     APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
     pci_data_write(phb->bus, addr, val, size);
 }
@@ -581,7 +592,6 @@ static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
 
     ret = pci_data_read(phb->bus, addr, size);
-    ret = qemu_bswap_len(ret, size);
     APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
     return ret;
 }
@@ -634,8 +644,6 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
 
 static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
 {
-    pci_bridge_initfn(dev, TYPE_PCI_BUS);
-
     /*
      * command register:
      * According to PCI bridge spec, after reset
@@ -645,16 +653,28 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
      *   the reset value should be zero unless the boot pin is tied high
      *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
      */
-    pci_set_word(dev->config + PCI_COMMAND,
-                 PCI_COMMAND_MEMORY);
+    uint16_t cmd = PCI_COMMAND_MEMORY;
+    PBMPCIBridge *br = PBM_PCI_BRIDGE(dev);
+
+    pci_bridge_initfn(dev, TYPE_PCI_BUS);
+
+    /* If initialising busA, ensure that we allow IO transactions so that
+       we get the early serial console until OpenBIOS configures the bridge */
+    if (br->busA) {
+        cmd |= PCI_COMMAND_IO;
+    }
+
+    pci_set_word(dev->config + PCI_COMMAND, cmd);
     pci_set_word(dev->config + PCI_STATUS,
                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                  PCI_STATUS_DEVSEL_MEDIUM);
+
+    pci_bridge_update_mappings(PCI_BRIDGE(br));
 }
 
 PCIBus *pci_apb_init(hwaddr special_base,
                      hwaddr mem_base,
-                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
+                     qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB,
                      qemu_irq **pbm_irqs)
 {
     DeviceState *dev;
@@ -703,20 +723,19 @@ PCIBus *pci_apb_init(hwaddr special_base,
 
     /* APB secondary busses */
     pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
-                                   "pbm-bridge");
+                                   TYPE_PBM_PCI_BRIDGE);
     br = PCI_BRIDGE(pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
-                       pci_apb_map_irq);
+    pci_bridge_map_irq(br, "pciB", pci_apb_map_irq);
     qdev_init_nofail(&pci_dev->qdev);
-    *bus2 = pci_bridge_get_sec_bus(br);
+    *busB = pci_bridge_get_sec_bus(br);
 
     pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
-                                   "pbm-bridge");
+                                   TYPE_PBM_PCI_BRIDGE);
     br = PCI_BRIDGE(pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
-                       pci_apb_map_irq);
+    pci_bridge_map_irq(br, "pciA", pci_apb_map_irq);
+    qdev_prop_set_bit(DEVICE(pci_dev), "busA", true);
     qdev_init_nofail(&pci_dev->qdev);
-    *bus3 = pci_bridge_get_sec_bus(br);
+    *busA = pci_bridge_get_sec_bus(br);
 
     return phb->bus;
 }
@@ -745,7 +764,7 @@ static void pci_pbm_reset(DeviceState *d)
 static const MemoryRegionOps pci_config_ops = {
     .read = apb_pci_config_read,
     .write = apb_pci_config_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int pci_pbm_init_device(SysBusDevice *dev)
@@ -836,6 +855,11 @@ static const TypeInfo pbm_host_info = {
     .class_init    = pbm_host_class_init,
 };
 
+static Property pbm_pci_properties[] = {
+    DEFINE_PROP_BOOL("busA", PBMPCIBridge, busA, false),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -851,12 +875,14 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->reset = pci_bridge_reset;
     dc->vmsd = &vmstate_pci_device;
+    dc->props = pbm_pci_properties;
 }
 
 static const TypeInfo pbm_pci_bridge_info = {
-    .name          = "pbm-bridge",
+    .name          = TYPE_PBM_PCI_BRIDGE,
     .parent        = TYPE_PCI_BRIDGE,
     .class_init    = pbm_pci_bridge_class_init,
+    .instance_size = sizeof(PBMPCIBridge),
 };
 
 static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index bbdb40c330..5e59269adc 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -224,13 +224,11 @@ static void isa_irq_handler(void *opaque, int n, int level)
 
 /* EBUS (Eight bit bus) bridge */
 static ISABus *
-pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
+pci_ebus_init(PCIDevice *pci_dev, qemu_irq *irqs)
 {
     qemu_irq *isa_irq;
-    PCIDevice *pci_dev;
     ISABus *isa_bus;
 
-    pci_dev = pci_create_simple(bus, devfn, "ebus");
     isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
     isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
     isa_bus_irqs(isa_bus, isa_irq);
@@ -428,7 +426,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     Nvram *nvram;
     unsigned int i;
     uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
-    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
+    PCIBus *pci_bus, *pci_busA, *pci_busB;
+    PCIDevice *ebus;
     ISABus *isa_bus;
     SysBusDevice *s;
     qemu_irq *ivec_irqs, *pbm_irqs;
@@ -447,12 +446,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     prom_init(hwdef->prom_addr, bios_name);
 
     ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX);
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
-                           &pci_bus3, &pbm_irqs);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA,
+                           &pci_busB, &pbm_irqs);
     pci_vga_init(pci_bus);
 
-    // XXX Should be pci_bus3
-    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
+    /* XXX Should be pci_busA */
+    ebus = pci_create_simple(pci_bus, -1, "ebus");
+    isa_bus = pci_ebus_init(ebus, pbm_irqs);
 
     i = 0;
     if (hwdef->console_serial_base) {
@@ -492,7 +492,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     /* Map NVRAM into I/O (ebus) space */
     nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59);
     s = SYS_BUS_DEVICE(nvram);
-    memory_region_add_subregion(get_system_io(), 0x2000,
+    memory_region_add_subregion(pci_address_space_io(ebus), 0x2000,
                                 sysbus_mmio_get_region(s, 0));
  
     initrd_size = 0;
@@ -512,7 +512,14 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
                            graphic_width, graphic_height, graphic_depth,
                            (uint8_t *)&nd_table[0].macaddr);
 
-    fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
+    dev = qdev_create(NULL, TYPE_FW_CFG_IO);
+    qdev_prop_set_bit(dev, "dma_enabled", false);
+    object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev), NULL);
+    qdev_init_nofail(dev);
+    memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT,
+                                &FW_CFG_IO(dev)->comb_iomem);
+
+    fw_cfg = FW_CFG(dev);
     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);