1 /* 2 * IDE device functions 3 * 4 * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "qapi/error.h" 22 #include "qapi/qapi-types-block.h" 23 #include "qemu/error-report.h" 24 #include "qemu/module.h" 25 #include "hw/ide/ide-dev.h" 26 #include "sysemu/block-backend.h" 27 #include "sysemu/blockdev.h" 28 #include "sysemu/sysemu.h" 29 #include "qapi/visitor.h" 30 #include "ide-internal.h" 31 32 static Property ide_props[] = { 33 DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), 34 DEFINE_PROP_BOOL("win2k-install-hack", IDEDevice, win2k_install_hack, false), 35 DEFINE_PROP_END_OF_LIST(), 36 }; 37 38 static void ide_qdev_realize(DeviceState *qdev, Error **errp) 39 { 40 IDEDevice *dev = IDE_DEVICE(qdev); 41 IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev); 42 IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); 43 44 if (dev->unit == -1) { 45 dev->unit = bus->master ? 1 : 0; 46 } 47 48 if (dev->unit >= bus->max_units) { 49 error_setg(errp, "Can't create IDE unit %d, bus supports only %d units", 50 dev->unit, bus->max_units); 51 return; 52 } 53 54 switch (dev->unit) { 55 case 0: 56 if (bus->master) { 57 error_setg(errp, "IDE unit %d is in use", dev->unit); 58 return; 59 } 60 bus->master = dev; 61 break; 62 case 1: 63 if (bus->slave) { 64 error_setg(errp, "IDE unit %d is in use", dev->unit); 65 return; 66 } 67 bus->slave = dev; 68 break; 69 default: 70 error_setg(errp, "Invalid IDE unit %d", dev->unit); 71 return; 72 } 73 dc->realize(dev, errp); 74 } 75 76 void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp) 77 { 78 IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); 79 IDEState *s = bus->ifs + dev->unit; 80 int ret; 81 82 if (!dev->conf.blk) { 83 if (kind != IDE_CD) { 84 error_setg(errp, "No drive specified"); 85 return; 86 } else { 87 /* Anonymous BlockBackend for an empty drive */ 88 dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 89 ret = blk_attach_dev(dev->conf.blk, &dev->qdev); 90 assert(ret == 0); 91 } 92 } 93 94 if (dev->conf.discard_granularity == -1) { 95 dev->conf.discard_granularity = 512; 96 } else if (dev->conf.discard_granularity && 97 dev->conf.discard_granularity != 512) { 98 error_setg(errp, "discard_granularity must be 512 for ide"); 99 return; 100 } 101 102 if (!blkconf_blocksizes(&dev->conf, errp)) { 103 return; 104 } 105 106 if (dev->conf.logical_block_size != 512) { 107 error_setg(errp, "logical_block_size must be 512 for IDE"); 108 return; 109 } 110 111 if (kind != IDE_CD) { 112 if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, 113 errp)) { 114 return; 115 } 116 } 117 if (!blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, 118 kind != IDE_CD, errp)) { 119 return; 120 } 121 122 if (ide_init_drive(s, dev, kind, errp) < 0) { 123 return; 124 } 125 126 if (!dev->version) { 127 dev->version = g_strdup(s->version); 128 } 129 if (!dev->serial) { 130 dev->serial = g_strdup(s->drive_serial_str); 131 } 132 133 add_boot_device_path(dev->conf.bootindex, &dev->qdev, 134 dev->unit ? "/disk@1" : "/disk@0"); 135 136 add_boot_device_lchs(&dev->qdev, dev->unit ? "/disk@1" : "/disk@0", 137 dev->conf.lcyls, 138 dev->conf.lheads, 139 dev->conf.lsecs); 140 } 141 142 static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name, 143 void *opaque, Error **errp) 144 { 145 IDEDevice *d = IDE_DEVICE(obj); 146 147 visit_type_int32(v, name, &d->conf.bootindex, errp); 148 } 149 150 static void ide_dev_set_bootindex(Object *obj, Visitor *v, const char *name, 151 void *opaque, Error **errp) 152 { 153 IDEDevice *d = IDE_DEVICE(obj); 154 int32_t boot_index; 155 Error *local_err = NULL; 156 157 if (!visit_type_int32(v, name, &boot_index, errp)) { 158 return; 159 } 160 /* check whether bootindex is present in fw_boot_order list */ 161 check_boot_index(boot_index, &local_err); 162 if (local_err) { 163 goto out; 164 } 165 /* change bootindex to a new one */ 166 d->conf.bootindex = boot_index; 167 168 if (d->unit != -1) { 169 add_boot_device_path(d->conf.bootindex, &d->qdev, 170 d->unit ? "/disk@1" : "/disk@0"); 171 } 172 out: 173 error_propagate(errp, local_err); 174 } 175 176 static void ide_dev_instance_init(Object *obj) 177 { 178 object_property_add(obj, "bootindex", "int32", 179 ide_dev_get_bootindex, 180 ide_dev_set_bootindex, NULL, NULL); 181 object_property_set_int(obj, "bootindex", -1, NULL); 182 } 183 184 static void ide_hd_realize(IDEDevice *dev, Error **errp) 185 { 186 ide_dev_initfn(dev, IDE_HD, errp); 187 } 188 189 static void ide_cd_realize(IDEDevice *dev, Error **errp) 190 { 191 ide_dev_initfn(dev, IDE_CD, errp); 192 } 193 194 static Property ide_hd_properties[] = { 195 DEFINE_IDE_DEV_PROPERTIES(), 196 DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf), 197 DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans", 198 IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO), 199 DEFINE_PROP_UINT16("rotation_rate", IDEDrive, dev.rotation_rate, 0), 200 DEFINE_PROP_END_OF_LIST(), 201 }; 202 203 static void ide_hd_class_init(ObjectClass *klass, void *data) 204 { 205 DeviceClass *dc = DEVICE_CLASS(klass); 206 IDEDeviceClass *k = IDE_DEVICE_CLASS(klass); 207 208 k->realize = ide_hd_realize; 209 dc->fw_name = "drive"; 210 dc->desc = "virtual IDE disk"; 211 device_class_set_props(dc, ide_hd_properties); 212 } 213 214 static const TypeInfo ide_hd_info = { 215 .name = "ide-hd", 216 .parent = TYPE_IDE_DEVICE, 217 .instance_size = sizeof(IDEDrive), 218 .class_init = ide_hd_class_init, 219 }; 220 221 static Property ide_cd_properties[] = { 222 DEFINE_IDE_DEV_PROPERTIES(), 223 DEFINE_PROP_END_OF_LIST(), 224 }; 225 226 static void ide_cd_class_init(ObjectClass *klass, void *data) 227 { 228 DeviceClass *dc = DEVICE_CLASS(klass); 229 IDEDeviceClass *k = IDE_DEVICE_CLASS(klass); 230 231 k->realize = ide_cd_realize; 232 dc->fw_name = "drive"; 233 dc->desc = "virtual IDE CD-ROM"; 234 device_class_set_props(dc, ide_cd_properties); 235 } 236 237 static const TypeInfo ide_cd_info = { 238 .name = "ide-cd", 239 .parent = TYPE_IDE_DEVICE, 240 .instance_size = sizeof(IDEDrive), 241 .class_init = ide_cd_class_init, 242 }; 243 244 static void ide_device_class_init(ObjectClass *klass, void *data) 245 { 246 DeviceClass *k = DEVICE_CLASS(klass); 247 k->realize = ide_qdev_realize; 248 set_bit(DEVICE_CATEGORY_STORAGE, k->categories); 249 k->bus_type = TYPE_IDE_BUS; 250 device_class_set_props(k, ide_props); 251 } 252 253 static const TypeInfo ide_device_type_info = { 254 .name = TYPE_IDE_DEVICE, 255 .parent = TYPE_DEVICE, 256 .instance_size = sizeof(IDEDevice), 257 .abstract = true, 258 .class_size = sizeof(IDEDeviceClass), 259 .class_init = ide_device_class_init, 260 .instance_init = ide_dev_instance_init, 261 }; 262 263 static void ide_register_types(void) 264 { 265 type_register_static(&ide_hd_info); 266 type_register_static(&ide_cd_info); 267 type_register_static(&ide_device_type_info); 268 } 269 270 type_init(ide_register_types) 271