xref: /freebsd/sys/dev/isci/scil/scif_sas_stp_io_request.c (revision 3ef51c5fb9163f2aafb1c14729e06a8bf0c4d113)
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    return SCI_SUCCESS;
175 }
176 /**
177  * @brief This method provides SATA/STP STARTED state specific handling for
178  *        when the user attempts to complete the supplied IO request.
179  *        It will perform data/response translation and free NCQ tags
180  *        if necessary.
181  *
182  * @param[in] io_request This parameter specifies the IO request object
183  *            to be started.
184  *
185  * @return This method returns a value indicating if the IO request was
186  *         successfully completed or not.
187  */
188 static
189 SCI_STATUS scif_sas_stp_core_cb_io_request_complete_handler(
190    SCIF_SAS_CONTROLLER_T    * fw_controller,
191    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
192    SCIF_SAS_REQUEST_T       * fw_request,
193    SCI_STATUS               * completion_status
194 )
195 {
196    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
197 
198    SCIF_LOG_TRACE((
199       sci_base_object_get_logger(fw_controller),
200       SCIF_LOG_OBJECT_IO_REQUEST,
201       "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
202       fw_controller, fw_device, fw_request, *completion_status
203    ));
204 
205    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA)
206       scif_sas_stp_remote_device_free_ncq_tag(
207          fw_request->device, fw_io->parent.stp.ncq_tag
208       );
209 
210    // Translating the response is only necessary if:
211    // - some sort of error occurred resulting in having the error bit
212    //   set in the ATA status register and values to decode in the
213    //   ATA error register.
214    // - the command returns information in the register FIS itself,
215    //   which requires translation.
216    // - the request completed ok but the sequence requires a callback
217    //   to possibly continue the translation
218    if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ||
219        ((sati_cb_do_translate_response(fw_request)) &&
220         (*completion_status != SCI_FAILURE_IO_TERMINATED)))
221    {
222       SATI_STATUS sati_status = sati_translate_command_response(
223                                    &fw_io->parent.stp.sequence, fw_io, fw_io
224                                 );
225       if (sati_status == SATI_COMPLETE)
226          *completion_status = SCI_SUCCESS;
227       else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
228          *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
229       else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
230       {
231          // The translation indicates that additional SATA requests are
232          // necessary to finish the original SCSI request.  As a result,
233          // do not complete the IO and begin the next stage of the
234          // translation.
235          return SCI_WARNING_SEQUENCE_INCOMPLETE;
236       }
237       else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY)
238          *completion_status = SCI_SUCCESS_IO_DONE_EARLY;
239       else
240       {
241          // Something unexpected occurred during translation.  Fail the
242          // IO request to the user.
243          *completion_status = SCI_FAILURE;
244       }
245    }
246    else if (*completion_status != SCI_SUCCESS)
247    {
248       SCIF_LOG_INFO((
249          sci_base_object_get_logger(fw_controller),
250          SCIF_LOG_OBJECT_IO_REQUEST,
251          "Sequence Terminated(0x%x, 0x%x, 0x%x)\n",
252          fw_controller, fw_device, fw_request
253       ));
254 
255       sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
256    }
257 
258    return SCI_SUCCESS;
259 }
260 
261 #if !defined(DISABLE_ATAPI)
262 /**
263  * @brief This method provides STP PACKET io request STARTED state specific handling for
264  *        when the user attempts to complete the supplied IO request.
265  *        It will perform data/response translation.
266  *
267  * @param[in] io_request This parameter specifies the IO request object
268  *            to be started.
269  *
270  * @return This method returns a value indicating if the IO request was
271  *         successfully completed or not.
272  */
273 static
274 SCI_STATUS scif_sas_stp_core_cb_packet_io_request_complete_handler(
275    SCIF_SAS_CONTROLLER_T    * fw_controller,
276    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
277    SCIF_SAS_REQUEST_T       * fw_request,
278    SCI_STATUS               * completion_status
279 )
280 {
281    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request;
282    SATI_STATUS sati_status;
283 
284    SCIF_LOG_TRACE((
285       sci_base_object_get_logger(fw_controller),
286       SCIF_LOG_OBJECT_IO_REQUEST,
287       "scif_sas_stp_packet_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
288       fw_controller, fw_device, fw_request, *completion_status
289    ));
290 
291    if (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID)
292    {
293       sati_status = sati_atapi_translate_command_response(
294                        &fw_io->parent.stp.sequence, fw_io, fw_io
295                     );
296 
297       if (sati_status == SATI_COMPLETE)
298          *completion_status = SCI_SUCCESS;
299       else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
300          *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
301       else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
302       {
303          // The translation indicates that additional REQUEST SENSE command is
304          // necessary to finish the original SCSI request.  As a result,
305          // do not complete the IO and begin the next stage of the IO.
306          return SCI_WARNING_SEQUENCE_INCOMPLETE;
307       }
308       else
309       {
310          // Something unexpected occurred during translation.  Fail the
311          // IO request to the user.
312          *completion_status = SCI_FAILURE;
313       }
314    }
315    else if (*completion_status == SCI_SUCCESS &&
316         fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
317    {
318       //The internal Request Sense command is completed successfully.
319       sati_atapi_translate_request_sense_response(
320          &fw_io->parent.stp.sequence, fw_io, fw_io
321       );
322 
323       *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
324    }
325 
326    return SCI_SUCCESS;
327 }
328 #endif // !defined(DISABLE_ATAPI)
329 
330 //******************************************************************************
331 // P R O T E C T E D   M E T H O D S
332 //******************************************************************************
333 
334 /**
335  * @brief This method will construct the SATA/STP specific IO request
336  *        object utilizing the SATI.
337  *
338  * @pre The scif_sas_request_construct() method should be invoked before
339  *      calling this method.
340  *
341  * @param[in,out] stp_io_request This parameter specifies the stp_io_request
342  *                to be constructed.
343  *
344  * @return Indicate if the construction was successful.
345  * @return SCI_FAILURE_NO_NCQ_TAG_AVAILABLE
346  * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
347  * @return SCI_FAILURE_IO_RESPONSE_VALID
348  * @return SCI_FAILURE This return value indicates a change in the translator
349  *         where a new return code has been given, but is not yet understood
350  *         by this routine.
351  */
352 SCI_STATUS scif_sas_stp_io_request_construct(
353    SCIF_SAS_IO_REQUEST_T * fw_io
354 )
355 {
356    SATI_STATUS                sati_status;
357    SCI_STATUS                 sci_status = SCI_FAILURE;
358    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
359 
360    SCIF_LOG_TRACE((
361       sci_base_object_get_logger(fw_io),
362       SCIF_LOG_OBJECT_IO_REQUEST,
363       "scif_sas_stp_io_request_construct(0x%x) enter\n",
364       fw_io
365    ));
366 
367    // The translator will indirectly invoke core methods to set the fields
368    // of the ATA register FIS inside of this method.
369    sati_status = sati_translate_command(
370                     &fw_io->parent.stp.sequence,
371                     &fw_device->protocol_device.stp_device.sati_device,
372                     fw_io,
373                     fw_io
374                  );
375 
376    if (sati_status == SATI_SUCCESS)
377    {
378       // Allow the core to finish construction of the IO request.
379       sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
380       fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
381       fw_io->parent.protocol_complete_handler
382          = scif_sas_stp_core_cb_io_request_complete_handler;
383    }
384    else if (sati_status == SATI_SUCCESS_SGL_TRANSLATED)
385    {
386       SCIC_IO_SATA_PARAMETERS_T parms;
387       parms.do_translate_sgl = FALSE;
388 
389       // The translation actually already caused translation of the
390       // scatter gather list.  So, call into the core through an API
391       // that will not attempt to translate the SGL.
392       scic_io_request_construct_advanced_sata(
393                       fw_io->parent.core_object, &parms
394                    );
395       fw_io->parent.state_handlers = &stp_io_request_constructed_handlers;
396       fw_io->parent.protocol_complete_handler
397          = scif_sas_stp_core_cb_io_request_complete_handler;
398       // Done with translation
399       sci_status = SCI_SUCCESS;
400    }
401    else if (sati_status == SATI_COMPLETE)
402       sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
403    else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
404       sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
405    else
406    {
407       SCIF_LOG_ERROR((
408          sci_base_object_get_logger(fw_io),
409          SCIF_LOG_OBJECT_IO_REQUEST,
410          "Unexpected SAT translation failure 0x%x\n",
411          fw_io
412       ));
413    }
414 
415    return sci_status;
416 }
417 
418 
419 #if !defined(DISABLE_ATAPI)
420 /**
421  * @brief This method will construct the STP PACKET protocol specific IO
422  *        request object.
423  *
424  * @pre The scif_sas_request_construct() method should be invoked before
425  *      calling this method.
426  *
427  * @param[in,out] fw_io This parameter specifies the stp packet io request
428  *                to be constructed.
429  *
430  * @return Indicate if the construction was successful.
431  * @return SCI_SUCCESS_IO_COMPLETE_BEFORE_START
432  * @return SCI_FAILURE_IO_RESPONSE_VALID
433  * @return SCI_FAILURE This return value indicates a change in the translator
434  *         where a new return code has been given, but is not yet understood
435  *         by this routine.
436  */
437 SCI_STATUS scif_sas_stp_packet_io_request_construct(
438    SCIF_SAS_IO_REQUEST_T * fw_io
439 )
440 {
441    SATI_STATUS                sati_status;
442    SCI_STATUS                 sci_status = SCI_FAILURE;
443    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = fw_io->parent.device;
444 
445    SCIF_LOG_TRACE((
446       sci_base_object_get_logger(fw_io),
447       SCIF_LOG_OBJECT_IO_REQUEST,
448       "scif_sas_stp_packet_io_request_construct(0x%x) enter\n",
449       fw_io
450    ));
451 
452    sati_status = sati_atapi_translate_command(
453                     &fw_io->parent.stp.sequence,
454                     &fw_device->protocol_device.stp_device.sati_device,
455                     fw_io,
456                     fw_io
457                  );
458 
459    if (sati_status == SATI_SUCCESS)
460    {
461       // Allow the core to finish construction of the IO request.
462       sci_status = scic_io_request_construct_basic_sata(fw_io->parent.core_object);
463 
464       fw_io->parent.protocol_complete_handler
465          = scif_sas_stp_core_cb_packet_io_request_complete_handler;
466    }
467    else if (sati_status == SATI_COMPLETE)
468       sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START;
469    else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
470       sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
471    else
472    {
473       SCIF_LOG_ERROR((
474          sci_base_object_get_logger(fw_io),
475          SCIF_LOG_OBJECT_IO_REQUEST,
476          "Unexpected SAT ATAPI translation failure 0x%x\n",
477          fw_io
478       ));
479    }
480 
481    return sci_status;
482 }
483 #endif
484 
485 
486 #if !defined(DISABLE_ATAPI)
487 /**
488  * @brief This method will get the number of bytes transferred in an packet IO.
489  *
490  * @param[in] fw_io This parameter specifies the stp packet io request whose
491  *                     actual transferred length is to be retrieved.
492  *
493  * @return Actual length of transferred data.
494  */
495 U32 scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(
496    SCIF_SAS_IO_REQUEST_T * fw_io
497 )
498 {
499    SCI_IO_REQUEST_HANDLE_T scic_io = scif_io_request_get_scic_handle(fw_io);
500    SCI_IO_STATUS io_status = scic_request_get_sci_status (scic_io);
501    U32 actual_data_length;
502 
503    if (io_status == SCI_IO_FAILURE_RESPONSE_VALID)
504        actual_data_length = 0;
505    else if (io_status == SCI_IO_SUCCESS_IO_DONE_EARLY)
506    {
507       actual_data_length = sati_atapi_translate_number_of_bytes_transferred(
508          &fw_io->parent.stp.sequence, fw_io, fw_io);
509 
510       if (actual_data_length == 0)
511          actual_data_length =
512             scic_io_request_get_number_of_bytes_transferred(scic_io);
513    }
514    else
515       actual_data_length =
516          scic_io_request_get_number_of_bytes_transferred(scic_io);
517 
518    return actual_data_length;
519 }
520 #endif
521 
522 
523 //******************************************************************************
524 // P U B L I C   M E T H O D S
525 //******************************************************************************
526 
527 BOOL scic_cb_io_request_do_copy_rx_frames(
528    void * scic_user_io_request
529 )
530 {
531    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
532 
533    SCIF_LOG_TRACE((
534       sci_base_object_get_logger(fw_io),
535       SCIF_LOG_OBJECT_IO_REQUEST,
536       "scic_cb_io_request_do_copy_rx_frames(0x%x) enter\n",
537       fw_io
538    ));
539 
540    // If the translation was a PIO DATA IN (i.e. read) and the request
541    // was actually a READ payload operation, then copy the data, since
542    // there will be SGL space allocated for the transfer.
543    if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_PIO_DATA_IN)
544    {
545       if (
546             (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_12)
547          || (fw_io->parent.stp.sequence.type ==  SATI_SEQUENCE_ATA_PASSTHROUGH_16)
548          || (
549                (fw_io->parent.stp.sequence.type >= SATI_SEQUENCE_TYPE_READ_MIN)
550             && (fw_io->parent.stp.sequence.type <= SATI_SEQUENCE_TYPE_READ_MAX)
551             )
552          )
553       {
554            SCIF_LOG_TRACE((
555                  sci_base_object_get_logger(fw_io),
556                  SCIF_LOG_OBJECT_IO_REQUEST,
557                  "scic_cb_io_request_do_copy_rx_frames(0x%x) TRUE\n",
558                  fw_io
559               ));
560            return TRUE;
561       }
562    }
563 
564    // For all other requests we leave the data in the core buffers.
565    // This allows the translation to translate without having to have
566    // separate space allocated into which to copy the data.
567    return FALSE;
568 }
569 
570 // ---------------------------------------------------------------------------
571 
572 U8 scic_cb_request_get_sat_protocol(
573    void * scic_user_io_request
574 )
575 {
576    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scic_user_io_request;
577 
578    return fw_io->parent.stp.sequence.protocol;
579 }
580 
581 U8 *scic_cb_io_request_get_virtual_address_from_sgl(
582    void * scic_user_io_request,
583    U32    byte_offset
584 )
585 {
586    SCIF_SAS_REQUEST_T *fw_request =
587       (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);
588 
589    return scif_cb_io_request_get_virtual_address_from_sgl(
590              sci_object_get_association(fw_request),
591              byte_offset
592           );
593 }
594 
595 #ifdef ENABLE_OSSL_COPY_BUFFER
596 void scic_cb_io_request_copy_buffer(
597    void * scic_user_io_request,
598    U8    *source_addr,
599    U32   offset,
600    U32   length
601 )
602 {
603    SCIF_SAS_REQUEST_T *fw_request =
604       (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);
605 
606    return scif_cb_io_request_copy_buffer(
607              sci_object_get_association(fw_request),
608              source_addr,
609              offset,
610              length
611           );
612 }
613 #endif
614 // ---------------------------------------------------------------------------
615 
616 SCI_BASE_REQUEST_STATE_HANDLER_T stp_io_request_constructed_handlers =
617 {
618    scif_sas_stp_io_request_constructed_start_handler,
619    scif_sas_io_request_constructed_abort_handler,
620    scif_sas_stp_io_request_constructed_complete_handler,
621    scif_sas_io_request_default_destruct_handler
622 };
623 
624