/*++

Copyright (c) 1997  Microsoft Corporation

Module Name:

    acpi.c

Abstract:

    WinDbg Extension Api for interpretting ACPI data structures

Author:

    Stephane Plante (splante) 21-Mar-1997

    Based on Code by:
        Peter Wieland (peterwie) 16-Oct-1995

Environment:

    User Mode.

Revision History:

--*/

#include "pch.h"
UCHAR       Buffer[2048];
PCCHAR      DeviceStateTable[] = {
    "Stopped",
    "Inactive",
    "Started",
    "Removed",
    "SurpriseRemoved",
    "Invalid",
};
PCCHAR      DevicePowerStateTable[] = {
    "PowerDeviceUnspecified",
    "PowerDeviceD0",
    "PowerDeviceD1",
    "PowerDeviceD2",
    "PowerDeviceD3",
    "PowerDeviceMaximum",
};
PCCHAR      SystemPowerStateTable[] = {
    "PowerSystemUnspecified",
    "PowerSystemWorking",
    "PowerSystemSleepingS1",
    "PowerSystemSleepingS2",
    "PowerSystemSleepingS3",
    "PowerSystemHibernate",
    "PowerSystemShutdown",
    "PowerSystemMaximum",
};
PCCHAR      SystemPowerActionTable[] = {
    "PowerActionNone",
    "PowerActionReserved",
    "PowerActionSleep",
    "PowerActionHibernate",
    "PowerActionShutdown",
    "PowerActionShutdownReset",
    "PowerActionShutdownOff",
    "PowerActionWarmEject"
};
CCHAR       ReallyShortDevicePowerStateTable[] = {
    'W',
    '0',
    '1',
    '2',
    '3',
    'M',
};
PCCHAR      ShortDevicePowerStateTable[] = {
    "Dw",
    "D0",
    "D1",
    "D2",
    "D3",
    "Dmax",
};
CCHAR       ReallyShortSystemPowerStateTable[] = {
    'W',
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    'M',
};
PCCHAR      ShortSystemPowerStateTable[] = {
    "Sx",
    "S0",
    "S1",
    "S2",
    "S3",
    "S4",
    "S5",
    "SM",
};
PCCHAR     WorkDone[] = {
    "Complete",
    "Pending",
    "Failure",
    "Step 0",
    "Step 1",
    "Step 2",
    "Step 3",
    "Step 4",
    "Step 5",
    "Step 6",
    "Step 7",
    "Step 8",
    "Step 9",
    "Step 10",
    "Step 11",
    "Step 12",
    "Step 13",
    "Step 14",
    "Step 15",
    "Step 16",
    "Step 17",
    "Step 18",
    "Step 19",
    "Step 20",
    "Step 21",
    "Step 22",
    "Step 23",
    "Step 24",
    "Step 25",
    "Step 26",
};

FLAG_RECORD DeviceExtensionButtonEventFlags[] = {
    { 0x00000001, "Pwr", "\"Power Button\"" , NULL, NULL },
    { 0x00000002, "Slp", "\"Sleep Button\"" , NULL, NULL },
    { 0x00000004, "Lid", "\"Lid Switch\"" , NULL, NULL },
    { 0x80000000, "Wake", "\"Wake Capable\"" , NULL, NULL },
};

FLAG_RECORD DeviceExtensionFlags[] = {
    { 0x0000000000000001, "Nev",   "NeverPresent" , NULL, NULL },
    { 0x0000000000000002, "!P" ,   "NotPresent" , NULL, NULL },
    { 0x0000000000000004, "Rmv",   "Removed" , NULL, NULL },
    { 0x0000000000000008, "!F" ,   "NotFound" , NULL, NULL },
    { 0x0000000000000010, "Fdo",   "FunctionalDeviceObject" , NULL, NULL  },
    { 0x0000000000000020, "Pdo",   "PhysicalDeviceObject" , NULL, NULL },
    { 0x0000000000000040, "Fil",   "Filter" , NULL, NULL },
    { 0x0000000000010000, "Wak",   "Wake" , NULL, NULL },
    { 0x0000000000020000, "Raw",   "RawOK" , NULL, NULL },
    { 0x0000000000040000, "But",   "Button" , NULL, NULL },
    { 0x0000000000080000, "PS0",   "AlwaysOn" , NULL, NULL },
    { 0x0000000000100000, "!Fil",  "NeverFilter" , NULL, NULL },
    { 0x0000000000200000, "!Stop", "NeverStop" , NULL, NULL },
    { 0x0000000000400000, "!Off",  "NeverOverrideOff" , NULL, NULL },
    { 0x0000000000800000, "ISA",   "ISABus" , NULL, NULL },
    { 0x0000000001000000, "EIO",   "EIOBus" , NULL, NULL },
    { 0x0000000002000000, "PCI",   "PCIBus" , NULL, NULL },
    { 0x0000000004000000, "Ser",   "SerialPort" , NULL, NULL },
    { 0x0000000008000000, "Tz",    "ThermalZone" , NULL, NULL },
    { 0x0000000010000000, "Lnk",   "LinkNode" , NULL, NULL },
    { 0x0000000020000000, "!UI",   "NoShowInUI" , NULL, NULL },
    { 0x0000000040000000, "!!UI",  "NeverShowInUI" , NULL, NULL },
    { 0x0000000080000000, "D3",    "StartInD3" , NULL, NULL },
    { 0x0000000100000000, "pci",   "PCIDevice" , NULL, NULL },
    { 0x0000000200000000, "PIC",   "ProgrammableInterruptController" , NULL, NULL },
    { 0x0000000400000000, "Dock-", "UnattachedDock" , NULL, NULL },
    { 0x0000100000000000, "Adr",   "HasAddress" , NULL, NULL },
    { 0x0000200000000000, "HID",   "HasHardwareID" , NULL, NULL },
    { 0x0000400000000000, "UID",   "HasUniqueID" , NULL, NULL },
    { 0x0000800000000000, "hid",   "FakeHardwareID" , NULL, NULL },
    { 0x0001000000000000, "uid",   "FakeUniqueID" , NULL, NULL },
    { 0x0002000000000000, "BAD",   "FailedInit" , NULL, NULL },
    { 0x0004000000000000, "SRS",   "Programmable" , NULL, NULL },
    { 0x0008000000000000, "Fake",  "NoAcpiObject" , NULL, NULL },
    { 0x0010000000000000, "Excl",  "Exclusive" , NULL, NULL },
    { 0x0020000000000000, "Ini",   "RanINI" , NULL, NULL },
    { 0x0040000000000000, "Ena",   "Enabled" , "!Ena", "NotEnabled" },
    { 0x0080000000000000, "BAD",   "Failed" , NULL, NULL },
    { 0x0100000000000000, "Pwr",   "AcpiPower" , NULL, NULL },
    { 0x0200000000000000, "Dock",  "DockProfile" , NULL, NULL },
    { 0x0400000000000000, "S->D",  "BuiltPowerTables" , NULL, NULL },
    { 0x0800000000000000, "PME",   "UsesPME" , NULL, NULL },
    { 0x1000000000000000, "!Lid",  "NoLidAction" , NULL, NULL },
};

FLAG_RECORD DeviceExtensionThermalFlags[] = {
    { 0x00000001, "Cooling", "\"Cooling Level\"" , NULL, NULL },
    { 0x00000002, "Temp", "Temp" , NULL, NULL },
    { 0x00000004, "Trip", "\"Trip Points\"" , NULL, NULL },
    { 0x00000008, "Mode", "Mode" , NULL, NULL },
    { 0x00000010, "Init", "Initialize" , NULL, NULL },
    { 0x20000000, "Wait", "\"Wait for Notify\"" , NULL, NULL },
    { 0x40000000, "Busy", "Busy" , NULL, NULL },
    { 0x80000000, "Loop", "\"In Service Loop\"" , NULL, NULL },
};

FLAG_RECORD PM1ControlFlags[] = {
    { 0x0001, "", "SCI_EN" , NULL, NULL },
    { 0x0002, "", "BM_RLD" , NULL, NULL },
    { 0x0004, "", "GBL_RLS" , NULL, NULL },
    { 0x0400, "", "SLP_TYP0" , NULL, NULL },
    { 0x0800, "", "SLP_TYP1" , NULL, NULL },
    { 0x1000, "", "SLP_TYP2" , NULL, NULL  },
    { 0x2000, "", "SLP_EN" , NULL, NULL  },
};

FLAG_RECORD PM1StatusFlags[] = {
    { 0x0001, "", "TMR_STS" , NULL, NULL },
    { 0x0010, "", "BM_STS" , NULL, NULL },
    { 0x0020, "", "GBL_STS" , NULL, NULL },
    { 0x0100, "", "PWRBTN_STS" , NULL, NULL },
    { 0x0200, "", "SLPBTN_STS" , NULL, NULL },
    { 0x0400, "", "RTC_STS" , NULL, NULL },
    { 0x8000, "", "WAK_STS" , NULL, NULL },
};

FLAG_RECORD PM1EnableFlags[] = {
    { 0x0001, "", "TMR_EN" , NULL, NULL },
    { 0x0020, "", "GBL_EN" , NULL, NULL },
    { 0x0100, "", "PWRBTN_EN" , NULL, NULL },
    { 0x0200, "", "SLPBTN_EN" , NULL, NULL },
    { 0x0400, "", "RTC_EN" , NULL, NULL },
};

FLAG_RECORD PowerNodeFlags[] = {
    { 0x00001, "PO", "Present" , NULL, NULL },
    { 0x00002, "Init", "Initialized" , NULL, NULL },
    { 0x00004, "!STA", "\"Status Unknown\"" , NULL, NULL },
    { 0x00010, "On", "On" , "Off", "Off" },
    { 0x00020, "On+", "OverrideOn" , NULL, NULL },
    { 0x00040, "Off-", "OverrideOff" , NULL, NULL },
    { 0x00200, "On++", "AlwaysOn" , NULL, NULL },
    { 0x00400, "Off--", "AlwaysOff" , NULL, NULL },
    { 0x10000, "Fail", "Failed" , NULL, NULL },
    { 0x20000, "Hiber", "HibernatePath" , NULL, NULL },
};

FLAG_RECORD PowerRequestFlags[] = {
    { 0x00001, "Dly",  "Delayed", NULL, NULL },
    { 0x00002, "!Q",   "NoQueue", NULL, NULL },
    { 0x00004, "Lck",  "LockDevice", NULL, NULL },
    { 0x00008, "!Lck", "UnlockDevice", NULL, NULL },
    { 0x00010, "+Hbr", "LockHiber", NULL, NULL },
    { 0x00020, "-Hbr", "UnlockHiber", NULL, NULL },
    { 0x00040, "Can",  "HasCancel", NULL, NULL },
};

