Statistics
| Branch: | Revision:

root / hw / slavio_intctl.c @ d78f3995

History | View | Annotate | Download (12.1 kB)

1 e80cfcfc bellard
/*
2 e80cfcfc bellard
 * QEMU Sparc SLAVIO interrupt controller emulation
3 5fafdf24 ths
 *
4 66321a11 bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 5fafdf24 ths
 *
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 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "sun4m.h"
26 376253ec aliguori
#include "monitor.h"
27 87ecb68b pbrook
28 e80cfcfc bellard
//#define DEBUG_IRQ_COUNT
29 66321a11 bellard
//#define DEBUG_IRQ
30 66321a11 bellard
31 66321a11 bellard
#ifdef DEBUG_IRQ
32 66321a11 bellard
#define DPRINTF(fmt, args...) \
33 66321a11 bellard
do { printf("IRQ: " fmt , ##args); } while (0)
34 66321a11 bellard
#else
35 66321a11 bellard
#define DPRINTF(fmt, args...)
36 66321a11 bellard
#endif
37 e80cfcfc bellard
38 e80cfcfc bellard
/*
39 e80cfcfc bellard
 * Registers of interrupt controller in sun4m.
40 e80cfcfc bellard
 *
41 e80cfcfc bellard
 * This is the interrupt controller part of chip STP2001 (Slave I/O), also
42 e80cfcfc bellard
 * produced as NCR89C105. See
43 e80cfcfc bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
44 e80cfcfc bellard
 *
45 e80cfcfc bellard
 * There is a system master controller and one for each cpu.
46 5fafdf24 ths
 *
47 e80cfcfc bellard
 */
48 e80cfcfc bellard
49 e80cfcfc bellard
#define MAX_CPUS 16
50 b3a23197 blueswir1
#define MAX_PILS 16
51 e80cfcfc bellard
52 a8f48dcc blueswir1
struct SLAVIO_CPUINTCTLState;
53 a8f48dcc blueswir1
54 e80cfcfc bellard
typedef struct SLAVIO_INTCTLState {
55 e80cfcfc bellard
    uint32_t intregm_pending;
56 e80cfcfc bellard
    uint32_t intregm_disabled;
57 e80cfcfc bellard
    uint32_t target_cpu;
58 e80cfcfc bellard
#ifdef DEBUG_IRQ_COUNT
59 e80cfcfc bellard
    uint64_t irq_count[32];
60 e80cfcfc bellard
#endif
61 b3a23197 blueswir1
    qemu_irq *cpu_irqs[MAX_CPUS];
62 e0353fe2 blueswir1
    const uint32_t *intbit_to_level;
63 e3a79bca blueswir1
    uint32_t cputimer_lbit, cputimer_mbit;
64 b3a23197 blueswir1
    uint32_t pil_out[MAX_CPUS];
65 a8f48dcc blueswir1
    struct SLAVIO_CPUINTCTLState *slaves[MAX_CPUS];
66 e80cfcfc bellard
} SLAVIO_INTCTLState;
67 e80cfcfc bellard
68 a8f48dcc blueswir1
typedef struct SLAVIO_CPUINTCTLState {
69 a8f48dcc blueswir1
    uint32_t intreg_pending;
70 a8f48dcc blueswir1
    SLAVIO_INTCTLState *master;
71 a8f48dcc blueswir1
    uint32_t cpu;
72 a8f48dcc blueswir1
} SLAVIO_CPUINTCTLState;
73 a8f48dcc blueswir1
74 e80cfcfc bellard
#define INTCTL_MAXADDR 0xf
75 5aca8c3b blueswir1
#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
76 a8f48dcc blueswir1
#define INTCTLM_SIZE 0x14
77 80be36b8 blueswir1
#define MASTER_IRQ_MASK ~0x0fa2007f
78 9a87ce9b blueswir1
#define MASTER_DISABLE 0x80000000
79 6341fdcb blueswir1
#define CPU_SOFTIRQ_MASK 0xfffe0000
80 9a87ce9b blueswir1
#define CPU_IRQ_INT15_IN 0x0004000
81 9a87ce9b blueswir1
#define CPU_IRQ_INT15_MASK 0x80000000
82 9a87ce9b blueswir1
83 a8f48dcc blueswir1
static void slavio_check_interrupts(SLAVIO_INTCTLState *s);
84 e80cfcfc bellard
85 e80cfcfc bellard
// per-cpu interrupt controller
86 e80cfcfc bellard
static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
87 e80cfcfc bellard
{
88 a8f48dcc blueswir1
    SLAVIO_CPUINTCTLState *s = opaque;
89 dd4131b3 blueswir1
    uint32_t saddr, ret;
90 e80cfcfc bellard
91 a8f48dcc blueswir1
    saddr = addr >> 2;
92 e80cfcfc bellard
    switch (saddr) {
93 e80cfcfc bellard
    case 0:
94 a8f48dcc blueswir1
        ret = s->intreg_pending;
95 dd4131b3 blueswir1
        break;
96 e80cfcfc bellard
    default:
97 dd4131b3 blueswir1
        ret = 0;
98 dd4131b3 blueswir1
        break;
99 e80cfcfc bellard
    }
100 3c4cf535 blueswir1
    DPRINTF("read cpu %d reg 0x" TARGET_FMT_plx " = %x\n", s->cpu, addr, ret);
101 dd4131b3 blueswir1
102 dd4131b3 blueswir1
    return ret;
103 e80cfcfc bellard
}
104 e80cfcfc bellard
105 77f193da blueswir1
static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
106 77f193da blueswir1
                                     uint32_t val)
