1230557Sjimharris/*- 2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license. When using or 3230557Sjimharris * redistributing this file, you may do so under either license. 4230557Sjimharris* 5230557Sjimharris* GPL LICENSE SUMMARY 6230557Sjimharris* 7230557Sjimharris* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8230557Sjimharris* 9230557Sjimharris* This program is free software; you can redistribute it and/or modify 10230557Sjimharris* it under the terms of version 2 of the GNU General Public License as 11230557Sjimharris* published by the Free Software Foundation. 12230557Sjimharris* 13230557Sjimharris* This program is distributed in the hope that it will be useful, but 14230557Sjimharris* WITHOUT ANY WARRANTY; without even the implied warranty of 15230557Sjimharris* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16230557Sjimharris* General Public License for more details. 17230557Sjimharris* 18230557Sjimharris* You should have received a copy of the GNU General Public License 19230557Sjimharris* along with this program; if not, write to the Free Software 20230557Sjimharris* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21230557Sjimharris* The full GNU General Public License is included in this distribution 22230557Sjimharris* in the file called LICENSE.GPL. 23230557Sjimharris* 24230557Sjimharris* BSD LICENSE 25230557Sjimharris* 26230557Sjimharris* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27230557Sjimharris* All rights reserved. 28230557Sjimharris* 29230557Sjimharris* Redistribution and use in source and binary forms, with or without 30230557Sjimharris* modification, are permitted provided that the following conditions 31230557Sjimharris* are met: 32230557Sjimharris* 33230557Sjimharris* * Redistributions of source code must retain the above copyright 34230557Sjimharris* notice, this list of conditions and the following disclaimer. 35230557Sjimharris* * Redistributions in binary form must reproduce the above copyright 36230557Sjimharris* notice, this list of conditions and the following disclaimer in 37230557Sjimharris* the documentation and/or other materials provided with the 38230557Sjimharris* distribution. 39230557Sjimharris* 40230557Sjimharris* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41230557Sjimharris* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42230557Sjimharris* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43230557Sjimharris* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44230557Sjimharris* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45230557Sjimharris* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46230557Sjimharris* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47230557Sjimharris* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48230557Sjimharris* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49230557Sjimharris* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50230557Sjimharris* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51230557Sjimharris */ 52230557Sjimharris 53230557Sjimharris#include <sys/cdefs.h> 54230557Sjimharris__FBSDID("$FreeBSD$"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris* @file 58230557Sjimharris* @brief This file contains the method implementations to translate 59230557Sjimharris* SCSI Write Buffer command based of the SAT2v07 spec. 60230557Sjimharris*/ 61230557Sjimharris 62230557Sjimharris#include <dev/isci/scil/sati_write_buffer.h> 63230557Sjimharris#include <dev/isci/scil/sati_callbacks.h> 64230557Sjimharris#include <dev/isci/scil/sati_util.h> 65230557Sjimharris 66230557Sjimharris#define WRITE_BUFFER_WRITE_DATA 0x02 67230557Sjimharris#define WRITE_BUFFER_DOWNLOAD_SAVE 0x05 68230557Sjimharris#define WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE 0x07 69240514Sjimharris#define DOWNLOAD_MICROCODE_BLOCK_SIZE 512 70230557Sjimharris 71230557Sjimharris/** 72230557Sjimharris* @brief This method will translate the SCSI Write Buffer command 73230557Sjimharris* into a corresponding ATA Write Buffer and Download Microcode commands. 74230557Sjimharris* For more information on the parameters passed to this method, 75230557Sjimharris* please reference sati_translate_command(). 76230557Sjimharris* 77230557Sjimharris* @return Indicates if the command translation succeeded. 78230557Sjimharris* @retval SATI_SUCCESS indicates that the translation was supported and occurred 79230557Sjimharris* without error. 80230557Sjimharris* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 81230557Sjimharris* there is a translation failure. 82230557Sjimharris*/ 83230557SjimharrisSATI_STATUS sati_write_buffer_translate_command( 84230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 85230557Sjimharris void * scsi_io, 86230557Sjimharris void * ata_io 87230557Sjimharris) 88230557Sjimharris{ 89230557Sjimharris U8 * cdb = sati_cb_get_cdb_address(scsi_io); 90230557Sjimharris SATI_STATUS status = SATI_FAILURE; 91230557Sjimharris U32 allocation_length; 92240514Sjimharris U32 allocation_blocks; 93230557Sjimharris U32 buffer_offset; 94230557Sjimharris 95230557Sjimharris allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) | 96230557Sjimharris (sati_get_cdb_byte(cdb, 7) << 8) | 97230557Sjimharris (sati_get_cdb_byte(cdb, 8))); 98230557Sjimharris 99230557Sjimharris buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) | 100230557Sjimharris (sati_get_cdb_byte(cdb, 4) << 8) | 101230557Sjimharris (sati_get_cdb_byte(cdb, 5))); 102230557Sjimharris 103230557Sjimharris sequence->allocation_length = allocation_length; 104240514Sjimharris allocation_blocks = allocation_length / DOWNLOAD_MICROCODE_BLOCK_SIZE; 105230557Sjimharris 106230557Sjimharris switch(sati_get_cdb_byte(cdb, 1)) 107230557Sjimharris { 108230557Sjimharris case WRITE_BUFFER_WRITE_DATA: 109240514Sjimharris if((allocation_length == DOWNLOAD_MICROCODE_BLOCK_SIZE) && 110240514Sjimharris (buffer_offset == 0) && 111230557Sjimharris (sati_get_cdb_byte(cdb, 2) == 0)) 112230557Sjimharris { 113230557Sjimharris sati_ata_write_buffer_construct(ata_io, sequence); 114230557Sjimharris sequence->type = SATI_SEQUENCE_WRITE_BUFFER; 115230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 116230557Sjimharris status = SATI_SUCCESS; 117230557Sjimharris } 118230557Sjimharris else 119230557Sjimharris { 120230557Sjimharris sati_scsi_sense_data_construct( 121230557Sjimharris sequence, 122230557Sjimharris scsi_io, 123230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 124230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 125230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 126230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 127230557Sjimharris ); 128230557Sjimharris 129230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 130230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 131230557Sjimharris } 132230557Sjimharris break; 133230557Sjimharris 134230557Sjimharris case WRITE_BUFFER_DOWNLOAD_SAVE: 135230557Sjimharris 136230557Sjimharris sati_ata_download_microcode_construct( 137230557Sjimharris ata_io, 138230557Sjimharris sequence, 139230557Sjimharris ATA_MICROCODE_DOWNLOAD_SAVE, 140230557Sjimharris allocation_length, 141230557Sjimharris buffer_offset 142230557Sjimharris ); 143230557Sjimharris 144230557Sjimharris sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE; 145230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 146230557Sjimharris status = SATI_SUCCESS; 147230557Sjimharris break; 148230557Sjimharris 149230557Sjimharris case WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE: 150230557Sjimharris if(((allocation_length & 0x000001FF) == 0) && //Bits 08:00 need to be zero per SAT2v7 151230557Sjimharris ((buffer_offset & 0x000001FF) == 0) && 152240514Sjimharris (allocation_blocks <= sequence->device->max_blocks_per_microcode_command) && 153240514Sjimharris ((allocation_blocks >= sequence->device->min_blocks_per_microcode_command) || 154240514Sjimharris (allocation_length == 0))) 155230557Sjimharris { 156230557Sjimharris sati_ata_download_microcode_construct( 157230557Sjimharris ata_io, 158230557Sjimharris sequence, 159230557Sjimharris ATA_MICROCODE_OFFSET_DOWNLOAD, 160230557Sjimharris allocation_length, 161230557Sjimharris buffer_offset 162230557Sjimharris ); 163230557Sjimharris 164230557Sjimharris sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE; 165230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE; 166230557Sjimharris status = SATI_SUCCESS; 167230557Sjimharris } 168230557Sjimharris else 169230557Sjimharris { 170230557Sjimharris sati_scsi_sense_data_construct( 171230557Sjimharris sequence, 172230557Sjimharris scsi_io, 173230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 174230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 175230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 176230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 177230557Sjimharris ); 178230557Sjimharris 179230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 180230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 181230557Sjimharris } 182230557Sjimharris break; 183230557Sjimharris 184230557Sjimharris default: //unsupported Write Buffer Mode 185230557Sjimharris sati_scsi_sense_data_construct( 186230557Sjimharris sequence, 187230557Sjimharris scsi_io, 188230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 189230557Sjimharris SCSI_SENSE_ILLEGAL_REQUEST, 190230557Sjimharris SCSI_ASC_INVALID_FIELD_IN_CDB, 191230557Sjimharris SCSI_ASCQ_INVALID_FIELD_IN_CDB 192230557Sjimharris ); 193230557Sjimharris 194230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 195230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 196230557Sjimharris break; 197230557Sjimharris } 198230557Sjimharris return status; 199230557Sjimharris} 200230557Sjimharris 201230557Sjimharris/** 202230557Sjimharris* @brief This method will complete the Write Buffer Translation by checking 203230557Sjimharris* for ATA errors and then creating a unit attention condition for 204230557Sjimharris* changed microcode. 205230557Sjimharris* 206230557Sjimharris* @return Indicates if the command translation succeeded. 207230557Sjimharris* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 208230557Sjimharris* there is a translation failure. 209230557Sjimharris* @retval SATI_COMPLETE indicates that the translation was supported, occurred without 210230557Sjimharris* error, and no additional translation is necessary. 211230557Sjimharris*/ 212230557SjimharrisSATI_STATUS sati_write_buffer_translate_response( 213230557Sjimharris SATI_TRANSLATOR_SEQUENCE_T * sequence, 214230557Sjimharris void * scsi_io, 215230557Sjimharris void * ata_io 216230557Sjimharris) 217230557Sjimharris{ 218230557Sjimharris U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 219230557Sjimharris U8 ata_status = (U8) sati_get_ata_status(register_fis); 220230557Sjimharris SATI_STATUS status = SATI_FAILURE; 221230557Sjimharris 222230557Sjimharris if (ata_status & ATA_STATUS_REG_ERROR_BIT) 223230557Sjimharris { 224230557Sjimharris sati_scsi_sense_data_construct( 225230557Sjimharris sequence, 226230557Sjimharris scsi_io, 227230557Sjimharris SCSI_STATUS_CHECK_CONDITION, 228230557Sjimharris SCSI_SENSE_ABORTED_COMMAND, 229230557Sjimharris SCSI_ASC_NO_ADDITIONAL_SENSE, 230230557Sjimharris SCSI_ASCQ_NO_ADDITIONAL_SENSE 231230557Sjimharris ); 232230557Sjimharris status = SATI_FAILURE_CHECK_RESPONSE_DATA; 233230557Sjimharris } 234230557Sjimharris else 235230557Sjimharris { 236230557Sjimharris switch(sequence->type) 237230557Sjimharris { 238230557Sjimharris case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE: 239230557Sjimharris sati_scsi_sense_data_construct( 240230557Sjimharris sequence, 241230557Sjimharris scsi_io, 242230557Sjimharris SCSI_STATUS_GOOD, 243230557Sjimharris SCSI_SENSE_UNIT_ATTENTION, 244230557Sjimharris SCSI_ASC_MICROCODE_HAS_CHANGED, 245230557Sjimharris SCSI_ASCQ_MICROCODE_HAS_CHANGED 246230557Sjimharris ); 247230557Sjimharris status = SATI_COMPLETE; 248230557Sjimharris break; 249230557Sjimharris 250230557Sjimharris default: 251230557Sjimharris status = SATI_COMPLETE; 252230557Sjimharris break; 253230557Sjimharris } 254230557Sjimharris } 255230557Sjimharris 256230557Sjimharris sequence->state = SATI_SEQUENCE_STATE_FINAL; 257230557Sjimharris return status; 258230557Sjimharris} 259