1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23  * The full GNU General Public License is included in this distribution
24  * in the file called LICENSE.GPL.
25  *
26  * BSD LICENSE
27  *
28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  *   * Redistributions of source code must retain the above copyright
36  *     notice, this list of conditions and the following disclaimer.
37  *   * Redistributions in binary form must reproduce the above copyright
38  *     notice, this list of conditions and the following disclaimer in
39  *     the documentation and/or other materials provided with the
40  *     distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
57 
58 /**
59  * @file
60  *
61  * @brief This file contains the method implementations for the
62  *        SCIF_SAS_STP_IO_REQUEST object.  The contents will implement
63  *        SATA/STP specific functionality.
64  */
65 
66 #include <dev/isci/scil/scif_sas_stp_io_request.h>
67 #include <dev/isci/scil/scif_sas_stp_remote_device.h>
68 #include <dev/isci/scil/scif_sas_logger.h>
69 #include <dev/isci/scil/scif_sas_controller.h>
70 
71 #include <dev/isci/scil/sci_status.h>
72 #include <dev/isci/scil/scic_io_request.h>
73 
74 #include <dev/isci/scil/sati.h>
75 #include <dev/isci/scil/sati_atapi.h>
76 #include <dev/isci/scil/intel_sat.h>
77 #include <dev/isci/scil/sati_util.h>
78 #include <dev/isci/scil/sati_callbacks.h>
79 
80 //******************************************************************************
81 // P R I V A T E   M E T H O D S
82 //******************************************************************************
83 
84 /**
85  * @brief This method provides SATA/STP CONSTRUCTED state specific handling
86  *        for when the user attempts to start the supplied IO request.  It
87  *        will allocate NCQ tags if necessary.
88  *
89  * @param[in] io_request This parameter specifies the IO request object
90  *            to be started.
91  *
92  * @return This method returns a value indicating if the IO request was
93  *         successfully started or not.
94  * @retval SCI_SUCCESS This return value indicates successful starting
95  *         of the IO request.
96  */
97 static
98 SCI_STATUS scif_sas_stp_io_request_constructed_start_handler(
99    SCI_BASE_REQUEST_T * io_request
100 )
101 {
102    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
103 
104    SCIF_LOG_TRACE((
105       sci_base_object_get_logger(io_request),
106       SCIF_LOG_OBJECT_IO_REQUEST,
107       "scif_sas_stp_io_request_constructed_start_handler(0x%x) enter\n",
108       io_request
109    ));
110 
111    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
112    {
113       SATA_FIS_REG_H2D_T * fis;
114 
115       // For NCQ, we need to attempt to allocate an available tag.
116       fw_io->parent.stp.ncq_tag = scif_sas_stp_remote_device_allocate_ncq_tag(
117                                      fw_io->parent.device
118                                   );
119 
120       if (fw_io->parent.stp.ncq_tag == SCIF_SAS_INVALID_NCQ_TAG)
121          return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE;
122 
123       // Set the NCQ tag in the host to device register FIS (upper 5 bits
124       // of the 8-bit sector count register).
125       fis = scic_stp_io_request_get_h2d_reg_address(fw_io->parent.core_object);
126       fis->sector_count = (fw_io->parent.stp.ncq_tag << 3);
127 
128       // The Core also requires that we inform it separately regarding the
129       // NCQ tag for this IO.
130       scic_stp_io_request_set_ncq_tag(
131          fw_io->parent.core_object, fw_io->parent.stp.ncq_tag
132       );
133    }
134 
135    return SCI_SUCCESS;
136 }
137 
138 /**
139  * @brief This method provides SATA/STP CONSTRUCTED state specific handling
140  *        for when the user attempts to complete the supplied IO request.
141  *        This method will be invoked in the event the call to start the
142  *        core IO request fails for some reason.  In this situation, the
143  *        NCQ tag will be freed.
144  *
145  * @param[in] io_request This parameter specifies the IO request object
146  *            to be started.
147  *
148  * @return This method returns a value indicating if the IO request was
149  *         successfully started or not.
150  * @retval SCI_SUCCESS This return value indicates successful starting
151  *         of the IO request.
152  */
153 static
154 SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler(
155    SCI_BASE_REQUEST_T * io_request
156 )
157 {
158    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) io_request;
159 
160    SCIF_LOG_TRACE((
161       sci_base_object_get_logger(io_request),
162       SCIF_LOG_OBJECT_IO_REQUEST,
163       "scif_sas_stp_io_request_constructed_complete_handler(0x%x) enter\n",
164       io_request
165    ));
166 
167    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
168    {
169       // For NCQ, we need to return the tag back to the free pool.
170       if (fw_io->parent.stp.ncq_tag != SCIF_SAS_INVALID_NCQ_TAG)
171          scif_sas_stp_remote_device_free_ncq_tag(
172             fw_io->parent.device, fw_io->parent.stp.ncq_tag
173          );
174    }
175 
176    sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
177 
178    return SCI_SUCCESS;
179 }
180 /**
181  * @brief This method provides SATA/STP STARTED state specific handling for
182  *        when the user attempts to complete the supplied IO request.
183  *        It will perform data/response translation and free NCQ tags
184  *        if necessary.
185  *
186  * @param[in] io_request This parameter specifies the IO request object
187  *            to be started.
188  *
189  * @return This method returns a value indicating if the IO request was
190  *         successfully completed or not.
191  */
192 static
193 SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
194    SCIF_SAS_CONTROLLER_T    * fw_controller,
195    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
196    SCIF_SAS_REQUEST_T       * fw_request,
197    SCI_STATUS               * completion_status
198 )
199 {
200    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
201 
202    SCIF_LOG_TRACE((
203       sci_base_object_get_logger(fw_controller),
204       SCIF_LOG_OBJECT_IO_REQUEST,
205       "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
206       fw_controller, fw_device, fw_request, *completion_status
207    ));
208 
209    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
210       scif_sas_stp_remote_device_free_ncq_tag(
211          fw_request->device, fw_io->parent.stp.ncq_tag
212       );
213 
214    // Translating the response is only necessary if:
215    // - some sort of error occurred resulting in having the error bit
216    //   set in the ATA status register and values to decode in the
217    //   ATA error register.
218    // - the command returns information in the register FIS itself,
219    //   which requires translation.
220    // - the request completed ok but the sequence requires a callback
221    //   to possibly continue the translation
222    if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
223        ((sati_cb_do_translate_response(fw_request)) &&
224         (*completion_status != SCI_FAILURE_IO_TERMINATED)))
225    {
226       SATI_STATUS sati_status = sati_translate_command_response(
227                                    &fw_io->parent.stp.sequence, fw_io, fw_io
228                                 );
229       if (sati_status == SATI_COMPLETE)
230          *completion_status = SCI_SUCCESS;
231       else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
232          *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
233       else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
234       {
235          // The translation indicates that additional SATA requests are
236          // necessary to finish the original SCSI request.  As a result,
237          // do not complete the IO and begin the next stage of the
238          // translation.
239          return SCI_WARNING_SEQUENCE_INCOMPLETE;
240       }
241       else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
242          *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
243       else
244       {
245          // Something unexpected occurred during translation.  Fail the
246          // IO request to the user.
247          *completion_status = SCI_FAILURE;
248       }
249    }
250    else if (*completion_status != SCI_SUCCESS)
251    {
252       SCIF_LOG_INFO((
253          sci_base_object_get_logger(fw_controller),
254          SCIF_LOG_OBJECT_IO_REQUEST,
255          "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
256          fw_controller, fw_device, fw_request
257       ));
258 
259       sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
260    }
261 
262    return SCI_SUCCESS;
263 }
264 
265 #if !defined(DISABLE_ATAPI)
266 /**
267  * @brief This method provides STP PACKET io request STARTED state specific handling for
268  *        when the user attempts to complete the supplied IO request.
269  *        It will perform data/response translation.
270  *
271  * @param[in] io_request This parameter specifies the IO request object
272  *            to be started.
273  *
274  * @return This method returns a value indicating if the IO request was
275  *         successfully completed or not.
276  */
277 static
278 SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
279    SCIF_SAS_CONTROLLER_T    * fw_controller,
280    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
281    SCIF_SAS_REQUEST_T       * fw_request,
282    SCI_STATUS               * completion_status
283 )
284 {
285    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
286    SATI_STATUS sati_status;
287 
288    SCIF_LOG_TRACE((
289       sci_base_object_get_logger(fw_controller),
290       SCIF_LOG_OBJECT_IO_REQUEST,
291       "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
292       fw_controller, fw_device, fw_request, *completion_status
293    ));
294 
295    if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
296    {
297       sati_status = sati_atapi_translate_command_response(
298                        &fw_io->parent.stp.sequence, fw_io, fw_io
299                     );
300 
301       if (sati_status == SATI_COMPLETE)
302          *completion_status = SCI_SUCCESS;
303       else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
304          *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
305       else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
306       {
307          // The translation indicates that additional REQUEST SENSE command is
308          // necessary to finish the original SCSI request.  As a result,
309          // do not complete the IO and begin the next stage of the IO.
310          return SCI_WARNING_SEQUENCE_INCOMPLETE;
311       }
312       else
313       {
314          // Something unexpected occurred during translation.  Fail the
315          // IO request to the user.
316          *completion_status = SCI_FAILURE;
317       }
318    }
319    else if (*completion_status == SCI_SUCCESS &&
320         fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
321    {
322       //The internal Request Sense command is completed successfully.
323       sati_atapi_translate_request_sense_response(
324          &fw_io->parent.stp.sequence, fw_io, fw_io
325       );
326 
327       *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
328    }
329 
330    return SCI_SUCCESS;
331 }
332 #endif // !defined(DISABLE_ATAPI)
333 
334 //******************************************************************************
335 // P R O T E C T E D   M E T H O D S
336 //******************************************************************************
337 
338 /**
339  * @brief This method will construct the SATA/STP specific IO request
340  *        object utilizing the SATI.
341  *
342  * @pre The scif_sas_request_construct() method should be invoked before
343  *      calling this method.
344  *
345  * @param[in,out] stp_io_request This parameter specifies the stp_io_request
346  *                to be constructed.
347  *
348  * @return Indicate if the construction was successful.
349  * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
350  * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
351  * @return SCI_FAILURE_IO_RESPONSE_VALID
352  * @return SCI_FAILURE This return value indicates a change in the translator
353  *         where a new return code has been given, but is not yet understood
354  *         by this routine.
355  */
356 SCI_STATUS scif_sas_stp_io_request_construct(
357    SCIF_SAS_IO_REQUEST_T * fw_io
358 )
359 {
360    SATI_STATUS                sati_status;
361    SCI_STATUS                 sci_status = SCI_FAILURE;
362    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
363 
364    SCIF_LOG_TRACE((
365       sci_base_object_get_logger(fw_io),
366       SCIF_LOG_OBJECT_IO_REQUEST,
367       "scif_sas_stp_io_request_construct(0x%x) enter\n",
368       fw_io
369    ));
370 
371    // The translator will indirectly invoke core methods to set the fields
372    // of the ATA register FIS inside of this method.
373    sati_status = sati_translate_command(
374                     &fw_io->parent.stp.sequence,
375                     &fw_device->protocol_device.stp_device.sati_device,
376                     fw_io,
377                     fw_io
378                  );
379 
380    if (sati_status == SATI_SUCCESS)
381    {
382       // Allow the core to finish construction of the IO request.
383       sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
384       fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
385       fw_io->parent.protocol_complete_handler
386          = scif_sas_stp_core_cb_io_request_complete_handler;
387    }
388    else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
389    {
390       SCIC_IO_SATA_PARAMETERS_T parms;
391       parms.do_translate_sgl = FALSE;
392 
393       // The translation actually already caused translation of the
394       // scatter gather list.  So, call into the core through an API
395       // that will not attempt to translate the SGL.
396       scic_io_request_construct_advanced_sata(
397                       fw_io->parent.core_object, &parms
398                    );
399       fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
400       fw_io->parent.protocol_complete_handler
401          = scif_sas_stp_core_cb_io_request_complete_handler;
402       // Done with translation
403       sci_status = SCI_SUCCESS;
404    }
405    else if (sati_status == SATI_COMPLETE)
406       sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
407    else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
408       sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
409    else
410    {
411       SCIF_LOG_ERROR((
412          sci_base_object_get_logger(fw_io),
413          SCIF_LOG_OBJECT_IO_REQUEST,
414          "Unexpected SAT translation failure 0x%x\n",
415          fw_io
416       ));
417    }
418 
419    return sci_status;
420 }
421 
422 
423 #if !defined(DISABLE_ATAPI)
424 /**
425  * @brief This method will construct the STP PACKET protocol specific IO
426  *        request object.
427  *
428  * @pre The scif_sas_request_construct() method should be invoked before
429  *      calling this method.
430  *
431  * @param[in,out] fw_io This parameter specifies the stp packet io request
432  *                to be constructed.
433  *
434  * @return Indicate if the construction was successful.
435  * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
436  * @return SCI_FAILURE_IO_RESPONSE_VALID
437  * @return SCI_FAILURE This return value indicates a change in the translator
438  *         where a new return code has been given, but is not yet understood
439  *         by this routine.
440  */
441 SCI_STATUS scif_sas_stp_packet_io_request_construct(
442    SCIF_SAS_IO_REQUEST_T * fw_io
443 )
444 {
445    SATI_STATUS                sati_status;
446    SCI_STATUS                 sci_status = SCI_FAILURE;
447    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
448 
449    SCIF_LOG_TRACE((
450       sci_base_object_get_logger(fw_io),
451       SCIF_LOG_OBJECT_IO_REQUEST,
452       "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
453       fw_io
454    ));
455 
456    sati_status = sati_atapi_translate_command(
457                     &fw_io->parent.stp.sequence,
458                     &fw_device->protocol_device.stp_device.sati_device,
459                     fw_io,
460                     fw_io
461                  );
462 
463    if (sati_status == SATI_SUCCESS)
464    {
465       // Allow the core to finish construction of the IO request.
466       sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
467 
468       fw_io->parent.protocol_complete_handler
469          = scif_sas_stp_core_cb_packet_io_request_complete_handler;
470    }
471    else if (sati_status == SATI_COMPLETE)
472       sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
473    else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
474       sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
475    else
476    {
477       SCIF_LOG_ERROR((
478          sci_base_object_get_logger(fw_io),
479          SCIF_LOG_OBJECT_IO_REQUEST,
480          "Unexpected SAT ATAPI translation failure 0x%x\n",
481          fw_io
482       ));
483    }
484 
485    return sci_status;
486 }
487 #endif
488 
489 
490 #if !defined(DISABLE_ATAPI)
491 /**
492  * @brief This method will get the number of bytes transferred in an packet IO.
493  *
494  * @param[in] fw_io This parameter specifies the stp packet io request whose
495  *                     actual transferred length is to be retrieved.
496  *
497  * @return Actual length of transferred data.
498  */
499 U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
500    SCIF_SAS_IO_REQUEST_T * fw_io
501 )
502 {
503    SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
504    SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
505    U32 actual_data_length;
506 
507    if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
508        actual_data_length = 0;
509    else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
510    {
511       actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
512          &fw_io->parent.stp.sequence, fw_io, fw_io);
513 
514       if (actual_data_length == 0)
515          actual_data_length =
516             scic_io_request_get_number_of_bytes_transferred(scic_io);
517    }
518    else
519       actual_data_length =
520          scic_io_request_get_number_of_bytes_transferred(scic_io);
521 
522    return actual_data_length;
523 }
524 #endif
525 
526 
527 //******************************************************************************
528 // P U B L I C   M E T H O D S
529 //******************************************************************************
530 
531 BOOL scic_cb_io_request_do_copy_rx_frames(
532    void * scic_user_io_request
533 )
534 {
535    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
536 
537    SCIF_LOG_TRACE((
538       sci_base_object_get_logger(fw_io),
539       SCIF_LOG_OBJECT_IO_REQUEST,
540       "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
541       fw_io
542    ));
543 
544    // If the translation was a PIO DATA IN (i.e. read) and the request
545    // was actually a READ payload operation, then copy the data, since
546    // there will be SGL space allocated for the transfer.
547    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
548    {
549       if (
550             (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_12)
551          || (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_16)
552          || (
553                (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
554             && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
555             )
556          )
557       {
558            SCIF_LOG_TRACE((
559                  sci_base_object_get_logger(fw_io),
560                  SCIF_LOG_OBJECT_IO_REQUEST,
561                  "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
562                  fw_io
563               ));
564            return TRUE;
565       }
566    }
567 
568    // For all other requests we leave the data in the core buffers.
569    // This allows the translation to translate without having to have
570    // separate space allocated into which to copy the data.
571    return FALSE;
572 }
573 
574 // ---------------------------------------------------------------------------
575 
576 U8 scic_cb_request_get_sat_protocol(
577    void * scic_user_io_request
578 )
579 {
580    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
581 
582    return fw_io->parent.stp.sequence.protocol;
583 }
584 
585 U8 *scic_cb_io_request_get_virtual_address_from_sgl(
586    void * scic_user_io_request,
587    U32    byte_offset
588 )
589 {
590    SCIF_SAS_REQUEST_T *fw_request =
591       (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
592 
593    return scif_cb_io_request_get_virtual_address_from_sgl(
594              sci_object_get_association(fw_request),
595              byte_offset
596           );
597 }
598 
599 #ifdef ENABLE_OSSL_COPY_BUFFER
600 void scic_cb_io_request_copy_buffer(
601    void * scic_user_io_request,
602    U8    *source_addr,
603    U32   offset,
604    U32   length
605 )
606 {
607    SCIF_SAS_REQUEST_T *fw_request =
608       (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
609 
610    return scif_cb_io_request_copy_buffer(
611              sci_object_get_association(fw_request),
612              source_addr,
613              offset,
614              length
615           );
616 }
617 #endif
618 // ---------------------------------------------------------------------------
619 
620 SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
621 {
622    scif_sas_stp_io_request_constructed_start_handler,
623    scif_sas_io_request_constructed_abort_handler,
624    scif_sas_stp_io_request_constructed_complete_handler,
625    scif_sas_io_request_default_destruct_handler
626 };
627 
628