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