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__) */ | ... | ... |