~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/openpic.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-07 06:20:34 UTC
  • mfrom: (1.1.9 upstream)
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20090307062034-i3pead4mw653v2el
Tags: 0.10.0-1
[ Aurelien Jarno ]
* New upstream release:
  - Fix fr-be keyboard mapping (closes: bug#514462).
  - Fix stat64 structure on ppc-linux-user (closes: bug#470231).
  - Add a chroot option (closes: bug#415996).
  - Add evdev support (closes: bug#513210).
  - Fix loop on symlinks in user mode (closes: bug#297572).
  - Bump depends on openbios-sparc.
  - Depends on openbios-ppc.
  - Update 12_signal_powerpc_support.patch.
  - Update 21_net_soopts.patch.
  - Drop 44_socklen_t_check.patch (merged upstream).
  - Drop 49_null_check.patch (merged upstream).
  - Update 64_ppc_asm_constraints.patch.
  - Drop security/CVE-2008-0928-fedora.patch (merged upstream).
  - Drop security/CVE-2007-5730.patch (merged upstream).
* patches/80_stable-branch.patch: add patches from stable branch:
  - Fix race condition between signal handler/execution loop (closes:
    bug#474386, bug#501731).
* debian/copyright: update.
* Compile and install .dtb files:
  - debian/control: build-depends on device-tree-compiler.
  - debian/patches/81_compile_dtb.patch: new patch from upstream.
  - debian/rules: compile and install bamboo.dtb and mpc8544.dtb.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
/*
25
25
 *
26
26
 * Based on OpenPic implementations:
27
 
 * - Intel GW80314 I/O compagnion chip developper's manual
 
27
 * - Intel GW80314 I/O companion chip developer's manual
28
28
 * - Motorola MPC8245 & MPC8540 user manuals.
29
29
 * - Motorola MCP750 (aka Raven) programmer manual.
30
30
 * - Motorola Harrier programmer manuel
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
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
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
 
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 */
 
95
#else
 
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 */
 
98
#endif
 
99
 
 
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))
 
109
 
 
110
/* Interrupt definitions */
 
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
};
86
140
 
87
141
#else
88
142
#error "Please select which OpenPic implementation is to be emulated"
89
143
#endif
90
144
 
91
 
#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
92
 
    (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
93
 
#define OPENPIC_SWAP
94
 
#endif
95
 
 
96
 
/* 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 */
103
 
#else
104
 
#define IRQ_DBL0   (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
105
 
#define IRQ_MBX0   (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
106
 
#endif
107
 
 
108
145
#define BF_WIDTH(_bits_) \
109
146
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
110
147
 
128
165
    IRQ_INTERNAL = 0x02,
129
166
    IRQ_TIMER    = 0x04,
130
167
    IRQ_SPECIAL  = 0x08,
131
 
} IRQ_src_type;
 
168
};
132
169
 
133
170
typedef struct IRQ_queue_t {
134
171
    uint32_t queue[BF_WIDTH(MAX_IRQ)];
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
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
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);
279
331
    }
280
332
    IRQ_get_next(opp, &dst->raised);
281
333
    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
282
 
        priority < dst->servicing.priority) {
 
334
        priority <= dst->servicing.priority) {
283
335
        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
284
336
                __func__, n_IRQ, dst->servicing.next, n_CPU);
285
337
        /* Already servicing a higher priority 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 */
367
419
    openpic_update_irq(opp, n_IRQ);
368
420
}
369
421
 
370
 
static void openpic_reset (openpic_t *opp)
 
422
static void openpic_reset (void *opaque)
371
423
{
 
424
    openpic_t *opp = (openpic_t *)opaque;
372
425
    int i;
373
426
 
374
427
    opp->glbc = 0x80000000;
375
428
    /* Initialise controller registers */
376
 
    opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
 
429
    opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
377
430
    opp->veni = VENI;
378
431
    opp->pint = 0x00000000;
379
432
    opp->spve = 0x000000FF;
381
434
    /* ? */
382
435
    opp->micr = 0x00000000;
383
436
    /* Initialise IRQ sources */
384
 
    for (i = 0; i < MAX_IRQ; i++) {
 
437
    for (i = 0; i < opp->max_irq; i++) {
385
438
        opp->src[i].ipvp = 0xA0000000;
386
439
        opp->src[i].ide  = 0x00000000;
387
440
    }
534
587
#endif
535
588
#endif /* 0 : Code provision for Intel model */
536
589
 
537
 
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)
538
591
{
539
592
    openpic_t *opp = opaque;
540
593
    IRQ_dst_t *dst;
543
596
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
544
597
    if (addr & 0xF)
545
598
        return;
546
 
#if defined OPENPIC_SWAP
547
 
    val = bswap32(val);
 
599
#if defined TARGET_WORDS_BIGENDIAN
 
600
    val = openpic_swap32(opp, val);
548
601
#endif
549
602
    addr &= 0xFF;
550
603
    switch (addr) {
551
604
    case 0x00: /* FREP */
552
605
        break;
553
606
    case 0x20: /* GLBC */
554
 
        if (val & 0x80000000)
555
 
            openpic_reset(opp);
 
607
        if (val & 0x80000000 && opp->reset)
 
608
            opp->reset(opp);
556
609
        opp->glbc = val & ~0x80000000;
557
610
        break;
558
611
    case 0x80: /* VENI */
579
632
        {
580
633
            int idx;
581
634
            idx = (addr - 0xA0) >> 4;
582
 
            write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
 
635
            write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
583
636
        }
584
637
        break;
585
638
#endif
594
647
    }
595
648
}
596
649
 
597
 
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)
598
651
{
599
652
    openpic_t *opp = opaque;
600
653
    uint32_t retval;
625
678
        {
626
679
            int idx;
627
680
            idx = (addr - 0xA0) >> 4;
628
 
            retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
 
681
            retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
629
682
        }
630
683
        break;
631
684
#endif
639
692
        break;
640
693
    }