107 e80cfcfc bellard
{
108 a8f48dcc blueswir1
    SLAVIO_CPUINTCTLState *s = opaque;
109 e80cfcfc bellard
    uint32_t saddr;
110 e80cfcfc bellard
111 a8f48dcc blueswir1
    saddr = addr >> 2;
112 3c4cf535 blueswir1
    DPRINTF("write cpu %d reg 0x" TARGET_FMT_plx " = %x\n", s->cpu, addr, val);
113 e80cfcfc bellard
    switch (saddr) {
114 e80cfcfc bellard
    case 1: // clear pending softints
115 9a87ce9b blueswir1
        if (val & CPU_IRQ_INT15_IN)
116 9a87ce9b blueswir1
            val |= CPU_IRQ_INT15_MASK;
117 6341fdcb blueswir1
        val &= CPU_SOFTIRQ_MASK;
118 a8f48dcc blueswir1
        s->intreg_pending &= ~val;
119 a8f48dcc blueswir1
        slavio_check_interrupts(s->master);
120 a8f48dcc blueswir1
        DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", s->cpu, val,
121 a8f48dcc blueswir1
                s->intreg_pending);
122 f930d07e blueswir1
        break;
123 e80cfcfc bellard
    case 2: // set softint
124 6341fdcb blueswir1
        val &= CPU_SOFTIRQ_MASK;
125 a8f48dcc blueswir1
        s->intreg_pending |= val;
126 a8f48dcc blueswir1
        slavio_check_interrupts(s->master);
127 a8f48dcc blueswir1
        DPRINTF("Set cpu %d irq mask %x, curmask %x\n", s->cpu, val,
128 a8f48dcc blueswir1
                s->intreg_pending);
129 f930d07e blueswir1
        break;
130 e80cfcfc bellard
    default:
131 f930d07e blueswir1
        break;
132 e80cfcfc bellard
    }
133 e80cfcfc bellard
}
134 e80cfcfc bellard
135 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
136 7c560456 blueswir1
    NULL,
137 7c560456 blueswir1
    NULL,
138 e80cfcfc bellard
    slavio_intctl_mem_readl,
139 e80cfcfc bellard
};
140 e80cfcfc bellard
141 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
142 7c560456 blueswir1
    NULL,
143 7c560456 blueswir1
    NULL,
144 e80cfcfc bellard
    slavio_intctl_mem_writel,
