]> Git Repo - qemu.git/blame - hw/ide/qdev.c
qemu-help: Sort devices by logical functionality
[qemu.git] / hw / ide / qdev.c
CommitLineData
da4d0419
GH
1/*
2 * ide bus support for qdev.
3 *
4 * Copyright (c) 2009 Gerd Hoffmann <[email protected]>
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 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#include <hw/hw.h>
9c17d615 20#include "sysemu/dma.h"
1de7afc9 21#include "qemu/error-report.h"
da4d0419 22#include <hw/ide/internal.h>
9c17d615 23#include "sysemu/blockdev.h"
0d09e41a 24#include "hw/block/block.h"
9c17d615 25#include "sysemu/sysemu.h"
da4d0419
GH
26
27/* --------------------------------- */
28
dc1a46b6
GN
29static char *idebus_get_fw_dev_path(DeviceState *dev);
30
3cb75a7c
PB
31static Property ide_props[] = {
32 DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
33 DEFINE_PROP_END_OF_LIST(),
34};
35
0d936928
AL
36static void ide_bus_class_init(ObjectClass *klass, void *data)
37{
38 BusClass *k = BUS_CLASS(klass);
39
40 k->get_fw_dev_path = idebus_get_fw_dev_path;
41}
42
43static const TypeInfo ide_bus_info = {
44 .name = TYPE_IDE_BUS,
45 .parent = TYPE_BUS,
46 .instance_size = sizeof(IDEBus),
47 .class_init = ide_bus_class_init,
da4d0419
GH
48};
49
0ee20e66 50void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id, int max_units)
da4d0419 51{
0d936928 52 qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL);
3835510f 53 idebus->bus_id = bus_id;
0ee20e66 54 idebus->max_units = max_units;
da4d0419
GH
55}
56
dc1a46b6
GN
57static char *idebus_get_fw_dev_path(DeviceState *dev)
58{
59 char path[30];
60
61 snprintf(path, sizeof(path), "%s@%d", qdev_fw_name(dev),
62 ((IDEBus*)dev->parent_bus)->bus_id);
63
a5cf8262 64 return g_strdup(path);
dc1a46b6
GN
65}
66
d307af79 67static int ide_qdev_init(DeviceState *qdev)
da4d0419 68{
d148211c
AL
69 IDEDevice *dev = IDE_DEVICE(qdev);
70 IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
da4d0419
GH
71 IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
72
f8b6cc00 73 if (!dev->conf.bs) {
f597627f 74 error_report("No drive specified");
da4d0419
GH
75 goto err;
76 }
77 if (dev->unit == -1) {
78 dev->unit = bus->master ? 1 : 0;
79 }
0ee20e66
KW
80
81 if (dev->unit >= bus->max_units) {
82 error_report("Can't create IDE unit %d, bus supports only %d units",
83 dev->unit, bus->max_units);
84 goto err;
85 }
86
da4d0419
GH
87 switch (dev->unit) {
88 case 0:
89 if (bus->master) {
f597627f 90 error_report("IDE unit %d is in use", dev->unit);
da4d0419
GH
91 goto err;
92 }
93 bus->master = dev;
94 break;
95 case 1:
96 if (bus->slave) {
f597627f 97 error_report("IDE unit %d is in use", dev->unit);
da4d0419
GH
98 goto err;
99 }
100 bus->slave = dev;
101 break;
102 default:
f597627f 103 error_report("Invalid IDE unit %d", dev->unit);
da4d0419
GH
104 goto err;
105 }
d148211c 106 return dc->init(dev);
da4d0419
GH
107
108err:
109 return -1;
110}
111
da4d0419
GH
112IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
113{
114 DeviceState *dev;
115
95b5edcd 116 dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
da4d0419 117 qdev_prop_set_uint32(dev, "unit", unit);
18846dee 118 qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
fa12fbbe 119 qdev_init_nofail(dev);
da4d0419
GH
120 return DO_UPCAST(IDEDevice, qdev, dev);
121}
122
9139046c
MA
123int ide_get_geometry(BusState *bus, int unit,
124 int16_t *cyls, int8_t *heads, int8_t *secs)
c0897e0c 125{
9139046c
MA
126 IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit];
127
9dc13e38 128 if (s->drive_kind != IDE_HD || !s->bs) {
9139046c
MA
129 return -1;
130 }
131
132 *cyls = s->cylinders;
133 *heads = s->heads;
134 *secs = s->sectors;
135 return 0;
136}
137
138int ide_get_bios_chs_trans(BusState *bus, int unit)
139{
140 return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans;
c0897e0c
MA
141}
142
da4d0419
GH
143/* --------------------------------- */
144
145typedef struct IDEDrive {
146 IDEDevice dev;
147} IDEDrive;
148
1f56e32a 149static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
da4d0419
GH
150{
151 IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
6ced55a5 152 IDEState *s = bus->ifs + dev->unit;
6ced55a5 153
215e47b9
PB
154 if (dev->conf.discard_granularity == -1) {
155 dev->conf.discard_granularity = 512;
156 } else if (dev->conf.discard_granularity &&
157 dev->conf.discard_granularity != 512) {
d353fb72
CH
158 error_report("discard_granularity must be 512 for ide");
159 return -1;
160 }
161
911525db 162 blkconf_serial(&dev->conf, &dev->serial);
b2df4314
MA
163 if (kind != IDE_CD
164 && blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
b7eb0c9f 165 return -1;
ba801960
MA
166 }
167
27e0c9a1 168 if (ide_init_drive(s, dev->conf.bs, kind,
911525db 169 dev->version, dev->serial, dev->model, dev->wwn,
ba801960 170 dev->conf.cyls, dev->conf.heads, dev->conf.secs,
6e6f61a6 171 dev->chs_trans) < 0) {
c4d74df7
MA
172 return -1;
173 }
6ced55a5 174
03432407 175 if (!dev->version) {
7267c094 176 dev->version = g_strdup(s->version);
03432407 177 }
6ced55a5 178 if (!dev->serial) {
7267c094 179 dev->serial = g_strdup(s->drive_serial_str);
6ced55a5 180 }
1ca4d09a
GN
181
182 add_boot_device_path(dev->conf.bootindex, &dev->qdev,
183 dev->unit ? "/disk@1" : "/disk@0");
184
da4d0419
GH
185 return 0;
186}
187
1f56e32a
MA
188static int ide_hd_initfn(IDEDevice *dev)
189{
190 return ide_dev_initfn(dev, IDE_HD);
191}
192
193static int ide_cd_initfn(IDEDevice *dev)
194{
195 return ide_dev_initfn(dev, IDE_CD);
196}
197
198static int ide_drive_initfn(IDEDevice *dev)
199{
95b5edcd
MA
200 DriveInfo *dinfo = drive_get_by_blockdev(dev->conf.bs);
201
202 return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD);
1f56e32a
MA
203}
204
205#define DEFINE_IDE_DEV_PROPERTIES() \
1f56e32a
MA
206 DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
207 DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
95ebda85 208 DEFINE_PROP_HEX64("wwn", IDEDrive, dev.wwn, 0), \
27e0c9a1
FB
209 DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\
210 DEFINE_PROP_STRING("model", IDEDrive, dev.model)
1f56e32a 211
39bffca2
AL
212static Property ide_hd_properties[] = {
213 DEFINE_IDE_DEV_PROPERTIES(),
ba801960 214 DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf),
6e6f61a6
MA
215 DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans",
216 IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO),
39bffca2
AL
217 DEFINE_PROP_END_OF_LIST(),
218};
219
d148211c
AL
220static void ide_hd_class_init(ObjectClass *klass, void *data)
221{
39bffca2 222 DeviceClass *dc = DEVICE_CLASS(klass);
d148211c
AL
223 IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
224 k->init = ide_hd_initfn;
39bffca2
AL
225 dc->fw_name = "drive";
226 dc->desc = "virtual IDE disk";
227 dc->props = ide_hd_properties;
d148211c
AL
228}
229
8c43a6f0 230static const TypeInfo ide_hd_info = {
39bffca2
AL
231 .name = "ide-hd",
232 .parent = TYPE_IDE_DEVICE,
233 .instance_size = sizeof(IDEDrive),
234 .class_init = ide_hd_class_init,
235};
236
237static Property ide_cd_properties[] = {
238 DEFINE_IDE_DEV_PROPERTIES(),
239 DEFINE_PROP_END_OF_LIST(),
da4d0419
GH
240};
241
d148211c 242static void ide_cd_class_init(ObjectClass *klass, void *data)
da4d0419 243{
39bffca2 244 DeviceClass *dc = DEVICE_CLASS(klass);
d148211c
AL
245 IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
246 k->init = ide_cd_initfn;
39bffca2
AL
247 dc->fw_name = "drive";
248 dc->desc = "virtual IDE CD-ROM";
249 dc->props = ide_cd_properties;
d148211c 250}
1f56e32a 251
8c43a6f0 252static const TypeInfo ide_cd_info = {
39bffca2
AL
253 .name = "ide-cd",
254 .parent = TYPE_IDE_DEVICE,
255 .instance_size = sizeof(IDEDrive),
256 .class_init = ide_cd_class_init,
257};
258
259static Property ide_drive_properties[] = {
260 DEFINE_IDE_DEV_PROPERTIES(),
261 DEFINE_PROP_END_OF_LIST(),
d148211c
AL
262};
263
264static void ide_drive_class_init(ObjectClass *klass, void *data)
265{
39bffca2 266 DeviceClass *dc = DEVICE_CLASS(klass);
d148211c
AL
267 IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
268 k->init = ide_drive_initfn;
39bffca2
AL
269 dc->fw_name = "drive";
270 dc->desc = "virtual IDE disk or CD-ROM (legacy)";
271 dc->props = ide_drive_properties;
d148211c
AL
272}
273
8c43a6f0 274static const TypeInfo ide_drive_info = {
39bffca2
AL
275 .name = "ide-drive",
276 .parent = TYPE_IDE_DEVICE,
277 .instance_size = sizeof(IDEDrive),
278 .class_init = ide_drive_class_init,
d148211c
AL
279};
280
39bffca2
AL
281static void ide_device_class_init(ObjectClass *klass, void *data)
282{
283 DeviceClass *k = DEVICE_CLASS(klass);
284 k->init = ide_qdev_init;
0d936928 285 k->bus_type = TYPE_IDE_BUS;
bce54474 286 k->props = ide_props;
39bffca2
AL
287}
288
8c43a6f0 289static const TypeInfo ide_device_type_info = {
d148211c
AL
290 .name = TYPE_IDE_DEVICE,
291 .parent = TYPE_DEVICE,
292 .instance_size = sizeof(IDEDevice),
293 .abstract = true,
294 .class_size = sizeof(IDEDeviceClass),
39bffca2 295 .class_init = ide_device_class_init,
d148211c
AL
296};
297
83f7d43a 298static void ide_register_types(void)
d148211c 299{
0d936928 300 type_register_static(&ide_bus_info);
39bffca2
AL
301 type_register_static(&ide_hd_info);
302 type_register_static(&ide_cd_info);
303 type_register_static(&ide_drive_info);
d148211c 304 type_register_static(&ide_device_type_info);
da4d0419 305}
83f7d43a
AF
306
307type_init(ide_register_types)
This page took 0.577577 seconds and 4 git commands to generate.