]> git.proxmox.com Git - qemu.git/commitdiff
pcmcia: QOM'ify PCMCIACardState and MicroDriveState
authorAndreas Färber <afaerber@suse.de>
Wed, 17 Jul 2013 17:46:16 +0000 (19:46 +0200)
committerAndreas Färber <afaerber@suse.de>
Tue, 5 Nov 2013 17:06:52 +0000 (18:06 +0100)
Turn PCMCIACardState into a device.
Move callbacks to new PCMCIACardClass.

Derive TYPE_MICRODRIVE from TYPE_PCMCIA_CARD.
Replace ide_init2_with_non_qdev_drives().

Signed-off-by: Othmar Pasteka <pasteka@kabsi.at>
Signed-off-by: Andreas Färber <afaerber@suse.de>
hw/Makefile.objs
hw/ide/microdrive.c
hw/misc/Makefile.objs
hw/misc/pxa2xx_pcmcia.c [deleted file]
hw/pcmcia/Makefile.objs [new file with mode: 0644]
hw/pcmcia/pcmcia.c [new file with mode: 0644]
hw/pcmcia/pxa2xx.c [new file with mode: 0644]
include/hw/pcmcia.h

index 0243d6aa0e6356d842c2ef7da6999c6efb3789f5..d91b9cc6c662a367a463c08234cfa48f8858ca49 100644 (file)
@@ -18,6 +18,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += net/
 devices-dirs-$(CONFIG_SOFTMMU) += nvram/
 devices-dirs-$(CONFIG_SOFTMMU) += pci/
 devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
+devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/
 devices-dirs-$(CONFIG_SOFTMMU) += scsi/
 devices-dirs-$(CONFIG_SOFTMMU) += sd/
 devices-dirs-$(CONFIG_SOFTMMU) += ssi/
index 92c1df0460f51b3cdfe7a4680f2fc6eadeb2c757..cdf0eb9ce7f56e54ca23ae26a993c21cea72a083 100644 (file)
 
 #include <hw/ide/internal.h>
 
+#define TYPE_MICRODRIVE "microdrive"
+#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
+
 /***********************************************************/
 /* CF-ATA Microdrive */
 
 #define METADATA_SIZE  0x20
 
 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
