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

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

unix.superglobalmegacorp.com