Commit b71699167155d3ae17bc18e74ea6d4360aa2540b
1 parent
72249e34
kvm/powerpc: Enable MPIC for E500 platform.
MPIC and OpenPIC have very similar design. So a lot of code can be reused. Signed-off-by: Liu Yu <yu.liu@freescale.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6659 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
618 additions
and
87 deletions
hw/openpic.c
@@ -35,6 +35,7 @@ | @@ -35,6 +35,7 @@ | ||
35 | #include "hw.h" | 35 | #include "hw.h" |
36 | #include "ppc_mac.h" | 36 | #include "ppc_mac.h" |
37 | #include "pci.h" | 37 | #include "pci.h" |
38 | +#include "openpic.h" | ||
38 | 39 | ||
39 | //#define DEBUG_OPENPIC | 40 | //#define DEBUG_OPENPIC |
40 | 41 | ||
@@ -60,14 +61,10 @@ | @@ -60,14 +61,10 @@ | ||
60 | 61 | ||
61 | #define VID (0x00000000) | 62 | #define VID (0x00000000) |
62 | 63 | ||
63 | -#define OPENPIC_LITTLE_ENDIAN 1 | ||
64 | -#define OPENPIC_BIG_ENDIAN 0 | ||
65 | - | ||
66 | #elif defined(USE_MPCxxx) | 64 | #elif defined(USE_MPCxxx) |
67 | 65 | ||
68 | #define MAX_CPU 2 | 66 | #define MAX_CPU 2 |
69 | -#define MAX_IRQ 64 | ||
70 | -#define EXT_IRQ 48 | 67 | +#define MAX_IRQ 128 |
71 | #define MAX_DBL 0 | 68 | #define MAX_DBL 0 |
72 | #define MAX_MBX 0 | 69 | #define MAX_MBX 0 |
73 | #define MAX_TMR 4 | 70 | #define MAX_TMR 4 |
@@ -81,28 +78,68 @@ enum { | @@ -81,28 +78,68 @@ enum { | ||
81 | IRQ_IDE, | 78 | IRQ_IDE, |
82 | }; | 79 | }; |
83 | 80 | ||
84 | -#define OPENPIC_LITTLE_ENDIAN 1 | ||
85 | -#define OPENPIC_BIG_ENDIAN 0 | 81 | +/* OpenPIC */ |
82 | +#define OPENPIC_MAX_CPU 2 | ||
83 | +#define OPENPIC_MAX_IRQ 64 | ||
84 | +#define OPENPIC_EXT_IRQ 48 | ||
85 | +#define OPENPIC_MAX_TMR MAX_TMR | ||
86 | +#define OPENPIC_MAX_IPI MAX_IPI | ||
86 | 87 | ||
88 | +/* Interrupt definitions */ | ||
89 | +#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */ | ||
90 | +#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */ | ||
91 | +#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */ | ||
92 | +#if OPENPIC_MAX_IPI > 0 | ||
93 | +#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */ | ||
94 | +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */ | ||
87 | #else | 95 | #else |
88 | -#error "Please select which OpenPic implementation is to be emulated" | 96 | +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */ |
97 | +#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */ | ||
89 | #endif | 98 | #endif |
90 | 99 | ||
91 | -#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \ | ||
92 | - (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN) | ||
93 | -#define OPENPIC_SWAP | ||
94 | -#endif | 100 | +/* MPIC */ |
101 | +#define MPIC_MAX_CPU 1 | ||
102 | +#define MPIC_MAX_EXT 12 | ||
103 | +#define MPIC_MAX_INT 64 | ||
104 | +#define MPIC_MAX_MSG 4 | ||
105 | +#define MPIC_MAX_MSI 8 | ||
106 | +#define MPIC_MAX_TMR MAX_TMR | ||
107 | +#define MPIC_MAX_IPI MAX_IPI | ||
108 | +#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU)) | ||
95 | 109 | ||
96 | /* Interrupt definitions */ | 110 | /* Interrupt definitions */ |
97 | -#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */ | ||
98 | -#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */ | ||
99 | -#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */ | ||
100 | -#if MAX_IPI > 0 | ||
101 | -#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */ | ||
102 | -#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */ | 111 | +#define MPIC_EXT_IRQ 0 |
112 | +#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT) | ||
113 | +#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT) | ||
114 | +#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR) | ||
115 | +#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG) | ||
116 | +#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI) | ||
117 | + | ||
118 | +#define MPIC_GLB_REG_START 0x0 | ||
119 | +#define MPIC_GLB_REG_SIZE 0x10F0 | ||
120 | +#define MPIC_TMR_REG_START 0x10F0 | ||
121 | +#define MPIC_TMR_REG_SIZE 0x220 | ||
122 | +#define MPIC_EXT_REG_START 0x10000 | ||
123 | +#define MPIC_EXT_REG_SIZE 0x180 | ||
124 | +#define MPIC_INT_REG_START 0x10200 | ||
125 | +#define MPIC_INT_REG_SIZE 0x800 | ||
126 | +#define MPIC_MSG_REG_START 0x11600 | ||
127 | +#define MPIC_MSG_REG_SIZE 0x100 | ||
128 | +#define MPIC_MSI_REG_START 0x11C00 | ||
129 | +#define MPIC_MSI_REG_SIZE 0x100 | ||
130 | +#define MPIC_CPU_REG_START 0x20000 | ||
131 | +#define MPIC_CPU_REG_SIZE 0x100 | ||
132 | + | ||
133 | +enum mpic_ide_bits { | ||
134 | + IDR_EP = 0, | ||
135 | + IDR_CI0 = 1, | ||
136 | + IDR_CI1 = 2, | ||
137 | + IDR_P1 = 30, | ||
138 | + IDR_P0 = 31, | ||
139 | +}; | ||
140 | + | ||
103 | #else | 141 | #else |
104 | -#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */ | ||
105 | -#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */ | 142 | +#error "Please select which OpenPic implementation is to be emulated" |
106 | #endif | 143 | #endif |
107 | 144 | ||
108 | #define BF_WIDTH(_bits_) \ | 145 | #define BF_WIDTH(_bits_) \ |
@@ -157,6 +194,7 @@ enum IPVP_bits { | @@ -157,6 +194,7 @@ enum IPVP_bits { | ||
157 | #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) | 194 | #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) |
158 | 195 | ||
159 | typedef struct IRQ_dst_t { | 196 | typedef struct IRQ_dst_t { |
197 | + uint32_t tfrr; | ||
160 | uint32_t pctp; /* CPU current task priority */ | 198 | uint32_t pctp; /* CPU current task priority */ |
161 | uint32_t pcsr; /* CPU sensitivity register */ | 199 | uint32_t pcsr; /* CPU sensitivity register */ |
162 | IRQ_queue_t raised; | 200 | IRQ_queue_t raised; |
@@ -200,8 +238,22 @@ typedef struct openpic_t { | @@ -200,8 +238,22 @@ typedef struct openpic_t { | ||
200 | #endif | 238 | #endif |
201 | /* IRQ out is used when in bypass mode (not implemented) */ | 239 | /* IRQ out is used when in bypass mode (not implemented) */ |
202 | qemu_irq irq_out; | 240 | qemu_irq irq_out; |
241 | + int max_irq; | ||
242 | + int irq_ipi0; | ||
243 | + int irq_tim0; | ||
244 | + int need_swap; | ||
245 | + void (*reset) (void *); | ||
246 | + void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *); | ||
203 | } openpic_t; | 247 | } openpic_t; |
204 | 248 | ||
249 | +static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val) | ||
250 | +{ | ||
251 | + if (opp->need_swap) | ||
252 | + return bswap32(val); | ||
253 | + | ||
254 | + return val; | ||
255 | +} | ||
256 | + | ||
205 | static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) | 257 | static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) |
206 | { | 258 | { |
207 | set_bit(q->queue, n_IRQ); | 259 | set_bit(q->queue, n_IRQ); |
@@ -224,7 +276,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) | @@ -224,7 +276,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) | ||
224 | 276 | ||
225 | next = -1; | 277 | next = -1; |
226 | priority = -1; | 278 | priority = -1; |
227 | - for (i = 0; i < MAX_IRQ; i++) { | 279 | + for (i = 0; i < opp->max_irq; i++) { |
228 | if (IRQ_testbit(q, i)) { | 280 | if (IRQ_testbit(q, i)) { |
229 | DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", | 281 | DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", |
230 | i, IPVP_PRIORITY(opp->src[i].ipvp), priority); | 282 | i, IPVP_PRIORITY(opp->src[i].ipvp), priority); |
@@ -286,7 +338,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) | @@ -286,7 +338,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) | ||
286 | return; | 338 | return; |
287 | } | 339 | } |
288 | DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ); | 340 | DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ); |
289 | - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); | 341 | + opp->irq_raise(opp, n_CPU, src); |
290 | } | 342 | } |
291 | 343 | ||
292 | /* update pic state because registers for n_IRQ have changed value */ | 344 | /* update pic state because registers for n_IRQ have changed value */ |
@@ -374,7 +426,7 @@ static void openpic_reset (void *opaque) | @@ -374,7 +426,7 @@ static void openpic_reset (void *opaque) | ||
374 | 426 | ||
375 | opp->glbc = 0x80000000; | 427 | opp->glbc = 0x80000000; |
376 | /* Initialise controller registers */ | 428 | /* Initialise controller registers */ |
377 | - opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; | 429 | + opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; |
378 | opp->veni = VENI; | 430 | opp->veni = VENI; |
379 | opp->pint = 0x00000000; | 431 | opp->pint = 0x00000000; |
380 | opp->spve = 0x000000FF; | 432 | opp->spve = 0x000000FF; |
@@ -382,7 +434,7 @@ static void openpic_reset (void *opaque) | @@ -382,7 +434,7 @@ static void openpic_reset (void *opaque) | ||
382 | /* ? */ | 434 | /* ? */ |
383 | opp->micr = 0x00000000; | 435 | opp->micr = 0x00000000; |
384 | /* Initialise IRQ sources */ | 436 | /* Initialise IRQ sources */ |
385 | - for (i = 0; i < MAX_IRQ; i++) { | 437 | + for (i = 0; i < opp->max_irq; i++) { |
386 | opp->src[i].ipvp = 0xA0000000; | 438 | opp->src[i].ipvp = 0xA0000000; |
387 | opp->src[i].ide = 0x00000000; | 439 | opp->src[i].ide = 0x00000000; |
388 | } | 440 | } |
@@ -535,7 +587,7 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx, | @@ -535,7 +587,7 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx, | ||
535 | #endif | 587 | #endif |
536 | #endif /* 0 : Code provision for Intel model */ | 588 | #endif /* 0 : Code provision for Intel model */ |
537 | 589 | ||
538 | -static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | 590 | +static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val) |
539 | { | 591 | { |
540 | openpic_t *opp = opaque; | 592 | openpic_t *opp = opaque; |
541 | IRQ_dst_t *dst; | 593 | IRQ_dst_t *dst; |
@@ -544,16 +596,16 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | @@ -544,16 +596,16 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | ||
544 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | 596 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
545 | if (addr & 0xF) | 597 | if (addr & 0xF) |
546 | return; | 598 | return; |
547 | -#if defined OPENPIC_SWAP | ||
548 | - val = bswap32(val); | 599 | +#if defined TARGET_WORDS_BIGENDIAN |
600 | + val = openpic_swap32(opp, val); | ||
549 | #endif | 601 | #endif |
550 | addr &= 0xFF; | 602 | addr &= 0xFF; |
551 | switch (addr) { | 603 | switch (addr) { |
552 | case 0x00: /* FREP */ | 604 | case 0x00: /* FREP */ |
553 | break; | 605 | break; |
554 | case 0x20: /* GLBC */ | 606 | case 0x20: /* GLBC */ |
555 | - if (val & 0x80000000) | ||
556 | - openpic_reset(opp); | 607 | + if (val & 0x80000000 && opp->reset) |
608 | + opp->reset(opp); | ||
557 | opp->glbc = val & ~0x80000000; | 609 | opp->glbc = val & ~0x80000000; |
558 | break; | 610 | break; |
559 | case 0x80: /* VENI */ | 611 | case 0x80: /* VENI */ |
@@ -580,7 +632,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | @@ -580,7 +632,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | ||
580 | { | 632 | { |
581 | int idx; | 633 | int idx; |
582 | idx = (addr - 0xA0) >> 4; | 634 | idx = (addr - 0xA0) >> 4; |
583 | - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val); | 635 | + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val); |
584 | } | 636 | } |
585 | break; | 637 | break; |
586 | #endif | 638 | #endif |
@@ -595,7 +647,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | @@ -595,7 +647,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) | ||
595 | } | 647 | } |
596 | } | 648 | } |
597 | 649 | ||
598 | -static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) | 650 | +static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr) |
599 | { | 651 | { |
600 | openpic_t *opp = opaque; | 652 | openpic_t *opp = opaque; |
601 | uint32_t retval; | 653 | uint32_t retval; |
@@ -626,7 +678,7 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) | @@ -626,7 +678,7 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) | ||
626 | { | 678 | { |
627 | int idx; | 679 | int idx; |
628 | idx = (addr - 0xA0) >> 4; | 680 | idx = (addr - 0xA0) >> 4; |
629 | - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP); | 681 | + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP); |
630 | } | 682 | } |
631 | break; | 683 | break; |
632 | #endif | 684 | #endif |
@@ -640,8 +692,8 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) | @@ -640,8 +692,8 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) | ||
640 | break; | 692 | break; |
641 | } | 693 | } |
642 | DPRINTF("%s: => %08x\n", __func__, retval); | 694 | DPRINTF("%s: => %08x\n", __func__, retval); |
643 | -#if defined OPENPIC_SWAP | ||
644 | - retval = bswap32(retval); | 695 | +#if defined TARGET_WORDS_BIGENDIAN |
696 | + retval = openpic_swap32(opp, retval); | ||
645 | #endif | 697 | #endif |
646 | 698 | ||
647 | return retval; | 699 | return retval; |
@@ -655,8 +707,8 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) | @@ -655,8 +707,8 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) | ||
655 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | 707 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
656 | if (addr & 0xF) | 708 | if (addr & 0xF) |
657 | return; | 709 | return; |
658 | -#if defined OPENPIC_SWAP | ||
659 | - val = bswap32(val); | 710 | +#if defined TARGET_WORDS_BIGENDIAN |
711 | + val = openpic_swap32(opp, val); | ||
660 | #endif | 712 | #endif |
661 | addr -= 0x1100; | 713 | addr -= 0x1100; |
662 | addr &= 0xFFFF; | 714 | addr &= 0xFFFF; |
@@ -673,10 +725,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) | @@ -673,10 +725,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) | ||
673 | opp->timers[idx].tibc = val; | 725 | opp->timers[idx].tibc = val; |
674 | break; | 726 | break; |
675 | case 0x20: /* TIVP */ | 727 | case 0x20: /* TIVP */ |
676 | - write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val); | 728 | + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val); |
677 | break; | 729 | break; |
678 | case 0x30: /* TIDE */ | 730 | case 0x30: /* TIDE */ |
679 | - write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val); | 731 | + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val); |
680 | break; | 732 | break; |
681 | } | 733 | } |
682 | } | 734 | } |
@@ -703,15 +755,15 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr) | @@ -703,15 +755,15 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr) | ||
703 | retval = opp->timers[idx].tibc; | 755 | retval = opp->timers[idx].tibc; |
704 | break; | 756 | break; |
705 | case 0x20: /* TIPV */ | 757 | case 0x20: /* TIPV */ |
706 | - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP); | 758 | + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP); |
707 | break; | 759 | break; |
708 | case 0x30: /* TIDE */ | 760 | case 0x30: /* TIDE */ |
709 | - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE); | 761 | + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE); |
710 | break; | 762 | break; |
711 | } | 763 | } |
712 | DPRINTF("%s: => %08x\n", __func__, retval); | 764 | DPRINTF("%s: => %08x\n", __func__, retval); |
713 | -#if defined OPENPIC_SWAP | ||
714 | - retval = bswap32(retval); | 765 | +#if defined TARGET_WORDS_BIGENDIAN |
766 | + retval = openpic_swap32(opp, retval); | ||
715 | #endif | 767 | #endif |
716 | 768 | ||
717 | return retval; | 769 | return retval; |
@@ -725,8 +777,8 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) | @@ -725,8 +777,8 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) | ||
725 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | 777 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
726 | if (addr & 0xF) | 778 | if (addr & 0xF) |
727 | return; | 779 | return; |
728 | -#if defined OPENPIC_SWAP | ||
729 | - val = tswap32(val); | 780 | +#if defined TARGET_WORDS_BIGENDIAN |
781 | + val = openpic_swap32(opp, val); | ||
730 | #endif | 782 | #endif |
731 | addr = addr & 0xFFF0; | 783 | addr = addr & 0xFFF0; |
732 | idx = addr >> 5; | 784 | idx = addr >> 5; |
@@ -759,14 +811,14 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr) | @@ -759,14 +811,14 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr) | ||
759 | retval = read_IRQreg(opp, idx, IRQ_IPVP); | 811 | retval = read_IRQreg(opp, idx, IRQ_IPVP); |
760 | } | 812 | } |
761 | DPRINTF("%s: => %08x\n", __func__, retval); | 813 | DPRINTF("%s: => %08x\n", __func__, retval); |
762 | -#if defined OPENPIC_SWAP | ||
763 | - retval = tswap32(retval); | 814 | +#if defined TARGET_WORDS_BIGENDIAN |
815 | + retval = openpic_swap32(opp, retval); | ||
764 | #endif | 816 | #endif |
765 | 817 | ||
766 | return retval; | 818 | return retval; |
767 | } | 819 | } |
768 | 820 | ||
769 | -static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | 821 | +static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t val) |
770 | { | 822 | { |
771 | openpic_t *opp = opaque; | 823 | openpic_t *opp = opaque; |
772 | IRQ_src_t *src; | 824 | IRQ_src_t *src; |
@@ -776,8 +828,8 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | @@ -776,8 +828,8 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | ||
776 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | 828 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
777 | if (addr & 0xF) | 829 | if (addr & 0xF) |
778 | return; | 830 | return; |
779 | -#if defined OPENPIC_SWAP | ||
780 | - val = bswap32(val); | 831 | +#if defined TARGET_WORDS_BIGENDIAN |
832 | + val = openpic_swap32(opp, val); | ||
781 | #endif | 833 | #endif |
782 | addr &= 0x1FFF0; | 834 | addr &= 0x1FFF0; |
783 | idx = addr / 0x1000; | 835 | idx = addr / 0x1000; |
@@ -790,9 +842,9 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | @@ -790,9 +842,9 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | ||
790 | case 0x60: | 842 | case 0x60: |
791 | case 0x70: | 843 | case 0x70: |
792 | idx = (addr - 0x40) >> 4; | 844 | idx = (addr - 0x40) >> 4; |
793 | - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val); | ||
794 | - openpic_set_irq(opp, IRQ_IPI0 + idx, 1); | ||
795 | - openpic_set_irq(opp, IRQ_IPI0 + idx, 0); | 845 | + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val); |
846 | + openpic_set_irq(opp, opp->irq_ipi0 + idx, 1); | ||
847 | + openpic_set_irq(opp, opp->irq_ipi0 + idx, 0); | ||
796 | break; | 848 | break; |
797 | #endif | 849 | #endif |
798 | case 0x80: /* PCTP */ | 850 | case 0x80: /* PCTP */ |
@@ -819,7 +871,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | @@ -819,7 +871,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | ||
819 | IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) { | 871 | IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) { |
820 | DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", | 872 | DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", |
821 | idx, n_IRQ); | 873 | idx, n_IRQ); |
822 | - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); | 874 | + opp->irq_raise(opp, idx, src); |
823 | } | 875 | } |
824 | break; | 876 | break; |
825 | default: | 877 | default: |
@@ -827,7 +879,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | @@ -827,7 +879,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) | ||
827 | } | 879 | } |
828 | } | 880 | } |
829 | 881 | ||
830 | -static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) | 882 | +static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr) |
831 | { | 883 | { |
832 | openpic_t *opp = opaque; | 884 | openpic_t *opp = opaque; |
833 | IRQ_src_t *src; | 885 | IRQ_src_t *src; |
@@ -889,15 +941,15 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) | @@ -889,15 +941,15 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) | ||
889 | case 0x40: /* IDE */ | 941 | case 0x40: /* IDE */ |
890 | case 0x50: | 942 | case 0x50: |
891 | idx = (addr - 0x40) >> 4; | 943 | idx = (addr - 0x40) >> 4; |
892 | - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE); | 944 | + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE); |
893 | break; | 945 | break; |
894 | #endif | 946 | #endif |
895 | default: | 947 | default: |
896 | break; | 948 | break; |
897 | } | 949 | } |
898 | DPRINTF("%s: => %08x\n", __func__, retval); | 950 | DPRINTF("%s: => %08x\n", __func__, retval); |
899 | -#if defined OPENPIC_SWAP | ||
900 | - retval= bswap32(retval); | 951 | +#if defined TARGET_WORDS_BIGENDIAN |
952 | + retval = openpic_swap32(opp, retval); | ||
901 | #endif | 953 | #endif |
902 | 954 | ||
903 | return retval; | 955 | return retval; |
@@ -989,7 +1041,7 @@ static void openpic_map(PCIDevice *pci_dev, int region_num, | @@ -989,7 +1041,7 @@ static void openpic_map(PCIDevice *pci_dev, int region_num, | ||
989 | addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR); | 1041 | addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR); |
990 | /* Interrupt source registers */ | 1042 | /* Interrupt source registers */ |
991 | DPRINTF("Register OPENPIC src %08x => %08x\n", | 1043 | DPRINTF("Register OPENPIC src %08x => %08x\n", |
992 | - addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2)); | 1044 | + addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2)); |
993 | /* Per CPU registers */ | 1045 | /* Per CPU registers */ |
994 | DPRINTF("Register OPENPIC dst %08x => %08x\n", | 1046 | DPRINTF("Register OPENPIC dst %08x => %08x\n", |
995 | addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU); | 1047 | addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU); |
@@ -1026,7 +1078,7 @@ static void openpic_save(QEMUFile* f, void *opaque) | @@ -1026,7 +1078,7 @@ static void openpic_save(QEMUFile* f, void *opaque) | ||
1026 | qemu_put_be32s(f, &opp->spve); | 1078 | qemu_put_be32s(f, &opp->spve); |
1027 | qemu_put_be32s(f, &opp->tifr); | 1079 | qemu_put_be32s(f, &opp->tifr); |
1028 | 1080 | ||
1029 | - for (i = 0; i < MAX_IRQ; i++) { | 1081 | + for (i = 0; i < opp->max_irq; i++) { |
1030 | qemu_put_be32s(f, &opp->src[i].ipvp); | 1082 | qemu_put_be32s(f, &opp->src[i].ipvp); |
1031 | qemu_put_be32s(f, &opp->src[i].ide); | 1083 | qemu_put_be32s(f, &opp->src[i].ide); |
1032 | qemu_put_sbe32s(f, &opp->src[i].type); | 1084 | qemu_put_sbe32s(f, &opp->src[i].type); |
@@ -1034,15 +1086,16 @@ static void openpic_save(QEMUFile* f, void *opaque) | @@ -1034,15 +1086,16 @@ static void openpic_save(QEMUFile* f, void *opaque) | ||
1034 | qemu_put_sbe32s(f, &opp->src[i].pending); | 1086 | qemu_put_sbe32s(f, &opp->src[i].pending); |
1035 | } | 1087 | } |
1036 | 1088 | ||
1037 | - for (i = 0; i < MAX_IRQ; i++) { | 1089 | + qemu_put_sbe32s(f, &opp->nb_cpus); |
1090 | + | ||
1091 | + for (i = 0; i < opp->nb_cpus; i++) { | ||
1092 | + qemu_put_be32s(f, &opp->dst[i].tfrr); | ||
1038 | qemu_put_be32s(f, &opp->dst[i].pctp); | 1093 | qemu_put_be32s(f, &opp->dst[i].pctp); |
1039 | qemu_put_be32s(f, &opp->dst[i].pcsr); | 1094 | qemu_put_be32s(f, &opp->dst[i].pcsr); |
1040 | openpic_save_IRQ_queue(f, &opp->dst[i].raised); | 1095 | openpic_save_IRQ_queue(f, &opp->dst[i].raised); |
1041 | openpic_save_IRQ_queue(f, &opp->dst[i].servicing); | 1096 | openpic_save_IRQ_queue(f, &opp->dst[i].servicing); |
1042 | } | 1097 | } |
1043 | 1098 | ||
1044 | - qemu_put_sbe32s(f, &opp->nb_cpus); | ||
1045 | - | ||
1046 | for (i = 0; i < MAX_TMR; i++) { | 1099 | for (i = 0; i < MAX_TMR; i++) { |
1047 | qemu_put_be32s(f, &opp->timers[i].ticc); | 1100 | qemu_put_be32s(f, &opp->timers[i].ticc); |
1048 | qemu_put_be32s(f, &opp->timers[i].tibc); | 1101 | qemu_put_be32s(f, &opp->timers[i].tibc); |
@@ -1092,7 +1145,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | @@ -1092,7 +1145,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | ||
1092 | qemu_get_be32s(f, &opp->spve); | 1145 | qemu_get_be32s(f, &opp->spve); |
1093 | qemu_get_be32s(f, &opp->tifr); | 1146 | qemu_get_be32s(f, &opp->tifr); |
1094 | 1147 | ||
1095 | - for (i = 0; i < MAX_IRQ; i++) { | 1148 | + for (i = 0; i < opp->max_irq; i++) { |
1096 | qemu_get_be32s(f, &opp->src[i].ipvp); | 1149 | qemu_get_be32s(f, &opp->src[i].ipvp); |
1097 | qemu_get_be32s(f, &opp->src[i].ide); | 1150 | qemu_get_be32s(f, &opp->src[i].ide); |
1098 | qemu_get_sbe32s(f, &opp->src[i].type); | 1151 | qemu_get_sbe32s(f, &opp->src[i].type); |
@@ -1100,15 +1153,16 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | @@ -1100,15 +1153,16 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | ||
1100 | qemu_get_sbe32s(f, &opp->src[i].pending); | 1153 | qemu_get_sbe32s(f, &opp->src[i].pending); |
1101 | } | 1154 | } |
1102 | 1155 | ||
1103 | - for (i = 0; i < MAX_IRQ; i++) { | 1156 | + qemu_get_sbe32s(f, &opp->nb_cpus); |
1157 | + | ||
1158 | + for (i = 0; i < opp->nb_cpus; i++) { | ||
1159 | + qemu_get_be32s(f, &opp->dst[i].tfrr); | ||
1104 | qemu_get_be32s(f, &opp->dst[i].pctp); | 1160 | qemu_get_be32s(f, &opp->dst[i].pctp); |
1105 | qemu_get_be32s(f, &opp->dst[i].pcsr); | 1161 | qemu_get_be32s(f, &opp->dst[i].pcsr); |
1106 | openpic_load_IRQ_queue(f, &opp->dst[i].raised); | 1162 | openpic_load_IRQ_queue(f, &opp->dst[i].raised); |
1107 | openpic_load_IRQ_queue(f, &opp->dst[i].servicing); | 1163 | openpic_load_IRQ_queue(f, &opp->dst[i].servicing); |
1108 | } | 1164 | } |
1109 | 1165 | ||
1110 | - qemu_get_sbe32s(f, &opp->nb_cpus); | ||
1111 | - | ||
1112 | for (i = 0; i < MAX_TMR; i++) { | 1166 | for (i = 0; i < MAX_TMR; i++) { |
1113 | qemu_get_be32s(f, &opp->timers[i].ticc); | 1167 | qemu_get_be32s(f, &opp->timers[i].ticc); |
1114 | qemu_get_be32s(f, &opp->timers[i].tibc); | 1168 | qemu_get_be32s(f, &opp->timers[i].tibc); |
@@ -1131,6 +1185,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | @@ -1131,6 +1185,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id) | ||
1131 | return pci_device_load(&opp->pci_dev, f); | 1185 | return pci_device_load(&opp->pci_dev, f); |
1132 | } | 1186 | } |
1133 | 1187 | ||
1188 | +static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) | ||
1189 | +{ | ||
1190 | + qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); | ||
1191 | +} | ||
1192 | + | ||
1134 | qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, | 1193 | qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, |
1135 | qemu_irq **irqs, qemu_irq irq_out) | 1194 | qemu_irq **irqs, qemu_irq irq_out) |
1136 | { | 1195 | { |
@@ -1164,33 +1223,499 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, | @@ -1164,33 +1223,499 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, | ||
1164 | 1223 | ||
1165 | // isu_base &= 0xFFFC0000; | 1224 | // isu_base &= 0xFFFC0000; |
1166 | opp->nb_cpus = nb_cpus; | 1225 | opp->nb_cpus = nb_cpus; |
1226 | + opp->max_irq = OPENPIC_MAX_IRQ; | ||
1227 | + opp->irq_ipi0 = OPENPIC_IRQ_IPI0; | ||
1228 | + opp->irq_tim0 = OPENPIC_IRQ_TIM0; | ||
1167 | /* Set IRQ types */ | 1229 | /* Set IRQ types */ |
1168 | - for (i = 0; i < EXT_IRQ; i++) { | 1230 | + for (i = 0; i < OPENPIC_EXT_IRQ; i++) { |
1169 | opp->src[i].type = IRQ_EXTERNAL; | 1231 | opp->src[i].type = IRQ_EXTERNAL; |
1170 | } | 1232 | } |
1171 | - for (; i < IRQ_TIM0; i++) { | 1233 | + for (; i < OPENPIC_IRQ_TIM0; i++) { |
1172 | opp->src[i].type = IRQ_SPECIAL; | 1234 | opp->src[i].type = IRQ_SPECIAL; |
1173 | } | 1235 | } |
1174 | #if MAX_IPI > 0 | 1236 | #if MAX_IPI > 0 |
1175 | - m = IRQ_IPI0; | 1237 | + m = OPENPIC_IRQ_IPI0; |
1176 | #else | 1238 | #else |
1177 | - m = IRQ_DBL0; | 1239 | + m = OPENPIC_IRQ_DBL0; |
1178 | #endif | 1240 | #endif |
1179 | for (; i < m; i++) { | 1241 | for (; i < m; i++) { |
1180 | opp->src[i].type = IRQ_TIMER; | 1242 | opp->src[i].type = IRQ_TIMER; |
1181 | } | 1243 | } |
1182 | - for (; i < MAX_IRQ; i++) { | 1244 | + for (; i < OPENPIC_MAX_IRQ; i++) { |
1183 | opp->src[i].type = IRQ_INTERNAL; | 1245 | opp->src[i].type = IRQ_INTERNAL; |
1184 | } | 1246 | } |
1185 | for (i = 0; i < nb_cpus; i++) | 1247 | for (i = 0; i < nb_cpus; i++) |
1186 | opp->dst[i].irqs = irqs[i]; | 1248 | opp->dst[i].irqs = irqs[i]; |
1187 | opp->irq_out = irq_out; | 1249 | opp->irq_out = irq_out; |
1250 | + opp->need_swap = 1; | ||
1188 | 1251 | ||
1189 | - register_savevm("openpic", 0, 1, openpic_save, openpic_load, opp); | 1252 | + register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp); |
1190 | qemu_register_reset(openpic_reset, opp); | 1253 | qemu_register_reset(openpic_reset, opp); |
1191 | - openpic_reset(opp); | 1254 | + |
1255 | + opp->irq_raise = openpic_irq_raise; | ||
1256 | + opp->reset = openpic_reset; | ||
1257 | + | ||
1258 | + opp->reset(opp); | ||
1192 | if (pmem_index) | 1259 | if (pmem_index) |
1193 | *pmem_index = opp->mem_index; | 1260 | *pmem_index = opp->mem_index; |
1194 | 1261 | ||
1195 | - return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ); | 1262 | + return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); |
1263 | +} | ||
1264 | + | ||
1265 | +static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src) | ||
1266 | +{ | ||
1267 | + int n_ci = IDR_CI0 - n_CPU; | ||
1268 | + DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__, | ||
1269 | + n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci); | ||
1270 | + if(test_bit(&src->ide, n_ci)) { | ||
1271 | + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]); | ||
1272 | + } | ||
1273 | + else { | ||
1274 | + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); | ||
1275 | + } | ||
1276 | +} | ||
1277 | + | ||
1278 | +static void mpic_reset (void *opaque) | ||
1279 | +{ | ||
1280 | + openpic_t *mpp = (openpic_t *)opaque; | ||
1281 | + int i; | ||
1282 | + | ||
1283 | + mpp->glbc = 0x80000000; | ||
1284 | + /* Initialise controller registers */ | ||
1285 | + mpp->frep = 0x004f0002; | ||
1286 | + mpp->veni = VENI; | ||
1287 | + mpp->pint = 0x00000000; | ||
1288 | + mpp->spve = 0x0000FFFF; | ||
1289 | + /* Initialise IRQ sources */ | ||
1290 | + for (i = 0; i < mpp->max_irq; i++) { | ||
1291 | + mpp->src[i].ipvp = 0x80800000; | ||
1292 | + mpp->src[i].ide = 0x00000001; | ||
1293 | + } | ||
1294 | + /* Initialise IRQ destinations */ | ||
1295 | + for (i = 0; i < MAX_CPU; i++) { | ||
1296 | + mpp->dst[i].pctp = 0x0000000F; | ||
1297 | + mpp->dst[i].tfrr = 0x00000000; | ||
1298 | + memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t)); | ||
1299 | + mpp->dst[i].raised.next = -1; | ||
1300 | + memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); | ||
1301 | + mpp->dst[i].servicing.next = -1; | ||
1302 | + } | ||
1303 | + /* Initialise timers */ | ||
1304 | + for (i = 0; i < MAX_TMR; i++) { | ||
1305 | + mpp->timers[i].ticc = 0x00000000; | ||
1306 | + mpp->timers[i].tibc = 0x80000000; | ||
1307 | + } | ||
1308 | + /* Go out of RESET state */ | ||
1309 | + mpp->glbc = 0x00000000; | ||
1310 | +} | ||
1311 | + | ||
1312 | +static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val) | ||
1313 | +{ | ||
1314 | + openpic_t *mpp = opaque; | ||
1315 | + int idx, cpu; | ||
1316 | + | ||
1317 | + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | ||
1318 | + if (addr & 0xF) | ||
1319 | + return; | ||
1320 | + addr &= 0xFFFF; | ||
1321 | + cpu = addr >> 12; | ||
1322 | + idx = (addr >> 6) & 0x3; | ||
1323 | + switch (addr & 0x30) { | ||
1324 | + case 0x00: /* gtccr */ | ||
1325 | + break; | ||
1326 | + case 0x10: /* gtbcr */ | ||
1327 | + if ((mpp->timers[idx].ticc & 0x80000000) != 0 && | ||
1328 | + (val & 0x80000000) == 0 && | ||
1329 | + (mpp->timers[idx].tibc & 0x80000000) != 0) | ||
1330 | + mpp->timers[idx].ticc &= ~0x80000000; | ||
1331 | + mpp->timers[idx].tibc = val; | ||
1332 | + break; | ||
1333 | + case 0x20: /* GTIVPR */ | ||
1334 | + write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val); | ||
1335 | + break; | ||
1336 | + case 0x30: /* GTIDR & TFRR */ | ||
1337 | + if ((addr & 0xF0) == 0xF0) | ||
1338 | + mpp->dst[cpu].tfrr = val; | ||
1339 | + else | ||
1340 | + write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val); | ||
1341 | + break; | ||
1342 | + } | ||
1343 | +} | ||
1344 | + | ||
1345 | +static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr) | ||
1346 | +{ | ||
1347 | + openpic_t *mpp = opaque; | ||
1348 | + uint32_t retval; | ||
1349 | + int idx, cpu; | ||
1350 | + | ||
1351 | + DPRINTF("%s: addr %08x\n", __func__, addr); | ||
1352 | + retval = 0xFFFFFFFF; | ||
1353 | + if (addr & 0xF) | ||
1354 | + return retval; | ||
1355 | + addr &= 0xFFFF; | ||
1356 | + cpu = addr >> 12; | ||
1357 | + idx = (addr >> 6) & 0x3; | ||
1358 | + switch (addr & 0x30) { | ||
1359 | + case 0x00: /* gtccr */ | ||
1360 | + retval = mpp->timers[idx].ticc; | ||
1361 | + break; | ||
1362 | + case 0x10: /* gtbcr */ | ||
1363 | + retval = mpp->timers[idx].tibc; | ||
1364 | + break; | ||
1365 | + case 0x20: /* TIPV */ | ||
1366 | + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP); | ||
1367 | + break; | ||
1368 | + case 0x30: /* TIDR */ | ||
1369 | + if ((addr &0xF0) == 0XF0) | ||
1370 | + retval = mpp->dst[cpu].tfrr; | ||
1371 | + else | ||
1372 | + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE); | ||
1373 | + break; | ||
1374 | + } | ||
1375 | + DPRINTF("%s: => %08x\n", __func__, retval); | ||
1376 | + | ||
1377 | + return retval; | ||
1378 | +} | ||
1379 | + | ||
1380 | +static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr, | ||
1381 | + uint32_t val) | ||
1382 | +{ | ||
1383 | + openpic_t *mpp = opaque; | ||
1384 | + int idx = MPIC_EXT_IRQ; | ||
1385 | + | ||
1386 | + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | ||
1387 | + if (addr & 0xF) | ||
1388 | + return; | ||
1389 | + | ||
1390 | + addr -= MPIC_EXT_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1391 | + if (addr < MPIC_EXT_REG_SIZE) { | ||
1392 | + idx += (addr & 0xFFF0) >> 5; | ||
1393 | + if (addr & 0x10) { | ||
1394 | + /* EXDE / IFEDE / IEEDE */ | ||
1395 | + write_IRQreg(mpp, idx, IRQ_IDE, val); | ||
1396 | + } else { | ||
1397 | + /* EXVP / IFEVP / IEEVP */ | ||
1398 | + write_IRQreg(mpp, idx, IRQ_IPVP, val); | ||
1399 | + } | ||
1400 | + } | ||
1401 | +} | ||
1402 | + | ||
1403 | +static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr) | ||
1404 | +{ | ||
1405 | + openpic_t *mpp = opaque; | ||
1406 | + uint32_t retval; | ||
1407 | + int idx = MPIC_EXT_IRQ; | ||
1408 | + | ||
1409 | + DPRINTF("%s: addr %08x\n", __func__, addr); | ||
1410 | + retval = 0xFFFFFFFF; | ||
1411 | + if (addr & 0xF) | ||
1412 | + return retval; | ||
1413 | + | ||
1414 | + addr -= MPIC_EXT_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1415 | + if (addr < MPIC_EXT_REG_SIZE) { | ||
1416 | + idx += (addr & 0xFFF0) >> 5; | ||
1417 | + if (addr & 0x10) { | ||
1418 | + /* EXDE / IFEDE / IEEDE */ | ||
1419 | + retval = read_IRQreg(mpp, idx, IRQ_IDE); | ||
1420 | + } else { | ||
1421 | + /* EXVP / IFEVP / IEEVP */ | ||
1422 | + retval = read_IRQreg(mpp, idx, IRQ_IPVP); | ||
1423 | + } | ||
1424 | + DPRINTF("%s: => %08x\n", __func__, retval); | ||
1425 | + } | ||
1426 | + | ||
1427 | + return retval; | ||
1428 | +} | ||
1429 | + | ||
1430 | +static void mpic_src_int_write (void *opaque, target_phys_addr_t addr, | ||
1431 | + uint32_t val) | ||
1432 | +{ | ||
1433 | + openpic_t *mpp = opaque; | ||
1434 | + int idx = MPIC_INT_IRQ; | ||
1435 | + | ||
1436 | + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | ||
1437 | + if (addr & 0xF) | ||
1438 | + return; | ||
1439 | + | ||
1440 | + addr -= MPIC_INT_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1441 | + if (addr < MPIC_INT_REG_SIZE) { | ||
1442 | + idx += (addr & 0xFFF0) >> 5; | ||
1443 | + if (addr & 0x10) { | ||
1444 | + /* EXDE / IFEDE / IEEDE */ | ||
1445 | + write_IRQreg(mpp, idx, IRQ_IDE, val); | ||
1446 | + } else { | ||
1447 | + /* EXVP / IFEVP / IEEVP */ | ||
1448 | + write_IRQreg(mpp, idx, IRQ_IPVP, val); | ||
1449 | + } | ||
1450 | + } | ||
1451 | +} | ||
1452 | + | ||
1453 | +static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr) | ||
1454 | +{ | ||
1455 | + openpic_t *mpp = opaque; | ||
1456 | + uint32_t retval; | ||
1457 | + int idx = MPIC_INT_IRQ; | ||
1458 | + | ||
1459 | + DPRINTF("%s: addr %08x\n", __func__, addr); | ||
1460 | + retval = 0xFFFFFFFF; | ||
1461 | + if (addr & 0xF) | ||
1462 | + return retval; | ||
1463 | + | ||
1464 | + addr -= MPIC_INT_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1465 | + if (addr < MPIC_INT_REG_SIZE) { | ||
1466 | + idx += (addr & 0xFFF0) >> 5; | ||
1467 | + if (addr & 0x10) { | ||
1468 | + /* EXDE / IFEDE / IEEDE */ | ||
1469 | + retval = read_IRQreg(mpp, idx, IRQ_IDE); | ||
1470 | + } else { | ||
1471 | + /* EXVP / IFEVP / IEEVP */ | ||
1472 | + retval = read_IRQreg(mpp, idx, IRQ_IPVP); | ||
1473 | + } | ||
1474 | + DPRINTF("%s: => %08x\n", __func__, retval); | ||
1475 | + } | ||
1476 | + | ||
1477 | + return retval; | ||
1478 | +} | ||
1479 | + | ||
1480 | +static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr, | ||
1481 | + uint32_t val) | ||
1482 | +{ | ||
1483 | + openpic_t *mpp = opaque; | ||
1484 | + int idx = MPIC_MSG_IRQ; | ||
1485 | + | ||
1486 | + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | ||
1487 | + if (addr & 0xF) | ||
1488 | + return; | ||
1489 | + | ||
1490 | + addr -= MPIC_MSG_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1491 | + if (addr < MPIC_MSG_REG_SIZE) { | ||
1492 | + idx += (addr & 0xFFF0) >> 5; | ||
1493 | + if (addr & 0x10) { | ||
1494 | + /* EXDE / IFEDE / IEEDE */ | ||
1495 | + write_IRQreg(mpp, idx, IRQ_IDE, val); | ||
1496 | + } else { | ||
1497 | + /* EXVP / IFEVP / IEEVP */ | ||
1498 | + write_IRQreg(mpp, idx, IRQ_IPVP, val); | ||
1499 | + } | ||
1500 | + } | ||
1501 | +} | ||
1502 | + | ||
1503 | +static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr) | ||
1504 | +{ | ||
1505 | + openpic_t *mpp = opaque; | ||
1506 | + uint32_t retval; | ||
1507 | + int idx = MPIC_MSG_IRQ; | ||
1508 | + | ||
1509 | + DPRINTF("%s: addr %08x\n", __func__, addr); | ||
1510 | + retval = 0xFFFFFFFF; | ||
1511 | + if (addr & 0xF) | ||
1512 | + return retval; | ||
1513 | + | ||
1514 | + addr -= MPIC_MSG_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1515 | + if (addr < MPIC_MSG_REG_SIZE) { | ||
1516 | + idx += (addr & 0xFFF0) >> 5; | ||
1517 | + if (addr & 0x10) { | ||
1518 | + /* EXDE / IFEDE / IEEDE */ | ||
1519 | + retval = read_IRQreg(mpp, idx, IRQ_IDE); | ||
1520 | + } else { | ||
1521 | + /* EXVP / IFEVP / IEEVP */ | ||
1522 | + retval = read_IRQreg(mpp, idx, IRQ_IPVP); | ||
1523 | + } | ||
1524 | + DPRINTF("%s: => %08x\n", __func__, retval); | ||
1525 | + } | ||
1526 | + | ||
1527 | + return retval; | ||
1528 | +} | ||
1529 | + | ||
1530 | +static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr, | ||
1531 | + uint32_t val) | ||
1532 | +{ | ||
1533 | + openpic_t *mpp = opaque; | ||
1534 | + int idx = MPIC_MSI_IRQ; | ||
1535 | + | ||
1536 | + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); | ||
1537 | + if (addr & 0xF) | ||
1538 | + return; | ||
1539 | + | ||
1540 | + addr -= MPIC_MSI_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1541 | + if (addr < MPIC_MSI_REG_SIZE) { | ||
1542 | + idx += (addr & 0xFFF0) >> 5; | ||
1543 | + if (addr & 0x10) { | ||
1544 | + /* EXDE / IFEDE / IEEDE */ | ||
1545 | + write_IRQreg(mpp, idx, IRQ_IDE, val); | ||
1546 | + } else { | ||
1547 | + /* EXVP / IFEVP / IEEVP */ | ||
1548 | + write_IRQreg(mpp, idx, IRQ_IPVP, val); | ||
1549 | + } | ||
1550 | + } | ||
1551 | +} | ||
1552 | +static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr) | ||
1553 | +{ | ||
1554 | + openpic_t *mpp = opaque; | ||
1555 | + uint32_t retval; | ||
1556 | + int idx = MPIC_MSI_IRQ; | ||
1557 | + | ||
1558 | + DPRINTF("%s: addr %08x\n", __func__, addr); | ||
1559 | + retval = 0xFFFFFFFF; | ||
1560 | + if (addr & 0xF) | ||
1561 | + return retval; | ||
1562 | + | ||
1563 | + addr -= MPIC_MSI_REG_START & (TARGET_PAGE_SIZE - 1); | ||
1564 | + if (addr < MPIC_MSI_REG_SIZE) { | ||
1565 | + idx += (addr & 0xFFF0) >> 5; | ||
1566 | + if (addr & 0x10) { | ||
1567 | + /* EXDE / IFEDE / IEEDE */ | ||
1568 | + retval = read_IRQreg(mpp, idx, IRQ_IDE); | ||
1569 | + } else { | ||
1570 | + /* EXVP / IFEVP / IEEVP */ | ||
1571 | + retval = read_IRQreg(mpp, idx, IRQ_IPVP); | ||
1572 | + } | ||
1573 | + DPRINTF("%s: => %08x\n", __func__, retval); | ||
1574 | + } | ||
1575 | + | ||
1576 | + return retval; | ||
1577 | +} | ||
1578 | + | ||
1579 | +static CPUWriteMemoryFunc *mpic_glb_write[] = { | ||
1580 | + &openpic_buggy_write, | ||
1581 | + &openpic_buggy_write, | ||
1582 | + &openpic_gbl_write, | ||
1583 | +}; | ||
1584 | + | ||
1585 | +static CPUReadMemoryFunc *mpic_glb_read[] = { | ||
1586 | + &openpic_buggy_read, | ||
1587 | + &openpic_buggy_read, | ||
1588 | + &openpic_gbl_read, | ||
1589 | +}; | ||
1590 | + | ||
1591 | +static CPUWriteMemoryFunc *mpic_tmr_write[] = { | ||
1592 | + &openpic_buggy_write, | ||
1593 | + &openpic_buggy_write, | ||
1594 | + &mpic_timer_write, | ||
1595 | +}; | ||
1596 | + | ||
1597 | +static CPUReadMemoryFunc *mpic_tmr_read[] = { | ||
1598 | + &openpic_buggy_read, | ||
1599 | + &openpic_buggy_read, | ||
1600 | + &mpic_timer_read, | ||
1601 | +}; | ||
1602 | + | ||
1603 | +static CPUWriteMemoryFunc *mpic_cpu_write[] = { | ||
1604 | + &openpic_buggy_write, | ||
1605 | + &openpic_buggy_write, | ||
1606 | + &openpic_cpu_write, | ||
1607 | +}; | ||
1608 | + | ||
1609 | +static CPUReadMemoryFunc *mpic_cpu_read[] = { | ||
1610 | + &openpic_buggy_read, | ||
1611 | + &openpic_buggy_read, | ||
1612 | + &openpic_cpu_read, | ||
1613 | +}; | ||
1614 | + | ||
1615 | +static CPUWriteMemoryFunc *mpic_ext_write[] = { | ||
1616 | + &openpic_buggy_write, | ||
1617 | + &openpic_buggy_write, | ||
1618 | + &mpic_src_ext_write, | ||
1619 | +}; | ||
1620 | + | ||
1621 | +static CPUReadMemoryFunc *mpic_ext_read[] = { | ||
1622 | + &openpic_buggy_read, | ||
1623 | + &openpic_buggy_read, | ||
1624 | + &mpic_src_ext_read, | ||
1625 | +}; | ||
1626 | + | ||
1627 | +static CPUWriteMemoryFunc *mpic_int_write[] = { | ||
1628 | + &openpic_buggy_write, | ||
1629 | + &openpic_buggy_write, | ||
1630 | + &mpic_src_int_write, | ||
1631 | +}; | ||
1632 | + | ||
1633 | +static CPUReadMemoryFunc *mpic_int_read[] = { | ||
1634 | + &openpic_buggy_read, | ||
1635 | + &openpic_buggy_read, | ||
1636 | + &mpic_src_int_read, | ||
1637 | +}; | ||
1638 | + | ||
1639 | +static CPUWriteMemoryFunc *mpic_msg_write[] = { | ||
1640 | + &openpic_buggy_write, | ||
1641 | + &openpic_buggy_write, | ||
1642 | + &mpic_src_msg_write, | ||
1643 | +}; | ||
1644 | + | ||
1645 | +static CPUReadMemoryFunc *mpic_msg_read[] = { | ||
1646 | + &openpic_buggy_read, | ||
1647 | + &openpic_buggy_read, | ||
1648 | + &mpic_src_msg_read, | ||
1649 | +}; | ||
1650 | +static CPUWriteMemoryFunc *mpic_msi_write[] = { | ||
1651 | + &openpic_buggy_write, | ||
1652 | + &openpic_buggy_write, | ||
1653 | + &mpic_src_msi_write, | ||
1654 | +}; | ||
1655 | + | ||
1656 | +static CPUReadMemoryFunc *mpic_msi_read[] = { | ||
1657 | + &openpic_buggy_read, | ||
1658 | + &openpic_buggy_read, | ||
1659 | + &mpic_src_msi_read, | ||
1660 | +}; | ||
1661 | + | ||
1662 | +qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus, | ||
1663 | + qemu_irq **irqs, qemu_irq irq_out) | ||
1664 | +{ | ||
1665 | + openpic_t *mpp; | ||
1666 | + int i; | ||
1667 | + struct { | ||
1668 | + CPUReadMemoryFunc **read; | ||
1669 | + CPUWriteMemoryFunc **write; | ||
1670 | + target_phys_addr_t start_addr; | ||
1671 | + ram_addr_t size; | ||
1672 | + } list[] = { | ||
1673 | + {mpic_glb_read, mpic_glb_write, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE}, | ||
1674 | + {mpic_tmr_read, mpic_tmr_write, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE}, | ||
1675 | + {mpic_ext_read, mpic_ext_write, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE}, | ||
1676 | + {mpic_int_read, mpic_int_write, MPIC_INT_REG_START, MPIC_INT_REG_SIZE}, | ||
1677 | + {mpic_msg_read, mpic_msg_write, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE}, | ||
1678 | + {mpic_msi_read, mpic_msi_write, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE}, | ||
1679 | + {mpic_cpu_read, mpic_cpu_write, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE}, | ||
1680 | + }; | ||
1681 | + | ||
1682 | + /* XXX: for now, only one CPU is supported */ | ||
1683 | + if (nb_cpus != 1) | ||
1684 | + return NULL; | ||
1685 | + | ||
1686 | + mpp = qemu_mallocz(sizeof(openpic_t)); | ||
1687 | + | ||
1688 | + for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) { | ||
1689 | + int mem_index; | ||
1690 | + | ||
1691 | + mem_index = cpu_register_io_memory(0, list[i].read, list[i].write, mpp); | ||
1692 | + if (mem_index < 0) { | ||
1693 | + goto free; | ||
1694 | + } | ||
1695 | + cpu_register_physical_memory(base + list[i].start_addr, | ||
1696 | + list[i].size, mem_index); | ||
1697 | + } | ||
1698 | + | ||
1699 | + mpp->nb_cpus = nb_cpus; | ||
1700 | + mpp->max_irq = MPIC_MAX_IRQ; | ||
1701 | + mpp->irq_ipi0 = MPIC_IPI_IRQ; | ||
1702 | + mpp->irq_tim0 = MPIC_TMR_IRQ; | ||
1703 | + | ||
1704 | + for (i = 0; i < nb_cpus; i++) | ||
1705 | + mpp->dst[i].irqs = irqs[i]; | ||
1706 | + mpp->irq_out = irq_out; | ||
1707 | + mpp->need_swap = 0; /* MPIC has the same endian as target */ | ||
1708 | + | ||
1709 | + mpp->irq_raise = mpic_irq_raise; | ||
1710 | + mpp->reset = mpic_reset; | ||
1711 | + | ||
1712 | + register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp); | ||
1713 | + qemu_register_reset(mpic_reset, mpp); | ||
1714 | + mpp->reset(mpp); | ||
1715 | + | ||
1716 | + return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq); | ||
1717 | + | ||
1718 | +free: | ||
1719 | + qemu_free(mpp); | ||
1720 | + return NULL; | ||
1196 | } | 1721 | } |
hw/openpic.h
0 → 100644
1 | +#if !defined(__OPENPIC_H__) | ||
2 | +#define __OPENPIC_H__ | ||
3 | + | ||
4 | +/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */ | ||
5 | +enum { | ||
6 | + OPENPIC_OUTPUT_INT = 0, /* IRQ */ | ||
7 | + OPENPIC_OUTPUT_CINT, /* critical IRQ */ | ||
8 | + OPENPIC_OUTPUT_MCK, /* Machine check event */ | ||
9 | + OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */ | ||
10 | + OPENPIC_OUTPUT_RESET, /* Core reset event */ | ||
11 | + OPENPIC_OUTPUT_NB, | ||
12 | +}; | ||
13 | + | ||
14 | +qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, | ||
15 | + qemu_irq **irqs, qemu_irq irq_out); | ||
16 | +qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus, | ||
17 | + qemu_irq **irqs, qemu_irq irq_out); | ||
18 | +#endif /* __OPENPIC_H__ */ |
hw/ppc_mac.h
@@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus); | @@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus); | ||
112 | 112 | ||
113 | extern ADBBusState adb_bus; | 113 | extern ADBBusState adb_bus; |
114 | 114 | ||
115 | -/* openpic.c */ | ||
116 | -/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */ | ||
117 | -enum { | ||
118 | - OPENPIC_OUTPUT_INT = 0, /* IRQ */ | ||
119 | - OPENPIC_OUTPUT_CINT, /* critical IRQ */ | ||
120 | - OPENPIC_OUTPUT_MCK, /* Machine check event */ | ||
121 | - OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */ | ||
122 | - OPENPIC_OUTPUT_RESET, /* Core reset event */ | ||
123 | - OPENPIC_OUTPUT_NB, | ||
124 | -}; | ||
125 | -qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, | ||
126 | - qemu_irq **irqs, qemu_irq irq_out); | ||
127 | - | ||
128 | #endif /* !defined(__PPC_MAC_H__) */ | 115 | #endif /* !defined(__PPC_MAC_H__) */ |
hw/ppc_newworld.c
@@ -34,6 +34,7 @@ | @@ -34,6 +34,7 @@ | ||
34 | #include "boards.h" | 34 | #include "boards.h" |
35 | #include "fw_cfg.h" | 35 | #include "fw_cfg.h" |
36 | #include "escc.h" | 36 | #include "escc.h" |
37 | +#include "openpic.h" | ||
37 | 38 | ||
38 | #define MAX_IDE_BUS 2 | 39 | #define MAX_IDE_BUS 2 |
39 | #define VGA_BIOS_SIZE 65536 | 40 | #define VGA_BIOS_SIZE 65536 |