-typedef struct {
+
+typedef struct MicroDriveState {
+    /*< private >*/
+    PCMCIACardState parent_obj;
+    /*< public >*/
+
     IDEBus bus;
-    PCMCIACardState card;
     uint32_t attr_base;
     uint32_t io_base;
 
@@ -81,10 +88,13 @@ enum md_ctrl {
 
 static inline void md_interrupt_update(MicroDriveState *s)
 {
-    if (!s->card.slot)
+    PCMCIACardState *card = PCMCIA_CARD(s);
+
+    if (card->slot == NULL) {
         return;
+    }
 
-    qemu_set_irq(s->card.slot->irq,
+    qemu_set_irq(card->slot->irq,
                     !(s->stat & STAT_INT) &&   /* Inverted */
                     !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
                     !(s->opt & OPT_SRESET));
@@ -101,8 +111,10 @@ static void md_set_irq(void *opaque, int irq, int level)
     md_interrupt_update(s);
 }
 
-static void md_reset(MicroDriveState *s)
+static void md_reset(DeviceState *dev)
 {
+    MicroDriveState *s = MICRODRIVE(dev);
+
     s->opt = OPT_MODE_MMAP;
     s->stat = 0;
     s->pins = 0;
@@ -111,14 +123,17 @@ static void md_reset(MicroDriveState *s)
     ide_bus_reset(&s->bus);
 }
 
-static uint8_t md_attr_read(void *opaque, uint32_t at)
+static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
+    PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
+
     if (at < s->attr_base) {
-        if (at < s->card.cis_len)
-            return s->card.cis[at];
-        else
+        if (at < pcc->cis_len) {
+            return pcc->cis[at];
+        } else {
             return 0x00;
+        }
     }
 
     at -= s->attr_base;
@@ -144,16 +159,18 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
     return 0;
 }
 
-static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
+static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
+
     at -= s->attr_base;
 
     switch (at) {
     case 0x00: /* Configuration Option Register */
         s->opt = value & 0xcf;
-        if (value & OPT_SRESET)
-            md_reset(s);
+        if (value & OPT_SRESET) {
+            device_reset(DEVICE(s));
+        }
         md_interrupt_update(s);
         break;
     case 0x02: /* Card Configuration Status Register */
@@ -175,9 +192,9 @@ static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
     }
 }
 
-static uint16_t md_common_read(void *opaque, uint32_t at)
+static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
     IDEState *ifs;
     uint16_t ret;
     at -= s->io_base;
@@ -237,9 +254,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
     return 0;
 }
 
-static void md_common_write(void *opaque, uint32_t at, uint16_t value)
+static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
 {
-    MicroDriveState *s = opaque;
+    MicroDriveState *s = MICRODRIVE(card);
     at -= s->io_base;
 
     switch (s->opt & OPT_MODE) {
@@ -285,8 +302,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
         break;
     case 0xe:  /* Device Control */
         s->ctrl = value;
-        if (value & CTRL_SRST)
-            md_reset(s);
+        if (value & CTRL_SRST) {
+            device_reset(DEVICE(s));
+        }
         md_interrupt_update(s);
         break;
     default:
@@ -501,49 +519,107 @@ static const uint8_t dscm1xxxx_cis[0x14a] = {
     [0x146] = CISTPL_END,      /* Tuple End */
 };
 
-static int dscm1xxxx_attach(void *opaque)
+#define TYPE_DSCM1XXXX "dscm1xxxx"
+
+static int dscm1xxxx_attach(PCMCIACardState *card)
 {
-    MicroDriveState *md = opaque;
-    md->card.attr_read = md_attr_read;
-    md->card.attr_write = md_attr_write;
-    md->card.common_read = md_common_read;
-    md->card.common_write = md_common_write;
-    md->card.io_read = md_common_read;
-    md->card.io_write = md_common_write;
-
-    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
+    MicroDriveState *md = MICRODRIVE(card);
+    PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
+
+    md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
     md->io_base = 0x0;
 
-    md_reset(md);
+    device_reset(DEVICE(md));
     md_interrupt_update(md);
 
-    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
+    card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
     return 0;
 }
 
-static int dscm1xxxx_detach(void *opaque)
+static int dscm1xxxx_detach(PCMCIACardState *card)
 {
-    MicroDriveState *md = opaque;
-    md_reset(md);
+    MicroDriveState *md = MICRODRIVE(card);
+
+    device_reset(DEVICE(md));
     return 0;
 }
 
-PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
+PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
 {
-    MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState));
-    md->card.state = md;
-    md->card.attach = dscm1xxxx_attach;
-    md->card.detach = dscm1xxxx_detach;
-    md->card.cis = dscm1xxxx_cis;
-    md->card.cis_len = sizeof(dscm1xxxx_cis);
-
-    ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
-                                   qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    MicroDriveState *md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
+    PCMCIACardState *card = PCMCIA_CARD(md);
+
+    if (dinfo != NULL) {
+        ide_create_drive(&md->bus, 0, dinfo);
+    }
     md->bus.ifs[0].drive_kind = IDE_CFATA;
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE);
 
-    vmstate_register(NULL, -1, &vmstate_microdrive, md);
+    return card;
+}
+
+static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
+{
+    PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
+
+    pcc->cis = dscm1xxxx_cis;
+    pcc->cis_len = sizeof(dscm1xxxx_cis);
+
+    pcc->attach = dscm1xxxx_attach;
+    pcc->detach = dscm1xxxx_detach;
+}
+
+static const TypeInfo dscm1xxxx_type_info = {
+    .name = TYPE_DSCM1XXXX,
+    .parent = TYPE_MICRODRIVE,
+    .class_init = dscm1xxxx_class_init,
+};
+
+static void microdrive_realize(DeviceState *dev, Error **errp)
+{
+    MicroDriveState *md = MICRODRIVE(dev);
+
+    ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+}
+
+static void microdrive_init(Object *obj)
+{
+    MicroDriveState *md = MICRODRIVE(obj);
+
+    ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
+}
 
-    return &md->card;
+static void microdrive_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
+
+    pcc->attr_read = md_attr_read;
+    pcc->attr_write = md_attr_write;
+    pcc->common_read = md_common_read;
+    pcc->common_write = md_common_write;
+    pcc->io_read = md_common_read;
+    pcc->io_write = md_common_write;
+
+    dc->realize = microdrive_realize;
+    dc->reset = md_reset;
+    dc->vmsd = &vmstate_microdrive;
 }
