1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris *
59230557Sjimharris * @brief This file contains all of the method implementations pertaining
60230557Sjimharris *        to the framework remote device READY sub-state handler methods.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris#include <dev/isci/scil/scic_remote_device.h>
64230557Sjimharris#include <dev/isci/scil/scic_io_request.h>
65230557Sjimharris
66230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
67230557Sjimharris#include <dev/isci/scil/scif_sas_remote_device.h>
68230557Sjimharris#include <dev/isci/scil/scif_sas_domain.h>
69230557Sjimharris#include <dev/isci/scil/scif_sas_task_request.h>
70230557Sjimharris#include <dev/isci/scil/scif_sas_io_request.h>
71230557Sjimharris#include <dev/isci/scil/scif_sas_internal_io_request.h>
72230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h>
73230557Sjimharris#include <dev/isci/scil/sci_abstract_list.h>
74230557Sjimharris#include <dev/isci/scil/intel_sat.h>
75230557Sjimharris#include <dev/isci/scil/sci_controller.h>
76230557Sjimharris
77230557Sjimharris//******************************************************************************
78230557Sjimharris//* P R I V A T E   M E T H O D S
79230557Sjimharris//******************************************************************************
80230557Sjimharris
81230557Sjimharris/**
82230557Sjimharris * @brief This method implements the behavior common to starting a task mgmt
83230557Sjimharris *        request.  It will change the ready substate to task management.
84230557Sjimharris *
85230557Sjimharris * @param[in]  fw_device This parameter specifies the remote device for
86230557Sjimharris *             which to complete a request.
87230557Sjimharris * @param[in]  fw_task This parameter specifies the task management
88230557Sjimharris *             request being started.
89230557Sjimharris *
90230557Sjimharris * @return This method returns a value indicating the status of the
91230557Sjimharris *         start operation.
92230557Sjimharris */
93230557Sjimharrisstatic
94230557SjimharrisSCI_STATUS scif_sas_remote_device_start_task_request(
95230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
96230557Sjimharris   SCIF_SAS_TASK_REQUEST_T  * fw_task
97230557Sjimharris)
98230557Sjimharris{
99230557Sjimharris   // Transition into the TASK MGMT substate if not already in it.
100230557Sjimharris   if (fw_device->ready_substate_machine.current_state_id
101230557Sjimharris       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
102230557Sjimharris   {
103230557Sjimharris      sci_base_state_machine_change_state(
104230557Sjimharris         &fw_device->ready_substate_machine,
105230557Sjimharris         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
106230557Sjimharris      );
107230557Sjimharris   }
108230557Sjimharris
109230557Sjimharris   fw_device->request_count++;
110230557Sjimharris   fw_device->task_request_count++;
111230557Sjimharris
112230557Sjimharris   return SCI_SUCCESS;
113230557Sjimharris}
114230557Sjimharris
115230557Sjimharris//******************************************************************************
116230557Sjimharris//* R E A D Y   O P E R A T I O N A L   H A N D L E R S
117230557Sjimharris//******************************************************************************
118230557Sjimharris
119230557Sjimharris/**
120230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
121230557Sjimharris *        when the core remote device object issues a device not ready
122230557Sjimharris *        notification.
123230557Sjimharris *
124230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
125230557Sjimharris *             object for which the notification occurred.
126230557Sjimharris *
127230557Sjimharris * @return none.
128230557Sjimharris */
129230557Sjimharrisstatic
130230557Sjimharrisvoid scif_sas_remote_device_ready_operational_not_ready_handler(
131230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
132230557Sjimharris   U32                        reason_code
133230557Sjimharris)
134230557Sjimharris{
135230557Sjimharris   if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
136230557Sjimharris   {
137230557Sjimharris      sci_base_state_machine_change_state(
138230557Sjimharris         &fw_device->ready_substate_machine,
139230557Sjimharris         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
140230557Sjimharris      );
141230557Sjimharris   }
142230557Sjimharris   else
143230557Sjimharris   {
144230557Sjimharris      // Even though we are in the OPERATIONAL state, the core remote device is not
145230557Sjimharris      // ready.  As a result, we process user requests/events as if we were
146230557Sjimharris      // stopping the framework remote device.
147230557Sjimharris      sci_base_state_machine_change_state(
148230557Sjimharris         &fw_device->ready_substate_machine,
149230557Sjimharris         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
150230557Sjimharris      );
151230557Sjimharris   }
152230557Sjimharris}
153230557Sjimharris
154230557Sjimharris/**
155230557Sjimharris * @brief This method provides TASK MGMT sub-state specific handling for when
156230557Sjimharris *        the core remote device object issues a device not ready notification.
157230557Sjimharris *
158230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
159230557Sjimharris *             object for which the notification occurred.
160230557Sjimharris *
161230557Sjimharris * @return none.
162230557Sjimharris */
163230557Sjimharrisstatic
164230557Sjimharrisvoid scif_sas_remote_device_ready_task_management_not_ready_handler(
165230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
166230557Sjimharris   U32                        reason_code
167230557Sjimharris)
168230557Sjimharris{
169230557Sjimharris   //do nothing. Don't need to go to suspended substate.
170230557Sjimharris}
171230557Sjimharris
172230557Sjimharris/**
173230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
174230557Sjimharris *        when the remote device is being stopped by the framework.
175230557Sjimharris *
176230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
177230557Sjimharris *             object for which the stop operation is being requested.
178230557Sjimharris *
179230557Sjimharris * @return This method returns an indication as to whether the failure
180230557Sjimharris *         operation completed successfully.
181230557Sjimharris */
182230557Sjimharrisstatic
183230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_stop_handler(
184230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device
185230557Sjimharris)
186230557Sjimharris{
187230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
188230557Sjimharris                                          remote_device;
189230557Sjimharris
190230557Sjimharris   sci_base_state_machine_change_state(
191230557Sjimharris      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
192230557Sjimharris   );
193230557Sjimharris
194230557Sjimharris   return fw_device->operation_status;
195230557Sjimharris}
196230557Sjimharris
197230557Sjimharris/**
198230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
199230557Sjimharris *        when the user attempts to destruct the remote device.  In
200230557Sjimharris *        the READY state the framework must first stop the device
201230557Sjimharris *        before destructing it.
202230557Sjimharris *
203230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
204230557Sjimharris *             object for which the framework is attempting to start.
205230557Sjimharris *
206230557Sjimharris * @return This method returns an indication as to whether the destruct
207230557Sjimharris *         operation completed successfully.
208230557Sjimharris */
209230557Sjimharrisstatic
210230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_destruct_handler(
211230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device
212230557Sjimharris)
213230557Sjimharris{
214230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
215230557Sjimharris                                          remote_device;
216230557Sjimharris
217230557Sjimharris   fw_device->destruct_when_stopped = TRUE;
218230557Sjimharris
219230557Sjimharris   return (fw_device->state_handlers->parent.stop_handler(&fw_device->parent));
220230557Sjimharris}
221230557Sjimharris
222230557Sjimharris/**
223230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
224230557Sjimharris *        when the remote device undergoes a failure condition.
225230557Sjimharris *
226230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
227230557Sjimharris *             object for which the failure condition occurred.
228230557Sjimharris *
229230557Sjimharris * @return This method returns an indication as to whether the failure
230230557Sjimharris *         operation completed successfully.
231230557Sjimharris */
232230557Sjimharrisstatic
233230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_fail_handler(
234230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device
235230557Sjimharris)
236230557Sjimharris{
237230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
238230557Sjimharris                                          remote_device;
239230557Sjimharris
240230557Sjimharris   SCIF_LOG_WARNING((
241230557Sjimharris      sci_base_object_get_logger(fw_device),
242230557Sjimharris      SCIF_LOG_OBJECT_REMOTE_DEVICE,
243230557Sjimharris      "RemoteDevice:0x%x ready device failed\n",
244230557Sjimharris      fw_device
245230557Sjimharris   ));
246230557Sjimharris
247230557Sjimharris   sci_base_state_machine_change_state(
248230557Sjimharris      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FAILED
249230557Sjimharris   );
250230557Sjimharris
251230557Sjimharris   /// @todo Fix the return code handling.
252230557Sjimharris   return SCI_FAILURE;
253230557Sjimharris}
254230557Sjimharris
255230557Sjimharris/**
256230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
257230557Sjimharris *        when a user attempts to start an IO request on a remote
258230557Sjimharris *        device.
259230557Sjimharris *
260230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
261230557Sjimharris *             object on which the user is attempting to perform a start
262230557Sjimharris *             IO operation.
263230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to be
264230557Sjimharris *             started.
265230557Sjimharris *
266230557Sjimharris * @return This method returns an indication as to whether the IO request
267230557Sjimharris *         started successfully.
268230557Sjimharris */
269230557Sjimharrisstatic
270230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_start_io_handler(
271230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
272230557Sjimharris   SCI_BASE_REQUEST_T       * io_request
273230557Sjimharris)
274230557Sjimharris{
275230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
276230557Sjimharris                                          remote_device;
277230557Sjimharris   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
278230557Sjimharris   SCI_STATUS                 status;
279230557Sjimharris
280230557Sjimharris   status = fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
281230557Sjimharris
282230557Sjimharris   if (status == SCI_SUCCESS)
283230557Sjimharris   {
284230557Sjimharris      fw_device->request_count++;
285230557Sjimharris   }
286230557Sjimharris
287230557Sjimharris   return status;
288230557Sjimharris}
289230557Sjimharris
290230557Sjimharris/**
291230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
292230557Sjimharris *        when a user attempts to start an IO request on a remote
293230557Sjimharris *        device.
294230557Sjimharris *
295230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
296230557Sjimharris *             object on which the user is attempting to perform a complete
297230557Sjimharris *             IO operation.
298230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to
299230557Sjimharris *             be completed.
300230557Sjimharris *
301230557Sjimharris * @return This method returns an indication as to whether the IO request
302230557Sjimharris *         completed successfully.
303230557Sjimharris */
304230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_complete_io_handler(
305230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
306230557Sjimharris   SCI_BASE_REQUEST_T       * io_request
307230557Sjimharris)
308230557Sjimharris{
309230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
310230557Sjimharris                                          remote_device;
311230557Sjimharris   fw_device->request_count--;
312230557Sjimharris   return SCI_SUCCESS;
313230557Sjimharris}
314230557Sjimharris
315230557Sjimharris
316230557Sjimharris/**
317230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
318230557Sjimharris *        when a user attempts to start an IO request on a remote
319230557Sjimharris *        device.
320230557Sjimharris *
321230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
322230557Sjimharris *             object on which the user is attempting to perform a complete
323230557Sjimharris *             IO operation.
324230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to
325230557Sjimharris *             be completed.
326230557Sjimharris *
327230557Sjimharris * @return This method returns an indication as to whether the IO request
328230557Sjimharris *         completed successfully.
329230557Sjimharris */
330230557Sjimharrisstatic
331230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_complete_high_priority_io_handler(
332230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
333230557Sjimharris   SCI_BASE_REQUEST_T       * io_request,
334230557Sjimharris   void                     * response_data,
335230557Sjimharris   SCI_IO_STATUS              completion_status
336230557Sjimharris)
337230557Sjimharris{
338230557Sjimharris   SCIF_LOG_WARNING((
339230557Sjimharris      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
340230557Sjimharris      SCIF_LOG_OBJECT_REMOTE_DEVICE,
341230557Sjimharris      "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
342230557Sjimharris      remote_device,
343230557Sjimharris      sci_base_state_machine_get_state(
344230557Sjimharris         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
345230557Sjimharris   ));
346230557Sjimharris
347230557Sjimharris   return SCI_FAILURE_INVALID_STATE;
348230557Sjimharris}
349230557Sjimharris
350230557Sjimharris
351230557Sjimharris/**
352230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for when
353230557Sjimharris *        the framework attempts to continue an IO request on a remote
354230557Sjimharris *        device.
355230557Sjimharris *
356230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
357230557Sjimharris *             object on which the user is attempting to perform a continue
358230557Sjimharris *             IO operation.
359230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to
360230557Sjimharris *             be continued.
361230557Sjimharris *
362230557Sjimharris * @return This method returns an indication as to whether the IO request
363230557Sjimharris *         completed successfully.
364230557Sjimharris */
365230557Sjimharrisstatic
366230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_continue_io_handler(
367230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
368230557Sjimharris   SCI_BASE_REQUEST_T       * io_request
369230557Sjimharris)
370230557Sjimharris{
371230557Sjimharris   /// @todo Fix the return code handling.
372230557Sjimharris   return SCI_FAILURE;
373230557Sjimharris}
374230557Sjimharris
375230557Sjimharris/**
376230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
377230557Sjimharris *        when a user attempts to start a task management request on
378230557Sjimharris *        a remote device.  This includes terminating all of the affected
379230557Sjimharris *        ongoing IO requests (i.e. aborting them in the silicon) and then
380230557Sjimharris *        issuing the task management request to the silicon.
381230557Sjimharris *
382230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
383230557Sjimharris *             object on which the user is attempting to perform a start
384230557Sjimharris *             task operation.
385230557Sjimharris * @param[in]  task_request This parameter specifies the task management
386230557Sjimharris *             request to be started.
387230557Sjimharris *
388230557Sjimharris * @return This method returns an indication as to whether the task
389230557Sjimharris *         management request started successfully.
390230557Sjimharris */
391230557Sjimharrisstatic
392230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_start_task_handler(
393230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
394230557Sjimharris   SCI_BASE_REQUEST_T       * task_request
395230557Sjimharris)
396230557Sjimharris{
397230557Sjimharris   SCI_STATUS                 status     = SCI_FAILURE;
398230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
399230557Sjimharris                                           remote_device;
400230557Sjimharris   SCIF_SAS_TASK_REQUEST_T  * fw_task    = (SCIF_SAS_TASK_REQUEST_T*)
401230557Sjimharris                                           task_request;
402230557Sjimharris   U8 task_function =
403230557Sjimharris         scif_sas_task_request_get_function(fw_task);
404230557Sjimharris
405230557Sjimharris   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
406230557Sjimharris
407230557Sjimharris   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
408230557Sjimharris   if (   dev_protocols.u.bits.attached_ssp_target
409230557Sjimharris       || dev_protocols.u.bits.attached_stp_target)
410230557Sjimharris   {
411230557Sjimharris      // //NOTE: For STP/SATA targets we currently terminate all requests for
412230557Sjimharris      //       any type of task management.
413230557Sjimharris      if (  (task_function == SCI_SAS_ABORT_TASK_SET)
414230557Sjimharris         || (task_function == SCI_SAS_CLEAR_TASK_SET)
415230557Sjimharris         || (task_function == SCI_SAS_LOGICAL_UNIT_RESET)
416230557Sjimharris         || (task_function == SCI_SAS_I_T_NEXUS_RESET)
417230557Sjimharris         || (task_function == SCI_SAS_HARD_RESET) )
418230557Sjimharris      {
419230557Sjimharris         // Terminate all of the requests in the silicon for this device.
420230557Sjimharris         scif_sas_domain_terminate_requests(
421230557Sjimharris            fw_device->domain, fw_device, NULL, fw_task
422230557Sjimharris         );
423230557Sjimharris
424230557Sjimharris         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
425230557Sjimharris      }
426230557Sjimharris      else if (  (task_function == SCI_SAS_CLEAR_ACA)
427230557Sjimharris              || (task_function == SCI_SAS_QUERY_TASK)
428230557Sjimharris              || (task_function == SCI_SAS_QUERY_TASK_SET)
429230557Sjimharris              || (task_function == SCI_SAS_QUERY_ASYNCHRONOUS_EVENT) )
430230557Sjimharris      {
431230557Sjimharris       ASSERT(!dev_protocols.u.bits.attached_stp_target);
432230557Sjimharris         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
433230557Sjimharris      }
434230557Sjimharris      else if (task_function == SCI_SAS_ABORT_TASK)
435230557Sjimharris      {
436230557Sjimharris         SCIF_SAS_REQUEST_T * fw_request
437230557Sjimharris            = scif_sas_domain_get_request_by_io_tag(
438230557Sjimharris                 fw_device->domain, fw_task->io_tag_to_manage
439230557Sjimharris              );
440230557Sjimharris
441230557Sjimharris         // Determine if the request being aborted was found.
442230557Sjimharris         if (fw_request != NULL)
443230557Sjimharris         {
444230557Sjimharris            scif_sas_domain_terminate_requests(
445230557Sjimharris               fw_device->domain, fw_device, fw_request, fw_task
446230557Sjimharris            );
447230557Sjimharris
448230557Sjimharris            status = scif_sas_remote_device_start_task_request(
449230557Sjimharris                        fw_device, fw_task
450230557Sjimharris                     );
451230557Sjimharris         }
452230557Sjimharris         else
453230557Sjimharris            status = SCI_FAILURE_INVALID_IO_TAG;
454230557Sjimharris      }
455230557Sjimharris   }
456230557Sjimharris   else
457230557Sjimharris      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
458230557Sjimharris
459230557Sjimharris   if (status != SCI_SUCCESS)
460230557Sjimharris   {
461230557Sjimharris      SCIF_LOG_ERROR((
462230557Sjimharris         sci_base_object_get_logger(fw_device),
463230557Sjimharris         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
464230557Sjimharris         "Controller:0x%x TaskRequest:0x%x Status:0x%x start task failure\n",
465230557Sjimharris         fw_device, fw_task, status
466230557Sjimharris      ));
467230557Sjimharris   }
468230557Sjimharris
469230557Sjimharris   return status;
470230557Sjimharris}
471230557Sjimharris
472230557Sjimharris/**
473230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
474230557Sjimharris *        when a user attempts to complete a task management request on
475230557Sjimharris *        a remote device.
476230557Sjimharris *
477230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device object
478230557Sjimharris *             on which the user is attempting to perform a complete task
479230557Sjimharris *             operation.
480230557Sjimharris * @param[in]  task_request This parameter specifies the task management
481230557Sjimharris *             request to be completed.
482230557Sjimharris *
483230557Sjimharris * @return This method returns an indication as to whether the task
484230557Sjimharris *         management request succeeded.
485230557Sjimharris */
486230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_complete_task_handler(
487230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
488230557Sjimharris   SCI_BASE_REQUEST_T       * task_request
489230557Sjimharris)
490230557Sjimharris{
491230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
492230557Sjimharris                                          remote_device;
493230557Sjimharris   fw_device->request_count--;
494230557Sjimharris   fw_device->task_request_count--;
495230557Sjimharris
496230557Sjimharris   return SCI_SUCCESS;
497230557Sjimharris}
498230557Sjimharris
499230557Sjimharris/**
500230557Sjimharris * @brief This method provides OPERATIONAL sub-state specific handling for
501230557Sjimharris *        when a user attempts to start a high priority IO request on a remote
502230557Sjimharris *        device.
503230557Sjimharris *
504230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
505230557Sjimharris *             object on which the user is attempting to perform a start
506230557Sjimharris *             IO operation.
507230557Sjimharris * @param[in]  io_request This parameter specifies the IO request to be
508230557Sjimharris *             started.
509230557Sjimharris *
510230557Sjimharris * @return This method returns an indication as to whether the IO request
511230557Sjimharris *         started successfully.
512230557Sjimharris */
513230557Sjimharrisstatic
514230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_operational_start_high_priority_io_handler(
515230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
516230557Sjimharris   SCI_BASE_REQUEST_T       * io_request
517230557Sjimharris)
518230557Sjimharris{
519230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
520230557Sjimharris                                          remote_device;
521230557Sjimharris   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
522230557Sjimharris
523230557Sjimharris   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
524230557Sjimharris
525230557Sjimharris   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
526230557Sjimharris
527230557Sjimharris   if (dev_protocols.u.bits.attached_smp_target)
528230557Sjimharris   {
529230557Sjimharris      //transit to task management state for smp request phase.
530230557Sjimharris      if (fw_device->ready_substate_machine.current_state_id
531230557Sjimharris       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
532230557Sjimharris      {
533230557Sjimharris         sci_base_state_machine_change_state(
534230557Sjimharris            &fw_device->ready_substate_machine,
535230557Sjimharris            SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
536230557Sjimharris         );
537230557Sjimharris      }
538230557Sjimharris   }
539230557Sjimharris
540230557Sjimharris   fw_device->request_count++;
541230557Sjimharris
542230557Sjimharris   return fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
543230557Sjimharris}
544230557Sjimharris
545230557Sjimharris
546230557Sjimharris/**
547230557Sjimharris * @brief This method provides TASK MANAGEMENT sub-state specific handling for
548230557Sjimharris *        when a user attempts to complete a task management request on
549230557Sjimharris *        a remote device.
550230557Sjimharris *
551230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device object
552230557Sjimharris *             on which the user is attempting to perform a complete task
553230557Sjimharris *             operation.
554230557Sjimharris * @param[in]  task_request This parameter specifies the task management
555230557Sjimharris *             request to be completed.
556230557Sjimharris *
557230557Sjimharris * @return This method returns an indication as to whether the task
558230557Sjimharris *         management request succeeded.
559230557Sjimharris */
560230557SjimharrisSCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler(
561230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
562230557Sjimharris   SCI_BASE_REQUEST_T       * task_request
563230557Sjimharris)
564230557Sjimharris{
565230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
566230557Sjimharris                                          remote_device;
567230557Sjimharris
568230557Sjimharris   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)
569230557Sjimharris                                       task_request;
570230557Sjimharris
571230557Sjimharris   fw_device->request_count--;
572230557Sjimharris   fw_device->task_request_count--;
573230557Sjimharris
574230557Sjimharris   // All existing task management requests and all of the IO requests
575230557Sjimharris   // affectected by the task management request must complete before
576230557Sjimharris   // the remote device can transition back into the READY / OPERATIONAL
577230557Sjimharris   // state.
578230557Sjimharris   if (  (fw_device->task_request_count == 0)
579230557Sjimharris      && (fw_task->affected_request_count == 0) )
580230557Sjimharris   {
581230557Sjimharris      sci_base_state_machine_change_state(
582230557Sjimharris         &fw_device->ready_substate_machine,
583230557Sjimharris         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
584230557Sjimharris      );
585230557Sjimharris   }
586230557Sjimharris
587230557Sjimharris   return SCI_SUCCESS;
588230557Sjimharris}
589230557Sjimharris
590230557Sjimharris/**
591230557Sjimharris * @brief This method provides SUSPENDED sub-state specific handling for
592230557Sjimharris *        when the core remote device object issues a device ready
593230557Sjimharris *        notification.  This effectively causes the framework remote
594230557Sjimharris *        device to transition back into the OPERATIONAL state.
595230557Sjimharris *
596230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
597230557Sjimharris *             object for which the notification occurred.
598230557Sjimharris *
599230557Sjimharris * @return none.
600230557Sjimharris */
601230557Sjimharrisstatic
602230557Sjimharrisvoid scif_sas_remote_device_ready_suspended_ready_handler(
603230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device
604230557Sjimharris)
605230557Sjimharris{
606230557Sjimharris   sci_base_state_machine_change_state(
607230557Sjimharris      &fw_device->ready_substate_machine,
608230557Sjimharris      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
609230557Sjimharris   );
610230557Sjimharris}
611230557Sjimharris
612230557Sjimharris
613230557Sjimharris/**
614230557Sjimharris * @brief This handler is currently solely used by smp remote device for
615230557Sjimharris *        discovering.
616230557Sjimharris *
617230557Sjimharris * @param[in]  remote_device This parameter specifies the remote device
618230557Sjimharris *             object on which the user is attempting to perform a complete high
619230557Sjimharris *             priority IO operation.
620230557Sjimharris * @param[in]  io_request This parameter specifies the high priority IO request
621230557Sjimharris *             to be completed.
622230557Sjimharris *
623230557Sjimharris * @return SCI_STATUS indicate whether the io complete successfully.
624230557Sjimharris */
625230557SjimharrisSCI_STATUS
626230557Sjimharrisscif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(
627230557Sjimharris   SCI_BASE_REMOTE_DEVICE_T * remote_device,
628230557Sjimharris   SCI_BASE_REQUEST_T       * io_request,
629230557Sjimharris   void                     * response_data,
630230557Sjimharris   SCI_IO_STATUS              completion_status
631230557Sjimharris)
632230557Sjimharris{
633230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
634230557Sjimharris                                           remote_device;
635230557Sjimharris   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
636230557Sjimharris   SCI_STATUS                 status     = SCI_SUCCESS;
637230557Sjimharris   SCIC_TRANSPORT_PROTOCOL    protocol;
638230557Sjimharris
639230557Sjimharris   SCIF_LOG_TRACE((
640230557Sjimharris      sci_base_object_get_logger(remote_device),
641230557Sjimharris      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
642230557Sjimharris      "scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
643230557Sjimharris      remote_device, io_request, response_data, completion_status
644230557Sjimharris   ));
645230557Sjimharris
646230557Sjimharris   fw_device->request_count--;
647230557Sjimharris
648230557Sjimharris   // we are back to ready operational sub state here.
649230557Sjimharris   sci_base_state_machine_change_state(
650230557Sjimharris      &fw_device->ready_substate_machine,
651230557Sjimharris      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
652230557Sjimharris   );
653230557Sjimharris
654230557Sjimharris   protocol = scic_io_request_get_protocol(fw_request->core_object);
655230557Sjimharris
656230557Sjimharris   // If this request was an SMP initiator request we created, then
657230557Sjimharris   // decode the response.
658230557Sjimharris   if (protocol == SCIC_SMP_PROTOCOL)
659230557Sjimharris   {
660230557Sjimharris      if (completion_status != SCI_IO_FAILURE_TERMINATED)
661230557Sjimharris      {
662230557Sjimharris         status = scif_sas_smp_remote_device_decode_smp_response(
663230557Sjimharris                     fw_device, fw_request, response_data, completion_status
664230557Sjimharris                  );
665230557Sjimharris      }
666230557Sjimharris      else
667230557Sjimharris         scif_sas_smp_remote_device_terminated_request_handler(fw_device, fw_request);
668230557Sjimharris   }
669230557Sjimharris   else
670230557Sjimharris   {
671230557Sjimharris      // Currently, there are only internal SMP requests.  So, default work
672230557Sjimharris      // is simply to clean up the internal request.
673230557Sjimharris      if (fw_request->is_internal == TRUE)
674230557Sjimharris      {
675230557Sjimharris         scif_sas_internal_io_request_complete(
676230557Sjimharris            fw_device->domain->controller,
677230557Sjimharris            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request,
678230557Sjimharris            SCI_SUCCESS
679230557Sjimharris         );
680230557Sjimharris      }
681230557Sjimharris   }
682230557Sjimharris
683230557Sjimharris   return status;
684230557Sjimharris}
685230557Sjimharris
686230557Sjimharris
687230557SjimharrisSCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
688230557Sjimharrisscif_sas_remote_device_ready_substate_handler_table[] =
689230557Sjimharris{
690230557Sjimharris   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
691230557Sjimharris   {
692230557Sjimharris      {
693230557Sjimharris         scif_sas_remote_device_default_start_handler,
694230557Sjimharris         scif_sas_remote_device_ready_operational_stop_handler,
695230557Sjimharris         scif_sas_remote_device_ready_operational_fail_handler,
696230557Sjimharris         scif_sas_remote_device_ready_operational_destruct_handler,
697230557Sjimharris         scif_sas_remote_device_default_reset_handler,
698230557Sjimharris         scif_sas_remote_device_default_reset_complete_handler,
699230557Sjimharris         scif_sas_remote_device_ready_operational_start_io_handler,
700230557Sjimharris         scif_sas_remote_device_ready_operational_complete_io_handler,
701230557Sjimharris         scif_sas_remote_device_ready_operational_continue_io_handler,
702230557Sjimharris         scif_sas_remote_device_ready_operational_start_task_handler,
703230557Sjimharris         scif_sas_remote_device_ready_operational_complete_task_handler
704230557Sjimharris      },
705230557Sjimharris      scif_sas_remote_device_default_start_complete_handler,
706230557Sjimharris      scif_sas_remote_device_default_stop_complete_handler,
707230557Sjimharris      scif_sas_remote_device_default_ready_handler,
708230557Sjimharris      scif_sas_remote_device_ready_operational_not_ready_handler,
709230557Sjimharris      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,  //
710230557Sjimharris      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
711230557Sjimharris   },
712230557Sjimharris   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
713230557Sjimharris   {
714230557Sjimharris      {
715230557Sjimharris         scif_sas_remote_device_default_start_handler,
716230557Sjimharris         scif_sas_remote_device_ready_operational_stop_handler,
717230557Sjimharris         scif_sas_remote_device_ready_operational_fail_handler,
718230557Sjimharris         scif_sas_remote_device_ready_operational_destruct_handler,
719230557Sjimharris         scif_sas_remote_device_default_reset_handler,
720230557Sjimharris         scif_sas_remote_device_default_reset_complete_handler,
721230557Sjimharris         scif_sas_remote_device_default_start_io_handler,
722230557Sjimharris         scif_sas_remote_device_ready_operational_complete_io_handler,
723230557Sjimharris         scif_sas_remote_device_default_continue_io_handler,
724230557Sjimharris         scif_sas_remote_device_ready_operational_start_task_handler,
725230557Sjimharris         scif_sas_remote_device_ready_operational_complete_task_handler
726230557Sjimharris      },
727230557Sjimharris      scif_sas_remote_device_default_start_complete_handler,
728230557Sjimharris      scif_sas_remote_device_default_stop_complete_handler,
729230557Sjimharris      scif_sas_remote_device_ready_suspended_ready_handler,
730230557Sjimharris      scif_sas_remote_device_default_not_ready_handler,
731230557Sjimharris      scif_sas_remote_device_default_start_io_handler,
732230557Sjimharris      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
733230557Sjimharris   },
734230557Sjimharris   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
735230557Sjimharris   {
736230557Sjimharris      {
737230557Sjimharris         scif_sas_remote_device_default_start_handler,
738230557Sjimharris         scif_sas_remote_device_ready_operational_stop_handler,
739230557Sjimharris         scif_sas_remote_device_ready_operational_fail_handler,
740230557Sjimharris         scif_sas_remote_device_ready_operational_destruct_handler,
741230557Sjimharris         scif_sas_remote_device_default_reset_handler,
742230557Sjimharris         scif_sas_remote_device_default_reset_complete_handler,
743230557Sjimharris         scif_sas_remote_device_default_start_io_handler,
744230557Sjimharris         scif_sas_remote_device_ready_operational_complete_io_handler,
745230557Sjimharris         scif_sas_remote_device_ready_operational_continue_io_handler,
746230557Sjimharris         scif_sas_remote_device_ready_operational_start_task_handler,
747230557Sjimharris         scif_sas_remote_device_ready_task_management_complete_task_handler
748230557Sjimharris      },
749230557Sjimharris      scif_sas_remote_device_default_start_complete_handler,
750230557Sjimharris      scif_sas_remote_device_default_stop_complete_handler,
751230557Sjimharris      scif_sas_remote_device_default_ready_handler,
752230557Sjimharris      scif_sas_remote_device_ready_task_management_not_ready_handler,
753230557Sjimharris      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,
754230557Sjimharris      scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler
755230557Sjimharris   },
756230557Sjimharris   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
757230557Sjimharris   {
758230557Sjimharris      {
759230557Sjimharris         scif_sas_remote_device_default_start_handler,
760230557Sjimharris         scif_sas_remote_device_ready_operational_stop_handler,
761230557Sjimharris         scif_sas_remote_device_ready_operational_fail_handler,
762230557Sjimharris         scif_sas_remote_device_ready_operational_destruct_handler,
763230557Sjimharris         scif_sas_remote_device_default_reset_handler,
764230557Sjimharris         scif_sas_remote_device_default_reset_complete_handler,
765230557Sjimharris         scif_sas_remote_device_default_start_io_handler,
766230557Sjimharris         scif_sas_remote_device_ready_operational_complete_io_handler,
767230557Sjimharris         scif_sas_remote_device_default_continue_io_handler,
768230557Sjimharris         scif_sas_remote_device_ready_operational_start_task_handler,
769230557Sjimharris         scif_sas_remote_device_ready_operational_complete_task_handler
770230557Sjimharris      },
771230557Sjimharris      scif_sas_remote_device_default_start_complete_handler,
772230557Sjimharris      scif_sas_remote_device_default_stop_complete_handler,
773230557Sjimharris      scif_sas_remote_device_ready_suspended_ready_handler,
774230557Sjimharris      scif_sas_remote_device_default_not_ready_handler,
775230557Sjimharris      scif_sas_remote_device_default_start_io_handler,
776230557Sjimharris      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
777230557Sjimharris   },
778230557Sjimharris};
779230557Sjimharris
780