Statistics
| Branch: | Revision:

root / hw / slavio_intctl.c @ 26a76461

History | View | Annotate | Download (10.8 kB)

1 e80cfcfc bellard
/*
2 e80cfcfc bellard
 * QEMU Sparc SLAVIO interrupt controller emulation
3 e80cfcfc bellard
 * 
4 66321a11 bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 e80cfcfc bellard
 * 
6 e80cfcfc bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e80cfcfc bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e80cfcfc bellard
 * in the Software without restriction, including without limitation the rights
9 e80cfcfc bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e80cfcfc bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e80cfcfc bellard
 * furnished to do so, subject to the following conditions:
12 e80cfcfc bellard
 *
13 e80cfcfc bellard
 * The above copyright notice and this permission notice shall be included in
14 e80cfcfc bellard
 * all copies or substantial portions of the Software.
15 e80cfcfc bellard
 *
16 e80cfcfc bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e80cfcfc bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e80cfcfc bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e80cfcfc bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e80cfcfc bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e80cfcfc bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e80cfcfc bellard
 * THE SOFTWARE.
23 e80cfcfc bellard
 */
24 e80cfcfc bellard
#include "vl.h"
25 e80cfcfc bellard
//#define DEBUG_IRQ_COUNT
26 66321a11 bellard
//#define DEBUG_IRQ
27 66321a11 bellard
28 66321a11 bellard
#ifdef DEBUG_IRQ
29 66321a11 bellard
#define DPRINTF(fmt, args...) \
30 66321a11 bellard
do { printf("IRQ: " fmt , ##args); } while (0)
31 66321a11 bellard
#else
32 66321a11 bellard
#define DPRINTF(fmt, args...)
33 66321a11 bellard
#endif
34 e80cfcfc bellard
35 e80cfcfc bellard
/*
36 e80cfcfc bellard
 * Registers of interrupt controller in sun4m.
37 e80cfcfc bellard
 *
38 e80cfcfc bellard
 * This is the interrupt controller part of chip STP2001 (Slave I/O), also
39 e80cfcfc bellard
 * produced as NCR89C105. See
40 e80cfcfc bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
41 e80cfcfc bellard
 *
42 e80cfcfc bellard
 * There is a system master controller and one for each cpu.
43 e80cfcfc bellard
 * 
44 e80cfcfc bellard
 */
45 e80cfcfc bellard
46 e80cfcfc bellard
#define MAX_CPUS 16
47 e80cfcfc bellard
48 e80cfcfc bellard
typedef struct SLAVIO_INTCTLState {
49 e80cfcfc bellard
    uint32_t intreg_pending[MAX_CPUS];
50 e80cfcfc bellard
    uint32_t intregm_pending;
51 e80cfcfc bellard
    uint32_t intregm_disabled;
52 e80cfcfc bellard
    uint32_t target_cpu;
53 e80cfcfc bellard
#ifdef DEBUG_IRQ_COUNT
54 e80cfcfc bellard
    uint64_t irq_count[32];
55 e80cfcfc bellard
#endif
56 ba3c64fb bellard
    CPUState *cpu_envs[MAX_CPUS];
57 e80cfcfc bellard
} SLAVIO_INTCTLState;
58 e80cfcfc bellard
59 e80cfcfc bellard
#define INTCTL_MAXADDR 0xf
60 e80cfcfc bellard
#define INTCTLM_MAXADDR 0xf
61 66321a11 bellard
static void slavio_check_interrupts(void *opaque);
62 e80cfcfc bellard
63 e80cfcfc bellard
// per-cpu interrupt controller
64 e80cfcfc bellard
static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
65 e80cfcfc bellard
{
66 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
67 e80cfcfc bellard
    uint32_t saddr;
68 e80cfcfc bellard
    int cpu;
69 e80cfcfc bellard
70 e80cfcfc bellard
    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
71 e80cfcfc bellard
    saddr = (addr & INTCTL_MAXADDR) >> 2;
72 e80cfcfc bellard
    switch (saddr) {
73 e80cfcfc bellard
    case 0:
74 e80cfcfc bellard
        return s->intreg_pending[cpu];
75 e80cfcfc bellard
    default:
76 e80cfcfc bellard
        break;
77 e80cfcfc bellard
    }
78 e80cfcfc bellard
    return 0;
79 e80cfcfc bellard
}
80 e80cfcfc bellard
81 e80cfcfc bellard
static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
82 e80cfcfc bellard
{
83 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
84 e80cfcfc bellard
    uint32_t saddr;
85 e80cfcfc bellard
    int cpu;
86 e80cfcfc bellard
87 e80cfcfc bellard
    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
88 e80cfcfc bellard
    saddr = (addr & INTCTL_MAXADDR) >> 2;
89 e80cfcfc bellard
    switch (saddr) {
90 e80cfcfc bellard
    case 1: // clear pending softints
91 e80cfcfc bellard
        if (val & 0x4000)
92 e80cfcfc bellard
            val |= 80000000;
93 e80cfcfc bellard
        val &= 0xfffe0000;
94 e80cfcfc bellard
        s->intreg_pending[cpu] &= ~val;
95 66321a11 bellard
        DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
96 e80cfcfc bellard
        break;
97 e80cfcfc bellard
    case 2: // set softint
98 e80cfcfc bellard
        val &= 0xfffe0000;
99 e80cfcfc bellard
        s->intreg_pending[cpu] |= val;
100 ba3c64fb bellard
        slavio_check_interrupts(s);
101 66321a11 bellard
        DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
102 e80cfcfc bellard
        break;
103 e80cfcfc bellard
    default:
104 e80cfcfc bellard
        break;
105 e80cfcfc bellard
    }
106 e80cfcfc bellard
}
107 e80cfcfc bellard
108 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
109 e80cfcfc bellard
    slavio_intctl_mem_readl,
110 e80cfcfc bellard
    slavio_intctl_mem_readl,
111 e80cfcfc bellard
    slavio_intctl_mem_readl,
112 e80cfcfc bellard
};
113 e80cfcfc bellard
114 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
115 e80cfcfc bellard
    slavio_intctl_mem_writel,
116 e80cfcfc bellard
    slavio_intctl_mem_writel,
117 e80cfcfc bellard
    slavio_intctl_mem_writel,
118 e80cfcfc bellard
};
119 e80cfcfc bellard
120 e80cfcfc bellard
// master system interrupt controller
121 e80cfcfc bellard
static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
122 e80cfcfc bellard
{
123 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
124 e80cfcfc bellard
    uint32_t saddr;
125 e80cfcfc bellard
126 e80cfcfc bellard
    saddr = (addr & INTCTLM_MAXADDR) >> 2;
127 e80cfcfc bellard
    switch (saddr) {
128 e80cfcfc bellard
    case 0:
129 6bae7071 bellard
        return s->intregm_pending & 0x7fffffff;
130 e80cfcfc bellard
    case 1:
131 e80cfcfc bellard
        return s->intregm_disabled;
132 e80cfcfc bellard
    case 4:
133 e80cfcfc bellard
        return s->target_cpu;
134 e80cfcfc bellard
    default:
135 e80cfcfc bellard
        break;
136 e80cfcfc bellard
    }
137 e80cfcfc bellard
    return 0;
138 e80cfcfc bellard
}
139 e80cfcfc bellard
140 e80cfcfc bellard
static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
141 e80cfcfc bellard
{
142 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
143 e80cfcfc bellard
    uint32_t saddr;
144 e80cfcfc bellard
145 e80cfcfc bellard
    saddr = (addr & INTCTLM_MAXADDR) >> 2;
146 e80cfcfc bellard
    switch (saddr) {
147 e80cfcfc bellard
    case 2: // clear (enable)
148 6bae7071 bellard
        // Force clear unused bits
149 3475187d bellard
        val &= ~0x4fb2007f;
150 e80cfcfc bellard
        s->intregm_disabled &= ~val;
151 66321a11 bellard
        DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
152 66321a11 bellard
        slavio_check_interrupts(s);
153 e80cfcfc bellard
        break;
154 e80cfcfc bellard
    case 3: // set (disable, clear pending)
155 6bae7071 bellard
        // Force clear unused bits
156 3475187d bellard
        val &= ~0x4fb2007f;
157 e80cfcfc bellard
        s->intregm_disabled |= val;
158 e80cfcfc bellard
        s->intregm_pending &= ~val;
159 66321a11 bellard
        DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
160 e80cfcfc bellard
        break;
161 e80cfcfc bellard
    case 4:
162 e80cfcfc bellard
        s->target_cpu = val & (MAX_CPUS - 1);
163 66321a11 bellard
        DPRINTF("Set master irq cpu %d\n", s->target_cpu);
164 e80cfcfc bellard
        break;
165 e80cfcfc bellard
    default:
166 e80cfcfc bellard
        break;
167 e80cfcfc bellard
    }
168 e80cfcfc bellard
}
169 e80cfcfc bellard
170 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
171 e80cfcfc bellard
    slavio_intctlm_mem_readl,
