cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

pxa2xx.c (6885B)


      1/*
      2 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
      3 *
      4 * Copyright (c) 2006 Openedhand Ltd.
      5 * Written by Andrzej Zaborowski <balrog@zabor.org>
      6 *
      7 * This code is licensed under the GPLv2.
      8 *
      9 * Contributions after 2012-01-13 are licensed under the terms of the
     10 * GNU GPL, version 2 or (at your option) any later version.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "hw/irq.h"
     15#include "hw/sysbus.h"
     16#include "qapi/error.h"
     17#include "qemu/module.h"
     18#include "hw/pcmcia.h"
     19#include "hw/arm/pxa.h"
     20
     21struct PXA2xxPCMCIAState {
     22    SysBusDevice parent_obj;
     23
     24    PCMCIASocket slot;
     25    MemoryRegion container_mem;
     26    MemoryRegion common_iomem;
     27    MemoryRegion attr_iomem;
     28    MemoryRegion iomem;
     29
     30    qemu_irq irq;
     31    qemu_irq cd_irq;
     32
     33    PCMCIACardState *card;
     34};
     35
     36static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
     37                hwaddr offset, unsigned size)
     38{
     39    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     40    PCMCIACardClass *pcc;
     41
     42    if (s->slot.attached) {
     43        pcc = PCMCIA_CARD_GET_CLASS(s->card);
     44        return pcc->common_read(s->card, offset);
     45    }
     46
     47    return 0;
     48}
     49
     50static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
     51                                       uint64_t value, unsigned size)
     52{
     53    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     54    PCMCIACardClass *pcc;
     55
     56    if (s->slot.attached) {
     57        pcc = PCMCIA_CARD_GET_CLASS(s->card);
     58        pcc->common_write(s->card, offset, value);
     59    }
     60}
     61
     62static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
     63                hwaddr offset, unsigned size)
     64{
     65    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     66    PCMCIACardClass *pcc;
     67
     68    if (s->slot.attached) {
     69        pcc = PCMCIA_CARD_GET_CLASS(s->card);
     70        return pcc->attr_read(s->card, offset);
     71    }
     72
     73    return 0;
     74}
     75
     76static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
     77                                     uint64_t value, unsigned size)
     78{
     79    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     80    PCMCIACardClass *pcc;
     81
     82    if (s->slot.attached) {
     83        pcc = PCMCIA_CARD_GET_CLASS(s->card);
     84        pcc->attr_write(s->card, offset, value);
     85    }
     86}
     87
     88static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
     89                hwaddr offset, unsigned size)
     90{
     91    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     92    PCMCIACardClass *pcc;
     93
     94    if (s->slot.attached) {
     95        pcc = PCMCIA_CARD_GET_CLASS(s->card);
     96        return pcc->io_read(s->card, offset);
     97    }
     98
     99    return 0;
    100}
    101
    102static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
    103                                   uint64_t value, unsigned size)
    104{
    105    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
    106    PCMCIACardClass *pcc;
    107
    108    if (s->slot.attached) {
    109        pcc = PCMCIA_CARD_GET_CLASS(s->card);
    110        pcc->io_write(s->card, offset, value);
    111    }
    112}
    113
    114static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
    115    .read = pxa2xx_pcmcia_common_read,
    116    .write = pxa2xx_pcmcia_common_write,
    117    .endianness = DEVICE_NATIVE_ENDIAN
    118};
    119
    120static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
    121    .read = pxa2xx_pcmcia_attr_read,
    122    .write = pxa2xx_pcmcia_attr_write,
    123    .endianness = DEVICE_NATIVE_ENDIAN
    124};
    125
    126static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
    127    .read = pxa2xx_pcmcia_io_read,
    128    .write = pxa2xx_pcmcia_io_write,
    129    .endianness = DEVICE_NATIVE_ENDIAN
    130};
    131
    132static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
    133{
    134    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
    135    if (!s->irq)
    136        return;
    137
    138    qemu_set_irq(s->irq, level);
    139}
    140
    141PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
    142                                      hwaddr base)
    143{
    144    DeviceState *dev;
    145    PXA2xxPCMCIAState *s;
    146
    147    dev = qdev_new(TYPE_PXA2XX_PCMCIA);
    148    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
    149    s = PXA2XX_PCMCIA(dev);
    150
    151    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    152
    153    return s;
    154}
    155
    156static void pxa2xx_pcmcia_initfn(Object *obj)
    157{
    158    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    159    PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj);
    160
    161    memory_region_init(&s->container_mem, obj, "container", 0x10000000);
    162    sysbus_init_mmio(sbd, &s->container_mem);
    163
    164    /* Socket I/O Memory Space */
    165    memory_region_init_io(&s->iomem, obj, &pxa2xx_pcmcia_io_ops, s,
    166                          "pxa2xx-pcmcia-io", 0x04000000);
    167    memory_region_add_subregion(&s->container_mem, 0x00000000,
    168                                &s->iomem);
    169
    170    /* Then next 64 MB is reserved */
    171
    172    /* Socket Attribute Memory Space */
    173    memory_region_init_io(&s->attr_iomem, obj, &pxa2xx_pcmcia_attr_ops, s,
    174                          "pxa2xx-pcmcia-attribute", 0x04000000);
    175    memory_region_add_subregion(&s->container_mem, 0x08000000,
    176                                &s->attr_iomem);
    177
    178    /* Socket Common Memory Space */
    179    memory_region_init_io(&s->common_iomem, obj, &pxa2xx_pcmcia_common_ops, s,
    180                          "pxa2xx-pcmcia-common", 0x04000000);
    181    memory_region_add_subregion(&s->container_mem, 0x0c000000,
    182                                &s->common_iomem);
    183
    184    s->slot.irq = qemu_allocate_irq(pxa2xx_pcmcia_set_irq, s, 0);
    185
    186    object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
    187                             (Object **)&s->card,
    188                             NULL, /* read-only property */
    189                             0);
    190}
    191
    192/* Insert a new card into a slot */
    193int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
    194{
    195    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
    196    PCMCIACardClass *pcc;
    197
    198    if (s->slot.attached) {
    199        return -EEXIST;
    200    }
    201
    202    if (s->cd_irq) {
    203        qemu_irq_raise(s->cd_irq);
    204    }
    205
    206    s->card = card;
    207    pcc = PCMCIA_CARD_GET_CLASS(s->card);
    208
    209    s->slot.attached = true;
    210    s->card->slot = &s->slot;
    211    pcc->attach(s->card);
    212
    213    return 0;
    214}
    215
    216/* Eject card from the slot */
    217int pxa2xx_pcmcia_detach(void *opaque)
    218{
    219    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
    220    PCMCIACardClass *pcc;
    221
    222    if (!s->slot.attached) {
    223        return -ENOENT;
    224    }
    225
    226    pcc = PCMCIA_CARD_GET_CLASS(s->card);
    227    pcc->detach(s->card);
    228    s->card->slot = NULL;
    229    s->card = NULL;
    230
    231    s->slot.attached = false;
    232
    233    if (s->irq) {
    234        qemu_irq_lower(s->irq);
    235    }
    236    if (s->cd_irq) {
    237        qemu_irq_lower(s->cd_irq);
    238    }
    239
    240    return 0;
    241}
    242
    243/* Who to notify on card events */
    244void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
    245{
    246    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
    247    s->irq = irq;
    248    s->cd_irq = cd_irq;
    249}
    250
    251static const TypeInfo pxa2xx_pcmcia_type_info = {
    252    .name = TYPE_PXA2XX_PCMCIA,
    253    .parent = TYPE_SYS_BUS_DEVICE,
    254    .instance_size = sizeof(PXA2xxPCMCIAState),
    255    .instance_init = pxa2xx_pcmcia_initfn,
    256};
    257
    258static void pxa2xx_pcmcia_register_types(void)
    259{
    260    type_register_static(&pxa2xx_pcmcia_type_info);
    261}
    262
    263type_init(pxa2xx_pcmcia_register_types)