[ACPI]
[reactos.git] / reactos / drivers / bus / acpi / busmgr / bus.c
1 /*
2 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
3 *
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25 /*
26 * Modified for ReactOS and latest ACPICA
27 * Copyright (C)2009 Samuel Serapion
28 */
29
30 #include <ntddk.h>
31
32 #include <acpi.h>
33 #include <acpi_bus.h>
34 #include <acpi_drivers.h>
35 #include <glue.h>
36
37 #define NDEBUG
38 #include <debug.h>
39
40 #define _COMPONENT ACPI_BUS_COMPONENT
41 ACPI_MODULE_NAME ("acpi_bus")
42
43 #define WALK_UP 0
44 #define WALK_DOWN 1
45
46 #define STRUCT_TO_INT(s) (*((int*)&s))
47 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
48 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children))
49 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node))
50
51 int event_is_open;
52 extern void acpi_pic_sci_set_trigger(unsigned int irq, UINT16 trigger);
53
54 typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*);
55
56 struct acpi_device *acpi_root;
57 KSPIN_LOCK acpi_bus_event_lock;
58 LIST_HEAD(acpi_bus_event_list);
59 //DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
60 KEVENT AcpiEventQueue;
61 KDPC event_dpc;
62
63
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 acpi_bus_generate_event_dpc(PKDPC Dpc,
461 PVOID DeferredContext,
462 PVOID SystemArgument1,
463 PVOID SystemArgument2)
464 {
465 struct acpi_bus_event *event = SystemArgument1;
466 KIRQL OldIrql;
467
468 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
469 list_add_tail(&event->node, &acpi_bus_event_list);
470 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
471
472 KeSetEvent(&AcpiEventQueue, IO_NO_INCREMENT, FALSE);
473 }
474
475 int
476 acpi_bus_generate_event (
477 struct acpi_device *device,
478 UINT8 type,
479 int data)
480 {
481 struct acpi_bus_event *event = NULL;
482
483 DPRINT("acpi_bus_generate_event");
484
485 if (!device)
486 return_VALUE(AE_BAD_PARAMETER);
487
488 /* drop event on the floor if no one's listening */
489 if (!event_is_open)
490 return_VALUE(0);
491
492 event = ExAllocatePool(NonPagedPool,sizeof(struct acpi_bus_event));
493 if (!event)
494 return_VALUE(-4);
495
496 sprintf(event->device_class, "%s", device->pnp.device_class);
497 sprintf(event->bus_id, "%s", device->pnp.bus_id);
498 event->type = type;
499 event->data = data;
500
501 if (!KeInsertQueueDpc(&event_dpc, event, NULL))
502 ExFreePool(event);
503
504 return_VALUE(0);
505 }
506
507 int
508 acpi_bus_receive_event (
509 struct acpi_bus_event *event)
510 {
511 // unsigned long flags = 0;
512 struct acpi_bus_event *entry = NULL;
513 KIRQL OldIrql;
514
515 //DECLARE_WAITQUEUE(wait, current);
516
517 DPRINT("acpi_bus_receive_event");
518
519 if (!event)
520 return AE_BAD_PARAMETER;
521
522 event_is_open++;
523 KeWaitForSingleObject(&AcpiEventQueue,
524 Executive,
525 KernelMode,
526 FALSE,
527 NULL);
528 event_is_open--;
529 KeClearEvent(&AcpiEventQueue);
530
531 if (list_empty(&acpi_bus_event_list))
532 return_VALUE(AE_NOT_FOUND);
533
534 // spin_lock_irqsave(&acpi_bus_event_lock, flags);
535 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql);
536 entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
537 if (entry)
538 list_del(&entry->node);
539 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql);
540 // spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
541
542 if (!entry)
543 return_VALUE(AE_NOT_FOUND);
544
545 memcpy(event, entry, sizeof(struct acpi_bus_event));
546
547 ExFreePool(entry);
548 return_VALUE(0);
549 }
550
551
552 /* --------------------------------------------------------------------------
553 Namespace Management
554 -------------------------------------------------------------------------- */
555
556
557 /**
558 * acpi_bus_walk
559 * -------------
560 * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first)
561 * or up. Able to parse starting at any node in the namespace. Note that a
562 * callback return value of -249 will terminate the walk.
563 *
564 * @start: starting point
565 * callback: function to call for every device encountered while parsing
566 * direction: direction to parse (up or down)
567 * @data: context for this search operation
568 */
569 static int
570 acpi_bus_walk (
571 struct acpi_device *start,
572 acpi_bus_walk_callback callback,
573 int direction,
574 void *data)
575 {
576 int result = 0;
577 int level = 0;
578 struct acpi_device *device = NULL;
579
580 if (!start || !callback)
581 return AE_BAD_PARAMETER;
582
583 device = start;
584
585 /*
586 * Parse Namespace
587 * ---------------
588 * Parse a given subtree (specified by start) in the given direction.
589 * Walking 'up' simply means that we execute the callback on leaf
590 * devices prior to their parents (useful for things like removing
591 * or powering down a subtree).
592 */
593
594 while (device) {
595
596 if (direction == WALK_DOWN)
597 if (-249 == callback(device, level, data))
598 break;
599
600 /* Depth First */
601
602 if (HAS_CHILDREN(device)) {
603 device = NODE_TO_DEVICE(device->children.next);
604 ++level;
605 continue;
606 }
607
608 if (direction == WALK_UP)
609 if (-249 == callback(device, level, data))
610 break;
611
612 /* Now Breadth */
613
614 if (HAS_SIBLINGS(device)) {
615 device = NODE_TO_DEVICE(device->node.next);
616 continue;
617 }
618
619 /* Scope Exhausted - Find Next */
620
621 while ((device = device->parent)) {
622 --level;
623 if (HAS_SIBLINGS(device)) {
624 device = NODE_TO_DEVICE(device->node.next);
625 break;
626 }
627 }
628 }
629
630 if ((direction == WALK_UP) && (result == 0))
631 callback(start, level, data);
632
633 return result;
634 }
635
636
637 /* --------------------------------------------------------------------------
638 Notification Handling
639 -------------------------------------------------------------------------- */
640
641 static void
642 acpi_bus_check_device (ACPI_HANDLE handle)
643 {
644 struct acpi_device *device;
645 ACPI_STATUS status = 0;
646 struct acpi_device_status old_status;
647
648 if (acpi_bus_get_device(handle, &device))
649 return;
650 if (!device)
651 return;
652
653 old_status = device->status;
654
655 /*
656 * Make sure this device's parent is present before we go about
657 * messing with the device.
658 */
659 if (device->parent && !device->parent->status.present) {
660 device->status = device->parent->status;
661 return;
662 }
663
664 status = acpi_bus_get_status(device);
665 if (ACPI_FAILURE(status))
666 return;
667
668 if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
669 return;
670
671
672 /*
673 * Device Insertion/Removal
674 */
675 if ((device->status.present) && !(old_status.present)) {
676 DPRINT("Device insertion detected\n");
677 /* TBD: Handle device insertion */
678 }
679 else if (!(device->status.present) && (old_status.present)) {
680 DPRINT("Device removal detected\n");
681 /* TBD: Handle device removal */
682 }
683
684 }
685
686
687 static void
688 acpi_bus_check_scope (ACPI_HANDLE handle)
689 {
690 /* Status Change? */
691 acpi_bus_check_device(handle);
692
693 /*
694 * TBD: Enumerate child devices within this device's scope and
695 * run acpi_bus_check_device()'s on them.
696 */
697 }
698
699
700 /**
701 * acpi_bus_notify
702 * ---------------
703 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
704 */
705 static void
706 acpi_bus_notify (
707 ACPI_HANDLE handle,
708 UINT32 type,
709 void *data)
710 {
711 struct acpi_device *device = NULL;
712 struct acpi_driver *driver;
713
714 DPRINT1("Notification %#02x to handle %p\n", type, handle);
715
716 //blocking_notifier_call_chain(&acpi_bus_notify_list,
717 // type, (void *)handle);
718
719 switch (type) {
720
721 case ACPI_NOTIFY_BUS_CHECK:
722 DPRINT("Received BUS CHECK notification for device [%s]\n",
723 device->pnp.bus_id);
724 acpi_bus_check_scope(handle);
725 /*
726 * TBD: We'll need to outsource certain events to non-ACPI
727 * drivers via the device manager (device.c).
728 */
729 break;
730
731 case ACPI_NOTIFY_DEVICE_CHECK:
732 DPRINT("Received DEVICE CHECK notification for device [%s]\n",
733 device->pnp.bus_id);
734 acpi_bus_check_device(handle);
735 /*
736 * TBD: We'll need to outsource certain events to non-ACPI
737 * drivers via the device manager (device.c).
738 */
739 break;
740
741 case ACPI_NOTIFY_DEVICE_WAKE:
742 DPRINT("Received DEVICE WAKE notification for device [%s]\n",
743 device->pnp.bus_id);
744 acpi_bus_check_device(handle);
745 /*
746 * TBD: We'll need to outsource certain events to non-ACPI
747 * drivers via the device manager (device.c).
748 */
749 break;
750
751 case ACPI_NOTIFY_EJECT_REQUEST:
752 DPRINT1("Received EJECT REQUEST notification for device [%s]\n",
753 device->pnp.bus_id);
754 /* TBD */
755 break;
756
757 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
758 DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n",
759 device->pnp.bus_id);
760 /* TBD: Exactly what does 'light' mean? */
761 break;
762
763 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
764 DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n",
765 device->pnp.bus_id);
766 /* TBD */
767 break;
768
769 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
770 DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n",
771 device->pnp.bus_id);
772 /* TBD */
773 break;
774
775 case ACPI_NOTIFY_POWER_FAULT:
776 DPRINT1("Received POWER FAULT notification for device [%s]\n",
777 device->pnp.bus_id);
778 /* TBD */
779 break;
780
781 default:
782 DPRINT1("Received unknown/unsupported notification [%08x]\n",
783 type);
784 break;
785 }
786
787 acpi_bus_get_device(handle, &device);
788 if (device) {
789 driver = device->driver;
790 if (driver && driver->ops.notify &&
791 (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
792 driver->ops.notify(device, type);
793 }
794 }
795
796
797 /* --------------------------------------------------------------------------
798 Driver Management
799 -------------------------------------------------------------------------- */
800
801
802 static LIST_HEAD(acpi_bus_drivers);
803 //static DECLARE_MUTEX(acpi_bus_drivers_lock);
804 static FAST_MUTEX acpi_bus_drivers_lock;
805
806
807 /**
808 * acpi_bus_match
809 * --------------
810 * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
811 * matches the specified driver's criteria.
812 */
813 static int
814 acpi_bus_match (
815 struct acpi_device *device,
816 struct acpi_driver *driver)
817 {
818 int error = 0;
819
820 if (device->flags.hardware_id)
821 if (strstr(driver->ids, device->pnp.hardware_id))
822 goto Done;
823
824 if (device->flags.compatible_ids) {
825 ACPI_DEVICE_ID_LIST *cid_list = device->pnp.cid_list;
826 int i;
827
828 /* compare multiple _CID entries against driver ids */
829 for (i = 0; i < cid_list->Count; i++)
830 {
831 if (strstr(driver->ids, cid_list->Ids[i].String))
832 goto Done;
833 }
834 }
835 error = -2;
836
837 Done:
838
839 return error;
840 }
841
842
843 /**
844 * acpi_bus_driver_init
845 * --------------------
846 * Used to initialize a device via its device driver. Called whenever a
847 * driver is bound to a device. Invokes the driver's add() and start() ops.
848 */
849 static int
850 acpi_bus_driver_init (
851 struct acpi_device *device,
852 struct acpi_driver *driver)
853 {
854 int result = 0;
855
856 if (!device || !driver)
857 return_VALUE(AE_BAD_PARAMETER);
858
859 if (!driver->ops.add)
860 return_VALUE(-38);
861
862 result = driver->ops.add(device);
863 if (result) {
864 device->driver = NULL;
865 //acpi_driver_data(device) = NULL;
866 return_VALUE(result);
867 }
868
869 device->driver = driver;
870
871 /*
872 * TBD - Configuration Management: Assign resources to device based
873 * upon possible configuration and currently allocated resources.
874 */
875
876 if (driver->ops.start) {
877 result = driver->ops.start(device);
878 if (result && driver->ops.remove)
879 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
880 return_VALUE(result);
881 }
882
883 DPRINT("Driver successfully bound to device\n");
884
885 if (driver->ops.scan) {
886 driver->ops.scan(device);
887 }
888
889 return_VALUE(0);
890 }
891
892
893 /**
894 * acpi_bus_attach
895 * -------------
896 * Callback for acpi_bus_walk() used to find devices that match a specific
897 * driver's criteria and then attach the driver.
898 */
899 static int
900 acpi_bus_attach (
901 struct acpi_device *device,
902 int level,
903 void *data)
904 {
905 int result = 0;
906 struct acpi_driver *driver = NULL;
907
908 if (!device || !data)
909 return_VALUE(AE_BAD_PARAMETER);
910
911 driver = (struct acpi_driver *) data;
912
913 if (device->driver)
914 return_VALUE(-9);
915
916 if (!device->status.present)
917 return_VALUE(AE_NOT_FOUND);
918
919 result = acpi_bus_match(device, driver);
920 if (result)
921 return_VALUE(result);
922
923 DPRINT("Found driver [%s] for device [%s]\n",
924 driver->name, device->pnp.bus_id);
925
926 result = acpi_bus_driver_init(device, driver);
927 if (result)
928 return_VALUE(result);
929
930 down(&acpi_bus_drivers_lock);
931 ++driver->references;
932 up(&acpi_bus_drivers_lock);
933
934 return_VALUE(0);
935 }
936
937
938 /**
939 * acpi_bus_unattach
940 * -----------------
941 * Callback for acpi_bus_walk() used to find devices that match a specific
942 * driver's criteria and unattach the driver.
943 */
944 static int
945 acpi_bus_unattach (
946 struct acpi_device *device,
947 int level,
948 void *data)
949 {
950 int result = 0;
951 struct acpi_driver *driver = (struct acpi_driver *) data;
952
953 if (!device || !driver)
954 return_VALUE(AE_BAD_PARAMETER);
955
956 if (device->driver != driver)
957 return_VALUE(-6);
958
959 if (!driver->ops.remove)
960 return_VALUE(-23);
961
962 result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
963 if (result)
964 return_VALUE(result);
965
966 device->driver = NULL;
967 acpi_driver_data(device) = NULL;
968
969 down(&acpi_bus_drivers_lock);
970 driver->references--;
971 up(&acpi_bus_drivers_lock);
972
973 return_VALUE(0);
974 }
975
976
977 /**
978 * acpi_bus_find_driver
979 * --------------------
980 * Parses the list of registered drivers looking for a driver applicable for
981 * the specified device.
982 */
983 static int
984 acpi_bus_find_driver (
985 struct acpi_device *device)
986 {
987 int result = AE_NOT_FOUND;
988 struct list_head *entry = NULL;
989 struct acpi_driver *driver = NULL;
990
991 if (!device || device->driver)
992 return_VALUE(AE_BAD_PARAMETER);
993
994 down(&acpi_bus_drivers_lock);
995
996 list_for_each(entry, &acpi_bus_drivers) {
997
998 driver = list_entry(entry, struct acpi_driver, node);
999
1000 if (acpi_bus_match(device, driver))
1001 continue;
1002
1003 result = acpi_bus_driver_init(device, driver);
1004 if (!result)
1005 ++driver->references;
1006
1007 break;
1008 }
1009
1010 up(&acpi_bus_drivers_lock);
1011
1012 return_VALUE(result);
1013 }
1014
1015
1016 /**
1017 * acpi_bus_register_driver
1018 * ------------------------
1019 * Registers a driver with the ACPI bus. Searches the namespace for all
1020 * devices that match the driver's criteria and binds.
1021 */
1022 int
1023 acpi_bus_register_driver (
1024 struct acpi_driver *driver)
1025 {
1026 if (!driver)
1027 return_VALUE(AE_BAD_PARAMETER);
1028
1029 //if (acpi_disabled)
1030 // return_VALUE(AE_NOT_FOUND);
1031
1032 down(&acpi_bus_drivers_lock);
1033 list_add_tail(&driver->node, &acpi_bus_drivers);
1034 up(&acpi_bus_drivers_lock);
1035
1036 acpi_bus_walk(acpi_root, acpi_bus_attach,
1037 WALK_DOWN, driver);
1038
1039 return_VALUE(driver->references);
1040 }
1041
1042
1043 /**
1044 * acpi_bus_unregister_driver
1045 * --------------------------
1046 * Unregisters a driver with the ACPI bus. Searches the namespace for all
1047 * devices that match the driver's criteria and unbinds.
1048 */
1049 void
1050 acpi_bus_unregister_driver (
1051 struct acpi_driver *driver)
1052 {
1053 if (!driver)
1054 return;
1055
1056 acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver);
1057
1058 if (driver->references)
1059 return;
1060
1061 down(&acpi_bus_drivers_lock);
1062 list_del(&driver->node);
1063 up(&acpi_bus_drivers_lock);
1064
1065 return;
1066 }
1067
1068
1069 /* --------------------------------------------------------------------------
1070 Device Enumeration
1071 -------------------------------------------------------------------------- */
1072
1073 static int
1074 acpi_bus_get_flags (
1075 struct acpi_device *device)
1076 {
1077 ACPI_STATUS status = AE_OK;
1078 ACPI_HANDLE temp = NULL;
1079
1080 /* Presence of _STA indicates 'dynamic_status' */
1081 status = AcpiGetHandle(device->handle, "_STA", &temp);
1082 if (ACPI_SUCCESS(status))
1083 device->flags.dynamic_status = 1;
1084
1085 /* Presence of _CID indicates 'compatible_ids' */
1086 status = AcpiGetHandle(device->handle, "_CID", &temp);
1087 if (ACPI_SUCCESS(status))
1088 device->flags.compatible_ids = 1;
1089
1090 /* Presence of _RMV indicates 'removable' */
1091 status = AcpiGetHandle(device->handle, "_RMV", &temp);
1092 if (ACPI_SUCCESS(status))
1093 device->flags.removable = 1;
1094
1095 /* Presence of _EJD|_EJ0 indicates 'ejectable' */
1096 status = AcpiGetHandle(device->handle, "_EJD", &temp);
1097 if (ACPI_SUCCESS(status))
1098 device->flags.ejectable = 1;
1099 else {
1100 status = AcpiGetHandle(device->handle, "_EJ0", &temp);
1101 if (ACPI_SUCCESS(status))
1102 device->flags.ejectable = 1;
1103 }
1104
1105 /* Presence of _LCK indicates 'lockable' */
1106 status = AcpiGetHandle(device->handle, "_LCK", &temp);
1107 if (ACPI_SUCCESS(status))
1108 device->flags.lockable = 1;
1109
1110 /* Presence of _PS0|_PR0 indicates 'power manageable' */
1111 status = AcpiGetHandle(device->handle, "_PS0", &temp);
1112 if (ACPI_FAILURE(status))
1113 status = AcpiGetHandle(device->handle, "_PR0", &temp);
1114 if (ACPI_SUCCESS(status))
1115 device->flags.power_manageable = 1;
1116
1117 /* TBD: Peformance management */
1118
1119 return_VALUE(0);
1120 }
1121
1122
1123 int
1124 acpi_bus_add (
1125 struct acpi_device **child,
1126 struct acpi_device *parent,
1127 ACPI_HANDLE handle,
1128 int type)
1129 {
1130 int result = 0;
1131 ACPI_STATUS status = AE_OK;
1132 struct acpi_device *device = NULL;
1133 char bus_id[5] = {'?',0};
1134 ACPI_BUFFER buffer;
1135 ACPI_DEVICE_INFO *info;
1136 char *hid = NULL;
1137 char *uid = NULL;
1138 ACPI_DEVICE_ID_LIST *cid_list = NULL;
1139 int i = 0;
1140
1141 if (!child)
1142 return_VALUE(AE_BAD_PARAMETER);
1143
1144 device = ExAllocatePool(NonPagedPool,sizeof(struct acpi_device));
1145 if (!device) {
1146 DPRINT1("Memory allocation error\n");
1147 return_VALUE(-12);
1148 }
1149 memset(device, 0, sizeof(struct acpi_device));
1150
1151 device->handle = handle;
1152 device->parent = parent;
1153
1154 /*
1155 * Bus ID
1156 * ------
1157 * The device's Bus ID is simply the object name.
1158 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
1159 */
1160 switch (type) {
1161 case ACPI_BUS_TYPE_SYSTEM:
1162 sprintf(device->pnp.bus_id, "%s", "ACPI");
1163 break;
1164 case ACPI_BUS_TYPE_POWER_BUTTONF:
1165 case ACPI_BUS_TYPE_POWER_BUTTON:
1166 sprintf(device->pnp.bus_id, "%s", "PWRF");
1167 break;
1168 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1169 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1170 sprintf(device->pnp.bus_id, "%s", "SLPF");
1171 break;
1172 default:
1173 buffer.Length = sizeof(bus_id);
1174 buffer.Pointer = bus_id;
1175 AcpiGetName(handle, ACPI_SINGLE_NAME, &buffer);
1176
1177
1178 /* Clean up trailing underscores (if any) */
1179 for (i = 3; i > 1; i--) {
1180 if (bus_id[i] == '_')
1181 bus_id[i] = '\0';
1182 else
1183 break;
1184 }
1185 sprintf(device->pnp.bus_id, "%s", bus_id);
1186 buffer.Pointer = NULL;
1187 break;
1188 }
1189
1190 /*
1191 * Flags
1192 * -----
1193 * Get prior to calling acpi_bus_get_status() so we know whether
1194 * or not _STA is present. Note that we only look for object
1195 * handles -- cannot evaluate objects until we know the device is
1196 * present and properly initialized.
1197 */
1198 result = acpi_bus_get_flags(device);
1199 if (result)
1200 goto end;
1201
1202 /*
1203 * Status
1204 * ------
1205 * See if the device is present. We always assume that non-Device()
1206 * objects (e.g. thermal zones, power resources, processors, etc.) are
1207 * present, functioning, etc. (at least when parent object is present).
1208 * Note that _STA has a different meaning for some objects (e.g.
1209 * power resources) so we need to be careful how we use it.
1210 */
1211 switch (type) {
1212 case ACPI_BUS_TYPE_DEVICE:
1213 result = acpi_bus_get_status(device);
1214 if (result)
1215 goto end;
1216 break;
1217 default:
1218 STRUCT_TO_INT(device->status) = 0x0F;
1219 break;
1220 }
1221 if (!device->status.present) {
1222 result = -2;
1223 goto end;
1224 }
1225
1226 /*
1227 * Initialize Device
1228 * -----------------
1229 * TBD: Synch with Core's enumeration/initialization process.
1230 */
1231
1232 /*
1233 * Hardware ID, Unique ID, & Bus Address
1234 * -------------------------------------
1235 */
1236 switch (type) {
1237 case ACPI_BUS_TYPE_DEVICE:
1238 status = AcpiGetObjectInfo(handle,&info);
1239 if (ACPI_FAILURE(status)) {
1240 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1241 "Error reading device info\n"));
1242 result = AE_NOT_FOUND;
1243 goto end;
1244 }
1245 if (info->Valid & ACPI_VALID_HID)
1246 hid = info->HardwareId.String;
1247 if (info->Valid & ACPI_VALID_UID)
1248 uid = info->UniqueId.String;
1249 if (info->Valid & ACPI_VALID_CID) {
1250 cid_list = &info->CompatibleIdList;
1251 device->pnp.cid_list = ExAllocatePool(NonPagedPool,cid_list->ListSize);
1252 if (device->pnp.cid_list)
1253 memcpy(device->pnp.cid_list, cid_list, cid_list->ListSize);
1254 else
1255 DPRINT("Memory allocation error\n");
1256 }
1257 if (info->Valid & ACPI_VALID_ADR) {
1258 device->pnp.bus_address = info->Address;
1259 device->flags.bus_address = 1;
1260 }
1261 break;
1262 case ACPI_BUS_TYPE_POWER:
1263 hid = ACPI_POWER_HID;
1264 break;
1265 case ACPI_BUS_TYPE_PROCESSOR:
1266 hid = ACPI_PROCESSOR_HID;
1267 break;
1268 case ACPI_BUS_TYPE_SYSTEM:
1269 hid = ACPI_SYSTEM_HID;
1270 break;
1271 case ACPI_BUS_TYPE_THERMAL:
1272 hid = ACPI_THERMAL_HID;
1273 break;
1274 case ACPI_BUS_TYPE_POWER_BUTTON:
1275 hid = ACPI_BUTTON_HID_POWER;
1276 break;
1277 case ACPI_BUS_TYPE_POWER_BUTTONF:
1278 hid = ACPI_BUTTON_HID_POWERF;
1279 break;
1280 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1281 hid = ACPI_BUTTON_HID_SLEEP;
1282 break;
1283 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1284 hid = ACPI_BUTTON_HID_SLEEPF;
1285 break;
1286 }
1287
1288 /*
1289 * \_SB
1290 * ----
1291 * Fix for the system root bus device -- the only root-level device.
1292 */
1293 if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
1294 hid = ACPI_BUS_HID;
1295 sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
1296 sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
1297 }
1298
1299 if (hid) {
1300 sprintf(device->pnp.hardware_id, "%s", hid);
1301 device->flags.hardware_id = 1;
1302 }
1303 if (uid) {
1304 sprintf(device->pnp.unique_id, "%s", uid);
1305 device->flags.unique_id = 1;
1306 }
1307
1308 /*
1309 * If we called get_object_info, we now are finished with the buffer,
1310 * so we can free it.
1311 */
1312 //if (buffer.Pointer)
1313 //AcpiOsFree(buffer.Pointer);
1314
1315 /*
1316 * Power Management
1317 * ----------------
1318 */
1319 if (device->flags.power_manageable) {
1320 result = acpi_bus_get_power_flags(device);
1321 if (result)
1322 goto end;
1323 }
1324
1325 /*
1326 * Performance Management
1327 * ----------------------
1328 */
1329 if (device->flags.performance_manageable) {
1330 result = acpi_bus_get_perf_flags(device);
1331 if (result)
1332 goto end;
1333 }
1334
1335 /*
1336 * Context
1337 * -------
1338 * Attach this 'struct acpi_device' to the ACPI object. This makes
1339 * resolutions from handle->device very efficient. Note that we need
1340 * to be careful with fixed-feature devices as they all attach to the
1341 * root object.
1342 */
1343 switch (type) {
1344 case ACPI_BUS_TYPE_POWER_BUTTON:
1345 case ACPI_BUS_TYPE_POWER_BUTTONF:
1346 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1347 case ACPI_BUS_TYPE_SLEEP_BUTTONF:
1348 break;
1349 default:
1350 status = AcpiAttachData(device->handle,
1351 acpi_bus_data_handler, device);
1352 break;
1353 }
1354 if (ACPI_FAILURE(status)) {
1355 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1356 "Error attaching device data\n"));
1357 result = AE_NOT_FOUND;
1358 goto end;
1359 }
1360
1361 /*
1362 * Linkage
1363 * -------
1364 * Link this device to its parent and siblings.
1365 */
1366 INIT_LIST_HEAD(&device->children);
1367 if (!device->parent)
1368 INIT_LIST_HEAD(&device->node);
1369 else
1370 list_add_tail(&device->node, &device->parent->children);
1371
1372 /*
1373 * Global Device Hierarchy:
1374 * ------------------------
1375 * Register this device with the global device hierarchy.
1376 */
1377 acpi_device_register(device, parent);
1378
1379 /*
1380 * Bind _ADR-Based Devices
1381 * -----------------------
1382 * If there's a a bus address (_ADR) then we utilize the parent's
1383 * 'bind' function (if exists) to bind the ACPI- and natively-
1384 * enumerated device representations.
1385 */
1386 if (device->flags.bus_address) {
1387 if (device->parent && device->parent->ops.bind)
1388 device->parent->ops.bind(device);
1389 }
1390
1391 /*
1392 * Locate & Attach Driver
1393 * ----------------------
1394 * If there's a hardware id (_HID) or compatible ids (_CID) we check
1395 * to see if there's a driver installed for this kind of device. Note
1396 * that drivers can install before or after a device is enumerated.
1397 *
1398 * TBD: Assumes LDM provides driver hot-plug capability.
1399 */
1400 if (device->flags.hardware_id || device->flags.compatible_ids)
1401 acpi_bus_find_driver(device);
1402
1403 end:
1404 if (result) {
1405 if (device->pnp.cid_list) {
1406 ExFreePool(device->pnp.cid_list);
1407 }
1408 ExFreePool(device);
1409 return_VALUE(result);
1410 }
1411 *child = device;
1412
1413 return_VALUE(0);
1414 }
1415
1416
1417 static int
1418 acpi_bus_remove (
1419 struct acpi_device *device,
1420 int type)
1421 {
1422
1423 if (!device)
1424 return_VALUE(AE_NOT_FOUND);
1425
1426 acpi_device_unregister(device);
1427
1428 if (device && device->pnp.cid_list)
1429 ExFreePool(device->pnp.cid_list);
1430
1431 if (device)
1432 ExFreePool(device);
1433
1434 return_VALUE(0);
1435 }
1436
1437
1438 int
1439 acpi_bus_scan (
1440 struct acpi_device *start)
1441 {
1442 ACPI_STATUS status = AE_OK;
1443 struct acpi_device *parent = NULL;
1444 struct acpi_device *child = NULL;
1445 ACPI_HANDLE phandle = 0;
1446 ACPI_HANDLE chandle = 0;
1447 ACPI_OBJECT_TYPE type = 0;
1448 UINT32 level = 1;
1449
1450 if (!start)
1451 return_VALUE(AE_BAD_PARAMETER);
1452
1453 parent = start;
1454 phandle = start->handle;
1455
1456 /*
1457 * Parse through the ACPI namespace, identify all 'devices', and
1458 * create a new 'struct acpi_device' for each.
1459 */
1460 while ((level > 0) && parent) {
1461
1462 status = AcpiGetNextObject(ACPI_TYPE_ANY, phandle,
1463 chandle, &chandle);
1464
1465 /*
1466 * If this scope is exhausted then move our way back up.
1467 */
1468 if (ACPI_FAILURE(status)) {
1469 level--;
1470 chandle = phandle;
1471 AcpiGetParent(phandle, &phandle);
1472 if (parent->parent)
1473 parent = parent->parent;
1474 continue;
1475 }
1476
1477 status = AcpiGetType(chandle, &type);
1478 if (ACPI_FAILURE(status))
1479 continue;
1480
1481 /*
1482 * If this is a scope object then parse it (depth-first).
1483 */
1484 if (type == ACPI_TYPE_LOCAL_SCOPE) {
1485 level++;
1486 phandle = chandle;
1487 chandle = 0;
1488 continue;
1489 }
1490
1491 /*
1492 * We're only interested in objects that we consider 'devices'.
1493 */
1494 switch (type) {
1495 case ACPI_TYPE_DEVICE:
1496 type = ACPI_BUS_TYPE_DEVICE;
1497 break;
1498 case ACPI_TYPE_PROCESSOR:
1499 type = ACPI_BUS_TYPE_PROCESSOR;
1500 break;
1501 case ACPI_TYPE_THERMAL:
1502 type = ACPI_BUS_TYPE_THERMAL;
1503 break;
1504 case ACPI_TYPE_POWER:
1505 type = ACPI_BUS_TYPE_POWER;
1506 break;
1507 default:
1508 continue;
1509 }
1510
1511 status = acpi_bus_add(&child, parent, chandle, type);
1512 if (ACPI_FAILURE(status))
1513 continue;
1514
1515 /*
1516 * If the device is present, enabled, and functioning then
1517 * parse its scope (depth-first). Note that we need to
1518 * represent absent devices to facilitate PnP notifications
1519 * -- but only the subtree head (not all of its children,
1520 * which will be enumerated when the parent is inserted).
1521 *
1522 * TBD: Need notifications and other detection mechanisms
1523 * in place before we can fully implement this.
1524 */
1525 if (child->status.present) {
1526 status = AcpiGetNextObject(ACPI_TYPE_ANY, chandle,
1527 0, NULL);
1528 if (ACPI_SUCCESS(status)) {
1529 level++;
1530 phandle = chandle;
1531 chandle = 0;
1532 parent = child;
1533 }
1534 }
1535 }
1536
1537 return_VALUE(0);
1538 }
1539
1540
1541 static int
1542 acpi_bus_scan_fixed (
1543 struct acpi_device *root)
1544 {
1545 int result = 0;
1546 struct acpi_device *device = NULL;
1547
1548 if (!root)
1549 return_VALUE(AE_NOT_FOUND);
1550
1551 /* If ACPI_FADT_POWER_BUTTON is set, then a control
1552 * method power button is present. Otherwise, a fixed
1553 * power button is present.
1554 */
1555 if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)
1556 result = acpi_bus_add(&device, acpi_root,
1557 NULL, ACPI_BUS_TYPE_POWER_BUTTON);
1558 else
1559 {
1560 /* Enable the fixed power button so we get notified if it is pressed */
1561 AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1);
1562
1563 result = acpi_bus_add(&device, acpi_root,
1564 NULL, ACPI_BUS_TYPE_POWER_BUTTONF);
1565 }
1566
1567 /* This one is a bit more complicated and we do it wrong
1568 * right now. If ACPI_FADT_SLEEP_BUTTON is set but no
1569 * device object is present then no sleep button is present, but
1570 * if the flags is clear and there is no device object then it is
1571 * a fixed sleep button. If the flag is set and there is a device object
1572 * the we have a control method button just like above.
1573 */
1574 if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON)
1575 result = acpi_bus_add(&device, acpi_root,
1576 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
1577 else
1578 {
1579 /* Enable the fixed sleep button so we get notified if it is pressed */
1580 AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE, 1);
1581
1582 result = acpi_bus_add(&device, acpi_root,
1583 NULL, ACPI_BUS_TYPE_SLEEP_BUTTONF);
1584 }
1585
1586 return_VALUE(result);
1587 }
1588
1589
1590 /* --------------------------------------------------------------------------
1591 Initialization/Cleanup
1592 -------------------------------------------------------------------------- */
1593
1594 int
1595 acpi_bus_init (void)
1596 {
1597 int result = 0;
1598 ACPI_STATUS status = AE_OK;
1599
1600 DPRINT("acpi_bus_init");
1601
1602 KeInitializeDpc(&event_dpc, acpi_bus_generate_event_dpc, NULL);
1603
1604 status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
1605 if (ACPI_FAILURE(status)) {
1606 DPRINT1("Unable to start the ACPI Interpreter\n");
1607 goto error1;
1608 }
1609
1610 /*
1611 * ACPI 2.0 requires the EC driver to be loaded and work before
1612 * the EC device is found in the namespace. This is accomplished
1613 * by looking for the ECDT table, and getting the EC parameters out
1614 * of that.
1615 */
1616 //result = acpi_ec_ecdt_probe();
1617 /* Ignore result. Not having an ECDT is not fatal. */
1618
1619 status = AcpiInitializeObjects(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
1620 if (ACPI_FAILURE(status)) {
1621 DPRINT1("Unable to initialize ACPI objects\n");
1622 goto error1;
1623 }
1624
1625 /*
1626 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
1627 * is necessary to enable it as early as possible.
1628 */
1629 //acpi_boot_ec_enable();
1630
1631 /* Initialize sleep structures */
1632 //acpi_sleep_init();
1633
1634 /*
1635 * Register the for all standard device notifications.
1636 */
1637 status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
1638 if (ACPI_FAILURE(status)) {
1639 DPRINT1("Unable to register for device notifications\n");
1640 result = AE_NOT_FOUND;
1641 goto error1;
1642 }
1643
1644 /*
1645 * Create the root device in the bus's device tree
1646 */
1647 result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
1648 ACPI_BUS_TYPE_SYSTEM);
1649 if (result)
1650 goto error2;
1651
1652
1653 /*
1654 * Enumerate devices in the ACPI namespace.
1655 */
1656 result = acpi_bus_scan_fixed(acpi_root);
1657 if (result)
1658 DPRINT1("acpi_bus_scan_fixed failed\n");
1659 result = acpi_bus_scan(acpi_root);
1660 if (result)
1661 DPRINT1("acpi_bus_scan failed\n");
1662
1663 return_VALUE(0);
1664
1665 /* Mimic structured exception handling */
1666 error2:
1667 AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
1668 ACPI_SYSTEM_NOTIFY, &acpi_bus_notify);
1669 error1:
1670 AcpiTerminate();
1671 return_VALUE(AE_NOT_FOUND);
1672 }
1673
1674 static void
1675 acpi_bus_exit (void)
1676 {
1677 ACPI_STATUS status = AE_OK;
1678
1679 DPRINT("acpi_bus_exit");
1680
1681 status = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
1682 ACPI_SYSTEM_NOTIFY, acpi_bus_notify);
1683 if (ACPI_FAILURE(status))
1684 DPRINT1("Error removing notify handler\n");
1685
1686 #ifdef CONFIG_ACPI_PCI
1687 acpi_pci_root_exit();
1688 acpi_pci_link_exit();
1689 #endif
1690 #ifdef CONFIG_ACPI_EC
1691 acpi_ec_exit();
1692 #endif
1693 //acpi_power_exit();
1694 acpi_system_exit();
1695
1696 acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
1697
1698 status = AcpiTerminate();
1699 if (ACPI_FAILURE(status))
1700 DPRINT1("Unable to terminate the ACPI Interpreter\n");
1701 else
1702 DPRINT1("Interpreter disabled\n");
1703
1704 return_VOID;
1705 }
1706
1707
1708 int
1709 acpi_init (void)
1710 {
1711 int result = 0;
1712
1713 DPRINT("acpi_init");
1714
1715 DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION);
1716
1717 KeInitializeSpinLock(&acpi_bus_event_lock);
1718 KeInitializeEvent(&AcpiEventQueue, NotificationEvent, FALSE);
1719 ExInitializeFastMutex(&acpi_bus_drivers_lock);
1720
1721 result = acpi_bus_init();
1722
1723 //if (!result) {
1724 //pci_mmcfg_late_init();
1725 //if (!(pm_flags & PM_APM))
1726 // pm_flags |= PM_ACPI;
1727 //else {
1728 //DPRINT1("APM is already active, exiting\n");
1729 //disable_acpi();
1730 //result = -ENODEV;
1731 //}
1732 //} else
1733 // disable_acpi();
1734
1735 /*
1736 * If the laptop falls into the DMI check table, the power state check
1737 * will be disabled in the course of device power transistion.
1738 */
1739 //dmi_check_system(power_nocheck_dmi_table);
1740
1741 /*
1742 * Install drivers required for proper enumeration of the
1743 * ACPI namespace.
1744 */
1745 acpi_system_init(); /* ACPI System */
1746 acpi_power_init(); /* ACPI Bus Power Management */
1747 acpi_button_init();
1748 //acpi_ec_init(); /* ACPI Embedded Controller */
1749 #ifdef CONFIG_ACPI_PCI
1750 if (!acpi_pci_disabled) {
1751 acpi_pci_link_init(); /* ACPI PCI Interrupt Link */
1752 acpi_pci_root_init(); /* ACPI PCI Root Bridge */
1753 }
1754 #endif
1755
1756 //acpi_scan_init();
1757 //acpi_ec_init();
1758 //acpi_power_init();
1759 //acpi_system_init();
1760 //acpi_debug_init();
1761 //acpi_sleep_proc_init();
1762 //acpi_wakeup_device_init();
1763
1764 return result;
1765 }
1766
1767
1768 void
1769 acpi_exit (void)
1770 {
1771 DPRINT("acpi_exit");
1772
1773 #ifdef CONFIG_PM
1774 pm_active = 0;
1775 #endif
1776
1777 acpi_bus_exit();
1778
1779 return_VOID;
1780 }
1781