File: /usr/src/linux/drivers/acpi/ospm/busmgr/bmnotify.c

1     /*****************************************************************************
2      *
3      * Module Name: bmnotify.c
4      *   $Revision: 21 $
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
32     	 MODULE_NAME		("bmnotify")
33     
34     
35     /****************************************************************************
36      *                            Internal Functions
37      ****************************************************************************/
38     
39     /****************************************************************************
40      *
41      * FUNCTION:    bm_generate_notify
42      *
43      * PARAMETERS:
44      *
45      * RETURN:
46      *
47      * DESCRIPTION:
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     	BM_DEVICE		*device = NULL;
58     
59     	FUNCTION_TRACE("bm_generate_notify");
60     
61     	if (!node) {
62     		return_ACPI_STATUS(AE_BAD_PARAMETER);
63     	}
64     
65     	device = &(node->device);
66     
67     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Sending notify [%02x] to device [%02x].\n", notify_type, node->device.handle));
68     
69     	if (!BM_IS_DRIVER_CONTROL(device)) {
70     		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No driver installed for device [%02x].\n", device->handle));
71     		return_ACPI_STATUS(AE_NOT_EXIST);
72     	}
73     
74     	status = node->driver.notify(notify_type, node->device.handle,
75     		&(node->driver.context));
76     
77     	return_ACPI_STATUS(status);
78     }
79     
80     
81     /****************************************************************************
82      *
83      * FUNCTION:    bm_device_check
84      *
85      * PARAMETERS:
86      *
87      * RETURN:
88      *
89      * DESCRIPTION:
90      *
91      ****************************************************************************/
92     
93     acpi_status
94     bm_device_check (
95     	BM_NODE			*node,
96     	u32			*status_change)
97     {
98     	acpi_status             status = AE_OK;
99     	BM_DEVICE		*device = NULL;
100     	BM_DEVICE_STATUS	old_status = BM_STATUS_UNKNOWN;
101     
102     	FUNCTION_TRACE("bm_device_check");
103     
104     	if (!node) {
105     		return_ACPI_STATUS(AE_BAD_PARAMETER);
106     	}
107     
108     	device = &(node->device);
109     
110     	if (status_change) {
111     		*status_change = FALSE;
112     	}
113     
114     	old_status = device->status;
115     
116     	/*
117     	 * Parent Present?
118     	 * ---------------
119     	 * Only check this device if its parent is present (which implies
120     	 * this device MAY be present).
121     	 */
122     	if (!BM_NODE_PRESENT(node->parent)) {
123     		return_ACPI_STATUS(AE_OK);
124     	}
125     
126     	/*
127     	 * Get Status:
128     	 * -----------
129     	 * And see if the status has changed.
130     	 */
131     	status = bm_get_status(device);
132     	if (ACPI_FAILURE(status)) {
133     		return_ACPI_STATUS(status);
134     	}
135     	
136     	if (old_status == node->device.status) {
137     		return_ACPI_STATUS(AE_OK);
138     	}
139     
140     	if (status_change) {
141     		*status_change = TRUE;
142     	}
143     	
144     	/*
145     	 * Device Insertion?
146     	 * -----------------
147     	 */
148     	if ((device->status & BM_STATUS_PRESENT) &&
149     		!(old_status & BM_STATUS_PRESENT)) {
150     		/* TBD: Make sure driver is loaded, and if not, load. */
151     		status = bm_generate_notify(node, BM_NOTIFY_DEVICE_ADDED);
152     	}
153     
154     	/*
155     	 * Device Removal?
156     	 * ---------------
157     	 */
158     	else if (!(device->status & BM_STATUS_PRESENT) &&
159     		(old_status & BM_STATUS_PRESENT)) {
160     		/* TBD: Unload driver if last device instance. */
161     		status = bm_generate_notify(node, BM_NOTIFY_DEVICE_REMOVED);
162     	}
163     
164     	return_ACPI_STATUS(AE_OK);
165     }
166     
167     
168     /****************************************************************************
169      *
170      * FUNCTION:    bm_bus_check
171      *
172      * PARAMETERS:
173      *
174      * RETURN:
175      *
176      * DESCRIPTION:
177      *
178      ****************************************************************************/
179     
180     acpi_status
181     bm_bus_check (
182     	BM_NODE			*parent_node)
183     {
184     	acpi_status             status = AE_OK;
185     	u32			status_change = FALSE;
186     
187     	FUNCTION_TRACE("bm_bus_check");
188     
189     	if (!parent_node) {
190     		return_ACPI_STATUS(AE_BAD_PARAMETER);
191     	}
192     
193     	/*
194     	 * Status Change?
195     	 * --------------
196     	 */
197     	status = bm_device_check(parent_node, &status_change);
198     	if (ACPI_FAILURE(status) || !status_change) {
199     		return_ACPI_STATUS(status);
200     	}
201     
202     	/*
203     	 * Enumerate Scope:
204     	 * ----------------
205     	 * TBD: Enumerate child devices within this device's scope and
206     	 *       run bm_device_check()'s on them...
207     	 */
208     
209     	return_ACPI_STATUS(AE_OK);
210     }
211     
212     
213     /****************************************************************************
214      *                            External Functions
215      ****************************************************************************/
216     
217     /****************************************************************************
218      *
219      * FUNCTION:    bm_notify
220      *
221      * PARAMETERS:
222      *
223      * RETURN:
224      *
225      * DESCRIPTION:
226      *
227      ****************************************************************************/
228     
229     void
230     bm_notify (
231     	acpi_handle             acpi_handle,
232     	u32                     notify_value,
233     	void                    *context)
234     {
235     	acpi_status             status = AE_OK;
236     	BM_NODE			*node = NULL;
237     
238     	FUNCTION_TRACE("bm_notify");
239     
240     	/*
241     	 * Resolve the ACPI handle.
242     	 */
243     	status = bm_get_node(0, acpi_handle, &node);
244     	if (ACPI_FAILURE(status)) {
245     		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Recieved notify [%02x] for unknown device [%p].\n", notify_value, acpi_handle));
246     		return_VOID;
247     	}
248     
249     	/*
250     	 * Device-Specific or Standard?
251     	 * ----------------------------
252     	 * Device-specific notifies are forwarded to the control module's
253     	 * notify() function for processing.  Standard notifies are handled
254     	 * internally.
255     	 */
256     	if (notify_value > 0x7F) {
257     		status = bm_generate_notify(node, notify_value);
258     	}
259     	else {
260     		switch (notify_value) {
261     
262     		case BM_NOTIFY_BUS_CHECK:
263     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received BUS CHECK notification for device [%02x].\n", node->device.handle));
264     			status = bm_bus_check(node);
265     			break;
266     
267     		case BM_NOTIFY_DEVICE_CHECK:
268     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%02x].\n", node->device.handle));
269     			status = bm_device_check(node, NULL);
270     			break;
271     
272     		case BM_NOTIFY_DEVICE_WAKE:
273     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%02x].\n", node->device.handle));
274     			/* TBD */
275     			break;
276     
277     		case BM_NOTIFY_EJECT_REQUEST:
278     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%02x].\n", node->device.handle));
279     			/* TBD */
280     			break;
281     
282     		case BM_NOTIFY_DEVICE_CHECK_LIGHT:
283     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%02x].\n", node->device.handle));
284     			/* TBD: Exactly what does the 'light' mean? */
285     			status = bm_device_check(node, NULL);
286     			break;
287     
288     		case BM_NOTIFY_FREQUENCY_MISMATCH:
289     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%02x].\n", node->device.handle));
290     			/* TBD */
291     			break;
292     
293     		case BM_NOTIFY_BUS_MODE_MISMATCH:
294     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%02x].\n", node->device.handle));
295     			/* TBD */
296     			break;
297     
298     		case BM_NOTIFY_POWER_FAULT:
299     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received POWER FAULT notification.\n"));
300     			/* TBD */
301     			break;
302     
303     		default:
304     			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Received unknown/unsupported notification.\n"));
305     			break;
306     		}
307     	}
308     
309     	return_VOID;
310     }
311     
312     
313