Annotation of qemu/hw/openpic.c, revision 1.1.1.8

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: }

unix.superglobalmegacorp.com