1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 __FBSDID("$FreeBSD$"); 57 58 /** 59 * @file 60 * @brief This file contains the implementation to translate 61 * SCSI Write Long 10 and 16 commands based on the SAT spec. 62 */ 63 64 #if !defined(DISABLE_SATI_WRITE_LONG) 65 66 #include <dev/isci/scil/sati_write_long.h> 67 #include <dev/isci/scil/sati_device.h> 68 #include <dev/isci/scil/sati_util.h> 69 #include <dev/isci/scil/intel_scsi.h> 70 #include <dev/isci/scil/intel_ata.h> 71 #include <dev/isci/scil/intel_sat.h> 72 #include <dev/isci/scil/sati_callbacks.h> 73 #include <dev/isci/scil/sati_move.h> 74 75 #define LOGICAL_PER_PHYSICAL_SECTOR 0xF 76 77 #define WR_UNCOR_BIT 0x02 78 #define WR_UNCOR_PBLOCK_BIT 0x03 79 #define COR_DIS_WR_UNCORR_BIT 0x06 80 81 82 /** 83 * @brief This method will translate the write long 10 & 16 SCSI commands into 84 * ATA write uncorrectable commands. For more information on the 85 * parameters passed to this method, please reference 86 * sati_translate_command(). 87 * 88 * @return Indicate if the command translation succeeded. 89 * @retval SCI_SUCCESS This is returned if the command translation was 90 * successful. 91 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was 92 * a problem with the translation of write long. 93 * 94 */ 95 SATI_STATUS sati_write_long_translate_command( 96 SATI_TRANSLATOR_SEQUENCE_T * sequence, 97 void * scsi_io, 98 void * ata_io 99 ) 100 { 101 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 102 SATI_STATUS status = SATI_FAILURE; 103 U16 byte_transfer_length; 104 U8 device_head = 0; 105 106 if((sequence->device->capabilities & 107 SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE) == 0) 108 { 109 sati_scsi_sense_data_construct( 110 sequence, 111 scsi_io, 112 SCSI_STATUS_CHECK_CONDITION, 113 SCSI_SENSE_ILLEGAL_REQUEST, 114 SCSI_ASC_INVALID_COMMAND_OPERATION_CODE, 115 SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 116 ); 117 return SATI_FAILURE_CHECK_RESPONSE_DATA; 118 } 119 120 //Write Long 10 121 if(sati_get_cdb_byte(cdb, 0) == SCSI_WRITE_LONG_10) 122 { 123 byte_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) | 124 (sati_get_cdb_byte(cdb, 8)); 125 126 sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io); 127 } 128 else //Write Long 16 129 { 130 byte_transfer_length = (sati_get_cdb_byte(cdb, 12) << 8) | 131 (sati_get_cdb_byte(cdb, 13)); 132 133 status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io); 134 135 if( status == SATI_FAILURE_CHECK_RESPONSE_DATA) 136 { 137 return status; 138 } 139 } 140 141 142 sati_move_translate_command(sequence, scsi_io, ata_io, device_head); 143 144 if( byte_transfer_length != 0 ) 145 { 146 sati_scsi_sense_data_construct( 147 sequence, 148 scsi_io, 149 SCSI_STATUS_CHECK_CONDITION, 150 SCSI_SENSE_ILLEGAL_REQUEST, 151 SCSI_ASC_INVALID_FIELD_IN_CDB, 152 SCSI_ASCQ_INVALID_FIELD_IN_CDB 153 ); 154 return SATI_FAILURE_CHECK_RESPONSE_DATA; 155 } 156 157 switch(SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb)) 158 { 159 case WR_UNCOR_BIT : 160 161 if( (sequence->device->capabilities & 162 SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR) != 0 ) 163 { 164 sati_scsi_sense_data_construct( 165 sequence, 166 scsi_io, 167 SCSI_STATUS_CHECK_CONDITION, 168 SCSI_SENSE_ILLEGAL_REQUEST, 169 SCSI_ASC_INVALID_FIELD_IN_CDB, 170 SCSI_ASCQ_INVALID_FIELD_IN_CDB 171 ); 172 return SATI_FAILURE_CHECK_RESPONSE_DATA; 173 } 174 else 175 { 176 sati_ata_write_uncorrectable_construct( 177 ata_io, 178 sequence, 179 ATA_WRITE_UNCORRECTABLE_PSEUDO 180 ); 181 sequence->type = SATI_SEQUENCE_WRITE_LONG; 182 status = SATI_SUCCESS; 183 } 184 break; 185 186 case WR_UNCOR_PBLOCK_BIT : 187 188 sati_ata_write_uncorrectable_construct( 189 ata_io, 190 sequence, 191 ATA_WRITE_UNCORRECTABLE_PSEUDO 192 ); 193 sequence->type = SATI_SEQUENCE_WRITE_LONG; 194 status = SATI_SUCCESS; 195 break; 196 197 case COR_DIS_WR_UNCORR_BIT : 198 199 sati_ata_write_uncorrectable_construct( 200 ata_io, 201 sequence, 202 ATA_WRITE_UNCORRECTABLE_FLAGGED 203 ); 204 sequence->type = SATI_SEQUENCE_WRITE_LONG; 205 status = SATI_SUCCESS; 206 break; 207 208 default : 209 210 sati_scsi_sense_data_construct( 211 sequence, 212 scsi_io, 213 SCSI_STATUS_CHECK_CONDITION, 214 SCSI_SENSE_ILLEGAL_REQUEST, 215 SCSI_ASC_INVALID_FIELD_IN_CDB, 216 SCSI_ASCQ_INVALID_FIELD_IN_CDB 217 ); 218 return SATI_FAILURE_CHECK_RESPONSE_DATA; 219 break; 220 } 221 return status; 222 } 223 224 /** 225 * @brief This method will translate the response to the SATI Write Long 226 * translation. This response is only error checking the 227 * ATA Write Uncorrectable command. 228 * 229 * @return SATI_STATUS Indicates if the response translation succeeded. 230 * @retval SCI_COMPLETE This is returned if the command translation was 231 * successful. 232 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was 233 * a problem with the translation of write long. 234 */ 235 SATI_STATUS sati_write_long_translate_response( 236 SATI_TRANSLATOR_SEQUENCE_T * sequence, 237 void * scsi_io, 238 void * ata_io 239 ) 240 { 241 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 242 243 if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 244 { 245 sati_scsi_sense_data_construct( 246 sequence, 247 scsi_io, 248 SCSI_STATUS_CHECK_CONDITION, 249 SCSI_SENSE_ABORTED_COMMAND, 250 SCSI_ASC_COMMAND_SEQUENCE_ERROR, 251 SCSI_ASCQ_NO_ADDITIONAL_SENSE 252 ); 253 return SATI_FAILURE_CHECK_RESPONSE_DATA; 254 } 255 else 256 { 257 return SATI_COMPLETE; 258 } 259 } 260 261 #endif // !defined(DISABLE_SATI_WRITE_LONG) 262