|
@@ -30,15 +30,22 @@
|
|
|
|
|
|
#include <hw/ide/internal.h>
|
|
#include <hw/ide/internal.h>
|
|
|
|
|
|
|
|
+#define TYPE_MICRODRIVE "microdrive"
|
|
|
|
+#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
|
|
|
|
+
|
|
/***********************************************************/
|
|
/***********************************************************/
|
|
/* CF-ATA Microdrive */
|
|
/* CF-ATA Microdrive */
|
|
|
|
|
|
#define METADATA_SIZE 0x20
|
|
#define METADATA_SIZE 0x20
|
|
|
|
|
|
/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
|
|
/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */
|
|
-typedef struct {
|
|
|
|
|
|
+
|
|
|
|
+typedef struct MicroDriveState {
|
|
|
|
+ /*< private >*/
|
|
|
|
+ PCMCIACardState parent_obj;
|
|
|
|
+ /*< public >*/
|
|
|
|
+
|
|
IDEBus bus;
|
|
IDEBus bus;
|
|
- PCMCIACardState card;
|
|
|
|
uint32_t attr_base;
|
|
uint32_t attr_base;
|
|
uint32_t io_base;
|
|
uint32_t io_base;
|
|
|
|
|
|
@@ -81,10 +88,13 @@ enum md_ctrl {
|
|
|
|
|
|
static inline void md_interrupt_update(MicroDriveState *s)
|
|
static inline void md_interrupt_update(MicroDriveState *s)
|
|
{
|
|
{
|
|
- if (!s->card.slot)
|
|
|
|
|
|
+ PCMCIACardState *card = PCMCIA_CARD(s);
|
|
|
|
+
|
|
|
|
+ if (card->slot == NULL) {
|
|
return;
|
|
return;
|
|
|
|
+ }
|
|
|
|
|
|
- qemu_set_irq(s->card.slot->irq,
|
|
|
|
|
|
+ qemu_set_irq(card->slot->irq,
|
|
!(s->stat & STAT_INT) && /* Inverted */
|
|
!(s->stat & STAT_INT) && /* Inverted */
|
|
!(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
|
|
!(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
|
|
!(s->opt & OPT_SRESET));
|
|
!(s->opt & OPT_SRESET));
|
|
@@ -101,8 +111,10 @@ static void md_set_irq(void *opaque, int irq, int level)
|
|
md_interrupt_update(s);
|
|
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->opt = OPT_MODE_MMAP;
|
|
s->stat = 0;
|
|
s->stat = 0;
|
|
s->pins = 0;
|
|
s->pins = 0;
|
|
@@ -111,14 +123,17 @@ static void md_reset(MicroDriveState *s)
|
|
ide_bus_reset(&s->bus);
|
|
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->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;
|
|
return 0x00;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
at -= s->attr_base;
|
|
at -= s->attr_base;
|
|
@@ -144,16 +159,18 @@ static uint8_t md_attr_read(void *opaque, uint32_t at)
|
|
return 0;
|
|
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;
|
|
at -= s->attr_base;
|
|
|
|
|
|
switch (at) {
|
|
switch (at) {
|
|
case 0x00: /* Configuration Option Register */
|
|
case 0x00: /* Configuration Option Register */
|
|
s->opt = value & 0xcf;
|
|
s->opt = value & 0xcf;
|
|
- if (value & OPT_SRESET)
|
|
|
|
- md_reset(s);
|
|
|
|
|
|
+ if (value & OPT_SRESET) {
|
|
|
|
+ device_reset(DEVICE(s));
|
|
|
|
+ }
|
|
md_interrupt_update(s);
|
|
md_interrupt_update(s);
|
|
break;
|
|
break;
|
|
case 0x02: /* Card Configuration Status Register */
|
|
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;
|
|
IDEState *ifs;
|
|
uint16_t ret;
|
|
uint16_t ret;
|
|
at -= s->io_base;
|
|
at -= s->io_base;
|
|
@@ -237,9 +254,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at)
|
|
return 0;
|
|
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;
|
|
at -= s->io_base;
|
|
|
|
|
|
switch (s->opt & OPT_MODE) {
|
|
switch (s->opt & OPT_MODE) {
|
|
@@ -285,8 +302,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value)
|
|
break;
|
|
break;
|
|
case 0xe: /* Device Control */
|
|
case 0xe: /* Device Control */
|
|
s->ctrl = value;
|
|
s->ctrl = value;
|
|
- if (value & CTRL_SRST)
|
|
|
|
- md_reset(s);
|
|
|
|
|
|
+ if (value & CTRL_SRST) {
|
|
|
|
+ device_reset(DEVICE(s));
|
|
|
|
+ }
|
|
md_interrupt_update(s);
|
|
md_interrupt_update(s);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -501,49 +519,107 @@ static const uint8_t dscm1xxxx_cis[0x14a] = {
|
|
[0x146] = CISTPL_END, /* Tuple End */
|
|
[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->io_base = 0x0;
|
|
|
|
|
|
- md_reset(md);
|
|
|
|
|
|
+ device_reset(DEVICE(md));
|
|
md_interrupt_update(md);
|
|
md_interrupt_update(md);
|
|
|
|
|
|
- md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
|
|
|
|
|
|
+ card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
|
|
return 0;
|
|
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;
|
|
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].drive_kind = IDE_CFATA;
|
|
md->bus.ifs[0].mdata_size = METADATA_SIZE;
|
|
md->bus.ifs[0].mdata_size = METADATA_SIZE;
|
|
md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(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)
|