xref: /freebsd/sys/dev/isci/scil/scif_sas_io_request.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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 implementation of the SCIF_SAS_IO_REQUEST
62  *        object.
63  */
64 
65 
66 #include <dev/isci/scil/scic_io_request.h>
67 #include <dev/isci/scil/scic_remote_device.h>
68 #include <dev/isci/scil/scic_user_callback.h>
69 #include <dev/isci/scil/scic_controller.h>
70 #include <dev/isci/scil/scif_user_callback.h>
71 
72 #include <dev/isci/scil/scif_sas_controller.h>
73 #include <dev/isci/scil/scif_sas_domain.h>
74 #include <dev/isci/scil/scif_sas_remote_device.h>
75 #include <dev/isci/scil/scif_sas_io_request.h>
76 #include <dev/isci/scil/scif_sas_task_request.h>
77 #include <dev/isci/scil/scif_sas_stp_io_request.h>
78 #include <dev/isci/scil/scif_sas_logger.h>
79 #include <dev/isci/scil/scif_sas_smp_io_request.h>
80 #include <dev/isci/scil/sci_fast_list.h>
81 #include <dev/isci/scil/sati.h>
82 #include <dev/isci/scil/intel_sat.h>
83 #include <dev/isci/scil/sati_translator_sequence.h>
84 
85 /**
86  * @brief This method represents common functionality for the
87  *        scif_io_request_construct() and scif_sas_io_request_continue()
88  *        methods.
89  *
90  * @return This method returns an indication as to whether the
91  *         construction succeeded.
92  */
93 static
94 SCI_STATUS scif_sas_io_request_construct(
95    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
96    SCIF_SAS_IO_REQUEST_T    * fw_io,
97    U16                        io_tag,
98    void                     * user_io_request_object,
99    SCI_IO_REQUEST_HANDLE_T  * scif_io_request,
100    BOOL                       is_initial_construction
101 )
102 {
103    SCI_STATUS                         status;
104    SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
105 
106    scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
107 
108    //Currently, all the io requests sent to smp target are internal.
109    //so we fail all the external io toward to it.
110    //Todo: is there a better way to handle external io to smp target?
111    if (dev_protocols.u.bits.attached_smp_target)
112       return SCI_FAILURE_INVALID_REMOTE_DEVICE;
113 
114    SCIF_LOG_TRACE((
115       sci_base_object_get_logger(fw_device),
116       SCIF_LOG_OBJECT_IO_REQUEST,
117       "scif_sas_io_request_construct(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) enter\n",
118       fw_device, fw_io, io_tag, user_io_request_object, scif_io_request,
119       is_initial_construction
120    ));
121 
122    // Initialize the users handle to the framework IO request.
123    *scif_io_request = fw_io;
124 
125    // Construct the parent object first in order to ensure logging can
126    // function.
127    scif_sas_request_construct(
128       &fw_io->parent,
129       fw_device,
130       sci_base_object_get_logger(fw_device),
131       scif_sas_io_request_state_table
132    );
133 
134    status = scic_io_request_construct(
135                fw_device->domain->controller->core_object,
136                fw_device->core_object,
137                io_tag,
138                fw_io,
139                ((U8 *)fw_io) + sizeof(SCIF_SAS_IO_REQUEST_T),
140                &fw_io->parent.core_object
141             );
142 
143    if (status == SCI_SUCCESS)
144    {
145       // These associations must be set early for the core io request
146       // object construction to complete correctly as there will be
147       // callbacks into the user driver framework during core construction
148       sci_object_set_association(fw_io, user_io_request_object);
149       sci_object_set_association(fw_io->parent.core_object, fw_io);
150 
151       // Perform protocol specific core IO request construction.
152       if (dev_protocols.u.bits.attached_ssp_target)
153          status = scic_io_request_construct_basic_ssp(fw_io->parent.core_object);
154       else if (dev_protocols.u.bits.attached_stp_target)
155       {
156          if (is_initial_construction == TRUE)
157                sati_sequence_construct(&fw_io->parent.stp.sequence);
158 
159 #if !defined(DISABLE_ATAPI)
160          if (!scic_remote_device_is_atapi(fw_device->core_object))
161          {
162 #endif
163             status = scif_sas_stp_io_request_construct(fw_io);
164 
165 #if !defined(DISABLE_ATAPI)
166          }
167          else
168             status = scif_sas_stp_packet_io_request_construct(fw_io);
169 #endif
170       }
171 
172       sci_base_state_machine_logger_initialize(
173          &fw_io->parent.parent.state_machine_logger,
174          &fw_io->parent.parent.state_machine,
175          &fw_io->parent.parent.parent,
176          scif_cb_logger_log_states,
177          "SCIF_IO_REQUEST_T", "base_state_machine",
178          SCIF_LOG_OBJECT_IO_REQUEST
179       );
180    }
181 
182    return status;
183 }
184 
185 //******************************************************************************
186 //* P U B L I C   M E T H O D S
187 //******************************************************************************
188 
189 U32 scif_io_request_get_object_size(
190    void
191 )
192 {
193    return (sizeof(SCIF_SAS_IO_REQUEST_T) + scic_io_request_get_object_size());
194 }
195 
196 // ----------------------------------------------------------------------------
197 U32 scif_io_request_get_number_of_bytes_transferred(
198    SCI_IO_REQUEST_HANDLE_T  scif_io_request
199 )
200 {
201    SCIF_SAS_IO_REQUEST_T * fw_request = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
202 
203    if(scic_io_request_get_protocol(scif_io_request_get_scic_handle(scif_io_request))
204        == SCIC_STP_PROTOCOL)
205    {
206       U16 sati_data_bytes_set =
207              sati_get_number_data_bytes_set(&(fw_request->parent.stp.sequence));
208 
209       if (sati_data_bytes_set != 0)
210          return sati_data_bytes_set;
211       else
212       {
213 #if !defined(DISABLE_ATAPI)
214          U8 sat_protocol = fw_request->parent.stp.sequence.protocol;
215          if ( sat_protocol & SAT_PROTOCOL_PACKET)
216             return
217                scif_sas_stp_packet_io_request_get_number_of_bytes_transferred(fw_request);
218          else
219 #endif
220             return scic_io_request_get_number_of_bytes_transferred(
221                       scif_io_request_get_scic_handle(scif_io_request));
222       }
223    }
224    else
225    {
226       return scic_io_request_get_number_of_bytes_transferred(
227                 scif_io_request_get_scic_handle(scif_io_request));
228    }
229 }
230 
231 // ---------------------------------------------------------------------------
232 
233 SCI_STATUS scif_io_request_construct(
234    SCI_CONTROLLER_HANDLE_T      scif_controller,
235    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
236    U16                          io_tag,
237    void                       * user_io_request_object,
238    void                       * io_request_memory,
239    SCI_IO_REQUEST_HANDLE_T    * scif_io_request
240 )
241 {
242    SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
243                                           io_request_memory;
244    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
245                                           scif_remote_device;
246 
247    return scif_sas_io_request_construct(
248              fw_device,
249              fw_io,
250              io_tag,
251              user_io_request_object,
252              scif_io_request,
253              TRUE
254           );
255 }
256 
257 // ---------------------------------------------------------------------------
258 
259 SCI_STATUS scif_request_construct(
260    SCI_CONTROLLER_HANDLE_T      scif_controller,
261    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
262    U16                          io_tag,
263    void                       * user_io_request_object,
264    void                       * io_request_memory,
265    SCI_IO_REQUEST_HANDLE_T    * scif_io_request
266 )
267 {
268    SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
269                                           io_request_memory;
270    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
271                                           scif_remote_device;
272    SCI_STATUS                 status;
273 
274    SCIF_LOG_TRACE((
275       sci_base_object_get_logger(fw_device),
276       SCIF_LOG_OBJECT_IO_REQUEST,
277       "scif_io_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
278       scif_controller, scif_remote_device, io_tag, user_io_request_object,
279       io_request_memory, scif_io_request
280    ));
281 
282    // Step 1: Create the scif io request.
283    // Initialize the users handle to the framework IO request.
284    *scif_io_request = fw_io;
285 
286    // Construct the parent object first in order to ensure logging can
287    // function.
288    scif_sas_request_construct(
289       &fw_io->parent,
290       fw_device,
291       sci_base_object_get_logger(fw_device),
292       scif_sas_io_request_state_table
293    );
294 
295    status = scic_io_request_construct(
296                (void *) ((SCIF_SAS_CONTROLLER_T *)scif_controller)->core_object,
297                (void *) fw_device->core_object,
298                io_tag,
299                fw_io,
300                (U8 *)io_request_memory + sizeof(SCIF_SAS_IO_REQUEST_T),
301                &fw_io->parent.core_object
302             );
303 
304    if (status == SCI_SUCCESS)
305    {
306       // These associations must be set early for the core io request
307       // object construction to complete correctly as there will be
308       // callbacks into the user driver framework during core construction
309       sci_object_set_association(fw_io, user_io_request_object);
310       sci_object_set_association(fw_io->parent.core_object, fw_io);
311 
312       sci_base_state_machine_logger_initialize(
313          &fw_io->parent.parent.state_machine_logger,
314          &fw_io->parent.parent.state_machine,
315          &fw_io->parent.parent.parent,
316          scif_cb_logger_log_states,
317          "SCIF_IO_REQUEST_T", "base_state_machine",
318          SCIF_LOG_OBJECT_IO_REQUEST
319       );
320    }
321 
322    return status;
323 }
324 
325 // ----------------------------------------------------------------------------
326 
327 SCI_STATUS scif_io_request_construct_with_core (
328    SCI_CONTROLLER_HANDLE_T      scif_controller,
329    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
330    void                       * scic_io_request,
331    void                       * user_io_request_object,
332    void                       * io_request_memory,
333    SCI_IO_REQUEST_HANDLE_T    * scif_io_request
334 )
335 {
336    SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*)
337                                           io_request_memory;
338    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
339                                           scif_remote_device;
340    SCI_STATUS                 status = SCI_SUCCESS;
341 
342    SCIF_LOG_TRACE((
343       sci_base_object_get_logger(fw_device),
344       SCIF_LOG_OBJECT_IO_REQUEST,
345       "scif_io_request_construct_pass_through(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
346       scif_remote_device, user_io_request_object,
347       io_request_memory, scif_io_request
348    ));
349 
350    // Initialize the users handle to the framework IO request.
351    *scif_io_request = fw_io;
352 
353    // Construct the parent object first in order to ensure logging can
354    // function.
355    scif_sas_request_construct(
356       &fw_io->parent,
357       fw_device,
358       sci_base_object_get_logger(fw_device),
359       scif_sas_io_request_state_table
360    );
361 
362    fw_io->parent.core_object = scic_io_request;
363 
364    //set association
365    sci_object_set_association(fw_io, user_io_request_object);
366    sci_object_set_association(fw_io->parent.core_object, fw_io);
367 
368 
369    sci_base_state_machine_logger_initialize(
370       &fw_io->parent.parent.state_machine_logger,
371       &fw_io->parent.parent.state_machine,
372       &fw_io->parent.parent.parent,
373       scif_cb_logger_log_states,
374       "SCIF_IO_REQUEST_T", "base_state_machine",
375       SCIF_LOG_OBJECT_IO_REQUEST
376    );
377 
378    return status;
379 }
380 
381 // ---------------------------------------------------------------------------
382 
383 void * scif_io_request_get_response_iu_address(
384    SCI_IO_REQUEST_HANDLE_T scif_io_request
385 )
386 {
387    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)scif_io_request;
388 
389    return (scic_io_request_get_response_iu_address(fw_io->parent.core_object ));
390 }
391 
392 // ---------------------------------------------------------------------------
393 
394 SCI_IO_REQUEST_HANDLE_T scif_io_request_get_scic_handle(
395    SCI_IO_REQUEST_HANDLE_T scif_io_request
396 )
397 {
398    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*) scif_io_request;
399    return fw_io->parent.core_object;
400 }
401 
402 // ---------------------------------------------------------------------------
403 
404 void scic_cb_io_request_complete(
405    SCI_CONTROLLER_HANDLE_T     controller,
406    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
407    SCI_IO_REQUEST_HANDLE_T     io_request,
408    SCI_IO_STATUS               completion_status
409 )
410 {
411    SCI_STATUS                 status;
412    SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
413                                       sci_object_get_association(controller);
414    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
415                                       sci_object_get_association(remote_device);
416    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*)
417                                       sci_object_get_association(io_request);
418 
419    SCIF_LOG_TRACE((
420       sci_base_object_get_logger(controller),
421       SCIF_LOG_OBJECT_IO_REQUEST,
422       "scic_cb_io_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
423       controller, remote_device, io_request, completion_status
424    ));
425 
426    // Invoke the common completion handler routine.
427    // A non-successful return indicates we are not in a correct state to
428    // receive a completion notification for this request.
429    status = fw_request->state_handlers->complete_handler(&fw_request->parent);
430 
431    // If the status indicates the completion handler was successful, then
432    // allow protocol specific completion processing to occur.
433    if (status == SCI_SUCCESS)
434    {
435       if (fw_request->protocol_complete_handler != NULL)
436       {
437          status = fw_request->protocol_complete_handler(
438                      fw_controller, fw_device, fw_request, (SCI_STATUS *)&completion_status
439                   );
440       }
441 
442       // If this isn't an internal framework IO request, then simply pass the
443       // notification up to the SCIF user.
444       if ( status == SCI_SUCCESS )
445       {
446          if (fw_request->is_high_priority == FALSE)
447          {
448             if (fw_request->is_waiting_for_abort_task_set == FALSE)
449             {
450                scif_cb_io_request_complete(
451                   fw_controller, fw_device, fw_request, completion_status);
452             }
453             else
454             {
455                // do nothing - will complete the I/O when the abort task
456                //  set completes
457             }
458          }
459          else
460             scif_sas_controller_complete_high_priority_io(
461                fw_controller, fw_device, fw_request);
462       }
463       else if ( status == SCI_WARNING_SEQUENCE_INCOMPLETE )
464       {
465          scif_sas_io_request_continue(fw_controller, fw_device, fw_request);
466       }
467    }
468 }
469 
470 // ---------------------------------------------------------------------------
471 
472 U32 scic_cb_io_request_get_transfer_length(
473    void * scic_user_io_request
474 )
475 {
476    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
477                                    scic_user_io_request;
478 
479    return (scif_cb_io_request_get_transfer_length(
480              fw_io->parent.parent.parent.associated_object
481            ));
482 }
483 
484 // ---------------------------------------------------------------------------
485 
486 SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
487    void * scic_user_io_request
488 )
489 {
490    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
491                                    scic_user_io_request;
492 
493    return (scif_cb_io_request_get_data_direction(
494              fw_io->parent.parent.parent.associated_object
495           ));
496 }
497 
498 // ---------------------------------------------------------------------------
499 #ifndef SCI_SGL_OPTIMIZATION_ENABLED
500 void scic_cb_io_request_get_next_sge(
501    void * scic_user_io_request,
502    void * current_sge_address,
503    void **next_sge
504 )
505 {
506    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
507                                    scic_user_io_request;
508 
509    scif_cb_io_request_get_next_sge(
510       fw_io->parent.parent.parent.associated_object,
511       current_sge_address,
512       next_sge
513    );
514 }
515 #endif
516 
517 // ---------------------------------------------------------------------------
518 
519 SCI_PHYSICAL_ADDRESS scic_cb_sge_get_address_field(
520    void * scic_user_io_request,
521    void * sge_address
522 )
523 {
524    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
525                                    scic_user_io_request;
526    return scif_cb_sge_get_address_field(
527              fw_io->parent.parent.parent.associated_object, sge_address
528           );
529 }
530 
531 // ---------------------------------------------------------------------------
532 
533 U32 scic_cb_sge_get_length_field(
534    void * scic_user_io_request,
535    void * sge_address
536 )
537 {
538    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
539                                    scic_user_io_request;
540 
541    return scif_cb_sge_get_length_field(
542              fw_io->parent.parent.parent.associated_object,
543              sge_address
544           );
545 }
546 
547 // ---------------------------------------------------------------------------
548 
549 void * scic_cb_ssp_io_request_get_cdb_address(
550    void * scic_user_io_request
551 )
552 {
553    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
554                                    scic_user_io_request;
555 
556    return scif_cb_io_request_get_cdb_address(
557              fw_io->parent.parent.parent.associated_object
558           );
559 }
560 
561 // ---------------------------------------------------------------------------
562 
563 U32 scic_cb_ssp_io_request_get_cdb_length(
564    void * scic_user_io_request
565 )
566 {
567    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
568                                    scic_user_io_request;
569 
570    return scif_cb_io_request_get_cdb_length(
571              fw_io->parent.parent.parent.associated_object
572           );
573 }
574 
575 // ---------------------------------------------------------------------------
576 
577 #if !defined(DISABLE_ATAPI)
578 void * scic_cb_stp_packet_io_request_get_cdb_address(
579    void * scic_user_io_request
580 )
581 {
582    SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)scic_user_io_request;
583 
584    SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
585 
586    if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
587       return scif_cb_io_request_get_cdb_address(
588                 fw_request->parent.parent.associated_object
589              );
590    else
591       return
592       &(sati_sequence->command_specific_data.sati_atapi_data.request_sense_cdb);
593 }
594 #endif
595 
596 // ---------------------------------------------------------------------------
597 
598 #if !defined(DISABLE_ATAPI)
599 U32 scic_cb_stp_packet_io_request_get_cdb_length(
600    void * scic_user_io_request
601 )
602 {
603    SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
604                                    scic_user_io_request;
605 
606    SATI_TRANSLATOR_SEQUENCE_T * sati_sequence = &fw_request->stp.sequence;
607 
608    if (sati_sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
609       return scif_cb_io_request_get_cdb_length(
610                 fw_request->parent.parent.associated_object
611              );
612    else
613       return SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH;
614 }
615 #endif
616 
617 // ---------------------------------------------------------------------------
618 
619 U32 scic_cb_ssp_io_request_get_lun(
620    void * scic_user_io_request
621 )
622 {
623    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
624                                    scic_user_io_request;
625 
626    return scif_cb_io_request_get_lun(
627              fw_io->parent.parent.parent.associated_object
628           );
629 }
630 
631 // ---------------------------------------------------------------------------
632 
633 U32 scic_cb_ssp_io_request_get_task_attribute(
634    void * scic_user_io_request
635 )
636 {
637    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
638                                    scic_user_io_request;
639 
640    return scif_cb_io_request_get_task_attribute(
641              fw_io->parent.parent.parent.associated_object
642           );
643 }
644 
645 // ---------------------------------------------------------------------------
646 
647 U32 scic_cb_ssp_io_request_get_command_priority(
648    void * scic_user_io_request
649 )
650 {
651    SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
652                                    scic_user_io_request;
653 
654    return scif_cb_io_request_get_command_priority(
655              fw_io->parent.parent.parent.associated_object
656           );
657 }
658 
659 // ---------------------------------------------------------------------------
660 
661 BOOL scic_cb_request_is_initial_construction(
662    void * scic_user_io_request
663 )
664 {
665    SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
666                                    scic_user_io_request;
667    SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;
668 
669    SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
670    scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
671 
672    if (dev_protocols.u.bits.attached_stp_target
673        && fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
674       return FALSE;
675 
676    return TRUE;
677 }
678 
679 
680 //******************************************************************************
681 //* P R O T E C T E D   M E T H O D S
682 //******************************************************************************
683 /**
684  * @brief This method constructs an scif sas smp request.
685  *
686  * @param[in] fw_controller The framework controller
687  * @param[in] fw_device The smp device that the smp request targets to.
688  * @param[in] fw_io_memory The memory space for the smp request.
689  * @param[in] core_io_memory The memory space for the core request.
690  * @param[in] io_tag The io tag for the internl io to be constructed.
691  * @param[in] smp_command A pointer to the smp request data structure according
692  *       to SAS protocol.
693  *
694  * @return Indicate if the internal io was successfully constructed.
695  * @retval SCI_SUCCESS This value is returned if the internal io was
696  *         successfully constructed.
697  * @retval SCI_FAILURE This value is returned if the internal io was failed to
698  *         be constructed.
699  */
700 SCI_STATUS scif_sas_io_request_construct_smp(
701    SCIF_SAS_CONTROLLER_T       * fw_controller,
702    SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
703    void                        * fw_io_memory,
704    void                        * core_io_memory,
705    U16                           io_tag,
706    SMP_REQUEST_T               * smp_command,
707    void                        * user_request_object
708 )
709 {
710    SCIF_SAS_IO_REQUEST_T * fw_io =
711      (SCIF_SAS_IO_REQUEST_T*)fw_io_memory;
712 
713    SCI_STATUS status = SCI_SUCCESS;
714 
715    SCIF_LOG_TRACE((
716       sci_base_object_get_logger(fw_device),
717       SCIF_LOG_OBJECT_IO_REQUEST,
718       "scif_sas_io_request_construct_smp(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
719       fw_controller,
720       fw_device,
721       fw_io_memory,
722       core_io_memory,
723       io_tag,
724       smp_command,
725       user_request_object
726    ));
727 
728    // Construct the parent object first in order to ensure logging can
729    // function.
730    scif_sas_request_construct(
731       &fw_io->parent,
732       fw_device,
733       sci_base_object_get_logger(fw_controller),
734       scif_sas_io_request_state_table
735    );
736 
737    status = scic_io_request_construct(
738                fw_device->domain->controller->core_object,
739                fw_device->core_object,
740                io_tag,
741                (void*)fw_io,
742                (U8 *)core_io_memory,
743                &fw_io->parent.core_object
744             );
745 
746    if (status == SCI_SUCCESS)
747    {
748       //set object association.
749       sci_object_set_association(fw_io, user_request_object);
750       sci_object_set_association(fw_io->parent.core_object, fw_io);
751 
752       scif_sas_smp_request_construct(&fw_io->parent, smp_command);
753 
754       fw_io->parent.is_high_priority = TRUE;
755 
756       sci_base_state_machine_logger_initialize(
757          &fw_io->parent.parent.state_machine_logger,
758          &fw_io->parent.parent.state_machine,
759          &fw_io->parent.parent.parent,
760          scif_cb_logger_log_states,
761          "SCIF_IO_REQUEST_T", "base_state_machine",
762          SCIF_LOG_OBJECT_IO_REQUEST
763       );
764    }
765 
766    return status;
767 }
768 
769 
770 /**
771  * @brief This method continues a scif sas request.
772  *
773  * @param[in] fw_controller The framework controller
774  * @param[in] fw_device The device that the IO request targets to.
775  * @param[in] fw_request The IO request to be continued.
776  *
777  * @return Indicate if the internal io was successfully constructed.
778  * @retval SCI_SUCCESS This value is returned if the internal io was
779  *         successfully continued.
780  * @retval SCI_FAILURE This value is returned if the io was failed to
781  *         be continued.
782  */
783 SCI_STATUS scif_sas_io_request_continue(
784    SCIF_SAS_CONTROLLER_T       * fw_controller,
785    SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
786    SCIF_SAS_REQUEST_T          * fw_request
787 )
788 {
789    SCI_IO_REQUEST_HANDLE_T dummy_handle;
790 
791    SCIF_LOG_TRACE((
792       sci_base_object_get_logger(fw_request),
793       SCIF_LOG_OBJECT_IO_REQUEST,
794       "scif_sas_io_request_continue(0x%x, 0x%x, 0x%x) enter\n",
795       fw_controller,
796       fw_device,
797       fw_request
798    ));
799 
800    //complete this io request in framework and core.
801    scif_controller_complete_io(fw_controller, fw_device, fw_request);
802 
803    //construct next command in the sequence using the same memory. We pass
804    //a dummy pointer to let the framework user keep the pointer to this IO
805    //request untouched.
806    scif_sas_io_request_construct(
807       fw_device,
808       (SCIF_SAS_IO_REQUEST_T*)fw_request,
809       SCI_CONTROLLER_INVALID_IO_TAG,
810       (void *)sci_object_get_association(fw_request),
811       &dummy_handle,
812       FALSE
813    );
814 
815    //start the new constructed IO.
816    return (SCI_STATUS)scif_controller_start_io(
817              (SCI_CONTROLLER_HANDLE_T) fw_controller,
818              (SCI_REMOTE_DEVICE_HANDLE_T) fw_device,
819              (SCI_IO_REQUEST_HANDLE_T) fw_request,
820              SCI_CONTROLLER_INVALID_IO_TAG
821           );
822 }
823