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

1.1       root        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 compagnion chip developper'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 "vl.h"
                     36: 
                     37: //#define DEBUG_OPENPIC
                     38: 
                     39: #ifdef DEBUG_OPENPIC
                     40: #define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
                     41: #else
                     42: #define DPRINTF(fmt, args...) do { } while (0)
                     43: #endif
                     44: #define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
                     45: 
                     46: #define USE_MPCxxx /* Intel model is broken, for now */
                     47: 
                     48: #if defined (USE_INTEL_GW80314)
                     49: /* Intel GW80314 I/O Companion chip */
                     50: 
                     51: #define MAX_CPU     4
                     52: #define MAX_IRQ    32
                     53: #define MAX_DBL     4
                     54: #define MAX_MBX     4
                     55: #define MAX_TMR     4
                     56: #define VECTOR_BITS 8
                     57: #define MAX_IPI     0
                     58: 
                     59: #define VID (0x00000000)
                     60: 
                     61: #define OPENPIC_LITTLE_ENDIAN 1
                     62: #define OPENPIC_BIG_ENDIAN    0
                     63: 
                     64: #elif defined(USE_MPCxxx)
                     65: 
                     66: #define MAX_CPU     2
                     67: #define MAX_IRQ    64
                     68: #define EXT_IRQ    48
                     69: #define MAX_DBL     0
                     70: #define MAX_MBX     0
                     71: #define MAX_TMR     4
                     72: #define VECTOR_BITS 8
                     73: #define MAX_IPI     4
                     74: #define VID         0x03 /* MPIC version ID */
                     75: #define VENI        0x00000000 /* Vendor ID */
                     76: 
                     77: enum {
                     78:     IRQ_IPVP = 0,
                     79:     IRQ_IDE,
                     80: };
                     81: 
                     82: #define OPENPIC_LITTLE_ENDIAN 1
                     83: #define OPENPIC_BIG_ENDIAN    0
                     84: 
                     85: #else
                     86: #error "Please select which OpenPic implementation is to be emulated"
                     87: #endif
                     88: 
                     89: #if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
                     90:     (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
                     91: #define OPENPIC_SWAP
                     92: #endif
                     93: 
                     94: /* Interrupt definitions */
                     95: #define IRQ_FE     (EXT_IRQ)     /* Internal functional IRQ */
                     96: #define IRQ_ERR    (EXT_IRQ + 1) /* Error IRQ */
                     97: #define IRQ_TIM0   (EXT_IRQ + 2) /* First timer IRQ */
                     98: #if MAX_IPI > 0
                     99: #define IRQ_IPI0   (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
                    100: #define IRQ_DBL0   (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */
                    101: #else
                    102: #define IRQ_DBL0   (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
                    103: #define IRQ_MBX0   (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
                    104: #endif
                    105: 
                    106: #define BF_WIDTH(_bits_) \
                    107: (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
                    108: 
                    109: static inline void set_bit (uint32_t *field, int bit)
                    110: {
                    111:     field[bit >> 5] |= 1 << (bit & 0x1F);
                    112: }
                    113: 
                    114: static inline void reset_bit (uint32_t *field, int bit)
                    115: {
                    116:     field[bit >> 5] &= ~(1 << (bit & 0x1F));
                    117: }
                    118: 
                    119: static inline int test_bit (uint32_t *field, int bit)
                    120: {
                    121:     return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
                    122: }
                    123: 
                    124: enum {
                    125:     IRQ_EXTERNAL = 0x01,
                    126:     IRQ_INTERNAL = 0x02,
                    127:     IRQ_TIMER    = 0x04,
                    128:     IRQ_SPECIAL  = 0x08,
                    129: } IRQ_src_type;
                    130: 
                    131: typedef struct IRQ_queue_t {
                    132:     uint32_t queue[BF_WIDTH(MAX_IRQ)];
                    133:     int next;
                    134:     int priority;
                    135: } IRQ_queue_t;
                    136: 
                    137: typedef struct IRQ_src_t {
                    138:     uint32_t ipvp;  /* IRQ vector/priority register */
                    139:     uint32_t ide;   /* IRQ destination register */
                    140:     int type;
                    141:     int last_cpu;
                    142:     int pending;    /* TRUE if IRQ is pending */
                    143: } IRQ_src_t;
                    144: 
                    145: enum IPVP_bits {
                    146:     IPVP_MASK     = 31,
                    147:     IPVP_ACTIVITY = 30,
                    148:     IPVP_MODE     = 29,
                    149:     IPVP_POLARITY = 23,
                    150:     IPVP_SENSE    = 22,
                    151: };
                    152: #define IPVP_PRIORITY_MASK     (0x1F << 16)
                    153: #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
                    154: #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
                    155: #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
                    156: 
                    157: typedef struct IRQ_dst_t {
                    158:     uint32_t pctp; /* CPU current task priority */
                    159:     uint32_t pcsr; /* CPU sensitivity register */
                    160:     IRQ_queue_t raised;
                    161:     IRQ_queue_t servicing;
1.1.1.2 ! root      162:     CPUState *env;
1.1       root      163: } IRQ_dst_t;
                    164: 
                    165: struct openpic_t {
                    166:     PCIDevice pci_dev;
                    167:     int mem_index;
                    168:     /* Global registers */
                    169:     uint32_t frep; /* Feature reporting register */
                    170:     uint32_t glbc; /* Global configuration register  */
                    171:     uint32_t micr; /* MPIC interrupt configuration register */
                    172:     uint32_t veni; /* Vendor identification register */
                    173:     uint32_t spve; /* Spurious vector register */
                    174:     uint32_t tifr; /* Timer frequency reporting register */
                    175:     /* Source registers */
                    176:     IRQ_src_t src[MAX_IRQ];
                    177:     /* Local registers per output pin */
                    178:     IRQ_dst_t dst[MAX_CPU];
                    179:     int nb_cpus;
                    180:     /* Timer registers */
                    181:     struct {
                    182:        uint32_t ticc;  /* Global timer current count register */
                    183:        uint32_t tibc;  /* Global timer base count register */
                    184:     } timers[MAX_TMR];
                    185: #if MAX_DBL > 0
                    186:     /* Doorbell registers */
                    187:     uint32_t dar;        /* Doorbell activate register */
                    188:     struct {
                    189:        uint32_t dmr;    /* Doorbell messaging register */
                    190:     } doorbells[MAX_DBL];
                    191: #endif
                    192: #if MAX_MBX > 0
                    193:     /* Mailbox registers */
                    194:     struct {
                    195:        uint32_t mbr;    /* Mailbox register */
                    196:     } mailboxes[MAX_MAILBOXES];
                    197: #endif
                    198: };
                    199: 
                    200: static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
                    201: {
                    202:     set_bit(q->queue, n_IRQ);
                    203: }
                    204: 
                    205: static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
                    206: {
                    207:     reset_bit(q->queue, n_IRQ);
                    208: }
                    209: 
                    210: static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
                    211: {
                    212:     return test_bit(q->queue, n_IRQ);
                    213: }
                    214: 
                    215: static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
                    216: {
                    217:     int next, i;
                    218:     int priority;
                    219: 
                    220:     next = -1;
                    221:     priority = -1;
                    222:     for (i = 0; i < MAX_IRQ; i++) {
                    223:        if (IRQ_testbit(q, i)) {
                    224:             DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", 
                    225:                     i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
                    226:            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
                    227:                next = i;
                    228:                priority = IPVP_PRIORITY(opp->src[i].ipvp);
                    229:            }
                    230:        }
                    231:     }
                    232:     q->next = next;
                    233:     q->priority = priority;
                    234: }
                    235: 
                    236: static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
                    237: {
                    238:     if (q->next == -1) {
                    239:         /* XXX: optimize */
                    240:        IRQ_check(opp, q);
                    241:     }
                    242: 
                    243:     return q->next;
                    244: }
                    245: 
                    246: static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
                    247: {
                    248:     IRQ_dst_t *dst;
                    249:     IRQ_src_t *src;
                    250:     int priority;
                    251: 
                    252:     dst = &opp->dst[n_CPU];
                    253:     src = &opp->src[n_IRQ];
                    254:     priority = IPVP_PRIORITY(src->ipvp);
                    255:     if (priority <= dst->pctp) {
                    256:        /* Too low priority */
                    257:        return;
                    258:     }
                    259:     if (IRQ_testbit(&dst->raised, n_IRQ)) {
                    260:        /* Interrupt miss */
                    261:        return;
                    262:     }
                    263:     set_bit(&src->ipvp, IPVP_ACTIVITY);
                    264:     IRQ_setbit(&dst->raised, n_IRQ);
                    265:     if (priority > dst->raised.priority) {
                    266:         IRQ_get_next(opp, &dst->raised);
                    267:         DPRINTF("Raise CPU IRQ\n");
1.1.1.2 ! root      268:         cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
1.1       root      269:     }
                    270: }
                    271: 
                    272: /* update pic state because registers for n_IRQ have changed value */
                    273: static void openpic_update_irq(openpic_t *opp, int n_IRQ)
                    274: {
                    275:     IRQ_src_t *src;
                    276:     int i;
                    277: 
                    278:     src = &opp->src[n_IRQ];
                    279: 
                    280:     if (!src->pending) {
                    281:         /* no irq pending */
                    282:         return;
                    283:     }
                    284:     if (test_bit(&src->ipvp, IPVP_MASK)) {
                    285:        /* Interrupt source is disabled */
                    286:        return;
                    287:     }
                    288:     if (IPVP_PRIORITY(src->ipvp) == 0) {
                    289:        /* Priority set to zero */
                    290:        return;
                    291:     }
                    292:     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
                    293:         /* IRQ already active */
                    294:         return;
                    295:     }
                    296:     if (src->ide == 0x00000000) {
                    297:        /* No target */
                    298:        return;
                    299:     }
                    300: 
                    301:     if (!test_bit(&src->ipvp, IPVP_MODE) ||
                    302:         src->ide == (1 << src->last_cpu)) {
                    303:         /* Directed delivery mode */
                    304:         for (i = 0; i < opp->nb_cpus; i++) {
                    305:             if (test_bit(&src->ide, i))
                    306:                 IRQ_local_pipe(opp, i, n_IRQ);
                    307:         }
                    308:     } else {
                    309:         /* Distributed delivery mode */
                    310:         /* XXX: incorrect code */
                    311:         for (i = src->last_cpu; i < src->last_cpu; i++) {
                    312:             if (i == MAX_IRQ)
                    313:                 i = 0;
                    314:             if (test_bit(&src->ide, i)) {
                    315:                 IRQ_local_pipe(opp, i, n_IRQ);
                    316:                 src->last_cpu = i;
                    317:                 break;
                    318:             }
                    319:         }
                    320:     }
                    321: }
                    322: 
                    323: void openpic_set_irq(void *opaque, int n_IRQ, int level)
                    324: {
                    325:     openpic_t *opp = opaque;
                    326:     IRQ_src_t *src;
                    327: 
                    328:     src = &opp->src[n_IRQ];
                    329:     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n", 
                    330:             n_IRQ, level, src->ipvp);
                    331:     if (test_bit(&src->ipvp, IPVP_SENSE)) {
                    332:         /* level-sensitive irq */
                    333:         src->pending = level;
                    334:         if (!level)
                    335:             reset_bit(&src->ipvp, IPVP_ACTIVITY);
                    336:     } else {
                    337:         /* edge-sensitive irq */
                    338:         if (level)
                    339:             src->pending = 1;
                    340:     }
                    341:     openpic_update_irq(opp, n_IRQ);
                    342: }
                    343: 
                    344: static void openpic_reset (openpic_t *opp)
                    345: {
                    346:     int i;
                    347: 
                    348:     opp->glbc = 0x80000000;
                    349:     /* Initialise controller registers */
                    350:     opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
                    351:     opp->veni = VENI;
                    352:     opp->spve = 0x000000FF;
                    353:     opp->tifr = 0x003F7A00;
                    354:     /* ? */
                    355:     opp->micr = 0x00000000;
                    356:     /* Initialise IRQ sources */
                    357:     for (i = 0; i < MAX_IRQ; i++) {
                    358:        opp->src[i].ipvp = 0xA0000000;
                    359:        opp->src[i].ide  = 0x00000000;
                    360:     }
                    361:     /* Initialise IRQ destinations */
                    362:     for (i = 0; i < opp->nb_cpus; i++) {
                    363:        opp->dst[i].pctp      = 0x0000000F;
                    364:        opp->dst[i].pcsr      = 0x00000000;
                    365:        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
                    366:        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
                    367:     }
                    368:     /* Initialise timers */
                    369:     for (i = 0; i < MAX_TMR; i++) {
                    370:        opp->timers[i].ticc = 0x00000000;
                    371:        opp->timers[i].tibc = 0x80000000;
                    372:     }
                    373:     /* Initialise doorbells */
                    374: #if MAX_DBL > 0
                    375:     opp->dar = 0x00000000;
                    376:     for (i = 0; i < MAX_DBL; i++) {
                    377:        opp->doorbells[i].dmr  = 0x00000000;
                    378:     }
                    379: #endif
                    380:     /* Initialise mailboxes */
                    381: #if MAX_MBX > 0
                    382:     for (i = 0; i < MAX_MBX; i++) { /* ? */
                    383:        opp->mailboxes[i].mbr   = 0x00000000;
                    384:     }
                    385: #endif
                    386:     /* Go out of RESET state */
                    387:     opp->glbc = 0x00000000;
                    388: }
                    389: 
                    390: static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
                    391: {
                    392:     uint32_t retval;
                    393: 
                    394:     switch (reg) {
                    395:     case IRQ_IPVP:
                    396:        retval = opp->src[n_IRQ].ipvp;
                    397:        break;
                    398:     case IRQ_IDE:
                    399:        retval = opp->src[n_IRQ].ide;
                    400:        break;
                    401:     }
                    402: 
                    403:     return retval;
                    404: }
                    405: 
                    406: static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
                    407:                                  uint32_t reg, uint32_t val)
                    408: {
                    409:     uint32_t tmp;
                    410: 
                    411:     switch (reg) {
                    412:     case IRQ_IPVP:
                    413:         /* NOTE: not fully accurate for special IRQs, but simple and
                    414:            sufficient */
                    415:         /* ACTIVITY bit is read-only */
                    416:        opp->src[n_IRQ].ipvp = 
                    417:             (opp->src[n_IRQ].ipvp & 0x40000000) |
                    418:             (val & 0x800F00FF);
                    419:         openpic_update_irq(opp, n_IRQ);
                    420:         DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", 
                    421:                 n_IRQ, val, opp->src[n_IRQ].ipvp);
                    422:        break;
                    423:     case IRQ_IDE:
                    424:        tmp = val & 0xC0000000;
                    425:         tmp |= val & ((1 << MAX_CPU) - 1);
                    426:        opp->src[n_IRQ].ide = tmp;
                    427:         DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
                    428:        break;
                    429:     }
                    430: }
                    431: 
                    432: #if 0 // Code provision for Intel model
                    433: #if MAX_DBL > 0
                    434: static uint32_t read_doorbell_register (openpic_t *opp,
                    435:                                        int n_dbl, uint32_t offset)
                    436: {
                    437:     uint32_t retval;
                    438: 
                    439:     switch (offset) {
                    440:     case DBL_IPVP_OFFSET:
                    441:        retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
                    442:        break;
                    443:     case DBL_IDE_OFFSET:
                    444:        retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
                    445:        break;
                    446:     case DBL_DMR_OFFSET:
                    447:        retval = opp->doorbells[n_dbl].dmr;
                    448:        break;
                    449:     }
                    450: 
                    451:     return retval;
                    452: }
                    453:      
                    454: static void write_doorbell_register (penpic_t *opp, int n_dbl,
                    455:                                     uint32_t offset, uint32_t value)
                    456: {
                    457:     switch (offset) {
                    458:     case DBL_IVPR_OFFSET:
                    459:        write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
                    460:        break;
                    461:     case DBL_IDE_OFFSET:
                    462:        write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
                    463:        break;
                    464:     case DBL_DMR_OFFSET:
                    465:        opp->doorbells[n_dbl].dmr = value;
                    466:        break;
                    467:     }
                    468: }
                    469: #endif
                    470: 
                    471: #if MAX_MBX > 0
                    472: static uint32_t read_mailbox_register (openpic_t *opp,
                    473:                                       int n_mbx, uint32_t offset)
                    474: {
                    475:     uint32_t retval;
                    476: 
                    477:     switch (offset) {
                    478:     case MBX_MBR_OFFSET:
                    479:        retval = opp->mailboxes[n_mbx].mbr;
                    480:        break;
                    481:     case MBX_IVPR_OFFSET:
                    482:        retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
                    483:        break;
                    484:     case MBX_DMR_OFFSET:
                    485:        retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
                    486:        break;
                    487:     }
                    488: 
                    489:     return retval;
                    490: }
                    491: 
                    492: static void write_mailbox_register (openpic_t *opp, int n_mbx,
                    493:                                    uint32_t address, uint32_t value)
                    494: {
                    495:     switch (offset) {
                    496:     case MBX_MBR_OFFSET:
                    497:        opp->mailboxes[n_mbx].mbr = value;
                    498:        break;
                    499:     case MBX_IVPR_OFFSET:
                    500:        write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
                    501:        break;
                    502:     case MBX_DMR_OFFSET:
                    503:        write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
                    504:        break;
                    505:     }
                    506: }
                    507: #endif
                    508: #endif /* 0 : Code provision for Intel model */
                    509: 
                    510: static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
                    511: {
                    512:     openpic_t *opp = opaque;
                    513: 
                    514:     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
                    515:     if (addr & 0xF)
                    516:         return;
                    517: #if defined OPENPIC_SWAP
                    518:     val = bswap32(val);
                    519: #endif
                    520:     addr &= 0xFF;
                    521:     switch (addr) {
                    522:     case 0x00: /* FREP */
                    523:         break;
                    524:     case 0x20: /* GLBC */
                    525:         if (val & 0x80000000)
                    526:             openpic_reset(opp);
                    527:         opp->glbc = val & ~0x80000000;
                    528:        break;
                    529:     case 0x80: /* VENI */
                    530:        break;
                    531:     case 0x90: /* PINT */
                    532:         /* XXX: Should be able to reset any CPU */
                    533:         if (val & 1) {
                    534:             DPRINTF("Reset CPU IRQ\n");
1.1.1.2 ! root      535:             //            cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
1.1       root      536:         }
                    537:        break;
                    538: #if MAX_IPI > 0
                    539:     case 0xA0: /* IPI_IPVP */
                    540:     case 0xB0:
                    541:     case 0xC0:
                    542:     case 0xD0:
                    543:         {
                    544:             int idx;
                    545:             idx = (addr - 0xA0) >> 4;
                    546:             write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
                    547:         }
                    548:         break;
                    549: #endif
                    550:     case 0xE0: /* SPVE */
                    551:         opp->spve = val & 0x000000FF;
                    552:         break;
                    553:     case 0xF0: /* TIFR */
                    554:         opp->tifr = val;
                    555:        break;
                    556:     default:
                    557:         break;
                    558:     }
                    559: }
                    560: 
                    561: static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
                    562: {
                    563:     openpic_t *opp = opaque;
                    564:     uint32_t retval;
                    565: 
                    566:     DPRINTF("%s: addr %08x\n", __func__, addr);
                    567:     retval = 0xFFFFFFFF;
                    568:     if (addr & 0xF)
                    569:         return retval;
                    570:     addr &= 0xFF;
                    571:     switch (addr) {
                    572:     case 0x00: /* FREP */
                    573:         retval = opp->frep;
                    574:         break;
                    575:     case 0x20: /* GLBC */
                    576:         retval = opp->glbc;
                    577:        break;
                    578:     case 0x80: /* VENI */
                    579:         retval = opp->veni;
                    580:        break;
                    581:     case 0x90: /* PINT */
                    582:         retval = 0x00000000;
                    583:        break;
                    584: #if MAX_IPI > 0
                    585:     case 0xA0: /* IPI_IPVP */
                    586:     case 0xB0:
                    587:     case 0xC0:
                    588:     case 0xD0:
                    589:         {
                    590:             int idx;
                    591:             idx = (addr - 0xA0) >> 4;
                    592:             retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
                    593:         }
                    594:        break;
                    595: #endif
                    596:     case 0xE0: /* SPVE */
                    597:         retval = opp->spve;
                    598:         break;
                    599:     case 0xF0: /* TIFR */
                    600:         retval = opp->tifr;
                    601:        break;
                    602:     default:
                    603:         break;
                    604:     }
                    605:     DPRINTF("%s: => %08x\n", __func__, retval);
                    606: #if defined OPENPIC_SWAP
                    607:     retval = bswap32(retval);
                    608: #endif
                    609: 
                    610:     return retval;
                    611: }
                    612: 
                    613: static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
                    614: {
                    615:     openpic_t *opp = opaque;
                    616:     int idx;
                    617: 
                    618:     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
                    619:     if (addr & 0xF)
                    620:         return;
                    621: #if defined OPENPIC_SWAP
                    622:     val = bswap32(val);
                    623: #endif
                    624:     addr -= 0x1100;
                    625:     addr &= 0xFFFF;
                    626:     idx = (addr & 0xFFF0) >> 6;
                    627:     addr = addr & 0x30;
                    628:     switch (addr) {
                    629:     case 0x00: /* TICC */
                    630:         break;
                    631:     case 0x10: /* TIBC */
                    632:        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
                    633:            (val & 0x80000000) == 0 &&
                    634:             (opp->timers[idx].tibc & 0x80000000) != 0)
                    635:            opp->timers[idx].ticc &= ~0x80000000;
                    636:        opp->timers[idx].tibc = val;
                    637:        break;
                    638:     case 0x20: /* TIVP */
                    639:        write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
                    640:        break;
                    641:     case 0x30: /* TIDE */
                    642:        write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
                    643:        break;
                    644:     }
                    645: }
                    646: 
                    647: static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
                    648: {
                    649:     openpic_t *opp = opaque;
                    650:     uint32_t retval;
                    651:     int idx;
                    652: 
                    653:     DPRINTF("%s: addr %08x\n", __func__, addr);
                    654:     retval = 0xFFFFFFFF;
                    655:     if (addr & 0xF)
                    656:         return retval;
                    657:     addr -= 0x1100;
                    658:     addr &= 0xFFFF;
                    659:     idx = (addr & 0xFFF0) >> 6;
                    660:     addr = addr & 0x30;
                    661:     switch (addr) {
                    662:     case 0x00: /* TICC */
                    663:        retval = opp->timers[idx].ticc;
                    664:         break;
                    665:     case 0x10: /* TIBC */
                    666:        retval = opp->timers[idx].tibc;
                    667:        break;
                    668:     case 0x20: /* TIPV */
                    669:        retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
                    670:        break;
                    671:     case 0x30: /* TIDE */
                    672:        retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
                    673:        break;
                    674:     }
                    675:     DPRINTF("%s: => %08x\n", __func__, retval);
                    676: #if defined OPENPIC_SWAP
                    677:     retval = bswap32(retval);
                    678: #endif
                    679: 
                    680:     return retval;
                    681: }
                    682: 
                    683: static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
                    684: {
                    685:     openpic_t *opp = opaque;
                    686:     int idx;
                    687: 
                    688:     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
                    689:     if (addr & 0xF)
                    690:         return;
                    691: #if defined OPENPIC_SWAP
                    692:     val = tswap32(val);
                    693: #endif
                    694:     addr = addr & 0xFFF0;
                    695:     idx = addr >> 5;
                    696:     if (addr & 0x10) {
                    697:         /* EXDE / IFEDE / IEEDE */
                    698:         write_IRQreg(opp, idx, IRQ_IDE, val);
                    699:     } else {
                    700:         /* EXVP / IFEVP / IEEVP */
                    701:         write_IRQreg(opp, idx, IRQ_IPVP, val);
                    702:     }
                    703: }
                    704: 
                    705: static uint32_t openpic_src_read (void *opaque, uint32_t addr)
                    706: {
                    707:     openpic_t *opp = opaque;
                    708:     uint32_t retval;
                    709:     int idx;
                    710: 
                    711:     DPRINTF("%s: addr %08x\n", __func__, addr);
                    712:     retval = 0xFFFFFFFF;
                    713:     if (addr & 0xF)
                    714:         return retval;
                    715:     addr = addr & 0xFFF0;
                    716:     idx = addr >> 5;
                    717:     if (addr & 0x10) {
                    718:         /* EXDE / IFEDE / IEEDE */
                    719:         retval = read_IRQreg(opp, idx, IRQ_IDE);
                    720:     } else {
                    721:         /* EXVP / IFEVP / IEEVP */
                    722:         retval = read_IRQreg(opp, idx, IRQ_IPVP);
                    723:     }
                    724:     DPRINTF("%s: => %08x\n", __func__, retval);
                    725: #if defined OPENPIC_SWAP
                    726:     retval = tswap32(retval);
                    727: #endif
                    728: 
                    729:     return retval;
                    730: }
                    731: 
                    732: static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
                    733: {
                    734:     openpic_t *opp = opaque;
                    735:     IRQ_src_t *src;
                    736:     IRQ_dst_t *dst;
                    737:     int idx, n_IRQ;
                    738: 
                    739:     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
                    740:     if (addr & 0xF)
                    741:         return;
                    742: #if defined OPENPIC_SWAP
                    743:     val = bswap32(val);
                    744: #endif
                    745:     addr &= 0x1FFF0;
                    746:     idx = addr / 0x1000;
                    747:     dst = &opp->dst[idx];
                    748:     addr &= 0xFF0;
                    749:     switch (addr) {
                    750: #if MAX_IPI > 0
                    751:     case 0x40: /* PIPD */
                    752:     case 0x50:
                    753:     case 0x60:
                    754:     case 0x70:
                    755:         idx = (addr - 0x40) >> 4;
                    756:         write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
                    757:         openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
                    758:         openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
                    759:         break;
                    760: #endif
                    761:     case 0x80: /* PCTP */
                    762:        dst->pctp = val & 0x0000000F;
                    763:        break;
                    764:     case 0x90: /* WHOAMI */
                    765:        /* Read-only register */
                    766:        break;
                    767:     case 0xA0: /* PIAC */
                    768:        /* Read-only register */
                    769:        break;
                    770:     case 0xB0: /* PEOI */
                    771:         DPRINTF("PEOI\n");
                    772:        n_IRQ = IRQ_get_next(opp, &dst->servicing);
                    773:        IRQ_resetbit(&dst->servicing, n_IRQ);
                    774:        dst->servicing.next = -1;
                    775:        src = &opp->src[n_IRQ];
                    776:        /* Set up next servicing IRQ */
                    777:        IRQ_get_next(opp, &dst->servicing);
                    778:        /* Check queued interrupts. */
                    779:        n_IRQ = IRQ_get_next(opp, &dst->raised);
                    780:        if (n_IRQ != -1) {
                    781:            src = &opp->src[n_IRQ];
                    782:            if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
                    783:                 DPRINTF("Raise CPU IRQ\n");
1.1.1.2 ! root      784:                 cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
1.1       root      785:             }
                    786:        }
                    787:        break;
                    788:     default:
                    789:         break;
                    790:     }
                    791: }
                    792: 
                    793: static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
                    794: {
                    795:     openpic_t *opp = opaque;
                    796:     IRQ_src_t *src;
                    797:     IRQ_dst_t *dst;
                    798:     uint32_t retval;
                    799:     int idx, n_IRQ;
                    800:     
                    801:     DPRINTF("%s: addr %08x\n", __func__, addr);
                    802:     retval = 0xFFFFFFFF;
                    803:     if (addr & 0xF)
                    804:         return retval;
                    805:     addr &= 0x1FFF0;
                    806:     idx = addr / 0x1000;
                    807:     dst = &opp->dst[idx];
                    808:     addr &= 0xFF0;
                    809:     switch (addr) {
                    810:     case 0x80: /* PCTP */
                    811:        retval = dst->pctp;
                    812:        break;
                    813:     case 0x90: /* WHOAMI */
                    814:        retval = idx;
                    815:        break;
                    816:     case 0xA0: /* PIAC */
                    817:        n_IRQ = IRQ_get_next(opp, &dst->raised);
                    818:         DPRINTF("PIAC: irq=%d\n", n_IRQ);
                    819:        if (n_IRQ == -1) {
                    820:            /* No more interrupt pending */
                    821:             retval = opp->spve;
                    822:        } else {
                    823:            src = &opp->src[n_IRQ];
                    824:            if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
                    825:                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
                    826:                /* - Spurious level-sensitive IRQ
                    827:                 * - Priorities has been changed
                    828:                 *   and the pending IRQ isn't allowed anymore
                    829:                 */
                    830:                reset_bit(&src->ipvp, IPVP_ACTIVITY);
                    831:                retval = IPVP_VECTOR(opp->spve);
                    832:            } else {
                    833:                /* IRQ enter servicing state */
                    834:                IRQ_setbit(&dst->servicing, n_IRQ);
                    835:                retval = IPVP_VECTOR(src->ipvp);
                    836:            }
                    837:            IRQ_resetbit(&dst->raised, n_IRQ);
                    838:            dst->raised.next = -1;
                    839:            if (!test_bit(&src->ipvp, IPVP_SENSE)) {
                    840:                 /* edge-sensitive IRQ */
                    841:                reset_bit(&src->ipvp, IPVP_ACTIVITY);
                    842:                 src->pending = 0;
                    843:             }
                    844:        }
                    845:        break;
                    846:     case 0xB0: /* PEOI */
                    847:        retval = 0;
                    848:        break;
                    849: #if MAX_IPI > 0
                    850:     case 0x40: /* IDE */
                    851:     case 0x50:
                    852:         idx = (addr - 0x40) >> 4;
                    853:         retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
                    854:         break;
                    855: #endif
                    856:     default:
                    857:         break;
                    858:     }
                    859:     DPRINTF("%s: => %08x\n", __func__, retval);
                    860: #if defined OPENPIC_SWAP
                    861:     retval= bswap32(retval);
                    862: #endif
                    863: 
                    864:     return retval;
                    865: }
                    866: 
                    867: static void openpic_buggy_write (void *opaque,
                    868:                                  target_phys_addr_t addr, uint32_t val)
                    869: {
                    870:     printf("Invalid OPENPIC write access !\n");
                    871: }
                    872: 
                    873: static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
                    874: {
                    875:     printf("Invalid OPENPIC read access !\n");
                    876: 
                    877:     return -1;
                    878: }
                    879: 
                    880: static void openpic_writel (void *opaque,
                    881:                             target_phys_addr_t addr, uint32_t val)
                    882: {
                    883:     openpic_t *opp = opaque;
                    884: 
                    885:     addr &= 0x3FFFF;
                    886:     DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
                    887:     if (addr < 0x1100) {
                    888:         /* Global registers */
                    889:         openpic_gbl_write(opp, addr, val);
                    890:     } else if (addr < 0x10000) {
                    891:         /* Timers registers */
                    892:         openpic_timer_write(opp, addr, val);
                    893:     } else if (addr < 0x20000) {
                    894:         /* Source registers */
                    895:         openpic_src_write(opp, addr, val);
                    896:     } else {
                    897:         /* CPU registers */
                    898:         openpic_cpu_write(opp, addr, val);
                    899:     }
                    900: }
                    901: 
                    902: static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
                    903: {
                    904:     openpic_t *opp = opaque;
                    905:     uint32_t retval;
                    906: 
                    907:     addr &= 0x3FFFF;
                    908:     DPRINTF("%s: offset %08x\n", __func__, (int)addr);
                    909:     if (addr < 0x1100) {
                    910:         /* Global registers */
                    911:         retval = openpic_gbl_read(opp, addr);
                    912:     } else if (addr < 0x10000) {
                    913:         /* Timers registers */
                    914:         retval = openpic_timer_read(opp, addr);
                    915:     } else if (addr < 0x20000) {
                    916:         /* Source registers */
                    917:         retval = openpic_src_read(opp, addr);
                    918:     } else {
                    919:         /* CPU registers */
                    920:         retval = openpic_cpu_read(opp, addr);
                    921:     }
                    922: 
                    923:     return retval;
                    924: }
                    925: 
                    926: static CPUWriteMemoryFunc *openpic_write[] = {
                    927:     &openpic_buggy_write,
                    928:     &openpic_buggy_write,
                    929:     &openpic_writel,
                    930: };
                    931: 
                    932: static CPUReadMemoryFunc *openpic_read[] = {
                    933:     &openpic_buggy_read,
                    934:     &openpic_buggy_read,
                    935:     &openpic_readl,
                    936: };
                    937: 
                    938: static void openpic_map(PCIDevice *pci_dev, int region_num, 
                    939:                         uint32_t addr, uint32_t size, int type)
                    940: {
                    941:     openpic_t *opp;
                    942: 
                    943:     DPRINTF("Map OpenPIC\n");
                    944:     opp = (openpic_t *)pci_dev;
                    945:     /* Global registers */
                    946:     DPRINTF("Register OPENPIC gbl   %08x => %08x\n",
                    947:             addr + 0x1000, addr + 0x1000 + 0x100);
                    948:     /* Timer registers */
                    949:     DPRINTF("Register OPENPIC timer %08x => %08x\n",
                    950:             addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
                    951:     /* Interrupt source registers */
                    952:     DPRINTF("Register OPENPIC src   %08x => %08x\n",
                    953:             addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
                    954:     /* Per CPU registers */
                    955:     DPRINTF("Register OPENPIC dst   %08x => %08x\n",
                    956:             addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
                    957:     cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
                    958: #if 0 // Don't implement ISU for now
                    959:     opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
                    960:                                            openpic_src_write);
                    961:     cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
                    962:                                  opp_io_memory);
                    963: #endif
                    964: }
                    965: 
1.1.1.2 ! root      966: openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
        !           967:                          CPUPPCState **envp)
