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$");
61 * @brief This file contains the method implementations for the
62 * SCIF_SAS_STP_IO_REQUEST object. The contents will implement
63 * SATA/STP specific functionality.
66 #include <dev/isci/scil/scif_sas_stp_io_request.h>
67 #include <dev/isci/scil/scif_sas_stp_remote_device.h>
68 #include <dev/isci/scil/scif_sas_logger.h>
69 #include <dev/isci/scil/scif_sas_controller.h>
71 #include <dev/isci/scil/sci_status.h>
72 #include <dev/isci/scil/scic_io_request.h>
74 #include <dev/isci/scil/sati.h>
75 #include <dev/isci/scil/sati_atapi.h>
76 #include <dev/isci/scil/intel_sat.h>
77 #include <dev/isci/scil/sati_util.h>
78 #include <dev/isci/scil/sati_callbacks.h>
80 //******************************************************************************
81 // P R I V A T E M E T H O D S
82 //******************************************************************************
85 * @brief This method provides SATA/STP CONSTRUCTED state specific handling
86 * for when the user attempts to start the supplied IO request. It
87 * will allocate NCQ tags if necessary.
89 * @param[in] io_request This parameter specifies the IO request object
92 * @return This method returns a value indicating if the IO request was
93 * successfully started or not.
94 * @retval SCI_SUCCESS This return value indicates successful starting
98 SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
99 SCI_BASE_REQUEST_T * io_request
102 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
105 sci_base_object_get_logger(io_request),
106 SCIF_LOG_OBJECT_IO_REQUEST,
107 "scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
111 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
113 SATA_FIS_REG_H2D_T * fis;
115 // For NCQ, we need to attempt to allocate an available tag.
116 fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
120 if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
121 return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
123 // Set the NCQ tag in the host to device register FIS (upper 5 bits
124 // of the 8-bit sector count register).
125 fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
126 fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
128 // The Core also requires that we inform it separately regarding the
129 // NCQ tag for this IO.
130 scic_stp_io_request_set_ncq_tag(
131 fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
139 * @brief This method provides SATA/STP CONSTRUCTED state specific handling
140 * for when the user attempts to complete the supplied IO request.
141 * This method will be invoked in the event the call to start the
142 * core IO request fails for some reason. In this situation, the
143 * NCQ tag will be freed.
145 * @param[in] io_request This parameter specifies the IO request object
148 * @return This method returns a value indicating if the IO request was
149 * successfully started or not.
150 * @retval SCI_SUCCESS This return value indicates successful starting
154 SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
155 SCI_BASE_REQUEST_T * io_request
158 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
161 sci_base_object_get_logger(io_request),
162 SCIF_LOG_OBJECT_IO_REQUEST,
163 "scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
167 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
169 // For NCQ, we need to return the tag back to the free pool.
170 if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
171 scif_sas_stp_remote_device_free_ncq_tag(
172 fw_io->parent.device, fw_io->parent.stp.ncq_tag
176 sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
181 * @brief This method provides SATA/STP STARTED state specific handling for
182 * when the user attempts to complete the supplied IO request.
183 * It will perform data/response translation and free NCQ tags
186 * @param[in] io_request This parameter specifies the IO request object
189 * @return This method returns a value indicating if the IO request was
190 * successfully completed or not.
193 SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
194 SCIF_SAS_CONTROLLER_T * fw_controller,
195 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
196 SCIF_SAS_REQUEST_T * fw_request,
197 SCI_STATUS * completion_status
200 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
203 sci_base_object_get_logger(fw_controller),
204 SCIF_LOG_OBJECT_IO_REQUEST,
205 "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
206 fw_controller, fw_device, fw_request, *completion_status
209 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
210 scif_sas_stp_remote_device_free_ncq_tag(
211 fw_request->device, fw_io->parent.stp.ncq_tag
214 // Translating the response is only necessary if:
215 // - some sort of error occurred resulting in having the error bit
216 // set in the ATA status register and values to decode in the
217 // ATA error register.
218 // - the command returns information in the register FIS itself,
219 // which requires translation.
220 // - the request completed ok but the sequence requires a callback
221 // to possibly continue the translation
222 if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
223 ((sati_cb_do_translate_response(fw_request)) &&
224 (*completion_status != SCI_FAILURE_IO_TERMINATED)))
226 SATI_STATUS sati_status = sati_translate_command_response(
227 &fw_io->parent.stp.sequence, fw_io, fw_io
229 if (sati_status == SATI_COMPLETE)
230 *completion_status = SCI_SUCCESS;
231 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
232 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
233 else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
235 // The translation indicates that additional SATA requests are
236 // necessary to finish the original SCSI request. As a result,
237 // do not complete the IO and begin the next stage of the
239 return SCI_WARNING_SEQUENCE_INCOMPLETE;
241 else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
242 *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
245 // Something unexpected occurred during translation. Fail the
246 // IO request to the user.
247 *completion_status = SCI_FAILURE;
250 else if (*completion_status != SCI_SUCCESS)
253 sci_base_object_get_logger(fw_controller),
254 SCIF_LOG_OBJECT_IO_REQUEST,
255 "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
256 fw_controller, fw_device, fw_request
259 sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
265 #if !defined(DISABLE_ATAPI)
267 * @brief This method provides STP PACKET io request STARTED state specific handling for
268 * when the user attempts to complete the supplied IO request.
269 * It will perform data/response translation.
271 * @param[in] io_request This parameter specifies the IO request object
274 * @return This method returns a value indicating if the IO request was
275 * successfully completed or not.
278 SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
279 SCIF_SAS_CONTROLLER_T * fw_controller,
280 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
281 SCIF_SAS_REQUEST_T * fw_request,
282 SCI_STATUS * completion_status
285 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
286 SATI_STATUS sati_status;
289 sci_base_object_get_logger(fw_controller),
290 SCIF_LOG_OBJECT_IO_REQUEST,
291 "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
292 fw_controller, fw_device, fw_request, *completion_status
295 if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
297 sati_status = sati_atapi_translate_command_response(
298 &fw_io->parent.stp.sequence, fw_io, fw_io
301 if (sati_status == SATI_COMPLETE)
302 *completion_status = SCI_SUCCESS;
303 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
304 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
305 else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
307 // The translation indicates that additional REQUEST SENSE command is
308 // necessary to finish the original SCSI request. As a result,
309 // do not complete the IO and begin the next stage of the IO.
310 return SCI_WARNING_SEQUENCE_INCOMPLETE;
314 // Something unexpected occurred during translation. Fail the
315 // IO request to the user.
316 *completion_status = SCI_FAILURE;
319 else if (*completion_status == SCI_SUCCESS &&
320 fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
322 //The internal Request Sense command is completed successfully.
323 sati_atapi_translate_request_sense_response(
324 &fw_io->parent.stp.sequence, fw_io, fw_io
327 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
332 #endif // !defined(DISABLE_ATAPI)
334 //******************************************************************************
335 // P R O T E C T E D M E T H O D S
336 //******************************************************************************
339 * @brief This method will construct the SATA/STP specific IO request
340 * object utilizing the SATI.
342 * @pre The scif_sas_request_construct() method should be invoked before
343 * calling this method.
345 * @param[in,out] stp_io_request This parameter specifies the stp_io_request
348 * @return Indicate if the construction was successful.
349 * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
350 * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
351 * @return SCI_FAILURE_IO_RESPONSE_VALID
352 * @return SCI_FAILURE This return value indicates a change in the translator
353 * where a new return code has been given, but is not yet understood
356 SCI_STATUS scif_sas_stp_io_request_construct(
357 SCIF_SAS_IO_REQUEST_T * fw_io
360 SATI_STATUS sati_status;
361 SCI_STATUS sci_status = SCI_FAILURE;
362 SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
365 sci_base_object_get_logger(fw_io),
366 SCIF_LOG_OBJECT_IO_REQUEST,
367 "scif_sas_stp_io_request_construct(0x%x) enter\n",
371 // The translator will indirectly invoke core methods to set the fields
372 // of the ATA register FIS inside of this method.
373 sati_status = sati_translate_command(
374 &fw_io->parent.stp.sequence,
375 &fw_device->protocol_device.stp_device.sati_device,
380 if (sati_status == SATI_SUCCESS)
382 // Allow the core to finish construction of the IO request.
383 sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
384 fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
385 fw_io->parent.protocol_complete_handler
386 = scif_sas_stp_core_cb_io_request_complete_handler;
388 else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
390 SCIC_IO_SATA_PARAMETERS_T parms;
391 parms.do_translate_sgl = FALSE;
393 // The translation actually already caused translation of the
394 // scatter gather list. So, call into the core through an API
395 // that will not attempt to translate the SGL.
396 scic_io_request_construct_advanced_sata(
397 fw_io->parent.core_object, &parms
399 fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
400 fw_io->parent.protocol_complete_handler
401 = scif_sas_stp_core_cb_io_request_complete_handler;
402 // Done with translation
403 sci_status = SCI_SUCCESS;
405 else if (sati_status == SATI_COMPLETE)
406 sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
407 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
408 sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
412 sci_base_object_get_logger(fw_io),
413 SCIF_LOG_OBJECT_IO_REQUEST,
414 "Unexpected SAT translation failure 0x%x\n",
423 #if !defined(DISABLE_ATAPI)
425 * @brief This method will construct the STP PACKET protocol specific IO
428 * @pre The scif_sas_request_construct() method should be invoked before
429 * calling this method.
431 * @param[in,out] fw_io This parameter specifies the stp packet io request
434 * @return Indicate if the construction was successful.
435 * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
436 * @return SCI_FAILURE_IO_RESPONSE_VALID
437 * @return SCI_FAILURE This return value indicates a change in the translator
438 * where a new return code has been given, but is not yet understood
441 SCI_STATUS scif_sas_stp_packet_io_request_construct(
442 SCIF_SAS_IO_REQUEST_T * fw_io
445 SATI_STATUS sati_status;
446 SCI_STATUS sci_status = SCI_FAILURE;
447 SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
450 sci_base_object_get_logger(fw_io),
451 SCIF_LOG_OBJECT_IO_REQUEST,
452 "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
456 sati_status = sati_atapi_translate_command(
457 &fw_io->parent.stp.sequence,
458 &fw_device->protocol_device.stp_device.sati_device,
463 if (sati_status == SATI_SUCCESS)
465 // Allow the core to finish construction of the IO request.
466 sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
468 fw_io->parent.protocol_complete_handler
469 = scif_sas_stp_core_cb_packet_io_request_complete_handler;
471 else if (sati_status == SATI_COMPLETE)
472 sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
473 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
474 sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
478 sci_base_object_get_logger(fw_io),
479 SCIF_LOG_OBJECT_IO_REQUEST,
480 "Unexpected SAT ATAPI translation failure 0x%x\n",
490 #if !defined(DISABLE_ATAPI)
492 * @brief This method will get the number of bytes transferred in an packet IO.
494 * @param[in] fw_io This parameter specifies the stp packet io request whose
495 * actual transferred length is to be retrieved.
497 * @return Actual length of transferred data.
499 U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
500 SCIF_SAS_IO_REQUEST_T * fw_io
503 SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
504 SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
505 U32 actual_data_length;
507 if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
508 actual_data_length = 0;
509 else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
511 actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
512 &fw_io->parent.stp.sequence, fw_io, fw_io);
514 if (actual_data_length == 0)
516 scic_io_request_get_number_of_bytes_transferred(scic_io);
520 scic_io_request_get_number_of_bytes_transferred(scic_io);
522 return actual_data_length;
527 //******************************************************************************
528 // P U B L I C M E T H O D S
529 //******************************************************************************
531 BOOL scic_cb_io_request_do_copy_rx_frames(
532 void * scic_user_io_request
535 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
538 sci_base_object_get_logger(fw_io),
539 SCIF_LOG_OBJECT_IO_REQUEST,
540 "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
544 // If the translation was a PIO DATA IN (i.e. read) and the request
545 // was actually a READ payload operation, then copy the data, since
546 // there will be SGL space allocated for the transfer.
547 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
550 (fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_12)
551 || (fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_16)
553 (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
554 && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
559 sci_base_object_get_logger(fw_io),
560 SCIF_LOG_OBJECT_IO_REQUEST,
561 "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
568 // For all other requests we leave the data in the core buffers.
569 // This allows the translation to translate without having to have
570 // separate space allocated into which to copy the data.
574 // ---------------------------------------------------------------------------
576 U8 scic_cb_request_get_sat_protocol(
577 void * scic_user_io_request
580 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
582 return fw_io->parent.stp.sequence.protocol;
585 U8 *scic_cb_io_request_get_virtual_address_from_sgl(
586 void * scic_user_io_request,
590 SCIF_SAS_REQUEST_T *fw_request =
591 (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
593 return scif_cb_io_request_get_virtual_address_from_sgl(
594 sci_object_get_association(fw_request),
599 #ifdef ENABLE_OSSL_COPY_BUFFER
600 void scic_cb_io_request_copy_buffer(
601 void * scic_user_io_request,
607 SCIF_SAS_REQUEST_T *fw_request =
608 (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
610 return scif_cb_io_request_copy_buffer(
611 sci_object_get_association(fw_request),
618 // ---------------------------------------------------------------------------
620 SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
622 scif_sas_stp_io_request_constructed_start_handler,
623 scif_sas_io_request_constructed_abort_handler,
624 scif_sas_stp_io_request_constructed_complete_handler,
625 scif_sas_io_request_default_destruct_handler