Statistics
| Branch: | Revision:

root / hw / slavio_intctl.c @ 52cc07d0

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 e0353fe2 blueswir1
    const uint32_t *intbit_to_level;
58 e80cfcfc bellard
} SLAVIO_INTCTLState;
59 e80cfcfc bellard
60 e80cfcfc bellard
#define INTCTL_MAXADDR 0xf
61 e80cfcfc bellard
#define INTCTLM_MAXADDR 0xf
62 66321a11 bellard
static void slavio_check_interrupts(void *opaque);
63 e80cfcfc bellard
64 e80cfcfc bellard
// per-cpu interrupt controller
65 e80cfcfc bellard
static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
66 e80cfcfc bellard
{
67 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
68 e80cfcfc bellard
    uint32_t saddr;
69 e80cfcfc bellard
    int cpu;
70 e80cfcfc bellard
71 e80cfcfc bellard
    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
72 e80cfcfc bellard
    saddr = (addr & INTCTL_MAXADDR) >> 2;
73 e80cfcfc bellard
    switch (saddr) {
74 e80cfcfc bellard
    case 0:
75 e80cfcfc bellard
        return s->intreg_pending[cpu];
76 e80cfcfc bellard
    default:
77 e80cfcfc bellard
        break;
78 e80cfcfc bellard
    }
79 e80cfcfc bellard
    return 0;
80 e80cfcfc bellard
}
81 e80cfcfc bellard
82 e80cfcfc bellard
static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
83 e80cfcfc bellard
{
84 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
85 e80cfcfc bellard
    uint32_t saddr;
86 e80cfcfc bellard
    int cpu;
87 e80cfcfc bellard
88 e80cfcfc bellard
    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
89 e80cfcfc bellard
    saddr = (addr & INTCTL_MAXADDR) >> 2;
90 e80cfcfc bellard
    switch (saddr) {
91 e80cfcfc bellard
    case 1: // clear pending softints
92 e80cfcfc bellard
        if (val & 0x4000)
93 e80cfcfc bellard
            val |= 80000000;
94 e80cfcfc bellard
        val &= 0xfffe0000;
95 e80cfcfc bellard
        s->intreg_pending[cpu] &= ~val;
96 66321a11 bellard
        DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
97 e80cfcfc bellard
        break;
98 e80cfcfc bellard
    case 2: // set softint
99 e80cfcfc bellard
        val &= 0xfffe0000;
100 e80cfcfc bellard
        s->intreg_pending[cpu] |= val;
101 ba3c64fb bellard
        slavio_check_interrupts(s);
102 66321a11 bellard
        DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
103 e80cfcfc bellard
        break;
104 e80cfcfc bellard
    default:
105 e80cfcfc bellard
        break;
106 e80cfcfc bellard
    }
107 e80cfcfc bellard
}
108 e80cfcfc bellard
109 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
110 e80cfcfc bellard
    slavio_intctl_mem_readl,
111 e80cfcfc bellard
    slavio_intctl_mem_readl,
112 e80cfcfc bellard
    slavio_intctl_mem_readl,
113 e80cfcfc bellard
};
114 e80cfcfc bellard
115 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
116 e80cfcfc bellard
    slavio_intctl_mem_writel,
117 e80cfcfc bellard
    slavio_intctl_mem_writel,
118 e80cfcfc bellard
    slavio_intctl_mem_writel,
