xref: /qemu/hw/ide/ide-dev.c (revision 5325cc34a2ca985283134c7e264be7851b112d4e)
1da4d0419SGerd Hoffmann /*
2da4d0419SGerd Hoffmann  * ide bus support for qdev.
3da4d0419SGerd Hoffmann  *
4da4d0419SGerd Hoffmann  * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
5da4d0419SGerd Hoffmann  *
6da4d0419SGerd Hoffmann  * This library is free software; you can redistribute it and/or
7da4d0419SGerd Hoffmann  * modify it under the terms of the GNU Lesser General Public
8da4d0419SGerd Hoffmann  * License as published by the Free Software Foundation; either
9da4d0419SGerd Hoffmann  * version 2 of the License, or (at your option) any later version.
10da4d0419SGerd Hoffmann  *
11da4d0419SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
12da4d0419SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13da4d0419SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14da4d0419SGerd Hoffmann  * Lesser General Public License for more details.
15da4d0419SGerd Hoffmann  *
16da4d0419SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
17da4d0419SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18da4d0419SGerd Hoffmann  */
190b8fa32fSMarkus Armbruster 
2053239262SPeter Maydell #include "qemu/osdep.h"
219c17d615SPaolo Bonzini #include "sysemu/dma.h"
22da34e65cSMarkus Armbruster #include "qapi/error.h"
232ae16a6aSMarkus Armbruster #include "qapi/qapi-types-block.h"
241de7afc9SPaolo Bonzini #include "qemu/error-report.h"
25db725815SMarkus Armbruster #include "qemu/main-loop.h"
260b8fa32fSMarkus Armbruster #include "qemu/module.h"
27a9c94277SMarkus Armbruster #include "hw/ide/internal.h"
28a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
29fa1d36dfSMarkus Armbruster #include "sysemu/block-backend.h"
309c17d615SPaolo Bonzini #include "sysemu/blockdev.h"
310d09e41aSPaolo Bonzini #include "hw/block/block.h"
329c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
3354d31236SMarkus Armbruster #include "sysemu/runstate.h"
3445563630SGonglei #include "qapi/visitor.h"
35da4d0419SGerd Hoffmann 
36da4d0419SGerd Hoffmann /* --------------------------------- */
37da4d0419SGerd Hoffmann 
38dc1a46b6SGleb Natapov static char *idebus_get_fw_dev_path(DeviceState *dev);
39b69c3c21SMarkus Armbruster static void idebus_unrealize(BusState *qdev);
40dc1a46b6SGleb Natapov 
413cb75a7cSPaolo Bonzini static Property ide_props[] = {
423cb75a7cSPaolo Bonzini     DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
433cb75a7cSPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
443cb75a7cSPaolo Bonzini };
453cb75a7cSPaolo Bonzini 
460d936928SAnthony Liguori static void ide_bus_class_init(ObjectClass *klass, void *data)
470d936928SAnthony Liguori {
480d936928SAnthony Liguori     BusClass *k = BUS_CLASS(klass);
490d936928SAnthony Liguori 
500d936928SAnthony Liguori     k->get_fw_dev_path = idebus_get_fw_dev_path;
5144a109c1SLi Qiang     k->unrealize = idebus_unrealize;
520d936928SAnthony Liguori }
530d936928SAnthony Liguori 
54b69c3c21SMarkus Armbruster static void idebus_unrealize(BusState *bus)
55ca44141dSAshijeet Acharya {
5644a109c1SLi Qiang     IDEBus *ibus = IDE_BUS(bus);
57ca44141dSAshijeet Acharya 
5844a109c1SLi Qiang     if (ibus->vmstate) {
5944a109c1SLi Qiang         qemu_del_vm_change_state_handler(ibus->vmstate);
60ca44141dSAshijeet Acharya     }
61ca44141dSAshijeet Acharya }
62ca44141dSAshijeet Acharya 
630d936928SAnthony Liguori static const TypeInfo ide_bus_info = {
640d936928SAnthony Liguori     .name = TYPE_IDE_BUS,
650d936928SAnthony Liguori     .parent = TYPE_BUS,
660d936928SAnthony Liguori     .instance_size = sizeof(IDEBus),
670d936928SAnthony Liguori     .class_init = ide_bus_class_init,
68da4d0419SGerd Hoffmann };
69da4d0419SGerd Hoffmann 
70c6baf942SAndreas Färber void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
71c6baf942SAndreas Färber                  int bus_id, int max_units)
72da4d0419SGerd Hoffmann {
73fb17dfe0SAndreas Färber     qbus_create_inplace(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL);
743835510fSGleb Natapov     idebus->bus_id = bus_id;
750ee20e66SKevin Wolf     idebus->max_units = max_units;
76da4d0419SGerd Hoffmann }
77da4d0419SGerd Hoffmann 
78dc1a46b6SGleb Natapov static char *idebus_get_fw_dev_path(DeviceState *dev)
79dc1a46b6SGleb Natapov {
80dc1a46b6SGleb Natapov     char path[30];
81dc1a46b6SGleb Natapov 
8228fa7133SMarkus Armbruster     snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev),
83dc1a46b6SGleb Natapov              ((IDEBus*)dev->parent_bus)->bus_id);
84dc1a46b6SGleb Natapov 
85a5cf8262SJim Meyering     return g_strdup(path);
86dc1a46b6SGleb Natapov }
87dc1a46b6SGleb Natapov 
88794939e8SMao Zhongyi static void ide_qdev_realize(DeviceState *qdev, Error **errp)
89da4d0419SGerd Hoffmann {
90d148211cSAnthony Liguori     IDEDevice *dev = IDE_DEVICE(qdev);
91d148211cSAnthony Liguori     IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
92da4d0419SGerd Hoffmann     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
93da4d0419SGerd Hoffmann 
94da4d0419SGerd Hoffmann     if (dev->unit == -1) {
95da4d0419SGerd Hoffmann         dev->unit = bus->master ? 1 : 0;
96da4d0419SGerd Hoffmann     }
970ee20e66SKevin Wolf 
980ee20e66SKevin Wolf     if (dev->unit >= bus->max_units) {
99794939e8SMao Zhongyi         error_setg(errp, "Can't create IDE unit %d, bus supports only %d units",
1000ee20e66SKevin Wolf                      dev->unit, bus->max_units);
101794939e8SMao Zhongyi         return;
1020ee20e66SKevin Wolf     }
1030ee20e66SKevin Wolf 
104da4d0419SGerd Hoffmann     switch (dev->unit) {
105da4d0419SGerd Hoffmann     case 0:
106da4d0419SGerd Hoffmann         if (bus->master) {
107794939e8SMao Zhongyi             error_setg(errp, "IDE unit %d is in use", dev->unit);
108794939e8SMao Zhongyi             return;
109da4d0419SGerd Hoffmann         }
110da4d0419SGerd Hoffmann         bus->master = dev;
111da4d0419SGerd Hoffmann         break;
112da4d0419SGerd Hoffmann     case 1:
113da4d0419SGerd Hoffmann         if (bus->slave) {
114794939e8SMao Zhongyi             error_setg(errp, "IDE unit %d is in use", dev->unit);
115794939e8SMao Zhongyi             return;
116da4d0419SGerd Hoffmann         }
117da4d0419SGerd Hoffmann         bus->slave = dev;
118da4d0419SGerd Hoffmann         break;
119da4d0419SGerd Hoffmann     default:
120794939e8SMao Zhongyi         error_setg(errp, "Invalid IDE unit %d", dev->unit);
121794939e8SMao Zhongyi         return;
122da4d0419SGerd Hoffmann     }
123794939e8SMao Zhongyi     dc->realize(dev, errp);
124da4d0419SGerd Hoffmann }
125da4d0419SGerd Hoffmann 
126da4d0419SGerd Hoffmann IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
127da4d0419SGerd Hoffmann {
128da4d0419SGerd Hoffmann     DeviceState *dev;
129da4d0419SGerd Hoffmann 
1303e80f690SMarkus Armbruster     dev = qdev_new(drive->media_cd ? "ide-cd" : "ide-hd");
131da4d0419SGerd Hoffmann     qdev_prop_set_uint32(dev, "unit", unit);
132934df912SMarkus Armbruster     qdev_prop_set_drive_err(dev, "drive", blk_by_legacy_dinfo(drive),
1336231a6daSMarkus Armbruster                             &error_fatal);
1343e80f690SMarkus Armbruster     qdev_realize_and_unref(dev, &bus->qbus, &error_fatal);
135da4d0419SGerd Hoffmann     return DO_UPCAST(IDEDevice, qdev, dev);
136da4d0419SGerd Hoffmann }
137da4d0419SGerd Hoffmann 
1389139046cSMarkus Armbruster int ide_get_geometry(BusState *bus, int unit,
1399139046cSMarkus Armbruster                      int16_t *cyls, int8_t *heads, int8_t *secs)
140c0897e0cSMarkus Armbruster {
1419139046cSMarkus Armbruster     IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit];
1429139046cSMarkus Armbruster 
1434be74634SMarkus Armbruster     if (s->drive_kind != IDE_HD || !s->blk) {
1449139046cSMarkus Armbruster         return -1;
1459139046cSMarkus Armbruster     }
1469139046cSMarkus Armbruster 
1479139046cSMarkus Armbruster     *cyls = s->cylinders;
1489139046cSMarkus Armbruster     *heads = s->heads;
1499139046cSMarkus Armbruster     *secs = s->sectors;
1509139046cSMarkus Armbruster     return 0;
1519139046cSMarkus Armbruster }
1529139046cSMarkus Armbruster 
1539139046cSMarkus Armbruster int ide_get_bios_chs_trans(BusState *bus, int unit)
1549139046cSMarkus Armbruster {
1559139046cSMarkus Armbruster     return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans;
156c0897e0cSMarkus Armbruster }
157c0897e0cSMarkus Armbruster 
158da4d0419SGerd Hoffmann /* --------------------------------- */
159da4d0419SGerd Hoffmann 
160da4d0419SGerd Hoffmann typedef struct IDEDrive {
161da4d0419SGerd Hoffmann     IDEDevice dev;
162da4d0419SGerd Hoffmann } IDEDrive;
163da4d0419SGerd Hoffmann 
164794939e8SMao Zhongyi static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
165da4d0419SGerd Hoffmann {
166da4d0419SGerd Hoffmann     IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
1676ced55a5SMarkus Armbruster     IDEState *s = bus->ifs + dev->unit;
168947231adSKevin Wolf     int ret;
1696ced55a5SMarkus Armbruster 
17067c75f3dSKevin Wolf     if (!dev->conf.blk) {
17167c75f3dSKevin Wolf         if (kind != IDE_CD) {
172794939e8SMao Zhongyi             error_setg(errp, "No drive specified");
173794939e8SMao Zhongyi             return;
17467c75f3dSKevin Wolf         } else {
17567c75f3dSKevin Wolf             /* Anonymous BlockBackend for an empty drive */
176d861ab3aSKevin Wolf             dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
177947231adSKevin Wolf             ret = blk_attach_dev(dev->conf.blk, &dev->qdev);
178947231adSKevin Wolf             assert(ret == 0);
17967c75f3dSKevin Wolf         }
18067c75f3dSKevin Wolf     }
18167c75f3dSKevin Wolf 
182215e47b9SPaolo Bonzini     if (dev->conf.discard_granularity == -1) {
183215e47b9SPaolo Bonzini         dev->conf.discard_granularity = 512;
184215e47b9SPaolo Bonzini     } else if (dev->conf.discard_granularity &&
185215e47b9SPaolo Bonzini                dev->conf.discard_granularity != 512) {
186794939e8SMao Zhongyi         error_setg(errp, "discard_granularity must be 512 for ide");
187794939e8SMao Zhongyi         return;
188d353fb72SChristoph Hellwig     }
189d353fb72SChristoph Hellwig 
190c56ee92fSRoman Kagan     if (!blkconf_blocksizes(&dev->conf, errp)) {
191c56ee92fSRoman Kagan         return;
192c56ee92fSRoman Kagan     }
193c56ee92fSRoman Kagan 
194d2005185SKevin Wolf     if (dev->conf.logical_block_size != 512) {
195794939e8SMao Zhongyi         error_setg(errp, "logical_block_size must be 512 for IDE");
196794939e8SMao Zhongyi         return;
197d2005185SKevin Wolf     }
198d2005185SKevin Wolf 
1995ff5efb4SFam Zheng     if (kind != IDE_CD) {
200ceff3e1fSMao Zhongyi         if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
201ceff3e1fSMao Zhongyi                               errp)) {
202794939e8SMao Zhongyi             return;
203ba801960SMarkus Armbruster         }
2045ff5efb4SFam Zheng     }
205ceff3e1fSMao Zhongyi     if (!blkconf_apply_backend_options(&dev->conf, kind == IDE_CD,
206ceff3e1fSMao Zhongyi                                        kind != IDE_CD, errp)) {
207794939e8SMao Zhongyi         return;
208a17c17a2SKevin Wolf     }
209ba801960SMarkus Armbruster 
2104be74634SMarkus Armbruster     if (ide_init_drive(s, dev->conf.blk, kind,
211911525dbSMarkus Armbruster                        dev->version, dev->serial, dev->model, dev->wwn,
212ba801960SMarkus Armbruster                        dev->conf.cyls, dev->conf.heads, dev->conf.secs,
213794939e8SMao Zhongyi                        dev->chs_trans, errp) < 0) {
214794939e8SMao Zhongyi         return;
215c4d74df7SMarkus Armbruster     }
2166ced55a5SMarkus Armbruster 
21703432407SMarkus Armbruster     if (!dev->version) {
2187267c094SAnthony Liguori         dev->version = g_strdup(s->version);
21903432407SMarkus Armbruster     }
2206ced55a5SMarkus Armbruster     if (!dev->serial) {
2217267c094SAnthony Liguori         dev->serial = g_strdup(s->drive_serial_str);
2226ced55a5SMarkus Armbruster     }
2231ca4d09aSGleb Natapov 
2241ca4d09aSGleb Natapov     add_boot_device_path(dev->conf.bootindex, &dev->qdev,
2251ca4d09aSGleb Natapov                          dev->unit ? "/disk@1" : "/disk@0");
22671f571a2SSam Eiderman 
22771f571a2SSam Eiderman     add_boot_device_lchs(&dev->qdev, dev->unit ? "/disk@1" : "/disk@0",
22871f571a2SSam Eiderman                          dev->conf.lcyls,
22971f571a2SSam Eiderman                          dev->conf.lheads,
23071f571a2SSam Eiderman                          dev->conf.lsecs);
231da4d0419SGerd Hoffmann }
232da4d0419SGerd Hoffmann 
233d7bce999SEric Blake static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
234d7bce999SEric Blake                                   void *opaque, Error **errp)
23545563630SGonglei {
23645563630SGonglei     IDEDevice *d = IDE_DEVICE(obj);
23745563630SGonglei 
23851e72bc1SEric Blake     visit_type_int32(v, name, &d->conf.bootindex, errp);
23945563630SGonglei }
24045563630SGonglei 
241d7bce999SEric Blake static void ide_dev_set_bootindex(Object *obj, Visitor *v, const char *name,
242d7bce999SEric Blake                                   void *opaque, Error **errp)
24345563630SGonglei {
24445563630SGonglei     IDEDevice *d = IDE_DEVICE(obj);
24545563630SGonglei     int32_t boot_index;
24645563630SGonglei     Error *local_err = NULL;
24745563630SGonglei 
24814217038SMarkus Armbruster     if (!visit_type_int32(v, name, &boot_index, errp)) {
24914217038SMarkus Armbruster         return;
25045563630SGonglei     }
25145563630SGonglei     /* check whether bootindex is present in fw_boot_order list  */
25245563630SGonglei     check_boot_index(boot_index, &local_err);
25345563630SGonglei     if (local_err) {
25445563630SGonglei         goto out;
25545563630SGonglei     }
25645563630SGonglei     /* change bootindex to a new one */
25745563630SGonglei     d->conf.bootindex = boot_index;
25845563630SGonglei 
259d2b186f9SGonglei     if (d->unit != -1) {
260d2b186f9SGonglei         add_boot_device_path(d->conf.bootindex, &d->qdev,
261d2b186f9SGonglei                              d->unit ? "/disk@1" : "/disk@0");
262d2b186f9SGonglei     }
26345563630SGonglei out:
26445563630SGonglei     error_propagate(errp, local_err);
26545563630SGonglei }
26645563630SGonglei 
26745563630SGonglei static void ide_dev_instance_init(Object *obj)
26845563630SGonglei {
26945563630SGonglei     object_property_add(obj, "bootindex", "int32",
27045563630SGonglei                         ide_dev_get_bootindex,
271d2623129SMarkus Armbruster                         ide_dev_set_bootindex, NULL, NULL);
272*5325cc34SMarkus Armbruster     object_property_set_int(obj, "bootindex", -1, NULL);
27345563630SGonglei }
27445563630SGonglei 
275794939e8SMao Zhongyi static void ide_hd_realize(IDEDevice *dev, Error **errp)
2761f56e32aSMarkus Armbruster {
277794939e8SMao Zhongyi     ide_dev_initfn(dev, IDE_HD, errp);
2781f56e32aSMarkus Armbruster }
2791f56e32aSMarkus Armbruster 
280794939e8SMao Zhongyi static void ide_cd_realize(IDEDevice *dev, Error **errp)
2811f56e32aSMarkus Armbruster {
282794939e8SMao Zhongyi     ide_dev_initfn(dev, IDE_CD, errp);
2831f56e32aSMarkus Armbruster }
2841f56e32aSMarkus Armbruster 
285794939e8SMao Zhongyi static void ide_drive_realize(IDEDevice *dev, Error **errp)
2861f56e32aSMarkus Armbruster {
28767c75f3dSKevin Wolf     DriveInfo *dinfo = NULL;
28867c75f3dSKevin Wolf 
2897d60133fSJohn Snow     warn_report("'ide-drive' is deprecated, "
2907d60133fSJohn Snow                 "please use 'ide-hd' or 'ide-cd' instead");
2917d60133fSJohn Snow 
29267c75f3dSKevin Wolf     if (dev->conf.blk) {
29367c75f3dSKevin Wolf         dinfo = blk_legacy_dinfo(dev->conf.blk);
29467c75f3dSKevin Wolf     }
29595b5edcdSMarkus Armbruster 
296794939e8SMao Zhongyi     ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD, errp);
2971f56e32aSMarkus Armbruster }
2981f56e32aSMarkus Armbruster 
2991f56e32aSMarkus Armbruster #define DEFINE_IDE_DEV_PROPERTIES()                     \
3001f56e32aSMarkus Armbruster     DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),        \
3018c398252SKevin Wolf     DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf),  \
3021f56e32aSMarkus Armbruster     DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),  \
303c7bcc85dSPaolo Bonzini     DEFINE_PROP_UINT64("wwn",  IDEDrive, dev.wwn, 0),   \
30427e0c9a1SFloris Bos     DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial),\
30527e0c9a1SFloris Bos     DEFINE_PROP_STRING("model", IDEDrive, dev.model)
3061f56e32aSMarkus Armbruster 
30739bffca2SAnthony Liguori static Property ide_hd_properties[] = {
3081f56e32aSMarkus Armbruster     DEFINE_IDE_DEV_PROPERTIES(),
309ba801960SMarkus Armbruster     DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf),
3106e6f61a6SMarkus Armbruster     DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans",
3116e6f61a6SMarkus Armbruster                 IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO),
3123b19f450SDaniel P. Berrange     DEFINE_PROP_UINT16("rotation_rate", IDEDrive, dev.rotation_rate, 0),
3131f56e32aSMarkus Armbruster     DEFINE_PROP_END_OF_LIST(),
31439bffca2SAnthony Liguori };
31539bffca2SAnthony Liguori 
31639bffca2SAnthony Liguori static void ide_hd_class_init(ObjectClass *klass, void *data)
31739bffca2SAnthony Liguori {
31839bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
31939bffca2SAnthony Liguori     IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
320794939e8SMao Zhongyi 
321794939e8SMao Zhongyi     k->realize  = ide_hd_realize;
32239bffca2SAnthony Liguori     dc->fw_name = "drive";
32339bffca2SAnthony Liguori     dc->desc    = "virtual IDE disk";
3244f67d30bSMarc-André Lureau     device_class_set_props(dc, ide_hd_properties);
3251f56e32aSMarkus Armbruster }
32639bffca2SAnthony Liguori 
3278c43a6f0SAndreas Färber static const TypeInfo ide_hd_info = {
32839bffca2SAnthony Liguori     .name          = "ide-hd",
32939bffca2SAnthony Liguori     .parent        = TYPE_IDE_DEVICE,
33039bffca2SAnthony Liguori     .instance_size = sizeof(IDEDrive),
33139bffca2SAnthony Liguori     .class_init    = ide_hd_class_init,
33239bffca2SAnthony Liguori };
33339bffca2SAnthony Liguori 
33439bffca2SAnthony Liguori static Property ide_cd_properties[] = {
33539bffca2SAnthony Liguori     DEFINE_IDE_DEV_PROPERTIES(),
33639bffca2SAnthony Liguori     DEFINE_PROP_END_OF_LIST(),
337d148211cSAnthony Liguori };
338d148211cSAnthony Liguori 
339d148211cSAnthony Liguori static void ide_cd_class_init(ObjectClass *klass, void *data)
340d148211cSAnthony Liguori {
34139bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
342d148211cSAnthony Liguori     IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
343794939e8SMao Zhongyi 
344794939e8SMao Zhongyi     k->realize  = ide_cd_realize;
34539bffca2SAnthony Liguori     dc->fw_name = "drive";
34639bffca2SAnthony Liguori     dc->desc    = "virtual IDE CD-ROM";
3474f67d30bSMarc-André Lureau     device_class_set_props(dc, ide_cd_properties);
348d148211cSAnthony Liguori }
349d148211cSAnthony Liguori 
3508c43a6f0SAndreas Färber static const TypeInfo ide_cd_info = {
351d148211cSAnthony Liguori     .name          = "ide-cd",
35239bffca2SAnthony Liguori     .parent        = TYPE_IDE_DEVICE,
35339bffca2SAnthony Liguori     .instance_size = sizeof(IDEDrive),
354d148211cSAnthony Liguori     .class_init    = ide_cd_class_init,
35539bffca2SAnthony Liguori };
35639bffca2SAnthony Liguori 
35739bffca2SAnthony Liguori static Property ide_drive_properties[] = {
3581f56e32aSMarkus Armbruster     DEFINE_IDE_DEV_PROPERTIES(),
3591f56e32aSMarkus Armbruster     DEFINE_PROP_END_OF_LIST(),
360d148211cSAnthony Liguori };
361d148211cSAnthony Liguori 
362d148211cSAnthony Liguori static void ide_drive_class_init(ObjectClass *klass, void *data)
363d148211cSAnthony Liguori {
36439bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
365d148211cSAnthony Liguori     IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
366794939e8SMao Zhongyi 
367794939e8SMao Zhongyi     k->realize  = ide_drive_realize;
36839bffca2SAnthony Liguori     dc->fw_name = "drive";
36939bffca2SAnthony Liguori     dc->desc    = "virtual IDE disk or CD-ROM (legacy)";
3704f67d30bSMarc-André Lureau     device_class_set_props(dc, ide_drive_properties);
371d148211cSAnthony Liguori }
372d148211cSAnthony Liguori 
3738c43a6f0SAndreas Färber static const TypeInfo ide_drive_info = {
37439bffca2SAnthony Liguori     .name          = "ide-drive",
37539bffca2SAnthony Liguori     .parent        = TYPE_IDE_DEVICE,
37639bffca2SAnthony Liguori     .instance_size = sizeof(IDEDrive),
377d148211cSAnthony Liguori     .class_init    = ide_drive_class_init,
378d148211cSAnthony Liguori };
379d148211cSAnthony Liguori 
38039bffca2SAnthony Liguori static void ide_device_class_init(ObjectClass *klass, void *data)
38139bffca2SAnthony Liguori {
38239bffca2SAnthony Liguori     DeviceClass *k = DEVICE_CLASS(klass);
383794939e8SMao Zhongyi     k->realize = ide_qdev_realize;
384125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
3850d936928SAnthony Liguori     k->bus_type = TYPE_IDE_BUS;
3864f67d30bSMarc-André Lureau     device_class_set_props(k, ide_props);
38739bffca2SAnthony Liguori }
38839bffca2SAnthony Liguori 
3898c43a6f0SAndreas Färber static const TypeInfo ide_device_type_info = {
390d148211cSAnthony Liguori     .name = TYPE_IDE_DEVICE,
391d148211cSAnthony Liguori     .parent = TYPE_DEVICE,
392d148211cSAnthony Liguori     .instance_size = sizeof(IDEDevice),
393d148211cSAnthony Liguori     .abstract = true,
394d148211cSAnthony Liguori     .class_size = sizeof(IDEDeviceClass),
39539bffca2SAnthony Liguori     .class_init = ide_device_class_init,
39645563630SGonglei     .instance_init = ide_dev_instance_init,
397da4d0419SGerd Hoffmann };
398da4d0419SGerd Hoffmann 
39983f7d43aSAndreas Färber static void ide_register_types(void)
400da4d0419SGerd Hoffmann {
4010d936928SAnthony Liguori     type_register_static(&ide_bus_info);
40239bffca2SAnthony Liguori     type_register_static(&ide_hd_info);
40339bffca2SAnthony Liguori     type_register_static(&ide_cd_info);
40439bffca2SAnthony Liguori     type_register_static(&ide_drive_info);
405d148211cSAnthony Liguori     type_register_static(&ide_device_type_info);
4061f56e32aSMarkus Armbruster }
40783f7d43aSAndreas Färber 
40883f7d43aSAndreas Färber type_init(ide_register_types)
409