Revision 7fc2f2c0
b/hw/usb-msd.c | ||
---|---|---|
8 | 8 |
*/ |
9 | 9 |
|
10 | 10 |
#include "qemu-common.h" |
11 |
#include "qemu-option.h" |
|
12 |
#include "qemu-config.h" |
|
11 | 13 |
#include "usb.h" |
12 | 14 |
#include "block.h" |
13 | 15 |
#include "scsi-disk.h" |
... | ... | |
43 | 45 |
uint32_t data_len; |
44 | 46 |
uint32_t residue; |
45 | 47 |
uint32_t tag; |
46 |
BlockDriverState *bs; |
|
47 | 48 |
SCSIBus *bus; |
49 |
DriveInfo *dinfo; |
|
48 | 50 |
SCSIDevice *scsi_dev; |
49 | 51 |
int result; |
50 | 52 |
/* For async completion. */ |
... | ... | |
511 | 513 |
MSDState *s = (MSDState *)dev; |
512 | 514 |
|
513 | 515 |
s->scsi_dev->info->destroy(s->scsi_dev); |
514 |
bdrv_delete(s->bs);
|
|
516 |
drive_uninit(s->dinfo->bdrv);
|
|
515 | 517 |
qemu_free(s); |
516 | 518 |
} |
517 | 519 |
|
... | ... | |
519 | 521 |
{ |
520 | 522 |
MSDState *s = DO_UPCAST(MSDState, dev, dev); |
521 | 523 |
|
524 |
if (!s->dinfo || !s->dinfo->bdrv) { |
|
525 |
qemu_error("usb-msd: drive property not set\n"); |
|
526 |
return -1; |
|
527 |
} |
|
528 |
|
|
522 | 529 |
s->dev.speed = USB_SPEED_FULL; |
530 |
s->bus = scsi_bus_new(&s->dev.qdev, 0, 1, usb_msd_command_complete); |
|
531 |
s->scsi_dev = scsi_bus_legacy_add_drive(s->bus, s->dinfo, 0); |
|
532 |
usb_msd_handle_reset(dev); |
|
523 | 533 |
return 0; |
524 | 534 |
} |
525 | 535 |
|
526 | 536 |
USBDevice *usb_msd_init(const char *filename) |
527 | 537 |
{ |
538 |
static int nr=0; |
|
539 |
char id[8]; |
|
540 |
QemuOpts *opts; |
|
541 |
DriveInfo *dinfo; |
|
528 | 542 |
USBDevice *dev; |
529 |
MSDState *s; |
|
530 |
BlockDriverState *bdrv; |
|
531 |
BlockDriver *drv = NULL; |
|
543 |
int fatal_error; |
|
532 | 544 |
const char *p1; |
533 | 545 |
char fmt[32]; |
534 | 546 |
|
547 |
/* parse -usbdevice disk: syntax into drive opts */ |
|
548 |
snprintf(id, sizeof(id), "usb%d", nr++); |
|
549 |
opts = qemu_opts_create(&qemu_drive_opts, id, 0); |
|
550 |
|
|
535 | 551 |
p1 = strchr(filename, ':'); |
536 | 552 |
if (p1++) { |
537 | 553 |
const char *p2; |
... | ... | |
539 | 555 |
if (strstart(filename, "format=", &p2)) { |
540 | 556 |
int len = MIN(p1 - p2, sizeof(fmt)); |
541 | 557 |
pstrcpy(fmt, len, p2); |
542 |
|
|
543 |
drv = bdrv_find_format(fmt); |
|
544 |
if (!drv) { |
|
545 |
printf("invalid format %s\n", fmt); |
|
546 |
return NULL; |
|
547 |
} |
|
558 |
qemu_opt_set(opts, "format", fmt); |
|
548 | 559 |
} else if (*filename != ':') { |
549 | 560 |
printf("unrecognized USB mass-storage option %s\n", filename); |
550 | 561 |
return NULL; |
551 | 562 |
} |
552 |
|
|
553 | 563 |
filename = p1; |
554 | 564 |
} |
555 |
|
|
556 | 565 |
if (!*filename) { |
557 | 566 |
printf("block device specification needed\n"); |
558 | 567 |
return NULL; |
559 | 568 |
} |
569 |
qemu_opt_set(opts, "file", filename); |
|
570 |
qemu_opt_set(opts, "if", "none"); |
|
560 | 571 |
|
561 |
bdrv = bdrv_new("usb"); |
|
562 |
if (bdrv_open2(bdrv, filename, 0, drv) < 0) |
|
572 |
/* create host drive */ |
|
573 |
dinfo = drive_init(opts, NULL, &fatal_error); |
|
574 |
if (!dinfo) { |
|
575 |
qemu_opts_del(opts); |
|
563 | 576 |
return NULL; |
577 |
} |
|
564 | 578 |
|
565 |
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB MSD"); |
|
566 |
s = DO_UPCAST(MSDState, dev, dev); |
|
567 |
s->bs = bdrv; |
|
568 |
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)", |
|
569 |
filename); |
|
579 |
/* create guest device */ |
|
580 |
dev = usb_create(NULL /* FIXME */, "QEMU USB MSD"); |
|
581 |
qdev_prop_set_drive(&dev->qdev, "drive", dinfo); |
|
582 |
qdev_init(&dev->qdev); |
|
570 | 583 |
|
571 |
s->bus = scsi_bus_new(&s->dev.qdev, 0, 1, usb_msd_command_complete); |
|
572 |
#if 0 |
|
573 |
s->scsi_dev = scsi_disk_init(s->bus, bdrv); |
|
574 |
#endif |
|
575 |
usb_msd_handle_reset((USBDevice *)s); |
|
576 |
return (USBDevice *)s; |
|
584 |
return dev; |
|
577 | 585 |
} |
578 | 586 |
|
579 | 587 |
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev) |
580 | 588 |
{ |
581 | 589 |
MSDState *s = (MSDState *)dev; |
582 | 590 |
|
583 |
return s->bs;
|
|
591 |
return s->dinfo->bdrv;
|
|
584 | 592 |
} |
585 | 593 |
|
586 | 594 |
static struct USBDeviceInfo msd_info = { |
587 | 595 |
.qdev.name = "QEMU USB MSD", |
596 |
.qdev.alias = "usb-storage", |
|
588 | 597 |
.qdev.size = sizeof(MSDState), |
589 | 598 |
.init = usb_msd_initfn, |
590 | 599 |
.handle_packet = usb_generic_handle_packet, |
... | ... | |
592 | 601 |
.handle_control = usb_msd_handle_control, |
593 | 602 |
.handle_data = usb_msd_handle_data, |
594 | 603 |
.handle_destroy = usb_msd_handle_destroy, |
604 |
.qdev.props = (Property[]) { |
|
605 |
DEFINE_PROP_DRIVE("drive", MSDState, dinfo), |
|
606 |
DEFINE_PROP_END_OF_LIST(), |
|
607 |
}, |
|
595 | 608 |
}; |
596 | 609 |
|
597 | 610 |
static void usb_msd_register_devices(void) |
Also available in: Unified diff