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
ide_qdev_realize(DeviceState * qdev,Error ** errp)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
ide_dev_initfn(IDEDevice * dev,IDEDriveKind kind,Error ** errp)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
ide_dev_get_bootindex(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
ide_dev_set_bootindex(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
ide_dev_instance_init(Object * obj)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
ide_hd_realize(IDEDevice * dev,Error ** errp)184 static void ide_hd_realize(IDEDevice *dev, Error **errp)
185 {
186 ide_dev_initfn(dev, IDE_HD, errp);
187 }
188
ide_cd_realize(IDEDevice * dev,Error ** errp)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
ide_hd_class_init(ObjectClass * klass,void * data)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
ide_cd_class_init(ObjectClass * klass,void * data)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
ide_device_class_init(ObjectClass * klass,void * data)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
ide_register_types(void)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