sati_read_buffer.c revision 230557
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*/ 83SATI_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*/ 186SATI_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