1 /* 2 * djMEMC, macintosh memory and interrupt controller 3 * (Quadra 610/650/800 & Centris 610/650) 4 * 5 * https://mac68k.info/wiki/display/mac68k/djMEMC+Information 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/misc/djmemc.h" 14 #include "hw/qdev-properties.h" 15 #include "trace.h" 16 17 18 #define DJMEMC_INTERLEAVECONF 0x0 19 #define DJMEMC_BANK0CONF 0x4 20 #define DJMEMC_BANK1CONF 0x8 21 #define DJMEMC_BANK2CONF 0xc 22 #define DJMEMC_BANK3CONF 0x10 23 #define DJMEMC_BANK4CONF 0x14 24 #define DJMEMC_BANK5CONF 0x18 25 #define DJMEMC_BANK6CONF 0x1c 26 #define DJMEMC_BANK7CONF 0x20 27 #define DJMEMC_BANK8CONF 0x24 28 #define DJMEMC_BANK9CONF 0x28 29 #define DJMEMC_MEMTOP 0x2c 30 #define DJMEMC_CONFIG 0x30 31 #define DJMEMC_REFRESH 0x34 32 33 34 static uint64_t djmemc_read(void *opaque, hwaddr addr, unsigned size) 35 { 36 DJMEMCState *s = opaque; 37 uint64_t val = 0; 38 39 switch (addr) { 40 case DJMEMC_INTERLEAVECONF: 41 case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF: 42 case DJMEMC_MEMTOP: 43 case DJMEMC_CONFIG: 44 case DJMEMC_REFRESH: 45 val = s->regs[addr >> 2]; 46 break; 47 default: 48 qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented read addr=0x%"PRIx64 49 " val=0x%"PRIx64 " size=%d\n", 50 addr, val, size); 51 } 52 53 trace_djmemc_read(addr, val, size); 54 return val; 55 } 56 57 static void djmemc_write(void *opaque, hwaddr addr, uint64_t val, 58 unsigned size) 59 { 60 DJMEMCState *s = opaque; 61 62 trace_djmemc_write(addr, val, size); 63 64 switch (addr) { 65 case DJMEMC_INTERLEAVECONF: 66 case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF: 67 case DJMEMC_MEMTOP: 68 case DJMEMC_CONFIG: 69 case DJMEMC_REFRESH: 70 s->regs[addr >> 2] = val; 71 break; 72 default: 73 qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented write addr=0x%"PRIx64 74 " val=0x%"PRIx64 " size=%d\n", 75 addr, val, size); 76 } 77 } 78 79 static const MemoryRegionOps djmemc_mmio_ops = { 80 .read = djmemc_read, 81 .write = djmemc_write, 82 .impl = { 83 .min_access_size = 4, 84 .max_access_size = 4, 85 }, 86 .endianness = DEVICE_BIG_ENDIAN, 87 }; 88 89 static void djmemc_init(Object *obj) 90 { 91 DJMEMCState *s = DJMEMC(obj); 92 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 93 94 memory_region_init_io(&s->mem_regs, obj, &djmemc_mmio_ops, s, "djMEMC", 95 DJMEMC_SIZE); 96 sysbus_init_mmio(sbd, &s->mem_regs); 97 } 98 99 static void djmemc_reset_hold(Object *obj) 100 { 101 DJMEMCState *s = DJMEMC(obj); 102 103 memset(s->regs, 0, sizeof(s->regs)); 104 } 105 106 static const VMStateDescription vmstate_djmemc = { 107 .name = "djMEMC", 108 .version_id = 1, 109 .minimum_version_id = 1, 110 .fields = (const VMStateField[]) { 111 VMSTATE_UINT32_ARRAY(regs, DJMEMCState, DJMEMC_NUM_REGS), 112 VMSTATE_END_OF_LIST() 113 } 114 }; 115 116 static void djmemc_class_init(ObjectClass *oc, void *data) 117 { 118 DeviceClass *dc = DEVICE_CLASS(oc); 119 ResettableClass *rc = RESETTABLE_CLASS(oc); 120 121 dc->vmsd = &vmstate_djmemc; 122 rc->phases.hold = djmemc_reset_hold; 123 } 124 125 static const TypeInfo djmemc_info_types[] = { 126 { 127 .name = TYPE_DJMEMC, 128 .parent = TYPE_SYS_BUS_DEVICE, 129 .instance_size = sizeof(DJMEMCState), 130 .instance_init = djmemc_init, 131 .class_init = djmemc_class_init, 132 }, 133 }; 134 135 DEFINE_TYPES(djmemc_info_types) 136