#include "qemu/osdep.h"
-#include "hw/hw.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "hw/qdev-properties.h"
#include "hw/scsi/scsi.h"
+#include "migration/qemu-file-types.h"
+#include "migration/vmstate.h"
#include "scsi/constants.h"
-#include "hw/qdev.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/runstate.h"
#include "trace.h"
#include "sysemu/dma.h"
#include "qemu/cutils.h"
}
}
+static void scsi_device_unrealize(SCSIDevice *s, Error **errp)
+{
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
+ if (sc->unrealize) {
+ sc->unrealize(s, errp);
+ }
+}
+
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
void *hba_private)
{
error_propagate(errp, local_err);
return;
}
- dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb,
- dev);
+ dev->vmsentry = qdev_add_vm_change_state_handler(DEVICE(dev),
+ scsi_dma_restart_cb, dev);
}
static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
{
SCSIDevice *dev = SCSI_DEVICE(qdev);
+ Error *local_err = NULL;
if (dev->vmsentry) {
qemu_del_vm_change_state_handler(dev->vmsentry);
}
scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE));
+
+ scsi_device_unrealize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
blockdev_mark_auto_del(dev->conf.blk);
}
/* handle legacy '-drive if=scsi,...' cmd line args */
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
int unit, bool removable, int bootindex,
+ bool share_rw,
+ BlockdevOnError rerror,
+ BlockdevOnError werror,
const char *serial, Error **errp)
{
const char *driver;
char *name;
DeviceState *dev;
Error *err = NULL;
+ DriveInfo *dinfo;
- driver = blk_is_sg(blk) ? "scsi-generic" : "scsi-disk";
+ if (blk_is_sg(blk)) {
+ driver = "scsi-generic";
+ } else {
+ dinfo = blk_legacy_dinfo(blk);
+ if (dinfo && dinfo->media_cd) {
+ driver = "scsi-cd";
+ } else {
+ driver = "scsi-hd";
+ }
+ }
dev = qdev_create(&bus->qbus, driver);
name = g_strdup_printf("legacy[%d]", unit);
object_property_add_child(OBJECT(bus), name, OBJECT(dev), NULL);
object_unparent(OBJECT(dev));
return NULL;
}
+ object_property_set_bool(OBJECT(dev), share_rw, "share-rw", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ object_unparent(OBJECT(dev));
+ return NULL;
+ }
+
+ qdev_prop_set_enum(dev, "rerror", rerror);
+ qdev_prop_set_enum(dev, "werror", werror);
+
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return SCSI_DEVICE(dev);
}
-void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated)
+void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
{
Location loc;
DriveInfo *dinfo;
continue;
}
qemu_opts_loc_restore(dinfo->opts);
- if (deprecated) {
- /* Handling -drive not claimed by machine initialization */
- if (blk_get_attached_dev(blk_by_legacy_dinfo(dinfo))) {
- continue; /* claimed */
- }
- if (!dinfo->is_default) {
- warn_report("bus=%d,unit=%d is deprecated with this"
- " machine type",
- bus->busnr, unit);
- }
- }
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
- unit, false, -1, NULL, &error_fatal);
+ unit, false, -1, false,
+ BLOCKDEV_ON_ERROR_AUTO,
+ BLOCKDEV_ON_ERROR_AUTO,
+ NULL, &error_fatal);
}
loc_pop(&loc);
}
-static bool is_scsi_hba_with_legacy_magic(Object *obj)
-{
- static const char *magic[] = {
- "am53c974", "dc390", "esp", "lsi53c810", "lsi53c895a",
- "megasas", "megasas-gen2", "mptsas1068", "spapr-vscsi",
- "virtio-scsi-device",
- NULL
- };
- const char *typename = object_get_typename(obj);
- int i;
-
- for (i = 0; magic[i]; i++)
- if (!strcmp(typename, magic[i])) {
- return true;
- }
-
- return false;
-}
-
-static int scsi_legacy_handle_cmdline_cb(Object *obj, void *opaque)
-{
- SCSIBus *bus = (SCSIBus *)object_dynamic_cast(obj, TYPE_SCSI_BUS);
-
- if (bus && is_scsi_hba_with_legacy_magic(OBJECT(bus->qbus.parent))) {
- scsi_bus_legacy_handle_cmdline(bus, true);
- }
-
- return 0;
-}
-
-void scsi_legacy_handle_cmdline(void)
-{
- object_child_foreach_recursive(object_get_root(),
- scsi_legacy_handle_cmdline_cb, NULL);
-}
-
static int32_t scsi_invalid_field(SCSIRequest *req, uint8_t *buf)
{
scsi_req_build_sense(req, SENSE_CODE(INVALID_FIELD));
break;
case WRITE_SAME_10:
case WRITE_SAME_16:
- cmd->xfer = dev->blocksize;
+ cmd->xfer = buf[1] & 1 ? 0 : dev->blocksize;
break;
case READ_CAPACITY_10:
cmd->xfer = 8;
BusChild *kid;
SCSIDevice *target_dev = NULL;
- QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) {
+ QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
SCSIDevice *dev = SCSI_DEVICE(qdev);
/* SCSI request list. For simplicity, pv points to the whole device */
static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
- VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, QJSON *vmdesc)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
}
static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
- VMStateField *field)
+ const VMStateField *field)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);