VOID
displayAcpiDeviceExtension(
    IN  PDEVICE_EXTENSION   DeviceExtension,
    IN  ULONG_PTR           Address,
    IN  ULONG               Verbose,
    IN  ULONG               IndentLevel
    )
/*++

Routine Description:

    This routine is responsible for displaying a device extension

Arguments:

    DeviceExtension - Extension to display
    Address         - Where the extension lives in memory
    Verbose         - How much information to display
    IndentLevel     - How much to tab it over

Return Value:

    None

--*/
{
    BOOL                b;
    DEVICE_POWER_STATE  k;
    DWORD_PTR           displacement;
    IRP_DISPATCH_TABLE  dispatchTable;
    PACPI_POWER_INFO    powerInfo;
    SYSTEM_POWER_STATE  s;
    UCHAR               indent[80];
    ULONG               i,j;
    ULONG               returnLength;

    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';
    powerInfo = &(DeviceExtension->PowerInfo);

    //
    // Check signature
    //
    if (DeviceExtension->Signature != ACPI_SIGNATURE) {

        dprintf(
            "%s  Unknown Signature. This does appear to be an "
            "ACPI Extension\n",
            indent
            );
        return;

    }

    //
    // Line #1
    //
    dprintf("%sACPI DeviceExtension - %lx - ",indent, Address);
    displayAcpiDeviceExtensionName( Address );
#if 0
    if (DeviceExtension->Flags & DEV_PROP_HID) {

        if (DeviceExtension->DeviceID != NULL) {

            memset( Buffer, '0', 2048 );
            b = ReadMemory(
                (ULONG_PTR) DeviceExtension->DeviceID,
                Buffer,
                32,
                &returnLength
                );
            if (!b || Buffer[0] == '\0') {

                dprintf(" (%lx)", DeviceExtension->DeviceID );

            } else {

                dprintf(" %s", Buffer );

            }

        } else {

            dprintf( " NULL" );

        }
        if (DeviceExtension->Flags & DEV_PROP_UID) {

            if (DeviceExtension->InstanceID) {

                memset( Buffer, '0', 256 );
                b = ReadMemory(
                    (ULONG_PTR) DeviceExtension->InstanceID,
                    Buffer,
                    256,
                    &returnLength);
                if (!b || returnLength != 256 || Buffer[0] == '\0') {

                    dprintf(" [ (%lx) ]", DeviceExtension->InstanceID );

                } else {

                    dprintf(" [%s]", Buffer );

                }

            } else {

                dprintf(" [NULL]");

            }

        }

    } else if (DeviceExtension->Flags & DEV_PROP_ADDRESS) {

        dprintf(" %lx", DeviceExtension->Address );

    }
#endif
    dprintf("\n");

    //
    // Line #2
    //
    dprintf(
        "%s  DevObj     %8lx   PhysicalObj  %8lx   ",
        indent,
        DeviceExtension->DeviceObject,
        DeviceExtension->PhysicalDeviceObject
        );
    if (DeviceExtension->TargetDeviceObject != NULL) {

        dprintf("AttachedTo %8lx", DeviceExtension->TargetDeviceObject );

    }
    dprintf("\n");

    //
    // Line #3
    //
    dprintf(
        "%s  AcpiObject %8lx   ParentExt    %8lx\n",
        indent,
        DeviceExtension->AcpiObject,
        DeviceExtension->ParentExtension
        );

    //
    // Line #4
    //
    dprintf(
        "%s  PnpState   %-8s   OldPnpState  %-8s\n",
        indent,
        DeviceStateTable[DeviceExtension->DeviceState],
        DeviceStateTable[DeviceExtension->PreviousState]
        );

    //
    // Line #4
    //
    dprintf("%s  ",indent);
    if (DeviceExtension->ResourceList != NULL) {

        dprintf("CmResList  %lx   ", DeviceExtension->ResourceList );

    } else {

        dprintf("                      ");

    }
    if (DeviceExtension->PnpResourceList != NULL) {

        dprintf("PnpResList   %lx   ", DeviceExtension->PnpResourceList );

    } else {

        dprintf("                        ");

    }

    dprintf(
        "RefCounts  %dD %dI %dH %dW\n",
        DeviceExtension->ReferenceCount,
        DeviceExtension->OutstandingIrpCount,
        DeviceExtension->HibernatePathCount,
        powerInfo->WakeSupportCount
        );

    //
    // Line #5
    //
    if (DeviceExtension->Flags & DEV_PROP_DOCK) {

        dprintf( "%s  Dock       %8lx   ", indent, DeviceExtension->Dock );

    } else {

        dprintf( "%s                        ", indent );

    }
    dprintf(
        "Dispatch     %8lx   ",
        DeviceExtension->DispatchTable
        );
    if (DeviceExtension->RemoveEvent != NULL) {

        dprintf("Remove %lx", DeviceExtension->RemoveEvent);

    }
    dprintf("\n");

    //
    // Line #6
    //
    if (powerInfo->DeviceNotifyHandler != NULL) {

        GetSymbol(
            powerInfo->DeviceNotifyHandler,
            Buffer,
            &displacement
            );
        dprintf(
            "%s  Handler    %lx   Context      %8lx   %s+%x\n",
            indent,
            powerInfo->DeviceNotifyHandler,
            powerInfo->Context,
            Buffer,
            displacement
            );

    }

    //
    // Line #7-12
    //
    for (k = PowerDeviceUnspecified; k <= PowerDeviceD3; k++) {

        if (k < PowerDeviceD3) {

            if (powerInfo->PowerObject[k] == NULL &&
                powerInfo->PowerNode[k] == NULL) {

                continue;

            }

        } else {

            if (powerInfo->PowerObject[k] == NULL) {

                continue;

            }

        }

        //
        // Did we print on this line?
        //
        b = FALSE;
        dprintf("%s  ", indent);
        if (powerInfo->PowerObject[k] != NULL) {

            dprintf(
                "_PS%c       %lx   ",
                ReallyShortDevicePowerStateTable[k],
                powerInfo->PowerObject[k]
                );
            b = TRUE;

        }
        if (k <= PowerDeviceD2 && powerInfo->PowerNode[k] != NULL) {

            if (b) {

                dprintf(
                    "%s Nodes     %lx   ",
                    ShortDevicePowerStateTable[k],
                    powerInfo->PowerNode[k]
                    );

            } else {

                dprintf(
                    "%s Nodes   %lx   ",
                    ShortDevicePowerStateTable[k],
                    powerInfo->PowerNode[k]
                    );

            }

        }
        dprintf("\n");

    }

    //
    // Line #13
    //
    dprintf( "%s  State      %-2s", indent, ShortDevicePowerStateTable[powerInfo->PowerState]);
    if (powerInfo->DesiredPowerState != powerInfo->PowerState) {

        dprintf("->%-4s   ", ShortDevicePowerStateTable[powerInfo->DesiredPowerState]);

    } else {

        dprintf("         ");

    }
    dprintf("SxD Mapping  ");
    for (s = PowerSystemWorking; s < PowerSystemMaximum; s++) {

        k = powerInfo->DevicePowerMatrix[s];
        if (k == PowerDeviceUnspecified) {

            continue;

        }
        dprintf(
            "S%c->D%c ",
            ReallyShortSystemPowerStateTable[s],
            ReallyShortDevicePowerStateTable[k]
            );

    }
    dprintf("\n");

    //
    // Line #14
    //
    if (DeviceExtension->Flags & DEV_CAP_WAKE) {

        //
        // Print the start of the line
        //
        dprintf("%s      ", indent);

        s = powerInfo->SystemWakeLevel;
        if (s == PowerSystemUnspecified) {

            dprintf("Sw->Sx " );

        } else {

            dprintf("Sw->S%c ", ReallyShortSystemPowerStateTable[s] );

        }

        k = DeviceExtension->PowerInfo.DeviceWakeLevel;
        if (k == PowerDeviceUnspecified) {

            dprintf("Dw->Dx " );

        } else {

            dprintf("Dw->D%c ", ReallyShortDevicePowerStateTable[k] );

        }
        dprintf(
            "    Wake Pin     %8d   WakeCount  %8x\n",
            powerInfo->WakeBit,
            powerInfo->WakeSupportCount
            );

    }

    //
    // Line #15
    //
    if (powerInfo->CurrentPowerRequest != NULL) {

        dprintf(
            "%s  CurrentReq %lx   ",
            indent,
            powerInfo->CurrentPowerRequest
            );
        if (powerInfo->PowerRequestListEntry.Flink !=
            (PLIST_ENTRY) (Address + FIELD_OFFSET(DEVICE_EXTENSION, PowerInfo.PowerRequestListEntry) ) ) {

            dprintf(
                "PowerReqList %lx %lx",
                CONTAINING_RECORD( powerInfo->PowerRequestListEntry.Flink, ACPI_POWER_REQUEST, SerialListEntry ),
                CONTAINING_RECORD( powerInfo->PowerRequestListEntry.Blink, ACPI_POWER_REQUEST, SerialListEntry )
                );

        }
        dprintf("\n");

    }

    //
    // At this point, we are done with the common bits, and now deal with the
    // special parts of the extension
    //
    if ( (DeviceExtension->Flags & DEV_TYPE_FDO) ) {

        dprintf(
            "%s  DPC Obj    %8lx   Int Object   %08lx\n",
            indent,
            (Address + FIELD_OFFSET(DEVICE_EXTENSION, Fdo.InterruptDpc) ),
            DeviceExtension->Fdo.InterruptObject
            );
        dprintf(
            "%s  PM1 Status %8lx\n",
            indent,
            DeviceExtension->Fdo.Pm1Status
            );
        dumpPM1StatusRegister( DeviceExtension->Fdo.Pm1Status, IndentLevel + 2 );

    }
    if ( (DeviceExtension->Flags & DEV_CAP_BUTTON) ) {

        dprintf(
            "%s  LidState   %-8s   SpinLock     %x   ",
            indent,
            (DeviceExtension->Button.LidState ? "TRUE" : "FALSE"),
            (Address + FIELD_OFFSET(DEVICE_EXTENSION, Button.SpinLock) )
        );
        if (DeviceExtension->Button.Events) {

            dumpFlags(
                (DeviceExtension->Button.Events),
                &DeviceExtensionButtonEventFlags[0],
                sizeof(DeviceExtensionButtonEventFlags)/sizeof(FLAG_RECORD),
                IndentLevel,
                (DUMP_FLAG_SHORT_NAME | DUMP_FLAG_NO_INDENT |
                 DUMP_FLAG_SINGLE_LINE | DUMP_FLAG_NO_EOL)
                );

        }
        dprintf("\n");

        if (DeviceExtension->Button.Capabilities) {

            dprintf(
                "%s  Capability %lx   ",
                indent,
                DeviceExtension->Button.Capabilities
                );
            dumpFlags(
                (DeviceExtension->Button.Capabilities),
                &DeviceExtensionButtonEventFlags[0],
                sizeof(DeviceExtensionButtonEventFlags)/sizeof(FLAG_RECORD),
                IndentLevel,
                (DUMP_FLAG_LONG_NAME | DUMP_FLAG_NO_INDENT |
                 DUMP_FLAG_SINGLE_LINE | DUMP_FLAG_NO_EOL)
                );
            dprintf("\n");

        }

    }
    if ( (DeviceExtension->Flags & DEV_CAP_THERMAL_ZONE) ) {

        THRM_INFO   thrm;

        dprintf(
            "%s  Info       %lx   Flags        %8x   ",
            indent,
            DeviceExtension->Thermal.Info,
            DeviceExtension->Thermal.Flags
            );
        dumpFlags(
            (DeviceExtension->Thermal.Flags),
            &DeviceExtensionThermalFlags[0],
            sizeof(DeviceExtensionThermalFlags)/sizeof(FLAG_RECORD),
            IndentLevel,
            (DUMP_FLAG_SHORT_NAME | DUMP_FLAG_NO_INDENT |
             DUMP_FLAG_SINGLE_LINE | DUMP_FLAG_NO_EOL)
            );
        dprintf("\n");

        //
        // Read the thermal Information and print it
        //
        b = ReadMemory(
            (ULONG_PTR) DeviceExtension->Thermal.Info,
            &thrm,
            sizeof(THRM_INFO),
            &returnLength
            );
        if (!b || returnLength != sizeof(THRM_INFO)) {

            dprintf(
                "%s  Could not read THRM_INFO @ %08lx\n",
                indent,
                DeviceExtension->Thermal.Info
                );

        } else {

            displayThermalInfo(
                &thrm,
                (ULONG_PTR) DeviceExtension->Thermal.Info,
                Verbose,
                IndentLevel + 2
                );

        }
    }

    //
    // Last Line. At this point, we can dump the ACPI Flags
    //
    dprintf("%s  Flags      %016I64x ", indent, DeviceExtension->Flags );
    dumpFlags(
        (DeviceExtension->Flags),
        &DeviceExtensionFlags[0],
        sizeof(DeviceExtensionFlags)/sizeof(FLAG_RECORD),
        IndentLevel + 4,
        (DUMP_FLAG_SHORT_NAME | DUMP_FLAG_NO_INDENT |
         DUMP_FLAG_SINGLE_LINE)
        );
    dumpFlags(
        (DeviceExtension->Flags),
        &DeviceExtensionFlags[0],
        sizeof(DeviceExtensionFlags)/sizeof(FLAG_RECORD),
        IndentLevel + 4,
        (DUMP_FLAG_LONG_NAME)
        );

}

