ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

bus.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.