diff options
Diffstat (limited to 'private/ntos/nthals/extender/pnpisa.sur/resource.c')
-rw-r--r-- | private/ntos/nthals/extender/pnpisa.sur/resource.c | 680 |
1 files changed, 680 insertions, 0 deletions
diff --git a/private/ntos/nthals/extender/pnpisa.sur/resource.c b/private/ntos/nthals/extender/pnpisa.sur/resource.c new file mode 100644 index 000000000..4e81668a5 --- /dev/null +++ b/private/ntos/nthals/extender/pnpisa.sur/resource.c @@ -0,0 +1,680 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + devres.c + +Abstract: + + This module contains the high level device resources support routines. + +Author: + + Shie-Lin Tzong (shielint) July-27-1995 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "busp.h" +#include "pnpisa.h" +#include "pbios.h" + +#define IDBG 0 + +#pragma alloc_text(INIT,PipGetCardIdentifier) +#pragma alloc_text(INIT,PipGetFunctionIdentifier) +#pragma alloc_text(INIT,PipGetCompatibleDeviceId) +#pragma alloc_text(INIT,PipQueryDeviceId) +#pragma alloc_text(INIT,PipQueryDeviceUniqueId) +#pragma alloc_text(INIT,PipQueryDeviceResources) +#pragma alloc_text(INIT,PipQueryDeviceResourceRequirements) +#pragma alloc_text(INIT,PipSetDeviceResources) + +NTSTATUS +PipGetCardIdentifier ( + PUCHAR CardData, + PWCHAR *Buffer, + PULONG BufferLength + ) +/*++ + +Routine Description: + + This function returns the identifier for a pnpisa card. + +Arguments: + + CardData - supplies a pointer to the pnp isa device data. + + Buffer - supplies a pointer to variable to receive a pointer to the Id. + + BufferLength - supplies a pointer to a variable to receive the size of the id buffer. + +Return Value: + + NTSTATUS code + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + UCHAR tag; + LONG size, length; + UNICODE_STRING unicodeString; + ANSI_STRING ansiString; + PCHAR ansiBuffer; + + *Buffer = NULL; + *BufferLength = 0; + + tag = *CardData; + + // + // Make sure CardData does *NOT* point to a Logical Device Id tag + // + + if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) { + DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n"); + return status; + } + + // + // Find the resource descriptor which describle identifier string + // + + do { + + // + // Do we find the identifer resource tag? + // + + if (tag == TAG_ANSI_ID) { + CardData++; + length = *(PUSHORT)CardData; + CardData += 2; + ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1); + if (ansiBuffer == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + RtlMoveMemory(ansiBuffer, CardData, length); + ansiBuffer[length] = 0; + RtlInitAnsiString(&ansiString, ansiBuffer); + RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); + ExFreePool(ansiBuffer); + *Buffer = unicodeString.Buffer; + *BufferLength = unicodeString.Length + sizeof(WCHAR); + break; + } + + // + // Determine the size of the BIOS resource descriptor and + // advance to next resource descriptor. + // + + if (!(tag & LARGE_RESOURCE_TAG)) { + size = (USHORT)(tag & SMALL_TAG_SIZE_MASK); + size += 1; // length of small tag + } else { + size = *(PUSHORT)(CardData + 1); + size += 3; // length of large tag + } + + CardData += size; + tag = *CardData; + + } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)); + + return status; +} + +NTSTATUS +PipGetFunctionIdentifier ( + PUCHAR DeviceData, + PWCHAR *Buffer, + PULONG BufferLength + ) +/*++ + +Routine Description: + + This function returns the desired pnp isa identifier for the specified + DeviceData/LogicalFunction. The Identifier for a logical function is + optional. If no Identifier available , Buffer is set to NULL. + +Arguments: + + DeviceData - supplies a pointer to the pnp isa device data. + + Buffer - supplies a pointer to variable to receive a pointer to the Id. + + BufferLength - supplies a pointer to a variable to receive the size of the id buffer. + +Return Value: + + NTSTATUS code + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + UCHAR tag; + LONG size, length; + UNICODE_STRING unicodeString; + ANSI_STRING ansiString; + PCHAR ansiBuffer; + + *Buffer = NULL; + *BufferLength = 0; + + tag = *DeviceData; + +#if DBG + + // + // Make sure device data points to Logical Device Id tag + // + + if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) { + DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n"); + } +#endif + + // + // Skip all the resource descriptors to find compatible Id descriptor + // + + do { + + // + // Determine the size of the BIOS resource descriptor and + // advance to next resource descriptor. + // + + if (!(tag & LARGE_RESOURCE_TAG)) { + size = (USHORT)(tag & SMALL_TAG_SIZE_MASK); + size += 1; // length of small tag + } else { + size = *(PUSHORT)(DeviceData + 1); + size += 3; // length of large tag + } + + DeviceData += size; + tag = *DeviceData; + + // + // Do we find the identifer resource tag? + // + + if (tag == TAG_ANSI_ID) { + DeviceData++; + length = *(PUSHORT)DeviceData; + DeviceData += 2; + ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1); + if (ansiBuffer == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + RtlMoveMemory(ansiBuffer, DeviceData, length); + ansiBuffer[length] = 0; + RtlInitAnsiString(&ansiString, ansiBuffer); + RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); + ExFreePool(ansiBuffer); + *Buffer = unicodeString.Buffer; + *BufferLength = unicodeString.Length + sizeof(WCHAR); + break; + } + + } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)); + + return status; +} + +NTSTATUS +PipGetCompatibleDeviceId ( + PUCHAR DeviceData, + ULONG IdIndex, + PWCHAR *Buffer + ) +/*++ + +Routine Description: + + This function returns the desired pnp isa id for the specified DeviceData + and Id index. If Id index = 0, the Hardware ID will be return; if id + index = n, the Nth compatible id will be returned. + +Arguments: + + DeviceData - supplies a pointer to the pnp isa device data. + + IdIndex - supplies the index of the compatible id desired. + + Buffer - supplies a pointer to variable to receive a pointer to the compatible Id. + +Return Value: + + NTSTATUS code + +--*/ +{ + NTSTATUS status = STATUS_NO_MORE_ENTRIES; + UCHAR tag; + ULONG count = 0; + LONG size; + UNICODE_STRING unicodeString; + ANSI_STRING ansiString; + UCHAR eisaId[8]; + ULONG id; + + tag = *DeviceData; + +#if DBG + + // + // Make sure device data points to Logical Device Id tag + // + + if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) { + DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n"); + } +#endif + + if (IdIndex == 0) { + + // + // Caller is asking for hardware id + // + + DeviceData++; // Skip tag + id = *(PULONG)DeviceData; + status = STATUS_SUCCESS; + } else { + + // + // caller is asking for compatible id + // + + IdIndex--; + + // + // Skip all the resource descriptors to find compatible Id descriptor + // + + do { + + // + // Determine the size of the BIOS resource descriptor and + // advance to next resource descriptor. + // + + if (!(tag & LARGE_RESOURCE_TAG)) { + size = (USHORT)(tag & SMALL_TAG_SIZE_MASK); + size += 1; // length of small tag + } else { + size = *(PUSHORT)(DeviceData + 1); + size += 3; // length of large tag + } + + DeviceData += size; + tag = *DeviceData; + + // + // Do we reach the compatible ID descriptor? + // + + if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) { + if (count == IdIndex) { + id = *(PULONG)(DeviceData + 1); + status = STATUS_SUCCESS; + break; + } else { + count++; + } + } + + } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)); + } + + if (NT_SUCCESS(status)) { + PipDecompressEisaId(id, eisaId); + RtlInitAnsiString(&ansiString, eisaId); + RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); + *Buffer = (PWCHAR)ExAllocatePool ( + PagedPool, + sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length + ); + if (*Buffer) { + swprintf(*Buffer, L"*%s", unicodeString.Buffer); + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + } + RtlFreeUnicodeString(&unicodeString); + } + return status; +} + +NTSTATUS +PipQueryDeviceUniqueId ( + PDEVICE_INFORMATION DeviceInfo, + PWCHAR *DeviceId + ) +/*++ + +Routine Description: + + This function returns the unique id for the particular device. + +Arguments: + + DeviceData - Device data information for the specificied device. + + DeviceId - supplies a pointer to a variable to receive device id. + +Return Value: + + NTSTATUS code. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + // + // Set up device's unique id. + // device unique id = SerialNumber of the card + // + + *DeviceId = (PWCHAR)ExAllocatePool ( + PagedPool, + (8 + 1) * sizeof(WCHAR) // serial number + null + ); + if (*DeviceId) { + swprintf (*DeviceId, + L"%08X", + ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber + ); +#if IDBG + { + ANSI_STRING ansiString; + UNICODE_STRING unicodeString; + + RtlInitUnicodeString(&unicodeString, *DeviceId); + RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE); + DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer); + RtlFreeAnsiString(&ansiString); + } +#endif + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + + } + + return status; +} + +NTSTATUS +PipQueryDeviceId ( + PDEVICE_INFORMATION DeviceInfo, + PWCHAR *DeviceId, + ULONG IdIndex + ) +/*++ + +Routine Description: + + This function returns the device id for the particular device. + +Arguments: + + DeviceInfo - Device information for the specificied device. + + DeviceId - supplies a pointer to a variable to receive the device id. + + IdIndex - specifies device id or compatible id (0 - device id) + +Return Value: + + NTSTATUS code. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PWSTR format; + ULONG size; + UCHAR eisaId[8]; + UNICODE_STRING unicodeString; + ANSI_STRING ansiString; + + // + // Set up device's id. + // device id = VenderId + Logical device number + // + + if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) { + format = L"ISAPNP\\%s"; + size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR); + } else { + format = L"ISAPNP\\%s_DEV%04X"; + size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR); + } + PipDecompressEisaId( + ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId, + eisaId + ); + RtlInitAnsiString(&ansiString, eisaId); + RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); + size += unicodeString.Length; + *DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size); + if (*DeviceId) { + swprintf (*DeviceId, + format, + unicodeString.Buffer, + DeviceInfo->LogicalDeviceNumber + ); +#if IDBG + { + ANSI_STRING dbgAnsiString; + UNICODE_STRING dbgUnicodeString; + + RtlInitUnicodeString(&dbgUnicodeString, *DeviceId); + RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE); + DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer); + RtlFreeAnsiString(&dbgAnsiString); + } +#endif + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + } + RtlFreeUnicodeString(&unicodeString); + + return status; +} + +NTSTATUS +PipQueryDeviceResources ( + PDEVICE_INFORMATION DeviceInfo, + ULONG BusNumber, + PCM_RESOURCE_LIST *CmResources, + ULONG *Size + ) +/*++ + +Routine Description: + + This function returns the bus resources being used by the specified device + +Arguments: + + DeviceInfo - Device information for the specificied slot + + BusNumber - should always be 0 + + CmResources - supplies a pointer to a variable to receive the device resource + data. + + Size - Supplies a pointer to avariable to receive the size of device resource + data. + +Return Value: + + NTSTATUS code. + +--*/ +{ + ULONG length; + NTSTATUS status; + PCM_RESOURCE_LIST cmResources; + + PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber, + DeviceInfo->LogicalDeviceNumber, + FALSE + ); + + status = PipReadDeviceBootResourceData ( + BusNumber, + DeviceInfo->DeviceData, + &cmResources, + &length + ); + + // + // Put all cards into wait for key state. + // + + PipWriteAddress(CONFIG_CONTROL_PORT); + PipWriteData(CONTROL_WAIT_FOR_KEY); + + // + // Return results + // + + if (NT_SUCCESS(status)) { + if (length == 0) { + cmResources = NULL; // Just to make sure. + } + *CmResources = cmResources; + *Size = length; +#if IDBG + PipDumpCmResourceList(cmResources); +#endif + } + return status; +} + +NTSTATUS +PipQueryDeviceResourceRequirements ( + PDEVICE_INFORMATION DeviceInfo, + ULONG BusNumber, + ULONG Slot, + PIO_RESOURCE_REQUIREMENTS_LIST *IoResources, + ULONG *Size + ) +/*++ + +Routine Description: + + This function returns the possible bus resources that this device may be + satisfied with. + +Arguments: + + DeviceData - Device data information for the specificied slot + + BusNumber - Supplies the bus number + + Slot - supplies the slot number of the BusNumber + + IoResources - supplies a pointer to a variable to receive the IO resource + requirements list + +Return Value: + + The device control is completed + +--*/ +{ + ULONG length = 0; + NTSTATUS status; + PUCHAR deviceData; + PIO_RESOURCE_REQUIREMENTS_LIST ioResources; + + deviceData = DeviceInfo->DeviceData; + status = PbBiosResourcesToNtResources ( + BusNumber, + Slot, + &deviceData, + &ioResources, + &length + ); + + // + // Return results + // + + if (NT_SUCCESS(status)) { + if (length == 0) { + ioResources = NULL; // Just ot make sure + } + *IoResources = ioResources; + *Size = length; +#if IDBG + PipDumpIoResourceList(ioResources); +#endif + } + return status; +} + +NTSTATUS +PipSetDeviceResources ( + PDEVICE_INFORMATION DeviceInfo, + PCM_RESOURCE_LIST CmResources + ) +/*++ + +Routine Description: + + This function configures the device to the specified device setttings + +Arguments: + + DeviceInfo - Device information for the specificied slot + + CmResources - pointer to the desired resource list + +Return Value: + + NTSTATUS code. + +--*/ +{ + NTSTATUS status; + + PAGED_CODE(); + + PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber, + DeviceInfo->LogicalDeviceNumber, + FALSE + ); + + // + // Set resource settings for the device + // + + status = PipWriteDeviceBootResourceData ( + DeviceInfo->DeviceData, + (PCM_RESOURCE_LIST) CmResources + ); + // + // Put all cards into wait for key state. + // + + PipWriteAddress(CONFIG_CONTROL_PORT); + PipWriteData(CONTROL_WAIT_FOR_KEY); + + return status; +} |