145 e80cfcfc bellard
};
146 e80cfcfc bellard
147 e80cfcfc bellard
// master system interrupt controller
148 e80cfcfc bellard
static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
149 e80cfcfc bellard
{
150 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
151 dd4131b3 blueswir1
    uint32_t saddr, ret;
152 e80cfcfc bellard
153 a8f48dcc blueswir1
    saddr = addr >> 2;
154 e80cfcfc bellard
    switch (saddr) {
155 e80cfcfc bellard
    case 0:
156 9a87ce9b blueswir1
        ret = s->intregm_pending & ~MASTER_DISABLE;
157 dd4131b3 blueswir1
        break;
158 e80cfcfc bellard
    case 1:
159 80be36b8 blueswir1
        ret = s->intregm_disabled & MASTER_IRQ_MASK;
160 dd4131b3 blueswir1
        break;
161 e80cfcfc bellard
    case 4:
162 dd4131b3 blueswir1
        ret = s->target_cpu;
163 dd4131b3 blueswir1
        break;
164 e80cfcfc bellard
    default:
165 dd4131b3 blueswir1
        ret = 0;
166 dd4131b3 blueswir1
        break;
167 e80cfcfc bellard
    }
168 1569fc29 blueswir1
    DPRINTF("read system reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
169 dd4131b3 blueswir1
170 dd4131b3 blueswir1
    return ret;
171 e80cfcfc bellard
}
172 e80cfcfc bellard
173 77f193da blueswir1
static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
174 77f193da blueswir1
                                      uint32_t val)
175 e80cfcfc bellard
{
176 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
177 e80cfcfc bellard
    uint32_t saddr;
178 e80cfcfc bellard
179 a8f48dcc blueswir1
    saddr = addr >> 2;
180 1569fc29 blueswir1
    DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
181 e80cfcfc bellard
    switch (saddr) {
182 e80cfcfc bellard
    case 2: // clear (enable)
183 f930d07e blueswir1
        // Force clear unused bits
184 9a87ce9b blueswir1
        val &= MASTER_IRQ_MASK;
185 f930d07e blueswir1
        s->intregm_disabled &= ~val;
186 77f193da blueswir1
        DPRINTF("Enabled master irq mask %x, curmask %x\n", val,
187 77f193da blueswir1
                s->intregm_disabled);
188 f930d07e blueswir1
        slavio_check_interrupts(s);
189 f930d07e blueswir1
        break;
190 e80cfcfc bellard
    case 3: // set (disable, clear pending)
191 f930d07e blueswir1
        // Force clear unused bits
192 9a87ce9b blueswir1
        val &= MASTER_IRQ_MASK;
193 f930d07e blueswir1
        s->intregm_disabled |= val;
194 f930d07e blueswir1
        s->intregm_pending &= ~val;
195 327ac2e7 blueswir1
        slavio_check_interrupts(s);
196 77f193da blueswir1
        DPRINTF("Disabled master irq mask %x, curmask %x\n", val,
197 77f193da blueswir1
                s->intregm_disabled);
198 f930d07e blueswir1
        break;
199 e80cfcfc bellard
    case 4:
200 f930d07e blueswir1
        s->target_cpu = val & (MAX_CPUS - 1);
201 327ac2e7 blueswir1
        slavio_check_interrupts(s);
202 f930d07e blueswir1
        DPRINTF("Set master irq cpu %d\n", s->target_cpu);
203 f930d07e blueswir1
        break;
204 e80cfcfc bellard
    default:
205 f930d07e blueswir1
        break;
206 e80cfcfc bellard
    }
207 e80cfcfc bellard
}
208 e80cfcfc bellard
209 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
210 7c560456 blueswir1
    NULL,
211 7c560456 blueswir1
    NULL,
212 e80cfcfc bellard
    slavio_intctlm_mem_readl,
213 e80cfcfc bellard
};
214 e80cfcfc bellard
215 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
216 7c560456 blueswir1
    NULL,
217 7c560456 blueswir1
    NULL,
