Statistics
| Branch: | Revision:

root / hw / slavio_intctl.c @ a6307b08

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