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

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

unix.superglobalmegacorp.com