1.1       root      968: {
                    969:     openpic_t *opp;
                    970:     uint8_t *pci_conf;
                    971:     int i, m;
                    972:     
                    973:     /* XXX: for now, only one CPU is supported */
                    974:     if (nb_cpus != 1)
                    975:         return NULL;
                    976:     if (bus) {
                    977:         opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
                    978:                                                -1, NULL, NULL);
                    979:         if (opp == NULL)
                    980:             return NULL;
                    981:         pci_conf = opp->pci_dev.config;
                    982:         pci_conf[0x00] = 0x14; // IBM MPIC2
                    983:         pci_conf[0x01] = 0x10;
                    984:         pci_conf[0x02] = 0xFF;
                    985:         pci_conf[0x03] = 0xFF;
                    986:         pci_conf[0x0a] = 0x80; // PIC
                    987:         pci_conf[0x0b] = 0x08;
                    988:         pci_conf[0x0e] = 0x00; // header_type
                    989:         pci_conf[0x3d] = 0x00; // no interrupt pin
                    990:         
                    991:         /* Register I/O spaces */
                    992:         pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
                    993:                                PCI_ADDRESS_SPACE_MEM, &openpic_map);
                    994:     } else {
                    995:         opp = qemu_mallocz(sizeof(openpic_t));
                    996:     }
                    997: 
                    998:     opp->mem_index = cpu_register_io_memory(0, openpic_read,
                    999:                                             openpic_write, opp);
                   1000:     
                   1001:     //    isu_base &= 0xFFFC0000;
                   1002:     opp->nb_cpus = nb_cpus;
                   1003:     /* Set IRQ types */
                   1004:     for (i = 0; i < EXT_IRQ; i++) {
                   1005:         opp->src[i].type = IRQ_EXTERNAL;
                   1006:     }
                   1007:     for (; i < IRQ_TIM0; i++) {
                   1008:         opp->src[i].type = IRQ_SPECIAL;
                   1009:     }
                   1010: #if MAX_IPI > 0
                   1011:     m = IRQ_IPI0;
                   1012: #else
                   1013:     m = IRQ_DBL0;
                   1014: #endif
                   1015:     for (; i < m; i++) {
                   1016:         opp->src[i].type = IRQ_TIMER;
                   1017:     }
                   1018:     for (; i < MAX_IRQ; i++) {
                   1019:         opp->src[i].type = IRQ_INTERNAL;
                   1020:     }
1.1.1.2 ! root     1021:     for (i = 0; i < nb_cpus; i++)
        !          1022:         opp->dst[i].env = envp[i];
1.1       root     1023:     openpic_reset(opp);
                   1024:     if (pmem_index)
                   1025:         *pmem_index = opp->mem_index;
                   1026:     return opp;
                   1027: }

unix.superglobalmegacorp.com