:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / ospm / busmgr / bmnotify.c
1 /*****************************************************************************
2  *
3  * Module Name: bmnotify.c
4  *   $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 Andrew Grover
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include <acpi.h>
28 #include "bm.h"
29
30
31 #define _COMPONENT              ACPI_BUS_MANAGER
32          MODULE_NAME            ("bmnotify")
33
34
35 /****************************************************************************
36  *                            Internal Functions
37  ****************************************************************************/
38
39 /****************************************************************************
40  *
41  * FUNCTION:    bm_generate_notify
42  *
43  * PARAMETERS:  <TBD>
44  *
45  * RETURN:      <TBD>
46  *
47  * DESCRIPTION: <TBD>
48  *
49  ****************************************************************************/
50
51 ACPI_STATUS
52 bm_generate_notify (
53         BM_NODE                 *node,
54         u32                     notify_type)
55 {
56         ACPI_STATUS             status = AE_OK;
57
58         FUNCTION_TRACE("bm_generate_notify");
59
60         if (!node) {
61                 return_ACPI_STATUS(AE_BAD_PARAMETER);
62         }
63
64         DEBUG_PRINT(ACPI_INFO, ("Sending notify [0x%02x] to device [0x%02x].\n", notify_type, node->device.handle));
65
66         if (!(node->device.flags & BM_FLAGS_DRIVER_CONTROL) || 
67                 !(node->driver.notify)) {
68                 DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [0x%02x].\n", node->device.handle));
69                 return_ACPI_STATUS(AE_NOT_EXIST);
70         }
71
72         status = node->driver.notify(notify_type, node->device.handle, 
73                 &(node->driver.context));
74
75         return_ACPI_STATUS(status);
76 }
77
78
79 /****************************************************************************
80  *
81  * FUNCTION:    bm_device_check
82  *
83  * PARAMETERS:  <TBD>
84  *
85  * RETURN:      <TBD>
86  *
87  * DESCRIPTION: <TBD>
88  *
89  ****************************************************************************/
90
91 ACPI_STATUS
92 bm_device_check (
93         BM_NODE                 *node,
94         u32                     *status_change)
95 {
96         ACPI_STATUS             status = AE_OK;
97         BM_DEVICE               *device = NULL;
98         BM_DEVICE_STATUS        old_status = BM_STATUS_UNKNOWN;
99
100         FUNCTION_TRACE("bm_device_check");
101
102         if (!node) {
103                 return_ACPI_STATUS(AE_BAD_PARAMETER);
104         }
105
106         device = &(node->device);
107
108         if (status_change) {
109                 *status_change = FALSE;
110         }
111
112         old_status = device->status;
113
114         /*
115          * Parent Present?
116          * ---------------
117          * Only check this device if its parent is present (which implies
118          * this device MAY be present).
119          */
120         if (!BM_NODE_PRESENT(node->parent)) {
121                 return_ACPI_STATUS(AE_OK);
122         }
123
124         /*
125          * Get Status:
126          * -----------
127          * And see if the status has changed.
128          */
129         status = bm_get_status(device);
130         if (ACPI_FAILURE(status)) {
131                 return_ACPI_STATUS(status);
132         }
133         
134         if (old_status == node->device.status) {
135                 return_ACPI_STATUS(AE_OK);
136         }
137
138         if (status_change) {
139                 *status_change = TRUE;
140         }
141         
142         /*
143          * Device Insertion?
144          * -----------------
145          */
146         if ((device->status & BM_STATUS_PRESENT) && 
147                 !(old_status & BM_STATUS_PRESENT)) {
148                 /* TODO: Make sure driver is loaded, and if not, load. */
149                 status = bm_generate_notify(node, BM_NOTIFY_DEVICE_ADDED);
150         }
151
152         /*
153          * Device Removal?
154          * ---------------
155          */
156         else if (!(device->status & BM_STATUS_PRESENT) && 
157                 (old_status & BM_STATUS_PRESENT)) {
158                 /* TODO: Unload driver if last device instance. */
159                 status = bm_generate_notify(node, BM_NOTIFY_DEVICE_REMOVED);
160         }
161
162         return_ACPI_STATUS(AE_OK);
163 }
164
165
166 /****************************************************************************
167  *
168  * FUNCTION:    bm_bus_check
169  *
170  * PARAMETERS:  <TBD>
171  *
172  * RETURN:      <TBD>
173  *
174  * DESCRIPTION: <TBD>
175  *
176  ****************************************************************************/
177
178 ACPI_STATUS
179 bm_bus_check (
180         BM_NODE                 *parent_node)
181 {
182         ACPI_STATUS             status = AE_OK;
183         u32                     status_change = FALSE;
184
185         FUNCTION_TRACE("bm_bus_check");
186
187         if (!parent_node) {
188                 return_ACPI_STATUS(AE_BAD_PARAMETER);
189         }
190
191         /*
192          * Status Change?
193          * --------------
194          */
195         status = bm_device_check(parent_node, &status_change);
196         if (ACPI_FAILURE(status) || !status_change) {
197                 return_ACPI_STATUS(status);
198         }
199
200         /*
201          * Enumerate Scope:
202          * ----------------
203          * TODO: Enumerate child devices within this device's scope and
204          *       run bm_device_check()'s on them...
205          */
206
207         return_ACPI_STATUS(AE_OK);
208 }
209
210
211 /****************************************************************************
212  *                            External Functions
213  ****************************************************************************/
214
215 /****************************************************************************
216  *
217  * FUNCTION:    bm_notify
218  *
219  * PARAMETERS:  <TBD>
220  *
221  * RETURN:      <TBD>
222  *
223  * DESCRIPTION: <TBD>
224  *
225  ****************************************************************************/
226
227 void
228 bm_notify (
229         ACPI_HANDLE             acpi_handle,
230         u32                     notify_value,
231         void                    *context)
232 {
233         ACPI_STATUS             status = AE_OK;
234         BM_NODE                 *node = NULL;
235
236         FUNCTION_TRACE("bm_notify");
237
238         /*
239          * Resolve the ACPI handle.
240          */
241         status = bm_get_node(0, acpi_handle, &node);
242         if (ACPI_FAILURE(status)) {
243                 DEBUG_PRINT(ACPI_INFO, ("Recieved notify [0x%02x] for unknown device [%p].\n", notify_value, acpi_handle));
244                 return_VOID;
245         }
246
247         /*
248          * Device-Specific or Standard?
249          * ----------------------------
250          * Device-specific notifies are forwarded to the control module's 
251          * notify() function for processing.  Standard notifies are handled
252          * internally.
253          */
254         if (notify_value > 0x7F) {
255                 status = bm_generate_notify(node, notify_value);
256         }
257         else {
258                 switch (notify_value) {
259
260                 case BM_NOTIFY_BUS_CHECK:
261                         DEBUG_PRINT(ACPI_INFO, ("Received BUS CHECK notification.\n"));
262                         status = bm_bus_check(node);
263                         break;
264
265                 case BM_NOTIFY_DEVICE_CHECK:
266                         DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK notification.\n"));
267                         status = bm_device_check(node, NULL);
268                         break;
269
270                 case BM_NOTIFY_DEVICE_WAKE:
271                         DEBUG_PRINT(ACPI_INFO, ("Received DEVICE WAKE notification.\n"));
272                         /* TODO */
273                         break;
274
275                 case BM_NOTIFY_EJECT_REQUEST:
276                         DEBUG_PRINT(ACPI_INFO, ("Received EJECT REQUEST notification.\n"));
277                         /* TODO */
278                         break;
279
280                 case BM_NOTIFY_DEVICE_CHECK_LIGHT:
281                         DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK LIGHT notification.\n"));
282                         /* TODO: Exactly what does the 'light' mean? */
283                         status = bm_device_check(node, NULL);
284                         break;
285
286                 case BM_NOTIFY_FREQUENCY_MISMATCH:
287                         DEBUG_PRINT(ACPI_INFO, ("Received FREQUENCY MISMATCH notification.\n"));
288                         /* TODO */
289                         break;
290
291                 case BM_NOTIFY_BUS_MODE_MISMATCH:
292                         DEBUG_PRINT(ACPI_INFO, ("Received BUS MODE MISMATCH notification.\n"));
293                         /* TODO */
294                         break;
295
296                 case BM_NOTIFY_POWER_FAULT:
297                         DEBUG_PRINT(ACPI_INFO, ("Received POWER FAULT notification.\n"));
298                         /* TODO */
299                         break;
300
301                 default:
302                         DEBUG_PRINT(ACPI_INFO, ("Received unknown/unsupported notification.\n"));
303                         break;
304                 }
305         }
306
307         return_VOID;
308 }
309
310