218 e80cfcfc bellard
    slavio_intctlm_mem_writel,
219 e80cfcfc bellard
};
220 e80cfcfc bellard
221 376253ec aliguori
void slavio_pic_info(Monitor *mon, void *opaque)
222 e80cfcfc bellard
{
223 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
224 e80cfcfc bellard
    int i;
225 e80cfcfc bellard
226 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
227 376253ec aliguori
        monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
228 376253ec aliguori
                       s->slaves[i]->intreg_pending);
229 e80cfcfc bellard
    }
230 376253ec aliguori
    monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
231 376253ec aliguori
                   s->intregm_pending, s->intregm_disabled);
232 e80cfcfc bellard
}
233 e80cfcfc bellard
234 376253ec aliguori
void slavio_irq_info(Monitor *mon, void *opaque)
235 e80cfcfc bellard
{
236 e80cfcfc bellard
#ifndef DEBUG_IRQ_COUNT
237 376253ec aliguori
    monitor_printf(mon, "irq statistic code not compiled.\n");
238 e80cfcfc bellard
#else
239 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
240 e80cfcfc bellard
    int i;
241 e80cfcfc bellard
    int64_t count;
242 e80cfcfc bellard
243 376253ec aliguori
    monitor_printf(mon, "IRQ statistics:\n");
244 e80cfcfc bellard
    for (i = 0; i < 32; i++) {
245 e80cfcfc bellard
        count = s->irq_count[i];
246 e80cfcfc bellard
        if (count > 0)
247 376253ec aliguori
            monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
248 e80cfcfc bellard
    }
249 e80cfcfc bellard
#endif
250 e80cfcfc bellard
}
251 e80cfcfc bellard
252 a8f48dcc blueswir1
static void slavio_check_interrupts(SLAVIO_INTCTLState *s)
253 66321a11 bellard
{
254 327ac2e7 blueswir1
    uint32_t pending = s->intregm_pending, pil_pending;
255 327ac2e7 blueswir1
    unsigned int i, j;
256 66321a11 bellard
257 66321a11 bellard
    pending &= ~s->intregm_disabled;
258 66321a11 bellard
259 b3a23197 blueswir1
    DPRINTF("pending %x disabled %x\n", pending, s->intregm_disabled);
260 ba3c64fb bellard
    for (i = 0; i < MAX_CPUS; i++) {
261 327ac2e7 blueswir1
        pil_pending = 0;
262 9a87ce9b blueswir1
        if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
263 b3a23197 blueswir1
            (i == s->target_cpu)) {
264 b3a23197 blueswir1
            for (j = 0; j < 32; j++) {
265 327ac2e7 blueswir1
                if (pending & (1 << j))
266 327ac2e7 blueswir1
                    pil_pending |= 1 << s->intbit_to_level[j];
267 b3a23197 blueswir1
            }
268 b3a23197 blueswir1
        }
269 a8f48dcc blueswir1
        pil_pending |= (s->slaves[i]->intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
270 327ac2e7 blueswir1
271 327ac2e7 blueswir1
        for (j = 0; j < MAX_PILS; j++) {
272 327ac2e7 blueswir1
            if (pil_pending & (1 << j)) {
273 327ac2e7 blueswir1
                if (!(s->pil_out[i] & (1 << j)))
274 327ac2e7 blueswir1
                    qemu_irq_raise(s->cpu_irqs[i][j]);
275 327ac2e7 blueswir1
            } else {
276 327ac2e7 blueswir1
                if (s->pil_out[i] & (1 << j))
277 327ac2e7 blueswir1
                    qemu_irq_lower(s->cpu_irqs[i][j]);
278 ba3c64fb bellard
            }
279 ba3c64fb bellard
        }
280 327ac2e7 blueswir1
        s->pil_out[i] = pil_pending;
281 ba3c64fb bellard
    }
282 66321a11 bellard
}
283 66321a11 bellard
284 e80cfcfc bellard
/*
285 e80cfcfc bellard
 * "irq" here is the bit number in the system interrupt register to
286 e80cfcfc bellard
 * separate serial and keyboard interrupts sharing a level.
287 e80cfcfc bellard
 */