172 e80cfcfc bellard
    slavio_intctlm_mem_readl,
173 e80cfcfc bellard
    slavio_intctlm_mem_readl,
174 e80cfcfc bellard
};
175 e80cfcfc bellard
176 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
177 e80cfcfc bellard
    slavio_intctlm_mem_writel,
178 e80cfcfc bellard
    slavio_intctlm_mem_writel,
179 e80cfcfc bellard
    slavio_intctlm_mem_writel,
180 e80cfcfc bellard
};
181 e80cfcfc bellard
182 e80cfcfc bellard
void slavio_pic_info(void *opaque)
183 e80cfcfc bellard
{
184 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
185 e80cfcfc bellard
    int i;
186 e80cfcfc bellard
187 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
188 e80cfcfc bellard
        term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
189 e80cfcfc bellard
    }
190 e80cfcfc bellard
    term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
191 e80cfcfc bellard
}
192 e80cfcfc bellard
193 e80cfcfc bellard
void slavio_irq_info(void *opaque)
194 e80cfcfc bellard
{
195 e80cfcfc bellard
#ifndef DEBUG_IRQ_COUNT
196 e80cfcfc bellard
    term_printf("irq statistic code not compiled.\n");
197 e80cfcfc bellard
#else
198 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
199 e80cfcfc bellard
    int i;
200 e80cfcfc bellard
    int64_t count;
201 e80cfcfc bellard
202 e80cfcfc bellard
    term_printf("IRQ statistics:\n");
203 e80cfcfc bellard
    for (i = 0; i < 32; i++) {
204 e80cfcfc bellard
        count = s->irq_count[i];
205 e80cfcfc bellard
        if (count > 0)
206 26a76461 bellard
            term_printf("%2d: %" PRId64 "\n", i, count);
207 e80cfcfc bellard
    }
208 e80cfcfc bellard
#endif
209 e80cfcfc bellard
}
210 e80cfcfc bellard
211 e80cfcfc bellard
static const uint32_t intbit_to_level[32] = {
212 e80cfcfc bellard
    2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
213 3475187d bellard
    6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
214 e80cfcfc bellard
};
215 e80cfcfc bellard
216 66321a11 bellard
static void slavio_check_interrupts(void *opaque)
217 66321a11 bellard
{
218 c68ea704 bellard
    CPUState *env;
219 66321a11 bellard
    SLAVIO_INTCTLState *s = opaque;
220 66321a11 bellard
    uint32_t pending = s->intregm_pending;
221 ba3c64fb bellard
    unsigned int i, j, max = 0;
222 66321a11 bellard
223 66321a11 bellard
    pending &= ~s->intregm_disabled;
224 66321a11 bellard
225 66321a11 bellard
    if (pending && !(s->intregm_disabled & 0x80000000)) {
226 66321a11 bellard
        for (i = 0; i < 32; i++) {
227 66321a11 bellard
            if (pending & (1 << i)) {
228 66321a11 bellard
                if (max < intbit_to_level[i])
229 66321a11 bellard
                    max = intbit_to_level[i];
230 66321a11 bellard
            }
231 66321a11 bellard
        }
232 ba3c64fb bellard
        env = s->cpu_envs[s->target_cpu];
233 ba3c64fb bellard
        if (!env) {
234 ba3c64fb bellard
            DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
235 ba3c64fb bellard
        }
236 ba3c64fb bellard
        else {
237 ba3c64fb bellard
            if (env->halted)
238 ba3c64fb bellard
                env->halted = 0;
239 ba3c64fb bellard
            if (env->interrupt_index == 0) {
240 ba3c64fb bellard
                DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
241 66321a11 bellard
#ifdef DEBUG_IRQ_COUNT
242 ba3c64fb bellard
                s->irq_count[max]++;
243 66321a11 bellard
#endif
244 ba3c64fb bellard
                env->interrupt_index = TT_EXTINT | max;
245 ba3c64fb bellard
                cpu_interrupt(env, CPU_INTERRUPT_HARD);
246 ba3c64fb bellard
            }
247 ba3c64fb bellard
            else
248 ba3c64fb bellard
                DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
249 66321a11 bellard
        }
250 66321a11 bellard
    }
251 66321a11 bellard
    else
252 66321a11 bellard
        DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
253 ba3c64fb bellard
    
254 ba3c64fb bellard
    for (i = 0; i < MAX_CPUS; i++) {
255 ba3c64fb bellard
        max = 0;
256 ba3c64fb bellard
        env = s->cpu_envs[i];
257 ba3c64fb bellard
        if (!env)
258 ba3c64fb bellard
            continue;
259 ba3c64fb bellard
        for (j = 17; j < 32; j++) {
260 ba3c64fb bellard
            if (s->intreg_pending[i] & (1 << j)) {
261 ba3c64fb bellard
                if (max < j - 16)
262 ba3c64fb bellard
                    max = j - 16;
263 ba3c64fb bellard
            }
264 ba3c64fb bellard
        }
265 ba3c64fb bellard
        if (max > 0) {
266 ba3c64fb bellard
            if (env->halted)
267 ba3c64fb bellard
                env->halted = 0;
268 ba3c64fb bellard
            if (env->interrupt_index == 0) {
269 ba3c64fb bellard
                DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
270 ba3c64fb bellard
#ifdef DEBUG_IRQ_COUNT
271 ba3c64fb bellard
                s->irq_count[max]++;
272 ba3c64fb bellard
#endif
273 ba3c64fb bellard
                env->interrupt_index = TT_EXTINT | max;
274 ba3c64fb bellard
                cpu_interrupt(env, CPU_INTERRUPT_HARD);
275 ba3c64fb bellard
            }
276 ba3c64fb bellard
        }
277 ba3c64fb bellard
    }
278 66321a11 bellard
}
279 66321a11 bellard
280 e80cfcfc bellard
/*
281 e80cfcfc bellard
 * "irq" here is the bit number in the system interrupt register to
282 e80cfcfc bellard
 * separate serial and keyboard interrupts sharing a level.
283 e80cfcfc bellard
 */
