Skip to content

Commit

Permalink
pcmcia: QOM'ify PCMCIACardState and MicroDriveState
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
afaerber committed Nov 5, 2013
1 parent 853ca11 commit d1f2c96
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 75 deletions.
1 change: 1 addition & 0 deletions hw/Makefile.objs
Expand Up @@ -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/
Expand Down
170 changes: 123 additions & 47 deletions hw/ide/microdrive.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
1 change: 0 additions & 1 deletion hw/misc/Makefile.objs
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions hw/pcmcia/Makefile.objs
@@ -0,0 +1,2 @@
common-obj-y += pcmcia.o
obj-$(CONFIG_PXA2XX) += pxa2xx.o
24 changes: 24 additions & 0 deletions 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)

0 comments on commit d1f2c96

Please sign in to comment.