641
694
    DPRINTF("%s: => %08x\n", __func__, retval);
642
 
#if defined OPENPIC_SWAP
643
 
    retval = bswap32(retval);
 
695
#if defined TARGET_WORDS_BIGENDIAN
 
696
    retval = openpic_swap32(opp, retval);
644
697
#endif
645
698
 
646
699
    return retval;
654
707
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
655
708
    if (addr & 0xF)
656
709
        return;
657
 
#if defined OPENPIC_SWAP
658
 
    val = bswap32(val);
 
710
#if defined TARGET_WORDS_BIGENDIAN
 
711
    val = openpic_swap32(opp, val);
659
712
#endif
660
713
    addr -= 0x1100;
661
714
    addr &= 0xFFFF;
672
725
        opp->timers[idx].tibc = val;
673
726
        break;
674
727
    case 0x20: /* TIVP */
675
 
        write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
 
728
        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
676
729
        break;
677
730
    case 0x30: /* TIDE */
678
 
        write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
 
731
        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val);
679
732
        break;
680
733
    }
681
734
}
702
755
        retval = opp->timers[idx].tibc;
703
756
        break;
704
757
    case 0x20: /* TIPV */
705
 
        retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
 
758
        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
706
759
        break;
707
760
    case 0x30: /* TIDE */
708
 
        retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
 
761
        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
709
762
        break;
710
763
    }
711
764
    DPRINTF("%s: => %08x\n", __func__, retval);
712
 
#if defined OPENPIC_SWAP
713
 
    retval = bswap32(retval);
 
765
#if defined TARGET_WORDS_BIGENDIAN
 
766
    retval = openpic_swap32(opp, retval);
714
767
#endif
715
768
 
716
769
    return retval;
724
777
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
725
778
    if (addr & 0xF)
726
779
        return;
727
 
#if defined OPENPIC_SWAP
728
 
    val = tswap32(val);
 
780
#if defined TARGET_WORDS_BIGENDIAN
 
781
    val = openpic_swap32(opp, val);
729
782
#endif
730
783
    addr = addr & 0xFFF0;
731
784
    idx = addr >> 5;
758
811
        retval = read_IRQreg(opp, idx, IRQ_IPVP);
759
812
    }
760
813
    DPRINTF("%s: => %08x\n", __func__, retval);
761
 
#if defined OPENPIC_SWAP
762
 
    retval = tswap32(retval);
 
814
#if defined TARGET_WORDS_BIGENDIAN
 
815
    retval = openpic_swap32(opp, retval);
763
816
#endif
764
817
 
765
818
    return retval;
766
819
}
767
820
 
768
 
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)
769
822
{
770
823
    openpic_t *opp = opaque;
771
824
    IRQ_src_t *src;
775
828
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
776
829
    if (addr & 0xF)
777
830
        return;
778
 
#if defined OPENPIC_SWAP
779
 
    val = bswap32(val);
 
831
#if defined TARGET_WORDS_BIGENDIAN
 
832
    val = openpic_swap32(opp, val);
780
833
#endif
781
834
    addr &= 0x1FFF0;
782
835
    idx = addr / 0x1000;
789
842
    case 0x60:
790
843
    case 0x70:
791
844
        idx = (addr - 0x40) >> 4;
792
 
        write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
793
 
        openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
794
 
        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);
795
848
        break;
796
849
#endif
797
850
    case 0x80: /* PCTP */
818
871
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
819
872
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
820
873
                    idx, n_IRQ);
821
 
            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
 
874
            opp->irq_raise(opp, idx, src);
822
875
        }
823
876
        break;
824
877
    default:
826
879
    }
827
880
}
828
881
 
