Merge trunk HEAD (r46369)
[reactos.git] / reactos / drivers / bus / acpi / ospm / busmgr / bmxface.c
1 /*****************************************************************************
2 *
3 * Module Name: bmxface.c
4 * $Revision: 1.1 $
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
29 #define _COMPONENT ACPI_BUS_MANAGER
30 MODULE_NAME ("bmxface")
31
32
33 /****************************************************************************
34 * External Functions
35 ****************************************************************************/
36
37 /****************************************************************************
38 *
39 * FUNCTION: bm_get_device_status
40 *
41 * PARAMETERS: <TBD>
42 *
43 * RETURN: <TBD>
44 *
45 * DESCRIPTION: <TBD>
46 *
47 ****************************************************************************/
48 ACPI_STATUS
49 bm_get_device_status (
50 BM_HANDLE device_handle,
51 BM_DEVICE_STATUS *device_status)
52 {
53 ACPI_STATUS status = AE_OK;
54 BM_NODE *node = NULL;
55
56 FUNCTION_TRACE("bm_get_device_status");
57
58 if (!device_status) {
59 return_ACPI_STATUS(AE_BAD_PARAMETER);
60 }
61
62 *device_status = BM_STATUS_UNKNOWN;
63
64 /*
65 * Resolve device handle to node.
66 */
67 status = bm_get_node(device_handle, 0, &node);
68 if (ACPI_FAILURE(status)) {
69 return_ACPI_STATUS(status);
70 }
71
72 /*
73 * Parent Present?
74 * ---------------
75 * If the parent isn't present we can't evalute _STA on the child.
76 * Return an unknown status.
77 */
78 if (!BM_NODE_PRESENT(node->parent)) {
79 return_ACPI_STATUS(AE_OK);
80 }
81
82 /*
83 * Dynamic Status?
84 * ---------------
85 * If _STA isn't present we just return the default status.
86 */
87 if (!(node->device.flags & BM_FLAGS_DYNAMIC_STATUS)) {
88 *device_status = BM_STATUS_DEFAULT;
89 return_ACPI_STATUS(AE_OK);
90 }
91
92 /*
93 * Evaluate _STA:
94 * --------------
95 */
96 status = bm_evaluate_simple_integer(node->device.acpi_handle, "_STA",
97 &(node->device.status));
98 if (ACPI_SUCCESS(status)) {
99 *device_status = node->device.status;
100 }
101
102 return_ACPI_STATUS(status);
103 }
104
105
106 /****************************************************************************
107 *
108 * FUNCTION: bm_get_device_info
109 *
110 * PARAMETERS: <TBD>
111 *
112 * RETURN: <TBD>
113 *
114 * DESCRIPTION: <TBD>
115 *
116 ****************************************************************************/
117 ACPI_STATUS
118 bm_get_device_info (
119 BM_HANDLE device_handle,
120 BM_DEVICE **device)
121 {
122 ACPI_STATUS status = AE_OK;
123 BM_NODE *node = NULL;
124
125 FUNCTION_TRACE("bm_get_device_info");
126
127 if (!device) {
128 return_ACPI_STATUS(AE_BAD_PARAMETER);
129 }
130
131 /*
132 * Resolve device handle to internal device.
133 */
134 status = bm_get_node(device_handle, 0, &node);
135 if (ACPI_FAILURE(status)) {
136 return_ACPI_STATUS(status);
137 }
138
139 *device = &(node->device);
140
141 return_ACPI_STATUS(AE_OK);
142 }
143
144
145 /****************************************************************************
146 *
147 * FUNCTION: bm_get_device_context
148 *
149 * PARAMETERS: <TBD>
150 *
151 * RETURN: <TBD>
152 *
153 * DESCRIPTION: <TBD>
154 *
155 ****************************************************************************/
156 ACPI_STATUS
157 bm_get_device_context (
158 BM_HANDLE device_handle,
159 BM_DRIVER_CONTEXT *context)
160 {
161 ACPI_STATUS status = AE_OK;
162 BM_NODE *node = NULL;
163
164 FUNCTION_TRACE("bm_get_device_context");
165
166 if (!context) {
167 return_ACPI_STATUS(AE_BAD_PARAMETER);
168 }
169
170 *context = NULL;
171
172 /*
173 * Resolve device handle to internal device.
174 */
175 status = bm_get_node(device_handle, 0, &node);
176 if (ACPI_FAILURE(status)) {
177 return_ACPI_STATUS(status);
178 }
179
180 if (!node->driver.context) {
181 return_ACPI_STATUS(AE_NULL_ENTRY);
182 }
183
184 *context = node->driver.context;
185
186 return_ACPI_STATUS(AE_OK);
187 }
188
189
190 /****************************************************************************
191 *
192 * FUNCTION: bm_register_driver
193 *
194 * PARAMETERS: <TBD>
195 *
196 * RETURN: <TBD>
197 *
198 * DESCRIPTION: <TBD>
199 *
200 ****************************************************************************/
201
202 ACPI_STATUS
203 bm_register_driver (
204 BM_DEVICE_ID *criteria,
205 BM_DRIVER *driver)
206 {
207 ACPI_STATUS status = AE_NOT_FOUND;
208 BM_HANDLE_LIST device_list;
209 BM_NODE *node = NULL;
210 u32 i = 0;
211
212 FUNCTION_TRACE("bm_register_driver");
213
214 if (!criteria || !driver || !driver->notify || !driver->request) {
215 return_ACPI_STATUS(AE_BAD_PARAMETER);
216 }
217
218 MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST));
219
220 /*
221 * Find Matches:
222 * -------------
223 * Search through the entire device hierarchy for matches against
224 * the given device criteria.
225 */
226 status = bm_search(BM_HANDLE_ROOT, criteria, &device_list);
227 if (ACPI_FAILURE(status)) {
228 return_ACPI_STATUS(status);
229 }
230
231 /*
232 * Install driver:
233 * ----------------
234 * For each match, record the driver information and execute the
235 * driver's Notify() funciton (if present) to notify the driver
236 * of the device's presence.
237 */
238 for (i = 0; i < device_list.count; i++) {
239
240 /* Resolve the device handle. */
241 status = bm_get_node(device_list.handles[i], 0, &node);
242 if (ACPI_FAILURE(status)) {
243 continue;
244 }
245
246 DEBUG_PRINT(ACPI_INFO, ("Registering driver for device [0x%02x].\n", node->device.handle));
247
248 /* Notify driver of new device. */
249 status = driver->notify(BM_NOTIFY_DEVICE_ADDED,
250 node->device.handle, &(node->driver.context));
251 if (ACPI_SUCCESS(status)) {
252 node->driver.notify = driver->notify;
253 node->driver.request = driver->request;
254 node->device.flags |= BM_FLAGS_DRIVER_CONTROL;
255 }
256 }
257
258 return_ACPI_STATUS(AE_OK);
259 }
260
261
262 /****************************************************************************
263 *
264 * FUNCTION: bm_unregister_driver
265 *
266 * PARAMETERS: <TBD>
267 *
268 * RETURN: <TBD>
269 *
270 * DESCRIPTION: <TBD>
271 *
272 ****************************************************************************/
273
274 ACPI_STATUS
275 bm_unregister_driver (
276 BM_DEVICE_ID *criteria,
277 BM_DRIVER *driver)
278 {
279 ACPI_STATUS status = AE_NOT_FOUND;
280 BM_HANDLE_LIST device_list;
281 BM_NODE *node = NULL;
282 u32 i = 0;
283
284 FUNCTION_TRACE("bm_unregister_driver");
285
286 if (!criteria || !driver || !driver->notify || !driver->request) {
287 return_ACPI_STATUS(AE_BAD_PARAMETER);
288 }
289
290 MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST));
291
292 /*
293 * Find Matches:
294 * -------------
295 * Search through the entire device hierarchy for matches against
296 * the given device criteria.
297 */
298 status = bm_search(BM_HANDLE_ROOT, criteria, &device_list);
299 if (ACPI_FAILURE(status)) {
300 return_ACPI_STATUS(status);
301 }
302
303 /*
304 * Remove driver:
305 * ---------------
306 * For each match, execute the driver's Notify() function to allow
307 * the driver to cleanup each device instance.
308 */
309 for (i = 0; i < device_list.count; i++) {
310 /*
311 * Resolve the device handle.
312 */
313 status = bm_get_node(device_list.handles[i], 0, &node);
314 if (ACPI_FAILURE(status)) {
315 continue;
316 }
317
318 DEBUG_PRINT(ACPI_INFO, ("Unregistering driver for device [0x%02x].\n", node->device.handle));
319
320 /* Notify driver of device removal. */
321 status = node->driver.notify(BM_NOTIFY_DEVICE_REMOVED,
322 node->device.handle, &(node->driver.context));
323
324 node->device.flags &= ~BM_FLAGS_DRIVER_CONTROL;
325
326 MEMSET(&(node->driver), 0, sizeof(BM_DRIVER));
327 }
328
329 return_ACPI_STATUS(AE_OK);
330 }