284 e80cfcfc bellard
void slavio_pic_set_irq(void *opaque, int irq, int level)
285 e80cfcfc bellard
{
286 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
287 e80cfcfc bellard
288 ba3c64fb bellard
    DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
289 e80cfcfc bellard
    if (irq < 32) {
290 e80cfcfc bellard
        uint32_t mask = 1 << irq;
291 e80cfcfc bellard
        uint32_t pil = intbit_to_level[irq];
292 e80cfcfc bellard
        if (pil > 0) {
293 e80cfcfc bellard
            if (level) {
294 e80cfcfc bellard
                s->intregm_pending |= mask;
295 e80cfcfc bellard
                s->intreg_pending[s->target_cpu] |= 1 << pil;
296 e80cfcfc bellard
            }
297 e80cfcfc bellard
            else {
298 e80cfcfc bellard
                s->intregm_pending &= ~mask;
299 e80cfcfc bellard
                s->intreg_pending[s->target_cpu] &= ~(1 << pil);
300 e80cfcfc bellard
            }
301 e80cfcfc bellard
        }
302 e80cfcfc bellard
    }
303 66321a11 bellard
    slavio_check_interrupts(s);
304 e80cfcfc bellard
}
305 e80cfcfc bellard
306 ba3c64fb bellard
void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
307 ba3c64fb bellard
{
308 ba3c64fb bellard
    SLAVIO_INTCTLState *s = opaque;
309 ba3c64fb bellard
310 ba3c64fb bellard
    DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
311 ba3c64fb bellard
    if (cpu == (unsigned int)-1) {
312 ba3c64fb bellard
        slavio_pic_set_irq(opaque, irq, level);
313 ba3c64fb bellard
        return;
314 ba3c64fb bellard
    }
315 ba3c64fb bellard
    if (irq < 32) {
316 ba3c64fb bellard
        uint32_t pil = intbit_to_level[irq];
317 ba3c64fb bellard
            if (pil > 0) {
318 ba3c64fb bellard
            if (level) {
319 ba3c64fb bellard
                s->intreg_pending[cpu] |= 1 << pil;
320 ba3c64fb bellard
            }
321 ba3c64fb bellard
            else {
322 ba3c64fb bellard
                s->intreg_pending[cpu] &= ~(1 << pil);
323 ba3c64fb bellard
            }
324 ba3c64fb bellard
        }
325 ba3c64fb bellard
    }
326 ba3c64fb bellard
    slavio_check_interrupts(s);
327 ba3c64fb bellard
}
328 ba3c64fb bellard
329 e80cfcfc bellard
static void slavio_intctl_save(QEMUFile *f, void *opaque)
330 e80cfcfc bellard
{
331 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
332 e80cfcfc bellard
    int i;
333 e80cfcfc bellard
    
334 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
335 e80cfcfc bellard
        qemu_put_be32s(f, &s->intreg_pending[i]);
336 e80cfcfc bellard
    }
