VirtualBox

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

Last change on this file since 27653 was 27653, checked in by vboxsync, 15 years ago

VSCSI: New SCSI interpreter component which will replace the old stuff in DrvSCSI

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1/* $Id: VSCSILunSbc.cpp 27653 2010-03-23 23:28:26Z vboxsync $ */
2/** @file
3 * Virtual SCSI driver: SBC LUN implementation (hard disks)
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_VSCSI
26#include <VBox/log.h>
27#include <VBox/err.h>
28#include <VBox/types.h>
29#include <VBox/vscsi.h>
30#include <iprt/assert.h>
31#include <iprt/mem.h>
32#include <iprt/string.h>
33
34#include "VSCSIInternal.h"
35
36/**
37 * SBC LUN instance
38 */
39typedef struct VSCSILUNSBC
40{
41 /** Core LUN structure */
42 VSCSILUNINT Core;
43 /** Size of the virtual disk. */
44 uint64_t cSectors;
45} VSCSILUNSBC;
46/** Pointer to a SBC LUN instance */
47typedef VSCSILUNSBC *PVSCSILUNSBC;
48
49static int vscsiLunSbcInit(PVSCSILUNINT pVScsiLun)
50{
51 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
52 uint64_t cbDisk = 0;
53 int rc = VINF_SUCCESS;
54
55 rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk);
56 if (RT_SUCCESS(rc))
57 pVScsiLunSbc->cSectors = cbDisk / 512; /* Fixed sector size */
58
59 return rc;
60}
61
62static int vscsiLunSbcDestroy(PVSCSILUNINT pVScsiLun)
63{
64 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
65
66 return VINF_SUCCESS;
67}
68
69static int vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
70{
71 PVSCSILUNSBC pVScsiLunSbc = (PVSCSILUNSBC)pVScsiLun;
72 int rc = VINF_SUCCESS;
73 int rcReq = SCSI_STATUS_OK;
74 uint64_t uLbaStart = 0;
75 uint32_t cSectorTransfer = 0;
76 VSCSIIOREQTXDIR enmTxDir = VSCSIIOREQTXDIR_INVALID;
77
78 switch(pVScsiReq->pbCDB[0])
79 {
80 case SCSI_INQUIRY:
81 {
82 SCSIINQUIRYDATA ScsiInquiryReply;
83
84 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
85
86 ScsiInquiryReply.cbAdditional = 31;
87 ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS;
88 ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED;
89 ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */
90 vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8);
91 vscsiPadStr(ScsiInquiryReply.achProductId, "HARDDISK", 16);
92 vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4);
93
94 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA));
95 rcReq = vscsiReqSenseOkSet(pVScsiReq);
96 break;
97 }
98 case SCSI_READ_CAPACITY:
99 {
100 uint8_t aReply[8];
101 memset(aReply, 0, sizeof(aReply));
102
103 /*
104 * If sector size exceeds the maximum value that is
105 * able to be stored in 4 bytes return 0xffffffff in this field
106 */
107 if (pVScsiLunSbc->cSectors > UINT32_C(0xffffffff))
108 vscsiH2BEU32(aReply, UINT32_C(0xffffffff));
109 else
110 vscsiH2BEU32(aReply, pVScsiLunSbc->cSectors - 1);
111 vscsiH2BEU32(&aReply[4], 512);
112 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, aReply, sizeof(aReply));
113 rcReq = vscsiReqSenseOkSet(pVScsiReq);
114 break;
115 }
116 case SCSI_MODE_SENSE_6:
117 {
118 uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f;
119 uint8_t aReply[24];
120 uint8_t *pu8ReplyPos;
121
122 memset(aReply, 0, sizeof(aReply));
123 aReply[0] = 4; /* Reply length 4. */
124 aReply[1] = 0; /* Default media type. */
125 aReply[2] = RT_BIT(4); /* Caching supported. */
126 aReply[3] = 0; /* Block descriptor length. */
127
128 pu8ReplyPos = aReply + 4;
129
130 if ((uModePage == 0x08) || (uModePage == 0x3f))
131 {
132 memset(pu8ReplyPos, 0, 20);
133 *pu8ReplyPos++ = 0x08; /* Page code. */
134 *pu8ReplyPos++ = 0x12; /* Size of the page. */
135 *pu8ReplyPos++ = 0x4; /* Write cache enabled. */
136 }
137
138 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, aReply, sizeof(aReply));
139 rcReq = vscsiReqSenseOkSet(pVScsiReq);
140 break;
141 }
142 case SCSI_READ_6:
143 {
144 enmTxDir = VSCSIIOREQTXDIR_READ;
145 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
146 | (pVScsiReq->pbCDB[2] << 8)
147 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
148 cSectorTransfer = pVScsiReq->pbCDB[4];
149 break;
150 }
151 case SCSI_READ_10:
152 {
153 enmTxDir = VSCSIIOREQTXDIR_READ;
154 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
155 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
156 break;
157 }
158 case SCSI_READ_12:
159 {
160 enmTxDir = VSCSIIOREQTXDIR_READ;
161 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
162 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
163 break;
164 }
165 case SCSI_READ_16:
166 {
167 enmTxDir = VSCSIIOREQTXDIR_READ;
168 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
169 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
170 break;
171 }
172 case SCSI_WRITE_6:
173 {
174 enmTxDir = VSCSIIOREQTXDIR_WRITE;
175 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3]
176 | (pVScsiReq->pbCDB[2] << 8)
177 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16));
178 cSectorTransfer = pVScsiReq->pbCDB[4];
179 break;
180 }
181 case SCSI_WRITE_10:
182 {
183 enmTxDir = VSCSIIOREQTXDIR_WRITE;
184 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
185 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
186 break;
187 }
188 case SCSI_WRITE_12:
189 {
190 enmTxDir = VSCSIIOREQTXDIR_WRITE;
191 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]);
192 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]);
193 break;
194 }
195 case SCSI_WRITE_16:
196 {
197 enmTxDir = VSCSIIOREQTXDIR_WRITE;
198 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]);
199 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]);
200 break;
201 }
202 case SCSI_SYNCHRONIZE_CACHE:
203 {
204 break; /* Handled below */
205 }
206 case SCSI_READ_BUFFER:
207 {
208 uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
209
210 switch (uDataMode)
211 {
212 case 0x00:
213 case 0x01:
214 case 0x02:
215 case 0x03:
216 case 0x0a:
217 break;
218 case 0x0b:
219 {
220 uint8_t aReply[4];
221
222 /* We do not implement an echo buffer. */
223 memset(aReply, 0, sizeof(aReply));
224
225 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, aReply, sizeof(aReply));
226 rcReq = vscsiReqSenseOkSet(pVScsiReq);
227 break;
228 }
229 case 0x1a:
230 case 0x1c:
231 break;
232 default:
233 AssertMsgFailed(("Invalid data mode\n"));
234 }
235 break;
236 }
237 case SCSI_START_STOP_UNIT:
238 {
239 rcReq = vscsiReqSenseOkSet(pVScsiReq);
240 break;
241 }
242 case SCSI_LOG_SENSE:
243 {
244 uint16_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
245 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
246 uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
247
248 switch (uPageCode)
249 {
250 case 0x00:
251 {
252 if (uSubPageCode == 0)
253 {
254 uint8_t aReply[4];
255
256 aReply[0] = 0;
257 aReply[1] = 0;
258 aReply[2] = 0;
259 aReply[3] = 0;
260 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, aReply, sizeof(aReply));
261 rcReq = vscsiReqSenseOkSet(pVScsiReq);
262 break;
263 }
264 }
265 default:
266 rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
267 }
268 break;
269 }
270 case SCSI_SERVICE_ACTION_IN_16:
271 {
272 switch (pVScsiReq->pbCDB[1] & 0x1f)
273 {
274 case SCSI_SVC_ACTION_IN_READ_CAPACITY_16:
275 {
276 uint8_t aReply[32];
277
278 memset(aReply, 0, sizeof(aReply));
279 vscsiH2BEU64(aReply, pVScsiLunSbc->cSectors - 1);
280 vscsiH2BEU32(&aReply[8], 512);
281 /* Leave the rest 0 */
282
283 vscsiCopyToIoMemCtx(&pVScsiReq->IoMemCtx, aReply, sizeof(aReply));
284 rcReq = vscsiReqSenseOkSet(pVScsiReq);
285 break;
286 }
287 default:
288 rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); /* Don't know if this is correct */
289 }
290 break;
291 }
292 default:
293 //AssertMsgFailed(("Command %#x [%s] not implemented\n", pRequest->pbCDB[0], SCSICmdText(pRequest->pbCDB[0])));
294 rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
295 }
296
297 if (enmTxDir != VSCSIIOREQTXDIR_INVALID)
298 {
299 LogFlow(("%s: uLbaStart=%llu cSectorTransfer=%u\n",
300 __FUNCTION__, uLbaStart, cSectorTransfer));
301
302 if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunSbc->cSectors))
303 {
304 rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
305 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
306 }
307 else
308 {
309 /* Enqueue new I/O request */
310 rc = vscsiIoReqTransferEnqueue(pVScsiLun, pVScsiReq, enmTxDir,
311 uLbaStart * 512, cSectorTransfer * 512);
312 }
313 }
314 else if (pVScsiReq->pbCDB[0] == SCSI_SYNCHRONIZE_CACHE)
315 {
316 /* Enqueue flush */
317 rc = vscsiIoReqFlushEnqueue(pVScsiLun, pVScsiReq);
318 }
319 else /* Request completed */
320 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
321
322 return rc;
323}
324
325VSCSILUNDESC g_VScsiLunTypeSbc =
326{
327 /** enmLunType */
328 VSCSILUNTYPE_SBC,
329 /** pcszDescName */
330 "SBC",
331 /** cbLun */
332 sizeof(VSCSILUNSBC),
333 /** pfnVScsiLunInit */
334 vscsiLunSbcInit,
335 /** pfnVScsiLunDestroy */
336 vscsiLunSbcDestroy,
337 /** pfnVScsiLunReqProcess */
338 vscsiLunSbcReqProcess
339};
340
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