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

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

unix.superglobalmegacorp.com