]> git.proxmox.com Git - qemu.git/blob - hw/openpic.c
2a3b56af49530ab1002adad5744bd39295f5bd70
[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 /* Sub-regions */
211 MemoryRegion sub_io_mem[7];
212
213 /* Global registers */
214 uint32_t frep; /* Feature reporting register */
215 uint32_t glbc; /* Global configuration register */
216 uint32_t micr; /* MPIC interrupt configuration register */
217 uint32_t veni; /* Vendor identification register */
218 uint32_t pint; /* Processor initialization register */
219 uint32_t spve; /* Spurious vector register */
220 uint32_t tifr; /* Timer frequency reporting register */
221 /* Source registers */
222 IRQ_src_t src[MAX_IRQ];
223 /* Local registers per output pin */
224 IRQ_dst_t dst[MAX_CPU];
225 int nb_cpus;
226 /* Timer registers */
227 struct {
228 uint32_t ticc; /* Global timer current count register */
229 uint32_t tibc; /* Global timer base count register */
230 } timers[MAX_TMR];
231 /* IRQ out is used when in bypass mode (not implemented) */
232 qemu_irq irq_out;
233 int max_irq;
234 int irq_ipi0;
235 int irq_tim0;
236 void (*reset) (void *);
237 void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
238 } openpic_t;
239
240 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
241 {
242 set_bit(q->queue, n_IRQ);
243 }
244
245 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
246 {
247 reset_bit(q->queue, n_IRQ);
248 }
249
250 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
251 {
252 return test_bit(q->queue, n_IRQ);
253 }
254
255 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
256 {
257 int next, i;
258 int priority;
259
260 next = -1;
261 priority = -1;
262 for (i = 0; i < opp->max_irq; i++) {
263 if (IRQ_testbit(q, i)) {
264 DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
265 i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
266 if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
267 next = i;
268 priority = IPVP_PRIORITY(opp->src[i].ipvp);
269 }
270 }
271 }
272 q->next = next;
273 q->priority = priority;
274 }
275
276 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
277 {
278 if (q->next == -1) {
279 /* XXX: optimize */
280 IRQ_check(opp, q);
281 }
282
283 return q->next;
284 }
285
286 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
287 {
288 IRQ_dst_t *dst;
289 IRQ_src_t *src;
290 int priority;
291
292 dst = &opp->dst[n_CPU];
293 src = &opp->src[n_IRQ];
294 priority = IPVP_PRIORITY(src->ipvp);
295 if (priority <= dst->pctp) {
296 /* Too low priority */
297 DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
298 __func__, n_IRQ, n_CPU);
299 return;
300 }
301 if (IRQ_testbit(&dst->raised, n_IRQ)) {
302 /* Interrupt miss */
303 DPRINTF("%s: IRQ %d was missed on CPU %d\n",
304 __func__, n_IRQ, n_CPU);
305 return;
306 }
307 set_bit(&src->ipvp, IPVP_ACTIVITY);
308 IRQ_setbit(&dst->raised, n_IRQ);
309 if (priority < dst->raised.priority) {
310 /* An higher priority IRQ is already raised */
311 DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
312 __func__, n_IRQ, dst->raised.next, n_CPU);
313 return;
314 }
315 IRQ_get_next(opp, &dst->raised);
316 if (IRQ_get_next(opp, &dst->servicing) != -1 &&
317 priority <= dst->servicing.priority) {
318 DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
319 __func__, n_IRQ, dst->servicing.next, n_CPU);
320 /* Already servicing a higher priority IRQ */
321 return;
322 }
323 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
324 opp->irq_raise(opp, n_CPU, src);
325 }
326
327 /* update pic state because registers for n_IRQ have changed value */
328 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
329 {
330 IRQ_src_t *src;
331 int i;
332
333 src = &opp->src[n_IRQ];
334
335 if (!src->pending) {
336 /* no irq pending */
337 DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
338 return;
339 }
340 if (test_bit(&src->ipvp, IPVP_MASK)) {
341 /* Interrupt source is disabled */
342 DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
343 return;
344 }
345 if (IPVP_PRIORITY(src->ipvp) == 0) {
346 /* Priority set to zero */
347 DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
348 return;
349 }
350 if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
351 /* IRQ already active */
352 DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
353 return;
354 }
355 if (src->ide == 0x00000000) {
356 /* No target */
357 DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
358 return;
359 }
360
361 if (src->ide == (1 << src->last_cpu)) {
362 /* Only one CPU is allowed to receive this IRQ */
363 IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
364 } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
365 /* Directed delivery mode */
366 for (i = 0; i < opp->nb_cpus; i++) {
367 if (test_bit(&src->ide, i))
368 IRQ_local_pipe(opp, i, n_IRQ);
369 }
370 } else {
371 /* Distributed delivery mode */
372 for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
373 if (i == opp->nb_cpus)
374 i = 0;
375 if (test_bit(&src->ide, i)) {
376 IRQ_local_pipe(opp, i, n_IRQ);
377 src->last_cpu = i;
378 break;
379 }
380 }
381 }
382 }
383
384 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
385 {
386 openpic_t *opp = opaque;
387 IRQ_src_t *src;
388
389 src = &opp->src[n_IRQ];
390 DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
391 n_IRQ, level, src->ipvp);
392 if (test_bit(&src->ipvp, IPVP_SENSE)) {
393 /* level-sensitive irq */
394 src->pending = level;
395 if (!level)
396 reset_bit(&src->ipvp, IPVP_ACTIVITY);
397 } else {
398 /* edge-sensitive irq */
399 if (level)
400 src->pending = 1;
401 }
402 openpic_update_irq(opp, n_IRQ);
403 }
404
405 static void openpic_reset (void *opaque)
406 {
407 openpic_t *opp = (openpic_t *)opaque;
408 int i;
409
410 opp->glbc = 0x80000000;
411 /* Initialise controller registers */
412 opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
413 opp->veni = VENI;
414 opp->pint = 0x00000000;
415 opp->spve = 0x000000FF;
416 opp->tifr = 0x003F7A00;
417 /* ? */
418 opp->micr = 0x00000000;
419 /* Initialise IRQ sources */
420 for (i = 0; i < opp->max_irq; i++) {
421 opp->src[i].ipvp = 0xA0000000;
422 opp->src[i].ide = 0x00000000;
423 }
424 /* Initialise IRQ destinations */
425 for (i = 0; i < MAX_CPU; i++) {
426 opp->dst[i].pctp = 0x0000000F;
427 opp->dst[i].pcsr = 0x00000000;
428 memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
429 opp->dst[i].raised.next = -1;
430 memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
431 opp->dst[i].servicing.next = -1;
432 }
433 /* Initialise timers */
434 for (i = 0; i < MAX_TMR; i++) {
435 opp->timers[i].ticc = 0x00000000;
436 opp->timers[i].tibc = 0x80000000;
437 }
438 /* Go out of RESET state */
439 opp->glbc = 0x00000000;
440 }
441
442 static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
443 {
444 return opp->src[n_IRQ].ide;
445 }
446
447 static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
448 {
449 return opp->src[n_IRQ].ipvp;
450 }
451
452 static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
453 {
454 uint32_t tmp;
455
456 tmp = val & 0xC0000000;
457 tmp |= val & ((1ULL << MAX_CPU) - 1);
458 opp->src[n_IRQ].ide = tmp;
459 DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
460 }
461
462 static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
463 {
464 /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
465 /* ACTIVITY bit is read-only */
466 opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
467 | (val & 0x800F00FF);
468 openpic_update_irq(opp, n_IRQ);
469 DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
470 opp->src[n_IRQ].ipvp);
471 }
472
473 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
474 unsigned len)
475 {
476 openpic_t *opp = opaque;
477 IRQ_dst_t *dst;
478 int idx;
479
480 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
481 if (addr & 0xF)
482 return;
483 switch (addr) {
484 case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
485 break;
486 case 0x40:
487 case 0x50:
488 case 0x60:
489 case 0x70:
490 case 0x80:
491 case 0x90:
492 case 0xA0:
493 case 0xB0:
494 openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
495 break;
496 case 0x1000: /* FREP */
497 break;
498 case 0x1020: /* GLBC */
499 if (val & 0x80000000 && opp->reset)
500 opp->reset(opp);
501 opp->glbc = val & ~0x80000000;
502 break;
503 case 0x1080: /* VENI */
504 break;
505 case 0x1090: /* PINT */
506 for (idx = 0; idx < opp->nb_cpus; idx++) {
507 if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
508 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
509 dst = &opp->dst[idx];
510 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
511 } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
512 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
513 dst = &opp->dst[idx];
514 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
515 }
516 }
517 opp->pint = val;
518 break;
519 case 0x10A0: /* IPI_IPVP */
520 case 0x10B0:
521 case 0x10C0:
522 case 0x10D0:
523 {
524 int idx;
525 idx = (addr - 0x10A0) >> 4;
526 write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
527 }
528 break;
529 case 0x10E0: /* SPVE */
530 opp->spve = val & 0x000000FF;
531 break;
532 case 0x10F0: /* TIFR */
533 opp->tifr = val;
534 break;
535 default:
536 break;
537 }
538 }
539
540 static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
541 {
542 openpic_t *opp = opaque;
543 uint32_t retval;
544
545 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
546 retval = 0xFFFFFFFF;
547 if (addr & 0xF)
548 return retval;
549 switch (addr) {
550 case 0x1000: /* FREP */
551 retval = opp->frep;
552 break;
553 case 0x1020: /* GLBC */
554 retval = opp->glbc;
555 break;
556 case 0x1080: /* VENI */
557 retval = opp->veni;
558 break;
559 case 0x1090: /* PINT */
560 retval = 0x00000000;
561 break;
562 case 0x00: /* Block Revision Register1 (BRR1) */
563 case 0x40:
564 case 0x50:
565 case 0x60:
566 case 0x70:
567 case 0x80:
568 case 0x90:
569 case 0xA0:
570 case 0xB0:
571 retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
572 break;
573 case 0x10A0: /* IPI_IPVP */
574 case 0x10B0:
575 case 0x10C0:
576 case 0x10D0:
577 {
578 int idx;
579 idx = (addr - 0x10A0) >> 4;
580 retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
581 }
582 break;
583 case 0x10E0: /* SPVE */
584 retval = opp->spve;
585 break;
586 case 0x10F0: /* TIFR */
587 retval = opp->tifr;
588 break;
589 default:
590 break;
591 }
592 DPRINTF("%s: => %08x\n", __func__, retval);
593
594 return retval;
595 }
596
597 static void openpic_timer_write(void *opaque, hwaddr addr, uint64_t val,
598 unsigned len)
599 {
600 openpic_t *opp = opaque;
601 int idx;
602
603 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
604 if (addr & 0xF)
605 return;
606 addr -= 0x10;
607 addr &= 0xFFFF;
608 idx = (addr & 0xFFF0) >> 6;
609 addr = addr & 0x30;
610 switch (addr) {
611 case 0x00: /* TICC */
612 break;
613 case 0x10: /* TIBC */
614 if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
615 (val & 0x80000000) == 0 &&
616 (opp->timers[idx].tibc & 0x80000000) != 0)
617 opp->timers[idx].ticc &= ~0x80000000;
618 opp->timers[idx].tibc = val;
619 break;
620 case 0x20: /* TIVP */
621 write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
622 break;
623 case 0x30: /* TIDE */
624 write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
625 break;
626 }
627 }
628
629 static uint64_t openpic_timer_read(void *opaque, hwaddr addr, unsigned len)
630 {
631 openpic_t *opp = opaque;
632 uint32_t retval;
633 int idx;
634
635 DPRINTF("%s: addr %08x\n", __func__, addr);
636 retval = 0xFFFFFFFF;
637 if (addr & 0xF)
638 return retval;
639 addr -= 0x10;
640 addr &= 0xFFFF;
641 idx = (addr & 0xFFF0) >> 6;
642 addr = addr & 0x30;
643 switch (addr) {
644 case 0x00: /* TICC */
645 retval = opp->timers[idx].ticc;
646 break;
647 case 0x10: /* TIBC */
648 retval = opp->timers[idx].tibc;
649 break;
650 case 0x20: /* TIPV */
651 retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
652 break;
653 case 0x30: /* TIDE */
654 retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
655 break;
656 }
657 DPRINTF("%s: => %08x\n", __func__, retval);
658
659 return retval;
660 }
661
662 static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
663 unsigned len)
664 {
665 openpic_t *opp = opaque;
666 int idx;
667
668 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
669 if (addr & 0xF)
670 return;
671 addr = addr & 0xFFF0;
672 idx = addr >> 5;
673 if (addr & 0x10) {
674 /* EXDE / IFEDE / IEEDE */
675 write_IRQreg_ide(opp, idx, val);
676 } else {
677 /* EXVP / IFEVP / IEEVP */
678 write_IRQreg_ipvp(opp, idx, val);
679 }
680 }
681
682 static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
683 {
684 openpic_t *opp = opaque;
685 uint32_t retval;
686 int idx;
687
688 DPRINTF("%s: addr %08x\n", __func__, addr);
689 retval = 0xFFFFFFFF;
690 if (addr & 0xF)
691 return retval;
692 addr = addr & 0xFFF0;
693 idx = addr >> 5;
694 if (addr & 0x10) {
695 /* EXDE / IFEDE / IEEDE */
696 retval = read_IRQreg_ide(opp, idx);
697 } else {
698 /* EXVP / IFEVP / IEEVP */
699 retval = read_IRQreg_ipvp(opp, idx);
700 }
701 DPRINTF("%s: => %08x\n", __func__, retval);
702
703 return retval;
704 }
705
706 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
707 uint32_t val, int idx)
708 {
709 openpic_t *opp = opaque;
710 IRQ_src_t *src;
711 IRQ_dst_t *dst;
712 int s_IRQ, n_IRQ;
713
714 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
715 addr, val);
716 if (addr & 0xF)
717 return;
718 dst = &opp->dst[idx];
719 addr &= 0xFF0;
720 switch (addr) {
721 case 0x40: /* IPIDR */
722 case 0x50:
723 case 0x60:
724 case 0x70:
725 idx = (addr - 0x40) >> 4;
726 /* we use IDE as mask which CPUs to deliver the IPI to still. */
727 write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
728 opp->src[opp->irq_ipi0 + idx].ide | val);
729 openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
730 openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
731 break;
732 case 0x80: /* PCTP */
733 dst->pctp = val & 0x0000000F;
734 break;
735 case 0x90: /* WHOAMI */
736 /* Read-only register */
737 break;
738 case 0xA0: /* PIAC */
739 /* Read-only register */
740 break;
741 case 0xB0: /* PEOI */
742 DPRINTF("PEOI\n");
743 s_IRQ = IRQ_get_next(opp, &dst->servicing);
744 IRQ_resetbit(&dst->servicing, s_IRQ);
745 dst->servicing.next = -1;
746 /* Set up next servicing IRQ */
747 s_IRQ = IRQ_get_next(opp, &dst->servicing);
748 /* Check queued interrupts. */
749 n_IRQ = IRQ_get_next(opp, &dst->raised);
750 src = &opp->src[n_IRQ];
751 if (n_IRQ != -1 &&
752 (s_IRQ == -1 ||
753 IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
754 DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
755 idx, n_IRQ);
756 opp->irq_raise(opp, idx, src);
757 }
758 break;
759 default:
760 break;
761 }
762 }
763
764 static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
765 unsigned len)
766 {
767 openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
768 }
769
770 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
771 int idx)
772 {
773 openpic_t *opp = opaque;
774 IRQ_src_t *src;
775 IRQ_dst_t *dst;
776 uint32_t retval;
777 int n_IRQ;
778
779 DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
780 retval = 0xFFFFFFFF;
781 if (addr & 0xF)
782 return retval;
783 dst = &opp->dst[idx];
784 addr &= 0xFF0;
785 switch (addr) {
786 case 0x00: /* Block Revision Register1 (BRR1) */
787 retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
788 break;
789 case 0x80: /* PCTP */
790 retval = dst->pctp;
791 break;
792 case 0x90: /* WHOAMI */
793 retval = idx;
794 break;
795 case 0xA0: /* PIAC */
796 DPRINTF("Lower OpenPIC INT output\n");
797 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
798 n_IRQ = IRQ_get_next(opp, &dst->raised);
799 DPRINTF("PIAC: irq=%d\n", n_IRQ);
800 if (n_IRQ == -1) {
801 /* No more interrupt pending */
802 retval = IPVP_VECTOR(opp->spve);
803 } else {
804 src = &opp->src[n_IRQ];
805 if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
806 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
807 /* - Spurious level-sensitive IRQ
808 * - Priorities has been changed
809 * and the pending IRQ isn't allowed anymore
810 */
811 reset_bit(&src->ipvp, IPVP_ACTIVITY);
812 retval = IPVP_VECTOR(opp->spve);
813 } else {
814 /* IRQ enter servicing state */
815 IRQ_setbit(&dst->servicing, n_IRQ);
816 retval = IPVP_VECTOR(src->ipvp);
817 }
818 IRQ_resetbit(&dst->raised, n_IRQ);
819 dst->raised.next = -1;
820 if (!test_bit(&src->ipvp, IPVP_SENSE)) {
821 /* edge-sensitive IRQ */
822 reset_bit(&src->ipvp, IPVP_ACTIVITY);
823 src->pending = 0;
824 }
825
826 if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
827 src->ide &= ~(1 << idx);
828 if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
829 /* trigger on CPUs that didn't know about it yet */
830 openpic_set_irq(opp, n_IRQ, 1);
831 openpic_set_irq(opp, n_IRQ, 0);
832 /* if all CPUs knew about it, set active bit again */
833 set_bit(&src->ipvp, IPVP_ACTIVITY);
834 }
835 }
836 }
837 break;
838 case 0xB0: /* PEOI */
839 retval = 0;
840 break;
841 default:
842 break;
843 }
844 DPRINTF("%s: => %08x\n", __func__, retval);
845
846 return retval;
847 }
848
849 static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
850 {
851 return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
852 }
853
854 static const MemoryRegionOps openpic_glb_ops = {
855 .write = openpic_gbl_write,
856 .read = openpic_gbl_read,
857 .endianness = DEVICE_LITTLE_ENDIAN,
858 .impl = {
859 .min_access_size = 4,
860 .max_access_size = 4,
861 },
862 };
863
864 static const MemoryRegionOps openpic_tmr_ops = {
865 .write = openpic_timer_write,
866 .read = openpic_timer_read,
867 .endianness = DEVICE_LITTLE_ENDIAN,
868 .impl = {
869 .min_access_size = 4,
870 .max_access_size = 4,
871 },
872 };
873
874 static const MemoryRegionOps openpic_cpu_ops = {
875 .write = openpic_cpu_write,
876 .read = openpic_cpu_read,
877 .endianness = DEVICE_LITTLE_ENDIAN,
878 .impl = {
879 .min_access_size = 4,
880 .max_access_size = 4,
881 },
882 };
883
884 static const MemoryRegionOps openpic_src_ops = {
885 .write = openpic_src_write,
886 .read = openpic_src_read,
887 .endianness = DEVICE_LITTLE_ENDIAN,
888 .impl = {
889 .min_access_size = 4,
890 .max_access_size = 4,
891 },
892 };
893
894 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
895 {
896 unsigned int i;
897
898 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
899 qemu_put_be32s(f, &q->queue[i]);
900
901 qemu_put_sbe32s(f, &q->next);
902 qemu_put_sbe32s(f, &q->priority);
903 }
904
905 static void openpic_save(QEMUFile* f, void *opaque)
906 {
907 openpic_t *opp = (openpic_t *)opaque;
908 unsigned int i;
909
910 qemu_put_be32s(f, &opp->frep);
911 qemu_put_be32s(f, &opp->glbc);
912 qemu_put_be32s(f, &opp->micr);
913 qemu_put_be32s(f, &opp->veni);
914 qemu_put_be32s(f, &opp->pint);
915 qemu_put_be32s(f, &opp->spve);
916 qemu_put_be32s(f, &opp->tifr);
917
918 for (i = 0; i < opp->max_irq; i++) {
919 qemu_put_be32s(f, &opp->src[i].ipvp);
920 qemu_put_be32s(f, &opp->src[i].ide);
921 qemu_put_sbe32s(f, &opp->src[i].type);
922 qemu_put_sbe32s(f, &opp->src[i].last_cpu);
923 qemu_put_sbe32s(f, &opp->src[i].pending);
924 }
925
926 qemu_put_sbe32s(f, &opp->nb_cpus);
927
928 for (i = 0; i < opp->nb_cpus; i++) {
929 qemu_put_be32s(f, &opp->dst[i].tfrr);
930 qemu_put_be32s(f, &opp->dst[i].pctp);
931 qemu_put_be32s(f, &opp->dst[i].pcsr);
932 openpic_save_IRQ_queue(f, &opp->dst[i].raised);
933 openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
934 }
935
936 for (i = 0; i < MAX_TMR; i++) {
937 qemu_put_be32s(f, &opp->timers[i].ticc);
938 qemu_put_be32s(f, &opp->timers[i].tibc);
939 }
940
941 pci_device_save(&opp->pci_dev, f);
942 }
943
944 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
945 {
946 unsigned int i;
947
948 for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
949 qemu_get_be32s(f, &q->queue[i]);
950
951 qemu_get_sbe32s(f, &q->next);
952 qemu_get_sbe32s(f, &q->priority);
953 }
954
955 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
956 {
957 openpic_t *opp = (openpic_t *)opaque;
958 unsigned int i;
959
960 if (version_id != 1)
961 return -EINVAL;
962
963 qemu_get_be32s(f, &opp->frep);
964 qemu_get_be32s(f, &opp->glbc);
965 qemu_get_be32s(f, &opp->micr);
966 qemu_get_be32s(f, &opp->veni);
967 qemu_get_be32s(f, &opp->pint);
968 qemu_get_be32s(f, &opp->spve);
969 qemu_get_be32s(f, &opp->tifr);
970
971 for (i = 0; i < opp->max_irq; i++) {
972 qemu_get_be32s(f, &opp->src[i].ipvp);
973 qemu_get_be32s(f, &opp->src[i].ide);
974 qemu_get_sbe32s(f, &opp->src[i].type);
975 qemu_get_sbe32s(f, &opp->src[i].last_cpu);
976 qemu_get_sbe32s(f, &opp->src[i].pending);
977 }
978
979 qemu_get_sbe32s(f, &opp->nb_cpus);
980
981 for (i = 0; i < opp->nb_cpus; i++) {
982 qemu_get_be32s(f, &opp->dst[i].tfrr);
983 qemu_get_be32s(f, &opp->dst[i].pctp);
984 qemu_get_be32s(f, &opp->dst[i].pcsr);
985 openpic_load_IRQ_queue(f, &opp->dst[i].raised);
986 openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
987 }
988
989 for (i = 0; i < MAX_TMR; i++) {
990 qemu_get_be32s(f, &opp->timers[i].ticc);
991 qemu_get_be32s(f, &opp->timers[i].tibc);
992 }
993
994 return pci_device_load(&opp->pci_dev, f);
995 }
996
997 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
998 {
999 qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1000 }
1001
1002 qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
1003 qemu_irq **irqs, qemu_irq irq_out)
1004 {
1005 openpic_t *opp;
1006 int i, m;
1007 struct {
1008 const char *name;
1009 MemoryRegionOps const *ops;
1010 hwaddr start_addr;
1011 ram_addr_t size;
1012 } const list[] = {
1013 {"glb", &openpic_glb_ops, OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1014 {"tmr", &openpic_tmr_ops, OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1015 {"src", &openpic_src_ops, OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1016 {"cpu", &openpic_cpu_ops, OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1017 };
1018
1019 /* XXX: for now, only one CPU is supported */
1020 if (nb_cpus != 1)
1021 return NULL;
1022 opp = g_malloc0(sizeof(openpic_t));
1023
1024 memory_region_init(&opp->mem, "openpic", 0x40000);
1025
1026 for (i = 0; i < ARRAY_SIZE(list); i++) {
1027
1028 memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1029 list[i].name, list[i].size);
1030
1031 memory_region_add_subregion(&opp->mem, list[i].start_addr,
1032 &opp->sub_io_mem[i]);
1033 }
1034
1035 // isu_base &= 0xFFFC0000;
1036 opp->nb_cpus = nb_cpus;
1037 opp->max_irq = OPENPIC_MAX_IRQ;
1038 opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1039 opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1040 /* Set IRQ types */
1041 for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1042 opp->src[i].type = IRQ_EXTERNAL;
1043 }
1044 for (; i < OPENPIC_IRQ_TIM0; i++) {
1045 opp->src[i].type = IRQ_SPECIAL;
1046 }
1047 m = OPENPIC_IRQ_IPI0;
1048 for (; i < m; i++) {
1049 opp->src[i].type = IRQ_TIMER;
1050 }
1051 for (; i < OPENPIC_MAX_IRQ; i++) {
1052 opp->src[i].type = IRQ_INTERNAL;
1053 }
1054 for (i = 0; i < nb_cpus; i++)
1055 opp->dst[i].irqs = irqs[i];
1056 opp->irq_out = irq_out;
1057
1058 register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1059 openpic_save, openpic_load, opp);
1060 qemu_register_reset(openpic_reset, opp);
1061
1062 opp->irq_raise = openpic_irq_raise;
1063 opp->reset = openpic_reset;
1064
1065 if (pmem)
1066 *pmem = &opp->mem;
1067
1068 return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1069 }
1070
1071 static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1072 {
1073 int n_ci = IDR_CI0 - n_CPU;
1074
1075 if(test_bit(&src->ide, n_ci)) {
1076 qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1077 }
1078 else {
1079 qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1080 }
1081 }
1082
1083 static void mpic_reset (void *opaque)
1084 {
1085 openpic_t *mpp = (openpic_t *)opaque;
1086 int i;
1087
1088 mpp->glbc = 0x80000000;
1089 /* Initialise controller registers */
1090 mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1091 mpp->veni = VENI;
1092 mpp->pint = 0x00000000;
1093 mpp->spve = 0x0000FFFF;
1094 /* Initialise IRQ sources */
1095 for (i = 0; i < mpp->max_irq; i++) {
1096 mpp->src[i].ipvp = 0x80800000;
1097 mpp->src[i].ide = 0x00000001;
1098 }
1099 /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1100 for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1101 mpp->src[i].ide = 0;
1102 }
1103 /* Initialise IRQ destinations */
1104 for (i = 0; i < MAX_CPU; i++) {
1105 mpp->dst[i].pctp = 0x0000000F;
1106 mpp->dst[i].tfrr = 0x00000000;
1107 memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1108 mpp->dst[i].raised.next = -1;
1109 memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1110 mpp->dst[i].servicing.next = -1;
1111 }
1112 /* Initialise timers */
1113 for (i = 0; i < MAX_TMR; i++) {
1114 mpp->timers[i].ticc = 0x00000000;
1115 mpp->timers[i].tibc = 0x80000000;
1116 }
1117 /* Go out of RESET state */
1118 mpp->glbc = 0x00000000;
1119 }
1120
1121 static void mpic_timer_write(void *opaque, hwaddr addr, uint64_t val,
1122 unsigned len)
1123 {
1124 openpic_t *mpp = opaque;
1125 int idx, cpu;
1126
1127 DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1128 if (addr & 0xF)
1129 return;
1130 cpu = addr >> 12;
1131 idx = (addr >> 6) & 0x3;
1132 switch (addr & 0x30) {
1133 case 0x00: /* gtccr */
1134 break;
1135 case 0x10: /* gtbcr */
1136 if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1137 (val & 0x80000000) == 0 &&
1138 (mpp->timers[idx].tibc & 0x80000000) != 0)
1139 mpp->timers[idx].ticc &= ~0x80000000;
1140 mpp->timers[idx].tibc = val;
1141 break;
1142 case 0x20: /* GTIVPR */
1143 write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1144 break;
1145 case 0x30: /* GTIDR & TFRR */
1146 if ((addr & 0xF0) == 0xF0)
1147 mpp->dst[cpu].tfrr = val;
1148 else
1149 write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1150 break;
1151 }
1152 }
1153
1154 static uint64_t mpic_timer_read(void *opaque, hwaddr addr, unsigned len)
1155 {
1156 openpic_t *mpp = opaque;
1157 uint32_t retval;
1158 int idx, cpu;
1159
1160 DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1161 retval = 0xFFFFFFFF;
1162 if (addr & 0xF)
1163 return retval;
1164 cpu = addr >> 12;
1165 idx = (addr >> 6) & 0x3;
1166 switch (addr & 0x30) {
1167 case 0x00: /* gtccr */
1168 retval = mpp->timers[idx].ticc;
1169 break;
1170 case 0x10: /* gtbcr */
1171 retval = mpp->timers[idx].tibc;
1172 break;
1173 case 0x20: /* TIPV */
1174 retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1175 break;
1176 case 0x30: /* TIDR */
1177 if ((addr &0xF0) == 0XF0)
1178 retval = mpp->dst[cpu].tfrr;
1179 else
1180 retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1181 break;
1182 }
1183 DPRINTF("%s: => %08x\n", __func__, retval);
1184
1185 return retval;
1186 }
1187
1188 static const MemoryRegionOps mpic_glb_ops = {
1189 .write = openpic_gbl_write,
1190 .read = openpic_gbl_read,
1191 .endianness = DEVICE_BIG_ENDIAN,
1192 .impl = {
1193 .min_access_size = 4,
1194 .max_access_size = 4,
1195 },
1196 };
1197
1198 static const MemoryRegionOps mpic_tmr_ops = {
1199 .write = mpic_timer_write,
1200 .read = mpic_timer_read,
1201 .endianness = DEVICE_BIG_ENDIAN,
1202 .impl = {
1203 .min_access_size = 4,
1204 .max_access_size = 4,
1205 },
1206 };
1207
1208 static const MemoryRegionOps mpic_cpu_ops = {
1209 .write = openpic_cpu_write,
1210 .read = openpic_cpu_read,
1211 .endianness = DEVICE_BIG_ENDIAN,
1212 .impl = {
1213 .min_access_size = 4,
1214 .max_access_size = 4,
1215 },
1216 };
1217
1218 static const MemoryRegionOps mpic_irq_ops = {
1219 .write = openpic_src_write,
1220 .read = openpic_src_read,
1221 .endianness = DEVICE_BIG_ENDIAN,
1222 .impl = {
1223 .min_access_size = 4,
1224 .max_access_size = 4,
1225 },
1226 };
1227
1228 qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
1229 int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1230 {
1231 openpic_t *mpp;
1232 int i;
1233 struct {
1234 const char *name;
1235 MemoryRegionOps const *ops;
1236 hwaddr start_addr;
1237 ram_addr_t size;
1238 } const list[] = {
1239 {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1240 {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1241 {"src", &mpic_irq_ops, MPIC_SRC_REG_START, MPIC_SRC_REG_SIZE},
1242 {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1243 };
1244
1245 mpp = g_malloc0(sizeof(openpic_t));
1246
1247 memory_region_init(&mpp->mem, "mpic", 0x40000);
1248 memory_region_add_subregion(address_space, base, &mpp->mem);
1249
1250 for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1251
1252 memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1253 list[i].name, list[i].size);
1254
1255 memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1256 &mpp->sub_io_mem[i]);
1257 }
1258
1259 mpp->nb_cpus = nb_cpus;
1260 mpp->max_irq = MPIC_MAX_IRQ;
1261 mpp->irq_ipi0 = MPIC_IPI_IRQ;
1262 mpp->irq_tim0 = MPIC_TMR_IRQ;
1263
1264 for (i = 0; i < nb_cpus; i++)
1265 mpp->dst[i].irqs = irqs[i];
1266 mpp->irq_out = irq_out;
1267
1268 mpp->irq_raise = mpic_irq_raise;
1269 mpp->reset = mpic_reset;
1270
1271 register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1272 qemu_register_reset(mpic_reset, mpp);
1273
1274 return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1275 }