qemu/hw/pxa2xx_pcmcia.c
<<
>>
Prefs
   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 "hw.h"
  14#include "pcmcia.h"
  15#include "pxa.h"
  16
  17
  18struct PXA2xxPCMCIAState {
  19    PCMCIASocket slot;
  20    PCMCIACardState *card;
  21    MemoryRegion common_iomem;
  22    MemoryRegion attr_iomem;
  23    MemoryRegion iomem;
  24
  25    qemu_irq irq;
  26    qemu_irq cd_irq;
  27};
  28
  29static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
  30                hwaddr offset, unsigned size)
  31{
  32    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  33
  34    if (s->slot.attached) {
  35        return s->card->common_read(s->card->state, offset);
  36    }
  37
  38    return 0;
  39}
  40
  41static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
  42                                       uint64_t value, unsigned size)
  43{
  44    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  45
  46    if (s->slot.attached) {
  47        s->card->common_write(s->card->state, offset, value);
  48    }
  49}
  50
  51static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
  52                hwaddr offset, unsigned size)
  53{
  54    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  55
  56    if (s->slot.attached) {
  57        return s->card->attr_read(s->card->state, offset);
  58    }
  59
  60    return 0;
  61}
  62
  63static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
  64                                     uint64_t value, unsigned size)
  65{
  66    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  67
  68    if (s->slot.attached) {
  69        s->card->attr_write(s->card->state, offset, value);
  70    }
  71}
  72
  73static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
  74                hwaddr offset, unsigned size)
  75{
  76    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  77
  78    if (s->slot.attached) {
  79        return s->card->io_read(s->card->state, offset);
  80    }
  81
  82    return 0;
  83}
  84
  85static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
  86                                   uint64_t value, unsigned size)
  87{
  88    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
  89
  90    if (s->slot.attached) {
  91        s->card->io_write(s->card->state, offset, value);
  92    }
  93}
  94
  95static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
  96    .read = pxa2xx_pcmcia_common_read,
  97    .write = pxa2xx_pcmcia_common_write,
  98    .endianness = DEVICE_NATIVE_ENDIAN
  99};
 100
 101static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
 102    .read = pxa2xx_pcmcia_attr_read,
 103    .write = pxa2xx_pcmcia_attr_write,
 104    .endianness = DEVICE_NATIVE_ENDIAN
 105};
 106
 107static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
 108    .read = pxa2xx_pcmcia_io_read,
 109    .write = pxa2xx_pcmcia_io_write,
 110    .endianness = DEVICE_NATIVE_ENDIAN
 111};
 112
 113static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
 114{
 115    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 116    if (!s->irq)
 117        return;
 118
 119    qemu_set_irq(s->irq, level);
 120}
 121
 122PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
 123                                      hwaddr base)
 124{
 125    PXA2xxPCMCIAState *s;
 126
 127    s = (PXA2xxPCMCIAState *)
 128            g_malloc0(sizeof(PXA2xxPCMCIAState));
 129
 130    /* Socket I/O Memory Space */
 131    memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
 132                          "pxa2xx-pcmcia-io", 0x04000000);
 133    memory_region_add_subregion(sysmem, base | 0x00000000,
 134                                &s->iomem);
 135
 136    /* Then next 64 MB is reserved */
 137
 138    /* Socket Attribute Memory Space */
 139    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
 140                          "pxa2xx-pcmcia-attribute", 0x04000000);
 141    memory_region_add_subregion(sysmem, base | 0x08000000,
 142                                &s->attr_iomem);
 143
 144    /* Socket Common Memory Space */
 145    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
 146                          "pxa2xx-pcmcia-common", 0x04000000);
 147    memory_region_add_subregion(sysmem, base | 0x0c000000,
 148                                &s->common_iomem);
 149
 150    if (base == 0x30000000)
 151        s->slot.slot_string = "PXA PC Card Socket 1";
 152    else
 153        s->slot.slot_string = "PXA PC Card Socket 0";
 154    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
 155    pcmcia_socket_register(&s->slot);
 156
 157    return s;
 158}
 159
 160/* Insert a new card into a slot */
 161int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
 162{
 163    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 164    if (s->slot.attached)
 165        return -EEXIST;
 166
 167    if (s->cd_irq) {
 168        qemu_irq_raise(s->cd_irq);
 169    }
 170
 171    s->card = card;
 172
 173    s->slot.attached = 1;
 174    s->card->slot = &s->slot;
 175    s->card->attach(s->card->state);
 176
 177    return 0;
 178}
 179
 180/* Eject card from the slot */
 181int pxa2xx_pcmcia_dettach(void *opaque)
 182{
 183    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 184    if (!s->slot.attached)
 185        return -ENOENT;
 186
 187    s->card->detach(s->card->state);
 188    s->card->slot = NULL;
 189    s->card = NULL;
 190
 191    s->slot.attached = 0;
 192
 193    if (s->irq)
 194        qemu_irq_lower(s->irq);
 195    if (s->cd_irq)
 196        qemu_irq_lower(s->cd_irq);
 197
 198    return 0;
 199}
 200
 201/* Who to notify on card events */
 202void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
 203{
 204    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
 205    s->irq = irq;
 206    s->cd_irq = cd_irq;
 207}
 208