4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5 * Copyright (c) Intel Corporation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "scsi_internal.h"
36 #include "spdk/endian.h"
38 #include "spdk/util.h"
41 spdk_scsi_task_free_data(struct spdk_scsi_task
*task
);
44 spdk_scsi_task_put(struct spdk_scsi_task
*task
)
53 struct spdk_bdev_io
*bdev_io
= task
->bdev_io
;
56 spdk_bdev_free_io(bdev_io
);
59 spdk_scsi_task_free_data(task
);
66 spdk_scsi_task_construct(struct spdk_scsi_task
*task
,
67 spdk_scsi_task_cpl cpl_fn
,
68 spdk_scsi_task_free free_fn
)
71 assert(cpl_fn
!= NULL
);
72 assert(free_fn
!= NULL
);
74 task
->cpl_fn
= cpl_fn
;
75 task
->free_fn
= free_fn
;
80 * Pre-fill the iov_buffers to point to the embedded iov
82 assert(task
->iov
.iov_base
== NULL
);
83 task
->iovs
= &task
->iov
;
88 spdk_scsi_task_free_data(struct spdk_scsi_task
*task
)
90 if (task
->alloc_len
!= 0) {
91 spdk_dma_free(task
->iov
.iov_base
);
95 task
->iov
.iov_base
= NULL
;
96 task
->iov
.iov_len
= 0;
100 spdk_scsi_task_alloc_data(struct spdk_scsi_task
*task
, uint32_t alloc_len
)
102 assert(task
->alloc_len
== 0);
104 task
->iov
.iov_base
= spdk_dma_zmalloc(alloc_len
, 0, NULL
);
105 task
->iov
.iov_len
= alloc_len
;
106 task
->alloc_len
= alloc_len
;
108 return task
->iov
.iov_base
;
112 spdk_scsi_task_scatter_data(struct spdk_scsi_task
*task
, const void *src
, size_t buf_len
)
115 size_t buf_left
= buf_len
;
117 struct iovec
*iovs
= task
->iovs
;
124 if (task
->iovcnt
== 1 && iovs
[0].iov_base
== NULL
) {
125 spdk_scsi_task_alloc_data(task
, buf_len
);
129 for (i
= 0; i
< task
->iovcnt
; i
++) {
130 assert(iovs
[i
].iov_base
!= NULL
);
131 len
+= iovs
[i
].iov_len
;
135 spdk_scsi_task_set_status(task
, SPDK_SCSI_STATUS_CHECK_CONDITION
,
136 SPDK_SCSI_SENSE_ILLEGAL_REQUEST
,
137 SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB
,
138 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE
);
144 for (i
= 0; i
< task
->iovcnt
; i
++) {
145 len
= spdk_min(iovs
[i
].iov_len
, buf_left
);
147 memcpy(iovs
[i
].iov_base
, pos
, len
);
155 spdk_scsi_task_gather_data(struct spdk_scsi_task
*task
, int *len
)
158 struct iovec
*iovs
= task
->iovs
;
162 for (i
= 0; i
< task
->iovcnt
; i
++) {
163 assert(iovs
[i
].iov_base
!= NULL
);
164 buf_len
+= iovs
[i
].iov_len
;
172 buf
= spdk_dma_malloc(buf_len
, 0, NULL
);
179 for (i
= 0; i
< task
->iovcnt
; i
++) {
180 memcpy(pos
, iovs
[i
].iov_base
, iovs
[i
].iov_len
);
181 pos
+= iovs
[i
].iov_len
;
189 spdk_scsi_task_set_data(struct spdk_scsi_task
*task
, void *data
, uint32_t len
)
191 assert(task
->iovcnt
== 1);
192 assert(task
->alloc_len
== 0);
194 task
->iovs
[0].iov_base
= data
;
195 task
->iovs
[0].iov_len
= len
;
199 spdk_scsi_task_build_sense_data(struct spdk_scsi_task
*task
, int sk
, int asc
, int ascq
)
204 resp_code
= 0x70; /* Current + Fixed format */
207 cp
= task
->sense_data
;
209 /* VALID(7) RESPONSE CODE(6-0) */
210 cp
[0] = 0x80 | resp_code
;
213 /* FILEMARK(7) EOM(6) ILI(5) SENSE KEY(3-0) */
216 memset(&cp
[3], 0, 4);
218 /* ADDITIONAL SENSE LENGTH */
221 /* COMMAND-SPECIFIC INFORMATION */
222 memset(&cp
[8], 0, 4);
223 /* ADDITIONAL SENSE CODE */
225 /* ADDITIONAL SENSE CODE QUALIFIER */
227 /* FIELD REPLACEABLE UNIT CODE */
230 /* SKSV(7) SENSE KEY SPECIFIC(6-0,7-0,7-0) */
236 task
->sense_data_len
= 18;
240 spdk_scsi_task_set_status(struct spdk_scsi_task
*task
, int sc
, int sk
,
243 if (sc
== SPDK_SCSI_STATUS_CHECK_CONDITION
) {
244 spdk_scsi_task_build_sense_data(task
, sk
, asc
, ascq
);
250 spdk_scsi_task_copy_status(struct spdk_scsi_task
*dst
,
251 struct spdk_scsi_task
*src
)
253 memcpy(dst
->sense_data
, src
->sense_data
, src
->sense_data_len
);
254 dst
->sense_data_len
= src
->sense_data_len
;
255 dst
->status
= src
->status
;