288 d7edfd27 blueswir1
static void slavio_set_irq(void *opaque, int irq, int level)
289 e80cfcfc bellard
{
290 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
291 b3a23197 blueswir1
    uint32_t mask = 1 << irq;
292 b3a23197 blueswir1
    uint32_t pil = s->intbit_to_level[irq];
293 b3a23197 blueswir1
294 b3a23197 blueswir1
    DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, irq, pil,
295 b3a23197 blueswir1
            level);
296 b3a23197 blueswir1
    if (pil > 0) {
297 b3a23197 blueswir1
        if (level) {
298 327ac2e7 blueswir1
#ifdef DEBUG_IRQ_COUNT
299 327ac2e7 blueswir1
            s->irq_count[pil]++;
300 327ac2e7 blueswir1
#endif
301 b3a23197 blueswir1
            s->intregm_pending |= mask;
302 a8f48dcc blueswir1
            s->slaves[s->target_cpu]->intreg_pending |= 1 << pil;
303 b3a23197 blueswir1
        } else {
304 b3a23197 blueswir1
            s->intregm_pending &= ~mask;
305 a8f48dcc blueswir1
            s->slaves[s->target_cpu]->intreg_pending &= ~(1 << pil);
306 b3a23197 blueswir1
        }
307 b3a23197 blueswir1
        slavio_check_interrupts(s);
308 e80cfcfc bellard
    }
309 e80cfcfc bellard
}
310 e80cfcfc bellard
311 d7edfd27 blueswir1
static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
312 ba3c64fb bellard
{
313 ba3c64fb bellard
    SLAVIO_INTCTLState *s = opaque;
314 ba3c64fb bellard
315 b3a23197 blueswir1
    DPRINTF("Set cpu %d local timer level %d\n", cpu, level);
316 d7edfd27 blueswir1
317 e3a79bca blueswir1
    if (level) {
318 e3a79bca blueswir1
        s->intregm_pending |= s->cputimer_mbit;
319 a8f48dcc blueswir1
        s->slaves[cpu]->intreg_pending |= s->cputimer_lbit;
320 e3a79bca blueswir1
    } else {
321 e3a79bca blueswir1
        s->intregm_pending &= ~s->cputimer_mbit;
322 a8f48dcc blueswir1
        s->slaves[cpu]->intreg_pending &= ~s->cputimer_lbit;
323 e3a79bca blueswir1
    }
324 d7edfd27 blueswir1
325 ba3c64fb bellard
    slavio_check_interrupts(s);
326 ba3c64fb bellard
}
327 ba3c64fb bellard
328 e80cfcfc bellard
static void slavio_intctl_save(QEMUFile *f, void *opaque)
329 e80cfcfc bellard
{
330 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
331 e80cfcfc bellard
    int i;
332 3b46e624 ths
333 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
334 a8f48dcc blueswir1
        qemu_put_be32s(f, &s->slaves[i]->intreg_pending);
335 e80cfcfc bellard
    }
336 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_pending);
337 e80cfcfc bellard
    qemu_put_be32s(f, &s->intregm_disabled);
338 e80cfcfc bellard
    qemu_put_be32s(f, &s->target_cpu);
339 e80cfcfc bellard
}
340 e80cfcfc bellard
341 e80cfcfc bellard
static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
342 e80cfcfc bellard
{
343 e80cfcfc bellard
    SLAVIO_INTCTLState *s = opaque;
344 e80cfcfc bellard
    int i;
345 e80cfcfc bellard
346 e80cfcfc bellard
    if (version_id != 1)
347 e80cfcfc bellard
        return -EINVAL;
348 e80cfcfc bellard
349 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
350 a8f48dcc blueswir1
        qemu_get_be32s(f, &s->slaves[i]->intreg_pending);
351 e80cfcfc bellard
    }
352 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_pending);
353 e80cfcfc bellard
    qemu_get_be32s(f, &s->intregm_disabled);
