diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/bonito.c | 146 |
1 files changed, 90 insertions, 56 deletions
diff --git a/hw/bonito.c b/hw/bonito.c index b990875cf0..062c701161 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -180,11 +180,14 @@ #define PCI_ADDR(busno,devno,funno,regno) \ ((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno)) -typedef PCIHostState BonitoState; +#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost" + +typedef struct BonitoState BonitoState; typedef struct PCIBonitoState { PCIDevice dev; + BonitoState *pcihost; uint32_t regs[BONITO_REGS]; @@ -218,7 +221,16 @@ typedef struct PCIBonitoState } PCIBonitoState; -PCIBonitoState * bonito_state; +#define BONITO_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE) + +struct BonitoState { + PCIHostState parent_obj; + + qemu_irq *pic; + + PCIBonitoState *pci_dev; +}; static void bonito_writel(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) @@ -314,9 +326,10 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - s->dev.config_write(&s->dev, addr, val, 4); + d->config_write(d, addr, val, 4); } static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr, @@ -324,9 +337,10 @@ static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr, { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr); - return s->dev.config_read(&s->dev, addr, 4); + return d->config_read(d, addr, 4); } /* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */ @@ -402,6 +416,7 @@ static const MemoryRegionOps bonito_cop_ops = { static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t cfgaddr; uint32_t idsel; uint32_t devno; @@ -423,13 +438,13 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr) regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET; if (idsel == 0) { - fprintf(stderr, "error in bonito pci config address" TARGET_FMT_plx + fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]); exit(1); } - pciaddr = PCI_ADDR(pci_bus_num(s->pcihost->bus), devno, funno, regno); + pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno); DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n", - cfgaddr, pciaddr, pci_bus_num(s->pcihost->bus), devno, funno, regno); + cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno); return pciaddr; } @@ -438,6 +453,8 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; @@ -449,24 +466,26 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val & 0xff, 1); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr&0x1)==0); + assert((addr & 0x1) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -475,24 +494,26 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 2); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val, 2); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val); - assert((addr&0x3)==0); + assert((addr & 0x3) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -501,18 +522,20 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr, } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); - pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 4); + phb->config_reg = (pciaddr) | (1u << 31); + pci_data_write(phb->bus, phb->config_reg, val, 4); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); } static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; @@ -524,24 +547,26 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1); + return pci_data_read(phb->bus, phb->config_reg, 1); } static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr); - assert((addr&0x1)==0); + assert((addr & 0x1) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -550,24 +575,26 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 2); + return pci_data_read(phb->bus, phb->config_reg, 2); } static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) { PCIBonitoState *s = opaque; + PCIDevice *d = PCI_DEVICE(s); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, SYS_BUS_DEVICE(s->pcihost)); uint32_t pciaddr; uint16_t status; DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr); - assert((addr&0x3) == 0); + assert((addr & 0x3) == 0); pciaddr = bonito_sbridge_pciaddr(s, addr); @@ -576,14 +603,14 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr) } /* set the pci address in s->config_reg */ - s->pcihost->config_reg = (pciaddr) | (1u << 31); + phb->config_reg = (pciaddr) | (1u << 31); /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */ - status = pci_get_word(s->dev.config + PCI_STATUS); + status = pci_get_word(d->config + PCI_STATUS); status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT); - pci_set_word(s->dev.config + PCI_STATUS, status); + pci_set_word(d->config + PCI_STATUS, status); - return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 4); + return pci_data_read(phb->bus, phb->config_reg, 4); } /* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */ @@ -607,13 +634,15 @@ static const MemoryRegionOps bonito_spciconf_ops = { static void pci_bonito_set_irq(void *opaque, int irq_num, int level) { - qemu_irq *pic = opaque; + BonitoState *s = opaque; + qemu_irq *pic = s->pic; + PCIBonitoState *bonito_state = s->pci_dev; int internal_irq = irq_num - BONITO_IRQ_BASE; - if (bonito_state->regs[BONITO_INTEDGE] & (1<<internal_irq)) { + if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) { qemu_irq_pulse(*pic); } else { /* level triggered */ - if (bonito_state->regs[BONITO_INTPOL] & (1<<internal_irq)) { + if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) { qemu_irq_raise(*pic); } else { qemu_irq_lower(*pic); @@ -673,13 +702,21 @@ static const VMStateDescription vmstate_bonito = { static int bonito_pcihost_initfn(SysBusDevice *dev) { + PCIHostState *phb = FROM_SYSBUS(PCIHostState, dev); + + phb->bus = pci_register_bus(DEVICE(dev), "pci", + pci_bonito_set_irq, pci_bonito_map_irq, dev, + get_system_memory(), get_system_io(), + 0x28, 32); + return 0; } static int bonito_initfn(PCIDevice *dev) { PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev); - SysBusDevice *sysbus = &s->pcihost->busdev; + SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); + PCIHostState *phb = FROM_SYSBUS(PCIHostState, sysbus); /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ pci_config_set_prog_interface(dev->config, 0x00); @@ -691,15 +728,15 @@ static int bonito_initfn(PCIDevice *dev) sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE); /* set the north bridge pci configure mapping */ - memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s, + memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s, "north-bridge-pci-config", BONITO_PCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &s->pcihost->conf_mem); + sysbus_init_mmio(sysbus, &phb->conf_mem); sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE); /* set the south bridge pci configure mapping */ - memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s, + memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s, "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE); - sysbus_init_mmio(sysbus, &s->pcihost->data_mem); + sysbus_init_mmio(sysbus, &phb->data_mem); sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE); memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s, @@ -742,28 +779,25 @@ static int bonito_initfn(PCIDevice *dev) PCIBus *bonito_init(qemu_irq *pic) { DeviceState *dev; - PCIBus *b; BonitoState *pcihost; + PCIHostState *phb; PCIBonitoState *s; PCIDevice *d; - dev = qdev_create(NULL, "Bonito-pcihost"); - pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); - b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, - pci_bonito_map_irq, pic, get_system_memory(), - get_system_io(), - 0x28, 32); - pcihost->bus = b; + dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE); + phb = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); + pcihost = BONITO_PCI_HOST_BRIDGE(dev); + pcihost->pic = pic; qdev_init_nofail(dev); /* set the pcihost pointer before bonito_initfn is called */ - d = pci_create(b, PCI_DEVFN(0, 0), "Bonito"); + d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito"); s = DO_UPCAST(PCIBonitoState, dev, d); s->pcihost = pcihost; - bonito_state = s; - qdev_init_nofail(&d->qdev); + pcihost->pci_dev = s; + qdev_init_nofail(DEVICE(d)); - return b; + return phb->bus; } static void bonito_class_init(ObjectClass *klass, void *data) @@ -798,7 +832,7 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo bonito_pcihost_info = { - .name = "Bonito-pcihost", + .name = TYPE_BONITO_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BonitoState), .class_init = bonito_pcihost_class_init, |