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