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