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

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

unix.superglobalmegacorp.com