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