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