829
 
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)
830
883
{
831
884
    openpic_t *opp = opaque;
832
885
    IRQ_src_t *src;
888
941
    case 0x40: /* IDE */
889
942
    case 0x50:
890
943
        idx = (addr - 0x40) >> 4;
891
 
        retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
 
944
        retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
892
945
        break;
893
946
#endif
894
947
    default:
895
948
        break;
896
949
    }
897
950
    DPRINTF("%s: => %08x\n", __func__, retval);
898
 
#if defined OPENPIC_SWAP
899
 
    retval= bswap32(retval);
 
951
#if defined TARGET_WORDS_BIGENDIAN
 
952
    retval = openpic_swap32(opp, retval);
900
953
#endif
901
954
 
902
955
    return retval;
988
1041
            addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
989
1042
    /* Interrupt source registers */
990
1043
    DPRINTF("Register OPENPIC src   %08x => %08x\n",
991
 
            addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
 
1044
            addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2));
992
1045
    /* Per CPU registers */
993
1046
    DPRINTF("Register OPENPIC dst   %08x => %08x\n",
994
1047
            addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
1001
1054
#endif
1002
1055
}
1003
1056
 
 
1057
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
 
1058
{
 
1059
    unsigned int i;
 
1060
 
 
1061
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
 
1062
        qemu_put_be32s(f, &q->queue[i]);
 
1063
 
 
1064
    qemu_put_sbe32s(f, &q->next);
 
1065
    qemu_put_sbe32s(f, &q->priority);
 
1066
}
 
1067
 
 
1068
static void openpic_save(QEMUFile* f, void *opaque)
 
1069
{
 
1070
    openpic_t *opp = (openpic_t *)opaque;
 
1071
    unsigned int i;
 
1072
 
 
1073
    qemu_put_be32s(f, &opp->frep);
 
1074
    qemu_put_be32s(f, &opp->glbc);
 
1075
    qemu_put_be32s(f, &opp->micr);
 
1076
    qemu_put_be32s(f, &opp->veni);
 
1077
    qemu_put_be32s(f, &opp->pint);
 
1078
    qemu_put_be32s(f, &opp->spve);
 
1079
    qemu_put_be32s(f, &opp->tifr);
 
1080
 
 
1081
    for (i = 0; i < opp->max_irq; i++) {
 
1082
        qemu_put_be32s(f, &opp->src[i].ipvp);
 
1083
        qemu_put_be32s(f, &opp->src[i].ide);
 
1084
        qemu_put_sbe32s(f, &opp->src[i].type);
 
1085
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
 
1086
        qemu_put_sbe32s(f, &opp->src[i].pending);
 
1087
    }
 
1088
 
 
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);
 
1093
        qemu_put_be32s(f, &opp->dst[i].pctp);
 
1094
        qemu_put_be32s(f, &opp->dst[i].pcsr);
 
1095
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
 
1096
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
 
1097
    }
 
1098
 
 
1099
    for (i = 0; i < MAX_TMR; i++) {
 
1100
        qemu_put_be32s(f, &opp->timers[i].ticc);
 
1101
        qemu_put_be32s(f, &opp->timers[i].tibc);
 
1102
    }
 
1103
 
 
1104
#if MAX_DBL > 0
 
1105
    qemu_put_be32s(f, &opp->dar);
 
1106
 
 
1107
    for (i = 0; i < MAX_DBL; i++) {
 
1108
        qemu_put_be32s(f, &opp->doorbells[i].dmr);
 
1109
    }
 
1110
#endif
 
1111
 
 
1112
#if MAX_MBX > 0
 
1113
    for (i = 0; i < MAX_MAILBOXES; i++) {
 
1114
        qemu_put_be32s(f, &opp->mailboxes[i].mbr);
 
1115
    }
 
1116
#endif
 
1117
 
 
1118
    pci_device_save(&opp->pci_dev, f);
 
1119
}
 
1120
 
 
1121
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
 
1122
{
 
1123
    unsigned int i;
 
1124
 
 
1125
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
 
1126
        qemu_get_be32s(f, &q->queue[i]);
 
1127
 
 
1128
    qemu_get_sbe32s(f, &q->next);
 
1129
    qemu_get_sbe32s(f, &q->priority);
 
1130
}
 
1131
 
 
1132
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
 
