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