/*++ 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; } }