526 lines
9.2 KiB
C
526 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
amlisupp.h
|
||
|
||
Abstract:
|
||
|
||
This contains some of the routines to read
|
||
and understand the AMLI library
|
||
|
||
Author:
|
||
|
||
Stephane Plante (splante)
|
||
|
||
Environment:
|
||
|
||
NT Kernel Model Driver only
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
|
||
|
||
PSZ gpszOSName = "Microsoft Windows NT";
|
||
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,ACPIAmliFindObject)
|
||
#endif
|
||
|
||
|
||
VOID
|
||
ACPIAmliDoubleToName(
|
||
IN OUT PUCHAR ACPIName,
|
||
IN ULONG DwordID,
|
||
IN BOOLEAN ConvertToID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Convert the DWORD ID into a 9 character name
|
||
|
||
Arguments:
|
||
|
||
ACPIName - Pointer to a memory location to fill
|
||
DwordID - The ID to verify with IsID()?
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
USHORT value;
|
||
|
||
//
|
||
// Leading Star
|
||
//
|
||
// Note: This has been left in since this is what Query ID should return:
|
||
// DeviceID = ACPI\PNPxxxx
|
||
// InstanceID = yyyy
|
||
// HardwareID = DeviceID,*PNPxxxx
|
||
//
|
||
if (ConvertToID) {
|
||
|
||
*ACPIName = '*';
|
||
ACPIName++;
|
||
}
|
||
|
||
//
|
||
// First character of DwordID[2..6]
|
||
//
|
||
*ACPIName = (UCHAR) ( ( (DwordID & 0x007C) >> 2 ) + 'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// Second Character from DwordID[13..15,0..1]
|
||
//
|
||
*ACPIName = (UCHAR) ( ( (DwordID & 0x3 )<< 3 ) +
|
||
( (DwordID & 0xE000) >> 13 ) + 'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// Third Character from dwID[8..12]
|
||
//
|
||
*ACPIName = (UCHAR) ( ( (DwordID >> 8 ) & 0x1F) + 'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// The rest is made up of the Product ID, which is the HIWORD of the
|
||
// DwordID
|
||
//
|
||
value = (USHORT) (DwordID >> 16);
|
||
|
||
//
|
||
// Add to the reset of the string
|
||
//
|
||
sprintf(ACPIName, "%02X%02X",(value & 0xFF ) ,( value >> 8 ));
|
||
}
|
||
|
||
|
||
VOID
|
||
ACPIAmliDoubleToNameWide(
|
||
IN OUT PWCHAR ACPIName,
|
||
IN ULONG DwordID,
|
||
IN BOOLEAN ConvertToID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Convert the DWORD ID into a 9 character name
|
||
|
||
Arguments:
|
||
|
||
ACPIName - Pointer to a memory location to fill
|
||
DwordID - The ID to verify with IsID()?
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
USHORT value;
|
||
|
||
//
|
||
// Leading Star
|
||
//
|
||
// Note: This has been left in since this is what Query ID should return:
|
||
// DeviceID = ACPI\PNPxxxx
|
||
// InstanceID = yyyy
|
||
// HardwareID = DeviceID,*PNPxxxx
|
||
//
|
||
if (ConvertToID) {
|
||
|
||
*ACPIName = L'*';
|
||
ACPIName++;
|
||
|
||
}
|
||
|
||
//
|
||
// First character of DwordID[2..6]
|
||
//
|
||
*ACPIName = (WCHAR) ( ( (DwordID & 0x007C) >> 2 ) + L'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// Second Character from DwordID[13..15,0..1]
|
||
//
|
||
*ACPIName = (WCHAR) ( ( (DwordID & 0x3 )<< 3 ) +
|
||
( (DwordID & 0xE000) >> 13 ) + L'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// Third Character from dwID[8..12]
|
||
//
|
||
*ACPIName = (WCHAR) ( ( (DwordID >> 8 ) & 0x1F) + L'A' - 1);
|
||
ACPIName++;
|
||
|
||
//
|
||
// The rest is made up of the Product ID, which is the HIWORD of the
|
||
// DwordID
|
||
//
|
||
value = (USHORT) (DwordID >> 16);
|
||
|
||
//
|
||
// Add to the reset of the string
|
||
//
|
||
swprintf(ACPIName, L"%02X%02X",(value & 0xFF ) ,( value >> 8 ));
|
||
}
|
||
|
||
VOID
|
||
EXPORT
|
||
AmlisuppCompletePassive(
|
||
IN PNSOBJ AcpiObject,
|
||
IN NTSTATUS Status,
|
||
IN POBJDATA Result,
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is used as the completion routine for several
|
||
functions in this file that run at passive level.
|
||
|
||
Arguments:
|
||
|
||
AcpiObject - unused
|
||
Status - status to be returned to caller
|
||
Result - unused
|
||
Context - contains the event to be set
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
{
|
||
PRKEVENT event = &((PAMLISUPP_CONTEXT_PASSIVE)Context)->Event;
|
||
|
||
ASSERT(Context);
|
||
|
||
((PAMLISUPP_CONTEXT_PASSIVE)Context)->Status = Status;
|
||
KeSetEvent(event, IO_NO_INCREMENT, FALSE);
|
||
}
|
||
|
||
PNSOBJ
|
||
ACPIAmliGetNamedChild(
|
||
IN PNSOBJ AcpiObject,
|
||
IN ULONG ObjectId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Looks at all the children of AcpiObject and returns
|
||
the one named 'ObjectId'.
|
||
|
||
Arguments:
|
||
|
||
AcpiObject - Object to search in
|
||
ObjectId - What we are looking for
|
||
|
||
Return Value:
|
||
|
||
A PNSOBJ, NULL if none
|
||
|
||
--*/
|
||
{
|
||
PNSOBJ tempObject;
|
||
|
||
//
|
||
// Lets try to find a child object
|
||
//
|
||
for (tempObject = NSGETFIRSTCHILD(AcpiObject);
|
||
tempObject != NULL;
|
||
tempObject = NSGETNEXTSIBLING(tempObject)) {
|
||
|
||
if (ObjectId == tempObject->dwNameSeg) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return tempObject;
|
||
}
|
||
|
||
PUCHAR
|
||
ACPIAmliNameObject(
|
||
IN PNSOBJ AcpiObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns a String that describes the objects
|
||
Debug Only
|
||
|
||
Arguments:
|
||
|
||
AcpiOBject - The object to name
|
||
|
||
Returns:
|
||
|
||
String
|
||
|
||
--*/
|
||
{
|
||
static UCHAR buffer[5];
|
||
|
||
RtlCopyMemory( &buffer[0], &(AcpiObject->dwNameSeg), 4 );
|
||
buffer[4] = '\0';
|
||
|
||
return &(buffer[0]);
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIAmliFindObject(
|
||
IN PUCHAR ObjectName,
|
||
IN PNSOBJ Scope,
|
||
OUT PNSOBJ *Object
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the first occurrence of an object within a given scope.
|
||
|
||
Arguments:
|
||
|
||
ObjectName - Name of the object. (null terminated)
|
||
|
||
Scope - Node to search under
|
||
|
||
Object - Pointer to return value
|
||
|
||
Returns:
|
||
|
||
status
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PNSOBJ child;
|
||
PNSOBJ sibling;
|
||
|
||
PAGED_CODE();
|
||
|
||
status = AMLIGetNameSpaceObject(ObjectName,
|
||
Scope,
|
||
Object,
|
||
NSF_LOCAL_SCOPE);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
return status;
|
||
}
|
||
|
||
child = NSGETFIRSTCHILD(Scope);
|
||
|
||
if (child) {
|
||
|
||
status = ACPIAmliFindObject(ObjectName,
|
||
child,
|
||
Object);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
return status;
|
||
}
|
||
}
|
||
|
||
sibling = NSGETNEXTSIBLING(Scope);
|
||
|
||
if (sibling) {
|
||
|
||
status = ACPIAmliFindObject(ObjectName,
|
||
sibling,
|
||
Object);
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIAmliGetFirstChild(
|
||
IN PUCHAR ObjectName,
|
||
OUT PNSOBJ *Object)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to get the first nsobject which is of type 'Device'
|
||
that lives under ObjectName
|
||
|
||
Arguments:
|
||
|
||
ObjectName - The parent of the child we are looking for
|
||
Object - Where to save a pointer to the PNSOBJ
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PNSOBJ parentObj;
|
||
|
||
status = AMLIGetNameSpaceObject(
|
||
ObjectName,
|
||
NULL,
|
||
&parentObj,
|
||
0
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
*Object = parentObj->pnsFirstChild;
|
||
if (*Object == NULL ) {
|
||
|
||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
||
}
|
||
|
||
if ( NSGETOBJTYPE(*Object) == OBJTYPE_DEVICE) {
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
*Object = (PNSOBJ) (*Object)->list.plistNext;
|
||
parentObj = parentObj->pnsFirstChild;
|
||
while (*Object != parentObj) {
|
||
|
||
if ( NSGETOBJTYPE( *Object ) == OBJTYPE_DEVICE) {
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
*Object = (PNSOBJ) (*Object)->list.plistNext;
|
||
|
||
}
|
||
|
||
*Object = NULL;
|
||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIAmliBuildObjectPathname(
|
||
IN PNSOBJ ACPIObject,
|
||
OUT PUCHAR *ConstructedPathName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function takes an ACPI node and constructs the full path name with
|
||
the parent/children seperated by '.'s, spaces with '*'s. e.g. (we smack
|
||
off the initial '\___'.
|
||
|
||
_SB*.PCI0.DOCK
|
||
|
||
Arguments:
|
||
|
||
ACPIObject - Object to start the enumeration at.
|
||
ConstructedPathName - Allocated from the paged pool.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
PNSOBJ currentAcpiObject, nextAcpiObject ;
|
||
ULONG nDepth, i, j ;
|
||
PUCHAR objectPathname ;
|
||
|
||
ASSERT(ACPIObject) ;
|
||
|
||
//
|
||
// First, calculate the size of data we must allocate
|
||
//
|
||
nDepth=0 ;
|
||
currentAcpiObject=ACPIObject ;
|
||
while(1) {
|
||
|
||
nextAcpiObject = NSGETPARENT(currentAcpiObject);
|
||
if (!nextAcpiObject) {
|
||
|
||
break;
|
||
|
||
}
|
||
nDepth++;
|
||
currentAcpiObject = nextAcpiObject;
|
||
|
||
}
|
||
|
||
objectPathname = (PUCHAR) ExAllocatePoolWithTag(
|
||
NonPagedPool,
|
||
(nDepth * 5) + 1,
|
||
ACPI_STRING_POOLTAG
|
||
);
|
||
if (!objectPathname) {
|
||
|
||
return STATUS_INSUFFICIENT_RESOURCES ;
|
||
|
||
}
|
||
|
||
objectPathname[ nDepth * 5 ] = '\0';
|
||
j = nDepth;
|
||
currentAcpiObject = ACPIObject;
|
||
|
||
while(1) {
|
||
|
||
nextAcpiObject = NSGETPARENT(currentAcpiObject);
|
||
if (!nextAcpiObject) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
j--;
|
||
RtlCopyMemory(
|
||
&objectPathname[ (j * 5) ],
|
||
&(currentAcpiObject->dwNameSeg),
|
||
sizeof(NAMESEG)
|
||
);
|
||
for(i = 0; i < 4; i++) {
|
||
|
||
if (objectPathname[ (j * 5) + i ] == '\0' ) {
|
||
|
||
objectPathname[ (j * 5) + i ] = '*';
|
||
|
||
}
|
||
|
||
}
|
||
objectPathname[ (j * 5) + 4 ] = '.';
|
||
currentAcpiObject = nextAcpiObject;
|
||
|
||
}
|
||
|
||
//
|
||
// Smack of trailing '.'
|
||
//
|
||
if (nDepth) {
|
||
|
||
objectPathname[ (nDepth * 5) - 1 ] = '\0';
|
||
|
||
}
|
||
|
||
*ConstructedPathName = objectPathname;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|