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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user