VOID
displayAcpiDeviceExtensionBrief(
    IN  PDEVICE_EXTENSION   DeviceExtension,
    IN  ULONG_PTR           Address,
    IN  ULONG               Verbose,
    IN  ULONG               IndentLevel
    )
/*++

Routine Description:

    This routine displays a one line summary of the device extension

Arguments:

    DeviceExtension - The extension to display
    Address         - Where the extension is located
    Verbose         - How much information to display
    IndentLevel     - How much whitespace to use

Return Value:

    VOID

--*/
{
    BOOL                b;
    PDEVICE_EXTENSION   deviceExtension;
    ULONG               address;
    ULONG               i;
    ULONG               returnLength;
    ULONG               startAddress;

    //
    // Should we print this extension?
    //
    if ( (Verbose & VERBOSE_PRESENT) &&
         (DeviceExtension->Flags & DEV_TYPE_NOT_FOUND) ) {

        return;

    }

    //
    // Make the IndentLevel 'relative' - Device By 4
    //
    IndentLevel /= 4;

    //
    // Indent the text
    //
    for (i = 0; i < IndentLevel; i++) {

        dprintf("| ");

    }

    //
    // Print the address of the object
    //
    dprintf("%08lx", Address );

    //
    // Try to get the name & instance
    //
    if (DeviceExtension->Flags & DEV_PROP_HID) {

        if (DeviceExtension->DeviceID) {

            memset( Buffer, '0', 2048 );
            b = ReadMemory(
                (ULONG_PTR) DeviceExtension->DeviceID,
                Buffer,
                256,
                &returnLength
                );
            if (b && Buffer[0] != '\0') {

                dprintf(" %s", Buffer );

            }

        } else {

            dprintf(" <Unknown HID>");

        }

        if (DeviceExtension->Flags & DEV_PROP_UID) {

            if (DeviceExtension->InstanceID) {

                memset( Buffer, '0', 2048 );
                b = ReadMemory(
                    (ULONG_PTR) DeviceExtension->InstanceID,
                    Buffer,
                    256,
                    &returnLength
                    );
                if (b && Buffer[0] != '\0') {

                    dprintf("(%s)", Buffer );

                }

            } else {

                dprintf(" <Unknown UID>");

            }

        }

    } else if (DeviceExtension->Flags & DEV_PROP_ADDRESS) {

        dprintf(" %lx", DeviceExtension->Address );

    } else {

        dprintf(" <NULL>");

    }

    if (Verbose & VERBOSE_THERMAL) {

        DEVICE_POWER_STATE  d;
        SYSTEM_POWER_STATE  s;

        if (DeviceExtension->PowerInfo.PowerState == 0) {

            dprintf(" Dx" );

        } else {

            dprintf(" D%d", (DeviceExtension->PowerInfo.PowerState - 1) );

        }

        for (s = PowerSystemWorking; s < PowerSystemMaximum; s++) {

            d = DeviceExtension->PowerInfo.DevicePowerMatrix[s];
            if (d == PowerDeviceUnspecified) {

                continue;

            }

            dprintf(
                " S%c->D%c",
                ReallyShortSystemPowerStateTable[s],
                ReallyShortDevicePowerStateTable[d]
                );

        }

        if (DeviceExtension->Flags & DEV_CAP_WAKE) {

            s = DeviceExtension->PowerInfo.SystemWakeLevel;
            if (s == PowerSystemUnspecified) {

                dprintf(" Sw->Sx" );

            } else {

                dprintf(" Sw->S%c", ReallyShortSystemPowerStateTable[s] );

            }

            d = DeviceExtension->PowerInfo.DeviceWakeLevel;
            if (d == PowerDeviceUnspecified) {

                dprintf(" Dw->Dx" );

            } else {

                dprintf(" Dw->D%c", ReallyShortDevicePowerStateTable[d] );

            }

        }

        //
        // If we are displaying thermal information, cut short early
        //
        dprintf("\n");
        return;

    }

    dprintf(" NS %08lx", DeviceExtension->AcpiObject );
    if (DeviceExtension->PowerInfo.PowerState == 0) {

        dprintf(" Dx" );

    } else {

        dprintf(" D%d", (DeviceExtension->PowerInfo.PowerState - 1) );

    }

    //
    // Print the device state
    //
    if (DeviceExtension->DeviceState == Stopped) {

        dprintf(" stop");

    } else if (DeviceExtension->DeviceState == Inactive) {

        dprintf(" inac");

    } else if (DeviceExtension->DeviceState == Started) {

        dprintf(" star");

    } else if (DeviceExtension->DeviceState == Removed) {

        dprintf(" remv");

    } else if (DeviceExtension->DeviceState == SurpriseRemoved) {

        dprintf(" surp");

    } else {

        dprintf(" inva");

    }
    dprintf(" %d-%d-%d",
        DeviceExtension->OutstandingIrpCount,
        DeviceExtension->ReferenceCount,
        DeviceExtension->HibernatePathCount
        );

    //
    // Display the flags
    //
    dumpFlags(
        (DeviceExtension->Flags),
        &DeviceExtensionFlags[0],
        sizeof(DeviceExtensionFlags)/sizeof(FLAG_RECORD),
        IndentLevel + 4,
        (DUMP_FLAG_SHORT_NAME | DUMP_FLAG_NO_INDENT |
         DUMP_FLAG_SINGLE_LINE)
        );

    // displayAcpiDeviceExtensionFlags( DeviceExtension );
}

VOID
displayAcpiDeviceExtensionFlags(
    IN  PDEVICE_EXTENSION   DeviceExtension
    )
/*++

Routine Description:

    This routine displays the Flag for a device extension

    This routine prints a new line at the end of the only line of text that
    it consumes

Arguments:

    DeviceExtension - The extension whose flags to dump

Return Value:

    None

--*/
{
    //
    // Dump the flags
    //
    if (DeviceExtension->Flags & DEV_TYPE_NEVER_PRESENT) {

        dprintf(" Nev");

    }
    if (DeviceExtension->Flags & DEV_TYPE_NOT_PRESENT) {

        dprintf(" N/P");

    }
    if (DeviceExtension->Flags & DEV_TYPE_REMOVED) {

        dprintf(" Rmv");

    }
    if (DeviceExtension->Flags & DEV_TYPE_NOT_FOUND) {

        dprintf(" N/F");

    }
    if (DeviceExtension->Flags & DEV_TYPE_FDO) {

        dprintf(" Fdo");

    }
    if (DeviceExtension->Flags & DEV_TYPE_PDO) {

        dprintf(" Pdo");

    }
    if (DeviceExtension->Flags & DEV_TYPE_FILTER) {

        dprintf(" Fil");

    }
    if (DeviceExtension->Flags & DEV_CAP_WAKE) {

        dprintf(" Wak");

    }
    if (DeviceExtension->Flags & DEV_CAP_RAW) {

        dprintf(" Raw");

    }
    if (DeviceExtension->Flags & DEV_CAP_BUTTON) {

        dprintf(" But");

    }
    if (DeviceExtension->Flags & DEV_CAP_ALWAYS_PS0) {

        dprintf(" PS0");

    }
    if (DeviceExtension->Flags & DEV_CAP_NO_FILTER) {

        dprintf(" !Fil");

    }
    if (DeviceExtension->Flags & DEV_CAP_NO_STOP) {

        dprintf(" !Stop");

    }
    if (DeviceExtension->Flags & DEV_CAP_NO_OVERRIDE) {

        dprintf(" !Off");

    }
    if (DeviceExtension->Flags & DEV_CAP_ISA) {

        dprintf(" Isa");

    }
    if (DeviceExtension->Flags & DEV_CAP_EIO) {

        dprintf(" Eio");

    }
    if (DeviceExtension->Flags & DEV_CAP_PCI) {

        dprintf(" Pci");

    }
    if (DeviceExtension->Flags & DEV_CAP_SERIAL) {

        dprintf(" Ser");

    }
    if (DeviceExtension->Flags & DEV_CAP_THERMAL_ZONE) {

        dprintf(" Thrm");

    }
    if (DeviceExtension->Flags & DEV_CAP_LINK_NODE) {

        dprintf(" Lnk");

    }
    if (DeviceExtension->Flags & DEV_CAP_NO_SHOW_IN_UI) {

        dprintf(" !UI");

    }
    if (DeviceExtension->Flags & DEV_CAP_NEVER_SHOW_IN_UI) {

        dprintf(" !!UI");

    }
    if (DeviceExtension->Flags & DEV_CAP_START_IN_D3) {

        dprintf(" D3");

    }
    if (DeviceExtension->Flags & DEV_CAP_PCI_DEVICE) {

        dprintf(" PciD");

    }
    if (DeviceExtension->Flags & DEV_CAP_PIC_DEVICE) {

        dprintf(" PIC");

    }
    if (DeviceExtension->Flags & DEV_CAP_UNATTACHED_DOCK) {

        dprintf(" Dock-");

    }
    if (DeviceExtension->Flags & DEV_PROP_ADDRESS) {

        dprintf(" Adr");

    }
    if (DeviceExtension->Flags & DEV_PROP_FIXED_HID) {

        dprintf(" FHid");

    } else if (DeviceExtension->Flags & DEV_PROP_HID) {

        dprintf(" Hid");

    }
    if (DeviceExtension->Flags & DEV_PROP_FIXED_UID) {

        dprintf(" FUid");

    } else if (DeviceExtension->Flags & DEV_PROP_UID) {

        dprintf(" Uid");

    }
    if (DeviceExtension->Flags & DEV_PROP_FAILED_INIT) {

        dprintf(" !INIT");

    }
    if (DeviceExtension->Flags & DEV_PROP_SRS_PRESENT) {

        dprintf(" SRS");

    }
    if (DeviceExtension->Flags & DEV_PROP_NO_OBJECT) {

        dprintf(" Fake");

    }
    if (DeviceExtension->Flags & DEV_PROP_EXCLUSIVE) {

        dprintf(" Excl");

    }
    if (DeviceExtension->Flags & DEV_PROP_RAN_INI) {

        dprintf(" Ini");

    }
    if (!(DeviceExtension->Flags & DEV_PROP_DEVICE_ENABLED)) {

        dprintf(" !Ena");

    }
    if (DeviceExtension->Flags & DEV_PROP_DEVICE_FAILED) {

        dprintf(" Fail");

    }
    if (DeviceExtension->Flags & DEV_PROP_ACPI_POWER) {

        dprintf(" Pwr");

    }

    if (DeviceExtension->Flags & DEV_PROP_DOCK) {

       dprintf(" Prof");

    }
    if (DeviceExtension->Flags & DEV_PROP_BUILT_POWER_TABLE) {

        dprintf(" S->D");

    }
    if (DeviceExtension->Flags & DEV_PROP_HAS_PME) {

        dprintf(" PME");

    }
    dprintf("\n");

}