1133
{
 
1134
    openpic_t *opp = (openpic_t *)opaque;
 
1135
    unsigned int i;
 
1136
 
 
1137
    if (version_id != 1)
 
1138
        return -EINVAL;
 
1139
 
 
1140
    qemu_get_be32s(f, &opp->frep);
 
1141
    qemu_get_be32s(f, &opp->glbc);
 
1142
    qemu_get_be32s(f, &opp->micr);
 
1143
    qemu_get_be32s(f, &opp->veni);
 
1144
    qemu_get_be32s(f, &opp->pint);
 
1145
    qemu_get_be32s(f, &opp->spve);
 
1146
    qemu_get_be32s(f, &opp->tifr);
 
1147
 
 
1148
    for (i = 0; i < opp->max_irq; i++) {
 
1149
        qemu_get_be32s(f, &opp->src[i].ipvp);
 
1150
        qemu_get_be32s(f, &opp->src[i].ide);
 
1151
        qemu_get_sbe32s(f, &opp->src[i].type);
 
1152
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
 
1153
        qemu_get_sbe32s(f, &opp->src[i].pending);
 
1154
    }
 
1155
 
 
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);
 
1160
        qemu_get_be32s(f, &opp->dst[i].pctp);
 
1161
        qemu_get_be32s(f, &opp->dst[i].pcsr);
 
1162
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
 
1163
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
 
1164
    }
 
1165
 
 
1166
    for (i = 0; i < MAX_TMR; i++) {
 
1167
        qemu_get_be32s(f, &opp->timers[i].ticc);
 
1168
        qemu_get_be32s(f, &opp->timers[i].tibc);
 
1169
    }
 
1170
 
 
1171
#if MAX_DBL > 0
 
1172
    qemu_get_be32s(f, &opp->dar);
 
1173
 
 
1174
    for (i = 0; i < MAX_DBL; i++) {
 
1175
        qemu_get_be32s(f, &opp->doorbells[i].dmr);
 
1176
    }
 
1177
#endif
 
1178
 
 
1179
#if MAX_MBX > 0
 
1180
    for (i = 0; i < MAX_MAILBOXES; i++) {
 
1181
        qemu_get_be32s(f, &opp->mailboxes[i].mbr);
 
1182
    }
 
1183
#endif
 
1184
 
 
1185
    return pci_device_load(&opp->pci_dev, f);
 
1186
}
 
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
 
1004
1193
qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
1005
1194
                        qemu_irq **irqs, qemu_irq irq_out)
1006
1195
{
1017
1206
        if (opp == NULL)
1018
1207
            return NULL;
1019
1208
        pci_conf = opp->pci_dev.config;
1020
 
        pci_conf[0x00] = 0x14; // IBM MPIC2
1021
 
        pci_conf[0x01] = 0x10;
1022
 
        pci_conf[0x02] = 0xFF;
1023
 
        pci_conf[0x03] = 0xFF;
1024
 
        pci_conf[0x0a] = 0x80; // PIC
1025
 
        pci_conf[0x0b] = 0x08;
 
1209
        pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
 
1210
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
 
1211
        pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
1026
1212
        pci_conf[0x0e] = 0x00; // header_type
1027
1213
        pci_conf[0x3d] = 0x00; // no interrupt pin
1028
1214
 
1037
1223
 
1038
1224
    //    isu_base &= 0xFFFC0000;
1039
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;
1040
1229
    /* Set IRQ types */
1041
 
    for (i = 0; i < EXT_IRQ; i++) {
 
1230
    for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1042
1231
        opp->src[i].type = IRQ_EXTERNAL;
1043
1232
    }
1044
 
    for (; i < IRQ_TIM0; i++) {
 
1233
    for (; i < OPENPIC_IRQ_TIM0; i++) {
1045
1234
        opp->src[i].type = IRQ_SPECIAL;
1046
1235
    }
1047
1236
#if MAX_IPI > 0
1048
 
    m = IRQ_IPI0;
 
1237
    m = OPENPIC_IRQ_IPI0;
1049
1238
#else
1050
 
    m = IRQ_DBL0;
 
1239
    m = OPENPIC_IRQ_DBL0;
1051
1240
#endif
1052
1241
    for (; i < m; i++) {
1053
1242
        opp->src[i].type = IRQ_TIMER;
1054
1243
    }
1055
 
    for (; i < MAX_IRQ; i++) {
 
1244
    for (; i < OPENPIC_MAX_IRQ; i++) {
1056
1245
        opp->src[i].type = IRQ_INTERNAL;
1057
1246
    }
1058
1247
    for (i = 0; i < nb_cpus; i++)
1059
1248
        opp->dst[i].irqs = irqs[i];
1060
1249
    opp->irq_out = irq_out;
1061
 
    openpic_reset(opp);
 
1250
    opp->need_swap = 1;
 
1251
 
 
1252
    register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
 
1253
    qemu_register_reset(openpic_reset, opp);
 
1254
 
 
1255
    opp->irq_raise = openpic_irq_raise;
 
1256
    opp->reset = openpic_reset;
 
1257
 
 
1258
    opp->reset(opp);
1062
1259
    if (pmem_index)
1063
1260
        *pmem_index = opp->mem_index;
1064
1261
 
1065
 
    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
    } const 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;
1066
1721
}