+
+static const TypeInfo microdrive_type_info = {
+    .name = TYPE_MICRODRIVE,
+    .parent = TYPE_PCMCIA_CARD,
+    .instance_size = sizeof(MicroDriveState),
+    .instance_init = microdrive_init,
+    .abstract = true,
+    .class_init = microdrive_class_init,
+};
+
+static void microdrive_register_types(void)
+{
+    type_register_static(&microdrive_type_info);
+    type_register_static(&dscm1xxxx_type_info);
+}
+
+type_init(microdrive_register_types)
index 9fbcebd15b8efb90426d81c1058946455a35020e..f6743659f7c5a0b695160f4336e3fd8cf9af0f48 100644 (file)
@@ -38,7 +38,6 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o
 obj-$(CONFIG_OMAP) += omap_l4.o
 obj-$(CONFIG_OMAP) += omap_sdrc.o
 obj-$(CONFIG_OMAP) += omap_tap.o
-obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 
diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/misc/pxa2xx_pcmcia.c
deleted file mode 100644 (file)
index 76724a6..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This code is licensed under the GPLv2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/hw.h"
-#include "hw/pcmcia.h"
-#include "hw/arm/pxa.h"
-
-
-struct PXA2xxPCMCIAState {
-    PCMCIASocket slot;
-    PCMCIACardState *card;
-    MemoryRegion common_iomem;
-    MemoryRegion attr_iomem;
-    MemoryRegion iomem;
-
-    qemu_irq irq;
-    qemu_irq cd_irq;
-};
-
-static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
-                hwaddr offset, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        return s->card->common_read(s->card->state, offset);
-    }
-
-    return 0;
-}
-
-static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
-                                       uint64_t value, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        s->card->common_write(s->card->state, offset, value);
-    }
-}
-
-static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
-                hwaddr offset, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        return s->card->attr_read(s->card->state, offset);
-    }
-
-    return 0;
-}
-
-static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
-                                     uint64_t value, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        s->card->attr_write(s->card->state, offset, value);
-    }
-}
-
-static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
-                hwaddr offset, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        return s->card->io_read(s->card->state, offset);
-    }
-
-    return 0;
-}
-
-static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
-                                   uint64_t value, unsigned size)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-
-    if (s->slot.attached) {
-        s->card->io_write(s->card->state, offset, value);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
-    .read = pxa2xx_pcmcia_common_read,
-    .write = pxa2xx_pcmcia_common_write,
-    .endianness = DEVICE_NATIVE_ENDIAN
-};
-
-static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
-    .read = pxa2xx_pcmcia_attr_read,
-    .write = pxa2xx_pcmcia_attr_write,
-    .endianness = DEVICE_NATIVE_ENDIAN
-};
-
-static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
-    .read = pxa2xx_pcmcia_io_read,
-    .write = pxa2xx_pcmcia_io_write,
-    .endianness = DEVICE_NATIVE_ENDIAN
-};
-
-static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    if (!s->irq)
-        return;
-
-    qemu_set_irq(s->irq, level);
-}
-
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
-                                      hwaddr base)
-{
-    PXA2xxPCMCIAState *s;
-
-    s = (PXA2xxPCMCIAState *)
-            g_malloc0(sizeof(PXA2xxPCMCIAState));
-
-    /* Socket I/O Memory Space */
-    memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
-                          "pxa2xx-pcmcia-io", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x00000000,
-                                &s->iomem);
-
-    /* Then next 64 MB is reserved */
-
-    /* Socket Attribute Memory Space */
-    memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
-                          "pxa2xx-pcmcia-attribute", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x08000000,
-                                &s->attr_iomem);
-
-    /* Socket Common Memory Space */
-    memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
-                          "pxa2xx-pcmcia-common", 0x04000000);
-    memory_region_add_subregion(sysmem, base | 0x0c000000,
-                                &s->common_iomem);
-
-    if (base == 0x30000000)
-        s->slot.slot_string = "PXA PC Card Socket 1";
-    else
-        s->slot.slot_string = "PXA PC Card Socket 0";
-    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
-    pcmcia_socket_register(&s->slot);
-
-    return s;
-}
-
-/* Insert a new card into a slot */
-int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    if (s->slot.attached)
-        return -EEXIST;
-
-    if (s->cd_irq) {
-        qemu_irq_raise(s->cd_irq);
-    }
-
-    s->card = card;
-
-    s->slot.attached = 1;
-    s->card->slot = &s->slot;
-    s->card->attach(s->card->state);
-
-    return 0;
-}
-
-/* Eject card from the slot */
-int pxa2xx_pcmcia_detach(void *opaque)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    if (!s->slot.attached)
-        return -ENOENT;
-
-    s->card->detach(s->card->state);
-    s->card->slot = NULL;
-    s->card = NULL;
-
-    s->slot.attached = 0;
-
-    if (s->irq)
-        qemu_irq_lower(s->irq);
-    if (s->cd_irq)
-        qemu_irq_lower(s->cd_irq);
-
-    return 0;
-}
-
-/* Who to notify on card events */
-void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
-{
-    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
-    s->irq = irq;
-    s->cd_irq = cd_irq;
-}
diff --git a/hw/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs
new file mode 100644 (file)
index 0000000..4eac060
--- /dev/null
@@ -0,0 +1,2 @@
+common-obj-y += pcmcia.o
+obj-$(CONFIG_PXA2XX) += pxa2xx.o
diff --git a/hw/pcmcia/pcmcia.c b/hw/pcmcia/pcmcia.c
new file mode 100644 (file)
index 0000000..78efe5a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * PCMCIA emulation
+ *
+ * Copyright 2013 SUSE LINUX Products GmbH
+ */
+
+#include "qemu-common.h"
+#include "hw/hw.h"
+#include "hw/pcmcia.h"
+
+static const TypeInfo pcmcia_card_type_info = {
+    .name = TYPE_PCMCIA_CARD,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(PCMCIACardState),
+    .abstract = true,
+    .class_size = sizeof(PCMCIACardClass),
+};
+
+static void pcmcia_register_types(void)
+{
+    type_register_static(&pcmcia_card_type_info);
+}
+
+type_init(pcmcia_register_types)
diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c
new file mode 100644 (file)
index 0000000..2c515be
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GPLv2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pcmcia.h"
+#include "hw/arm/pxa.h"
+
+
+struct PXA2xxPCMCIAState {
+    PCMCIASocket slot;
+    PCMCIACardState *card;
+    MemoryRegion common_iomem;
+    MemoryRegion attr_iomem;
+    MemoryRegion iomem;
+
+    qemu_irq irq;
+    qemu_irq cd_irq;
+};
+
+static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
+                hwaddr offset, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->common_read(s->card, offset);
+    }
+
+    return 0;
+}
+
+static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
+                                       uint64_t value, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->common_write(s->card, offset, value);
+    }
+}
+
+static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
+                hwaddr offset, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->attr_read(s->card, offset);
+    }
+
+    return 0;
+}
+
+static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->attr_write(s->card, offset, value);
+    }
+}
+
+static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
+                hwaddr offset, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        return pcc->io_read(s->card, offset);
+    }
+
+    return 0;
+}
+
+static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
+                                   uint64_t value, unsigned size)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        pcc = PCMCIA_CARD_GET_CLASS(s->card);
+        pcc->io_write(s->card, offset, value);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
+    .read = pxa2xx_pcmcia_common_read,
+    .write = pxa2xx_pcmcia_common_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
+};
+
+static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
+    .read = pxa2xx_pcmcia_attr_read,
+    .write = pxa2xx_pcmcia_attr_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
+};
+
+static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
+    .read = pxa2xx_pcmcia_io_read,
+    .write = pxa2xx_pcmcia_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN
+};
+
+static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    if (!s->irq)
+        return;
+
+    qemu_set_irq(s->irq, level);
+}
+
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+                                      hwaddr base)
+{
+    PXA2xxPCMCIAState *s;
+
+    s = (PXA2xxPCMCIAState *)
+            g_malloc0(sizeof(PXA2xxPCMCIAState));
+
+    /* Socket I/O Memory Space */
+    memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
+                          "pxa2xx-pcmcia-io", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x00000000,
+                                &s->iomem);
+
+    /* Then next 64 MB is reserved */
+
+    /* Socket Attribute Memory Space */
+    memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
+                          "pxa2xx-pcmcia-attribute", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x08000000,
+                                &s->attr_iomem);
+
+    /* Socket Common Memory Space */
+    memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
+                          "pxa2xx-pcmcia-common", 0x04000000);
+    memory_region_add_subregion(sysmem, base | 0x0c000000,
+                                &s->common_iomem);
+
+    if (base == 0x30000000)
+        s->slot.slot_string = "PXA PC Card Socket 1";
+    else
+        s->slot.slot_string = "PXA PC Card Socket 0";
+    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
+    pcmcia_socket_register(&s->slot);
+
+    return s;
+}
+
+/* Insert a new card into a slot */
+int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (s->slot.attached) {
+        return -EEXIST;
+    }
+
+    if (s->cd_irq) {
+        qemu_irq_raise(s->cd_irq);
+    }
+
+    s->card = card;
+    pcc = PCMCIA_CARD_GET_CLASS(s->card);
+
+    s->slot.attached = true;
+    s->card->slot = &s->slot;
+    pcc->attach(s->card);
+
+    return 0;
+}
+
+/* Eject card from the slot */
+int pxa2xx_pcmcia_detach(void *opaque)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    PCMCIACardClass *pcc;
+
+    if (!s->slot.attached) {
+        return -ENOENT;
+    }
+
+    pcc = PCMCIA_CARD_GET_CLASS(s->card);
+    pcc->detach(s->card);
+    s->card->slot = NULL;
+    s->card = NULL;
+
+    s->slot.attached = false;
+
+    if (s->irq) {
+        qemu_irq_lower(s->irq);
+    }
+    if (s->cd_irq) {
+        qemu_irq_lower(s->cd_irq);
+    }
+
+    return 0;
+}
+
+/* Who to notify on card events */
+void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
+{
+    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
+    s->irq = irq;
+    s->cd_irq = cd_irq;
+}
index f91669305e1e158ce24f29b0049d4305078576c2..2695d3cba6198d43b298cc78eeb0cec535e6e43a 100644 (file)
@@ -3,11 +3,11 @@
 
 /* PCMCIA/Cardbus */
 