337 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_pending);
338 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_disabled);
339 e80cfcfc bellard
    qemu_put_be32s(f, &s->target_cpu);
340 e80cfcfc bellard
}
341 e80cfcfc bellard
342 e80cfcfc bellard
static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
343 e80cfcfc bellard
{
344 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
345 e80cfcfc bellard
    int i;
346 e80cfcfc bellard
347 e80cfcfc bellard
    if (version_id != 1)
348 e80cfcfc bellard
        return -EINVAL;
349 e80cfcfc bellard
350 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
351 e80cfcfc bellard
        qemu_get_be32s(f, &s->intreg_pending[i]);
352 e80cfcfc bellard
    }
353 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_pending);
354 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_disabled);
355 e80cfcfc bellard
    qemu_get_be32s(f, &s->target_cpu);
356 e80cfcfc bellard
    return 0;
357 e80cfcfc bellard
}
358 e80cfcfc bellard
359 e80cfcfc bellard
static void slavio_intctl_reset(void *opaque)
360 e80cfcfc bellard
{
361 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
362 e80cfcfc bellard
    int i;
363 e80cfcfc bellard
364 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
365 e80cfcfc bellard
        s->intreg_pending[i] = 0;
366 e80cfcfc bellard
    }
367 6bae7071 bellard
    s->intregm_disabled = ~0xffb2007f;
