xref: /freebsd/sys/dev/isci/scil/sci_base_state_machine.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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 functionality common to all state
60  *        machine object implementations.
61  */
62 
63 #include <dev/isci/scil/sci_base_state_machine.h>
64 
65 #define SCI_STATE_MACHINE_EXIT_STATE(state_machine) \
66    if ( \
67        ((state_machine)->state_table[(state_machine)->current_state_id].\
68           exit_state != NULL) \
69       ) \
70    { \
71       ((state_machine)->state_table[(state_machine)->current_state_id].\
72       exit_state((state_machine)->state_machine_owner)); \
73    }
74 
75 #define SCI_STATE_MACHINE_ENTER_STATE(state_machine) \
76       ((state_machine)->state_table[(state_machine)->current_state_id].\
77       enter_state((state_machine)->state_machine_owner))
78 
79 #define SCI_STATE_MACHINE_SET_STATE(state_machine, id) \
80    ((state_machine)->current_state_id = (id))
81 
82 //******************************************************************************
83 //* P R O T E C T E D    M E T H O D S
84 //******************************************************************************
85 
86 /**
87  * @brief This method will set the initial state and state table
88  *        for the state machine. The caller should follow this
89  *        request with the initialize request to cause the state
90  *        machine to start.
91  *
92  * @param[in] this_state_machine This parameter provides the state machine
93  *            object to be constructed.
94  * @param[in] state_machine_owner This parameter indicates the object that
95  *            is owns the state machine being constructed.
96  * @param[in] state_table This parameter specifies the table of state objects
97  *            that is managed by this state machine.
98  * @param[in] initial_state This parameter specifies the value of the initial
99  *            state for this state machine.
100  *
101  * @return none
102  */
103 void sci_base_state_machine_construct(
104    SCI_BASE_STATE_MACHINE_T * this_state_machine,
105    SCI_BASE_OBJECT_T        * my_state_machine_owner,
106    SCI_BASE_STATE_T         * state_table,
107    U32                        initial_state
108 )
109 {
110 #if defined(SCI_LOGGING)
111    sci_base_subject_construct(&this_state_machine->parent);
112 #endif // defined(SCI_LOGGING)
113 
114    this_state_machine->state_machine_owner = my_state_machine_owner;
115    this_state_machine->initial_state_id  = initial_state;
116    this_state_machine->previous_state_id = initial_state;
117    this_state_machine->current_state_id  = initial_state;
118    this_state_machine->state_table       = state_table;
119 }
120 
121 /**
122  * @brief This method will cause the state machine to enter the
123  *        initial state.
124  *
125  * @see sci_base_state_machine_construct() for how to set the initial state
126  *
127  * @param[in] this_state_machine This parameter specifies the state machine
128  *            that is to be started.
129  *
130  * @return none
131  */
132 void sci_base_state_machine_start(
133    SCI_BASE_STATE_MACHINE_T *this_state_machine
134 )
135 {
136    SCI_STATE_MACHINE_SET_STATE(
137       this_state_machine, this_state_machine->initial_state_id
138    );
139 
140 #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
141    sci_base_subject_notify(&this_state_machine->parent);
142 #endif
143 
144    SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
145 }
146 
147 /**
148  * @brief This method will cause the state machine to exit it's current
149  *        state only.
150  *
151  * @param[in] this_state_machine This parameter specifies the state machine
152  *            that is to be stopped.
153  *
154  * @return none
155  */
156 void sci_base_state_machine_stop(
157    SCI_BASE_STATE_MACHINE_T *this_state_machine
158 )
159 {
160    SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
161 
162 #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
163    sci_base_subject_notify(&this_state_machine->parent);
164 #endif
165 }
166 
167 /**
168  * @brief This method performs an update to the current state of
169  *        the state machine.
170  *
171  * @param[in] this_state_machine This parameter specifies the state machine
172  *            for which the caller wishes to perform a state change.
173  * @param[in] next_state This parameter specifies the new state for the
174  *            state machine.
175  *
176  * @return none
177  */
178 void sci_base_state_machine_change_state(
179    SCI_BASE_STATE_MACHINE_T *this_state_machine,
180    U32   next_state
181 )
182 {
183    SCI_STATE_MACHINE_EXIT_STATE(this_state_machine);
184 
185    this_state_machine->previous_state_id = this_state_machine->current_state_id;
186    SCI_STATE_MACHINE_SET_STATE(this_state_machine, next_state);
187 
188 #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
189    // Notify of the state change prior to entering the state.
190    sci_base_subject_notify(&this_state_machine->parent);
191 #endif
192 
193    SCI_STATE_MACHINE_ENTER_STATE(this_state_machine);
194 }
195 
196 /**
197  * @brief This method simply returns the current state of the
198  *         state machine to the caller.
199  *
200  * @param[in] this_state_machine  This parameter specifies the state
201  *            machine for which to retrieve the current state.
202  *
203  * @return This method returns a U32 value indicating the current state for
204  *         the supplied state machine.
205  */
206 U32 sci_base_state_machine_get_state(
207    SCI_BASE_STATE_MACHINE_T *this_state_machine
208 )
209 {
210    return this_state_machine->current_state_id;
211 }
212 
213