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 *
59230557Sjimharris * @brief This file contains the method implementations for the
60230557Sjimharris *        SCIF_SAS_STP_IO_REQUEST object.  The contents will implement
61230557Sjimharris *        SATA/STP specific functionality.
62230557Sjimharris */
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/scif_sas_stp_io_request.h>
65230557Sjimharris#include <dev/isci/scil/scif_sas_stp_remote_device.h>
66230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
67230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h>
68230557Sjimharris
69230557Sjimharris#include <dev/isci/scil/sci_status.h>
70230557Sjimharris#include <dev/isci/scil/scic_io_request.h>
71230557Sjimharris
72230557Sjimharris#include <dev/isci/scil/sati.h>
73230557Sjimharris#include <dev/isci/scil/sati_atapi.h>
74230557Sjimharris#include <dev/isci/scil/intel_sat.h>
75230557Sjimharris#include <dev/isci/scil/sati_util.h>
76230557Sjimharris#include <dev/isci/scil/sati_callbacks.h>
77230557Sjimharris
78230557Sjimharris//******************************************************************************
79230557Sjimharris// P R I V A T E   M E T H O D S
80230557Sjimharris//******************************************************************************
81230557Sjimharris
82230557Sjimharris/**
83230557Sjimharris * @brief This method provides SATA/STP CONSTRUCTED state specific handling
84230557Sjimharris *        for when the user attempts to start the supplied IO request.  It
85230557Sjimharris *        will allocate NCQ tags if necessary.
86230557Sjimharris *
87230557Sjimharris * @param[in] io_request This parameter specifies the IO request object
88230557Sjimharris *            to be started.
89230557Sjimharris *
90230557Sjimharris * @return This method returns a value indicating if the IO request was
91230557Sjimharris *         successfully started or not.
92230557Sjimharris * @retval SCI_SUCCESS This return value indicates successful starting
93230557Sjimharris *         of the IO request.
94230557Sjimharris */
95230557Sjimharrisstatic
96230557SjimharrisSCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
97230557Sjimharris   SCI_BASE_REQUEST_T * io_request
98230557Sjimharris)
99230557Sjimharris{
100230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
101230557Sjimharris
102230557Sjimharris   SCIF_LOG_TRACE((
103230557Sjimharris      sci_base_object_get_logger(io_request),
104230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
105230557Sjimharris      "scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
106230557Sjimharris      io_request
107230557Sjimharris   ));
108230557Sjimharris
109230557Sjimharris   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
110230557Sjimharris   {
111230557Sjimharris      SATA_FIS_REG_H2D_T * fis;
112230557Sjimharris
113230557Sjimharris      // For NCQ, we need to attempt to allocate an available tag.
114230557Sjimharris      fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
115230557Sjimharris                                     fw_io->parent.device
116230557Sjimharris                                  );
117230557Sjimharris
118230557Sjimharris      if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
119230557Sjimharris         return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
120230557Sjimharris
121230557Sjimharris      // Set the NCQ tag in the host to device register FIS (upper 5 bits
122230557Sjimharris      // of the 8-bit sector count register).
123230557Sjimharris      fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
124230557Sjimharris      fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
125230557Sjimharris
126230557Sjimharris      // The Core also requires that we inform it separately regarding the
127230557Sjimharris      // NCQ tag for this IO.
128230557Sjimharris      scic_stp_io_request_set_ncq_tag(
129230557Sjimharris         fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
130230557Sjimharris      );
131230557Sjimharris   }
132230557Sjimharris
133230557Sjimharris   return SCI_SUCCESS;
134230557Sjimharris}
135230557Sjimharris
136230557Sjimharris/**
137230557Sjimharris * @brief This method provides SATA/STP CONSTRUCTED state specific handling
138230557Sjimharris *        for when the user attempts to complete the supplied IO request.
139230557Sjimharris *        This method will be invoked in the event the call to start the
140230557Sjimharris *        core IO request fails for some reason.  In this situation, the
141230557Sjimharris *        NCQ tag will be freed.
142230557Sjimharris *
143230557Sjimharris * @param[in] io_request This parameter specifies the IO request object
144230557Sjimharris *            to be started.
145230557Sjimharris *
146230557Sjimharris * @return This method returns a value indicating if the IO request was
147230557Sjimharris *         successfully started or not.
148230557Sjimharris * @retval SCI_SUCCESS This return value indicates successful starting
149230557Sjimharris *         of the IO request.
150230557Sjimharris */
151230557Sjimharrisstatic
152230557SjimharrisSCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
153230557Sjimharris   SCI_BASE_REQUEST_T * io_request
154230557Sjimharris)
155230557Sjimharris{
156230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
157230557Sjimharris
158230557Sjimharris   SCIF_LOG_TRACE((
159230557Sjimharris      sci_base_object_get_logger(io_request),
160230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
161230557Sjimharris      "scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
162230557Sjimharris      io_request
163230557Sjimharris   ));
164230557Sjimharris
165230557Sjimharris   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
166230557Sjimharris   {
167230557Sjimharris      // For NCQ, we need to return the tag back to the free pool.
168230557Sjimharris      if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
169230557Sjimharris         scif_sas_stp_remote_device_free_ncq_tag(
170230557Sjimharris            fw_io->parent.device, fw_io->parent.stp.ncq_tag
171230557Sjimharris         );
172230557Sjimharris   }
173230557Sjimharris
174239545Sjimharris   sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
175239545Sjimharris
176230557Sjimharris   return SCI_SUCCESS;
177230557Sjimharris}
178230557Sjimharris/**
179230557Sjimharris * @brief This method provides SATA/STP STARTED state specific handling for
180230557Sjimharris *        when the user attempts to complete the supplied IO request.
181230557Sjimharris *        It will perform data/response translation and free NCQ tags
182230557Sjimharris *        if necessary.
183230557Sjimharris *
184230557Sjimharris * @param[in] io_request This parameter specifies the IO request object
185230557Sjimharris *            to be started.
186230557Sjimharris *
187230557Sjimharris * @return This method returns a value indicating if the IO request was
188230557Sjimharris *         successfully completed or not.
189230557Sjimharris */
190230557Sjimharrisstatic
191230557SjimharrisSCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
192230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
193230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
194230557Sjimharris   SCIF_SAS_REQUEST_T       * fw_request,
195230557Sjimharris   SCI_STATUS               * completion_status
196230557Sjimharris)
197230557Sjimharris{
198230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
199230557Sjimharris
200230557Sjimharris   SCIF_LOG_TRACE((
201230557Sjimharris      sci_base_object_get_logger(fw_controller),
202230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
203230557Sjimharris      "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
204230557Sjimharris      fw_controller, fw_device, fw_request, *completion_status
205230557Sjimharris   ));
206230557Sjimharris
207230557Sjimharris   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
208230557Sjimharris      scif_sas_stp_remote_device_free_ncq_tag(
209230557Sjimharris         fw_request->device, fw_io->parent.stp.ncq_tag
210230557Sjimharris      );
211230557Sjimharris
212230557Sjimharris   // Translating the response is only necessary if:
213230557Sjimharris   // - some sort of error occurred resulting in having the error bit
214230557Sjimharris   //   set in the ATA status register and values to decode in the
215230557Sjimharris   //   ATA error register.
216230557Sjimharris   // - the command returns information in the register FIS itself,
217230557Sjimharris   //   which requires translation.
218230557Sjimharris   // - the request completed ok but the sequence requires a callback
219230557Sjimharris   //   to possibly continue the translation
220230557Sjimharris   if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
221230557Sjimharris       ((sati_cb_do_translate_response(fw_request)) &&
222230557Sjimharris        (*completion_status != SCI_FAILURE_IO_TERMINATED)))
223230557Sjimharris   {
224230557Sjimharris      SATI_STATUS sati_status = sati_translate_command_response(
225230557Sjimharris                                   &fw_io->parent.stp.sequence, fw_io, fw_io
226230557Sjimharris                                );
227230557Sjimharris      if (sati_status == SATI_COMPLETE)
228230557Sjimharris         *completion_status = SCI_SUCCESS;
229230557Sjimharris      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
230230557Sjimharris         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
231230557Sjimharris      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
232230557Sjimharris      {
233230557Sjimharris         // The translation indicates that additional SATA requests are
234230557Sjimharris         // necessary to finish the original SCSI request.  As a result,
235230557Sjimharris         // do not complete the IO and begin the next stage of the
236230557Sjimharris         // translation.
237230557Sjimharris         return SCI_WARNING_SEQUENCE_INCOMPLETE;
238230557Sjimharris      }
239230557Sjimharris      else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
240230557Sjimharris         *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
241230557Sjimharris      else
242230557Sjimharris      {
243230557Sjimharris         // Something unexpected occurred during translation.  Fail the
244230557Sjimharris         // IO request to the user.
245230557Sjimharris         *completion_status = SCI_FAILURE;
246230557Sjimharris      }
247230557Sjimharris   }
248230557Sjimharris   else if (*completion_status != SCI_SUCCESS)
249230557Sjimharris   {
250230557Sjimharris      SCIF_LOG_INFO((
251230557Sjimharris         sci_base_object_get_logger(fw_controller),
252230557Sjimharris         SCIF_LOG_OBJECT_IO_REQUEST,
253230557Sjimharris         "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
254230557Sjimharris         fw_controller, fw_device, fw_request
255230557Sjimharris      ));
256230557Sjimharris
257230557Sjimharris      sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
258230557Sjimharris   }
259230557Sjimharris
260230557Sjimharris   return SCI_SUCCESS;
261230557Sjimharris}
262230557Sjimharris
263230557Sjimharris#if !defined(DISABLE_ATAPI)
264230557Sjimharris/**
265230557Sjimharris * @brief This method provides STP PACKET io request STARTED state specific handling for
266230557Sjimharris *        when the user attempts to complete the supplied IO request.
267230557Sjimharris *        It will perform data/response translation.
268230557Sjimharris *
269230557Sjimharris * @param[in] io_request This parameter specifies the IO request object
270230557Sjimharris *            to be started.
271230557Sjimharris *
272230557Sjimharris * @return This method returns a value indicating if the IO request was
273230557Sjimharris *         successfully completed or not.
274230557Sjimharris */
275230557Sjimharrisstatic
276230557SjimharrisSCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
277230557Sjimharris   SCIF_SAS_CONTROLLER_T    * fw_controller,
278230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
279230557Sjimharris   SCIF_SAS_REQUEST_T       * fw_request,
280230557Sjimharris   SCI_STATUS               * completion_status
281230557Sjimharris)
282230557Sjimharris{
283230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
284230557Sjimharris   SATI_STATUS sati_status;
285230557Sjimharris
286230557Sjimharris   SCIF_LOG_TRACE((
287230557Sjimharris      sci_base_object_get_logger(fw_controller),
288230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
289230557Sjimharris      "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
290230557Sjimharris      fw_controller, fw_device, fw_request, *completion_status
291230557Sjimharris   ));
292230557Sjimharris
293230557Sjimharris   if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
294230557Sjimharris   {
295230557Sjimharris      sati_status = sati_atapi_translate_command_response(
296230557Sjimharris                       &fw_io->parent.stp.sequence, fw_io, fw_io
297230557Sjimharris                    );
298230557Sjimharris
299230557Sjimharris      if (sati_status == SATI_COMPLETE)
300230557Sjimharris         *completion_status = SCI_SUCCESS;
301230557Sjimharris      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
302230557Sjimharris         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
303230557Sjimharris      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
304230557Sjimharris      {
305230557Sjimharris         // The translation indicates that additional REQUEST SENSE command is
306230557Sjimharris         // necessary to finish the original SCSI request.  As a result,
307230557Sjimharris         // do not complete the IO and begin the next stage of the IO.
308230557Sjimharris         return SCI_WARNING_SEQUENCE_INCOMPLETE;
309230557Sjimharris      }
310230557Sjimharris      else
311230557Sjimharris      {
312230557Sjimharris         // Something unexpected occurred during translation.  Fail the
313230557Sjimharris         // IO request to the user.
314230557Sjimharris         *completion_status = SCI_FAILURE;
315230557Sjimharris      }
316230557Sjimharris   }
317230557Sjimharris   else if (*completion_status == SCI_SUCCESS &&
318230557Sjimharris        fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
319230557Sjimharris   {
320230557Sjimharris      //The internal Request Sense command is completed successfully.
321230557Sjimharris      sati_atapi_translate_request_sense_response(
322230557Sjimharris         &fw_io->parent.stp.sequence, fw_io, fw_io
323230557Sjimharris      );
324230557Sjimharris
325230557Sjimharris      *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
326230557Sjimharris   }
327230557Sjimharris
328230557Sjimharris   return SCI_SUCCESS;
329230557Sjimharris}
330230557Sjimharris#endif // !defined(DISABLE_ATAPI)
331230557Sjimharris
332230557Sjimharris//******************************************************************************
333230557Sjimharris// P R O T E C T E D   M E T H O D S
334230557Sjimharris//******************************************************************************
335230557Sjimharris
336230557Sjimharris/**
337230557Sjimharris * @brief This method will construct the SATA/STP specific IO request
338230557Sjimharris *        object utilizing the SATI.
339230557Sjimharris *
340230557Sjimharris * @pre The scif_sas_request_construct() method should be invoked before
341230557Sjimharris *      calling this method.
342230557Sjimharris *
343230557Sjimharris * @param[in,out] stp_io_request This parameter specifies the stp_io_request
344230557Sjimharris *                to be constructed.
345230557Sjimharris *
346230557Sjimharris * @return Indicate if the construction was successful.
347230557Sjimharris * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
348230557Sjimharris * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
349230557Sjimharris * @return SCI_FAILURE_IO_RESPONSE_VALID
350230557Sjimharris * @return SCI_FAILURE This return value indicates a change in the translator
351230557Sjimharris *         where a new return code has been given, but is not yet understood
352230557Sjimharris *         by this routine.
353230557Sjimharris */
354230557SjimharrisSCI_STATUS scif_sas_stp_io_request_construct(
355230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io
356230557Sjimharris)
357230557Sjimharris{
358230557Sjimharris   SATI_STATUS                sati_status;
359230557Sjimharris   SCI_STATUS                 sci_status = SCI_FAILURE;
360230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
361230557Sjimharris
362230557Sjimharris   SCIF_LOG_TRACE((
363230557Sjimharris      sci_base_object_get_logger(fw_io),
364230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
365230557Sjimharris      "scif_sas_stp_io_request_construct(0x%x) enter\n",
366230557Sjimharris      fw_io
367230557Sjimharris   ));
368230557Sjimharris
369230557Sjimharris   // The translator will indirectly invoke core methods to set the fields
370230557Sjimharris   // of the ATA register FIS inside of this method.
371230557Sjimharris   sati_status = sati_translate_command(
372230557Sjimharris                    &fw_io->parent.stp.sequence,
373230557Sjimharris                    &fw_device->protocol_device.stp_device.sati_device,
374230557Sjimharris                    fw_io,
375230557Sjimharris                    fw_io
376230557Sjimharris                 );
377230557Sjimharris
378230557Sjimharris   if (sati_status == SATI_SUCCESS)
379230557Sjimharris   {
380230557Sjimharris      // Allow the core to finish construction of the IO request.
381230557Sjimharris      sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
382230557Sjimharris      fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
383230557Sjimharris      fw_io->parent.protocol_complete_handler
384230557Sjimharris         = scif_sas_stp_core_cb_io_request_complete_handler;
385230557Sjimharris   }
386230557Sjimharris   else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
387230557Sjimharris   {
388230557Sjimharris      SCIC_IO_SATA_PARAMETERS_T parms;
389230557Sjimharris      parms.do_translate_sgl = FALSE;
390230557Sjimharris
391230557Sjimharris      // The translation actually already caused translation of the
392230557Sjimharris      // scatter gather list.  So, call into the core through an API
393230557Sjimharris      // that will not attempt to translate the SGL.
394230557Sjimharris      scic_io_request_construct_advanced_sata(
395230557Sjimharris                      fw_io->parent.core_object, &parms
396230557Sjimharris                   );
397230557Sjimharris      fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
398230557Sjimharris      fw_io->parent.protocol_complete_handler
399230557Sjimharris         = scif_sas_stp_core_cb_io_request_complete_handler;
400230557Sjimharris      // Done with translation
401231296Sjimharris      sci_status = SCI_SUCCESS;
402230557Sjimharris   }
403230557Sjimharris   else if (sati_status == SATI_COMPLETE)
404230557Sjimharris      sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
405230557Sjimharris   else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
406230557Sjimharris      sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
407230557Sjimharris   else
408230557Sjimharris   {
409230557Sjimharris      SCIF_LOG_ERROR((
410230557Sjimharris         sci_base_object_get_logger(fw_io),
411230557Sjimharris         SCIF_LOG_OBJECT_IO_REQUEST,
412230557Sjimharris         "Unexpected SAT translation failure 0x%x\n",
413230557Sjimharris         fw_io
414230557Sjimharris      ));
415230557Sjimharris   }
416230557Sjimharris
417230557Sjimharris   return sci_status;
418230557Sjimharris}
419230557Sjimharris
420230557Sjimharris
421230557Sjimharris#if !defined(DISABLE_ATAPI)
422230557Sjimharris/**
423230557Sjimharris * @brief This method will construct the STP PACKET protocol specific IO
424230557Sjimharris *        request object.
425230557Sjimharris *
426230557Sjimharris * @pre The scif_sas_request_construct() method should be invoked before
427230557Sjimharris *      calling this method.
428230557Sjimharris *
429230557Sjimharris * @param[in,out] fw_io This parameter specifies the stp packet io request
430230557Sjimharris *                to be constructed.
431230557Sjimharris *
432230557Sjimharris * @return Indicate if the construction was successful.
433230557Sjimharris * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
434230557Sjimharris * @return SCI_FAILURE_IO_RESPONSE_VALID
435230557Sjimharris * @return SCI_FAILURE This return value indicates a change in the translator
436230557Sjimharris *         where a new return code has been given, but is not yet understood
437230557Sjimharris *         by this routine.
438230557Sjimharris */
439230557SjimharrisSCI_STATUS scif_sas_stp_packet_io_request_construct(
440230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io
441230557Sjimharris)
442230557Sjimharris{
443230557Sjimharris   SATI_STATUS                sati_status;
444230557Sjimharris   SCI_STATUS                 sci_status = SCI_FAILURE;
445230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
446230557Sjimharris
447230557Sjimharris   SCIF_LOG_TRACE((
448230557Sjimharris      sci_base_object_get_logger(fw_io),
449230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
450230557Sjimharris      "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
451230557Sjimharris      fw_io
452230557Sjimharris   ));
453230557Sjimharris
454230557Sjimharris   sati_status = sati_atapi_translate_command(
455230557Sjimharris                    &fw_io->parent.stp.sequence,
456230557Sjimharris                    &fw_device->protocol_device.stp_device.sati_device,
457230557Sjimharris                    fw_io,
458230557Sjimharris                    fw_io
459230557Sjimharris                 );
460230557Sjimharris
461230557Sjimharris   if (sati_status == SATI_SUCCESS)
462230557Sjimharris   {
463230557Sjimharris      // Allow the core to finish construction of the IO request.
464230557Sjimharris      sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
465230557Sjimharris
466230557Sjimharris      fw_io->parent.protocol_complete_handler
467230557Sjimharris         = scif_sas_stp_core_cb_packet_io_request_complete_handler;
468230557Sjimharris   }
469230557Sjimharris   else if (sati_status == SATI_COMPLETE)
470230557Sjimharris      sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
471230557Sjimharris   else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
472230557Sjimharris      sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
473230557Sjimharris   else
474230557Sjimharris   {
475230557Sjimharris      SCIF_LOG_ERROR((
476230557Sjimharris         sci_base_object_get_logger(fw_io),
477230557Sjimharris         SCIF_LOG_OBJECT_IO_REQUEST,
478230557Sjimharris         "Unexpected SAT ATAPI translation failure 0x%x\n",
479230557Sjimharris         fw_io
480230557Sjimharris      ));
481230557Sjimharris   }
482230557Sjimharris
483230557Sjimharris   return sci_status;
484230557Sjimharris}
485230557Sjimharris#endif
486230557Sjimharris
487230557Sjimharris
488230557Sjimharris#if !defined(DISABLE_ATAPI)
489230557Sjimharris/**
490230557Sjimharris * @brief This method will get the number of bytes transferred in an packet IO.
491230557Sjimharris *
492230557Sjimharris * @param[in] fw_io This parameter specifies the stp packet io request whose
493230557Sjimharris *                     actual transferred length is to be retrieved.
494230557Sjimharris *
495230557Sjimharris * @return Actual length of transferred data.
496230557Sjimharris */
497230557SjimharrisU32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
498230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io
499230557Sjimharris)
500230557Sjimharris{
501230557Sjimharris   SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
502230557Sjimharris   SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
503230557Sjimharris   U32 actual_data_length;
504230557Sjimharris
505230557Sjimharris   if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
506230557Sjimharris       actual_data_length = 0;
507230557Sjimharris   else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
508230557Sjimharris   {
509230557Sjimharris      actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
510230557Sjimharris         &fw_io->parent.stp.sequence, fw_io, fw_io);
511230557Sjimharris
512230557Sjimharris      if (actual_data_length == 0)
513230557Sjimharris         actual_data_length =
514230557Sjimharris            scic_io_request_get_number_of_bytes_transferred(scic_io);
515230557Sjimharris   }
516230557Sjimharris   else
517230557Sjimharris      actual_data_length =
518230557Sjimharris         scic_io_request_get_number_of_bytes_transferred(scic_io);
519230557Sjimharris
520230557Sjimharris   return actual_data_length;
521230557Sjimharris}
522230557Sjimharris#endif
523230557Sjimharris
524230557Sjimharris
525230557Sjimharris//******************************************************************************
526230557Sjimharris// P U B L I C   M E T H O D S
527230557Sjimharris//******************************************************************************
528230557Sjimharris
529230557SjimharrisBOOL scic_cb_io_request_do_copy_rx_frames(
530230557Sjimharris   void * scic_user_io_request
531230557Sjimharris)
532230557Sjimharris{
533230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
534230557Sjimharris
535230557Sjimharris   SCIF_LOG_TRACE((
536230557Sjimharris      sci_base_object_get_logger(fw_io),
537230557Sjimharris      SCIF_LOG_OBJECT_IO_REQUEST,
538230557Sjimharris      "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
539230557Sjimharris      fw_io
540230557Sjimharris   ));
541230557Sjimharris
542230557Sjimharris   // If the translation was a PIO DATA IN (i.e. read) and the request
543230557Sjimharris   // was actually a READ payload operation, then copy the data, since
544230557Sjimharris   // there will be SGL space allocated for the transfer.
545230557Sjimharris   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
546230557Sjimharris   {
547230557Sjimharris      if (
548230557Sjimharris            (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_12)
549230557Sjimharris         || (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_16)
550230557Sjimharris         || (
551230557Sjimharris               (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
552230557Sjimharris            && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
553230557Sjimharris            )
554230557Sjimharris         )
555230557Sjimharris      {
556230557Sjimharris           SCIF_LOG_TRACE((
557230557Sjimharris                 sci_base_object_get_logger(fw_io),
558230557Sjimharris                 SCIF_LOG_OBJECT_IO_REQUEST,
559230557Sjimharris                 "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
560230557Sjimharris                 fw_io
561230557Sjimharris              ));
562230557Sjimharris           return TRUE;
563230557Sjimharris      }
564230557Sjimharris   }
565230557Sjimharris
566230557Sjimharris   // For all other requests we leave the data in the core buffers.
567230557Sjimharris   // This allows the translation to translate without having to have
568230557Sjimharris   // separate space allocated into which to copy the data.
569230557Sjimharris   return FALSE;
570230557Sjimharris}
571230557Sjimharris
572230557Sjimharris// ---------------------------------------------------------------------------
573230557Sjimharris
574230557SjimharrisU8 scic_cb_request_get_sat_protocol(
575230557Sjimharris   void * scic_user_io_request
576230557Sjimharris)
577230557Sjimharris{
578230557Sjimharris   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
579230557Sjimharris
580230557Sjimharris   return fw_io->parent.stp.sequence.protocol;
581230557Sjimharris}
582230557Sjimharris
583230557SjimharrisU8 *scic_cb_io_request_get_virtual_address_from_sgl(
584230557Sjimharris   void * scic_user_io_request,
585230557Sjimharris   U32    byte_offset
586230557Sjimharris)
587230557Sjimharris{
588230557Sjimharris   SCIF_SAS_REQUEST_T *fw_request =
589230557Sjimharris      (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
590230557Sjimharris
591230557Sjimharris   return scif_cb_io_request_get_virtual_address_from_sgl(
592230557Sjimharris             sci_object_get_association(fw_request),
593230557Sjimharris             byte_offset
594230557Sjimharris          );
595230557Sjimharris}
596230557Sjimharris
597230557Sjimharris#ifdef ENABLE_OSSL_COPY_BUFFER
598230557Sjimharrisvoid scic_cb_io_request_copy_buffer(
599230557Sjimharris   void * scic_user_io_request,
600230557Sjimharris   U8    *source_addr,
601230557Sjimharris   U32   offset,
602230557Sjimharris   U32   length
603230557Sjimharris)
604230557Sjimharris{
605230557Sjimharris   SCIF_SAS_REQUEST_T *fw_request =
606230557Sjimharris      (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
607230557Sjimharris
608230557Sjimharris   return scif_cb_io_request_copy_buffer(
609230557Sjimharris             sci_object_get_association(fw_request),
610230557Sjimharris             source_addr,
611230557Sjimharris             offset,
612230557Sjimharris             length
613230557Sjimharris          );
614230557Sjimharris}
615230557Sjimharris#endif
616230557Sjimharris// ---------------------------------------------------------------------------
617230557Sjimharris
618230557SjimharrisSCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
619230557Sjimharris{
620230557Sjimharris   scif_sas_stp_io_request_constructed_start_handler,
621230557Sjimharris   scif_sas_io_request_constructed_abort_handler,
622230557Sjimharris   scif_sas_stp_io_request_constructed_complete_handler,
623230557Sjimharris   scif_sas_io_request_default_destruct_handler
624230557Sjimharris};
625230557Sjimharris
626