354 e80cfcfc bellard
    qemu_get_be32s(f, &s->target_cpu);
355 327ac2e7 blueswir1
    slavio_check_interrupts(s);
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 a8f48dcc blueswir1
        s->slaves[i]->intreg_pending = 0;
366 e80cfcfc bellard
    }
367 9a87ce9b blueswir1
    s->intregm_disabled = ~MASTER_IRQ_MASK;
368 e80cfcfc bellard
    s->intregm_pending = 0;
369 e80cfcfc bellard
    s->target_cpu = 0;
370 327ac2e7 blueswir1
    slavio_check_interrupts(s);
371 e80cfcfc bellard
}
372 e80cfcfc bellard
373 5dcb6b91 blueswir1
void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
374 d537cf6c pbrook
                         const uint32_t *intbit_to_level,
375 d7edfd27 blueswir1
                         qemu_irq **irq, qemu_irq **cpu_irq,
376 b3a23197 blueswir1
                         qemu_irq **parent_irq, unsigned int cputimer)
377 e80cfcfc bellard
{
378 e80cfcfc bellard
    int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
379 e80cfcfc bellard
    SLAVIO_INTCTLState *s;
380 a8f48dcc blueswir1
    SLAVIO_CPUINTCTLState *slave;
381 e80cfcfc bellard
382 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
383 e80cfcfc bellard
384 e0353fe2 blueswir1
    s->intbit_to_level = intbit_to_level;
385 e80cfcfc bellard
    for (i = 0; i < MAX_CPUS; i++) {
386 a8f48dcc blueswir1
        slave = qemu_mallocz(sizeof(SLAVIO_CPUINTCTLState));
387 a8f48dcc blueswir1
388 a8f48dcc blueswir1
        slave->cpu = i;
389 a8f48dcc blueswir1
        slave->master = s;
390 a8f48dcc blueswir1
391 77f193da blueswir1
        slavio_intctl_io_memory = cpu_register_io_memory(0,
392 77f193da blueswir1
                                                         slavio_intctl_mem_read,
393 77f193da blueswir1
                                                         slavio_intctl_mem_write,
394 a8f48dcc blueswir1
                                                         slave);
395 a8f48dcc blueswir1
        cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
396 a8f48dcc blueswir1
                                     slavio_intctl_io_memory);
397 a8f48dcc blueswir1
398 a8f48dcc blueswir1
        s->slaves[i] = slave;
399 b3a23197 blueswir1
        s->cpu_irqs[i] = parent_irq[i];
400 e80cfcfc bellard
    }
401 e80cfcfc bellard
402 77f193da blueswir1
    slavio_intctlm_io_memory = cpu_register_io_memory(0,
403 77f193da blueswir1
                                                      slavio_intctlm_mem_read,
404 77f193da blueswir1
                                                      slavio_intctlm_mem_write,
405 77f193da blueswir1
                                                      s);
406 5aca8c3b blueswir1
    cpu_register_physical_memory(addrg, INTCTLM_SIZE, slavio_intctlm_io_memory);
407 e80cfcfc bellard
408 77f193da blueswir1
    register_savevm("slavio_intctl", addr, 1, slavio_intctl_save,
409 77f193da blueswir1
                    slavio_intctl_load, s);
410 e80cfcfc bellard
    qemu_register_reset(slavio_intctl_reset, s);
411 d537cf6c pbrook
    *irq = qemu_allocate_irqs(slavio_set_irq, s, 32);
412 d7edfd27 blueswir1
413 d7edfd27 blueswir1
    *cpu_irq = qemu_allocate_irqs(slavio_set_timer_irq_cpu, s, MAX_CPUS);
414 e3a79bca blueswir1
    s->cputimer_mbit = 1 << cputimer;
415 e3a79bca blueswir1
    s->cputimer_lbit = 1 << intbit_to_level[cputimer];
416 e80cfcfc bellard
    slavio_intctl_reset(s);
417 e80cfcfc bellard
    return s;
418 e80cfcfc bellard
}