[ACPI]
[reactos.git] / reactos / drivers / bus / acpi / busmgr / bus.c
1 /*
2 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
3 *
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
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.
12 *
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.
17 *
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.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25 /*
26 * Modified for ReactOS and latest ACPICA
27 * Copyright (C)2009 Samuel Serapion
28 */
29
30 #include <ntddk.h>
31
32 #include <acpi.h>
33 #include <acpi_bus.h>
34 #include <acpi_drivers.h>
35 #include <glue.h>
36
37 #define NDEBUG
38 #include <debug.h>
39
40 #define _COMPONENT ACPI_BUS_COMPONENT
41 ACPI_MODULE_NAME ("acpi_bus")
42
43 #define WALK_UP 0
44 #define WALK_DOWN 1
45
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))
50
51 int event_is_open;
52 extern void acpi_pic_sci_set_trigger(unsigned int irq, UINT16 trigger);
53
54 typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*);
55
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;
61 KDPC event_dpc;
62
63 int ProcessorCount, PowerDeviceCount, PowerButtonCount, FixedPowerButtonCount;
64 int FixedSleepButtonCount, SleepButtonCount, ThermalZoneCount;
65
66 static int
67 acpi_device_register (
68 struct acpi_device *device,
69 struct acpi_device *parent)
70 {
71 int result = 0;
72
73 if (!device)
74 return_VALUE(AE_BAD_PARAMETER);
75
76 return_VALUE(result);
77 }
78
79
80 static int
81 acpi_device_unregister (
82 struct acpi_device *device)
83 {
84 if (!device)
85 return_VALUE(AE_BAD_PARAMETER);
86
87 #ifdef CONFIG_LDM
88 put_device(&device->dev);
89 #endif /*CONFIG_LDM*/
90
91 return_VALUE(0);
92 }
93
94
95 /* --------------------------------------------------------------------------
96 Device Management
97 -------------------------------------------------------------------------- */
98
99 void
100 acpi_bus_data_handler (
101 ACPI_HANDLE handle,
102 void *context)
103 {
104 DPRINT1("acpi_bus_data_handler not implemented");
105
106 /* TBD */
107
108 return;
109 }
110
111
112 int
113 acpi_bus_get_device (
114 ACPI_HANDLE handle,
115 struct acpi_device **device)
116 {
117 ACPI_STATUS status = AE_OK;
118
119 if (!device)
120 return_VALUE(AE_BAD_PARAMETER);
121
122 /* TBD: Support fixed-feature devices */
123
124 status = AcpiGetData(handle, acpi_bus_data_handler, (void**)device);
125 if (ACPI_FAILURE(status) || !*device) {
126 DPRINT( "Error getting context for object [%p]\n",
127 handle);
128 return_VALUE(AE_NOT_FOUND);
129 }
130
131 return 0;
132 }
133
134 ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle,
135 unsigned long long *sta)
136 {
137 ACPI_STATUS status;
138
139 status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
140 if (ACPI_SUCCESS(status))
141 return AE_OK;
142
143 if (status == AE_NOT_FOUND) {
144 *sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
145 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
146 return AE_OK;
147 }
148 return status;
149 }
150
151 int
152 acpi_bus_get_status (
153 struct acpi_device *device)
154 {
155 ACPI_STATUS status;
156 unsigned long long sta;
157
158 status = acpi_bus_get_status_handle(device->handle, &sta);
159 if (ACPI_FAILURE(status))
160 return -1;
161
162 STRUCT_TO_INT(device->status) = (int) sta;
163
164 if (device->status.functional && !device->status.present) {
165 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
166 "functional but not present;\n",
167 device->pnp.bus_id,
168 (UINT32) STRUCT_TO_INT(device->status)));
169 }
170
171 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
172 device->pnp.bus_id,
173 (UINT32) STRUCT_TO_INT(device->status)));
174 return 0;
175 }
176
177 void acpi_bus_private_data_handler(ACPI_HANDLE handle,
178 void *context)
179 {
180 return;
181 }
182
183 int acpi_bus_get_private_data(ACPI_HANDLE handle, void **data)
184 {
185 ACPI_STATUS status = AE_OK;
186
187 if (!*data)
188 return -1;
189
190 status = AcpiGetData(handle, acpi_bus_private_data_handler, data);
191 if (ACPI_FAILURE(status) || !*data) {
192 DPRINT("No context for object [%p]\n", handle);
193 return -1;
194 }
195
196 return 0;
197 }
198 /* --------------------------------------------------------------------------
199 Power Management
200 -------------------------------------------------------------------------- */
201
202 int
203 acpi_bus_get_power (
204 ACPI_HANDLE handle,
205 int *state)
206 {
207 int result = 0;
208 ACPI_STATUS status = 0;
209 struct acpi_device *device = NULL;
210 unsigned long long psc = 0;
211
212 result = acpi_bus_get_device(handle, &device);
213 if (result)
214 return_VALUE(result);
215
216 *state = ACPI_STATE_UNKNOWN;
217
218 if (!device->flags.power_manageable) {
219 /* TBD: Non-recursive algorithm for walking up hierarchy */
220 if (device->parent)
221 *state = device->parent->power.state;
222 else
223 *state = ACPI_STATE_D0;
224 }
225 else {
226 /*
227 * Get the device's power state either directly (via _PSC) or
228 * indirectly (via power resources).
229 */
230 if (device->power.flags.explicit_get) {
231 status = acpi_evaluate_integer(device->handle, "_PSC",
232 NULL, &psc);
233 if (ACPI_FAILURE(status))
234 return_VALUE(AE_NOT_FOUND);
235 device->power.state = (int) psc;
236 }
237 else if (device->power.flags.power_resources) {
238 result = acpi_power_get_inferred_state(device);
239 if (result)
240 return_VALUE(result);
241 }
242
243 *state = device->power.state;
244 }
245
246 DPRINT("Device [%s] power state is D%d\n",
247 device->pnp.bus_id, device->power.state);
248
249 return_VALUE(0);
250 }
251
252
253 int
254 acpi_bus_set_power (
255 ACPI_HANDLE handle,
256 int state)
257 {
258 int result = 0;
259 ACPI_STATUS status = AE_OK;
260 struct acpi_device *device = NULL;
261 char object_name[5] = {'_','P','S','0'+state,'\0'};
262
263
264 result = acpi_bus_get_device(handle, &device);
265 if (result)
266 return_VALUE(result);
267
268 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
269 return_VALUE(AE_BAD_PARAMETER);
270
271 /* Make sure this is a valid target state */
272
273 if (!device->flags.power_manageable) {
274 DPRINT1( "Device is not power manageable\n");
275 return_VALUE(AE_NOT_FOUND);
276 }
277 /*
278 * Get device's current power state
279 */
280 //if (!acpi_power_nocheck) {
281 /*
282 * Maybe the incorrect power state is returned on the bogus
283 * bios, which is different with the real power state.
284 * For example: the bios returns D0 state and the real power
285 * state is D3. OS expects to set the device to D0 state. In
286 * such case if OS uses the power state returned by the BIOS,
287 * the device can't be transisted to the correct power state.
288 * So if the acpi_power_nocheck is set, it is unnecessary to
289 * get the power state by calling acpi_bus_get_power.
290 */
291 acpi_bus_get_power(device->handle, &device->power.state);
292 //}
293
294 if ((state == device->power.state) && !device->flags.force_power_state) {
295 DPRINT1("Device is already at D%d\n", state);
296 return 0;
297 }
298 if (!device->power.states[state].flags.valid) {
299 DPRINT1( "Device does not support D%d\n", state);
300 return AE_NOT_FOUND;
301 }
302 if (device->parent && (state < device->parent->power.state)) {
303 DPRINT1( "Cannot set device to a higher-powered state than parent\n");
304 return AE_NOT_FOUND;
305 }
306
307 /*
308 * Transition Power
309 * ----------------
310 * On transitions to a high-powered state we first apply power (via
311 * power resources) then evalute _PSx. Conversly for transitions to
312 * a lower-powered state.
313 */
314 if (state < device->power.state) {
315 if (device->power.flags.power_resources) {
316 result = acpi_power_transition(device, state);
317 if (result)
318 goto end;
319 }
320 if (device->power.states[state].flags.explicit_set) {
321 status = AcpiEvaluateObject(device->handle,
322 object_name, NULL, NULL);
323 if (ACPI_FAILURE(status)) {
324 result = AE_NOT_FOUND;
325 goto end;
326 }
327 }
328 }
329 else {
330 if (device->power.states[state].flags.explicit_set) {
331 status = AcpiEvaluateObject(device->handle,
332 object_name, NULL, NULL);
333 if (ACPI_FAILURE(status)) {
334 result = AE_NOT_FOUND;
335 goto end;
336 }
337 }
338 if (device->power.flags.power_resources) {
339 result = acpi_power_transition(device, state);
340 if (result)
341 goto end;
342 }
343 }
344
345 end:
346 if (result)
347 DPRINT( "Error transitioning device [%s] to D%d\n",
348 device->pnp.bus_id, state);
349 else
350 DPRINT("Device [%s] transitioned to D%d\n",
351 device->pnp.bus_id, state);
352
353 return result;
354 }
355
356 BOOLEAN acpi_bus_power_manageable(ACPI_HANDLE handle)
357 {
358 struct acpi_device *device;
359 int result;
360
361 result = acpi_bus_get_device(handle, &device);
362 return result ? 0 : device->flags.power_manageable;
363 }
364
365 BOOLEAN acpi_bus_can_wakeup(ACPI_HANDLE handle)
366 {
367 struct acpi_device *device;
368 int result;
369
370 result = acpi_bus_get_device(handle, &device);
371 return result ? 0 : device->wakeup.flags.valid;
372 }
373
374 static int
375 acpi_bus_get_power_flags (
376 struct acpi_device *device)
377 {
378 ACPI_STATUS status = 0;
379 ACPI_HANDLE handle = 0;
380 UINT32 i = 0;
381
382 if (!device)
383 return AE_NOT_FOUND;
384
385 /*
386 * Power Management Flags
387 */
388 status = AcpiGetHandle(device->handle, "_PSC", &handle);
389 if (ACPI_SUCCESS(status))
390 device->power.flags.explicit_get = 1;
391 status = AcpiGetHandle(device->handle, "_IRC", &handle);
392 if (ACPI_SUCCESS(status))
393 device->power.flags.inrush_current = 1;
394 status = AcpiGetHandle(device->handle, "_PRW", &handle);
395 if (ACPI_SUCCESS(status))
396 device->flags.wake_capable = 1;
397
398 /*
399 * Enumerate supported power management states
400 */
401 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
402 struct acpi_device_power_state *ps = &device->power.states[i];
403 char object_name[5] = {'_','P','R','0'+i,'\0'};
404
405 /* Evaluate "_PRx" to se if power resources are referenced */
406 status = acpi_evaluate_reference(device->handle, object_name, NULL,
407 &ps->resources);
408 if (ACPI_SUCCESS(status) && ps->resources.count) {
409 device->power.flags.power_resources = 1;
410 ps->flags.valid = 1;
411 }
412
413 /* Evaluate "_PSx" to see if we can do explicit sets */
414 object_name[2] = 'S';
415 status = AcpiGetHandle(device->handle, object_name, &handle);
416 if (ACPI_SUCCESS(status)) {
417 ps->flags.explicit_set = 1;
418 ps->flags.valid = 1;
419 }
420
421 /* State is valid if we have some power control */
422 if (ps->resources.count || ps->flags.explicit_set)
423 ps->flags.valid = 1;
424
425 ps->power = -1; /* Unknown - driver assigned */
426 ps->latency = -1; /* Unknown - driver assigned */
427 }
428
429 /* Set defaults for D0 and D3 states (always valid) */
430 device->power.states[ACPI_STATE_D0].flags.valid = 1;
431 device->power.states[ACPI_STATE_D0].power = 100;
432 device->power.states[ACPI_STATE_D3].flags.valid = 1;
433 device->power.states[ACPI_STATE_D3].power = 0;
434
435 device->power.state = ACPI_STATE_UNKNOWN;
436
437 return 0;
438 }
439
440 /* --------------------------------------------------------------------------
441 Performance Management
442 -------------------------------------------------------------------------- */
443
444 static int
445 acpi_bus_get_perf_flags (
446 struct acpi_device *device)
447 {
448 if (!device)
449 return AE_NOT_FOUND;
450
451 device->performance.state = ACPI_STATE_UNKNOWN;
452
453 return 0;
454 }
455
456
457 /* --------------------------------------------------------------------------
458 Event Management
459 -------------------------------------------------------------------------- */
460
461 void
462 NTAPI
463 acpi_bus_generate_event_dpc(PKDPC Dpc,
464 PVOID DeferredContext,
465 PVOID SystemArgument1,
466 PVOID SystemArgument2)
467 {
468 struct acpi_bus_event *event;
469 struct acpi_device *device = SystemArgument1;
470 ULONG_PTR TypeData = (ULONG_PTR)SystemArgument2;
471 KIRQL OldIrql;
472
473 event = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_bus_event), 'IPCA');
474 if (!event)
475 return;
476
477 sprintf(event->device_class, "%s", device->pnp.device_class);
478 sprintf(event->bus_id, "%s", device->pnp.bus_id);
479 event->type = (TypeData & 0xFF000000) >> 24;
480 event->data = (TypeData & 0x00FFFFFF);
481
482 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
483 list_add_tail(&event->node, &acpi_bus_event_list);
484 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
485
486 KeSetEvent(&AcpiEventQueue, IO_NO_INCREMENT, FALSE);
487 }
488
489 int
490 acpi_bus_generate_event (
491 struct acpi_device *device,
492 UINT8 type,
493 int data)
494 {
495 ULONG_PTR TypeData = 0;
496
497 DPRINT("acpi_bus_generate_event");
498
499 if (!device)
500 return_VALUE(AE_BAD_PARAMETER);
501
502 /* drop event on the floor if no one's listening */
503 if (!event_is_open)
504 return_VALUE(0);
505
506 /* Data shouldn't even get near 24 bits */
507 ASSERT(!(data & 0xFF000000));
508
509 TypeData = data;
510 TypeData |= type << 24;
511
512 KeInsertQueueDpc(&event_dpc, device, (PVOID)TypeData);
513
514 return_VALUE(0);
515 }
516
517 int
518 acpi_bus_receive_event (
519 struct acpi_bus_event *event)
520 {
521 // unsigned long flags = 0;
522 struct acpi_bus_event *entry = NULL;
523 KIRQL OldIrql;
524
525 //DECLARE_WAITQUEUE(wait, current);
526
527 DPRINT("acpi_bus_receive_event");
528
529 if (!event)
530 return AE_BAD_PARAMETER;
531
532 event_is_open++;
533 KeWaitForSingleObject(&AcpiEventQueue,
534 Executive,
535 KernelMode,
536 FALSE,
537 NULL);
538 event_is_open--;
539 KeClearEvent(&AcpiEventQueue);
540
541 if (list_empty(&acpi_bus_event_list))
542 return_VALUE(AE_NOT_FOUND);
543
544 // spin_lock_irqsave(&acpi_bus_event_lock, flags);
545 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
546 entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
547 if (entry)
548 list_del(&entry->node);
549 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
550 // spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
551
552 if (!entry)
553 return_VALUE(AE_NOT_FOUND);
554
555 memcpy(event, entry, sizeof(struct acpi_bus_event));
556
557 ExFreePoolWithTag(entry, 'IPCA');
558 return_VALUE(0);
559 }
560
561
562 /* --------------------------------------------------------------------------
563 Namespace Management
564 -------------------------------------------------------------------------- */
565
566
567 /**
568 * acpi_bus_walk
569 * -------------
570 * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first)
571 * or up. Able to parse starting at any node in the namespace. Note that a
572 * callback return value of -249 will terminate the walk.
573 *
574 * @start: starting point
575 * callback: function to call for every device encountered while parsing
576 * direction: direction to parse (up or down)
577 * @data: context for this search operation
578 */
579 static int
580 acpi_bus_walk (
581 struct acpi_device *start,
582 acpi_bus_walk_callback callback,
583 int direction,
584 void *data)
585 {
586 int result = 0;
587 int level = 0;
588 struct acpi_device *device = NULL;
589
590 if (!start || !callback)
591 return AE_BAD_PARAMETER;
592
593 device = start;
594
595 /*
596 * Parse Namespace
597 * ---------------
598 * Parse a given subtree (specified by start) in the given direction.
599 * Walking 'up' simply means that we execute the callback on leaf
600 * devices prior to their parents (useful for things like removing
601 * or powering down a subtree).
602 */
603
604 while (device) {
605
606 if (direction == WALK_DOWN)
607 if (-249 == callback(device, level, data))
608 break;
609
610 /* Depth First */
611
612 if (HAS_CHILDREN(device)) {
613 device = NODE_TO_DEVICE(device->children.next);
614 ++level;
615 continue;
616 }
617
618 if (direction == WALK_UP)
619 if (-249 == callback(device, level, data))
620 break;
621
622 /* Now Breadth */
623
624 if (HAS_SIBLINGS(device)) {
625 device = NODE_TO_DEVICE(device->node.next);
626 continue;
627 }
628
629 /* Scope Exhausted - Find Next */
630
631 while ((device = device->parent)) {
632 --level;
633 if (HAS_SIBLINGS(device)) {
634 device = NODE_TO_DEVICE(device->node.next);
635 break;
636 }
637 }
638 }
639
640 if ((direction == WALK_UP) && (result == 0))
641 callback(start, level, data);
642
643 return result;
644 }
645
646
647 /* --------------------------------------------------------------------------
648 Notification Handling
649 -------------------------------------------------------------------------- */
650
651 static void
652 acpi_bus_check_device (ACPI_HANDLE handle)
653 {
654 struct acpi_device *device;
655 ACPI_STATUS status = 0;
656 struct acpi_device_status old_status;
657
658 if (acpi_bus_get_device(handle, &device))
659 return;
660 if (!device)
661 return;
662
663 old_status = device->status;
664
665 /*
666 * Make sure this device's parent is present before we go about
667 * messing with the device.
668 */
669 if (device->parent && !device->parent->status.present) {
670 device->status = device->parent->status;
671 return;
672 }
673
674 status = acpi_bus_get_status(device);
675 if (ACPI_FAILURE(status))
676 return;
677
678 if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
679 return;
680
681
682 /*
683 * Device Insertion/Removal
684 */
685 if ((device->status.present) && !(old_status.present)) {
686 DPRINT("Device insertion detected\n");
687 /* TBD: Handle device insertion */
688 }
689 else if (!(device->status.present) && (old_status.present)) {
690 DPRINT("Device removal detected\n");
691 /* TBD: Handle device removal */
692 }
693
694 }
695
696
697 static void
698 acpi_bus_check_scope (ACPI_HANDLE handle)
699 {
700 /* Status Change? */
701 acpi_bus_check_device(handle);
702
703 /*
704 * TBD: Enumerate child devices within this device's scope and
705 * run acpi_bus_check_device()'s on them.
706 */
707 }
708
709
710 /**
711 * acpi_bus_notify
712 * ---------------
713 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
714 */
715 static void
716 acpi_bus_notify (
717 ACPI_HANDLE handle,
718 UINT32 type,
719 void *data)
720 {
721 struct acpi_device *device = NULL;
722 struct acpi_driver *driver;
723
724 DPRINT1("Notification %#02x to handle %p\n", type, handle);
725
726 //blocking_notifier_call_chain(&acpi_bus_notify_list,
727 // type, (void *)handle);
728
729 switch (type) {
730
731 case ACPI_NOTIFY_BUS_CHECK:
732 DPRINT("Received BUS CHECK notification for device [%s]\n",
733 device->pnp.bus_id);
734 acpi_bus_check_scope(handle);
735 /*
736 * TBD: We'll need to outsource certain events to non-ACPI
737 * drivers via the device manager (device.c).
738 */
739 break;
740
741 case ACPI_NOTIFY_DEVICE_CHECK:
742 DPRINT("Received DEVICE CHECK notification for device [%s]\n",
743 device->pnp.bus_id);
744 acpi_bus_check_device(handle);
745 /*
746 * TBD: We'll need to outsource certain events to non-ACPI
747 * drivers via the device manager (device.c).
748 */
749 break;
750
751 case ACPI_NOTIFY_DEVICE_WAKE:
752 DPRINT("Received DEVICE WAKE notification for device [%s]\n",
753 device->pnp.bus_id);
754 acpi_bus_check_device(handle);
755 /*
756 * TBD: We'll need to outsource certain events to non-ACPI
757 * drivers via the device manager (device.c).
758 */
759 break;
760
761 case ACPI_NOTIFY_EJECT_REQUEST:
762 DPRINT1("Received EJECT REQUEST notification for device [%s]\n",
763 device->pnp.bus_id);
764 /* TBD */
765 break;
766
767 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
768 DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n",
769 device->pnp.bus_id);
770 /* TBD: Exactly what does 'light' mean? */
771 break;
772
773 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
774 DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n",
775 device->pnp.bus_id);
776 /* TBD */
777 break;
778
779 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
780 DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n",
781 device->pnp.bus_id);
782 /* TBD */
783 break;
784
785 case ACPI_NOTIFY_POWER_FAULT:
786 DPRINT1("Received POWER FAULT notification for device [%s]\n",
787 device->pnp.bus_id);
788 /* TBD */
789 break;
790
791 default:
792 DPRINT1("Received unknown/unsupported notification [%08x]\n",
793 type);
794 break;
795 }
796
797 acpi_bus_get_device(handle, &device);
798 if (device) {
799 driver = device->driver;
800 if (driver && driver->ops.notify &&
801 (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
802 driver->ops.notify(device, type);
803 }
804 }
805
806
807 /* --------------------------------------------------------------------------
808 Driver Management
809 -------------------------------------------------------------------------- */
810
811
812 static LIST_HEAD(acpi_bus_drivers);
813 //static DECLARE_MUTEX(acpi_bus_drivers_lock);
814 static FAST_MUTEX acpi_bus_drivers_lock;
815
816
817 /**
818 * acpi_bus_match
819 * --------------
820 * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
821 * matches the specified driver's criteria.
822 */
823 static int
824 acpi_bus_match (
825 struct acpi_device *device,
826 struct acpi_driver *driver)
827 {
828 int error = 0;
829
830 if (device->flags.hardware_id)
831 if (strstr(driver->ids, device->pnp.hardware_id))
832 goto Done;
833
834 if (device->flags.compatible_ids) {
835 ACPI_DEVICE_ID_LIST *cid_list = device->pnp.cid_list;
836 int i;
837
838 /* compare multiple _CID entries against driver ids */
839 for (i = 0; i < cid_list->Count; i++)
840 {
841 if (strstr(driver->ids, cid_list->Ids[i].String))
842 goto Done;
843 }
844 }
845 error = -2;
846
847 Done:
848
849 return error;
850 }
851
852
853 /**
854 * acpi_bus_driver_init
855 * --------------------
856 * Used to initialize a device via its device driver. Called whenever a
857 * driver is bound to a device. Invokes the driver's add() and start() ops.
858 */
859 static int
860 acpi_bus_driver_init (
861 struct acpi_device *device,
862 struct acpi_driver *driver)
863 {
864 int result = 0;
865
866 if (!device || !driver)
867 return_VALUE(AE_BAD_PARAMETER);
868
869 if (!driver->ops.add)
870 return_VALUE(-38);
871
872 result = driver->ops.add(device);
873 if (result) {
874 device->driver = NULL;
875 //acpi_driver_data(device) = NULL;
876 return_VALUE(result);
877 }
878
879 device->driver = driver;
880
881 /*
882 * TBD - Configuration Management: Assign resources to device based
883 * upon possible configuration and currently allocated resources.
884 */
885
886 if (driver->ops.start) {
887 result = driver->ops.start(device);
888 if (result && driver->ops.remove)
889 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
890 return_VALUE(result);
891 }
892
893 DPRINT("Driver successfully bound to device\n");
894
895 if (driver->ops.scan) {
896 driver->ops.scan(device);
897 }
898
899 return_VALUE(0);
900 }
901
902
903 /**
904 * acpi_bus_attach
905 * -------------
906 * Callback for acpi_bus_walk() used to find devices that match a specific
907 * driver's criteria and then attach the driver.
908 */
909 static int
910 acpi_bus_attach (
911 struct acpi_device *device,
912 int level,
913 void *data)
914 {
915 int result = 0;
916 struct acpi_driver *driver = NULL;
917
918 if (!device || !data)
919 return_VALUE(AE_BAD_PARAMETER);
920
921 driver = (struct acpi_driver *) data;
922
923 if (device->driver)
924 return_VALUE(-9);
925
926 if (!device->status.present)
927 return_VALUE(AE_NOT_FOUND);
928
929 result = acpi_bus_match(device, driver);
930 if (result)
931 return_VALUE(result);
932
933 DPRINT("Found driver [%s] for device [%s]\n",
934 driver->name, device->pnp.bus_id);
935
936 result = acpi_bus_driver_init(device, driver);
937 if (result)
938 return_VALUE(result);
939
940 down(&acpi_bus_drivers_lock);
941 ++driver->references;
942 up(&acpi_bus_drivers_lock);
943
944 return_VALUE(0);
945 }
946
947
948 /**
949 * acpi_bus_unattach
950 * -----------------
951 * Callback for acpi_bus_walk() used to find devices that match a specific
952 * driver's criteria and unattach the driver.
953 */
954 static int
955 acpi_bus_unattach (
956 struct acpi_device *device,
957 int level,
958 void *data)
959 {
960 int result = 0;
961 struct acpi_driver *driver = (struct acpi_driver *) data;
962
963 if (!device || !driver)
964 return_VALUE(AE_BAD_PARAMETER);
965
966 if (device->driver != driver)
967 return_VALUE(-6);
968
969 if (!driver->ops.remove)
970 return_VALUE(-23);
971
972 result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
973 if (result)
974 return_VALUE(result);
975
976 device->driver = NULL;
977 acpi_driver_data(device) = NULL;
978
979 down(&acpi_bus_drivers_lock);
980 driver->references--;
981 up(&acpi_bus_drivers_lock);
982
983 return_VALUE(0);
984 }
985
986
987 /**
988 * acpi_bus_find_driver
989 * --------------------
990 * Parses the list of registered drivers looking for a driver applicable for
991 * the specified device.
992 */
993 static int
994 acpi_bus_find_driver (
995 struct acpi_device *device)
996 {
997 int result = AE_NOT_FOUND;
998 struct list_head *entry = NULL;
999 struct acpi_driver *driver = NULL;
1000
1001 if (!device || device->driver)
1002 return_VALUE(AE_BAD_PARAMETER);
1003
1004 down(&acpi_bus_drivers_lock);
1005
1006 list_for_each(entry, &acpi_bus_drivers) {
1007
1008 driver = list_entry(entry, struct acpi_driver, node);
1009
1010 if (acpi_bus_match(device, driver))
1011 continue;
1012
1013 result = acpi_bus_driver_init(device, driver);
1014 if (!result)
1015 ++driver->references;
1016
1017 break;
1018 }
1019
1020 up(&acpi_bus_drivers_lock);
1021
1022 return_VALUE(result);
1023 }
1024
1025
1026 /**
1027 * acpi_bus_register_driver
1028 * ------------------------
1029 * Registers a driver with the ACPI bus. Searches the namespace for all
1030 * devices that match the driver's criteria and binds.
1031 */
1032 int
1033 acpi_bus_register_driver (
1034 struct acpi_driver *driver)
1035 {
1036 if (!driver)
1037 return_VALUE(AE_BAD_PARAMETER);
1038
1039 //if (acpi_disabled)
1040 // return_VALUE(AE_NOT_FOUND);
1041
1042 down(&acpi_bus_drivers_lock);
1043 list_add_tail(&driver->node, &acpi_bus_drivers);
1044 up(&acpi_bus_drivers_lock);
1045
1046 acpi_bus_walk(acpi_root, acpi_bus_attach,
1047 WALK_DOWN, driver);
1048
1049 return_VALUE(driver->references);
1050 }
1051
1052
1053 /**
1054 * acpi_bus_unregister_driver
1055 * --------------------------
1056 * Unregisters a driver with the ACPI bus. Searches the namespace for all
1057 * devices that match the driver's criteria and unbinds.
1058 */
1059 void
1060 acpi_bus_unregister_driver (
1061 struct acpi_driver *driver)
1062 {
1063 if (!driver)
1064 return;
1065
1066 acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver);
1067
1068 if (driver->references)
1069 return;
1070
1071 down(&acpi_bus_drivers_lock);
1072 list_del(&driver->node);
1073 up(&acpi_bus_drivers_lock);
1074
1075 return;
1076 }
1077
1078
1079 /* --------------------------------------------------------------------------
1080 Device Enumeration
1081 -------------------------------------------------------------------------- */
1082
1083 static int
1084 acpi_bus_get_flags (
1085 struct acpi_device *device)
1086 {
1087 ACPI_STATUS status = AE_OK;
1088 ACPI_HANDLE temp = NULL;
1089
1090 /* Presence of _STA indicates 'dynamic_status' */
1091 status = AcpiGetHandle(device->handle, "_STA", &temp);
1092 if (ACPI_SUCCESS(status))
1093 device->flags.dynamic_status = 1;
1094
1095 /* Presence of _CID indicates 'compatible_ids' */
1096 status = AcpiGetHandle(device->handle, "_CID", &temp);
1097 if (ACPI_SUCCESS(status))
1098 device->flags.compatible_ids = 1;
1099
1100 /* Presence of _RMV indicates 'removable' */
1101 status = AcpiGetHandle(device->handle, "_RMV", &temp);
1102 if (ACPI_SUCCESS(status))
1103 device->flags.removable = 1;
1104
1105 /* Presence of _EJD|_EJ0 indicates 'ejectable' */
1106 status = AcpiGetHandle(device->handle, "_EJD", &temp);
1107 if (ACPI_SUCCESS(status))
1108 device->flags.ejectable = 1;
1109 else {
1110 status = AcpiGetHandle(device->handle, "_EJ0", &temp);
1111 if (ACPI_SUCCESS(status))
1112 device->flags.ejectable = 1;
1113 }
1114
1115 /* Presence of _LCK indicates 'lockable' */
1116 status = AcpiGetHandle(device->handle, "_LCK", &temp);
1117 if (ACPI_SUCCESS(status))
1118 device->flags.lockable = 1;
1119
1120 /* Presence of _PS0|_PR0 indicates 'power manageable' */
1121 status = AcpiGetHandle(device->handle, "_PS0", &temp);
1122 if (ACPI_FAILURE(status))
1123 status = AcpiGetHandle(device->handle, "_PR0", &temp);
1124 if (ACPI_SUCCESS(status))
1125 device->flags.power_manageable = 1;
1126
1127 /* TBD: Peformance management */
1128
1129 return_VALUE(0);
1130 }
1131
1132
1133 int
1134 acpi_bus_add (
1135 struct acpi_device **child,
1136 struct acpi_device *parent,
1137 ACPI_HANDLE handle,
1138 int type)
1139 {
1140 int result = 0;
1141 ACPI_STATUS status = AE_OK;
1142 struct acpi_device *device = NULL;
1143 char bus_id[5] = {'?',0};
1144 ACPI_BUFFER buffer;
1145 ACPI_DEVICE_INFO *info;
1146 char *hid = NULL;
1147 char *uid = NULL;
1148 ACPI_DEVICE_ID_LIST *cid_list = NULL;
1149 int i = 0;
1150 char static_uid_buffer[5];
1151
1152 if (!child)
1153 return_VALUE(AE_BAD_PARAMETER);
1154
1155 device = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_device), 'IPCA');
1156 if (!device) {
1157 DPRINT1("Memory allocation error\n");
1158 return_VALUE(-12);
1159 }
1160 memset(device, 0, sizeof(struct acpi_device));
1161
1162 device->handle = handle;
1163 device->parent = parent;
1164
1165 /*
1166 * Bus ID
1167 * ------
1168 * The device's Bus ID is simply the object name.
1169 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
1170 */
1171 switch (type) {
1172 case ACPI_BUS_TYPE_SYSTEM:
1173 sprintf(device->pnp.bus_id, "%s", "ACPI");
1174 break;
1175 case ACPI_BUS_TYPE_POWER_BUTTONF:
1176 case ACPI_BUS_TYPE_POWER_BUTTON:
1177 sprintf(device->pnp.bus_id, "%s", "PWRF");
1178 break;
1179 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1180 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1181 sprintf(device->pnp.bus_id, "%s", "SLPF");
1182 break;
1183 default:
1184 buffer.Length = sizeof(bus_id);
1185 buffer.Pointer = bus_id;
1186 AcpiGetName(handle, ACPI_SINGLE_NAME, &buffer);
1187
1188
1189 /* Clean up trailing underscores (if any) */
1190 for (i = 3; i > 1; i--) {
1191 if (bus_id[i] == '_')
1192 bus_id[i] = '\0';
1193 else
1194 break;
1195 }
1196 sprintf(device->pnp.bus_id, "%s", bus_id);
1197 buffer.Pointer = NULL;
1198
1199 /* HACK: Skip HPET */
1200 if (strstr(device->pnp.bus_id, "HPET"))
1201 {
1202 DPRINT1("Using HPET hack\n");
1203 result = -1;
1204 goto end;
1205 }
1206
1207 break;
1208 }
1209
1210 /*
1211 * Flags
1212 * -----
1213 * Get prior to calling acpi_bus_get_status() so we know whether
1214 * or not _STA is present. Note that we only look for object
1215 * handles -- cannot evaluate objects until we know the device is
1216 * present and properly initialized.
1217 */
1218 result = acpi_bus_get_flags(device);
1219 if (result)
1220 goto end;
1221
1222 /*
1223 * Status
1224 * ------
1225 * See if the device is present. We always assume that non-Device()
1226 * objects (e.g. thermal zones, power resources, processors, etc.) are
1227 * present, functioning, etc. (at least when parent object is present).
1228 * Note that _STA has a different meaning for some objects (e.g.
1229 * power resources) so we need to be careful how we use it.
1230 */
1231 switch (type) {
1232 case ACPI_BUS_TYPE_DEVICE:
1233 result = acpi_bus_get_status(device);
1234 if (result)
1235 goto end;
1236 break;
1237 default:
1238 STRUCT_TO_INT(device->status) = 0x0F;
1239 break;
1240 }
1241 if (!device->status.present) {
1242 result = -2;
1243 goto end;
1244 }
1245
1246 /*
1247 * Initialize Device
1248 * -----------------
1249 * TBD: Synch with Core's enumeration/initialization process.
1250 */
1251
1252 /*
1253 * Hardware ID, Unique ID, & Bus Address
1254 * -------------------------------------
1255 */
1256 switch (type) {
1257 case ACPI_BUS_TYPE_DEVICE:
1258 status = AcpiGetObjectInfo(handle,&info);
1259 if (ACPI_FAILURE(status)) {
1260 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1261 "Error reading device info\n"));
1262 result = AE_NOT_FOUND;
1263 goto end;
1264 }
1265 if (info->Valid & ACPI_VALID_HID)
1266 hid = info->HardwareId.String;
1267 if (info->Valid & ACPI_VALID_UID)
1268 uid = info->UniqueId.String;
1269 if (info->Valid & ACPI_VALID_CID) {
1270 cid_list = &info->CompatibleIdList;
1271 device->pnp.cid_list = ExAllocatePoolWithTag(NonPagedPool,cid_list->ListSize, 'IPCA');
1272 if (device->pnp.cid_list)
1273 memcpy(device->pnp.cid_list, cid_list, cid_list->ListSize);
1274 else
1275 DPRINT("Memory allocation error\n");
1276 }
1277 if (info->Valid & ACPI_VALID_ADR) {
1278 device->pnp.bus_address = info->Address;
1279 device->flags.bus_address = 1;
1280 }
1281 break;
1282 case ACPI_BUS_TYPE_POWER:
1283 hid = ACPI_POWER_HID;
1284 uid = static_uid_buffer;
1285 sprintf(uid, "%d", (PowerDeviceCount++));
1286 break;
1287 case ACPI_BUS_TYPE_PROCESSOR:
1288 hid = ACPI_PROCESSOR_HID;
1289 uid = static_uid_buffer;
1290 sprintf(uid, "_%d", (ProcessorCount++));
1291 break;
1292 case ACPI_BUS_TYPE_SYSTEM:
1293 hid = ACPI_SYSTEM_HID;
1294 break;
1295 case ACPI_BUS_TYPE_THERMAL:
1296 hid = ACPI_THERMAL_HID;
1297 uid = static_uid_buffer;
1298 sprintf(uid, "%d", (ThermalZoneCount++));
1299 break;
1300 case ACPI_BUS_TYPE_POWER_BUTTON:
1301 hid = ACPI_BUTTON_HID_POWER;
1302 uid = static_uid_buffer;
1303 sprintf(uid, "%d", (PowerButtonCount++));
1304 break;
1305 case ACPI_BUS_TYPE_POWER_BUTTONF:
1306 hid = ACPI_BUTTON_HID_POWERF;
1307 uid = static_uid_buffer;
1308 sprintf(uid, "%d", (FixedPowerButtonCount++));
1309 break;
1310 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1311 hid = ACPI_BUTTON_HID_SLEEP;
1312 uid = static_uid_buffer;
1313 sprintf(uid, "%d", (SleepButtonCount++));
1314 break;
1315 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1316 hid = ACPI_BUTTON_HID_SLEEPF;
1317 uid = static_uid_buffer;
1318 sprintf(uid, "%d", (FixedSleepButtonCount++));
1319 break;
1320 }
1321
1322 /*
1323 * \_SB
1324 * ----
1325 * Fix for the system root bus device -- the only root-level device.
1326 */
1327 if (((ACPI_HANDLE)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
1328 hid = ACPI_BUS_HID;
1329 sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
1330 sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
1331 }
1332
1333 if (hid) {
1334 sprintf(device->pnp.hardware_id, "%s", hid);
1335 device->flags.hardware_id = 1;
1336 }
1337 if (uid) {
1338 sprintf(device->pnp.unique_id, "%s", uid);
1339 device->flags.unique_id = 1;
1340 }
1341
1342 /*
1343 * If we called get_object_info, we now are finished with the buffer,
1344 * so we can free it.
1345 */
1346 //if (buffer.Pointer)
1347 //AcpiOsFree(buffer.Pointer);
1348
1349 /*
1350 * Power Management
1351 * ----------------
1352 */
1353 if (device->flags.power_manageable) {
1354 result = acpi_bus_get_power_flags(device);
1355 if (result)
1356 goto end;
1357 }
1358
1359 /*
1360 * Performance Management
1361 * ----------------------
1362 */
1363 if (device->flags.performance_manageable) {
1364 result = acpi_bus_get_perf_flags(device);
1365 if (result)
1366 goto end;
1367 }
1368
1369 /*
1370 * Context
1371 * -------
1372 * Attach this 'struct acpi_device' to the ACPI object. This makes
1373 * resolutions from handle->device very efficient. Note that we need
1374 * to be careful with fixed-feature devices as they all attach to the
1375 * root object.
1376 */
1377 switch (type) {
1378 case ACPI_BUS_TYPE_POWER_BUTTON:
1379 case ACPI_BUS_TYPE_POWER_BUTTONF:
1380 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1381 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1382 break;
1383 default:
1384 status = AcpiAttachData(device->handle,
1385 acpi_bus_data_handler, device);
1386 break;
1387 }
1388 if (ACPI_FAILURE(status)) {
1389 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1390 "Error attaching device data\n"));
1391 result = AE_NOT_FOUND;
1392 goto end;
1393 }
1394
1395 /*
1396 * Linkage
1397 * -------
1398 * Link this device to its parent and siblings.
1399 */
1400 INIT_LIST_HEAD(&device->children);
1401 if (!device->parent)
1402 INIT_LIST_HEAD(&device->node);
1403 else
1404 list_add_tail(&device->node, &device->parent->children);
1405
1406 /*
1407 * Global Device Hierarchy:
1408 * ------------------------
1409 * Register this device with the global device hierarchy.
1410 */
1411 acpi_device_register(device, parent);
1412
1413 /*
1414 * Bind _ADR-Based Devices
1415 * -----------------------
1416 * If there's a a bus address (_ADR) then we utilize the parent's
1417 * 'bind' function (if exists) to bind the ACPI- and natively-
1418 * enumerated device representations.
1419 */
1420 if (device->flags.bus_address) {
1421 if (device->parent && device->parent->ops.bind)
1422 device->parent->ops.bind(device);
1423 }
1424
1425 /*
1426 * Locate & Attach Driver
1427 * ----------------------
1428 * If there's a hardware id (_HID) or compatible ids (_CID) we check
1429 * to see if there's a driver installed for this kind of device. Note
1430 * that drivers can install before or after a device is enumerated.
1431 *
1432 * TBD: Assumes LDM provides driver hot-plug capability.
1433 */
1434 if (device->flags.hardware_id || device->flags.compatible_ids)
1435 acpi_bus_find_driver(device);
1436
1437 end:
1438 if (result) {
1439 if (device->pnp.cid_list) {
1440 ExFreePoolWithTag(device->pnp.cid_list, 'IPCA');
1441 }
1442 ExFreePoolWithTag(device, 'IPCA');
1443 return_VALUE(result);
1444 }
1445 *child = device;
1446
1447 return_VALUE(0);
1448 }
1449
1450
1451 static int
1452 acpi_bus_remove (
1453 struct acpi_device *device,
1454 int type)
1455 {
1456
1457 if (!device)
1458 return_VALUE(AE_NOT_FOUND);
1459
1460 acpi_device_unregister(device);
1461
1462 if (device && device->pnp.cid_list)
1463 ExFreePoolWithTag(device->pnp.cid_list, 'IPCA');
1464
1465 if (device)
1466 ExFreePoolWithTag(device, 'IPCA');
1467
1468 return_VALUE(0);
1469 }
1470
1471
1472 int
1473 acpi_bus_scan (
1474 struct acpi_device *start)
1475 {
1476 ACPI_STATUS status = AE_OK;
1477 struct acpi_device *parent = NULL;
1478 struct acpi_device *child = NULL;
1479 ACPI_HANDLE phandle = 0;
1480 ACPI_HANDLE chandle = 0;
1481 ACPI_OBJECT_TYPE type = 0;
1482 UINT32 level = 1;
1483
1484 if (!start)
1485 return_VALUE(AE_BAD_PARAMETER);
1486
1487 parent = start;
1488 phandle = start->handle;
1489
1490 /*
1491 * Parse through the ACPI namespace, identify all 'devices', and
1492 * create a new 'struct acpi_device' for each.
1493 */
1494 while ((level > 0) && parent) {
1495
1496 status = AcpiGetNextObject(ACPI_TYPE_ANY, phandle,
1497 chandle, &chandle);
1498
1499 /*
1500 * If this scope is exhausted then move our way back up.
1501 */
1502 if (ACPI_FAILURE(status)) {
1503 level--;
1504 chandle = phandle;
1505 AcpiGetParent(phandle, &phandle);
1506 if (parent->parent)
1507 parent = parent->parent;
1508 continue;
1509 }
1510
1511 status = AcpiGetType(chandle, &type);
1512 if (ACPI_FAILURE(status))
1513 continue;
1514
1515 /*
1516 * If this is a scope object then parse it (depth-first).
1517 */
1518 if (type == ACPI_TYPE_LOCAL_SCOPE) {
1519 level++;
1520 phandle = chandle;
1521 chandle = 0;
1522 continue;
1523 }
1524
1525 /*
1526 * We're only interested in objects that we consider 'devices'.
1527 */
1528 switch (type) {
1529 case ACPI_TYPE_DEVICE:
1530 type = ACPI_BUS_TYPE_DEVICE;
1531 break;
1532 case ACPI_TYPE_PROCESSOR:
1533 type = ACPI_BUS_TYPE_PROCESSOR;
1534 break;
1535 case ACPI_TYPE_THERMAL:
1536 type = ACPI_BUS_TYPE_THERMAL;
1537 break;
1538 case ACPI_TYPE_POWER:
1539 type = ACPI_BUS_TYPE_POWER;
1540 break;
1541 default:
1542 continue;
1543 }
1544
1545 status = acpi_bus_add(&child, parent, chandle, type);
1546 if (ACPI_FAILURE(status))
1547 continue;
1548
1549 /*
1550 * If the device is present, enabled, and functioning then
1551 * parse its scope (depth-first). Note that we need to
1552 * represent absent devices to facilitate PnP notifications
1553 * -- but only the subtree head (not all of its children,
1554 * which will be enumerated when the parent is inserted).
1555 *
1556 * TBD: Need notifications and other detection mechanisms
1557 * in place before we can fully implement this.
1558 */
1559 if (child->status.present) {
1560 status = AcpiGetNextObject(ACPI_TYPE_ANY, chandle,
1561 0, NULL);
1562 if (ACPI_SUCCESS(status)) {
1563 level++;
1564 phandle = chandle;
1565 chandle = 0;
1566 parent = child;
1567 }
1568 }
1569 }
1570
1571 return_VALUE(0);
1572 }
1573
1574
1575 static int
1576 acpi_bus_scan_fixed (
1577 struct acpi_device *root)
1578 {
1579 int result = 0;
1580 struct acpi_device *device = NULL;
1581
1582 if (!root)
1583 return_VALUE(AE_NOT_FOUND);
1584
1585 /* If ACPI_FADT_POWER_BUTTON is set, then a control
1586 * method power button is present. Otherwise, a fixed
1587 * power button is present.
1588 */
1589 if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)
1590 result = acpi_bus_add(&device, acpi_root,
1591 NULL, ACPI_BUS_TYPE_POWER_BUTTON);
1592 else
1593 {
1594 /* Enable the fixed power button so we get notified if it is pressed */
1595 AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1);
1596
1597 result = acpi_bus_add(&device, acpi_root,
1598 NULL, ACPI_BUS_TYPE_POWER_BUTTONF);
1599 }
1600
1601 /* This one is a bit more complicated and we do it wrong
1602 * right now. If ACPI_FADT_SLEEP_BUTTON is set but no
1603 * device object is present then no sleep button is present, but
1604 * if the flags is clear and there is no device object then it is
1605 * a fixed sleep button. If the flag is set and there is a device object
1606 * the we have a control method button just like above.
1607 */
1608 if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON)
1609 result = acpi_bus_add(&device, acpi_root,
1610 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
1611 else
1612 {
1613 /* Enable the fixed sleep button so we get notified if it is pressed */
1614 AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE, 1);
1615
1616 result = acpi_bus_add(&device, acpi_root,
1617 NULL, ACPI_BUS_TYPE_SLEEP_BUTTONF);
1618 }
1619
1620 return_VALUE(result);
1621 }
1622
1623
1624 /* --------------------------------------------------------------------------
1625 Initialization/Cleanup
1626 -------------------------------------------------------------------------- */
1627
1628 int
1629 acpi_bus_init (void)
1630 {
1631 int result = 0;
1632 ACPI_STATUS status = AE_OK;
1633
1634 DPRINT("acpi_bus_init");
1635
1636 KeInitializeDpc(&event_dpc, acpi_bus_generate_event_dpc, NULL);
1637
1638 status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
1639 if (ACPI_FAILURE(status)) {
1640 DPRINT1("Unable to start the ACPI Interpreter\n");
1641 goto error1;
1642 }
1643
1644 /*
1645 * ACPI 2.0 requires the EC driver to be loaded and work before
1646 * the EC device is found in the namespace. This is accomplished
1647 * by looking for the ECDT table, and getting the EC parameters out
1648 * of that.
1649 */
1650 //result = acpi_ec_ecdt_probe();
1651 /* Ignore result. Not having an ECDT is not fatal. */
1652
1653 status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
1654 if (ACPI_FAILURE(status)) {
1655 DPRINT1("Unable to initialize ACPI objects\n");
1656 goto error1;
1657 }
1658
1659 /*
1660 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
1661 * is necessary to enable it as early as possible.
1662 */
1663 //acpi_boot_ec_enable();
1664
1665 /* Initialize sleep structures */
1666 //acpi_sleep_init();
1667
1668 /*
1669 * Register the for all standard device notifications.
1670 */
1671 status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
1672 if (ACPI_FAILURE(status)) {
1673 DPRINT1("Unable to register for device notifications\n");
1674 result = AE_NOT_FOUND;
1675 goto error1;
1676 }
1677
1678 /*
1679 * Create the root device in the bus's device tree
1680 */
1681 result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
1682 ACPI_BUS_TYPE_SYSTEM);
1683 if (result)
1684 goto error2;
1685
1686
1687 /*
1688 * Enumerate devices in the ACPI namespace.
1689 */
1690 result = acpi_bus_scan_fixed(acpi_root);
1691 if (result)
1692 DPRINT1("acpi_bus_scan_fixed failed\n");
1693 result = acpi_bus_scan(acpi_root);
1694 if (result)
1695 DPRINT1("acpi_bus_scan failed\n");
1696
1697 return_VALUE(0);
1698
1699 /* Mimic structured exception handling */
1700 error2:
1701 AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
1702 ACPI_SYSTEM_NOTIFY, &acpi_bus_notify);
1703 error1:
1704 AcpiTerminate();
1705 return_VALUE(AE_NOT_FOUND);
1706 }
1707
1708 static void
1709 acpi_bus_exit (void)
1710 {
1711 ACPI_STATUS status = AE_OK;
1712
1713 DPRINT("acpi_bus_exit");
1714
1715 status = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
1716 ACPI_SYSTEM_NOTIFY, acpi_bus_notify);
1717 if (ACPI_FAILURE(status))
1718 DPRINT1("Error removing notify handler\n");
1719
1720 #ifdef CONFIG_ACPI_PCI
1721 acpi_pci_root_exit();
1722 acpi_pci_link_exit();
1723 #endif
1724 #ifdef CONFIG_ACPI_EC
1725 acpi_ec_exit();
1726 #endif
1727 //acpi_power_exit();
1728 acpi_system_exit();
1729
1730 acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
1731
1732 status = AcpiTerminate();
1733 if (ACPI_FAILURE(status))
1734 DPRINT1("Unable to terminate the ACPI Interpreter\n");
1735 else
1736 DPRINT1("Interpreter disabled\n");
1737
1738 return_VOID;
1739 }
1740
1741
1742 int
1743 acpi_init (void)
1744 {
1745 int result = 0;
1746
1747 DPRINT("acpi_init");
1748
1749 DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION);
1750
1751 KeInitializeSpinLock(&acpi_bus_event_lock);
1752 KeInitializeEvent(&AcpiEventQueue, NotificationEvent, FALSE);
1753 ExInitializeFastMutex(&acpi_bus_drivers_lock);
1754
1755 result = acpi_bus_init();
1756
1757 //if (!result) {
1758 //pci_mmcfg_late_init();
1759 //if (!(pm_flags & PM_APM))
1760 // pm_flags |= PM_ACPI;
1761 //else {
1762 //DPRINT1("APM is already active, exiting\n");
1763 //disable_acpi();
1764 //result = -ENODEV;
1765 //}
1766 //} else
1767 // disable_acpi();
1768
1769 /*
1770 * If the laptop falls into the DMI check table, the power state check
1771 * will be disabled in the course of device power transistion.
1772 */
1773 //dmi_check_system(power_nocheck_dmi_table);
1774
1775 /*
1776 * Install drivers required for proper enumeration of the
1777 * ACPI namespace.
1778 */
1779 acpi_system_init(); /* ACPI System */
1780 acpi_power_init(); /* ACPI Bus Power Management */
1781 acpi_button_init();
1782 //acpi_ec_init(); /* ACPI Embedded Controller */
1783 #ifdef CONFIG_ACPI_PCI
1784 if (!acpi_pci_disabled) {
1785 acpi_pci_link_init(); /* ACPI PCI Interrupt Link */
1786 acpi_pci_root_init(); /* ACPI PCI Root Bridge */
1787 }
1788 #endif
1789
1790 //acpi_scan_init();
1791 //acpi_ec_init();
1792 //acpi_power_init();
1793 //acpi_system_init();
1794 //acpi_debug_init();
1795 //acpi_sleep_proc_init();
1796 //acpi_wakeup_device_init();
1797
1798 return result;
1799 }
1800
1801
1802 void
1803 acpi_exit (void)
1804 {
1805 DPRINT("acpi_exit");
1806
1807 #ifdef CONFIG_PM
1808 pm_active = 0;
1809 #endif
1810
1811 acpi_bus_exit();
1812
1813 return_VOID;
1814 }
1815