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 | 35 | #include "hw.h" |
36 | 36 | #include "ppc_mac.h" |
37 | 37 | #include "pci.h" |
38 | +#include "openpic.h" | |
38 | 39 | |
39 | 40 | //#define DEBUG_OPENPIC |
40 | 41 | |
... | ... | @@ -60,14 +61,10 @@ |
60 | 61 | |
61 | 62 | #define VID (0x00000000) |
62 | 63 | |
63 | -#define OPENPIC_LITTLE_ENDIAN 1 | |
64 | -#define OPENPIC_BIG_ENDIAN 0 | |
65 | - | |
66 | 64 | #elif defined(USE_MPCxxx) |
67 | 65 | |
68 | 66 | #define MAX_CPU 2 |
69 | -#define MAX_IRQ 64 | |
70 | -#define EXT_IRQ 48 | |
67 | +#define MAX_IRQ 128 | |
71 | 68 | #define MAX_DBL 0 |
72 | 69 | #define MAX_MBX 0 |
73 | 70 | #define MAX_TMR 4 |
... | ... | @@ -81,28 +78,68 @@ enum { |
81 | 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 | 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 | 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 | 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 | 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 | 143 | #endif |
107 | 144 | |
108 | 145 | #define BF_WIDTH(_bits_) \ |
... | ... | @@ -157,6 +194,7 @@ enum IPVP_bits { |
157 | 194 | #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) |
158 | 195 | |
159 | 196 | typedef struct IRQ_dst_t { |
197 | + uint32_t tfrr; | |
160 | 198 | uint32_t pctp; /* CPU current task priority */ |
161 | 199 | uint32_t pcsr; /* CPU sensitivity register */ |
162 | 200 | IRQ_queue_t raised; |
... | ... | @@ -200,8 +238,22 @@ typedef struct openpic_t { |
200 | 238 | #endif |
201 | 239 | /* IRQ out is used when in bypass mode (not implemented) */ |
202 | 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 | 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 | 257 | static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) |
206 | 258 | { |
207 | 259 | set_bit(q->queue, n_IRQ); |
... | ... | @@ -224,7 +276,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) |
224 | 276 | |
225 | 277 | next = -1; |
226 | 278 | priority = -1; |
227 | - for (i = 0; i < MAX_IRQ; i++) { | |
279 | + for (i = 0; i < opp->max_irq; i++) { | |
228 | 280 | if (IRQ_testbit(q, i)) { |
229 | 281 | DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", |
230 | 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 | 338 | return; |
287 | 339 | } |
288 | 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 | 344 | /* update pic state because registers for n_IRQ have changed value */ |
... | ... | @@ -374,7 +426,7 @@ static void openpic_reset (void *opaque) |
374 | 426 | |
375 | 427 | opp->glbc = 0x80000000; |
376 | 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 | 430 | opp->veni = VENI; |
379 | 431 | opp->pint = 0x00000000; |
380 | 432 | opp->spve = 0x000000FF; |
... | ... | @@ -382,7 +434,7 @@ static void openpic_reset (void *opaque) |
382 | 434 | /* ? */ |
383 | 435 | opp->micr = 0x00000000; |
384 | 436 | /* Initialise IRQ sources */ |
385 | - for (i = 0; i < MAX_IRQ; i++) { | |
437 | + for (i = 0; i < opp->max_irq; i++) { | |
386 | 438 | opp->src[i].ipvp = 0xA0000000; |
387 | 439 | opp->src[i].ide = 0x00000000; |
388 | 440 | } |
... | ... | @@ -535,7 +587,7 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx, |
535 | 587 | #endif |
536 | 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 | 592 | openpic_t *opp = opaque; |
541 | 593 | IRQ_dst_t *dst; |
... | ... | @@ -544,16 +596,16 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) |
544 | 596 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
545 | 597 | if (addr & 0xF) |
546 | 598 | return; |
547 | -#if defined OPENPIC_SWAP | |
548 | - val = bswap32(val); | |
599 | +#if defined TARGET_WORDS_BIGENDIAN | |
600 | + val = openpic_swap32(opp, val); | |
549 | 601 | #endif |
550 | 602 | addr &= 0xFF; |
551 | 603 | switch (addr) { |
552 | 604 | case 0x00: /* FREP */ |
553 | 605 | break; |
554 | 606 | case 0x20: /* GLBC */ |
555 | - if (val & 0x80000000) | |
556 | - openpic_reset(opp); | |
607 | + if (val & 0x80000000 && opp->reset) | |
608 | + opp->reset(opp); | |
557 | 609 | opp->glbc = val & ~0x80000000; |
558 | 610 | break; |
559 | 611 | case 0x80: /* VENI */ |
... | ... | @@ -580,7 +632,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) |
580 | 632 | { |
581 | 633 | int idx; |
582 | 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 | 637 | break; |
586 | 638 | #endif |
... | ... | @@ -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 | 652 | openpic_t *opp = opaque; |
601 | 653 | uint32_t retval; |
... | ... | @@ -626,7 +678,7 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) |
626 | 678 | { |
627 | 679 | int idx; |
628 | 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 | 683 | break; |
632 | 684 | #endif |
... | ... | @@ -640,8 +692,8 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) |
640 | 692 | break; |
641 | 693 | } |
642 | 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 | 697 | #endif |
646 | 698 | |
647 | 699 | return retval; |
... | ... | @@ -655,8 +707,8 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) |
655 | 707 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
656 | 708 | if (addr & 0xF) |
657 | 709 | return; |
658 | -#if defined OPENPIC_SWAP | |
659 | - val = bswap32(val); | |
710 | +#if defined TARGET_WORDS_BIGENDIAN | |
711 | + val = openpic_swap32(opp, val); | |
660 | 712 | #endif |
661 | 713 | addr -= 0x1100; |
662 | 714 | addr &= 0xFFFF; |
... | ... | @@ -673,10 +725,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) |
673 | 725 | opp->timers[idx].tibc = val; |
674 | 726 | break; |
675 | 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 | 729 | break; |
678 | 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 | 732 | break; |
681 | 733 | } |
682 | 734 | } |
... | ... | @@ -703,15 +755,15 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr) |
703 | 755 | retval = opp->timers[idx].tibc; |
704 | 756 | break; |
705 | 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 | 759 | break; |
708 | 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 | 762 | break; |
711 | 763 | } |
712 | 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 | 767 | #endif |
716 | 768 | |
717 | 769 | return retval; |
... | ... | @@ -725,8 +777,8 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) |
725 | 777 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
726 | 778 | if (addr & 0xF) |
727 | 779 | return; |
728 | -#if defined OPENPIC_SWAP | |
729 | - val = tswap32(val); | |
780 | +#if defined TARGET_WORDS_BIGENDIAN | |
781 | + val = openpic_swap32(opp, val); | |
730 | 782 | #endif |
731 | 783 | addr = addr & 0xFFF0; |
732 | 784 | idx = addr >> 5; |
... | ... | @@ -759,14 +811,14 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr) |
759 | 811 | retval = read_IRQreg(opp, idx, IRQ_IPVP); |
760 | 812 | } |
761 | 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 | 816 | #endif |
765 | 817 | |
766 | 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 | 823 | openpic_t *opp = opaque; |
772 | 824 | IRQ_src_t *src; |
... | ... | @@ -776,8 +828,8 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) |
776 | 828 | DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); |
777 | 829 | if (addr & 0xF) |
778 | 830 | return; |
779 | -#if defined OPENPIC_SWAP | |
780 | - val = bswap32(val); | |
831 | +#if defined TARGET_WORDS_BIGENDIAN | |
832 | + val = openpic_swap32(opp, val); | |
781 | 833 | #endif |
782 | 834 | addr &= 0x1FFF0; |
783 | 835 | idx = addr / 0x1000; |
... | ... | @@ -790,9 +842,9 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) |
790 | 842 | case 0x60: |
791 | 843 | case 0x70: |
792 | 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 | 848 | break; |
797 | 849 | #endif |
798 | 850 | case 0x80: /* PCTP */ |
... | ... | @@ -819,7 +871,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) |
819 | 871 | IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) { |
820 | 872 | DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", |
821 | 873 | idx, n_IRQ); |
822 | - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); | |
874 | + opp->irq_raise(opp, idx, src); | |
823 | 875 | } |
824 | 876 | break; |
825 | 877 | default: |
... | ... | @@ -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 | 884 | openpic_t *opp = opaque; |
833 | 885 | IRQ_src_t *src; |
... | ... | @@ -889,15 +941,15 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) |
889 | 941 | case 0x40: /* IDE */ |
890 | 942 | case 0x50: |
891 | 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 | 945 | break; |
894 | 946 | #endif |
895 | 947 | default: |
896 | 948 | break; |
897 | 949 | } |
898 | 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 | 953 | #endif |
902 | 954 | |
903 | 955 | return retval; |
... | ... | @@ -989,7 +1041,7 @@ static void openpic_map(PCIDevice *pci_dev, int region_num, |
989 | 1041 | addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR); |
990 | 1042 | /* Interrupt source registers */ |
991 | 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 | 1045 | /* Per CPU registers */ |
994 | 1046 | DPRINTF("Register OPENPIC dst %08x => %08x\n", |
995 | 1047 | addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU); |
... | ... | @@ -1026,7 +1078,7 @@ static void openpic_save(QEMUFile* f, void *opaque) |
1026 | 1078 | qemu_put_be32s(f, &opp->spve); |
1027 | 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 | 1082 | qemu_put_be32s(f, &opp->src[i].ipvp); |
1031 | 1083 | qemu_put_be32s(f, &opp->src[i].ide); |
1032 | 1084 | qemu_put_sbe32s(f, &opp->src[i].type); |
... | ... | @@ -1034,15 +1086,16 @@ static void openpic_save(QEMUFile* f, void *opaque) |
1034 | 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 | 1093 | qemu_put_be32s(f, &opp->dst[i].pctp); |
1039 | 1094 | qemu_put_be32s(f, &opp->dst[i].pcsr); |
1040 | 1095 | openpic_save_IRQ_queue(f, &opp->dst[i].raised); |
1041 | 1096 | openpic_save_IRQ_queue(f, &opp->dst[i].servicing); |
1042 | 1097 | } |
1043 | 1098 | |
1044 | - qemu_put_sbe32s(f, &opp->nb_cpus); | |
1045 | - | |
1046 | 1099 | for (i = 0; i < MAX_TMR; i++) { |
1047 | 1100 | qemu_put_be32s(f, &opp->timers[i].ticc); |
1048 | 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 | 1145 | qemu_get_be32s(f, &opp->spve); |
1093 | 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 | 1149 | qemu_get_be32s(f, &opp->src[i].ipvp); |
1097 | 1150 | qemu_get_be32s(f, &opp->src[i].ide); |
1098 | 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 | 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 | 1160 | qemu_get_be32s(f, &opp->dst[i].pctp); |
1105 | 1161 | qemu_get_be32s(f, &opp->dst[i].pcsr); |
1106 | 1162 | openpic_load_IRQ_queue(f, &opp->dst[i].raised); |
1107 | 1163 | openpic_load_IRQ_queue(f, &opp->dst[i].servicing); |
1108 | 1164 | } |
1109 | 1165 | |
1110 | - qemu_get_sbe32s(f, &opp->nb_cpus); | |
1111 | - | |
1112 | 1166 | for (i = 0; i < MAX_TMR; i++) { |
1113 | 1167 | qemu_get_be32s(f, &opp->timers[i].ticc); |
1114 | 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 | 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 | 1193 | qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, |
1135 | 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 | 1223 | |
1165 | 1224 | // isu_base &= 0xFFFC0000; |
1166 | 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 | 1229 | /* Set IRQ types */ |
1168 | - for (i = 0; i < EXT_IRQ; i++) { | |
1230 | + for (i = 0; i < OPENPIC_EXT_IRQ; i++) { | |
1169 | 1231 | opp->src[i].type = IRQ_EXTERNAL; |
1170 | 1232 | } |
1171 | - for (; i < IRQ_TIM0; i++) { | |
1233 | + for (; i < OPENPIC_IRQ_TIM0; i++) { | |
1172 | 1234 | opp->src[i].type = IRQ_SPECIAL; |
1173 | 1235 | } |
1174 | 1236 | #if MAX_IPI > 0 |
1175 | - m = IRQ_IPI0; | |
1237 | + m = OPENPIC_IRQ_IPI0; | |
1176 | 1238 | #else |
1177 | - m = IRQ_DBL0; | |
1239 | + m = OPENPIC_IRQ_DBL0; | |
1178 | 1240 | #endif |
1179 | 1241 | for (; i < m; i++) { |
1180 | 1242 | opp->src[i].type = IRQ_TIMER; |
1181 | 1243 | } |
1182 | - for (; i < MAX_IRQ; i++) { | |
1244 | + for (; i < OPENPIC_MAX_IRQ; i++) { | |
1183 | 1245 | opp->src[i].type = IRQ_INTERNAL; |
1184 | 1246 | } |
1185 | 1247 | for (i = 0; i < nb_cpus; i++) |
1186 | 1248 | opp->dst[i].irqs = irqs[i]; |
1187 | 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 | 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 | 1259 | if (pmem_index) |
1193 | 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 | 112 | |
113 | 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 | 115 | #endif /* !defined(__PPC_MAC_H__) */ | ... | ... |