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

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

unix.superglobalmegacorp.com