119 e80cfcfc bellard
};
120 e80cfcfc bellard
121 e80cfcfc bellard
// master system interrupt controller
122 e80cfcfc bellard
static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
123 e80cfcfc bellard
{
124 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
125 e80cfcfc bellard
    uint32_t saddr;
126 e80cfcfc bellard
127 e80cfcfc bellard
    saddr = (addr & INTCTLM_MAXADDR) >> 2;
128 e80cfcfc bellard
    switch (saddr) {
129 e80cfcfc bellard
    case 0:
130 6bae7071 bellard
        return s->intregm_pending & 0x7fffffff;
131 e80cfcfc bellard
    case 1:
132 e80cfcfc bellard
        return s->intregm_disabled;
133 e80cfcfc bellard
    case 4:
134 e80cfcfc bellard
        return s->target_cpu;
135 e80cfcfc bellard
    default:
136 e80cfcfc bellard
        break;
137 e80cfcfc bellard
    }
138 e80cfcfc bellard
    return 0;
139 e80cfcfc bellard
}
140 e80cfcfc bellard
141 e80cfcfc bellard
static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
142 e80cfcfc bellard
{
143 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
144 e80cfcfc bellard
    uint32_t saddr;
145 e80cfcfc bellard
146 e80cfcfc bellard
    saddr = (addr & INTCTLM_MAXADDR) >> 2;
147 e80cfcfc bellard
    switch (saddr) {
148 e80cfcfc bellard
    case 2: // clear (enable)
149 6bae7071 bellard
        // Force clear unused bits
150 3475187d bellard
        val &= ~0x4fb2007f;
151 e80cfcfc bellard
        s->intregm_disabled &= ~val;
152 66321a11 bellard
        DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
153 66321a11 bellard
        slavio_check_interrupts(s);
154 e80cfcfc bellard
        break;
155 e80cfcfc bellard
    case 3: // set (disable, clear pending)
156 6bae7071 bellard
        // Force clear unused bits
157 3475187d bellard
        val &= ~0x4fb2007f;
158 e80cfcfc bellard
        s->intregm_disabled |= val;
159 e80cfcfc bellard
        s->intregm_pending &= ~val;
160 66321a11 bellard
        DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
161 e80cfcfc bellard
        break;
162 e80cfcfc bellard
    case 4:
163 e80cfcfc bellard
        s->target_cpu = val & (MAX_CPUS - 1);
164 66321a11 bellard
        DPRINTF("Set master irq cpu %d\n", s->target_cpu);
165 e80cfcfc bellard
        break;
166 e80cfcfc bellard
    default:
167 e80cfcfc bellard
        break;
168 e80cfcfc bellard
    }
169 e80cfcfc bellard
}
170 e80cfcfc bellard
171 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
172 e80cfcfc bellard
    slavio_intctlm_mem_readl,
173 e80cfcfc bellard
    slavio_intctlm_mem_readl,
174 e80cfcfc bellard
    slavio_intctlm_mem_readl,
175 e80cfcfc bellard
};
176 e80cfcfc bellard
177 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
178 e80cfcfc bellard
    slavio_intctlm_mem_writel,
179 e80cfcfc bellard
    slavio_intctlm_mem_writel,
180 e80cfcfc bellard
    slavio_intctlm_mem_writel,
181 e80cfcfc bellard
};
182 e80cfcfc bellard
183 e80cfcfc bellard
void slavio_pic_info(void *opaque)
184 e80cfcfc bellard
{
185 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
186 e80cfcfc bellard
    int i;
187 e80cfcfc bellard
188 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
189 e80cfcfc bellard
        term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
190 e80cfcfc bellard
    }
191 e80cfcfc bellard
    term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
