1 /* 2 * QEMU IOSB emulation 3 * 4 * Copyright (c) 2019 Laurent Vivier 5 * Copyright (c) 2022 Mark Cave-Ayland 6 * 7 * SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qemu/log.h" 12 #include "migration/vmstate.h" 13 #include "hw/sysbus.h" 14 #include "hw/misc/iosb.h" 15 #include "trace.h" 16 17 #define IOSB_SIZE 0x2000 18 19 #define IOSB_CONFIG 0x0 20 #define IOSB_CONFIG2 0x100 21 #define IOSB_SONIC_SCSI 0x200 22 #define IOSB_REVISION 0x300 23 #define IOSB_SCSI_RESID 0x400 24 #define IOSB_BRIGHTNESS 0x500 25 #define IOSB_TIMEOUT 0x600 26 27 28 static uint64_t iosb_read(void *opaque, hwaddr addr, 29 unsigned size) 30 { 31 IOSBState *s = IOSB(opaque); 32 uint64_t val = 0; 33 34 switch (addr) { 35 case IOSB_CONFIG: 36 case IOSB_CONFIG2: 37 case IOSB_SONIC_SCSI: 38 case IOSB_REVISION: 39 case IOSB_SCSI_RESID: 40 case IOSB_BRIGHTNESS: 41 case IOSB_TIMEOUT: 42 val = s->regs[addr >> 8]; 43 break; 44 default: 45 qemu_log_mask(LOG_UNIMP, "IOSB: unimplemented read addr=0x%"PRIx64 46 " val=0x%"PRIx64 " size=%d\n", 47 addr, val, size); 48 } 49 50 trace_iosb_read(addr, val, size); 51 return val; 52 } 53 54 static void iosb_write(void *opaque, hwaddr addr, uint64_t val, 55 unsigned size) 56 { 57 IOSBState *s = IOSB(opaque); 58 59 switch (addr) { 60 case IOSB_CONFIG: 61 case IOSB_CONFIG2: 62 case IOSB_SONIC_SCSI: 63 case IOSB_REVISION: 64 case IOSB_SCSI_RESID: 65 case IOSB_BRIGHTNESS: 66 case IOSB_TIMEOUT: 67 s->regs[addr >> 8] = val; 68 break; 69 default: 70 qemu_log_mask(LOG_UNIMP, "IOSB: unimplemented write addr=0x%"PRIx64 71 " val=0x%"PRIx64 " size=%d\n", 72 addr, val, size); 73 } 74 75 trace_iosb_write(addr, val, size); 76 } 77 78 static const MemoryRegionOps iosb_mmio_ops = { 79 .read = iosb_read, 80 .write = iosb_write, 81 .endianness = DEVICE_BIG_ENDIAN, 82 }; 83 84 static void iosb_reset_hold(Object *obj, ResetType type) 85 { 86 IOSBState *s = IOSB(obj); 87 88 memset(s->regs, 0, sizeof(s->regs)); 89 90 /* BCLK 33 MHz */ 91 s->regs[IOSB_CONFIG >> 8] = 1; 92 } 93 94 static void iosb_init(Object *obj) 95 { 96 IOSBState *s = IOSB(obj); 97 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 98 99 memory_region_init_io(&s->mem_regs, obj, &iosb_mmio_ops, s, "IOSB", 100 IOSB_SIZE); 101 sysbus_init_mmio(sbd, &s->mem_regs); 102 } 103 104 static const VMStateDescription vmstate_iosb = { 105 .name = "IOSB", 106 .version_id = 1, 107 .minimum_version_id = 1, 108 .fields = (const VMStateField[]) { 109 VMSTATE_UINT32_ARRAY(regs, IOSBState, IOSB_REGS), 110 VMSTATE_END_OF_LIST() 111 } 112 }; 113 114 static void iosb_class_init(ObjectClass *oc, void *data) 115 { 116 DeviceClass *dc = DEVICE_CLASS(oc); 117 ResettableClass *rc = RESETTABLE_CLASS(oc); 118 119 dc->vmsd = &vmstate_iosb; 120 rc->phases.hold = iosb_reset_hold; 121 } 122 123 static const TypeInfo iosb_info_types[] = { 124 { 125 .name = TYPE_IOSB, 126 .parent = TYPE_SYS_BUS_DEVICE, 127 .instance_size = sizeof(IOSBState), 128 .instance_init = iosb_init, 129 .class_init = iosb_class_init, 130 }, 131 }; 132 133 DEFINE_TYPES(iosb_info_types) 134