472 lines
11 KiB
C
472 lines
11 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
misc.c
|
||
|
||
Abstract:
|
||
|
||
This file contains pnp bios bus extender support routines.
|
||
|
||
Author:
|
||
|
||
Shie-Lin Tzong (shielint) 20-Apr-1995
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "busp.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,MbCreateClose)
|
||
#pragma alloc_text(PAGE,PbGetRegistryValue)
|
||
#pragma alloc_text(PAGE,PbDecompressEisaId)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
MbCreateClose (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles open and close requests such that our device objects
|
||
can be opened. All it does it to complete the Irp with success.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Supplies a pointer to the device object to be opened or closed.
|
||
|
||
Irp - supplies a pointer to I/O request packet.
|
||
|
||
Return Value:
|
||
|
||
Always returns STATUS_SUCCESS, since this is a null operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNREFERENCED_PARAMETER( DeviceObject );
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Null operation. Do not give an I/O boost since no I/O was
|
||
// actually done. IoStatus.Information should be
|
||
// FILE_OPENED for an open; it's undefined for a close.
|
||
//
|
||
|
||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
Irp->IoStatus.Information = FILE_OPENED;
|
||
|
||
IoCompleteRequest( Irp, 0);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
VOID
|
||
PbDecompressEisaId(
|
||
IN ULONG CompressedId,
|
||
IN PUCHAR EisaId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine decompressed compressed Eisa Id and returns the Id to caller
|
||
specified character buffer.
|
||
|
||
Arguments:
|
||
|
||
CompressedId - supplies the compressed Eisa Id.
|
||
|
||
EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT c1, c2;
|
||
LONG i;
|
||
|
||
PAGED_CODE();
|
||
|
||
CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
|
||
c1 = c2 = (USHORT)CompressedId;
|
||
c1 = (c1 & 0xff) << 8;
|
||
c2 = (c2 & 0xff00) >> 8;
|
||
c1 |= c2;
|
||
for (i = 2; i >= 0; i--) {
|
||
*(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
|
||
c1 >>= 5;
|
||
}
|
||
EisaId += 3;
|
||
c1 = c2 = (USHORT)(CompressedId >> 16);
|
||
c1 = (c1 & 0xff) << 8;
|
||
c2 = (c2 & 0xff00) >> 8;
|
||
c1 |= c2;
|
||
sprintf (EisaId, "%04x", c1);
|
||
}
|
||
|
||
NTSTATUS
|
||
PbGetRegistryValue(
|
||
IN HANDLE KeyHandle,
|
||
IN PWSTR ValueName,
|
||
OUT PKEY_VALUE_FULL_INFORMATION *Information
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to retrieve the data for a registry key's value.
|
||
This is done by querying the value of the key with a zero-length buffer
|
||
to determine the size of the value, and then allocating a buffer and
|
||
actually querying the value into the buffer.
|
||
|
||
It is the responsibility of the caller to free the buffer.
|
||
|
||
Arguments:
|
||
|
||
KeyHandle - Supplies the key handle whose value is to be queried
|
||
|
||
ValueName - Supplies the null-terminated Unicode name of the value.
|
||
|
||
Information - Returns a pointer to the allocated data buffer.
|
||
|
||
Return Value:
|
||
|
||
The function value is the final status of the query operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING unicodeString;
|
||
NTSTATUS status;
|
||
PKEY_VALUE_FULL_INFORMATION infoBuffer;
|
||
ULONG keyValueLength;
|
||
|
||
PAGED_CODE();
|
||
|
||
RtlInitUnicodeString( &unicodeString, ValueName );
|
||
|
||
//
|
||
// Figure out how big the data value is so that a buffer of the
|
||
// appropriate size can be allocated.
|
||
//
|
||
|
||
status = ZwQueryValueKey( KeyHandle,
|
||
&unicodeString,
|
||
KeyValueFullInformation,
|
||
(PVOID) NULL,
|
||
0,
|
||
&keyValueLength );
|
||
if (status != STATUS_BUFFER_OVERFLOW &&
|
||
status != STATUS_BUFFER_TOO_SMALL) {
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Allocate a buffer large enough to contain the entire key data value.
|
||
//
|
||
|
||
infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
|
||
if (!infoBuffer) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Query the data for the key value.
|
||
//
|
||
|
||
status = ZwQueryValueKey( KeyHandle,
|
||
&unicodeString,
|
||
KeyValueFullInformation,
|
||
infoBuffer,
|
||
keyValueLength,
|
||
&keyValueLength );
|
||
if (!NT_SUCCESS( status )) {
|
||
ExFreePool( infoBuffer );
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Everything worked, so simply return the address of the allocated
|
||
// buffer to the caller, who is now responsible for freeing it.
|
||
//
|
||
|
||
*Information = infoBuffer;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
#if DBG
|
||
|
||
VOID
|
||
PbDebugPrint (
|
||
ULONG Level,
|
||
PCCHAR DebugMessage,
|
||
...
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays debugging message or causes a break.
|
||
|
||
Arguments:
|
||
|
||
Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
|
||
DEBUG_BREAK - displays message and break.
|
||
|
||
DebugMessage - supplies a pointer to the debugging message.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR Buffer[256];
|
||
va_list ap;
|
||
|
||
va_start(ap, DebugMessage);
|
||
|
||
vsprintf(Buffer, DebugMessage, ap);
|
||
DbgPrint(Buffer);
|
||
if (Level == DEBUG_BREAK) {
|
||
DbgBreakPoint();
|
||
}
|
||
|
||
va_end(ap);
|
||
}
|
||
|
||
VOID
|
||
MbpDumpIoResourceDescriptor (
|
||
IN PUCHAR Indent,
|
||
IN PIO_RESOURCE_DESCRIPTOR Desc
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
|
||
|
||
Arguments:
|
||
|
||
Indent - # char of indentation.
|
||
|
||
Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
UCHAR c = ' ';
|
||
|
||
if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
|
||
c = 'A';
|
||
} else if (Desc->Option == IO_RESOURCE_PREFERRED) {
|
||
c = 'P';
|
||
}
|
||
switch (Desc->Type) {
|
||
case CmResourceTypePort:
|
||
DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
|
||
Indent, c,
|
||
Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
|
||
Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
|
||
Desc->u.Port.Alignment,
|
||
Desc->u.Port.Length
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeMemory:
|
||
DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
|
||
Indent, c,
|
||
Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
|
||
Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
|
||
Desc->u.Memory.Alignment,
|
||
Desc->u.Memory.Length
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeInterrupt:
|
||
DbgPrint ("%sINT %c Min: %x, Max: %x\n",
|
||
Indent, c,
|
||
Desc->u.Interrupt.MinimumVector,
|
||
Desc->u.Interrupt.MaximumVector
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeDma:
|
||
DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
|
||
Indent, c,
|
||
Desc->u.Dma.MinimumChannel,
|
||
Desc->u.Dma.MaximumChannel
|
||
);
|
||
break;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MbpDumpIoResourceList (
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays Io resource requirements list.
|
||
|
||
Arguments:
|
||
|
||
IoList - supplies a pointer to the Io resource requirements list to be displayed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
|
||
PIO_RESOURCE_LIST resList;
|
||
PIO_RESOURCE_DESCRIPTOR resDesc;
|
||
ULONG listCount, count, i, j;
|
||
|
||
DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
|
||
DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
|
||
listCount = IoList->AlternativeLists;
|
||
resList = &IoList->List[0];
|
||
for (i = 0; i < listCount; i++) {
|
||
DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
|
||
resList->Revision, resList->Count);
|
||
resDesc = &resList->Descriptors[0];
|
||
count = resList->Count;
|
||
for (j = 0; j < count; j++) {
|
||
MbpDumpIoResourceDescriptor(" ", resDesc);
|
||
resDesc++;
|
||
}
|
||
resList = (PIO_RESOURCE_LIST) resDesc;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MbpDumpCmResourceDescriptor (
|
||
IN PUCHAR Indent,
|
||
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
|
||
|
||
Arguments:
|
||
|
||
Indent - # char of indentation.
|
||
|
||
Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
switch (Desc->Type) {
|
||
case CmResourceTypePort:
|
||
DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
|
||
Indent,
|
||
Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
|
||
Desc->u.Port.Length
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeMemory:
|
||
DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
|
||
Indent,
|
||
Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
|
||
Desc->u.Memory.Length
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeInterrupt:
|
||
DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
|
||
Indent,
|
||
Desc->u.Interrupt.Level,
|
||
Desc->u.Interrupt.Vector,
|
||
Desc->u.Interrupt.Affinity
|
||
);
|
||
break;
|
||
|
||
case CmResourceTypeDma:
|
||
DbgPrint ("%sDMA Channel: %x, Port: %x\n",
|
||
Indent,
|
||
Desc->u.Dma.Channel,
|
||
Desc->u.Dma.Port
|
||
);
|
||
break;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MbpDumpCmResourceList (
|
||
IN PCM_RESOURCE_LIST CmList,
|
||
IN ULONG SlotNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays CM resource list.
|
||
|
||
Arguments:
|
||
|
||
CmList - supplies a pointer to CM resource list
|
||
|
||
SlotNumber - slot number of the resources
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
|
||
PCM_PARTIAL_RESOURCE_LIST partialDesc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
|
||
ULONG count, i;
|
||
|
||
fullDesc = &CmList->List[0];
|
||
DbgPrint("Pnp Bios Cm Resource List for Slot %x -\n", SlotNumber);
|
||
DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
|
||
partialDesc = &fullDesc->PartialResourceList;
|
||
DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
|
||
partialDesc->Revision, partialDesc->Count);
|
||
count = partialDesc->Count;
|
||
desc = &partialDesc->PartialDescriptors[0];
|
||
for (i = 0; i < count; i++) {
|
||
MbpDumpCmResourceDescriptor(" ", desc);
|
||
desc++;
|
||
}
|
||
}
|
||
#endif
|