qemu

Форк
0
/
lasi.c 
287 строк · 6.7 Кб
1
/*
2
 * HP-PARISC Lasi chipset emulation.
3
 *
4
 * (C) 2019 by Helge Deller <deller@gmx.de>
5
 *
6
 * This work is licensed under the GNU GPL license version 2 or later.
7
 *
8
 * Documentation available at:
9
 * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
10
 */
11

12
#include "qemu/osdep.h"
13
#include "qemu/units.h"
14
#include "qemu/log.h"
15
#include "qapi/error.h"
16
#include "trace.h"
17
#include "hw/irq.h"
18
#include "sysemu/sysemu.h"
19
#include "sysemu/runstate.h"
20
#include "migration/vmstate.h"
21
#include "qom/object.h"
22
#include "hw/misc/lasi.h"
23

24

25
static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
26
                                unsigned size, bool is_write,
27
                                MemTxAttrs attrs)
28
{
29
    bool ret = false;
30

31
    switch (addr) {
32
    case LASI_IRR:
33
    case LASI_IMR:
34
    case LASI_IPR:
35
    case LASI_ICR:
36
    case LASI_IAR:
37

38
    case LASI_LPT:
39
    case LASI_AUDIO:
40
    case LASI_AUDIO + 4:
41
    case LASI_UART:
42
    case LASI_LAN:
43
    case LASI_LAN + 12: /* LASI LAN MAC */
44
    case LASI_RTC:
45
    case LASI_FDC:
46

47
    case LASI_PCR ... LASI_AMR:
48
        ret = true;
49
    }
50

51
    trace_lasi_chip_mem_valid(addr, ret);
52
    return ret;
53
}
54

55
static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
56
                                             uint64_t *data, unsigned size,
57
                                             MemTxAttrs attrs)
58
{
59
    LasiState *s = opaque;
60
    MemTxResult ret = MEMTX_OK;
61
    uint32_t val;
62

63
    switch (addr) {
64
    case LASI_IRR:
65
        val = s->irr;
66
        break;
67
    case LASI_IMR:
68
        val = s->imr;
69
        break;
70
    case LASI_IPR:
71
        val = s->ipr;
72
        /* Any read to IPR clears the register.  */
73
        s->ipr = 0;
74
        break;
75
    case LASI_ICR:
76
        val = s->icr & ICR_BUS_ERROR_BIT; /* bus_error */
77
        break;
78
    case LASI_IAR:
79
        val = s->iar;
80
        break;
81

82
    case LASI_LPT:
83
    case LASI_UART:
84
    case LASI_LAN:
85
    case LASI_LAN + 12:
86
    case LASI_FDC:
87
        val = 0;
88
        break;
89
    case LASI_RTC:
90
        val = time(NULL);
91
        val += s->rtc_ref;
92
        break;
93

94
    case LASI_PCR:
95
    case LASI_VER:      /* only version 0 existed. */
96
    case LASI_IORESET:
97
        val = 0;
98
        break;
99
    case LASI_ERRLOG:
100
        val = s->errlog;
101
        break;
102
    case LASI_AMR:
103
        val = s->amr;
104
        break;
105

106
    default:
107
        /* Controlled by lasi_chip_mem_valid above. */
108
        g_assert_not_reached();
109
    }
110

111
    trace_lasi_chip_read(addr, val);
112

113
    *data = val;
114
    return ret;
115
}
116

117
static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
118
                                              uint64_t val, unsigned size,
119
                                              MemTxAttrs attrs)
