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
60230557Sjimharris */
61230557Sjimharris
62230557Sjimharris#include <dev/isci/scil/scic_remote_device.h>
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/scif_sas_remote_device.h>
65230557Sjimharris#include <dev/isci/scil/scif_sas_domain.h>
66230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
67230557Sjimharris
68230557Sjimharris
69230557Sjimharris/**
70230557Sjimharris * This constant indicates the number of milliseconds to wait for the core
71230557Sjimharris * to start/stop it's remote device object.
72230557Sjimharris */
73230557Sjimharris//#define SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT 1000
74230557Sjimharris
75230557Sjimharris//******************************************************************************
76230557Sjimharris//* P R O T E C T E D   M E T H O D S
77230557Sjimharris//******************************************************************************
78230557Sjimharris
79230557Sjimharris/**
80230557Sjimharris * @brief This method implements the actions taken when entering the
81230557Sjimharris *        INITIAL state.  This basically, causes an immediate transition
82230557Sjimharris *        into the STOPPED state.
83230557Sjimharris *
84230557Sjimharris * @param[in]  object This parameter specifies the base object for which
85230557Sjimharris *             the state transition is occurring.  This is cast into a
86230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
87230557Sjimharris *
88230557Sjimharris * @return none
89230557Sjimharris */
90230557Sjimharrisstatic
91230557Sjimharrisvoid scif_sas_remote_device_initial_state_enter(
92230557Sjimharris   SCI_BASE_OBJECT_T *object
93230557Sjimharris)
94230557Sjimharris{
95230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
96230557Sjimharris
97230557Sjimharris   SET_STATE_HANDLER(
98230557Sjimharris      fw_device,
99230557Sjimharris      scif_sas_remote_device_state_handler_table,
100230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
101230557Sjimharris   );
102230557Sjimharris
103230557Sjimharris   // Initial state is a transitional state to the stopped state
104230557Sjimharris   sci_base_state_machine_change_state(
105230557Sjimharris      &fw_device->parent.state_machine,
106230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
107230557Sjimharris   );
108230557Sjimharris}
109230557Sjimharris
110230557Sjimharris/**
111230557Sjimharris * @brief This method implements the actions taken when entering the
112230557Sjimharris *        STOPPED state.  This method updates the domains count of started
113230557Sjimharris *        devices and will invoke the destruct method if this entrance into
114230557Sjimharris *        the STOPPED state was due to a scif_remote_device_destruct()
115230557Sjimharris *        call by the user.
116230557Sjimharris *
117230557Sjimharris * @param[in]  object This parameter specifies the base object for which
118230557Sjimharris *             the state transition is occurring.  This is cast into a
119230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
120230557Sjimharris *
121230557Sjimharris * @return none
122230557Sjimharris */
123230557Sjimharrisstatic
124230557Sjimharrisvoid scif_sas_remote_device_stopped_state_enter(
125230557Sjimharris   SCI_BASE_OBJECT_T *object
126230557Sjimharris)
127230557Sjimharris{
128230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
129230557Sjimharris
130230557Sjimharris   SET_STATE_HANDLER(
131230557Sjimharris      fw_device,
132230557Sjimharris      scif_sas_remote_device_state_handler_table,
133230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
134230557Sjimharris   );
135230557Sjimharris
136230557Sjimharris   // There should be no outstanding requests for this device in the
137230557Sjimharris   // stopped state.
138230557Sjimharris   ASSERT(fw_device->request_count == 0);
139230557Sjimharris
140230557Sjimharris   // If we are entering the stopped state as a result of a destruct
141230557Sjimharris   // request, then let's perform the actual destruct operation now.
142230557Sjimharris   if (fw_device->destruct_when_stopped == TRUE)
143230557Sjimharris      fw_device->operation_status
144230557Sjimharris         = fw_device->state_handlers->parent.destruct_handler(
145230557Sjimharris              &fw_device->parent
146230557Sjimharris           );
147230557Sjimharris
148230557Sjimharris   /// @todo What should we do if this call fails?
149230557Sjimharris   fw_device->domain->state_handlers->device_stop_complete_handler(
150230557Sjimharris      &fw_device->domain->parent, &fw_device->parent
151230557Sjimharris   );
152230557Sjimharris}
153230557Sjimharris
154230557Sjimharris/**
155230557Sjimharris * @brief This method implements the actions taken when entering the
156230557Sjimharris *        STARTING state.  This method will attempt to start the core
157230557Sjimharris *        remote device and will kick-start the starting sub-state machine
158230557Sjimharris *        if no errors are encountered.
159230557Sjimharris *
160230557Sjimharris * @param[in]  object This parameter specifies the base object for which
161230557Sjimharris *             the state transition is occurring.  This is cast into a
162230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
163230557Sjimharris *
164230557Sjimharris * @return none
165230557Sjimharris */
166230557Sjimharrisstatic
167230557Sjimharrisvoid scif_sas_remote_device_starting_state_enter(
168230557Sjimharris   SCI_BASE_OBJECT_T *object
169230557Sjimharris)
170230557Sjimharris{
171230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
172230557Sjimharris
173230557Sjimharris   SET_STATE_HANDLER(
174230557Sjimharris      fw_device,
175230557Sjimharris      scif_sas_remote_device_state_handler_table,
176230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STARTING
177230557Sjimharris   );
178230557Sjimharris
179230557Sjimharris   SCIF_LOG_INFO((
180230557Sjimharris      sci_base_object_get_logger(fw_device),
181230557Sjimharris      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
182230557Sjimharris      "RemoteDevice:0x%x starting/configuring\n",
183230557Sjimharris      fw_device
184230557Sjimharris   ));
185230557Sjimharris
186230557Sjimharris   fw_device->destination_state =
187230557Sjimharris      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
188230557Sjimharris
189230557Sjimharris   sci_base_state_machine_start(&fw_device->starting_substate_machine);
190230557Sjimharris
191230557Sjimharris   fw_device->operation_status = scic_remote_device_start(
192230557Sjimharris                                    fw_device->core_object,
193230557Sjimharris                                    SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
194230557Sjimharris                                 );
195230557Sjimharris
196230557Sjimharris   if (fw_device->operation_status != SCI_SUCCESS)
197230557Sjimharris   {
198230557Sjimharris      fw_device->state_handlers->parent.fail_handler(&fw_device->parent);
199230557Sjimharris
200230557Sjimharris      // Something is seriously wrong.  Starting the core remote device
201230557Sjimharris      // shouldn't fail in anyway in this state.
202230557Sjimharris      scif_cb_controller_error(fw_device->domain->controller,
203230557Sjimharris              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
204230557Sjimharris   }
205230557Sjimharris}
206230557Sjimharris
207230557Sjimharris/**
208230557Sjimharris * @brief This method implements the actions taken when exiting the
209230557Sjimharris *        STARTING state.  Currently this method simply stops the
210230557Sjimharris *        sub-state machine.
211230557Sjimharris *
212230557Sjimharris * @param[in]  object This parameter specifies the base object for which
213230557Sjimharris *             the state transition is occurring.  This is cast into a
214230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
215230557Sjimharris *
216230557Sjimharris * @return none
217230557Sjimharris */
218230557Sjimharrisstatic
219230557Sjimharrisvoid scif_sas_remote_device_starting_state_exit(
220230557Sjimharris   SCI_BASE_OBJECT_T *object
221230557Sjimharris)
222230557Sjimharris{
223230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
224230557Sjimharris
225230557Sjimharris   fw_device->destination_state =
226230557Sjimharris      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
227230557Sjimharris
228230557Sjimharris   // Transition immediately into the operational sub-state.
229230557Sjimharris   sci_base_state_machine_stop(&fw_device->starting_substate_machine);
230230557Sjimharris}
231230557Sjimharris
232230557Sjimharris/**
233230557Sjimharris * @brief This method implements the actions taken when entering the
234230557Sjimharris *        READY state.  Currently this method simply starts the
235230557Sjimharris *        sub-state machine.
236230557Sjimharris *
237230557Sjimharris * @param[in]  object This parameter specifies the base object for which
238230557Sjimharris *             the state transition is occurring.  This is cast into a
239230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
240230557Sjimharris *
241230557Sjimharris * @return none
242230557Sjimharris */
243230557Sjimharrisstatic
244230557Sjimharrisvoid scif_sas_remote_device_ready_state_enter(
245230557Sjimharris   SCI_BASE_OBJECT_T *object
246230557Sjimharris)
247230557Sjimharris{
248230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
249230557Sjimharris
250230557Sjimharris   // Transition immediately into the operational sub-state.
251230557Sjimharris   sci_base_state_machine_start(&fw_device->ready_substate_machine);
252230557Sjimharris
253230557Sjimharris#if defined(DISABLE_WIDE_PORTED_TARGETS)
254230557Sjimharris   scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
255230557Sjimharris#endif
256230557Sjimharris}
257230557Sjimharris
258230557Sjimharris/**
259230557Sjimharris * @brief This method implements the actions taken when exiting the
260230557Sjimharris *        READY state.  Currently this method simply stops the
261230557Sjimharris *        sub-state machine.
262230557Sjimharris *
263230557Sjimharris * @param[in]  object This parameter specifies the base object for which
264230557Sjimharris *             the state transition is occurring.  This is cast into a
265230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
266230557Sjimharris *
267230557Sjimharris * @return none
268230557Sjimharris */
269230557Sjimharrisstatic
270230557Sjimharrisvoid scif_sas_remote_device_ready_state_exit(
271230557Sjimharris   SCI_BASE_OBJECT_T *object
272230557Sjimharris)
273230557Sjimharris{
274230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
275230557Sjimharris
276230557Sjimharris   // Transition immediately into the operational sub-state.
277230557Sjimharris   sci_base_state_machine_stop(&fw_device->ready_substate_machine);
278230557Sjimharris}
279230557Sjimharris
280230557Sjimharris/**
281230557Sjimharris * @brief This method implements the actions taken when entering the
282230557Sjimharris *        STOPPING state.  This includes: stopping the core remote device
283230557Sjimharris *        and handling any errors that may occur.
284230557Sjimharris *
285230557Sjimharris * @param[in]  object This parameter specifies the base object for which
286230557Sjimharris *             the state transition is occurring.  This is cast into a
287230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
288230557Sjimharris *
289230557Sjimharris * @return none
290230557Sjimharris */
291230557Sjimharrisstatic
292230557Sjimharrisvoid scif_sas_remote_device_stopping_state_enter(
293230557Sjimharris   SCI_BASE_OBJECT_T *object
294230557Sjimharris)
295230557Sjimharris{
296230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
297230557Sjimharris
298230557Sjimharris   SET_STATE_HANDLER(
299230557Sjimharris      fw_device,
300230557Sjimharris      scif_sas_remote_device_state_handler_table,
301230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
302230557Sjimharris   );
303230557Sjimharris
304230557Sjimharris   fw_device->operation_status = scic_remote_device_stop(
305230557Sjimharris                                    fw_device->core_object,
306230557Sjimharris                                    SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
307230557Sjimharris                                 );
308230557Sjimharris
309230557Sjimharris   // If there was a failure, then transition directly to the stopped state.
310230557Sjimharris   if (fw_device->operation_status != SCI_SUCCESS)
311230557Sjimharris   {
312230557Sjimharris      /**
313230557Sjimharris       * @todo We may want to consider adding handling to reset the
314230557Sjimharris       *       structure data for the framework and core devices here
315230557Sjimharris       *       in order to help aid recovery.
316230557Sjimharris       */
317230557Sjimharris
318230557Sjimharris      fw_device->state_handlers->stop_complete_handler(
319230557Sjimharris         fw_device, fw_device->operation_status
320230557Sjimharris      );
321230557Sjimharris   }
322230557Sjimharris}
323230557Sjimharris
324230557Sjimharris/**
325230557Sjimharris * @brief This method implements the actions taken when exiting the
326230557Sjimharris *        STOPPING state.
327230557Sjimharris *
328230557Sjimharris * @param[in]  object This parameter specifies the base object for which
329230557Sjimharris *             the state transition is occurring.  This is cast into a
330230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
331230557Sjimharris *
332230557Sjimharris * @return none
333230557Sjimharris */
334230557Sjimharrisstatic
335230557Sjimharrisvoid scif_sas_remote_device_stopping_state_exit(
336230557Sjimharris   SCI_BASE_OBJECT_T *object
337230557Sjimharris)
338230557Sjimharris{
339230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
340230557Sjimharris
341230557Sjimharris   // Let the domain know that the device has stopped
342230557Sjimharris   fw_device->domain->device_start_count--;
343230557Sjimharris}
344230557Sjimharris
345230557Sjimharris/**
346230557Sjimharris * @brief This method implements the actions taken when entering the
347230557Sjimharris *        FAILED state.  This includes setting the state handler methods
348230557Sjimharris *        and issuing a scif_cb_remote_device_failed() notification to
349230557Sjimharris *        the user.
350230557Sjimharris *
351230557Sjimharris * @param[in]  object This parameter specifies the base object for which
352230557Sjimharris *             the state transition is occurring.  This is cast into a
353230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
354230557Sjimharris *
355230557Sjimharris * @return none
356230557Sjimharris */
357230557Sjimharrisstatic
358230557Sjimharrisvoid scif_sas_remote_device_failed_state_enter(
359230557Sjimharris   SCI_BASE_OBJECT_T *object
360230557Sjimharris)
361230557Sjimharris{
362230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
363230557Sjimharris
364230557Sjimharris   SET_STATE_HANDLER(
365230557Sjimharris      fw_device,
366230557Sjimharris      scif_sas_remote_device_state_handler_table,
367230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_FAILED
368230557Sjimharris   );
369230557Sjimharris
370230557Sjimharris   SCIF_LOG_INFO((
371230557Sjimharris      sci_base_object_get_logger(fw_device),
372230557Sjimharris      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
373230557Sjimharris      "Domain:0x%x Device:0x%x Status:0x%x device failed\n",
374230557Sjimharris      fw_device->domain, fw_device, fw_device->operation_status
375230557Sjimharris   ));
376230557Sjimharris
377230557Sjimharris   // Notify the user that the device has failed.
378230557Sjimharris   scif_cb_remote_device_failed(
379230557Sjimharris      fw_device->domain->controller,
380230557Sjimharris      fw_device->domain,
381230557Sjimharris      fw_device,
382230557Sjimharris      fw_device->operation_status
383230557Sjimharris   );
384230557Sjimharris
385230557Sjimharris   // Only call start_complete for the remote device if the device failed
386230557Sjimharris   // from the STARTING state.
387230557Sjimharris   if (fw_device->parent.state_machine.previous_state_id
388230557Sjimharris       == SCI_BASE_REMOTE_DEVICE_STATE_STARTING)
389230557Sjimharris      scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
390230557Sjimharris}
391230557Sjimharris
392230557Sjimharris/**
393230557Sjimharris * @brief This method implements the actions taken when entering the RESETTING
394230557Sjimharris *        state.
395230557Sjimharris *
396230557Sjimharris * @param[in]  object This parameter specifies the base object for which
397230557Sjimharris *             the state transition is occurring.  This is cast into a
398230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
399230557Sjimharris *
400230557Sjimharris * @return none
401230557Sjimharris */
402230557Sjimharrisstatic
403230557Sjimharrisvoid scif_sas_remote_device_resetting_state_enter(
404230557Sjimharris   SCI_BASE_OBJECT_T *object
405230557Sjimharris)
406230557Sjimharris{
407230557Sjimharris}
408230557Sjimharris
409230557Sjimharris#if !defined(DISABLE_WIDE_PORTED_TARGETS)
410230557Sjimharris/**
411230557Sjimharris * @brief This method implements the actions taken when entering the UPDATING
412230557Sjimharris *        PORT WIDTH state.
413230557Sjimharris *
414230557Sjimharris * @param[in]  object This parameter specifies the base object for which
415230557Sjimharris *             the state transition is occurring.  This is cast into a
416230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
417230557Sjimharris *
418230557Sjimharris * @return none
419230557Sjimharris */
420230557Sjimharrisstatic
421230557Sjimharrisvoid scif_sas_remote_device_updating_port_width_state_enter(
422230557Sjimharris   SCI_BASE_OBJECT_T *object
423230557Sjimharris)
424230557Sjimharris{
425230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
426230557Sjimharris
427230557Sjimharris   SET_STATE_HANDLER(
428230557Sjimharris      fw_device,
429230557Sjimharris      scif_sas_remote_device_state_handler_table,
430230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
431230557Sjimharris   );
432230557Sjimharris
433230557Sjimharris   fw_device->destination_state = SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
434230557Sjimharris
435230557Sjimharris   //If the request count is zero, go ahead to update the RNC.
436230557Sjimharris   //If not, don't do anything for now. The IO complete handler of this state
437230557Sjimharris   //will update the RNC whenever the request count goes down to zero.
438230557Sjimharris   if (fw_device->request_count == 0)
439230557Sjimharris   {
440230557Sjimharris      //stop the device, upon the stop complete callback, start the device again
441230557Sjimharris      //with the updated port width.
442230557Sjimharris      scic_remote_device_stop(
443230557Sjimharris         fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
444230557Sjimharris   }
445230557Sjimharris}
446230557Sjimharris
447230557Sjimharris
448230557Sjimharris/**
449230557Sjimharris * @brief This method implements the actions taken when exiting the
450230557Sjimharris *        STOPPING state.
451230557Sjimharris *
452230557Sjimharris * @param[in]  object This parameter specifies the base object for which
453230557Sjimharris *             the state transition is occurring.  This is cast into a
454230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
455230557Sjimharris *
456230557Sjimharris * @return none
457230557Sjimharris */
458230557Sjimharrisstatic
459230557Sjimharrisvoid scif_sas_remote_device_updating_port_width_state_exit(
460230557Sjimharris   SCI_BASE_OBJECT_T *object
461230557Sjimharris)
462230557Sjimharris{
463230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
464230557Sjimharris
465230557Sjimharris   fw_device->destination_state =
466230557Sjimharris      SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
467230557Sjimharris}
468230557Sjimharris
469230557Sjimharris
470230557Sjimharris#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
471230557Sjimharris
472230557Sjimharris/**
473230557Sjimharris * @brief This method implements the actions taken when entering the
474230557Sjimharris *        FINAL state.  This includes setting the FINAL state handler
475230557Sjimharris *        methods.
476230557Sjimharris *
477230557Sjimharris * @param[in]  object This parameter specifies the base object for which
478230557Sjimharris *             the state transition is occurring.  This is cast into a
479230557Sjimharris *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
480230557Sjimharris *
481230557Sjimharris * @return none
482230557Sjimharris */
483230557Sjimharrisstatic
484230557Sjimharrisvoid scif_sas_remote_device_final_state_enter(
485230557Sjimharris   SCI_BASE_OBJECT_T *object
486230557Sjimharris)
487230557Sjimharris{
488230557Sjimharris   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
489230557Sjimharris
490230557Sjimharris   SET_STATE_HANDLER(
491230557Sjimharris      fw_device,
492230557Sjimharris      scif_sas_remote_device_state_handler_table,
493230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_FINAL
494230557Sjimharris   );
495230557Sjimharris}
496230557Sjimharris
497230557Sjimharris
498230557SjimharrisSCI_BASE_STATE_T
499230557Sjimharris   scif_sas_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
500230557Sjimharris{
501230557Sjimharris   {
502230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
503230557Sjimharris      scif_sas_remote_device_initial_state_enter,
504230557Sjimharris      NULL
505230557Sjimharris   },
506230557Sjimharris   {
507230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
508230557Sjimharris      scif_sas_remote_device_stopped_state_enter,
509230557Sjimharris      NULL
510230557Sjimharris   },
511230557Sjimharris   {
512230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
513230557Sjimharris      scif_sas_remote_device_starting_state_enter,
514230557Sjimharris      scif_sas_remote_device_starting_state_exit
515230557Sjimharris   },
516230557Sjimharris   {
517230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_READY,
518230557Sjimharris      scif_sas_remote_device_ready_state_enter,
519230557Sjimharris      scif_sas_remote_device_ready_state_exit
520230557Sjimharris   },
521230557Sjimharris   {
522230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
523230557Sjimharris      scif_sas_remote_device_stopping_state_enter,
524230557Sjimharris      scif_sas_remote_device_stopping_state_exit
525230557Sjimharris   },
526230557Sjimharris   {
527230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
528230557Sjimharris      scif_sas_remote_device_failed_state_enter,
529230557Sjimharris      NULL
530230557Sjimharris   },
531230557Sjimharris   {
532230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
533230557Sjimharris      scif_sas_remote_device_resetting_state_enter,
534230557Sjimharris      NULL
535230557Sjimharris   },
536230557Sjimharris#if !defined(DISABLE_WIDE_PORTED_TARGETS)
537230557Sjimharris   {
538230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
539230557Sjimharris      scif_sas_remote_device_updating_port_width_state_enter,
540230557Sjimharris      scif_sas_remote_device_updating_port_width_state_exit
541230557Sjimharris   },
542230557Sjimharris#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
543230557Sjimharris   {
544230557Sjimharris      SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
545230557Sjimharris      scif_sas_remote_device_final_state_enter,
546230557Sjimharris      NULL
547230557Sjimharris   },
548230557Sjimharris};
549230557Sjimharris
550