VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/UsbMsd.cpp@ 49435

Last change on this file since 49435 was 49093, checked in by vboxsync, 11 years ago

Storage/UsbMsd: Implement save state handlers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.1 KB
Line 
1/* $Id: UsbMsd.cpp 49093 2013-10-14 22:02:15Z vboxsync $ */
2/** @file
3 * UsbMSD - USB Mass Storage Device Emulation.
4 */
5
6/*
7 * Copyright (C) 2007-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_USB_MSD
22#include <VBox/vmm/pdmusb.h>
23#include <VBox/log.h>
24#include <VBox/err.h>
25#include <VBox/scsi.h>
26#include <iprt/assert.h>
27#include <iprt/critsect.h>
28#include <iprt/mem.h>
29#include <iprt/semaphore.h>
30#include <iprt/string.h>
31#include <iprt/uuid.h>
32#include "VBoxDD.h"
33
34
35/*******************************************************************************
36* Defined Constants And Macros *
37*******************************************************************************/
38/** @name USB MSD string IDs
39 * @{ */
40#define USBMSD_STR_ID_MANUFACTURER 1
41#define USBMSD_STR_ID_PRODUCT_HD 2
42#define USBMSD_STR_ID_PRODUCT_CDROM 3
43/** @} */
44
45/** @name USB MSD vendor and product IDs
46 * @{ */
47#define VBOX_USB_VENDOR 0x80EE
48#define USBMSD_PID_HD 0x0030
49#define USBMSD_PID_CD 0x0031
50/** @} */
51
52/** Saved state version. */
53#define USB_MSD_SAVED_STATE_VERSION 1
54
55/*******************************************************************************
56* Structures and Typedefs *
57*******************************************************************************/
58
59/**
60 * USB MSD Command Block Wrapper or CBW. The command block
61 * itself (CBWCB) contains protocol-specific data (here SCSI).
62 */
63#pragma pack(1)
64typedef struct USBCBW
65{
66 uint32_t dCBWSignature;
67#define USBCBW_SIGNATURE UINT32_C(0x43425355)
68 uint32_t dCBWTag;
69 uint32_t dCBWDataTransferLength;
70 uint8_t bmCBWFlags;
71#define USBCBW_DIR_MASK RT_BIT(7)
72#define USBCBW_DIR_OUT 0
73#define USBCBW_DIR_IN RT_BIT(7)
74 uint8_t bCBWLun;
75 uint8_t bCBWCBLength;
76 uint8_t CBWCB[16];
77} USBCBW;
78#pragma pack()
79AssertCompileSize(USBCBW, 31);
80/** Pointer to a Command Block Wrapper. */
81typedef USBCBW *PUSBCBW;
82/** Pointer to a const Command Block Wrapper. */
83typedef const USBCBW *PCUSBCBW;
84
85/**
86 * USB MSD Command Status Wrapper or CSW.
87 */
88#pragma pack(1)
89typedef struct USBCSW
90{
91 uint32_t dCSWSignature;
92#define USBCSW_SIGNATURE UINT32_C(0x53425355)
93 uint32_t dCSWTag;
94 uint32_t dCSWDataResidue;
95#define USBCSW_STATUS_OK UINT8_C(0)
96#define USBCSW_STATUS_FAILED UINT8_C(1)
97#define USBCSW_STATUS_PHASE_ERROR UINT8_C(2)
98 uint8_t bCSWStatus;
99} USBCSW;
100#pragma pack()
101AssertCompileSize(USBCSW, 13);
102/** Pointer to a Command Status Wrapper. */
103typedef USBCSW *PUSBCSW;
104/** Pointer to a const Command Status Wrapper. */
105typedef const USBCSW *PCUSBCSW;
106
107
108/**
109 * The USB MSD request state.
110 */
111typedef enum USBMSDREQSTATE
112{
113 /** Invalid status. */
114 USBMSDREQSTATE_INVALID = 0,
115 /** Ready to receive a new SCSI command. */
116 USBMSDREQSTATE_READY,
117 /** Waiting for the host to supply data. */
118 USBMSDREQSTATE_DATA_FROM_HOST,
119 /** The SCSI request is being executed by the driver. */
120 USBMSDREQSTATE_EXECUTING,
121 /** Have (more) data for the host. */
122 USBMSDREQSTATE_DATA_TO_HOST,
123 /** Waiting to supply status information to the host. */
124 USBMSDREQSTATE_STATUS,
125 /** Destroy the request upon completion.
126 * This is set when the SCSI request doesn't complete before for the device or
127 * mass storage reset operation times out. USBMSD::pReq will be set to NULL
128 * and the only reference to this request will be with DrvSCSI. */
129 USBMSDREQSTATE_DESTROY_ON_COMPLETION,
130 /** The end of the valid states. */
131 USBMSDREQSTATE_END,
132 /** 32bit blow up hack. */
133 USBMSDREQSTATE_32BIT_HACK = 0x7fffffff
134} USBMSDREQSTATE;
135
136
137/**
138 * A pending USB MSD request.
139 */
140typedef struct USBMSDREQ
141{
142 /** The state of the request. */
143 USBMSDREQSTATE enmState;
144 /** The size of the data buffer. */
145 size_t cbBuf;
146 /** Pointer to the data buffer. */
147 uint8_t *pbBuf;
148 /** Current buffer offset. */
149 uint32_t offBuf;
150 /** The current Cbw when we're in the pending state. */
151 USBCBW Cbw;
152 /** The current SCSI request. */
153 PDMSCSIREQUEST ScsiReq;
154 /** The scatter-gather segment used by ScsiReq for describing pbBuf. */
155 RTSGSEG ScsiReqSeg;
156 /** The sense buffer for the current SCSI request. */
157 uint8_t ScsiReqSense[64];
158 /** The status of a completed SCSI request. */
159 int iScsiReqStatus;
160 /** Set if the request structure must be destroyed when the SCSI driver
161 * completes it. This is used to deal with requests that runs while the
162 * device is being reset. */
163 bool fDestoryOnCompletion;
164 /** Pointer to the USB device instance owning it. */
165 PPDMUSBINS pUsbIns;
166} USBMSDREQ;
167/** Pointer to a USB MSD request. */
168typedef USBMSDREQ *PUSBMSDREQ;
169
170
171/**
172 * Endpoint status data.
173 */
174typedef struct USBMSDEP
175{
176 bool fHalted;
177} USBMSDEP;
178/** Pointer to the endpoint status. */
179typedef USBMSDEP *PUSBMSDEP;
180
181
182/**
183 * A URB queue.
184 */
185typedef struct USBMSDURBQUEUE
186{
187 /** The head pointer. */
188 PVUSBURB pHead;
189 /** Where to insert the next entry. */
190 PVUSBURB *ppTail;
191} USBMSDURBQUEUE;
192/** Pointer to a URB queue. */
193typedef USBMSDURBQUEUE *PUSBMSDURBQUEUE;
194/** Pointer to a const URB queue. */
195typedef USBMSDURBQUEUE const *PCUSBMSDURBQUEUE;
196
197
198/**
199 * The USB MSD instance data.
200 */
201typedef struct USBMSD
202{
203 /** Pointer back to the PDM USB Device instance structure. */
204 PPDMUSBINS pUsbIns;
205 /** Critical section protecting the device state. */
206 RTCRITSECT CritSect;
207
208 /** The current configuration.
209 * (0 - default, 1 - the only, i.e configured.) */
210 uint8_t bConfigurationValue;
211#if 0
212 /** The state of the MSD (state machine).*/
213 USBMSDSTATE enmState;
214#endif
215 /** Endpoint 0 is the default control pipe, 1 is the host->dev bulk pipe and 2
216 * is the dev->host one. */
217 USBMSDEP aEps[3];
218 /** The current request. */
219 PUSBMSDREQ pReq;
220
221 /** Pending to-host queue.
222 * The URBs waiting here are pending the completion of the current request and
223 * data or status to become available.
224 */
225 USBMSDURBQUEUE ToHostQueue;
226
227 /** Done queue
228 * The URBs stashed here are waiting to be reaped. */
229 USBMSDURBQUEUE DoneQueue;
230 /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
231 * is set. */
232 RTSEMEVENT hEvtDoneQueue;
233 /** Someone is waiting on the done queue. */
234 bool fHaveDoneQueueWaiter;
235
236 /** Whether to signal the reset semaphore when the current request completes. */
237 bool fSignalResetSem;
238 /** Semaphore usbMsdUsbReset waits on when a request is executing at reset
239 * time. Only signalled when fSignalResetSem is set. */
240 RTSEMEVENTMULTI hEvtReset;
241 /** The reset URB.
242 * This is waiting for SCSI request completion before finishing the reset. */
243 PVUSBURB pResetUrb;
244 /** Indicates that PDMUsbHlpAsyncNotificationCompleted should be called when
245 * the MSD is entering the idle state. */
246 volatile bool fSignalIdle;
247
248 /**
249 * LUN\#0 data.
250 */
251 struct
252 {
253 /** The base interface for LUN\#0. */
254 PDMIBASE IBase;
255 /** The SCSI port interface for LUN\#0 */
256 PDMISCSIPORT IScsiPort;
257
258 /** The base interface for the SCSI driver connected to LUN\#0. */
259 PPDMIBASE pIBase;
260 /** The SCSI connector interface for the SCSI driver connected to LUN\#0. */
261 PPDMISCSICONNECTOR pIScsiConnector;
262 } Lun0;
263
264} USBMSD;
265/** Pointer to the USB MSD instance data. */
266typedef USBMSD *PUSBMSD;
267
268
269/*******************************************************************************
270* Global Variables *
271*******************************************************************************/
272static const PDMUSBDESCCACHESTRING g_aUsbMsdStrings_en_US[] =
273{
274 { USBMSD_STR_ID_MANUFACTURER, "VirtualBox" },
275 { USBMSD_STR_ID_PRODUCT_HD, "USB Harddisk" },
276 { USBMSD_STR_ID_PRODUCT_CDROM, "USB CD-ROM" }
277};
278
279static const PDMUSBDESCCACHELANG g_aUsbMsdLanguages[] =
280{
281 { 0x0409, RT_ELEMENTS(g_aUsbMsdStrings_en_US), g_aUsbMsdStrings_en_US }
282};
283
284static const VUSBDESCENDPOINTEX g_aUsbMsdEndpointDescsFS[2] =
285{
286 {
287 {
288 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
289 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
290 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
291 /* .bmAttributes = */ 2 /* bulk */,
292 /* .wMaxPacketSize = */ 64 /* maximum possible */,
293 /* .bInterval = */ 0 /* not applicable for bulk EP */
294 },
295 /* .pvMore = */ NULL,
296 /* .pvClass = */ NULL,
297 /* .cbClass = */ 0
298 },
299 {
300 {
301 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
302 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
303 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
304 /* .bmAttributes = */ 2 /* bulk */,
305 /* .wMaxPacketSize = */ 64 /* maximum possible */,
306 /* .bInterval = */ 0 /* not applicable for bulk EP */
307 },
308 /* .pvMore = */ NULL,
309 /* .pvClass = */ NULL,
310 /* .cbClass = */ 0
311 }
312};
313
314static const VUSBDESCENDPOINTEX g_aUsbMsdEndpointDescsHS[2] =
315{
316 {
317 {
318 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
319 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
320 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
321 /* .bmAttributes = */ 2 /* bulk */,
322 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
323 /* .bInterval = */ 0 /* no NAKs */
324 },
325 /* .pvMore = */ NULL,
326 /* .pvClass = */ NULL,
327 /* .cbClass = */ 0
328 },
329 {
330 {
331 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
332 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
333 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
334 /* .bmAttributes = */ 2 /* bulk */,
335 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
336 /* .bInterval = */ 0 /* no NAKs */
337 },
338 /* .pvMore = */ NULL,
339 /* .pvClass = */ NULL,
340 /* .cbClass = */ 0
341 }
342};
343
344static const VUSBDESCINTERFACEEX g_UsbMsdInterfaceDescFS =
345{
346 {
347 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
348 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
349 /* .bInterfaceNumber = */ 0,
350 /* .bAlternateSetting = */ 0,
351 /* .bNumEndpoints = */ 2,
352 /* .bInterfaceClass = */ 8 /* Mass Storage */,
353 /* .bInterfaceSubClass = */ 6 /* SCSI transparent command set */,
354 /* .bInterfaceProtocol = */ 0x50 /* Bulk-Only Transport */,
355 /* .iInterface = */ 0
356 },
357 /* .pvMore = */ NULL,
358 /* .pvClass = */ NULL,
359 /* .cbClass = */ 0,
360 &g_aUsbMsdEndpointDescsFS[0],
361 /* .pIAD = */ NULL,
362 /* .cbIAD = */ 0
363};
364
365static const VUSBDESCINTERFACEEX g_UsbMsdInterfaceDescHS =
366{
367 {
368 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
369 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
370 /* .bInterfaceNumber = */ 0,
371 /* .bAlternateSetting = */ 0,
372 /* .bNumEndpoints = */ 2,
373 /* .bInterfaceClass = */ 8 /* Mass Storage */,
374 /* .bInterfaceSubClass = */ 6 /* SCSI transparent command set */,
375 /* .bInterfaceProtocol = */ 0x50 /* Bulk-Only Transport */,
376 /* .iInterface = */ 0
377 },
378 /* .pvMore = */ NULL,
379 /* .pvClass = */ NULL,
380 /* .cbClass = */ 0,
381 &g_aUsbMsdEndpointDescsHS[0],
382 /* .pIAD = */ NULL,
383 /* .cbIAD = */ 0
384};
385
386static const VUSBINTERFACE g_aUsbMsdInterfacesFS[] =
387{
388 { &g_UsbMsdInterfaceDescFS, /* .cSettings = */ 1 },
389};
390
391static const VUSBINTERFACE g_aUsbMsdInterfacesHS[] =
392{
393 { &g_UsbMsdInterfaceDescHS, /* .cSettings = */ 1 },
394};
395
396static const VUSBDESCCONFIGEX g_UsbMsdConfigDescFS =
397{
398 {
399 /* .bLength = */ sizeof(VUSBDESCCONFIG),
400 /* .bDescriptorType = */ VUSB_DT_CONFIG,
401 /* .wTotalLength = */ 0 /* recalculated on read */,
402 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbMsdInterfacesFS),
403 /* .bConfigurationValue =*/ 1,
404 /* .iConfiguration = */ 0,
405 /* .bmAttributes = */ RT_BIT(7),
406 /* .MaxPower = */ 50 /* 100mA */
407 },
408 NULL, /* pvMore */
409 &g_aUsbMsdInterfacesFS[0],
410 NULL /* pvOriginal */
411};
412
413static const VUSBDESCCONFIGEX g_UsbMsdConfigDescHS =
414{
415 {
416 /* .bLength = */ sizeof(VUSBDESCCONFIG),
417 /* .bDescriptorType = */ VUSB_DT_CONFIG,
418 /* .wTotalLength = */ 0 /* recalculated on read */,
419 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbMsdInterfacesHS),
420 /* .bConfigurationValue =*/ 1,
421 /* .iConfiguration = */ 0,
422 /* .bmAttributes = */ RT_BIT(7),
423 /* .MaxPower = */ 50 /* 100mA */
424 },
425 NULL, /* pvMore */
426 &g_aUsbMsdInterfacesHS[0],
427 NULL /* pvOriginal */
428};
429
430static const VUSBDESCDEVICE g_UsbMsdDeviceDesc =
431{
432 /* .bLength = */ sizeof(g_UsbMsdDeviceDesc),
433 /* .bDescriptorType = */ VUSB_DT_DEVICE,
434 /* .bcdUsb = */ 0x200, /* USB 2.0 */
435 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
436 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
437 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
438 /* .bMaxPacketSize0 = */ 64,
439 /* .idVendor = */ VBOX_USB_VENDOR,
440 /* .idProduct = */ USBMSD_PID_HD,
441 /* .bcdDevice = */ 0x0100, /* 1.0 */
442 /* .iManufacturer = */ USBMSD_STR_ID_MANUFACTURER,
443 /* .iProduct = */ USBMSD_STR_ID_PRODUCT_HD,
444 /* .iSerialNumber = */ 0,
445 /* .bNumConfigurations = */ 1
446};
447
448static const VUSBDEVICEQUALIFIER g_UsbMsdDeviceQualifier =
449{
450 /* .bLength = */ sizeof(g_UsbMsdDeviceQualifier),
451 /* .bDescriptorType = */ VUSB_DT_DEVICE_QUALIFIER,
452 /* .bcdUsb = */ 0x200, /* USB 2.0 */
453 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
454 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
455 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
456 /* .bMaxPacketSize0 = */ 64,
457 /* .bNumConfigurations = */ 1,
458 /* .bReserved = */ 0
459};
460
461static const PDMUSBDESCCACHE g_UsbMsdDescCacheFS =
462{
463 /* .pDevice = */ &g_UsbMsdDeviceDesc,
464 /* .paConfigs = */ &g_UsbMsdConfigDescFS,
465 /* .paLanguages = */ g_aUsbMsdLanguages,
466 /* .cLanguages = */ RT_ELEMENTS(g_aUsbMsdLanguages),
467 /* .fUseCachedDescriptors = */ true,
468 /* .fUseCachedStringsDescriptors = */ true
469};
470
471static const PDMUSBDESCCACHE g_UsbMsdDescCacheHS =
472{
473 /* .pDevice = */ &g_UsbMsdDeviceDesc,
474 /* .paConfigs = */ &g_UsbMsdConfigDescHS,
475 /* .paLanguages = */ g_aUsbMsdLanguages,
476 /* .cLanguages = */ RT_ELEMENTS(g_aUsbMsdLanguages),
477 /* .fUseCachedDescriptors = */ true,
478 /* .fUseCachedStringsDescriptors = */ true
479};
480
481
482/*******************************************************************************
483* Internal Functions *
484*******************************************************************************/
485static int usbMsdHandleBulkDevToHost(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb);
486
487
488/**
489 * Initializes an URB queue.
490 *
491 * @param pQueue The URB queue.
492 */
493static void usbMsdQueueInit(PUSBMSDURBQUEUE pQueue)
494{
495 pQueue->pHead = NULL;
496 pQueue->ppTail = &pQueue->pHead;
497}
498
499
500
501/**
502 * Inserts an URB at the end of the queue.
503 *
504 * @param pQueue The URB queue.
505 * @param pUrb The URB to insert.
506 */
507DECLINLINE(void) usbMsdQueueAddTail(PUSBMSDURBQUEUE pQueue, PVUSBURB pUrb)
508{
509 pUrb->Dev.pNext = NULL;
510 *pQueue->ppTail = pUrb;
511 pQueue->ppTail = &pUrb->Dev.pNext;
512}
513
514
515/**
516 * Unlinks the head of the queue and returns it.
517 *
518 * @returns The head entry.
519 * @param pQueue The URB queue.
520 */
521DECLINLINE(PVUSBURB) usbMsdQueueRemoveHead(PUSBMSDURBQUEUE pQueue)
522{
523 PVUSBURB pUrb = pQueue->pHead;
524 if (pUrb)
525 {
526 PVUSBURB pNext = pUrb->Dev.pNext;
527 pQueue->pHead = pNext;
528 if (!pNext)
529 pQueue->ppTail = &pQueue->pHead;
530 else
531 pUrb->Dev.pNext = NULL;
532 }
533 return pUrb;
534}
535
536
537/**
538 * Removes an URB from anywhere in the queue.
539 *
540 * @returns true if found, false if not.
541 * @param pQueue The URB queue.
542 * @param pUrb The URB to remove.
543 */
544DECLINLINE(bool) usbMsdQueueRemove(PUSBMSDURBQUEUE pQueue, PVUSBURB pUrb)
545{
546 PVUSBURB pCur = pQueue->pHead;
547 if (pCur == pUrb)
548 pQueue->pHead = pUrb->Dev.pNext;
549 else
550 {
551 while (pCur)
552 {
553 if (pCur->Dev.pNext == pUrb)
554 {
555 pCur->Dev.pNext = pUrb->Dev.pNext;
556 break;
557 }
558 pCur = pCur->Dev.pNext;
559 }
560 if (!pCur)
561 return false;
562 }
563 if (!pUrb->Dev.pNext)
564 pQueue->ppTail = &pQueue->pHead;
565 return true;
566}
567
568
569/**
570 * Checks if the queue is empty or not.
571 *
572 * @returns true if it is, false if it isn't.
573 * @param pQueue The URB queue.
574 */
575DECLINLINE(bool) usbMsdQueueIsEmpty(PCUSBMSDURBQUEUE pQueue)
576{
577 return pQueue->pHead == NULL;
578}
579
580
581/**
582 * Links an URB into the done queue.
583 *
584 * @param pThis The MSD instance.
585 * @param pUrb The URB.
586 */
587static void usbMsdLinkDone(PUSBMSD pThis, PVUSBURB pUrb)
588{
589 usbMsdQueueAddTail(&pThis->DoneQueue, pUrb);
590
591 if (pThis->fHaveDoneQueueWaiter)
592 {
593 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
594 AssertRC(rc);
595 }
596}
597
598
599
600
601/**
602 * Allocates a new request and does basic init.
603 *
604 * @returns Pointer to the new request. NULL if we're out of memory.
605 * @param pUsbIns The instance allocating it.
606 */
607static PUSBMSDREQ usbMsdReqAlloc(PPDMUSBINS pUsbIns)
608{
609 PUSBMSDREQ pReq = (PUSBMSDREQ)PDMUsbHlpMMHeapAllocZ(pUsbIns, sizeof(*pReq));
610 if (pReq)
611 {
612 pReq->enmState = USBMSDREQSTATE_READY;
613 pReq->iScsiReqStatus = -1;
614 pReq->pUsbIns = pUsbIns;
615 }
616 else
617 LogRel(("usbMsdReqAlloc: Out of memory\n"));
618 return pReq;
619}
620
621
622/**
623 * Frees a request.
624 *
625 * @param pReq The request.
626 */
627static void usbMsdReqFree(PUSBMSDREQ pReq)
628{
629 /*
630 * Check the input.
631 */
632 AssertReturnVoid( pReq->enmState > USBMSDREQSTATE_INVALID
633 && pReq->enmState != USBMSDREQSTATE_EXECUTING
634 && pReq->enmState < USBMSDREQSTATE_END);
635 PPDMUSBINS pUsbIns = pReq->pUsbIns;
636 AssertPtrReturnVoid(pUsbIns);
637 AssertReturnVoid(PDM_VERSION_ARE_COMPATIBLE(pUsbIns->u32Version, PDM_USBINS_VERSION));
638
639 /*
640 * Invalidate it and free the associated resources.
641 */
642 pReq->enmState = USBMSDREQSTATE_INVALID;
643 pReq->cbBuf = 0;
644 pReq->offBuf = 0;
645 pReq->ScsiReq.pbCDB = NULL;
646 pReq->ScsiReq.paScatterGatherHead = NULL;
647 pReq->ScsiReq.pbSenseBuffer = NULL;
648 pReq->ScsiReq.pvUser = NULL;
649 pReq->ScsiReqSeg.cbSeg = 0;
650 pReq->ScsiReqSeg.pvSeg = NULL;
651
652 if (pReq->pbBuf)
653 {
654 PDMUsbHlpMMHeapFree(pUsbIns, pReq->pbBuf);
655 pReq->pbBuf = NULL;
656 }
657
658 PDMUsbHlpMMHeapFree(pUsbIns, pReq);
659}
660
661
662/**
663 * Prepares a request for execution or data buffering.
664 *
665 * @param pReq The request.
666 * @param pCbw The SCSI command block wrapper.
667 */
668static void usbMsdReqPrepare(PUSBMSDREQ pReq, PCUSBCBW pCbw)
669{
670 /* Copy the CBW */
671 size_t cbCopy = RT_OFFSETOF(USBCBW, CBWCB[pCbw->bCBWCBLength]);
672 memcpy(&pReq->Cbw, pCbw, cbCopy);
673 memset((uint8_t *)&pReq->Cbw + cbCopy, 0, sizeof(pReq->Cbw) - cbCopy);
674
675 /* Setup the SCSI request. */
676 pReq->ScsiReq.uLogicalUnit = pReq->Cbw.bCBWLun;
677 pReq->ScsiReq.uDataDirection = (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT
678 ? PDMSCSIREQUESTTXDIR_TO_DEVICE
679 : PDMSCSIREQUESTTXDIR_FROM_DEVICE;
680 pReq->ScsiReq.cbCDB = pReq->Cbw.bCBWCBLength;
681
682 pReq->ScsiReq.pbCDB = &pReq->Cbw.CBWCB[0];
683 pReq->offBuf = 0;
684 pReq->ScsiReqSeg.pvSeg = pReq->pbBuf;
685 pReq->ScsiReqSeg.cbSeg = pReq->Cbw.dCBWDataTransferLength;
686 pReq->ScsiReq.cbScatterGather = pReq->Cbw.dCBWDataTransferLength;
687 pReq->ScsiReq.cScatterGatherEntries = 1;
688 pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg;
689 pReq->ScsiReq.cbSenseBuffer = sizeof(pReq->ScsiReqSense);
690 pReq->ScsiReq.pbSenseBuffer = &pReq->ScsiReqSense[0];
691 pReq->ScsiReq.pvUser = NULL;
692 RT_ZERO(pReq->ScsiReqSense);
693 pReq->iScsiReqStatus = -1;
694}
695
696
697/**
698 * Makes sure that there is sufficient buffer space available.
699 *
700 * @returns Success indicator (true/false)
701 * @param pReq
702 * @param cbBuf The required buffer space.
703 */
704static int usbMsdReqEnsureBuffer(PUSBMSDREQ pReq, size_t cbBuf)
705{
706 if (RT_LIKELY(pReq->cbBuf >= cbBuf))
707 RT_BZERO(pReq->pbBuf, cbBuf);
708 else
709 {
710 PDMUsbHlpMMHeapFree(pReq->pUsbIns, pReq->pbBuf);
711 pReq->cbBuf = 0;
712
713 cbBuf = RT_ALIGN_Z(cbBuf, 0x1000);
714 pReq->pbBuf = (uint8_t *)PDMUsbHlpMMHeapAllocZ(pReq->pUsbIns, cbBuf);
715 if (!pReq->pbBuf)
716 return false;
717
718 pReq->cbBuf = cbBuf;
719 }
720 return true;
721}
722
723
724/**
725 * Completes the URB with a stalled state, halting the pipe.
726 */
727static int usbMsdCompleteStall(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb, const char *pszWhy)
728{
729 Log(("usbMsdCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
730
731 pUrb->enmStatus = VUSBSTATUS_STALL;
732
733 /** @todo figure out if the stall is global or pipe-specific or both. */
734 if (pEp)
735 pEp->fHalted = true;
736 else
737 {
738 pThis->aEps[1].fHalted = true;
739 pThis->aEps[2].fHalted = true;
740 }
741
742 usbMsdLinkDone(pThis, pUrb);
743 return VINF_SUCCESS;
744}
745
746
747/**
748 * Completes the URB with a OK state.
749 */
750static int usbMsdCompleteOk(PUSBMSD pThis, PVUSBURB pUrb, size_t cbData)
751{
752 Log(("usbMsdCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
753
754 pUrb->enmStatus = VUSBSTATUS_OK;
755 pUrb->cbData = (uint32_t)cbData;
756
757 usbMsdLinkDone(pThis, pUrb);
758 return VINF_SUCCESS;
759}
760
761
762/**
763 * Reset worker for usbMsdUsbReset, usbMsdUsbSetConfiguration and
764 * usbMsdUrbHandleDefaultPipe.
765 *
766 * @returns VBox status code.
767 * @param pThis The MSD instance.
768 * @param pUrb Set when usbMsdUrbHandleDefaultPipe is the
769 * caller.
770 * @param fSetConfig Set when usbMsdUsbSetConfiguration is the
771 * caller.
772 */
773static int usbMsdResetWorker(PUSBMSD pThis, PVUSBURB pUrb, bool fSetConfig)
774{
775 /*
776 * Wait for the any command currently executing to complete before
777 * resetting. (We cannot cancel its execution.) How we do this depends
778 * on the reset method.
779 */
780 PUSBMSDREQ pReq = pThis->pReq;
781 if ( pReq
782 && pReq->enmState == USBMSDREQSTATE_EXECUTING)
783 {
784 /* Don't try to deal with the set config variant nor multiple build-only
785 mass storage resets. */
786 if (pThis->pResetUrb && (pUrb || fSetConfig))
787 {
788 Log(("usbMsdResetWorker: pResetUrb is already %p:%s - stalling\n", pThis->pResetUrb, pThis->pResetUrb->pszDesc));
789 return usbMsdCompleteStall(pThis, NULL, pUrb, "pResetUrb");
790 }
791
792 /* Bulk-Only Mass Storage Reset: Complete the reset on request completion. */
793 if (pUrb)
794 {
795 pThis->pResetUrb = pUrb;
796 Log(("usbMsdResetWorker: Setting pResetUrb to %p:%s\n", pThis->pResetUrb, pThis->pResetUrb->pszDesc));
797 return VINF_SUCCESS;
798 }
799
800 /* Device reset: Wait for up to 10 ms. If it doesn't work, ditch
801 whoe the request structure. We'll allocate a new one when needed. */
802 Log(("usbMsdResetWorker: Waiting for completion...\n"));
803 Assert(!pThis->fSignalResetSem);
804 pThis->fSignalResetSem = true;
805 RTSemEventMultiReset(pThis->hEvtReset);
806 RTCritSectLeave(&pThis->CritSect);
807
808 int rc = RTSemEventMultiWait(pThis->hEvtReset, 10 /*ms*/);
809
810 RTCritSectEnter(&pThis->CritSect);
811 pThis->fSignalResetSem = false;
812 if ( RT_FAILURE(rc)
813 || pReq->enmState == USBMSDREQSTATE_EXECUTING)
814 {
815 Log(("usbMsdResetWorker: Didn't complete, ditching the current request (%p)!\n", pReq));
816 Assert(pReq == pThis->pReq);
817 pReq->enmState = USBMSDREQSTATE_DESTROY_ON_COMPLETION;
818 pThis->pReq = NULL;
819 pReq = NULL;
820 }
821 }
822
823 /*
824 * Reset the request and device state.
825 */
826 if (pReq)
827 {
828 pReq->enmState = USBMSDREQSTATE_READY;
829 pReq->iScsiReqStatus = -1;
830 }
831
832 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
833 pThis->aEps[i].fHalted = false;
834
835 if (!pUrb && !fSetConfig) /* (only device reset) */
836 pThis->bConfigurationValue = 0; /* default */
837
838 /*
839 * Ditch all pending URBs.
840 */
841 PVUSBURB pCurUrb;
842 while ((pCurUrb = usbMsdQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
843 {
844 pCurUrb->enmStatus = VUSBSTATUS_CRC;
845 usbMsdLinkDone(pThis, pCurUrb);
846 }
847
848 pCurUrb = pThis->pResetUrb;
849 if (pCurUrb)
850 {
851 pThis->pResetUrb = NULL;
852 pCurUrb->enmStatus = VUSBSTATUS_CRC;
853 usbMsdLinkDone(pThis, pCurUrb);
854 }
855
856 if (pUrb)
857 return usbMsdCompleteOk(pThis, pUrb, 0);
858 return VINF_SUCCESS;
859}
860
861
862/**
863 * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
864 */
865static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
866 int rcCompletion, bool fRedo, int rcReq)
867{
868 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
869 PUSBMSDREQ pReq = RT_FROM_MEMBER(pSCSIRequest, USBMSDREQ, ScsiReq);
870
871 Log(("usbMsdLun0ScsiRequestCompleted: pReq=%p dCBWTag=%#x iScsiReqStatus=%u \n", pReq, pReq->Cbw.dCBWTag, rcCompletion));
872 RTCritSectEnter(&pThis->CritSect);
873
874 if (pReq->enmState != USBMSDREQSTATE_DESTROY_ON_COMPLETION)
875 {
876 Assert(pReq->enmState == USBMSDREQSTATE_EXECUTING);
877 Assert(pThis->pReq == pReq);
878 pReq->iScsiReqStatus = rcCompletion;
879
880 /*
881 * Advance the state machine. The state machine is not affected by
882 * SCSI errors.
883 */
884 if ((pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT)
885 {
886 pReq->enmState = USBMSDREQSTATE_STATUS;
887 Log(("usbMsdLun0ScsiRequestCompleted: Entering STATUS\n"));
888 }
889 else
890 {
891 pReq->enmState = USBMSDREQSTATE_DATA_TO_HOST;
892 Log(("usbMsdLun0ScsiRequestCompleted: Entering DATA_TO_HOST\n"));
893 }
894
895 /*
896 * Deal with pending to-host URBs.
897 */
898 for (;;)
899 {
900 PVUSBURB pUrb = usbMsdQueueRemoveHead(&pThis->ToHostQueue);
901 if (!pUrb)
902 break;
903
904 /* Process it the normal way. */
905 usbMsdHandleBulkDevToHost(pThis, &pThis->aEps[1], pUrb);
906 }
907 }
908 else
909 {
910 Log(("usbMsdLun0ScsiRequestCompleted: freeing %p\n", pReq));
911 usbMsdReqFree(pReq);
912 }
913
914 if (pThis->fSignalResetSem)
915 RTSemEventMultiSignal(pThis->hEvtReset);
916
917 if (pThis->pResetUrb)
918 {
919 pThis->pResetUrb = NULL;
920 usbMsdResetWorker(pThis, pThis->pResetUrb, false /*fSetConfig*/);
921 }
922
923 RTCritSectLeave(&pThis->CritSect);
924 return VINF_SUCCESS;
925}
926
927
928/**
929 * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation}
930 */
931static DECLCALLBACK(int) usbMsdLun0QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
932 uint32_t *piInstance, uint32_t *piLUN)
933{
934 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
935 PPDMUSBINS pUsbIns = pThis->pUsbIns;
936
937 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
938 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
939 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
940
941 *ppcszController = pUsbIns->pReg->szName;
942 *piInstance = pUsbIns->iInstance;
943 *piLUN = 0;
944
945 return VINF_SUCCESS;
946}
947
948
949/**
950 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
951 */
952static DECLCALLBACK(void *) usbMsdLun0QueryInterface(PPDMIBASE pInterface, const char *pszIID)
953{
954 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IBase);
955 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
956 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pThis->Lun0.IScsiPort);
957 return NULL;
958}
959
960
961/**
962 * Checks if all asynchronous I/O is finished.
963 *
964 * Used by usbMsdVMReset, usbMsdVMSuspend and usbMsdVMPowerOff.
965 *
966 * @returns true if quiesced, false if busy.
967 * @param pUsbIns The USB device instance.
968 */
969static bool usbMsdAllAsyncIOIsFinished(PPDMUSBINS pUsbIns)
970{
971 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
972
973 if ( VALID_PTR(pThis->pReq)
974 && pThis->pReq->enmState == USBMSDREQSTATE_EXECUTING)
975 return false;
976
977 return true;
978}
979
980/**
981 * @callback_method_impl{FNPDMDEVASYNCNOTIFY,
982 * Callback employed by usbMsdVMSuspend and usbMsdVMPowerOff.}
983 */
984static DECLCALLBACK(bool) usbMsdIsAsyncSuspendOrPowerOffDone(PPDMUSBINS pUsbIns)
985{
986 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))
987 return false;
988
989 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
990 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
991 return true;
992}
993
994/**
995 * Common worker for usbMsdVMSuspend and usbMsdVMPowerOff.
996 */
997static void usbMsdSuspendOrPowerOff(PPDMUSBINS pUsbIns)
998{
999 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1000
1001 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
1002 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))
1003 PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncSuspendOrPowerOffDone);
1004 else
1005 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
1006}
1007
1008
1009/* -=-=-=-=- Saved State -=-=-=-=- */
1010
1011/**
1012 * @copydoc FNUSBSSMSAVEPREP
1013 */
1014static DECLCALLBACK(int) usbMsdSavePrep(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM)
1015{
1016 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1017
1018 Assert(usbMsdAllAsyncIOIsFinished(pUsbIns));
1019 Assert(usbMsdQueueIsEmpty(&pThis->ToHostQueue));
1020 Assert(usbMsdQueueIsEmpty(&pThis->DoneQueue));
1021 return VINF_SUCCESS;
1022}
1023
1024/**
1025 * @copydoc FNUSBSSMLOADPREP
1026 */
1027static DECLCALLBACK(int) usbMsdLoadPrep(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM)
1028{
1029 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1030
1031 Assert(usbMsdAllAsyncIOIsFinished(pUsbIns));
1032 Assert(usbMsdQueueIsEmpty(&pThis->ToHostQueue));
1033 Assert(usbMsdQueueIsEmpty(&pThis->DoneQueue));
1034 return VINF_SUCCESS;
1035}
1036
1037/**
1038 * @copydoc FNUSBSSMLIVEEXEC
1039 */
1040static DECLCALLBACK(int) usbMsdLiveExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass)
1041{
1042 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1043
1044 /* config. */
1045 SSMR3PutBool(pSSM, pThis->Lun0.pIBase != NULL);
1046 return VINF_SSM_DONT_CALL_AGAIN;
1047}
1048
1049/**
1050 * @copydoc FNUSBSSMSAVEEXEC
1051 */
1052static DECLCALLBACK(int) usbMsdSaveExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM)
1053{
1054 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1055 uint32_t i;
1056 int rc;
1057
1058 /* The config */
1059 rc = usbMsdLiveExec(pUsbIns, pSSM, SSM_PASS_FINAL);
1060 AssertRCReturn(rc, rc);
1061
1062 SSMR3PutU8(pSSM, pThis->bConfigurationValue);
1063 SSMR3PutBool(pSSM, pThis->aEps[0].fHalted);
1064 SSMR3PutBool(pSSM, pThis->aEps[1].fHalted);
1065 SSMR3PutBool(pSSM, pThis->aEps[2].fHalted);
1066 SSMR3PutBool(pSSM, pThis->pReq != NULL);
1067
1068 if (pThis->pReq)
1069 {
1070 PUSBMSDREQ pReq = pThis->pReq;
1071
1072 SSMR3PutU32(pSSM, pReq->enmState);
1073 SSMR3PutU32(pSSM, pReq->cbBuf);
1074 if (pReq->cbBuf)
1075 {
1076 AssertPtr(pReq->pbBuf);
1077 SSMR3PutMem(pSSM, pReq->pbBuf, pReq->cbBuf);
1078 }
1079
1080 SSMR3PutU32(pSSM, pReq->offBuf);
1081 SSMR3PutMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw));
1082 SSMR3PutU32(pSSM, pReq->ScsiReq.uLogicalUnit);
1083 SSMR3PutU32(pSSM, pReq->ScsiReq.uDataDirection);
1084 SSMR3PutU32(pSSM, pReq->ScsiReq.cbCDB);
1085 SSMR3PutU32(pSSM, pReq->ScsiReq.cbScatterGather);
1086 SSMR3PutMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense));
1087 SSMR3PutS32(pSSM, pReq->iScsiReqStatus);
1088 }
1089
1090 return SSMR3PutU32(pSSM, UINT32_MAX); /* sanity/terminator */
1091}
1092
1093/**
1094 * @copydoc FNUSBSSMLOADEXEC
1095 */
1096static DECLCALLBACK(int) usbMsdLoadExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1097{
1098 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1099 uint32_t u32;
1100 int rc;
1101
1102 if (uVersion > USB_MSD_SAVED_STATE_VERSION)
1103 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1104
1105 /* Verify config. */
1106 bool fInUse;
1107 rc = SSMR3GetBool(pSSM, &fInUse);
1108 AssertRCReturn(rc, rc);
1109 if (fInUse != (pThis->Lun0.pIBase != NULL))
1110 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
1111 N_("The %s VM is missing a USB mass storage device. Please make sure the source and target VMs have compatible storage configurations"),
1112 fInUse ? "target" : "source");
1113
1114 if (uPass == SSM_PASS_FINAL)
1115 {
1116 /* Restore data. */
1117 bool fReqAlloc = false;
1118
1119 Assert(!pThis->pReq);
1120
1121 SSMR3GetU8(pSSM, &pThis->bConfigurationValue);
1122 SSMR3GetBool(pSSM, &pThis->aEps[0].fHalted);
1123 SSMR3GetBool(pSSM, &pThis->aEps[1].fHalted);
1124 SSMR3GetBool(pSSM, &pThis->aEps[2].fHalted);
1125 SSMR3GetBool(pSSM, &fReqAlloc);
1126
1127 if (fReqAlloc)
1128 {
1129 PUSBMSDREQ pReq = usbMsdReqAlloc(pUsbIns);
1130
1131 if (pReq)
1132 {
1133 uint32_t cbBuf = 0;
1134
1135 pThis->pReq = pReq;
1136
1137 SSMR3GetU32(pSSM, (uint32_t *)&pReq->enmState);
1138 SSMR3GetU32(pSSM, &cbBuf);
1139 if (cbBuf)
1140 {
1141 if (usbMsdReqEnsureBuffer(pReq, cbBuf))
1142 {
1143 AssertPtr(pReq->pbBuf);
1144 Assert(cbBuf = pReq->cbBuf);
1145 SSMR3GetMem(pSSM, pReq->pbBuf, pReq->cbBuf);
1146 }
1147 else
1148 rc = VERR_NO_MEMORY;
1149 }
1150
1151 if (RT_SUCCESS(rc))
1152 {
1153 SSMR3GetU32(pSSM, &pReq->offBuf);
1154 SSMR3GetMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw));
1155 SSMR3GetU32(pSSM, &pReq->ScsiReq.uLogicalUnit);
1156 SSMR3GetU32(pSSM, (uint32_t *)&pReq->ScsiReq.uDataDirection);
1157 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbCDB);
1158 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbScatterGather);
1159 SSMR3GetMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense));
1160 SSMR3GetS32(pSSM, &pReq->iScsiReqStatus);
1161
1162 /* Setup the rest of the SCSI request. */
1163 pReq->ScsiReq.cbCDB = pReq->Cbw.bCBWCBLength;
1164 pReq->ScsiReq.pbCDB = &pReq->Cbw.CBWCB[0];
1165 pReq->ScsiReqSeg.pvSeg = pReq->pbBuf;
1166 pReq->ScsiReqSeg.cbSeg = pReq->ScsiReq.cbScatterGather;
1167 pReq->ScsiReq.cScatterGatherEntries = 1;
1168 pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg;
1169 pReq->ScsiReq.cbSenseBuffer = sizeof(pReq->ScsiReqSense);
1170 pReq->ScsiReq.pbSenseBuffer = &pReq->ScsiReqSense[0];
1171 pReq->ScsiReq.pvUser = NULL;
1172 }
1173 }
1174 else
1175 rc = VERR_NO_MEMORY;
1176 }
1177
1178 if (RT_SUCCESS(rc))
1179 rc = SSMR3GetU32(pSSM, &u32);
1180
1181 if (RT_FAILURE(rc))
1182 return rc;
1183 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
1184 }
1185
1186 return VINF_SUCCESS;
1187}
1188
1189
1190/**
1191 * @copydoc PDMUSBREG::pfnUrbReap
1192 */
1193static DECLCALLBACK(PVUSBURB) usbMsdUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1194{
1195 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1196 LogFlow(("usbMsdUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
1197
1198 RTCritSectEnter(&pThis->CritSect);
1199
1200 PVUSBURB pUrb = usbMsdQueueRemoveHead(&pThis->DoneQueue);
1201 if (!pUrb && cMillies)
1202 {
1203 /* Wait */
1204 pThis->fHaveDoneQueueWaiter = true;
1205 RTCritSectLeave(&pThis->CritSect);
1206
1207 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1208
1209 RTCritSectEnter(&pThis->CritSect);
1210 pThis->fHaveDoneQueueWaiter = false;
1211
1212 pUrb = usbMsdQueueRemoveHead(&pThis->DoneQueue);
1213 }
1214
1215 RTCritSectLeave(&pThis->CritSect);
1216
1217 if (pUrb)
1218 Log(("usbMsdUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1219 return pUrb;
1220}
1221
1222
1223/**
1224 * @copydoc PDMUSBREG::pfnUrbCancel
1225 */
1226static DECLCALLBACK(int) usbMsdUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1227{
1228 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1229 LogFlow(("usbMsdUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1230 RTCritSectEnter(&pThis->CritSect);
1231
1232 /*
1233 * Remove the URB from the to-host queue and move it onto the done queue.
1234 */
1235 if (usbMsdQueueRemove(&pThis->ToHostQueue, pUrb))
1236 usbMsdLinkDone(pThis, pUrb);
1237
1238 RTCritSectLeave(&pThis->CritSect);
1239 return VINF_SUCCESS;
1240}
1241
1242
1243/**
1244 * Fails an illegal SCSI request.
1245 *
1246 * @returns VBox status code.
1247 * @param pThis The MSD instance data.
1248 * @param pReq The MSD request.
1249 * @param bAsc The ASC for the SCSI_SENSE_ILLEGAL_REQUEST.
1250 * @param bAscq The ASC qualifier.
1251 * @param pszWhy For logging why.
1252 */
1253static int usbMsdScsiIllegalRequest(PUSBMSD pThis, PUSBMSDREQ pReq, uint8_t bAsc, uint8_t bAscq, const char *pszWhy)
1254{
1255 Log(("usbMsdScsiIllegalRequest: bAsc=%#x bAscq=%#x %s\n", bAsc, bAscq, pszWhy));
1256
1257 RT_ZERO(pReq->ScsiReqSense);
1258 pReq->ScsiReqSense[0] = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
1259 pReq->ScsiReqSense[2] = SCSI_SENSE_ILLEGAL_REQUEST;
1260 pReq->ScsiReqSense[7] = 10;
1261 pReq->ScsiReqSense[12] = SCSI_ASC_INVALID_MESSAGE;
1262 pReq->ScsiReqSense[13] = 0; /* Should be ASCQ but it has the same value for success. */
1263
1264 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
1265 return VINF_SUCCESS;
1266}
1267
1268
1269/**
1270 * The SCSI driver doesn't handle SCSI_REQUEST_SENSE but instead
1271 * returns the sense info with the request.
1272 *
1273 */
1274static int usbMsdHandleScsiReqestSense(PUSBMSD pThis, PUSBMSDREQ pReq, PCUSBCBW pCbw)
1275{
1276 Log(("usbMsdHandleScsiReqestSense: Entering EXECUTING (dCBWTag=%#x).\n", pReq->Cbw.dCBWTag));
1277 Assert(pReq == pThis->pReq);
1278 pReq->enmState = USBMSDREQSTATE_EXECUTING;
1279
1280 /* validation */
1281 if ((pCbw->bmCBWFlags & USBCBW_DIR_MASK) != USBCBW_DIR_IN)
1282 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "direction");
1283 if (pCbw->bCBWCBLength < 6)
1284 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "length");
1285 if ((pCbw->CBWCB[1] >> 5) != pCbw->bCBWLun)
1286 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "lun");
1287 if (pCbw->bCBWLun != 0)
1288 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "lun0");
1289 if (pCbw->CBWCB[4] < 6)
1290 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "out length");
1291
1292 /* If the previous command succeeded successfully, whip up some sense data. */
1293 if ( pReq->iScsiReqStatus == SCSI_STATUS_OK
1294 && pReq->ScsiReqSense[0] == 0)
1295 {
1296 RT_ZERO(pReq->ScsiReqSense);
1297#if 0 /** @todo something upsets linux about this stuff. Needs investigation. */
1298 pReq->ScsiReqSense[0] = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
1299 pReq->ScsiReqSense[0] = SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
1300 pReq->ScsiReqSense[2] = SCSI_SENSE_NONE;
1301 pReq->ScsiReqSense[7] = 10;
1302 pReq->ScsiReqSense[12] = SCSI_ASC_NONE;
1303 pReq->ScsiReqSense[13] = SCSI_ASC_NONE; /* Should be ASCQ but it has the same value for success. */
1304#endif
1305 }
1306
1307 /* Copy the data into the result buffer. */
1308 size_t cbCopy = RT_MIN(pCbw->dCBWDataTransferLength, sizeof(pReq->ScsiReqSense));
1309 Log(("usbMsd: SCSI_REQUEST_SENSE - CBWCB[4]=%#x iOldState=%d, %u bytes, raw: %.*Rhxs\n",
1310 pCbw->CBWCB[4], pReq->iScsiReqStatus, pCbw->dCBWDataTransferLength, RT_MAX(1, cbCopy), pReq->ScsiReqSense));
1311 memcpy(pReq->pbBuf, &pReq->ScsiReqSense[0], cbCopy);
1312
1313 usbMsdReqPrepare(pReq, pCbw);
1314
1315 /* Do normal completion. */
1316 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
1317 return VINF_SUCCESS;
1318}
1319
1320
1321/**
1322 * Wrapper around PDMISCSICONNECTOR::pfnSCSIRequestSend that deals with
1323 * SCSI_REQUEST_SENSE.
1324 *
1325 * @returns VBox status code.
1326 * @param pThis The MSD instance data.
1327 * @param pReq The MSD request.
1328 * @param pszCaller Where we're called from.
1329 */
1330static int usbMsdSubmitScsiCommand(PUSBMSD pThis, PUSBMSDREQ pReq, const char *pszCaller)
1331{
1332 Log(("%s: Entering EXECUTING (dCBWTag=%#x).\n", pszCaller, pReq->Cbw.dCBWTag));
1333 Assert(pReq == pThis->pReq);
1334 pReq->enmState = USBMSDREQSTATE_EXECUTING;
1335
1336 switch (pReq->ScsiReq.pbCDB[0])
1337 {
1338 case SCSI_REQUEST_SENSE:
1339 {
1340 }
1341
1342 default:
1343 return pThis->Lun0.pIScsiConnector->pfnSCSIRequestSend(pThis->Lun0.pIScsiConnector, &pReq->ScsiReq);
1344 }
1345}
1346
1347/**
1348 * Validates a SCSI request before passing it down to the SCSI driver.
1349 *
1350 * @returns true / false. The request will be completed on failure.
1351 * @param pThis The MSD instance data.
1352 * @param pCbw The USB command block wrapper.
1353 * @param pUrb The URB.
1354 */
1355static bool usbMsdIsValidCommand(PUSBMSD pThis, PCUSBCBW pCbw, PVUSBURB pUrb)
1356{
1357 switch (pCbw->CBWCB[0])
1358 {
1359 case SCSI_REQUEST_SENSE:
1360 /** @todo validate this. */
1361 return true;
1362
1363 default:
1364 return true;
1365 }
1366}
1367
1368
1369/**
1370 * Handle requests sent to the outbound (to device) bulk pipe.
1371 */
1372static int usbMsdHandleBulkHostToDev(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb)
1373{
1374 /*
1375 * Stall the request if the pipe is halted.
1376 */
1377 if (RT_UNLIKELY(pEp->fHalted))
1378 return usbMsdCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1379
1380 /*
1381 * Deal with the URB according to the current state.
1382 */
1383 PUSBMSDREQ pReq = pThis->pReq;
1384 USBMSDREQSTATE enmState = pReq ? pReq->enmState : USBMSDREQSTATE_READY;
1385 switch (enmState)
1386 {
1387 case USBMSDREQSTATE_STATUS:
1388 LogFlow(("usbMsdHandleBulkHostToDev: Skipping pending status.\n"));
1389 pReq->enmState = USBMSDREQSTATE_READY;
1390 /* fall thru */
1391
1392 /*
1393 * We're ready to receive a command. Start off by validating the
1394 * incoming request.
1395 */
1396 case USBMSDREQSTATE_READY:
1397 {
1398 PCUSBCBW pCbw = (PUSBCBW)&pUrb->abData[0];
1399 if (pUrb->cbData < RT_UOFFSETOF(USBCBW, CBWCB[1]))
1400 {
1401 Log(("usbMsd: Bad CBW: cbData=%#x < min=%#x\n", pUrb->cbData, RT_UOFFSETOF(USBCBW, CBWCB[1]) ));
1402 return usbMsdCompleteStall(pThis, NULL, pUrb, "BAD CBW");
1403 }
1404 if (pCbw->dCBWSignature != USBCBW_SIGNATURE)
1405 {
1406 Log(("usbMsd: CBW: Invalid dCBWSignature value: %#x\n", pCbw->dCBWSignature));
1407 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad CBW");
1408 }
1409 Log(("usbMsd: CBW: dCBWTag=%#x dCBWDataTransferLength=%#x bmCBWFlags=%#x bCBWLun=%#x bCBWCBLength=%#x cbData=%#x fShortNotOk=%RTbool\n",
1410 pCbw->dCBWTag, pCbw->dCBWDataTransferLength, pCbw->bmCBWFlags, pCbw->bCBWLun, pCbw->bCBWCBLength, pUrb->cbData, pUrb->fShortNotOk));
1411 if (pCbw->bmCBWFlags & ~USBCBW_DIR_MASK)
1412 {
1413 Log(("usbMsd: CBW: Bad bmCBWFlags value: %#x\n", pCbw->bmCBWFlags));
1414 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad CBW");
1415
1416 }
1417 if (pCbw->bCBWLun != 0)
1418 {
1419 Log(("usbMsd: CBW: Bad bCBWLun value: %#x\n", pCbw->bCBWLun));
1420 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad CBW");
1421 }
1422 if (pCbw->bCBWCBLength == 0)
1423 {
1424 Log(("usbMsd: CBW: Bad bCBWCBLength value: %#x\n", pCbw->bCBWCBLength));
1425 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad CBW");
1426 }
1427 if (pUrb->cbData < RT_UOFFSETOF(USBCBW, CBWCB[pCbw->bCBWCBLength]))
1428 {
1429 Log(("usbMsd: CBW: Mismatching cbData and bCBWCBLength values: %#x vs. %#x (%#x)\n",
1430 pUrb->cbData, RT_UOFFSETOF(USBCBW, CBWCB[pCbw->bCBWCBLength]), pCbw->bCBWCBLength));
1431 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad CBW");
1432 }
1433 if (pCbw->dCBWDataTransferLength > _1M)
1434 {
1435 Log(("usbMsd: CBW: dCBWDataTransferLength is too large: %#x (%u)\n",
1436 pCbw->dCBWDataTransferLength, pCbw->dCBWDataTransferLength));
1437 return usbMsdCompleteStall(pThis, NULL, pUrb, "Too big transfer");
1438 }
1439
1440 if (!usbMsdIsValidCommand(pThis, pCbw, pUrb))
1441 return VINF_SUCCESS;
1442
1443 /*
1444 * Make sure we've got a request and a sufficient buffer space.
1445 *
1446 * Note! This will make sure the buffer is ZERO as well, thus
1447 * saving us the trouble of clearing the output buffer on
1448 * failure later.
1449 */
1450 if (!pReq)
1451 {
1452 pReq = usbMsdReqAlloc(pThis->pUsbIns);
1453 if (!pReq)
1454 return usbMsdCompleteStall(pThis, NULL, pUrb, "Request allocation failure");
1455 pThis->pReq = pReq;
1456 }
1457 if (!usbMsdReqEnsureBuffer(pReq, pCbw->dCBWDataTransferLength))
1458 return usbMsdCompleteStall(pThis, NULL, pUrb, "Buffer allocation failure");
1459
1460 /*
1461 * Special case REQUEST SENSE requests, usbMsdReqPrepare will
1462 * trash the sense data otherwise.
1463 */
1464 if (pCbw->CBWCB[0] == SCSI_REQUEST_SENSE)
1465 usbMsdHandleScsiReqestSense(pThis, pReq, pCbw);
1466 else
1467 {
1468 /*
1469 * Prepare the request. Kick it off right away if possible.
1470 */
1471 usbMsdReqPrepare(pReq, pCbw);
1472
1473 if ( pReq->Cbw.dCBWDataTransferLength == 0
1474 || (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_IN)
1475 {
1476 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev");
1477 if (RT_FAILURE(rc))
1478 {
1479 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
1480 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #1");
1481 }
1482 }
1483 else
1484 {
1485 Log(("usbMsdHandleBulkHostToDev: Entering DATA_FROM_HOST.\n"));
1486 pReq->enmState = USBMSDREQSTATE_DATA_FROM_HOST;
1487 }
1488 }
1489
1490 return usbMsdCompleteOk(pThis, pUrb, pUrb->cbData);
1491 }
1492
1493 /*
1494 * Stuff the data into the buffer.
1495 */
1496 case USBMSDREQSTATE_DATA_FROM_HOST:
1497 {
1498 uint32_t cbData = pUrb->cbData;
1499 uint32_t cbLeft = pReq->Cbw.dCBWDataTransferLength - pReq->offBuf;
1500 if (cbData > cbLeft)
1501 {
1502 Log(("usbMsd: Too much data: cbData=%#x offBuf=%#x dCBWDataTransferLength=%#x cbLeft=%#x\n",
1503 cbData, pReq->offBuf, pReq->Cbw.dCBWDataTransferLength, cbLeft));
1504 return usbMsdCompleteStall(pThis, NULL, pUrb, "Too much data");
1505 }
1506 memcpy(&pReq->pbBuf[pReq->offBuf], &pUrb->abData[0], cbData);
1507 pReq->offBuf += cbData;
1508
1509 if (pReq->offBuf == pReq->Cbw.dCBWDataTransferLength)
1510 {
1511 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev");
1512 if (RT_FAILURE(rc))
1513 {
1514 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
1515 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #2");
1516 }
1517 }
1518 return usbMsdCompleteOk(pThis, pUrb, cbData);
1519 }
1520
1521 /*
1522 * Bad state, stall.
1523 */
1524 case USBMSDREQSTATE_DATA_TO_HOST:
1525 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad state H2D: DATA_TO_HOST");
1526
1527 case USBMSDREQSTATE_EXECUTING:
1528 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad state H2D: EXECUTING");
1529
1530 default:
1531 AssertMsgFailed(("enmState=%d\n", enmState));
1532 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad state (H2D)");
1533 }
1534}
1535
1536
1537/**
1538 * Handle requests sent to the inbound (to host) bulk pipe.
1539 */
1540static int usbMsdHandleBulkDevToHost(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb)
1541{
1542 /*
1543 * Stall the request if the pipe is halted OR if there is no
1544 * pending request yet.
1545 */
1546 PUSBMSDREQ pReq = pThis->pReq;
1547 if (RT_UNLIKELY(pEp->fHalted || !pReq))
1548 return usbMsdCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1549
1550 /*
1551 * Deal with the URB according to the state.
1552 */
1553 switch (pReq->enmState)
1554 {
1555 /*
1556 * We've data left to transfer to the host.
1557 */
1558 case USBMSDREQSTATE_DATA_TO_HOST:
1559 {
1560 uint32_t cbData = pUrb->cbData;
1561 uint32_t cbCopy = pReq->Cbw.dCBWDataTransferLength - pReq->offBuf;
1562 if (cbData <= cbCopy)
1563 cbCopy = cbData;
1564 else if (pUrb->fShortNotOk)
1565 {
1566 Log(("usbMsd: Requested more data that we've got; cbData=%#x offBuf=%#x dCBWDataTransferLength=%#x cbLeft=%#x\n",
1567 cbData, pReq->offBuf, pReq->Cbw.dCBWDataTransferLength, cbCopy));
1568 return usbMsdCompleteStall(pThis, NULL, pUrb, "Data underrun");
1569 }
1570 memcpy(&pUrb->abData[0], &pReq->pbBuf[pReq->offBuf], cbCopy);
1571 pReq->offBuf += cbCopy;
1572
1573 if (pReq->offBuf == pReq->Cbw.dCBWDataTransferLength)
1574 {
1575 Log(("usbMsdHandleBulkDevToHost: Entering STATUS\n"));
1576 pReq->enmState = USBMSDREQSTATE_STATUS;
1577 }
1578 return usbMsdCompleteOk(pThis, pUrb, cbCopy);
1579 }
1580
1581 /*
1582 * Status transfer.
1583 */
1584 case USBMSDREQSTATE_STATUS:
1585 {
1586 if ((pUrb->cbData < sizeof(USBCSW)) || (pUrb->cbData > sizeof(USBCSW) && pUrb->fShortNotOk))
1587 {
1588 Log(("usbMsd: Unexpected status request size: %#x (expected %#x), fShortNotOK=%RTbool\n", pUrb->cbData, sizeof(USBCSW), pUrb->fShortNotOk));
1589 return usbMsdCompleteStall(pThis, NULL, pUrb, "Invalid CSW size");
1590 }
1591
1592 /* Enter a CSW into the URB data buffer. */
1593 PUSBCSW pCsw = (PUSBCSW)&pUrb->abData[0];
1594 pCsw->dCSWSignature = USBCSW_SIGNATURE;
1595 pCsw->dCSWTag = pReq->Cbw.dCBWTag;
1596 pCsw->bCSWStatus = pReq->iScsiReqStatus == SCSI_STATUS_OK
1597 ? USBCSW_STATUS_OK
1598 : pReq->iScsiReqStatus >= 0
1599 ? USBCSW_STATUS_FAILED
1600 : USBCSW_STATUS_PHASE_ERROR;
1601 /** @todo the following is not always accurate; VSCSI needs
1602 * to implement residual counts properly! */
1603 if ((pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT)
1604 pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK
1605 ? pReq->Cbw.dCBWDataTransferLength - pReq->ScsiReq.cbScatterGather
1606 : pReq->Cbw.dCBWDataTransferLength;
1607 else
1608 pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK
1609 ? 0
1610 : pReq->ScsiReq.cbScatterGather;
1611 Log(("usbMsd: CSW: dCSWTag=%#x bCSWStatus=%d dCSWDataResidue=%#x\n",
1612 pCsw->dCSWTag, pCsw->bCSWStatus, pCsw->dCSWDataResidue));
1613
1614 Log(("usbMsdHandleBulkDevToHost: Entering READY\n"));
1615 pReq->enmState = USBMSDREQSTATE_READY;
1616 return usbMsdCompleteOk(pThis, pUrb, sizeof(*pCsw));
1617 }
1618
1619 /*
1620 * Status request before we've received all (or even any) data.
1621 * Linux 2.4.31 does this sometimes. The recommended behavior is to
1622 * to accept the current data amount and execute the request. (The
1623 * alternative behavior is to stall.)
1624 */
1625 case USBMSDREQSTATE_DATA_FROM_HOST:
1626 {
1627 if (pUrb->cbData != sizeof(USBCSW))
1628 {
1629 Log(("usbMsdHandleBulkDevToHost: DATA_FROM_HOST; cbData=%#x -> stall\n", pUrb->cbData));
1630 return usbMsdCompleteStall(pThis, NULL, pUrb, "Invalid CSW size");
1631 }
1632
1633 /* Adjust the request and kick it off. Special case the no-data
1634 case since the SCSI driver doesn't like that. */
1635 pReq->ScsiReq.cbScatterGather = pReq->offBuf;
1636 pReq->ScsiReqSeg.cbSeg = pReq->offBuf;
1637 if (!pReq->offBuf)
1638 {
1639 Log(("usbMsdHandleBulkDevToHost: Entering EXECUTING (offBuf=0x0).\n"));
1640 pReq->enmState = USBMSDREQSTATE_EXECUTING;
1641
1642 usbMsdQueueAddTail(&pThis->ToHostQueue, pUrb);
1643 LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
1644
1645 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
1646 return VINF_SUCCESS;
1647 }
1648
1649 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkDevToHost");
1650 if (RT_FAILURE(rc))
1651 {
1652 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
1653 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #3");
1654 }
1655
1656 /* fall thru */
1657 }
1658
1659 /*
1660 * The SCSI command is still pending, queue the URB awaiting its
1661 * completion.
1662 */
1663 case USBMSDREQSTATE_EXECUTING:
1664 usbMsdQueueAddTail(&pThis->ToHostQueue, pUrb);
1665 LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
1666 return VINF_SUCCESS;
1667
1668 /*
1669 * Bad states, stall.
1670 */
1671 case USBMSDREQSTATE_READY:
1672 Log(("usbMsdHandleBulkDevToHost: enmState=READ (cbData=%#x)\n", pReq->enmState, pUrb->cbData));
1673 return usbMsdCompleteStall(pThis, NULL, pUrb, "Bad state D2H: READY");
1674
1675 default:
1676 Log(("usbMsdHandleBulkDevToHost: enmState=%d cbData=%#x\n", pReq->enmState, pUrb->cbData));
1677 return usbMsdCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
1678 }
1679}
1680
1681
1682/**
1683 * Handles request send to the default control pipe.
1684 */
1685static int usbMsdHandleDefaultPipe(PUSBMSD pThis, PUSBMSDEP pEp, PVUSBURB pUrb)
1686{
1687 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1688 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1689
1690 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1691 {
1692 switch (pSetup->bRequest)
1693 {
1694 case VUSB_REQ_GET_DESCRIPTOR:
1695 {
1696 if (pSetup->bmRequestType != (VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST))
1697 {
1698 Log(("usbMsd: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
1699 return usbMsdCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1700 }
1701
1702 switch (pSetup->wValue >> 8)
1703 {
1704 uint32_t cbCopy;
1705
1706 case VUSB_DT_STRING:
1707 Log(("usbMsd: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1708 break;
1709 case VUSB_DT_DEVICE_QUALIFIER:
1710 Log(("usbMsd: GET_DESCRIPTOR DT_DEVICE_QUALIFIER wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1711 /* Returned data is written after the setup message. */
1712 cbCopy = pUrb->cbData - sizeof(*pSetup);
1713 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbMsdDeviceQualifier));
1714 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbMsdDeviceQualifier, cbCopy);
1715 return usbMsdCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1716 default:
1717 Log(("usbMsd: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1718 break;
1719 }
1720 break;
1721 }
1722
1723 case VUSB_REQ_CLEAR_FEATURE:
1724 break;
1725 }
1726
1727 /** @todo implement this. */
1728 Log(("usbMsd: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1729 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1730
1731 usbMsdCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1732 }
1733 /* 3.1 Bulk-Only Mass Storage Reset */
1734 else if ( pSetup->bmRequestType == (VUSB_REQ_CLASS | VUSB_TO_INTERFACE)
1735 && pSetup->bRequest == 0xff
1736 && !pSetup->wValue
1737 && !pSetup->wLength
1738 && pSetup->wIndex == 0)
1739 {
1740 Log(("usbMsdHandleDefaultPipe: Bulk-Only Mass Storage Reset\n"));
1741 return usbMsdResetWorker(pThis, pUrb, false /*fSetConfig*/);
1742 }
1743 /* 3.2 Get Max LUN, may stall if we like (but we don't). */
1744 else if ( pSetup->bmRequestType == (VUSB_REQ_CLASS | VUSB_TO_INTERFACE | VUSB_DIR_TO_HOST)
1745 && pSetup->bRequest == 0xfe
1746 && !pSetup->wValue
1747 && pSetup->wLength == 1
1748 && pSetup->wIndex == 0)
1749 {
1750 *(uint8_t *)(pSetup + 1) = 0; /* max lun is 0 */
1751 usbMsdCompleteOk(pThis, pUrb, 1);
1752 }
1753 else
1754 {
1755 Log(("usbMsd: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1756 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1757 return usbMsdCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
1758 }
1759
1760 return VINF_SUCCESS;
1761}
1762
1763
1764/**
1765 * @copydoc PDMUSBREG::pfnQueue
1766 */
1767static DECLCALLBACK(int) usbMsdQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1768{
1769 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1770 LogFlow(("usbMsdQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
1771 RTCritSectEnter(&pThis->CritSect);
1772
1773 /*
1774 * Parse on a per end-point basis.
1775 */
1776 int rc;
1777 switch (pUrb->EndPt)
1778 {
1779 case 0:
1780 rc = usbMsdHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
1781 break;
1782
1783 case 0x81:
1784 AssertFailed();
1785 case 0x01:
1786 rc = usbMsdHandleBulkDevToHost(pThis, &pThis->aEps[1], pUrb);
1787 break;
1788
1789 case 0x02:
1790 rc = usbMsdHandleBulkHostToDev(pThis, &pThis->aEps[2], pUrb);
1791 break;
1792
1793 default:
1794 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
1795 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
1796 break;
1797 }
1798
1799 RTCritSectLeave(&pThis->CritSect);
1800 return rc;
1801}
1802
1803
1804/**
1805 * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
1806 */
1807static DECLCALLBACK(int) usbMsdUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
1808{
1809 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1810 LogFlow(("usbMsdUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
1811
1812 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
1813 {
1814 RTCritSectEnter(&pThis->CritSect);
1815 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
1816 RTCritSectLeave(&pThis->CritSect);
1817 }
1818
1819 return VINF_SUCCESS;
1820}
1821
1822
1823/**
1824 * @copydoc PDMUSBREG::pfnUsbSetInterface
1825 */
1826static DECLCALLBACK(int) usbMsdUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
1827{
1828 LogFlow(("usbMsdUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
1829 Assert(bAlternateSetting == 0);
1830 return VINF_SUCCESS;
1831}
1832
1833
1834/**
1835 * @copydoc PDMUSBREG::pfnUsbSetConfiguration
1836 */
1837static DECLCALLBACK(int) usbMsdUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
1838 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
1839{
1840 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1841 LogFlow(("usbMsdUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
1842 Assert(bConfigurationValue == 1);
1843 RTCritSectEnter(&pThis->CritSect);
1844
1845 /*
1846 * If the same config is applied more than once, it's a kind of reset.
1847 */
1848 if (pThis->bConfigurationValue == bConfigurationValue)
1849 usbMsdResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
1850 pThis->bConfigurationValue = bConfigurationValue;
1851
1852 RTCritSectLeave(&pThis->CritSect);
1853 return VINF_SUCCESS;
1854}
1855
1856
1857/**
1858 * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
1859 */
1860static DECLCALLBACK(PCPDMUSBDESCCACHE) usbMsdUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
1861{
1862 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1863 LogFlow(("usbMsdUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
1864 if (pThis->pUsbIns->iUsbHubVersion & VUSB_STDVER_20)
1865 return &g_UsbMsdDescCacheHS;
1866 else
1867 return &g_UsbMsdDescCacheFS;
1868}
1869
1870
1871/**
1872 * @copydoc PDMUSBREG::pfnUsbReset
1873 */
1874static DECLCALLBACK(int) usbMsdUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
1875{
1876 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1877 LogFlow(("usbMsdUsbReset/#%u:\n", pUsbIns->iInstance));
1878 RTCritSectEnter(&pThis->CritSect);
1879
1880 int rc = usbMsdResetWorker(pThis, NULL, false /*fSetConfig*/);
1881
1882 RTCritSectLeave(&pThis->CritSect);
1883 return rc;
1884}
1885
1886
1887/**
1888 * @copydoc PDMUSBREG::pfnVMSuspend
1889 */
1890static DECLCALLBACK(void) usbMsdVMSuspend(PPDMUSBINS pUsbIns)
1891{
1892 LogFlow(("usbMsdVMSuspend/#%u:\n", pUsbIns->iInstance));
1893 usbMsdSuspendOrPowerOff(pUsbIns);
1894}
1895
1896
1897/**
1898 * @copydoc PDMUSBREG::pfnVMSuspend
1899 */
1900static DECLCALLBACK(void) usbMsdVMPowerOff(PPDMUSBINS pUsbIns)
1901{
1902 LogFlow(("usbMsdVMPowerOff/#%u:\n", pUsbIns->iInstance));
1903 usbMsdSuspendOrPowerOff(pUsbIns);
1904}
1905
1906
1907/**
1908 * @copydoc PDMUSBREG::pfnDriverAttach
1909 */
1910static DECLCALLBACK(int) usbMsdDriverAttach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
1911{
1912 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1913 int rc;
1914
1915 LogFlow(("usbMsdDetach/#%u:\n", pUsbIns->iInstance));
1916
1917 AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n"));
1918 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
1919 ("UsbMsd: Device does not support hotplugging\n"));
1920
1921 /* the usual paranoia */
1922 AssertRelease(!pThis->Lun0.pIBase);
1923 AssertRelease(!pThis->Lun0.pIScsiConnector);
1924
1925 /*
1926 * Try attach the block device and get the interfaces,
1927 * required as well as optional.
1928 */
1929 rc = PDMUsbHlpDriverAttach(pUsbIns, iLUN, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, NULL);
1930 if (RT_SUCCESS(rc))
1931 {
1932 /* Get SCSI connector interface. */
1933 pThis->Lun0.pIScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR);
1934 AssertMsgReturn(pThis->Lun0.pIScsiConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
1935 }
1936 else
1937 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", iLUN, rc));
1938
1939 if (RT_FAILURE(rc))
1940 {
1941 pThis->Lun0.pIBase = NULL;
1942 pThis->Lun0.pIScsiConnector = NULL;
1943 }
1944 return rc;
1945}
1946
1947
1948/**
1949 * @copydoc PDMUSBREG::pfnDriverDetach
1950 */
1951static DECLCALLBACK(void) usbMsdDriverDetach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
1952{
1953 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1954
1955 LogFlow(("usbMsdDetach/#%u:\n", pUsbIns->iInstance));
1956
1957 AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n"));
1958 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
1959 ("UsbMsd: Device does not support hotplugging\n"));
1960
1961 /*
1962 * Zero some important members.
1963 */
1964 pThis->Lun0.pIBase = NULL;
1965 pThis->Lun0.pIScsiConnector = NULL;
1966}
1967
1968
1969/**
1970 * @callback_method_impl{FNPDMDEVASYNCNOTIFY,
1971 * Callback employed by usbMsdVMReset.}
1972 */
1973static DECLCALLBACK(bool) usbMsdIsAsyncResetDone(PPDMUSBINS pUsbIns)
1974{
1975 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1976
1977 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))
1978 return false;
1979 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
1980
1981 int rc = usbMsdResetWorker(pThis, NULL, false /*fSetConfig*/);
1982 AssertRC(rc);
1983 return true;
1984}
1985
1986/**
1987 * @interface_method_impl{PDMDEVREG,pfnReset}
1988 */
1989static DECLCALLBACK(void) usbMsdVMReset(PPDMUSBINS pUsbIns)
1990{
1991 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
1992
1993 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
1994 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))
1995 PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncResetDone);
1996 else
1997 {
1998 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
1999 int rc = usbMsdResetWorker(pThis, NULL, false /*fSetConfig*/);
2000 AssertRC(rc);
2001 }
2002}
2003
2004
2005/**
2006 * @copydoc PDMUSBREG::pfnDestruct
2007 */
2008static void usbMsdDestruct(PPDMUSBINS pUsbIns)
2009{
2010 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
2011 LogFlow(("usbMsdDestruct/#%u:\n", pUsbIns->iInstance));
2012
2013 if (RTCritSectIsInitialized(&pThis->CritSect))
2014 {
2015 RTCritSectEnter(&pThis->CritSect);
2016 RTCritSectLeave(&pThis->CritSect);
2017 RTCritSectDelete(&pThis->CritSect);
2018 }
2019
2020 if (pThis->pReq)
2021 {
2022 usbMsdReqFree(pThis->pReq);
2023 pThis->pReq = NULL;
2024 }
2025
2026 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
2027 {
2028 RTSemEventDestroy(pThis->hEvtDoneQueue);
2029 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2030 }
2031
2032 if (pThis->hEvtReset != NIL_RTSEMEVENTMULTI)
2033 {
2034 RTSemEventMultiDestroy(pThis->hEvtReset);
2035 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2036 }
2037}
2038
2039
2040/**
2041 * @copydoc PDMUSBREG::pfnConstruct
2042 */
2043static DECLCALLBACK(int) usbMsdConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
2044{
2045 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
2046 Log(("usbMsdConstruct/#%u:\n", iInstance));
2047
2048 /*
2049 * Perform the basic structure initialization first so the destructor
2050 * will not misbehave.
2051 */
2052 pThis->pUsbIns = pUsbIns;
2053 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2054 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2055 pThis->Lun0.IBase.pfnQueryInterface = usbMsdLun0QueryInterface;
2056 pThis->Lun0.IScsiPort.pfnSCSIRequestCompleted = usbMsdLun0ScsiRequestCompleted;
2057 pThis->Lun0.IScsiPort.pfnQueryDeviceLocation = usbMsdLun0QueryDeviceLocation;
2058 usbMsdQueueInit(&pThis->ToHostQueue);
2059 usbMsdQueueInit(&pThis->DoneQueue);
2060
2061 int rc = RTCritSectInit(&pThis->CritSect);
2062 AssertRCReturn(rc, rc);
2063
2064 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
2065 AssertRCReturn(rc, rc);
2066
2067 rc = RTSemEventMultiCreate(&pThis->hEvtReset);
2068 AssertRCReturn(rc, rc);
2069
2070 /*
2071 * Validate and read the configuration.
2072 */
2073 rc = CFGMR3ValidateConfig(pCfg, "/", "", "", "UsbMsd", iInstance);
2074 if (RT_FAILURE(rc))
2075 return rc;
2076
2077 /*
2078 * Attach the SCSI driver.
2079 */
2080 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, "SCSI Port");
2081 if (RT_FAILURE(rc))
2082 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("MSD failed to attach SCSI driver"));
2083 pThis->Lun0.pIScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR);
2084 if (!pThis->Lun0.pIScsiConnector)
2085 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
2086 N_("MSD failed to query the PDMISCSICONNECTOR from the driver below it"));
2087
2088 /*
2089 * Register the saved state data unit.
2090 */
2091 rc = PDMUsbHlpSSMRegister(pUsbIns, USB_MSD_SAVED_STATE_VERSION, sizeof(*pThis),
2092 NULL, usbMsdLiveExec, NULL,
2093 usbMsdSavePrep, usbMsdSaveExec, NULL,
2094 usbMsdLoadPrep, usbMsdLoadExec, NULL);
2095 if (RT_FAILURE(rc))
2096 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS,
2097 N_("MSD failed to register SSM save state handlers"));
2098
2099 return VINF_SUCCESS;
2100}
2101
2102
2103/**
2104 * The USB Mass Storage Device (MSD) registration record.
2105 */
2106const PDMUSBREG g_UsbMsd =
2107{
2108 /* u32Version */
2109 PDM_USBREG_VERSION,
2110 /* szName */
2111 "Msd",
2112 /* pszDescription */
2113 "USB Mass Storage Device, one LUN.",
2114 /* fFlags */
2115 PDM_USBREG_HIGHSPEED_CAPABLE | PDM_USBREG_EMULATED_DEVICE,
2116 /* cMaxInstances */
2117 ~0U,
2118 /* cbInstance */
2119 sizeof(USBMSD),
2120 /* pfnConstruct */
2121 usbMsdConstruct,
2122 /* pfnDestruct */
2123 usbMsdDestruct,
2124 /* pfnVMInitComplete */
2125 NULL,
2126 /* pfnVMPowerOn */
2127 NULL,
2128 /* pfnVMReset */
2129 usbMsdVMReset,
2130 /* pfnVMSuspend */
2131 usbMsdVMSuspend,
2132 /* pfnVMResume */
2133 NULL,
2134 /* pfnVMPowerOff */
2135 usbMsdVMPowerOff,
2136 /* pfnHotPlugged */
2137 NULL,
2138 /* pfnHotUnplugged */
2139 NULL,
2140 /* pfnDriverAttach */
2141 usbMsdDriverAttach,
2142 /* pfnDriverDetach */
2143 usbMsdDriverDetach,
2144 /* pfnQueryInterface */
2145 NULL,
2146 /* pfnUsbReset */
2147 usbMsdUsbReset,
2148 /* pfnUsbGetCachedDescriptors */
2149 usbMsdUsbGetDescriptorCache,
2150 /* pfnUsbSetConfiguration */
2151 usbMsdUsbSetConfiguration,
2152 /* pfnUsbSetInterface */
2153 usbMsdUsbSetInterface,
2154 /* pfnUsbClearHaltedEndpoint */
2155 usbMsdUsbClearHaltedEndpoint,
2156 /* pfnUrbNew */
2157 NULL/*usbMsdUrbNew*/,
2158 /* pfnQueue */
2159 usbMsdQueue,
2160 /* pfnUrbCancel */
2161 usbMsdUrbCancel,
2162 /* pfnUrbReap */
2163 usbMsdUrbReap,
2164 /* u32TheEnd */
2165 PDM_USBREG_VERSION
2166};
2167
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette