aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/apb_pci.c22
-rw-r--r--hw/pci.c26
-rw-r--r--hw/pci.h1
3 files changed, 29 insertions, 20 deletions
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index f2ed136fda..fe8faa6d05 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -182,6 +182,25 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[irq_num], level);
}
+static void apb_pci_bridge_init(PCIBus *b)
+{
+ PCIDevice *dev = pci_bridge_get_device(b);
+
+ /*
+ * command register:
+ * According to PCI bridge spec, after reset
+ * bus master bit is off
+ * memory space enable bit is off
+ * According to manual (805-1251.pdf).
+ * 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 | PCI_COMMAND_MASTER);
+ dev->config[PCI_LATENCY_TIMER] = 0x10;
+ dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
+}
+
PCIBus *pci_apb_init(target_phys_addr_t special_base,
target_phys_addr_t mem_base,
qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
@@ -212,10 +231,13 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
pci_apb_map_irq,
"Advanced PCI Bus secondary bridge 1");
+ apb_pci_bridge_init(*bus2);
+
*bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
pci_apb_map_irq,
"Advanced PCI Bus secondary bridge 2");
+ apb_pci_bridge_init(*bus3);
return d->host_state.bus;
}
diff --git a/hw/pci.c b/hw/pci.c
index 8cf008d31d..0359f30010 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1217,29 +1217,10 @@ static int pci_bridge_initfn(PCIDevice *dev)
pci_config_set_vendor_id(s->dev.config, s->vid);
pci_config_set_device_id(s->dev.config, s->did);
- /* TODO: intial value
- * command register:
- * According to PCI bridge spec, after reset
- * bus master bit is off
- * memory space enable bit is off
- * According to manual (805-1251.pdf).(See abp_pbi.c for its links.)
- * the reset value should be zero unless the boot pin is tied high
- * (which is tru) and thus it should be PCI_COMMAND_MEMORY.
- *
- * For now, don't touch the value.
- * Later command register will be set to zero and apb_pci.c will
- * override the value.
- * Same for latency timer, and multi function bit of header type.
- */
- pci_set_word(dev->config + PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-
pci_set_word(dev->config + PCI_STATUS,
PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
- dev->config[PCI_LATENCY_TIMER] = 0x10;
- dev->config[PCI_HEADER_TYPE] =
- PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE;
+ dev->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE;
pci_set_word(dev->config + PCI_SEC_STATUS,
PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
return 0;
@@ -1269,6 +1250,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
return &s->bus;
}
+PCIDevice *pci_bridge_get_device(PCIBus *bus)
+{
+ return bus->parent_dev;
+}
+
static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
{
PCIDevice *pci_dev = (PCIDevice *)qdev;
diff --git a/hw/pci.h b/hw/pci.h
index 0baf69bd5d..3e8abad222 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -298,6 +298,7 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
void pci_info(Monitor *mon);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name);
+PCIDevice *pci_bridge_get_device(PCIBus *bus);
static inline void
pci_set_byte(uint8_t *config, uint8_t val)