188455ec4SChristoph Hellwig /*
288455ec4SChristoph Hellwig  * SCSI Primary Commands (SPC) parsing and emulation.
388455ec4SChristoph Hellwig  *
488455ec4SChristoph Hellwig  * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
588455ec4SChristoph Hellwig  * Copyright (c) 2005, 2006, 2007 SBE, Inc.
688455ec4SChristoph Hellwig  * Copyright (c) 2007-2010 Rising Tide Systems
788455ec4SChristoph Hellwig  * Copyright (c) 2008-2010 Linux-iSCSI.org
888455ec4SChristoph Hellwig  *
988455ec4SChristoph Hellwig  * Nicholas A. Bellinger <nab@kernel.org>
1088455ec4SChristoph Hellwig  *
1188455ec4SChristoph Hellwig  * This program is free software; you can redistribute it and/or modify
1288455ec4SChristoph Hellwig  * it under the terms of the GNU General Public License as published by
1388455ec4SChristoph Hellwig  * the Free Software Foundation; either version 2 of the License, or
1488455ec4SChristoph Hellwig  * (at your option) any later version.
1588455ec4SChristoph Hellwig  *
1688455ec4SChristoph Hellwig  * This program is distributed in the hope that it will be useful,
1788455ec4SChristoph Hellwig  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1888455ec4SChristoph Hellwig  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1988455ec4SChristoph Hellwig  * GNU General Public License for more details.
2088455ec4SChristoph Hellwig  *
2188455ec4SChristoph Hellwig  * You should have received a copy of the GNU General Public License
2288455ec4SChristoph Hellwig  * along with this program; if not, write to the Free Software
2388455ec4SChristoph Hellwig  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2488455ec4SChristoph Hellwig  */
2588455ec4SChristoph Hellwig 
2688455ec4SChristoph Hellwig #include <linux/kernel.h>
2788455ec4SChristoph Hellwig #include <linux/module.h>
2888455ec4SChristoph Hellwig #include <asm/unaligned.h>
2988455ec4SChristoph Hellwig 
3088455ec4SChristoph Hellwig #include <scsi/scsi.h>
3188455ec4SChristoph Hellwig #include <scsi/scsi_tcq.h>
3288455ec4SChristoph Hellwig 
3388455ec4SChristoph Hellwig #include <target/target_core_base.h>
3488455ec4SChristoph Hellwig #include <target/target_core_backend.h>
3588455ec4SChristoph Hellwig #include <target/target_core_fabric.h>
3688455ec4SChristoph Hellwig 
3788455ec4SChristoph Hellwig #include "target_core_internal.h"
3888455ec4SChristoph Hellwig #include "target_core_pr.h"
3988455ec4SChristoph Hellwig #include "target_core_ua.h"
4088455ec4SChristoph Hellwig 
4188455ec4SChristoph Hellwig 
4288455ec4SChristoph Hellwig int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough)
4388455ec4SChristoph Hellwig {
4488455ec4SChristoph Hellwig 	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
4588455ec4SChristoph Hellwig 	unsigned char *cdb = cmd->t_task_cdb;
4688455ec4SChristoph Hellwig 
4788455ec4SChristoph Hellwig 	switch (cdb[0]) {
4888455ec4SChristoph Hellwig 	case MODE_SELECT:
4988455ec4SChristoph Hellwig 		*size = cdb[4];
5088455ec4SChristoph Hellwig 		break;
5188455ec4SChristoph Hellwig 	case MODE_SELECT_10:
5288455ec4SChristoph Hellwig 		*size = (cdb[7] << 8) + cdb[8];
5388455ec4SChristoph Hellwig 		break;
5488455ec4SChristoph Hellwig 	case MODE_SENSE:
5588455ec4SChristoph Hellwig 		*size = cdb[4];
5688455ec4SChristoph Hellwig 		if (!passthrough)
5788455ec4SChristoph Hellwig 			cmd->execute_cmd = target_emulate_modesense;
5888455ec4SChristoph Hellwig 		break;
5988455ec4SChristoph Hellwig 	case MODE_SENSE_10:
6088455ec4SChristoph Hellwig 		*size = (cdb[7] << 8) + cdb[8];
6188455ec4SChristoph Hellwig 		if (!passthrough)
6288455ec4SChristoph Hellwig 			cmd->execute_cmd = target_emulate_modesense;
6388455ec4SChristoph Hellwig 		break;
6488455ec4SChristoph Hellwig 	case LOG_SELECT:
6588455ec4SChristoph Hellwig 	case LOG_SENSE:
6688455ec4SChristoph Hellwig 		*size = (cdb[7] << 8) + cdb[8];
6788455ec4SChristoph Hellwig 		break;
6888455ec4SChristoph Hellwig 	case PERSISTENT_RESERVE_IN:
6988455ec4SChristoph Hellwig 		if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
7088455ec4SChristoph Hellwig 			cmd->execute_cmd = target_scsi3_emulate_pr_in;
7188455ec4SChristoph Hellwig 		*size = (cdb[7] << 8) + cdb[8];
7288455ec4SChristoph Hellwig 		break;
7388455ec4SChristoph Hellwig 	case PERSISTENT_RESERVE_OUT:
7488455ec4SChristoph Hellwig 		if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
7588455ec4SChristoph Hellwig 			cmd->execute_cmd = target_scsi3_emulate_pr_out;
7688455ec4SChristoph Hellwig 		*size = (cdb[7] << 8) + cdb[8];
7788455ec4SChristoph Hellwig 		break;
7888455ec4SChristoph Hellwig 	case RELEASE:
7988455ec4SChristoph Hellwig 	case RELEASE_10:
8088455ec4SChristoph Hellwig 		if (cdb[0] == RELEASE_10)
8188455ec4SChristoph Hellwig 			*size = (cdb[7] << 8) | cdb[8];
8288455ec4SChristoph Hellwig 		else
8388455ec4SChristoph Hellwig 			*size = cmd->data_length;
8488455ec4SChristoph Hellwig 
8588455ec4SChristoph Hellwig 		if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
8688455ec4SChristoph Hellwig 			cmd->execute_cmd = target_scsi2_reservation_release;
8788455ec4SChristoph Hellwig 		break;
8888455ec4SChristoph Hellwig 	case RESERVE:
8988455ec4SChristoph Hellwig 	case RESERVE_10:
9088455ec4SChristoph Hellwig 		/*
9188455ec4SChristoph Hellwig 		 * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
9288455ec4SChristoph Hellwig 		 * Assume the passthrough or $FABRIC_MOD will tell us about it.
9388455ec4SChristoph Hellwig 		 */
9488455ec4SChristoph Hellwig 		if (cdb[0] == RESERVE_10)
9588455ec4SChristoph Hellwig 			*size = (cdb[7] << 8) | cdb[8];
9688455ec4SChristoph Hellwig 		else
9788455ec4SChristoph Hellwig 			*size = cmd->data_length;
9888455ec4SChristoph Hellwig 
9988455ec4SChristoph Hellwig 		/*
10088455ec4SChristoph Hellwig 		 * Setup the legacy emulated handler for SPC-2 and
10188455ec4SChristoph Hellwig 		 * >= SPC-3 compatible reservation handling (CRH=1)
10288455ec4SChristoph Hellwig 		 * Otherwise, we assume the underlying SCSI logic is
10388455ec4SChristoph Hellwig 		 * is running in SPC_PASSTHROUGH, and wants reservations
10488455ec4SChristoph Hellwig 		 * emulation disabled.
10588455ec4SChristoph Hellwig 		 */
10688455ec4SChristoph Hellwig 		if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
10788455ec4SChristoph Hellwig 			cmd->execute_cmd = target_scsi2_reservation_reserve;
10888455ec4SChristoph Hellwig 		break;
10988455ec4SChristoph Hellwig 	case REQUEST_SENSE:
11088455ec4SChristoph Hellwig 		*size = cdb[4];
11188455ec4SChristoph Hellwig 		if (!passthrough)
11288455ec4SChristoph Hellwig 			cmd->execute_cmd = target_emulate_request_sense;
11388455ec4SChristoph Hellwig 		break;
11488455ec4SChristoph Hellwig 	case INQUIRY:
11588455ec4SChristoph Hellwig 		*size = (cdb[3] << 8) + cdb[4];
11688455ec4SChristoph Hellwig 
11788455ec4SChristoph Hellwig 		/*
11888455ec4SChristoph Hellwig 		 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
11988455ec4SChristoph Hellwig 		 * See spc4r17 section 5.3
12088455ec4SChristoph Hellwig 		 */
12188455ec4SChristoph Hellwig 		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
12288455ec4SChristoph Hellwig 			cmd->sam_task_attr = MSG_HEAD_TAG;
12388455ec4SChristoph Hellwig 		if (!passthrough)
12488455ec4SChristoph Hellwig 			cmd->execute_cmd = target_emulate_inquiry;
12588455ec4SChristoph Hellwig 		break;
12688455ec4SChristoph Hellwig 	case SECURITY_PROTOCOL_IN:
12788455ec4SChristoph Hellwig 	case SECURITY_PROTOCOL_OUT:
12888455ec4SChristoph Hellwig 		*size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
12988455ec4SChristoph Hellwig 		break;
13088455ec4SChristoph Hellwig 	case EXTENDED_COPY:
13188455ec4SChristoph Hellwig 	case READ_ATTRIBUTE:
13288455ec4SChristoph Hellwig 	case RECEIVE_COPY_RESULTS:
13388455ec4SChristoph Hellwig 	case WRITE_ATTRIBUTE:
13488455ec4SChristoph Hellwig 		*size = (cdb[10] << 24) | (cdb[11] << 16) |
13588455ec4SChristoph Hellwig 		       (cdb[12] << 8) | cdb[13];
13688455ec4SChristoph Hellwig 		break;
13788455ec4SChristoph Hellwig 	case RECEIVE_DIAGNOSTIC:
13888455ec4SChristoph Hellwig 	case SEND_DIAGNOSTIC:
13988455ec4SChristoph Hellwig 		*size = (cdb[3] << 8) | cdb[4];
14088455ec4SChristoph Hellwig 		break;
14188455ec4SChristoph Hellwig 	case WRITE_BUFFER:
14288455ec4SChristoph Hellwig 		*size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
14388455ec4SChristoph Hellwig 		break;
14488455ec4SChristoph Hellwig 	case REPORT_LUNS:
14588455ec4SChristoph Hellwig 		cmd->execute_cmd = target_report_luns;
14688455ec4SChristoph Hellwig 		*size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
14788455ec4SChristoph Hellwig 		/*
14888455ec4SChristoph Hellwig 		 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
14988455ec4SChristoph Hellwig 		 * See spc4r17 section 5.3
15088455ec4SChristoph Hellwig 		 */
15188455ec4SChristoph Hellwig 		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
15288455ec4SChristoph Hellwig 			cmd->sam_task_attr = MSG_HEAD_TAG;
15388455ec4SChristoph Hellwig 		break;
15488455ec4SChristoph Hellwig 	case TEST_UNIT_READY:
155d6e0175cSChristoph Hellwig 		*size = 0;
15688455ec4SChristoph Hellwig 		if (!passthrough)
15788455ec4SChristoph Hellwig 			cmd->execute_cmd = target_emulate_noop;
15888455ec4SChristoph Hellwig 		break;
15988455ec4SChristoph Hellwig 	default:
16088455ec4SChristoph Hellwig 		pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
16188455ec4SChristoph Hellwig 			" 0x%02x, sending CHECK_CONDITION.\n",
16288455ec4SChristoph Hellwig 			cmd->se_tfo->get_fabric_name(), cdb[0]);
16388455ec4SChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
16488455ec4SChristoph Hellwig 		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
16588455ec4SChristoph Hellwig 		return -EINVAL;
16688455ec4SChristoph Hellwig 	}
16788455ec4SChristoph Hellwig 
16888455ec4SChristoph Hellwig 	return 0;
16988455ec4SChristoph Hellwig }
17088455ec4SChristoph Hellwig EXPORT_SYMBOL(spc_parse_cdb);
171