120
{
121
    LasiState *s = opaque;
122

123
    trace_lasi_chip_write(addr, val);
124

125
    switch (addr) {
126
    case LASI_IRR:
127
        /* read-only.  */
128
        break;
129
    case LASI_IMR:
130
        s->imr = val;
131
        if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
132
            qemu_log_mask(LOG_GUEST_ERROR,
133
                "LASI: tried to set invalid %lx IMR value.\n",
134
                (unsigned long) val);
135
        }
136
        break;
137
    case LASI_IPR:
138
        /* Any write to IPR clears the register. */
139
        s->ipr = 0;
140
        break;
141
    case LASI_ICR:
142
        s->icr = val;
143
        /* if (val & ICR_TOC_BIT) issue_toc(); */
144
        break;
145
    case LASI_IAR:
146
        s->iar = val;
147
        break;
148

149
    case LASI_LPT:
150
        /* XXX: reset parallel port */
151
        break;
152
    case LASI_AUDIO:
153
    case LASI_AUDIO + 4:
154
        /* XXX: reset audio port */
155
        break;
156
    case LASI_UART:
157
        /* XXX: reset serial port */
158
        break;
159
    case LASI_LAN:
160
        /* XXX: reset LAN card */
161
        break;
162
    case LASI_FDC:
163
        /* XXX: reset Floppy controller */
164
        break;
165
    case LASI_RTC:
166
        s->rtc_ref = val - time(NULL);
167
        break;
168

169
    case LASI_PCR:
170
        if (val == 0x02) { /* immediately power off */
171
            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
172
        }
173
        break;
174
    case LASI_ERRLOG:
175
        s->errlog = val;
176
        break;
177
    case LASI_VER:
178
        /* read-only.  */
179
        break;
180
    case LASI_IORESET:
181
        break;  /* XXX: TODO: Reset various devices. */
182
    case LASI_AMR:
183
        s->amr = val;
184
        break;
185

186
    default:
187
        /* Controlled by lasi_chip_mem_valid above. */
188
        g_assert_not_reached();
189
    }
190
    return MEMTX_OK;
191
}
192

193
static const MemoryRegionOps lasi_chip_ops = {
194
    .read_with_attrs = lasi_chip_read_with_attrs,
195
    .write_with_attrs = lasi_chip_write_with_attrs,
196
    .endianness = DEVICE_BIG_ENDIAN,
197
    .valid = {
198
        .min_access_size = 1,
199
        .max_access_size = 4,
200
        .accepts = lasi_chip_mem_valid,
201
    },
202
    .impl = {
203
        .min_access_size = 1,
204
        .max_access_size = 4,
205
    },
206
};
207

208
static const VMStateDescription vmstate_lasi = {
209
    .name = "Lasi",
210
    .version_id = 2,
211
    .minimum_version_id = 1,
212
    .fields = (const VMStateField[]) {
213
        VMSTATE_UINT32(irr, LasiState),
214
        VMSTATE_UINT32(imr, LasiState),
215
        VMSTATE_UINT32(ipr, LasiState),
216
        VMSTATE_UINT32(icr, LasiState),
217
        VMSTATE_UINT32(iar, LasiState),
218
        VMSTATE_UINT32(errlog, LasiState),
219
        VMSTATE_UINT32(amr, LasiState),
220
        VMSTATE_UINT32_V(rtc_ref, LasiState, 2),
221
        VMSTATE_END_OF_LIST()
222
    }
223
};
224

225

226
static void lasi_set_irq(void *opaque, int irq, int level)
227
{
228
    LasiState *s = opaque;
229
    uint32_t bit = 1u << irq;
230

231
    if (level) {
232
        s->ipr |= bit;
233
        if (bit & s->imr) {
234
            uint32_t iar = s->iar;
235
            s->irr |= bit;
236
            if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
237
                stl_be_phys(&address_space_memory, iar & -32, iar & 31);
238
            }
239
        }
240
    }
241
}
242

243
static void lasi_reset(DeviceState *dev)
244
{
245
    LasiState *s = LASI_CHIP(dev);
246

247
    s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
248

249
    /* Real time clock (RTC), it's only one 32-bit counter @9000 */
250
    s->rtc_ref = 0;
251
}
252

253
static void lasi_init(Object *obj)
254
{
255
    LasiState *s = LASI_CHIP(obj);
256
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
257

258
    memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
259
                          s, "lasi", 0x100000);
260

261
    sysbus_init_mmio(sbd, &s->this_mem);
262

263
    qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
264
}
265

266
static void lasi_class_init(ObjectClass *klass, void *data)
267
{
268
    DeviceClass *dc = DEVICE_CLASS(klass);
269

270
    dc->reset = lasi_reset;
271
    dc->vmsd = &vmstate_lasi;
272
}
273

274
static const TypeInfo lasi_pcihost_info = {
275
    .name          = TYPE_LASI_CHIP,
276
    .parent        = TYPE_SYS_BUS_DEVICE,
277
    .instance_init = lasi_init,
278
    .instance_size = sizeof(LasiState),
279
    .class_init    = lasi_class_init,
280
};
281

282
static void lasi_register_types(void)
283
{
284
    type_register_static(&lasi_pcihost_info);
285
}
286

287
type_init(lasi_register_types)
288

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.