xref: /qemu/hw/misc/djmemc.c (revision bb302772)
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 = (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