Peter Maydell <peter.mayd...@linaro.org> writes: > The lack of a write-only-memory device is a gaping hole in QEMU's > otherwise comprehensive range of device models. This patch implements > a model of the popular Signetics 25120 9046xN random access WOM.
Applied, thanks. Regards, Anthony Liguori > --- > hw/Makefile.objs | 2 + > hw/wom.c | 127 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 129 insertions(+) > create mode 100644 hw/wom.c > > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index d0b2ecb..f26b593 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -195,6 +195,8 @@ common-obj-y += bt-hci-csr.o > common-obj-y += ps2.o > common-obj-y += qdev-properties-system.o > > +common-obj-y += wom.o > + > # xen backend driver support > common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o > common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o > xen_nic.o > diff --git a/hw/wom.c b/hw/wom.c > new file mode 100644 > index 0000000..ff3c66c > --- /dev/null > +++ b/hw/wom.c > @@ -0,0 +1,127 @@ > +// > +// Signetics 25120 9046xN random access write only memory > +// > +// Written by Peter Maydell > +// > +// This code is licensed under the Shrove Tuesday Public Licence > +// You should have received a copy of the STPL along with this code; > +// if not, see > +// http://www.chiark.greenend.org.uk/~christi/public/initview/LICENCE > +// > +// Datasheet for this chip available here: > +// > http://www2.vmi.edu/Faculty/squirejc/Research/IC_Datasheets/digital_cmos/Write%20Only%20Memory.pdf > + > +// TODO : consider adding WOM support to QEMU core memory system > +// for improved efficiency and symmetry with ROM support > + > +#include "hw/sysbus.h" > + > +#define WOMSIZE 9046 > + > +typedef struct wom_state { > + SysBusDevice parent_obj; > + MemoryRegion iomem; > + qemu_irq irq[30]; > + uint8_t memory[WOMSIZE]; > + uint32_t numinsertions; > +} wom_state; > + > +#define TYPE_WOM "wom" > +#define WOM(obj) OBJECT_CHECK(wom_state, (obj), TYPE_WOM) > + > +static uint64_t wom_read(void *opaque, hwaddr offset, unsigned size) > +{ > + qemu_log_mask(LOG_GUEST_ERROR, "wom_read: attempt to read from write only > memory\n"); > + > + return 0xdeadbeef; > +} > + > +static void wom_write(void *opaque, hwaddr offset, uint64_t value, > + unsigned size) > +{ > + // Most important feature of this device > + wom_state *s = (wom_state *)opaque; > + assert(offset < WOMSIZE); > + s->memory[offset] = value; > +} > + > +static const MemoryRegionOps wom_ops = { > + .read = wom_read, > + .write = wom_write, > + .endianness = DEVICE_NATIVE_ENDIAN, > +}; > + > +static void wom_set_chipdestruct(void *opaque, int line, int level) > +{ > + // Self-destruct signal > + if (0 != level) > + { > + // We use hw_error to simulate a blown-up chip taking out the rest of > the board > + hw_error("WOM has self-destructed!\n"); > + } > +} > + > +static void wom_reset(DeviceState *dev) > +{ > + wom_state *s = WOM(dev); > + memset(s->memory, 0, WOMSIZE); > +} > + > +static void wom_realize(DeviceState *dev, Error **errp) > +{ > + wom_state *s = WOM(dev); > + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); > + > + // GPIO input 0 is the self-destruct signal > + qdev_init_gpio_in(dev, wom_set_chipdestruct, 1); > + > + // TODO: better model the relation between number of insertions and number > of pins to more > + // closely track the graph in the datasheet > + int numirqs = 30 / (s->numinsertions + 1); > + for (int i = 0; i < numirqs; i++) > + { > + sysbus_init_irq(sbd, &s->irq[i]); > + } > + > + memory_region_init_io(&s->iomem, &wom_ops, s, "wom", WOMSIZE); > + sysbus_init_mmio(sbd, &s->iomem); > +} > + > +static const VMStateDescription vmstate_wom = { > + .name = "wom", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8_ARRAY(memory, wom_state, WOMSIZE), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static Property wom_properties[] = { > + DEFINE_PROP_UINT32("num-insertions", wom_state, numinsertions, 0), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void wom_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->realize = wom_realize; > + dc->props = wom_properties; > + dc->vmsd = &vmstate_wom; > + dc->reset = wom_reset; > +} > + > +static const TypeInfo wom_info = { > + .name = TYPE_WOM, > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(wom_state), > + .class_init = wom_class_init, > +}; > + > +static void wom_register_types(void) > +{ > + type_register_static(&wom_info); > +} > + > +type_init(wom_register_types) > -- > 1.7.11.4