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