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