1/*-
2 * This file is provided under a dual BSD/GPLv2 license.  When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 *   * Redistributions of source code must retain the above copyright
34 *     notice, this list of conditions and the following disclaimer.
35 *   * Redistributions in binary form must reproduce the above copyright
36 *     notice, this list of conditions and the following disclaimer in
37 *     the documentation and/or other materials provided with the
38 *     distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD$");
55
56/**
57 * @file
58 *
59 * @brief This file contains all of the entrance and exit methods for each
60 *        of the controller states defined by the SCI_BASE_CONTROLLER state
61 *        machine.
62 */
63
64#include <dev/isci/scil/scic_controller.h>
65
66#include <dev/isci/scil/scif_sas_logger.h>
67#include <dev/isci/scil/scif_sas_controller.h>
68
69//******************************************************************************
70//* P R O T E C T E D    M E T H O D S
71//******************************************************************************
72
73/**
74 * @brief This method implements the actions taken when entering the
75 *        INITIAL state.
76 *
77 * @param[in]  object This parameter specifies the base object for which
78 *             the state transition is occurring.  This is cast into a
79 *             SCIF_SAS_CONTROLLER object in the method implementation.
80 *
81 * @return none
82 */
83static
84void scif_sas_controller_initial_state_enter(
85   SCI_BASE_OBJECT_T * object
86)
87{
88   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
89
90   SET_STATE_HANDLER(
91      fw_controller,
92      scif_sas_controller_state_handler_table,
93      SCI_BASE_CONTROLLER_STATE_INITIAL
94   );
95}
96
97/**
98 * @brief This method implements the actions taken when entering the
99 *        RESET state.
100 *
101 * @param[in]  object This parameter specifies the base object for which
102 *             the state transition is occurring.  This is cast into a
103 *             SCIF_SAS_CONTROLLER object in the method implementation.
104 *
105 * @return none
106 */
107static
108void scif_sas_controller_reset_state_enter(
109   SCI_BASE_OBJECT_T * object
110)
111{
112   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
113   U8 index;
114   U16 smp_phy_index;
115
116   SET_STATE_HANDLER(
117      fw_controller,
118      scif_sas_controller_state_handler_table,
119      SCI_BASE_CONTROLLER_STATE_RESET
120   );
121
122   scif_sas_high_priority_request_queue_construct(
123      &fw_controller->hprq, sci_base_object_get_logger(fw_controller)
124   );
125
126   // Construct the abstract element pool. This pool will store the
127   // references to the framework's remote devices objects.
128   sci_abstract_element_pool_construct(
129      &fw_controller->free_remote_device_pool,
130      fw_controller->remote_device_pool_elements,
131      SCI_MAX_REMOTE_DEVICES
132   );
133
134   // Construct the domain objects.
135   for (index = 0; index < SCI_MAX_DOMAINS; index++)
136   {
137      scif_sas_domain_construct(
138         &fw_controller->domains[index], index, fw_controller
139      );
140   }
141
142   //Initialize SMP PHY MEMORY LIST.
143   sci_fast_list_init(&fw_controller->smp_phy_memory_list);
144
145   for (smp_phy_index = 0;
146        smp_phy_index < SCIF_SAS_SMP_PHY_COUNT;
147        smp_phy_index++)
148   {
149      sci_fast_list_element_init(
150         &fw_controller->smp_phy_array[smp_phy_index],
151         &(fw_controller->smp_phy_array[smp_phy_index].list_element)
152      );
153
154      //insert to owning device's smp phy list.
155      sci_fast_list_insert_tail(
156         (&(fw_controller->smp_phy_memory_list)),
157         (&(fw_controller->smp_phy_array[smp_phy_index].list_element))
158      );
159   }
160
161   scif_sas_controller_set_default_config_parameters(fw_controller);
162
163   fw_controller->internal_request_entries =
164      SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT;
165
166   //@Todo: may need to verify all timers are released. Including domain's
167   //operation timer and all the Internal IO's timer.
168
169   //take care of the lock.
170   scif_cb_lock_disassociate(fw_controller, &fw_controller->hprq.lock);
171}
172
173/**
174 * @brief This method implements the actions taken when entering the
175 *        INITIALIZING state.
176 *
177 * @param[in]  object This parameter specifies the base object for which
178 *             the state transition is occurring.  This is cast into a
179 *             SCIF_SAS_CONTROLLER object in the method implementation.
180 *
181 * @return none
182 */
183static
184void scif_sas_controller_initializing_state_enter(
185   SCI_BASE_OBJECT_T * object
186)
187{
188   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
189
190   SET_STATE_HANDLER(
191      fw_controller,
192      scif_sas_controller_state_handler_table,
193      SCI_BASE_CONTROLLER_STATE_INITIALIZING
194   );
195}
196
197/**
198 * @brief This method implements the actions taken when entering the
199 *        INITIALIZED state.
200 *
201 * @param[in]  object This parameter specifies the base object for which
202 *             the state transition is occurring.  This is cast into a
203 *             SCIF_SAS_CONTROLLER object in the method implementation.
204 *
205 * @return none
206 */
207static
208void scif_sas_controller_initialized_state_enter(
209   SCI_BASE_OBJECT_T * object
210)
211{
212   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
213
214   SET_STATE_HANDLER(
215      fw_controller,
216      scif_sas_controller_state_handler_table,
217      SCI_BASE_CONTROLLER_STATE_INITIALIZED
218   );
219}
220
221/**
222 * @brief This method implements the actions taken when entering the
223 *        STARTING state.
224 *
225 * @param[in]  object This parameter specifies the base object for which
226 *             the state transition is occurring.  This is cast into a
227 *             SCIF_SAS_CONTROLLER object in the method implementation.
228 *
229 * @return none
230 */
231static
232void scif_sas_controller_starting_state_enter(
233   SCI_BASE_OBJECT_T * object
234)
235{
236   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
237
238   SET_STATE_HANDLER(
239      fw_controller,
240      scif_sas_controller_state_handler_table,
241      SCI_BASE_CONTROLLER_STATE_STARTING
242   );
243}
244
245/**
246 * @brief This method implements the actions taken when entering the
247 *        READY state.
248 *
249 * @param[in]  object This parameter specifies the base object for which
250 *             the state transition is occurring.  This is cast into a
251 *             SCIF_SAS_CONTROLLER object in the method implementation.
252 *
253 * @return none
254 */
255static
256void scif_sas_controller_ready_state_enter(
257   SCI_BASE_OBJECT_T * object
258)
259{
260   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
261
262   SET_STATE_HANDLER(
263      fw_controller,
264      scif_sas_controller_state_handler_table,
265      SCI_BASE_CONTROLLER_STATE_READY
266   );
267}
268
269/**
270 * @brief This method implements the actions taken when entering the
271 *        STOPPING state.
272 *
273 * @param[in]  object This parameter specifies the base object for which
274 *             the state transition is occurring.  This is cast into a
275 *             SCIF_SAS_CONTROLLER object in the method implementation.
276 *
277 * @return none
278 */
279static
280void scif_sas_controller_stopping_state_enter(
281   SCI_BASE_OBJECT_T * object
282)
283{
284   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
285
286   SET_STATE_HANDLER(
287      fw_controller,
288      scif_sas_controller_state_handler_table,
289      SCI_BASE_CONTROLLER_STATE_STOPPING
290   );
291}
292
293/**
294 * @brief This method implements the actions taken when entering the
295 *        STOPPED state.
296 *
297 * @param[in]  object This parameter specifies the base object for which
298 *             the state transition is occurring.  This is cast into a
299 *             SCIF_SAS_CONTROLLER object in the method implementation.
300 *
301 * @return none
302 */
303static
304void scif_sas_controller_stopped_state_enter(
305   SCI_BASE_OBJECT_T * object
306)
307{
308   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
309
310   SET_STATE_HANDLER(
311      fw_controller,
312      scif_sas_controller_state_handler_table,
313      SCI_BASE_CONTROLLER_STATE_STOPPED
314   );
315}
316
317/**
318 * @brief This method implements the actions taken when entering the
319 *        RESETTING state.
320 *
321 * @param[in]  object This parameter specifies the base object for which
322 *             the state transition is occurring.  This is cast into a
323 *             SCIF_SAS_CONTROLLER object in the method implementation.
324 *
325 * @return none
326 */
327static
328void scif_sas_controller_resetting_state_enter(
329   SCI_BASE_OBJECT_T * object
330)
331{
332   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
333
334   SET_STATE_HANDLER(
335      fw_controller,
336      scif_sas_controller_state_handler_table,
337      SCI_BASE_CONTROLLER_STATE_RESETTING
338   );
339
340   // Attempt to reset the core controller.
341   fw_controller->operation_status = scic_controller_reset(
342                                        fw_controller->core_object
343                                     );
344   if (fw_controller->operation_status == SCI_SUCCESS)
345   {
346      // Reset the framework controller.
347      sci_base_state_machine_change_state(
348         &fw_controller->parent.state_machine,
349         SCI_BASE_CONTROLLER_STATE_RESET
350      );
351   }
352   else
353   {
354      SCIF_LOG_ERROR((
355         sci_base_object_get_logger(fw_controller),
356         SCIF_LOG_OBJECT_CONTROLLER,
357         "Controller: unable to successfully reset controller.\n"
358      ));
359
360      sci_base_state_machine_change_state(
361         &fw_controller->parent.state_machine,
362         SCI_BASE_CONTROLLER_STATE_FAILED
363      );
364   }
365}
366
367/**
368 * @brief This method implements the actions taken when entering the
369 *        FAILED state.
370 *
371 * @param[in]  object This parameter specifies the base object for which
372 *             the state transition is occurring.  This is cast into a
373 *             SCIF_SAS_CONTROLLER object in the method implementation.
374 *
375 * @return none
376 */
377static
378void scif_sas_controller_failed_state_enter(
379   SCI_BASE_OBJECT_T * object
380)
381{
382   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
383
384   SCIF_LOG_ERROR((
385      sci_base_object_get_logger(fw_controller),
386      SCIF_LOG_OBJECT_CONTROLLER,
387      "Controller: entered FAILED state.\n"
388   ));
389
390   SET_STATE_HANDLER(
391      fw_controller,
392      scif_sas_controller_state_handler_table,
393      SCI_BASE_CONTROLLER_STATE_FAILED
394   );
395
396   if (fw_controller->parent.error != SCI_CONTROLLER_FATAL_MEMORY_ERROR)
397   {
398       //clean timers to avoid timer leak.
399       scif_sas_controller_release_resource(fw_controller);
400
401       //notify user.
402       scif_cb_controller_error(fw_controller, fw_controller->parent.error);
403   }
404}
405
406SCI_BASE_STATE_T
407scif_sas_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
408{
409   {
410      SCI_BASE_CONTROLLER_STATE_INITIAL,
411      scif_sas_controller_initial_state_enter,
412      NULL,
413   },
414   {
415      SCI_BASE_CONTROLLER_STATE_RESET,
416      scif_sas_controller_reset_state_enter,
417      NULL,
418   },
419   {
420      SCI_BASE_CONTROLLER_STATE_INITIALIZING,
421      scif_sas_controller_initializing_state_enter,
422      NULL,
423   },
424   {
425      SCI_BASE_CONTROLLER_STATE_INITIALIZED,
426      scif_sas_controller_initialized_state_enter,
427      NULL,
428   },
429   {
430      SCI_BASE_CONTROLLER_STATE_STARTING,
431      scif_sas_controller_starting_state_enter,
432      NULL,
433   },
434   {
435      SCI_BASE_CONTROLLER_STATE_READY,
436      scif_sas_controller_ready_state_enter,
437      NULL,
438   },
439   {
440      SCI_BASE_CONTROLLER_STATE_RESETTING,
441      scif_sas_controller_resetting_state_enter,
442      NULL,
443   },
444   {
445      SCI_BASE_CONTROLLER_STATE_STOPPING,
446      scif_sas_controller_stopping_state_enter,
447      NULL,
448   },
449   {
450      SCI_BASE_CONTROLLER_STATE_STOPPED,
451      scif_sas_controller_stopped_state_enter,
452      NULL,
453   },
454   {
455      SCI_BASE_CONTROLLER_STATE_FAILED,
456      scif_sas_controller_failed_state_enter,
457      NULL,
458   }
459};
460
461