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/>.
21 #include "qemu-error.h"
22 #include <hw/ide/internal.h>
26 /* --------------------------------- */
28 static char *idebus_get_fw_dev_path(DeviceState
*dev
);
30 static struct BusInfo ide_bus_info
= {
32 .size
= sizeof(IDEBus
),
33 .get_fw_dev_path
= idebus_get_fw_dev_path
,
36 void ide_bus_new(IDEBus
*idebus
, DeviceState
*dev
, int bus_id
)
38 qbus_create_inplace(&idebus
->qbus
, &ide_bus_info
, dev
, NULL
);
39 idebus
->bus_id
= bus_id
;
42 static char *idebus_get_fw_dev_path(DeviceState
*dev
)
46 snprintf(path
, sizeof(path
), "%s@%d", qdev_fw_name(dev
),
47 ((IDEBus
*)dev
->parent_bus
)->bus_id
);
52 static int ide_qdev_init(DeviceState
*qdev
, DeviceInfo
*base
)
54 IDEDevice
*dev
= DO_UPCAST(IDEDevice
, qdev
, qdev
);
55 IDEDeviceInfo
*info
= DO_UPCAST(IDEDeviceInfo
, qdev
, base
);
56 IDEBus
*bus
= DO_UPCAST(IDEBus
, qbus
, qdev
->parent_bus
);
59 error_report("No drive specified");
62 if (dev
->unit
== -1) {
63 dev
->unit
= bus
->master
? 1 : 0;
68 error_report("IDE unit %d is in use", dev
->unit
);
75 error_report("IDE unit %d is in use", dev
->unit
);
81 error_report("Invalid IDE unit %d", dev
->unit
);
84 return info
->init(dev
);
90 static void ide_qdev_register(IDEDeviceInfo
*info
)
92 info
->qdev
.init
= ide_qdev_init
;
93 info
->qdev
.bus_info
= &ide_bus_info
;
94 qdev_register(&info
->qdev
);
97 IDEDevice
*ide_create_drive(IDEBus
*bus
, int unit
, DriveInfo
*drive
)
101 dev
= qdev_create(&bus
->qbus
, drive
->media_cd
? "ide-cd" : "ide-hd");
102 qdev_prop_set_uint32(dev
, "unit", unit
);
103 qdev_prop_set_drive_nofail(dev
, "drive", drive
->bdrv
);
104 qdev_init_nofail(dev
);
105 return DO_UPCAST(IDEDevice
, qdev
, dev
);
108 void ide_get_bs(BlockDriverState
*bs
[], BusState
*qbus
)
110 IDEBus
*bus
= DO_UPCAST(IDEBus
, qbus
, qbus
);
111 bs
[0] = bus
->master
? bus
->master
->conf
.bs
: NULL
;
112 bs
[1] = bus
->slave
? bus
->slave
->conf
.bs
: NULL
;
115 /* --------------------------------- */
117 typedef struct IDEDrive
{
121 static int ide_dev_initfn(IDEDevice
*dev
, IDEDriveKind kind
)
123 IDEBus
*bus
= DO_UPCAST(IDEBus
, qbus
, dev
->qdev
.parent_bus
);
124 IDEState
*s
= bus
->ifs
+ dev
->unit
;
128 if (dev
->conf
.discard_granularity
&& dev
->conf
.discard_granularity
!= 512) {
129 error_report("discard_granularity must be 512 for ide");
133 serial
= dev
->serial
;
135 /* try to fall back to value set with legacy -drive serial=... */
136 dinfo
= drive_get_by_blockdev(dev
->conf
.bs
);
137 if (*dinfo
->serial
) {
138 serial
= dinfo
->serial
;
142 if (ide_init_drive(s
, dev
->conf
.bs
, kind
, dev
->version
, serial
) < 0) {
147 dev
->version
= qemu_strdup(s
->version
);
150 dev
->serial
= qemu_strdup(s
->drive_serial_str
);
153 add_boot_device_path(dev
->conf
.bootindex
, &dev
->qdev
,
154 dev
->unit
? "/disk@1" : "/disk@0");
159 static int ide_hd_initfn(IDEDevice
*dev
)
161 return ide_dev_initfn(dev
, IDE_HD
);
164 static int ide_cd_initfn(IDEDevice
*dev
)
166 return ide_dev_initfn(dev
, IDE_CD
);
169 static int ide_drive_initfn(IDEDevice
*dev
)
171 DriveInfo
*dinfo
= drive_get_by_blockdev(dev
->conf
.bs
);
173 return ide_dev_initfn(dev
, dinfo
->media_cd
? IDE_CD
: IDE_HD
);
176 #define DEFINE_IDE_DEV_PROPERTIES() \
177 DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1), \
178 DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
179 DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
180 DEFINE_PROP_STRING("serial", IDEDrive, dev.serial)
182 static IDEDeviceInfo ide_dev_info
[] = {
184 .qdev
.name
= "ide-hd",
185 .qdev
.fw_name
= "drive",
186 .qdev
.desc
= "virtual IDE disk",
187 .qdev
.size
= sizeof(IDEDrive
),
188 .init
= ide_hd_initfn
,
189 .qdev
.props
= (Property
[]) {
190 DEFINE_IDE_DEV_PROPERTIES(),
191 DEFINE_PROP_END_OF_LIST(),
194 .qdev
.name
= "ide-cd",
195 .qdev
.fw_name
= "drive",
196 .qdev
.desc
= "virtual IDE CD-ROM",
197 .qdev
.size
= sizeof(IDEDrive
),
198 .init
= ide_cd_initfn
,
199 .qdev
.props
= (Property
[]) {
200 DEFINE_IDE_DEV_PROPERTIES(),
201 DEFINE_PROP_END_OF_LIST(),
204 .qdev
.name
= "ide-drive", /* legacy -device ide-drive */
205 .qdev
.fw_name
= "drive",
206 .qdev
.desc
= "virtual IDE disk or CD-ROM (legacy)",
207 .qdev
.size
= sizeof(IDEDrive
),
208 .init
= ide_drive_initfn
,
209 .qdev
.props
= (Property
[]) {
210 DEFINE_IDE_DEV_PROPERTIES(),
211 DEFINE_PROP_END_OF_LIST(),
216 static void ide_dev_register(void)
220 for (i
= 0; i
< ARRAY_SIZE(ide_dev_info
); i
++) {
221 ide_qdev_register(&ide_dev_info
[i
]);
224 device_init(ide_dev_register
);