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
djmemc_read(void * opaque,hwaddr addr,unsigned size)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
djmemc_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)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
djmemc_init(Object * obj)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
djmemc_reset_hold(Object * obj,ResetType type)99 static void djmemc_reset_hold(Object *obj, ResetType type)
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
djmemc_class_init(ObjectClass * oc,void * data)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