1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * @brief This file contains the implementation to translate 59 * SCSI Read Buffer command based on the SAT spec. 60 */ 61 62 #if !defined(DISABLE_SATI_READ_BUFFER) 63 64 #include <dev/isci/scil/sati_read_buffer.h> 65 #include <dev/isci/scil/sati_callbacks.h> 66 #include <dev/isci/scil/sati_util.h> 67 68 69 /** 70 * @brief This method will translate the SCSI Read Buffer command 71 * into a corresponding ATA Read Buffer command. 72 * For more information on the parameters passed to this method, 73 * please reference sati_translate_command(). 74 * 75 * @return Indicates if the command translation succeeded. 76 * @retval SATI_SUCCESS indicates that the translation was supported and occurred 77 * without error. 78 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 79 * there is a translation failure. 80 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without 81 * error, and no additional translation is necessary. 82 */ 83 SATI_STATUS sati_read_buffer_translate_command( 84 SATI_TRANSLATOR_SEQUENCE_T * sequence, 85 void * scsi_io, 86 void * ata_io 87 ) 88 { 89 U8 * cdb = sati_cb_get_cdb_address(scsi_io); 90 SATI_STATUS status = SATI_FAILURE; 91 U32 allocation_length; 92 U32 buffer_offset; 93 94 allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) | 95 (sati_get_cdb_byte(cdb, 7) << 8) | 96 (sati_get_cdb_byte(cdb, 8))); 97 98 buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) | 99 (sati_get_cdb_byte(cdb, 4) << 8) | 100 (sati_get_cdb_byte(cdb, 5))); 101 102 sequence->allocation_length = allocation_length; 103 104 switch(sati_get_cdb_byte(cdb, 1)) 105 { 106 case SATI_READ_BUFFER_MODE_DATA: 107 if((allocation_length == 512) && (buffer_offset == 0) && 108 (sati_get_cdb_byte(cdb, 2) == 0)) 109 { 110 sati_ata_read_buffer_construct(ata_io, sequence); 111 sequence->type = SATI_SEQUENCE_READ_BUFFER; 112 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 113 status = SATI_SUCCESS; 114 } 115 else 116 { 117 sati_scsi_sense_data_construct( 118 sequence, 119 scsi_io, 120 SCSI_STATUS_CHECK_CONDITION, 121 SCSI_SENSE_ILLEGAL_REQUEST, 122 SCSI_ASC_INVALID_FIELD_IN_CDB, 123 SCSI_ASCQ_INVALID_FIELD_IN_CDB 124 ); 125 sequence->state = SATI_SEQUENCE_STATE_FINAL; 126 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 127 } 128 break; 129 130 case SATI_READ_BUFFER_MODE_DESCRIPTOR: 131 132 //allocation legnth must be at least four to return translated data 133 if(allocation_length < 4) 134 { 135 sati_scsi_sense_data_construct( 136 sequence, 137 scsi_io, 138 SCSI_STATUS_CHECK_CONDITION, 139 SCSI_SENSE_ILLEGAL_REQUEST, 140 SCSI_ASC_INVALID_FIELD_IN_CDB, 141 SCSI_ASCQ_INVALID_FIELD_IN_CDB 142 ); 143 sequence->state = SATI_SEQUENCE_STATE_FINAL; 144 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 145 } 146 else 147 { 148 //figure out if we support other buffer id's 149 sati_set_data_byte(sequence, scsi_io, 0, 0x09); //offset boundary 150 sati_set_data_byte(sequence, scsi_io, 1, 0x00); 151 sati_set_data_byte(sequence, scsi_io, 2, 0x02); //buffer capacity 0x200 152 sati_set_data_byte(sequence, scsi_io, 3, 0x00); 153 sequence->state = SATI_SEQUENCE_STATE_FINAL; 154 status = SATI_COMPLETE; 155 } 156 break; 157 158 default: 159 //Unspecified sat2v7, returning invalid cdb 160 sati_scsi_sense_data_construct( 161 sequence, 162 scsi_io, 163 SCSI_STATUS_CHECK_CONDITION, 164 SCSI_SENSE_ILLEGAL_REQUEST, 165 SCSI_ASC_INVALID_FIELD_IN_CDB, 166 SCSI_ASCQ_INVALID_FIELD_IN_CDB 167 ); 168 sequence->state = SATI_SEQUENCE_STATE_FINAL; 169 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 170 } 171 return status; 172 } 173 174 /** 175 * @brief This method will complete the Read Buffer Translation by copying the 176 ATA response data into the SCSI request DATA buffer. 177 * For more information on the parameters passed to this method, 178 * please reference sati_translate_command(). 179 * 180 * @return Indicates if the command translation succeeded. 181 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 182 * there is a translation failure. 183 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without 184 * error, and no additional translation is necessary. 185 */ 186 SATI_STATUS sati_read_buffer_translate_response( 187 SATI_TRANSLATOR_SEQUENCE_T * sequence, 188 void * scsi_io, 189 void * ata_io 190 ) 191 { 192 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 193 U8 ata_status = (U8) sati_get_ata_status(register_fis); 194 SATI_STATUS status = SATI_COMPLETE; 195 196 if (ata_status & ATA_STATUS_REG_ERROR_BIT) 197 { 198 sati_scsi_sense_data_construct( 199 sequence, 200 scsi_io, 201 SCSI_STATUS_CHECK_CONDITION, 202 SCSI_SENSE_ABORTED_COMMAND, 203 SCSI_ASC_NO_ADDITIONAL_SENSE, 204 SCSI_ASCQ_NO_ADDITIONAL_SENSE 205 ); 206 207 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 208 } 209 else 210 { 211 void * ata_data = sati_cb_get_ata_data_address(ata_io); 212 213 if(ata_data == NULL) 214 { 215 status = SATI_FAILURE; 216 } 217 else 218 { 219 //copy ATA data into SCSI data buffer 220 sati_copy_data( 221 sequence, 222 scsi_io, 223 0, 224 ata_data, 225 512 226 ); 227 } 228 } 229 230 sequence->state = SATI_SEQUENCE_STATE_FINAL; 231 return status; 232 } 233 234 235 #endif //!defined(DISABLE_SATI_READ_BUFFER) 236