qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

microdrive.c (19874B)


      1 /*
      2  * QEMU IDE Emulation: microdrive (CF / PCMCIA)
      3  *
      4  * Copyright (c) 2003 Fabrice Bellard
      5  * Copyright (c) 2006 Openedhand Ltd.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  */
     25 
     26 #include "qemu/osdep.h"
     27 #include "hw/pcmcia.h"
     28 #include "migration/vmstate.h"
     29 #include "qapi/error.h"
     30 #include "qemu/module.h"
     31 #include "sysemu/dma.h"
     32 
     33 #include "hw/ide/internal.h"
     34 #include "qom/object.h"
     35 
     36 #define TYPE_MICRODRIVE "microdrive"
     37 OBJECT_DECLARE_SIMPLE_TYPE(MicroDriveState, MICRODRIVE)
     38 
     39 /***********************************************************/
     40 /* CF-ATA Microdrive */
     41 
     42 #define METADATA_SIZE	0x20
     43 
     44 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
     45 
     46 struct MicroDriveState {
     47     /*< private >*/
     48     PCMCIACardState parent_obj;
     49     /*< public >*/
     50 
     51     IDEBus bus;
     52     uint32_t attr_base;
     53     uint32_t io_base;
     54 
     55     /* Card state */
     56     uint8_t opt;
     57     uint8_t stat;
     58     uint8_t pins;
     59 
     60     uint8_t ctrl;
     61     uint16_t io;
     62     uint8_t cycle;
     63 };
     64 
     65 /* Register bitfields */
     66 enum md_opt {
     67     OPT_MODE_MMAP	= 0,
     68     OPT_MODE_IOMAP16	= 1,
     69     OPT_MODE_IOMAP1	= 2,
     70     OPT_MODE_IOMAP2	= 3,
     71     OPT_MODE		= 0x3f,
     72     OPT_LEVIREQ		= 0x40,
     73     OPT_SRESET		= 0x80,
     74 };
     75 enum md_cstat {
     76     STAT_INT		= 0x02,
     77     STAT_PWRDWN		= 0x04,
     78     STAT_XE		= 0x10,
     79     STAT_IOIS8		= 0x20,
     80     STAT_SIGCHG		= 0x40,
     81     STAT_CHANGED	= 0x80,
     82 };
     83 enum md_pins {
     84     PINS_MRDY		= 0x02,
     85     PINS_CRDY		= 0x20,
     86 };
     87 enum md_ctrl {
     88     CTRL_IEN		= 0x02,
     89     CTRL_SRST		= 0x04,
     90 };
     91 
     92 static inline void md_interrupt_update(MicroDriveState *s)
     93 {
     94     PCMCIACardState *card = PCMCIA_CARD(s);
     95 
     96     if (card->slot == NULL) {
     97         return;
     98     }
     99 
    100     qemu_set_irq(card->slot->irq,
    101                     !(s->stat & STAT_INT) &&	/* Inverted */
    102                     !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
    103                     !(s->opt & OPT_SRESET));
    104 }
    105 
    106 static void md_set_irq(void *opaque, int irq, int level)
    107 {
    108     MicroDriveState *s = opaque;
    109 
    110     if (level) {
    111         s->stat |= STAT_INT;
    112     } else {
    113         s->stat &= ~STAT_INT;
    114     }
    115 
    116     md_interrupt_update(s);
    117 }
    118 
    119 static void md_reset(DeviceState *dev)
    120 {
    121     MicroDriveState *s = MICRODRIVE(dev);
    122 
    123     s->opt = OPT_MODE_MMAP;
    124     s->stat = 0;
    125     s->pins = 0;
    126     s->cycle = 0;
    127     s->ctrl = 0;
    128     ide_bus_reset(&s->bus);
    129 }
    130 
    131 static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at)
    132 {
    133     MicroDriveState *s = MICRODRIVE(card);
    134     PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
    135 
    136     if (at < s->attr_base) {
    137         if (at < pcc->cis_len) {
    138             return pcc->cis[at];
    139         } else {
    140             return 0x00;
    141         }
    142     }
    143 
    144     at -= s->attr_base;
    145 
    146     switch (at) {
    147     case 0x00:	/* Configuration Option Register */
    148         return s->opt;
    149     case 0x02:	/* Card Configuration Status Register */
    150         if (s->ctrl & CTRL_IEN) {
    151             return s->stat & ~STAT_INT;
    152         } else {
    153             return s->stat;
    154         }
    155     case 0x04:	/* Pin Replacement Register */
    156         return (s->pins & PINS_CRDY) | 0x0c;
    157     case 0x06:	/* Socket and Copy Register */
    158         return 0x00;
    159 #ifdef VERBOSE
    160     default:
    161         printf("%s: Bad attribute space register %02x\n", __func__, at);
    162 #endif
    163     }
    164 
    165     return 0;
    166 }
    167 
    168 static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
    169 {
    170     MicroDriveState *s = MICRODRIVE(card);
    171 
    172     at -= s->attr_base;
    173 
    174     switch (at) {
    175     case 0x00:	/* Configuration Option Register */
    176         s->opt = value & 0xcf;
    177         if (value & OPT_SRESET) {
    178             device_cold_reset(DEVICE(s));
    179         }
    180         md_interrupt_update(s);
    181         break;
    182     case 0x02:	/* Card Configuration Status Register */
    183         if ((s->stat ^ value) & STAT_PWRDWN) {
    184             s->pins |= PINS_CRDY;
    185         }
    186         s->stat &= 0x82;
    187         s->stat |= value & 0x74;
    188         md_interrupt_update(s);
    189         /* Word 170 in Identify Device must be equal to STAT_XE */
    190         break;
    191     case 0x04:	/* Pin Replacement Register */
    192         s->pins &= PINS_CRDY;
    193         s->pins |= value & PINS_MRDY;
    194         break;
    195     case 0x06:	/* Socket and Copy Register */
    196         break;
    197     default:
    198         printf("%s: Bad attribute space register %02x\n", __func__, at);
    199     }
    200 }
    201 
    202 static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
    203 {
    204     MicroDriveState *s = MICRODRIVE(card);
    205     IDEState *ifs;
    206     uint16_t ret;
    207     at -= s->io_base;
    208 
    209     switch (s->opt & OPT_MODE) {
    210     case OPT_MODE_MMAP:
    211         if ((at & ~0x3ff) == 0x400) {
    212             at = 0;
    213         }
    214         break;
    215     case OPT_MODE_IOMAP16:
    216         at &= 0xf;
    217         break;
    218     case OPT_MODE_IOMAP1:
    219         if ((at & ~0xf) == 0x3f0) {
    220             at -= 0x3e8;
    221         } else if ((at & ~0xf) == 0x1f0) {
    222             at -= 0x1f0;
    223         }
    224         break;
    225     case OPT_MODE_IOMAP2:
    226         if ((at & ~0xf) == 0x370) {
    227             at -= 0x368;
    228         } else if ((at & ~0xf) == 0x170) {
    229             at -= 0x170;
    230         }
    231     }
    232 
    233     switch (at) {
    234     case 0x0:	/* Even RD Data */
    235     case 0x8:
    236         return ide_data_readw(&s->bus, 0);
    237 
    238         /* TODO: 8-bit accesses */
    239         if (s->cycle) {
    240             ret = s->io >> 8;
    241         } else {
    242             s->io = ide_data_readw(&s->bus, 0);
    243             ret = s->io & 0xff;
    244         }
    245         s->cycle = !s->cycle;
    246         return ret;
    247     case 0x9:	/* Odd RD Data */
    248         return s->io >> 8;
    249     case 0xd:	/* Error */
    250         return ide_ioport_read(&s->bus, 0x1);
    251     case 0xe:	/* Alternate Status */
    252         ifs = idebus_active_if(&s->bus);
    253         if (ifs->blk) {
    254             return ifs->status;
    255         } else {
    256             return 0;
    257         }
    258     case 0xf:	/* Device Address */
    259         ifs = idebus_active_if(&s->bus);
    260         return 0xc2 | ((~ifs->select << 2) & 0x3c);
    261     default:
    262         return ide_ioport_read(&s->bus, at);
    263     }
    264 
    265     return 0;
    266 }
    267 
    268 static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
    269 {
    270     MicroDriveState *s = MICRODRIVE(card);
    271     at -= s->io_base;
    272 
    273     switch (s->opt & OPT_MODE) {
    274     case OPT_MODE_MMAP:
    275         if ((at & ~0x3ff) == 0x400) {
    276             at = 0;
    277         }
    278         break;
    279     case OPT_MODE_IOMAP16:
    280         at &= 0xf;
    281         break;
    282     case OPT_MODE_IOMAP1:
    283         if ((at & ~0xf) == 0x3f0) {
    284             at -= 0x3e8;
    285         } else if ((at & ~0xf) == 0x1f0) {
    286             at -= 0x1f0;
    287         }
    288         break;
    289     case OPT_MODE_IOMAP2:
    290         if ((at & ~0xf) == 0x370) {
    291             at -= 0x368;
    292         } else if ((at & ~0xf) == 0x170) {
    293             at -= 0x170;
    294         }
    295     }
    296 
    297     switch (at) {
    298     case 0x0:	/* Even WR Data */
    299     case 0x8:
    300         ide_data_writew(&s->bus, 0, value);
    301         break;
    302 
    303         /* TODO: 8-bit accesses */
    304         if (s->cycle) {
    305             ide_data_writew(&s->bus, 0, s->io | (value << 8));
    306         } else {
    307             s->io = value & 0xff;
    308         }
    309         s->cycle = !s->cycle;
    310         break;
    311     case 0x9:
    312         s->io = value & 0xff;
    313         s->cycle = !s->cycle;
    314         break;
    315     case 0xd:	/* Features */
    316         ide_ioport_write(&s->bus, 0x1, value);
    317         break;
    318     case 0xe:	/* Device Control */
    319         s->ctrl = value;
    320         if (value & CTRL_SRST) {
    321             device_cold_reset(DEVICE(s));
    322         }
    323         md_interrupt_update(s);
    324         break;
    325     default:
    326         if (s->stat & STAT_PWRDWN) {
    327             s->pins |= PINS_CRDY;
    328             s->stat &= ~STAT_PWRDWN;
    329         }
    330         ide_ioport_write(&s->bus, at, value);
    331     }
    332 }
    333 
    334 static const VMStateDescription vmstate_microdrive = {
    335     .name = "microdrive",
    336     .version_id = 3,
    337     .minimum_version_id = 0,
    338     .fields = (VMStateField[]) {
    339         VMSTATE_UINT8(opt, MicroDriveState),
    340         VMSTATE_UINT8(stat, MicroDriveState),
    341         VMSTATE_UINT8(pins, MicroDriveState),
    342         VMSTATE_UINT8(ctrl, MicroDriveState),
    343         VMSTATE_UINT16(io, MicroDriveState),
    344         VMSTATE_UINT8(cycle, MicroDriveState),
    345         VMSTATE_IDE_BUS(bus, MicroDriveState),
    346         VMSTATE_IDE_DRIVES(bus.ifs, MicroDriveState),
    347         VMSTATE_END_OF_LIST()
    348     }
    349 };
    350 
    351 static const uint8_t dscm1xxxx_cis[0x14a] = {
    352     [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
    353     [0x002] = 0x03,		/* Tuple length = 4 bytes */
    354     [0x004] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
    355     [0x006] = 0x01,		/* Size = 2K bytes */
    356     [0x008] = CISTPL_ENDMARK,
    357 
    358     [0x00a] = CISTPL_DEVICE_OC,	/* Additional Device Information */
    359     [0x00c] = 0x04,		/* Tuple length = 4 byest */
    360     [0x00e] = 0x03,		/* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
    361     [0x010] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
    362     [0x012] = 0x01,		/* Size = 2K bytes */
    363     [0x014] = CISTPL_ENDMARK,
    364 
    365     [0x016] = CISTPL_JEDEC_C,	/* JEDEC ID */
    366     [0x018] = 0x02,		/* Tuple length = 2 bytes */
    367     [0x01a] = 0xdf,		/* PC Card ATA with no Vpp required */
    368     [0x01c] = 0x01,
    369 
    370     [0x01e] = CISTPL_MANFID,	/* Manufacture ID */
    371     [0x020] = 0x04,		/* Tuple length = 4 bytes */
    372     [0x022] = 0xa4,		/* TPLMID_MANF = 00a4 (IBM) */
    373     [0x024] = 0x00,
    374     [0x026] = 0x00,		/* PLMID_CARD = 0000 */
    375     [0x028] = 0x00,
    376 
    377     [0x02a] = CISTPL_VERS_1,	/* Level 1 Version */
    378     [0x02c] = 0x12,		/* Tuple length = 23 bytes */
    379     [0x02e] = 0x04,		/* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
    380     [0x030] = 0x01,		/* Minor Version = 1 */
    381     [0x032] = 'I',
    382     [0x034] = 'B',
    383     [0x036] = 'M',
    384     [0x038] = 0x00,
    385     [0x03a] = 'm',
    386     [0x03c] = 'i',
    387     [0x03e] = 'c',
    388     [0x040] = 'r',
    389     [0x042] = 'o',
    390     [0x044] = 'd',
    391     [0x046] = 'r',
    392     [0x048] = 'i',
    393     [0x04a] = 'v',
    394     [0x04c] = 'e',
    395     [0x04e] = 0x00,
    396     [0x050] = CISTPL_ENDMARK,
    397 
    398     [0x052] = CISTPL_FUNCID,	/* Function ID */
    399     [0x054] = 0x02,		/* Tuple length = 2 bytes */
    400     [0x056] = 0x04,		/* TPLFID_FUNCTION = Fixed Disk */
    401     [0x058] = 0x01,		/* TPLFID_SYSINIT: POST = 1, ROM = 0 */
    402 
    403     [0x05a] = CISTPL_FUNCE,	/* Function Extension */
    404     [0x05c] = 0x02,		/* Tuple length = 2 bytes */
    405     [0x05e] = 0x01,		/* TPLFE_TYPE = Disk Device Interface */
    406     [0x060] = 0x01,		/* TPLFE_DATA = PC Card ATA Interface */
    407 
    408     [0x062] = CISTPL_FUNCE,	/* Function Extension */
    409     [0x064] = 0x03,		/* Tuple length = 3 bytes */
    410     [0x066] = 0x02,		/* TPLFE_TYPE = Basic PC Card ATA Interface */
    411     [0x068] = 0x08,		/* TPLFE_DATA: Rotating, Unique, Single */
    412     [0x06a] = 0x0f,		/* TPLFE_DATA: Sleep, Standby, Idle, Auto */
    413 
    414     [0x06c] = CISTPL_CONFIG,	/* Configuration */
    415     [0x06e] = 0x05,		/* Tuple length = 5 bytes */
    416     [0x070] = 0x01,		/* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
    417     [0x072] = 0x07,		/* TPCC_LAST = 7 */
    418     [0x074] = 0x00,		/* TPCC_RADR = 0200 */
    419     [0x076] = 0x02,
    420     [0x078] = 0x0f,		/* TPCC_RMSK = 200, 202, 204, 206 */
    421 
    422     [0x07a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    423     [0x07c] = 0x0b,		/* Tuple length = 11 bytes */
    424     [0x07e] = 0xc0,		/* TPCE_INDX = Memory Mode, Default, Iface */
    425     [0x080] = 0xc0,		/* TPCE_IF = Memory, no BVDs, no WP, READY */
    426     [0x082] = 0xa1,		/* TPCE_FS = Vcc only, no I/O, Memory, Misc */
    427     [0x084] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
    428     [0x086] = 0x55,		/* NomV: 5.0 V */
    429     [0x088] = 0x4d,		/* MinV: 4.5 V */
    430     [0x08a] = 0x5d,		/* MaxV: 5.5 V */
    431     [0x08c] = 0x4e,		/* Peakl: 450 mA */
    432     [0x08e] = 0x08,		/* TPCE_MS = 1 window, 1 byte, Host address */
    433     [0x090] = 0x00,		/* Window descriptor: Window length = 0 */
    434     [0x092] = 0x20,		/* TPCE_MI: support power down mode, RW */
    435 
    436     [0x094] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    437     [0x096] = 0x06,		/* Tuple length = 6 bytes */
    438     [0x098] = 0x00,		/* TPCE_INDX = Memory Mode, no Default */
    439     [0x09a] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
    440     [0x09c] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
    441     [0x09e] = 0xb5,		/* NomV: 3.3 V */
    442     [0x0a0] = 0x1e,
    443     [0x0a2] = 0x3e,		/* Peakl: 350 mA */
    444 
    445     [0x0a4] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    446     [0x0a6] = 0x0d,		/* Tuple length = 13 bytes */
    447     [0x0a8] = 0xc1,		/* TPCE_INDX = I/O and Memory Mode, Default */
    448     [0x0aa] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
    449     [0x0ac] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
    450     [0x0ae] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
    451     [0x0b0] = 0x55,		/* NomV: 5.0 V */
    452     [0x0b2] = 0x4d,		/* MinV: 4.5 V */
    453     [0x0b4] = 0x5d,		/* MaxV: 5.5 V */
    454     [0x0b6] = 0x4e,		/* Peakl: 450 mA */
    455     [0x0b8] = 0x64,		/* TPCE_IO = 16-byte boundary, 16/8 accesses */
    456     [0x0ba] = 0xf0,		/* TPCE_IR =  MASK, Level, Pulse, Share */
    457     [0x0bc] = 0xff,		/* IRQ0..IRQ7 supported */
    458     [0x0be] = 0xff,		/* IRQ8..IRQ15 supported */
    459     [0x0c0] = 0x20,		/* TPCE_MI = support power down mode */
    460 
    461     [0x0c2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    462     [0x0c4] = 0x06,		/* Tuple length = 6 bytes */
    463     [0x0c6] = 0x01,		/* TPCE_INDX = I/O and Memory Mode */
    464     [0x0c8] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
    465     [0x0ca] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
    466     [0x0cc] = 0xb5,		/* NomV: 3.3 V */
    467     [0x0ce] = 0x1e,
    468     [0x0d0] = 0x3e,		/* Peakl: 350 mA */
    469 
    470     [0x0d2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    471     [0x0d4] = 0x12,		/* Tuple length = 18 bytes */
    472     [0x0d6] = 0xc2,		/* TPCE_INDX = I/O Primary Mode */
    473     [0x0d8] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
    474     [0x0da] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
    475     [0x0dc] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
    476     [0x0de] = 0x55,		/* NomV: 5.0 V */
    477     [0x0e0] = 0x4d,		/* MinV: 4.5 V */
    478     [0x0e2] = 0x5d,		/* MaxV: 5.5 V */
    479     [0x0e4] = 0x4e,		/* Peakl: 450 mA */
    480     [0x0e6] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
    481     [0x0e8] = 0x61,		/* Range: 2 fields, 2 bytes addr, 1 byte len */
    482     [0x0ea] = 0xf0,		/* Field 1 address = 0x01f0 */
    483     [0x0ec] = 0x01,
    484     [0x0ee] = 0x07,		/* Address block length = 8 */
    485     [0x0f0] = 0xf6,		/* Field 2 address = 0x03f6 */
    486     [0x0f2] = 0x03,
    487     [0x0f4] = 0x01,		/* Address block length = 2 */
    488     [0x0f6] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
    489     [0x0f8] = 0x20,		/* TPCE_MI = support power down mode */
    490 
    491     [0x0fa] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    492     [0x0fc] = 0x06,		/* Tuple length = 6 bytes */
    493     [0x0fe] = 0x02,		/* TPCE_INDX = I/O Primary Mode, no Default */
    494     [0x100] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
    495     [0x102] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
    496     [0x104] = 0xb5,		/* NomV: 3.3 V */
    497     [0x106] = 0x1e,
    498     [0x108] = 0x3e,		/* Peakl: 350 mA */
    499 
    500     [0x10a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    501     [0x10c] = 0x12,		/* Tuple length = 18 bytes */
    502     [0x10e] = 0xc3,		/* TPCE_INDX = I/O Secondary Mode, Default */
    503     [0x110] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
    504     [0x112] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
    505     [0x114] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
    506     [0x116] = 0x55,		/* NomV: 5.0 V */
    507     [0x118] = 0x4d,		/* MinV: 4.5 V */
    508     [0x11a] = 0x5d,		/* MaxV: 5.5 V */
    509     [0x11c] = 0x4e,		/* Peakl: 450 mA */
    510     [0x11e] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
    511     [0x120] = 0x61,		/* Range: 2 fields, 2 byte addr, 1 byte len */
    512     [0x122] = 0x70,		/* Field 1 address = 0x0170 */
    513     [0x124] = 0x01,
    514     [0x126] = 0x07,		/* Address block length = 8 */
    515     [0x128] = 0x76,		/* Field 2 address = 0x0376 */
    516     [0x12a] = 0x03,
    517     [0x12c] = 0x01,		/* Address block length = 2 */
    518     [0x12e] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
    519     [0x130] = 0x20,		/* TPCE_MI = support power down mode */
    520 
    521     [0x132] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
    522     [0x134] = 0x06,		/* Tuple length = 6 bytes */
    523     [0x136] = 0x03,		/* TPCE_INDX = I/O Secondary Mode */
    524     [0x138] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
    525     [0x13a] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
    526     [0x13c] = 0xb5,		/* NomV: 3.3 V */
    527     [0x13e] = 0x1e,
    528     [0x140] = 0x3e,		/* Peakl: 350 mA */
    529 
    530     [0x142] = CISTPL_NO_LINK,	/* No Link */
    531     [0x144] = 0x00,		/* Tuple length = 0 bytes */
    532 
    533     [0x146] = CISTPL_END,	/* Tuple End */
    534 };
    535 
    536 #define TYPE_DSCM1XXXX "dscm1xxxx"
    537 
    538 static int dscm1xxxx_attach(PCMCIACardState *card)
    539 {
    540     MicroDriveState *md = MICRODRIVE(card);
    541     PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card);
    542 
    543     md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
    544     md->io_base = 0x0;
    545 
    546     device_cold_reset(DEVICE(md));
    547     md_interrupt_update(md);
    548 
    549     return 0;
    550 }
    551 
    552 static int dscm1xxxx_detach(PCMCIACardState *card)
    553 {
    554     MicroDriveState *md = MICRODRIVE(card);
    555 
    556     device_cold_reset(DEVICE(md));
    557     return 0;
    558 }
    559 
    560 PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
    561 {
    562     MicroDriveState *md;
    563 
    564     md = MICRODRIVE(object_new(TYPE_DSCM1XXXX));
    565     qdev_realize(DEVICE(md), NULL, &error_fatal);
    566 
    567     if (dinfo != NULL) {
    568         ide_create_drive(&md->bus, 0, dinfo);
    569     }
    570     md->bus.ifs[0].drive_kind = IDE_CFATA;
    571     md->bus.ifs[0].mdata_size = METADATA_SIZE;
    572     md->bus.ifs[0].mdata_storage = g_malloc0(METADATA_SIZE);
    573 
    574     return PCMCIA_CARD(md);
    575 }
    576 
    577 static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
    578 {
    579     PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
    580     DeviceClass *dc = DEVICE_CLASS(oc);
    581 
    582     pcc->cis = dscm1xxxx_cis;
    583     pcc->cis_len = sizeof(dscm1xxxx_cis);
    584 
    585     pcc->attach = dscm1xxxx_attach;
    586     pcc->detach = dscm1xxxx_detach;
    587     /* Reason: Needs to be wired-up in code, see dscm1xxxx_init() */
    588     dc->user_creatable = false;
    589 }
    590 
    591 static const TypeInfo dscm1xxxx_type_info = {
    592     .name = TYPE_DSCM1XXXX,
    593     .parent = TYPE_MICRODRIVE,
    594     .class_init = dscm1xxxx_class_init,
    595 };
    596 
    597 static void microdrive_realize(DeviceState *dev, Error **errp)
    598 {
    599     MicroDriveState *md = MICRODRIVE(dev);
    600 
    601     ide_init2(&md->bus, qemu_allocate_irq(md_set_irq, md, 0));
    602 }
    603 
    604 static void microdrive_init(Object *obj)
    605 {
    606     MicroDriveState *md = MICRODRIVE(obj);
    607 
    608     ide_bus_init(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
    609 }
    610 
    611 static void microdrive_class_init(ObjectClass *oc, void *data)
    612 {
    613     DeviceClass *dc = DEVICE_CLASS(oc);
    614     PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
    615 
    616     pcc->attr_read = md_attr_read;
    617     pcc->attr_write = md_attr_write;
    618     pcc->common_read = md_common_read;
    619     pcc->common_write = md_common_write;
    620     pcc->io_read = md_common_read;
    621     pcc->io_write = md_common_write;
    622 
    623     dc->realize = microdrive_realize;
    624     dc->reset = md_reset;
    625     dc->vmsd = &vmstate_microdrive;
    626 }
    627 
    628 static const TypeInfo microdrive_type_info = {
    629     .name = TYPE_MICRODRIVE,
    630     .parent = TYPE_PCMCIA_CARD,
    631     .instance_size = sizeof(MicroDriveState),
    632     .instance_init = microdrive_init,
    633     .abstract = true,
    634     .class_init = microdrive_class_init,
    635 };
    636 
    637 static void microdrive_register_types(void)
    638 {
    639     type_register_static(&microdrive_type_info);
    640     type_register_static(&dscm1xxxx_type_info);
    641 }
    642 
    643 type_init(microdrive_register_types)