2 * ide bus support for qdev.
4 * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
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.
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.
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/>.
20 #include "sysemu/dma.h"
21 #include "qemu/error-report.h"
22 #include <hw/ide/internal.h>
23 #include "sysemu/blockdev.h"
24 #include "hw/block/block.h"
25 #include "sysemu/sysemu.h"
27 /* --------------------------------- */
29 static char *idebus_get_fw_dev_path(DeviceState
*dev
);
31 static Property ide_props
[] = {
32 DEFINE_PROP_UINT32("unit", IDEDevice
, unit
, -1),
33 DEFINE_PROP_END_OF_LIST(),
36 static void ide_bus_class_init(ObjectClass
*klass
, void *data
)
38 BusClass
*k
= BUS_CLASS(klass
);
40 k
->get_fw_dev_path
= idebus_get_fw_dev_path
;
43 static const TypeInfo ide_bus_info
= {
46 .instance_size
= sizeof(IDEBus
),
47 .class_init
= ide_bus_class_init
,
50 void ide_bus_new(IDEBus
*idebus
, DeviceState
*dev
, int bus_id
, int max_units
)
52 qbus_create_inplace(&idebus
->qbus
, TYPE_IDE_BUS
, dev
, NULL
);
53 idebus
->bus_id
= bus_id
;
54 idebus
->max_units
= max_units
;
57 static char *idebus_get_fw_dev_path(DeviceState
*dev
)
61 snprintf(path
, sizeof(path
), "%s@%d", qdev_fw_name(dev
),
62 ((IDEBus
*)dev
->parent_bus
)->bus_id
);
64 return g_strdup(path
);
67 static int ide_qdev_init(DeviceState
*qdev
)
69 IDEDevice
*dev
= IDE_DEVICE(qdev
);
70 IDEDeviceClass
*dc
= IDE_DEVICE_GET_CLASS(dev
);
71 IDEBus
*bus
= DO_UPCAST(IDEBus
, qbus
, qdev
->parent_bus
);
74 error_report("No drive specified");
77 if (dev
->unit
== -1) {
78 dev
->unit
= bus
->master
? 1 : 0;
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
);
90 error_report("IDE unit %d is in use", dev
->unit
);
97 error_report("IDE unit %d is in use", dev
->unit
);
103 error_report("Invalid IDE unit %d", dev
->unit
);
106 return dc
->init(dev
);
112 IDEDevice
*ide_create_drive(IDEBus
*bus
, int unit
, DriveInfo
*drive
)
116 dev
= qdev_create(&bus
->qbus
, drive
->media_cd
? "ide-cd" : "ide-hd");
117 qdev_prop_set_uint32(dev
, "unit", unit
);
118 qdev_prop_set_drive_nofail(dev
, "drive", drive
->bdrv
);
119 qdev_init_nofail(dev
);
120 return DO_UPCAST(IDEDevice
, qdev
, dev
);
123 int ide_get_geometry(BusState
*bus
, int unit
,
124 int16_t *cyls
, int8_t *heads
, int8_t *secs
)
126 IDEState
*s
= &DO_UPCAST(IDEBus
, qbus
, bus
)->ifs
[unit
];
128 if (s
->drive_kind
!= IDE_HD
|| !s
->bs
) {
132 *cyls
= s
->cylinders
;
138 int ide_get_bios_chs_trans(BusState
*bus
, int unit
)
140 return DO_UPCAST(IDEBus
, qbus
, bus
)->ifs
[unit
].chs_trans
;
143 /* --------------------------------- */
145 typedef struct IDEDrive
{
149 static int ide_dev_initfn(IDEDevice
*dev
, IDEDriveKind kind
)
151 IDEBus
*bus
= DO_UPCAST(IDEBus
, qbus
, dev
->qdev
.parent_bus
);
152 IDEState
*s
= bus
->ifs
+ dev
->unit
;
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) {
158 error_report("discard_granularity must be 512 for ide");
162 blkconf_serial(&dev
->conf
, &dev
->serial
);
164 && blkconf_geometry(&dev
->conf
, &dev
->chs_trans
, 65536, 16, 255) < 0) {
168 if (ide_init_drive(s
, dev
->conf
.bs
, kind
,
169 dev
->version
, dev
->serial
, dev
->model
, dev
->wwn
,
170 dev
->conf
.cyls
, dev
->conf
.heads
, dev
->conf
.secs
,
171 dev
->chs_trans
) < 0) {
176 dev
->version
= g_strdup(s
->version
);
179 dev
->serial
= g_strdup(s
->drive_serial_str
);
182 add_boot_device_path(dev
->conf
.bootindex
, &dev
->qdev
,
183 dev
->unit
? "/disk@1" : "/disk@0");
188 static int ide_hd_initfn(IDEDevice
*dev
)
190 return ide_dev_initfn(dev
, IDE_HD
);
193 static int ide_cd_initfn(IDEDevice
*dev
)
195 return ide_dev_initfn(dev
, IDE_CD
);
198 static int ide_drive_initfn(IDEDevice
*dev
)
200 DriveInfo
*dinfo
= drive_get_by_blockdev(dev
->conf
.bs
);
202 return ide_dev_initfn(dev
, dinfo
->media_cd
? IDE_CD
: IDE_HD
);
205 #define DEFINE_IDE_DEV_PROPERTIES() \
206 DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
207 DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
208 DEFINE_PROP_HEX64("wwn", IDEDrive, dev.wwn, 0), \
209 DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\
210 DEFINE_PROP_STRING("model", IDEDrive, dev.model)
212 static Property ide_hd_properties
[] = {
213 DEFINE_IDE_DEV_PROPERTIES(),
214 DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive
, dev
.conf
),
215 DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans",
216 IDEDrive
, dev
.chs_trans
, BIOS_ATA_TRANSLATION_AUTO
),
217 DEFINE_PROP_END_OF_LIST(),
220 static void ide_hd_class_init(ObjectClass
*klass
, void *data
)
222 DeviceClass
*dc
= DEVICE_CLASS(klass
);
223 IDEDeviceClass
*k
= IDE_DEVICE_CLASS(klass
);
224 k
->init
= ide_hd_initfn
;
225 dc
->fw_name
= "drive";
226 dc
->desc
= "virtual IDE disk";
227 dc
->props
= ide_hd_properties
;
230 static const TypeInfo ide_hd_info
= {
232 .parent
= TYPE_IDE_DEVICE
,
233 .instance_size
= sizeof(IDEDrive
),
234 .class_init
= ide_hd_class_init
,
237 static Property ide_cd_properties
[] = {
238 DEFINE_IDE_DEV_PROPERTIES(),
239 DEFINE_PROP_END_OF_LIST(),
242 static void ide_cd_class_init(ObjectClass
*klass
, void *data
)
244 DeviceClass
*dc
= DEVICE_CLASS(klass
);
245 IDEDeviceClass
*k
= IDE_DEVICE_CLASS(klass
);
246 k
->init
= ide_cd_initfn
;
247 dc
->fw_name
= "drive";
248 dc
->desc
= "virtual IDE CD-ROM";
249 dc
->props
= ide_cd_properties
;
252 static const TypeInfo ide_cd_info
= {
254 .parent
= TYPE_IDE_DEVICE
,
255 .instance_size
= sizeof(IDEDrive
),
256 .class_init
= ide_cd_class_init
,
259 static Property ide_drive_properties
[] = {
260 DEFINE_IDE_DEV_PROPERTIES(),
261 DEFINE_PROP_END_OF_LIST(),
264 static void ide_drive_class_init(ObjectClass
*klass
, void *data
)
266 DeviceClass
*dc
= DEVICE_CLASS(klass
);
267 IDEDeviceClass
*k
= IDE_DEVICE_CLASS(klass
);
268 k
->init
= ide_drive_initfn
;
269 dc
->fw_name
= "drive";
270 dc
->desc
= "virtual IDE disk or CD-ROM (legacy)";
271 dc
->props
= ide_drive_properties
;
274 static const TypeInfo ide_drive_info
= {
276 .parent
= TYPE_IDE_DEVICE
,
277 .instance_size
= sizeof(IDEDrive
),
278 .class_init
= ide_drive_class_init
,
281 static void ide_device_class_init(ObjectClass
*klass
, void *data
)
283 DeviceClass
*k
= DEVICE_CLASS(klass
);
284 k
->init
= ide_qdev_init
;
285 k
->bus_type
= TYPE_IDE_BUS
;
286 k
->props
= ide_props
;
289 static const TypeInfo ide_device_type_info
= {
290 .name
= TYPE_IDE_DEVICE
,
291 .parent
= TYPE_DEVICE
,
292 .instance_size
= sizeof(IDEDevice
),
294 .class_size
= sizeof(IDEDeviceClass
),
295 .class_init
= ide_device_class_init
,
298 static void ide_register_types(void)
300 type_register_static(&ide_bus_info
);
301 type_register_static(&ide_hd_info
);
302 type_register_static(&ide_cd_info
);
303 type_register_static(&ide_drive_info
);
304 type_register_static(&ide_device_type_info
);
307 type_init(ide_register_types
)