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