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 functionality common to all state
60230557Sjimharris *        machine object implementations.
61230557Sjimharris */
62230557Sjimharris
63230557Sjimharris#include <dev/isci/scil/sci_base_state_machine.h>
64230557Sjimharris
65230557Sjimharris#define SCI_STATE_MACHINE_EXIT_STATE(state_machine) \
66230557Sjimharris   if ( \
67230557Sjimharris       ((state_machine)->state_table[(state_machine)->current_state_id].\
68230557Sjimharris          exit_state != NULL) \
69230557Sjimharris      ) \
70230557Sjimharris   { \
71230557Sjimharris      ((state_machine)->state_table[(state_machine)->current_state_id].\
72230557Sjimharris      exit_state((state_machine)->state_machine_owner)); \
73230557Sjimharris   }
74230557Sjimharris
75230557Sjimharris#define SCI_STATE_MACHINE_ENTER_STATE(state_machine) \
76230557Sjimharris      ((state_machine)->state_table[(state_machine)->current_state_id].\
77230557Sjimharris      enter_state((state_machine)->state_machine_owner))
78230557Sjimharris
79230557Sjimharris#define SCI_STATE_MACHINE_SET_STATE(state_machine, id) \
80230557Sjimharris   ((state_machine)->current_state_id = (id))
81230557Sjimharris
82230557Sjimharris//******************************************************************************
83230557Sjimharris//* P R O T E C T E D    M E T H O D S
84230557Sjimharris//******************************************************************************
85230557Sjimharris
86230557Sjimharris/**
87230557Sjimharris * @brief This method will set the initial state and state table
88230557Sjimharris *        for the state machine. The caller should follow this
89230557Sjimharris *        request with the initialize request to cause the state
90230557Sjimharris *        machine to start.
91230557Sjimharris *
92230557Sjimharris * @param[in] this_state_machine This parameter provides the state machine
93230557Sjimharris *            object to be constructed.
94230557Sjimharris * @param[in] state_machine_owner This parameter indicates the object that
95230557Sjimharris *            is owns the state machine being constructed.
96230557Sjimharris * @param[in] state_table This parameter specifies the table of state objects
97230557Sjimharris *            that is managed by this state machine.
98230557Sjimharris * @param[in] initial_state This parameter specifies the value of the initial
99230557Sjimharris *            state for this state machine.
100230557Sjimharris *
101230557Sjimharris * @return none
102230557Sjimharris */
103230557Sjimharrisvoid sci_base_state_machine_construct(
104230557Sjimharris   SCI_BASE_STATE_MACHINE_T * this_state_machine,
105230557Sjimharris   SCI_BASE_OBJECT_T        * my_state_machine_owner,
106230557Sjimharris   SCI_BASE_STATE_T         * state_table,
107230557Sjimharris   U32                        initial_state
108230557Sjimharris)
109230557Sjimharris{
110230557Sjimharris#if defined(SCI_LOGGING)
111230557Sjimharris   sci_base_subject_construct(&this_state_machine->parent);
112230557Sjimharris#endif // defined(SCI_LOGGING)
113230557Sjimharris
114230557Sjimharris   this_state_machine->state_machine_owner = my_state_machine_owner;
115230557Sjimharris   this_state_machine->initial_state_id  = initial_state;
116230557Sjimharris   this_state_machine->previous_state_id = initial_state;
117230557Sjimharris   this_state_machine->current_state_id  = initial_state;
118230557Sjimharris   this_state_machine->state_table       = state_table;
119230557Sjimharris}
120230557Sjimharris
121230557Sjimharris/**
122230557Sjimharris * @brief This method will cause the state machine to enter the
123230557Sjimharris *        initial state.
124230557Sjimharris *
125230557Sjimharris * @see sci_base_state_machine_construct() for how to set the initial state
126230557Sjimharris *
127230557Sjimharris * @param[in] this_state_machine This parameter specifies the state machine
128230557Sjimharris *            that is to be started.
129230557Sjimharris *
130230557Sjimharris * @return none
131230557Sjimharris */
132230557Sjimharrisvoid sci_base_state_machine_start(
133230557Sjimharris   SCI_BASE_STATE_MACHINE_T *this_state_machine
134230557Sjimharris)
135230557Sjimharris{
136230557Sjimharris   SCI_STATE_MACHINE_SET_STATE(
137230557Sjimharris      this_state_machine, this_state_machine->initial_state_id
138230557Sjimharris   );
139230557Sjimharris
140230557Sjimharris#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
141230557Sjimharris   sci_base_subject_notify(&this_state_machine->parent);
142230557Sjimharris#endif
143230557Sjimharris
144230557Sjimharris   SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
145230557Sjimharris}
146230557Sjimharris
147230557Sjimharris/**
148230557Sjimharris * @brief This method will cause the state machine to exit it's current
149230557Sjimharris *        state only.
150230557Sjimharris *
151230557Sjimharris * @param[in] this_state_machine This parameter specifies the state machine
152230557Sjimharris *            that is to be stopped.
153230557Sjimharris *
154230557Sjimharris * @return none
155230557Sjimharris */
156230557Sjimharrisvoid sci_base_state_machine_stop(
157230557Sjimharris   SCI_BASE_STATE_MACHINE_T *this_state_machine
158230557Sjimharris)
159230557Sjimharris{
160230557Sjimharris   SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
161230557Sjimharris
162230557Sjimharris#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
163230557Sjimharris   sci_base_subject_notify(&this_state_machine->parent);
164230557Sjimharris#endif
165230557Sjimharris}
166230557Sjimharris
167230557Sjimharris/**
168230557Sjimharris * @brief This method performs an update to the current state of
169230557Sjimharris *        the state machine.
170230557Sjimharris *
171230557Sjimharris * @param[in] this_state_machine This parameter specifies the state machine
172230557Sjimharris *            for which the caller wishes to perform a state change.
173230557Sjimharris * @param[in] next_state This parameter specifies the new state for the
174230557Sjimharris *            state machine.
175230557Sjimharris *
176230557Sjimharris * @return none
177230557Sjimharris */
178230557Sjimharrisvoid sci_base_state_machine_change_state(
179230557Sjimharris   SCI_BASE_STATE_MACHINE_T *this_state_machine,
180230557Sjimharris   U32   next_state
181230557Sjimharris)
182230557Sjimharris{
183230557Sjimharris   SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
184230557Sjimharris
185230557Sjimharris   this_state_machine->previous_state_id = this_state_machine->current_state_id;
186230557Sjimharris   SCI_STATE_MACHINE_SET_STATE(this_state_machine, next_state);
187230557Sjimharris
188230557Sjimharris#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
189230557Sjimharris   // Notify of the state change prior to entering the state.
190230557Sjimharris   sci_base_subject_notify(&this_state_machine->parent);
191230557Sjimharris#endif
192230557Sjimharris
193230557Sjimharris   SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
194230557Sjimharris}
195230557Sjimharris
196230557Sjimharris/**
197230557Sjimharris * @brief This method simply returns the current state of the
198230557Sjimharris *         state machine to the caller.
199230557Sjimharris *
200230557Sjimharris * @param[in] this_state_machine  This parameter specifies the state
201230557Sjimharris *            machine for which to retrieve the current state.
202230557Sjimharris *
203230557Sjimharris * @return This method returns a U32 value indicating the current state for
204230557Sjimharris *         the supplied state machine.
205230557Sjimharris */
206230557SjimharrisU32 sci_base_state_machine_get_state(
207230557Sjimharris   SCI_BASE_STATE_MACHINE_T *this_state_machine
208230557Sjimharris)
209230557Sjimharris{
210230557Sjimharris   return this_state_machine->current_state_id;
211230557Sjimharris}
212230557Sjimharris
213