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