powerpc/kvm: fix a openpic bug (Liu Yu)
[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 compagnion chip developper'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 (openpic_t *opp)
371 {
372     int i;
373
374     opp->glbc = 0x80000000;
375     /* Initialise controller registers */
376     opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
377     opp->veni = VENI;
378     opp->pint = 0x00000000;
379     opp->spve = 0x000000FF;
380     opp->tifr = 0x003F7A00;
381     /* ? */
382     opp->micr = 0x00000000;
383     /* Initialise IRQ sources */
384     for (i = 0; i < MAX_IRQ; i++) {
385         opp->src[i].ipvp = 0xA0000000;
386         opp->src[i].ide  = 0x00000000;
387     }
388     /* Initialise IRQ destinations */
389     for (i = 0; i < MAX_CPU; i++) {
390         opp->dst[i].pctp      = 0x0000000F;
391         opp->dst[i].pcsr      = 0x00000000;
392         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
393         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
394     }
395     /* Initialise timers */
396     for (i = 0; i < MAX_TMR; i++) {
397         opp->timers[i].ticc = 0x00000000;
398         opp->timers[i].tibc = 0x80000000;
399     }
400     /* Initialise doorbells */
401 #if MAX_DBL > 0
402     opp->dar = 0x00000000;
403     for (i = 0; i < MAX_DBL; i++) {
404         opp->doorbells[i].dmr  = 0x00000000;
405     }
406 #endif
407     /* Initialise mailboxes */
408 #if MAX_MBX > 0
409     for (i = 0; i < MAX_MBX; i++) { /* ? */
410         opp->mailboxes[i].mbr   = 0x00000000;
411     }
412 #endif
413     /* Go out of RESET state */
414     opp->glbc = 0x00000000;
415 }
416
417 static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
418 {
419     uint32_t retval;
420
421     switch (reg) {
422     case IRQ_IPVP:
423         retval = opp->src[n_IRQ].ipvp;
424         break;
425     case IRQ_IDE:
426         retval = opp->src[n_IRQ].ide;
427         break;
428     }
429
430     return retval;
431 }
432
433 static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
434                                  uint32_t reg, uint32_t val)
435 {
436     uint32_t tmp;
437
438     switch (reg) {
439     case IRQ_IPVP:
440         /* NOTE: not fully accurate for special IRQs, but simple and
441            sufficient */
442         /* ACTIVITY bit is read-only */
443         opp->src[n_IRQ].ipvp =
444             (opp->src[n_IRQ].ipvp & 0x40000000) |
445             (val & 0x800F00FF);
446         openpic_update_irq(opp, n_IRQ);
447         DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
448                 n_IRQ, val, opp->src[n_IRQ].ipvp);
449         break;
450     case IRQ_IDE:
451         tmp = val & 0xC0000000;
452         tmp |= val & ((1 << MAX_CPU) - 1);
453         opp->src[n_IRQ].ide = tmp;
454         DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
455         break;
456     }
457 }
458
459 #if 0 // Code provision for Intel model
460 #if MAX_DBL > 0
461 static uint32_t read_doorbell_register (openpic_t *opp,
462                                         int n_dbl, uint32_t offset)
463 {
464     uint32_t retval;
465
466     switch (offset) {
467     case DBL_IPVP_OFFSET:
468         retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
469         break;
470     case DBL_IDE_OFFSET:
471         retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
472         break;
473     case DBL_DMR_OFFSET:
474         retval = opp->doorbells[n_dbl].dmr;
475         break;
476     }
477
478     return retval;
479 }
480
481 static void write_doorbell_register (penpic_t *opp, int n_dbl,
482                                      uint32_t offset, uint32_t value)
483 {
484     switch (offset) {
485     case DBL_IVPR_OFFSET:
486         write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
487         break;
488     case DBL_IDE_OFFSET:
489         write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
490         break;
491     case DBL_DMR_OFFSET:
492         opp->doorbells[n_dbl].dmr = value;
493         break;
494     }
495 }
496 #endif
497
498 #if MAX_MBX > 0
499 static uint32_t read_mailbox_register (openpic_t *opp,
500                                        int n_mbx, uint32_t offset)
501 {
502     uint32_t retval;
503
504     switch (offset) {
505     case MBX_MBR_OFFSET:
506         retval = opp->mailboxes[n_mbx].mbr;
507         break;
508     case MBX_IVPR_OFFSET:
509         retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
510         break;
511     case MBX_DMR_OFFSET:
512         retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
513         break;
514     }
515
516     return retval;
517 }
518
519 static void write_mailbox_register (openpic_t *opp, int n_mbx,
520                                     uint32_t address, uint32_t value)
521 {
522     switch (offset) {
523     case MBX_MBR_OFFSET:
524         opp->mailboxes[n_mbx].mbr = value;
525         break;
526     case MBX_IVPR_OFFSET:
527         write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
528         break;
529     case MBX_DMR_OFFSET:
530         write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
531         break;
532     }
533 }
534 #endif
535 #endif /* 0 : Code provision for Intel model */
536
537 static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
538 {
539     openpic_t *opp = opaque;
540     IRQ_dst_t *dst;
541     int idx;
542
543     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
544     if (addr & 0xF)
545         return;
546 #if defined OPENPIC_SWAP
547     val = bswap32(val);
548 #endif
549     addr &= 0xFF;
550     switch (addr) {
551     case 0x00: /* FREP */
552         break;
553     case 0x20: /* GLBC */
554         if (val & 0x80000000)
555             openpic_reset(opp);
556         opp->glbc = val & ~0x80000000;
557         break;
558     case 0x80: /* VENI */
559         break;
560     case 0x90: /* PINT */
561         for (idx = 0; idx < opp->nb_cpus; idx++) {
562             if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
563                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
564                 dst = &opp->dst[idx];
565                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
566             } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
567                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
568                 dst = &opp->dst[idx];
569                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
570             }
571         }
572         opp->pint = val;
573         break;
574 #if MAX_IPI > 0
575     case 0xA0: /* IPI_IPVP */
576     case 0xB0:
577     case 0xC0:
578     case 0xD0:
579         {
580             int idx;
581             idx = (addr - 0xA0) >> 4;
582             write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
583         }
584         break;
585 #endif
586     case 0xE0: /* SPVE */
587         opp->spve = val & 0x000000FF;
588         break;
589     case 0xF0: /* TIFR */
590         opp->tifr = val;
591         break;
592     default:
593         break;
594     }
595 }
596
597 static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
598 {
599     openpic_t *opp = opaque;
600     uint32_t retval;
601
602     DPRINTF("%s: addr %08x\n", __func__, addr);
603     retval = 0xFFFFFFFF;
604     if (addr & 0xF)
605         return retval;
606     addr &= 0xFF;
607     switch (addr) {
608     case 0x00: /* FREP */
609         retval = opp->frep;
610         break;
611     case 0x20: /* GLBC */
612         retval = opp->glbc;
613         break;
614     case 0x80: /* VENI */
615         retval = opp->veni;
616         break;
617     case 0x90: /* PINT */
618         retval = 0x00000000;
619         break;
620 #if MAX_IPI > 0
621     case 0xA0: /* IPI_IPVP */
622     case 0xB0:
623     case 0xC0:
624     case 0xD0:
625         {
626             int idx;
627             idx = (addr - 0xA0) >> 4;
628             retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
629         }
630         break;
631 #endif
632     case 0xE0: /* SPVE */
633         retval = opp->spve;
634         break;
635     case 0xF0: /* TIFR */
636         retval = opp->tifr;
637         break;
638     default:
639         break;
640     }
641     DPRINTF("%s: => %08x\n", __func__, retval);
642 #if defined OPENPIC_SWAP
643     retval = bswap32(retval);
644 #endif
645
646     return retval;
647 }
648
649 static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
650 {
651     openpic_t *opp = opaque;
652     int idx;
653
654     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
655     if (addr & 0xF)
656         return;
657 #if defined OPENPIC_SWAP
658     val = bswap32(val);
659 #endif
660     addr -= 0x1100;
661     addr &= 0xFFFF;
662     idx = (addr & 0xFFF0) >> 6;
663     addr = addr & 0x30;
664     switch (addr) {
665     case 0x00: /* TICC */
666         break;
667     case 0x10: /* TIBC */
668         if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
669             (val & 0x80000000) == 0 &&
670             (opp->timers[idx].tibc & 0x80000000) != 0)
671             opp->timers[idx].ticc &= ~0x80000000;
672         opp->timers[idx].tibc = val;
673         break;
674     case 0x20: /* TIVP */
675         write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
676         break;
677     case 0x30: /* TIDE */
678         write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
679         break;
680     }
681 }
682
683 static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
684 {
685     openpic_t *opp = opaque;
686     uint32_t retval;
687     int idx;
688
689     DPRINTF("%s: addr %08x\n", __func__, addr);
690     retval = 0xFFFFFFFF;
691     if (addr & 0xF)
692         return retval;
693     addr -= 0x1100;
694     addr &= 0xFFFF;
695     idx = (addr & 0xFFF0) >> 6;
696     addr = addr & 0x30;
697     switch (addr) {
698     case 0x00: /* TICC */
699         retval = opp->timers[idx].ticc;
700         break;
701     case 0x10: /* TIBC */
702         retval = opp->timers[idx].tibc;
703         break;
704     case 0x20: /* TIPV */
705         retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
706         break;
707     case 0x30: /* TIDE */
708         retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
709         break;
710     }
711     DPRINTF("%s: => %08x\n", __func__, retval);
712 #if defined OPENPIC_SWAP
713     retval = bswap32(retval);
714 #endif
715
716     return retval;
717 }
718
719 static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
720 {
721     openpic_t *opp = opaque;
722     int idx;
723
724     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
725     if (addr & 0xF)
726         return;
727 #if defined OPENPIC_SWAP
728     val = tswap32(val);
729 #endif
730     addr = addr & 0xFFF0;
731     idx = addr >> 5;
732     if (addr & 0x10) {
733         /* EXDE / IFEDE / IEEDE */
734         write_IRQreg(opp, idx, IRQ_IDE, val);
735     } else {
736         /* EXVP / IFEVP / IEEVP */
737         write_IRQreg(opp, idx, IRQ_IPVP, val);
738     }
739 }
740
741 static uint32_t openpic_src_read (void *opaque, uint32_t addr)
742 {
743     openpic_t *opp = opaque;
744     uint32_t retval;
745     int idx;
746
747     DPRINTF("%s: addr %08x\n", __func__, addr);
748     retval = 0xFFFFFFFF;
749     if (addr & 0xF)
750         return retval;
751     addr = addr & 0xFFF0;
752     idx = addr >> 5;
753     if (addr & 0x10) {
754         /* EXDE / IFEDE / IEEDE */
755         retval = read_IRQreg(opp, idx, IRQ_IDE);
756     } else {
757         /* EXVP / IFEVP / IEEVP */
758         retval = read_IRQreg(opp, idx, IRQ_IPVP);
759     }
760     DPRINTF("%s: => %08x\n", __func__, retval);
761 #if defined OPENPIC_SWAP
762     retval = tswap32(retval);
763 #endif
764
765     return retval;
766 }
767
768 static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
769 {
770     openpic_t *opp = opaque;
771     IRQ_src_t *src;
772     IRQ_dst_t *dst;
773     int idx, s_IRQ, n_IRQ;
774
775     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
776     if (addr & 0xF)
777         return;
778 #if defined OPENPIC_SWAP
779     val = bswap32(val);
780 #endif
781     addr &= 0x1FFF0;
782     idx = addr / 0x1000;
783     dst = &opp->dst[idx];
784     addr &= 0xFF0;
785     switch (addr) {
786 #if MAX_IPI > 0
787     case 0x40: /* PIPD */
788     case 0x50:
789     case 0x60:
790     case 0x70:
791         idx = (addr - 0x40) >> 4;
792         write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
793         openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
794         openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
795         break;
796 #endif
797     case 0x80: /* PCTP */
798         dst->pctp = val & 0x0000000F;
799         break;
800     case 0x90: /* WHOAMI */
801         /* Read-only register */
802         break;
803     case 0xA0: /* PIAC */
804         /* Read-only register */
805         break;
806     case 0xB0: /* PEOI */
807         DPRINTF("PEOI\n");
808         s_IRQ = IRQ_get_next(opp, &dst->servicing);
809         IRQ_resetbit(&dst->servicing, s_IRQ);
810         dst->servicing.next = -1;
811         /* Set up next servicing IRQ */
812         s_IRQ = IRQ_get_next(opp, &dst->servicing);
813         /* Check queued interrupts. */
814         n_IRQ = IRQ_get_next(opp, &dst->raised);
815         src = &opp->src[n_IRQ];
816         if (n_IRQ != -1 &&
817             (s_IRQ == -1 ||
818              IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
819             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
820                     idx, n_IRQ);
821             qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
822         }
823         break;
824     default:
825         break;
826     }
827 }
828
829 static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
830 {
831     openpic_t *opp = opaque;
832     IRQ_src_t *src;
833     IRQ_dst_t *dst;
834     uint32_t retval;
835     int idx, n_IRQ;
836
837     DPRINTF("%s: addr %08x\n", __func__, addr);
838     retval = 0xFFFFFFFF;
839     if (addr & 0xF)
840         return retval;
841     addr &= 0x1FFF0;
842     idx = addr / 0x1000;
843     dst = &opp->dst[idx];
844     addr &= 0xFF0;
845     switch (addr) {
846     case 0x80: /* PCTP */
847         retval = dst->pctp;
848         break;
849     case 0x90: /* WHOAMI */
850         retval = idx;
851         break;
852     case 0xA0: /* PIAC */
853         DPRINTF("Lower OpenPIC INT output\n");
854         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
855         n_IRQ = IRQ_get_next(opp, &dst->raised);
856         DPRINTF("PIAC: irq=%d\n", n_IRQ);
857         if (n_IRQ == -1) {
858             /* No more interrupt pending */
859             retval = IPVP_VECTOR(opp->spve);
860         } else {
861             src = &opp->src[n_IRQ];
862             if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
863                 !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
864                 /* - Spurious level-sensitive IRQ
865                  * - Priorities has been changed
866                  *   and the pending IRQ isn't allowed anymore
867                  */
868                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
869                 retval = IPVP_VECTOR(opp->spve);
870             } else {
871                 /* IRQ enter servicing state */
872                 IRQ_setbit(&dst->servicing, n_IRQ);
873                 retval = IPVP_VECTOR(src->ipvp);
874             }
875             IRQ_resetbit(&dst->raised, n_IRQ);
876             dst->raised.next = -1;
877             if (!test_bit(&src->ipvp, IPVP_SENSE)) {
878                 /* edge-sensitive IRQ */
879                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
880                 src->pending = 0;
881             }
882         }
883         break;
884     case 0xB0: /* PEOI */
885         retval = 0;
886         break;
887 #if MAX_IPI > 0
888     case 0x40: /* IDE */
889     case 0x50:
890         idx = (addr - 0x40) >> 4;
891         retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
892         break;
893 #endif
894     default:
895         break;
896     }
897     DPRINTF("%s: => %08x\n", __func__, retval);
898 #if defined OPENPIC_SWAP
899     retval= bswap32(retval);
900 #endif
901
902     return retval;
903 }
904
905 static void openpic_buggy_write (void *opaque,
906                                  target_phys_addr_t addr, uint32_t val)
907 {
908     printf("Invalid OPENPIC write access !\n");
909 }
910
911 static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
912 {
913     printf("Invalid OPENPIC read access !\n");
914
915     return -1;
916 }
917
918 static void openpic_writel (void *opaque,
919                             target_phys_addr_t addr, uint32_t val)
920 {
921     openpic_t *opp = opaque;
922
923     addr &= 0x3FFFF;
924     DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
925     if (addr < 0x1100) {
926         /* Global registers */
927         openpic_gbl_write(opp, addr, val);
928     } else if (addr < 0x10000) {
929         /* Timers registers */
930         openpic_timer_write(opp, addr, val);
931     } else if (addr < 0x20000) {
932         /* Source registers */
933         openpic_src_write(opp, addr, val);
934     } else {
935         /* CPU registers */
936         openpic_cpu_write(opp, addr, val);
937     }
938 }
939
940 static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
941 {
942     openpic_t *opp = opaque;
943     uint32_t retval;
944
945     addr &= 0x3FFFF;
946     DPRINTF("%s: offset %08x\n", __func__, (int)addr);
947     if (addr < 0x1100) {
948         /* Global registers */
949         retval = openpic_gbl_read(opp, addr);
950     } else if (addr < 0x10000) {
951         /* Timers registers */
952         retval = openpic_timer_read(opp, addr);
953     } else if (addr < 0x20000) {
954         /* Source registers */
955         retval = openpic_src_read(opp, addr);
956     } else {
957         /* CPU registers */
958         retval = openpic_cpu_read(opp, addr);
959     }
960
961     return retval;
962 }
963
964 static CPUWriteMemoryFunc *openpic_write[] = {
965     &openpic_buggy_write,
966     &openpic_buggy_write,
967     &openpic_writel,
968 };
969
970 static CPUReadMemoryFunc *openpic_read[] = {
971     &openpic_buggy_read,
972     &openpic_buggy_read,
973     &openpic_readl,
974 };
975
976 static void openpic_map(PCIDevice *pci_dev, int region_num,
977                         uint32_t addr, uint32_t size, int type)
978 {
979     openpic_t *opp;
980
981     DPRINTF("Map OpenPIC\n");
982     opp = (openpic_t *)pci_dev;
983     /* Global registers */
984     DPRINTF("Register OPENPIC gbl   %08x => %08x\n",
985             addr + 0x1000, addr + 0x1000 + 0x100);
986     /* Timer registers */
987     DPRINTF("Register OPENPIC timer %08x => %08x\n",
988             addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
989     /* Interrupt source registers */
990     DPRINTF("Register OPENPIC src   %08x => %08x\n",
991             addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
992     /* Per CPU registers */
993     DPRINTF("Register OPENPIC dst   %08x => %08x\n",
994             addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
995     cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
996 #if 0 // Don't implement ISU for now
997     opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
998                                            openpic_src_write);
999     cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
1000                                  opp_io_memory);
1001 #endif
1002 }
1003
1004 qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
1005                         qemu_irq **irqs, qemu_irq irq_out)
1006 {
1007     openpic_t *opp;
1008     uint8_t *pci_conf;
1009     int i, m;
1010
1011     /* XXX: for now, only one CPU is supported */
1012     if (nb_cpus != 1)
1013         return NULL;
1014     if (bus) {
1015         opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
1016                                                -1, NULL, NULL);
1017         if (opp == NULL)
1018             return NULL;
1019         pci_conf = opp->pci_dev.config;
1020         pci_conf[0x00] = 0x14; // IBM MPIC2
1021         pci_conf[0x01] = 0x10;
1022         pci_conf[0x02] = 0xFF;
1023         pci_conf[0x03] = 0xFF;
1024         pci_conf[0x0a] = 0x80; // PIC
1025         pci_conf[0x0b] = 0x08;
1026         pci_conf[0x0e] = 0x00; // header_type
1027         pci_conf[0x3d] = 0x00; // no interrupt pin
1028
1029         /* Register I/O spaces */
1030         pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
1031                                PCI_ADDRESS_SPACE_MEM, &openpic_map);
1032     } else {
1033         opp = qemu_mallocz(sizeof(openpic_t));
1034     }
1035     opp->mem_index = cpu_register_io_memory(0, openpic_read,
1036                                             openpic_write, opp);
1037
1038     //    isu_base &= 0xFFFC0000;
1039     opp->nb_cpus = nb_cpus;
1040     /* Set IRQ types */
1041     for (i = 0; i < EXT_IRQ; i++) {
1042         opp->src[i].type = IRQ_EXTERNAL;
1043     }
1044     for (; i < IRQ_TIM0; i++) {
1045         opp->src[i].type = IRQ_SPECIAL;
1046     }
1047 #if MAX_IPI > 0
1048     m = IRQ_IPI0;
1049 #else
1050     m = IRQ_DBL0;
1051 #endif
1052     for (; i < m; i++) {
1053         opp->src[i].type = IRQ_TIMER;
1054     }
1055     for (; i < MAX_IRQ; i++) {
1056         opp->src[i].type = IRQ_INTERNAL;
1057     }
1058     for (i = 0; i < nb_cpus; i++)
1059         opp->dst[i].irqs = irqs[i];
1060     opp->irq_out = irq_out;
1061     openpic_reset(opp);
1062     if (pmem_index)
1063         *pmem_index = opp->mem_index;
1064
1065     return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
1066 }