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