-#include "qemu-common.h"
+#include "hw/qdev.h"
 
-typedef struct {
+typedef struct PCMCIASocket {
     qemu_irq irq;
-    int attached;
+    bool attached;
     const char *slot_string;
     const char *card_string;
 } PCMCIASocket;
@@ -16,22 +16,42 @@ void pcmcia_socket_register(PCMCIASocket *socket);
 void pcmcia_socket_unregister(PCMCIASocket *socket);
 void pcmcia_info(Monitor *mon, const QDict *qdict);
 
+#define TYPE_PCMCIA_CARD "pcmcia-card"
+#define PCMCIA_CARD(obj) \
+    OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
+#define PCMCIA_CARD_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
+#define PCMCIA_CARD_CLASS(cls) \
+    OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
+
 struct PCMCIACardState {
-    void *state;
+    /*< private >*/
+    DeviceState parent_obj;
+    /*< public >*/
+
     PCMCIASocket *slot;
-    int (*attach)(void *state);
-    int (*detach)(void *state);
+};
+
+typedef struct PCMCIACardClass {
+    /*< private >*/
+    DeviceClass parent_class;
+    /*< public >*/
+
+    int (*attach)(PCMCIACardState *state);
+    int (*detach)(PCMCIACardState *state);
+
     const uint8_t *cis;
     int cis_len;
 
     /* Only valid if attached */
-    uint8_t (*attr_read)(void *state, uint32_t address);
-    void (*attr_write)(void *state, uint32_t address, uint8_t value);
-    uint16_t (*common_read)(void *state, uint32_t address);
-    void (*common_write)(void *state, uint32_t address, uint16_t value);
-    uint16_t (*io_read)(void *state, uint32_t address);
-    void (*io_write)(void *state, uint32_t address, uint16_t value);
-};
+    uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
+    void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
+    uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
+    void (*common_write)(PCMCIACardState *card,
+                         uint32_t address, uint16_t value);
+    uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
+    void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
+} PCMCIACardClass;
 
 #define CISTPL_DEVICE          0x01    /* 5V Device Information Tuple */
 #define CISTPL_NO_LINK         0x14    /* No Link Tuple */