1/*-
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.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
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.
12 *
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.
17 *
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.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
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
38 *     distribution.
39 *
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.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD$");
55
56/**
57 * @file
58 *
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.
62 */
63
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>
68
69#include <dev/isci/scil/sci_status.h>
70#include <dev/isci/scil/scic_io_request.h>
71
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>
77
78//******************************************************************************
79// P R I V A T E   M E T H O D S
80//******************************************************************************
81
82/**
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.
86 *
87 * @param[in] io_request This parameter specifies the IO request object
88 *            to be started.
89 *
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
93 *         of the IO request.
94 */
95static
96SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
97   SCI_BASE_REQUEST_T * io_request
98)
99{
100   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
101
102   SCIF_LOG_TRACE((
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",
106      io_request
107   ));
108
109   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
110   {
111      SATA_FIS_REG_H2D_T * fis;
112
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(
115                                     fw_io->parent.device
116                                  );
117
118      if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
119         return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
120
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);
125
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
130      );
131   }
132
133   return SCI_SUCCESS;
134}
135
136/**
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.
142 *
143 * @param[in] io_request This parameter specifies the IO request object
144 *            to be started.
145 *
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
149 *         of the IO request.
150 */
151static
152SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
153   SCI_BASE_REQUEST_T * io_request
154)
155{
156   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
157
158   SCIF_LOG_TRACE((
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",
162      io_request
163   ));
164
165   if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
166   {
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
171         );
172   }
173
174   sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
175
176   return SCI_SUCCESS;
177}
178/**
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
182 *        if necessary.
183 *
184 * @param[in] io_request This parameter specifies the IO request object
185 *            to be started.
186 *
187 * @return This method returns a value indicating if the IO request was
188 *         successfully completed or not.
189 */
190static
191SCI_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
196)
197{
198   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
199
200   SCIF_LOG_TRACE((
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
205   ));
206
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
210      );
211
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)))
223   {
224      SATI_STATUS sati_status = sati_translate_command_response(
225                                   &fw_io->parent.stp.sequence, fw_io, fw_io
226                                );
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)
232      {
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
236         // translation.
237         return SCI_WARNING_SEQUENCE_INCOMPLETE;
238      }
239      else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
240         *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
241      else
242      {
243         // Something unexpected occurred during translation.  Fail the
244         // IO request to the user.
245         *completion_status = SCI_FAILURE;
246      }
247   }
248   else if (*completion_status != SCI_SUCCESS)
249   {
250      SCIF_LOG_INFO((
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
255      ));
256
257      sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
258   }
259
260   return SCI_SUCCESS;
261}
262
263#if !defined(DISABLE_ATAPI)
264/**
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.
268 *
269 * @param[in] io_request This parameter specifies the IO request object
270 *            to be started.
271 *
272 * @return This method returns a value indicating if the IO request was
273 *         successfully completed or not.
274 */
275static
276SCI_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
281)
282{
283   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
284   SATI_STATUS sati_status;
285
286   SCIF_LOG_TRACE((
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
291   ));
292
293   if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
294   {
295      sati_status = sati_atapi_translate_command_response(
296                       &fw_io->parent.stp.sequence, fw_io, fw_io
297                    );
298
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)
304      {
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;
309      }
310      else
311      {
312         // Something unexpected occurred during translation.  Fail the
313         // IO request to the user.
314         *completion_status = SCI_FAILURE;
315      }
316   }
317   else if (*completion_status == SCI_SUCCESS &&
318        fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
319   {
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
323      );
324
325      *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
326   }
327
328   return SCI_SUCCESS;
329}
330#endif // !defined(DISABLE_ATAPI)
331
332//******************************************************************************
333// P R O T E C T E D   M E T H O D S
334//******************************************************************************
335
336/**
337 * @brief This method will construct the SATA/STP specific IO request
338 *        object utilizing the SATI.
339 *
340 * @pre The scif_sas_request_construct() method should be invoked before
341 *      calling this method.
342 *
343 * @param[in,out] stp_io_request This parameter specifies the stp_io_request
344 *                to be constructed.
345 *
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
352 *         by this routine.
353 */
354SCI_STATUS scif_sas_stp_io_request_construct(
355   SCIF_SAS_IO_REQUEST_T * fw_io
356)
357{
358   SATI_STATUS                sati_status;
359   SCI_STATUS                 sci_status = SCI_FAILURE;
360   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
361
362   SCIF_LOG_TRACE((
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",
366      fw_io
367   ));
368
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,
374                    fw_io,
375                    fw_io
376                 );
377
378   if (sati_status == SATI_SUCCESS)
379   {
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;
385   }
386   else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
387   {
388      SCIC_IO_SATA_PARAMETERS_T parms;
389      parms.do_translate_sgl = FALSE;
390
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
396                   );
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;
402   }
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;
407   else
408   {
409      SCIF_LOG_ERROR((
410         sci_base_object_get_logger(fw_io),
411         SCIF_LOG_OBJECT_IO_REQUEST,
412         "Unexpected SAT translation failure 0x%x\n",
413         fw_io
414      ));
415   }
416
417   return sci_status;
418}
419
420
421#if !defined(DISABLE_ATAPI)
422/**
423 * @brief This method will construct the STP PACKET protocol specific IO
424 *        request object.
425 *
426 * @pre The scif_sas_request_construct() method should be invoked before
427 *      calling this method.
428 *
429 * @param[in,out] fw_io This parameter specifies the stp packet io request
430 *                to be constructed.
431 *
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
437 *         by this routine.
438 */
439SCI_STATUS scif_sas_stp_packet_io_request_construct(
440   SCIF_SAS_IO_REQUEST_T * fw_io
441)
442{
443   SATI_STATUS                sati_status;
444   SCI_STATUS                 sci_status = SCI_FAILURE;
445   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
446
447   SCIF_LOG_TRACE((
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",
451      fw_io
452   ));
453
454   sati_status = sati_atapi_translate_command(
455                    &fw_io->parent.stp.sequence,
456                    &fw_device->protocol_device.stp_device.sati_device,
457                    fw_io,
458                    fw_io
459                 );
460
461   if (sati_status == SATI_SUCCESS)
462   {
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);
465
466      fw_io->parent.protocol_complete_handler
467         = scif_sas_stp_core_cb_packet_io_request_complete_handler;
468   }
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;
473   else
474   {
475      SCIF_LOG_ERROR((
476         sci_base_object_get_logger(fw_io),
477         SCIF_LOG_OBJECT_IO_REQUEST,
478         "Unexpected SAT ATAPI translation failure 0x%x\n",
479         fw_io
480      ));
481   }
482
483   return sci_status;
484}
485#endif
486
487
488#if !defined(DISABLE_ATAPI)
489/**
490 * @brief This method will get the number of bytes transferred in an packet IO.
491 *
492 * @param[in] fw_io This parameter specifies the stp packet io request whose
493 *                     actual transferred length is to be retrieved.
494 *
495 * @return Actual length of transferred data.
496 */
497U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
498   SCIF_SAS_IO_REQUEST_T * fw_io
499)
500{
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;
504
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)
508   {
509      actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
510         &fw_io->parent.stp.sequence, fw_io, fw_io);
511
512      if (actual_data_length == 0)
513         actual_data_length =
514            scic_io_request_get_number_of_bytes_transferred(scic_io);
515   }
516   else
517      actual_data_length =
518         scic_io_request_get_number_of_bytes_transferred(scic_io);
519
520   return actual_data_length;
521}
522#endif
523
524
525//******************************************************************************
526// P U B L I C   M E T H O D S
527//******************************************************************************
528
529BOOL scic_cb_io_request_do_copy_rx_frames(
530   void * scic_user_io_request
531)
532{
533   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
534
535   SCIF_LOG_TRACE((
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",
539      fw_io
540   ));
541
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)
546   {
547      if (
548            (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_12)
549         || (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_16)
550         || (
551               (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
552            && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
553            )
554         )
555      {
556           SCIF_LOG_TRACE((
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",
560                 fw_io
561              ));
562           return TRUE;
563      }
564   }
565
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.
569   return FALSE;
570}
571
572// ---------------------------------------------------------------------------
573
574U8 scic_cb_request_get_sat_protocol(
575   void * scic_user_io_request
576)
577{
578   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
579
580   return fw_io->parent.stp.sequence.protocol;
581}
582
583U8 *scic_cb_io_request_get_virtual_address_from_sgl(
584   void * scic_user_io_request,
585   U32    byte_offset
586)
587{
588   SCIF_SAS_REQUEST_T *fw_request =
589      (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
590
591   return scif_cb_io_request_get_virtual_address_from_sgl(
592             sci_object_get_association(fw_request),
593             byte_offset
594          );
595}
596
597#ifdef ENABLE_OSSL_COPY_BUFFER
598void scic_cb_io_request_copy_buffer(
599   void * scic_user_io_request,
600   U8    *source_addr,
601   U32   offset,
602   U32   length
603)
604{
605   SCIF_SAS_REQUEST_T *fw_request =
606      (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
607
608   return scif_cb_io_request_copy_buffer(
609             sci_object_get_association(fw_request),
610             source_addr,
611             offset,
612             length
613          );
614}
615#endif
616// ---------------------------------------------------------------------------
617
618SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
619{
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
624};
625
626