368 e80cfcfc bellard
    s->intregm_pending = 0;
369 e80cfcfc bellard
    s->target_cpu = 0;
370 e80cfcfc bellard
}
371 e80cfcfc bellard
372 ba3c64fb bellard
void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
373 ba3c64fb bellard
{
374 ba3c64fb bellard
    SLAVIO_INTCTLState *s = opaque;
375 ba3c64fb bellard
    s->cpu_envs[cpu] = env;
376 ba3c64fb bellard
}
377 ba3c64fb bellard
378 e80cfcfc bellard
void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
379 e80cfcfc bellard
{
380 e80cfcfc bellard
    int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
381 e80cfcfc bellard
    SLAVIO_INTCTLState *s;
382 e80cfcfc bellard
383 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
384 e80cfcfc bellard
    if (!s)
385 e80cfcfc bellard
        return NULL;
386 e80cfcfc bellard
387 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
388 e80cfcfc bellard
        slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
389 e80cfcfc bellard
        cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
390 e80cfcfc bellard
    }
391 e80cfcfc bellard
392 e80cfcfc bellard
    slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
393 e80cfcfc bellard
    cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
394 e80cfcfc bellard
395 e80cfcfc bellard
    register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
396 e80cfcfc bellard
    qemu_register_reset(slavio_intctl_reset, s);
397 e80cfcfc bellard
    slavio_intctl_reset(s);
398 e80cfcfc bellard
    return s;
399 e80cfcfc bellard
}