2 * USB Mass Storage Device emulation
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the LGPL.
10 #include "qemu/osdep.h"
11 #include "qapi/error.h"
12 #include "qapi/visitor.h"
14 #include "hw/usb/desc.h"
15 #include "hw/usb/msd.h"
16 #include "sysemu/sysemu.h"
17 #include "sysemu/block-backend.h"
19 static const struct SCSIBusInfo usb_msd_scsi_info_storage
= {
24 .transfer_data
= usb_msd_transfer_data
,
25 .complete
= usb_msd_command_complete
,
26 .cancel
= usb_msd_request_cancelled
,
27 .load_request
= usb_msd_load_request
,
30 static void usb_msd_storage_realize(USBDevice
*dev
, Error
**errp
)
32 MSDState
*s
= USB_STORAGE_DEV(dev
);
33 BlockBackend
*blk
= s
->conf
.blk
;
37 error_setg(errp
, "drive property not set");
41 if (!blkconf_blocksizes(&s
->conf
, errp
)) {
45 if (!blkconf_apply_backend_options(&s
->conf
, !blk_supports_write_perm(blk
),
51 * Hack alert: this pretends to be a block device, but it's really
52 * a SCSI bus that can serve only a single device, which it
53 * creates automatically. But first it needs to detach from its
54 * blockdev, or else scsi_bus_legacy_add_drive() dies when it
55 * attaches again. We also need to take another reference so that
56 * blk_detach_dev() doesn't free blk while we still need it.
58 * The hack is probably a bad idea.
61 blk_detach_dev(blk
, DEVICE(s
));
64 usb_desc_create_serial(dev
);
66 dev
->flags
|= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE
);
67 scsi_bus_init(&s
->bus
, sizeof(s
->bus
), DEVICE(dev
),
68 &usb_msd_scsi_info_storage
);
69 scsi_dev
= scsi_bus_legacy_add_drive(&s
->bus
, blk
, 0, !!s
->removable
,
70 s
->conf
.bootindex
, s
->conf
.share_rw
,
71 s
->conf
.rerror
, s
->conf
.werror
,
78 usb_msd_handle_reset(dev
);
79 s
->scsi_dev
= scsi_dev
;
82 static Property msd_properties
[] = {
83 DEFINE_BLOCK_PROPERTIES(MSDState
, conf
),
84 DEFINE_BLOCK_ERROR_PROPERTIES(MSDState
, conf
),
85 DEFINE_PROP_BOOL("removable", MSDState
, removable
, false),
86 DEFINE_PROP_BOOL("commandlog", MSDState
, commandlog
, false),
87 DEFINE_PROP_END_OF_LIST(),
90 static void usb_msd_class_storage_initfn(ObjectClass
*klass
, void *data
)
92 DeviceClass
*dc
= DEVICE_CLASS(klass
);
93 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
95 uc
->realize
= usb_msd_storage_realize
;
96 device_class_set_props(dc
, msd_properties
);
99 static void usb_msd_get_bootindex(Object
*obj
, Visitor
*v
, const char *name
,
100 void *opaque
, Error
**errp
)
102 USBDevice
*dev
= USB_DEVICE(obj
);
103 MSDState
*s
= USB_STORAGE_DEV(dev
);
105 visit_type_int32(v
, name
, &s
->conf
.bootindex
, errp
);
108 static void usb_msd_set_bootindex(Object
*obj
, Visitor
*v
, const char *name
,
109 void *opaque
, Error
**errp
)
111 USBDevice
*dev
= USB_DEVICE(obj
);
112 MSDState
*s
= USB_STORAGE_DEV(dev
);
114 Error
*local_err
= NULL
;
116 if (!visit_type_int32(v
, name
, &boot_index
, errp
)) {
119 /* check whether bootindex is present in fw_boot_order list */
120 check_boot_index(boot_index
, &local_err
);
124 /* change bootindex to a new one */
125 s
->conf
.bootindex
= boot_index
;
128 object_property_set_int(OBJECT(s
->scsi_dev
), "bootindex", boot_index
,
133 error_propagate(errp
, local_err
);
136 static void usb_msd_instance_init(Object
*obj
)
138 object_property_add(obj
, "bootindex", "int32",
139 usb_msd_get_bootindex
,
140 usb_msd_set_bootindex
, NULL
, NULL
);
141 object_property_set_int(obj
, "bootindex", -1, NULL
);
144 static const TypeInfo msd_info
= {
145 .name
= "usb-storage",
146 .parent
= TYPE_USB_STORAGE
,
147 .class_init
= usb_msd_class_storage_initfn
,
148 .instance_init
= usb_msd_instance_init
,
151 static void register_types(void)
153 type_register_static(&msd_info
);
156 type_init(register_types
)