diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/apb_pci.c | 22 | ||||
-rw-r--r-- | hw/pci.c | 26 | ||||
-rw-r--r-- | hw/pci.h | 1 |
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; } @@ -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; @@ -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) |