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 all of the state handler routines for each
62  *        of the domain states defined by the SCI_BASE_DOMAIN state
63  *        machine.
64  * @note
65  *        - The discover method must be synchronized with the
66  *          controller's completion handler.  The OS specific driver
67  *          component is responsible for ensuring this occurs.  If the
68  *          discovery method is called from within the call
69  *          tree of the completion routine, then no action is necessary.
70  */
71 
72 
73 #include <dev/isci/scil/scic_port.h>
74 #include <dev/isci/scil/scic_io_request.h>
75 #include <dev/isci/scil/scif_sas_logger.h>
76 #include <dev/isci/scil/scif_sas_domain.h>
77 
78 //******************************************************************************
79 //* P R O T E C T E D   M E T H O D S
80 //******************************************************************************
81 
82 //******************************************************************************
83 //* S T A R T I N G   H A N D L E R S
84 //******************************************************************************
85 
86 static
87 SCI_STATUS scif_sas_domain_starting_port_ready_handler(
88    SCI_BASE_DOMAIN_T * domain
89 )
90 {
91    SCIF_LOG_TRACE((
92       sci_base_object_get_logger(domain),
93       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
94       "scif_sas_domain_starting_port_ready_handler(0x%x) enter\n",
95       domain
96    ));
97 
98    // The domain was previously completely stopped.  Now that the port is
99    // ready we can transition the domain to the ready state.
100    sci_base_state_machine_change_state(
101       &domain->state_machine, SCI_BASE_DOMAIN_STATE_READY
102    );
103 
104    return SCI_SUCCESS;
105 }
106 
107 //******************************************************************************
108 //* R E A D Y   H A N D L E R S
109 //******************************************************************************
110 
111 /**
112  * @brief This method provides READY state specific handling for
113  *        when a user attempts to discover a domain.
114  *
115  * @param[in]  domain This parameter specifies the domain object
116  *             on which the user is attempting to perform a discover
117  *             operation.
118  *
119  * @return This method returns an indication of whether the discover operation
120  *         succeeded.
121  * @retval SCI_SUCCESSS This value is returned when the discover operation
122  *         begins successfully.
123  */
124 static
125 SCI_STATUS scif_sas_domain_ready_discover_handler(
126    SCI_BASE_DOMAIN_T * domain,
127    U32                 op_timeout,
128    U32                 device_timeout
129 )
130 {
131    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
132 
133    SCIF_LOG_TRACE((
134       sci_base_object_get_logger(domain),
135       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
136       "scif_sas_domain_ready_discover_handler(0x%x, 0x%x, 0x%x) enter\n",
137       domain, op_timeout, device_timeout
138    ));
139 
140    fw_domain->operation.timeout        = op_timeout;
141    fw_domain->operation.device_timeout = device_timeout;
142    fw_domain->operation.status         = SCI_SUCCESS;
143 
144    scif_cb_timer_start(
145       fw_domain->controller,
146       fw_domain->operation.timer,
147       fw_domain->operation.timeout
148    );
149 
150    scif_sas_domain_transition_to_discovering_state(fw_domain);
151 
152    return fw_domain->operation.status;
153 }
154 
155 /**
156  * @brief This method provides READY state processing for reception of a
157  *        port NOT ready notification from the core.
158  *
159  * @param[in]  domain This parameter specifies the domain object
160  *             on which the core port has just come ready.
161  *
162  * @return
163  */
164 static
165 SCI_STATUS scif_sas_domain_ready_port_not_ready_handler(
166    SCI_BASE_DOMAIN_T * domain,
167    U32                 reason_code
168 )
169 {
170    SCIF_LOG_TRACE((
171       sci_base_object_get_logger(domain),
172       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
173       "scif_sas_domain_ready_port_not_ready_handler(0x%x, 0x%x) enter\n",
174       domain,
175       reason_code
176    ));
177 
178    if (reason_code != SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED)
179    {
180       // Change to the STOPPING state to cause existing request
181       // completions to be terminated and devices removed.
182       sci_base_state_machine_change_state(
183          &domain->state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
184       );
185    }
186 
187    return SCI_SUCCESS;
188 }
189 
190 /**
191  * @brief This method provides READY state specific handling for
192  *        when a user attempts to start an IO request.
193  *
194  * @param[in]  domain This parameter specifies the domain object
195  *             on which the user is attempting to perform a start IO
196  *             operation.
197  * @param[in]  remote_device This parameter specifies the remote device
198  *             object on which the user is attempting to perform a start IO
199  *             operation.
200  * @param[in]  io_request This parameter specifies the io request that is
201  *             being started.
202  *
203  * @return This method returns an indication of whether the start IO
204  *         operation succeeded.
205  * @retval SCI_SUCCESS This value is returned when the start IO operation
206  *         begins successfully.
207  */
208 static
209 SCI_STATUS scif_sas_domain_ready_start_io_handler(
210    SCI_BASE_DOMAIN_T        * domain,
211    SCI_BASE_REMOTE_DEVICE_T * remote_device,
212    SCI_BASE_REQUEST_T       * io_request
213 )
214 {
215    SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
216    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
217                                            remote_device;
218    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
219    SCI_STATUS                 status;
220 
221    SCIF_LOG_TRACE((
222       sci_base_object_get_logger(domain),
223       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
224       "scif_sas_domain_ready_start_io_handler(0x%x, 0x%x, 0x%x) enter\n",
225       domain, remote_device, io_request
226    ));
227 
228    status = fw_device->state_handlers->parent.start_io_handler(
229                &fw_device->parent, &fw_request->parent
230             );
231 
232    if (status == SCI_SUCCESS)
233    {
234       // Add the IO to the list of outstanding requests on the domain.
235       sci_fast_list_insert_tail(
236          &fw_domain->request_list, &fw_request->list_element
237       );
238    }
239 
240    return status;
241 }
242 
243 /**
244  * @brief This method provides READY state specific handling for
245  *        when a user attempts to complete an IO request.
246  *
247  * @param[in]  domain This parameter specifies the domain object
248  *             on which the user is attempting to perform a complete IO
249  *             operation.
250  * @param[in]  remote_device This parameter specifies the remote device
251  *             object on which the user is attempting to perform a complete
252  *             IO operation.
253  * @param[in]  io_request This parameter specifies the io request that is
254  *             being completed.
255  *
256  * @return This method returns an indication of whether the complete IO
257  *         operation succeeded.
258  * @retval SCI_SUCCESS This value is returned when the complete IO operation
259  *         is successful.
260  */
261 static
262 SCI_STATUS scif_sas_domain_ready_complete_io_handler(
263    SCI_BASE_DOMAIN_T        * domain,
264    SCI_BASE_REMOTE_DEVICE_T * remote_device,
265    SCI_BASE_REQUEST_T       * io_request
266 )
267 {
268    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
269                                           remote_device;
270    SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
271 
272    SCIF_LOG_TRACE((
273       sci_base_object_get_logger(domain),
274       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
275       "scif_sas_domain_ready_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
276       domain, remote_device, io_request
277    ));
278 
279    // Remove the IO from the list of outstanding requests on the domain.
280    sci_fast_list_remove_element(&fw_request->list_element);
281 
282    return fw_device->state_handlers->parent.complete_io_handler(
283              &fw_device->parent, &fw_request->parent
284           );
285 }
286 
287 /**
288  * @brief This method provides READY state specific handling for
289  *        when a user attempts to continue an IO request.
290  *
291  * @param[in]  domain This parameter specifies the domain object
292  *             on which the user is attempting to perform a continue IO
293  *             operation.
294  * @param[in]  remote_device This parameter specifies the remote device
295  *             object on which the user is attempting to perform a start IO
296  *             operation.
297  * @param[in]  io_request This parameter specifies the io request that is
298  *             being started.
299  *
300  * @return This method returns an indication of whether the continue IO
301  *         operation succeeded.
302  * @retval SCI_SUCCESS This value is returned when the continue IO operation
303  *         begins successfully.
304  */
305 static
306 SCI_STATUS scif_sas_domain_ready_continue_io_handler(
307    SCI_BASE_DOMAIN_T        * domain,
308    SCI_BASE_REMOTE_DEVICE_T * remote_device,
309    SCI_BASE_REQUEST_T       * io_request
310 )
311 {
312    SCIF_LOG_TRACE((
313       sci_base_object_get_logger(domain),
314       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
315       "scif_sas_domain_ready_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
316       domain, remote_device, io_request
317    ));
318 
319    /// @todo fix return code handling.
320    return SCI_FAILURE;
321 }
322 
323 /**
324  * @brief This method provides READY state specific handling for
325  *        when a user attempts to start a task request.
326  *
327  * @param[in]  domain This parameter specifies the domain object
328  *             on which the user is attempting to perform a start task
329  *             operation.
330  * @param[in]  remote_device This parameter specifies the remote device
331  *             object on which the user is attempting to perform a start IO
332  *             operation.
333  * @param[in]  task_request This parameter specifies the task request that
334  *             is being started.
335  *
336  * @return This method returns an indication of whether the start task
337  *         operation succeeded.
338  * @retval SCI_SUCCESS This value is returned when the start task operation
339  *         begins successfully.
340  */
341 static
342 SCI_STATUS scif_sas_domain_ready_start_task_handler(
343    SCI_BASE_DOMAIN_T        * domain,
344    SCI_BASE_REMOTE_DEVICE_T * remote_device,
345    SCI_BASE_REQUEST_T       * task_request
346 )
347 {
348    SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
349    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
350                                            remote_device;
351    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) task_request;
352    SCI_STATUS                 status;
353 
354    SCIF_LOG_TRACE((
355       sci_base_object_get_logger(domain),
356       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
357       "scif_sas_domain_ready_start_task_handler(0x%x, 0x%x, 0x%x) enter\n",
358       domain, remote_device, task_request
359    ));
360 
361    status = fw_device->state_handlers->parent.start_task_handler(
362                &fw_device->parent, &fw_request->parent
363             );
364 
365    if (status == SCI_SUCCESS)
366    {
367       // Add the task to the list of outstanding requests on the domain.
368       sci_fast_list_insert_tail(
369          &fw_domain->request_list, &fw_request->list_element
370       );
371    }
372 
373    return status;
374 }
375 
376 /**
377  * @brief This method provides READY state specific handling for
378  *        when a user attempts to complete a task request.
379  *
380  * @param[in]  domain This parameter specifies the domain object
381  *             on which the user is attempting to perform a complete task
382  *             operation.
383  * @param[in]  remote_device This parameter specifies the remote device
384  *             object on which the user is attempting to perform a start IO
385  *             operation.
386  * @param[in]  task_request This parameter specifies the task request that
387  *             is being started.
388  *
389  * @return This method returns an indication of whether the complete task
390  *         operation succeeded.
391  * @retval SCI_SUCCESS This value is returned when the complete task operation
392  *         begins successfully.
393  */
394 static
395 SCI_STATUS scif_sas_domain_ready_complete_task_handler(
396    SCI_BASE_DOMAIN_T        * domain,
397    SCI_BASE_REMOTE_DEVICE_T * remote_device,
398    SCI_BASE_REQUEST_T       * task_request
399 )
400 {
401    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
402                                            remote_device;
403    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) task_request;
404 
405    SCIF_LOG_TRACE((
406       sci_base_object_get_logger(domain),
407       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
408       "scif_sas_domain_ready_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
409       domain, remote_device, task_request
410    ));
411 
412    // Remove the IO from the list of outstanding requests on the domain.
413    sci_fast_list_remove_element(&fw_request->list_element);
414 
415    return fw_device->state_handlers->parent.complete_task_handler(
416              &fw_device->parent, &fw_request->parent
417           );
418 }
419 
420 
421 /**
422  * @brief This method provides READY state specific handling for when a user
423  *        attempts to start a high priority IO request.
424  *
425  * @param[in]  domain This parameter specifies the domain object
426  *             on which the user is attempting to perform a start high priority
427  *             IO operation (which is exclusively for Phy Control hard reset).
428  * @param[in]  remote_device This parameter specifies the remote device
429  *             object on which the user is attempting to perform a start
430  *             high priority IO operation.
431  * @param[in]  io_request This parameter specifies the io request that is
432  *             being started.
433  *
434  * @return This method returns an indication of whether the start IO
435  *         operation succeeded.
436  * @retval SCI_SUCCESS This value is returned when the start IO operation
437  *         begins successfully.
438  */
439 static
440 SCI_STATUS scif_sas_domain_ready_start_high_priority_io_handler(
441    SCI_BASE_DOMAIN_T        * domain,
442    SCI_BASE_REMOTE_DEVICE_T * remote_device,
443    SCI_BASE_REQUEST_T       * io_request
444 )
445 {
446    SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
447    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
448                                            remote_device;
449    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
450    SCI_STATUS                 status;
451 
452    SCIF_LOG_TRACE((
453       sci_base_object_get_logger(domain),
454       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
455       "scif_sas_domain_ready_start_high_priority_request_handler(0x%x, 0x%x, 0x%x) enter\n",
456       domain, remote_device, io_request
457    ));
458 
459    status = fw_device->state_handlers->start_high_priority_io_handler(
460                &fw_device->parent, &fw_request->parent
461             );
462 
463    if (status == SCI_SUCCESS)
464    {
465       // Add the IO to the list of outstanding requests on the domain.
466 
467       // When domain is in READY state, this high priority io is likely
468       // a smp Phy Control or Discover request sent to parent device of
469       // a target device, which is to be Target Reset. This high priority
470       // IO's probably has already been added to the domain's list as a
471       // SCIF_SAS_TASK_REQUEST. We need to check if it is already on the
472       // list.
473 
474       if ( ! sci_fast_list_is_on_this_list(
475                 &fw_domain->request_list, &fw_request->list_element))
476 
477          sci_fast_list_insert_tail(
478             &fw_domain->request_list, &fw_request->list_element
479          );
480    }
481 
482    return status;
483 }
484 
485 
486 /**
487  * @brief This method provides READY state specific handling for
488  *        when a user attempts to complete an high priroity IO request.
489  *
490  * @param[in]  domain This parameter specifies the domain object
491  *             on which the user is attempting to perform a complete high
492  *             priority IO operation (which is exclusively for Phy Control
493  *             hard reset).
494  * @param[in]  remote_device This parameter specifies the remote device
495  *             object on which the user is attempting to perform a complete
496  *             IO operation.
497  * @param[in]  io_request This parameter specifies the io request that is
498  *             being completed.
499  *
500  * @return This method returns an indication of whether the complete IO
501  *         operation succeeded.
502  * @retval SCI_SUCCESS This value is returned when the complete IO operation
503  *         is successful.
504  */
505 static
506 SCI_STATUS scif_sas_domain_ready_complete_high_priority_io_handler(
507    SCI_BASE_DOMAIN_T        * domain,
508    SCI_BASE_REMOTE_DEVICE_T * remote_device,
509    SCI_BASE_REQUEST_T       * io_request,
510    void                     * response_data,
511    SCI_IO_STATUS              completion_status
512 )
513 {
514    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
515                                           remote_device;
516    SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
517 
518    SCIC_TRANSPORT_PROTOCOL    protocol;
519 
520    SCIF_LOG_TRACE((
521       sci_base_object_get_logger(domain),
522       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
523       "scif_sas_domain_ready_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
524       domain, remote_device, io_request, response_data
525    ));
526 
527    protocol = scic_io_request_get_protocol(fw_request->core_object);
528 
529    // If the request is an SMP HARD/LINK RESET request, then the request
530    // came through the task management path (partially).  As a result,
531    // the accounting for the request is managed in the task request
532    // completion path.  Thus, only change the domain request counter if
533    // the request is not an SMP target reset of some sort.
534    if (
535          (protocol != SCIC_SMP_PROTOCOL)
536       || (fw_device->protocol_device.smp_device.current_activity !=
537                 SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
538       )
539    {
540       sci_fast_list_remove_element(&fw_request->list_element);
541    }
542 
543    return fw_device->state_handlers->complete_high_priority_io_handler(
544              &fw_device->parent, &fw_request->parent, response_data, completion_status
545           );
546 }
547 
548 //******************************************************************************
549 //* S T O P P I N G   H A N D L E R S
550 //******************************************************************************
551 
552 static
553 SCI_STATUS scif_sas_domain_stopping_device_stop_complete_handler(
554    SCI_BASE_DOMAIN_T        * domain,
555    SCI_BASE_REMOTE_DEVICE_T * remote_device
556 )
557 {
558    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
559 
560    SCIF_LOG_TRACE((
561       sci_base_object_get_logger(domain),
562       SCIF_LOG_OBJECT_DOMAIN,
563       "scif_sas_domain_stopping_device_stop_complete_handler(0x%x, 0x%x) enter\n",
564       domain, remote_device
565    ));
566 
567    // Attempt to transition to the stopped state.
568    scif_sas_domain_transition_to_stopped_state(fw_domain);
569 
570    return SCI_SUCCESS;
571 }
572 
573 /**
574  * @brief This method provides STOPPING state specific handling for
575  *        when a user attempts to complete an IO request.
576  *
577  * @param[in]  domain This parameter specifies the domain object
578  *             on which the user is attempting to perform a complete IO
579  *             operation.
580  * @param[in]  remote_device This parameter specifies the remote device
581  *             object on which the user is attempting to perform a complete
582  *             IO operation.
583  * @param[in]  io_request This parameter specifies the io request that is
584  *             being completed.
585  *
586  * @return This method returns an indication of whether the complete IO
587  *         operation succeeded.
588  * @retval SCI_SUCCESS This value is returned when the complete IO operation
589  *         is successful.
590  */
591 static
592 SCI_STATUS scif_sas_domain_stopping_complete_io_handler(
593    SCI_BASE_DOMAIN_T        * domain,
594    SCI_BASE_REMOTE_DEVICE_T * remote_device,
595    SCI_BASE_REQUEST_T       * io_request
596 )
597 {
598    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
599    SCI_STATUS          status;
600 
601    SCIF_LOG_TRACE((
602       sci_base_object_get_logger(domain),
603       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
604       "scif_sas_domain_stopping_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
605       domain, remote_device, io_request
606    ));
607 
608    status = scif_sas_domain_ready_complete_io_handler(
609                domain, remote_device, io_request
610             );
611 
612    // Attempt to transition to the stopped state.
613    scif_sas_domain_transition_to_stopped_state(fw_domain);
614 
615    return status;
616 }
617 
618 
619 /**
620  * @brief This method provides STOPPING state specific handling for
621  *        when a user attempts to complete an IO request.
622  *
623  * @param[in]  domain This parameter specifies the domain object
624  *             on which the user is attempting to perform a complete IO
625  *             operation.
626  * @param[in]  remote_device This parameter specifies the remote device
627  *             object on which the user is attempting to perform a complete
628  *             IO operation.
629  * @param[in]  io_request This parameter specifies the io request that is
630  *             being completed.
631  *
632  * @return This method returns an indication of whether the complete IO
633  *         operation succeeded.
634  * @retval SCI_SUCCESS This value is returned when the complete IO operation
635  *         is successful.
636  */
637 static
638 SCI_STATUS scif_sas_domain_stopping_complete_high_priority_io_handler(
639    SCI_BASE_DOMAIN_T        * domain,
640    SCI_BASE_REMOTE_DEVICE_T * remote_device,
641    SCI_BASE_REQUEST_T       * io_request,
642    void                     * response_data,
643    SCI_IO_STATUS              completion_status
644 )
645 {
646    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
647    SCI_STATUS          status;
648 
649    SCIF_LOG_TRACE((
650       sci_base_object_get_logger(domain),
651       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
652       "scif_sas_domain_stopping_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
653       domain, remote_device, io_request
654    ));
655 
656    status = scif_sas_domain_ready_complete_high_priority_io_handler(
657                domain, remote_device, io_request, response_data, completion_status
658             );
659 
660    // Attempt to transition to the stopped state.
661    scif_sas_domain_transition_to_stopped_state(fw_domain);
662 
663    return status;
664 }
665 
666 
667 /**
668  * @brief This method provides STOPPING state specific handling for
669  *        when a user attempts to complete a task request.
670  *
671  * @param[in]  domain This parameter specifies the domain object
672  *             on which the user is attempting to perform a complete task
673  *             operation.
674  *
675  * @return This method returns an indication of whether the complete task
676  *         operation succeeded.
677  * @retval SCI_SUCCESS This value is returned when the complete task operation
678  *         begins successfully.
679  */
680 static
681 SCI_STATUS scif_sas_domain_stopping_complete_task_handler(
682    SCI_BASE_DOMAIN_T        * domain,
683    SCI_BASE_REMOTE_DEVICE_T * remote_device,
684    SCI_BASE_REQUEST_T       * task_request
685 )
686 {
687    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
688    SCI_STATUS          status;
689 
690    SCIF_LOG_TRACE((
691       sci_base_object_get_logger(domain),
692       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
693       "scif_sas_domain_stopping_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
694       domain, remote_device, task_request
695    ));
696 
697    status = scif_sas_domain_ready_complete_task_handler(
698                domain, remote_device, task_request
699             );
700 
701    // Attempt to transition to the stopped state.
702    scif_sas_domain_transition_to_stopped_state(fw_domain);
703 
704    return SCI_SUCCESS;
705 }
706 
707 //******************************************************************************
708 //* D I S C O V E R I N G   H A N D L E R S
709 //******************************************************************************
710 
711 /**
712  * @brief This method provides DISCOVERING state specific processing for
713  *        reception of a port NOT ready notification from the core.  A port
714  *        NOT ready notification forces the discovery operation to complete
715  *        in error.  Additionally, all IOs are aborted and devices removed.
716  *
717  * @param[in]  domain This parameter specifies the domain object
718  *             for which the core port is no longer ready.
719  *
720  * @return
721  */
722 static
723 SCI_STATUS scif_sas_domain_discovering_port_not_ready_handler(
724    SCI_BASE_DOMAIN_T * domain,
725    U32                 reason_code
726 )
727 {
728    SCIF_LOG_TRACE((
729       sci_base_object_get_logger(domain),
730       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
731       "scif_sas_domain_discovering_port_not_ready_handler(0x%x, 0x%x) enter\n",
732       domain,
733       reason_code
734    ));
735 
736    // Change to the STOPPING state to cause existing request
737    // completions to be terminated and devices removed.
738    sci_base_state_machine_change_state(
739       &domain->state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
740    );
741 
742    return SCI_SUCCESS;
743 }
744 
745 static
746 SCI_STATUS scif_sas_domain_discovering_device_start_complete_handler(
747    SCI_BASE_DOMAIN_T        * domain,
748    SCI_BASE_REMOTE_DEVICE_T * remote_device
749 )
750 {
751    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
752 
753    SCIF_LOG_TRACE((
754       sci_base_object_get_logger(domain),
755       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
756       "scif_sas_domain_discovering_device_start_complete_handler(0x%x) enter\n",
757       domain, remote_device
758    ));
759 
760    //domain will decide what's next step.
761    scif_sas_domain_continue_discover(fw_domain);
762 
763    return SCI_SUCCESS;
764 }
765 
766 // ---------------------------------------------------------------------------
767 
768 static
769 SCI_STATUS scif_sas_domain_discovering_device_stop_complete_handler(
770    SCI_BASE_DOMAIN_T        * domain,
771    SCI_BASE_REMOTE_DEVICE_T * remote_device
772 )
773 {
774    SCIF_LOG_TRACE((
775       sci_base_object_get_logger(domain),
776       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
777       "scif_sas_domain_discovering_device_stop_complete_handler(0x%x) enter\n",
778       domain, remote_device
779    ));
780 
781    return SCI_FAILURE;
782 }
783 
784 
785 /**
786  * @brief This method provides DISCOVERING state specific handling for when a user
787  *        attempts to start a high priority IO request.
788  *
789  * @param[in]  domain This parameter specifies the domain object
790  *             on which the user is attempting to perform a start IO
791  *             operation.
792  * @param[in]  remote_device This parameter specifies the remote device
793  *             object on which the user is attempting to perform a start IO
794  *             operation.
795  * @param[in]  io_request This parameter specifies the io request that is
796  *             being started.
797  *
798  * @return This method returns an indication of whether the start IO
799  *         operation succeeded.
800  * @retval SCI_SUCCESS This value is returned when the start IO operation
801  *         begins successfully.
802  */
803 static
804 SCI_STATUS scif_sas_domain_discovering_start_high_priority_io_handler(
805    SCI_BASE_DOMAIN_T        * domain,
806    SCI_BASE_REMOTE_DEVICE_T * remote_device,
807    SCI_BASE_REQUEST_T       * io_request
808 )
809 {
810    SCIF_SAS_DOMAIN_T        * fw_domain  = (SCIF_SAS_DOMAIN_T*) domain;
811    SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
812                                            remote_device;
813    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
814    SCI_STATUS                 status;
815 
816    SCIF_LOG_TRACE((
817       sci_base_object_get_logger(domain),
818       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
819       "scif_sas_domain_discovery_start_high_priority_request_handler(0x%x, 0x%x, 0x%x) enter\n",
820       domain, remote_device, io_request
821    ));
822 
823    status = fw_device->state_handlers->start_high_priority_io_handler(
824                &fw_device->parent, &fw_request->parent
825             );
826 
827    if (status == SCI_SUCCESS)
828    {
829       // Add the IO to the list of outstanding requests on the domain.
830 
831       // It is possible this high priority IO's has already been added to
832       // the domain's list as a SCIF_SAS_TASK_REQUEST. We need to check
833       // if it is already on the list.
834       if ( ! sci_fast_list_is_on_this_list(
835                &fw_domain->request_list, &fw_request->list_element))
836 
837          sci_fast_list_insert_tail(
838             &fw_domain->request_list, &fw_request->list_element
839          );
840    }
841 
842    return status;
843 }
844 
845 
846 /**
847  * @brief This method provides DISCOVERING state specific handling for
848  *        when a user attempts to complete an IO request.  User IOs are
849  *        allowed to be completed during discovery.
850  *
851  * @param[in]  domain This parameter specifies the domain object
852  *             on which the user is attempting to perform a complete IO
853  *             operation.
854  * @param[in]  remote_device This parameter specifies the remote device
855  *             object on which the user is attempting to perform a complete
856  *             IO operation.
857  * @param[in]  io_request This parameter specifies the io request that is
858  *             being completed.
859  *
860  * @return This method returns an indication of whether the complete IO
861  *         operation succeeded.
862  * @retval SCI_SUCCESS This value is returned when the complete IO operation
863  *         is successful.
864  */
865 static
866 SCI_STATUS scif_sas_domain_discovering_complete_io_handler(
867    SCI_BASE_DOMAIN_T        * domain,
868    SCI_BASE_REMOTE_DEVICE_T * remote_device,
869    SCI_BASE_REQUEST_T       * io_request
870 )
871 {
872    SCIF_LOG_TRACE((
873       sci_base_object_get_logger(domain),
874       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
875       "scif_sas_domain_discovering_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
876       domain, remote_device, io_request
877    ));
878 
879    return scif_sas_domain_ready_complete_io_handler(
880              domain, remote_device, io_request
881           );
882 }
883 
884 /**
885  * @brief This method provides DISCOVERING state specific handling for
886  *        when a user attempts to complete an high priroity IO request.  User
887  *        IOs are allowed to be completed during discovery.
888  *
889  * @param[in]  domain This parameter specifies the domain object
890  *             on which the user is attempting to perform a complete IO
891  *             operation.
892  * @param[in]  remote_device This parameter specifies the remote device
893  *             object on which the user is attempting to perform a complete
894  *             IO operation.
895  * @param[in]  io_request This parameter specifies the io request that is
896  *             being completed.
897  *
898  * @return This method returns an indication of whether the complete IO
899  *         operation succeeded.
900  * @retval SCI_SUCCESS This value is returned when the complete IO operation
901  *         is successful.
902  */
903 static
904 SCI_STATUS scif_sas_domain_discovering_complete_high_priority_io_handler(
905    SCI_BASE_DOMAIN_T        * domain,
906    SCI_BASE_REMOTE_DEVICE_T * remote_device,
907    SCI_BASE_REQUEST_T       * io_request,
908    void                     * response_data,
909    SCI_IO_STATUS              completion_status
910 )
911 {
912    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
913                                           remote_device;
914    SCIF_SAS_REQUEST_T       * fw_request= (SCIF_SAS_REQUEST_T*) io_request;
915 
916    SCIC_TRANSPORT_PROTOCOL    protocol;
917 
918    SCIF_LOG_TRACE((
919       sci_base_object_get_logger(domain),
920       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
921       "scif_sas_domain_discovering_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
922       domain, remote_device, io_request, response_data
923    ));
924 
925    protocol = scic_io_request_get_protocol(fw_request->core_object);
926 
927    // Remove the IO from the list of outstanding requests on the domain.
928 
929    // If the request is an SMP HARD/LINK RESET request, then the request
930    // came through the task management path (partially).  As a result,
931    // the accounting for the request is managed in the task request
932    // completion path.  Thus, only change the domain request counter if
933    // the request is not an SMP target reset of some sort.
934    if (
935          (protocol != SCIC_SMP_PROTOCOL)
936       || (fw_device->protocol_device.smp_device.current_activity !=
937                 SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET)
938    )
939    {
940       sci_fast_list_remove_element(&fw_request->list_element);
941    }
942 
943    return fw_device->state_handlers->complete_high_priority_io_handler(
944              &fw_device->parent, &fw_request->parent, response_data, completion_status
945           );
946 }
947 
948 
949 /**
950  * @brief This method provides DISCOVERING state specific handling for
951  *        when the framework attempts to complete an IO request.  Internal
952  *        Framework IOs allowed to be continued during discovery.
953  *
954  * @param[in]  domain This parameter specifies the domain object
955  *             on which the user is attempting to perform a continue IO
956  *             operation.
957  * @param[in]  remote_device This parameter specifies the remote device
958  *             object on which the user is attempting to perform a continue
959  *             IO operation.
960  * @param[in]  io_request This parameter specifies the io request that is
961  *             being continued.
962  *
963  * @return This method returns an indication of whether the continue IO
964  *         operation succeeded.
965  * @retval SCI_SUCCESS This value is returned when the continue IO operation
966  *         is successful.
967  */
968 static
969 SCI_STATUS scif_sas_domain_discovering_continue_io_handler(
970    SCI_BASE_DOMAIN_T        * domain,
971    SCI_BASE_REMOTE_DEVICE_T * remote_device,
972    SCI_BASE_REQUEST_T       * io_request
973 )
974 {
975    SCIF_LOG_TRACE((
976       sci_base_object_get_logger(domain),
977       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_IO_REQUEST,
978       "scif_sas_domain_discovering_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
979       domain, remote_device, io_request
980    ));
981 
982    /// @todo fix return code handling.
983    return SCI_FAILURE;
984 }
985 
986 
987 /**
988  * @brief This method provides handling when a user attempts to start
989  *        a task on a domain in DISCOVER state, only hard reset is allowed.
990  *
991  * @param[in]  domain This parameter specifies the domain object
992  *             on which the user is attempting to perform a start task
993  *             operation.
994  * @param[in]  remote_device This parameter specifies the remote device
995  *             object on which the user is attempting to perform a start IO
996  *             operation.
997  * @param[in]  task_request This parameter specifies the task request that
998  *             is being started.
999  *
1000  * @return This method returns a status of start task operations
1001  * @retval SCI_FAILURE_INVALID_STATE This value is returned for any tasks,
1002  *         except for HARD RESET.
1003  */
1004 static
1005 SCI_STATUS scif_sas_domain_discovering_start_task_handler(
1006    SCI_BASE_DOMAIN_T        * domain,
1007    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1008    SCI_BASE_REQUEST_T       * task_request
1009 )
1010 {
1011    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
1012                                           remote_device;
1013    SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
1014 
1015    //Only let target reset go through.
1016    if (scif_sas_task_request_get_function(fw_task)
1017              == SCI_SAS_HARD_RESET)
1018    {
1019       //If the domain is in the middle of smp DISCOVER process,
1020       //interrupt it. After target reset is done, resume the smp DISCOVERY.
1021       scif_sas_domain_cancel_smp_activities(fw_device->domain);
1022 
1023       return scif_sas_domain_ready_start_task_handler(domain, remote_device, task_request);
1024    }
1025    else{
1026       SCIF_LOG_WARNING((
1027          sci_base_object_get_logger(domain),
1028          SCIF_LOG_OBJECT_DOMAIN,
1029          "Domain:0x%x Device:0x%x State:0x%x start task message invalid\n",
1030          domain, remote_device,
1031          sci_base_state_machine_get_state(&domain->state_machine)
1032       ));
1033 
1034       return SCI_FAILURE_INVALID_STATE;
1035    }
1036 }
1037 
1038 
1039 /**
1040  * @brief This method provides DISCOVERING state specific handling for
1041  *        when a user attempts to complete a task request.  User task
1042  *        management requests are allowed to be completed during discovery.
1043  *
1044  * @param[in]  domain This parameter specifies the domain object
1045  *             on which the user is attempting to perform a complete IO
1046  *             operation.
1047  * @param[in]  remote_device This parameter specifies the remote device
1048  *             object on which the user is attempting to perform a complete
1049  *             IO operation.
1050  * @param[in]  task_request This parameter specifies the task request that
1051  *             is being completed.
1052  *
1053  * @return This method returns an indication of whether the complete task
1054  *         management operation succeeded.
1055  * @retval SCI_SUCCESS This value is returned when the complete task request
1056  *         is successful.
1057  */
1058 static
1059 SCI_STATUS scif_sas_domain_discovering_complete_task_handler(
1060    SCI_BASE_DOMAIN_T        * domain,
1061    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1062    SCI_BASE_REQUEST_T       * task_request
1063 )
1064 {
1065    SCI_STATUS status;
1066 
1067    SCIF_LOG_TRACE((
1068       sci_base_object_get_logger(domain),
1069       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
1070       "scif_sas_domain_discovering_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
1071       domain, remote_device, task_request
1072    ));
1073 
1074    status = scif_sas_domain_ready_complete_task_handler(
1075                domain, remote_device, task_request
1076             );
1077 
1078    return status;
1079 }
1080 
1081 //******************************************************************************
1082 //* D E F A U L T   H A N D L E R S
1083 //******************************************************************************
1084 
1085 /**
1086  * @brief This method provides default handling (i.e. returns an error)
1087  *        when a user attempts to discover a domain and a discovery
1088  *        operation is not allowed.
1089  *
1090  * @param[in]  domain This parameter specifies the domain object
1091  *             on which the user is attempting to perform an discover
1092  *             operation.
1093  * @param[in]  op_timeout This parameter specifies the timeout
1094  *             (in milliseconds) for the entire discovery operation.
1095  *             This timeout value should be some multiple of the
1096  *             individual device_timeout value.
1097  * @param[in]  device_timeout This parameter specifies the timeout
1098  *             (in milliseconds) for an individual device being discovered
1099  *             and configured during this operation.
1100  *
1101  * @return This method returns an indication that discovery operations
1102  *         are not allowed.
1103  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1104  */
1105 static
1106 SCI_STATUS scif_sas_domain_default_discover_handler(
1107    SCI_BASE_DOMAIN_T * domain,
1108    U32                 op_timeout,
1109    U32                 device_timeout
1110 )
1111 {
1112    SCIF_LOG_WARNING((
1113       sci_base_object_get_logger((SCIF_SAS_DOMAIN_T *)domain),
1114       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
1115       "Domain:0x%x State:0x%x requested to discover in invalid state\n",
1116       domain,
1117       sci_base_state_machine_get_state(&domain->state_machine)
1118    ));
1119 
1120    return SCI_FAILURE_INVALID_STATE;
1121 }
1122 
1123 /**
1124  * @brief This method provides default processing for reception of a port
1125  *        ready notification from the core.
1126  *
1127  * @param[in]  domain This parameter specifies the domain object
1128  *             on which the core port has just come ready.
1129  *
1130  * @return
1131  */
1132 static
1133 SCI_STATUS scif_sas_domain_default_port_ready_handler(
1134    SCI_BASE_DOMAIN_T * domain
1135 )
1136 {
1137    SCIF_LOG_INFO((
1138       sci_base_object_get_logger(domain),
1139       SCIF_LOG_OBJECT_DOMAIN,
1140       "Domain:0x%x State:0x%x port now ready\n",
1141       domain,
1142       sci_base_state_machine_get_state(&domain->state_machine)
1143    ));
1144 
1145    return SCI_SUCCESS;
1146 }
1147 
1148 /**
1149  * @brief This method provides default processing for reception of a port
1150  *        NOT ready notification from the core.
1151  *
1152  * @param[in]  domain This parameter specifies the domain object
1153  *             on which the core port has just come ready.
1154  *
1155  * @return
1156  */
1157 static
1158 SCI_STATUS scif_sas_domain_default_port_not_ready_handler(
1159    SCI_BASE_DOMAIN_T * domain,
1160    U32                 reason_code
1161 )
1162 {
1163    SCIF_LOG_WARNING((
1164       sci_base_object_get_logger(domain),
1165       SCIF_LOG_OBJECT_DOMAIN,
1166       "Domain:0x%x State:0x%x Port Not Ready 0x%x in invalid state\n",
1167       domain,
1168       sci_base_state_machine_get_state(&domain->state_machine),
1169       reason_code
1170    ));
1171 
1172    return SCI_FAILURE_INVALID_STATE;
1173 }
1174 
1175 /**
1176  * @brief This method provides default handling (i.e. returns an error)
1177  *        when a user attempts to start an IO on a domain and a start
1178  *        IO operation is not allowed.
1179  *
1180  * @param[in]  domain This parameter specifies the domain object
1181  *             on which the user is attempting to perform a start IO
1182  *             operation.
1183  * @param[in]  remote_device This parameter specifies the remote device
1184  *             object on which the user is attempting to perform a start IO
1185  *             operation.
1186  * @param[in]  io_request This parameter specifies the io request that is
1187  *             being started.
1188  *
1189  * @return This method returns an indication that start IO operations
1190  *         are not allowed.
1191  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1192  */
1193 static
1194 SCI_STATUS scif_sas_domain_default_start_io_handler(
1195    SCI_BASE_DOMAIN_T        * domain,
1196    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1197    SCI_BASE_REQUEST_T       * io_request
1198 )
1199 {
1200    SCIF_LOG_WARNING((
1201       sci_base_object_get_logger(domain),
1202       SCIF_LOG_OBJECT_DOMAIN,
1203       "Domain:0x%x Device:0x%x State:0x%x start IO message invalid\n",
1204       domain, remote_device,
1205       sci_base_state_machine_get_state(&domain->state_machine)
1206    ));
1207 
1208    return SCI_FAILURE_INVALID_STATE;
1209 }
1210 
1211 /**
1212  * @brief This method provides default handling (i.e. returns an error)
1213  *        when a user attempts to complete an IO on a domain and a
1214  *        complete IO operation is not allowed.
1215  *
1216  * @param[in]  domain This parameter specifies the domain object
1217  *             on which the user is attempting to perform a complete IO
1218  *             operation.
1219  * @param[in]  remote_device This parameter specifies the remote device
1220  *             object on which the user is attempting to perform a complete IO
1221  *             operation.
1222  * @param[in]  io_request This parameter specifies the io request that is
1223  *             being completed.
1224  *
1225  * @return This method returns an indication that complete IO operations
1226  *         are not allowed.
1227  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1228  */
1229 static
1230 SCI_STATUS scif_sas_domain_default_complete_io_handler(
1231    SCI_BASE_DOMAIN_T        * domain,
1232    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1233    SCI_BASE_REQUEST_T       * io_request
1234 )
1235 {
1236    SCIF_LOG_WARNING((
1237       sci_base_object_get_logger(domain),
1238       SCIF_LOG_OBJECT_DOMAIN,
1239       "Domain:0x%x Device:0x%x State:0x%x complete IO message invalid\n",
1240       domain, remote_device,
1241       sci_base_state_machine_get_state(&domain->state_machine)
1242    ));
1243 
1244    return SCI_FAILURE_INVALID_STATE;
1245 }
1246 
1247 
1248 /**
1249  * @brief This method provides default handling (i.e. returns an error)
1250  *        when a user attempts to complete an IO on a domain and a
1251  *        complete IO operation is not allowed.
1252  *
1253  * @param[in]  domain This parameter specifies the domain object
1254  *             on which the user is attempting to perform a complete IO
1255  *             operation.
1256  * @param[in]  remote_device This parameter specifies the remote device
1257  *             object on which the user is attempting to perform a complete IO
1258  *             operation.
1259  * @param[in]  io_request This parameter specifies the io request that is
1260  *             being completed.
1261  *
1262  * @return This method returns an indication that complete IO operations
1263  *         are not allowed.
1264  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1265  */
1266 static
1267 SCI_STATUS scif_sas_domain_default_complete_high_priority_io_handler(
1268    SCI_BASE_DOMAIN_T        * domain,
1269    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1270    SCI_BASE_REQUEST_T       * io_request,
1271    void                     * response_data,
1272    SCI_IO_STATUS              completion_status
1273 )
1274 {
1275    SCIF_LOG_WARNING((
1276       sci_base_object_get_logger(domain),
1277       SCIF_LOG_OBJECT_DOMAIN,
1278       "Domain:0x%x Device:0x%x State:0x%x complete IO message invalid\n",
1279       domain, remote_device,
1280       sci_base_state_machine_get_state(&domain->state_machine)
1281    ));
1282 
1283    return SCI_FAILURE_INVALID_STATE;
1284 }
1285 
1286 /**
1287  * @brief This method provides default handling (i.e. returns an error)
1288  *        when a user attempts to continue an IO on a domain and a
1289  *        continue IO operation is not allowed.
1290  *
1291  * @param[in]  domain This parameter specifies the domain object
1292  *             on which the user is attempting to perform a continue IO
1293  *             operation.
1294  * @param[in]  remote_device This parameter specifies the remote device
1295  *             object on which the user is attempting to perform a start IO
1296  *             operation.
1297  * @param[in]  io_request This parameter specifies the io request that is
1298  *             being started.
1299  *
1300  * @return This method returns an indication that continue IO operations
1301  *         are not allowed.
1302  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1303  */
1304 static
1305 SCI_STATUS scif_sas_domain_default_continue_io_handler(
1306    SCI_BASE_DOMAIN_T        * domain,
1307    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1308    SCI_BASE_REQUEST_T       * io_request
1309 )
1310 {
1311    SCIF_LOG_WARNING((
1312       sci_base_object_get_logger(domain),
1313       SCIF_LOG_OBJECT_DOMAIN,
1314       "Domain:0x%x Device:0x%x State:0x%x contineu IO message invalid\n",
1315       domain, remote_device,
1316       sci_base_state_machine_get_state(&domain->state_machine)
1317    ));
1318 
1319    return SCI_FAILURE_INVALID_STATE;
1320 }
1321 
1322 /**
1323  * @brief This method provides default handling (i.e. returns an error)
1324  *        when a user attempts to start a task on a domain and a start
1325  *        task operation is not allowed.
1326  *
1327  * @param[in]  domain This parameter specifies the domain object
1328  *             on which the user is attempting to perform a start task
1329  *             operation.
1330  * @param[in]  remote_device This parameter specifies the remote device
1331  *             object on which the user is attempting to perform a start IO
1332  *             operation.
1333  * @param[in]  task_request This parameter specifies the task request that
1334  *             is being started.
1335  *
1336  * @return This method returns an indication that start task operations
1337  *         are not allowed.
1338  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1339  */
1340 static
1341 SCI_STATUS scif_sas_domain_default_start_task_handler(
1342    SCI_BASE_DOMAIN_T        * domain,
1343    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1344    SCI_BASE_REQUEST_T       * task_request
1345 )
1346 {
1347    SCIF_LOG_WARNING((
1348       sci_base_object_get_logger(domain),
1349       SCIF_LOG_OBJECT_DOMAIN,
1350       "Domain:0x%x Device:0x%x State:0x%x start task message invalid\n",
1351       domain, remote_device,
1352       sci_base_state_machine_get_state(&domain->state_machine)
1353    ));
1354 
1355    return SCI_FAILURE_INVALID_STATE;
1356 }
1357 
1358 /**
1359  * @brief This method provides default handling (i.e. returns an error)
1360  *        when a user attempts to complete a task on a domain and a
1361  *        complete task operation is not allowed.
1362  *
1363  * @param[in]  domain This parameter specifies the domain object
1364  *             on which the user is attempting to perform a complete task
1365  *             operation.
1366  * @param[in]  remote_device This parameter specifies the remote device
1367  *             object on which the user is attempting to perform a start IO
1368  *             operation.
1369  * @param[in]  task_request This parameter specifies the task request that
1370  *             is being started.
1371  *
1372  * @return This method returns an indication that complete task operations
1373  *         are not allowed.
1374  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1375  */
1376 static
1377 SCI_STATUS scif_sas_domain_default_complete_task_handler(
1378    SCI_BASE_DOMAIN_T        * domain,
1379    SCI_BASE_REMOTE_DEVICE_T * remote_device,
1380    SCI_BASE_REQUEST_T       * task_request
1381 )
1382 {
1383    SCIF_LOG_WARNING((
1384       sci_base_object_get_logger(domain),
1385       SCIF_LOG_OBJECT_DOMAIN,
1386       "Domain:0x%x Device:0x%x State:0x%x complete task message invalid\n",
1387       domain, remote_device,
1388       sci_base_state_machine_get_state(&domain->state_machine)
1389    ));
1390 
1391    return SCI_FAILURE_INVALID_STATE;
1392 }
1393 
1394 /**
1395  * @brief This method provides default handling (i.e. returns an error)
1396  *        when a remote device start operation completes in a state.
1397  *
1398  * @param[in]  domain This parameter specifies the domain object
1399  *             on which the remote device start operation is completing.
1400  * @param[in]  remote_device This parameter specifies the remote device
1401  *             for which the start operation is completing.
1402  *
1403  * @return This method returns an indication that start operation
1404  *         completion is not allowed.
1405  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1406  */
1407 static
1408 SCI_STATUS scif_sas_domain_default_device_start_complete_handler(
1409    SCI_BASE_DOMAIN_T        * domain,
1410    SCI_BASE_REMOTE_DEVICE_T * remote_device
1411 )
1412 {
1413    SCIF_LOG_WARNING((
1414       sci_base_object_get_logger(domain),
1415       SCIF_LOG_OBJECT_DOMAIN,
1416       "Domain:0x%x Device:0x%x State:0x%x device stop complete message invalid\n",
1417       domain, remote_device,
1418       sci_base_state_machine_get_state(&domain->state_machine)
1419    ));
1420 
1421    return SCI_FAILURE_INVALID_STATE;
1422 }
1423 
1424 /**
1425  * @brief This method provides default handling (i.e. returns an error)
1426  *        when a remote device stop operation completes in a state.
1427  *
1428  * @param[in]  domain This parameter specifies the domain object
1429  *             on which the remote device stop operation is completing.
1430  * @param[in]  remote_device This parameter specifies the remote device
1431  *             for which the stop operation is completing.
1432  *
1433  * @return This method returns an indication that stop operation
1434  *         completion is not allowed.
1435  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1436  */
1437 static
1438 SCI_STATUS scif_sas_domain_default_device_stop_complete_handler(
1439    SCI_BASE_DOMAIN_T        * domain,
1440    SCI_BASE_REMOTE_DEVICE_T * remote_device
1441 )
1442 {
1443    SCIF_LOG_WARNING((
1444       sci_base_object_get_logger(domain),
1445       SCIF_LOG_OBJECT_DOMAIN,
1446       "Domain:0x%x Device:0x%x State:0x%x device stop complete message invalid\n",
1447       domain, remote_device,
1448       sci_base_state_machine_get_state(&domain->state_machine)
1449    ));
1450 
1451    return SCI_FAILURE_INVALID_STATE;
1452 }
1453 
1454 /**
1455  * @brief This method provides default handling (i.e. returns an error)
1456  *        when sci user try to destruct a remote device of this domain.
1457  *
1458  * @param[in]  domain This parameter specifies the domain object
1459  *             on which the remote device is to be destructed.
1460  * @param[in]  remote_device This parameter specifies the remote device
1461  *             to be destructed.
1462  *
1463  * @return This method returns an indication that device destruction
1464  *         is not allowed.
1465  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1466  */
1467 static
1468 SCI_STATUS scif_sas_domain_default_device_destruct_handler(
1469    SCI_BASE_DOMAIN_T        * domain,
1470    SCI_BASE_REMOTE_DEVICE_T * remote_device
1471 )
1472 {
1473    SCIF_LOG_WARNING((
1474       sci_base_object_get_logger(domain),
1475       SCIF_LOG_OBJECT_DOMAIN,
1476       "Domain:0x%x Device:0x%x State:0x%x device destruct in invalid state\n",
1477       domain, remote_device,
1478       sci_base_state_machine_get_state(&domain->state_machine)
1479    ));
1480 
1481    return SCI_FAILURE_INVALID_STATE;
1482 }
1483 
1484 
1485 /**
1486  * @brief This method provides handling when sci user destruct a remote
1487  *        device of this domain in discovering state. Mainly the device
1488  *        is removed from domain's remote_device_list.
1489  *
1490  * @param[in]  domain This parameter specifies the domain object
1491  *             on which the remote device is to be destructed.
1492  * @param[in]  remote_device This parameter specifies the remote device
1493  *             to be destructed.
1494  *
1495  * @return This method returns a status of the device destruction.
1496  * @retval SCI_SUCCESS This value is returned when a remote device is
1497  *         successfully removed from domain.
1498  */
1499 static
1500 SCI_STATUS scif_sas_domain_discovering_device_destruct_handler(
1501    SCI_BASE_DOMAIN_T        * domain,
1502    SCI_BASE_REMOTE_DEVICE_T * remote_device
1503 )
1504 {
1505    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)domain;
1506 
1507    SCIF_LOG_WARNING((
1508       sci_base_object_get_logger(domain),
1509       SCIF_LOG_OBJECT_DOMAIN,
1510       "Domain:0x%x Device:0x%x State:0x%x device destruct in domain DISCOVERING state\n",
1511       domain, remote_device,
1512       sci_base_state_machine_get_state(&domain->state_machine)
1513    ));
1514 
1515    //remove the remote device from domain's remote_device_list
1516    sci_abstract_list_erase(
1517       &(fw_domain->remote_device_list),
1518       remote_device
1519    );
1520 
1521    return SCI_SUCCESS;
1522 }
1523 
1524 
1525 #define scif_sas_domain_stopped_discover_handler \
1526         scif_sas_domain_ready_discover_handler
1527 
1528 #define scif_sas_domain_default_start_high_priority_io_handler \
1529         scif_sas_domain_default_start_io_handler
1530 
1531 
1532 SCI_BASE_DOMAIN_STATE_HANDLER_T
1533    scif_sas_domain_state_handler_table[SCI_BASE_DOMAIN_MAX_STATES] =
1534 {
1535    // SCI_BASE_DOMAIN_STATE_INITIAL
1536    {
1537       scif_sas_domain_default_discover_handler,
1538       scif_sas_domain_default_port_ready_handler,
1539       scif_sas_domain_default_port_not_ready_handler,
1540       scif_sas_domain_default_device_start_complete_handler,
1541       scif_sas_domain_default_device_stop_complete_handler,
1542       scif_sas_domain_default_device_destruct_handler,
1543       scif_sas_domain_default_start_io_handler,
1544       scif_sas_domain_default_start_high_priority_io_handler,
1545       scif_sas_domain_default_complete_io_handler,
1546       scif_sas_domain_default_complete_high_priority_io_handler,
1547       scif_sas_domain_default_continue_io_handler,
1548       scif_sas_domain_default_start_task_handler,
1549       scif_sas_domain_default_complete_task_handler
1550    },
1551    // SCI_BASE_DOMAIN_STATE_STARTING
1552    {
1553       scif_sas_domain_default_discover_handler,
1554       scif_sas_domain_starting_port_ready_handler,
1555       scif_sas_domain_default_port_not_ready_handler,
1556       scif_sas_domain_default_device_start_complete_handler,
1557       scif_sas_domain_default_device_stop_complete_handler,
1558       scif_sas_domain_default_device_destruct_handler,
1559       scif_sas_domain_default_start_io_handler,
1560       scif_sas_domain_default_start_high_priority_io_handler,
1561       scif_sas_domain_default_complete_io_handler,
1562       scif_sas_domain_default_complete_high_priority_io_handler,
1563       scif_sas_domain_default_continue_io_handler,
1564       scif_sas_domain_default_start_task_handler,
1565       scif_sas_domain_default_complete_task_handler
1566    },
1567    // SCI_BASE_DOMAIN_STATE_READY
1568    {
1569       scif_sas_domain_ready_discover_handler,
1570       scif_sas_domain_default_port_ready_handler,
1571       scif_sas_domain_ready_port_not_ready_handler,
1572       scif_sas_domain_default_device_start_complete_handler,
1573       scif_sas_domain_default_device_stop_complete_handler,
1574       scif_sas_domain_default_device_destruct_handler,
1575       scif_sas_domain_ready_start_io_handler,
1576       scif_sas_domain_ready_start_high_priority_io_handler,
1577       scif_sas_domain_ready_complete_io_handler,
1578       scif_sas_domain_ready_complete_high_priority_io_handler,
1579       scif_sas_domain_ready_continue_io_handler,
1580       scif_sas_domain_ready_start_task_handler,
1581       scif_sas_domain_ready_complete_task_handler
1582    },
1583    // SCI_BASE_DOMAIN_STATE_STOPPING
1584    {
1585       scif_sas_domain_default_discover_handler,
1586       scif_sas_domain_default_port_ready_handler,
1587       scif_sas_domain_default_port_not_ready_handler,
1588       scif_sas_domain_default_device_start_complete_handler,
1589       scif_sas_domain_stopping_device_stop_complete_handler,
1590       scif_sas_domain_default_device_destruct_handler,
1591       scif_sas_domain_default_start_io_handler,
1592       scif_sas_domain_default_start_high_priority_io_handler,
1593       scif_sas_domain_stopping_complete_io_handler,
1594       scif_sas_domain_stopping_complete_high_priority_io_handler,
1595       scif_sas_domain_default_continue_io_handler,
1596       scif_sas_domain_default_start_task_handler,
1597       scif_sas_domain_stopping_complete_task_handler
1598    },
1599    // SCI_BASE_DOMAIN_STATE_STOPPED
1600    {
1601       scif_sas_domain_stopped_discover_handler,
1602       scif_sas_domain_default_port_ready_handler,
1603       scif_sas_domain_default_port_not_ready_handler,
1604       scif_sas_domain_default_device_start_complete_handler,
1605       scif_sas_domain_default_device_stop_complete_handler,
1606       scif_sas_domain_default_device_destruct_handler,
1607       scif_sas_domain_default_start_io_handler,
1608       scif_sas_domain_default_start_high_priority_io_handler,
1609       scif_sas_domain_default_complete_io_handler,
1610       scif_sas_domain_default_complete_high_priority_io_handler,
1611       scif_sas_domain_default_continue_io_handler,
1612       scif_sas_domain_default_start_task_handler,
1613       scif_sas_domain_default_complete_task_handler
1614    },
1615    // SCI_BASE_DOMAIN_STATE_DISCOVERING
1616    {
1617       scif_sas_domain_default_discover_handler,
1618       scif_sas_domain_default_port_ready_handler,
1619       scif_sas_domain_discovering_port_not_ready_handler,
1620       scif_sas_domain_discovering_device_start_complete_handler,
1621       scif_sas_domain_discovering_device_stop_complete_handler,
1622       scif_sas_domain_discovering_device_destruct_handler,  //
1623       scif_sas_domain_default_start_io_handler,
1624       scif_sas_domain_discovering_start_high_priority_io_handler,
1625       scif_sas_domain_discovering_complete_io_handler,
1626       scif_sas_domain_discovering_complete_high_priority_io_handler, //
1627       scif_sas_domain_discovering_continue_io_handler,
1628       scif_sas_domain_discovering_start_task_handler,
1629       scif_sas_domain_discovering_complete_task_handler
1630    }
1631 };
1632 
1633