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.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
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
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.
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
59 * @brief This file contains the method implementations for the
60 * SCIF_SAS_STP_IO_REQUEST object. The contents will implement
61 * SATA/STP specific functionality.
64 #include <dev/isci/scil/scif_sas_stp_io_request.h>
65 #include <dev/isci/scil/scif_sas_stp_remote_device.h>
66 #include <dev/isci/scil/scif_sas_logger.h>
67 #include <dev/isci/scil/scif_sas_controller.h>
69 #include <dev/isci/scil/sci_status.h>
70 #include <dev/isci/scil/scic_io_request.h>
72 #include <dev/isci/scil/sati.h>
73 #include <dev/isci/scil/sati_atapi.h>
74 #include <dev/isci/scil/intel_sat.h>
75 #include <dev/isci/scil/sati_util.h>
76 #include <dev/isci/scil/sati_callbacks.h>
78 //******************************************************************************
79 // P R I V A T E M E T H O D S
80 //******************************************************************************
83 * @brief This method provides SATA/STP CONSTRUCTED state specific handling
84 * for when the user attempts to start the supplied IO request. It
85 * will allocate NCQ tags if necessary.
87 * @param[in] io_request This parameter specifies the IO request object
90 * @return This method returns a value indicating if the IO request was
91 * successfully started or not.
92 * @retval SCI_SUCCESS This return value indicates successful starting
96 SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
97 SCI_BASE_REQUEST_T * io_request
100 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
103 sci_base_object_get_logger(io_request),
104 SCIF_LOG_OBJECT_IO_REQUEST,
105 "scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
109 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
111 SATA_FIS_REG_H2D_T * fis;
113 // For NCQ, we need to attempt to allocate an available tag.
114 fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
118 if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
119 return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
121 // Set the NCQ tag in the host to device register FIS (upper 5 bits
122 // of the 8-bit sector count register).
123 fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
124 fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
126 // The Core also requires that we inform it separately regarding the
127 // NCQ tag for this IO.
128 scic_stp_io_request_set_ncq_tag(
129 fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
137 * @brief This method provides SATA/STP CONSTRUCTED state specific handling
138 * for when the user attempts to complete the supplied IO request.
139 * This method will be invoked in the event the call to start the
140 * core IO request fails for some reason. In this situation, the
141 * NCQ tag will be freed.
143 * @param[in] io_request This parameter specifies the IO request object
146 * @return This method returns a value indicating if the IO request was
147 * successfully started or not.
148 * @retval SCI_SUCCESS This return value indicates successful starting
152 SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
153 SCI_BASE_REQUEST_T * io_request
156 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
159 sci_base_object_get_logger(io_request),
160 SCIF_LOG_OBJECT_IO_REQUEST,
161 "scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
165 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
167 // For NCQ, we need to return the tag back to the free pool.
168 if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
169 scif_sas_stp_remote_device_free_ncq_tag(
170 fw_io->parent.device, fw_io->parent.stp.ncq_tag
174 sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
179 * @brief This method provides SATA/STP STARTED state specific handling for
180 * when the user attempts to complete the supplied IO request.
181 * It will perform data/response translation and free NCQ tags
184 * @param[in] io_request This parameter specifies the IO request object
187 * @return This method returns a value indicating if the IO request was
188 * successfully completed or not.
191 SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
192 SCIF_SAS_CONTROLLER_T * fw_controller,
193 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
194 SCIF_SAS_REQUEST_T * fw_request,
195 SCI_STATUS * completion_status
198 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
201 sci_base_object_get_logger(fw_controller),
202 SCIF_LOG_OBJECT_IO_REQUEST,
203 "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
204 fw_controller, fw_device, fw_request, *completion_status
207 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
208 scif_sas_stp_remote_device_free_ncq_tag(
209 fw_request->device, fw_io->parent.stp.ncq_tag
212 // Translating the response is only necessary if:
213 // - some sort of error occurred resulting in having the error bit
214 // set in the ATA status register and values to decode in the
215 // ATA error register.
216 // - the command returns information in the register FIS itself,
217 // which requires translation.
218 // - the request completed ok but the sequence requires a callback
219 // to possibly continue the translation
220 if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
221 ((sati_cb_do_translate_response(fw_request)) &&
222 (*completion_status != SCI_FAILURE_IO_TERMINATED)))
224 SATI_STATUS sati_status = sati_translate_command_response(
225 &fw_io->parent.stp.sequence, fw_io, fw_io
227 if (sati_status == SATI_COMPLETE)
228 *completion_status = SCI_SUCCESS;
229 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
230 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
231 else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
233 // The translation indicates that additional SATA requests are
234 // necessary to finish the original SCSI request. As a result,
235 // do not complete the IO and begin the next stage of the
237 return SCI_WARNING_SEQUENCE_INCOMPLETE;
239 else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
240 *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
243 // Something unexpected occurred during translation. Fail the
244 // IO request to the user.
245 *completion_status = SCI_FAILURE;
248 else if (*completion_status != SCI_SUCCESS)
251 sci_base_object_get_logger(fw_controller),
252 SCIF_LOG_OBJECT_IO_REQUEST,
253 "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
254 fw_controller, fw_device, fw_request
257 sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
263 #if !defined(DISABLE_ATAPI)
265 * @brief This method provides STP PACKET io request STARTED state specific handling for
266 * when the user attempts to complete the supplied IO request.
267 * It will perform data/response translation.
269 * @param[in] io_request This parameter specifies the IO request object
272 * @return This method returns a value indicating if the IO request was
273 * successfully completed or not.
276 SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
277 SCIF_SAS_CONTROLLER_T * fw_controller,
278 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
279 SCIF_SAS_REQUEST_T * fw_request,
280 SCI_STATUS * completion_status
283 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
284 SATI_STATUS sati_status;
287 sci_base_object_get_logger(fw_controller),
288 SCIF_LOG_OBJECT_IO_REQUEST,
289 "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
290 fw_controller, fw_device, fw_request, *completion_status
293 if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
295 sati_status = sati_atapi_translate_command_response(
296 &fw_io->parent.stp.sequence, fw_io, fw_io
299 if (sati_status == SATI_COMPLETE)
300 *completion_status = SCI_SUCCESS;
301 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
302 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
303 else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
305 // The translation indicates that additional REQUEST SENSE command is
306 // necessary to finish the original SCSI request. As a result,
307 // do not complete the IO and begin the next stage of the IO.
308 return SCI_WARNING_SEQUENCE_INCOMPLETE;
312 // Something unexpected occurred during translation. Fail the
313 // IO request to the user.
314 *completion_status = SCI_FAILURE;
317 else if (*completion_status == SCI_SUCCESS &&
318 fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
320 //The internal Request Sense command is completed successfully.
321 sati_atapi_translate_request_sense_response(
322 &fw_io->parent.stp.sequence, fw_io, fw_io
325 *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
330 #endif // !defined(DISABLE_ATAPI)
332 //******************************************************************************
333 // P R O T E C T E D M E T H O D S
334 //******************************************************************************
337 * @brief This method will construct the SATA/STP specific IO request
338 * object utilizing the SATI.
340 * @pre The scif_sas_request_construct() method should be invoked before
341 * calling this method.
343 * @param[in,out] stp_io_request This parameter specifies the stp_io_request
346 * @return Indicate if the construction was successful.
347 * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
348 * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
349 * @return SCI_FAILURE_IO_RESPONSE_VALID
350 * @return SCI_FAILURE This return value indicates a change in the translator
351 * where a new return code has been given, but is not yet understood
354 SCI_STATUS scif_sas_stp_io_request_construct(
355 SCIF_SAS_IO_REQUEST_T * fw_io
358 SATI_STATUS sati_status;
359 SCI_STATUS sci_status = SCI_FAILURE;
360 SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
363 sci_base_object_get_logger(fw_io),
364 SCIF_LOG_OBJECT_IO_REQUEST,
365 "scif_sas_stp_io_request_construct(0x%x) enter\n",
369 // The translator will indirectly invoke core methods to set the fields
370 // of the ATA register FIS inside of this method.
371 sati_status = sati_translate_command(
372 &fw_io->parent.stp.sequence,
373 &fw_device->protocol_device.stp_device.sati_device,
378 if (sati_status == SATI_SUCCESS)
380 // Allow the core to finish construction of the IO request.
381 sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
382 fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
383 fw_io->parent.protocol_complete_handler
384 = scif_sas_stp_core_cb_io_request_complete_handler;
386 else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
388 SCIC_IO_SATA_PARAMETERS_T parms;
389 parms.do_translate_sgl = FALSE;
391 // The translation actually already caused translation of the
392 // scatter gather list. So, call into the core through an API
393 // that will not attempt to translate the SGL.
394 scic_io_request_construct_advanced_sata(
395 fw_io->parent.core_object, &parms
397 fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
398 fw_io->parent.protocol_complete_handler
399 = scif_sas_stp_core_cb_io_request_complete_handler;
400 // Done with translation
401 sci_status = SCI_SUCCESS;
403 else if (sati_status == SATI_COMPLETE)
404 sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
405 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
406 sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
410 sci_base_object_get_logger(fw_io),
411 SCIF_LOG_OBJECT_IO_REQUEST,
412 "Unexpected SAT translation failure 0x%x\n",
421 #if !defined(DISABLE_ATAPI)
423 * @brief This method will construct the STP PACKET protocol specific IO
426 * @pre The scif_sas_request_construct() method should be invoked before
427 * calling this method.
429 * @param[in,out] fw_io This parameter specifies the stp packet io request
432 * @return Indicate if the construction was successful.
433 * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
434 * @return SCI_FAILURE_IO_RESPONSE_VALID
435 * @return SCI_FAILURE This return value indicates a change in the translator
436 * where a new return code has been given, but is not yet understood
439 SCI_STATUS scif_sas_stp_packet_io_request_construct(
440 SCIF_SAS_IO_REQUEST_T * fw_io
443 SATI_STATUS sati_status;
444 SCI_STATUS sci_status = SCI_FAILURE;
445 SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_io->parent.device;
448 sci_base_object_get_logger(fw_io),
449 SCIF_LOG_OBJECT_IO_REQUEST,
450 "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
454 sati_status = sati_atapi_translate_command(
455 &fw_io->parent.stp.sequence,
456 &fw_device->protocol_device.stp_device.sati_device,
461 if (sati_status == SATI_SUCCESS)
463 // Allow the core to finish construction of the IO request.
464 sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
466 fw_io->parent.protocol_complete_handler
467 = scif_sas_stp_core_cb_packet_io_request_complete_handler;
469 else if (sati_status == SATI_COMPLETE)
470 sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
471 else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
472 sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
476 sci_base_object_get_logger(fw_io),
477 SCIF_LOG_OBJECT_IO_REQUEST,
478 "Unexpected SAT ATAPI translation failure 0x%x\n",
488 #if !defined(DISABLE_ATAPI)
490 * @brief This method will get the number of bytes transferred in an packet IO.
492 * @param[in] fw_io This parameter specifies the stp packet io request whose
493 * actual transferred length is to be retrieved.
495 * @return Actual length of transferred data.
497 U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
498 SCIF_SAS_IO_REQUEST_T * fw_io
501 SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
502 SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
503 U32 actual_data_length;
505 if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
506 actual_data_length = 0;
507 else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
509 actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
510 &fw_io->parent.stp.sequence, fw_io, fw_io);
512 if (actual_data_length == 0)
514 scic_io_request_get_number_of_bytes_transferred(scic_io);
518 scic_io_request_get_number_of_bytes_transferred(scic_io);
520 return actual_data_length;
525 //******************************************************************************
526 // P U B L I C M E T H O D S
527 //******************************************************************************
529 BOOL scic_cb_io_request_do_copy_rx_frames(
530 void * scic_user_io_request
533 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
536 sci_base_object_get_logger(fw_io),
537 SCIF_LOG_OBJECT_IO_REQUEST,
538 "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
542 // If the translation was a PIO DATA IN (i.e. read) and the request
543 // was actually a READ payload operation, then copy the data, since
544 // there will be SGL space allocated for the transfer.
545 if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
548 (fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_12)
549 || (fw_io->parent.stp.sequence.type == SATI_SEQUENCE_ATA_PASSTHROUGH_16)
551 (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
552 && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
557 sci_base_object_get_logger(fw_io),
558 SCIF_LOG_OBJECT_IO_REQUEST,
559 "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
566 // For all other requests we leave the data in the core buffers.
567 // This allows the translation to translate without having to have
568 // separate space allocated into which to copy the data.
572 // ---------------------------------------------------------------------------
574 U8 scic_cb_request_get_sat_protocol(
575 void * scic_user_io_request
578 SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
580 return fw_io->parent.stp.sequence.protocol;
583 U8 *scic_cb_io_request_get_virtual_address_from_sgl(
584 void * scic_user_io_request,
588 SCIF_SAS_REQUEST_T *fw_request =
589 (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
591 return scif_cb_io_request_get_virtual_address_from_sgl(
592 sci_object_get_association(fw_request),
597 #ifdef ENABLE_OSSL_COPY_BUFFER
598 void scic_cb_io_request_copy_buffer(
599 void * scic_user_io_request,
605 SCIF_SAS_REQUEST_T *fw_request =
606 (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
608 return scif_cb_io_request_copy_buffer(
609 sci_object_get_association(fw_request),
616 // ---------------------------------------------------------------------------
618 SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
620 scif_sas_stp_io_request_constructed_start_handler,
621 scif_sas_io_request_constructed_abort_handler,
622 scif_sas_stp_io_request_constructed_complete_handler,
623 scif_sas_io_request_default_destruct_handler