Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbus.c
Go to the documentation of this file.
00001 /* 00002 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $) 00003 * 00004 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 00005 * 00006 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or (at 00011 * your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License along 00019 * with this program; if not, write to the Free Software Foundation, Inc., 00020 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00021 * 00022 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00023 */ 00024 00025 /* 00026 * Modified for ReactOS and latest ACPICA 00027 * Copyright (C)2009 Samuel Serapion 00028 */ 00029 00030 #include <ntddk.h> 00031 00032 #include <acpi.h> 00033 #include <acpi_bus.h> 00034 #include <acpi_drivers.h> 00035 #include <glue.h> 00036 00037 #define NDEBUG 00038 #include <debug.h> 00039 00040 #define _COMPONENT ACPI_BUS_COMPONENT 00041 ACPI_MODULE_NAME ("acpi_bus") 00042 00043 #define WALK_UP 0 00044 #define WALK_DOWN 1 00045 00046 #define STRUCT_TO_INT(s) (*((int*)&s)) 00047 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children)) 00048 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children)) 00049 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node)) 00050 00051 int event_is_open; 00052 extern void acpi_pic_sci_set_trigger(unsigned int irq, UINT16 trigger); 00053 00054 typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*); 00055 00056 struct acpi_device *acpi_root; 00057 KSPIN_LOCK acpi_bus_event_lock; 00058 LIST_HEAD(acpi_bus_event_list); 00059 //DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); 00060 KEVENT AcpiEventQueue; 00061 KDPC event_dpc; 00062 00063 int ProcessorCount, PowerDeviceCount, PowerButtonCount, FixedPowerButtonCount; 00064 int FixedSleepButtonCount, SleepButtonCount, ThermalZoneCount; 00065 00066 static int 00067 acpi_device_register ( 00068 struct acpi_device *device, 00069 struct acpi_device *parent) 00070 { 00071 int result = 0; 00072 00073 if (!device) 00074 return_VALUE(AE_BAD_PARAMETER); 00075 00076 return_VALUE(result); 00077 } 00078 00079 00080 static int 00081 acpi_device_unregister ( 00082 struct acpi_device *device) 00083 { 00084 if (!device) 00085 return_VALUE(AE_BAD_PARAMETER); 00086 00087 #ifdef CONFIG_LDM 00088 put_device(&device->dev); 00089 #endif /*CONFIG_LDM*/ 00090 00091 return_VALUE(0); 00092 } 00093 00094 00095 /* -------------------------------------------------------------------------- 00096 Device Management 00097 -------------------------------------------------------------------------- */ 00098 00099 void 00100 acpi_bus_data_handler ( 00101 ACPI_HANDLE handle, 00102 void *context) 00103 { 00104 DPRINT1("acpi_bus_data_handler not implemented"); 00105 00106 /* TBD */ 00107 00108 return; 00109 } 00110 00111 00112 int 00113 acpi_bus_get_device ( 00114 ACPI_HANDLE handle, 00115 struct acpi_device **device) 00116 { 00117 ACPI_STATUS status = AE_OK; 00118 00119 if (!device) 00120 return_VALUE(AE_BAD_PARAMETER); 00121 00122 /* TBD: Support fixed-feature devices */ 00123 00124 status = AcpiGetData(handle, acpi_bus_data_handler, (void**)device); 00125 if (ACPI_FAILURE(status) || !*device) { 00126 DPRINT( "Error getting context for object [%p]\n", 00127 handle); 00128 return_VALUE(AE_NOT_FOUND); 00129 } 00130 00131 return 0; 00132 } 00133 00134 ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle, 00135 unsigned long long *sta) 00136 { 00137 ACPI_STATUS status; 00138 00139 status = acpi_evaluate_integer(handle, "_STA", NULL, sta); 00140 if (ACPI_SUCCESS(status)) 00141 return AE_OK; 00142 00143 if (status == AE_NOT_FOUND) { 00144 *sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | 00145 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; 00146 return AE_OK; 00147 } 00148 return status; 00149 } 00150 00151 int 00152 acpi_bus_get_status ( 00153 struct acpi_device *device) 00154 { 00155 ACPI_STATUS status; 00156 unsigned long long sta; 00157 00158 status = acpi_bus_get_status_handle(device->handle, &sta); 00159 if (ACPI_FAILURE(status)) 00160 return -1; 00161 00162 STRUCT_TO_INT(device->status) = (int) sta; 00163 00164 if (device->status.functional && !device->status.present) { 00165 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " 00166 "functional but not present;\n", 00167 device->pnp.bus_id, 00168 (UINT32) STRUCT_TO_INT(device->status))); 00169 } 00170 00171 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", 00172 device->pnp.bus_id, 00173 (UINT32) STRUCT_TO_INT(device->status))); 00174 return 0; 00175 } 00176 00177 void acpi_bus_private_data_handler(ACPI_HANDLE handle, 00178 void *context) 00179 { 00180 return; 00181 } 00182 00183 int acpi_bus_get_private_data(ACPI_HANDLE handle, void **data) 00184 { 00185 ACPI_STATUS status = AE_OK; 00186 00187 if (!*data) 00188 return -1; 00189 00190 status = AcpiGetData(handle, acpi_bus_private_data_handler, data); 00191 if (ACPI_FAILURE(status) || !*data) { 00192 DPRINT("No context for object [%p]\n", handle); 00193 return -1; 00194 } 00195 00196 return 0; 00197 } 00198 /* -------------------------------------------------------------------------- 00199 Power Management 00200 -------------------------------------------------------------------------- */ 00201 00202 int 00203 acpi_bus_get_power ( 00204 ACPI_HANDLE handle, 00205 int *state) 00206 { 00207 int result = 0; 00208 ACPI_STATUS status = 0; 00209 struct acpi_device *device = NULL; 00210 unsigned long long psc = 0; 00211 00212 result = acpi_bus_get_device(handle, &device); 00213 if (result) 00214 return_VALUE(result); 00215 00216 *state = ACPI_STATE_UNKNOWN; 00217 00218 if (!device->flags.power_manageable) { 00219 /* TBD: Non-recursive algorithm for walking up hierarchy */ 00220 if (device->parent) 00221 *state = device->parent->power.state; 00222 else 00223 *state = ACPI_STATE_D0; 00224 } 00225 else { 00226 /* 00227 * Get the device's power state either directly (via _PSC) or 00228 * indirectly (via power resources). 00229 */ 00230 if (device->power.flags.explicit_get) { 00231 status = acpi_evaluate_integer(device->handle, "_PSC", 00232 NULL, &psc); 00233 if (ACPI_FAILURE(status)) 00234 return_VALUE(AE_NOT_FOUND); 00235 device->power.state = (int) psc; 00236 } 00237 else if (device->power.flags.power_resources) { 00238 result = acpi_power_get_inferred_state(device); 00239 if (result) 00240 return_VALUE(result); 00241 } 00242 00243 *state = device->power.state; 00244 } 00245 00246 DPRINT("Device [%s] power state is D%d\n", 00247 device->pnp.bus_id, device->power.state); 00248 00249 return_VALUE(0); 00250 } 00251 00252 00253 int 00254 acpi_bus_set_power ( 00255 ACPI_HANDLE handle, 00256 int state) 00257 { 00258 int result = 0; 00259 ACPI_STATUS status = AE_OK; 00260 struct acpi_device *device = NULL; 00261 char object_name[5] = {'_','P','S','0'+state,'\0'}; 00262 00263 00264 result = acpi_bus_get_device(handle, &device); 00265 if (result) 00266 return_VALUE(result); 00267 00268 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 00269 return_VALUE(AE_BAD_PARAMETER); 00270 00271 /* Make sure this is a valid target state */ 00272 00273 if (!device->flags.power_manageable) { 00274 DPRINT1( "Device is not power manageable\n"); 00275 return_VALUE(AE_NOT_FOUND); 00276 } 00277 /* 00278 * Get device's current power state 00279 */ 00280 //if (!acpi_power_nocheck) { 00281 /* 00282 * Maybe the incorrect power state is returned on the bogus 00283 * bios, which is different with the real power state. 00284 * For example: the bios returns D0 state and the real power 00285 * state is D3. OS expects to set the device to D0 state. In 00286 * such case if OS uses the power state returned by the BIOS, 00287 * the device can't be transisted to the correct power state. 00288 * So if the acpi_power_nocheck is set, it is unnecessary to 00289 * get the power state by calling acpi_bus_get_power. 00290 */ 00291 acpi_bus_get_power(device->handle, &device->power.state); 00292 //} 00293 00294 if ((state == device->power.state) && !device->flags.force_power_state) { 00295 DPRINT1("Device is already at D%d\n", state); 00296 return 0; 00297 } 00298 if (!device->power.states[state].flags.valid) { 00299 DPRINT1( "Device does not support D%d\n", state); 00300 return AE_NOT_FOUND; 00301 } 00302 if (device->parent && (state < device->parent->power.state)) { 00303 DPRINT1( "Cannot set device to a higher-powered state than parent\n"); 00304 return AE_NOT_FOUND; 00305 } 00306 00307 /* 00308 * Transition Power 00309 * ---------------- 00310 * On transitions to a high-powered state we first apply power (via 00311 * power resources) then evalute _PSx. Conversly for transitions to 00312 * a lower-powered state. 00313 */ 00314 if (state < device->power.state) { 00315 if (device->power.flags.power_resources) { 00316 result = acpi_power_transition(device, state); 00317 if (result) 00318 goto end; 00319 } 00320 if (device->power.states[state].flags.explicit_set) { 00321 status = AcpiEvaluateObject(device->handle, 00322 object_name, NULL, NULL); 00323 if (ACPI_FAILURE(status)) { 00324 result = AE_NOT_FOUND; 00325 goto end; 00326 } 00327 } 00328 } 00329 else { 00330 if (device->power.states[state].flags.explicit_set) { 00331 status = AcpiEvaluateObject(device->handle, 00332 object_name, NULL, NULL); 00333 if (ACPI_FAILURE(status)) { 00334 result = AE_NOT_FOUND; 00335 goto end; 00336 } 00337 } 00338 if (device->power.flags.power_resources) { 00339 result = acpi_power_transition(device, state); 00340 if (result) 00341 goto end; 00342 } 00343 } 00344 00345 end: 00346 if (result) 00347 DPRINT( "Error transitioning device [%s] to D%d\n", 00348 device->pnp.bus_id, state); 00349 else 00350 DPRINT("Device [%s] transitioned to D%d\n", 00351 device->pnp.bus_id, state); 00352 00353 return result; 00354 } 00355 00356 BOOLEAN acpi_bus_power_manageable(ACPI_HANDLE handle) 00357 { 00358 struct acpi_device *device; 00359 int result; 00360 00361 result = acpi_bus_get_device(handle, &device); 00362 return result ? 0 : device->flags.power_manageable; 00363 } 00364 00365 BOOLEAN acpi_bus_can_wakeup(ACPI_HANDLE handle) 00366 { 00367 struct acpi_device *device; 00368 int result; 00369 00370 result = acpi_bus_get_device(handle, &device); 00371 return result ? 0 : device->wakeup.flags.valid; 00372 } 00373 00374 static int 00375 acpi_bus_get_power_flags ( 00376 struct acpi_device *device) 00377 { 00378 ACPI_STATUS status = 0; 00379 ACPI_HANDLE handle = 0; 00380 UINT32 i = 0; 00381 00382 if (!device) 00383 return AE_NOT_FOUND; 00384 00385 /* 00386 * Power Management Flags 00387 */ 00388 status = AcpiGetHandle(device->handle, "_PSC", &handle); 00389 if (ACPI_SUCCESS(status)) 00390 device->power.flags.explicit_get = 1; 00391 status = AcpiGetHandle(device->handle, "_IRC", &handle); 00392 if (ACPI_SUCCESS(status)) 00393 device->power.flags.inrush_current = 1; 00394 status = AcpiGetHandle(device->handle, "_PRW", &handle); 00395 if (ACPI_SUCCESS(status)) 00396 device->flags.wake_capable = 1; 00397 00398 /* 00399 * Enumerate supported power management states 00400 */ 00401 for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { 00402 struct acpi_device_power_state *ps = &device->power.states[i]; 00403 char object_name[5] = {'_','P','R','0'+i,'\0'}; 00404 00405 /* Evaluate "_PRx" to se if power resources are referenced */ 00406 status = acpi_evaluate_reference(device->handle, object_name, NULL, 00407 &ps->resources); 00408 if (ACPI_SUCCESS(status) && ps->resources.count) { 00409 device->power.flags.power_resources = 1; 00410 ps->flags.valid = 1; 00411 } 00412 00413 /* Evaluate "_PSx" to see if we can do explicit sets */ 00414 object_name[2] = 'S'; 00415 status = AcpiGetHandle(device->handle, object_name, &handle); 00416 if (ACPI_SUCCESS(status)) { 00417 ps->flags.explicit_set = 1; 00418 ps->flags.valid = 1; 00419 } 00420 00421 /* State is valid if we have some power control */ 00422 if (ps->resources.count || ps->flags.explicit_set) 00423 ps->flags.valid = 1; 00424 00425 ps->power = -1; /* Unknown - driver assigned */ 00426 ps->latency = -1; /* Unknown - driver assigned */ 00427 } 00428 00429 /* Set defaults for D0 and D3 states (always valid) */ 00430 device->power.states[ACPI_STATE_D0].flags.valid = 1; 00431 device->power.states[ACPI_STATE_D0].power = 100; 00432 device->power.states[ACPI_STATE_D3].flags.valid = 1; 00433 device->power.states[ACPI_STATE_D3].power = 0; 00434 00435 device->power.state = ACPI_STATE_UNKNOWN; 00436 00437 return 0; 00438 } 00439 00440 /* -------------------------------------------------------------------------- 00441 Performance Management 00442 -------------------------------------------------------------------------- */ 00443 00444 static int 00445 acpi_bus_get_perf_flags ( 00446 struct acpi_device *device) 00447 { 00448 if (!device) 00449 return AE_NOT_FOUND; 00450 00451 device->performance.state = ACPI_STATE_UNKNOWN; 00452 00453 return 0; 00454 } 00455 00456 00457 /* -------------------------------------------------------------------------- 00458 Event Management 00459 -------------------------------------------------------------------------- */ 00460 00461 void 00462 NTAPI 00463 acpi_bus_generate_event_dpc(PKDPC Dpc, 00464 PVOID DeferredContext, 00465 PVOID SystemArgument1, 00466 PVOID SystemArgument2) 00467 { 00468 struct acpi_bus_event *event; 00469 struct acpi_device *device = SystemArgument1; 00470 ULONG_PTR TypeData = (ULONG_PTR)SystemArgument2; 00471 KIRQL OldIrql; 00472 00473 event = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_bus_event), 'IPCA'); 00474 if (!event) 00475 return; 00476 00477 sprintf(event->device_class, "%s", device->pnp.device_class); 00478 sprintf(event->bus_id, "%s", device->pnp.bus_id); 00479 event->type = (TypeData & 0xFF000000) >> 24; 00480 event->data = (TypeData & 0x00FFFFFF); 00481 00482 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql); 00483 list_add_tail(&event->node, &acpi_bus_event_list); 00484 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql); 00485 00486 KeSetEvent(&AcpiEventQueue, IO_NO_INCREMENT, FALSE); 00487 } 00488 00489 int 00490 acpi_bus_generate_event ( 00491 struct acpi_device *device, 00492 UINT8 type, 00493 int data) 00494 { 00495 ULONG_PTR TypeData = 0; 00496 00497 DPRINT("acpi_bus_generate_event"); 00498 00499 if (!device) 00500 return_VALUE(AE_BAD_PARAMETER); 00501 00502 /* drop event on the floor if no one's listening */ 00503 if (!event_is_open) 00504 return_VALUE(0); 00505 00506 /* Data shouldn't even get near 24 bits */ 00507 ASSERT(!(data & 0xFF000000)); 00508 00509 TypeData = data; 00510 TypeData |= type << 24; 00511 00512 KeInsertQueueDpc(&event_dpc, device, (PVOID)TypeData); 00513 00514 return_VALUE(0); 00515 } 00516 00517 int 00518 acpi_bus_receive_event ( 00519 struct acpi_bus_event *event) 00520 { 00521 // unsigned long flags = 0; 00522 struct acpi_bus_event *entry = NULL; 00523 KIRQL OldIrql; 00524 00525 //DECLARE_WAITQUEUE(wait, current); 00526 00527 DPRINT("acpi_bus_receive_event"); 00528 00529 if (!event) 00530 return AE_BAD_PARAMETER; 00531 00532 event_is_open++; 00533 KeWaitForSingleObject(&AcpiEventQueue, 00534 Executive, 00535 KernelMode, 00536 FALSE, 00537 NULL); 00538 event_is_open--; 00539 KeClearEvent(&AcpiEventQueue); 00540 00541 if (list_empty(&acpi_bus_event_list)) 00542 return_VALUE(AE_NOT_FOUND); 00543 00544 // spin_lock_irqsave(&acpi_bus_event_lock, flags); 00545 KeAcquireSpinLock(&acpi_bus_event_lock, &OldIrql); 00546 entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); 00547 if (entry) 00548 list_del(&entry->node); 00549 KeReleaseSpinLock(&acpi_bus_event_lock, OldIrql); 00550 // spin_unlock_irqrestore(&acpi_bus_event_lock, flags); 00551 00552 if (!entry) 00553 return_VALUE(AE_NOT_FOUND); 00554 00555 memcpy(event, entry, sizeof(struct acpi_bus_event)); 00556 00557 ExFreePoolWithTag(entry, 'IPCA'); 00558 return_VALUE(0); 00559 } 00560 00561 00562 /* -------------------------------------------------------------------------- 00563 Namespace Management 00564 -------------------------------------------------------------------------- */ 00565 00566 00579 static int 00580 acpi_bus_walk ( 00581 struct acpi_device *start, 00582 acpi_bus_walk_callback callback, 00583 int direction, 00584 void *data) 00585 { 00586 int result = 0; 00587 int level = 0; 00588 struct acpi_device *device = NULL; 00589 00590 if (!start || !callback) 00591 return AE_BAD_PARAMETER; 00592 00593 device = start; 00594 00595 /* 00596 * Parse Namespace 00597 * --------------- 00598 * Parse a given subtree (specified by start) in the given direction. 00599 * Walking 'up' simply means that we execute the callback on leaf 00600 * devices prior to their parents (useful for things like removing 00601 * or powering down a subtree). 00602 */ 00603 00604 while (device) { 00605 00606 if (direction == WALK_DOWN) 00607 if (-249 == callback(device, level, data)) 00608 break; 00609 00610 /* Depth First */ 00611 00612 if (HAS_CHILDREN(device)) { 00613 device = NODE_TO_DEVICE(device->children.next); 00614 ++level; 00615 continue; 00616 } 00617 00618 if (direction == WALK_UP) 00619 if (-249 == callback(device, level, data)) 00620 break; 00621 00622 /* Now Breadth */ 00623 00624 if (HAS_SIBLINGS(device)) { 00625 device = NODE_TO_DEVICE(device->node.next); 00626 continue; 00627 } 00628 00629 /* Scope Exhausted - Find Next */ 00630 00631 while ((device = device->parent)) { 00632 --level; 00633 if (HAS_SIBLINGS(device)) { 00634 device = NODE_TO_DEVICE(device->node.next); 00635 break; 00636 } 00637 } 00638 } 00639 00640 if ((direction == WALK_UP) && (result == 0)) 00641 callback(start, level, data); 00642 00643 return result; 00644 } 00645 00646 00647 /* -------------------------------------------------------------------------- 00648 Notification Handling 00649 -------------------------------------------------------------------------- */ 00650 00651 static void 00652 acpi_bus_check_device (ACPI_HANDLE handle) 00653 { 00654 struct acpi_device *device; 00655 ACPI_STATUS status = 0; 00656 struct acpi_device_status old_status; 00657 00658 if (acpi_bus_get_device(handle, &device)) 00659 return; 00660 if (!device) 00661 return; 00662 00663 old_status = device->status; 00664 00665 /* 00666 * Make sure this device's parent is present before we go about 00667 * messing with the device. 00668 */ 00669 if (device->parent && !device->parent->status.present) { 00670 device->status = device->parent->status; 00671 return; 00672 } 00673 00674 status = acpi_bus_get_status(device); 00675 if (ACPI_FAILURE(status)) 00676 return; 00677 00678 if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) 00679 return; 00680 00681 00682 /* 00683 * Device Insertion/Removal 00684 */ 00685 if ((device->status.present) && !(old_status.present)) { 00686 DPRINT("Device insertion detected\n"); 00687 /* TBD: Handle device insertion */ 00688 } 00689 else if (!(device->status.present) && (old_status.present)) { 00690 DPRINT("Device removal detected\n"); 00691 /* TBD: Handle device removal */ 00692 } 00693 00694 } 00695 00696 00697 static void 00698 acpi_bus_check_scope (ACPI_HANDLE handle) 00699 { 00700 /* Status Change? */ 00701 acpi_bus_check_device(handle); 00702 00703 /* 00704 * TBD: Enumerate child devices within this device's scope and 00705 * run acpi_bus_check_device()'s on them. 00706 */ 00707 } 00708 00709 00715 static void 00716 acpi_bus_notify ( 00717 ACPI_HANDLE handle, 00718 UINT32 type, 00719 void *data) 00720 { 00721 struct acpi_device *device = NULL; 00722 struct acpi_driver *driver; 00723 00724 DPRINT1("Notification %#02x to handle %p\n", type, handle); 00725 00726 //blocking_notifier_call_chain(&acpi_bus_notify_list, 00727 // type, (void *)handle); 00728 00729 switch (type) { 00730 00731 case ACPI_NOTIFY_BUS_CHECK: 00732 DPRINT("Received BUS CHECK notification for device [%s]\n", 00733 device->pnp.bus_id); 00734 acpi_bus_check_scope(handle); 00735 /* 00736 * TBD: We'll need to outsource certain events to non-ACPI 00737 * drivers via the device manager (device.c). 00738 */ 00739 break; 00740 00741 case ACPI_NOTIFY_DEVICE_CHECK: 00742 DPRINT("Received DEVICE CHECK notification for device [%s]\n", 00743 device->pnp.bus_id); 00744 acpi_bus_check_device(handle); 00745 /* 00746 * TBD: We'll need to outsource certain events to non-ACPI 00747 * drivers via the device manager (device.c). 00748 */ 00749 break; 00750 00751 case ACPI_NOTIFY_DEVICE_WAKE: 00752 DPRINT("Received DEVICE WAKE notification for device [%s]\n", 00753 device->pnp.bus_id); 00754 acpi_bus_check_device(handle); 00755 /* 00756 * TBD: We'll need to outsource certain events to non-ACPI 00757 * drivers via the device manager (device.c). 00758 */ 00759 break; 00760 00761 case ACPI_NOTIFY_EJECT_REQUEST: 00762 DPRINT1("Received EJECT REQUEST notification for device [%s]\n", 00763 device->pnp.bus_id); 00764 /* TBD */ 00765 break; 00766 00767 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: 00768 DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n", 00769 device->pnp.bus_id); 00770 /* TBD: Exactly what does 'light' mean? */ 00771 break; 00772 00773 case ACPI_NOTIFY_FREQUENCY_MISMATCH: 00774 DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n", 00775 device->pnp.bus_id); 00776 /* TBD */ 00777 break; 00778 00779 case ACPI_NOTIFY_BUS_MODE_MISMATCH: 00780 DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n", 00781 device->pnp.bus_id); 00782 /* TBD */ 00783 break; 00784 00785 case ACPI_NOTIFY_POWER_FAULT: 00786 DPRINT1("Received POWER FAULT notification for device [%s]\n", 00787 device->pnp.bus_id); 00788 /* TBD */ 00789 break; 00790 00791 default: 00792 DPRINT1("Received unknown/unsupported notification [%08x]\n", 00793 type); 00794 break; 00795 } 00796 00797 acpi_bus_get_device(handle, &device); 00798 if (device) { 00799 driver = device->driver; 00800 if (driver && driver->ops.notify && 00801 (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) 00802 driver->ops.notify(device, type); 00803 } 00804 } 00805 00806 00807 /* -------------------------------------------------------------------------- 00808 Driver Management 00809 -------------------------------------------------------------------------- */ 00810 00811 00812 static LIST_HEAD(acpi_bus_drivers); 00813 //static DECLARE_MUTEX(acpi_bus_drivers_lock); 00814 static FAST_MUTEX acpi_bus_drivers_lock; 00815 00816 00823 static int 00824 acpi_bus_match ( 00825 struct acpi_device *device, 00826 struct acpi_driver *driver) 00827 { 00828 int error = 0; 00829 00830 if (device->flags.hardware_id) 00831 if (strstr(driver->ids, device->pnp.hardware_id)) 00832 goto Done; 00833 00834 if (device->flags.compatible_ids) { 00835 ACPI_DEVICE_ID_LIST *cid_list = device->pnp.cid_list; 00836 int i; 00837 00838 /* compare multiple _CID entries against driver ids */ 00839 for (i = 0; i < cid_list->Count; i++) 00840 { 00841 if (strstr(driver->ids, cid_list->Ids[i].String)) 00842 goto Done; 00843 } 00844 } 00845 error = -2; 00846 00847 Done: 00848 00849 return error; 00850 } 00851 00852 00859 static int 00860 acpi_bus_driver_init ( 00861 struct acpi_device *device, 00862 struct acpi_driver *driver) 00863 { 00864 int result = 0; 00865 00866 if (!device || !driver) 00867 return_VALUE(AE_BAD_PARAMETER); 00868 00869 if (!driver->ops.add) 00870 return_VALUE(-38); 00871 00872 result = driver->ops.add(device); 00873 if (result) { 00874 device->driver = NULL; 00875 //acpi_driver_data(device) = NULL; 00876 return_VALUE(result); 00877 } 00878 00879 device->driver = driver; 00880 00881 /* 00882 * TBD - Configuration Management: Assign resources to device based 00883 * upon possible configuration and currently allocated resources. 00884 */ 00885 00886 if (driver->ops.start) { 00887 result = driver->ops.start(device); 00888 if (result && driver->ops.remove) 00889 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); 00890 return_VALUE(result); 00891 } 00892 00893 DPRINT("Driver successfully bound to device\n"); 00894 00895 if (driver->ops.scan) { 00896 driver->ops.scan(device); 00897 } 00898 00899 return_VALUE(0); 00900 } 00901 00902 00909 static int 00910 acpi_bus_attach ( 00911 struct acpi_device *device, 00912 int level, 00913 void *data) 00914 { 00915 int result = 0; 00916 struct acpi_driver *driver = NULL; 00917 00918 if (!device || !data) 00919 return_VALUE(AE_BAD_PARAMETER); 00920 00921 driver = (struct acpi_driver *) data; 00922 00923 if (device->driver) 00924 return_VALUE(-9); 00925 00926 if (!device->status.present) 00927 return_VALUE(AE_NOT_FOUND); 00928 00929 result = acpi_bus_match(device, driver); 00930 if (result) 00931 return_VALUE(result); 00932 00933 DPRINT("Found driver [%s] for device [%s]\n", 00934 driver->name, device->pnp.bus_id); 00935 00936 result = acpi_bus_driver_init(device, driver); 00937 if (result) 00938 return_VALUE(result); 00939 00940 down(&acpi_bus_drivers_lock); 00941 ++driver->references; 00942 up(&acpi_bus_drivers_lock); 00943 00944 return_VALUE(0); 00945 } 00946 00947 00954 static int 00955 acpi_bus_unattach ( 00956 struct acpi_device *device, 00957 int level, 00958 void *data) 00959 { 00960 int result = 0; 00961 struct acpi_driver *driver = (struct acpi_driver *) data; 00962 00963 if (!device || !driver) 00964 return_VALUE(AE_BAD_PARAMETER); 00965 00966 if (device->driver != driver) 00967 return_VALUE(-6); 00968 00969 if (!driver->ops.remove) 00970 return_VALUE(-23); 00971 00972 result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); 00973 if (result) 00974 return_VALUE(result); 00975 00976 device->driver = NULL; 00977 acpi_driver_data(device) = NULL; 00978 00979 down(&acpi_bus_drivers_lock); 00980 driver->references--; 00981 up(&acpi_bus_drivers_lock); 00982 00983 return_VALUE(0); 00984 } 00985 00986 00993 static int 00994 acpi_bus_find_driver ( 00995 struct acpi_device *device) 00996 { 00997 int result = AE_NOT_FOUND; 00998 struct list_head *entry = NULL; 00999 struct acpi_driver *driver = NULL; 01000 01001 if (!device || device->driver) 01002 return_VALUE(AE_BAD_PARAMETER); 01003 01004 down(&acpi_bus_drivers_lock); 01005 01006 list_for_each(entry, &acpi_bus_drivers) { 01007 01008 driver = list_entry(entry, struct acpi_driver, node); 01009 01010 if (acpi_bus_match(device, driver)) 01011 continue; 01012 01013 result = acpi_bus_driver_init(device, driver); 01014 if (!result) 01015 ++driver->references; 01016 01017 break; 01018 } 01019 01020 up(&acpi_bus_drivers_lock); 01021 01022 return_VALUE(result); 01023 } 01024 01025 01032 int 01033 acpi_bus_register_driver ( 01034 struct acpi_driver *driver) 01035 { 01036 if (!driver) 01037 return_VALUE(AE_BAD_PARAMETER); 01038 01039 //if (acpi_disabled) 01040 // return_VALUE(AE_NOT_FOUND); 01041 01042 down(&acpi_bus_drivers_lock); 01043 list_add_tail(&driver->node, &acpi_bus_drivers); 01044 up(&acpi_bus_drivers_lock); 01045 01046 acpi_bus_walk(acpi_root, acpi_bus_attach, 01047 WALK_DOWN, driver); 01048 01049 return_VALUE(driver->references); 01050 } 01051 01052 01059 void 01060 acpi_bus_unregister_driver ( 01061 struct acpi_driver *driver) 01062 { 01063 if (!driver) 01064 return; 01065 01066 acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver); 01067 01068 if (driver->references) 01069 return; 01070 01071 down(&acpi_bus_drivers_lock); 01072 list_del(&driver->node); 01073 up(&acpi_bus_drivers_lock); 01074 01075 return; 01076 } 01077 01078 01079 /* -------------------------------------------------------------------------- 01080 Device Enumeration 01081 -------------------------------------------------------------------------- */ 01082 01083 static int 01084 acpi_bus_get_flags ( 01085 struct acpi_device *device) 01086 { 01087 ACPI_STATUS status = AE_OK; 01088 ACPI_HANDLE temp = NULL; 01089 01090 /* Presence of _STA indicates 'dynamic_status' */ 01091 status = AcpiGetHandle(device->handle, "_STA", &temp); 01092 if (ACPI_SUCCESS(status)) 01093 device->flags.dynamic_status = 1; 01094 01095 /* Presence of _CID indicates 'compatible_ids' */ 01096 status = AcpiGetHandle(device->handle, "_CID", &temp); 01097 if (ACPI_SUCCESS(status)) 01098 device->flags.compatible_ids = 1; 01099 01100 /* Presence of _RMV indicates 'removable' */ 01101 status = AcpiGetHandle(device->handle, "_RMV", &temp); 01102 if (ACPI_SUCCESS(status)) 01103 device->flags.removable = 1; 01104 01105 /* Presence of _EJD|_EJ0 indicates 'ejectable' */ 01106 status = AcpiGetHandle(device->handle, "_EJD", &temp); 01107 if (ACPI_SUCCESS(status)) 01108 device->flags.ejectable = 1; 01109 else { 01110 status = AcpiGetHandle(device->handle, "_EJ0", &temp); 01111 if (ACPI_SUCCESS(status)) 01112 device->flags.ejectable = 1; 01113 } 01114 01115 /* Presence of _LCK indicates 'lockable' */ 01116 status = AcpiGetHandle(device->handle, "_LCK", &temp); 01117 if (ACPI_SUCCESS(status)) 01118 device->flags.lockable = 1; 01119 01120 /* Presence of _PS0|_PR0 indicates 'power manageable' */ 01121 status = AcpiGetHandle(device->handle, "_PS0", &temp); 01122 if (ACPI_FAILURE(status)) 01123 status = AcpiGetHandle(device->handle, "_PR0", &temp); 01124 if (ACPI_SUCCESS(status)) 01125 device->flags.power_manageable = 1; 01126 01127 /* TBD: Peformance management */ 01128 01129 return_VALUE(0); 01130 } 01131 01132 01133 int 01134 acpi_bus_add ( 01135 struct acpi_device **child, 01136 struct acpi_device *parent, 01137 ACPI_HANDLE handle, 01138 int type) 01139 { 01140 int result = 0; 01141 ACPI_STATUS status = AE_OK; 01142 struct acpi_device *device = NULL; 01143 char bus_id[5] = {'?',0}; 01144 ACPI_BUFFER buffer; 01145 ACPI_DEVICE_INFO *info; 01146 char *hid = NULL; 01147 char *uid = NULL; 01148 ACPI_DEVICE_ID_LIST *cid_list = NULL; 01149 int i = 0; 01150 char static_uid_buffer[5]; 01151 01152 if (!child) 01153 return_VALUE(AE_BAD_PARAMETER); 01154 01155 device = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_device), 'IPCA'); 01156 if (!device) { 01157 DPRINT1("Memory allocation error\n"); 01158 return_VALUE(-12); 01159 } 01160 memset(device, 0, sizeof(struct acpi_device)); 01161 01162 device->handle = handle; 01163 device->parent = parent; 01164 01165 /* 01166 * Bus ID 01167 * ------ 01168 * The device's Bus ID is simply the object name. 01169 * TBD: Shouldn't this value be unique (within the ACPI namespace)? 01170 */ 01171 switch (type) { 01172 case ACPI_BUS_TYPE_SYSTEM: 01173 sprintf(device->pnp.bus_id, "%s", "ACPI"); 01174 break; 01175 case ACPI_BUS_TYPE_POWER_BUTTONF: 01176 case ACPI_BUS_TYPE_POWER_BUTTON: 01177 sprintf(device->pnp.bus_id, "%s", "PWRF"); 01178 break; 01179 case ACPI_BUS_TYPE_SLEEP_BUTTONF: 01180 case ACPI_BUS_TYPE_SLEEP_BUTTON: 01181 sprintf(device->pnp.bus_id, "%s", "SLPF"); 01182 break; 01183 default: 01184 buffer.Length = sizeof(bus_id); 01185 buffer.Pointer = bus_id; 01186 AcpiGetName(handle, ACPI_SINGLE_NAME, &buffer); 01187 01188 01189 /* Clean up trailing underscores (if any) */ 01190 for (i = 3; i > 1; i--) { 01191 if (bus_id[i] == '_') 01192 bus_id[i] = '\0'; 01193 else 01194 break; 01195 } 01196 sprintf(device->pnp.bus_id, "%s", bus_id); 01197 buffer.Pointer = NULL; 01198 01199 /* HACK: Skip HPET */ 01200 if (strstr(device->pnp.bus_id, "HPET")) 01201 { 01202 DPRINT1("Using HPET hack\n"); 01203 result = -1; 01204 goto end; 01205 } 01206 01207 break; 01208 } 01209 01210 /* 01211 * Flags 01212 * ----- 01213 * Get prior to calling acpi_bus_get_status() so we know whether 01214 * or not _STA is present. Note that we only look for object 01215 * handles -- cannot evaluate objects until we know the device is 01216 * present and properly initialized. 01217 */ 01218 result = acpi_bus_get_flags(device); 01219 if (result) 01220 goto end; 01221 01222 /* 01223 * Status 01224 * ------ 01225 * See if the device is present. We always assume that non-Device() 01226 * objects (e.g. thermal zones, power resources, processors, etc.) are 01227 * present, functioning, etc. (at least when parent object is present). 01228 * Note that _STA has a different meaning for some objects (e.g. 01229 * power resources) so we need to be careful how we use it. 01230 */ 01231 switch (type) { 01232 case ACPI_BUS_TYPE_DEVICE: 01233 result = acpi_bus_get_status(device); 01234 if (result) 01235 goto end; 01236 break; 01237 default: 01238 STRUCT_TO_INT(device->status) = 0x0F; 01239 break; 01240 } 01241 if (!device->status.present) { 01242 result = -2; 01243 goto end; 01244 } 01245 01246 /* 01247 * Initialize Device 01248 * ----------------- 01249 * TBD: Synch with Core's enumeration/initialization process. 01250 */ 01251 01252 /* 01253 * Hardware ID, Unique ID, & Bus Address 01254 * ------------------------------------- 01255 */ 01256 switch (type) { 01257 case ACPI_BUS_TYPE_DEVICE: 01258 status = AcpiGetObjectInfo(handle,&info); 01259 if (ACPI_FAILURE(status)) { 01260 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 01261 "Error reading device info\n")); 01262 result = AE_NOT_FOUND; 01263 goto end; 01264 } 01265 if (info->Valid & ACPI_VALID_HID) 01266 hid = info->HardwareId.String; 01267 if (info->Valid & ACPI_VALID_UID) 01268 uid = info->UniqueId.String; 01269 if (info->Valid & ACPI_VALID_CID) { 01270 cid_list = &info->CompatibleIdList; 01271 device->pnp.cid_list = ExAllocatePoolWithTag(NonPagedPool,cid_list->ListSize, 'IPCA'); 01272 if (device->pnp.cid_list) 01273 memcpy(device->pnp.cid_list, cid_list, cid_list->ListSize); 01274 else 01275 DPRINT("Memory allocation error\n"); 01276 } 01277 if (info->Valid & ACPI_VALID_ADR) { 01278 device->pnp.bus_address = info->Address; 01279 device->flags.bus_address = 1; 01280 } 01281 break; 01282 case ACPI_BUS_TYPE_POWER: 01283 hid = ACPI_POWER_HID; 01284 uid = static_uid_buffer; 01285 sprintf(uid, "%d", (PowerDeviceCount++)); 01286 break; 01287 case ACPI_BUS_TYPE_PROCESSOR: 01288 hid = ACPI_PROCESSOR_HID; 01289 uid = static_uid_buffer; 01290 sprintf(uid, "%d", (ProcessorCount++)); 01291 break; 01292 case ACPI_BUS_TYPE_SYSTEM: 01293 hid = ACPI_SYSTEM_HID; 01294 break; 01295 case ACPI_BUS_TYPE_THERMAL: 01296 hid = ACPI_THERMAL_HID; 01297 uid = static_uid_buffer; 01298 sprintf(uid, "%d", (ThermalZoneCount++)); 01299 break; 01300 case ACPI_BUS_TYPE_POWER_BUTTON: 01301 hid = ACPI_BUTTON_HID_POWER; 01302 uid = static_uid_buffer; 01303 sprintf(uid, "%d", (PowerButtonCount++)); 01304 break; 01305 case ACPI_BUS_TYPE_POWER_BUTTONF: 01306 hid = ACPI_BUTTON_HID_POWERF; 01307 uid = static_uid_buffer; 01308 sprintf(uid, "%d", (FixedPowerButtonCount++)); 01309 break; 01310 case ACPI_BUS_TYPE_SLEEP_BUTTON: 01311 hid = ACPI_BUTTON_HID_SLEEP; 01312 uid = static_uid_buffer; 01313 sprintf(uid, "%d", (SleepButtonCount++)); 01314 break; 01315 case ACPI_BUS_TYPE_SLEEP_BUTTONF: 01316 hid = ACPI_BUTTON_HID_SLEEPF; 01317 uid = static_uid_buffer; 01318 sprintf(uid, "%d", (FixedSleepButtonCount++)); 01319 break; 01320 } 01321 01322 /* 01323 * \_SB 01324 * ---- 01325 * Fix for the system root bus device -- the only root-level device. 01326 */ 01327 if (((ACPI_HANDLE)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { 01328 hid = ACPI_BUS_HID; 01329 sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME); 01330 sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS); 01331 } 01332 01333 if (hid) { 01334 sprintf(device->pnp.hardware_id, "%s", hid); 01335 device->flags.hardware_id = 1; 01336 } 01337 if (uid) { 01338 sprintf(device->pnp.unique_id, "%s", uid); 01339 device->flags.unique_id = 1; 01340 } 01341 01342 /* 01343 * If we called get_object_info, we now are finished with the buffer, 01344 * so we can free it. 01345 */ 01346 //if (buffer.Pointer) 01347 //AcpiOsFree(buffer.Pointer); 01348 01349 /* 01350 * Power Management 01351 * ---------------- 01352 */ 01353 if (device->flags.power_manageable) { 01354 result = acpi_bus_get_power_flags(device); 01355 if (result) 01356 goto end; 01357 } 01358 01359 /* 01360 * Performance Management 01361 * ---------------------- 01362 */ 01363 if (device->flags.performance_manageable) { 01364 result = acpi_bus_get_perf_flags(device); 01365 if (result) 01366 goto end; 01367 } 01368 01369 /* 01370 * Context 01371 * ------- 01372 * Attach this 'struct acpi_device' to the ACPI object. This makes 01373 * resolutions from handle->device very efficient. Note that we need 01374 * to be careful with fixed-feature devices as they all attach to the 01375 * root object. 01376 */ 01377 switch (type) { 01378 case ACPI_BUS_TYPE_POWER_BUTTON: 01379 case ACPI_BUS_TYPE_POWER_BUTTONF: 01380 case ACPI_BUS_TYPE_SLEEP_BUTTON: 01381 case ACPI_BUS_TYPE_SLEEP_BUTTONF: 01382 break; 01383 default: 01384 status = AcpiAttachData(device->handle, 01385 acpi_bus_data_handler, device); 01386 break; 01387 } 01388 if (ACPI_FAILURE(status)) { 01389 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 01390 "Error attaching device data\n")); 01391 result = AE_NOT_FOUND; 01392 goto end; 01393 } 01394 01395 /* 01396 * Linkage 01397 * ------- 01398 * Link this device to its parent and siblings. 01399 */ 01400 INIT_LIST_HEAD(&device->children); 01401 if (!device->parent) 01402 INIT_LIST_HEAD(&device->node); 01403 else 01404 list_add_tail(&device->node, &device->parent->children); 01405 01406 /* 01407 * Global Device Hierarchy: 01408 * ------------------------ 01409 * Register this device with the global device hierarchy. 01410 */ 01411 acpi_device_register(device, parent); 01412 01413 /* 01414 * Bind _ADR-Based Devices 01415 * ----------------------- 01416 * If there's a a bus address (_ADR) then we utilize the parent's 01417 * 'bind' function (if exists) to bind the ACPI- and natively- 01418 * enumerated device representations. 01419 */ 01420 if (device->flags.bus_address) { 01421 if (device->parent && device->parent->ops.bind) 01422 device->parent->ops.bind(device); 01423 } 01424 01425 /* 01426 * Locate & Attach Driver 01427 * ---------------------- 01428 * If there's a hardware id (_HID) or compatible ids (_CID) we check 01429 * to see if there's a driver installed for this kind of device. Note 01430 * that drivers can install before or after a device is enumerated. 01431 * 01432 * TBD: Assumes LDM provides driver hot-plug capability. 01433 */ 01434 if (device->flags.hardware_id || device->flags.compatible_ids) 01435 acpi_bus_find_driver(device); 01436 01437 end: 01438 if (result) { 01439 if (device->pnp.cid_list) { 01440 ExFreePoolWithTag(device->pnp.cid_list, 'IPCA'); 01441 } 01442 ExFreePoolWithTag(device, 'IPCA'); 01443 return_VALUE(result); 01444 } 01445 *child = device; 01446 01447 return_VALUE(0); 01448 } 01449 01450 01451 static int 01452 acpi_bus_remove ( 01453 struct acpi_device *device, 01454 int type) 01455 { 01456 01457 if (!device) 01458 return_VALUE(AE_NOT_FOUND); 01459 01460 acpi_device_unregister(device); 01461 01462 if (device && device->pnp.cid_list) 01463 ExFreePoolWithTag(device->pnp.cid_list, 'IPCA'); 01464 01465 if (device) 01466 ExFreePoolWithTag(device, 'IPCA'); 01467 01468 return_VALUE(0); 01469 } 01470 01471 01472 int 01473 acpi_bus_scan ( 01474 struct acpi_device *start) 01475 { 01476 ACPI_STATUS status = AE_OK; 01477 struct acpi_device *parent = NULL; 01478 struct acpi_device *child = NULL; 01479 ACPI_HANDLE phandle = 0; 01480 ACPI_HANDLE chandle = 0; 01481 ACPI_OBJECT_TYPE type = 0; 01482 UINT32 level = 1; 01483 01484 if (!start) 01485 return_VALUE(AE_BAD_PARAMETER); 01486 01487 parent = start; 01488 phandle = start->handle; 01489 01490 /* 01491 * Parse through the ACPI namespace, identify all 'devices', and 01492 * create a new 'struct acpi_device' for each. 01493 */ 01494 while ((level > 0) && parent) { 01495 01496 status = AcpiGetNextObject(ACPI_TYPE_ANY, phandle, 01497 chandle, &chandle); 01498 01499 /* 01500 * If this scope is exhausted then move our way back up. 01501 */ 01502 if (ACPI_FAILURE(status)) { 01503 level--; 01504 chandle = phandle; 01505 AcpiGetParent(phandle, &phandle); 01506 if (parent->parent) 01507 parent = parent->parent; 01508 continue; 01509 } 01510 01511 status = AcpiGetType(chandle, &type); 01512 if (ACPI_FAILURE(status)) 01513 continue; 01514 01515 /* 01516 * If this is a scope object then parse it (depth-first). 01517 */ 01518 if (type == ACPI_TYPE_LOCAL_SCOPE) { 01519 level++; 01520 phandle = chandle; 01521 chandle = 0; 01522 continue; 01523 } 01524 01525 /* 01526 * We're only interested in objects that we consider 'devices'. 01527 */ 01528 switch (type) { 01529 case ACPI_TYPE_DEVICE: 01530 type = ACPI_BUS_TYPE_DEVICE; 01531 break; 01532 case ACPI_TYPE_PROCESSOR: 01533 type = ACPI_BUS_TYPE_PROCESSOR; 01534 break; 01535 case ACPI_TYPE_THERMAL: 01536 type = ACPI_BUS_TYPE_THERMAL; 01537 break; 01538 case ACPI_TYPE_POWER: 01539 type = ACPI_BUS_TYPE_POWER; 01540 break; 01541 default: 01542 continue; 01543 } 01544 01545 status = acpi_bus_add(&child, parent, chandle, type); 01546 if (ACPI_FAILURE(status)) 01547 continue; 01548 01549 /* 01550 * If the device is present, enabled, and functioning then 01551 * parse its scope (depth-first). Note that we need to 01552 * represent absent devices to facilitate PnP notifications 01553 * -- but only the subtree head (not all of its children, 01554 * which will be enumerated when the parent is inserted). 01555 * 01556 * TBD: Need notifications and other detection mechanisms 01557 * in place before we can fully implement this. 01558 */ 01559 if (child->status.present) { 01560 status = AcpiGetNextObject(ACPI_TYPE_ANY, chandle, 01561 0, NULL); 01562 if (ACPI_SUCCESS(status)) { 01563 level++; 01564 phandle = chandle; 01565 chandle = 0; 01566 parent = child; 01567 } 01568 } 01569 } 01570 01571 return_VALUE(0); 01572 } 01573 01574 01575 static int 01576 acpi_bus_scan_fixed ( 01577 struct acpi_device *root) 01578 { 01579 int result = 0; 01580 struct acpi_device *device = NULL; 01581 01582 if (!root) 01583 return_VALUE(AE_NOT_FOUND); 01584 01585 /* If ACPI_FADT_POWER_BUTTON is set, then a control 01586 * method power button is present. Otherwise, a fixed 01587 * power button is present. 01588 */ 01589 if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) 01590 result = acpi_bus_add(&device, acpi_root, 01591 NULL, ACPI_BUS_TYPE_POWER_BUTTON); 01592 else 01593 { 01594 /* Enable the fixed power button so we get notified if it is pressed */ 01595 AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1); 01596 01597 result = acpi_bus_add(&device, acpi_root, 01598 NULL, ACPI_BUS_TYPE_POWER_BUTTONF); 01599 } 01600 01601 /* This one is a bit more complicated and we do it wrong 01602 * right now. If ACPI_FADT_SLEEP_BUTTON is set but no 01603 * device object is present then no sleep button is present, but 01604 * if the flags is clear and there is no device object then it is 01605 * a fixed sleep button. If the flag is set and there is a device object 01606 * the we have a control method button just like above. 01607 */ 01608 if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) 01609 result = acpi_bus_add(&device, acpi_root, 01610 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); 01611 else 01612 { 01613 /* Enable the fixed sleep button so we get notified if it is pressed */ 01614 AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE, 1); 01615 01616 result = acpi_bus_add(&device, acpi_root, 01617 NULL, ACPI_BUS_TYPE_SLEEP_BUTTONF); 01618 } 01619 01620 return_VALUE(result); 01621 } 01622 01623 01624 /* -------------------------------------------------------------------------- 01625 Initialization/Cleanup 01626 -------------------------------------------------------------------------- */ 01627 01628 int 01629 acpi_bus_init (void) 01630 { 01631 int result = 0; 01632 ACPI_STATUS status = AE_OK; 01633 01634 DPRINT("acpi_bus_init"); 01635 01636 KeInitializeDpc(&event_dpc, acpi_bus_generate_event_dpc, NULL); 01637 01638 status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); 01639 if (ACPI_FAILURE(status)) { 01640 DPRINT1("Unable to start the ACPI Interpreter\n"); 01641 goto error1; 01642 } 01643 01644 /* 01645 * ACPI 2.0 requires the EC driver to be loaded and work before 01646 * the EC device is found in the namespace. This is accomplished 01647 * by looking for the ECDT table, and getting the EC parameters out 01648 * of that. 01649 */ 01650 //result = acpi_ec_ecdt_probe(); 01651 /* Ignore result. Not having an ECDT is not fatal. */ 01652 01653 status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); 01654 if (ACPI_FAILURE(status)) { 01655 DPRINT1("Unable to initialize ACPI objects\n"); 01656 goto error1; 01657 } 01658 01659 /* 01660 * Maybe EC region is required at bus_scan/acpi_get_devices. So it 01661 * is necessary to enable it as early as possible. 01662 */ 01663 //acpi_boot_ec_enable(); 01664 01665 /* Initialize sleep structures */ 01666 //acpi_sleep_init(); 01667 01668 /* 01669 * Register the for all standard device notifications. 01670 */ 01671 status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); 01672 if (ACPI_FAILURE(status)) { 01673 DPRINT1("Unable to register for device notifications\n"); 01674 result = AE_NOT_FOUND; 01675 goto error1; 01676 } 01677 01678 /* 01679 * Create the root device in the bus's device tree 01680 */ 01681 result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 01682 ACPI_BUS_TYPE_SYSTEM); 01683 if (result) 01684 goto error2; 01685 01686 01687 /* 01688 * Enumerate devices in the ACPI namespace. 01689 */ 01690 result = acpi_bus_scan_fixed(acpi_root); 01691 if (result) 01692 DPRINT1("acpi_bus_scan_fixed failed\n"); 01693 result = acpi_bus_scan(acpi_root); 01694 if (result) 01695 DPRINT1("acpi_bus_scan failed\n"); 01696 01697 return_VALUE(0); 01698 01699 /* Mimic structured exception handling */ 01700 error2: 01701 AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, 01702 ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); 01703 error1: 01704 AcpiTerminate(); 01705 return_VALUE(AE_NOT_FOUND); 01706 } 01707 01708 static void 01709 acpi_bus_exit (void) 01710 { 01711 ACPI_STATUS status = AE_OK; 01712 01713 DPRINT("acpi_bus_exit"); 01714 01715 status = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, 01716 ACPI_SYSTEM_NOTIFY, acpi_bus_notify); 01717 if (ACPI_FAILURE(status)) 01718 DPRINT1("Error removing notify handler\n"); 01719 01720 #ifdef CONFIG_ACPI_PCI 01721 acpi_pci_root_exit(); 01722 acpi_pci_link_exit(); 01723 #endif 01724 #ifdef CONFIG_ACPI_EC 01725 acpi_ec_exit(); 01726 #endif 01727 //acpi_power_exit(); 01728 acpi_system_exit(); 01729 01730 acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); 01731 01732 status = AcpiTerminate(); 01733 if (ACPI_FAILURE(status)) 01734 DPRINT1("Unable to terminate the ACPI Interpreter\n"); 01735 else 01736 DPRINT1("Interpreter disabled\n"); 01737 01738 return_VOID; 01739 } 01740 01741 01742 int 01743 acpi_init (void) 01744 { 01745 int result = 0; 01746 01747 DPRINT("acpi_init"); 01748 01749 DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION); 01750 01751 KeInitializeSpinLock(&acpi_bus_event_lock); 01752 KeInitializeEvent(&AcpiEventQueue, NotificationEvent, FALSE); 01753 ExInitializeFastMutex(&acpi_bus_drivers_lock); 01754 01755 result = acpi_bus_init(); 01756 01757 //if (!result) { 01758 //pci_mmcfg_late_init(); 01759 //if (!(pm_flags & PM_APM)) 01760 // pm_flags |= PM_ACPI; 01761 //else { 01762 //DPRINT1("APM is already active, exiting\n"); 01763 //disable_acpi(); 01764 //result = -ENODEV; 01765 //} 01766 //} else 01767 // disable_acpi(); 01768 01769 /* 01770 * If the laptop falls into the DMI check table, the power state check 01771 * will be disabled in the course of device power transistion. 01772 */ 01773 //dmi_check_system(power_nocheck_dmi_table); 01774 01775 /* 01776 * Install drivers required for proper enumeration of the 01777 * ACPI namespace. 01778 */ 01779 acpi_system_init(); /* ACPI System */ 01780 acpi_power_init(); /* ACPI Bus Power Management */ 01781 acpi_button_init(); 01782 //acpi_ec_init(); /* ACPI Embedded Controller */ 01783 #ifdef CONFIG_ACPI_PCI 01784 if (!acpi_pci_disabled) { 01785 acpi_pci_link_init(); /* ACPI PCI Interrupt Link */ 01786 acpi_pci_root_init(); /* ACPI PCI Root Bridge */ 01787 } 01788 #endif 01789 01790 //acpi_scan_init(); 01791 //acpi_ec_init(); 01792 //acpi_power_init(); 01793 //acpi_system_init(); 01794 //acpi_debug_init(); 01795 //acpi_sleep_proc_init(); 01796 //acpi_wakeup_device_init(); 01797 01798 return result; 01799 } 01800 01801 01802 void 01803 acpi_exit (void) 01804 { 01805 DPRINT("acpi_exit"); 01806 01807 #ifdef CONFIG_PM 01808 pm_active = 0; 01809 #endif 01810 01811 acpi_bus_exit(); 01812 01813 return_VOID; 01814 } 01815 Generated on Sat May 26 2012 04:25:58 for ReactOS by
1.7.6.1
|