Add savevm and reset support for OpenPic
[qemu] / hw / openpic.c
1 /*
2  * OpenPIC emulation
3  *
4  * Copyright (c) 2004 Jocelyn Mayer
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 /*
25  *
26  * Based on OpenPic implementations:
27  * - Intel GW80314 I/O companion chip developer's manual
28  * - Motorola MPC8245 & MPC8540 user manuals.
29  * - Motorola MCP750 (aka Raven) programmer manual.
30  * - Motorola Harrier programmer manuel
31  *
32  * Serial interrupts, as implemented in Raven chipset are not supported yet.
33  *
34  */
35 #include "hw.h"
36 #include "ppc_mac.h"
37 #include "pci.h"
38
39 //#define DEBUG_OPENPIC
40
41 #ifdef DEBUG_OPENPIC
42 #define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
43 #else
44 #define DPRINTF(fmt, args...) do { } while (0)
45 #endif
46 #define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
47
48 #define USE_MPCxxx /* Intel model is broken, for now */
49
50 #if defined (USE_INTEL_GW80314)
51 /* Intel GW80314 I/O Companion chip */
52
53 #define MAX_CPU     4
54 #define MAX_IRQ    32
55 #define MAX_DBL     4
56 #define MAX_MBX     4
57 #define MAX_TMR     4
58 #define VECTOR_BITS 8
59 #define MAX_IPI     0
60
61 #define VID (0x00000000)
62
63 #define OPENPIC_LITTLE_ENDIAN 1
64 #define OPENPIC_BIG_ENDIAN    0
65
66 #elif defined(USE_MPCxxx)
67
68 #define MAX_CPU     2
69 #define MAX_IRQ    64
70 #define EXT_IRQ    48
71 #define MAX_DBL     0
72 #define MAX_MBX     0
73 #define MAX_TMR     4
74 #define VECTOR_BITS 8
75 #define MAX_IPI     4
76 #define VID         0x03 /* MPIC version ID */
77 #define VENI        0x00000000 /* Vendor ID */
78
79 enum {
80     IRQ_IPVP = 0,
81     IRQ_IDE,
82 };
83
84 #define OPENPIC_LITTLE_ENDIAN 1
85 #define OPENPIC_BIG_ENDIAN    0
86
87 #else
88 #error "Please select which OpenPic implementation is to be emulated"
89 #endif
90
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 #define BF_WIDTH(_bits_) \
109 (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
110
111 static inline void set_bit (uint32_t *field, int bit)
112 {
113     field[bit >> 5] |= 1 << (bit & 0x1F);
114 }
115
116 static inline void reset_bit (uint32_t *field, int bit)
117 {
118     field[bit >> 5] &= ~(1 << (bit & 0x1F));
119 }
120
121 static inline int test_bit (uint32_t *field, int bit)
122 {
123     return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
124 }
125
126 enum {
127     IRQ_EXTERNAL = 0x01,
128     IRQ_INTERNAL = 0x02,
129     IRQ_TIMER    = 0x04,
130     IRQ_SPECIAL  = 0x08,
131 };
132
133 typedef struct IRQ_queue_t {
134     uint32_t queue[BF_WIDTH(MAX_IRQ)];
135     int next;
136     int priority;
137 } IRQ_queue_t;
138
139 typedef struct IRQ_src_t {
140     uint32_t ipvp;  /* IRQ vector/priority register */
141     uint32_t ide;   /* IRQ destination register */
142     int type;
143     int last_cpu;
144     int pending;    /* TRUE if IRQ is pending */
145 } IRQ_src_t;
146
147 enum IPVP_bits {
148     IPVP_MASK     = 31,
149     IPVP_ACTIVITY = 30,
150     IPVP_MODE     = 29,
151     IPVP_POLARITY = 23,
152     IPVP_SENSE    = 22,
153 };
154 #define IPVP_PRIORITY_MASK     (0x1F << 16)
155 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
156 #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
157 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
158
159 typedef struct IRQ_dst_t {
160     uint32_t pctp; /* CPU current task priority */
161     uint32_t pcsr; /* CPU sensitivity register */
162     IRQ_queue_t raised;
163     IRQ_queue_t servicing;
164     qemu_irq *irqs;
165 } IRQ_dst_t;
166
167 typedef struct openpic_t {
168     PCIDevice pci_dev;
169     int mem_index;
170     /* Global registers */
171     uint32_t frep; /* Feature reporting register */
172     uint32_t glbc; /* Global configuration register  */
173     uint32_t micr; /* MPIC interrupt configuration register */
174     uint32_t veni; /* Vendor identification register */
175     uint32_t pint; /* Processor initialization register */
176     uint32_t spve; /* Spurious vector register */
177     uint32_t tifr; /* Timer frequency reporting register */
178     /* Source registers */
179     IRQ_src_t src[MAX_IRQ];
180     /* Local registers per output pin */
181     IRQ_dst_t dst[MAX_CPU];
182     int nb_cpus;
183     /* Timer registers */
184     struct {
185         uint32_t ticc;  /* Global timer current count register */
186         uint32_t tibc;  /* Global timer base count register */
187     } timers[MAX_TMR];
188 #if MAX_DBL > 0
189     /* Doorbell registers */
190     uint32_t dar;        /* Doorbell activate register */
191     struct {
192         uint32_t dmr;    /* Doorbell messaging register */
193     } doorbells[MAX_DBL];
194 #endif
195 #if MAX_MBX > 0
196     /* Mailbox registers */
197     struct {
198         uint32_t mbr;    /* Mailbox register */
199     } mailboxes[MAX_MAILBOXES];
200 #endif
201     /* IRQ out is used when in bypass mode (not implemented) */
202     qemu_irq irq_out;
203 } openpic_t;
204
205 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
206 {
207     set_bit(q->queue, n_IRQ);
208 }
209
210 static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
211 {
212     reset_bit(q->queue, n_IRQ);
213 }
214
215 static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
216 {
217     return test_bit(q->queue, n_IRQ);
218 }
219
220 static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
221 {
222     int next, i;
223     int priority;
224
225     next = -1;
226     priority = -1;
227     for (i = 0; i < MAX_IRQ; i++) {
228         if (IRQ_testbit(q, i)) {
229             DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
230                     i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
231             if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
232                 next = i;
233                 priority = IPVP_PRIORITY(opp->src[i].ipvp);
234             }
235         }
236     }
237     q->next = next;
238     q->priority = priority;
239 }
240
241 static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
242 {
243     if (q->next == -1) {
244         /* XXX: optimize */
245         IRQ_check(opp, q);
246     }
247
248     return q->next;
249 }
250
251 static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
252 {
253     IRQ_dst_t *dst;
254     IRQ_src_t *src;
255     int priority;
256
257     dst = &opp->dst[n_CPU];
258     src = &opp->src[n_IRQ];
259     priority = IPVP_PRIORITY(src->ipvp);
260     if (priority <= dst->pctp) {
261         /* Too low priority */
262         DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
263                 __func__, n_IRQ, n_CPU);
264         return;
265     }
266     if (IRQ_testbit(&dst->raised, n_IRQ)) {
267         /* Interrupt miss */
268         DPRINTF("%s: IRQ %d was missed on CPU %d\n",
269                 __func__, n_IRQ, n_CPU);
270         return;
271     }
272     set_bit(&src->ipvp, IPVP_ACTIVITY);
273     IRQ_setbit(&dst->raised, n_IRQ);
274     if (priority < dst->raised.priority) {
275         /* An higher priority IRQ is already raised */
276         DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
277                 __func__, n_IRQ, dst->raised.next, n_CPU);
278         return;
279     }
280     IRQ_get_next(opp, &dst->raised);
281     if (IRQ_get_next(opp, &dst->servicing) != -1 &&
282         priority <= dst->servicing.priority) {
283         DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
284                 __func__, n_IRQ, dst->servicing.next, n_CPU);
285         /* Already servicing a higher priority IRQ */
286         return;
287     }
288     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
289     qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
290 }
291
292 /* update pic state because registers for n_IRQ have changed value */
293 static void openpic_update_irq(openpic_t *opp, int n_IRQ)
294 {
295     IRQ_src_t *src;
296     int i;
297
298     src = &opp->src[n_IRQ];
299
300     if (!src->pending) {
301         /* no irq pending */
302         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
303         return;
304     }
305     if (test_bit(&src->ipvp, IPVP_MASK)) {
306         /* Interrupt source is disabled */
307         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
308         return;
309     }
310     if (IPVP_PRIORITY(src->ipvp) == 0) {
311         /* Priority set to zero */
312         DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
313         return;
314     }
315     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
316         /* IRQ already active */
317         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
318         return;
319     }
320     if (src->ide == 0x00000000) {
321         /* No target */
322         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
323         return;
324     }
325
326     if (src->ide == (1 << src->last_cpu)) {
327         /* Only one CPU is allowed to receive this IRQ */
328         IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
329     } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
330         /* Directed delivery mode */
331         for (i = 0; i < opp->nb_cpus; i++) {
332             if (test_bit(&src->ide, i))
333                 IRQ_local_pipe(opp, i, n_IRQ);
334         }
335     } else {
336         /* Distributed delivery mode */
337         for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
338             if (i == opp->nb_cpus)
339                 i = 0;
340             if (test_bit(&src->ide, i)) {
341                 IRQ_local_pipe(opp, i, n_IRQ);
342                 src->last_cpu = i;
343                 break;
344             }
345         }
346     }
347 }
348
349 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
350 {
351     openpic_t *opp = opaque;
352     IRQ_src_t *src;
353
354     src = &opp->src[n_IRQ];
355     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
356             n_IRQ, level, src->ipvp);
357     if (test_bit(&src->ipvp, IPVP_SENSE)) {
358         /* level-sensitive irq */
359         src->pending = level;
360         if (!level)
361             reset_bit(&src->ipvp, IPVP_ACTIVITY);
362     } else {
363         /* edge-sensitive irq */
364         if (level)
365             src->pending = 1;
366     }
367     openpic_update_irq(opp, n_IRQ);
368 }
369
370 static void openpic_reset (void *opaque)
371 {
372     openpic_t *opp = (openpic_t *)opaque;
373     int i;
374
375     opp->glbc = 0x80000000;
376     /* Initialise controller registers */
377     opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
378     opp->veni = VENI;
379     opp->pint = 0x00000000;
380     opp->spve = 0x000000FF;
381     opp->tifr = 0x003F7A00;
382     /* ? */
383     opp->micr = 0x00000000;
384     /* Initialise IRQ sources */
385     for (i = 0; i < MAX_IRQ; i++) {
386         opp->src[i].ipvp = 0xA0000000;
387         opp->src[i].ide  = 0x00000000;
388     }
389     /* Initialise IRQ destinations */
390     for (i = 0; i < MAX_CPU; i++) {
391         opp->dst[i].pctp      = 0x0000000F;
392         opp->dst[i].pcsr      = 0x00000000;
393         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
394         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
395     }
396     /* Initialise timers */
397     for (i = 0; i < MAX_TMR; i++) {
398         opp->timers[i].ticc = 0x00000000;
399         opp->timers[i].tibc = 0x80000000;
400     }
401     /* Initialise doorbells */
402 #if MAX_DBL > 0
403     opp->dar = 0x00000000;
404     for (i = 0; i < MAX_DBL; i++) {
405         opp->doorbells[i].dmr  = 0x00000000;
406     }
407 #endif
408     /* Initialise mailboxes */
409 #if MAX_MBX > 0
410     for (i = 0; i < MAX_MBX; i++) { /* ? */
411         opp->mailboxes[i].mbr   = 0x00000000;
412     }
413 #endif
414     /* Go out of RESET state */
415     opp->glbc = 0x00000000;
416 }
417
418 static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
419 {
420     uint32_t retval;
421
422     switch (reg) {
423     case IRQ_IPVP:
424         retval = opp->src[n_IRQ].ipvp;
425         break;
426     case IRQ_IDE:
427         retval = opp->src[n_IRQ].ide;
428         break;
429     }
430
431     return retval;
432 }
433
434 static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
435                                  uint32_t reg, uint32_t val)
436 {
437     uint32_t tmp;
438
439     switch (reg) {
440     case IRQ_IPVP:
441         /* NOTE: not fully accurate for special IRQs, but simple and
442            sufficient */
443         /* ACTIVITY bit is read-only */
444         opp->src[n_IRQ].ipvp =
445             (opp->src[n_IRQ].ipvp & 0x40000000) |
446             (val & 0x800F00FF);
447         openpic_update_irq(opp, n_IRQ);
448         DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
449                 n_IRQ, val, opp->src[n_IRQ].ipvp);
450         break;
451     case IRQ_IDE:
452         tmp = val & 0xC0000000;
453         tmp |= val & ((1 << MAX_CPU) - 1);
454         opp->src[n_IRQ].ide = tmp;
455         DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
456         break;
457     }
458 }
459
460 #if 0 // Code provision for Intel model
461 #if MAX_DBL > 0
462 static uint32_t read_doorbell_register (openpic_t *opp,
463                                         int n_dbl, uint32_t offset)
464 {
465     uint32_t retval;
466
467     switch (offset) {
468     case DBL_IPVP_OFFSET:
469         retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
470         break;
471     case DBL_IDE_OFFSET:
472         retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
473         break;
474     case DBL_DMR_OFFSET:
475         retval = opp->doorbells[n_dbl].dmr;
476         break;
477     }
478
479     return retval;
480 }
481
482 static void write_doorbell_register (penpic_t *opp, int n_dbl,
483                                      uint32_t offset, uint32_t value)
484 {
485     switch (offset) {
486     case DBL_IVPR_OFFSET:
487         write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
488         break;
489     case DBL_IDE_OFFSET:
490         write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
491         break;
492     case DBL_DMR_OFFSET:
493         opp->doorbells[n_dbl].dmr = value;
494         break;
495     }
496 }
497 #endif
498
499 #if MAX_MBX > 0
500 static uint32_t read_mailbox_register (openpic_t *opp,
501                                        int n_mbx, uint32_t offset)
502 {
503     uint32_t retval;
504
505     switch (offset) {
506     case MBX_MBR_OFFSET:
507         retval = opp->mailboxes[n_mbx].mbr;
508         break;
509     case MBX_IVPR_OFFSET:
510         retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
511         break;
512     case MBX_DMR_OFFSET:
513         retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
514         break;
515     }
516
517     return retval;
518 }
519
520 static void write_mailbox_register (openpic_t *opp, int n_mbx,
521                                     uint32_t address, uint32_t value)
522 {
523     switch (offset) {
524     case MBX_MBR_OFFSET:
525         opp->mailboxes[n_mbx].mbr = value;
526         break;
527     case MBX_IVPR_OFFSET:
528         write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
529         break;
530     case MBX_DMR_OFFSET:
531         write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
532         break;
533     }
534 }
535 #endif
536 #endif /* 0 : Code provision for Intel model */
537
538 static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
539 {
540     openpic_t *opp = opaque;
541     IRQ_dst_t *dst;
542     int idx;
543
544     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
545     if (addr & 0xF)
546         return;
547 #if defined OPENPIC_SWAP
548     val = bswap32(val);
549 #endif
550     addr &= 0xFF;
551     switch (addr) {
552     case 0x00: /* FREP */
553         break;
554     case 0x20: /* GLBC */
555         if (val & 0x80000000)
556             openpic_reset(opp);
557         opp->glbc = val & ~0x80000000;
558         break;
559     case 0x80: /* VENI */
560         break;
561     case 0x90: /* PINT */
562         for (idx = 0; idx < opp->nb_cpus; idx++) {
563             if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
564                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
565                 dst = &opp->dst[idx];
566                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
567             } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
568                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
569                 dst = &opp->dst[idx];
570                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
571             }
572         }
573         opp->pint = val;
574         break;
575 #if MAX_IPI > 0
576     case 0xA0: /* IPI_IPVP */
577     case 0xB0:
578     case 0xC0:
579     case 0xD0:
580         {
581             int idx;
582             idx = (addr - 0xA0) >> 4;
583             write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
584         }
585         break;
586 #endif
587     case 0xE0: /* SPVE */
588         opp->spve = val & 0x000000FF;
589         break;
590     case 0xF0: /* TIFR */
591         opp->tifr = val;
592         break;
593     default:
594         break;
595     }
596 }
597
598 static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
599 {
600     openpic_t *opp = opaque;
601     uint32_t retval;
602
603     DPRINTF("%s: addr %08x\n", __func__, addr);
604     retval = 0xFFFFFFFF;
605     if (addr & 0xF)
606         return retval;
607     addr &= 0xFF;
608     switch (addr) {
609     case 0x00: /* FREP */
610         retval = opp->frep;
611         break;
612     case 0x20: /* GLBC */
613         retval = opp->glbc;
614         break;
615     case 0x80: /* VENI */
616         retval = opp->veni;
617         break;
618     case 0x90: /* PINT */
619         retval = 0x00000000;
620         break;
621 #if MAX_IPI > 0
622     case 0xA0: /* IPI_IPVP */
623     case 0xB0:
624     case 0xC0:
625     case 0xD0:
626         {
627             int idx;
628             idx = (addr - 0xA0) >> 4;
629             retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
630         }
631         break;
632 #endif
633     case 0xE0: /* SPVE */
634         retval = opp->spve;
635         break;
636     case 0xF0: /* TIFR */
637         retval = opp->tifr;
638         break;
639     default:
640         break;
641     }
642     DPRINTF("%s: => %08x\n", __func__, retval);
643 #if defined OPENPIC_SWAP
644     retval = bswap32(retval);
645 #endif
646
647     return retval;
648 }
649
650 static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
651 {
652     openpic_t *opp = opaque;
653     int idx;
654
655     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
656     if (addr & 0xF)
657         return;
658 #if defined OPENPIC_SWAP
659     val = bswap32(val);
660 #endif
661     addr -= 0x1100;
662     addr &= 0xFFFF;
663     idx = (addr & 0xFFF0) >> 6;
664     addr = addr & 0x30;
665     switch (addr) {
666     case 0x00: /* TICC */
667         break;
668     case 0x10: /* TIBC */
669         if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
670             (val & 0x80000000) == 0 &&
671             (opp->timers[idx].tibc & 0x80000000) != 0)
672             opp->timers[idx].ticc &= ~0x80000000;
673         opp->timers[idx].tibc = val;
674         break;
675     case 0x20: /* TIVP */
676         write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
677         break;
678     case 0x30: /* TIDE */
679         write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
680         break;
681     }
682 }
683
684 static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
685 {
686     openpic_t *opp = opaque;
687     uint32_t retval;
688     int idx;
689
690     DPRINTF("%s: addr %08x\n", __func__, addr);
691     retval = 0xFFFFFFFF;
692     if (addr & 0xF)
693         return retval;
694     addr -= 0x1100;
695     addr &= 0xFFFF;
696     idx = (addr & 0xFFF0) >> 6;
697     addr = addr & 0x30;
698     switch (addr) {
699     case 0x00: /* TICC */
700         retval = opp->timers[idx].ticc;
701         break;
702     case 0x10: /* TIBC */
703         retval = opp->timers[idx].tibc;
704         break;
705     case 0x20: /* TIPV */
706         retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
707         break;
708     case 0x30: /* TIDE */
709         retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
710         break;
711     }
712     DPRINTF("%s: => %08x\n", __func__, retval);
713 #if defined OPENPIC_SWAP
714     retval = bswap32(retval);
715 #endif
716
717     return retval;
718 }
719
720 static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
721 {
722     openpic_t *opp = opaque;
723     int idx;
724
725     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
726     if (addr & 0xF)
727         return;
728 #if defined OPENPIC_SWAP
729     val = tswap32(val);
730 #endif
731     addr = addr & 0xFFF0;
732     idx = addr >> 5;
733     if (addr & 0x10) {
734         /* EXDE / IFEDE / IEEDE */
735         write_IRQreg(opp, idx, IRQ_IDE, val);
736     } else {
737         /* EXVP / IFEVP / IEEVP */
738         write_IRQreg(opp, idx, IRQ_IPVP, val);
739     }
740 }
741
742 static uint32_t openpic_src_read (void *opaque, uint32_t addr)
743 {
744     openpic_t *opp = opaque;
745     uint32_t retval;
746     int idx;
747
748     DPRINTF("%s: addr %08x\n", __func__, addr);
749     retval = 0xFFFFFFFF;
750     if (addr & 0xF)
751         return retval;
752     addr = addr & 0xFFF0;
753     idx = addr >> 5;
754     if (addr & 0x10) {
755         /* EXDE / IFEDE / IEEDE */
756         retval = read_IRQreg(opp, idx, IRQ_IDE);
757     } else {
758         /* EXVP / IFEVP / IEEVP */
759         retval = read_IRQreg(opp, idx, IRQ_IPVP);
760     }
761     DPRINTF("%s: => %08x\n", __func__, retval);
762 #if defined OPENPIC_SWAP
763     retval = tswap32(retval);
764 #endif
765
766     return retval;
767 }
768
769 static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
770 {
771     openpic_t *opp = opaque;
772     IRQ_src_t *src;
773     IRQ_dst_t *dst;
774     int idx, s_IRQ, n_IRQ;
775
776     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
777     if (addr & 0xF)
778         return;
779 #if defined OPENPIC_SWAP
780     val = bswap32(val);
781 #endif
782     addr &= 0x1FFF0;
783     idx = addr / 0x1000;
784     dst = &opp->dst[idx];
785     addr &= 0xFF0;
786     switch (addr) {
787 #if MAX_IPI > 0
788     case 0x40: /* PIPD */
789     case 0x50:
790     case 0x60:
791     case 0x70:
792         idx = (addr - 0x40) >> 4;
793         write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
794         openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
795         openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
796         break;
797 #endif
798     case 0x80: /* PCTP */
799         dst->pctp = val & 0x0000000F;
800         break;
801     case 0x90: /* WHOAMI */
802         /* Read-only register */
803         break;
804     case 0xA0: /* PIAC */
805         /* Read-only register */
806         break;
807     case 0xB0: /* PEOI */
808         DPRINTF("PEOI\n");
809         s_IRQ = IRQ_get_next(opp, &dst->servicing);
810         IRQ_resetbit(&dst->servicing, s_IRQ);
811         dst->servicing.next = -1;
812         /* Set up next servicing IRQ */
813         s_IRQ = IRQ_get_next(opp, &dst->servicing);
814         /* Check queued interrupts. */
815         n_IRQ = IRQ_get_next(opp, &dst->raised);
816         src = &opp->src[n_IRQ];
817         if (n_IRQ != -1 &&
818             (s_IRQ == -1 ||
819              IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
820             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
821                     idx, n_IRQ);
822             qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
823         }
824         break;
825     default:
826         break;
827     }
828 }
829
830 static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
831 {
832     openpic_t *opp = opaque;
833     IRQ_src_t *src;
834     IRQ_dst_t *dst;
835     uint32_t retval;
836     int idx, n_IRQ;
837
838     DPRINTF("%s: addr %08x\n", __func__, addr);
839     retval = 0xFFFFFFFF;
840     if (addr & 0xF)
841         return retval;
842     addr &= 0x1FFF0;
843     idx = addr / 0x1000;
844     dst = &opp->dst[idx];
845     addr &= 0xFF0;
846     switch (addr) {
847     case 0x80: /* PCTP */
848         retval = dst->pctp;
849         break;
850     case 0x90: /* WHOAMI */
851         retval = idx;
852         break;
853     case 0xA0: /* PIAC */
854         DPRINTF("Lower OpenPIC INT output\n");
855         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
856         n_IRQ = IRQ_get_next(opp, &dst->raised);
857         DPRINTF("PIAC: irq=%d\n", n_IRQ);
858         if (n_IRQ == -1) {
859             /* No more interrupt pending */
860             retval = IPVP_VECTOR(opp->spve);
861         } else {
862             src = &opp->src[n_IRQ];
863             if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
864                 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
865                 /* - Spurious level-sensitive IRQ
866                  * - Priorities has been changed
867                  *   and the pending IRQ isn't allowed anymore
868                  */
869                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
870                 retval = IPVP_VECTOR(opp->spve);
871             } else {
872                 /* IRQ enter servicing state */
873                 IRQ_setbit(&dst->servicing, n_IRQ);
874                 retval = IPVP_VECTOR(src->ipvp);
875             }
876             IRQ_resetbit(&dst->raised, n_IRQ);
877             dst->raised.next = -1;
878             if (!test_bit(&src->ipvp, IPVP_SENSE)) {
879                 /* edge-sensitive IRQ */
880                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
881                 src->pending = 0;
882             }
883         }
884         break;
885     case 0xB0: /* PEOI */
886         retval = 0;
887         break;
888 #if MAX_IPI > 0
889     case 0x40: /* IDE */
890     case 0x50:
891         idx = (addr - 0x40) >> 4;
892         retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
893         break;
894 #endif
895     default:
896         break;
897     }
898     DPRINTF("%s: => %08x\n", __func__, retval);
899 #if defined OPENPIC_SWAP
900     retval= bswap32(retval);
901 #endif
902
903     return retval;
904 }
905
906 static void openpic_buggy_write (void *opaque,
907                                  target_phys_addr_t addr, uint32_t val)
908 {
909     printf("Invalid OPENPIC write access !\n");
910 }
911
912 static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
913 {
914     printf("Invalid OPENPIC read access !\n");
915
916     return -1;
917 }
918
919 static void openpic_writel (void *opaque,
920                             target_phys_addr_t addr, uint32_t val)
921 {
922     openpic_t *opp = opaque;
923
924     addr &= 0x3FFFF;
925     DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
926     if (addr < 0x1100) {
927         /* Global registers */
928         openpic_gbl_write(opp, addr, val);
929     } else if (addr < 0x10000) {
930         /* Timers registers */
931         openpic_timer_write(opp, addr, val);
932     } else if (addr < 0x20000) {
933         /* Source registers */
934         openpic_src_write(opp, addr, val);
935     } else {
936         /* CPU registers */
937         openpic_cpu_write(opp, addr, val);
938     }
939 }
940
941 static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
942 {
943     openpic_t *opp = opaque;
944     uint32_t retval;
945
946     addr &= 0x3FFFF;
947     DPRINTF("%s: offset %08x\n", __func__, (int)addr);
948     if (addr < 0x1100) {
949         /* Global registers */
950         retval = openpic_gbl_read(opp, addr);
951     } else if (addr < 0x10000) {
952         /* Timers registers */
953         retval = openpic_timer_read(opp, addr);
954     } else if (addr < 0x20000) {
955         /* Source registers */
956         retval = openpic_src_read(opp, addr);
957     } else {
958         /* CPU registers */
959         retval = openpic_cpu_read(opp, addr);
960     }
961
962     return retval;
963 }
964
965 static CPUWriteMemoryFunc *openpic_write[] = {
966     &openpic_buggy_write,
967     &openpic_buggy_write,
968     &openpic_writel,
969 };
970
971 static CPUReadMemoryFunc *openpic_read[] = {
972     &openpic_buggy_read,
973     &openpic_buggy_read,
974     &openpic_readl,
975 };
976
977 static void openpic_map(PCIDevice *pci_dev, int region_num,
978                         uint32_t addr, uint32_t size, int type)
979 {
980     openpic_t *opp;
981
982     DPRINTF("Map OpenPIC\n");
983     opp = (openpic_t *)pci_dev;
984     /* Global registers */
985     DPRINTF("Register OPENPIC gbl   %08x => %08x\n",
986             addr + 0x1000, addr + 0x1000 + 0x100);
987     /* Timer registers */
988     DPRINTF("Register OPENPIC timer %08x => %08x\n",
989             addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
990     /* Interrupt source registers */
991     DPRINTF("Register OPENPIC src   %08x => %08x\n",
992             addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
993     /* Per CPU registers */
994     DPRINTF("Register OPENPIC dst   %08x => %08x\n",
995             addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
996     cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
997 #if 0 // Don't implement ISU for now
998     opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
999                                            openpic_src_write);
1000     cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
1001                                  opp_io_memory);
1002 #endif
1003 }
1004
1005 static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1006 {
1007     unsigned int i;
1008
1009     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1010         qemu_put_be32s(f, &q->queue[i]);
1011
1012     qemu_put_sbe32s(f, &q->next);
1013     qemu_put_sbe32s(f, &q->priority);
1014 }
1015
1016 static void openpic_save(QEMUFile* f, void *opaque)
1017 {
1018     openpic_t *opp = (openpic_t *)opaque;
1019     unsigned int i;
1020
1021     qemu_put_be32s(f, &opp->frep);
1022     qemu_put_be32s(f, &opp->glbc);
1023     qemu_put_be32s(f, &opp->micr);
1024     qemu_put_be32s(f, &opp->veni);
1025     qemu_put_be32s(f, &opp->pint);
1026     qemu_put_be32s(f, &opp->spve);
1027     qemu_put_be32s(f, &opp->tifr);
1028
1029     for (i = 0; i < MAX_IRQ; i++) {
1030         qemu_put_be32s(f, &opp->src[i].ipvp);
1031         qemu_put_be32s(f, &opp->src[i].ide);
1032         qemu_put_sbe32s(f, &opp->src[i].type);
1033         qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1034         qemu_put_sbe32s(f, &opp->src[i].pending);
1035     }
1036
1037     for (i = 0; i < MAX_IRQ; i++) {
1038         qemu_put_be32s(f, &opp->dst[i].pctp);
1039         qemu_put_be32s(f, &opp->dst[i].pcsr);
1040         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1041         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1042     }
1043
1044     qemu_put_sbe32s(f, &opp->nb_cpus);
1045
1046     for (i = 0; i < MAX_TMR; i++) {
1047         qemu_put_be32s(f, &opp->timers[i].ticc);
1048         qemu_put_be32s(f, &opp->timers[i].tibc);
1049     }
1050
1051 #if MAX_DBL > 0
1052     qemu_put_be32s(f, &opp->dar);
1053
1054     for (i = 0; i < MAX_DBL; i++) {
1055         qemu_put_be32s(f, &opp->doorbells[i].dmr);
1056     }
1057 #endif
1058
1059 #if MAX_MBX > 0
1060     for (i = 0; i < MAX_MAILBOXES; i++) {
1061         qemu_put_be32s(f, &opp->mailboxes[i].mbr);
1062     }
1063 #endif
1064
1065     pci_device_save(&opp->pci_dev, f);
1066 }
1067
1068 static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1069 {
1070     unsigned int i;
1071
1072     for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1073         qemu_get_be32s(f, &q->queue[i]);
1074
1075     qemu_get_sbe32s(f, &q->next);
1076     qemu_get_sbe32s(f, &q->priority);
1077 }
1078
1079 static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1080 {
1081     openpic_t *opp = (openpic_t *)opaque;
1082     unsigned int i;
1083
1084     if (version_id != 1)
1085         return -EINVAL;
1086
1087     qemu_get_be32s(f, &opp->frep);
1088     qemu_get_be32s(f, &opp->glbc);
1089     qemu_get_be32s(f, &opp->micr);
1090     qemu_get_be32s(f, &opp->veni);
1091     qemu_get_be32s(f, &opp->pint);
1092     qemu_get_be32s(f, &opp->spve);
1093     qemu_get_be32s(f, &opp->tifr);
1094
1095     for (i = 0; i < MAX_IRQ; i++) {
1096         qemu_get_be32s(f, &opp->src[i].ipvp);
1097         qemu_get_be32s(f, &opp->src[i].ide);
1098         qemu_get_sbe32s(f, &opp->src[i].type);
1099         qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1100         qemu_get_sbe32s(f, &opp->src[i].pending);
1101     }
1102
1103     for (i = 0; i < MAX_IRQ; i++) {
1104         qemu_get_be32s(f, &opp->dst[i].pctp);
1105         qemu_get_be32s(f, &opp->dst[i].pcsr);
1106         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1107         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1108     }
1109
1110     qemu_get_sbe32s(f, &opp->nb_cpus);
1111
1112     for (i = 0; i < MAX_TMR; i++) {
1113         qemu_get_be32s(f, &opp->timers[i].ticc);
1114         qemu_get_be32s(f, &opp->timers[i].tibc);
1115     }
1116
1117 #if MAX_DBL > 0
1118     qemu_get_be32s(f, &opp->dar);
1119
1120     for (i = 0; i < MAX_DBL; i++) {
1121         qemu_get_be32s(f, &opp->doorbells[i].dmr);
1122     }
1123 #endif
1124
1125 #if MAX_MBX > 0
1126     for (i = 0; i < MAX_MAILBOXES; i++) {
1127         qemu_get_be32s(f, &opp->mailboxes[i].mbr);
1128     }
1129 #endif
1130
1131     return pci_device_load(&opp->pci_dev, f);
1132 }
1133
1134 qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
1135                         qemu_irq **irqs, qemu_irq irq_out)
1136 {
1137     openpic_t *opp;
1138     uint8_t *pci_conf;
1139     int i, m;
1140
1141     /* XXX: for now, only one CPU is supported */
1142     if (nb_cpus != 1)
1143         return NULL;
1144     if (bus) {
1145         opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
1146                                                -1, NULL, NULL);
1147         if (opp == NULL)
1148             return NULL;
1149         pci_conf = opp->pci_dev.config;
1150         pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
1151         pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
1152         pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
1153         pci_conf[0x0e] = 0x00; // header_type
1154         pci_conf[0x3d] = 0x00; // no interrupt pin
1155
1156         /* Register I/O spaces */
1157         pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
1158                                PCI_ADDRESS_SPACE_MEM, &openpic_map);
1159     } else {
1160         opp = qemu_mallocz(sizeof(openpic_t));
1161     }
1162     opp->mem_index = cpu_register_io_memory(0, openpic_read,
1163                                             openpic_write, opp);
1164
1165     //    isu_base &= 0xFFFC0000;
1166     opp->nb_cpus = nb_cpus;
1167     /* Set IRQ types */
1168     for (i = 0; i < EXT_IRQ; i++) {
1169         opp->src[i].type = IRQ_EXTERNAL;
1170     }
1171     for (; i < IRQ_TIM0; i++) {
1172         opp->src[i].type = IRQ_SPECIAL;
1173     }
1174 #if MAX_IPI > 0
1175     m = IRQ_IPI0;
1176 #else
1177     m = IRQ_DBL0;
1178 #endif
1179     for (; i < m; i++) {
1180         opp->src[i].type = IRQ_TIMER;
1181     }
1182     for (; i < MAX_IRQ; i++) {
1183         opp->src[i].type = IRQ_INTERNAL;
1184     }
1185     for (i = 0; i < nb_cpus; i++)
1186         opp->dst[i].irqs = irqs[i];
1187     opp->irq_out = irq_out;
1188
1189     register_savevm("openpic", 0, 1, openpic_save, openpic_load, opp);
1190     qemu_register_reset(openpic_reset, opp);
1191     openpic_reset(opp);
1192     if (pmem_index)
1193         *pmem_index = opp->mem_index;
1194
1195     return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
1196 }