VOID
displayAcpiDeviceExtensionName(
    IN  ULONG_PTR DeviceExtensionAddress
    )
/*++

Routine Description:


    This routine is tasked to with displaying the name of the device in the
    best possible manner

Arguments:

    DeviceExtensionAddress  - The Address of the DeviceExtension

Return Value:

    NONE

--*/
{
    BOOL                status;
    DEVICE_EXTENSION    deviceExtension;
    NSOBJ               acpiObject;
    UCHAR               nameBuffer[80];
    ULONG_PTR           nameAddress;
    ULONG               returnLength;

    //
    // Read the entier extension
    //
    status = ReadMemory(
        DeviceExtensionAddress,
        &deviceExtension,
        sizeof(DEVICE_EXTENSION),
        &returnLength
        );
    if (status && returnLength == sizeof(DEVICE_EXTENSION) ) {

        if (deviceExtension.Flags & DEV_PROP_HID) {

            if (deviceExtension.DeviceID != NULL) {

                //
                // Now, try to read the name into the buffer
                //
                status = ReadMemory(
                    (ULONG_PTR) deviceExtension.DeviceID,
                    nameBuffer,
                    79,
                    &returnLength
                    );
                if (status && returnLength) {

                    nameBuffer[returnLength] = '\0';
                    dprintf("%s",nameBuffer);


                } else {

                    dprintf("(%lx)", deviceExtension.DeviceID);

                }

            } else {

                dprintf("NULL");

            }

        }
        if (deviceExtension.Flags & DEV_PROP_UID) {

            if (deviceExtension.InstanceID != NULL) {

                //
                // Now, try to read the name into the buffer
                //
                status = ReadMemory(
                    (ULONG_PTR) deviceExtension.InstanceID,
                    nameBuffer,
                    79,
                    &returnLength
                    );
                if (status && returnLength) {

                    nameBuffer[returnLength] = '\0';
                    dprintf(" [%s]",nameBuffer);


                } else {

                    dprintf(" [ (%lx) ]", deviceExtension.InstanceID);

                }

            } else {

                dprintf(" [NULL]");

            }

        }
        if (deviceExtension.Flags & DEV_PROP_ADDRESS) {

            dprintf("%lx", deviceExtension.Address );

        }
        return;

    }

    //
    // In this case, obtain the address of the ACPIObject for this device
    //
    nameAddress = (ULONG_PTR) &(deviceExtension.AcpiObject) -
        (ULONG_PTR) &(deviceExtension) + DeviceExtensionAddress;
    status = ReadMemory(
        nameAddress,
        &(deviceExtension.AcpiObject),
        sizeof(PNSOBJ),
        &returnLength
        );
    if (status && returnLength == sizeof(PNSOBJ)) {

        //
        // Read the object
        //
        status = ReadMemory(
            (ULONG_PTR) deviceExtension.AcpiObject,
            &acpiObject,
            sizeof(NSOBJ),
            &returnLength
            );
        if (status && returnLength == sizeof(NSOBJ)) {

            memcpy( nameBuffer, &(acpiObject.dwNameSeg), 4 );
            nameBuffer[4] = '\0';

            dprintf("Acpi(%s)", nameBuffer);
            return;

        }

    }

    dprintf("Unknown");
    return;
}
VOID
displayThermalInfo(
    IN  PTHRM_INFO  ThrmInfo,
    IN  ULONG_PTR   Address,
    IN  ULONG       Verbose,
    IN  ULONG       IndentLevel
    )
/*++

    This routine displays a thermal information structure

--*/
{
    BOOLEAN             noIndent;
    UCHAR               indent[80];
    UINT                i;

    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';

    dprintf(
        "%s  Stamp      %8lx   Affinity     %08lx   Mode       %s\n",
        indent,
        ThrmInfo->Info.ThermalStamp,
        ThrmInfo->Info.Processors,
        (ThrmInfo->Mode == 0 ? "Active" : "Passive")
        );
    dprintf(
        "%s  SampleRate %8ss  Constant1    %08lx   Constant2  %08lx\n",
        indent,
        TimeToSeconds( ThrmInfo->Info.SamplingPeriod ),
        ThrmInfo->Info.ThermalConstant1,
        ThrmInfo->Info.ThermalConstant2
        );
    dprintf(
        "%s  _TMP       %8lx   TempData     %8lx   CoolingLvl  %2d\n",
        indent,
        ThrmInfo->TempMethod,
        Address + FIELD_OFFSET( THRM_INFO, Temp ),
        ThrmInfo->CoolingLevel
        );
    for (i = 0; i < 10; i++) {

        noIndent = FALSE;

        if (i == 0) {

            dprintf(
                "%s  Current    %8sK  ",
                indent,
                TempToKelvins( ThrmInfo->Info.CurrentTemperature )
                );

        } else if (i == 1) {

            dprintf(
                "%s  Critical   %8sK  ",
                indent,
                TempToKelvins( ThrmInfo->Info.CriticalTripPoint )
                );

        } else if (i == 2) {

            dprintf(
                "%s  Passive    %8sK  ",
                indent,
                TempToKelvins( ThrmInfo->Info.PassiveTripPoint )
                );

        } else {

            noIndent = TRUE;

        }

        if (i >= ThrmInfo->Info.ActiveTripPointCount) {

            if (ThrmInfo->Info.ActiveTripPoint[i] != 0 ||
                ThrmInfo->ActiveList[i] != NULL) {

                if (noIndent == TRUE) {

                    dprintf( "%s                        ", indent );

                }
                dprintf(
                    "*Active #%d   %8sK  Method     %lx\n",
                    i,
                    TempToKelvins( ThrmInfo->Info.ActiveTripPoint[i] ),
                    ThrmInfo->ActiveList[i]
                    );

            } else if (i < 3) {

                dprintf("\n");

            } else {

                break;

            }


        } else {

            if (noIndent == TRUE) {

                dprintf( "%s                        ", indent );

            }
            dprintf(
                "Active #%d    %8sK  Method     %lx\n",
                i,
                TempToKelvins( ThrmInfo->Info.ActiveTripPoint[i] ),
                ThrmInfo->ActiveList[i]
                );

        }

    }
}

VOID
dumpAcpiDeviceNode(
    IN  PACPI_DEVICE_POWER_NODE DeviceNode,
    IN  ULONG_PTR               Address,
    IN  ULONG                   Verbose,
    IN  ULONG                   IndentLevel
    )
/*++

Routine Description:

    This routine dumps the contents of a single device node

Arguments:

    DeviceNode  - What to dump
    Address     - Where that node is located
    IndentLevel - How much whitespace to use

Return Value:

    None

--*/
{
    UCHAR   indent[80];

    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';

    dprintf(
        "%sDevice Node - %08lx -> Extension - %08lx",
        indent,
        Address,
        DeviceNode->DeviceExtension
        );
    if (DeviceNode->DeviceExtension != NULL) {

        dprintf(" - ");
        displayAcpiDeviceExtensionName(
            (ULONG_PTR) DeviceNode->DeviceExtension
            );

    }
    dprintf("\n");

    dprintf(
        "%s  System     %2s         Device       %2s         Wake       %s\n",
        indent,
        ShortSystemPowerStateTable[DeviceNode->SystemState],
        ShortDevicePowerStateTable[DeviceNode->AssociatedDeviceState],
        (DeviceNode->WakePowerResource ? "TRUE" : "FALSE")
        );

}

VOID
dumpAcpiDeviceNodes(
    IN  ULONG_PTR Address,
    IN  ULONG   Verbose,
    IN  ULONG   IndentLevel
    )