192 e80cfcfc bellard
}
193 e80cfcfc bellard
194 e80cfcfc bellard
void slavio_irq_info(void *opaque)
195 e80cfcfc bellard
{
196 e80cfcfc bellard
#ifndef DEBUG_IRQ_COUNT
197 e80cfcfc bellard
    term_printf("irq statistic code not compiled.\n");
198 e80cfcfc bellard
#else
199 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
200 e80cfcfc bellard
    int i;
201 e80cfcfc bellard
    int64_t count;
202 e80cfcfc bellard
203 e80cfcfc bellard
    term_printf("IRQ statistics:\n");
204 e80cfcfc bellard
    for (i = 0; i < 32; i++) {
205 e80cfcfc bellard
        count = s->irq_count[i];
206 e80cfcfc bellard
        if (count > 0)
207 26a76461 bellard
            term_printf("%2d: %" PRId64 "\n", i, count);
208 e80cfcfc bellard
    }
209 e80cfcfc bellard
#endif
210 e80cfcfc bellard
}
211 e80cfcfc bellard
212 66321a11 bellard
static void slavio_check_interrupts(void *opaque)
213 66321a11 bellard
{
214 c68ea704 bellard
    CPUState *env;
215 66321a11 bellard
    SLAVIO_INTCTLState *s = opaque;
216 66321a11 bellard
    uint32_t pending = s->intregm_pending;
217 ba3c64fb bellard
    unsigned int i, j, max = 0;
218 66321a11 bellard
219 66321a11 bellard
    pending &= ~s->intregm_disabled;
220 66321a11 bellard
221 66321a11 bellard
    if (pending && !(s->intregm_disabled & 0x80000000)) {
222 66321a11 bellard
        for (i = 0; i < 32; i++) {
223 66321a11 bellard
            if (pending & (1 << i)) {
224 e0353fe2 blueswir1
                if (max < s->intbit_to_level[i])
225 e0353fe2 blueswir1
                    max = s->intbit_to_level[i];
226 66321a11 bellard
            }
227 66321a11 bellard
        }
228 ba3c64fb bellard
        env = s->cpu_envs[s->target_cpu];
229 ba3c64fb bellard
        if (!env) {
230 ba3c64fb bellard
            DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
231 ba3c64fb bellard
        }
232 ba3c64fb bellard
        else {
233 ba3c64fb bellard
            if (env->halted)
234 ba3c64fb bellard
                env->halted = 0;
235 ba3c64fb bellard
            if (env->interrupt_index == 0) {
236 ba3c64fb bellard
                DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
237 66321a11 bellard
#ifdef DEBUG_IRQ_COUNT
238 ba3c64fb bellard
                s->irq_count[max]++;
239 66321a11 bellard
#endif
240 ba3c64fb bellard
                env->interrupt_index = TT_EXTINT | max;
241 ba3c64fb bellard
                cpu_interrupt(env, CPU_INTERRUPT_HARD);
242 ba3c64fb bellard
            }
243 ba3c64fb bellard
            else
244 ba3c64fb bellard
                DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
245 66321a11 bellard
        }
246 66321a11 bellard
    }
247 66321a11 bellard
    else
248 66321a11 bellard
        DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
249 ba3c64fb bellard
    
250 ba3c64fb bellard
    for (i = 0; i < MAX_CPUS; i++) {
251 ba3c64fb bellard
        max = 0;
252 ba3c64fb bellard
        env = s->cpu_envs[i];
253 ba3c64fb bellard
        if (!env)
254 ba3c64fb bellard
            continue;
255 ba3c64fb bellard
        for (j = 17; j < 32; j++) {
256 ba3c64fb bellard
            if (s->intreg_pending[i] & (1 << j)) {
257 ba3c64fb bellard
                if (max < j - 16)
258 ba3c64fb bellard
                    max = j - 16;
259 ba3c64fb bellard
            }
260 ba3c64fb bellard
        }
261 ba3c64fb bellard
        if (max > 0) {
262 ba3c64fb bellard
            if (env->halted)
263 ba3c64fb bellard
                env->halted = 0;
264 ba3c64fb bellard
            if (env->interrupt_index == 0) {
265 ba3c64fb bellard
                DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
266 ba3c64fb bellard
#ifdef DEBUG_IRQ_COUNT
267 ba3c64fb bellard
                s->irq_count[max]++;
268 ba3c64fb bellard
#endif
269 ba3c64fb bellard
                env->interrupt_index = TT_EXTINT | max;
270 ba3c64fb bellard
                cpu_interrupt(env, CPU_INTERRUPT_HARD);
271 ba3c64fb bellard
            }
272 ba3c64fb bellard
        }
273 ba3c64fb bellard
    }
274 66321a11 bellard
}
275 66321a11 bellard
276 e80cfcfc bellard
/*
277 e80cfcfc bellard
 * "irq" here is the bit number in the system interrupt register to
278 e80cfcfc bellard
 * separate serial and keyboard interrupts sharing a level.
279 e80cfcfc bellard
 */
280 52cc07d0 blueswir1
void pic_set_irq_new(void *opaque, int irq, int level)
281 e80cfcfc bellard
{
282 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
283 e80cfcfc bellard
284 ba3c64fb bellard
    DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
285 e80cfcfc bellard
    if (irq < 32) {
286 e80cfcfc bellard
        uint32_t mask = 1 << irq;
287 e0353fe2 blueswir1
        uint32_t pil = s->intbit_to_level[irq];
288 e80cfcfc bellard
        if (pil > 0) {
289 e80cfcfc bellard
            if (level) {
290 e80cfcfc bellard
                s->intregm_pending |= mask;
291 e80cfcfc bellard
                s->intreg_pending[s->target_cpu] |= 1 << pil;
292 491730f3 ths
                slavio_check_interrupts(s);
293 e80cfcfc bellard
            }
294 e80cfcfc bellard
            else {
295 e80cfcfc bellard
                s->intregm_pending &= ~mask;
296 e80cfcfc bellard
                s->intreg_pending[s->target_cpu] &= ~(1 << pil);
297 e80cfcfc bellard
            }
298 e80cfcfc bellard
        }
299 e80cfcfc bellard
    }
300 e80cfcfc bellard
}
301 e80cfcfc bellard
302 52cc07d0 blueswir1
void pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
303 ba3c64fb bellard
{
304 ba3c64fb bellard
    SLAVIO_INTCTLState *s = opaque;
305 ba3c64fb bellard
306 ba3c64fb bellard
    DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
307 ba3c64fb bellard
    if (cpu == (unsigned int)-1) {
308 52cc07d0 blueswir1
        pic_set_irq_new(opaque, irq, level);
309 ba3c64fb bellard
        return;
310 ba3c64fb bellard
    }
311 ba3c64fb bellard
    if (irq < 32) {
312 e0353fe2 blueswir1
        uint32_t pil = s->intbit_to_level[irq];
313 ba3c64fb bellard
            if (pil > 0) {
314 ba3c64fb bellard
            if (level) {
315 ba3c64fb bellard
                s->intreg_pending[cpu] |= 1 << pil;
316 ba3c64fb bellard
            }
317 ba3c64fb bellard
            else {
318 ba3c64fb bellard
                s->intreg_pending[cpu] &= ~(1 << pil);
319 ba3c64fb bellard
            }
320 ba3c64fb bellard
        }
321 ba3c64fb bellard
    }
322 ba3c64fb bellard
    slavio_check_interrupts(s);
323 ba3c64fb bellard
}
324 ba3c64fb bellard
325 e80cfcfc bellard
static void slavio_intctl_save(QEMUFile *f, void *opaque)
326 e80cfcfc bellard
{
327 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
328 e80cfcfc bellard
    int i;
329 e80cfcfc bellard
    
330 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
331 e80cfcfc bellard
        qemu_put_be32s(f, &s->intreg_pending[i]);
332 e80cfcfc bellard
    }
