xref: /freebsd/sys/dev/isci/scil/scif_sas_stp_io_request.c (revision 3a92d97ff0f22d21608e1c19b83104c4937523b6)
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  */
95 static
96 SCI_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  */
151 static
152 SCI_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  */
190 static
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
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  */
275 static
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
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  */
354 SCI_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  */
439 SCI_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  */
497 U32 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 
529 BOOL 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 
574 U8 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 
583 U8 *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
598 void 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 
618 SCI_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