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"
40 spdk_scsi_task_put(struct spdk_scsi_task
*task
)
49 struct spdk_bdev_io
*bdev_io
= task
->blockdev_io
;
52 spdk_scsi_task_put(task
->parent
);
57 /* due to lun reset, the bdev_io status could be pending */
58 if (bdev_io
->status
== SPDK_BDEV_IO_STATUS_PENDING
) {
59 bdev_io
->status
= SPDK_BDEV_IO_STATUS_FAILED
;
61 spdk_bdev_free_io(bdev_io
);
64 spdk_scsi_task_free_data(task
);
65 assert(task
->owner_task_ctr
!= NULL
);
67 if (*(task
->owner_task_ctr
) > 0) {
68 *(task
->owner_task_ctr
) -= 1;
70 SPDK_ERRLOG("task counter already 0\n");
78 spdk_scsi_task_construct(struct spdk_scsi_task
*task
, uint32_t *owner_task_ctr
,
79 struct spdk_scsi_task
*parent
)
83 assert(owner_task_ctr
!= NULL
);
84 task
->owner_task_ctr
= owner_task_ctr
;
88 * Pre-fill the iov_buffers to point to the embedded iov
90 assert(task
->iov
.iov_base
== NULL
);
91 task
->iovs
= &task
->iov
;
96 task
->parent
= parent
;
97 task
->type
= parent
->type
;
98 task
->dxfer_dir
= parent
->dxfer_dir
;
99 task
->transfer_len
= parent
->transfer_len
;
100 task
->lun
= parent
->lun
;
101 task
->cdb
= parent
->cdb
;
102 task
->target_port
= parent
->target_port
;
103 task
->initiator_port
= parent
->initiator_port
;
104 task
->id
= parent
->id
;
109 spdk_scsi_task_free_data(struct spdk_scsi_task
*task
)
111 if (task
->alloc_len
!= 0) {
112 spdk_free(task
->iov
.iov_base
);
116 task
->iov
.iov_base
= NULL
;
117 task
->iov
.iov_len
= 0;
121 spdk_scsi_task_alloc_data(struct spdk_scsi_task
*task
, uint32_t alloc_len
)
123 assert(task
->alloc_len
== 0);
125 task
->iov
.iov_base
= spdk_zmalloc(alloc_len
, 0, NULL
);
126 task
->iov
.iov_len
= alloc_len
;
127 task
->alloc_len
= alloc_len
;
129 return task
->iov
.iov_base
;
133 spdk_scsi_task_scatter_data(struct spdk_scsi_task
*task
, const void *src
, size_t buf_len
)
136 size_t buf_left
= buf_len
;
138 struct iovec
*iovs
= task
->iovs
;
144 if (task
->iovcnt
== 1 && iovs
[0].iov_base
== NULL
) {
145 spdk_scsi_task_alloc_data(task
, buf_len
);
149 for (i
= 0; i
< task
->iovcnt
; i
++) {
150 assert(iovs
[i
].iov_base
!= NULL
);
151 len
+= iovs
[i
].iov_len
;
155 spdk_scsi_task_set_status(task
, SPDK_SCSI_STATUS_CHECK_CONDITION
,
156 SPDK_SCSI_SENSE_ILLEGAL_REQUEST
,
157 SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB
,
158 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE
);
164 for (i
= 0; i
< task
->iovcnt
; i
++) {
165 len
= SPDK_MIN(iovs
[i
].iov_len
, buf_left
);
167 memcpy(iovs
[i
].iov_base
, pos
, len
);
175 spdk_scsi_task_gather_data(struct spdk_scsi_task
*task
, int *len
)
178 struct iovec
*iovs
= task
->iovs
;
182 for (i
= 0; i
< task
->iovcnt
; i
++) {
183 assert(iovs
[i
].iov_base
!= NULL
);
184 buf_len
+= iovs
[i
].iov_len
;
192 buf
= spdk_malloc(buf_len
, 0, NULL
);
199 for (i
= 0; i
< task
->iovcnt
; i
++) {
200 memcpy(pos
, iovs
[i
].iov_base
, iovs
[i
].iov_len
);
201 pos
+= iovs
[i
].iov_len
;
209 spdk_scsi_task_set_data(struct spdk_scsi_task
*task
, void *data
, uint32_t len
)
211 assert(task
->iovcnt
== 1);
212 assert(task
->alloc_len
== 0);
214 task
->iovs
[0].iov_base
= data
;
215 task
->iovs
[0].iov_len
= len
;
219 spdk_scsi_task_build_sense_data(struct spdk_scsi_task
*task
, int sk
, int asc
, int ascq
)
224 resp_code
= 0x70; /* Current + Fixed format */
227 cp
= task
->sense_data
;
229 /* VALID(7) RESPONSE CODE(6-0) */
230 cp
[0] = 0x80 | resp_code
;
233 /* FILEMARK(7) EOM(6) ILI(5) SENSE KEY(3-0) */
236 memset(&cp
[3], 0, 4);
238 /* ADDITIONAL SENSE LENGTH */
241 /* COMMAND-SPECIFIC INFORMATION */
242 memset(&cp
[8], 0, 4);
243 /* ADDITIONAL SENSE CODE */
245 /* ADDITIONAL SENSE CODE QUALIFIER */
247 /* FIELD REPLACEABLE UNIT CODE */
250 /* SKSV(7) SENSE KEY SPECIFIC(6-0,7-0,7-0) */
256 task
->sense_data_len
= 18;
260 spdk_scsi_task_set_status(struct spdk_scsi_task
*task
, int sc
, int sk
,
263 if (sc
== SPDK_SCSI_STATUS_CHECK_CONDITION
) {
264 spdk_scsi_task_build_sense_data(task
, sk
, asc
, ascq
);