sati_write_buffer.c revision 231134
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 method implementations to translate 59* SCSI Write Buffer command based of the SAT2v07 spec. 60*/ 61 62#include <dev/isci/scil/sati_write_buffer.h> 63#include <dev/isci/scil/sati_callbacks.h> 64#include <dev/isci/scil/sati_util.h> 65 66#define WRITE_BUFFER_WRITE_DATA 0x02 67#define WRITE_BUFFER_DOWNLOAD_SAVE 0x05 68#define WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE 0x07 69#define BLOCK_SIZE 512 70 71/** 72* @brief This method will translate the SCSI Write Buffer command 73* into a corresponding ATA Write Buffer and Download Microcode commands. 74* For more information on the parameters passed to this method, 75* please reference sati_translate_command(). 76* 77* @return Indicates if the command translation succeeded. 78* @retval SATI_SUCCESS indicates that the translation was supported and occurred 79* without error. 80* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 81* there is a translation failure. 82*/ 83SATI_STATUS sati_write_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 WRITE_BUFFER_WRITE_DATA: 107 if((allocation_length == BLOCK_SIZE) && (buffer_offset == 0) && 108 (sati_get_cdb_byte(cdb, 2) == 0)) 109 { 110 sati_ata_write_buffer_construct(ata_io, sequence); 111 sequence->type = SATI_SEQUENCE_WRITE_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 126 sequence->state = SATI_SEQUENCE_STATE_FINAL; 127 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 128 } 129 break; 130 131 case WRITE_BUFFER_DOWNLOAD_SAVE: 132 133 sati_ata_download_microcode_construct( 134 ata_io, 135 sequence, 136 ATA_MICROCODE_DOWNLOAD_SAVE, 137 allocation_length, 138 buffer_offset 139 ); 140 141 sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE; 142 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 143 status = SATI_SUCCESS; 144 break; 145 146 case WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE: 147 if(((allocation_length & 0x000001FF) == 0) && //Bits 08:00 need to be zero per SAT2v7 148 ((buffer_offset & 0x000001FF) == 0) && 149 (allocation_length <= sequence->device->max_blocks_per_microcode_command) && 150 (allocation_length >= sequence->device->min_blocks_per_microcode_command)) 151 { 152 sati_ata_download_microcode_construct( 153 ata_io, 154 sequence, 155 ATA_MICROCODE_OFFSET_DOWNLOAD, 156 allocation_length, 157 buffer_offset 158 ); 159 160 sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE; 161 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 162 status = SATI_SUCCESS; 163 } 164 else 165 { 166 sati_scsi_sense_data_construct( 167 sequence, 168 scsi_io, 169 SCSI_STATUS_CHECK_CONDITION, 170 SCSI_SENSE_ILLEGAL_REQUEST, 171 SCSI_ASC_INVALID_FIELD_IN_CDB, 172 SCSI_ASCQ_INVALID_FIELD_IN_CDB 173 ); 174 175 sequence->state = SATI_SEQUENCE_STATE_FINAL; 176 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 177 } 178 break; 179 180 default: //unsupported Write Buffer Mode 181 sati_scsi_sense_data_construct( 182 sequence, 183 scsi_io, 184 SCSI_STATUS_CHECK_CONDITION, 185 SCSI_SENSE_ILLEGAL_REQUEST, 186 SCSI_ASC_INVALID_FIELD_IN_CDB, 187 SCSI_ASCQ_INVALID_FIELD_IN_CDB 188 ); 189 190 sequence->state = SATI_SEQUENCE_STATE_FINAL; 191 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 192 break; 193 } 194 return status; 195} 196 197/** 198* @brief This method will complete the Write Buffer Translation by checking 199* for ATA errors and then creating a unit attention condition for 200* changed microcode. 201* 202* @return Indicates if the command translation succeeded. 203* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 204* there is a translation failure. 205* @retval SATI_COMPLETE indicates that the translation was supported, occurred without 206* error, and no additional translation is necessary. 207*/ 208SATI_STATUS sati_write_buffer_translate_response( 209 SATI_TRANSLATOR_SEQUENCE_T * sequence, 210 void * scsi_io, 211 void * ata_io 212) 213{ 214 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 215 U8 ata_status = (U8) sati_get_ata_status(register_fis); 216 SATI_STATUS status = SATI_FAILURE; 217 218 if (ata_status & ATA_STATUS_REG_ERROR_BIT) 219 { 220 sati_scsi_sense_data_construct( 221 sequence, 222 scsi_io, 223 SCSI_STATUS_CHECK_CONDITION, 224 SCSI_SENSE_ABORTED_COMMAND, 225 SCSI_ASC_NO_ADDITIONAL_SENSE, 226 SCSI_ASCQ_NO_ADDITIONAL_SENSE 227 ); 228 status = SATI_FAILURE_CHECK_RESPONSE_DATA; 229 } 230 else 231 { 232 switch(sequence->type) 233 { 234 case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE: 235 sati_scsi_sense_data_construct( 236 sequence, 237 scsi_io, 238 SCSI_STATUS_GOOD, 239 SCSI_SENSE_UNIT_ATTENTION, 240 SCSI_ASC_MICROCODE_HAS_CHANGED, 241 SCSI_ASCQ_MICROCODE_HAS_CHANGED 242 ); 243 status = SATI_COMPLETE; 244 break; 245 246 default: 247 status = SATI_COMPLETE; 248 break; 249 } 250 } 251 252 sequence->state = SATI_SEQUENCE_STATE_FINAL; 253 return status; 254} 255