diff options
-rw-r--r-- | hw/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/ide/microdrive.c | 170 | ||||
-rw-r--r-- | hw/misc/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/pcmcia/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/pcmcia/pcmcia.c | 24 | ||||
-rw-r--r-- | hw/pcmcia/pxa2xx.c (renamed from hw/misc/pxa2xx_pcmcia.c) | 50 | ||||
-rw-r--r-- | include/hw/pcmcia.h | 46 |
7 files changed, 219 insertions, 75 deletions
diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 0243d6aa0e..d91b9cc6c6 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -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/ diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 92c1df0460..cdf0eb9ce7 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -30,15 +30,22 @@ #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(µdrive_type_info); + type_register_static(&dscm1xxxx_type_info); +} + +type_init(microdrive_register_types) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 9fbcebd15b..f6743659f7 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -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/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs new file mode 100644 index 0000000000..4eac060c93 --- /dev/null +++ b/hw/pcmcia/Makefile.objs @@ -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 index 0000000000..78efe5a67a --- /dev/null +++ b/hw/pcmcia/pcmcia.c @@ -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/misc/pxa2xx_pcmcia.c b/hw/pcmcia/pxa2xx.c index 76724a6ac6..2c515bee06 100644 --- a/hw/misc/pxa2xx_pcmcia.c +++ b/hw/pcmcia/pxa2xx.c @@ -30,9 +30,11 @@ static uint64_t pxa2xx_pcmcia_common_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->common_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->common_read(s->card, offset); } return 0; @@ -42,9 +44,11 @@ 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) { - s->card->common_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->common_write(s->card, offset, value); } } @@ -52,9 +56,11 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->attr_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->attr_read(s->card, offset); } return 0; @@ -64,9 +70,11 @@ 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) { - s->card->attr_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->attr_write(s->card, offset, value); } } @@ -74,9 +82,11 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->io_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->io_read(s->card, offset); } return 0; @@ -86,9 +96,11 @@ 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) { - s->card->io_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->io_write(s->card, offset, value); } } @@ -161,18 +173,22 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (s->slot.attached) + 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 = 1; + s->slot.attached = true; s->card->slot = &s->slot; - s->card->attach(s->card->state); + pcc->attach(s->card); return 0; } @@ -181,19 +197,25 @@ int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) int pxa2xx_pcmcia_detach(void *opaque) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (!s->slot.attached) + PCMCIACardClass *pcc; + + if (!s->slot.attached) { return -ENOENT; + } - s->card->detach(s->card->state); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->detach(s->card); s->card->slot = NULL; s->card = NULL; - s->slot.attached = 0; + s->slot.attached = false; - if (s->irq) + if (s->irq) { qemu_irq_lower(s->irq); - if (s->cd_irq) + } + if (s->cd_irq) { qemu_irq_lower(s->cd_irq); + } return 0; } diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h index f91669305e..2695d3cba6 100644 --- a/include/hw/pcmcia.h +++ b/include/hw/pcmcia.h @@ -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 */ |