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