/*++

Routine Description:

    This routine walks a Device Power List (given the address of the
    start of that list)

Arguments:

    Address     - Where in memory the first node is located
    Verbose     - How much information to display
    IndentLevel - How many characters to indent

Return Value:

    VOID

--*/
{
    BOOL                    status;
    ACPI_DEVICE_POWER_NODE  deviceNode;
    ACPI_POWER_DEVICE_NODE  powerNode;
    ULONG                   returnLength;
    ULONG_PTR               deviceAddress = Address;

    while (deviceAddress != 0) {

        //
        // Read the current node
        //
        status = ReadMemory(
            deviceAddress,
            &deviceNode,
            sizeof(ACPI_DEVICE_POWER_NODE),
            &returnLength
            );
        if (status != TRUE || returnLength != sizeof(ACPI_DEVICE_POWER_NODE)) {

            dprintf(
                "dumpAcpiDeviceNodes: could not read device node memory "
                "%08lx\n",
                deviceAddress
                );
            return;

        }

        //
        // Dump the node
        //
        dumpAcpiDeviceNode(
            &deviceNode,
            deviceAddress,
            Verbose,
            IndentLevel
            );

        status = ReadMemory(
            (ULONG_PTR) deviceNode.PowerNode,
            &powerNode,
            sizeof(ACPI_POWER_DEVICE_NODE),
            &returnLength);
        if (status != TRUE ||
            returnLength != sizeof(ACPI_POWER_DEVICE_NODE)) {

            dprintf(
                "dumpAcpiDeviceNode: could not read power node memory "
                "%08lx\n",
                deviceNode.PowerNode
                );
            return;

        }

        //
        // Dump the power resource
        //
        dumpAcpiPowerNode(
            &powerNode,
            (ULONG_PTR) deviceNode.PowerNode,
            Verbose,
            IndentLevel
            );

        //
        // setup next entry in the list
        //
        deviceAddress = (ULONG_PTR) deviceNode.Next;

    }

}

VOID
dumpAcpiExtension(
    IN  ULONG_PTR Address,
    IN  ULONG   Verbose,
    IN  ULONG   IndentLevel
    )
/*++

Routine Description:

    This dumps the ACPI device extension in a format that is readable by the
    user debugging the system

Arguments:

    Address     - Where the DeviceObject is located
    Verbose     - How much information to display
    IndentLevel - How much whitespace to have

Return Value:

    None

--*/
{
    BOOL                b;
    DEVICE_EXTENSION    deviceExtension;
    PLIST_ENTRY         listEntry;
    UCHAR               indent[80];
    ULONG_PTR           curAddress;
    ULONG               returnLength;
    ULONG_PTR           stopAddress;
    ULONG               subVerbose;

    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';

    //
    // Read the sibling device extension
    //
    b = ReadMemory(
        Address,
        &deviceExtension,
        sizeof(DEVICE_EXTENSION),
        &returnLength
        );
    if (!b) {

        dprintf(
            "%s***ReadMemory Failed from %p\n",
            Address
            );
        return;

    } else if (returnLength != sizeof(DEVICE_EXTENSION) ) {

        dprintf(
            "%s***Error: Only read %08lx of %08lx bytes for %p\n",
            returnLength,
            sizeof(DEVICE_EXTENSION),
            Address
            );
        return;

    }

    if ( (Verbose & VERBOSE_ALL) ) {

        displayAcpiDeviceExtension(
            &deviceExtension,
            Address,
            Verbose,
            IndentLevel
            );

    } else {

        displayAcpiDeviceExtensionBrief(
            &deviceExtension,
            Address,
            Verbose,
            IndentLevel
            );

    }

    if (! (Verbose & VERBOSE_LOOP) ) {

        return;

    }

    //
    // Determine the current and stop addresses
    //
    stopAddress = (ULONG_PTR) &(deviceExtension.ChildDeviceList) -
        (ULONG_PTR) &deviceExtension + Address;
    listEntry = deviceExtension.ChildDeviceList.Flink;

    //
    // Loop while there are children
    //
    while (listEntry != (PLIST_ENTRY) stopAddress) {

        //
        // Check for Ctrl-C
        //
        if (CheckControlC()) {

            break;

        }

        //
        // The currentAddress is at the ListEntry --- lets convert
        //
        curAddress = (ULONG_PTR) CONTAINING_RECORD(
            listEntry,
            DEVICE_EXTENSION,
            SiblingDeviceList
            );

        //
        // Read the entry
        //
        b = ReadMemory(
            curAddress,
            &deviceExtension,
            sizeof(DEVICE_EXTENSION),
            &returnLength
            );
        if (!b) {

            dprintf(
                "%s    ***ReadMemory Failed from %p\n",
                curAddress
                );
            return;

        } else if (returnLength != sizeof(DEVICE_EXTENSION) ) {

            dprintf(
                "%s    ***Error: Only read %08lx of %08lx bytes "
                "for %p\n",
                returnLength,
                sizeof(DEVICE_EXTENSION),
                curAddress
                );
            return;

        }

        //
        // Recurse
        //
        dumpAcpiExtension(
            curAddress,
            Verbose,
            IndentLevel + 4
            );

        //
        // Point to the next extension
        //
        listEntry = deviceExtension.SiblingDeviceList.Flink;

    }
}

VOID
dumpPM1ControlRegister(
    IN  ULONG   Value,
    IN  ULONG   IndentLevel
    )
{


    //
    // Dump the PM1 Control Flags
    //
    dumpFlags(
        (Value & 0xFF),
        &PM1StatusFlags[0],
        sizeof(PM1ControlFlags) / sizeof(FLAG_RECORD),
        IndentLevel,
        (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE)
        );

}

VOID
dumpPM1StatusRegister(
    IN  ULONG   Value,
    IN  ULONG   IndentLevel
    )
{

    //
    // Dump the PM1 Status Flags
    //
    dumpFlags(
        (Value & 0xFFFF),
        PM1StatusFlags,
        (sizeof(PM1StatusFlags) / sizeof(FLAG_RECORD)),
        IndentLevel,
        (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE)
        );

    //
    // Switch to the PM1 Enable Flags
    //
    Value >>= 16;


    //
    // Dump the PM1 Enable Flags
    //
    dumpFlags(
        (Value & 0xFFFF),
        PM1EnableFlags,
        (sizeof(PM1EnableFlags) / sizeof(FLAG_RECORD)),
        IndentLevel,
        (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE)
        );
}

VOID
dumpAcpiPowerList(
    IN  PUCHAR  ListName
    )
/*++

    This routine fetects a single Power Device List from the target and
    displays it

Arguments:

    None

Return Value:

    None

--*/
{
    BOOL        status;
    LIST_ENTRY  listEntry;
    ULONG_PTR   address;
    ULONG       returnLength;

    //
    // Handle the queue list
    //
    address = GetExpression( ListName );
    if (!address) {

        dprintf( "dumpAcpiPowerList: could not read %s\n", ListName );

    } else {

        dprintf("  %s at %p\n", ListName, address );
        status = ReadMemory(
            address,
            &listEntry,
            sizeof(LIST_ENTRY),
            &returnLength
            );
        if (status == FALSE || returnLength != sizeof(LIST_ENTRY)) {

            dprintf(
                "dumpAcpiPowerList: could not read LIST_ENTRY at %08lx\n",
                address
                );

        } else {

            dumpDeviceListEntry(
                &listEntry,
                address
                );
            dprintf("\n");

        }

    }
}

VOID
dumpAcpiPowerLists(
    VOID
    )
