VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp@ 38680

Last change on this file since 38680 was 38680, checked in by vboxsync, 13 years ago

VSCSI+DrvSCSI: Add support for the UNMAP command if discarding is enabled

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1/* $Id: VSCSILunSbc.cpp 38680 2011-09-08 07:52:08Z vboxsync $ */
2/** @file
3 * Virtual SCSI driver: SBC LUN implementation (hard disks)
4 */
5
6/*
7 * Copyright (C) 2006-2011 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_VSCSI
22#include <VBox/log.h>
23#include <VBox/err.h>
24#include <VBox/types.h>
25#include <VBox/vscsi.h>
26#include <iprt/cdefs.h>
27#include <iprt/asm.h>
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30#include <iprt/string.h>
31
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)
36
37/**
38 * SBC LUN instance
39 */
40typedef struct VSCSILUNSBC
41{
42 /** Core LUN structure */
43 VSCSILUNINT Core;
44 /** Size of the virtual disk. */
45 uint64_t cSectors;
46 /** VPD page pool. */
47 VSCSIVPDPOOL VpdPagePool;
48} VSCSILUNSBC;
49/** Pointer to a SBC LUN instance */
50typedef VSCSILUNSBC *PVSCSILUNSBC;
51
52static int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
53{
54 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
55 uint64_t cbDisk = 0;
56 int rc = VINF_SUCCESS;
57 int cVpdPages = 0;
58
59 rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
60 if (RT_SUCCESS(rc))
61 pVScsiLunSbc->cSectors = cbDisk / 512; /* Fixed sector size */
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
151 return rc;
152}
153
154static int vscsiLunSbcDestroy(PVSCSILUNINT pVScsiLun)
155{
156 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
157
158 vscsiVpdPagePoolDestroy(&pVScsiLunSbc->VpdPagePool);
159
160 return VINF_SUCCESS;
161}
162
163static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
164{
165 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
166 int rc = VINF_SUCCESS;
167 int rcReq = SCSI_STATUS_OK;
168 uint64_t uLbaStart = 0;
169 uint32_t cSectorTransfer = 0;
170 VSCSIIOREQTXDIR enmTxDir = VSCSIIOREQTXDIR_INVALID;
171
172 switch(pVScsiReq->pbCDB[0])
173 {
174 case SCSI_INQUIRY:
175 {
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 }
211 break;
212 }
213 case SCSI_READ_CAPACITY:
214 {
215 uint8_t aReply[8];
216 memset(aReply, 0, sizeof(aReply));
217
218 /*
219 * If sector size exceeds the maximum value that is
220 * able to be stored in 4 bytes return 0xffffffff in this field
221 */
222 if (pVScsiLunSbc->cSectors > UINT32_C(0xffffffff))
223 vscsiH2BEU32(aReply, UINT32_C(0xffffffff));
224 else
225 vscsiH2BEU32(aReply, pVScsiLunSbc->cSectors - 1);
226 vscsiH2BEU32(&aReply[4], 512);
227 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
228 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
229 break;
230 }
231 case SCSI_MODE_SENSE_6:
232 {
233 uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f;
234 uint8_t aReply[24];
235 uint8_t *pu8ReplyPos;
236
237 memset(aReply, 0, sizeof(aReply));
238 aReply[0] = 4; /* Reply length 4. */
239 aReply[1] = 0; /* Default media type. */
240 aReply[2] = RT_BIT(4); /* Caching supported. */
241 aReply[3] = 0; /* Block descriptor length. */
242
243 pu8ReplyPos = aReply + 4;
244
245 if ((uModePage == 0x08) || (uModePage == 0x3f))
246 {
247 memset(pu8ReplyPos, 0, 20);
248 *pu8ReplyPos++ = 0x08; /* Page code. */
249 *pu8ReplyPos++ = 0x12; /* Size of the page. */
250 *pu8ReplyPos++ = 0x4; /* Write cache enabled. */
251 }
252
253 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
254 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
255 break;
256 }
257 case SCSI_READ_6:
258 {
259 enmTxDir = VSCSIIOREQTXDIR_READ;
260 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
261 | (pVScsiReq->pbCDB[2] << 8)
262 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
263 cSectorTransfer = pVScsiReq->pbCDB[4];
264 break;
265 }
266 case SCSI_READ_10:
267 {
268 enmTxDir = VSCSIIOREQTXDIR_READ;
269 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
270 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
271 break;
272 }
273 case SCSI_READ_12:
274 {
275 enmTxDir = VSCSIIOREQTXDIR_READ;
276 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
277 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
278 break;
279 }
280 case SCSI_READ_16:
281 {
282 enmTxDir = VSCSIIOREQTXDIR_READ;
283 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
284 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
285 break;
286 }
287 case SCSI_WRITE_6:
288 {
289 enmTxDir = VSCSIIOREQTXDIR_WRITE;
290 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
291 | (pVScsiReq->pbCDB[2] << 8)
292 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
293 cSectorTransfer = pVScsiReq->pbCDB[4];
294 break;
295 }
296 case SCSI_WRITE_10:
297 {
298 enmTxDir = VSCSIIOREQTXDIR_WRITE;
299 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
300 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
301 break;
302 }
303 case SCSI_WRITE_12:
304 {
305 enmTxDir = VSCSIIOREQTXDIR_WRITE;
306 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
307 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
308 break;
309 }
310 case SCSI_WRITE_16:
311 {
312 enmTxDir = VSCSIIOREQTXDIR_WRITE;
313 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
314 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
315 break;
316 }
317 case SCSI_SYNCHRONIZE_CACHE:
318 {
319 break; /* Handled below */
320 }
321 case SCSI_READ_BUFFER:
322 {
323 uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
324
325 switch (uDataMode)
326 {
327 case 0x00:
328 case 0x01:
329 case 0x02:
330 case 0x03:
331 case 0x0a:
332 break;
333 case 0x0b:
334 {
335 uint8_t aReply[4];
336
337 /* We do not implement an echo buffer. */
338 memset(aReply, 0, sizeof(aReply));
339
340 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
341 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
342 break;
343 }
344 case 0x1a:
345 case 0x1c:
346 break;
347 default:
348 AssertMsgFailed(("Invalid data mode\n"));
349 }
350 break;
351 }
352 case SCSI_VERIFY_10:
353 case SCSI_START_STOP_UNIT:
354 {
355 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
356 break;
357 }
358 case SCSI_LOG_SENSE:
359 {
360 uint16_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
361 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
362 uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
363
364 switch (uPageCode)
365 {
366 case 0x00:
367 {
368 if (uSubPageCode == 0)
369 {
370 uint8_t aReply[4];
371
372 aReply[0] = 0;
373 aReply[1] = 0;
374 aReply[2] = 0;
375 aReply[3] = 0;
376 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
377 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
378 break;
379 }
380 }
381 default:
382 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
383 }
384 break;
385 }
386 case SCSI_SERVICE_ACTION_IN_16:
387 {
388 switch (pVScsiReq->pbCDB[1] & 0x1f)
389 {
390 case SCSI_SVC_ACTION_IN_READ_CAPACITY_16:
391 {
392 uint8_t aReply[32];
393
394 memset(aReply, 0, sizeof(aReply));
395 vscsiH2BEU64(aReply, pVScsiLunSbc->cSectors - 1);
396 vscsiH2BEU32(&aReply[8], 512);
397 if (pVScsiLun->fFeatures & VSCSI_LUN_FEATURE_UNMAP)
398 aReply[14] = 0x80; /* LPME enabled */
399 /* Leave the rest 0 */
400
401 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
402 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
403 break;
404 }
405 default:
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
466 break;
467 }
468 default:
469 //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0])));
470 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00);
471 }
472
473 if (enmTxDir != VSCSIIOREQTXDIR_INVALID)
474 {
475 LogFlow(("%s: uLbaStart=%llu cSectorTransfer=%u\n",
476 __FUNCTION__, uLbaStart, cSectorTransfer));
477
478 if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunSbc->cSectors))
479 {
480 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00);
481 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
482 }
483 else
484 {
485 /* Enqueue new I/O request */
486 rc = vscsiIoReqTransferEnqueue(pVScsiLun, pVScsiReq, enmTxDir,
487 uLbaStart * 512, cSectorTransfer * 512);
488 }
489 }
490 else if (pVScsiReq->pbCDB[0] == SCSI_SYNCHRONIZE_CACHE)
491 {
492 /* Enqueue flush */
493 rc = vscsiIoReqFlushEnqueue(pVScsiLun, pVScsiReq);
494 }
495 else if (pVScsiReq->pbCDB[0] != SCSI_UNMAP) /* Request completed */
496 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
497
498 return rc;
499}
500
501VSCSILUNDESC g_VScsiLunTypeSbc =
502{
503 /** enmLunType */
504 VSCSILUNTYPE_SBC,
505 /** pcszDescName */
506 "SBC",
507 /** cbLun */
508 sizeof(VSCSILUNSBC),
509 /** pfnVScsiLunInit */
510 vscsiLunSbcInit,
511 /** pfnVScsiLunDestroy */
512 vscsiLunSbcDestroy,
513 /** pfnVScsiLunReqProcess */
514 vscsiLunSbcReqProcess
515};
516
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