]> Git Repo - qemu.git/blob - hw/openpic.c
Merge remote-tracking branch 'upstream' into memory/batch
[qemu.git] / hw / openpic.c
1 /*
2  * OpenPIC emulation
3  *
4  * Copyright (c) 2004 Jocelyn Mayer
5  *               2011 Alexander Graf
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 /*
26  *
27  * Based on OpenPic implementations:
28  * - Intel GW80314 I/O companion chip developer's manual
29  * - Motorola MPC8245 & MPC8540 user manuals.
30  * - Motorola MCP750 (aka Raven) programmer manual.
31  * - Motorola Harrier programmer manuel
32  *
33  * Serial interrupts, as implemented in Raven chipset are not supported yet.
34  *
35  */
36 #include "hw.h"
37 #include "ppc_mac.h"
38 #include "pci.h"
39 #include "openpic.h"
40
41 //#define DEBUG_OPENPIC
42
43 #ifdef DEBUG_OPENPIC
44 #define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
45 #else
46 #define DPRINTF(fmt, ...) do { } while (0)
47 #endif
48
49 #define USE_MPCxxx /* Intel model is broken, for now */
50
51 #if defined (USE_INTEL_GW80314)
52 /* Intel GW80314 I/O Companion chip */
53
54 #define MAX_CPU     4
55 #define MAX_IRQ    32
56 #define MAX_DBL     4
57 #define MAX_MBX     4
58 #define MAX_TMR     4
59 #define VECTOR_BITS 8
60 #define MAX_IPI     4
61
62 #define VID (0x00000000)
63
64 #elif defined(USE_MPCxxx)
65
66 #define MAX_CPU    15
67 #define MAX_IRQ   128
68 #define MAX_DBL     0
69 #define MAX_MBX     0
70 #define MAX_TMR     4
71 #define VECTOR_BITS 8
72 #define MAX_IPI     4
73 #define VID         0x03 /* MPIC version ID */
74 #define VENI        0x00000000 /* Vendor ID */
75
76 enum {
77     IRQ_IPVP = 0,
78     IRQ_IDE,
79 };
80
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 + ((MAX_CPU - 1) * 0x1000)
132
133 enum mpic_ide_bits {
134     IDR_EP     = 31,
135     IDR_CI0     = 30,
136     IDR_CI1     = 29,
137     IDR_P1     = 1,
138     IDR_P0     = 0,
139 };
140
141 #else
142 #error "Please select which OpenPic implementation is to be emulated"
143 #endif
144
145 #define OPENPIC_PAGE_SIZE 4096
146
147 #define BF_WIDTH(_bits_) \
148 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
149
150 static inline void set_bit (uint32_t *field, int bit)
151 {
152     field[bit >> 5] |= 1 << (bit & 0x1F);
153 }
154
155 static inline void reset_bit (uint32_t *field, int bit)
156 {
157     field[bit >> 5] &= ~(1 << (bit & 0x1F));
158 }
159
160 static inline int test_bit (uint32_t *field, int bit)
161 {
162     return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
163 }
164
165 static int get_current_cpu(void)
166 {
167   return cpu_single_env->cpu_index;
168 }
169
170 static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
171                                           int idx);
172 static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
173                                        uint32_t val, int idx);
174
175 enum {
176     IRQ_EXTERNAL = 0x01,
177     IRQ_INTERNAL = 0x02,
178     IRQ_TIMER    = 0x04,
179     IRQ_SPECIAL  = 0x08,
180 };
181
182 typedef struct IRQ_queue_t {
183     uint32_t queue[BF_WIDTH(MAX_IRQ)];
184     int next;
185     int priority;
186 } IRQ_queue_t;
187
188 typedef struct IRQ_src_t {
189     uint32_t ipvp;  /* IRQ vector/priority register */
190     uint32_t ide;   /* IRQ destination register */
191     int type;
192     int last_cpu;
193     int pending;    /* TRUE if IRQ is pending */
194 } IRQ_src_t;
195
196 enum IPVP_bits {
197     IPVP_MASK     = 31,
198     IPVP_ACTIVITY = 30,
199     IPVP_MODE     = 29,
200     IPVP_POLARITY = 23,
201     IPVP_SENSE    = 22,
202 };
203 #define IPVP_PRIORITY_MASK     (0x1F << 16)
204 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
205 #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
206 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
207
208 typedef struct IRQ_dst_t {
209     uint32_t tfrr;
210     uint32_t pctp; /* CPU current task priority */
211     uint32_t pcsr; /* CPU sensitivity register */
212     IRQ_queue_t raised;
213     IRQ_queue_t servicing;
214     qemu_irq *irqs;
215 } IRQ_dst_t;
216
217 typedef struct openpic_t {
218     PCIDevice pci_dev;
219     MemoryRegion mem;
220
221     /* Sub-regions */
222     MemoryRegion sub_io_mem[7];
223
224     /* Global registers */
225     uint32_t frep; /* Feature reporting register */
226     uint32_t glbc; /* Global configuration register  */
227     uint32_t micr; /* MPIC interrupt configuration register */
228     uint32_t veni; /* Vendor identification register */
229     uint32_t pint; /* Processor initialization register */
230     uint32_t spve; /* Spurious vector register */
231     uint32_t tifr; /* Timer frequency reporting register */
232     /* Source registers */
233     IRQ_src_t src[MAX_IRQ];
234     /* Local registers per output pin */
235     IRQ_dst_t dst[MAX_CPU];
236     int nb_cpus;
237     /* Timer registers */
238     struct {
239         uint32_t ticc;  /* Global timer current count register */
240         uint32_t tibc;  /* Global timer base count register */
241     } timers[MAX_TMR];
242 #if MAX_DBL > 0
243     /* Doorbell registers */
244     uint32_t dar;        /* Doorbell activate register */
245     struct {
246         uint32_t dmr;    /* Doorbell messaging register */
247     } doorbells[MAX_DBL];
248 #endif
249 #if MAX_MBX > 0
250     /* Mailbox registers */
251     struct {
252         uint32_t mbr;    /* Mailbox register */
253     } mailboxes[MAX_MAILBOXES];
254 #endif
255     /* IRQ out is used when in bypass mode (not implemented) */
256     qemu_irq irq_out;
257     int max_irq;
258     int irq_ipi0;
259     int irq_tim0;
260     void (*reset) (void *);
261     void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
262 } openpic_t;
263
264 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
265 {
266     set_bit(q->queue, n_IRQ);
267 }
268
269 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
270 {
271     reset_bit(q->queue, n_IRQ);
272 }
273
274 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
275 {
276     return test_bit(q->queue, n_IRQ);
277 }
278
279 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
280 {
281     int next, i;
282     int priority;
283
284     next = -1;
285     priority = -1;
286     for (i = 0; i < opp->max_irq; i++) {
287         if (IRQ_testbit(q, i)) {
288             DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
289                     i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
290             if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
291                 next = i;
292                 priority = IPVP_PRIORITY(opp->src[i].ipvp);
293             }
294         }
295     }
296     q->next = next;
297     q->priority = priority;
298 }
299
300 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
301 {
302     if (q->next == -1) {
303         /* XXX: optimize */
304         IRQ_check(opp, q);
305     }
306
307     return q->next;
308 }
309
310 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
311 {
312     IRQ_dst_t *dst;
313     IRQ_src_t *src;
314     int priority;
315
316     dst = &opp->dst[n_CPU];
317     src = &opp->src[n_IRQ];
318     priority = IPVP_PRIORITY(src->ipvp);
319     if (priority <= dst->pctp) {
320         /* Too low priority */
321         DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
322                 __func__, n_IRQ, n_CPU);
323         return;
324     }
325     if (IRQ_testbit(&dst->raised, n_IRQ)) {
326         /* Interrupt miss */
327         DPRINTF("%s: IRQ %d was missed on CPU %d\n",
328                 __func__, n_IRQ, n_CPU);
329         return;
330     }
331     set_bit(&src->ipvp, IPVP_ACTIVITY);
332     IRQ_setbit(&dst->raised, n_IRQ);
333     if (priority < dst->raised.priority) {
334         /* An higher priority IRQ is already raised */
335         DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
336                 __func__, n_IRQ, dst->raised.next, n_CPU);
337         return;
338     }
339     IRQ_get_next(opp, &dst->raised);
340     if (IRQ_get_next(opp, &dst->servicing) != -1 &&
341         priority <= dst->servicing.priority) {
342         DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
343                 __func__, n_IRQ, dst->servicing.next, n_CPU);
344         /* Already servicing a higher priority IRQ */
345         return;
346     }
347     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
348     opp->irq_raise(opp, n_CPU, src);
349 }
350
351 /* update pic state because registers for n_IRQ have changed value */
352 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
353 {
354     IRQ_src_t *src;
355     int i;
356
357     src = &opp->src[n_IRQ];
358
359     if (!src->pending) {
360         /* no irq pending */
361         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
362         return;
363     }
364     if (test_bit(&src->ipvp, IPVP_MASK)) {
365         /* Interrupt source is disabled */
366         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
367         return;
368     }
369     if (IPVP_PRIORITY(src->ipvp) == 0) {
370         /* Priority set to zero */
371         DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
372         return;
373     }
374     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
375         /* IRQ already active */
376         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
377         return;
378     }
379     if (src->ide == 0x00000000) {
380         /* No target */
381         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
382         return;
383     }
384
385     if (src->ide == (1 << src->last_cpu)) {
386         /* Only one CPU is allowed to receive this IRQ */
387         IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
388     } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
389         /* Directed delivery mode */
390         for (i = 0; i < opp->nb_cpus; i++) {
391             if (test_bit(&src->ide, i))
392                 IRQ_local_pipe(opp, i, n_IRQ);
393         }
394     } else {
395         /* Distributed delivery mode */
396         for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
397             if (i == opp->nb_cpus)
398                 i = 0;
399             if (test_bit(&src->ide, i)) {
400                 IRQ_local_pipe(opp, i, n_IRQ);
401                 src->last_cpu = i;
402                 break;
403             }
404         }
405     }
406 }
407
408 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
409 {
410     openpic_t *opp = opaque;
411     IRQ_src_t *src;
412
413     src = &opp->src[n_IRQ];
414     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
415             n_IRQ, level, src->ipvp);
416     if (test_bit(&src->ipvp, IPVP_SENSE)) {
417         /* level-sensitive irq */
418         src->pending = level;
419         if (!level)
420             reset_bit(&src->ipvp, IPVP_ACTIVITY);
421     } else {
422         /* edge-sensitive irq */
423         if (level)
424             src->pending = 1;
425     }
426     openpic_update_irq(opp, n_IRQ);
427 }
428
429 static void openpic_reset (void *opaque)
430 {
431     openpic_t *opp = (openpic_t *)opaque;
432     int i;
433
434     opp->glbc = 0x80000000;
435     /* Initialise controller registers */
436     opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
437     opp->veni = VENI;
438     opp->pint = 0x00000000;
439     opp->spve = 0x000000FF;
440     opp->tifr = 0x003F7A00;
441     /* ? */
442     opp->micr = 0x00000000;
443     /* Initialise IRQ sources */
444     for (i = 0; i < opp->max_irq; i++) {
445         opp->src[i].ipvp = 0xA0000000;
446         opp->src[i].ide  = 0x00000000;
447     }
448     /* Initialise IRQ destinations */
449     for (i = 0; i < MAX_CPU; i++) {
450         opp->dst[i].pctp      = 0x0000000F;
451         opp->dst[i].pcsr      = 0x00000000;
452         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
453         opp->dst[i].raised.next = -1;
454         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
455         opp->dst[i].servicing.next = -1;
456     }
457     /* Initialise timers */
458     for (i = 0; i < MAX_TMR; i++) {
459         opp->timers[i].ticc = 0x00000000;
460         opp->timers[i].tibc = 0x80000000;
461     }
462     /* Initialise doorbells */
463 #if MAX_DBL > 0
464     opp->dar = 0x00000000;
465     for (i = 0; i < MAX_DBL; i++) {
466         opp->doorbells[i].dmr  = 0x00000000;
467     }
468 #endif
469     /* Initialise mailboxes */
470 #if MAX_MBX > 0
471     for (i = 0; i < MAX_MBX; i++) { /* ? */
472         opp->mailboxes[i].mbr   = 0x00000000;
473     }
474 #endif
475     /* Go out of RESET state */
476     opp->glbc = 0x00000000;
477 }
478
479 static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
480 {
481     return opp->src[n_IRQ].ide;
482 }
483
484 static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
485 {
486     return opp->src[n_IRQ].ipvp;
487 }
488
489 static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
490 {
491     uint32_t tmp;
492
493     tmp = val & 0xC0000000;
494     tmp |= val & ((1ULL << MAX_CPU) - 1);
495     opp->src[n_IRQ].ide = tmp;
496     DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
497 }
498
499 static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
500 {
501     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
502     /* ACTIVITY bit is read-only */
503     opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
504                          | (val & 0x800F00FF);
505     openpic_update_irq(opp, n_IRQ);
506     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
507             opp->src[n_IRQ].ipvp);
508 }
509
510 #if 0 // Code provision for Intel model
511 #if MAX_DBL > 0
512 static uint32_t read_doorbell_register (openpic_t *opp,
513                                         int n_dbl, uint32_t offset)
514 {
515     uint32_t retval;
516
517     switch (offset) {
518     case DBL_IPVP_OFFSET:
519         retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
520         break;
521     case DBL_IDE_OFFSET:
522         retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
523         break;
524     case DBL_DMR_OFFSET:
525         retval = opp->doorbells[n_dbl].dmr;
526         break;
527     }
528
529     return retval;
530 }
531
532 static void write_doorbell_register (penpic_t *opp, int n_dbl,
533                                      uint32_t offset, uint32_t value)
534 {
535     switch (offset) {
536     case DBL_IVPR_OFFSET:
537         write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
538         break;
539     case DBL_IDE_OFFSET:
540         write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
541         break;
542     case DBL_DMR_OFFSET:
543         opp->doorbells[n_dbl].dmr = value;
544         break;
545     }
546 }
547 #endif
548
549 #if MAX_MBX > 0
550 static uint32_t read_mailbox_register (openpic_t *opp,
551                                        int n_mbx, uint32_t offset)
552 {
553     uint32_t retval;
554
555     switch (offset) {
556     case MBX_MBR_OFFSET:
557         retval = opp->mailboxes[n_mbx].mbr;
558         break;
559     case MBX_IVPR_OFFSET:
560         retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
561         break;
562     case MBX_DMR_OFFSET:
563         retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
564         break;
565     }
566
567     return retval;
568 }
569
570 static void write_mailbox_register (openpic_t *opp, int n_mbx,
571                                     uint32_t address, uint32_t value)
572 {
573     switch (offset) {
574     case MBX_MBR_OFFSET:
575         opp->mailboxes[n_mbx].mbr = value;
576         break;
577     case MBX_IVPR_OFFSET:
578         write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
579         break;
580     case MBX_DMR_OFFSET:
581         write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
582         break;
583     }
584 }
585 #endif
586 #endif /* 0 : Code provision for Intel model */
587
588 static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
589 {
590     openpic_t *opp = opaque;
591     IRQ_dst_t *dst;
592     int idx;
593
594     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
595     if (addr & 0xF)
596         return;
597     switch (addr) {
598     case 0x40:
599     case 0x50:
600     case 0x60:
601     case 0x70:
602     case 0x80:
603     case 0x90:
604     case 0xA0:
605     case 0xB0:
606         openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
607         break;
608     case 0x1000: /* FREP */
609         break;
610     case 0x1020: /* GLBC */
611         if (val & 0x80000000 && opp->reset)
612             opp->reset(opp);
613         opp->glbc = val & ~0x80000000;
614         break;
615     case 0x1080: /* VENI */
616         break;
617     case 0x1090: /* PINT */
618         for (idx = 0; idx < opp->nb_cpus; idx++) {
619             if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
620                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
621                 dst = &opp->dst[idx];
622                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
623             } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
624                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
625                 dst = &opp->dst[idx];
626                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
627             }
628         }
629         opp->pint = val;
630         break;
631     case 0x10A0: /* IPI_IPVP */
632     case 0x10B0:
633     case 0x10C0:
634     case 0x10D0:
635         {
636             int idx;
637             idx = (addr - 0x10A0) >> 4;
638             write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
639         }
640         break;
641     case 0x10E0: /* SPVE */
642         opp->spve = val & 0x000000FF;
643         break;
644     case 0x10F0: /* TIFR */
645         opp->tifr = val;
646         break;
647     default:
648         break;
649     }
650 }
651
652 static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
653 {
654     openpic_t *opp = opaque;
655     uint32_t retval;
656
657     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
658     retval = 0xFFFFFFFF;
659     if (addr & 0xF)
660         return retval;
661     switch (addr) {
662     case 0x1000: /* FREP */
663         retval = opp->frep;
664         break;
665     case 0x1020: /* GLBC */
666         retval = opp->glbc;
667         break;
668     case 0x1080: /* VENI */
669         retval = opp->veni;
670         break;
671     case 0x1090: /* PINT */
672         retval = 0x00000000;
673         break;
674     case 0x40:
675     case 0x50:
676     case 0x60:
677     case 0x70:
678     case 0x80:
679     case 0x90:
680     case 0xA0:
681     case 0xB0:
682         retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
683         break;
684     case 0x10A0: /* IPI_IPVP */
685     case 0x10B0:
686     case 0x10C0:
687     case 0x10D0:
688         {
689             int idx;
690             idx = (addr - 0x10A0) >> 4;
691             retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
692         }
693         break;
694     case 0x10E0: /* SPVE */
695         retval = opp->spve;
696         break;
697     case 0x10F0: /* TIFR */
698         retval = opp->tifr;
699         break;
700     default:
701         break;
702     }
703     DPRINTF("%s: => %08x\n", __func__, retval);
704
705     return retval;
706 }
707
708 static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
709 {
710     openpic_t *opp = opaque;
711     int idx;
712
713     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
714     if (addr & 0xF)
715         return;
716     addr -= 0x1100;
717     addr &= 0xFFFF;
718     idx = (addr & 0xFFF0) >> 6;
719     addr = addr & 0x30;
720     switch (addr) {
721     case 0x00: /* TICC */
722         break;
723     case 0x10: /* TIBC */
724         if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
725             (val & 0x80000000) == 0 &&
726             (opp->timers[idx].tibc & 0x80000000) != 0)
727             opp->timers[idx].ticc &= ~0x80000000;
728         opp->timers[idx].tibc = val;
729         break;
730     case 0x20: /* TIVP */
731         write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
732         break;
733     case 0x30: /* TIDE */
734         write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
735         break;
736     }
737 }
738
739 static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
740 {
741     openpic_t *opp = opaque;
742     uint32_t retval;
743     int idx;
744
745     DPRINTF("%s: addr %08x\n", __func__, addr);
746     retval = 0xFFFFFFFF;
747     if (addr & 0xF)
748         return retval;
749     addr -= 0x1100;
750     addr &= 0xFFFF;
751     idx = (addr & 0xFFF0) >> 6;
752     addr = addr & 0x30;
753     switch (addr) {
754     case 0x00: /* TICC */
755         retval = opp->timers[idx].ticc;
756         break;
757     case 0x10: /* TIBC */
758         retval = opp->timers[idx].tibc;
759         break;
760     case 0x20: /* TIPV */
761         retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
762         break;
763     case 0x30: /* TIDE */
764         retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
765         break;
766     }
767     DPRINTF("%s: => %08x\n", __func__, retval);
768
769     return retval;
770 }
771
772 static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
773 {
774     openpic_t *opp = opaque;
775     int idx;
776
777     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
778     if (addr & 0xF)
779         return;
780     addr = addr & 0xFFF0;
781     idx = addr >> 5;
782     if (addr & 0x10) {
783         /* EXDE / IFEDE / IEEDE */
784         write_IRQreg_ide(opp, idx, val);
785     } else {
786         /* EXVP / IFEVP / IEEVP */
787         write_IRQreg_ipvp(opp, idx, val);
788     }
789 }
790
791 static uint32_t openpic_src_read (void *opaque, uint32_t addr)
792 {
793     openpic_t *opp = opaque;
794     uint32_t retval;
795     int idx;
796
797     DPRINTF("%s: addr %08x\n", __func__, addr);
798     retval = 0xFFFFFFFF;
799     if (addr & 0xF)
800         return retval;
801     addr = addr & 0xFFF0;
802     idx = addr >> 5;
803     if (addr & 0x10) {
804         /* EXDE / IFEDE / IEEDE */
805         retval = read_IRQreg_ide(opp, idx);
806     } else {
807         /* EXVP / IFEVP / IEEVP */
808         retval = read_IRQreg_ipvp(opp, idx);
809     }
810     DPRINTF("%s: => %08x\n", __func__, retval);
811
812     return retval;
813 }
814
815 static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
816                                        uint32_t val, int idx)
817 {
818     openpic_t *opp = opaque;
819     IRQ_src_t *src;
820     IRQ_dst_t *dst;
821     int s_IRQ, n_IRQ;
822
823     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
824             addr, val);
825     if (addr & 0xF)
826         return;
827     dst = &opp->dst[idx];
828     addr &= 0xFF0;
829     switch (addr) {
830 #if MAX_IPI > 0
831     case 0x40: /* IPIDR */
832     case 0x50:
833     case 0x60:
834     case 0x70:
835         idx = (addr - 0x40) >> 4;
836         /* we use IDE as mask which CPUs to deliver the IPI to still. */
837         write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
838                          opp->src[opp->irq_ipi0 + idx].ide | val);
839         openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
840         openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
841         break;
842 #endif
843     case 0x80: /* PCTP */
844         dst->pctp = val & 0x0000000F;
845         break;
846     case 0x90: /* WHOAMI */
847         /* Read-only register */
848         break;
849     case 0xA0: /* PIAC */
850         /* Read-only register */
851         break;
852     case 0xB0: /* PEOI */
853         DPRINTF("PEOI\n");
854         s_IRQ = IRQ_get_next(opp, &dst->servicing);
855         IRQ_resetbit(&dst->servicing, s_IRQ);
856         dst->servicing.next = -1;
857         /* Set up next servicing IRQ */
858         s_IRQ = IRQ_get_next(opp, &dst->servicing);
859         /* Check queued interrupts. */
860         n_IRQ = IRQ_get_next(opp, &dst->raised);
861         src = &opp->src[n_IRQ];
862         if (n_IRQ != -1 &&
863             (s_IRQ == -1 ||
864              IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
865             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
866                     idx, n_IRQ);
867             opp->irq_raise(opp, idx, src);
868         }
869         break;
870     default:
871         break;
872     }
873 }
874
875 static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
876 {
877     openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
878 }
879
880 static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
881                                           int idx)
882 {
883     openpic_t *opp = opaque;
884     IRQ_src_t *src;
885     IRQ_dst_t *dst;
886     uint32_t retval;
887     int n_IRQ;
888
889     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
890     retval = 0xFFFFFFFF;
891     if (addr & 0xF)
892         return retval;
893     dst = &opp->dst[idx];
894     addr &= 0xFF0;
895     switch (addr) {
896     case 0x80: /* PCTP */
897         retval = dst->pctp;
898         break;
899     case 0x90: /* WHOAMI */
900         retval = idx;
901         break;
902     case 0xA0: /* PIAC */
903         DPRINTF("Lower OpenPIC INT output\n");
904         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
905         n_IRQ = IRQ_get_next(opp, &dst->raised);
906         DPRINTF("PIAC: irq=%d\n", n_IRQ);
907         if (n_IRQ == -1) {
908             /* No more interrupt pending */
909             retval = IPVP_VECTOR(opp->spve);
910         } else {
911             src = &opp->src[n_IRQ];
912             if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
913                 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
914                 /* - Spurious level-sensitive IRQ
915                  * - Priorities has been changed
916                  *   and the pending IRQ isn't allowed anymore
917                  */
918                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
919                 retval = IPVP_VECTOR(opp->spve);
920             } else {
921                 /* IRQ enter servicing state */
922                 IRQ_setbit(&dst->servicing, n_IRQ);
923                 retval = IPVP_VECTOR(src->ipvp);
924             }
925             IRQ_resetbit(&dst->raised, n_IRQ);
926             dst->raised.next = -1;
927             if (!test_bit(&src->ipvp, IPVP_SENSE)) {
928                 /* edge-sensitive IRQ */
929                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
930                 src->pending = 0;
931             }
932
933             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
934                 src->ide &= ~(1 << idx);
935                 if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
936                     /* trigger on CPUs that didn't know about it yet */
937                     openpic_set_irq(opp, n_IRQ, 1);
938                     openpic_set_irq(opp, n_IRQ, 0);
939                     /* if all CPUs knew about it, set active bit again */
940                     set_bit(&src->ipvp, IPVP_ACTIVITY);
941                 }
942             }
943         }
944         break;
945     case 0xB0: /* PEOI */
946         retval = 0;
947         break;
948     default:
949         break;
950     }
951     DPRINTF("%s: => %08x\n", __func__, retval);
952
953     return retval;
954 }
955
956 static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
957 {
958     return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
959 }
960
961 static void openpic_buggy_write (void *opaque,
962                                  target_phys_addr_t addr, uint32_t val)
963 {
964     printf("Invalid OPENPIC write access !\n");
965 }
966
967 static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
968 {
969     printf("Invalid OPENPIC read access !\n");
970
971     return -1;
972 }
973
974 static void openpic_writel (void *opaque,
975                             target_phys_addr_t addr, uint32_t val)
976 {
977     openpic_t *opp = opaque;
978
979     addr &= 0x3FFFF;
980     DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
981     if (addr < 0x1100) {
982         /* Global registers */
983         openpic_gbl_write(opp, addr, val);
984     } else if (addr < 0x10000) {
985         /* Timers registers */
986         openpic_timer_write(opp, addr, val);
987     } else if (addr < 0x20000) {
988         /* Source registers */
989         openpic_src_write(opp, addr, val);
990     } else {
991         /* CPU registers */
992         openpic_cpu_write(opp, addr, val);
993     }
994 }
995
996 static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
997 {
998     openpic_t *opp = opaque;
999     uint32_t retval;
1000
1001     addr &= 0x3FFFF;
1002     DPRINTF("%s: offset %08x\n", __func__, (int)addr);
1003     if (addr < 0x1100) {
1004         /* Global registers */
1005         retval = openpic_gbl_read(opp, addr);
1006     } else if (addr < 0x10000) {
1007         /* Timers registers */
1008         retval = openpic_timer_read(opp, addr);
1009     } else if (addr < 0x20000) {
1010         /* Source registers */
1011         retval = openpic_src_read(opp, addr);
1012     } else {
1013         /* CPU registers */
1014         retval = openpic_cpu_read(opp, addr);
1015     }
1016
1017     return retval;
1018 }
1019
1020 static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
1021                              unsigned size)
1022 {
1023     openpic_t *opp = opaque;
1024
1025     switch (size) {
1026     case 4: return openpic_readl(opp, addr);
1027     default: return openpic_buggy_read(opp, addr);
1028     }
1029 }
1030
1031 static void openpic_write(void *opaque, target_phys_addr_t addr,
1032                           uint64_t data, unsigned size)
1033 {
1034     openpic_t *opp = opaque;
1035
1036     switch (size) {
1037     case 4: return openpic_writel(opp, addr, data);
1038     default: return openpic_buggy_write(opp, addr, data);
1039     }
1040 }
1041
1042 static const MemoryRegionOps openpic_ops = {
1043     .read = openpic_read,
1044     .write = openpic_write,
1045     .endianness = DEVICE_LITTLE_ENDIAN,
1046 };
1047
1048 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1049 {
1050     unsigned int i;
1051
1052     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1053         qemu_put_be32s(f, &q->queue[i]);
1054
1055     qemu_put_sbe32s(f, &q->next);
1056     qemu_put_sbe32s(f, &q->priority);
1057 }
1058
1059 static void openpic_save(QEMUFile* f, void *opaque)
1060 {
1061     openpic_t *opp = (openpic_t *)opaque;
1062     unsigned int i;
1063
1064     qemu_put_be32s(f, &opp->frep);
1065     qemu_put_be32s(f, &opp->glbc);
1066     qemu_put_be32s(f, &opp->micr);
1067     qemu_put_be32s(f, &opp->veni);
1068     qemu_put_be32s(f, &opp->pint);
1069     qemu_put_be32s(f, &opp->spve);
1070     qemu_put_be32s(f, &opp->tifr);
1071
1072     for (i = 0; i < opp->max_irq; i++) {
1073         qemu_put_be32s(f, &opp->src[i].ipvp);
1074         qemu_put_be32s(f, &opp->src[i].ide);
1075         qemu_put_sbe32s(f, &opp->src[i].type);
1076         qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1077         qemu_put_sbe32s(f, &opp->src[i].pending);
1078     }
1079
1080     qemu_put_sbe32s(f, &opp->nb_cpus);
1081
1082     for (i = 0; i < opp->nb_cpus; i++) {
1083         qemu_put_be32s(f, &opp->dst[i].tfrr);
1084         qemu_put_be32s(f, &opp->dst[i].pctp);
1085         qemu_put_be32s(f, &opp->dst[i].pcsr);
1086         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1087         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1088     }
1089
1090     for (i = 0; i < MAX_TMR; i++) {
1091         qemu_put_be32s(f, &opp->timers[i].ticc);
1092         qemu_put_be32s(f, &opp->timers[i].tibc);
1093     }
1094
1095 #if MAX_DBL > 0
1096     qemu_put_be32s(f, &opp->dar);
1097
1098     for (i = 0; i < MAX_DBL; i++) {
1099         qemu_put_be32s(f, &opp->doorbells[i].dmr);
1100     }
1101 #endif
1102
1103 #if MAX_MBX > 0
1104     for (i = 0; i < MAX_MAILBOXES; i++) {
1105         qemu_put_be32s(f, &opp->mailboxes[i].mbr);
1106     }
1107 #endif
1108
1109     pci_device_save(&opp->pci_dev, f);
1110 }
1111
1112 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1113 {
1114     unsigned int i;
1115
1116     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1117         qemu_get_be32s(f, &q->queue[i]);
1118
1119     qemu_get_sbe32s(f, &q->next);
1120     qemu_get_sbe32s(f, &q->priority);
1121 }
1122
1123 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1124 {
1125     openpic_t *opp = (openpic_t *)opaque;
1126     unsigned int i;
1127
1128     if (version_id != 1)
1129         return -EINVAL;
1130
1131     qemu_get_be32s(f, &opp->frep);
1132     qemu_get_be32s(f, &opp->glbc);
1133     qemu_get_be32s(f, &opp->micr);
1134     qemu_get_be32s(f, &opp->veni);
1135     qemu_get_be32s(f, &opp->pint);
1136     qemu_get_be32s(f, &opp->spve);
1137     qemu_get_be32s(f, &opp->tifr);
1138
1139     for (i = 0; i < opp->max_irq; i++) {
1140         qemu_get_be32s(f, &opp->src[i].ipvp);
1141         qemu_get_be32s(f, &opp->src[i].ide);
1142         qemu_get_sbe32s(f, &opp->src[i].type);
1143         qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1144         qemu_get_sbe32s(f, &opp->src[i].pending);
1145     }
1146
1147     qemu_get_sbe32s(f, &opp->nb_cpus);
1148
1149     for (i = 0; i < opp->nb_cpus; i++) {
1150         qemu_get_be32s(f, &opp->dst[i].tfrr);
1151         qemu_get_be32s(f, &opp->dst[i].pctp);
1152         qemu_get_be32s(f, &opp->dst[i].pcsr);
1153         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1154         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1155     }
1156
1157     for (i = 0; i < MAX_TMR; i++) {
1158         qemu_get_be32s(f, &opp->timers[i].ticc);
1159         qemu_get_be32s(f, &opp->timers[i].tibc);
1160     }
1161
1162 #if MAX_DBL > 0
1163     qemu_get_be32s(f, &opp->dar);
1164
1165     for (i = 0; i < MAX_DBL; i++) {
1166         qemu_get_be32s(f, &opp->doorbells[i].dmr);
1167     }
1168 #endif
1169
1170 #if MAX_MBX > 0
1171     for (i = 0; i < MAX_MAILBOXES; i++) {
1172         qemu_get_be32s(f, &opp->mailboxes[i].mbr);
1173     }
1174 #endif
1175
1176     return pci_device_load(&opp->pci_dev, f);
1177 }
1178
1179 static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
1180 {
1181     qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1182 }
1183
1184 qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
1185                         qemu_irq **irqs, qemu_irq irq_out)
1186 {
1187     openpic_t *opp;
1188     uint8_t *pci_conf;
1189     int i, m;
1190
1191     /* XXX: for now, only one CPU is supported */
1192     if (nb_cpus != 1)
1193         return NULL;
1194     if (bus) {
1195         opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
1196                                                -1, NULL, NULL);
1197         pci_conf = opp->pci_dev.config;
1198         pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
1199         pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
1200         pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
1201         pci_conf[0x3d] = 0x00; // no interrupt pin
1202
1203         memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1204 #if 0 // Don't implement ISU for now
1205         opp_io_memory = cpu_register_io_memory(openpic_src_read,
1206                                                openpic_src_write, NULL
1207                                                DEVICE_NATIVE_ENDIAN);
1208         cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
1209                                      opp_io_memory);
1210 #endif
1211
1212         /* Register I/O spaces */
1213         pci_register_bar(&opp->pci_dev, 0,
1214                          PCI_BASE_ADDRESS_SPACE_MEMORY, &opp->mem);
1215     } else {
1216         opp = g_malloc0(sizeof(openpic_t));
1217         memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1218     }
1219
1220     //    isu_base &= 0xFFFC0000;
1221     opp->nb_cpus = nb_cpus;
1222     opp->max_irq = OPENPIC_MAX_IRQ;
1223     opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1224     opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1225     /* Set IRQ types */
1226     for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1227         opp->src[i].type = IRQ_EXTERNAL;
1228     }
1229     for (; i < OPENPIC_IRQ_TIM0; i++) {
1230         opp->src[i].type = IRQ_SPECIAL;
1231     }
1232 #if MAX_IPI > 0
1233     m = OPENPIC_IRQ_IPI0;
1234 #else
1235     m = OPENPIC_IRQ_DBL0;
1236 #endif
1237     for (; i < m; i++) {
1238         opp->src[i].type = IRQ_TIMER;
1239     }
1240     for (; i < OPENPIC_MAX_IRQ; i++) {
1241         opp->src[i].type = IRQ_INTERNAL;
1242     }
1243     for (i = 0; i < nb_cpus; i++)
1244         opp->dst[i].irqs = irqs[i];
1245     opp->irq_out = irq_out;
1246
1247     register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1248                     openpic_save, openpic_load, opp);
1249     qemu_register_reset(openpic_reset, opp);
1250
1251     opp->irq_raise = openpic_irq_raise;
1252     opp->reset = openpic_reset;
1253
1254     if (pmem)
1255         *pmem = &opp->mem;
1256
1257     return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1258 }
1259
1260 static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1261 {
1262     int n_ci = IDR_CI0 - n_CPU;
1263
1264     if(test_bit(&src->ide, n_ci)) {
1265         qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1266     }
1267     else {
1268         qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1269     }
1270 }
1271
1272 static void mpic_reset (void *opaque)
1273 {
1274     openpic_t *mpp = (openpic_t *)opaque;
1275     int i;
1276
1277     mpp->glbc = 0x80000000;
1278     /* Initialise controller registers */
1279     mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1280     mpp->veni = VENI;
1281     mpp->pint = 0x00000000;
1282     mpp->spve = 0x0000FFFF;
1283     /* Initialise IRQ sources */
1284     for (i = 0; i < mpp->max_irq; i++) {
1285         mpp->src[i].ipvp = 0x80800000;
1286         mpp->src[i].ide  = 0x00000001;
1287     }
1288     /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1289     for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1290         mpp->src[i].ide = 0;
1291     }
1292     /* Initialise IRQ destinations */
1293     for (i = 0; i < MAX_CPU; i++) {
1294         mpp->dst[i].pctp      = 0x0000000F;
1295         mpp->dst[i].tfrr      = 0x00000000;
1296         memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1297         mpp->dst[i].raised.next = -1;
1298         memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1299         mpp->dst[i].servicing.next = -1;
1300     }
1301     /* Initialise timers */
1302     for (i = 0; i < MAX_TMR; i++) {
1303         mpp->timers[i].ticc = 0x00000000;
1304         mpp->timers[i].tibc = 0x80000000;
1305     }
1306     /* Go out of RESET state */
1307     mpp->glbc = 0x00000000;
1308 }
1309
1310 static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
1311 {
1312     openpic_t *mpp = opaque;
1313     int idx, cpu;
1314
1315     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1316     if (addr & 0xF)
1317         return;
1318     addr &= 0xFFFF;
1319     cpu = addr >> 12;
1320     idx = (addr >> 6) & 0x3;
1321     switch (addr & 0x30) {
1322     case 0x00: /* gtccr */
1323         break;
1324     case 0x10: /* gtbcr */
1325         if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1326             (val & 0x80000000) == 0 &&
1327             (mpp->timers[idx].tibc & 0x80000000) != 0)
1328             mpp->timers[idx].ticc &= ~0x80000000;
1329         mpp->timers[idx].tibc = val;
1330         break;
1331     case 0x20: /* GTIVPR */
1332         write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1333         break;
1334     case 0x30: /* GTIDR & TFRR */
1335         if ((addr & 0xF0) == 0xF0)
1336             mpp->dst[cpu].tfrr = val;
1337         else
1338             write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1339         break;
1340     }
1341 }
1342
1343 static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
1344 {
1345     openpic_t *mpp = opaque;
1346     uint32_t retval;
1347     int idx, cpu;
1348
1349     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1350     retval = 0xFFFFFFFF;
1351     if (addr & 0xF)
1352         return retval;
1353     addr &= 0xFFFF;
1354     cpu = addr >> 12;
1355     idx = (addr >> 6) & 0x3;
1356     switch (addr & 0x30) {
1357     case 0x00: /* gtccr */
1358         retval = mpp->timers[idx].ticc;
1359         break;
1360     case 0x10: /* gtbcr */
1361         retval = mpp->timers[idx].tibc;
1362         break;
1363     case 0x20: /* TIPV */
1364         retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1365         break;
1366     case 0x30: /* TIDR */
1367         if ((addr &0xF0) == 0XF0)
1368             retval = mpp->dst[cpu].tfrr;
1369         else
1370             retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1371         break;
1372     }
1373     DPRINTF("%s: => %08x\n", __func__, retval);
1374
1375     return retval;
1376 }
1377
1378 static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
1379                                 uint32_t val)
1380 {
1381     openpic_t *mpp = opaque;
1382     int idx = MPIC_EXT_IRQ;
1383
1384     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1385     if (addr & 0xF)
1386         return;
1387
1388     addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1389     if (addr < MPIC_EXT_REG_SIZE) {
1390         idx += (addr & 0xFFF0) >> 5;
1391         if (addr & 0x10) {
1392             /* EXDE / IFEDE / IEEDE */
1393             write_IRQreg_ide(mpp, idx, val);
1394         } else {
1395             /* EXVP / IFEVP / IEEVP */
1396             write_IRQreg_ipvp(mpp, idx, val);
1397         }
1398     }
1399 }
1400
1401 static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
1402 {
1403     openpic_t *mpp = opaque;
1404     uint32_t retval;
1405     int idx = MPIC_EXT_IRQ;
1406
1407     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1408     retval = 0xFFFFFFFF;
1409     if (addr & 0xF)
1410         return retval;
1411
1412     addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1413     if (addr < MPIC_EXT_REG_SIZE) {
1414         idx += (addr & 0xFFF0) >> 5;
1415         if (addr & 0x10) {
1416             /* EXDE / IFEDE / IEEDE */
1417             retval = read_IRQreg_ide(mpp, idx);
1418         } else {
1419             /* EXVP / IFEVP / IEEVP */
1420             retval = read_IRQreg_ipvp(mpp, idx);
1421         }
1422         DPRINTF("%s: => %08x\n", __func__, retval);
1423     }
1424
1425     return retval;
1426 }
1427
1428 static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
1429                                 uint32_t val)
1430 {
1431     openpic_t *mpp = opaque;
1432     int idx = MPIC_INT_IRQ;
1433
1434     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1435     if (addr & 0xF)
1436         return;
1437
1438     addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1439     if (addr < MPIC_INT_REG_SIZE) {
1440         idx += (addr & 0xFFF0) >> 5;
1441         if (addr & 0x10) {
1442             /* EXDE / IFEDE / IEEDE */
1443             write_IRQreg_ide(mpp, idx, val);
1444         } else {
1445             /* EXVP / IFEVP / IEEVP */
1446             write_IRQreg_ipvp(mpp, idx, val);
1447         }
1448     }
1449 }
1450
1451 static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
1452 {
1453     openpic_t *mpp = opaque;
1454     uint32_t retval;
1455     int idx = MPIC_INT_IRQ;
1456
1457     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1458     retval = 0xFFFFFFFF;
1459     if (addr & 0xF)
1460         return retval;
1461
1462     addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
1463     if (addr < MPIC_INT_REG_SIZE) {
1464         idx += (addr & 0xFFF0) >> 5;
1465         if (addr & 0x10) {
1466             /* EXDE / IFEDE / IEEDE */
1467             retval = read_IRQreg_ide(mpp, idx);
1468         } else {
1469             /* EXVP / IFEVP / IEEVP */
1470             retval = read_IRQreg_ipvp(mpp, idx);
1471         }
1472         DPRINTF("%s: => %08x\n", __func__, retval);
1473     }
1474
1475     return retval;
1476 }
1477
1478 static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
1479                                 uint32_t val)
1480 {
1481     openpic_t *mpp = opaque;
1482     int idx = MPIC_MSG_IRQ;
1483
1484     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1485     if (addr & 0xF)
1486         return;
1487
1488     addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
1489     if (addr < MPIC_MSG_REG_SIZE) {
1490         idx += (addr & 0xFFF0) >> 5;
1491         if (addr & 0x10) {
1492             /* EXDE / IFEDE / IEEDE */
1493             write_IRQreg_ide(mpp, idx, val);
1494         } else {
1495             /* EXVP / IFEVP / IEEVP */
1496             write_IRQreg_ipvp(mpp, idx, val);
1497         }
1498     }
1499 }
1500
1501 static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
1502 {
1503     openpic_t *mpp = opaque;
1504     uint32_t retval;
1505     int idx = MPIC_MSG_IRQ;
1506
1507     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1508     retval = 0xFFFFFFFF;
1509     if (addr & 0xF)
1510         return retval;
1511
1512     addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
1513     if (addr < MPIC_MSG_REG_SIZE) {
1514         idx += (addr & 0xFFF0) >> 5;
1515         if (addr & 0x10) {
1516             /* EXDE / IFEDE / IEEDE */
1517             retval = read_IRQreg_ide(mpp, idx);
1518         } else {
1519             /* EXVP / IFEVP / IEEVP */
1520             retval = read_IRQreg_ipvp(mpp, idx);
1521         }
1522         DPRINTF("%s: => %08x\n", __func__, retval);
1523     }
1524
1525     return retval;
1526 }
1527
1528 static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
1529                                 uint32_t val)
1530 {
1531     openpic_t *mpp = opaque;
1532     int idx = MPIC_MSI_IRQ;
1533
1534     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1535     if (addr & 0xF)
1536         return;
1537
1538     addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
1539     if (addr < MPIC_MSI_REG_SIZE) {
1540         idx += (addr & 0xFFF0) >> 5;
1541         if (addr & 0x10) {
1542             /* EXDE / IFEDE / IEEDE */
1543             write_IRQreg_ide(mpp, idx, val);
1544         } else {
1545             /* EXVP / IFEVP / IEEVP */
1546             write_IRQreg_ipvp(mpp, idx, val);
1547         }
1548     }
1549 }
1550 static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
1551 {
1552     openpic_t *mpp = opaque;
1553     uint32_t retval;
1554     int idx = MPIC_MSI_IRQ;
1555
1556     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1557     retval = 0xFFFFFFFF;
1558     if (addr & 0xF)
1559         return retval;
1560
1561     addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
1562     if (addr < MPIC_MSI_REG_SIZE) {
1563         idx += (addr & 0xFFF0) >> 5;
1564         if (addr & 0x10) {
1565             /* EXDE / IFEDE / IEEDE */
1566             retval = read_IRQreg_ide(mpp, idx);
1567         } else {
1568             /* EXVP / IFEVP / IEEVP */
1569             retval = read_IRQreg_ipvp(mpp, idx);
1570         }
1571         DPRINTF("%s: => %08x\n", __func__, retval);
1572     }
1573
1574     return retval;
1575 }
1576
1577 static const MemoryRegionOps mpic_glb_ops = {
1578     .old_mmio = {
1579         .write = { openpic_buggy_write,
1580                    openpic_buggy_write,
1581                    openpic_gbl_write,
1582         },
1583         .read  = { openpic_buggy_read,
1584                    openpic_buggy_read,
1585                    openpic_gbl_read,
1586         },
1587     },
1588     .endianness = DEVICE_BIG_ENDIAN,
1589 };
1590
1591 static const MemoryRegionOps mpic_tmr_ops = {
1592     .old_mmio = {
1593         .write = { openpic_buggy_write,
1594                    openpic_buggy_write,
1595                    mpic_timer_write,
1596         },
1597         .read  = { openpic_buggy_read,
1598                    openpic_buggy_read,
1599                    mpic_timer_read,
1600         },
1601     },
1602     .endianness = DEVICE_BIG_ENDIAN,
1603 };
1604
1605 static const MemoryRegionOps mpic_cpu_ops = {
1606     .old_mmio = {
1607         .write = { openpic_buggy_write,
1608                    openpic_buggy_write,
1609                    openpic_cpu_write,
1610         },
1611         .read  = { openpic_buggy_read,
1612                    openpic_buggy_read,
1613                    openpic_cpu_read,
1614         },
1615     },
1616     .endianness = DEVICE_BIG_ENDIAN,
1617 };
1618
1619 static const MemoryRegionOps mpic_ext_ops = {
1620     .old_mmio = {
1621         .write = { openpic_buggy_write,
1622                    openpic_buggy_write,
1623                    mpic_src_ext_write,
1624         },
1625         .read  = { openpic_buggy_read,
1626                    openpic_buggy_read,
1627                    mpic_src_ext_read,
1628         },
1629     },
1630     .endianness = DEVICE_BIG_ENDIAN,
1631 };
1632
1633 static const MemoryRegionOps mpic_int_ops = {
1634     .old_mmio = {
1635         .write = { openpic_buggy_write,
1636                    openpic_buggy_write,
1637                    mpic_src_int_write,
1638         },
1639         .read  = { openpic_buggy_read,
1640                    openpic_buggy_read,
1641                    mpic_src_int_read,
1642         },
1643     },
1644     .endianness = DEVICE_BIG_ENDIAN,
1645 };
1646
1647 static const MemoryRegionOps mpic_msg_ops = {
1648     .old_mmio = {
1649         .write = { openpic_buggy_write,
1650                    openpic_buggy_write,
1651                    mpic_src_msg_write,
1652         },
1653         .read  = { openpic_buggy_read,
1654                    openpic_buggy_read,
1655                    mpic_src_msg_read,
1656         },
1657     },
1658     .endianness = DEVICE_BIG_ENDIAN,
1659 };
1660
1661 static const MemoryRegionOps mpic_msi_ops = {
1662     .old_mmio = {
1663         .write = { openpic_buggy_write,
1664                    openpic_buggy_write,
1665                    mpic_src_msi_write,
1666         },
1667         .read  = { openpic_buggy_read,
1668                    openpic_buggy_read,
1669                    mpic_src_msi_read,
1670         },
1671     },
1672     .endianness = DEVICE_BIG_ENDIAN,
1673 };
1674
1675 qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
1676                      int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1677 {
1678     openpic_t    *mpp;
1679     int           i;
1680     struct {
1681         const char             *name;
1682         MemoryRegionOps const  *ops;
1683         target_phys_addr_t      start_addr;
1684         ram_addr_t              size;
1685     } const list[] = {
1686         {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1687         {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1688         {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1689         {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1690         {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1691         {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1692         {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1693     };
1694
1695     mpp = g_malloc0(sizeof(openpic_t));
1696
1697     memory_region_init(&mpp->mem, "mpic", 0x40000);
1698     memory_region_add_subregion(address_space, base, &mpp->mem);
1699
1700     for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1701
1702         memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1703                               list[i].name, list[i].size);
1704
1705         memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1706                                     &mpp->sub_io_mem[i]);
1707     }
1708
1709     mpp->nb_cpus = nb_cpus;
1710     mpp->max_irq = MPIC_MAX_IRQ;
1711     mpp->irq_ipi0 = MPIC_IPI_IRQ;
1712     mpp->irq_tim0 = MPIC_TMR_IRQ;
1713
1714     for (i = 0; i < nb_cpus; i++)
1715         mpp->dst[i].irqs = irqs[i];
1716     mpp->irq_out = irq_out;
1717
1718     mpp->irq_raise = mpic_irq_raise;
1719     mpp->reset = mpic_reset;
1720
1721     register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1722     qemu_register_reset(mpic_reset, mpp);
1723
1724     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1725 }
This page took 0.123145 seconds and 4 git commands to generate.