]> git.proxmox.com Git - qemu.git/blob - hw/openpic.c
openpic: combine mpic and openpic irq raise functions
[qemu.git] / hw / openpic.c
1 /*
2 * OpenPIC emulation
3 *
4 * Copyright (c) 2004 Jocelyn Mayer
5 * 2011 Alexander Graf
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25 /*
26 *
27 * Based on OpenPic implementations:
28 * - Intel GW80314 I/O companion chip developer's manual
29 * - Motorola MPC8245 & MPC8540 user manuals.
30 * - Motorola MCP750 (aka Raven) programmer manual.
31 * - Motorola Harrier programmer manuel
32 *
33 * Serial interrupts, as implemented in Raven chipset are not supported yet.
34 *
35 */
36 #include "hw.h"
37 #include "ppc_mac.h"
38 #include "pci.h"
39 #include "openpic.h"
40
41 //#define DEBUG_OPENPIC
42
43 #ifdef DEBUG_OPENPIC
44 #define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
45 #else
46 #define DPRINTF(fmt, ...) do { } while (0)
47 #endif
48
49 #define MAX_CPU 15
50 #define MAX_SRC 256
51 #define MAX_TMR 4
52 #define VECTOR_BITS 8
53 #define MAX_IPI 4
54 #define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR)
55 #define VID 0x03 /* MPIC version ID */
56 #define VENI 0x00000000 /* Vendor ID */
57
58 enum {
59 IRQ_IPVP = 0,
60 IRQ_IDE,
61 };
62
63 /* OpenPIC */
64 #define OPENPIC_MAX_CPU 2
65 #define OPENPIC_MAX_IRQ 64
66 #define OPENPIC_EXT_IRQ 48
67 #define OPENPIC_MAX_TMR MAX_TMR
68 #define OPENPIC_MAX_IPI MAX_IPI
69
70 /* Interrupt definitions */
71 #define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
72 #define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
73 #define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
74 #if OPENPIC_MAX_IPI > 0
75 #define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
76 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
77 #else
78 #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
79 #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
80 #endif
81
82 #define OPENPIC_GLB_REG_START 0x0
83 #define OPENPIC_GLB_REG_SIZE 0x10F0
84 #define OPENPIC_TMR_REG_START 0x10F0
85 #define OPENPIC_TMR_REG_SIZE 0x220
86 #define OPENPIC_SRC_REG_START 0x10000
87 #define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
88 #define OPENPIC_CPU_REG_START 0x20000
89 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
90
91 /* MPIC */
92 #define MPIC_MAX_CPU 1
93 #define MPIC_MAX_EXT 12
94 #define MPIC_MAX_INT 64
95 #define MPIC_MAX_IRQ MAX_IRQ
96
97 /* Interrupt definitions */
98 /* IRQs, accessible through the IRQ region */
99 #define MPIC_EXT_IRQ 0x00
100 #define MPIC_INT_IRQ 0x10
101 #define MPIC_MSG_IRQ 0xb0
102 #define MPIC_MSI_IRQ 0xe0
103 /* These are available through separate regions, but
104 for simplicity's sake mapped into the same number space */
105 #define MPIC_TMR_IRQ 0x100
106 #define MPIC_IPI_IRQ 0x104
107
108 #define MPIC_GLB_REG_START 0x0
109 #define MPIC_GLB_REG_SIZE 0x10F0
110 #define MPIC_TMR_REG_START 0x10F0
111 #define MPIC_TMR_REG_SIZE 0x220
112 #define MPIC_SRC_REG_START 0x10000
113 #define MPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
114 #define MPIC_CPU_REG_START 0x20000
115 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
116
117 /*
118 * Block Revision Register1 (BRR1): QEMU does not fully emulate
119 * any version on MPIC. So to start with, set the IP version to 0.
120 *
121 * NOTE: This is Freescale MPIC specific register. Keep it here till
122 * this code is refactored for different variants of OPENPIC and MPIC.
123 */
124 #define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
125 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
126 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
127
128 enum mpic_ide_bits {
129 IDR_EP = 31,
130 IDR_CI0 = 30,
131 IDR_CI1 = 29,
132 IDR_P1 = 1,
133 IDR_P0 = 0,
134 };
135
136 #define BF_WIDTH(_bits_) \
137 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
138
139 static inline void set_bit (uint32_t *field, int bit)
140 {
141 field[bit >> 5] |= 1 << (bit & 0x1F);
142 }
143
144 static inline void reset_bit (uint32_t *field, int bit)
145 {
146 field[bit >> 5] &= ~(1 << (bit & 0x1F));
147 }
148
149 static inline int test_bit (uint32_t *field, int bit)
150 {
151 return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
152 }
153
154 static int get_current_cpu(void)
155 {
156 return cpu_single_env->cpu_index;
157 }
158
159 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
160 int idx);
161 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
162 uint32_t val, int idx);
163
164 enum {
165 IRQ_EXTERNAL = 0x01,
166 IRQ_INTERNAL = 0x02,
167 IRQ_TIMER = 0x04,
168 IRQ_SPECIAL = 0x08,
169 };
170
171 typedef struct IRQ_queue_t {
172 uint32_t queue[BF_WIDTH(MAX_IRQ)];
173 int next;
174 int priority;
175 } IRQ_queue_t;
176
177 typedef struct IRQ_src_t {
178 uint32_t ipvp; /* IRQ vector/priority register */
179 uint32_t ide; /* IRQ destination register */
180 int type;
181 int last_cpu;
182 int pending; /* TRUE if IRQ is pending */
183 } IRQ_src_t;
184
185 enum IPVP_bits {
186 IPVP_MASK = 31,
187 IPVP_ACTIVITY = 30,
188 IPVP_MODE = 29,
189 IPVP_POLARITY = 23,
190 IPVP_SENSE = 22,
191 };
192 #define IPVP_PRIORITY_MASK (0x1F << 16)
193 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
194 #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
195 #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
196
197 typedef struct IRQ_dst_t {
198 uint32_t tfrr;
199 uint32_t pctp; /* CPU current task priority */
200 uint32_t pcsr; /* CPU sensitivity register */
201 IRQ_queue_t raised;
202 IRQ_queue_t servicing;
203 qemu_irq *irqs;
204 } IRQ_dst_t;
205
206 typedef struct openpic_t {
207 PCIDevice pci_dev;
208 MemoryRegion mem;
209
210 /* Behavior control */
211 uint32_t flags;
212
213 /* Sub-regions */
214 MemoryRegion sub_io_mem[7];
215
216 /* Global registers */
217 uint32_t frep; /* Feature reporting register */
218 uint32_t glbc; /* Global configuration register */
219 uint32_t micr; /* MPIC interrupt configuration register */
220 uint32_t veni; /* Vendor identification register */
221 uint32_t pint; /* Processor initialization register */
222 uint32_t spve; /* Spurious vector register */
223 uint32_t tifr; /* Timer frequency reporting register */
224 /* Source registers */
225 IRQ_src_t src[MAX_IRQ];
226 /* Local registers per output pin */
227 IRQ_dst_t dst[MAX_CPU];
228 int nb_cpus;
229 /* Timer registers */
230 struct {
231 uint32_t ticc; /* Global timer current count register */
232 uint32_t tibc; /* Global timer base count register */
233 } timers[MAX_TMR];
234 /* IRQ out is used when in bypass mode (not implemented) */
235 qemu_irq irq_out;
236 int max_irq;
237 int irq_ipi0;
238 int irq_tim0;
239 void (*reset) (void *);
240 } openpic_t;
241
242 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src);
243
244 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
245 {
246 set_bit(q->queue, n_IRQ);
247 }
248
249 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
250 {
251 reset_bit(q->queue, n_IRQ);
252 }
253
254 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
255 {
256 return test_bit(q->queue, n_IRQ);
257 }
258
259 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
260 {
261 int next, i;
262 int priority;
263
264 next = -1;
265 priority = -1;
266 for (i = 0; i < opp->max_irq; i++) {
267 if (IRQ_testbit(q, i)) {
268 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
269 i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
270 if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
271 next = i;
272 priority = IPVP_PRIORITY(opp->src[i].ipvp);
273 }
274 }
275 }
276 q->next = next;
277 q->priority = priority;
278 }
279
280 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
281 {
282 if (q->next == -1) {
283 /* XXX: optimize */
284 IRQ_check(opp, q);
285 }
286
287 return q->next;
288 }
289
290 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
291 {
292 IRQ_dst_t *dst;
293 IRQ_src_t *src;
294 int priority;
295
296 dst = &opp->dst[n_CPU];
297 src = &opp->src[n_IRQ];
298 priority = IPVP_PRIORITY(src->ipvp);
299 if (priority <= dst->pctp) {
300 /* Too low priority */
301 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
302 __func__, n_IRQ, n_CPU);
303 return;
304 }
305 if (IRQ_testbit(&dst->raised, n_IRQ)) {
306 /* Interrupt miss */
307 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
308 __func__, n_IRQ, n_CPU);
309 return;
310 }
311 set_bit(&src->ipvp, IPVP_ACTIVITY);
312 IRQ_setbit(&dst->raised, n_IRQ);
313 if (priority < dst->raised.priority) {
314 /* An higher priority IRQ is already raised */
315 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
316 __func__, n_IRQ, dst->raised.next, n_CPU);
317 return;
318 }
319 IRQ_get_next(opp, &dst->raised);
320 if (IRQ_get_next(opp, &dst->servicing) != -1 &&
321 priority <= dst->servicing.priority) {
322 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
323 __func__, n_IRQ, dst->servicing.next, n_CPU);
324 /* Already servicing a higher priority IRQ */
325 return;
326 }
327 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
328 openpic_irq_raise(opp, n_CPU, src);
329 }
330
331 /* update pic state because registers for n_IRQ have changed value */
332 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
333 {
334 IRQ_src_t *src;
335 int i;
336
337 src = &opp->src[n_IRQ];
338
339 if (!src->pending) {
340 /* no irq pending */
341 DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
342 return;
343 }
344 if (test_bit(&src->ipvp, IPVP_MASK)) {
345 /* Interrupt source is disabled */
346 DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
347 return;
348 }
349 if (IPVP_PRIORITY(src->ipvp) == 0) {
350 /* Priority set to zero */
351 DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
352 return;
353 }
354 if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
355 /* IRQ already active */
356 DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
357 return;
358 }
359 if (src->ide == 0x00000000) {
360 /* No target */
361 DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
362 return;
363 }
364
365 if (src->ide == (1 << src->last_cpu)) {
366 /* Only one CPU is allowed to receive this IRQ */
367 IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
368 } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
369 /* Directed delivery mode */
370 for (i = 0; i < opp->nb_cpus; i++) {
371 if (test_bit(&src->ide, i))
372 IRQ_local_pipe(opp, i, n_IRQ);
373 }
374 } else {
375 /* Distributed delivery mode */
376 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
377 if (i == opp->nb_cpus)
378 i = 0;
379 if (test_bit(&src->ide, i)) {
380 IRQ_local_pipe(opp, i, n_IRQ);
381 src->last_cpu = i;
382 break;
383 }
384 }
385 }
386 }
387
388 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
389 {
390 openpic_t *opp = opaque;
391 IRQ_src_t *src;
392
393 src = &opp->src[n_IRQ];
394 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
395 n_IRQ, level, src->ipvp);
396 if (test_bit(&src->ipvp, IPVP_SENSE)) {
397 /* level-sensitive irq */
398 src->pending = level;
399 if (!level)
400 reset_bit(&src->ipvp, IPVP_ACTIVITY);
401 } else {
402 /* edge-sensitive irq */
403 if (level)
404 src->pending = 1;
405 }
406 openpic_update_irq(opp, n_IRQ);
407 }
408
409 static void openpic_reset (void *opaque)
410 {
411 openpic_t *opp = (openpic_t *)opaque;
412 int i;
413
414 opp->glbc = 0x80000000;
415 /* Initialise controller registers */
416 opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
417 opp->veni = VENI;
418 opp->pint = 0x00000000;
419 opp->spve = 0x000000FF;
420 opp->tifr = 0x003F7A00;
421 /* ? */
422 opp->micr = 0x00000000;
423 /* Initialise IRQ sources */
424 for (i = 0; i < opp->max_irq; i++) {
425 opp->src[i].ipvp = 0xA0000000;
426 opp->src[i].ide = 0x00000000;
427 }
428 /* Initialise IRQ destinations */
429 for (i = 0; i < MAX_CPU; i++) {
430 opp->dst[i].pctp = 0x0000000F;
431 opp->dst[i].pcsr = 0x00000000;
432 memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
433 opp->dst[i].raised.next = -1;
434 memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
435 opp->dst[i].servicing.next = -1;
436 }
437 /* Initialise timers */
438 for (i = 0; i < MAX_TMR; i++) {
439 opp->timers[i].ticc = 0x00000000;
440 opp->timers[i].tibc = 0x80000000;
441 }
442 /* Go out of RESET state */
443 opp->glbc = 0x00000000;
444 }
445
446 static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
447 {
448 return opp->src[n_IRQ].ide;
449 }
450
451 static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
452 {
453 return opp->src[n_IRQ].ipvp;
454 }
455
456 static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
457 {
458 uint32_t tmp;
459
460 tmp = val & 0xC0000000;
461 tmp |= val & ((1ULL << MAX_CPU) - 1);
462 opp->src[n_IRQ].ide = tmp;
463 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
464 }
465
466 static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
467 {
468 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
469 /* ACTIVITY bit is read-only */
470 opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
471 | (val & 0x800F00FF);
472 openpic_update_irq(opp, n_IRQ);
473 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
474 opp->src[n_IRQ].ipvp);
475 }
476
477 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
478 unsigned len)
479 {
480 openpic_t *opp = opaque;
481 IRQ_dst_t *dst;
482 int idx;
483
484 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
485 if (addr & 0xF)
486 return;
487 switch (addr) {
488 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
489 break;
490 case 0x40:
491 case 0x50:
492 case 0x60:
493 case 0x70:
494 case 0x80:
495 case 0x90:
496 case 0xA0:
497 case 0xB0:
498 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
499 break;
500 case 0x1000: /* FREP */
501 break;
502 case 0x1020: /* GLBC */
503 if (val & 0x80000000 && opp->reset)
504 opp->reset(opp);
505 opp->glbc = val & ~0x80000000;
506 break;
507 case 0x1080: /* VENI */
508 break;
509 case 0x1090: /* PINT */
510 for (idx = 0; idx < opp->nb_cpus; idx++) {
511 if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
512 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
513 dst = &opp->dst[idx];
514 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
515 } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
516 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
517 dst = &opp->dst[idx];
518 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
519 }
520 }
521 opp->pint = val;
522 break;
523 case 0x10A0: /* IPI_IPVP */
524 case 0x10B0:
525 case 0x10C0:
526 case 0x10D0:
527 {
528 int idx;
529 idx = (addr - 0x10A0) >> 4;
530 write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
531 }
532 break;
533 case 0x10E0: /* SPVE */
534 opp->spve = val & 0x000000FF;
535 break;
536 case 0x10F0: /* TIFR */
537 opp->tifr = val;
538 break;
539 default:
540 break;
541 }
542 }
543
544 static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
545 {
546 openpic_t *opp = opaque;
547 uint32_t retval;
548
549 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
550 retval = 0xFFFFFFFF;
551 if (addr & 0xF)
552 return retval;
553 switch (addr) {
554 case 0x1000: /* FREP */
555 retval = opp->frep;
556 break;
557 case 0x1020: /* GLBC */
558 retval = opp->glbc;
559 break;
560 case 0x1080: /* VENI */
561 retval = opp->veni;
562 break;
563 case 0x1090: /* PINT */
564 retval = 0x00000000;
565 break;
566 case 0x00: /* Block Revision Register1 (BRR1) */
567 case 0x40:
568 case 0x50:
569 case 0x60:
570 case 0x70:
571 case 0x80:
572 case 0x90:
573 case 0xA0:
574 case 0xB0:
575 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
576 break;
577 case 0x10A0: /* IPI_IPVP */
578 case 0x10B0:
579 case 0x10C0:
580 case 0x10D0:
581 {
582 int idx;
583 idx = (addr - 0x10A0) >> 4;
584 retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
585 }
586 break;
587 case 0x10E0: /* SPVE */
588 retval = opp->spve;
589 break;
590 case 0x10F0: /* TIFR */
591 retval = opp->tifr;
592 break;
593 default:
594 break;
595 }
596 DPRINTF("%s: => %08x\n", __func__, retval);
597
598 return retval;
599 }
600
601 static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val,
602 unsigned len)
603 {
604 openpic_t *opp = opaque;
605 int idx;
606
607 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
608 if (addr & 0xF)
609 return;
610 addr -= 0x10;
611 addr &= 0xFFFF;
612 idx = (addr & 0xFFF0) >> 6;
613 addr = addr & 0x30;
614 switch (addr) {
615 case 0x00: /* TICC */
616 break;
617 case 0x10: /* TIBC */
618 if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
619 (val & 0x80000000) == 0 &&
620 (opp->timers[idx].tibc & 0x80000000) != 0)
621 opp->timers[idx].ticc &= ~0x80000000;
622 opp->timers[idx].tibc = val;
623 break;
624 case 0x20: /* TIVP */
625 write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
626 break;
627 case 0x30: /* TIDE */
628 write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
629 break;
630 }
631 }
632
633 static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len)
634 {
635 openpic_t *opp = opaque;
636 uint32_t retval;
637 int idx;
638
639 DPRINTF("%s: addr %08x\n", __func__, addr);
640 retval = 0xFFFFFFFF;
641 if (addr & 0xF)
642 return retval;
643 addr -= 0x10;
644 addr &= 0xFFFF;
645 idx = (addr & 0xFFF0) >> 6;
646 addr = addr & 0x30;
647 switch (addr) {
648 case 0x00: /* TICC */
649 retval = opp->timers[idx].ticc;
650 break;
651 case 0x10: /* TIBC */
652 retval = opp->timers[idx].tibc;
653 break;
654 case 0x20: /* TIPV */
655 retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
656 break;
657 case 0x30: /* TIDE */
658 retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
659 break;
660 }
661 DPRINTF("%s: => %08x\n", __func__, retval);
662
663 return retval;
664 }
665
666 static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
667 unsigned len)
668 {
669 openpic_t *opp = opaque;
670 int idx;
671
672 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
673 if (addr & 0xF)
674 return;
675 addr = addr & 0xFFF0;
676 idx = addr >> 5;
677 if (addr & 0x10) {
678 /* EXDE / IFEDE / IEEDE */
679 write_IRQreg_ide(opp, idx, val);
680 } else {
681 /* EXVP / IFEVP / IEEVP */
682 write_IRQreg_ipvp(opp, idx, val);
683 }
684 }
685
686 static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
687 {
688 openpic_t *opp = opaque;
689 uint32_t retval;
690 int idx;
691
692 DPRINTF("%s: addr %08x\n", __func__, addr);
693 retval = 0xFFFFFFFF;
694 if (addr & 0xF)
695 return retval;
696 addr = addr & 0xFFF0;
697 idx = addr >> 5;
698 if (addr & 0x10) {
699 /* EXDE / IFEDE / IEEDE */
700 retval = read_IRQreg_ide(opp, idx);
701 } else {
702 /* EXVP / IFEVP / IEEVP */
703 retval = read_IRQreg_ipvp(opp, idx);
704 }
705 DPRINTF("%s: => %08x\n", __func__, retval);
706
707 return retval;
708 }
709
710 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
711 uint32_t val, int idx)
712 {
713 openpic_t *opp = opaque;
714 IRQ_src_t *src;
715 IRQ_dst_t *dst;
716 int s_IRQ, n_IRQ;
717
718 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
719 addr, val);
720 if (addr & 0xF)
721 return;
722 dst = &opp->dst[idx];
723 addr &= 0xFF0;
724 switch (addr) {
725 case 0x40: /* IPIDR */
726 case 0x50:
727 case 0x60:
728 case 0x70:
729 idx = (addr - 0x40) >> 4;
730 /* we use IDE as mask which CPUs to deliver the IPI to still. */
731 write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
732 opp->src[opp->irq_ipi0 + idx].ide | val);
733 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
734 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
735 break;
736 case 0x80: /* PCTP */
737 dst->pctp = val & 0x0000000F;
738 break;
739 case 0x90: /* WHOAMI */
740 /* Read-only register */
741 break;
742 case 0xA0: /* PIAC */
743 /* Read-only register */
744 break;
745 case 0xB0: /* PEOI */
746 DPRINTF("PEOI\n");
747 s_IRQ = IRQ_get_next(opp, &dst->servicing);
748 IRQ_resetbit(&dst->servicing, s_IRQ);
749 dst->servicing.next = -1;
750 /* Set up next servicing IRQ */
751 s_IRQ = IRQ_get_next(opp, &dst->servicing);
752 /* Check queued interrupts. */
753 n_IRQ = IRQ_get_next(opp, &dst->raised);
754 src = &opp->src[n_IRQ];
755 if (n_IRQ != -1 &&
756 (s_IRQ == -1 ||
757 IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
758 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
759 idx, n_IRQ);
760 openpic_irq_raise(opp, idx, src);
761 }
762 break;
763 default:
764 break;
765 }
766 }
767
768 static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
769 unsigned len)
770 {
771 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
772 }
773
774 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
775 int idx)
776 {
777 openpic_t *opp = opaque;
778 IRQ_src_t *src;
779 IRQ_dst_t *dst;
780 uint32_t retval;
781 int n_IRQ;
782
783 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
784 retval = 0xFFFFFFFF;
785 if (addr & 0xF)
786 return retval;
787 dst = &opp->dst[idx];
788 addr &= 0xFF0;
789 switch (addr) {
790 case 0x00: /* Block Revision Register1 (BRR1) */
791 retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
792 break;
793 case 0x80: /* PCTP */
794 retval = dst->pctp;
795 break;
796 case 0x90: /* WHOAMI */
797 retval = idx;
798 break;
799 case 0xA0: /* PIAC */
800 DPRINTF("Lower OpenPIC INT output\n");
801 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
802 n_IRQ = IRQ_get_next(opp, &dst->raised);
803 DPRINTF("PIAC: irq=%d\n", n_IRQ);
804 if (n_IRQ == -1) {
805 /* No more interrupt pending */
806 retval = IPVP_VECTOR(opp->spve);
807 } else {
808 src = &opp->src[n_IRQ];
809 if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
810 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
811 /* - Spurious level-sensitive IRQ
812 * - Priorities has been changed
813 * and the pending IRQ isn't allowed anymore
814 */
815 reset_bit(&src->ipvp, IPVP_ACTIVITY);
816 retval = IPVP_VECTOR(opp->spve);
817 } else {
818 /* IRQ enter servicing state */
819 IRQ_setbit(&dst->servicing, n_IRQ);
820 retval = IPVP_VECTOR(src->ipvp);
821 }
822 IRQ_resetbit(&dst->raised, n_IRQ);
823 dst->raised.next = -1;
824 if (!test_bit(&src->ipvp, IPVP_SENSE)) {
825 /* edge-sensitive IRQ */
826 reset_bit(&src->ipvp, IPVP_ACTIVITY);
827 src->pending = 0;
828 }
829
830 if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
831 src->ide &= ~(1 << idx);
832 if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
833 /* trigger on CPUs that didn't know about it yet */
834 openpic_set_irq(opp, n_IRQ, 1);
835 openpic_set_irq(opp, n_IRQ, 0);
836 /* if all CPUs knew about it, set active bit again */
837 set_bit(&src->ipvp, IPVP_ACTIVITY);
838 }
839 }
840 }
841 break;
842 case 0xB0: /* PEOI */
843 retval = 0;
844 break;
845 default:
846 break;
847 }
848 DPRINTF("%s: => %08x\n", __func__, retval);
849
850 return retval;
851 }
852
853 static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
854 {
855 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
856 }
857
858 static const MemoryRegionOps openpic_glb_ops = {
859 .write = openpic_gbl_write,
860 .read = openpic_gbl_read,
861 .endianness = DEVICE_LITTLE_ENDIAN,
862 .impl = {
863 .min_access_size = 4,
864 .max_access_size = 4,
865 },
866 };
867
868 static const MemoryRegionOps openpic_tmr_ops = {
869 .write = openpic_timer_write,
870 .read = openpic_timer_read,
871 .endianness = DEVICE_LITTLE_ENDIAN,
872 .impl = {
873 .min_access_size = 4,
874 .max_access_size = 4,
875 },
876 };
877
878 static const MemoryRegionOps openpic_cpu_ops = {
879 .write = openpic_cpu_write,
880 .read = openpic_cpu_read,
881 .endianness = DEVICE_LITTLE_ENDIAN,
882 .impl = {
883 .min_access_size = 4,
884 .max_access_size = 4,
885 },
886 };
887
888 static const MemoryRegionOps openpic_src_ops = {
889 .write = openpic_src_write,
890 .read = openpic_src_read,
891 .endianness = DEVICE_LITTLE_ENDIAN,
892 .impl = {
893 .min_access_size = 4,
894 .max_access_size = 4,
895 },
896 };
897
898 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
899 {
900 unsigned int i;
901
902 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
903 qemu_put_be32s(f, &q->queue[i]);
904
905 qemu_put_sbe32s(f, &q->next);
906 qemu_put_sbe32s(f, &q->priority);
907 }
908
909 static void openpic_save(QEMUFile* f, void *opaque)
910 {
911 openpic_t *opp = (openpic_t *)opaque;
912 unsigned int i;
913
914 qemu_put_be32s(f, &opp->frep);
915 qemu_put_be32s(f, &opp->glbc);
916 qemu_put_be32s(f, &opp->micr);
917 qemu_put_be32s(f, &opp->veni);
918 qemu_put_be32s(f, &opp->pint);
919 qemu_put_be32s(f, &opp->spve);
920 qemu_put_be32s(f, &opp->tifr);
921
922 for (i = 0; i < opp->max_irq; i++) {
923 qemu_put_be32s(f, &opp->src[i].ipvp);
924 qemu_put_be32s(f, &opp->src[i].ide);
925 qemu_put_sbe32s(f, &opp->src[i].type);
926 qemu_put_sbe32s(f, &opp->src[i].last_cpu);
927 qemu_put_sbe32s(f, &opp->src[i].pending);
928 }
929
930 qemu_put_sbe32s(f, &opp->nb_cpus);
931
932 for (i = 0; i < opp->nb_cpus; i++) {
933 qemu_put_be32s(f, &opp->dst[i].tfrr);
934 qemu_put_be32s(f, &opp->dst[i].pctp);
935 qemu_put_be32s(f, &opp->dst[i].pcsr);
936 openpic_save_IRQ_queue(f, &opp->dst[i].raised);
937 openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
938 }
939
940 for (i = 0; i < MAX_TMR; i++) {
941 qemu_put_be32s(f, &opp->timers[i].ticc);
942 qemu_put_be32s(f, &opp->timers[i].tibc);
943 }
944
945 pci_device_save(&opp->pci_dev, f);
946 }
947
948 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
949 {
950 unsigned int i;
951
952 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
953 qemu_get_be32s(f, &q->queue[i]);
954
955 qemu_get_sbe32s(f, &q->next);
956 qemu_get_sbe32s(f, &q->priority);
957 }
958
959 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
960 {
961 openpic_t *opp = (openpic_t *)opaque;
962 unsigned int i;
963
964 if (version_id != 1)
965 return -EINVAL;
966
967 qemu_get_be32s(f, &opp->frep);
968 qemu_get_be32s(f, &opp->glbc);
969 qemu_get_be32s(f, &opp->micr);
970 qemu_get_be32s(f, &opp->veni);
971 qemu_get_be32s(f, &opp->pint);
972 qemu_get_be32s(f, &opp->spve);
973 qemu_get_be32s(f, &opp->tifr);
974
975 for (i = 0; i < opp->max_irq; i++) {
976 qemu_get_be32s(f, &opp->src[i].ipvp);
977 qemu_get_be32s(f, &opp->src[i].ide);
978 qemu_get_sbe32s(f, &opp->src[i].type);
979 qemu_get_sbe32s(f, &opp->src[i].last_cpu);
980 qemu_get_sbe32s(f, &opp->src[i].pending);
981 }
982
983 qemu_get_sbe32s(f, &opp->nb_cpus);
984
985 for (i = 0; i < opp->nb_cpus; i++) {
986 qemu_get_be32s(f, &opp->dst[i].tfrr);
987 qemu_get_be32s(f, &opp->dst[i].pctp);
988 qemu_get_be32s(f, &opp->dst[i].pcsr);
989 openpic_load_IRQ_queue(f, &opp->dst[i].raised);
990 openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
991 }
992
993 for (i = 0; i < MAX_TMR; i++) {
994 qemu_get_be32s(f, &opp->timers[i].ticc);
995 qemu_get_be32s(f, &opp->timers[i].tibc);
996 }
997
998 return pci_device_load(&opp->pci_dev, f);
999 }
1000
1001 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1002 {
1003 int n_ci = IDR_CI0 - n_CPU;
1004
1005 if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && test_bit(&src->ide, n_ci)) {
1006 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1007 } else {
1008 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1009 }
1010 }
1011
1012 qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1013 qemu_irq **irqs, qemu_irq irq_out)
1014 {
1015 openpic_t *opp;
1016 int i, m;
1017 struct {
1018 const char *name;
1019 MemoryRegionOps const *ops;
1020 hwaddr start_addr;
1021 ram_addr_t size;
1022 } const list[] = {
1023 {"glb", &openpic_glb_ops, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1024 {"tmr", &openpic_tmr_ops, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1025 {"src", &openpic_src_ops, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1026 {"cpu", &openpic_cpu_ops, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1027 };
1028
1029 /* XXX: for now, only one CPU is supported */
1030 if (nb_cpus != 1)
1031 return NULL;
1032 opp = g_malloc0(sizeof(openpic_t));
1033
1034 memory_region_init(&opp->mem, "openpic", 0x40000);
1035
1036 for (i = 0; i < ARRAY_SIZE(list); i++) {
1037
1038 memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1039 list[i].name, list[i].size);
1040
1041 memory_region_add_subregion(&opp->mem, list[i].start_addr,
1042 &opp->sub_io_mem[i]);
1043 }
1044
1045 // isu_base &= 0xFFFC0000;
1046 opp->nb_cpus = nb_cpus;
1047 opp->max_irq = OPENPIC_MAX_IRQ;
1048 opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1049 opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1050 /* Set IRQ types */
1051 for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1052 opp->src[i].type = IRQ_EXTERNAL;
1053 }
1054 for (; i < OPENPIC_IRQ_TIM0; i++) {
1055 opp->src[i].type = IRQ_SPECIAL;
1056 }
1057 m = OPENPIC_IRQ_IPI0;
1058 for (; i < m; i++) {
1059 opp->src[i].type = IRQ_TIMER;
1060 }
1061 for (; i < OPENPIC_MAX_IRQ; i++) {
1062 opp->src[i].type = IRQ_INTERNAL;
1063 }
1064 for (i = 0; i < nb_cpus; i++)
1065 opp->dst[i].irqs = irqs[i];
1066 opp->irq_out = irq_out;
1067
1068 register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1069 openpic_save, openpic_load, opp);
1070 qemu_register_reset(openpic_reset, opp);
1071
1072 opp->reset = openpic_reset;
1073
1074 if (pmem)
1075 *pmem = &opp->mem;
1076
1077 return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1078 }
1079
1080 static void mpic_reset (void *opaque)
1081 {
1082 openpic_t *mpp = (openpic_t *)opaque;
1083 int i;
1084
1085 mpp->glbc = 0x80000000;
1086 /* Initialise controller registers */
1087 mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1088 mpp->veni = VENI;
1089 mpp->pint = 0x00000000;
1090 mpp->spve = 0x0000FFFF;
1091 /* Initialise IRQ sources */
1092 for (i = 0; i < mpp->max_irq; i++) {
1093 mpp->src[i].ipvp = 0x80800000;
1094 mpp->src[i].ide = 0x00000001;
1095 }
1096 /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1097 for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1098 mpp->src[i].ide = 0;
1099 }
1100 /* Initialise IRQ destinations */
1101 for (i = 0; i < MAX_CPU; i++) {
1102 mpp->dst[i].pctp = 0x0000000F;
1103 mpp->dst[i].tfrr = 0x00000000;
1104 memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1105 mpp->dst[i].raised.next = -1;
1106 memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1107 mpp->dst[i].servicing.next = -1;
1108 }
1109 /* Initialise timers */
1110 for (i = 0; i < MAX_TMR; i++) {
1111 mpp->timers[i].ticc = 0x00000000;
1112 mpp->timers[i].tibc = 0x80000000;
1113 }
1114 /* Go out of RESET state */
1115 mpp->glbc = 0x00000000;
1116 }
1117
1118 static void mpic_timer_write(void *opaque, hwaddr addr, uint64_t val,
1119 unsigned len)
1120 {
1121 openpic_t *mpp = opaque;
1122 int idx, cpu;
1123
1124 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1125 if (addr & 0xF)
1126 return;
1127 cpu = addr >> 12;
1128 idx = (addr >> 6) & 0x3;
1129 switch (addr & 0x30) {
1130 case 0x00: /* gtccr */
1131 break;
1132 case 0x10: /* gtbcr */
1133 if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1134 (val & 0x80000000) == 0 &&
1135 (mpp->timers[idx].tibc & 0x80000000) != 0)
1136 mpp->timers[idx].ticc &= ~0x80000000;
1137 mpp->timers[idx].tibc = val;
1138 break;
1139 case 0x20: /* GTIVPR */
1140 write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1141 break;
1142 case 0x30: /* GTIDR & TFRR */
1143 if ((addr & 0xF0) == 0xF0)
1144 mpp->dst[cpu].tfrr = val;
1145 else
1146 write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1147 break;
1148 }
1149 }
1150
1151 static uint64_t mpic_timer_read(void *opaque, hwaddr addr, unsigned len)
1152 {
1153 openpic_t *mpp = opaque;
1154 uint32_t retval;
1155 int idx, cpu;
1156
1157 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1158 retval = 0xFFFFFFFF;
1159 if (addr & 0xF)
1160 return retval;
1161 cpu = addr >> 12;
1162 idx = (addr >> 6) & 0x3;
1163 switch (addr & 0x30) {
1164 case 0x00: /* gtccr */
1165 retval = mpp->timers[idx].ticc;
1166 break;
1167 case 0x10: /* gtbcr */
1168 retval = mpp->timers[idx].tibc;
1169 break;
1170 case 0x20: /* TIPV */
1171 retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1172 break;
1173 case 0x30: /* TIDR */
1174 if ((addr &0xF0) == 0XF0)
1175 retval = mpp->dst[cpu].tfrr;
1176 else
1177 retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1178 break;
1179 }
1180 DPRINTF("%s: => %08x\n", __func__, retval);
1181
1182 return retval;
1183 }
1184
1185 static const MemoryRegionOps mpic_glb_ops = {
1186 .write = openpic_gbl_write,
1187 .read = openpic_gbl_read,
1188 .endianness = DEVICE_BIG_ENDIAN,
1189 .impl = {
1190 .min_access_size = 4,
1191 .max_access_size = 4,
1192 },
1193 };
1194
1195 static const MemoryRegionOps mpic_tmr_ops = {
1196 .write = mpic_timer_write,
1197 .read = mpic_timer_read,
1198 .endianness = DEVICE_BIG_ENDIAN,
1199 .impl = {
1200 .min_access_size = 4,
1201 .max_access_size = 4,
1202 },
1203 };
1204
1205 static const MemoryRegionOps mpic_cpu_ops = {
1206 .write = openpic_cpu_write,
1207 .read = openpic_cpu_read,
1208 .endianness = DEVICE_BIG_ENDIAN,
1209 .impl = {
1210 .min_access_size = 4,
1211 .max_access_size = 4,
1212 },
1213 };
1214
1215 static const MemoryRegionOps mpic_irq_ops = {
1216 .write = openpic_src_write,
1217 .read = openpic_src_read,
1218 .endianness = DEVICE_BIG_ENDIAN,
1219 .impl = {
1220 .min_access_size = 4,
1221 .max_access_size = 4,
1222 },
1223 };
1224
1225 qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
1226 int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1227 {
1228 openpic_t *mpp;
1229 int i;
1230 struct {
1231 const char *name;
1232 MemoryRegionOps const *ops;
1233 hwaddr start_addr;
1234 ram_addr_t size;
1235 } const list[] = {
1236 {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1237 {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1238 {"src", &mpic_irq_ops, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE},
1239 {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1240 };
1241
1242 mpp = g_malloc0(sizeof(openpic_t));
1243
1244 memory_region_init(&mpp->mem, "mpic", 0x40000);
1245 memory_region_add_subregion(address_space, base, &mpp->mem);
1246
1247 for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1248
1249 memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1250 list[i].name, list[i].size);
1251
1252 memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1253 &mpp->sub_io_mem[i]);
1254 }
1255
1256 mpp->nb_cpus = nb_cpus;
1257 mpp->max_irq = MPIC_MAX_IRQ;
1258 mpp->irq_ipi0 = MPIC_IPI_IRQ;
1259 mpp->irq_tim0 = MPIC_TMR_IRQ;
1260
1261 for (i = 0; i < nb_cpus; i++)
1262 mpp->dst[i].irqs = irqs[i];
1263 mpp->irq_out = irq_out;
1264
1265 /* Enable critical interrupt support */
1266 mpp->flags |= OPENPIC_FLAG_IDE_CRIT;
1267 mpp->reset = mpic_reset;
1268
1269 register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1270 qemu_register_reset(mpic_reset, mpp);
1271
1272 return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1273 }