2 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
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.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 * Modified for ReactOS and latest ACPICA
27 * Copyright (C)2009 Samuel Serapion
34 #include <acpi_drivers.h>
40 #define _COMPONENT ACPI_BUS_COMPONENT
41 ACPI_MODULE_NAME ("acpi_bus")
46 #define STRUCT_TO_INT(s) (*((int*)&s))
47 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
48 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children))
49 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node))
52 extern void acpi_pic_sci_set_trigger(unsigned int irq
, UINT16 trigger
);
54 typedef int (*acpi_bus_walk_callback
)(struct acpi_device
*, int, void*);
56 struct acpi_device
*acpi_root
;
57 KSPIN_LOCK acpi_bus_event_lock
;
58 LIST_HEAD(acpi_bus_event_list
);
59 //DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
60 KEVENT AcpiEventQueue
;
64 acpi_device_register (
65 struct acpi_device
*device
,
66 struct acpi_device
*parent
)
71 return_VALUE(AE_BAD_PARAMETER
);
78 acpi_device_unregister (
79 struct acpi_device
*device
)
82 return_VALUE(AE_BAD_PARAMETER
);
85 put_device(&device
->dev
);
92 /* --------------------------------------------------------------------------
94 -------------------------------------------------------------------------- */
97 acpi_bus_data_handler (
101 DPRINT1("acpi_bus_data_handler not implemented");
110 acpi_bus_get_device (
112 struct acpi_device
**device
)
114 ACPI_STATUS status
= AE_OK
;
117 return_VALUE(AE_BAD_PARAMETER
);
119 /* TBD: Support fixed-feature devices */
121 status
= AcpiGetData(handle
, acpi_bus_data_handler
, (void**)device
);
122 if (ACPI_FAILURE(status
) || !*device
) {
123 DPRINT( "Error getting context for object [%p]\n",
125 return_VALUE(AE_NOT_FOUND
);
131 ACPI_STATUS
acpi_bus_get_status_handle(ACPI_HANDLE handle
,
132 unsigned long long *sta
)
136 status
= acpi_evaluate_integer(handle
, "_STA", NULL
, sta
);
137 if (ACPI_SUCCESS(status
))
140 if (status
== AE_NOT_FOUND
) {
141 *sta
= ACPI_STA_DEVICE_PRESENT
| ACPI_STA_DEVICE_ENABLED
|
142 ACPI_STA_DEVICE_UI
| ACPI_STA_DEVICE_FUNCTIONING
;
149 acpi_bus_get_status (
150 struct acpi_device
*device
)
153 unsigned long long sta
;
155 status
= acpi_bus_get_status_handle(device
->handle
, &sta
);
156 if (ACPI_FAILURE(status
))
159 STRUCT_TO_INT(device
->status
) = (int) sta
;
161 if (device
->status
.functional
&& !device
->status
.present
) {
162 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Device [%s] status [%08x]: "
163 "functional but not present;\n",
165 (UINT32
) STRUCT_TO_INT(device
->status
)));
168 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Device [%s] status [%08x]\n",
170 (UINT32
) STRUCT_TO_INT(device
->status
)));
174 void acpi_bus_private_data_handler(ACPI_HANDLE handle
,
180 int acpi_bus_get_private_data(ACPI_HANDLE handle
, void **data
)
182 ACPI_STATUS status
= AE_OK
;
187 status
= AcpiGetData(handle
, acpi_bus_private_data_handler
, data
);
188 if (ACPI_FAILURE(status
) || !*data
) {
189 DPRINT("No context for object [%p]\n", handle
);
195 /* --------------------------------------------------------------------------
197 -------------------------------------------------------------------------- */
205 ACPI_STATUS status
= 0;
206 struct acpi_device
*device
= NULL
;
207 unsigned long long psc
= 0;
209 result
= acpi_bus_get_device(handle
, &device
);
211 return_VALUE(result
);
213 *state
= ACPI_STATE_UNKNOWN
;
215 if (!device
->flags
.power_manageable
) {
216 /* TBD: Non-recursive algorithm for walking up hierarchy */
218 *state
= device
->parent
->power
.state
;
220 *state
= ACPI_STATE_D0
;
224 * Get the device's power state either directly (via _PSC) or
225 * indirectly (via power resources).
227 if (device
->power
.flags
.explicit_get
) {
228 status
= acpi_evaluate_integer(device
->handle
, "_PSC",
230 if (ACPI_FAILURE(status
))
231 return_VALUE(AE_NOT_FOUND
);
232 device
->power
.state
= (int) psc
;
234 else if (device
->power
.flags
.power_resources
) {
235 result
= acpi_power_get_inferred_state(device
);
237 return_VALUE(result
);
240 *state
= device
->power
.state
;
243 DPRINT("Device [%s] power state is D%d\n",
244 device
->pnp
.bus_id
, device
->power
.state
);
256 ACPI_STATUS status
= AE_OK
;
257 struct acpi_device
*device
= NULL
;
258 char object_name
[5] = {'_','P','S','0'+state
,'\0'};
261 result
= acpi_bus_get_device(handle
, &device
);
263 return_VALUE(result
);
265 if ((state
< ACPI_STATE_D0
) || (state
> ACPI_STATE_D3
))
266 return_VALUE(AE_BAD_PARAMETER
);
268 /* Make sure this is a valid target state */
270 if (!device
->flags
.power_manageable
) {
271 DPRINT1( "Device is not power manageable\n");
272 return_VALUE(AE_NOT_FOUND
);
275 * Get device's current power state
277 //if (!acpi_power_nocheck) {
279 * Maybe the incorrect power state is returned on the bogus
280 * bios, which is different with the real power state.
281 * For example: the bios returns D0 state and the real power
282 * state is D3. OS expects to set the device to D0 state. In
283 * such case if OS uses the power state returned by the BIOS,
284 * the device can't be transisted to the correct power state.
285 * So if the acpi_power_nocheck is set, it is unnecessary to
286 * get the power state by calling acpi_bus_get_power.
288 acpi_bus_get_power(device
->handle
, &device
->power
.state
);
291 if ((state
== device
->power
.state
) && !device
->flags
.force_power_state
) {
292 DPRINT1("Device is already at D%d\n", state
);
295 if (!device
->power
.states
[state
].flags
.valid
) {
296 DPRINT1( "Device does not support D%d\n", state
);
299 if (device
->parent
&& (state
< device
->parent
->power
.state
)) {
300 DPRINT1( "Cannot set device to a higher-powered state than parent\n");
307 * On transitions to a high-powered state we first apply power (via
308 * power resources) then evalute _PSx. Conversly for transitions to
309 * a lower-powered state.
311 if (state
< device
->power
.state
) {
312 if (device
->power
.flags
.power_resources
) {
313 result
= acpi_power_transition(device
, state
);
317 if (device
->power
.states
[state
].flags
.explicit_set
) {
318 status
= AcpiEvaluateObject(device
->handle
,
319 object_name
, NULL
, NULL
);
320 if (ACPI_FAILURE(status
)) {
321 result
= AE_NOT_FOUND
;
327 if (device
->power
.states
[state
].flags
.explicit_set
) {
328 status
= AcpiEvaluateObject(device
->handle
,
329 object_name
, NULL
, NULL
);
330 if (ACPI_FAILURE(status
)) {
331 result
= AE_NOT_FOUND
;
335 if (device
->power
.flags
.power_resources
) {
336 result
= acpi_power_transition(device
, state
);
344 DPRINT( "Error transitioning device [%s] to D%d\n",
345 device
->pnp
.bus_id
, state
);
347 DPRINT("Device [%s] transitioned to D%d\n",
348 device
->pnp
.bus_id
, state
);
353 BOOLEAN
acpi_bus_power_manageable(ACPI_HANDLE handle
)
355 struct acpi_device
*device
;
358 result
= acpi_bus_get_device(handle
, &device
);
359 return result
? 0 : device
->flags
.power_manageable
;
362 BOOLEAN
acpi_bus_can_wakeup(ACPI_HANDLE handle
)
364 struct acpi_device
*device
;
367 result
= acpi_bus_get_device(handle
, &device
);
368 return result
? 0 : device
->wakeup
.flags
.valid
;
372 acpi_bus_get_power_flags (
373 struct acpi_device
*device
)
375 ACPI_STATUS status
= 0;
376 ACPI_HANDLE handle
= 0;
383 * Power Management Flags
385 status
= AcpiGetHandle(device
->handle
, "_PSC", &handle
);
386 if (ACPI_SUCCESS(status
))
387 device
->power
.flags
.explicit_get
= 1;
388 status
= AcpiGetHandle(device
->handle
, "_IRC", &handle
);
389 if (ACPI_SUCCESS(status
))
390 device
->power
.flags
.inrush_current
= 1;
391 status
= AcpiGetHandle(device
->handle
, "_PRW", &handle
);
392 if (ACPI_SUCCESS(status
))
393 device
->flags
.wake_capable
= 1;
396 * Enumerate supported power management states
398 for (i
= ACPI_STATE_D0
; i
<= ACPI_STATE_D3
; i
++) {
399 struct acpi_device_power_state
*ps
= &device
->power
.states
[i
];
400 char object_name
[5] = {'_','P','R','0'+i
,'\0'};
402 /* Evaluate "_PRx" to se if power resources are referenced */
403 acpi_evaluate_reference(device
->handle
, object_name
, NULL
,
405 if (ps
->resources
.count
) {
406 device
->power
.flags
.power_resources
= 1;
410 /* Evaluate "_PSx" to see if we can do explicit sets */
411 object_name
[2] = 'S';
412 status
= AcpiGetHandle(device
->handle
, object_name
, &handle
);
413 if (ACPI_SUCCESS(status
)) {
414 ps
->flags
.explicit_set
= 1;
418 /* State is valid if we have some power control */
419 if (ps
->resources
.count
|| ps
->flags
.explicit_set
)
422 ps
->power
= -1; /* Unknown - driver assigned */
423 ps
->latency
= -1; /* Unknown - driver assigned */
426 /* Set defaults for D0 and D3 states (always valid) */
427 device
->power
.states
[ACPI_STATE_D0
].flags
.valid
= 1;
428 device
->power
.states
[ACPI_STATE_D0
].power
= 100;
429 device
->power
.states
[ACPI_STATE_D3
].flags
.valid
= 1;
430 device
->power
.states
[ACPI_STATE_D3
].power
= 0;
432 device
->power
.state
= ACPI_STATE_UNKNOWN
;
437 /* --------------------------------------------------------------------------
438 Performance Management
439 -------------------------------------------------------------------------- */
442 acpi_bus_get_perf_flags (
443 struct acpi_device
*device
)
448 device
->performance
.state
= ACPI_STATE_UNKNOWN
;
454 /* --------------------------------------------------------------------------
456 -------------------------------------------------------------------------- */
460 acpi_bus_generate_event (
461 struct acpi_device
*device
,
465 struct acpi_bus_event
*event
= NULL
;
466 //unsigned long flags = 0;
469 DPRINT1("acpi_bus_generate_event");
472 return_VALUE(AE_BAD_PARAMETER
);
474 /* drop event on the floor if no one's listening */
478 event
= ExAllocatePool(NonPagedPool
,sizeof(struct acpi_bus_event
));
482 sprintf(event
->device_class
, "%s", device
->pnp
.device_class
);
483 sprintf(event
->bus_id
, "%s", device
->pnp
.bus_id
);
487 //spin_lock_irqsave(&acpi_bus_event_lock, flags);
488 KeAcquireSpinLock(&acpi_bus_event_lock
, &OldIrql
);
489 list_add_tail(&event
->node
, &acpi_bus_event_list
);
490 KeReleaseSpinLock(&acpi_bus_event_lock
, OldIrql
);
491 //spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
493 KeSetEvent(&AcpiEventQueue
, IO_NO_INCREMENT
, FALSE
);
494 //wake_up_interruptible(&acpi_bus_event_queue);
500 acpi_bus_receive_event (
501 struct acpi_bus_event
*event
)
503 // unsigned long flags = 0;
504 struct acpi_bus_event
*entry
= NULL
;
507 //DECLARE_WAITQUEUE(wait, current);
509 DPRINT1("acpi_bus_receive_event");
512 return AE_BAD_PARAMETER
;
515 KeWaitForSingleObject(&AcpiEventQueue
,
521 KeClearEvent(&AcpiEventQueue
);
523 if (list_empty(&acpi_bus_event_list
))
524 return_VALUE(AE_NOT_FOUND
);
526 // spin_lock_irqsave(&acpi_bus_event_lock, flags);
527 KeAcquireSpinLock(&acpi_bus_event_lock
, &OldIrql
);
528 entry
= list_entry(acpi_bus_event_list
.next
, struct acpi_bus_event
, node
);
530 list_del(&entry
->node
);
531 KeReleaseSpinLock(&acpi_bus_event_lock
, OldIrql
);
532 // spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
535 return_VALUE(AE_NOT_FOUND
);
537 memcpy(event
, entry
, sizeof(struct acpi_bus_event
));
544 /* --------------------------------------------------------------------------
546 -------------------------------------------------------------------------- */
552 * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first)
553 * or up. Able to parse starting at any node in the namespace. Note that a
554 * callback return value of -249 will terminate the walk.
556 * @start: starting point
557 * callback: function to call for every device encountered while parsing
558 * direction: direction to parse (up or down)
559 * @data: context for this search operation
563 struct acpi_device
*start
,
564 acpi_bus_walk_callback callback
,
570 struct acpi_device
*device
= NULL
;
572 if (!start
|| !callback
)
573 return AE_BAD_PARAMETER
;
580 * Parse a given subtree (specified by start) in the given direction.
581 * Walking 'up' simply means that we execute the callback on leaf
582 * devices prior to their parents (useful for things like removing
583 * or powering down a subtree).
588 if (direction
== WALK_DOWN
)
589 if (-249 == callback(device
, level
, data
))
594 if (HAS_CHILDREN(device
)) {
595 device
= NODE_TO_DEVICE(device
->children
.next
);
600 if (direction
== WALK_UP
)
601 if (-249 == callback(device
, level
, data
))
606 if (HAS_SIBLINGS(device
)) {
607 device
= NODE_TO_DEVICE(device
->node
.next
);
611 /* Scope Exhausted - Find Next */
613 while ((device
= device
->parent
)) {
615 if (HAS_SIBLINGS(device
)) {
616 device
= NODE_TO_DEVICE(device
->node
.next
);
622 if ((direction
== WALK_UP
) && (result
== 0))
623 callback(start
, level
, data
);
629 /* --------------------------------------------------------------------------
630 Notification Handling
631 -------------------------------------------------------------------------- */
634 acpi_bus_check_device (ACPI_HANDLE handle
)
636 struct acpi_device
*device
;
637 ACPI_STATUS status
= 0;
638 struct acpi_device_status old_status
;
640 if (acpi_bus_get_device(handle
, &device
))
645 old_status
= device
->status
;
648 * Make sure this device's parent is present before we go about
649 * messing with the device.
651 if (device
->parent
&& !device
->parent
->status
.present
) {
652 device
->status
= device
->parent
->status
;
656 status
= acpi_bus_get_status(device
);
657 if (ACPI_FAILURE(status
))
660 if (STRUCT_TO_INT(old_status
) == STRUCT_TO_INT(device
->status
))
665 * Device Insertion/Removal
667 if ((device
->status
.present
) && !(old_status
.present
)) {
668 DPRINT("Device insertion detected\n");
669 /* TBD: Handle device insertion */
671 else if (!(device
->status
.present
) && (old_status
.present
)) {
672 DPRINT("Device removal detected\n");
673 /* TBD: Handle device removal */
680 acpi_bus_check_scope (ACPI_HANDLE handle
)
683 acpi_bus_check_device(handle
);
686 * TBD: Enumerate child devices within this device's scope and
687 * run acpi_bus_check_device()'s on them.
695 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
703 struct acpi_device
*device
= NULL
;
704 struct acpi_driver
*driver
;
706 DPRINT1("Notification %#02x to handle %p\n", type
, handle
);
708 //blocking_notifier_call_chain(&acpi_bus_notify_list,
709 // type, (void *)handle);
713 case ACPI_NOTIFY_BUS_CHECK
:
714 DPRINT("Received BUS CHECK notification for device [%s]\n",
716 acpi_bus_check_scope(handle
);
718 * TBD: We'll need to outsource certain events to non-ACPI
719 * drivers via the device manager (device.c).
723 case ACPI_NOTIFY_DEVICE_CHECK
:
724 DPRINT("Received DEVICE CHECK notification for device [%s]\n",
726 acpi_bus_check_device(handle
);
728 * TBD: We'll need to outsource certain events to non-ACPI
729 * drivers via the device manager (device.c).
733 case ACPI_NOTIFY_DEVICE_WAKE
:
734 DPRINT("Received DEVICE WAKE notification for device [%s]\n",
736 acpi_bus_check_device(handle
);
738 * TBD: We'll need to outsource certain events to non-ACPI
739 * drivers via the device manager (device.c).
743 case ACPI_NOTIFY_EJECT_REQUEST
:
744 DPRINT1("Received EJECT REQUEST notification for device [%s]\n",
749 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT
:
750 DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n",
752 /* TBD: Exactly what does 'light' mean? */
755 case ACPI_NOTIFY_FREQUENCY_MISMATCH
:
756 DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n",
761 case ACPI_NOTIFY_BUS_MODE_MISMATCH
:
762 DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n",
767 case ACPI_NOTIFY_POWER_FAULT
:
768 DPRINT1("Received POWER FAULT notification for device [%s]\n",
774 DPRINT1("Received unknown/unsupported notification [%08x]\n",
779 acpi_bus_get_device(handle
, &device
);
781 driver
= device
->driver
;
782 if (driver
&& driver
->ops
.notify
&&
783 (driver
->flags
& ACPI_DRIVER_ALL_NOTIFY_EVENTS
))
784 driver
->ops
.notify(device
, type
);
789 /* --------------------------------------------------------------------------
791 -------------------------------------------------------------------------- */
794 static LIST_HEAD(acpi_bus_drivers
);
795 //static DECLARE_MUTEX(acpi_bus_drivers_lock);
796 static FAST_MUTEX acpi_bus_drivers_lock
;
802 * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
803 * matches the specified driver's criteria.
807 struct acpi_device
*device
,
808 struct acpi_driver
*driver
)
812 if (device
->flags
.hardware_id
)
813 if (strstr(driver
->ids
, device
->pnp
.hardware_id
))
816 if (device
->flags
.compatible_ids
) {
817 ACPI_DEVICE_ID_LIST
*cid_list
= device
->pnp
.cid_list
;
820 /* compare multiple _CID entries against driver ids */
821 for (i
= 0; i
< cid_list
->Count
; i
++)
823 if (strstr(driver
->ids
, cid_list
->Ids
[i
].String
))
836 * acpi_bus_driver_init
837 * --------------------
838 * Used to initialize a device via its device driver. Called whenever a
839 * driver is bound to a device. Invokes the driver's add() and start() ops.
842 acpi_bus_driver_init (
843 struct acpi_device
*device
,
844 struct acpi_driver
*driver
)
848 if (!device
|| !driver
)
849 return_VALUE(AE_BAD_PARAMETER
);
851 if (!driver
->ops
.add
)
854 result
= driver
->ops
.add(device
);
856 device
->driver
= NULL
;
857 //acpi_driver_data(device) = NULL;
858 return_VALUE(result
);
861 device
->driver
= driver
;
864 * TBD - Configuration Management: Assign resources to device based
865 * upon possible configuration and currently allocated resources.
868 if (driver
->ops
.start
) {
869 result
= driver
->ops
.start(device
);
870 if (result
&& driver
->ops
.remove
)
871 driver
->ops
.remove(device
, ACPI_BUS_REMOVAL_NORMAL
);
872 return_VALUE(result
);
875 DPRINT("Driver successfully bound to device\n");
877 if (driver
->ops
.scan
) {
878 driver
->ops
.scan(device
);
888 * Callback for acpi_bus_walk() used to find devices that match a specific
889 * driver's criteria and then attach the driver.
893 struct acpi_device
*device
,
898 struct acpi_driver
*driver
= NULL
;
900 if (!device
|| !data
)
901 return_VALUE(AE_BAD_PARAMETER
);
903 driver
= (struct acpi_driver
*) data
;
908 if (!device
->status
.present
)
909 return_VALUE(AE_NOT_FOUND
);
911 result
= acpi_bus_match(device
, driver
);
913 return_VALUE(result
);
915 DPRINT("Found driver [%s] for device [%s]\n",
916 driver
->name
, device
->pnp
.bus_id
);
918 result
= acpi_bus_driver_init(device
, driver
);
920 return_VALUE(result
);
922 down(&acpi_bus_drivers_lock
);
923 ++driver
->references
;
924 up(&acpi_bus_drivers_lock
);
933 * Callback for acpi_bus_walk() used to find devices that match a specific
934 * driver's criteria and unattach the driver.
938 struct acpi_device
*device
,
943 struct acpi_driver
*driver
= (struct acpi_driver
*) data
;
945 if (!device
|| !driver
)
946 return_VALUE(AE_BAD_PARAMETER
);
948 if (device
->driver
!= driver
)
951 if (!driver
->ops
.remove
)
954 result
= driver
->ops
.remove(device
, ACPI_BUS_REMOVAL_NORMAL
);
956 return_VALUE(result
);
958 device
->driver
= NULL
;
959 acpi_driver_data(device
) = NULL
;
961 down(&acpi_bus_drivers_lock
);
962 driver
->references
--;
963 up(&acpi_bus_drivers_lock
);
970 * acpi_bus_find_driver
971 * --------------------
972 * Parses the list of registered drivers looking for a driver applicable for
973 * the specified device.
976 acpi_bus_find_driver (
977 struct acpi_device
*device
)
979 int result
= AE_NOT_FOUND
;
980 struct list_head
*entry
= NULL
;
981 struct acpi_driver
*driver
= NULL
;
983 if (!device
|| device
->driver
)
984 return_VALUE(AE_BAD_PARAMETER
);
986 down(&acpi_bus_drivers_lock
);
988 list_for_each(entry
, &acpi_bus_drivers
) {
990 driver
= list_entry(entry
, struct acpi_driver
, node
);
992 if (acpi_bus_match(device
, driver
))
995 result
= acpi_bus_driver_init(device
, driver
);
997 ++driver
->references
;
1002 up(&acpi_bus_drivers_lock
);
1004 return_VALUE(result
);
1009 * acpi_bus_register_driver
1010 * ------------------------
1011 * Registers a driver with the ACPI bus. Searches the namespace for all
1012 * devices that match the driver's criteria and binds.
1015 acpi_bus_register_driver (
1016 struct acpi_driver
*driver
)
1019 return_VALUE(AE_BAD_PARAMETER
);
1021 //if (acpi_disabled)
1022 // return_VALUE(AE_NOT_FOUND);
1024 down(&acpi_bus_drivers_lock
);
1025 list_add_tail(&driver
->node
, &acpi_bus_drivers
);
1026 up(&acpi_bus_drivers_lock
);
1028 acpi_bus_walk(acpi_root
, acpi_bus_attach
,
1031 return_VALUE(driver
->references
);
1036 * acpi_bus_unregister_driver
1037 * --------------------------
1038 * Unregisters a driver with the ACPI bus. Searches the namespace for all
1039 * devices that match the driver's criteria and unbinds.
1042 acpi_bus_unregister_driver (
1043 struct acpi_driver
*driver
)
1048 acpi_bus_walk(acpi_root
, acpi_bus_unattach
, WALK_UP
, driver
);
1050 if (driver
->references
)
1053 down(&acpi_bus_drivers_lock
);
1054 list_del(&driver
->node
);
1055 up(&acpi_bus_drivers_lock
);
1061 /* --------------------------------------------------------------------------
1063 -------------------------------------------------------------------------- */
1066 acpi_bus_get_flags (
1067 struct acpi_device
*device
)
1069 ACPI_STATUS status
= AE_OK
;
1070 ACPI_HANDLE temp
= NULL
;
1072 /* Presence of _STA indicates 'dynamic_status' */
1073 status
= AcpiGetHandle(device
->handle
, "_STA", &temp
);
1074 if (ACPI_SUCCESS(status
))
1075 device
->flags
.dynamic_status
= 1;
1077 /* Presence of _CID indicates 'compatible_ids' */
1078 status
= AcpiGetHandle(device
->handle
, "_CID", &temp
);
1079 if (ACPI_SUCCESS(status
))
1080 device
->flags
.compatible_ids
= 1;
1082 /* Presence of _RMV indicates 'removable' */
1083 status
= AcpiGetHandle(device
->handle
, "_RMV", &temp
);
1084 if (ACPI_SUCCESS(status
))
1085 device
->flags
.removable
= 1;
1087 /* Presence of _EJD|_EJ0 indicates 'ejectable' */
1088 status
= AcpiGetHandle(device
->handle
, "_EJD", &temp
);
1089 if (ACPI_SUCCESS(status
))
1090 device
->flags
.ejectable
= 1;
1092 status
= AcpiGetHandle(device
->handle
, "_EJ0", &temp
);
1093 if (ACPI_SUCCESS(status
))
1094 device
->flags
.ejectable
= 1;
1097 /* Presence of _LCK indicates 'lockable' */
1098 status
= AcpiGetHandle(device
->handle
, "_LCK", &temp
);
1099 if (ACPI_SUCCESS(status
))
1100 device
->flags
.lockable
= 1;
1102 /* Presence of _PS0|_PR0 indicates 'power manageable' */
1103 status
= AcpiGetHandle(device
->handle
, "_PS0", &temp
);
1104 if (ACPI_FAILURE(status
))
1105 status
= AcpiGetHandle(device
->handle
, "_PR0", &temp
);
1106 if (ACPI_SUCCESS(status
))
1107 device
->flags
.power_manageable
= 1;
1109 /* TBD: Peformance management */
1117 struct acpi_device
**child
,
1118 struct acpi_device
*parent
,
1123 ACPI_STATUS status
= AE_OK
;
1124 struct acpi_device
*device
= NULL
;
1125 char bus_id
[5] = {'?',0};
1127 ACPI_DEVICE_INFO
*info
;
1130 ACPI_DEVICE_ID_LIST
*cid_list
= NULL
;
1134 return_VALUE(AE_BAD_PARAMETER
);
1136 device
= ExAllocatePool(NonPagedPool
,sizeof(struct acpi_device
));
1138 DPRINT1("Memory allocation error\n");
1141 memset(device
, 0, sizeof(struct acpi_device
));
1143 device
->handle
= handle
;
1144 device
->parent
= parent
;
1149 * The device's Bus ID is simply the object name.
1150 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
1153 case ACPI_BUS_TYPE_SYSTEM
:
1154 sprintf(device
->pnp
.bus_id
, "%s", "ACPI");
1156 case ACPI_BUS_TYPE_POWER_BUTTON
:
1157 sprintf(device
->pnp
.bus_id
, "%s", "PWRF");
1159 case ACPI_BUS_TYPE_SLEEP_BUTTON
:
1160 sprintf(device
->pnp
.bus_id
, "%s", "SLPF");
1163 buffer
.Length
= sizeof(bus_id
);
1164 buffer
.Pointer
= bus_id
;
1165 AcpiGetName(handle
, ACPI_SINGLE_NAME
, &buffer
);
1168 /* Clean up trailing underscores (if any) */
1169 for (i
= 3; i
> 1; i
--) {
1170 if (bus_id
[i
] == '_')
1175 sprintf(device
->pnp
.bus_id
, "%s", bus_id
);
1176 buffer
.Pointer
= NULL
;
1183 * Get prior to calling acpi_bus_get_status() so we know whether
1184 * or not _STA is present. Note that we only look for object
1185 * handles -- cannot evaluate objects until we know the device is
1186 * present and properly initialized.
1188 result
= acpi_bus_get_flags(device
);
1195 * See if the device is present. We always assume that non-Device()
1196 * objects (e.g. thermal zones, power resources, processors, etc.) are
1197 * present, functioning, etc. (at least when parent object is present).
1198 * Note that _STA has a different meaning for some objects (e.g.
1199 * power resources) so we need to be careful how we use it.
1202 case ACPI_BUS_TYPE_DEVICE
:
1203 result
= acpi_bus_get_status(device
);
1208 STRUCT_TO_INT(device
->status
) = 0x0F;
1211 if (!device
->status
.present
) {
1219 * TBD: Synch with Core's enumeration/initialization process.
1223 * Hardware ID, Unique ID, & Bus Address
1224 * -------------------------------------
1227 case ACPI_BUS_TYPE_DEVICE
:
1228 status
= AcpiGetObjectInfo(handle
,&info
);
1229 if (ACPI_FAILURE(status
)) {
1230 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1231 "Error reading device info\n"));
1232 result
= AE_NOT_FOUND
;
1235 if (info
->Valid
& ACPI_VALID_HID
)
1236 hid
= info
->HardwareId
.String
;
1237 if (info
->Valid
& ACPI_VALID_UID
)
1238 uid
= info
->UniqueId
.String
;
1239 if (info
->Valid
& ACPI_VALID_CID
) {
1240 cid_list
= &info
->CompatibleIdList
;
1241 device
->pnp
.cid_list
= ExAllocatePool(NonPagedPool
,cid_list
->ListSize
);
1242 if (device
->pnp
.cid_list
)
1243 memcpy(device
->pnp
.cid_list
, cid_list
, cid_list
->ListSize
);
1245 DPRINT("Memory allocation error\n");
1247 if (info
->Valid
& ACPI_VALID_ADR
) {
1248 device
->pnp
.bus_address
= info
->Address
;
1249 device
->flags
.bus_address
= 1;
1252 case ACPI_BUS_TYPE_POWER
:
1253 hid
= ACPI_POWER_HID
;
1255 case ACPI_BUS_TYPE_PROCESSOR
:
1256 hid
= ACPI_PROCESSOR_HID
;
1258 case ACPI_BUS_TYPE_SYSTEM
:
1259 hid
= ACPI_SYSTEM_HID
;
1261 case ACPI_BUS_TYPE_THERMAL
:
1262 hid
= ACPI_THERMAL_HID
;
1264 case ACPI_BUS_TYPE_POWER_BUTTON
:
1265 hid
= ACPI_BUTTON_HID_POWER
;
1267 case ACPI_BUS_TYPE_POWER_BUTTONF
:
1268 hid
= ACPI_BUTTON_HID_POWERF
;
1270 case ACPI_BUS_TYPE_SLEEP_BUTTON
:
1271 hid
= ACPI_BUTTON_HID_SLEEP
;
1273 case ACPI_BUS_TYPE_SLEEP_BUTTONF
:
1274 hid
= ACPI_BUTTON_HID_SLEEPF
;
1281 * Fix for the system root bus device -- the only root-level device.
1283 if ((parent
== ACPI_ROOT_OBJECT
) && (type
== ACPI_BUS_TYPE_DEVICE
)) {
1285 sprintf(device
->pnp
.device_name
, "%s", ACPI_BUS_DEVICE_NAME
);
1286 sprintf(device
->pnp
.device_class
, "%s", ACPI_BUS_CLASS
);
1290 sprintf(device
->pnp
.hardware_id
, "%s", hid
);
1291 device
->flags
.hardware_id
= 1;
1294 sprintf(device
->pnp
.unique_id
, "%s", uid
);
1295 device
->flags
.unique_id
= 1;
1299 * If we called get_object_info, we now are finished with the buffer,
1300 * so we can free it.
1302 //if (buffer.Pointer)
1303 //AcpiOsFree(buffer.Pointer);
1309 if (device
->flags
.power_manageable
) {
1310 result
= acpi_bus_get_power_flags(device
);
1316 * Performance Management
1317 * ----------------------
1319 if (device
->flags
.performance_manageable
) {
1320 result
= acpi_bus_get_perf_flags(device
);
1328 * Attach this 'struct acpi_device' to the ACPI object. This makes
1329 * resolutions from handle->device very efficient. Note that we need
1330 * to be careful with fixed-feature devices as they all attach to the
1334 case ACPI_BUS_TYPE_POWER_BUTTON
:
1335 case ACPI_BUS_TYPE_POWER_BUTTONF
:
1336 case ACPI_BUS_TYPE_SLEEP_BUTTON
:
1337 case ACPI_BUS_TYPE_SLEEP_BUTTONF
:
1340 status
= AcpiAttachData(device
->handle
,
1341 acpi_bus_data_handler
, device
);
1344 if (ACPI_FAILURE(status
)) {
1345 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1346 "Error attaching device data\n"));
1347 result
= AE_NOT_FOUND
;
1354 * Link this device to its parent and siblings.
1356 INIT_LIST_HEAD(&device
->children
);
1357 if (!device
->parent
)
1358 INIT_LIST_HEAD(&device
->node
);
1360 list_add_tail(&device
->node
, &device
->parent
->children
);
1363 * Global Device Hierarchy:
1364 * ------------------------
1365 * Register this device with the global device hierarchy.
1367 acpi_device_register(device
, parent
);
1370 * Bind _ADR-Based Devices
1371 * -----------------------
1372 * If there's a a bus address (_ADR) then we utilize the parent's
1373 * 'bind' function (if exists) to bind the ACPI- and natively-
1374 * enumerated device representations.
1376 if (device
->flags
.bus_address
) {
1377 if (device
->parent
&& device
->parent
->ops
.bind
)
1378 device
->parent
->ops
.bind(device
);
1382 * Locate & Attach Driver
1383 * ----------------------
1384 * If there's a hardware id (_HID) or compatible ids (_CID) we check
1385 * to see if there's a driver installed for this kind of device. Note
1386 * that drivers can install before or after a device is enumerated.
1388 * TBD: Assumes LDM provides driver hot-plug capability.
1390 if (device
->flags
.hardware_id
|| device
->flags
.compatible_ids
)
1391 acpi_bus_find_driver(device
);
1395 if (device
->pnp
.cid_list
) {
1396 ExFreePool(device
->pnp
.cid_list
);
1399 return_VALUE(result
);
1409 struct acpi_device
*device
,
1414 return_VALUE(AE_NOT_FOUND
);
1416 acpi_device_unregister(device
);
1418 if (device
&& device
->pnp
.cid_list
)
1419 ExFreePool(device
->pnp
.cid_list
);
1430 struct acpi_device
*start
)
1432 ACPI_STATUS status
= AE_OK
;
1433 struct acpi_device
*parent
= NULL
;
1434 struct acpi_device
*child
= NULL
;
1435 ACPI_HANDLE phandle
= 0;
1436 ACPI_HANDLE chandle
= 0;
1437 ACPI_OBJECT_TYPE type
= 0;
1441 return_VALUE(AE_BAD_PARAMETER
);
1444 phandle
= start
->handle
;
1447 * Parse through the ACPI namespace, identify all 'devices', and
1448 * create a new 'struct acpi_device' for each.
1450 while ((level
> 0) && parent
) {
1452 status
= AcpiGetNextObject(ACPI_TYPE_ANY
, phandle
,
1456 * If this scope is exhausted then move our way back up.
1458 if (ACPI_FAILURE(status
)) {
1461 AcpiGetParent(phandle
, &phandle
);
1463 parent
= parent
->parent
;
1467 status
= AcpiGetType(chandle
, &type
);
1468 if (ACPI_FAILURE(status
))
1472 * If this is a scope object then parse it (depth-first).
1474 if (type
== ACPI_TYPE_LOCAL_SCOPE
) {
1482 * We're only interested in objects that we consider 'devices'.
1485 case ACPI_TYPE_DEVICE
:
1486 type
= ACPI_BUS_TYPE_DEVICE
;
1488 case ACPI_TYPE_PROCESSOR
:
1489 type
= ACPI_BUS_TYPE_PROCESSOR
;
1491 case ACPI_TYPE_THERMAL
:
1492 type
= ACPI_BUS_TYPE_THERMAL
;
1494 case ACPI_TYPE_POWER
:
1495 type
= ACPI_BUS_TYPE_POWER
;
1501 status
= acpi_bus_add(&child
, parent
, chandle
, type
);
1502 if (ACPI_FAILURE(status
))
1506 * If the device is present, enabled, and functioning then
1507 * parse its scope (depth-first). Note that we need to
1508 * represent absent devices to facilitate PnP notifications
1509 * -- but only the subtree head (not all of its children,
1510 * which will be enumerated when the parent is inserted).
1512 * TBD: Need notifications and other detection mechanisms
1513 * in place before we can fully implement this.
1515 if (child
->status
.present
) {
1516 status
= AcpiGetNextObject(ACPI_TYPE_ANY
, chandle
,
1518 if (ACPI_SUCCESS(status
)) {
1532 acpi_bus_scan_fixed (
1533 struct acpi_device
*root
)
1536 struct acpi_device
*device
= NULL
;
1539 return_VALUE(AE_NOT_FOUND
);
1541 /* If ACPI_FADT_POWER_BUTTON is set, then a control
1542 * method power button is present. Otherwise, a fixed
1543 * power button is present.
1545 if (AcpiGbl_FADT
.Flags
& ACPI_FADT_POWER_BUTTON
)
1546 result
= acpi_bus_add(&device
, acpi_root
,
1547 NULL
, ACPI_BUS_TYPE_POWER_BUTTON
);
1550 /* Enable the fixed power button so we get notified if it is pressed */
1551 AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE
, 1);
1553 result
= acpi_bus_add(&device
, acpi_root
,
1554 NULL
, ACPI_BUS_TYPE_POWER_BUTTONF
);
1557 /* This one is a bit more complicated and we do it wrong
1558 * right now. If ACPI_FADT_SLEEP_BUTTON is set but no
1559 * device object is present then no sleep button is present, but
1560 * if the flags is clear and there is no device object then it is
1561 * a fixed sleep button. If the flag is set and there is a device object
1562 * the we have a control method button just like above.
1564 if (AcpiGbl_FADT
.Flags
& ACPI_FADT_SLEEP_BUTTON
)
1565 result
= acpi_bus_add(&device
, acpi_root
,
1566 NULL
, ACPI_BUS_TYPE_SLEEP_BUTTON
);
1569 /* Enable the fixed sleep button so we get notified if it is pressed */
1570 AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE
, 1);
1572 result
= acpi_bus_add(&device
, acpi_root
,
1573 NULL
, ACPI_BUS_TYPE_SLEEP_BUTTONF
);
1576 return_VALUE(result
);
1580 /* --------------------------------------------------------------------------
1581 Initialization/Cleanup
1582 -------------------------------------------------------------------------- */
1585 acpi_bus_init (void)
1588 ACPI_STATUS status
= AE_OK
;
1590 DPRINT("acpi_bus_init");
1592 status
= AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION
);
1593 if (ACPI_FAILURE(status
)) {
1594 DPRINT1("Unable to start the ACPI Interpreter\n");
1599 * ACPI 2.0 requires the EC driver to be loaded and work before
1600 * the EC device is found in the namespace. This is accomplished
1601 * by looking for the ECDT table, and getting the EC parameters out
1604 //result = acpi_ec_ecdt_probe();
1605 /* Ignore result. Not having an ECDT is not fatal. */
1607 status
= AcpiInitializeObjects(ACPI_NO_DEVICE_INIT
| ACPI_NO_OBJECT_INIT
);
1608 if (ACPI_FAILURE(status
)) {
1609 DPRINT1("Unable to initialize ACPI objects\n");
1614 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
1615 * is necessary to enable it as early as possible.
1617 //acpi_boot_ec_enable();
1619 /* Initialize sleep structures */
1620 //acpi_sleep_init();
1623 * Register the for all standard device notifications.
1625 status
= AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT
, ACPI_SYSTEM_NOTIFY
, &acpi_bus_notify
, NULL
);
1626 if (ACPI_FAILURE(status
)) {
1627 DPRINT1("Unable to register for device notifications\n");
1628 result
= AE_NOT_FOUND
;
1633 * Create the root device in the bus's device tree
1635 result
= acpi_bus_add(&acpi_root
, NULL
, ACPI_ROOT_OBJECT
,
1636 ACPI_BUS_TYPE_SYSTEM
);
1642 * Enumerate devices in the ACPI namespace.
1644 result
= acpi_bus_scan_fixed(acpi_root
);
1646 DPRINT1("acpi_bus_scan_fixed failed\n");
1647 result
= acpi_bus_scan(acpi_root
);
1649 DPRINT1("acpi_bus_scan failed\n");
1653 /* Mimic structured exception handling */
1655 AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT
,
1656 ACPI_SYSTEM_NOTIFY
, &acpi_bus_notify
);
1659 return_VALUE(AE_NOT_FOUND
);
1663 acpi_bus_exit (void)
1665 ACPI_STATUS status
= AE_OK
;
1667 DPRINT("acpi_bus_exit");
1669 status
= AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT
,
1670 ACPI_SYSTEM_NOTIFY
, acpi_bus_notify
);
1671 if (ACPI_FAILURE(status
))
1672 DPRINT1("Error removing notify handler\n");
1674 #ifdef CONFIG_ACPI_PCI
1675 acpi_pci_root_exit();
1676 acpi_pci_link_exit();
1678 #ifdef CONFIG_ACPI_EC
1681 //acpi_power_exit();
1684 acpi_bus_remove(acpi_root
, ACPI_BUS_REMOVAL_NORMAL
);
1686 status
= AcpiTerminate();
1687 if (ACPI_FAILURE(status
))
1688 DPRINT1("Unable to terminate the ACPI Interpreter\n");
1690 DPRINT1("Interpreter disabled\n");
1701 DPRINT("acpi_init");
1703 DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION
);
1705 KeInitializeSpinLock(&acpi_bus_event_lock
);
1706 KeInitializeEvent(&AcpiEventQueue
, NotificationEvent
, FALSE
);
1707 ExInitializeFastMutex(&acpi_bus_drivers_lock
);
1709 result
= acpi_bus_init();
1712 //pci_mmcfg_late_init();
1713 //if (!(pm_flags & PM_APM))
1714 // pm_flags |= PM_ACPI;
1716 //DPRINT1("APM is already active, exiting\n");
1724 * If the laptop falls into the DMI check table, the power state check
1725 * will be disabled in the course of device power transistion.
1727 //dmi_check_system(power_nocheck_dmi_table);
1730 * Install drivers required for proper enumeration of the
1733 acpi_system_init(); /* ACPI System */
1734 acpi_power_init(); /* ACPI Bus Power Management */
1736 //acpi_ec_init(); /* ACPI Embedded Controller */
1737 #ifdef CONFIG_ACPI_PCI
1738 if (!acpi_pci_disabled
) {
1739 acpi_pci_link_init(); /* ACPI PCI Interrupt Link */
1740 acpi_pci_root_init(); /* ACPI PCI Root Bridge */
1746 //acpi_power_init();
1747 //acpi_system_init();
1748 //acpi_debug_init();
1749 //acpi_sleep_proc_init();
1750 //acpi_wakeup_device_init();
1759 DPRINT("acpi_exit");