VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp@ 38678

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

VSCSI: Replace I/O memory context with S/G buffers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.0 KB
Line 
1/* $Id: VSCSIIoReq.cpp 38678 2011-09-07 17:33:13Z vboxsync $ */
2/** @file
3 * Virtual SCSI driver: I/O request handling.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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#define LOG_GROUP LOG_GROUP_VSCSI
18#include <VBox/log.h>
19#include <VBox/err.h>
20#include <VBox/types.h>
21#include <VBox/vscsi.h>
22#include <iprt/assert.h>
23#include <iprt/mem.h>
24#include <iprt/asm.h>
25
26#include "VSCSIInternal.h"
27
28int vscsiIoReqFlushEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
29{
30 int rc = VINF_SUCCESS;
31 PVSCSIIOREQINT pVScsiIoReq = NULL;
32
33 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
34 if (!pVScsiIoReq)
35 return VERR_NO_MEMORY;
36
37 pVScsiIoReq->pVScsiReq = pVScsiReq;
38 pVScsiIoReq->pVScsiLun = pVScsiLun;
39 pVScsiIoReq->enmTxDir = VSCSIIOREQTXDIR_FLUSH;
40
41 ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
42
43 rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
44 if (RT_FAILURE(rc))
45 {
46 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
47 RTMemFree(pVScsiIoReq);
48 }
49
50 return rc;
51}
52
53
54int vscsiIoReqTransferEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
55 VSCSIIOREQTXDIR enmTxDir, uint64_t uOffset,
56 size_t cbTransfer)
57{
58 int rc = VINF_SUCCESS;
59 PVSCSIIOREQINT pVScsiIoReq = NULL;
60
61 LogFlowFunc(("pVScsiLun=%#p pVScsiReq=%#p enmTxDir=%u uOffset=%llu cbTransfer=%u\n",
62 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer));
63
64 pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
65 if (!pVScsiIoReq)
66 return VERR_NO_MEMORY;
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;
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
89uint32_t vscsiIoReqOutstandingCountGet(PVSCSILUNINT pVScsiLun)
90{
91 return ASMAtomicReadU32(&pVScsiLun->IoReq.cReqOutstanding);
92}
93
94
95VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible)
96{
97 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
98 PVSCSILUNINT pVScsiLun;
99 PVSCSIREQINT pVScsiReq;
100 int rcReq = SCSI_STATUS_OK;
101
102 AssertPtrReturn(pVScsiIoReq, VERR_INVALID_HANDLE);
103
104 LogFlowFunc(("hVScsiIoReq=%#p rcIoReq=%Rrc\n", hVScsiIoReq, rcIoReq));
105
106 pVScsiLun = pVScsiIoReq->pVScsiLun;
107 pVScsiReq = pVScsiIoReq->pVScsiReq;
108
109 AssertMsg(pVScsiLun->IoReq.cReqOutstanding > 0,
110 ("Unregistered I/O request completed\n"));
111
112 ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
113
114 /** @todo error reporting */
115 if (RT_SUCCESS(rcIoReq))
116 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
117 else if (!fRedoPossible)
118 {
119 /** @todo Not 100% correct for the write case as the 0x00 ASCQ for write errors
120 * is not used for SBC devices. */
121 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_MEDIUM_ERROR,
122 pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ
123 ? SCSI_ASC_READ_ERROR
124 : SCSI_ASC_WRITE_ERROR);
125 }
126 else
127 rcReq = SCSI_STATUS_CHECK_CONDITION;
128
129 /* Free the I/O request */
130 RTMemFree(pVScsiIoReq);
131
132 /* Notify completion of the SCSI request. */
133 vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, fRedoPossible, rcIoReq);
134
135 return VINF_SUCCESS;
136}
137
138
139VBOXDDU_DECL(VSCSIIOREQTXDIR) VSCSIIoReqTxDirGet(VSCSIIOREQ hVScsiIoReq)
140{
141 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
142
143 AssertPtrReturn(pVScsiIoReq, VSCSIIOREQTXDIR_INVALID);
144
145 return pVScsiIoReq->enmTxDir;
146}
147
148
149VBOXDDU_DECL(int) VSCSIIoReqParamsGet(VSCSIIOREQ hVScsiIoReq, uint64_t *puOffset,
150 size_t *pcbTransfer, unsigned *pcSeg,
151 size_t *pcbSeg, PCRTSGSEG *ppaSeg)
152{
153 PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
154
155 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;
163
164 return VINF_SUCCESS;
165}
166
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