|
|
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;
1.1.1.10! root 716: addr -= 0x10;
1.1 root 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;
1.1.1.10! root 749: addr -= 0x10;
1.1 root 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.10! root 1184: qemu_irq *openpic_init (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: int i, m;
1.1.1.3 root 1189:
1.1 root 1190: /* XXX: for now, only one CPU is supported */
1191: if (nb_cpus != 1)
1192: return NULL;
1.1.1.10! root 1193: opp = g_malloc0(sizeof(openpic_t));
! 1194: memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
1.1.1.3 root 1195:
1.1 root 1196: // isu_base &= 0xFFFC0000;
1197: opp->nb_cpus = nb_cpus;
1.1.1.4 root 1198: opp->max_irq = OPENPIC_MAX_IRQ;
1199: opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
1200: opp->irq_tim0 = OPENPIC_IRQ_TIM0;
1.1 root 1201: /* Set IRQ types */
1.1.1.4 root 1202: for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
1.1 root 1203: opp->src[i].type = IRQ_EXTERNAL;
1204: }
1.1.1.4 root 1205: for (; i < OPENPIC_IRQ_TIM0; i++) {
1.1 root 1206: opp->src[i].type = IRQ_SPECIAL;
1207: }
1208: #if MAX_IPI > 0
1.1.1.4 root 1209: m = OPENPIC_IRQ_IPI0;
1.1 root 1210: #else
1.1.1.4 root 1211: m = OPENPIC_IRQ_DBL0;
1.1 root 1212: #endif
1213: for (; i < m; i++) {
1214: opp->src[i].type = IRQ_TIMER;
1215: }
1.1.1.4 root 1216: for (; i < OPENPIC_MAX_IRQ; i++) {
1.1 root 1217: opp->src[i].type = IRQ_INTERNAL;
1218: }
1.1.1.2 root 1219: for (i = 0; i < nb_cpus; i++)
1.1.1.3 root 1220: opp->dst[i].irqs = irqs[i];
1221: opp->irq_out = irq_out;
1.1.1.4 root 1222:
1.1.1.7 root 1223: register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
1224: openpic_save, openpic_load, opp);
1.1.1.4 root 1225: qemu_register_reset(openpic_reset, opp);
1226:
1227: opp->irq_raise = openpic_irq_raise;
1228: opp->reset = openpic_reset;
1229:
1.1.1.9 root 1230: if (pmem)
1231: *pmem = &opp->mem;
1.1.1.3 root 1232:
1.1.1.4 root 1233: return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
1234: }
1235:
1236: static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
1237: {
1238: int n_ci = IDR_CI0 - n_CPU;
1.1.1.5 root 1239:
1.1.1.4 root 1240: if(test_bit(&src->ide, n_ci)) {
1241: qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1242: }
1243: else {
1244: qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1245: }
1246: }
1247:
1248: static void mpic_reset (void *opaque)
1249: {
1250: openpic_t *mpp = (openpic_t *)opaque;
1251: int i;
1252:
1253: mpp->glbc = 0x80000000;
1254: /* Initialise controller registers */
1.1.1.9 root 1255: mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
1.1.1.4 root 1256: mpp->veni = VENI;
1257: mpp->pint = 0x00000000;
1258: mpp->spve = 0x0000FFFF;
1259: /* Initialise IRQ sources */
1260: for (i = 0; i < mpp->max_irq; i++) {
1261: mpp->src[i].ipvp = 0x80800000;
1262: mpp->src[i].ide = 0x00000001;
1263: }
1.1.1.9 root 1264: /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
1265: for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
1266: mpp->src[i].ide = 0;
1267: }
1.1.1.4 root 1268: /* Initialise IRQ destinations */
1269: for (i = 0; i < MAX_CPU; i++) {
1270: mpp->dst[i].pctp = 0x0000000F;
1271: mpp->dst[i].tfrr = 0x00000000;
1272: memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
1273: mpp->dst[i].raised.next = -1;
1274: memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
1275: mpp->dst[i].servicing.next = -1;
1276: }
1277: /* Initialise timers */
1278: for (i = 0; i < MAX_TMR; i++) {
1279: mpp->timers[i].ticc = 0x00000000;
1280: mpp->timers[i].tibc = 0x80000000;
1281: }
1282: /* Go out of RESET state */
1283: mpp->glbc = 0x00000000;
1284: }
1285:
1286: static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
1287: {
1288: openpic_t *mpp = opaque;
1289: int idx, cpu;
1290:
1.1.1.5 root 1291: DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1.1.1.4 root 1292: if (addr & 0xF)
1293: return;
1294: addr &= 0xFFFF;
1295: cpu = addr >> 12;
1296: idx = (addr >> 6) & 0x3;
1297: switch (addr & 0x30) {
1298: case 0x00: /* gtccr */
1299: break;
1300: case 0x10: /* gtbcr */
1301: if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
1302: (val & 0x80000000) == 0 &&
1303: (mpp->timers[idx].tibc & 0x80000000) != 0)
1304: mpp->timers[idx].ticc &= ~0x80000000;
1305: mpp->timers[idx].tibc = val;
1306: break;
1307: case 0x20: /* GTIVPR */
1.1.1.9 root 1308: write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
1.1.1.4 root 1309: break;
1310: case 0x30: /* GTIDR & TFRR */
1311: if ((addr & 0xF0) == 0xF0)
1312: mpp->dst[cpu].tfrr = val;
1313: else
1.1.1.9 root 1314: write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
1.1.1.4 root 1315: break;
1316: }
1317: }
1318:
1319: static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
1320: {
1321: openpic_t *mpp = opaque;
1322: uint32_t retval;
1323: int idx, cpu;
1324:
1.1.1.5 root 1325: DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1.1.1.4 root 1326: retval = 0xFFFFFFFF;
1327: if (addr & 0xF)
1328: return retval;
1329: addr &= 0xFFFF;
1330: cpu = addr >> 12;
1331: idx = (addr >> 6) & 0x3;
1332: switch (addr & 0x30) {
1333: case 0x00: /* gtccr */
1334: retval = mpp->timers[idx].ticc;
1335: break;
1336: case 0x10: /* gtbcr */
1337: retval = mpp->timers[idx].tibc;
1338: break;
1339: case 0x20: /* TIPV */
1.1.1.9 root 1340: retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
1.1.1.4 root 1341: break;
1342: case 0x30: /* TIDR */
1343: if ((addr &0xF0) == 0XF0)
1344: retval = mpp->dst[cpu].tfrr;
1345: else
1.1.1.9 root 1346: retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
1.1.1.4 root 1347: break;
1348: }
1349: DPRINTF("%s: => %08x\n", __func__, retval);
1350:
1351: return retval;
1352: }
1353:
1354: static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
1355: uint32_t val)
1356: {
1357: openpic_t *mpp = opaque;
1358: int idx = MPIC_EXT_IRQ;
1359:
1.1.1.5 root 1360: DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1.1.1.4 root 1361: if (addr & 0xF)
1362: return;
1363:
1364: if (addr < MPIC_EXT_REG_SIZE) {
1365: idx += (addr & 0xFFF0) >> 5;
1366: if (addr & 0x10) {
1367: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1368: write_IRQreg_ide(mpp, idx, val);
1.1.1.4 root 1369: } else {
1370: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1371: write_IRQreg_ipvp(mpp, idx, val);
1.1.1.4 root 1372: }
1373: }
1374: }
1375:
1376: static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
1377: {
1378: openpic_t *mpp = opaque;
1379: uint32_t retval;
1380: int idx = MPIC_EXT_IRQ;
1381:
1.1.1.5 root 1382: DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1.1.1.4 root 1383: retval = 0xFFFFFFFF;
1384: if (addr & 0xF)
1385: return retval;
1386:
1387: if (addr < MPIC_EXT_REG_SIZE) {
1388: idx += (addr & 0xFFF0) >> 5;
1389: if (addr & 0x10) {
1390: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1391: retval = read_IRQreg_ide(mpp, idx);
1.1.1.4 root 1392: } else {
1393: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1394: retval = read_IRQreg_ipvp(mpp, idx);
1.1.1.4 root 1395: }
1396: DPRINTF("%s: => %08x\n", __func__, retval);
1397: }
1398:
1399: return retval;
1400: }
1401:
1402: static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
1403: uint32_t val)
1404: {
1405: openpic_t *mpp = opaque;
1406: int idx = MPIC_INT_IRQ;
1407:
1.1.1.5 root 1408: DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1.1.1.4 root 1409: if (addr & 0xF)
1410: return;
1411:
1412: if (addr < MPIC_INT_REG_SIZE) {
1413: idx += (addr & 0xFFF0) >> 5;
1414: if (addr & 0x10) {
1415: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1416: write_IRQreg_ide(mpp, idx, val);
1.1.1.4 root 1417: } else {
1418: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1419: write_IRQreg_ipvp(mpp, idx, val);
1.1.1.4 root 1420: }
1421: }
1422: }
1423:
1424: static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
1425: {
1426: openpic_t *mpp = opaque;
1427: uint32_t retval;
1428: int idx = MPIC_INT_IRQ;
1429:
1.1.1.5 root 1430: DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1.1.1.4 root 1431: retval = 0xFFFFFFFF;
1432: if (addr & 0xF)
1433: return retval;
1434:
1435: if (addr < MPIC_INT_REG_SIZE) {
1436: idx += (addr & 0xFFF0) >> 5;
1437: if (addr & 0x10) {
1438: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1439: retval = read_IRQreg_ide(mpp, idx);
1.1.1.4 root 1440: } else {
1441: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1442: retval = read_IRQreg_ipvp(mpp, idx);
1.1.1.4 root 1443: }
1444: DPRINTF("%s: => %08x\n", __func__, retval);
1445: }
1446:
1447: return retval;
1448: }
1449:
1450: static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
1451: uint32_t val)
1452: {
1453: openpic_t *mpp = opaque;
1454: int idx = MPIC_MSG_IRQ;
1455:
1.1.1.5 root 1456: DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1.1.1.4 root 1457: if (addr & 0xF)
1458: return;
1459:
1460: if (addr < MPIC_MSG_REG_SIZE) {
1461: idx += (addr & 0xFFF0) >> 5;
1462: if (addr & 0x10) {
1463: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1464: write_IRQreg_ide(mpp, idx, val);
1.1.1.4 root 1465: } else {
1466: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1467: write_IRQreg_ipvp(mpp, idx, val);
1.1.1.4 root 1468: }
1469: }
1470: }
1471:
1472: static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
1473: {
1474: openpic_t *mpp = opaque;
1475: uint32_t retval;
1476: int idx = MPIC_MSG_IRQ;
1477:
1.1.1.5 root 1478: DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1.1.1.4 root 1479: retval = 0xFFFFFFFF;
1480: if (addr & 0xF)
1481: return retval;
1482:
1483: if (addr < MPIC_MSG_REG_SIZE) {
1484: idx += (addr & 0xFFF0) >> 5;
1485: if (addr & 0x10) {
1486: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1487: retval = read_IRQreg_ide(mpp, idx);
1.1.1.4 root 1488: } else {
1489: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1490: retval = read_IRQreg_ipvp(mpp, idx);
1.1.1.4 root 1491: }
1492: DPRINTF("%s: => %08x\n", __func__, retval);
1493: }
1494:
1495: return retval;
1496: }
1497:
1498: static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
1499: uint32_t val)
1500: {
1501: openpic_t *mpp = opaque;
1502: int idx = MPIC_MSI_IRQ;
1503:
1.1.1.5 root 1504: DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
1.1.1.4 root 1505: if (addr & 0xF)
1506: return;
1507:
1508: if (addr < MPIC_MSI_REG_SIZE) {
1509: idx += (addr & 0xFFF0) >> 5;
1510: if (addr & 0x10) {
1511: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1512: write_IRQreg_ide(mpp, idx, val);
1.1.1.4 root 1513: } else {
1514: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1515: write_IRQreg_ipvp(mpp, idx, val);
1.1.1.4 root 1516: }
1517: }
1518: }
1519: static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
1520: {
1521: openpic_t *mpp = opaque;
1522: uint32_t retval;
1523: int idx = MPIC_MSI_IRQ;
1524:
1.1.1.5 root 1525: DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1.1.1.4 root 1526: retval = 0xFFFFFFFF;
1527: if (addr & 0xF)
1528: return retval;
1529:
1530: if (addr < MPIC_MSI_REG_SIZE) {
1531: idx += (addr & 0xFFF0) >> 5;
1532: if (addr & 0x10) {
1533: /* EXDE / IFEDE / IEEDE */
1.1.1.9 root 1534: retval = read_IRQreg_ide(mpp, idx);
1.1.1.4 root 1535: } else {
1536: /* EXVP / IFEVP / IEEVP */
1.1.1.9 root 1537: retval = read_IRQreg_ipvp(mpp, idx);
1.1.1.4 root 1538: }
1539: DPRINTF("%s: => %08x\n", __func__, retval);
1540: }
1541:
1542: return retval;
1543: }
1544:
1.1.1.9 root 1545: static const MemoryRegionOps mpic_glb_ops = {
1546: .old_mmio = {
1547: .write = { openpic_buggy_write,
1548: openpic_buggy_write,
1549: openpic_gbl_write,
1550: },
1551: .read = { openpic_buggy_read,
1552: openpic_buggy_read,
1553: openpic_gbl_read,
1554: },
1555: },
1556: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1557: };
1558:
1.1.1.9 root 1559: static const MemoryRegionOps mpic_tmr_ops = {
1560: .old_mmio = {
1561: .write = { openpic_buggy_write,
1562: openpic_buggy_write,
1563: mpic_timer_write,
1564: },
1565: .read = { openpic_buggy_read,
1566: openpic_buggy_read,
1567: mpic_timer_read,
1568: },
1569: },
1570: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1571: };
1572:
1.1.1.9 root 1573: static const MemoryRegionOps mpic_cpu_ops = {
1574: .old_mmio = {
1575: .write = { openpic_buggy_write,
1576: openpic_buggy_write,
1577: openpic_cpu_write,
1578: },
1579: .read = { openpic_buggy_read,
1580: openpic_buggy_read,
1581: openpic_cpu_read,
1582: },
1583: },
1584: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1585: };
1586:
1.1.1.9 root 1587: static const MemoryRegionOps mpic_ext_ops = {
1588: .old_mmio = {
1589: .write = { openpic_buggy_write,
1590: openpic_buggy_write,
1591: mpic_src_ext_write,
1592: },
1593: .read = { openpic_buggy_read,
1594: openpic_buggy_read,
1595: mpic_src_ext_read,
1596: },
1597: },
1598: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1599: };
1600:
1.1.1.9 root 1601: static const MemoryRegionOps mpic_int_ops = {
1602: .old_mmio = {
1603: .write = { openpic_buggy_write,
1604: openpic_buggy_write,
1605: mpic_src_int_write,
1606: },
1607: .read = { openpic_buggy_read,
1608: openpic_buggy_read,
1609: mpic_src_int_read,
1610: },
1611: },
1612: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1613: };
1614:
1.1.1.9 root 1615: static const MemoryRegionOps mpic_msg_ops = {
1616: .old_mmio = {
1617: .write = { openpic_buggy_write,
1618: openpic_buggy_write,
1619: mpic_src_msg_write,
1620: },
1621: .read = { openpic_buggy_read,
1622: openpic_buggy_read,
1623: mpic_src_msg_read,
1624: },
1625: },
1626: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1627: };
1628:
1.1.1.9 root 1629: static const MemoryRegionOps mpic_msi_ops = {
1630: .old_mmio = {
1631: .write = { openpic_buggy_write,
1632: openpic_buggy_write,
1633: mpic_src_msi_write,
1634: },
1635: .read = { openpic_buggy_read,
1636: openpic_buggy_read,
1637: mpic_src_msi_read,
1638: },
1639: },
1640: .endianness = DEVICE_BIG_ENDIAN,
1.1.1.4 root 1641: };
1642:
1.1.1.9 root 1643: qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
1644: int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
1.1.1.4 root 1645: {
1.1.1.9 root 1646: openpic_t *mpp;
1647: int i;
1.1.1.4 root 1648: struct {
1.1.1.9 root 1649: const char *name;
1650: MemoryRegionOps const *ops;
1651: target_phys_addr_t start_addr;
1652: ram_addr_t size;
1.1.1.4 root 1653: } const list[] = {
1.1.1.9 root 1654: {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
1655: {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
1656: {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
1657: {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
1658: {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
1659: {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
1660: {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
1.1.1.4 root 1661: };
1662:
1.1.1.9 root 1663: mpp = g_malloc0(sizeof(openpic_t));
1.1.1.4 root 1664:
1.1.1.9 root 1665: memory_region_init(&mpp->mem, "mpic", 0x40000);
1666: memory_region_add_subregion(address_space, base, &mpp->mem);
1.1.1.4 root 1667:
1668: for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
1669:
1.1.1.9 root 1670: memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
1671: list[i].name, list[i].size);
1672:
1673: memory_region_add_subregion(&mpp->mem, list[i].start_addr,
1674: &mpp->sub_io_mem[i]);
1.1.1.4 root 1675: }
1676:
1677: mpp->nb_cpus = nb_cpus;
1678: mpp->max_irq = MPIC_MAX_IRQ;
1679: mpp->irq_ipi0 = MPIC_IPI_IRQ;
1680: mpp->irq_tim0 = MPIC_TMR_IRQ;
1681:
1682: for (i = 0; i < nb_cpus; i++)
1683: mpp->dst[i].irqs = irqs[i];
1684: mpp->irq_out = irq_out;
1685:
1686: mpp->irq_raise = mpic_irq_raise;
1687: mpp->reset = mpic_reset;
1688:
1.1.1.7 root 1689: register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
1.1.1.4 root 1690: qemu_register_reset(mpic_reset, mpp);
1691:
1692: return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
1.1 root 1693: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.