]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/target/target_core_spc.c
target: add a parse_cdb method to the backend drivers
[mirror_ubuntu-hirsute-kernel.git] / drivers / target / target_core_spc.c
CommitLineData
88455ec4
CH
1/*
2 * SCSI Primary Commands (SPC) parsing and emulation.
3 *
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
8 *
9 * Nicholas A. Bellinger <nab@kernel.org>
10 *
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.
15 *
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.
20 *
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.
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <asm/unaligned.h>
29
30#include <scsi/scsi.h>
31#include <scsi/scsi_tcq.h>
32
33#include <target/target_core_base.h>
34#include <target/target_core_backend.h>
35#include <target/target_core_fabric.h>
36
37#include "target_core_internal.h"
38#include "target_core_pr.h"
39#include "target_core_ua.h"
40
41
42int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough)
43{
44 struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
45 unsigned char *cdb = cmd->t_task_cdb;
46
47 switch (cdb[0]) {
48 case MODE_SELECT:
49 *size = cdb[4];
50 break;
51 case MODE_SELECT_10:
52 *size = (cdb[7] << 8) + cdb[8];
53 break;
54 case MODE_SENSE:
55 *size = cdb[4];
56 if (!passthrough)
57 cmd->execute_cmd = target_emulate_modesense;
58 break;
59 case MODE_SENSE_10:
60 *size = (cdb[7] << 8) + cdb[8];
61 if (!passthrough)
62 cmd->execute_cmd = target_emulate_modesense;
63 break;
64 case LOG_SELECT:
65 case LOG_SENSE:
66 *size = (cdb[7] << 8) + cdb[8];
67 break;
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];
72 break;
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];
77 break;
78 case RELEASE:
79 case RELEASE_10:
80 if (cdb[0] == RELEASE_10)
81 *size = (cdb[7] << 8) | cdb[8];
82 else
83 *size = cmd->data_length;
84
85 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
86 cmd->execute_cmd = target_scsi2_reservation_release;
87 break;
88 case RESERVE:
89 case RESERVE_10:
90 /*
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.
93 */
94 if (cdb[0] == RESERVE_10)
95 *size = (cdb[7] << 8) | cdb[8];
96 else
97 *size = cmd->data_length;
98
99 /*
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.
105 */
106 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
107 cmd->execute_cmd = target_scsi2_reservation_reserve;
108 break;
109 case REQUEST_SENSE:
110 *size = cdb[4];
111 if (!passthrough)
112 cmd->execute_cmd = target_emulate_request_sense;
113 break;
114 case INQUIRY:
115 *size = (cdb[3] << 8) + cdb[4];
116
117 /*
118 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
119 * See spc4r17 section 5.3
120 */
121 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
122 cmd->sam_task_attr = MSG_HEAD_TAG;
123 if (!passthrough)
124 cmd->execute_cmd = target_emulate_inquiry;
125 break;
126 case SECURITY_PROTOCOL_IN:
127 case SECURITY_PROTOCOL_OUT:
128 *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
129 break;
130 case EXTENDED_COPY:
131 case READ_ATTRIBUTE:
132 case RECEIVE_COPY_RESULTS:
133 case WRITE_ATTRIBUTE:
134 *size = (cdb[10] << 24) | (cdb[11] << 16) |
135 (cdb[12] << 8) | cdb[13];
136 break;
137 case RECEIVE_DIAGNOSTIC:
138 case SEND_DIAGNOSTIC:
139 *size = (cdb[3] << 8) | cdb[4];
140 break;
141 case WRITE_BUFFER:
142 *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
143 break;
144 case REPORT_LUNS:
145 cmd->execute_cmd = target_report_luns;
146 *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
147 /*
148 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
149 * See spc4r17 section 5.3
150 */
151 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
152 cmd->sam_task_attr = MSG_HEAD_TAG;
153 break;
154 case TEST_UNIT_READY:
d6e0175c 155 *size = 0;
88455ec4
CH
156 if (!passthrough)
157 cmd->execute_cmd = target_emulate_noop;
158 break;
159 default:
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;
165 return -EINVAL;
166 }
167
168 return 0;
169}
170EXPORT_SYMBOL(spc_parse_cdb);