SerialState currently inherits just from DeviceState and serial devices use SerialState as an "IP block". Since DeviceState doesn't have an API to provide MMIO regions or IRQs, all serial devices access attributes internal to SerialState directly. Fix this by having SerialState inherit from SysBusDevice.
In addition, SerialState doesn't participate in the reset framework while SysBusDevice does. This allows for implementing reset functionality more idiomatically. Signed-off-by: Bernhard Beschow <[email protected]> --- include/hw/char/serial.h | 4 ++-- hw/char/diva-gsp.c | 22 +++++++++++----------- hw/char/serial-isa.c | 19 ++++++++++++------- hw/char/serial-mm.c | 10 +++++----- hw/char/serial-pci-multi.c | 22 +++++++++++----------- hw/char/serial-pci.c | 13 +++++++------ hw/char/serial.c | 5 ++++- 7 files changed, 52 insertions(+), 43 deletions(-) diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index ea82ffac47..650fc27693 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -26,7 +26,7 @@ #ifndef HW_SERIAL_H #define HW_SERIAL_H -#include "hw/core/qdev.h" +#include "hw/core/sysbus.h" #include "chardev/char-fe.h" #include "system/memory.h" #include "qemu/fifo8.h" @@ -35,7 +35,7 @@ #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ struct SerialState { - DeviceState parent; + SysBusDevice parent; uint16_t divider; uint8_t rbr; /* receive register */ diff --git a/hw/char/diva-gsp.c b/hw/char/diva-gsp.c index 280d0413c6..60ddc78752 100644 --- a/hw/char/diva-gsp.c +++ b/hw/char/diva-gsp.c @@ -57,13 +57,13 @@ typedef struct PCIDivaSerialState { static void diva_pci_exit(PCIDevice *dev) { PCIDivaSerialState *pci = DO_UPCAST(PCIDivaSerialState, dev, dev); - SerialState *s; int i; for (i = 0; i < pci->ports; i++) { - s = pci->state + i; - qdev_unrealize(DEVICE(s)); - memory_region_del_subregion(&pci->membar, &s->io); + SysBusDevice *sbd = SYS_BUS_DEVICE(pci->state + i); + qdev_unrealize(DEVICE(sbd)); + memory_region_del_subregion(&pci->membar, + sysbus_mmio_get_region(sbd, 0)); g_free(pci->name[i]); } qemu_free_irqs(pci->irqs, pci->ports); @@ -118,7 +118,6 @@ static void diva_pci_realize(PCIDevice *dev, Error **errp) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); PCIDivaSerialState *pci = DO_UPCAST(PCIDivaSerialState, dev, dev); - SerialState *s; struct diva_info di = diva_get_diva_info(pc); size_t i, offset = 0; size_t portmask = di.omask; @@ -130,22 +129,23 @@ static void diva_pci_realize(PCIDevice *dev, Error **errp) pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, di.nports); for (i = 0; i < di.nports; i++) { - s = pci->state + i; - if (!qdev_realize(DEVICE(s), NULL, errp)) { + SysBusDevice *sbd = SYS_BUS_DEVICE(pci->state + i); + if (!sysbus_realize(sbd, errp)) { diva_pci_exit(dev); return; } - s->irq = pci->irqs[i]; + sysbus_connect_irq(sbd, 0, pci->irqs[i]); pci->name[i] = g_strdup_printf("uart #%zu", i + 1); - memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, - pci->name[i], 8); + memory_region_init_io(sysbus_mmio_get_region(sbd, 0), OBJECT(pci), + &serial_io_ops, sbd, pci->name[i], 8); /* calculate offset of given port based on bitmask */ while ((portmask & BIT(0)) == 0) { offset += 8; portmask >>= 1; } - memory_region_add_subregion(&pci->membar, offset, &s->io); + memory_region_add_subregion(&pci->membar, offset, + sysbus_mmio_get_region(sbd, 0)); offset += 8; portmask >>= 1; pci->ports++; diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index a4be0492c5..d3a401f56c 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -58,7 +58,7 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) static int index; ISADevice *isadev = ISA_DEVICE(dev); ISASerialState *isa = ISA_SERIAL(dev); - SerialState *s = &isa->state; + SysBusDevice *sbd = SYS_BUS_DEVICE(&isa->state); if (isa->index == -1) { isa->index = index; @@ -76,12 +76,13 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) } index++; - s->irq = isa_get_irq(isadev, isa->isairq); - qdev_realize(DEVICE(s), NULL, errp); + sysbus_realize(sbd, errp); + sysbus_connect_irq(sbd, 0, isa_get_irq(isadev, isa->isairq)); qdev_set_legacy_instance_id(dev, isa->iobase, 3); - memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8); - isa_register_ioport(isadev, &s->io, isa->iobase); + memory_region_init_io(sysbus_mmio_get_region(sbd, 0), OBJECT(isa), + &serial_io_ops, sbd, "serial", 8); + isa_register_ioport(isadev, sysbus_mmio_get_region(sbd, 0), isa->iobase); } static void serial_isa_build_aml(AcpiDevAmlIf *adev, Aml *scope) @@ -188,13 +189,17 @@ void serial_hds_isa_init(ISABus *bus, int from, int to) void isa_serial_set_iobase(ISADevice *serial, hwaddr iobase) { ISASerialState *s = ISA_SERIAL(serial); + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->state); serial->ioport_id = iobase; s->iobase = iobase; - memory_region_set_address(&s->state.io, s->iobase); + memory_region_set_address(sysbus_mmio_get_region(sbd, 0), s->iobase); } void isa_serial_set_enabled(ISADevice *serial, bool enabled) { - memory_region_set_enabled(&ISA_SERIAL(serial)->state.io, enabled); + ISASerialState *s = ISA_SERIAL(serial); + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->state); + + memory_region_set_enabled(sysbus_mmio_get_region(sbd, 0), enabled); } diff --git a/hw/char/serial-mm.c b/hw/char/serial-mm.c index 0e0be26fa9..de11498278 100644 --- a/hw/char/serial-mm.c +++ b/hw/char/serial-mm.c @@ -71,17 +71,17 @@ static const MemoryRegionOps serial_mm_ops[] = { static void serial_mm_realize(DeviceState *dev, Error **errp) { SerialMM *smm = SERIAL_MM(dev); - SerialState *s = &smm->serial; + SysBusDevice *sbd = SYS_BUS_DEVICE(&smm->serial); - if (!qdev_realize(DEVICE(s), NULL, errp)) { + if (!sysbus_realize(sbd, errp)) { return; } - memory_region_init_io(&s->io, OBJECT(dev), + memory_region_init_io(sysbus_mmio_get_region(sbd, 0), OBJECT(dev), &serial_mm_ops[smm->endianness], smm, "serial", 8 << smm->regshift); - sysbus_init_mmio(SYS_BUS_DEVICE(smm), &s->io); - sysbus_init_irq(SYS_BUS_DEVICE(smm), &smm->serial.irq); + sysbus_init_mmio(SYS_BUS_DEVICE(smm), sysbus_mmio_get_region(sbd, 0)); + sysbus_pass_irq(SYS_BUS_DEVICE(smm), SYS_BUS_DEVICE(sbd)); } static const VMStateDescription vmstate_serial_mm = { diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c index 17796b93dd..7545ab7425 100644 --- a/hw/char/serial-pci-multi.c +++ b/hw/char/serial-pci-multi.c @@ -51,13 +51,13 @@ typedef struct PCIMultiSerialState { static void multi_serial_pci_exit(PCIDevice *dev) { PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); - SerialState *s; int i; for (i = 0; i < pci->ports; i++) { - s = pci->state + i; - qdev_unrealize(DEVICE(s)); - memory_region_del_subregion(&pci->iobar, &s->io); + SysBusDevice *sbd = SYS_BUS_DEVICE(pci->state + i); + qdev_unrealize(DEVICE(sbd)); + memory_region_del_subregion(&pci->iobar, + sysbus_mmio_get_region(sbd, 0)); g_free(pci->name[i]); } } @@ -93,7 +93,6 @@ static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); - SerialState *s; size_t i, nports = multi_serial_get_port_count(pc); pci->dev.config[PCI_CLASS_PROG] = 2; /* 16550 compatible */ @@ -102,16 +101,17 @@ static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); for (i = 0; i < nports; i++) { - s = pci->state + i; - if (!qdev_realize(DEVICE(s), NULL, errp)) { + SysBusDevice *sbd = SYS_BUS_DEVICE(pci->state + i); + if (!sysbus_realize(sbd, errp)) { multi_serial_pci_exit(dev); return; } - s->irq = &pci->irqs[i]; + sysbus_connect_irq(sbd, 0, &pci->irqs[i]); pci->name[i] = g_strdup_printf("uart #%zu", i + 1); - memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, - pci->name[i], 8); - memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); + memory_region_init_io(sysbus_mmio_get_region(sbd, 0), OBJECT(pci), + &serial_io_ops, sbd, pci->name[i], 8); + memory_region_add_subregion(&pci->iobar, 8 * i, + sysbus_mmio_get_region(sbd, 0)); pci->ports++; } } diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index d8cacc9085..10a99592b6 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -46,18 +46,20 @@ OBJECT_DECLARE_SIMPLE_TYPE(PCISerialState, PCI_SERIAL) static void serial_pci_realize(PCIDevice *dev, Error **errp) { PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); - SerialState *s = &pci->state; + SysBusDevice *sbd = SYS_BUS_DEVICE(&pci->state); - if (!qdev_realize(DEVICE(s), NULL, errp)) { + if (!sysbus_realize(sbd, errp)) { return; } pci->dev.config[PCI_CLASS_PROG] = 2; /* 16550 compatible */ pci->dev.config[PCI_INTERRUPT_PIN] = 1; - s->irq = pci_allocate_irq(&pci->dev); + sysbus_connect_irq(sbd, 0, pci_allocate_irq(&pci->dev)); - memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8); - pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); + memory_region_init_io(sysbus_mmio_get_region(sbd, 0), OBJECT(pci), + &serial_io_ops, sbd, "serial", 8); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, + sysbus_mmio_get_region(sbd, 0)); } static void serial_pci_exit(PCIDevice *dev) @@ -66,7 +68,6 @@ static void serial_pci_exit(PCIDevice *dev) SerialState *s = &pci->state; qdev_unrealize(DEVICE(s)); - qemu_free_irq(s->irq); } static const VMStateDescription vmstate_pci_serial = { diff --git a/hw/char/serial.c b/hw/char/serial.c index 0f3469a1e8..c58337bd20 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -934,6 +934,9 @@ static void serial_realize(DeviceState *dev, Error **errp) serial_event, serial_be_change, s, NULL, true); fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH); fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH); + + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); } static void serial_unrealize(DeviceState *dev) @@ -984,7 +987,7 @@ static void serial_class_init(ObjectClass *klass, const void *data) static const TypeInfo serial_info = { .name = TYPE_SERIAL, - .parent = TYPE_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SerialState), .class_init = serial_class_init, }; -- 2.53.0
