diff options
Diffstat (limited to 'hw/apb_pci.c')
-rw-r--r-- | hw/apb_pci.c | 103 |
1 files changed, 71 insertions, 32 deletions
diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 9f2a44d551..8b42fa8690 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -26,7 +26,7 @@ Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is the secondary PCI bridge. */ -#include "hw.h" +#include "sysbus.h" #include "pci.h" /* debug APB */ @@ -42,7 +42,10 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) typedef target_phys_addr_t pci_addr_t; #include "pci_host.h" -typedef PCIHostState APBState; +typedef struct APBState { + SysBusDevice busdev; + PCIHostState host_state; +} APBState; static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val) @@ -54,7 +57,7 @@ static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr, #endif APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr, val); - s->config_reg = val; + s->host_state.config_reg = val; } static uint32_t pci_apb_config_readl (void *opaque, @@ -63,7 +66,7 @@ static uint32_t pci_apb_config_readl (void *opaque, APBState *s = opaque; uint32_t val; - val = s->config_reg; + val = s->host_state.config_reg; #ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val); #endif @@ -225,34 +228,65 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base, qemu_irq *pic, PCIBus **bus2, PCIBus **bus3) { - APBState *s; - PCIDevice *d; - int pci_mem_config, pci_mem_data, apb_config, pci_ioport; + DeviceState *dev; + SysBusDevice *s; + APBState *d; - s = qemu_mallocz(sizeof(APBState)); /* Ultrasparc PBM main bus */ - s->bus = pci_register_bus(NULL, "pci", - pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32); + dev = qdev_create(NULL, "pbm"); + qdev_init(dev); + s = sysbus_from_qdev(dev); + /* apb_config */ + sysbus_mmio_map(s, 0, special_base + 0x2000ULL); + /* pci_ioport */ + sysbus_mmio_map(s, 1, special_base + 0x2000000ULL); + /* mem_config: XXX size should be 4G-prom */ + sysbus_mmio_map(s, 2, special_base + 0x1000000ULL); + /* mem_data */ + sysbus_mmio_map(s, 3, mem_base); + d = FROM_SYSBUS(APBState, s); + d->host_state.bus = pci_register_bus(NULL, "pci", + pci_apb_set_irq, pci_pbm_map_irq, pic, + 0, 32); + pci_create_simple(d->host_state.bus, 0, "pbm"); + /* APB secondary busses */ + *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN, + PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq, + "Advanced PCI Bus secondary bridge 1"); + *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN, + PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq, + "Advanced PCI Bus secondary bridge 2"); - pci_mem_config = cpu_register_io_memory(pci_apb_config_read, - pci_apb_config_write, s); + return d->host_state.bus; +} + +static void pci_pbm_init_device(SysBusDevice *dev) +{ + + APBState *s; + int pci_mem_config, pci_mem_data, apb_config, pci_ioport; + + s = FROM_SYSBUS(APBState, dev); + /* apb_config */ apb_config = cpu_register_io_memory(apb_config_read, apb_config_write, s); - pci_mem_data = cpu_register_io_memory(pci_apb_read, - pci_apb_write, s); + sysbus_init_mmio(dev, 0x40ULL, apb_config); + /* pci_ioport */ pci_ioport = cpu_register_io_memory(pci_apb_ioread, pci_apb_iowrite, s); + sysbus_init_mmio(dev, 0x10000ULL, pci_ioport); + /* mem_config */ + pci_mem_config = cpu_register_io_memory(pci_apb_config_read, + pci_apb_config_write, s); + sysbus_init_mmio(dev, 0x10ULL, pci_mem_config); + /* mem_data */ + pci_mem_data = cpu_register_io_memory(pci_apb_read, + pci_apb_write, &s->host_state); + sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data); +} - cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config); - cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, - pci_mem_config); - cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, - pci_ioport); - cpu_register_physical_memory(mem_base, 0x10000000, - pci_mem_data); // XXX size should be 4G-prom - - d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice), - 0, NULL, NULL); +static void pbm_pci_host_init(PCIDevice *d) +{ pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN); pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE); d->config[0x04] = 0x06; // command = bus master, pci mem @@ -264,13 +298,18 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0D] = 0x10; // latency_timer d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type +} - /* APB secondary busses */ - *bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN, - PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq, - "Advanced PCI Bus secondary bridge 1"); - *bus3 = pci_bridge_init(s->bus, 9, PCI_VENDOR_ID_SUN, - PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq, - "Advanced PCI Bus secondary bridge 2"); - return s->bus; +static PCIDeviceInfo pbm_pci_host_info = { + .qdev.name = "pbm", + .qdev.size = sizeof(PCIDevice), + .init = pbm_pci_host_init, +}; + +static void pbm_register_devices(void) +{ + sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device); + pci_qdev_register(&pbm_pci_host_info); } + +device_init(pbm_register_devices) |