2 * SCSI Primary Commands (SPC) parsing and emulation.
4 * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
5 * Copyright (c) 2005, 2006, 2007 SBE, Inc.
6 * Copyright (c) 2007-2010 Rising Tide Systems
7 * Copyright (c) 2008-2010 Linux-iSCSI.org
9 * Nicholas A. Bellinger <nab@kernel.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <asm/unaligned.h>
30 #include <scsi/scsi.h>
31 #include <scsi/scsi_tcq.h>
33 #include <target/target_core_base.h>
34 #include <target/target_core_backend.h>
35 #include <target/target_core_fabric.h>
37 #include "target_core_internal.h"
38 #include "target_core_pr.h"
39 #include "target_core_ua.h"
42 int spc_parse_cdb(struct se_cmd
*cmd
, unsigned int *size
, bool passthrough
)
44 struct se_subsystem_dev
*su_dev
= cmd
->se_dev
->se_sub_dev
;
45 unsigned char *cdb
= cmd
->t_task_cdb
;
52 *size
= (cdb
[7] << 8) + cdb
[8];
57 cmd
->execute_cmd
= target_emulate_modesense
;
60 *size
= (cdb
[7] << 8) + cdb
[8];
62 cmd
->execute_cmd
= target_emulate_modesense
;
66 *size
= (cdb
[7] << 8) + cdb
[8];
68 case PERSISTENT_RESERVE_IN
:
69 if (su_dev
->t10_pr
.res_type
== SPC3_PERSISTENT_RESERVATIONS
)
70 cmd
->execute_cmd
= target_scsi3_emulate_pr_in
;
71 *size
= (cdb
[7] << 8) + cdb
[8];
73 case PERSISTENT_RESERVE_OUT
:
74 if (su_dev
->t10_pr
.res_type
== SPC3_PERSISTENT_RESERVATIONS
)
75 cmd
->execute_cmd
= target_scsi3_emulate_pr_out
;
76 *size
= (cdb
[7] << 8) + cdb
[8];
80 if (cdb
[0] == RELEASE_10
)
81 *size
= (cdb
[7] << 8) | cdb
[8];
83 *size
= cmd
->data_length
;
85 if (su_dev
->t10_pr
.res_type
!= SPC_PASSTHROUGH
)
86 cmd
->execute_cmd
= target_scsi2_reservation_release
;
91 * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
92 * Assume the passthrough or $FABRIC_MOD will tell us about it.
94 if (cdb
[0] == RESERVE_10
)
95 *size
= (cdb
[7] << 8) | cdb
[8];
97 *size
= cmd
->data_length
;
100 * Setup the legacy emulated handler for SPC-2 and
101 * >= SPC-3 compatible reservation handling (CRH=1)
102 * Otherwise, we assume the underlying SCSI logic is
103 * is running in SPC_PASSTHROUGH, and wants reservations
104 * emulation disabled.
106 if (su_dev
->t10_pr
.res_type
!= SPC_PASSTHROUGH
)
107 cmd
->execute_cmd
= target_scsi2_reservation_reserve
;
112 cmd
->execute_cmd
= target_emulate_request_sense
;
115 *size
= (cdb
[3] << 8) + cdb
[4];
118 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
119 * See spc4r17 section 5.3
121 if (cmd
->se_dev
->dev_task_attr_type
== SAM_TASK_ATTR_EMULATED
)
122 cmd
->sam_task_attr
= MSG_HEAD_TAG
;
124 cmd
->execute_cmd
= target_emulate_inquiry
;
126 case SECURITY_PROTOCOL_IN
:
127 case SECURITY_PROTOCOL_OUT
:
128 *size
= (cdb
[6] << 24) | (cdb
[7] << 16) | (cdb
[8] << 8) | cdb
[9];
132 case RECEIVE_COPY_RESULTS
:
133 case WRITE_ATTRIBUTE
:
134 *size
= (cdb
[10] << 24) | (cdb
[11] << 16) |
135 (cdb
[12] << 8) | cdb
[13];
137 case RECEIVE_DIAGNOSTIC
:
138 case SEND_DIAGNOSTIC
:
139 *size
= (cdb
[3] << 8) | cdb
[4];
142 *size
= (cdb
[6] << 16) + (cdb
[7] << 8) + cdb
[8];
145 cmd
->execute_cmd
= target_report_luns
;
146 *size
= (cdb
[6] << 24) | (cdb
[7] << 16) | (cdb
[8] << 8) | cdb
[9];
148 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
149 * See spc4r17 section 5.3
151 if (cmd
->se_dev
->dev_task_attr_type
== SAM_TASK_ATTR_EMULATED
)
152 cmd
->sam_task_attr
= MSG_HEAD_TAG
;
154 case TEST_UNIT_READY
:
157 cmd
->execute_cmd
= target_emulate_noop
;
160 pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
161 " 0x%02x, sending CHECK_CONDITION.\n",
162 cmd
->se_tfo
->get_fabric_name(), cdb
[0]);
163 cmd
->se_cmd_flags
|= SCF_SCSI_CDB_EXCEPTION
;
164 cmd
->scsi_sense_reason
= TCM_UNSUPPORTED_SCSI_OPCODE
;
170 EXPORT_SYMBOL(spc_parse_cdb
);