/*++

Routine Description:

    This routine fetches the Power Device list from the target and
    displays it

Arguments:

    None

Return Value:

    None

--*/
{
    BOOL        status;
    LIST_ENTRY  listEntry;
    ULONG_PTR   address;
    ULONG       returnLength;
    ULONG       value;

    status = GetUlongPtr( "ACPI!AcpiPowerLock", &address );
    if (status == FALSE) {

        dprintf("dumpAcpiPowerLists: Could not read ACPI!AcpiPowerLock\n");
        return;

    }

    dprintf("ACPI Power Information\n");
    if (address) {

        dprintf("  + ACPI!AcpiPowerLock is owned");

        //
        // The bits other then the lowest is where the owning thread is
        // located. This function uses the property that -2 is every bit
        // except the least significant one
        //
        if ( (address & (ULONG_PTR) -2) != 0) {

            dprintf(" by thread at %p\n", (address & (ULONG_PTR) - 2) );

        } else {

            dprintf("\n");

        }

    } else {

        dprintf("  - ACPI!AcpiPowerLock is not owned\n");

    }

    status = GetUlongPtr( "ACPI!AcpiPowerQueueLock", &address );
    if (status == FALSE) {

        dprintf("dumpAcpiPowerLists: Could not read ACPI!AcpiPowerQueueLock\n");
        return;

    }
    if (address) {

        dprintf("  + ACPI!AcpiPowerQueueLock is owned\n");

        if ( (address & (ULONG_PTR) -2) != 0) {

            dprintf(" by thread at %p\n", (address & (ULONG_PTR) - 2) );

        } else {

            dprintf("\n");

        }

    } else {

        dprintf("  - ACPI!AcpiPowerQueueLock is not owned\n" );

    }

    status = GetUlong( "ACPI!AcpiPowerWorkDone", &value );
    if (status == FALSE) {

        dprintf("dumpAcpiPowerLists: Could not read ACPI!AcpiPowerWorkDone\n");
        return;

    }
    dprintf("  + AcpiPowerWorkDone = %s\n", (value ? "TRUE" : "FALSE" ) );


    status = GetUlong( "ACPI!AcpiPowerDpcRunning", &value );
    if (status == FALSE) {

        dprintf("dumpAcpiPowerLists: Could not read ACPI!AcpiPowerDpcRunning\n");
        return;

    }
    dprintf("  + AcpiPowerDpcRunning = %s\n", (value ? "TRUE" : "FALSE" ) );

    dumpAcpiPowerList( "ACPI!AcpiPowerQueueList" );
    dumpAcpiPowerList( "ACPI!AcpiPowerDelayedQueueList" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase0List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase1List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase2List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase3List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase4List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerPhase5List" );
    dumpAcpiPowerList( "ACPI!AcpiPowerWaitWakeList" );

}

VOID
dumpAcpiPowerNode(
    IN  PACPI_POWER_DEVICE_NODE PowerNode,
    IN  ULONG_PTR               Address,
    IN  ULONG                   Verbose,
    IN  ULONG                   IndentLevel
    )
/*++

Routine Description:

    This routine is called to display a power node

Arguments:

    PowerNode   - The power node to dump
    Address     - Where the power node is located
    Verbose     - How much information to display
    IndentLevel - How many characters to indent

Return Value:

    None

--*/
{
    BOOL    status;
    NSOBJ   ns;
    UCHAR   buffer[5];
    UCHAR   indent[80];
    ULONG   returnLength;

    buffer[4] = '\0';
    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';

    //
    // Read the associated power resource object
    //
    status = ReadMemory(
        (ULONG_PTR) PowerNode->PowerObject,
        &ns,
        sizeof(NSOBJ),
        &returnLength
        );
    if (status != FALSE && returnLength == sizeof(NSOBJ)) {

        memcpy( buffer, &(ns.dwNameSeg), 4 );

    } else {

        buffer[0] = '\0';

    }

    dprintf("%sPower Node - %08lx %s\n", indent, Address, buffer );
    dprintf(
        "%s  Resource   %8lx   Order        %8lx   WorkDone    %8s\n",
        indent,
        PowerNode->PowerObject,
        PowerNode->ResourceOrder,
        WorkDone[ PowerNode->WorkDone ]
        );
    dprintf(
        "%s  On Method  %8lx   Off Method   %8lx   UseCounts   %8lx\n",
        indent,
        PowerNode->PowerOnObject,
        PowerNode->PowerOffObject,
        PowerNode->UseCounts
        );
    dprintf(
        "%s  Level      %8s   Flags        %8lx   ",
        indent,
        ShortSystemPowerStateTable[PowerNode->SystemLevel],
        PowerNode->Flags
        );
    dumpFlags(
        (PowerNode->Flags),
        &PowerNodeFlags[0],
        sizeof(PowerNodeFlags)/sizeof(FLAG_RECORD),
        0,
        (DUMP_FLAG_SHORT_NAME | DUMP_FLAG_NO_INDENT |
         DUMP_FLAG_SINGLE_LINE)
        );
    if (Verbose & VERBOSE_4) {

        dumpFlags(
            (PowerNode->Flags),
            &PowerNodeFlags[0],
            sizeof(PowerNodeFlags)/sizeof(FLAG_RECORD),
            IndentLevel + 4,
            (DUMP_FLAG_LONG_NAME)
            );

    }

}

VOID
dumpAcpiPowerNodes(
    VOID
    )
/*++

Routine Description:

    This routine fetches the Power Device list from the target and
    displays it

Arguments:

    None

Return Value:

    None

--*/
{
    ACPI_DEVICE_POWER_NODE  deviceNode;
    ACPI_POWER_DEVICE_NODE  powerNode;
    BOOL                    status;
    LIST_ENTRY              listEntry;
    PLIST_ENTRY             list;
    ULONG_PTR               addr;
    ULONG_PTR               address;
    ULONG_PTR               endAddress;
    ULONG                   returnLength;
    ULONG_PTR               startAddress;

    status = GetUlongPtr( "ACPI!AcpiPowerLock", &address );
    if (status == FALSE) {

        dprintf("dumpAcpiPowerNodes: Could not read ACPI!AcpiPowerLock\n");
        return;

    }

    dprintf("ACPI Power Nodes\n");
    if (address) {

        dprintf("  + ACPI!AcpiPowerLock is owned");

        //
        // The bits other then the lowest is where the owning thread is
        // located. This function uses the property that -2 is every bit
        // except the least significant one
        //
        if ( (address & (ULONG_PTR) -2) != 0) {

            dprintf(" by thread at %p\n", (address & (ULONG_PTR) - 2) );

        } else {

            dprintf("\n");

        }

    } else {

        dprintf("  - ACPI!AcpiPowerLock is not owned\n");

    }

    dprintf("Power Node List\n");
    startAddress = GetExpression( "ACPI!AcpiPowerNodeList" );
    if (!startAddress) {

        dprintf("dumpAcpiPowerNodes: could not read ACPI!AcpiPowerNodeList\n");
        return;

    }
    status = ReadMemory(
        startAddress,
        &listEntry,
        sizeof(LIST_ENTRY),
        &returnLength
        );
    if (status == FALSE || returnLength != sizeof(LIST_ENTRY)) {

        dprintf(
            "dumpAcpiPowerNodes: could not read LIST_ENTRY at %08lx\n",
            startAddress
            );
        return;

    }

    //
    // Check to see if the list is empty
    //
    if ( (ULONG_PTR) listEntry.Flink == startAddress) {

        dprintf("  Empty\n");
        return;

    }

    address = (ULONG_PTR) CONTAINING_RECORD(
        (listEntry.Flink),
        ACPI_POWER_DEVICE_NODE,
        ListEntry
        );
    while (address != startAddress && address != 0) {

        //
        // Read the queued item
        //
        status = ReadMemory(
            address,
            &powerNode,
            sizeof(ACPI_POWER_DEVICE_NODE),
            &returnLength
            );
        if (status == FALSE || returnLength != sizeof(ACPI_POWER_DEVICE_NODE)) {

            dprintf(
                "dumpIrpListEntry: Cannot read Node at %08lx\n",
                address
                );
            return;

        }

        //
        // dump the node
        //
        dumpAcpiPowerNode(
            &powerNode,
            address,
            0,
            0
            );

        //
        // Lets walk the list of power nodes
        //
        list = powerNode.DevicePowerListHead.Flink;
        endAddress = ( (ULONG_PTR) &(powerNode.DevicePowerListHead) -
                 (ULONG_PTR) &(powerNode) ) +
               address;

        //
        // Loop until back at the start
        //
        while (list != (PLIST_ENTRY) endAddress) {

            //
            // Crack the record
            //
            addr = (ULONG_PTR) CONTAINING_RECORD(
                list,
                ACPI_DEVICE_POWER_NODE,
                DevicePowerListEntry
                );

            status = ReadMemory(
                addr,
                &deviceNode,
                sizeof(ACPI_DEVICE_POWER_NODE),
                &returnLength
                );
            if (status == FALSE ||
                returnLength != sizeof(ACPI_DEVICE_POWER_NODE)) {

                dprintf(
                    "dumpIrpListEntry: Cannot read Node at %08lx\n",
                    addr
                    );
                continue;

            }

            //
            // Dump the record
            //
            dumpAcpiDeviceNode(
                &deviceNode,
                addr,
                0,
                2
                );

            //
            // Next record
            //
            list = deviceNode.DevicePowerListEntry.Flink;

        }

        dprintf("\n");

        //
        // Next record
        //
        address = (ULONG_PTR) CONTAINING_RECORD(
            powerNode.ListEntry.Flink,
            ACPI_POWER_DEVICE_NODE,
            ListEntry
            );

    }

}

VOID
dumpDeviceListEntry(
    IN  PLIST_ENTRY ListEntry,
    IN  ULONG_PTR   Address
    )
/*++

Routine Description:

    This routine is called to dump a list of devices in one of the queues

Arguments:

    ListEntry   - The head of the list
    Address     - The original address of the list (to see when we looped
                  around

Return Value:

    NONE

--*/
{
    ULONG_PTR           displacement;
    ACPI_POWER_REQUEST  request;
    BOOL                stat;
    PACPI_POWER_REQUEST nextRequest;
    PACPI_POWER_REQUEST requestAddress;
    ULONG               i = 0;
    ULONG               returnLength;

    //
    // Look at the next address
    //
    ListEntry = ListEntry->Flink;

    while (ListEntry != (PLIST_ENTRY) Address) {

        //
        // Crack the listEntry to determine where the powerRequest is
        //
        requestAddress = CONTAINING_RECORD(
            ListEntry,
            ACPI_POWER_REQUEST,
            ListEntry
            );

        //
        // Read the queued item
        //
        stat = ReadMemory(
            (ULONG_PTR) requestAddress,
            &request,
            sizeof(ACPI_POWER_REQUEST),
            &returnLength
            );
        if (stat == FALSE || returnLength != sizeof(ACPI_POWER_REQUEST)) {

            dprintf(
                "dumpDeviceListEntry: Cannot read PowerRequest at %08lx\n",
                requestAddress
                );
            return;

        }

        if (request.CallBack != NULL) {

            GetSymbol(
                request.CallBack,
                Buffer,
                &displacement
                );

        } else {

            Buffer[0] = '\0';

        }

        //
        // Dump the entry for the device
        //
        dprintf(
            "      %08lx\n"
            "        DeviceExtension:     %08lx",
            requestAddress,
            request.DeviceExtension
            );
        if (request.DeviceExtension != NULL) {

            dprintf(" - ");
            displayAcpiDeviceExtensionName(
                (ULONG_PTR) request.DeviceExtension
                );

        }
        dprintf("\n");
        dprintf(
            "        Status:              %08lx %s->%s\n",
            request.Status,
            WorkDone[request.WorkDone],
            WorkDone[request.NextWorkDone]
            );
        nextRequest = CONTAINING_RECORD(
            request.SerialListEntry.Flink,
            ACPI_POWER_REQUEST,
            SerialListEntry
            );
        if (nextRequest != requestAddress) {

            dprintf(
                "        SerialListEntry:     F - %08lx B - %08lx -> %08lx\n",
                request.SerialListEntry.Flink,
                request.SerialListEntry.Blink,
                nextRequest
                );

        }
        dprintf(
            "        CallBack:            %08lx (%s)\n"
            "        Context:             %08lx\n"
            "        RequestType:         %02lx\n"
            "        ResultData:          %08lx\n",
            request.CallBack,
            Buffer,
            request.Context,
            request.RequestType,
            requestAddress + (FIELD_OFFSET(ACPI_POWER_REQUEST, ResultData ) )
            );

        //
        // Dump some of the request specific information
        //
        if (request.RequestType == AcpiPowerRequestDevice) {

            dprintf(
                "        RequestType:         AcpiPowerRequestDevice\n"
                "        DevicePowerState:    %s\n"
                "        Flags:               %x ",
                DevicePowerStateTable[request.u.DevicePowerRequest.DevicePowerState],
                request.u.DevicePowerRequest.Flags
                );
            dumpFlags(
                (request.u.DevicePowerRequest.Flags),
                &PowerRequestFlags[0],
                sizeof(PowerRequestFlags)/sizeof(FLAG_RECORD),
                0,
                (DUMP_FLAG_LONG_NAME | DUMP_FLAG_NO_INDENT |
                 DUMP_FLAG_SINGLE_LINE)
                );

        } else if (request.RequestType == AcpiPowerRequestSystem) {

            dprintf(
                "        RequestType:         AcpiPowerRequestSystem\n"
                "        SystemPowerState:    %s\n"
                "        SystemPowerAction:   %s\n",
                SystemPowerStateTable[request.u.SystemPowerRequest.SystemPowerState],
                SystemPowerActionTable[request.u.SystemPowerRequest.SystemPowerAction]
                );

        } else if (request.RequestType == AcpiPowerRequestWaitWake) {

            dprintf(
                "        RequestType:         AcpiPowerRequestWaitWake\n"
                "        SystemPowerState:    %s\n"
                "        Flags:               %x ",
                SystemPowerStateTable[request.u.WaitWakeRequest.SystemPowerState],
                request.u.WaitWakeRequest.Flags
                );
            dumpFlags(
                (request.u.WaitWakeRequest.Flags),
                &PowerRequestFlags[0],
                sizeof(PowerRequestFlags)/sizeof(FLAG_RECORD),
                0,
                (DUMP_FLAG_LONG_NAME | DUMP_FLAG_NO_INDENT |
                 DUMP_FLAG_SINGLE_LINE)
                );

        }

        //
        // Point to the next entry
        //
        ListEntry = request.ListEntry.Flink;

    } // while

}

VOID
dumpIrpListEntry(
    IN  PLIST_ENTRY ListEntry,
    IN  ULONG_PTR   Address
    )
/*++

Routine Description:

    This routine is called to dump a list of devices in one of the queues

Arguments:

    ListEntry   - The head of the list
    Address     - The original address of the list (to see when we looped
                  around

Return Value:

    NONE

--*/
{
    BOOL                stat;
    DEVICE_OBJECT       deviceObject;
    DEVICE_EXTENSION    deviceExtension;
    IO_STACK_LOCATION   irpStack;
    PIRP                irpAddress;
    PIO_STACK_LOCATION  tempStack;
    IRP                 irp;
    ULONG               returnLength;

    //
    // Look at the first element in the list
    //
    ListEntry = ListEntry->Flink;

    //
    // Loop for all items in the list
    //
    while (ListEntry != (PLIST_ENTRY) Address) {

        irpAddress = CONTAINING_RECORD(
            ListEntry,
            IRP,
            Tail.Overlay.ListEntry
            );

        //
        // Read the queued item
        //
        stat = ReadMemory(
            (ULONG_PTR) irpAddress,
            &irp,
            sizeof(IRP),
            &returnLength
            );
        if (stat == FALSE || returnLength != sizeof(IRP)) {

            dprintf(
                "dumpIrpListEntry: Cannot read Irp at %08lx\n",
                irpAddress
                );
            return;

        }

        //
        // Get the current stack location
        //
        tempStack = IoGetCurrentIrpStackLocation( &irp );
        if (tempStack == NULL) {

            dprintf(
                "dumpIrpListEntry: Cannot read IrpStack for Irp at %08lx\n",
                irpAddress
                );
            return;

        }

        stat = ReadMemory(
            (ULONG_PTR) tempStack,
            &irpStack,
            sizeof(IO_STACK_LOCATION),
            &returnLength
            );
        if (stat == FALSE || returnLength != sizeof(IO_STACK_LOCATION)) {

            dprintf(
                "dumpIrpListEntry: Cannot read IoStackLocation at %08lx\n",
                tempStack
                );
            return;

        }

        stat = ReadMemory(
            (ULONG_PTR) irpStack.DeviceObject,
            &deviceObject,
            sizeof(DEVICE_OBJECT),
            &returnLength
            );
        if (stat == FALSE || returnLength != sizeof(DEVICE_OBJECT)) {

            dprintf(
                "dumpIrpListEntry: Cannot read DeviceObject at %08lx\n",
                irpStack.DeviceObject
                );
            return;

        }

        stat = ReadMemory(
            (ULONG_PTR) deviceObject.DeviceExtension,
            &deviceExtension,
            sizeof(DEVICE_EXTENSION),
            &returnLength
            );
        if (stat == FALSE || returnLength != sizeof(DEVICE_EXTENSION)) {

            dprintf(
                "dumpIrpListEntry: Cannot read DeviceExtension at %08lx\n",
                deviceObject.DeviceExtension
                );
            return;

        }

        memset( Buffer, '0', 2048 );
        stat = ReadMemory(
            (ULONG_PTR) deviceExtension.DeviceID,
            Buffer,
            256,
            &returnLength
            );
        if (stat && Buffer[0] != '\0' && returnLength != 0) {

            dprintf(
                "    Irp: %08x Device: %08lx (%s)\n",
                irpAddress,
                irpStack.DeviceObject,
                Buffer
                );

        } else {

            dprintf(
                "    Irp: %08x Device: %08lx\n",
                irpAddress,
                irpStack.DeviceObject
                );

        }

        //
        // Next item on the queue
        //
        ListEntry = irp.Tail.Overlay.ListEntry.Flink;

    }

}

VOID
dumpNSObject(
    IN  ULONG_PTR Address,
    IN  ULONG   Verbose,
    IN  ULONG   IndentLevel
    )
/*++

Routine Description:

    This function dumps a Name space object

Arguments:

    Address     - Where to find the object
    Verbose     - Should the object be dumped as well?
    IndentLevel - How much to indent

Return Value:

    None

--*/
{
    BOOL    b;
    NSOBJ   ns;
    UCHAR   buffer[5];
    UCHAR   indent[80];

    //
    // Init the buffers
    //
    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';
    buffer[4] = '\0';

    //
    // First step is to read the root NS
    //
    b = ReadMemory(
        Address,
        &ns,
        sizeof(NSOBJ),
        NULL
        );
    if (!b) {

        dprintf("%sdumpNSObject: could not read %x\n", indent,Address );
        return;

    }

    if (ns.dwNameSeg != 0) {

        memcpy( buffer, &(ns.dwNameSeg), 4 );

    } else {

        sprintf( buffer, "    ");

    }

    dprintf(
        "%sNameSpace Object %s (%08lx) - Device %08lx\n",
        indent,
        buffer,
        Address,
        ns.Context
        );
    if (Verbose & VERBOSE_NSOBJ) {

        dprintf(
            "%s  Flink %08lx  Blink  %08lx  Parent %08lx  Child %08lx\n",
            indent,
            ns.list.plistNext,
            ns.list.plistPrev,
            ns.pnsParent,
            ns.pnsFirstChild
            );

    }
    dprintf(
        "%s  Value %08lx  Length %08lx  Buffer %08lx  Flags %08lx",
        indent,
        ns.ObjData.uipDataValue,
        ns.ObjData.dwDataLen,
        ns.ObjData.pbDataBuff,
        ns.ObjData.dwfData
        );
    if (ns.ObjData.dwfData & DATAF_BUFF_ALIAS) {

        dprintf("  Alias" );

    }
    if (ns.ObjData.dwfData & DATAF_GLOBAL_LOCK) {

        dprintf("  Lock");

    }
    dprintf("\n");

    dumpObject( Address, &(ns.ObjData), Verbose, IndentLevel + 4);
}

VOID
dumpNSTree(
    IN  ULONG_PTR   Address,
    IN  ULONG       Level
    )
/*++

Routine Description:

    This thing dumps the NS tree

Arguments:

    Address - Where to find the root node --- we start dumping at the children

Return Value:

    None

--*/
{
    BOOL        end = FALSE;
    BOOL        b;
    NSOBJ       ns;
    UCHAR       buffer[5];
    ULONG_PTR   next;
    ULONG       back;
    ULONG_PTR   m1 = 0;
    ULONG_PTR   m2 = 0;
    ULONG       reason;
    ULONG       dataBuffSize;

    buffer[4] = '\0';

    //
    // Indent
    //
    for (m1 = 0; m1 < Level; m1 ++) {

        dprintf("| ");

    }

    //
    // First step is to read the root NS
    //
    b = ReadMemory(
        Address,
        &ns,
        sizeof(NSOBJ),
        NULL
        );
    if (!b) {

        dprintf("dumpNSTree: could not read %x\n", Address );
        return;

    }

    if (ns.dwNameSeg != 0) {

        memcpy( buffer, &(ns.dwNameSeg), 4 );
        dprintf("%4s ", buffer );

    } else {

        dprintf("     " );

    }
    dprintf(
        "(%08x) - ", Address );

    if (ns.Context != 0) {

        dprintf("Device %08lx\n", ns.Context );

    } else {

        //
        // We need to read the pbDataBuff here
        //
        if (ns.ObjData.pbDataBuff != 0) {

            dataBuffSize = (ns.ObjData.dwDataLen > 2047 ?
                2047 : ns.ObjData.dwDataLen
                );
            b = ReadMemory(
                (ULONG_PTR) ns.ObjData.pbDataBuff,
                Buffer,
                dataBuffSize,
                NULL
                );
            if (!b) {

                dprintf(
                    "dumpNSTree: could not read %x\n",
                    ns.ObjData.pbDataBuff
                    );
                return;

            }

        }
        switch(ns.ObjData.dwDataType) {
            default:
            case OBJTYPE_UNKNOWN:       dprintf("Unknown\n");           break;
            case OBJTYPE_INTDATA:
                dprintf("Integer - %lx\n", ns.ObjData.uipDataValue);
                break;
            case OBJTYPE_STRDATA:
                Buffer[dataBuffSize+1] = '\0';
                dprintf(
                     "String - %s\n",
                     Buffer
                     );
                break;
            case OBJTYPE_BUFFDATA:
                dprintf(
                     "Buffer - %08lx L=%04x\n",
                     ns.ObjData.pbDataBuff,
                     ns.ObjData.dwDataLen
                     );
                break;
            case OBJTYPE_PKGDATA: {

                PPACKAGEOBJ package = (PPACKAGEOBJ) Buffer;

                dprintf("Package - NumElements %x\n",package->dwcElements);
                break;

            }
            case OBJTYPE_FIELDUNIT:{

                PFIELDUNITOBJ   fieldUnit = (PFIELDUNITOBJ) Buffer;

                dprintf(
                    "FieldUnit - Parent %x Offset %x Start %x "
                    "Num %x Flags %x\n",
                    fieldUnit->pnsFieldParent,
                    fieldUnit->FieldDesc.dwByteOffset,
                    fieldUnit->FieldDesc.dwStartBitPos,
                    fieldUnit->FieldDesc.dwNumBits,
                    fieldUnit->FieldDesc.dwFieldFlags
                    );
                break;

            }
            case OBJTYPE_DEVICE:
                dprintf("Device\n");
                break;
            case OBJTYPE_EVENT:
                dprintf("Event - PKEvent %x\n", ns.ObjData.pbDataBuff);
                break;
            case OBJTYPE_METHOD: {

                PMETHODOBJ  method = (PMETHODOBJ) Buffer;

                dprintf(
                     "Method - Flags %x Start %08lx Len %x\n",
                     method->bMethodFlags,
                     (ULONG_PTR) method->abCodeBuff - (ULONG_PTR) method +
                        (ULONG_PTR) ns.ObjData.pbDataBuff,
                     (ULONG) ns.ObjData.dwDataLen - sizeof(METHODOBJ) +
                        ANYSIZE_ARRAY
                     );
                 break;

            }
            case OBJTYPE_OPREGION: {

                POPREGIONOBJ    opRegion = (POPREGIONOBJ) Buffer;

                dprintf(
                    "Opregion - RegionsSpace=%08x OffSet=%x Len=%x\n",
                    opRegion->bRegionSpace,
                    opRegion->uipOffset,
                    opRegion->dwLen
                    );
                break;

            }
            case OBJTYPE_BUFFFIELD: {

                PBUFFFIELDOBJ   field   = (PBUFFFIELDOBJ) Buffer;

                dprintf(
                    "Buffer Field Ptr=%x Len=%x Offset=%x Start=%x"
                    "NumBits=%x Flgas=%x\n",
                    field->pbDataBuff,
                    field->dwBuffLen,
                    field->FieldDesc.dwByteOffset,
                    field->FieldDesc.dwStartBitPos,
                    field->FieldDesc.dwNumBits,
                    field->FieldDesc.dwFieldFlags
                    );
                break;

            }
            case OBJTYPE_FIELD: {

                dprintf("Field\n");
                break;

            }
            case OBJTYPE_INDEXFIELD:    dprintf("Index Field\n");       break;

            case OBJTYPE_MUTEX:         dprintf("Mutex\n");             break;
            case OBJTYPE_POWERRES:      dprintf("Power Resource\n");    break;
            case OBJTYPE_PROCESSOR:     dprintf("Processor\n");         break;
            case OBJTYPE_THERMALZONE:   dprintf("Thermal Zone\n");      break;
            case OBJTYPE_DDBHANDLE:     dprintf("DDB Handle\n");        break;
            case OBJTYPE_DEBUG:         dprintf("Debug\n");             break;
            case OBJTYPE_OBJALIAS:      dprintf("Object Alias\n");      break;
            case OBJTYPE_DATAALIAS:     dprintf("Data Alias\n");        break;
            case OBJTYPE_BANKFIELD:     dprintf("Bank Field\n");        break;

        }

    }
    m1 = next = (ULONG_PTR) ns.pnsFirstChild;

    while (next != 0 && end == FALSE) {

        if (CheckControlC()) {

            break;

        }

        b = ReadMemory(
            next,
            &ns,
            sizeof(NSOBJ),
            NULL
            );
        if (!b) {

            dprintf("dumpNSTree: could not read %x\n", next );
            return;

        }

        dumpNSTree( next, Level + 1);

        //
        // Do the end check tests
        //
        if ( m2 == 0) {

            m2 = (ULONG_PTR) ns.list.plistPrev;

        } else if (m1 == (ULONG_PTR) ns.list.plistNext) {

            end = TRUE;
            reason = 1;

        } else if (m2 == next) {

            end = TRUE;
            reason = 2;
        }

        next = (ULONG_PTR) ns.list.plistNext;

    }

}

VOID
dumpObject(
    IN  ULONG_PTR   Address,
    IN  POBJDATA    Object,
    IN  ULONG       Verbose,
    IN  ULONG       IndentLevel
    )
/*++

Routine Description:

    This dumps an Objdata so that it can be understand --- great for debugging some of the
    AML code

Arguments:

    Address - Where the Object is located
    Object  - Pointer to the object

Return Value:

    None

--*/
{
    BOOL        b;
    NTSTATUS    status;
    UCHAR       buffer[2048];
    UCHAR       indent[80];
    ULONG       max;
    ULONG       returnLength;

    //
    // Init the buffers
    //
    IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
    memset( indent, ' ', IndentLevel );
    indent[IndentLevel] = '\0';

    dprintf("%sObject Data - %08lx Type - ", indent, Address );

    //
    // First step is to read whatever the buffer points to, if it
    // points to something
    //
    if (Object->pbDataBuff != 0) {

        max = (Object->dwDataLen > 2047 ? 2047 : Object->dwDataLen );
        b = ReadMemory(
            (ULONG_PTR) Object->pbDataBuff,
            buffer,
            max,
            &returnLength
            );
        if (!b || returnLength != max) {

            dprintf(
                "%sdumpObject: Could not read buffer %08lx (%d) %x<->%x\n",
                indent,
                Object->pbDataBuff,
                b,
                max,
                returnLength
                );
            return;

        }

    }
    switch( Object->dwDataType ) {
        case OBJTYPE_INTDATA:
            dprintf(
                "%02x <Integer> Value=%08lx\n",
                Object->dwDataType,
                Object->uipDataValue
                );
            break;
        case OBJTYPE_STRDATA:
            buffer[max] = '\0';
            dprintf(
                "%02x <String> String=%s\n",
                Object->dwDataType,
                buffer
                );
            break;
        case OBJTYPE_BUFFDATA:
            dprintf(
                "%02x <Buffer> Ptr=%08lx Length = %2x\n",
                Object->dwDataType,
                Object->pbDataBuff,
                Object->dwDataLen
                );
            break;
        case OBJTYPE_PKGDATA: {

            PPACKAGEOBJ package = (PPACKAGEOBJ) buffer;
            ULONG       i = 0;
            ULONG       j = package->dwcElements;

            dprintf(
                "%02x <Package> NumElements=%02x\n",
                Object->dwDataType,
                j
                );

            if (Verbose & VERBOSE_OBJECT) {

                for (; i < j; i++) {

                    dumpObject(
                        (ULONG_PTR) &(package->adata[i]) - (ULONG_PTR) package +
                        (ULONG_PTR) Object->pbDataBuff,
                        &(package->adata[i]),
                        Verbose,
                        IndentLevel+ 2
                        );

                }

            }

            break;

        }
        case OBJTYPE_FIELDUNIT: {

            PFIELDUNITOBJ   fieldUnit = (PFIELDUNITOBJ) buffer;

            dprintf(
                "%02x <Field Unit> Parent=%08lx Offset=%08lx Start=%08x "
                "Num=%x Flags=%x\n",
                Object->dwDataType,
                fieldUnit->pnsFieldParent,
                fieldUnit->FieldDesc.dwByteOffset,
                fieldUnit->FieldDesc.dwStartBitPos,
                fieldUnit->FieldDesc.dwNumBits,
                fieldUnit->FieldDesc.dwFieldFlags
                );
            break;

        }
        case OBJTYPE_DEVICE:
            dprintf(
                "%02x <Device>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_EVENT:
            dprintf(
                "%02x <Event> PKEvent=%08lx\n",
                Object->dwDataType,
                Object->pbDataBuff
                );
            break;
        case OBJTYPE_METHOD: {

            PMETHODOBJ  method = (PMETHODOBJ) buffer;

            max = Object->dwDataLen - sizeof(METHODOBJ) + ANYSIZE_ARRAY;
            dprintf(
                "%02x <Method> Flags=%x Start=%x Len=%x\n",
                Object->dwDataType,
                method->bMethodFlags,
                (ULONG_PTR) method->abCodeBuff - (ULONG_PTR) method +
                (ULONG_PTR) Object->pbDataBuff,
                max
                );
            break;

        }
        case OBJTYPE_MUTEX:

            dprintf(
                "%02x <Mutex> Mutex=%08lx\n",
                Object->dwDataType,
                Object->pbDataBuff
                );
            break;

        case OBJTYPE_OPREGION: {

            POPREGIONOBJ    opRegion = (POPREGIONOBJ) buffer;

            dprintf(
                "%02x <Operational Region> RegionSpace=%08x OffSet=%x "
                "Len=%x\n",
                Object->dwDataType,
                opRegion->bRegionSpace,
                opRegion->uipOffset,
                opRegion->dwLen
                );
            break;

        }

        case OBJTYPE_POWERRES: {

            PPOWERRESOBJ    powerRes = (PPOWERRESOBJ) buffer;

            dprintf(
                "%02x <Power Resource> SystemLevel=S%d Order=%x\n",
                Object->dwDataType,
                powerRes->bSystemLevel,
                powerRes->bResOrder
                );
            break;

        }

        case OBJTYPE_PROCESSOR: {

            PPROCESSOROBJ   proc = (PPROCESSOROBJ) buffer;

            dprintf(
                "%02x <Processor> AcpiID=%x PBlk=%x PBlkLen=%x\n",
                Object->dwDataType,
                proc->bApicID,
                proc->dwPBlk,
                proc->dwPBlkLen
                );
            break;

        }

        case OBJTYPE_THERMALZONE:
            dprintf(
                "%02x <Thermal Zone>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_BUFFFIELD: {

            PBUFFFIELDOBJ   field   = (PBUFFFIELDOBJ) buffer;

            dprintf(
                "%02x <Buffer Field> Ptr=%x Len=%x Offset=%x Start=%x "
                "NumBits=%x Flags=%x\n",
                Object->dwDataType,
                field->pbDataBuff,
                field->dwBuffLen,
                field->FieldDesc.dwByteOffset,
                field->FieldDesc.dwStartBitPos,
                field->FieldDesc.dwNumBits,
                field->FieldDesc.dwFieldFlags
                );
            break;

        }

        case OBJTYPE_DDBHANDLE:
            dprintf(
                "%02x <DDB Handle> Handle=%x\n",
                Object->dwDataType,
                Object->pbDataBuff
                );
            break;
        case OBJTYPE_DEBUG:
            dprintf(
                "%02x <Internal Debug>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_OBJALIAS:

            dprintf(
                "%02x <Internal Object Alias> NS Object=%x\n",
                Object->dwDataType,
                Object->uipDataValue
                );
            dumpNSObject( Object->uipDataValue, Verbose, IndentLevel + 2 );
            break;
        case OBJTYPE_DATAALIAS: {

            OBJDATA     objData;

            dprintf(
                "%02x <Internal Data Alias> Data Object=%x\n",
                Object->dwDataType,
                Object->uipDataValue
                );

            b = ReadMemory(
                (ULONG) Object->uipDataValue,
                &objData,
                sizeof(OBJDATA),
                NULL
                );
            if (!b) {

                dprintf(
                    "dumpObject: could not read %x\n",
                    Object->uipDataValue
                    );
                return;

            }
            dumpObject(
                (ULONG) Object->uipDataValue,
                &objData,
                Verbose,
                IndentLevel + 2
                );
            break;

        }
        case OBJTYPE_BANKFIELD:
            dprintf(
                "%02x <Internal Bank Field>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_FIELD:
            dprintf(
                "%02x <Internal Field>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_INDEXFIELD:
            dprintf(
                "%02x <Index Field>\n",
                Object->dwDataType
                );
            break;
        case OBJTYPE_UNKNOWN:
        default:
            dprintf(
                "%02x <Unknown>\n",
                Object->dwDataType
                );
            break;
    }
}


VOID
dumpPObject(
    IN  ULONG_PTR   Address,
    IN  ULONG       Verbose,
    IN  ULONG       IndentLevel
    )
/*++

Routine Description:

    This is a wrapper for dumpObject


--*/
{
    BOOL    result;
    OBJDATA objdata;
    ULONG   returnLength;

    result = ReadMemory(
        Address,
        &objdata,
        sizeof(OBJDATA),
        &returnLength
        );
    if (result != TRUE || returnLength != sizeof(OBJDATA) ) {

        UCHAR   indent[80];

        IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
        memset( indent, ' ', IndentLevel );
        indent[IndentLevel] = '\0';

        dprintf(
            "%sdumpPObject: Could not OBJDATA %08lx\n",
            indent,
            Address
            );
        return;

    }

    dumpObject(
        Address,
        &objdata,
        Verbose,
        IndentLevel
        );
    return;

}

PUCHAR
TempToKelvins(
    IN  ULONG   Temp
    )
{
    static  UCHAR buffer[80];

    sprintf( buffer, "%d.%d", (Temp / 10 ), (Temp % 10) );
    return buffer;
}

PUCHAR
TimeToSeconds(
    IN  ULONG   Time
    )
{
    static  UCHAR buffer[80];

    sprintf( buffer, "%d.%d", (Time / 10 ), (Time % 10) );
    return buffer;

}