qdev/scsi+usb: convert usb-storage to qdev.
Full coverage with properties and everything. You can add virtual usb sticks this way now: -drive if=none,id=pendrive,path=/some/where -device usb-storage,drive=pendrive -usbdevice disk:/path/to/image continues to work. Other side effects: usb storage is listed in 'info block' now. kvm tree should be able to boot from usb via extboot (untested though). Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
d52affa7f6
commit
7fc2f2c086
67
hw/usb-msd.c
67
hw/usb-msd.c
|
@ -8,6 +8,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu-option.h"
|
||||||
|
#include "qemu-config.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
#include "scsi-disk.h"
|
#include "scsi-disk.h"
|
||||||
|
@ -43,8 +45,8 @@ typedef struct {
|
||||||
uint32_t data_len;
|
uint32_t data_len;
|
||||||
uint32_t residue;
|
uint32_t residue;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
BlockDriverState *bs;
|
|
||||||
SCSIBus *bus;
|
SCSIBus *bus;
|
||||||
|
DriveInfo *dinfo;
|
||||||
SCSIDevice *scsi_dev;
|
SCSIDevice *scsi_dev;
|
||||||
int result;
|
int result;
|
||||||
/* For async completion. */
|
/* For async completion. */
|
||||||
|
@ -511,7 +513,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
|
||||||
MSDState *s = (MSDState *)dev;
|
MSDState *s = (MSDState *)dev;
|
||||||
|
|
||||||
s->scsi_dev->info->destroy(s->scsi_dev);
|
s->scsi_dev->info->destroy(s->scsi_dev);
|
||||||
bdrv_delete(s->bs);
|
drive_uninit(s->dinfo->bdrv);
|
||||||
qemu_free(s);
|
qemu_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,19 +521,33 @@ static int usb_msd_initfn(USBDevice *dev)
|
||||||
{
|
{
|
||||||
MSDState *s = DO_UPCAST(MSDState, dev, dev);
|
MSDState *s = DO_UPCAST(MSDState, dev, dev);
|
||||||
|
|
||||||
|
if (!s->dinfo || !s->dinfo->bdrv) {
|
||||||
|
qemu_error("usb-msd: drive property not set\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
s->dev.speed = USB_SPEED_FULL;
|
s->dev.speed = USB_SPEED_FULL;
|
||||||
|
s->bus = scsi_bus_new(&s->dev.qdev, 0, 1, usb_msd_command_complete);
|
||||||
|
s->scsi_dev = scsi_bus_legacy_add_drive(s->bus, s->dinfo, 0);
|
||||||
|
usb_msd_handle_reset(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice *usb_msd_init(const char *filename)
|
USBDevice *usb_msd_init(const char *filename)
|
||||||
{
|
{
|
||||||
|
static int nr=0;
|
||||||
|
char id[8];
|
||||||
|
QemuOpts *opts;
|
||||||
|
DriveInfo *dinfo;
|
||||||
USBDevice *dev;
|
USBDevice *dev;
|
||||||
MSDState *s;
|
int fatal_error;
|
||||||
BlockDriverState *bdrv;
|
|
||||||
BlockDriver *drv = NULL;
|
|
||||||
const char *p1;
|
const char *p1;
|
||||||
char fmt[32];
|
char fmt[32];
|
||||||
|
|
||||||
|
/* parse -usbdevice disk: syntax into drive opts */
|
||||||
|
snprintf(id, sizeof(id), "usb%d", nr++);
|
||||||
|
opts = qemu_opts_create(&qemu_drive_opts, id, 0);
|
||||||
|
|
||||||
p1 = strchr(filename, ':');
|
p1 = strchr(filename, ':');
|
||||||
if (p1++) {
|
if (p1++) {
|
||||||
const char *p2;
|
const char *p2;
|
||||||
|
@ -539,52 +555,45 @@ USBDevice *usb_msd_init(const char *filename)
|
||||||
if (strstart(filename, "format=", &p2)) {
|
if (strstart(filename, "format=", &p2)) {
|
||||||
int len = MIN(p1 - p2, sizeof(fmt));
|
int len = MIN(p1 - p2, sizeof(fmt));
|
||||||
pstrcpy(fmt, len, p2);
|
pstrcpy(fmt, len, p2);
|
||||||
|
qemu_opt_set(opts, "format", fmt);
|
||||||
drv = bdrv_find_format(fmt);
|
|
||||||
if (!drv) {
|
|
||||||
printf("invalid format %s\n", fmt);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else if (*filename != ':') {
|
} else if (*filename != ':') {
|
||||||
printf("unrecognized USB mass-storage option %s\n", filename);
|
printf("unrecognized USB mass-storage option %s\n", filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
filename = p1;
|
filename = p1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*filename) {
|
if (!*filename) {
|
||||||
printf("block device specification needed\n");
|
printf("block device specification needed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
qemu_opt_set(opts, "file", filename);
|
||||||
|
qemu_opt_set(opts, "if", "none");
|
||||||
|
|
||||||
bdrv = bdrv_new("usb");
|
/* create host drive */
|
||||||
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
dinfo = drive_init(opts, NULL, &fatal_error);
|
||||||
|
if (!dinfo) {
|
||||||
|
qemu_opts_del(opts);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB MSD");
|
/* create guest device */
|
||||||
s = DO_UPCAST(MSDState, dev, dev);
|
dev = usb_create(NULL /* FIXME */, "QEMU USB MSD");
|
||||||
s->bs = bdrv;
|
qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
|
||||||
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
|
qdev_init(&dev->qdev);
|
||||||
filename);
|
|
||||||
|
|
||||||
s->bus = scsi_bus_new(&s->dev.qdev, 0, 1, usb_msd_command_complete);
|
return dev;
|
||||||
#if 0
|
|
||||||
s->scsi_dev = scsi_disk_init(s->bus, bdrv);
|
|
||||||
#endif
|
|
||||||
usb_msd_handle_reset((USBDevice *)s);
|
|
||||||
return (USBDevice *)s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
|
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
|
||||||
{
|
{
|
||||||
MSDState *s = (MSDState *)dev;
|
MSDState *s = (MSDState *)dev;
|
||||||
|
|
||||||
return s->bs;
|
return s->dinfo->bdrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct USBDeviceInfo msd_info = {
|
static struct USBDeviceInfo msd_info = {
|
||||||
.qdev.name = "QEMU USB MSD",
|
.qdev.name = "QEMU USB MSD",
|
||||||
|
.qdev.alias = "usb-storage",
|
||||||
.qdev.size = sizeof(MSDState),
|
.qdev.size = sizeof(MSDState),
|
||||||
.init = usb_msd_initfn,
|
.init = usb_msd_initfn,
|
||||||
.handle_packet = usb_generic_handle_packet,
|
.handle_packet = usb_generic_handle_packet,
|
||||||
|
@ -592,6 +601,10 @@ static struct USBDeviceInfo msd_info = {
|
||||||
.handle_control = usb_msd_handle_control,
|
.handle_control = usb_msd_handle_control,
|
||||||
.handle_data = usb_msd_handle_data,
|
.handle_data = usb_msd_handle_data,
|
||||||
.handle_destroy = usb_msd_handle_destroy,
|
.handle_destroy = usb_msd_handle_destroy,
|
||||||
|
.qdev.props = (Property[]) {
|
||||||
|
DEFINE_PROP_DRIVE("drive", MSDState, dinfo),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usb_msd_register_devices(void)
|
static void usb_msd_register_devices(void)
|
||||||
|
|
Loading…
Reference in a new issue