Changeset 38680 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Sep 8, 2011 7:52:08 AM (13 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Makefile.kmk
r38679 r38680 73 73 Storage/VSCSI/VSCSISense.cpp \ 74 74 Storage/VSCSI/VSCSIIoReq.cpp \ 75 Storage/VSCSI/VSCSIVpdPagePool.cpp \ 75 76 build/VBoxDDUDeps.cpp 76 77 ifdef VBOX_WITH_USB -
trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
r35353 r38680 105 105 /** Errors printed in the release log. */ 106 106 unsigned cErrors; 107 /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */ 108 bool fNonRotational; 107 109 } DRVSCSI, *PDRVSCSI; 108 110 … … 188 190 break; 189 191 } 192 case VSCSIIOREQTXDIR_UNMAP: 193 { 194 PVSCSIRANGE paRanges; 195 unsigned cRanges; 196 197 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges); 198 AssertRC(rc); 199 200 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1; 201 rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, (PPDMRANGE)paRanges, cRanges); 202 pThis->pLed->Actual.s.fWriting = 0; 203 break; 204 } 190 205 default: 191 206 AssertMsgFailed(("Invalid transfer direction %d\n", enmTxDir)); … … 200 215 } 201 216 202 static intdrvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize)217 static DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize) 203 218 { 204 219 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; … … 259 274 } 260 275 261 static intdrvscsiReqTransferEnqueue(VSCSILUN hVScsiLun,262 void *pvScsiLunUser,263 VSCSIIOREQ hVScsiIoReq)276 static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, 277 void *pvScsiLunUser, 278 VSCSIIOREQ hVScsiIoReq) 264 279 { 265 280 int rc = VINF_SUCCESS; … … 372 387 } 373 388 389 static DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun, 390 void *pvScsiLunUser, 391 uint64_t *pfFeatures) 392 { 393 int rc = VINF_SUCCESS; 394 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 395 396 *pfFeatures = 0; 397 398 if (pThis->pDrvBlock->pfnDiscard) 399 *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP; 400 401 if (pThis->fNonRotational) 402 *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL; 403 404 return VINF_SUCCESS; 405 } 406 374 407 static void drvscsiVScsiReqCompleted(VSCSIDEVICE hVScsiDevice, void *pVScsiDeviceUser, 375 408 void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible, … … 741 774 742 775 /* 776 * Validate and read configuration. 777 */ 778 if (!CFGMR3AreValuesValid(pCfg, "NonRotationalMedium\0")) 779 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, 780 N_("SCSI configuration error: unknown option specified")); 781 782 rc = CFGMR3QueryBoolDef(pCfg, "NonRotationalMedium", &pThis->fNonRotational, false); 783 if (RT_FAILURE(rc)) 784 return PDMDRV_SET_ERROR(pDrvIns, rc, 785 N_("SCSI configuration error: failed to read \"NonRotationalMedium\" as boolean")); 786 787 /* 743 788 * Initialize the instance data. 744 789 */ … … 803 848 pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize = drvscsiGetSize; 804 849 pThis->VScsiIoCallbacks.pfnVScsiLunReqTransferEnqueue = drvscsiReqTransferEnqueue; 850 pThis->VScsiIoCallbacks.pfnVScsiLunGetFeatureFlags = drvscsiGetFeatureFlags; 805 851 806 852 rc = VSCSIDeviceCreate(&pThis->hVScsiDevice, drvscsiVScsiReqCompleted, pThis); -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp
r38678 r38680 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 16 */ 17 /******************************************************************************* 18 * Header Files * 19 *******************************************************************************/ 17 20 #define LOG_GROUP LOG_GROUP_VSCSI 18 21 #include <VBox/log.h> … … 81 84 */ 82 85 if (vscsiBE2HU32(&pVScsiReq->pbCDB[6]) < 16) 83 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET );86 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 84 87 else 85 88 { … … 91 94 cbData = RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 92 95 if (cbData < 16) 93 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET );96 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 94 97 else 95 98 *prcReq = vscsiReqSenseOkSet(&pVScsiDevice->VScsiSense, pVScsiReq); … … 106 109 /* Descriptor format sense data is not supported and results in an error. */ 107 110 if ((pVScsiReq->pbCDB[1] & 0x1) != 0) 108 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET );111 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 109 112 else 110 113 *prcReq = vscsiReqSenseCmd(&pVScsiDevice->VScsiSense, pVScsiReq); … … 293 296 vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, 294 297 SCSI_SENSE_ILLEGAL_REQUEST, 295 SCSI_ASC_LOGICAL_UNIT_DOES_NOT_RESPOND_TO_SELECTION); 298 SCSI_ASC_LOGICAL_UNIT_DOES_NOT_RESPOND_TO_SELECTION, 299 0x00); 296 300 297 301 vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq, … … 333 337 pVScsiReq->pvVScsiReqUser = pvVScsiReqUser; 334 338 335 RTSgBufInit(&pVScsiReq->SgBuf, paSGList, cSGListEntries); 339 if (cSGListEntries) 340 RTSgBufInit(&pVScsiReq->SgBuf, paSGList, cSGListEntries); 336 341 337 342 *phVScsiReq = pVScsiReq; -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
r38678 r38680 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 #include <iprt/memcache.h> 23 23 #include <iprt/sg.h> 24 #include <iprt/list.h> 24 25 25 26 #include "VSCSIInline.h" 27 #include "VSCSIVpdPages.h" 26 28 27 29 /** Pointer to an internal virtual SCSI device. */ … … 84 86 /** Pointer to the LUN type descriptor. */ 85 87 PVSCSILUNDESC pVScsiLunDesc; 88 /** Flags of supported features. */ 89 uint64_t fFeatures; 86 90 /** I/O request processing data */ 87 91 struct … … 119 123 { 120 124 /** The associated request. */ 121 PVSCSIREQINT pVScsiReq;125 PVSCSIREQINT pVScsiReq; 122 126 /** Lun for this I/O request. */ 123 PVSCSILUNINT pVScsiLun;127 PVSCSILUNINT pVScsiLun; 124 128 /** Transfer direction */ 125 VSCSIIOREQTXDIR enmTxDir; 126 /** Start offset */ 127 uint64_t uOffset; 128 /** Number of bytes to transfer */ 129 size_t cbTransfer; 130 /** Number of bytes the S/G list holds */ 131 size_t cbSeg; 132 /** Number of segments. */ 133 unsigned cSeg; 134 /** Segment array. */ 135 PCRTSGSEG paSeg; 129 VSCSIIOREQTXDIR enmTxDir; 130 /** Direction dependent data. */ 131 union 132 { 133 /** Read/Write request. */ 134 struct 135 { 136 /** Start offset */ 137 uint64_t uOffset; 138 /** Number of bytes to transfer */ 139 size_t cbTransfer; 140 /** Number of bytes the S/G list holds */ 141 size_t cbSeg; 142 /** Number of segments. */ 143 unsigned cSeg; 144 /** Segment array. */ 145 PCRTSGSEG paSeg; 146 } Io; 147 /** Unmape request. */ 148 struct 149 { 150 /** Array of ranges to unmap. */ 151 PVSCSIRANGE paRanges; 152 /** Number of ranges. */ 153 unsigned cRanges; 154 } Unmap; 155 } u; 136 156 } VSCSIIOREQINT; 157 158 /** 159 * VPD page pool. 160 */ 161 typedef struct VSCSIVPDPOOL 162 { 163 /** List of registered pages. */ 164 RTLISTNODE ListPages; 165 } VSCSIVPDPOOL; 166 /** Pointer to the VSCSI VPD page pool. */ 167 typedef VSCSIVPDPOOL *PVSCSIVPDPOOL; 137 168 138 169 /** … … 217 248 * @param uSCSISenseKey The SCSI sense key to set. 218 249 * @param uSCSIASC The ASC value. 219 */ 220 int vscsiReqSenseErrorSet(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC); 250 * @param uSCSIASC The ASCQ value. 251 */ 252 int vscsiReqSenseErrorSet(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, 253 uint8_t uSCSIASC, uint8_t uSCSIASCQ); 221 254 222 255 /** … … 228 261 */ 229 262 int vscsiReqSenseCmd(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq); 263 264 /** 265 * Inits the VPD page pool. 266 * 267 * @returns VBox status code. 268 * @param pVScsiVpdPool The VPD page pool to initialize. 269 */ 270 int vscsiVpdPagePoolInit(PVSCSIVPDPOOL pVScsiVpdPool); 271 272 /** 273 * Destroys the given VPD page pool freeing all pages in it. 274 * 275 * @returns nothing. 276 * @param pVScsiVpdPool The VPD page pool to destroy. 277 */ 278 void vscsiVpdPagePoolDestroy(PVSCSIVPDPOOL pVScsiVpdPool); 279 280 /** 281 * Allocates a new page in the VPD page pool with the given number. 282 * 283 * @returns VBox status code. 284 * @retval VERR_ALREADY_EXIST if the page number is in use. 285 * @param pVScsiVpdPool The VPD page pool the page will belong to. 286 * @param uPage The page number, must be unique. 287 * @param cbPage Size of the page in bytes. 288 * @param ppbPage Where to store the pointer to the raw page data on success. 289 */ 290 int vscsiVpdPagePoolAllocNewPage(PVSCSIVPDPOOL pVScsiVpdPool, uint8_t uPage, size_t cbPage, uint8_t **ppbPage); 291 292 /** 293 * Queries the given page from the pool and cpies it to the buffer given 294 * by the SCSI request. 295 * 296 * @returns VBox status code. 297 * @retval VERR_NOT_FOUND if the page is not in the pool. 298 * @param pVScsiVpdPool The VPD page pool to use. 299 * @param pVScsiReq The SCSI request. 300 * @param uPage Page to query. 301 */ 302 int vscsiVpdPagePoolQueryPage(PVSCSIVPDPOOL pVScsiVpdPool, PVSCSIREQINT pVScsiReq, uint8_t uPage); 230 303 231 304 /** … … 253 326 254 327 /** 328 * Enqueue a new unmap request. 329 * 330 * @returns VBox status code. 331 * @param pVScsiLun The LUN instance which issued the request. 332 * @param pVScsiReq The virtual SCSI request associated with the transfer. 333 * @param paRanges The array of ranges to unmap. 334 * @param cRanges Number of ranges in the array. 335 */ 336 int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, 337 PVSCSIRANGE paRanges, unsigned cRanges); 338 339 /** 255 340 * Returns the current number of outstanding tasks on the given LUN. 256 341 * … … 289 374 290 375 /** 376 * Wrapper for the get feature flags I/O callback. 377 * 378 * @returns VBox status code. 379 * @param pVScsiLun The LUN. 380 * @param pVScsiIoReq The I/O request to enqueue. 381 */ 382 DECLINLINE(int) vscsiLunGetFeatureFlags(PVSCSILUNINT pVScsiLun, uint64_t *pfFeatures) 383 { 384 return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunGetFeatureFlags(pVScsiLun, 385 pVScsiLun->pvVScsiLunUser, 386 pfFeatures); 387 } 388 389 /** 291 390 * Wrapper around vscsiReqSenseOkSet() 292 391 */ … … 299 398 * Wrapper around vscsiReqSenseErrorSet() 300 399 */ 301 DECLINLINE(int) vscsiLunReqSenseErrorSet(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC )302 { 303 return vscsiReqSenseErrorSet(&pVScsiLun->pVScsiDevice->VScsiSense, pVScsiReq, uSCSISenseKey, uSCSIASC );400 DECLINLINE(int) vscsiLunReqSenseErrorSet(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC, uint8_t uSCSIASCQ) 401 { 402 return vscsiReqSenseErrorSet(&pVScsiLun->pVScsiDevice->VScsiSense, pVScsiReq, uSCSISenseKey, uSCSIASC, uSCSIASCQ); 304 403 } 305 404 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp
r38678 r38680 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 66 66 return VERR_NO_MEMORY; 67 67 68 pVScsiIoReq->pVScsiReq = pVScsiReq; 69 pVScsiIoReq->pVScsiLun = pVScsiLun; 70 pVScsiIoReq->enmTxDir = enmTxDir; 71 pVScsiIoReq->uOffset = uOffset; 72 pVScsiIoReq->cbTransfer = cbTransfer; 73 pVScsiIoReq->paSeg = pVScsiReq->SgBuf.paSegs; 74 pVScsiIoReq->cSeg = pVScsiReq->SgBuf.cSegs; 68 pVScsiIoReq->pVScsiReq = pVScsiReq; 69 pVScsiIoReq->pVScsiLun = pVScsiLun; 70 pVScsiIoReq->enmTxDir = enmTxDir; 71 pVScsiIoReq->u.Io.uOffset = uOffset; 72 pVScsiIoReq->u.Io.cbTransfer = cbTransfer; 73 pVScsiIoReq->u.Io.paSeg = pVScsiReq->SgBuf.paSegs; 74 pVScsiIoReq->u.Io.cSeg = pVScsiReq->SgBuf.cSegs; 75 76 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); 77 78 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq); 79 if (RT_FAILURE(rc)) 80 { 81 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding); 82 RTMemFree(pVScsiIoReq); 83 } 84 85 return rc; 86 } 87 88 89 int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, 90 PVSCSIRANGE paRanges, unsigned cRanges) 91 { 92 int rc = VINF_SUCCESS; 93 PVSCSIIOREQINT pVScsiIoReq = NULL; 94 95 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p paRanges=%#p cRanges=%u\n", 96 pVScsiLun, pVScsiReq, paRanges, cRanges)); 97 98 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT)); 99 if (!pVScsiIoReq) 100 return VERR_NO_MEMORY; 101 102 pVScsiIoReq->pVScsiReq = pVScsiReq; 103 pVScsiIoReq->pVScsiLun = pVScsiLun; 104 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_UNMAP; 105 pVScsiIoReq->u.Unmap.paRanges = paRanges; 106 pVScsiIoReq->u.Unmap.cRanges = cRanges; 75 107 76 108 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding); … … 112 144 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding); 113 145 114 /** @todo error reporting */115 146 if (RT_SUCCESS(rcIoReq)) 116 147 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); … … 122 153 pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ 123 154 ? SCSI_ASC_READ_ERROR 124 : SCSI_ASC_WRITE_ERROR); 155 : SCSI_ASC_WRITE_ERROR, 156 0x00); 125 157 } 126 158 else 127 159 rcReq = SCSI_STATUS_CHECK_CONDITION; 160 161 if (pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP) 162 RTMemFree(pVScsiIoReq->u.Unmap.paRanges); 128 163 129 164 /* Free the I/O request */ … … 154 189 155 190 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE); 156 AssertReturn(pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_FLUSH, VERR_NOT_SUPPORTED); 157 158 *puOffset = pVScsiIoReq->uOffset; 159 *pcbTransfer = pVScsiIoReq->cbTransfer; 160 *pcSeg = pVScsiIoReq->cSeg; 161 *pcbSeg = pVScsiIoReq->cbSeg; 162 *ppaSeg = pVScsiIoReq->paSeg; 191 AssertReturn( pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_FLUSH 192 && pVScsiIoReq->enmTxDir != VSCSIIOREQTXDIR_UNMAP, 193 VERR_NOT_SUPPORTED); 194 195 *puOffset = pVScsiIoReq->u.Io.uOffset; 196 *pcbTransfer = pVScsiIoReq->u.Io.cbTransfer; 197 *pcSeg = pVScsiIoReq->u.Io.cSeg; 198 *pcbSeg = pVScsiIoReq->u.Io.cbSeg; 199 *ppaSeg = pVScsiIoReq->u.Io.paSeg; 163 200 164 201 return VINF_SUCCESS; 165 202 } 166 203 204 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PVSCSIRANGE *ppaRanges, 205 unsigned *pcRanges) 206 { 207 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq; 208 209 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE); 210 AssertReturn(pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_UNMAP, VERR_NOT_SUPPORTED); 211 212 *ppaRanges = pVScsiIoReq->u.Unmap.paRanges; 213 *pcRanges = pVScsiIoReq->u.Unmap.cRanges; 214 215 return VINF_SUCCESS; 216 } 217 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILun.cpp
r33540 r38680 71 71 pVScsiLun->pVScsiLunDesc = pVScsiLunDesc; 72 72 73 int rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun);73 int rc = vscsiLunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures); 74 74 if (RT_SUCCESS(rc)) 75 75 { 76 /** @todo Init other stuff */ 77 *phVScsiLun = pVScsiLun; 78 return VINF_SUCCESS; 76 rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun); 77 if (RT_SUCCESS(rc)) 78 { 79 *phVScsiLun = pVScsiLun; 80 return VINF_SUCCESS; 81 } 79 82 } 80 83 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
r38678 r38680 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 24 24 #include <VBox/types.h> 25 25 #include <VBox/vscsi.h> 26 #include <iprt/cdefs.h> 27 #include <iprt/asm.h> 26 28 #include <iprt/assert.h> 27 29 #include <iprt/mem.h> … … 29 31 30 32 #include "VSCSIInternal.h" 33 34 /** Maximum of amount of LBAs to unmap with one command. */ 35 #define VSCSI_UNMAP_LBAS_MAX ((10*_1M) / 512) 31 36 32 37 /** … … 39 44 /** Size of the virtual disk. */ 40 45 uint64_t cSectors; 46 /** VPD page pool. */ 47 VSCSIVPDPOOL VpdPagePool; 41 48 } VSCSILUNSBC; 42 49 /** Pointer to a SBC LUN instance */ … … 48 55 uint64_t cbDisk = 0; 49 56 int rc = VINF_SUCCESS; 57 int cVpdPages = 0; 50 58 51 59 rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk); … … 53 61 pVScsiLunSbc->cSectors = cbDisk / 512; /* Fixed sector size */ 54 62 63 if (RT_SUCCESS(rc)) 64 rc = vscsiVpdPagePoolInit(&pVScsiLunSbc->VpdPagePool); 65 66 if ( RT_SUCCESS(rc) 67 && (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP)) 68 { 69 PVSCSIVPDPAGEBLOCKLIMITS pBlkPage; 70 PVSCSIVPDPAGEBLOCKPROV pBlkProvPage; 71 72 /* Create the page and fill it. */ 73 rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_LIMITS_NUMBER, 74 VSCSI_VPD_BLOCK_LIMITS_SIZE, (uint8_t **)&pBlkPage); 75 if (RT_SUCCESS(rc)) 76 { 77 pBlkPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 78 pBlkPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 79 pBlkPage->u16PageLength = RT_H2BE_U16(0x3c); 80 pBlkPage->u8MaxCmpWriteLength = 0; 81 pBlkPage->u16OptTrfLengthGran = 0; 82 pBlkPage->u32MaxTrfLength = 0; 83 pBlkPage->u32OptTrfLength = 0; 84 pBlkPage->u32MaxPreXdTrfLength = 0; 85 pBlkPage->u32MaxUnmapLbaCount = RT_H2BE_U32(VSCSI_UNMAP_LBAS_MAX); 86 pBlkPage->u32MaxUnmapBlkDescCount = UINT32_C(0xffffffff); 87 pBlkPage->u32OptUnmapGranularity = 0; 88 pBlkPage->u32UnmapGranularityAlignment = 0; 89 cVpdPages++; 90 } 91 92 if (RT_SUCCESS(rc)) 93 { 94 rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_PROV_NUMBER, 95 VSCSI_VPD_BLOCK_PROV_SIZE, (uint8_t **)&pBlkProvPage); 96 if (RT_SUCCESS(rc)) 97 { 98 pBlkProvPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 99 pBlkProvPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 100 pBlkProvPage->u16PageLength = RT_H2BE_U16(0x4); 101 pBlkProvPage->u8ThresholdExponent = 1; 102 pBlkProvPage->fLBPU = true; 103 cVpdPages++; 104 } 105 } 106 } 107 108 if ( RT_SUCCESS(rc) 109 && (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_NON_ROTATIONAL)) 110 { 111 PVSCSIVPDPAGEBLOCKCHARACTERISTICS pBlkPage; 112 113 /* Create the page and fill it. */ 114 rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_BLOCK_CHARACTERISTICS_NUMBER, 115 VSCSI_VPD_BLOCK_CHARACTERISTICS_SIZE, (uint8_t **)&pBlkPage); 116 if (RT_SUCCESS(rc)) 117 { 118 pBlkPage->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 119 pBlkPage->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 120 pBlkPage->u16PageLength = RT_H2BE_U16(0x3c); 121 pBlkPage->u16MediumRotationRate = RT_H2BE_U16(VSCSI_VPD_BLOCK_CHARACT_MEDIUM_ROTATION_RATE_NON_ROTATING); 122 cVpdPages++; 123 } 124 } 125 126 if ( RT_SUCCESS(rc) 127 && cVpdPages) 128 { 129 PVSCSIVPDPAGESUPPORTEDPAGES pVpdPages; 130 131 rc = vscsiVpdPagePoolAllocNewPage(&pVScsiLunSbc->VpdPagePool, VSCSI_VPD_SUPPORTED_PAGES_NUMBER, 132 VSCSI_VPD_SUPPORTED_PAGES_SIZE + cVpdPages - 1, (uint8_t **)&pVpdPages); 133 if (RT_SUCCESS(rc)) 134 { 135 unsigned idxVpdPage = 0; 136 pVpdPages->u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 137 pVpdPages->u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 138 pVpdPages->u16PageLength = RT_H2BE_U16(cVpdPages); 139 140 if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP) 141 { 142 pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_LIMITS_NUMBER; 143 pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_PROV_NUMBER; 144 } 145 146 if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_NON_ROTATIONAL) 147 pVpdPages->abVpdPages[idxVpdPage++] = VSCSI_VPD_BLOCK_CHARACTERISTICS_NUMBER; 148 } 149 } 150 55 151 return rc; 56 152 } … … 59 155 { 60 156 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun; 157 158 vscsiVpdPagePoolDestroy(&pVScsiLunSbc->VpdPagePool); 61 159 62 160 return VINF_SUCCESS; … … 76 174 case SCSI_INQUIRY: 77 175 { 78 SCSIINQUIRYDATA ScsiInquiryReply; 79 80 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); 81 82 ScsiInquiryReply.cbAdditional = 31; 83 ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 84 ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 85 ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */ 86 ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ 87 ScsiInquiryReply.fWBus16 = 1; 88 vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8); 89 vscsiPadStr(ScsiInquiryReply.achProductId, "HARDDISK", 16); 90 vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4); 91 92 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); 93 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 176 /* Check for EVPD bit. */ 177 if (pVScsiReq->pbCDB[1] & 0x1) 178 { 179 rc = vscsiVpdPagePoolQueryPage(&pVScsiLunSbc->VpdPagePool, pVScsiReq, pVScsiReq->pbCDB[2]); 180 if (RT_UNLIKELY(rc == VERR_NOT_FOUND)) 181 { 182 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 183 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 184 rc = VINF_SUCCESS; 185 } 186 else 187 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 188 } 189 else if (pVScsiReq->pbCDB[2] != 0) /* A non zero page code is an error. */ 190 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 191 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 192 else 193 { 194 SCSIINQUIRYDATA ScsiInquiryReply; 195 196 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); 197 198 ScsiInquiryReply.cbAdditional = 31; 199 ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; 200 ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 201 ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */ 202 ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ 203 ScsiInquiryReply.fWBus16 = 1; 204 vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8); 205 vscsiPadStr(ScsiInquiryReply.achProductId, "HARDDISK", 16); 206 vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4); 207 208 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); 209 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 210 } 94 211 break; 95 212 } … … 263 380 } 264 381 default: 265 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET );382 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 266 383 } 267 384 break; … … 278 395 vscsiH2BEU64(aReply, pVScsiLunSbc->cSectors - 1); 279 396 vscsiH2BEU32(&aReply[8], 512); 397 if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP) 398 aReply[14] = 0x80; /* LPME enabled */ 280 399 /* Leave the rest 0 */ 281 400 … … 285 404 } 286 405 default: 287 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); /* Don't know if this is correct */ 288 } 406 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */ 407 } 408 break; 409 } 410 case SCSI_UNMAP: 411 { 412 if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP) 413 { 414 uint8_t abHdr[8]; 415 size_t cbCopied; 416 size_t cbList = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 417 418 /* Copy the header. */ 419 cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abHdr[0], sizeof(abHdr)); 420 421 /* Using the anchor bit is not supported. */ 422 if ( !(pVScsiReq->pbCDB[1] & 0x01) 423 && cbCopied == sizeof(abHdr) 424 && cbList >= 8) 425 { 426 size_t cBlkDesc = vscsiBE2HU16(&abHdr[2]) / 16; 427 428 if (cBlkDesc) 429 { 430 PVSCSIRANGE paRanges; 431 432 paRanges = (PVSCSIRANGE)RTMemAllocZ(cBlkDesc * sizeof(PVSCSIRANGE)); 433 if (paRanges) 434 { 435 for (unsigned i = 0; i < cBlkDesc; i++) 436 { 437 uint8_t abBlkDesc[16]; 438 439 cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abBlkDesc[0], sizeof(abBlkDesc)); 440 if (RT_UNLIKELY(cbCopied != sizeof(abBlkDesc))) 441 { 442 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 443 break; 444 } 445 446 paRanges[i].offStart = vscsiBE2HU64(&abBlkDesc[0]) * 512; 447 paRanges[i].cbRange = vscsiBE2HU32(&abBlkDesc[8]) * 512; 448 } 449 450 if (rcReq == SCSI_STATUS_OK) 451 rc = vscsiIoReqUnmapEnqueue(pVScsiLun, pVScsiReq, paRanges, cBlkDesc); 452 } 453 else /* Out of memory. */ 454 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_HARDWARE_ERROR, SCSI_ASC_SYSTEM_RESOURCE_FAILURE, 455 SCSI_ASCQ_SYSTEM_BUFFER_FULL); 456 } 457 else /* No block descriptors is not an error condition. */ 458 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 459 } 460 else /* Invalid CDB. */ 461 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 462 } 463 else 464 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00); 465 289 466 break; 290 467 } 291 468 default: 292 469 //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0]))); 293 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE );470 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00); 294 471 } 295 472 … … 301 478 if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunSbc->cSectors)) 302 479 { 303 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR );480 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00); 304 481 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS); 305 482 } … … 316 493 rc = vscsiIoReqFlushEnqueue(pVScsiLun, pVScsiReq); 317 494 } 318 else /* Request completed */495 else if (pVScsiReq->pbCDB[0] != SCSI_UNMAP) /* Request completed */ 319 496 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS); 320 497 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSISense.cpp
r38678 r38680 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 43 43 } 44 44 45 int vscsiReqSenseErrorSet(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC )45 int vscsiReqSenseErrorSet(PVSCSISENSE pVScsiSense, PVSCSIREQINT pVScsiReq, uint8_t uSCSISenseKey, uint8_t uSCSIASC, uint8_t uSCSIASCQ) 46 46 { 47 47 memset(pVScsiSense->abSenseBuf, 0, sizeof(pVScsiSense->abSenseBuf)); … … 50 50 pVScsiSense->abSenseBuf[7] = 10; 51 51 pVScsiSense->abSenseBuf[12] = uSCSIASC; 52 pVScsiSense->abSenseBuf[13] = 0x00; /** @todo: Provide more info. */52 pVScsiSense->abSenseBuf[13] = uSCSIASCQ; 53 53 54 54 if (pVScsiReq->pbSense && pVScsiReq->cbSense)
Note:
See TracChangeset
for help on using the changeset viewer.