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