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