qemu/hw/misc/unimp.c
<<
>>
Prefs
   1/* "Unimplemented" device
   2 *
   3 * This is a dummy device which accepts and logs all accesses.
   4 * It's useful for stubbing out regions of an SoC or board
   5 * map which correspond to devices that have not yet been
   6 * implemented. This is often sufficient to placate initial
   7 * guest device driver probing such that the system will
   8 * come up.
   9 *
  10 * Copyright Linaro Limited, 2017
  11 * Written by Peter Maydell
  12 */
  13
  14#include "qemu/osdep.h"
  15#include "hw/sysbus.h"
  16#include "hw/misc/unimp.h"
  17#include "qemu/log.h"
  18#include "qemu/module.h"
  19#include "qapi/error.h"
  20
  21static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
  22{
  23    UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
  24
  25    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read  "
  26                  "(size %d, offset 0x%0*" HWADDR_PRIx ")\n",
  27                  s->name, size, s->offset_fmt_width, offset);
  28    return 0;
  29}
  30
  31static void unimp_write(void *opaque, hwaddr offset,
  32                        uint64_t value, unsigned size)
  33{
  34    UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
  35
  36    qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
  37                  "(size %d, offset 0x%0*" HWADDR_PRIx
  38                  ", value 0x%0*" PRIx64 ")\n",
  39                  s->name, size, s->offset_fmt_width, offset, size << 1, value);
  40}
  41
  42static const MemoryRegionOps unimp_ops = {
  43    .read = unimp_read,
  44    .write = unimp_write,
  45    .impl.min_access_size = 1,
  46    .impl.max_access_size = 8,
  47    .valid.min_access_size = 1,
  48    .valid.max_access_size = 8,
  49    .endianness = DEVICE_NATIVE_ENDIAN,
  50};
  51
  52static void unimp_realize(DeviceState *dev, Error **errp)
  53{
  54    UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(dev);
  55
  56    if (s->size == 0) {
  57        error_setg(errp, "property 'size' not specified or zero");
  58        return;
  59    }
  60
  61    if (s->name == NULL) {
  62        error_setg(errp, "property 'name' not specified");
  63        return;
  64    }
  65
  66    s->offset_fmt_width = DIV_ROUND_UP(64 - clz64(s->size - 1), 4);
  67
  68    memory_region_init_io(&s->iomem, OBJECT(s), &unimp_ops, s,
  69                          s->name, s->size);
  70    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
  71}
  72
  73static Property unimp_properties[] = {
  74    DEFINE_PROP_UINT64("size", UnimplementedDeviceState, size, 0),
  75    DEFINE_PROP_STRING("name", UnimplementedDeviceState, name),
  76    DEFINE_PROP_END_OF_LIST(),
  77};
  78
  79static void unimp_class_init(ObjectClass *klass, void *data)
  80{
  81    DeviceClass *dc = DEVICE_CLASS(klass);
  82
  83    dc->realize = unimp_realize;
  84    device_class_set_props(dc, unimp_properties);
  85}
  86
  87static const TypeInfo unimp_info = {
  88    .name = TYPE_UNIMPLEMENTED_DEVICE,
  89    .parent = TYPE_SYS_BUS_DEVICE,
  90    .instance_size = sizeof(UnimplementedDeviceState),
  91    .class_init = unimp_class_init,
  92};
  93
  94static void unimp_register_types(void)
  95{
  96    type_register_static(&unimp_info);
  97}
  98
  99type_init(unimp_register_types)
 100