You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
548 lines
14 KiB
548 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
match.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the routines that try to match a PNSOBJ with a DeviceObject
|
|
|
|
Author:
|
|
|
|
Stephane Plante (splante)
|
|
|
|
Environment:
|
|
|
|
NT Kernel Model Driver only
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "hdlsblk.h"
|
|
#include "hdlsterm.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,ACPIMatchHardwareAddress)
|
|
#pragma alloc_text(PAGE,ACPIMatchHardwareId)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
ACPIMatchHardwareAddress(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG DeviceAddress,
|
|
OUT BOOLEAN *Success
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines the device address of the two supplied objects and checks
|
|
for a match
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The NT DeviceObject that we wish to check
|
|
DeviceAddress - The ACPI address of the device
|
|
Success - Pointer of where to store the result of the comparison
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
DEVICE_CAPABILITIES deviceCapabilities;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( DeviceObject != NULL );
|
|
ASSERT( Success != NULL );
|
|
|
|
//
|
|
// Assume that we don't succeed
|
|
//
|
|
*Success = FALSE;
|
|
|
|
//
|
|
// Get the capabilities
|
|
//
|
|
status = ACPIInternalGetDeviceCapabilities(
|
|
DeviceObject,
|
|
&deviceCapabilities
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
goto ACPIMatchHardwareAddressExit;
|
|
|
|
}
|
|
|
|
//
|
|
// Lets compare the two answers
|
|
//
|
|
ACPIPrint( (
|
|
ACPI_PRINT_LOADING,
|
|
"%lx: ACPIMatchHardwareAddress - Device %08lx - %08lx\n",
|
|
DeviceAddress,
|
|
DeviceObject,
|
|
deviceCapabilities.Address
|
|
) );
|
|
if (DeviceAddress == deviceCapabilities.Address) {
|
|
|
|
*Success = TRUE;
|
|
|
|
}
|
|
|
|
ACPIMatchHardwareAddressExit:
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_LOADING,
|
|
"%lx: ACPIMatchHardwareAddress - Device: %#08lx - Status: %#08lx "
|
|
"Success:%#02lx\n",
|
|
DeviceAddress,
|
|
DeviceObject,
|
|
status,
|
|
*Success
|
|
) );
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
ACPIMatchHardwareId(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PUNICODE_STRING AcpiUnicodeId,
|
|
OUT BOOLEAN *Success
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is responsible for determining if the supplied objects have the
|
|
same device name
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The NT Device Object whose name we want to check
|
|
UnicodeId - The ID that we are trying to match with
|
|
Success - Where to store the success status
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
IO_STACK_LOCATION irpSp;
|
|
NTSTATUS status;
|
|
PWSTR buffer;
|
|
PWSTR currentPtr;
|
|
UNICODE_STRING objectDeviceId;
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( DeviceObject != NULL );
|
|
ASSERT( Success != NULL );
|
|
|
|
*Success = FALSE;
|
|
|
|
//
|
|
// Initialize the stack location to pass to ACPIInternalSendSynchronousIrp()
|
|
//
|
|
RtlZeroMemory( &irpSp, sizeof(IO_STACK_LOCATION) );
|
|
RtlZeroMemory( &objectDeviceId, sizeof(UNICODE_STRING) );
|
|
|
|
//
|
|
// Set the function codes
|
|
//
|
|
irpSp.MajorFunction = IRP_MJ_PNP;
|
|
irpSp.MinorFunction = IRP_MN_QUERY_ID;
|
|
irpSp.Parameters.QueryId.IdType = BusQueryHardwareIDs;
|
|
|
|
//
|
|
// Make the call now...
|
|
//
|
|
status = ACPIInternalSendSynchronousIrp( DeviceObject, &irpSp, &buffer );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
goto ACPIMatchHardwareIdExit;
|
|
|
|
}
|
|
|
|
//
|
|
// The return from the call is actually a MultiString, so we have to
|
|
// walk all of its components
|
|
//
|
|
currentPtr = buffer;
|
|
while (currentPtr && *currentPtr != L'\0') {
|
|
|
|
//
|
|
// At this point, we can make a Unicode String from the buffer...
|
|
//
|
|
RtlInitUnicodeString( &objectDeviceId, currentPtr );
|
|
|
|
//
|
|
// Increment the current pointer to the next part of the MultiString
|
|
//
|
|
currentPtr += (objectDeviceId.MaximumLength / sizeof(WCHAR) );
|
|
|
|
//
|
|
// Now try to compare the two unicode strings...
|
|
//
|
|
if (RtlEqualUnicodeString( &objectDeviceId, AcpiUnicodeId, TRUE) ) {
|
|
|
|
*Success = TRUE;
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Done -- free resources
|
|
//
|
|
ExFreePool( buffer );
|
|
|
|
ACPIMatchHardwareIdExit:
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_LOADING,
|
|
"%ws: ACPIMatchHardwareId - %08lx - Status: %#08lx Success:%#02lx\n",
|
|
AcpiUnicodeId->Buffer,
|
|
DeviceObject,
|
|
status,
|
|
*Success
|
|
) );
|
|
|
|
return status;
|
|
}
|
|
|
|
VOID
|
|
ACPIMatchKernelPorts(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN POBJDATA Resources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to determine if the supplied deviceExtension
|
|
is currently in use by the Kernel as the debugger port or the headless
|
|
port. If it is so marked, then we handle it 'special'.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Port to check
|
|
Resources - What resources the port is using
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN ioFound;
|
|
BOOLEAN matchFound = FALSE;
|
|
PUCHAR buffer = Resources->pbDataBuff;
|
|
UCHAR tagName = *buffer;
|
|
PUCHAR baseAddress = NULL;
|
|
ULONG count = 0;
|
|
PUCHAR headlessBaseAddress = NULL;
|
|
USHORT increment;
|
|
SIZE_T length;
|
|
NTSTATUS status;
|
|
HEADLESS_RSP_QUERY_INFO response;
|
|
PUCHAR kdBaseAddr = NULL;
|
|
|
|
//
|
|
// Get the information about headless
|
|
//
|
|
length = sizeof(HEADLESS_RSP_QUERY_INFO);
|
|
status = HeadlessDispatch(HeadlessCmdQueryInformation,
|
|
NULL,
|
|
0,
|
|
&response,
|
|
&length
|
|
);
|
|
|
|
if (NT_SUCCESS(status) &&
|
|
(response.PortType == HeadlessSerialPort) &&
|
|
response.Serial.TerminalAttached) {
|
|
|
|
headlessBaseAddress = response.Serial.TerminalPortBaseAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// First of all, see if the any Kernel port is in use
|
|
//
|
|
if ((KdComPortInUse == NULL || *KdComPortInUse == 0) &&
|
|
(headlessBaseAddress == NULL)) {
|
|
|
|
//
|
|
// No port in use
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( KdComPortInUse ) {
|
|
kdBaseAddr = *KdComPortInUse;
|
|
}
|
|
|
|
//
|
|
// Look through all the descriptors
|
|
//
|
|
while (count < Resources->dwDataLen) {
|
|
|
|
//
|
|
// We haven't found any IO ports
|
|
//
|
|
ioFound = FALSE;
|
|
|
|
//
|
|
// Determine the size of the PNP resource descriptor
|
|
//
|
|
if (!(tagName & LARGE_RESOURCE_TAG) ) {
|
|
|
|
//
|
|
// This is a small tag
|
|
//
|
|
increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1;
|
|
tagName &= SMALL_TAG_MASK;
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is a large tag
|
|
//
|
|
increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3;
|
|
|
|
}
|
|
|
|
//
|
|
// We are done if the current tag is the end tag
|
|
//
|
|
if (tagName == TAG_END) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (tagName) {
|
|
case TAG_IO: {
|
|
|
|
PPNP_PORT_DESCRIPTOR desc = (PPNP_PORT_DESCRIPTOR) buffer;
|
|
|
|
//
|
|
// We found an IO port and so we will note that
|
|
//
|
|
baseAddress = (PUCHAR) ((ULONG_PTR)desc->MinimumAddress);
|
|
ioFound = TRUE;
|
|
break;
|
|
}
|
|
case TAG_IO_FIXED: {
|
|
|
|
PPNP_FIXED_PORT_DESCRIPTOR desc = (PPNP_FIXED_PORT_DESCRIPTOR) buffer;
|
|
|
|
//
|
|
// We found an IO port so we will note that
|
|
//
|
|
baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress & 0x3FF));
|
|
ioFound = TRUE;
|
|
break;
|
|
|
|
}
|
|
case TAG_WORD_ADDRESS: {
|
|
|
|
PPNP_WORD_ADDRESS_DESCRIPTOR desc = (PPNP_WORD_ADDRESS_DESCRIPTOR) buffer;
|
|
|
|
//
|
|
// Determine the address type
|
|
//
|
|
switch (desc->RFlag) {
|
|
case PNP_ADDRESS_MEMORY_TYPE:
|
|
|
|
//
|
|
// We found a Mem IO Port
|
|
//
|
|
|
|
if ( kdBaseAddr ) {
|
|
kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
|
|
}
|
|
|
|
//
|
|
// fall through to the IO behavior.
|
|
// The MinimumAddress will contain the memIO
|
|
// address.
|
|
//
|
|
|
|
case PNP_ADDRESS_IO_TYPE:
|
|
|
|
//
|
|
// We found an IO Port, so we will note that
|
|
//
|
|
baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress +
|
|
desc->TranslationAddress));
|
|
ioFound = TRUE;
|
|
break;
|
|
|
|
default:
|
|
NOTHING;
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
case TAG_DOUBLE_ADDRESS: {
|
|
|
|
PPNP_DWORD_ADDRESS_DESCRIPTOR desc = (PPNP_DWORD_ADDRESS_DESCRIPTOR) buffer;
|
|
|
|
//
|
|
// Determine the address type
|
|
//
|
|
switch (desc->RFlag) {
|
|
case PNP_ADDRESS_MEMORY_TYPE:
|
|
|
|
//
|
|
// We found a Mem IO Port
|
|
//
|
|
|
|
if ( kdBaseAddr ) {
|
|
kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
|
|
}
|
|
|
|
//
|
|
// fall through to the IO behavior.
|
|
// The MinimumAddress will contain the memIO
|
|
// address.
|
|
//
|
|
|
|
case PNP_ADDRESS_IO_TYPE:
|
|
|
|
//
|
|
// We found an IO Port, so we will note that
|
|
//
|
|
baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress +
|
|
desc->TranslationAddress));
|
|
ioFound = TRUE;
|
|
break;
|
|
|
|
default:
|
|
NOTHING;
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
case TAG_QUAD_ADDRESS: {
|
|
|
|
PPNP_QWORD_ADDRESS_DESCRIPTOR desc = (PPNP_QWORD_ADDRESS_DESCRIPTOR) buffer;
|
|
|
|
|
|
//
|
|
// Determine the address type
|
|
//
|
|
switch (desc->RFlag) {
|
|
case PNP_ADDRESS_MEMORY_TYPE:
|
|
|
|
//
|
|
// We found a Mem IO Port
|
|
//
|
|
|
|
if ( kdBaseAddr ) {
|
|
kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
|
|
}
|
|
|
|
//
|
|
// fall through to the IO behavior.
|
|
// The MinimumAddress will contain the memIO
|
|
// address.
|
|
//
|
|
|
|
case PNP_ADDRESS_IO_TYPE:
|
|
|
|
//
|
|
// We found an IO Port, so we will note that
|
|
//
|
|
baseAddress = (PUCHAR) (desc->MinimumAddress +
|
|
desc->TranslationAddress);
|
|
ioFound = TRUE;
|
|
break;
|
|
|
|
default:
|
|
NOTHING;
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} // switch
|
|
|
|
//
|
|
// Did we find an IO port?
|
|
//
|
|
|
|
if (ioFound == TRUE) {
|
|
|
|
//
|
|
// Does the minimum address match?
|
|
//
|
|
if (((KdComPortInUse != NULL) && (baseAddress == kdBaseAddr)) ||
|
|
((headlessBaseAddress != NULL) && (baseAddress == headlessBaseAddress))) {
|
|
|
|
//
|
|
// Mark the node as being special
|
|
//
|
|
ACPIInternalUpdateFlags(
|
|
&(DeviceExtension->Flags),
|
|
(DEV_CAP_NO_OVERRIDE | DEV_CAP_NO_STOP | DEV_CAP_ALWAYS_PS0 |
|
|
DEV_TYPE_NOT_PRESENT | DEV_TYPE_NEVER_PRESENT),
|
|
FALSE);
|
|
|
|
if ((KdComPortInUse != NULL) && (baseAddress == kdBaseAddr)) {
|
|
ACPIDevPrint( (
|
|
ACPI_PRINT_LOADING,
|
|
DeviceExtension,
|
|
"ACPIMatchKernelPorts - Found KD Port at %lx\n",
|
|
baseAddress
|
|
) );
|
|
} else {
|
|
ACPIDevPrint( (
|
|
ACPI_PRINT_LOADING,
|
|
DeviceExtension,
|
|
"ACPIMatchKernelPorts - Found Headless Port at %lx\n",
|
|
baseAddress
|
|
) );
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Move of the next descriptor
|
|
//
|
|
count += increment;
|
|
buffer += increment;
|
|
tagName = *buffer;
|
|
|
|
}
|
|
|
|
|
|
}
|