File:  [Qemu by Fabrice Bellard] / qemu / hw / openpic.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:23:28 2018 UTC (2 years, 11 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0111, qemu0110, HEAD
qemu 0.11.0

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

unix.superglobalmegacorp.com