2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
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.
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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
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.
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
60 * @brief This file contains the method implementations to translate
61 * SCSI Write Buffer command based of the SAT2v07 spec.
64 #include <dev/isci/scil/sati_write_buffer.h>
65 #include <dev/isci/scil/sati_callbacks.h>
66 #include <dev/isci/scil/sati_util.h>
68 #define WRITE_BUFFER_WRITE_DATA 0x02
69 #define WRITE_BUFFER_DOWNLOAD_SAVE 0x05
70 #define WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE 0x07
71 #define DOWNLOAD_MICROCODE_BLOCK_SIZE 512
74 * @brief This method will translate the SCSI Write Buffer command
75 * into a corresponding ATA Write Buffer and Download Microcode commands.
76 * For more information on the parameters passed to this method,
77 * please reference sati_translate_command().
79 * @return Indicates if the command translation succeeded.
80 * @retval SATI_SUCCESS indicates that the translation was supported and occurred
82 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
83 * there is a translation failure.
85 SATI_STATUS sati_write_buffer_translate_command(
86 SATI_TRANSLATOR_SEQUENCE_T * sequence,
91 U8 * cdb = sati_cb_get_cdb_address(scsi_io);
92 SATI_STATUS status = SATI_FAILURE;
93 U32 allocation_length;
94 U32 allocation_blocks;
97 allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
98 (sati_get_cdb_byte(cdb, 7) << 8) |
99 (sati_get_cdb_byte(cdb, 8)));
101 buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
102 (sati_get_cdb_byte(cdb, 4) << 8) |
103 (sati_get_cdb_byte(cdb, 5)));
105 sequence->allocation_length = allocation_length;
106 allocation_blocks = allocation_length / DOWNLOAD_MICROCODE_BLOCK_SIZE;
108 switch(sati_get_cdb_byte(cdb, 1))
110 case WRITE_BUFFER_WRITE_DATA:
111 if((allocation_length == DOWNLOAD_MICROCODE_BLOCK_SIZE) &&
112 (buffer_offset == 0) &&
113 (sati_get_cdb_byte(cdb, 2) == 0))
115 sati_ata_write_buffer_construct(ata_io, sequence);
116 sequence->type = SATI_SEQUENCE_WRITE_BUFFER;
117 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
118 status = SATI_SUCCESS;
122 sati_scsi_sense_data_construct(
125 SCSI_STATUS_CHECK_CONDITION,
126 SCSI_SENSE_ILLEGAL_REQUEST,
127 SCSI_ASC_INVALID_FIELD_IN_CDB,
128 SCSI_ASCQ_INVALID_FIELD_IN_CDB
131 sequence->state = SATI_SEQUENCE_STATE_FINAL;
132 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
136 case WRITE_BUFFER_DOWNLOAD_SAVE:
138 sati_ata_download_microcode_construct(
141 ATA_MICROCODE_DOWNLOAD_SAVE,
146 sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
147 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
148 status = SATI_SUCCESS;
151 case WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE:
152 if(((allocation_length & 0x000001FF) == 0) && //Bits 08:00 need to be zero per SAT2v7
153 ((buffer_offset & 0x000001FF) == 0) &&
154 (allocation_blocks <= sequence->device->max_blocks_per_microcode_command) &&
155 ((allocation_blocks >= sequence->device->min_blocks_per_microcode_command) ||
156 (allocation_length == 0)))
158 sati_ata_download_microcode_construct(
161 ATA_MICROCODE_OFFSET_DOWNLOAD,
166 sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
167 sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
168 status = SATI_SUCCESS;
172 sati_scsi_sense_data_construct(
175 SCSI_STATUS_CHECK_CONDITION,
176 SCSI_SENSE_ILLEGAL_REQUEST,
177 SCSI_ASC_INVALID_FIELD_IN_CDB,
178 SCSI_ASCQ_INVALID_FIELD_IN_CDB
181 sequence->state = SATI_SEQUENCE_STATE_FINAL;
182 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
186 default: //unsupported Write Buffer Mode
187 sati_scsi_sense_data_construct(
190 SCSI_STATUS_CHECK_CONDITION,
191 SCSI_SENSE_ILLEGAL_REQUEST,
192 SCSI_ASC_INVALID_FIELD_IN_CDB,
193 SCSI_ASCQ_INVALID_FIELD_IN_CDB
196 sequence->state = SATI_SEQUENCE_STATE_FINAL;
197 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
204 * @brief This method will complete the Write Buffer Translation by checking
205 * for ATA errors and then creating a unit attention condition for
208 * @return Indicates if the command translation succeeded.
209 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
210 * there is a translation failure.
211 * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
212 * error, and no additional translation is necessary.
214 SATI_STATUS sati_write_buffer_translate_response(
215 SATI_TRANSLATOR_SEQUENCE_T * sequence,
220 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
221 U8 ata_status = (U8) sati_get_ata_status(register_fis);
222 SATI_STATUS status = SATI_FAILURE;
224 if (ata_status & ATA_STATUS_REG_ERROR_BIT)
226 sati_scsi_sense_data_construct(
229 SCSI_STATUS_CHECK_CONDITION,
230 SCSI_SENSE_ABORTED_COMMAND,
231 SCSI_ASC_NO_ADDITIONAL_SENSE,
232 SCSI_ASCQ_NO_ADDITIONAL_SENSE
234 status = SATI_FAILURE_CHECK_RESPONSE_DATA;
238 switch(sequence->type)
240 case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
241 sati_scsi_sense_data_construct(
245 SCSI_SENSE_UNIT_ATTENTION,
246 SCSI_ASC_MICROCODE_HAS_CHANGED,
247 SCSI_ASCQ_MICROCODE_HAS_CHANGED
249 status = SATI_COMPLETE;
253 status = SATI_COMPLETE;
258 sequence->state = SATI_SEQUENCE_STATE_FINAL;