]> git.proxmox.com Git - mirror_qemu.git/blame - hw/usb/dev-storage.c
MAINTAINERS: update RBD block maintainer
[mirror_qemu.git] / hw / usb / dev-storage.c
CommitLineData
5fafdf24 1/*
2e5d83bb
PB
2 * USB Mass Storage Device emulation
3 *
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
6 *
8e31bf38 7 * This code is licensed under the LGPL.
2e5d83bb
PB
8 */
9
e532b2e0 10#include "qemu/osdep.h"
da34e65c 11#include "qapi/error.h"
d49b6836 12#include "qemu/error-report.h"
0b8fa32f 13#include "qemu/module.h"
1de7afc9
PB
14#include "qemu/option.h"
15#include "qemu/config-file.h"
f1ae32a1 16#include "hw/usb.h"
463581a8 17#include "desc.h"
0d09e41a 18#include "hw/scsi/scsi.h"
28ecbaee 19#include "ui/console.h"
83c9089e 20#include "monitor/monitor.h"
9c17d615 21#include "sysemu/sysemu.h"
fa1d36df 22#include "sysemu/block-backend.h"
89f0762d 23#include "qapi/visitor.h"
f348b6d1 24#include "qemu/cutils.h"
2e5d83bb
PB
25
26//#define DEBUG_MSD
27
28#ifdef DEBUG_MSD
001faf32
BS
29#define DPRINTF(fmt, ...) \
30do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 31#else
001faf32 32#define DPRINTF(fmt, ...) do {} while(0)
2e5d83bb
PB
33#endif
34
35/* USB requests. */
36#define MassStorageReset 0xff
37#define GetMaxLun 0xfe
38
39enum USBMSDMode {
40 USB_MSDM_CBW, /* Command Block. */
94843f66 41 USB_MSDM_DATAOUT, /* Transfer data to device. */
2e5d83bb
PB
42 USB_MSDM_DATAIN, /* Transfer data from device. */
43 USB_MSDM_CSW /* Command Status. */
44};
45
92a114f6
GH
46struct usb_msd_csw {
47 uint32_t sig;
48 uint32_t tag;
49 uint32_t residue;
50 uint8_t status;
51};
52
2e5d83bb
PB
53typedef struct {
54 USBDevice dev;
55 enum USBMSDMode mode;
1dc90367 56 uint32_t scsi_off;
a917d384 57 uint32_t scsi_len;
2e5d83bb 58 uint32_t data_len;
92a114f6 59 struct usb_msd_csw csw;
5c6c0e51 60 SCSIRequest *req;
ca9c39fa 61 SCSIBus bus;
34707333
GH
62 /* For async completion. */
63 USBPacket *packet;
64 /* usb-storage only */
428c149b 65 BlockConf conf;
6bb7b867 66 uint32_t removable;
89f0762d 67 SCSIDevice *scsi_dev;
2e5d83bb
PB
68} MSDState;
69
79e2590c
GA
70#define TYPE_USB_STORAGE "usb-storage-dev"
71#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE)
72
a917d384
PB
73struct usb_msd_cbw {
74 uint32_t sig;
75 uint32_t tag;
76 uint32_t data_len;
77 uint8_t flags;
78 uint8_t lun;
79 uint8_t cmd_len;
80 uint8_t cmd[16];
81};
82
81bfd2f2
GH
83enum {
84 STR_MANUFACTURER = 1,
85 STR_PRODUCT,
86 STR_SERIALNUMBER,
ca0c730d
GH
87 STR_CONFIG_FULL,
88 STR_CONFIG_HIGH,
79b40459 89 STR_CONFIG_SUPER,
2e5d83bb
PB
90};
91
81bfd2f2 92static const USBDescStrings desc_strings = {
93bfef4c 93 [STR_MANUFACTURER] = "QEMU",
81bfd2f2
GH
94 [STR_PRODUCT] = "QEMU USB HARDDRIVE",
95 [STR_SERIALNUMBER] = "1",
ca0c730d
GH
96 [STR_CONFIG_FULL] = "Full speed config (usb 1.1)",
97 [STR_CONFIG_HIGH] = "High speed config (usb 2.0)",
79b40459 98 [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
81bfd2f2
GH
99};
100
ca0c730d 101static const USBDescIface desc_iface_full = {
81bfd2f2
GH
102 .bInterfaceNumber = 0,
103 .bNumEndpoints = 2,
104 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
105 .bInterfaceSubClass = 0x06, /* SCSI */
106 .bInterfaceProtocol = 0x50, /* Bulk */
107 .eps = (USBDescEndpoint[]) {
108 {
109 .bEndpointAddress = USB_DIR_IN | 0x01,
110 .bmAttributes = USB_ENDPOINT_XFER_BULK,
111 .wMaxPacketSize = 64,
112 },{
113 .bEndpointAddress = USB_DIR_OUT | 0x02,
114 .bmAttributes = USB_ENDPOINT_XFER_BULK,
115 .wMaxPacketSize = 64,
116 },
117 }
118};
119
ca0c730d
GH
120static const USBDescDevice desc_device_full = {
121 .bcdUSB = 0x0200,
81bfd2f2
GH
122 .bMaxPacketSize0 = 8,
123 .bNumConfigurations = 1,
124 .confs = (USBDescConfig[]) {
125 {
126 .bNumInterfaces = 1,
127 .bConfigurationValue = 1,
ca0c730d 128 .iConfiguration = STR_CONFIG_FULL,
bd93976a 129 .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
add75088 130 .nif = 1,
ca0c730d
GH
131 .ifs = &desc_iface_full,
132 },
133 },
134};
135
136static const USBDescIface desc_iface_high = {
137 .bInterfaceNumber = 0,
138 .bNumEndpoints = 2,
139 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
140 .bInterfaceSubClass = 0x06, /* SCSI */
141 .bInterfaceProtocol = 0x50, /* Bulk */
142 .eps = (USBDescEndpoint[]) {
143 {
144 .bEndpointAddress = USB_DIR_IN | 0x01,
145 .bmAttributes = USB_ENDPOINT_XFER_BULK,
146 .wMaxPacketSize = 512,
147 },{
148 .bEndpointAddress = USB_DIR_OUT | 0x02,
149 .bmAttributes = USB_ENDPOINT_XFER_BULK,
150 .wMaxPacketSize = 512,
151 },
152 }
153};
154
155static const USBDescDevice desc_device_high = {
156 .bcdUSB = 0x0200,
157 .bMaxPacketSize0 = 64,
158 .bNumConfigurations = 1,
159 .confs = (USBDescConfig[]) {
160 {
161 .bNumInterfaces = 1,
162 .bConfigurationValue = 1,
163 .iConfiguration = STR_CONFIG_HIGH,
bd93976a 164 .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
add75088 165 .nif = 1,
ca0c730d 166 .ifs = &desc_iface_high,
81bfd2f2
GH
167 },
168 },
169};
170
79b40459
GH
171static const USBDescIface desc_iface_super = {
172 .bInterfaceNumber = 0,
173 .bNumEndpoints = 2,
174 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
175 .bInterfaceSubClass = 0x06, /* SCSI */
176 .bInterfaceProtocol = 0x50, /* Bulk */
177 .eps = (USBDescEndpoint[]) {
178 {
179 .bEndpointAddress = USB_DIR_IN | 0x01,
180 .bmAttributes = USB_ENDPOINT_XFER_BULK,
181 .wMaxPacketSize = 1024,
182 .bMaxBurst = 15,
183 },{
184 .bEndpointAddress = USB_DIR_OUT | 0x02,
185 .bmAttributes = USB_ENDPOINT_XFER_BULK,
186 .wMaxPacketSize = 1024,
187 .bMaxBurst = 15,
188 },
189 }
190};
191
192static const USBDescDevice desc_device_super = {
193 .bcdUSB = 0x0300,
194 .bMaxPacketSize0 = 9,
195 .bNumConfigurations = 1,
196 .confs = (USBDescConfig[]) {
197 {
198 .bNumInterfaces = 1,
199 .bConfigurationValue = 1,
200 .iConfiguration = STR_CONFIG_SUPER,
bd93976a 201 .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
79b40459
GH
202 .nif = 1,
203 .ifs = &desc_iface_super,
204 },
205 },
206};
207
81bfd2f2
GH
208static const USBDesc desc = {
209 .id = {
db80358a
RT
210 .idVendor = 0x46f4, /* CRC16() of "QEMU" */
211 .idProduct = 0x0001,
81bfd2f2
GH
212 .bcdDevice = 0,
213 .iManufacturer = STR_MANUFACTURER,
214 .iProduct = STR_PRODUCT,
215 .iSerialNumber = STR_SERIALNUMBER,
216 },
79b40459
GH
217 .full = &desc_device_full,
218 .high = &desc_device_high,
219 .super = &desc_device_super,
220 .str = desc_strings,
2e5d83bb
PB
221};
222
29c74f76 223static void usb_msd_copy_data(MSDState *s, USBPacket *p)
a917d384
PB
224{
225 uint32_t len;
9a77a0f5 226 len = p->iov.size - p->actual_length;
a917d384
PB
227 if (len > s->scsi_len)
228 len = s->scsi_len;
1dc90367 229 usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
a917d384 230 s->scsi_len -= len;
1dc90367 231 s->scsi_off += len;
a917d384 232 s->data_len -= len;
fa7935c1 233 if (s->scsi_len == 0 || s->data_len == 0) {
ad3376cc 234 scsi_req_continue(s->req);
a917d384
PB
235 }
236}
237
ab4797ad 238static void usb_msd_send_status(MSDState *s, USBPacket *p)
a917d384 239{
ab4797ad 240 int len;
a917d384 241
e04da7c3 242 DPRINTF("Command status %d tag 0x%x, len %zd\n",
e2854bf3 243 s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size);
92a114f6 244
e2854bf3 245 assert(s->csw.sig == cpu_to_le32(0x53425355));
92a114f6
GH
246 len = MIN(sizeof(s->csw), p->iov.size);
247 usb_packet_copy(p, &s->csw, len);
248 memset(&s->csw, 0, sizeof(s->csw));
a917d384
PB
249}
250
1e6ed80b
GH
251static void usb_msd_packet_complete(MSDState *s)
252{
253 USBPacket *p = s->packet;
254
255 /* Set s->packet to NULL before calling usb_packet_complete
256 because another request may be issued before
257 usb_packet_complete returns. */
258 DPRINTF("Packet complete %p\n", p);
259 s->packet = NULL;
260 usb_packet_complete(&s->dev, p);
261}
262
aba1f023 263static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
2e5d83bb 264{
5c6c0e51 265 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
a917d384 266 USBPacket *p = s->packet;
4d611c9a 267
ad3376cc 268 assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
aba1f023 269 s->scsi_len = len;
1dc90367 270 s->scsi_off = 0;
a917d384 271 if (p) {
29c74f76
GH
272 usb_msd_copy_data(s, p);
273 p = s->packet;
9a77a0f5
HG
274 if (p && p->actual_length == p->iov.size) {
275 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
1e6ed80b 276 usb_msd_packet_complete(s);
a917d384 277 }
4d611c9a 278 }
2e5d83bb
PB
279}
280
01e95455 281static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
c6df7102
PB
282{
283 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
284 USBPacket *p = s->packet;
285
7b863f41 286 DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
92a114f6
GH
287
288 s->csw.sig = cpu_to_le32(0x53425355);
7b863f41 289 s->csw.tag = cpu_to_le32(req->tag);
0659879e 290 s->csw.residue = cpu_to_le32(s->data_len);
414c4604 291 s->csw.status = status != 0;
92a114f6 292
c6df7102
PB
293 if (s->packet) {
294 if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
295 /* A deferred packet with no write data remaining must be
296 the status read packet. */
297 usb_msd_send_status(s, p);
298 s->mode = USB_MSDM_CBW;
54414218
GH
299 } else if (s->mode == USB_MSDM_CSW) {
300 usb_msd_send_status(s, p);
301 s->mode = USB_MSDM_CBW;
c6df7102
PB
302 } else {
303 if (s->data_len) {
9a77a0f5 304 int len = (p->iov.size - p->actual_length);
29c74f76
GH
305 usb_packet_skip(p, len);
306 s->data_len -= len;
c6df7102
PB
307 }
308 if (s->data_len == 0) {
309 s->mode = USB_MSDM_CSW;
310 }
311 }
9a77a0f5 312 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
1e6ed80b 313 usb_msd_packet_complete(s);
c6df7102
PB
314 } else if (s->data_len == 0) {
315 s->mode = USB_MSDM_CSW;
316 }
317 scsi_req_unref(req);
318 s->req = NULL;
319}
320
94d3f98a
PB
321static void usb_msd_request_cancelled(SCSIRequest *req)
322{
323 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
324
325 if (req == s->req) {
326 scsi_req_unref(s->req);
327 s->req = NULL;
94d3f98a
PB
328 s->scsi_len = 0;
329 }
330}
331
059809e4 332static void usb_msd_handle_reset(USBDevice *dev)
2e5d83bb
PB
333{
334 MSDState *s = (MSDState *)dev;
335
336 DPRINTF("Reset\n");
24a5bbe1
GH
337 if (s->req) {
338 scsi_req_cancel(s->req);
339 }
340 assert(s->req == NULL);
341
342 if (s->packet) {
9a77a0f5 343 s->packet->status = USB_RET_STALL;
1e6ed80b 344 usb_msd_packet_complete(s);
24a5bbe1
GH
345 }
346
2e5d83bb 347 s->mode = USB_MSDM_CBW;
2e5d83bb
PB
348}
349
9a77a0f5 350static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
007fd62f 351 int request, int value, int index, int length, uint8_t *data)
2e5d83bb
PB
352{
353 MSDState *s = (MSDState *)dev;
34707333
GH
354 SCSIDevice *scsi_dev;
355 int ret, maxlun;
2e5d83bb 356
007fd62f 357 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
81bfd2f2 358 if (ret >= 0) {
9a77a0f5 359 return;
81bfd2f2
GH
360 }
361
2e5d83bb 362 switch (request) {
2e5d83bb 363 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
e5322f76 364 break;
2e5d83bb 365 /* Class specific requests. */
f3571b1a 366 case ClassInterfaceOutRequest | MassStorageReset:
2e5d83bb
PB
367 /* Reset state ready for the next CBW. */
368 s->mode = USB_MSDM_CBW;
2e5d83bb 369 break;
f3571b1a 370 case ClassInterfaceRequest | GetMaxLun:
34707333
GH
371 maxlun = 0;
372 for (;;) {
373 scsi_dev = scsi_device_find(&s->bus, 0, 0, maxlun+1);
374 if (scsi_dev == NULL) {
375 break;
376 }
377 if (scsi_dev->lun != maxlun+1) {
378 break;
379 }
380 maxlun++;
381 }
382 DPRINTF("MaxLun %d\n", maxlun);
383 data[0] = maxlun;
9a77a0f5 384 p->actual_length = 1;
2e5d83bb
PB
385 break;
386 default:
9a77a0f5 387 p->status = USB_RET_STALL;
2e5d83bb
PB
388 break;
389 }
2e5d83bb
PB
390}
391
eb5e680a 392static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
4d611c9a 393{
79e2590c 394 MSDState *s = USB_STORAGE_DEV(dev);
d3ac1a87 395
6d7aeeeb
GH
396 assert(s->packet == p);
397 s->packet = NULL;
398
d3ac1a87
GH
399 if (s->req) {
400 scsi_req_cancel(s->req);
401 }
4d611c9a
PB
402}
403
9a77a0f5 404static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
2e5d83bb
PB
405{
406 MSDState *s = (MSDState *)dev;
7b863f41 407 uint32_t tag;
2e5d83bb 408 struct usb_msd_cbw cbw;
079d0b7f 409 uint8_t devep = p->ep->nr;
34707333 410 SCSIDevice *scsi_dev;
9db7c414 411 uint32_t len;
2e5d83bb 412
4d611c9a 413 switch (p->pid) {
2e5d83bb
PB
414 case USB_TOKEN_OUT:
415 if (devep != 2)
416 goto fail;
417
418 switch (s->mode) {
419 case USB_MSDM_CBW:
29c74f76 420 if (p->iov.size != 31) {
f5dc5978 421 error_report("usb-msd: Bad CBW size");
2e5d83bb
PB
422 goto fail;
423 }
29c74f76 424 usb_packet_copy(p, &cbw, 31);
2e5d83bb 425 if (le32_to_cpu(cbw.sig) != 0x43425355) {
f5dc5978
GA
426 error_report("usb-msd: Bad signature %08x",
427 le32_to_cpu(cbw.sig));
2e5d83bb
PB
428 goto fail;
429 }
430 DPRINTF("Command on LUN %d\n", cbw.lun);
34707333
GH
431 scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun);
432 if (scsi_dev == NULL) {
f5dc5978 433 error_report("usb-msd: Bad LUN %d", cbw.lun);
2e5d83bb
PB
434 goto fail;
435 }
7b863f41 436 tag = le32_to_cpu(cbw.tag);
2e5d83bb
PB
437 s->data_len = le32_to_cpu(cbw.data_len);
438 if (s->data_len == 0) {
439 s->mode = USB_MSDM_CSW;
440 } else if (cbw.flags & 0x80) {
441 s->mode = USB_MSDM_DATAIN;
442 } else {
443 s->mode = USB_MSDM_DATAOUT;
444 }
445 DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
7b863f41 446 tag, cbw.flags, cbw.cmd_len, s->data_len);
0659879e 447 assert(le32_to_cpu(s->csw.residue) == 0);
ef0bdf77 448 s->scsi_len = 0;
34707333 449 s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL);
06f9847d
GH
450#ifdef DEBUG_MSD
451 scsi_req_print(s->req);
452#endif
9db7c414
GH
453 len = scsi_req_enqueue(s->req);
454 if (len) {
ad3376cc 455 scsi_req_continue(s->req);
a917d384 456 }
2e5d83bb
PB
457 break;
458
459 case USB_MSDM_DATAOUT:
29c74f76
GH
460 DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
461 if (p->iov.size > s->data_len) {
2e5d83bb 462 goto fail;
29c74f76 463 }
2e5d83bb 464
a917d384 465 if (s->scsi_len) {
29c74f76 466 usb_msd_copy_data(s, p);
a917d384 467 }
0659879e 468 if (le32_to_cpu(s->csw.residue)) {
9a77a0f5 469 int len = p->iov.size - p->actual_length;
29c74f76
GH
470 if (len) {
471 usb_packet_skip(p, len);
472 s->data_len -= len;
473 if (s->data_len == 0) {
474 s->mode = USB_MSDM_CSW;
475 }
476 }
a917d384 477 }
9a77a0f5 478 if (p->actual_length < p->iov.size) {
06f9847d 479 DPRINTF("Deferring packet %p [wait data-out]\n", p);
4d611c9a 480 s->packet = p;
9a77a0f5 481 p->status = USB_RET_ASYNC;
4d611c9a 482 }
2e5d83bb
PB
483 break;
484
485 default:
29c74f76 486 DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
2e5d83bb
PB
487 goto fail;
488 }
489 break;
490
491 case USB_TOKEN_IN:
492 if (devep != 1)
493 goto fail;
494
495 switch (s->mode) {
a917d384 496 case USB_MSDM_DATAOUT:
29c74f76 497 if (s->data_len != 0 || p->iov.size < 13) {
a917d384 498 goto fail;
29c74f76 499 }
a917d384 500 /* Waiting for SCSI write to complete. */
a917d384 501 s->packet = p;
9a77a0f5 502 p->status = USB_RET_ASYNC;
a917d384
PB
503 break;
504
2e5d83bb 505 case USB_MSDM_CSW:
29c74f76 506 if (p->iov.size < 13) {
2e5d83bb 507 goto fail;
29c74f76 508 }
2e5d83bb 509
59310659
GH
510 if (s->req) {
511 /* still in flight */
06f9847d 512 DPRINTF("Deferring packet %p [wait status]\n", p);
59310659 513 s->packet = p;
9a77a0f5 514 p->status = USB_RET_ASYNC;
59310659
GH
515 } else {
516 usb_msd_send_status(s, p);
517 s->mode = USB_MSDM_CBW;
59310659 518 }
2e5d83bb
PB
519 break;
520
521 case USB_MSDM_DATAIN:
29c74f76
GH
522 DPRINTF("Data in %zd/%d, scsi_len %d\n",
523 p->iov.size, s->data_len, s->scsi_len);
a917d384 524 if (s->scsi_len) {
29c74f76 525 usb_msd_copy_data(s, p);
a917d384 526 }
0659879e 527 if (le32_to_cpu(s->csw.residue)) {
9a77a0f5 528 int len = p->iov.size - p->actual_length;
29c74f76
GH
529 if (len) {
530 usb_packet_skip(p, len);
531 s->data_len -= len;
532 if (s->data_len == 0) {
533 s->mode = USB_MSDM_CSW;
534 }
535 }
a917d384 536 }
9a77a0f5 537 if (p->actual_length < p->iov.size) {
06f9847d 538 DPRINTF("Deferring packet %p [wait data-in]\n", p);
4d611c9a 539 s->packet = p;
9a77a0f5 540 p->status = USB_RET_ASYNC;
4d611c9a 541 }
2e5d83bb
PB
542 break;
543
544 default:
29c74f76 545 DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
2e5d83bb
PB
546 goto fail;
547 }
548 break;
549
550 default:
551 DPRINTF("Bad token\n");
552 fail:
9a77a0f5 553 p->status = USB_RET_STALL;
2e5d83bb
PB
554 break;
555 }
2e5d83bb
PB
556}
557
5de88b1d
GH
558static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
559{
560 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
561
562 /* nothing to load, just store req in our state struct */
563 assert(s->req == NULL);
564 scsi_req_ref(req);
565 s->req = req;
566 return NULL;
567}
568
34707333 569static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
afd4030c 570 .tcq = false,
7e0380b9
PB
571 .max_target = 0,
572 .max_lun = 0,
afd4030c 573
c6df7102 574 .transfer_data = usb_msd_transfer_data,
94d3f98a 575 .complete = usb_msd_command_complete,
5de88b1d
GH
576 .cancel = usb_msd_request_cancelled,
577 .load_request = usb_msd_load_request,
cfdc1bb0
PB
578};
579
34707333
GH
580static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
581 .tcq = false,
582 .max_target = 0,
583 .max_lun = 15,
584
585 .transfer_data = usb_msd_transfer_data,
586 .complete = usb_msd_command_complete,
587 .cancel = usb_msd_request_cancelled,
588 .load_request = usb_msd_load_request,
589};
590
6db3ea39 591static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
806b6024 592{
79e2590c 593 MSDState *s = USB_STORAGE_DEV(dev);
4be74634 594 BlockBackend *blk = s->conf.blk;
34707333 595 SCSIDevice *scsi_dev;
806b6024 596
4be74634 597 if (!blk) {
5a882e40
GA
598 error_setg(errp, "drive property not set");
599 return;
7fc2f2c0
GH
600 }
601
0eb28a42 602 blkconf_blocksizes(&s->conf);
ceff3e1f
MZ
603 if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
604 errp)) {
a17c17a2
KW
605 return;
606 }
911525db 607
14bafc54
MA
608 /*
609 * Hack alert: this pretends to be a block device, but it's really
610 * a SCSI bus that can serve only a single device, which it
18846dee
MA
611 * creates automatically. But first it needs to detach from its
612 * blockdev, or else scsi_bus_legacy_add_drive() dies when it
8daea510
KW
613 * attaches again. We also need to take another reference so that
614 * blk_detach_dev() doesn't free blk while we still need it.
14bafc54
MA
615 *
616 * The hack is probably a bad idea.
617 */
8daea510 618 blk_ref(blk);
4ffebe23 619 blk_detach_dev(blk, DEVICE(s));
4be74634 620 s->conf.blk = NULL;
14bafc54 621
71938a09 622 usb_desc_create_serial(dev);
a980a065 623 usb_desc_init(dev);
b1187b51
AF
624 scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
625 &usb_msd_scsi_info_storage, NULL);
4be74634 626 scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
395b9539 627 s->conf.bootindex, s->conf.share_rw,
b8efb36b 628 s->conf.rerror, s->conf.werror,
395b9539 629 dev->serial,
ceff3e1f 630 errp);
8daea510 631 blk_unref(blk);
34707333 632 if (!scsi_dev) {
5a882e40 633 return;
fa66b909 634 }
7fc2f2c0 635 usb_msd_handle_reset(dev);
89f0762d 636 s->scsi_dev = scsi_dev;
806b6024
GH
637}
638
6db3ea39 639static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
34707333 640{
79e2590c 641 MSDState *s = USB_STORAGE_DEV(dev);
b78ecd09 642 DeviceState *d = DEVICE(dev);
34707333
GH
643
644 usb_desc_create_serial(dev);
645 usb_desc_init(dev);
b78ecd09
GH
646 if (d->hotplugged) {
647 s->dev.auto_attach = 0;
648 }
649
b1187b51
AF
650 scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
651 &usb_msd_scsi_info_bot, NULL);
34707333 652 usb_msd_handle_reset(dev);
34707333
GH
653}
654
f54b6563
GH
655static const VMStateDescription vmstate_usb_msd = {
656 .name = "usb-storage",
f54b6563
GH
657 .version_id = 1,
658 .minimum_version_id = 1,
6e3d652a 659 .fields = (VMStateField[]) {
f54b6563 660 VMSTATE_USB_DEVICE(dev, MSDState),
5de88b1d
GH
661 VMSTATE_UINT32(mode, MSDState),
662 VMSTATE_UINT32(scsi_len, MSDState),
663 VMSTATE_UINT32(scsi_off, MSDState),
664 VMSTATE_UINT32(data_len, MSDState),
665 VMSTATE_UINT32(csw.sig, MSDState),
666 VMSTATE_UINT32(csw.tag, MSDState),
667 VMSTATE_UINT32(csw.residue, MSDState),
668 VMSTATE_UINT8(csw.status, MSDState),
f54b6563
GH
669 VMSTATE_END_OF_LIST()
670 }
671};
672
39bffca2
AL
673static Property msd_properties[] = {
674 DEFINE_BLOCK_PROPERTIES(MSDState, conf),
b8efb36b 675 DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
39bffca2
AL
676 DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
677 DEFINE_PROP_END_OF_LIST(),
678};
679
79e2590c 680static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
62aed765 681{
39bffca2 682 DeviceClass *dc = DEVICE_CLASS(klass);
62aed765
AL
683 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
684
62aed765
AL
685 uc->product_desc = "QEMU USB MSD";
686 uc->usb_desc = &desc;
62aed765
AL
687 uc->cancel_packet = usb_msd_cancel_io;
688 uc->handle_attach = usb_desc_attach;
689 uc->handle_reset = usb_msd_handle_reset;
690 uc->handle_control = usb_msd_handle_control;
691 uc->handle_data = usb_msd_handle_data;
125ee0ed 692 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
39bffca2
AL
693 dc->fw_name = "storage";
694 dc->vmsd = &vmstate_usb_msd;
34707333
GH
695}
696
6db3ea39 697static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
34707333
GH
698{
699 DeviceClass *dc = DEVICE_CLASS(klass);
700 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
701
6db3ea39 702 uc->realize = usb_msd_storage_realize;
39bffca2 703 dc->props = msd_properties;
34707333
GH
704}
705
d7bce999
EB
706static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
707 void *opaque, Error **errp)
89f0762d
GA
708{
709 USBDevice *dev = USB_DEVICE(obj);
79e2590c 710 MSDState *s = USB_STORAGE_DEV(dev);
89f0762d 711
51e72bc1 712 visit_type_int32(v, name, &s->conf.bootindex, errp);
89f0762d
GA
713}
714
d7bce999
EB
715static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
716 void *opaque, Error **errp)
89f0762d
GA
717{
718 USBDevice *dev = USB_DEVICE(obj);
79e2590c 719 MSDState *s = USB_STORAGE_DEV(dev);
89f0762d
GA
720 int32_t boot_index;
721 Error *local_err = NULL;
722
51e72bc1 723 visit_type_int32(v, name, &boot_index, &local_err);
89f0762d
GA
724 if (local_err) {
725 goto out;
726 }
727 /* check whether bootindex is present in fw_boot_order list */
728 check_boot_index(boot_index, &local_err);
729 if (local_err) {
730 goto out;
731 }
732 /* change bootindex to a new one */
733 s->conf.bootindex = boot_index;
734
735 if (s->scsi_dev) {
736 object_property_set_int(OBJECT(s->scsi_dev), boot_index, "bootindex",
737 &error_abort);
738 }
739
740out:
621ff94d 741 error_propagate(errp, local_err);
89f0762d
GA
742}
743
79e2590c
GA
744static const TypeInfo usb_storage_dev_type_info = {
745 .name = TYPE_USB_STORAGE,
746 .parent = TYPE_USB_DEVICE,
747 .instance_size = sizeof(MSDState),
748 .abstract = true,
749 .class_init = usb_msd_class_initfn_common,
750};
751
89f0762d
GA
752static void usb_msd_instance_init(Object *obj)
753{
754 object_property_add(obj, "bootindex", "int32",
755 usb_msd_get_bootindex,
756 usb_msd_set_bootindex, NULL, NULL, NULL);
757 object_property_set_int(obj, -1, "bootindex", NULL);
758}
759
6db3ea39 760static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
34707333
GH
761{
762 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
763
6db3ea39 764 uc->realize = usb_msd_bot_realize;
b78ecd09 765 uc->attached_settable = true;
62aed765
AL
766}
767
8c43a6f0 768static const TypeInfo msd_info = {
39bffca2 769 .name = "usb-storage",
79e2590c 770 .parent = TYPE_USB_STORAGE,
6db3ea39 771 .class_init = usb_msd_class_storage_initfn,
89f0762d 772 .instance_init = usb_msd_instance_init,
34707333
GH
773};
774
775static const TypeInfo bot_info = {
776 .name = "usb-bot",
79e2590c 777 .parent = TYPE_USB_STORAGE,
6db3ea39 778 .class_init = usb_msd_class_bot_initfn,
806b6024
GH
779};
780
83f7d43a 781static void usb_msd_register_types(void)
806b6024 782{
79e2590c 783 type_register_static(&usb_storage_dev_type_info);
39bffca2 784 type_register_static(&msd_info);
34707333 785 type_register_static(&bot_info);
806b6024 786}
83f7d43a
AF
787
788type_init(usb_msd_register_types)