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