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 entrance and exit methods for each
60230557Sjimharris *        of the controller states defined by the SCI_BASE_CONTROLLER state
61230557Sjimharris *        machine.
62230557Sjimharris */
63230557Sjimharris
64230557Sjimharris#include <dev/isci/scil/scic_controller.h>
65230557Sjimharris
66230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h>
67230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h>
68230557Sjimharris
69230557Sjimharris//******************************************************************************
70230557Sjimharris//* P R O T E C T E D    M E T H O D S
71230557Sjimharris//******************************************************************************
72230557Sjimharris
73230557Sjimharris/**
74230557Sjimharris * @brief This method implements the actions taken when entering the
75230557Sjimharris *        INITIAL state.
76230557Sjimharris *
77230557Sjimharris * @param[in]  object This parameter specifies the base object for which
78230557Sjimharris *             the state transition is occurring.  This is cast into a
79230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
80230557Sjimharris *
81230557Sjimharris * @return none
82230557Sjimharris */
83230557Sjimharrisstatic
84230557Sjimharrisvoid scif_sas_controller_initial_state_enter(
85230557Sjimharris   SCI_BASE_OBJECT_T * object
86230557Sjimharris)
87230557Sjimharris{
88230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
89230557Sjimharris
90230557Sjimharris   SET_STATE_HANDLER(
91230557Sjimharris      fw_controller,
92230557Sjimharris      scif_sas_controller_state_handler_table,
93230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIAL
94230557Sjimharris   );
95230557Sjimharris}
96230557Sjimharris
97230557Sjimharris/**
98230557Sjimharris * @brief This method implements the actions taken when entering the
99230557Sjimharris *        RESET state.
100230557Sjimharris *
101230557Sjimharris * @param[in]  object This parameter specifies the base object for which
102230557Sjimharris *             the state transition is occurring.  This is cast into a
103230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
104230557Sjimharris *
105230557Sjimharris * @return none
106230557Sjimharris */
107230557Sjimharrisstatic
108230557Sjimharrisvoid scif_sas_controller_reset_state_enter(
109230557Sjimharris   SCI_BASE_OBJECT_T * object
110230557Sjimharris)
111230557Sjimharris{
112230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
113230557Sjimharris   U8 index;
114230557Sjimharris   U16 smp_phy_index;
115230557Sjimharris
116230557Sjimharris   SET_STATE_HANDLER(
117230557Sjimharris      fw_controller,
118230557Sjimharris      scif_sas_controller_state_handler_table,
119230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESET
120230557Sjimharris   );
121230557Sjimharris
122230557Sjimharris   scif_sas_high_priority_request_queue_construct(
123230557Sjimharris      &fw_controller->hprq, sci_base_object_get_logger(fw_controller)
124230557Sjimharris   );
125230557Sjimharris
126230557Sjimharris   // Construct the abstract element pool. This pool will store the
127230557Sjimharris   // references to the framework's remote devices objects.
128230557Sjimharris   sci_abstract_element_pool_construct(
129230557Sjimharris      &fw_controller->free_remote_device_pool,
130230557Sjimharris      fw_controller->remote_device_pool_elements,
131230557Sjimharris      SCI_MAX_REMOTE_DEVICES
132230557Sjimharris   );
133230557Sjimharris
134230557Sjimharris   // Construct the domain objects.
135230557Sjimharris   for (index = 0; index < SCI_MAX_DOMAINS; index++)
136230557Sjimharris   {
137230557Sjimharris      scif_sas_domain_construct(
138230557Sjimharris         &fw_controller->domains[index], index, fw_controller
139230557Sjimharris      );
140230557Sjimharris   }
141230557Sjimharris
142230557Sjimharris   //Initialize SMP PHY MEMORY LIST.
143230557Sjimharris   sci_fast_list_init(&fw_controller->smp_phy_memory_list);
144230557Sjimharris
145230557Sjimharris   for (smp_phy_index = 0;
146230557Sjimharris        smp_phy_index < SCIF_SAS_SMP_PHY_COUNT;
147230557Sjimharris        smp_phy_index++)
148230557Sjimharris   {
149230557Sjimharris      sci_fast_list_element_init(
150230557Sjimharris         &fw_controller->smp_phy_array[smp_phy_index],
151230557Sjimharris         &(fw_controller->smp_phy_array[smp_phy_index].list_element)
152230557Sjimharris      );
153230557Sjimharris
154230557Sjimharris      //insert to owning device's smp phy list.
155230557Sjimharris      sci_fast_list_insert_tail(
156230557Sjimharris         (&(fw_controller->smp_phy_memory_list)),
157230557Sjimharris         (&(fw_controller->smp_phy_array[smp_phy_index].list_element))
158230557Sjimharris      );
159230557Sjimharris   }
160230557Sjimharris
161230557Sjimharris   scif_sas_controller_set_default_config_parameters(fw_controller);
162230557Sjimharris
163230557Sjimharris   fw_controller->internal_request_entries =
164230557Sjimharris      SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT;
165230557Sjimharris
166230557Sjimharris   //@Todo: may need to verify all timers are released. Including domain's
167230557Sjimharris   //operation timer and all the Internal IO's timer.
168230557Sjimharris
169230557Sjimharris   //take care of the lock.
170230557Sjimharris   scif_cb_lock_disassociate(fw_controller, &fw_controller->hprq.lock);
171230557Sjimharris}
172230557Sjimharris
173230557Sjimharris/**
174230557Sjimharris * @brief This method implements the actions taken when entering the
175230557Sjimharris *        INITIALIZING state.
176230557Sjimharris *
177230557Sjimharris * @param[in]  object This parameter specifies the base object for which
178230557Sjimharris *             the state transition is occurring.  This is cast into a
179230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
180230557Sjimharris *
181230557Sjimharris * @return none
182230557Sjimharris */
183230557Sjimharrisstatic
184230557Sjimharrisvoid scif_sas_controller_initializing_state_enter(
185230557Sjimharris   SCI_BASE_OBJECT_T * object
186230557Sjimharris)
187230557Sjimharris{
188230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
189230557Sjimharris
190230557Sjimharris   SET_STATE_HANDLER(
191230557Sjimharris      fw_controller,
192230557Sjimharris      scif_sas_controller_state_handler_table,
193230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZING
194230557Sjimharris   );
195230557Sjimharris}
196230557Sjimharris
197230557Sjimharris/**
198230557Sjimharris * @brief This method implements the actions taken when entering the
199230557Sjimharris *        INITIALIZED state.
200230557Sjimharris *
201230557Sjimharris * @param[in]  object This parameter specifies the base object for which
202230557Sjimharris *             the state transition is occurring.  This is cast into a
203230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
204230557Sjimharris *
205230557Sjimharris * @return none
206230557Sjimharris */
207230557Sjimharrisstatic
208230557Sjimharrisvoid scif_sas_controller_initialized_state_enter(
209230557Sjimharris   SCI_BASE_OBJECT_T * object
210230557Sjimharris)
211230557Sjimharris{
212230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
213230557Sjimharris
214230557Sjimharris   SET_STATE_HANDLER(
215230557Sjimharris      fw_controller,
216230557Sjimharris      scif_sas_controller_state_handler_table,
217230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZED
218230557Sjimharris   );
219230557Sjimharris}
220230557Sjimharris
221230557Sjimharris/**
222230557Sjimharris * @brief This method implements the actions taken when entering the
223230557Sjimharris *        STARTING state.
224230557Sjimharris *
225230557Sjimharris * @param[in]  object This parameter specifies the base object for which
226230557Sjimharris *             the state transition is occurring.  This is cast into a
227230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
228230557Sjimharris *
229230557Sjimharris * @return none
230230557Sjimharris */
231230557Sjimharrisstatic
232230557Sjimharrisvoid scif_sas_controller_starting_state_enter(
233230557Sjimharris   SCI_BASE_OBJECT_T * object
234230557Sjimharris)
235230557Sjimharris{
236230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
237230557Sjimharris
238230557Sjimharris   SET_STATE_HANDLER(
239230557Sjimharris      fw_controller,
240230557Sjimharris      scif_sas_controller_state_handler_table,
241230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STARTING
242230557Sjimharris   );
243230557Sjimharris}
244230557Sjimharris
245230557Sjimharris/**
246230557Sjimharris * @brief This method implements the actions taken when entering the
247230557Sjimharris *        READY state.
248230557Sjimharris *
249230557Sjimharris * @param[in]  object This parameter specifies the base object for which
250230557Sjimharris *             the state transition is occurring.  This is cast into a
251230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
252230557Sjimharris *
253230557Sjimharris * @return none
254230557Sjimharris */
255230557Sjimharrisstatic
256230557Sjimharrisvoid scif_sas_controller_ready_state_enter(
257230557Sjimharris   SCI_BASE_OBJECT_T * object
258230557Sjimharris)
259230557Sjimharris{
260230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
261230557Sjimharris
262230557Sjimharris   SET_STATE_HANDLER(
263230557Sjimharris      fw_controller,
264230557Sjimharris      scif_sas_controller_state_handler_table,
265230557Sjimharris      SCI_BASE_CONTROLLER_STATE_READY
266230557Sjimharris   );
267230557Sjimharris}
268230557Sjimharris
269230557Sjimharris/**
270230557Sjimharris * @brief This method implements the actions taken when entering the
271230557Sjimharris *        STOPPING state.
272230557Sjimharris *
273230557Sjimharris * @param[in]  object This parameter specifies the base object for which
274230557Sjimharris *             the state transition is occurring.  This is cast into a
275230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
276230557Sjimharris *
277230557Sjimharris * @return none
278230557Sjimharris */
279230557Sjimharrisstatic
280230557Sjimharrisvoid scif_sas_controller_stopping_state_enter(
281230557Sjimharris   SCI_BASE_OBJECT_T * object
282230557Sjimharris)
283230557Sjimharris{
284230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
285230557Sjimharris
286230557Sjimharris   SET_STATE_HANDLER(
287230557Sjimharris      fw_controller,
288230557Sjimharris      scif_sas_controller_state_handler_table,
289230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPING
290230557Sjimharris   );
291230557Sjimharris}
292230557Sjimharris
293230557Sjimharris/**
294230557Sjimharris * @brief This method implements the actions taken when entering the
295230557Sjimharris *        STOPPED state.
296230557Sjimharris *
297230557Sjimharris * @param[in]  object This parameter specifies the base object for which
298230557Sjimharris *             the state transition is occurring.  This is cast into a
299230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
300230557Sjimharris *
301230557Sjimharris * @return none
302230557Sjimharris */
303230557Sjimharrisstatic
304230557Sjimharrisvoid scif_sas_controller_stopped_state_enter(
305230557Sjimharris   SCI_BASE_OBJECT_T * object
306230557Sjimharris)
307230557Sjimharris{
308230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
309230557Sjimharris
310230557Sjimharris   SET_STATE_HANDLER(
311230557Sjimharris      fw_controller,
312230557Sjimharris      scif_sas_controller_state_handler_table,
313230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPED
314230557Sjimharris   );
315230557Sjimharris}
316230557Sjimharris
317230557Sjimharris/**
318230557Sjimharris * @brief This method implements the actions taken when entering the
319230557Sjimharris *        RESETTING state.
320230557Sjimharris *
321230557Sjimharris * @param[in]  object This parameter specifies the base object for which
322230557Sjimharris *             the state transition is occurring.  This is cast into a
323230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
324230557Sjimharris *
325230557Sjimharris * @return none
326230557Sjimharris */
327230557Sjimharrisstatic
328230557Sjimharrisvoid scif_sas_controller_resetting_state_enter(
329230557Sjimharris   SCI_BASE_OBJECT_T * object
330230557Sjimharris)
331230557Sjimharris{
332230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
333230557Sjimharris
334230557Sjimharris   SET_STATE_HANDLER(
335230557Sjimharris      fw_controller,
336230557Sjimharris      scif_sas_controller_state_handler_table,
337230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESETTING
338230557Sjimharris   );
339230557Sjimharris
340230557Sjimharris   // Attempt to reset the core controller.
341230557Sjimharris   fw_controller->operation_status = scic_controller_reset(
342230557Sjimharris                                        fw_controller->core_object
343230557Sjimharris                                     );
344230557Sjimharris   if (fw_controller->operation_status == SCI_SUCCESS)
345230557Sjimharris   {
346230557Sjimharris      // Reset the framework controller.
347230557Sjimharris      sci_base_state_machine_change_state(
348230557Sjimharris         &fw_controller->parent.state_machine,
349230557Sjimharris         SCI_BASE_CONTROLLER_STATE_RESET
350230557Sjimharris      );
351230557Sjimharris   }
352230557Sjimharris   else
353230557Sjimharris   {
354230557Sjimharris      SCIF_LOG_ERROR((
355230557Sjimharris         sci_base_object_get_logger(fw_controller),
356230557Sjimharris         SCIF_LOG_OBJECT_CONTROLLER,
357230557Sjimharris         "Controller: unable to successfully reset controller.\n"
358230557Sjimharris      ));
359230557Sjimharris
360230557Sjimharris      sci_base_state_machine_change_state(
361230557Sjimharris         &fw_controller->parent.state_machine,
362230557Sjimharris         SCI_BASE_CONTROLLER_STATE_FAILED
363230557Sjimharris      );
364230557Sjimharris   }
365230557Sjimharris}
366230557Sjimharris
367230557Sjimharris/**
368230557Sjimharris * @brief This method implements the actions taken when entering the
369230557Sjimharris *        FAILED state.
370230557Sjimharris *
371230557Sjimharris * @param[in]  object This parameter specifies the base object for which
372230557Sjimharris *             the state transition is occurring.  This is cast into a
373230557Sjimharris *             SCIF_SAS_CONTROLLER object in the method implementation.
374230557Sjimharris *
375230557Sjimharris * @return none
376230557Sjimharris */
377230557Sjimharrisstatic
378230557Sjimharrisvoid scif_sas_controller_failed_state_enter(
379230557Sjimharris   SCI_BASE_OBJECT_T * object
380230557Sjimharris)
381230557Sjimharris{
382230557Sjimharris   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
383230557Sjimharris
384230557Sjimharris   SCIF_LOG_ERROR((
385230557Sjimharris      sci_base_object_get_logger(fw_controller),
386230557Sjimharris      SCIF_LOG_OBJECT_CONTROLLER,
387230557Sjimharris      "Controller: entered FAILED state.\n"
388230557Sjimharris   ));
389230557Sjimharris
390230557Sjimharris   SET_STATE_HANDLER(
391230557Sjimharris      fw_controller,
392230557Sjimharris      scif_sas_controller_state_handler_table,
393230557Sjimharris      SCI_BASE_CONTROLLER_STATE_FAILED
394230557Sjimharris   );
395230557Sjimharris
396230557Sjimharris   if (fw_controller->parent.error != SCI_CONTROLLER_FATAL_MEMORY_ERROR)
397230557Sjimharris   {
398230557Sjimharris       //clean timers to avoid timer leak.
399230557Sjimharris       scif_sas_controller_release_resource(fw_controller);
400230557Sjimharris
401230557Sjimharris       //notify user.
402230557Sjimharris       scif_cb_controller_error(fw_controller, fw_controller->parent.error);
403230557Sjimharris   }
404230557Sjimharris}
405230557Sjimharris
406230557SjimharrisSCI_BASE_STATE_T
407230557Sjimharrisscif_sas_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
408230557Sjimharris{
409230557Sjimharris   {
410230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIAL,
411230557Sjimharris      scif_sas_controller_initial_state_enter,
412230557Sjimharris      NULL,
413230557Sjimharris   },
414230557Sjimharris   {
415230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESET,
416230557Sjimharris      scif_sas_controller_reset_state_enter,
417230557Sjimharris      NULL,
418230557Sjimharris   },
419230557Sjimharris   {
420230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZING,
421230557Sjimharris      scif_sas_controller_initializing_state_enter,
422230557Sjimharris      NULL,
423230557Sjimharris   },
424230557Sjimharris   {
425230557Sjimharris      SCI_BASE_CONTROLLER_STATE_INITIALIZED,
426230557Sjimharris      scif_sas_controller_initialized_state_enter,
427230557Sjimharris      NULL,
428230557Sjimharris   },
429230557Sjimharris   {
430230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STARTING,
431230557Sjimharris      scif_sas_controller_starting_state_enter,
432230557Sjimharris      NULL,
433230557Sjimharris   },
434230557Sjimharris   {
435230557Sjimharris      SCI_BASE_CONTROLLER_STATE_READY,
436230557Sjimharris      scif_sas_controller_ready_state_enter,
437230557Sjimharris      NULL,
438230557Sjimharris   },
439230557Sjimharris   {
440230557Sjimharris      SCI_BASE_CONTROLLER_STATE_RESETTING,
441230557Sjimharris      scif_sas_controller_resetting_state_enter,
442230557Sjimharris      NULL,
443230557Sjimharris   },
444230557Sjimharris   {
445230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPING,
446230557Sjimharris      scif_sas_controller_stopping_state_enter,
447230557Sjimharris      NULL,
448230557Sjimharris   },
449230557Sjimharris   {
450230557Sjimharris      SCI_BASE_CONTROLLER_STATE_STOPPED,
451230557Sjimharris      scif_sas_controller_stopped_state_enter,
452230557Sjimharris      NULL,
453230557Sjimharris   },
454230557Sjimharris   {
455230557Sjimharris      SCI_BASE_CONTROLLER_STATE_FAILED,
456230557Sjimharris      scif_sas_controller_failed_state_enter,
457230557Sjimharris      NULL,
458230557Sjimharris   }
459230557Sjimharris};
460230557Sjimharris
461