qemu/hw/intc/heathrow_pic.c
<<
>>
Prefs
   1/*
   2 * Heathrow PIC support (OldWorld PowerMac)
   3 *
   4 * Copyright (c) 2005-2007 Fabrice Bellard
   5 * Copyright (c) 2007 Jocelyn Mayer
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#include "qemu/osdep.h"
  26#include "hw/hw.h"
  27#include "hw/ppc/mac.h"
  28
  29/* debug PIC */
  30//#define DEBUG_PIC
  31
  32#ifdef DEBUG_PIC
  33#define PIC_DPRINTF(fmt, ...)                                   \
  34    do { printf("PIC: " fmt , ## __VA_ARGS__); } while (0)
  35#else
  36#define PIC_DPRINTF(fmt, ...)
  37#endif
  38
  39typedef struct HeathrowPIC {
  40    uint32_t events;
  41    uint32_t mask;
  42    uint32_t levels;
  43    uint32_t level_triggered;
  44} HeathrowPIC;
  45
  46typedef struct HeathrowPICS {
  47    MemoryRegion mem;
  48    HeathrowPIC pics[2];
  49    qemu_irq *irqs;
  50} HeathrowPICS;
  51
  52static inline int check_irq(HeathrowPIC *pic)
  53{
  54    return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask;
  55}
  56
  57/* update the CPU irq state */
  58static void heathrow_pic_update(HeathrowPICS *s)
  59{
  60    if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
  61        qemu_irq_raise(s->irqs[0]);
  62    } else {
  63        qemu_irq_lower(s->irqs[0]);
  64    }
  65}
  66
  67static void pic_write(void *opaque, hwaddr addr,
  68                      uint64_t value, unsigned size)
  69{
  70    HeathrowPICS *s = opaque;
  71    HeathrowPIC *pic;
  72    unsigned int n;
  73
  74    n = ((addr & 0xfff) - 0x10) >> 4;
  75    PIC_DPRINTF("writel: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
  76    if (n >= 2)
  77        return;
  78    pic = &s->pics[n];
  79    switch(addr & 0xf) {
  80    case 0x04:
  81        pic->mask = value;
  82        heathrow_pic_update(s);
  83        break;
  84    case 0x08:
  85        /* do not reset level triggered IRQs */
  86        value &= ~pic->level_triggered;
  87        pic->events &= ~value;
  88        heathrow_pic_update(s);
  89        break;
  90    default:
  91        break;
  92    }
  93}
  94
  95static uint64_t pic_read(void *opaque, hwaddr addr,
  96                         unsigned size)
  97{
  98    HeathrowPICS *s = opaque;
  99    HeathrowPIC *pic;
 100    unsigned int n;
 101    uint32_t value;
 102
 103    n = ((addr & 0xfff) - 0x10) >> 4;
 104    if (n >= 2) {
 105        value = 0;
 106    } else {
 107        pic = &s->pics[n];
 108        switch(addr & 0xf) {
 109        case 0x0:
 110            value = pic->events;
 111            break;
 112        case 0x4:
 113            value = pic->mask;
 114            break;
 115        case 0xc:
 116            value = pic->levels;
 117            break;
 118        default:
 119            value = 0;
 120            break;
 121        }
 122    }
 123    PIC_DPRINTF("readl: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
 124    return value;
 125}
 126
 127static const MemoryRegionOps heathrow_pic_ops = {
 128    .read = pic_read,
 129    .write = pic_write,
 130    .endianness = DEVICE_LITTLE_ENDIAN,
 131};
 132
 133static void heathrow_pic_set_irq(void *opaque, int num, int level)
 134{
 135    HeathrowPICS *s = opaque;
 136    HeathrowPIC *pic;
 137    unsigned int irq_bit;
 138
 139#if defined(DEBUG)
 140    {
 141        static int last_level[64];
 142        if (last_level[num] != level) {
 143            PIC_DPRINTF("set_irq: num=0x%02x level=%d\n", num, level);
 144            last_level[num] = level;
 145        }
 146    }
 147#endif
 148    pic = &s->pics[1 - (num >> 5)];
 149    irq_bit = 1 << (num & 0x1f);
 150    if (level) {
 151        pic->events |= irq_bit & ~pic->level_triggered;
 152        pic->levels |= irq_bit;
 153    } else {
 154        pic->levels &= ~irq_bit;
 155    }
 156    heathrow_pic_update(s);
 157}
 158
 159static const VMStateDescription vmstate_heathrow_pic_one = {
 160    .name = "heathrow_pic_one",
 161    .version_id = 0,
 162    .minimum_version_id = 0,
 163    .fields = (VMStateField[]) {
 164        VMSTATE_UINT32(events, HeathrowPIC),
 165        VMSTATE_UINT32(mask, HeathrowPIC),
 166        VMSTATE_UINT32(levels, HeathrowPIC),
 167        VMSTATE_UINT32(level_triggered, HeathrowPIC),
 168        VMSTATE_END_OF_LIST()
 169    }
 170};
 171
 172static const VMStateDescription vmstate_heathrow_pic = {
 173    .name = "heathrow_pic",
 174    .version_id = 1,
 175    .minimum_version_id = 1,
 176    .fields = (VMStateField[]) {
 177        VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1,
 178                             vmstate_heathrow_pic_one, HeathrowPIC),
 179        VMSTATE_END_OF_LIST()
 180    }
 181};
 182
 183static void heathrow_pic_reset_one(HeathrowPIC *s)
 184{
 185    memset(s, '\0', sizeof(HeathrowPIC));
 186}
 187
 188static void heathrow_pic_reset(void *opaque)
 189{
 190    HeathrowPICS *s = opaque;
 191
 192    heathrow_pic_reset_one(&s->pics[0]);
 193    heathrow_pic_reset_one(&s->pics[1]);
 194
 195    s->pics[0].level_triggered = 0;
 196    s->pics[1].level_triggered = 0x1ff00000;
 197}
 198
 199qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
 200                            int nb_cpus, qemu_irq **irqs)
 201{
 202    HeathrowPICS *s;
 203
 204    s = g_malloc0(sizeof(HeathrowPICS));
 205    /* only 1 CPU */
 206    s->irqs = irqs[0];
 207    memory_region_init_io(&s->mem, NULL, &heathrow_pic_ops, s,
 208                          "heathrow-pic", 0x1000);
 209    *pmem = &s->mem;
 210
 211    vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
 212    qemu_register_reset(heathrow_pic_reset, s);
 213    return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
 214}
 215