333 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_pending);
334 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_disabled);
335 e80cfcfc bellard
    qemu_put_be32s(f, &s->target_cpu);
336 e80cfcfc bellard
}
337 e80cfcfc bellard
338 e80cfcfc bellard
static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
339 e80cfcfc bellard
{
340 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
341 e80cfcfc bellard
    int i;
342 e80cfcfc bellard
343 e80cfcfc bellard
    if (version_id != 1)
344 e80cfcfc bellard
        return -EINVAL;
345 e80cfcfc bellard
346 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
347 e80cfcfc bellard
        qemu_get_be32s(f, &s->intreg_pending[i]);
348 e80cfcfc bellard
    }
349 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_pending);
350 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_disabled);
351 e80cfcfc bellard
    qemu_get_be32s(f, &s->target_cpu);
352 e80cfcfc bellard
    return 0;
353 e80cfcfc bellard
}
354 e80cfcfc bellard
355 e80cfcfc bellard
static void slavio_intctl_reset(void *opaque)
356 e80cfcfc bellard
{
357 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
358 e80cfcfc bellard
    int i;
359 e80cfcfc bellard
360 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
361 e80cfcfc bellard
        s->intreg_pending[i] = 0;
362 e80cfcfc bellard
    }
363 6bae7071 bellard
    s->intregm_disabled = ~0xffb2007f;
364 e80cfcfc bellard
    s->intregm_pending = 0;
365 e80cfcfc bellard
    s->target_cpu = 0;
366 e80cfcfc bellard
}
367 e80cfcfc bellard
368 ba3c64fb bellard
void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
369 ba3c64fb bellard
{
370 ba3c64fb bellard
    SLAVIO_INTCTLState *s = opaque;
371 ba3c64fb bellard
    s->cpu_envs[cpu] = env;
372 ba3c64fb bellard
}
373 ba3c64fb bellard
374 e0353fe2 blueswir1
void *slavio_intctl_init(uint32_t addr, uint32_t addrg,
375 e0353fe2 blueswir1
                         const uint32_t *intbit_to_level)
376 e80cfcfc bellard
{
377 e80cfcfc bellard
    int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
378 e80cfcfc bellard
    SLAVIO_INTCTLState *s;
379 e80cfcfc bellard
380 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
381 e80cfcfc bellard
    if (!s)
382 e80cfcfc bellard
        return NULL;
383 e80cfcfc bellard
384 e0353fe2 blueswir1
    s->intbit_to_level = intbit_to_level;
385 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
386 e80cfcfc bellard
        slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
387 e80cfcfc bellard
        cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
388 e80cfcfc bellard
    }
389 e80cfcfc bellard
390 e80cfcfc bellard
    slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
391 e80cfcfc bellard
    cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
392 e80cfcfc bellard
393 e80cfcfc bellard
    register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
394 e80cfcfc bellard
    qemu_register_reset(slavio_intctl_reset, s);
395 e80cfcfc bellard
    slavio_intctl_reset(s);
396 e80cfcfc bellard
    return s;
397 e80cfcfc bellard
}