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