qemu/hw/usb/dev-storage-classic.c

158 lines
4.5 KiB
C
Raw Normal View History

/*
* USB Mass Storage Device emulation
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licensed under the LGPL.
*/
#include "qemu/osdep.h"
#include "qemu/typedefs.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "hw/usb/msd.h"
#include "sysemu/sysemu.h"
#include "sysemu/block-backend.h"
static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
.tcq = false,
.max_target = 0,
.max_lun = 0,
.transfer_data = usb_msd_transfer_data,
.complete = usb_msd_command_complete,
.cancel = usb_msd_request_cancelled,
.load_request = usb_msd_load_request,
};
static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
{
MSDState *s = USB_STORAGE_DEV(dev);
BlockBackend *blk = s->conf.blk;
SCSIDevice *scsi_dev;
if (!blk) {
error_setg(errp, "drive property not set");
return;
}
if (!blkconf_blocksizes(&s->conf, errp)) {
return;
}
if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk),
true, errp)) {
return;
}
/*
* Hack alert: this pretends to be a block device, but it's really
* a SCSI bus that can serve only a single device, which it
* creates automatically. But first it needs to detach from its
* blockdev, or else scsi_bus_legacy_add_drive() dies when it
* attaches again. We also need to take another reference so that
* blk_detach_dev() doesn't free blk while we still need it.
*
* The hack is probably a bad idea.
*/
blk_ref(blk);
blk_detach_dev(blk, DEVICE(s));
s->conf.blk = NULL;
usb_desc_create_serial(dev);
usb_desc_init(dev);
dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
scsi: Replace scsi_bus_new() with scsi_bus_init(), scsi_bus_init_named() The function scsi_bus_new() creates a new SCSI bus; callers can either pass in a name argument to specify the name of the new bus, or they can pass in NULL to allow the bus to be given an automatically generated unique name. Almost all callers want to use the autogenerated name; the only exception is the virtio-scsi device. Taking a name argument that should almost always be NULL is an easy-to-misuse API design -- it encourages callers to think perhaps they should pass in some standard name like "scsi" or "scsi-bus". We don't do this anywhere for SCSI, but we do (incorrectly) do it for other bus types such as i2c. The function name also implies that it will return a newly allocated object, when it in fact does in-place allocation. We more commonly name such functions foo_init(), with foo_new() being the allocate-and-return variant. Replace all the scsi_bus_new() callsites with either: * scsi_bus_init() for the usual case where the caller wants an autogenerated bus name * scsi_bus_init_named() for the rare case where the caller needs to specify the bus name and document that for the _named() version it's then the caller's responsibility to think about uniqueness of bus names. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923121153.23754-2-peter.maydell@linaro.org
2021-09-23 15:11:48 +03:00
scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev),
&usb_msd_scsi_info_storage);
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
s->conf.bootindex, s->conf.share_rw,
s->conf.rerror, s->conf.werror,
dev->serial,
errp);
blk_unref(blk);
if (!scsi_dev) {
return;
}
usb_msd_handle_reset(dev);
s->scsi_dev = scsi_dev;
}
static Property msd_properties[] = {
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
DEFINE_PROP_BOOL("removable", MSDState, removable, false),
DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false),
DEFINE_PROP_END_OF_LIST(),
};
static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
uc->realize = usb_msd_storage_realize;
device_class_set_props(dc, msd_properties);
}
static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
USBDevice *dev = USB_DEVICE(obj);
MSDState *s = USB_STORAGE_DEV(dev);
visit_type_int32(v, name, &s->conf.bootindex, errp);
}
static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
USBDevice *dev = USB_DEVICE(obj);
MSDState *s = USB_STORAGE_DEV(dev);
int32_t boot_index;
Error *local_err = NULL;
if (!visit_type_int32(v, name, &boot_index, errp)) {
return;
}
/* check whether bootindex is present in fw_boot_order list */
check_boot_index(boot_index, &local_err);
if (local_err) {
goto out;
}
/* change bootindex to a new one */
s->conf.bootindex = boot_index;
if (s->scsi_dev) {
object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index,
&error_abort);
}
out:
error_propagate(errp, local_err);
}
static void usb_msd_instance_init(Object *obj)
{
object_property_add(obj, "bootindex", "int32",
usb_msd_get_bootindex,
usb_msd_set_bootindex, NULL, NULL);
object_property_set_int(obj, "bootindex", -1, NULL);
}
static const TypeInfo msd_info = {
.name = "usb-storage",
.parent = TYPE_USB_STORAGE,
.class_init = usb_msd_class_storage_initfn,
.instance_init = usb_msd_instance_init,
};
static void register_types(void)
{
type_register_static(&msd_info);
}
type_init(register_types)